Extract 'struct bregs' out of biosvar.h; clean up header includes.
[seabios.git] / src / apm.c
1 // Basic support for apmbios callbacks.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
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 GPLv3 license.
8
9 #include "farptr.h" // GET_VAR
10 #include "bregs.h" // struct bregs
11 #include "ioport.h" // outb
12 #include "util.h" // irq_enable
13 #include "config.h" // CONFIG_*
14
15 static void
16 out_str(const char *str_cs)
17 {
18     if (CONFIG_COREBOOT) {
19         dprintf(1, "APM request '%s'\n", str_cs);
20         return;
21     }
22
23     u8 *s = (u8*)str_cs;
24     for (;;) {
25         u8 c = GET_VAR(CS, *s);
26         if (!c)
27             break;
28         outb(c, PORT_BIOS_APM);
29         s++;
30     }
31 }
32
33 // APM installation check
34 static void
35 handle_155300(struct bregs *regs)
36 {
37     regs->ah = 1; // APM major version
38     regs->al = 2; // APM minor version
39     regs->bh = 'P';
40     regs->bl = 'M';
41     // bit 0 : 16 bit interface supported
42     // bit 1 : 32 bit interface supported
43     regs->cx = 0x03;
44     set_success(regs);
45 }
46
47 // APM real mode interface connect
48 static void
49 handle_155301(struct bregs *regs)
50 {
51     set_success(regs);
52 }
53
54 // Assembler entry points defined in romlayout.S
55 extern void apm16protected_entry();
56 extern void apm32protected_entry();
57
58 // APM 16 bit protected mode interface connect
59 static void
60 handle_155302(struct bregs *regs)
61 {
62     regs->bx = (u32)apm16protected_entry;
63     regs->ax = SEG_BIOS; // 16 bit code segment base
64     regs->si = 0xfff0;   // 16 bit code segment size
65     regs->cx = SEG_BIOS; // data segment address
66     regs->di = 0xfff0;   // data segment length
67     set_success(regs);
68 }
69
70 // APM 32 bit protected mode interface connect
71 static void
72 handle_155303(struct bregs *regs)
73 {
74     regs->ax = SEG_BIOS; // 32 bit code segment base
75     regs->ebx = (u32)apm32protected_entry;
76     regs->cx = SEG_BIOS; // 16 bit code segment base
77     // 32 bit code segment size (low 16 bits)
78     // 16 bit code segment size (high 16 bits)
79     regs->esi = 0xfff0fff0;
80     regs->dx = SEG_BIOS; // data segment address
81     regs->di = 0xfff0; // data segment length
82     set_success(regs);
83 }
84
85 // APM interface disconnect
86 static void
87 handle_155304(struct bregs *regs)
88 {
89     set_success(regs);
90 }
91
92 // APM cpu idle
93 static void
94 handle_155305(struct bregs *regs)
95 {
96     irq_enable();
97     hlt();
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
108 // APM Set Power State
109 static void
110 handle_155307(struct bregs *regs)
111 {
112     if (regs->bx != 1) {
113         set_success(regs);
114         return;
115     }
116     switch (regs->cx) {
117     case 1:
118         out_str("Standby");
119         break;
120     case 2:
121         out_str("Suspend");
122         break;
123     case 3:
124         irq_disable();
125         out_str("Shutdown");
126         for (;;)
127             hlt();
128         break;
129     }
130     set_success(regs);
131 }
132
133 static void
134 handle_155308(struct bregs *regs)
135 {
136     set_success(regs);
137 }
138
139 // Get Power Status
140 static void
141 handle_15530a(struct bregs *regs)
142 {
143     regs->bh = 0x01; // on line
144     regs->bl = 0xff; // unknown battery status
145     regs->ch = 0x80; // no system battery
146     regs->cl = 0xff; // unknown remaining time
147     regs->dx = 0xffff; // unknown remaining time
148     regs->si = 0x00; // zero battery
149     set_success(regs);
150 }
151
152 #define RET_ENOEVENT 0x80
153
154 // Get PM Event
155 static void
156 handle_15530b(struct bregs *regs)
157 {
158     set_code_fail_silent(regs, RET_ENOEVENT);
159 }
160
161 // APM Driver Version
162 static void
163 handle_15530e(struct bregs *regs)
164 {
165     regs->ah = 1;
166     regs->al = 2;
167     set_success(regs);
168 }
169
170 // APM Engage / Disengage
171 static void
172 handle_15530f(struct bregs *regs)
173 {
174     set_success(regs);
175 }
176
177 // APM Get Capabilities
178 static void
179 handle_155310(struct bregs *regs)
180 {
181     regs->bl = 0;
182     regs->cx = 0;
183     set_success(regs);
184 }
185
186 static void
187 handle_1553XX(struct bregs *regs)
188 {
189     set_fail(regs);
190 }
191
192 void VISIBLE16
193 handle_1553(struct bregs *regs)
194 {
195     if (! CONFIG_APMBIOS) {
196         set_code_fail(regs, RET_EUNSUPPORTED);
197         return;
198     }
199
200     //debug_stub(regs);
201     switch (regs->al) {
202     case 0x00: handle_155300(regs); break;
203     case 0x01: handle_155301(regs); break;
204     case 0x02: handle_155302(regs); break;
205     case 0x03: handle_155303(regs); break;
206     case 0x04: handle_155304(regs); break;
207     case 0x05: handle_155305(regs); break;
208     case 0x06: handle_155306(regs); break;
209     case 0x07: handle_155307(regs); break;
210     case 0x08: handle_155308(regs); break;
211     case 0x0a: handle_15530a(regs); break;
212     case 0x0b: handle_15530b(regs); break;
213     case 0x0e: handle_15530e(regs); break;
214     case 0x0f: handle_15530f(regs); break;
215     case 0x10: handle_155310(regs); break;
216     default:   handle_1553XX(regs); break;
217     }
218 }