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