aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware/rombios/apmbios.S
blob: a010949f7d0a6048d5e490a0dd49f1c2d1e34f66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
//  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., 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

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)
  pushf ; XEN
  sti   ; XEN: OS calls us with ints disabled -- better re-enable here!
  hlt
  popf  ; XEN
  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