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 31APMSYM(out_str): 32 push eax 33 push ebx 34 mov ebx, eax 35APMSYM(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) 43APMSYM(out_str2): 44 pop ebx 45 pop eax 46 ret 47 48APMSYM(07_poweroff_str): 49 .ascii "Shutdown" 50 db 0 51APMSYM(07_suspend_str): 52 .ascii "Suspend" 53 db 0 54APMSYM(07_standby_str): 55 .ascii "Standby" 56 db 0 57 58#if DEBUG_APM 59APMSYM(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 67APMSYM(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 75APMSYM(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 82APMSYM(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 93APMSYM(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 111APMSYM(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 164APMSYM(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 181APMSYM(01): 182 cmp al, #0x01 183 jne APMSYM(02) 184 jmp APMSYM(ok) 185 186;----------------- 187; APM 16 bit protected mode interface connect 188APMSYM(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 202APMSYM(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 218APMSYM(04): 219 cmp al, #0x04 220 jne APMSYM(05) 221 jmp APMSYM(ok) 222 223;----------------- 224; APM cpu idle 225APMSYM(05): 226 cmp al, #0x05 227 jne APMSYM(07) 228 sti 229 hlt 230 jmp APMSYM(ok) 231 232;----------------- 233; APM Set Power State 234APMSYM(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 252APMSYM(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 259APMSYM(07_1): 260 hlt 261 jmp APMSYM(07_1) 262 263APMSYM(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 271APMSYM(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 281APMSYM(08): 282 cmp al, #0x08 283 jne APMSYM(0a) 284 285 jmp APMSYM(ok) 286 287;----------------- 288; Get Power Status 289APMSYM(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 307APMSYM(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 315APMSYM(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 326APMSYM(0f): 327 cmp al, #0x0f 328 jne APMSYM(10) 329 330 jmp APMSYM(ok) 331 332;----------------- 333; APM Get Capabilities 334APMSYM(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;----------------- 344APMSYM(ok): 345 popf 346 clc 347#if defined(APM_REAL) 348 jmp iret_modify_cf 349#else 350 retf 351#endif 352APMSYM(unimplemented): 353APMSYM(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