]> git.ipfire.org Git - ipfire-2.x.git/blame - src/hwinfo/src/hd/cpu.c
Kleiner netter neuer Versuch.
[ipfire-2.x.git] / src / hwinfo / src / hd / cpu.c
CommitLineData
a6316ce4
MT
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5
6#ifdef __ia64__
7#include <fcntl.h>
8#include <errno.h>
9#include <stdint.h>
10#include <sys/mman.h>
11#endif
12
13#ifdef __powerpc__
14#include <sys/utsname.h>
15#endif
16
17#include "hd.h"
18#include "hd_int.h"
19#include "klog.h"
20#include "cpu.h"
21
22/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23 * cpu info
24 *
25 * Note: on other architectures, entries differ (cf. Alpha)!!!
26 *
27 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28 */
29
30static void read_cpuinfo(hd_data_t *hd_data);
31static void dump_cpu_data(hd_data_t *hd_data);
32
33#if defined(__i386__) || defined(__x86_64__)
34static inline unsigned units_per_cpu();
35#endif
36#ifdef __ia64__
37static int ia64DetectSMP(hd_data_t *hd_data);
38#endif
39
40void hd_scan_cpu(hd_data_t *hd_data)
41{
42 hd_t *hd0, *hd;
43 int i, cpus;
44 unsigned u;
45
46 if(!hd_probe_feature(hd_data, pr_cpu)) return;
47
48 hd_data->module = mod_cpu;
49
50 /* some clean-up */
51 remove_hd_entries(hd_data);
52 hd_data->cpu = free_str_list(hd_data->cpu);
53
54 PROGRESS(1, 0, "cpuinfo");
55
56 read_cpuinfo(hd_data);
57
58 for(hd0 = hd_data->hd; hd0; hd0 = hd0->next) {
59 if(hd0->base_class.id == bc_internal && hd0->sub_class.id == sc_int_cpu) break;
60 }
61
62 if(!hd0 || hd0->next) return; /* 0 or > 1 entries */
63
64 /* only one entry, maybe UP kernel on SMP system */
65
66 cpus = 0;
67
68#ifdef __ia64__
69 cpus = ia64DetectSMP(hd_data);
70#endif
71
72 for(i = 1; i < cpus; i++) {
73 hd = add_hd_entry(hd_data, __LINE__, 0);
74 u = hd->idx;
75 hd_copy(hd, hd0);
76 hd->idx = u;
77 hd->slot = i;
78 }
79}
80
81
82void read_cpuinfo(hd_data_t *hd_data)
83{
84 hd_t *hd;
85 unsigned cpus = 0;
86 cpu_info_t *ct;
87 str_list_t *sl;
88
89#if defined(__i386__) || defined (__x86_64__)
90 char model_id[80], vendor_id[80], features[0x100];
91 unsigned bogo, mhz, cache, family, model, stepping;
92 char *t0, *t;
93#endif
94
95#ifdef __ia64__
96 char model_id[80], vendor_id[80], features[0x100];
97 unsigned mhz, stepping;
98 char *t0, *t;
99#endif
100
101#ifdef __alpha__
102 char model_id[80], system_id[80], serial_number[80], platform[80];
103 unsigned cpu_variation, cpu_revision, u, hz;
104 cpu_info_t *ct1;
105#endif
106
107#ifdef __PPC__
108 char model_id[80], vendor_id[80], motherboard[80];
109 unsigned bogo, mhz, cache, family, model, stepping;
110 struct utsname un;
111#endif
112
113#ifdef __sparc__
114 char cpu_id[80], fpu_id[80], promlib[80], prom[80], type[80], mmu[80];
115 unsigned u, bogo, cpus_active;
116#endif
117
118#if defined(__s390__) || defined(__s390x__)
119 char vendor_id[80];
120 unsigned bogo;
121 unsigned u0, u1, u2, u3;
122#endif
123
124 hd_data->cpu = read_file(PROC_CPUINFO, 0, 0);
125 if((hd_data->debug & HD_DEB_CPU)) dump_cpu_data(hd_data);
126 if(!hd_data->cpu) return;
127
128#ifdef __alpha__
129 *model_id = *system_id = *serial_number = *platform = 0;
130 cpu_variation = cpu_revision = hz = 0;
131
132 for(sl = hd_data->cpu; sl; sl = sl->next) {
133 if(sscanf(sl->str, "cpu model : %79[^\n]", model_id) == 1) continue;
134 if(sscanf(sl->str, "system type : %79[^\n]", system_id) == 1) continue;
135 if(sscanf(sl->str, "cpu variation : %u", &cpu_variation) == 1) continue;
136 if(sscanf(sl->str, "cpu revision : %u", &cpu_revision) == 1) continue;
137 if(sscanf(sl->str, "system serial number : %79[^\n]", serial_number) == 1) continue;
138 if(sscanf(sl->str, "cpus detected : %u", &cpus) == 1) continue;
139 if(sscanf(sl->str, "cycle frequency [Hz] : %u", &hz) == 1) continue;
140 if(sscanf(sl->str, "system variation : %79[^\n]", platform) == 1) continue;
141 }
142
143 if(*model_id || *system_id) { /* at least one of those */
144 ct = new_mem(sizeof *ct);
145 ct->architecture = arch_alpha;
146 if(model_id) ct->model_name = new_str(model_id);
147 if(system_id) ct->vend_name = new_str(system_id);
148 if(strncmp(serial_number, "MILO", 4) == 0)
149 hd_data->boot = boot_milo;
150 else
151 hd_data->boot = boot_aboot;
152
153 ct->family = cpu_variation;
154 ct->model = cpu_revision;
155 ct->stepping = 0;
156 ct->cache = 0;
157 ct->clock = (hz + 500000) / 1000000;
158
159 if(platform && strcmp(platform, "0")) {
160 ct->platform = new_str(platform);
161 }
162
163 if(!cpus) cpus = 1; /* at least 1 machine had a "cpus: 0" entry... */
164 for(u = 0; u < cpus; u++) {
165 hd = add_hd_entry(hd_data, __LINE__, 0);
166 hd->base_class.id = bc_internal;
167 hd->sub_class.id = sc_int_cpu;
168 hd->slot = u;
169 hd->detail = new_mem(sizeof *hd->detail);
170 hd->detail->type = hd_detail_cpu;
171 if(u) {
172 hd->detail->cpu.data = ct1 = new_mem(sizeof *ct);
173 *ct1 = *ct;
174 ct1->model_name = new_str(ct1->model_name);
175 ct1->vend_name = new_str(ct1->vend_name);
176 ct1->platform = new_str(ct1->platform);
177 }
178 else {
179 hd->detail->cpu.data = ct;
180 }
181 }
182
183 }
184#endif /* __alpha__ */
185
186
187#ifdef __sparc__
188 *cpu_id = *fpu_id = *promlib = *prom = *type = *mmu = 0;
189 cpus = cpus_active = bogo = 0;
190
191 for(sl = hd_data->cpu; sl; sl = sl->next) {
192 if(sscanf(sl->str, "cpu : %79[^\n]", cpu_id) == 1);
193 if(sscanf(sl->str, "fpu : %79[^\n]", fpu_id) == 1);
194 if(sscanf(sl->str, "promlib : %79[^\n]", promlib) == 1);
195 if(sscanf(sl->str, "prom : %79[^\n]", prom) == 1);
196 if(sscanf(sl->str, "type : %79[^\n]", type) == 1);
197 if(sscanf(sl->str, "ncpus probed : %u", &cpus) == 1);
198 if(sscanf(sl->str, "ncpus active : %u", &cpus_active) == 1);
199 if(sscanf(sl->str, "BogoMips : %u", &bogo) == 1);
200 if(sscanf(sl->str, "MMU Type : %79[^\n]", mmu) == 1);
201 }
202
203 if(*cpu_id) {
204 for(u = 0; u < cpus; u++) {
205 ct = new_mem(sizeof *ct);
206 ct->platform = new_str (type);
207 if(strcmp (type, "sun4u") == 0)
208 ct->architecture = arch_sparc64;
209 else
210 ct->architecture = arch_sparc;
211
212 ct->model_name = new_str(cpu_id);
213 hd_data->boot = boot_silo;
214
215 hd = add_hd_entry(hd_data, __LINE__, 0);
216 hd->base_class.id = bc_internal;
217 hd->sub_class.id = sc_int_cpu;
218 hd->slot = u;
219 hd->detail = new_mem(sizeof *hd->detail);
220 hd->detail->type = hd_detail_cpu;
221 hd->detail->cpu.data = ct;
222 }
223 }
224#endif /* sparc */
225
226
227#if defined(__i386__) || defined (__x86_64__)
228 *model_id = *vendor_id = *features = 0;
229 bogo = mhz = cache = family = model = stepping = 0;
230
231 for(sl = hd_data->cpu; sl; sl = sl->next) {
232 if(sscanf(sl->str, "model name : %79[^\n]", model_id) == 1);
233 if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1);
234 if(sscanf(sl->str, "flags : %255[^\n]", features) == 1);
235 if(sscanf(sl->str, "bogomips : %u", &bogo) == 1);
236 if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1);
237 if(sscanf(sl->str, "cache size : %u KB", &cache) == 1);
238
239 if(sscanf(sl->str, "cpu family : %u", &family) == 1);
240 if(sscanf(sl->str, "model : %u", &model) == 1);
241 if(sscanf(sl->str, "stepping : %u", &stepping) == 1);
242
243 if(strstr(sl->str, "processor") == sl->str || !sl->next) { /* EOF */
244 if(*model_id || *vendor_id) { /* at least one of those */
245 ct = new_mem(sizeof *ct);
246#ifdef __i386__
247 ct->architecture = arch_intel;
248#endif
249#ifdef __x86_64__
250 ct->architecture = arch_x86_64;
251#endif
252 if(model_id) ct->model_name = new_str(model_id);
253 if(vendor_id) ct->vend_name = new_str(vendor_id);
254 ct->family = family;
255 ct->model = model;
256 ct->stepping = stepping;
257 ct->cache = cache;
258 hd_data->boot = boot_grub;
259
260 /* round clock to typical values */
261 if(mhz >= 38 && mhz <= 42)
262 mhz = 40;
263 else if(mhz >= 88 && mhz <= 92)
264 mhz = 90;
265 else {
266 unsigned u, v;
267
268 u = (mhz + 2) % 100;
269 v = (mhz + 2) / 100;
270 if(u <= 4)
271 u = 2;
272 else if(u >= 25 && u <= 29)
273 u = 25 + 2;
274 else if(u >= 33 && u <= 37)
275 u = 33 + 2;
276 else if(u >= 50 && u <= 54)
277 u = 50 + 2;
278 else if(u >= 66 && u <= 70)
279 u = 66 + 2;
280 else if(u >= 75 && u <= 79)
281 u = 75 + 2;
282 else if(u >= 80 && u <= 84) /* there are 180MHz PPros */
283 u = 80 + 2;
284 u -= 2;
285 mhz = v * 100 + u;
286 }
287
288 ct->clock = mhz;
289
290 hd = add_hd_entry(hd_data, __LINE__, 0);
291 hd->base_class.id = bc_internal;
292 hd->sub_class.id = sc_int_cpu;
293 hd->slot = cpus;
294 hd->detail = new_mem(sizeof *hd->detail);
295 hd->detail->type = hd_detail_cpu;
296 hd->detail->cpu.data = ct;
297
298 if(*features) {
299 for(t0 = features; (t = strsep(&t0, " ")); ) {
300 add_str_list(&ct->features, t);
301 if(!strcmp(t, "ht")) ct->units = units_per_cpu();
302 }
303 }
304
305 *model_id = *vendor_id = 0;
306 bogo = mhz = cache = family = model= 0;
307 cpus++;
308 }
309 }
310 }
311#endif /* __i386__ || __x86_64__ */
312
313
314#ifdef __PPC__
315 *model_id = *vendor_id = *motherboard = 0;
316 bogo = mhz = cache = family = model = stepping = 0;
317
318 for(sl = hd_data->cpu; sl; sl = sl->next) {
319 if(sscanf(sl->str, "machine : %79[^\n]", vendor_id) == 1);
320 }
321
322 for(sl = hd_data->cpu; sl; sl = sl->next) {
323 if(sscanf(sl->str, "cpu : %79[^\n]", model_id) == 1);
324 if(sscanf(sl->str, "motherboard : %79[^\n]", motherboard) == 1);
325 if(sscanf(sl->str, "bogomips : %u", &bogo) == 1);
326 if(sscanf(sl->str, "clock : %u", &mhz) == 1);
327 if(sscanf(sl->str, "L2 cache : %u KB", &cache) == 1);
328
329 if(strstr(sl->str, "processor") == sl->str || !sl->next) { /* EOF */
330 if(*model_id) { /* at least one of those */
331 ct = new_mem(sizeof *ct);
332 ct->architecture = arch_ppc;
333 if(model_id) {
334 ct->model_name = new_str(model_id);
335 }
336
337 if(!uname(&un))
338 if(strstr(un.machine,"ppc64"))
339 ct->architecture = arch_ppc64;
340
341 if(vendor_id) ct->vend_name = new_str(vendor_id);
342 if(motherboard) ct->platform = new_str(motherboard);
343 ct->family = family;
344 ct->model = model;
345 ct->stepping = stepping;
346 ct->cache = cache;
347 hd_data->boot = boot_ppc;
348 ct->clock = mhz;
349
350 hd = add_hd_entry(hd_data, __LINE__, 0);
351 hd->base_class.id = bc_internal;
352 hd->sub_class.id = sc_int_cpu;
353 hd->slot = cpus;
354 hd->detail = new_mem(sizeof *hd->detail);
355 hd->detail->type = hd_detail_cpu;
356 hd->detail->cpu.data = ct;
357
358 if(ct->vend_name && !strcmp(ct->vend_name, "PowerBook") && !hd_data->color_code) {
359 hd_data->color_code = 7; // black
360 }
361
362 *model_id = 0;
363 bogo = mhz = cache = family = model= 0;
364 cpus++;
365 }
366 }
367 }
368#endif /* __PPC__ */
369
370
371#ifdef __ia64__
372 *model_id = *vendor_id = *features = 0;
373 mhz = stepping = 0;
374
375 for(sl = hd_data->cpu; sl; sl = sl->next) {
376 if(sscanf(sl->str, "family : %79[^\n]", model_id) == 1);
377 if(sscanf(sl->str, "vendor : %79[^\n]", vendor_id) == 1);
378 if(sscanf(sl->str, "features : %255[^\n]", features) == 1);
379 if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1);
380 if(sscanf(sl->str, "revision : %u", &stepping) == 1);
381
382 if(strstr(sl->str, "processor") == sl->str || !sl->next) { /* EOF */
383 if(*model_id || *vendor_id) { /* at least one of those */
384 ct = new_mem(sizeof *ct);
385 ct->architecture = arch_ia64;
386 if(model_id) ct->model_name = new_str(model_id);
387 if(vendor_id) ct->vend_name = new_str(vendor_id);
388 ct->stepping = stepping;
389 hd_data->boot = boot_elilo;
390
391 /* round clock to typical values */
392 if(mhz >= 38 && mhz <= 42)
393 mhz = 40;
394 else if(mhz >= 88 && mhz <= 92)
395 mhz = 90;
396 else {
397 unsigned u, v;
398
399 u = (mhz + 2) % 100;
400 v = (mhz + 2) / 100;
401 if(u <= 4)
402 u = 2;
403 else if(u >= 25 && u <= 29)
404 u = 25 + 2;
405 else if(u >= 33 && u <= 37)
406 u = 33 + 2;
407 else if(u >= 50 && u <= 54)
408 u = 50 + 2;
409 else if(u >= 66 && u <= 70)
410 u = 66 + 2;
411 else if(u >= 75 && u <= 79)
412 u = 75 + 2;
413 else if(u >= 80 && u <= 84) /* there are 180MHz PPros */
414 u = 80 + 2;
415 u -= 2;
416 mhz = v * 100 + u;
417 }
418
419 ct->clock = mhz;
420
421 hd = add_hd_entry(hd_data, __LINE__, 0);
422 hd->base_class.id = bc_internal;
423 hd->sub_class.id = sc_int_cpu;
424 hd->slot = cpus;
425 hd->detail = new_mem(sizeof *hd->detail);
426 hd->detail->type = hd_detail_cpu;
427 hd->detail->cpu.data = ct;
428
429 if(*features) {
430 for(t0 = features; (t = strsep(&t0, " ")); ) {
431 add_str_list(&ct->features, t);
432 }
433 }
434
435 *model_id = *vendor_id = 0;
436 mhz = 0;
437 cpus++;
438 }
439 }
440 }
441
442#endif /* __ia64__ */
443
444
445#if defined(__s390__) || defined(__s390x__)
446 *vendor_id = 0;
447 bogo = 0;
448
449 for(sl = hd_data->cpu; sl; sl = sl->next) {
450 if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1);
451 if(sscanf(sl->str, "bogomips per cpu : %u", &bogo) == 1);
452 }
453
454 for(sl = hd_data->cpu; sl; sl = sl->next) {
455 if(
456 sscanf(sl->str, "processor %u : version = %x , identification = %x , machine = %x", &u0, &u1, &u2, &u3) == 4
457 ) {
458 ct = new_mem(sizeof *ct);
459#ifdef __s390x__
460 ct->architecture = arch_s390x;
461#else
462 ct->architecture = arch_s390;
463#endif
464 if(vendor_id) ct->vend_name = new_str(vendor_id);
465 ct->stepping = u1;
466 hd_data->boot = boot_s390;
467
468 hd = add_hd_entry(hd_data, __LINE__, 0);
469 hd->base_class.id = bc_internal;
470 hd->sub_class.id = sc_int_cpu;
471 hd->slot = cpus;
472 hd->detail = new_mem(sizeof *hd->detail);
473 hd->detail->type = hd_detail_cpu;
474 hd->detail->cpu.data = ct;
475
476 bogo = 0;
477 cpus++;
478 }
479 }
480#endif /* defined(__s390__) || defined(__s390x__) */
481}
482
483/*
484 * Add some cpu data to the global log.
485 */
486void dump_cpu_data(hd_data_t *hd_data)
487{
488 str_list_t *sl;
489
490 ADD2LOG("----- /proc/cpuinfo -----\n");
491 for(sl = hd_data->cpu; sl; sl = sl->next) {
492 ADD2LOG(" %s", sl->str);
493 }
494 ADD2LOG("----- /proc/cpuinfo end -----\n");
495}
496
497
498#if defined(__i386__) || defined(__x86_64__)
499inline unsigned units_per_cpu()
500{
501 unsigned u;
502
503 asm(
504#ifdef __i386__
505 "push %%ebx\n\t"
506#else
507 "push %%rbx\n\t"
508#endif
509 "mov $1,%%eax\n\t"
510 "cpuid\n\t"
511 "shr $8,%%ebx\n\t"
512 "movzx %%bh,%%eax\n\t"
513#ifdef __i386__
514 "pop %%ebx"
515#else
516 "pop %%rbx"
517#endif
518 : "=a" (u)
519 :: "%ecx", "%edx"
520 );
521
522 return u;
523}
524#endif
525
526
527#ifdef __ia64__
528
529/*
530 * IA64 SMP detection code
531 */
532
533#define PAGE_OFFSET(addr) ((uintptr_t) (addr) & (getpagesize () - 1))
534
535typedef struct
536{
537 uint8_t type;
538 uint8_t length;
539} __attribute__ ((packed)) acpi_table_entry_header;
540
541struct acpi20_table_rsdp
542{
543 char signature[8];
544 uint8_t checksum;
545 char oem_id[6];
546 uint8_t revision;
547 uint32_t rsdt_address;
548 uint32_t length;
549 unsigned long xsdt_address;
550 uint8_t ext_checksum;
551 uint8_t reserved[3];
552} __attribute__ ((packed));
553
554struct acpi_table_header
555{
556 char signature[4];
557 uint32_t length;
558 uint8_t revision;
559 uint8_t checksum;
560 char oem_id[6];
561 char oem_table_id[8];
562 uint32_t oem_revision;
563 char asl_compiler_id[4];
564 uint32_t asl_compiler_revision;
565};
566
567#define ACPI_XSDT_SIG "XSDT"
568struct acpi_table_xsdt
569{
570 struct acpi_table_header header;
571 unsigned long entry[0];
572} __attribute__ ((packed));
573
574#define ACPI_MADT_SIG "ACPI"
575struct acpi_table_madt
576{
577 struct acpi_table_header header;
578 uint32_t lapic_address;
579 struct
580 {
581 uint32_t pcat_compat:1;
582 uint32_t reserved:31;
583 } flags;
584} __attribute__ ((packed));
585
586#define ACPI_MADT_LSAPIC 7
587
588struct acpi_table_lsapic
589{
590 acpi_table_entry_header header;
591 uint8_t acpi_id;
592 uint8_t id;
593 uint8_t eid;
594 uint8_t reserved[3];
595 struct
596 {
597 uint32_t enabled:1;
598 uint32_t reserved:31;
599 } flags;
600} __attribute__ ((packed));
601
602/*
603 * Map an ACPI table into virtual memory
604 */
605static struct acpi_table_header *
606acpi_map_table (int mem, unsigned long addr, char *signature)
607{
608 /* mmap header to determine table size */
609 struct acpi_table_header *table = NULL;
610 unsigned long offset = PAGE_OFFSET (addr);
611 uint8_t *mapped = mmap (NULL,
612 sizeof (struct acpi_table_header) + offset,
613 PROT_READ,
614 MAP_PRIVATE,
615 mem,
616 (unsigned long) addr - offset);
617 table = (struct acpi_table_header *) (mapped != MAP_FAILED
618 ? mapped + offset
619 : NULL);
620 if (table)
621 {
622 if (memcmp (table->signature, signature, sizeof (table->signature)))
623 {
624 munmap ((char *) table - offset,
625 sizeof (struct acpi_table_header) + offset);
626 return NULL;
627 }
628 {
629 /* re-mmap entire table */
630 unsigned long size = table->length;
631 munmap ((uint8_t *) table - offset,
632 sizeof (struct acpi_table_header) + offset);
633 mapped = mmap (NULL, size + offset, PROT_READ, MAP_PRIVATE, mem,
634 (unsigned long) addr - offset);
635 table = (struct acpi_table_header *) (mapped != MAP_FAILED
636 ? mapped + offset
637 : NULL);
638 }
639 }
640 return table;
641}
642
643/*
644 * Unmap an ACPI table from virtual memory
645 */
646static void
647acpi_unmap_table (struct acpi_table_header * table)
648{
649 if (table)
650 {
651 unsigned long offset = PAGE_OFFSET (table);
652 munmap ((uint8_t *) table - offset, table->length + offset);
653 }
654}
655
656int
657acpi_parse_lsapic (acpi_table_entry_header *p)
658{
659 struct acpi_table_lsapic *lsapic = (struct acpi_table_lsapic *) p;
660
661 return lsapic->flags.enabled;
662}
663
664static int
665acpi_parse_madt (struct acpi_table_madt *madt)
666{
667 acpi_table_entry_header *p, *end;
668 int n_cpu = 0;
669
670 p = (acpi_table_entry_header *) (madt + 1);
671 end = (acpi_table_entry_header *) ((char *) madt + madt->header.length);
672
673 while (p < end)
674 {
675 if (p->type == ACPI_MADT_LSAPIC)
676 n_cpu += acpi_parse_lsapic (p);
677
678 p = (acpi_table_entry_header *) ((char *) p + p->length);
679 }
680
681 return n_cpu;
682}
683
684static int
685acpi_parse_rsdp (int mem_fd, struct acpi20_table_rsdp *rsdp)
686{
687 int n_cpu = 0;
688 int i;
689 struct acpi_table_xsdt *xsdt = 0;
690 int tables;
691
692 if (rsdp->xsdt_address)
693 xsdt = (struct acpi_table_xsdt *) acpi_map_table (mem_fd, rsdp->xsdt_address,
694 ACPI_XSDT_SIG);
695 if (xsdt)
696 {
697 tables = (xsdt->header.length - sizeof (struct acpi_table_header)) / 8;
698 for (i = 0; i < tables; i++)
699 {
700 struct acpi_table_header *dt
701 = acpi_map_table (mem_fd, xsdt->entry[i], ACPI_MADT_SIG);
702 if (dt)
703 n_cpu += acpi_parse_madt ((struct acpi_table_madt *) dt);
704 acpi_unmap_table (dt);
705 }
706 acpi_unmap_table ((struct acpi_table_header *) xsdt);
707 }
708 return n_cpu;
709}
710
711int ia64DetectSMP(hd_data_t *hd_data)
712{
713 int n_cpu = 0, mem_fd, systab_fd;
714 struct acpi20_table_rsdp rsdp;
715 uint8_t *mapped;
716 unsigned long addr = 0, offset;
717 int ok = 0;
718 str_list_t *sl;
719 const char *rsd_klog = "ACPI 2.0=";
720 const char *rsd_systab = "ACPI20=";
721 char *s;
722
723 mem_fd = open("/dev/mem", O_RDONLY);
724 if(mem_fd == -1) return -1;
725
726 systab_fd = open("/proc/efi/systab", O_RDONLY);
727 if (systab_fd != -1)
728 {
729 char buffer[512];
730 int n_read = read(systab_fd, buffer, sizeof(buffer) - 1);
731 close(systab_fd);
732 if (n_read > 0)
733 {
734 buffer[n_read] = 0;
735 if ((s = strstr(buffer, rsd_systab)) != NULL &&
736 sscanf(s + strlen(rsd_systab), "%lx", &addr) == 1)
737 goto found_it;
738 }
739 }
740
741 if(!hd_data->klog) read_klog(hd_data);
742
743 for(sl = hd_data->klog; sl; sl = sl->next) {
744 if((s = strstr(sl->str, rsd_klog))) {
745 if(sscanf(s + strlen(rsd_klog), "%lx", &addr) == 1) {
746 found_it:
747 offset= PAGE_OFFSET (addr);
748 mapped = mmap(NULL, sizeof rsdp + offset, PROT_READ, MAP_PRIVATE,
749 mem_fd, (unsigned long) addr - offset);
750 if(mapped != MAP_FAILED) {
751 ADD2LOG("seek to 0x%lx\n", addr);
752 memcpy(&rsdp, mapped + offset, sizeof rsdp);
753 munmap(mapped, sizeof rsdp + offset);
754 ok = 1;
755 }
756 break;
757 }
758 }
759 }
760
761 if(ok) {
762 n_cpu = acpi_parse_rsdp(mem_fd, &rsdp);
763 if(n_cpu) {
764 ADD2LOG("RSDP found at 0x%lx\n", addr);
765 }
766 }
767
768 close (mem_fd);
769
770 ADD2LOG("n_cpu = %d\n", n_cpu);
771
772 return n_cpu;
773}
774
775
776#endif /* __ia64__ */
777