Home | History | Annotate | Download | only in bios
      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