|
|
1.1 root 1: // Basic support for apmbios callbacks.
2: //
3: // Copyright (C) 2008 Kevin O'Connor <[email protected]>
4: // Copyright (C) 2005 Struan Bartlett
5: // Copyright (C) 2004 Fabrice Bellard
6: //
7: // This file may be distributed under the terms of the GNU LGPLv3 license.
8:
9: #include "farptr.h" // GET_VAR
10: #include "bregs.h" // struct bregs
11: #include "ioport.h" // outb
12: #include "util.h" // wait_irq
13: #include "config.h" // CONFIG_*
14: #include "biosvar.h" // GET_GLOBAL
15:
16: static void
17: out_str(const char *str_cs)
18: {
19: if (CONFIG_COREBOOT) {
20: dprintf(1, "APM request '%s'\n", str_cs);
21: return;
22: }
23:
24: u8 *s = (u8*)str_cs;
25: for (;;) {
26: u8 c = GET_GLOBAL(*s);
27: if (!c)
28: break;
29: outb(c, PORT_BIOS_APM);
30: s++;
31: }
32: }
33:
34: // APM installation check
35: static void
36: handle_155300(struct bregs *regs)
37: {
38: regs->ah = 1; // APM major version
39: regs->al = 2; // APM minor version
40: regs->bh = 'P';
41: regs->bl = 'M';
42: // bit 0 : 16 bit interface supported
43: // bit 1 : 32 bit interface supported
44: regs->cx = 0x03;
45: set_success(regs);
46: }
47:
48: // APM real mode interface connect
49: static void
50: handle_155301(struct bregs *regs)
51: {
52: set_success(regs);
53: }
54:
55: // Assembler entry points defined in romlayout.S
1.1.1.4 ! root 56: extern void entry_apm16(void);
! 57: extern void entry_apm32(void);
1.1 root 58:
59: // APM 16 bit protected mode interface connect
60: static void
61: handle_155302(struct bregs *regs)
62: {
1.1.1.4 ! root 63: regs->bx = (u32)entry_apm16;
1.1 root 64: regs->ax = SEG_BIOS; // 16 bit code segment base
65: regs->si = 0xfff0; // 16 bit code segment size
66: regs->cx = SEG_BIOS; // data segment address
67: regs->di = 0xfff0; // data segment length
68: set_success(regs);
69: }
70:
71: // APM 32 bit protected mode interface connect
72: static void
73: handle_155303(struct bregs *regs)
74: {
75: regs->ax = SEG_BIOS; // 32 bit code segment base
1.1.1.4 ! root 76: regs->ebx = (u32)entry_apm32;
1.1 root 77: regs->cx = SEG_BIOS; // 16 bit code segment base
78: // 32 bit code segment size (low 16 bits)
79: // 16 bit code segment size (high 16 bits)
80: regs->esi = 0xfff0fff0;
81: regs->dx = SEG_BIOS; // data segment address
82: regs->di = 0xfff0; // data segment length
83: set_success(regs);
84: }
85:
86: // APM interface disconnect
87: static void
88: handle_155304(struct bregs *regs)
89: {
90: set_success(regs);
91: }
92:
93: // APM cpu idle
94: static void
95: handle_155305(struct bregs *regs)
96: {
97: wait_irq();
98: set_success(regs);
99: }
100:
101: // APM cpu busy
102: static void
103: handle_155306(struct bregs *regs)
104: {
105: set_success(regs);
106: }
107:
1.1.1.3 root 108: void
109: apm_shutdown(void)
110: {
111: irq_disable();
112: out_str("Shutdown");
113: for (;;)
114: hlt();
115: }
116:
1.1 root 117: // APM Set Power State
118: static void
119: handle_155307(struct bregs *regs)
120: {
121: if (regs->bx != 1) {
122: set_success(regs);
123: return;
124: }
125: switch (regs->cx) {
126: case 1:
127: out_str("Standby");
128: break;
129: case 2:
130: out_str("Suspend");
131: break;
132: case 3:
1.1.1.3 root 133: apm_shutdown();
1.1 root 134: break;
135: }
136: set_success(regs);
137: }
138:
139: static void
140: handle_155308(struct bregs *regs)
141: {
142: set_success(regs);
143: }
144:
145: // Get Power Status
146: static void
147: handle_15530a(struct bregs *regs)
148: {
149: regs->bh = 0x01; // on line
150: regs->bl = 0xff; // unknown battery status
151: regs->ch = 0x80; // no system battery
152: regs->cl = 0xff; // unknown remaining time
153: regs->dx = 0xffff; // unknown remaining time
154: regs->si = 0x00; // zero battery
155: set_success(regs);
156: }
157:
158: #define RET_ENOEVENT 0x80
159:
160: // Get PM Event
161: static void
162: handle_15530b(struct bregs *regs)
163: {
164: set_code_invalid_silent(regs, RET_ENOEVENT);
165: }
166:
167: // APM Driver Version
168: static void
169: handle_15530e(struct bregs *regs)
170: {
171: regs->ah = 1;
172: regs->al = 2;
173: set_success(regs);
174: }
175:
176: // APM Engage / Disengage
177: static void
178: handle_15530f(struct bregs *regs)
179: {
180: set_success(regs);
181: }
182:
183: // APM Get Capabilities
184: static void
185: handle_155310(struct bregs *regs)
186: {
187: regs->bl = 0;
188: regs->cx = 0;
189: set_success(regs);
190: }
191:
192: static void
193: handle_1553XX(struct bregs *regs)
194: {
195: set_unimplemented(regs);
196: }
197:
1.1.1.2 root 198: void
1.1 root 199: handle_1553(struct bregs *regs)
200: {
201: if (! CONFIG_APMBIOS) {
202: set_code_invalid(regs, RET_EUNSUPPORTED);
203: return;
204: }
205:
206: //debug_stub(regs);
207: switch (regs->al) {
208: case 0x00: handle_155300(regs); break;
209: case 0x01: handle_155301(regs); break;
210: case 0x02: handle_155302(regs); break;
211: case 0x03: handle_155303(regs); break;
212: case 0x04: handle_155304(regs); break;
213: case 0x05: handle_155305(regs); break;
214: case 0x06: handle_155306(regs); break;
215: case 0x07: handle_155307(regs); break;
216: case 0x08: handle_155308(regs); break;
217: case 0x0a: handle_15530a(regs); break;
218: case 0x0b: handle_15530b(regs); break;
219: case 0x0e: handle_15530e(regs); break;
220: case 0x0f: handle_15530f(regs); break;
221: case 0x10: handle_155310(regs); break;
222: default: handle_1553XX(regs); break;
223: }
224: }
1.1.1.2 root 225:
226: void VISIBLE16
227: handle_apm16(struct bregs *regs)
228: {
229: debug_enter(regs, DEBUG_HDL_apm);
230: handle_1553(regs);
231: }
232:
233: void VISIBLE32SEG
234: handle_apm32(struct bregs *regs)
235: {
236: debug_enter(regs, DEBUG_HDL_apm);
237: handle_1553(regs);
238: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.