| // APM BIOS support for the Bochs BIOS |
| // Copyright (C) 2004 Fabrice Bellard |
| // |
| // Debugging extensions, 16-bit interface and extended power options |
| // Copyright (C) 2005 Struan Bartlett |
| // |
| // This library is free software; you can redistribute it and/or |
| // modify it under the terms of the GNU Lesser General Public |
| // License as published by the Free Software Foundation; either |
| // version 2 of the License, or (at your option) any later version. |
| // |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| // Lesser General Public License for more details. |
| // |
| // You should have received a copy of the GNU Lesser General Public |
| // License along with this library; if not, write to the Free Software |
| // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| |
| #if defined(APM_REAL) |
| #define APMSYM(s) apmreal_ ## s |
| #elif defined(APM_PROT16) |
| #define APMSYM(s) apm16_ ## s |
| #elif defined(APM_PROT32) |
| #define APMSYM(s) apm32_ ## s |
| #else |
| #error unsupported APM mode |
| #endif |
| |
| APMSYM(out_str): |
| push eax |
| push ebx |
| mov ebx, eax |
| APMSYM(out_str1): |
| SEG CS |
| mov al, byte ptr [bx] |
| cmp al, #0 |
| je APMSYM(out_str2) |
| outb dx, al |
| inc ebx |
| jmp APMSYM(out_str1) |
| APMSYM(out_str2): |
| pop ebx |
| pop eax |
| ret |
| |
| APMSYM(07_poweroff_str): |
| .ascii "Shutdown" |
| db 0 |
| APMSYM(07_suspend_str): |
| .ascii "Suspend" |
| db 0 |
| APMSYM(07_standby_str): |
| .ascii "Standby" |
| db 0 |
| |
| #if DEBUG_APM |
| APMSYM(put_str): |
| push edx |
| mov dx, #INFO_PORT |
| call APMSYM(out_str) |
| pop edx |
| ret |
| |
| ; print the hex number in eax |
| APMSYM(put_num): |
| push eax |
| push ebx |
| push ecx |
| push edx |
| mov ecx, eax |
| mov bx, #8 |
| mov dx, #INFO_PORT |
| APMSYM(put_num1): |
| mov eax, ecx |
| shr eax, #28 |
| add al, #0x30 |
| cmp al, #0x39 |
| jbe APMSYM(put_num2) |
| add al, #0x27 |
| APMSYM(put_num2): |
| outb dx, al |
| shl ecx, #4 |
| dec bx |
| jne APMSYM(put_num1) |
| pop edx |
| pop ecx |
| pop ebx |
| pop eax |
| ret |
| |
| APMSYM(put_reg): |
| outb dx, al |
| shr eax, #8 |
| outb dx, al |
| shr eax, #8 |
| outb dx, al |
| shr eax, #8 |
| outb dx, al |
| |
| mov eax,ebx |
| call APMSYM(put_num) |
| |
| mov al, #0x3b |
| outb dx,al |
| mov al, #0x20 |
| outb dx,al |
| ret |
| |
| APMSYM(put_regs): |
| push eax |
| push edx |
| push ebx |
| mov dx, #INFO_PORT |
| |
| mov ebx, eax |
| mov eax, #0x3d584145 // 'EAX=' |
| call APMSYM(put_reg) |
| pop ebx |
| push ebx |
| mov eax, #0x3d584245 // 'EBX=' |
| call APMSYM(put_reg) |
| mov ebx, ecx |
| mov eax, #0x3d584345 // 'ECX=' |
| call APMSYM(put_reg) |
| mov ebx, edx |
| mov eax, #0x3d584445 // 'EDX=' |
| call APMSYM(put_reg) |
| mov ebx, esi |
| mov eax, #0x3d495345 // 'ESI=' |
| call APMSYM(put_reg) |
| mov ebx, edi |
| mov eax, #0x3d494445 // 'EDI=' |
| call APMSYM(put_reg) |
| |
| mov al, #0x0a |
| outb dx, al |
| pop ebx |
| pop edx |
| pop eax |
| ret |
| #endif |
| |
| #if defined(APM_PROT32) |
| _apm32_entry: |
| #endif |
| #if defined(APM_PROT16) |
| _apm16_entry: |
| #endif |
| pushf |
| |
| #if defined(APM_REAL) |
| _apmreal_entry: |
| #endif |
| |
| #if DEBUG_APM |
| call APMSYM(put_regs) |
| #endif |
| |
| #if defined(APM_REAL) |
| ;----------------- |
| ; APM installation check |
| APMSYM(00): |
| cmp al, #0x00 |
| jne APMSYM(01) |
| |
| mov ah, #1 // APM major version |
| mov al, #2 // APM minor version |
| |
| mov bh, #0x50 // 'P' |
| mov bl, #0x4d // 'M' |
| |
| // bit 0 : 16 bit interface supported |
| // bit 1 : 32 bit interface supported |
| mov cx, #0x3 |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM real mode interface connect |
| APMSYM(01): |
| cmp al, #0x01 |
| jne APMSYM(02) |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM 16 bit protected mode interface connect |
| APMSYM(02): |
| cmp al, #0x02 |
| jne APMSYM(03) |
| |
| mov bx, #_apm16_entry |
| |
| mov ax, #0xf000 // 16 bit code segment base |
| mov si, #0xfff0 // 16 bit code segment size |
| mov cx, #0xf000 // data segment address |
| mov di, #0xfff0 // data segment length |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM 32 bit protected mode interface connect |
| APMSYM(03): |
| cmp al, #0x03 |
| jne APMSYM(04) |
| mov ax, #0xf000 // 32 bit code segment base |
| mov ebx, #_apm32_entry |
| mov cx, #0xf000 // 16 bit code segment base |
| // 32 bit code segment size (low 16 bits) |
| // 16 bit code segment size (high 16 bits) |
| mov esi, #0xfff0fff0 |
| mov dx, #0xf000 // data segment address |
| mov di, #0xfff0 // data segment length |
| jmp APMSYM(ok) |
| #endif |
| |
| ;----------------- |
| ; APM interface disconnect |
| APMSYM(04): |
| cmp al, #0x04 |
| jne APMSYM(05) |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM cpu idle |
| APMSYM(05): |
| cmp al, #0x05 |
| jne APMSYM(07) |
| sti |
| hlt |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM Set Power State |
| APMSYM(07): |
| cmp al, #0x07 |
| jne APMSYM(08) |
| |
| cmp bx, #1 |
| jne APMSYM(ok) |
| |
| cmp cx, #3 |
| je APMSYM(07_poweroff) |
| |
| cmp cx, #2 |
| je APMSYM(07_suspend) |
| |
| cmp cx, #1 |
| je APMSYM(07_standby) |
| |
| jne APMSYM(ok) |
| |
| APMSYM(07_poweroff): |
| // send power off event to emulator |
| cli |
| mov dx, #0x8900 |
| mov ax, #APMSYM(07_poweroff_str) |
| call APMSYM(out_str) |
| |
| APMSYM(07_1): |
| hlt |
| jmp APMSYM(07_1) |
| |
| APMSYM(07_suspend): |
| push edx |
| mov dx, #0x8900 |
| mov ax, #APMSYM(07_suspend_str) |
| call APMSYM(out_str) |
| pop edx |
| jmp APMSYM(ok) |
| |
| APMSYM(07_standby): |
| push edx |
| mov dx, #0x8900 |
| mov ax, #APMSYM(07_standby_str) |
| call APMSYM(out_str) |
| pop edx |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM Enable / Disable |
| APMSYM(08): |
| cmp al, #0x08 |
| jne APMSYM(0a) |
| |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; Get Power Status |
| APMSYM(0a): |
| cmp al, #0x0a |
| jne APMSYM(0b) |
| mov bh, #0x01 // on line |
| // mov bh, #0x02 // battery |
| mov bl, #0xff // unknown battery status |
| // mov bl, #0x03 // charging |
| mov ch, #0x80 // no system battery |
| // mov ch, #0x8 // charging |
| mov cl, #0xff // unknown remaining time |
| // mov cl, #50 |
| mov dx, #0xffff // unknown remaining time |
| mov si, #0 // zero battery |
| // mov si, #1 // one battery |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; Get PM Event |
| APMSYM(0b): |
| cmp al, #0x0b |
| jne APMSYM(0e) |
| mov ah, #0x80 // no event pending |
| jmp APMSYM(error) |
| |
| ;----------------- |
| ; APM Driver Version |
| APMSYM(0e): |
| cmp al, #0x0e |
| jne APMSYM(0f) |
| |
| mov ah, #1 |
| mov al, #2 |
| |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM Engage / Disengage |
| APMSYM(0f): |
| cmp al, #0x0f |
| jne APMSYM(10) |
| |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| ; APM Get Capabilities |
| APMSYM(10): |
| cmp al, #0x10 |
| jne APMSYM(unimplemented) |
| |
| mov bl, #0 |
| mov cx, #0 |
| |
| jmp APMSYM(ok) |
| |
| ;----------------- |
| APMSYM(ok): |
| popf |
| clc |
| #if defined(APM_REAL) |
| jmp iret_modify_cf |
| #else |
| retf |
| #endif |
| APMSYM(unimplemented): |
| APMSYM(error): |
| popf |
| stc |
| #if defined(APM_REAL) |
| jmp iret_modify_cf |
| #else |
| retf |
| #endif |
| |
| #undef APM_PROT32 |
| #undef APM_PROT16 |
| #undef APM_REAL |
| #undef APMSYM |