coverity appeasement
[minix.git] / kernel / arch / i386 / acpi.c
blob225467ba2c4bdfeed8b4ace262bb646bfc373229
2 #include <string.h>
4 #include "kernel/kernel.h"
5 #include "acpi.h"
6 #include "arch_proto.h"
8 typedef int ((* acpi_read_t)(phys_bytes addr, void * buff, size_t size));
10 struct acpi_rsdp acpi_rsdp;
12 static acpi_read_t read_func;
14 #define MAX_RSDT 35 /* ACPI defines 35 signatures */
16 static struct acpi_rsdt {
17 struct acpi_sdt_header hdr;
18 u32_t data[MAX_RSDT];
19 } rsdt;
21 static struct {
22 char signature [ACPI_SDT_SIGNATURE_LEN + 1];
23 size_t length;
24 } sdt_trans[MAX_RSDT];
26 static int sdt_count;
28 static int acpi_check_csum(struct acpi_sdt_header * tb, size_t size)
30 u8_t total = 0;
31 int i;
32 for (i = 0; i < size; i++)
33 total += ((unsigned char *)tb)[i];
34 return total == 0 ? 0 : -1;
37 static int acpi_check_signature(const char * orig, const char * match)
39 return strncmp(orig, match, ACPI_SDT_SIGNATURE_LEN);
42 static u32_t acpi_phys2vir(u32_t p)
44 if(!vm_running) {
45 printf("acpi: returning 0x%lx as vir addr\n", p);
46 return p;
48 panic("acpi: can't get virtual address of arbitrary physical address");
51 static int acpi_phys_copy(phys_bytes phys, void *target, size_t len)
53 if(!vm_running) {
54 memcpy(target, (void *) phys, len);
55 return 0;
57 panic("can't acpi_phys_copy with vm");
60 static int acpi_read_sdt_at(phys_bytes addr,
61 struct acpi_sdt_header * tb,
62 size_t size,
63 const char * name)
65 struct acpi_sdt_header hdr;
67 /* if NULL is supplied, we only return the size of the table */
68 if (tb == NULL) {
69 if (read_func(addr, &hdr, sizeof(struct acpi_sdt_header))) {
70 printf("ERROR acpi cannot read %s header\n", name);
71 return -1;
74 return hdr.length;
77 if (read_func(addr, tb, sizeof(struct acpi_sdt_header))) {
78 printf("ERROR acpi cannot read %s header\n", name);
79 return -1;
82 if (acpi_check_signature(tb->signature, name)) {
83 printf("ERROR acpi %s signature does not match\n", name);
84 return -1;
87 if (size < tb->length) {
88 printf("ERROR acpi buffer too small for %s\n", name);
89 return -1;
92 if (read_func(addr, tb, size)) {
93 printf("ERROR acpi cannot read %s\n", name);
94 return -1;
97 if (acpi_check_csum(tb, tb->length)) {
98 printf("ERROR acpi %s checksum does not match\n", name);
99 return -1;
102 return tb->length;
105 phys_bytes acpi_get_table_base(const char * name)
107 int i;
109 for(i = 0; i < sdt_count; i++) {
110 if (strncmp(name, sdt_trans[i].signature,
111 ACPI_SDT_SIGNATURE_LEN) == 0)
112 return (phys_bytes) rsdt.data[i];
115 return (phys_bytes) NULL;
118 size_t acpi_get_table_length(const char * name)
120 int i;
122 for(i = 0; i < sdt_count; i++) {
123 if (strncmp(name, sdt_trans[i].signature,
124 ACPI_SDT_SIGNATURE_LEN) == 0)
125 return sdt_trans[i].length;
128 return 0;
131 static void * acpi_madt_get_typed_item(struct acpi_madt_hdr * hdr,
132 unsigned char type,
133 unsigned idx)
135 u8_t * t, * end;
136 int i;
138 t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr);
139 end = (u8_t *) hdr + hdr->hdr.length;
141 i = 0;
142 while(t < end) {
143 if (type == ((struct acpi_madt_item_hdr *) t)->type) {
144 if (i == idx)
145 return t;
146 else
147 i++;
149 t += ((struct acpi_madt_item_hdr *) t)->length;
152 return NULL;
155 #if 0
156 static void * acpi_madt_get_item(struct acpi_madt_hdr * hdr,
157 unsigned idx)
159 u8_t * t, * end;
160 int i;
162 t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr);
163 end = (u8_t *) hdr + hdr->hdr.length;
165 for(i = 0 ; i <= idx && t < end; i++) {
166 if (i == idx)
167 return t;
168 t += ((struct acpi_madt_item_hdr *) t)->length;
171 return NULL;
173 #endif
175 static int acpi_rsdp_test(void * buff)
177 struct acpi_rsdp * rsdp = (struct acpi_rsdp *) buff;
179 if (!platform_tbl_checksum_ok(buff, 20))
180 return 0;
181 if (strncmp(rsdp->signature, "RSD PTR ", 8))
182 return 0;
184 return 1;
187 static int get_acpi_rsdp(void)
189 u16_t ebda;
191 * Read 40:0Eh - to find the starting address of the EBDA.
193 acpi_phys_copy (0x40E, &ebda, sizeof(ebda));
194 if (ebda) {
195 ebda <<= 4;
196 if(platform_tbl_ptr(ebda, ebda + 0x400, 16, &acpi_rsdp,
197 sizeof(acpi_rsdp), &machine.acpi_rsdp,
198 acpi_rsdp_test))
199 return 1;
202 /* try BIOS read only mem space */
203 if(platform_tbl_ptr(0xE0000, 0x100000, 16, &acpi_rsdp,
204 sizeof(acpi_rsdp), &machine.acpi_rsdp,
205 acpi_rsdp_test))
206 return 1;
208 machine.acpi_rsdp = 0; /* RSDP cannot be found at this address therefore
209 it is a valid negative value */
210 return 0;
213 void acpi_init(void)
215 int s, i;
216 read_func = acpi_phys_copy;
218 if (!get_acpi_rsdp()) {
219 printf("WARNING : Cannot configure ACPI\n");
220 return;
223 s = acpi_read_sdt_at(acpi_rsdp.rsdt_addr, (struct acpi_sdt_header *) &rsdt,
224 sizeof(struct acpi_rsdt), ACPI_SDT_SIGNATURE(RSDT));
226 sdt_count = (s - sizeof(struct acpi_sdt_header)) / sizeof(u32_t);
228 for (i = 0; i < sdt_count; i++) {
229 struct acpi_sdt_header hdr;
230 int j;
231 if (read_func(rsdt.data[i], &hdr, sizeof(struct acpi_sdt_header))) {
232 printf("ERROR acpi cannot read header at 0x%x\n",
233 rsdt.data[i]);
234 return;
237 for (j = 0 ; j < ACPI_SDT_SIGNATURE_LEN; j++)
238 sdt_trans[i].signature[j] = hdr.signature[j];
239 sdt_trans[i].signature[ACPI_SDT_SIGNATURE_LEN] = '\0';
240 sdt_trans[i].length = hdr.length;
244 struct acpi_madt_ioapic * acpi_get_ioapic_next(void)
246 static unsigned idx = 0;
247 static struct acpi_madt_hdr * madt_hdr;
249 struct acpi_madt_ioapic * ret;
251 if (idx == 0) {
252 madt_hdr = (struct acpi_madt_hdr *)
253 acpi_phys2vir(acpi_get_table_base("APIC"));
254 if (madt_hdr == NULL)
255 return NULL;
258 ret = (struct acpi_madt_ioapic *)
259 acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_IOAPIC, idx);
260 if (ret)
261 idx++;
263 return ret;
266 struct acpi_madt_lapic * acpi_get_lapic_next(void)
268 static unsigned idx = 0;
269 static struct acpi_madt_hdr * madt_hdr;
271 struct acpi_madt_lapic * ret;
273 if (idx == 0) {
274 madt_hdr = (struct acpi_madt_hdr *)
275 acpi_phys2vir(acpi_get_table_base("APIC"));
276 if (madt_hdr == NULL)
277 return NULL;
280 for (;;) {
281 ret = (struct acpi_madt_lapic *)
282 acpi_madt_get_typed_item(madt_hdr,
283 ACPI_MADT_TYPE_LAPIC, idx);
284 if (!ret)
285 break;
287 idx++;
289 /* report only usable CPUs */
290 if (ret->flags & 1)
291 break;
294 return ret;