]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/acpi.cpp
a3915cc7c8bf01cffdd905b3e6da0639cb910bc7
[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
121 Acpi_rsdt const *Acpi::_rsdt;
122 Acpi_xsdt const *Acpi::_xsdt;
123 bool Acpi::_init_done;
124
125 PUBLIC static
126 void
127 Acpi::init_virt()
128 {
129   if (_init_done)
130     return;
131   _init_done = 1;
132
133   printf("ACPI-Init\n");
134
135   Acpi_rsdp const *rsdp = Acpi_rsdp::locate();
136   if (!rsdp)
137     {
138       printf("ACPI: Could not find RSDP, skip init\n");
139       return;
140     }
141
142   printf("ACPI: RSDP = %p   pRSDT = %08x   pXSDT = %16llx\n",
143          rsdp, rsdp->rsdt_phys, rsdp->xsdt_phys);
144   printf("ACPI: OEM: %c%c%c%c%c%c\n",
145          rsdp->oem[0], rsdp->oem[1], rsdp->oem[2],
146          rsdp->oem[3], rsdp->oem[4], rsdp->oem[5]);
147
148   if (rsdp->rev && rsdp->xsdt_phys)
149     {
150       Acpi_xsdt const *x = Kmem::dev_map.map((const Acpi_xsdt *)rsdp->xsdt_phys);
151       if (x == (Acpi_xsdt const *)~0UL)
152         printf("ACPI: Could not map XSDT\n");
153       else if (!x->checksum_ok())
154         printf("ACPI: Checksum mismatch in XSDT\n");
155       else
156         _xsdt = x;
157     }
158
159   if (rsdp->rsdt_phys)
160     {
161       Acpi_rsdt const *r = Kmem::dev_map.map((const Acpi_rsdt *)rsdp->rsdt_phys);
162       if (r == (Acpi_rsdt const *)~0UL)
163         printf("ACPI: Could not map RSDT\n");
164       else if (!r->checksum_ok())
165         printf("ACPI: Checksum mismatch in RSDT\n");
166       else
167         _rsdt = r;
168     }
169 }
170
171 PUBLIC static
172 template< typename T >
173 T
174 Acpi::find(const char *s)
175 {
176   T a = 0;
177   init_virt();
178   if (_xsdt)
179     a = static_cast<T>(_xsdt->find(s));
180   else if (_rsdt)
181     a = static_cast<T>(_rsdt->find(s));
182   return a;
183 }
184
185 IMPLEMENT
186 Acpi_rsdt const *
187 Acpi_rsdp::rsdt() const
188 {
189   return (Acpi_rsdt const*)rsdt_phys;
190 }
191
192 IMPLEMENT
193 Acpi_xsdt const *
194 Acpi_rsdp::xsdt() const
195 {
196   if (rev == 0)
197     return 0;
198   return (Acpi_xsdt const*)xsdt_phys;
199 }
200
201 IMPLEMENT
202 bool
203 Acpi_rsdp::checksum_ok() const
204 {
205   // ACPI 1.0 checksum
206   Unsigned8 sum = 0;
207   for (unsigned i = 0; i < 20; i++)
208     sum += *((Unsigned8 *)this + i);
209
210   if (sum)
211     return false;
212
213   if (rev == 0)
214     return true;
215
216   // Extended Checksum
217   for (unsigned i = 0; i < len && i < 4096; ++i)
218     sum += *((Unsigned8 *)this + i);
219
220   return !sum;
221 }
222
223 IMPLEMENT
224 bool
225 Acpi_table_head::checksum_ok() const
226 {
227   Unsigned8 sum = 0;
228   for (unsigned i = 0; i < len && i < 4096; ++i)
229     sum += *((Unsigned8 *)this + i);
230
231   return !sum;
232 }
233
234 PUBLIC
235 template< typename T >
236 Acpi_table_head const *
237 Acpi_sdt<T>::find(char const sig[4]) const
238 {
239   for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i)
240     {
241       Acpi_table_head const *t = Kmem::dev_map.lookup((Acpi_table_head const*)ptrs[i]);
242       if (t == (Acpi_table_head const *)~0UL)
243         continue;
244
245       if (t->signature[0] == sig[0]
246           && t->signature[1] == sig[1]
247           && t->signature[2] == sig[2]
248           && t->signature[3] == sig[3]
249           && t->checksum_ok())
250         return t;
251     }
252
253   return 0;
254 }
255
256 PUBLIC
257 Acpi_madt::Apic_head const *
258 Acpi_madt::find(Unsigned8 type, int idx) const
259 {
260   for (unsigned i = 0; i < len-sizeof(Acpi_madt);)
261     {
262       Apic_head const *a = (Apic_head const *)(data + i);
263       //printf("a=%p, a->type=%u, a->len=%u\n", a, a->type, a->len);
264       if (a->type == type)
265         {
266           if (!idx)
267             return a;
268           --idx;
269         }
270       i += a->len;
271     }
272
273   return 0;
274 }
275
276 // ------------------------------------------------------------------------
277 IMPLEMENTATION [ia32,amd64]:
278
279 IMPLEMENT
280 Acpi_rsdp const *
281 Acpi_rsdp::locate()
282 {
283   enum
284   {
285     ACPI20_PC99_RSDP_START = 0x0e0000,
286     ACPI20_PC99_RSDP_END =   0x100000
287   };
288
289   for (Address p = ACPI20_PC99_RSDP_START; p < ACPI20_PC99_RSDP_END; p += 16)
290     {
291       Acpi_rsdp const* r = (Acpi_rsdp const *)p;
292       if (r->signature[0] == 'R' &&
293           r->signature[1] == 'S' &&
294           r->signature[2] == 'D' &&
295           r->signature[3] == ' ' &&
296           r->signature[4] == 'P' &&
297           r->signature[5] == 'T' &&
298           r->signature[6] == 'R' &&
299           r->signature[7] == ' ' &&
300           r->checksum_ok())
301         return r;
302     }
303
304   return 0;
305 }