1 // APM BIOS support for the Bochs BIOS 2 // Copyright (C) 2004 Fabrice Bellard 3 // 4 // Debugging extensions, 16-bit interface and extended power options 5 // Copyright (C) 2005 Struan Bartlett 6 // 7 // This library is free software; you can redistribute it and/or 8 // modify it under the terms of the GNU Lesser General Public 9 // License as published by the Free Software Foundation; either 10 // version 2 of the License, or (at your option) any later version. 11 // 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 // Lesser General Public License for more details. 16 // 17 // You should have received a copy of the GNU Lesser General Public 18 // License along with this library; if not, write to the Free Software 19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 21 #if defined(APM_REAL) 22 #define APMSYM(s) apmreal_ ## s 23 #elif defined(APM_PROT16) 24 #define APMSYM(s) apm16_ ## s 25 #elif defined(APM_PROT32) 26 #define APMSYM(s) apm32_ ## s 27 #else 28 #error unsupported APM mode 29 #endif 30 31 APMSYM(out_str): 32 push eax 33 push ebx 34 mov ebx, eax 35 APMSYM(out_str1): 36 SEG CS 37 mov al, byte ptr [bx] 38 cmp al, #0 39 je APMSYM(out_str2) 40 outb dx, al 41 inc ebx 42 jmp APMSYM(out_str1) 43 APMSYM(out_str2): 44 pop ebx 45 pop eax 46 ret 47 48 APMSYM(07_poweroff_str): 49 .ascii "Shutdown" 50 db 0 51 APMSYM(07_suspend_str): 52 .ascii "Suspend" 53 db 0 54 APMSYM(07_standby_str): 55 .ascii "Standby" 56 db 0 57 58 #if DEBUG_APM 59 APMSYM(put_str): 60 push edx 61 mov dx, #INFO_PORT 62 call APMSYM(out_str) 63 pop edx 64 ret 65 66 ; print the hex number in eax 67 APMSYM(put_num): 68 push eax 69 push ebx 70 push ecx 71 push edx 72 mov ecx, eax 73 mov bx, #8 74 mov dx, #INFO_PORT 75 APMSYM(put_num1): 76 mov eax, ecx 77 shr eax, #28 78 add al, #0x30 79 cmp al, #0x39 80 jbe APMSYM(put_num2) 81 add al, #0x27 82 APMSYM(put_num2): 83 outb dx, al 84 shl ecx, #4 85 dec bx 86 jne APMSYM(put_num1) 87 pop edx 88 pop ecx 89 pop ebx 90 pop eax 91 ret 92 93 APMSYM(put_reg): 94 outb dx, al 95 shr eax, #8 96 outb dx, al 97 shr eax, #8 98 outb dx, al 99 shr eax, #8 100 outb dx, al 101 102 mov eax,ebx 103 call APMSYM(put_num) 104 105 mov al, #0x3b 106 outb dx,al 107 mov al, #0x20 108 outb dx,al 109 ret 110 111 APMSYM(put_regs): 112 push eax 113 push edx 114 push ebx 115 mov dx, #INFO_PORT 116 117 mov ebx, eax 118 mov eax, #0x3d584145 // 'EAX=' 119 call APMSYM(put_reg) 120 pop ebx 121 push ebx 122 mov eax, #0x3d584245 // 'EBX=' 123 call APMSYM(put_reg) 124 mov ebx, ecx 125 mov eax, #0x3d584345 // 'ECX=' 126 call APMSYM(put_reg) 127 mov ebx, edx 128 mov eax, #0x3d584445 // 'EDX=' 129 call APMSYM(put_reg) 130 mov ebx, esi 131 mov eax, #0x3d495345 // 'ESI=' 132 call APMSYM(put_reg) 133 mov ebx, edi 134 mov eax, #0x3d494445 // 'EDI=' 135 call APMSYM(put_reg) 136 137 mov al, #0x0a 138 outb dx, al 139 pop ebx 140 pop edx 141 pop eax 142 ret 143 #endif 144 145 #if defined(APM_PROT32) 146 _apm32_entry: 147 #endif 148 #if defined(APM_PROT16) 149 _apm16_entry: 150 #endif 151 pushf 152 153 #if defined(APM_REAL) 154 _apmreal_entry: 155 #endif 156 157 #if DEBUG_APM 158 call APMSYM(put_regs) 159 #endif 160 161 #if defined(APM_REAL) 162 ;----------------- 163 ; APM installation check 164 APMSYM(00): 165 cmp al, #0x00 166 jne APMSYM(01) 167 168 mov ah, #1 // APM major version 169 mov al, #2 // APM minor version 170 171 mov bh, #0x50 // 'P' 172 mov bl, #0x4d // 'M' 173 174 // bit 0 : 16 bit interface supported 175 // bit 1 : 32 bit interface supported 176 mov cx, #0x3 177 jmp APMSYM(ok) 178 179 ;----------------- 180 ; APM real mode interface connect 181 APMSYM(01): 182 cmp al, #0x01 183 jne APMSYM(02) 184 jmp APMSYM(ok) 185 186 ;----------------- 187 ; APM 16 bit protected mode interface connect 188 APMSYM(02): 189 cmp al, #0x02 190 jne APMSYM(03) 191 192 mov bx, #_apm16_entry 193 194 mov ax, #0xf000 // 16 bit code segment base 195 mov si, #0xfff0 // 16 bit code segment size 196 mov cx, #0xf000 // data segment address 197 mov di, #0xfff0 // data segment length 198 jmp APMSYM(ok) 199 200 ;----------------- 201 ; APM 32 bit protected mode interface connect 202 APMSYM(03): 203 cmp al, #0x03 204 jne APMSYM(04) 205 mov ax, #0xf000 // 32 bit code segment base 206 mov ebx, #_apm32_entry 207 mov cx, #0xf000 // 16 bit code segment base 208 // 32 bit code segment size (low 16 bits) 209 // 16 bit code segment size (high 16 bits) 210 mov esi, #0xfff0fff0 211 mov dx, #0xf000 // data segment address 212 mov di, #0xfff0 // data segment length 213 jmp APMSYM(ok) 214 #endif 215 216 ;----------------- 217 ; APM interface disconnect 218 APMSYM(04): 219 cmp al, #0x04 220 jne APMSYM(05) 221 jmp APMSYM(ok) 222 223 ;----------------- 224 ; APM cpu idle 225 APMSYM(05): 226 cmp al, #0x05 227 jne APMSYM(07) 228 sti 229 hlt 230 jmp APMSYM(ok) 231 232 ;----------------- 233 ; APM Set Power State 234 APMSYM(07): 235 cmp al, #0x07 236 jne APMSYM(08) 237 238 cmp bx, #1 239 jne APMSYM(ok) 240 241 cmp cx, #3 242 je APMSYM(07_poweroff) 243 244 cmp cx, #2 245 je APMSYM(07_suspend) 246 247 cmp cx, #1 248 je APMSYM(07_standby) 249 250 jne APMSYM(ok) 251 252 APMSYM(07_poweroff): 253 // send power off event to emulator 254 cli 255 mov dx, #0x8900 256 mov ax, #APMSYM(07_poweroff_str) 257 call APMSYM(out_str) 258 259 APMSYM(07_1): 260 hlt 261 jmp APMSYM(07_1) 262 263 APMSYM(07_suspend): 264 push edx 265 mov dx, #0x8900 266 mov ax, #APMSYM(07_suspend_str) 267 call APMSYM(out_str) 268 pop edx 269 jmp APMSYM(ok) 270 271 APMSYM(07_standby): 272 push edx 273 mov dx, #0x8900 274 mov ax, #APMSYM(07_standby_str) 275 call APMSYM(out_str) 276 pop edx 277 jmp APMSYM(ok) 278 279 ;----------------- 280 ; APM Enable / Disable 281 APMSYM(08): 282 cmp al, #0x08 283 jne APMSYM(0a) 284 285 jmp APMSYM(ok) 286 287 ;----------------- 288 ; Get Power Status 289 APMSYM(0a): 290 cmp al, #0x0a 291 jne APMSYM(0b) 292 mov bh, #0x01 // on line 293 // mov bh, #0x02 // battery 294 mov bl, #0xff // unknown battery status 295 // mov bl, #0x03 // charging 296 mov ch, #0x80 // no system battery 297 // mov ch, #0x8 // charging 298 mov cl, #0xff // unknown remaining time 299 // mov cl, #50 300 mov dx, #0xffff // unknown remaining time 301 mov si, #0 // zero battery 302 // mov si, #1 // one battery 303 jmp APMSYM(ok) 304 305 ;----------------- 306 ; Get PM Event 307 APMSYM(0b): 308 cmp al, #0x0b 309 jne APMSYM(0e) 310 mov ah, #0x80 // no event pending 311 jmp APMSYM(error) 312 313 ;----------------- 314 ; APM Driver Version 315 APMSYM(0e): 316 cmp al, #0x0e 317 jne APMSYM(0f) 318 319 mov ah, #1 320 mov al, #2 321 322 jmp APMSYM(ok) 323 324 ;----------------- 325 ; APM Engage / Disengage 326 APMSYM(0f): 327 cmp al, #0x0f 328 jne APMSYM(10) 329 330 jmp APMSYM(ok) 331 332 ;----------------- 333 ; APM Get Capabilities 334 APMSYM(10): 335 cmp al, #0x10 336 jne APMSYM(unimplemented) 337 338 mov bl, #0 339 mov cx, #0 340 341 jmp APMSYM(ok) 342 343 ;----------------- 344 APMSYM(ok): 345 popf 346 clc 347 #if defined(APM_REAL) 348 jmp iret_modify_cf 349 #else 350 retf 351 #endif 352 APMSYM(unimplemented): 353 APMSYM(error): 354 popf 355 stc 356 #if defined(APM_REAL) 357 jmp iret_modify_cf 358 #else 359 retf 360 #endif 361 362 #undef APM_PROT32 363 #undef APM_PROT16 364 #undef APM_REAL 365 #undef APMSYM 366