Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / 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 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
56 extern void entry_apm16(void);
57 extern void entry_apm32(void);
58
59 // APM 16 bit protected mode interface connect
60 static void
61 handle_155302(struct bregs *regs)
62 {
63     regs->bx = (u32)entry_apm16;
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
76     regs->ebx = (u32)entry_apm32;
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
108 void
109 apm_shutdown(void)
110 {
111     irq_disable();
112     out_str("Shutdown");
113     for (;;)
114         hlt();
115 }
116
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:
133         apm_shutdown();
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
198 void
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 }
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 }