]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/acpi.cpp
update
[l4.git] / kernel / fiasco / src / kern / acpi.cpp
1 INTERFACE:
2
3 #include <types.h>
4
5 class Acpi_gas
6 {
7 public:
8   enum Type { System_mem = 0, System_io = 1, Pci_cfg_mem = 2 };
9   Unsigned8  id;
10   Unsigned8  width;
11   Unsigned8  offset;
12   Unsigned8  access_size;
13   Unsigned64 addr;
14 } __attribute__((packed));
15
16
17
18 class Acpi_table_head
19 {
20 public:
21   char       signature[4];
22   Unsigned32 len;
23   Unsigned8  rev;
24   Unsigned8  chk_sum;
25   char       oem_id[6];
26   char       oem_tid[8];
27   Unsigned32 oem_rev;
28   Unsigned32 creator_id;
29   Unsigned32 creator_rev;
30
31   bool checksum_ok() const;
32 } __attribute__((packed));
33
34
35 template< typename T >
36 class Acpi_sdt : public Acpi_table_head
37 {
38 public:
39   T ptrs[0];
40
41 } __attribute__((packed));
42
43 typedef Acpi_sdt<Unsigned32> Acpi_rsdt;
44 typedef Acpi_sdt<Unsigned64> Acpi_xsdt;
45
46 class Acpi_rsdp
47 {
48 public:
49   char       signature[8];
50   Unsigned8  chk_sum;
51   char       oem[6];
52   Unsigned8  rev;
53   Unsigned32 rsdt_phys;
54   Unsigned32 len;
55   Unsigned64 xsdt_phys;
56   Unsigned8  ext_chk_sum;
57   char       reserved[3];
58
59   Acpi_rsdt const *rsdt() const;
60   Acpi_xsdt const *xsdt() const;
61
62   bool checksum_ok() const;
63
64   static Acpi_rsdp const *locate();
65 } __attribute__((packed));
66
67 class Acpi
68 {
69 public:
70   static Acpi_rsdt const *rsdt() { return _rsdt; }
71   static Acpi_xsdt const *xsdt() { return _xsdt; }
72
73 private:
74   static Acpi_rsdt const *_rsdt;
75   static Acpi_xsdt const *_xsdt;
76   static bool _init_done;
77 };
78
79 class Acpi_madt : public Acpi_table_head
80 {
81 public:
82   enum Type
83   { LAPIC, IOAPIC, Irq_src_ovr, NMI, LAPIC_NMI, LAPIC_adr_ovr, IOSAPIC,
84     LSAPIC, Irq_src };
85
86   struct Apic_head
87   {
88     Unsigned8 type;
89     Unsigned8 len;
90   } __attribute__((packed));
91
92   struct Io_apic : public Apic_head
93   {
94     Unsigned8 id;
95     Unsigned8 res;
96     Unsigned32 adr;
97     Unsigned32 irq_base;
98   } __attribute__((packed));
99
100   struct Irq_source : public Apic_head
101   {
102     Unsigned8  bus;
103     Unsigned8  src;
104     Unsigned32 irq;
105     Unsigned16 flags;
106   } __attribute__((packed));
107
108 public:
109   Unsigned32 local_apic;
110   Unsigned32 apic_flags;
111
112 private:
113   char data[0];
114 } __attribute__((packed));
115
116
117 IMPLEMENTATION:
118
119 #include "kmem.h"
120 #include <cctype>
121
122 Acpi_rsdt const *Acpi::_rsdt;
123 Acpi_xsdt const *Acpi::_xsdt;
124 bool Acpi::_init_done;
125
126
127 static void
128 print_acpi_id(char const *id, unsigned len)
129 {
130   char ID[len];
131   for (unsigned i = 0; i < len; ++i)
132     ID[i] = isalnum(id[i]) ? id[i] : '.';
133   printf("%.*s", len, ID);
134 }
135
136 PUBLIC void
137 Acpi_rsdp::print_info() const
138 {
139   printf("ACPI: RSDP[%p]\tr%02x OEM:", this, rev);
140   print_acpi_id(oem, 6);
141   printf("\n");
142 }
143
144 PUBLIC void
145 Acpi_table_head::print_info() const
146 {
147   printf("ACPI: ");
148   print_acpi_id(signature, 4);
149   printf("[%p]\tr%02x OEM:", this, rev);
150   print_acpi_id(oem_id, 6);
151   printf(" OEMTID:");
152   print_acpi_id(oem_tid, 8);
153   printf("\n");
154 }
155
156 PUBLIC template< typename T >
157 void
158 Acpi_sdt<T>::print_summary() const
159 {
160   for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i)
161     {
162       Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)ptrs[i]);
163       if (t == (Acpi_table_head const *)~0UL)
164         continue;
165
166       t->print_info();
167     }
168 }
169
170
171 PUBLIC static
172 void
173 Acpi::init_virt()
174 {
175   if (_init_done)
176     return;
177   _init_done = 1;
178
179   printf("ACPI-Init\n");
180
181   Acpi_rsdp const *rsdp = Acpi_rsdp::locate();
182   if (!rsdp)
183     {
184       printf("ACPI: Could not find RSDP, skip init\n");
185       return;
186     }
187
188   rsdp->print_info();
189
190   if (rsdp->rev && rsdp->xsdt_phys)
191     {
192       Acpi_xsdt const *x = Kmem::dev_map.map((const Acpi_xsdt *)rsdp->xsdt_phys);
193       if (x == (Acpi_xsdt const *)~0UL)
194         printf("ACPI: Could not map XSDT\n");
195       else if (!x->checksum_ok())
196         printf("ACPI: Checksum mismatch in XSDT\n");
197       else
198         {
199           _xsdt = x;
200           x->print_info();
201         }
202     }
203
204   if (rsdp->rsdt_phys)
205     {
206       Acpi_rsdt const *r = Kmem::dev_map.map((const Acpi_rsdt *)rsdp->rsdt_phys);
207       if (r == (Acpi_rsdt const *)~0UL)
208         printf("ACPI: Could not map RSDT\n");
209       else if (!r->checksum_ok())
210         printf("ACPI: Checksum mismatch in RSDT\n");
211       else
212         {
213           _rsdt = r;
214           r->print_info();
215         }
216     }
217
218   if (_xsdt)
219     _xsdt->print_summary();
220   else if (_rsdt)
221     _rsdt->print_summary();
222 }
223
224 PUBLIC static
225 template< typename T >
226 T
227 Acpi::find(const char *s)
228 {
229   T a = 0;
230   init_virt();
231   if (_xsdt)
232     a = static_cast<T>(_xsdt->find(s));
233   else if (_rsdt)
234     a = static_cast<T>(_rsdt->find(s));
235   return a;
236 }
237
238 IMPLEMENT
239 Acpi_rsdt const *
240 Acpi_rsdp::rsdt() const
241 {
242   return (Acpi_rsdt const*)rsdt_phys;
243 }
244
245 IMPLEMENT
246 Acpi_xsdt const *
247 Acpi_rsdp::xsdt() const
248 {
249   if (rev == 0)
250     return 0;
251   return (Acpi_xsdt const*)xsdt_phys;
252 }
253
254 IMPLEMENT
255 bool
256 Acpi_rsdp::checksum_ok() const
257 {
258   // ACPI 1.0 checksum
259   Unsigned8 sum = 0;
260   for (unsigned i = 0; i < 20; i++)
261     sum += *((Unsigned8 *)this + i);
262
263   if (sum)
264     return false;
265
266   if (rev == 0)
267     return true;
268
269   // Extended Checksum
270   for (unsigned i = 0; i < len && i < 4096; ++i)
271     sum += *((Unsigned8 *)this + i);
272
273   return !sum;
274 }
275
276 IMPLEMENT
277 bool
278 Acpi_table_head::checksum_ok() const
279 {
280   Unsigned8 sum = 0;
281   for (unsigned i = 0; i < len && i < 4096; ++i)
282     sum += *((Unsigned8 *)this + i);
283
284   return !sum;
285 }
286
287 PUBLIC
288 template< typename T >
289 Acpi_table_head const *
290 Acpi_sdt<T>::find(char const sig[4]) const
291 {
292   for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i)
293     {
294       Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)ptrs[i]);
295       if (t == (Acpi_table_head const *)~0UL)
296         continue;
297
298       if (t->signature[0] == sig[0]
299           && t->signature[1] == sig[1]
300           && t->signature[2] == sig[2]
301           && t->signature[3] == sig[3]
302           && t->checksum_ok())
303         return t;
304     }
305
306   return 0;
307 }
308
309 PUBLIC
310 Acpi_madt::Apic_head const *
311 Acpi_madt::find(Unsigned8 type, int idx) const
312 {
313   for (unsigned i = 0; i < len-sizeof(Acpi_madt);)
314     {
315       Apic_head const *a = (Apic_head const *)(data + i);
316       //printf("a=%p, a->type=%u, a->len=%u\n", a, a->type, a->len);
317       if (a->type == type)
318         {
319           if (!idx)
320             return a;
321           --idx;
322         }
323       i += a->len;
324     }
325
326   return 0;
327 }
328
329 // ------------------------------------------------------------------------
330 IMPLEMENTATION [ia32,amd64]:
331
332 IMPLEMENT
333 Acpi_rsdp const *
334 Acpi_rsdp::locate()
335 {
336   enum
337   {
338     ACPI20_PC99_RSDP_START = 0x0e0000,
339     ACPI20_PC99_RSDP_END =   0x100000
340   };
341
342   for (Address p = ACPI20_PC99_RSDP_START; p < ACPI20_PC99_RSDP_END; p += 16)
343     {
344       Acpi_rsdp const* r = (Acpi_rsdp const *)p;
345       if (r->signature[0] == 'R' &&
346           r->signature[1] == 'S' &&
347           r->signature[2] == 'D' &&
348           r->signature[3] == ' ' &&
349           r->signature[4] == 'P' &&
350           r->signature[5] == 'T' &&
351           r->signature[6] == 'R' &&
352           r->signature[7] == ' ' &&
353           r->checksum_ok())
354         return r;
355     }
356
357   return 0;
358 }