2004-06-20 22:28:40 +04:00
|
|
|
// APM BIOS support for the Bochs BIOS
|
|
|
|
// Copyright (C) 2004 Fabrice Bellard
|
|
|
|
//
|
2005-04-06 22:05:47 +04:00
|
|
|
// Debugging extensions, 16-bit interface and extended power options
|
|
|
|
// Copyright (C) 2005 Struan Bartlett
|
|
|
|
//
|
2004-06-20 22:28:40 +04:00
|
|
|
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
|
|
|
|
|
2008-01-26 12:15:27 +03:00
|
|
|
APMSYM(out_str):
|
2004-06-20 22:28:40 +04:00
|
|
|
push eax
|
|
|
|
push ebx
|
|
|
|
mov ebx, eax
|
2005-04-06 22:05:47 +04:00
|
|
|
APMSYM(out_str1):
|
2004-06-20 22:28:40 +04:00
|
|
|
SEG CS
|
|
|
|
mov al, byte ptr [bx]
|
|
|
|
cmp al, #0
|
2005-04-06 22:05:47 +04:00
|
|
|
je APMSYM(out_str2)
|
2004-06-20 22:28:40 +04:00
|
|
|
outb dx, al
|
|
|
|
inc ebx
|
2005-04-06 22:05:47 +04:00
|
|
|
jmp APMSYM(out_str1)
|
|
|
|
APMSYM(out_str2):
|
2004-06-20 22:28:40 +04:00
|
|
|
pop ebx
|
|
|
|
pop eax
|
|
|
|
ret
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
APMSYM(07_poweroff_str):
|
|
|
|
.ascii "Shutdown"
|
|
|
|
db 0
|
|
|
|
APMSYM(07_suspend_str):
|
|
|
|
.ascii "Suspend"
|
|
|
|
db 0
|
|
|
|
APMSYM(07_standby_str):
|
|
|
|
.ascii "Standby"
|
|
|
|
db 0
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
#if DEBUG_APM
|
2008-01-26 12:15:27 +03:00
|
|
|
APMSYM(put_str):
|
2005-04-06 22:05:47 +04:00
|
|
|
push edx
|
|
|
|
mov dx, #INFO_PORT
|
|
|
|
call APMSYM(out_str)
|
|
|
|
pop edx
|
|
|
|
ret
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
; print the hex number in eax
|
2008-01-26 12:15:27 +03:00
|
|
|
APMSYM(put_num):
|
2004-06-20 22:28:40 +04:00
|
|
|
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
|
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
APMSYM(put_reg):
|
|
|
|
outb dx, al
|
|
|
|
shr eax, #8
|
|
|
|
outb dx, al
|
|
|
|
shr eax, #8
|
|
|
|
outb dx, al
|
|
|
|
shr eax, #8
|
|
|
|
outb dx, al
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
mov eax,ebx
|
|
|
|
call APMSYM(put_num)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
mov al, #0x3b
|
|
|
|
outb dx,al
|
|
|
|
mov al, #0x20
|
|
|
|
outb dx,al
|
2008-01-26 12:15:27 +03:00
|
|
|
ret
|
2005-04-06 22:05:47 +04:00
|
|
|
|
|
|
|
APMSYM(put_regs):
|
|
|
|
push eax
|
|
|
|
push edx
|
|
|
|
push ebx
|
|
|
|
mov dx, #INFO_PORT
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
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)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
mov al, #0x0a
|
|
|
|
outb dx, al
|
|
|
|
pop ebx
|
|
|
|
pop edx
|
|
|
|
pop eax
|
|
|
|
ret
|
2004-06-20 22:28:40 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(APM_PROT32)
|
|
|
|
_apm32_entry:
|
|
|
|
#endif
|
|
|
|
#if defined(APM_PROT16)
|
|
|
|
_apm16_entry:
|
|
|
|
#endif
|
|
|
|
pushf
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
#if defined(APM_REAL)
|
|
|
|
_apmreal_entry:
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DEBUG_APM
|
2005-04-06 22:05:47 +04:00
|
|
|
call APMSYM(put_regs)
|
2004-06-20 22:28:40 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(APM_REAL)
|
|
|
|
;-----------------
|
|
|
|
; APM installation check
|
|
|
|
APMSYM(00):
|
|
|
|
cmp al, #0x00
|
|
|
|
jne APMSYM(01)
|
2005-04-06 22:05:47 +04:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
mov ah, #1 // APM major version
|
|
|
|
mov al, #2 // APM minor version
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
mov bh, #0x50 // 'P'
|
|
|
|
mov bl, #0x4d // 'M'
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
// bit 0 : 16 bit interface supported
|
|
|
|
// bit 1 : 32 bit interface supported
|
2005-04-06 22:05:47 +04:00
|
|
|
mov cx, #0x3
|
2004-06-20 22:28:40 +04:00
|
|
|
jmp APMSYM(ok)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
;-----------------
|
|
|
|
; APM real mode interface connect
|
|
|
|
APMSYM(01):
|
|
|
|
cmp al, #0x01
|
2005-04-06 22:05:47 +04:00
|
|
|
jne APMSYM(02)
|
|
|
|
jmp APMSYM(ok)
|
|
|
|
|
|
|
|
;-----------------
|
|
|
|
; APM 16 bit protected mode interface connect
|
|
|
|
APMSYM(02):
|
|
|
|
cmp al, #0x02
|
2004-06-20 22:28:40 +04:00
|
|
|
jne APMSYM(03)
|
2005-04-06 22:05:47 +04:00
|
|
|
|
|
|
|
mov bx, #_apm16_entry
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
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
|
2004-06-20 22:28:40 +04:00
|
|
|
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
|
2005-12-26 13:36:52 +03:00
|
|
|
jne APMSYM(05)
|
|
|
|
jmp APMSYM(ok)
|
|
|
|
|
|
|
|
;-----------------
|
|
|
|
; APM cpu idle
|
|
|
|
APMSYM(05):
|
|
|
|
cmp al, #0x05
|
2004-06-20 22:28:40 +04:00
|
|
|
jne APMSYM(07)
|
2006-05-07 14:40:53 +04:00
|
|
|
sti
|
2005-12-26 13:36:52 +03:00
|
|
|
hlt
|
2004-06-20 22:28:40 +04:00
|
|
|
jmp APMSYM(ok)
|
|
|
|
|
|
|
|
;-----------------
|
|
|
|
; APM Set Power State
|
|
|
|
APMSYM(07):
|
|
|
|
cmp al, #0x07
|
2005-10-24 15:14:37 +04:00
|
|
|
jne APMSYM(08)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
cmp bx, #1
|
|
|
|
jne APMSYM(ok)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
cmp cx, #3
|
2005-04-06 22:05:47 +04:00
|
|
|
je APMSYM(07_poweroff)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
cmp cx, #2
|
|
|
|
je APMSYM(07_suspend)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
cmp cx, #1
|
|
|
|
je APMSYM(07_standby)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
jne APMSYM(ok)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
|
|
|
APMSYM(07_poweroff):
|
2005-04-06 22:05:47 +04:00
|
|
|
// send power off event to emulator
|
2004-06-20 22:28:40 +04:00
|
|
|
cli
|
|
|
|
mov dx, #0x8900
|
2005-04-06 22:05:47 +04:00
|
|
|
mov ax, #APMSYM(07_poweroff_str)
|
|
|
|
call APMSYM(out_str)
|
2004-06-20 22:28:40 +04:00
|
|
|
|
|
|
|
APMSYM(07_1):
|
|
|
|
hlt
|
|
|
|
jmp APMSYM(07_1)
|
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
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)
|
|
|
|
|
2005-10-24 15:14:37 +04:00
|
|
|
;-----------------
|
|
|
|
; APM Enable / Disable
|
|
|
|
APMSYM(08):
|
|
|
|
cmp al, #0x08
|
|
|
|
jne APMSYM(0a)
|
|
|
|
|
|
|
|
jmp APMSYM(ok)
|
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
;-----------------
|
|
|
|
; Get Power Status
|
|
|
|
APMSYM(0a):
|
|
|
|
cmp al, #0x0a
|
|
|
|
jne APMSYM(0b)
|
|
|
|
mov bh, #0x01 // on line
|
2005-04-06 22:05:47 +04:00
|
|
|
// mov bh, #0x02 // battery
|
2004-06-20 22:28:40 +04:00
|
|
|
mov bl, #0xff // unknown battery status
|
2005-04-06 22:05:47 +04:00
|
|
|
// mov bl, #0x03 // charging
|
2004-06-20 22:28:40 +04:00
|
|
|
mov ch, #0x80 // no system battery
|
2005-04-06 22:05:47 +04:00
|
|
|
// mov ch, #0x8 // charging
|
2004-06-20 22:28:40 +04:00
|
|
|
mov cl, #0xff // unknown remaining time
|
2005-04-06 22:05:47 +04:00
|
|
|
// mov cl, #50
|
2008-01-26 12:15:27 +03:00
|
|
|
mov dx, #0xffff // unknown remaining time
|
2004-06-20 22:28:40 +04:00
|
|
|
mov si, #0 // zero battery
|
2005-04-06 22:05:47 +04:00
|
|
|
// mov si, #1 // one battery
|
2004-06-20 22:28:40 +04:00
|
|
|
jmp APMSYM(ok)
|
|
|
|
|
|
|
|
;-----------------
|
|
|
|
; Get PM Event
|
|
|
|
APMSYM(0b):
|
|
|
|
cmp al, #0x0b
|
|
|
|
jne APMSYM(0e)
|
|
|
|
mov ah, #0x80 // no event pending
|
|
|
|
jmp APMSYM(error)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
;-----------------
|
|
|
|
; APM Driver Version
|
|
|
|
APMSYM(0e):
|
|
|
|
cmp al, #0x0e
|
2005-10-24 15:14:37 +04:00
|
|
|
jne APMSYM(0f)
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2005-04-06 22:05:47 +04:00
|
|
|
mov ah, #1
|
|
|
|
mov al, #2
|
2008-01-26 12:15:27 +03:00
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
jmp APMSYM(ok)
|
|
|
|
|
2005-10-24 15:14:37 +04:00
|
|
|
;-----------------
|
|
|
|
; 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)
|
|
|
|
|
2004-06-20 22:28:40 +04:00
|
|
|
;-----------------
|
|
|
|
APMSYM(ok):
|
|
|
|
popf
|
|
|
|
clc
|
|
|
|
#if defined(APM_REAL)
|
|
|
|
jmp iret_modify_cf
|
|
|
|
#else
|
2008-01-26 12:15:27 +03:00
|
|
|
retf
|
2004-06-20 22:28:40 +04:00
|
|
|
#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
|