- fixed segfault bug in alpha smp code
[opensuse:hwinfo.git] / src / hd / cpu.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "hd.h"
6 #include "hd_int.h"
7 #include "cpu.h"
8
9 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
10  * cpu info
11  *
12  * Note: on other architectures, entries differ (cf. Alpha)!!!
13  *
14  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
15  */
16
17
18 static void dump_cpu_data(hd_data_t *hd_data);
19
20 void hd_scan_cpu(hd_data_t *hd_data)
21 {
22   hd_t *hd;
23   unsigned cpus = 0;
24   cpu_info_t *ct;
25   str_list_t *sl;
26
27 #ifdef __i386__
28   char model_id[80], vendor_id[80], features[0x100];
29   unsigned bogo, mhz, cache, family, model, stepping;
30   char *t0, *t;
31 #endif
32
33 #ifdef __ia64__
34   char model_id[80], vendor_id[80], features[0x100];
35   unsigned mhz, stepping;
36   char *t0, *t;
37 #endif
38
39 #ifdef __alpha__
40   char model_id[80], system_id[80], serial_number[80], platform[80];
41   unsigned cpu_variation, cpu_revision, u, hz;
42   cpu_info_t *ct1;
43 #endif
44
45 #ifdef __PPC__
46   char model_id[80], vendor_id[80], motherboard[80];
47   unsigned bogo, mhz, cache, family, model, stepping;
48 #endif
49
50 #ifdef __sparc__
51   char cpu_id[80], fpu_id[80], promlib[80], prom[80], type[80], mmu[80];
52   unsigned u, bogo, cpus_active;
53 #endif
54
55 #ifdef __s390__
56   char vendor_id[80];
57   unsigned bogo;
58   unsigned u0, u1, u2, u3;
59 #endif
60
61   if(!hd_probe_feature(hd_data, pr_cpu)) return;
62
63   hd_data->module = mod_cpu;
64
65   /* some clean-up */
66   remove_hd_entries(hd_data);
67   hd_data->cpu = free_str_list(hd_data->cpu);
68
69   PROGRESS(1, 0, "cpuinfo");
70
71   hd_data->cpu = read_file(PROC_CPUINFO, 0, 0);
72   if((hd_data->debug & HD_DEB_CPU)) dump_cpu_data(hd_data);
73   if(!hd_data->cpu) return;
74
75 #ifdef __alpha__
76   *model_id = *system_id = *serial_number = *platform = 0;
77   cpu_variation = cpu_revision = hz = 0;
78
79   for(sl = hd_data->cpu; sl; sl = sl->next) {
80     if(sscanf(sl->str, "cpu model : %79[^\n]", model_id) == 1) continue;
81     if(sscanf(sl->str, "system type : %79[^\n]", system_id) == 1) continue;
82     if(sscanf(sl->str, "cpu variation : %u", &cpu_variation) == 1) continue;
83     if(sscanf(sl->str, "cpu revision : %u", &cpu_revision) == 1) continue;
84     if(sscanf(sl->str, "system serial number : %79[^\n]", serial_number) == 1) continue;
85     if(sscanf(sl->str, "cpus detected : %u", &cpus) == 1) continue;
86     if(sscanf(sl->str, "cycle frequency [Hz] : %u", &hz) == 1) continue;
87     if(sscanf(sl->str, "system variation : %79[^\n]", platform) == 1) continue;
88   }
89
90   if(*model_id || *system_id) { /* at least one of those */
91     ct = new_mem(sizeof *ct);
92     ct->architecture = arch_alpha;
93     if(model_id) ct->model_name = new_str(model_id);
94     if(system_id) ct->vend_name = new_str(system_id);
95     if(strncmp(serial_number, "MILO", 4) == 0)
96       hd_data->boot = boot_milo;
97     else
98       hd_data->boot = boot_aboot;
99
100     ct->family = cpu_variation;
101     ct->model = cpu_revision;
102     ct->stepping = 0;
103     ct->cache = 0;
104     ct->clock = (hz + 500000) / 1000000;
105
106     if(platform && strcmp(platform, "0")) {
107       ct->platform = new_str(platform);
108     }
109
110     if(!cpus) cpus = 1;         /* at least 1 machine had a "cpus: 0" entry... */
111     for(u = 0; u < cpus; u++) {
112       hd = add_hd_entry(hd_data, __LINE__, 0);
113       hd->base_class = bc_internal;
114       hd->sub_class = sc_int_cpu;
115       hd->slot = u;
116       hd->detail = new_mem(sizeof *hd->detail);
117       hd->detail->type = hd_detail_cpu;
118       if(u) {
119         hd->detail->cpu.data = ct1 = new_mem(sizeof *ct);
120         *ct1 = *ct;
121         ct1->model_name = new_str(ct1->model_name);
122         ct1->vend_name = new_str(ct1->vend_name);
123         ct1->platform = new_str(ct1->platform);
124       }
125       else {
126         hd->detail->cpu.data = ct;
127       }
128     }
129
130   }
131 #endif  /* __alpha__ */
132
133
134 #ifdef __sparc__
135   *cpu_id = *fpu_id = *promlib = *prom = *type = *mmu = 0;
136   cpus = cpus_active = bogo = 0;
137
138   for(sl = hd_data->cpu; sl; sl = sl->next) {
139     if(sscanf(sl->str, "cpu             : %79[^\n]", cpu_id) == 1);
140     if(sscanf(sl->str, "fpu             : %79[^\n]", fpu_id) == 1);
141     if(sscanf(sl->str, "promlib         : %79[^\n]", promlib) == 1);
142     if(sscanf(sl->str, "prom            : %79[^\n]", prom) == 1);
143     if(sscanf(sl->str, "type            : %79[^\n]", type) == 1);
144     if(sscanf(sl->str, "ncpus probed    : %u", &cpus) == 1);
145     if(sscanf(sl->str, "ncpus active    : %u", &cpus_active) == 1);
146     if(sscanf(sl->str, "BogoMips        : %u", &bogo) == 1);
147     if(sscanf(sl->str, "MMU Type        : %79[^\n]", mmu) == 1);
148   }
149
150   if(*cpu_id) {
151     for(u = 0; u < cpus; u++) {
152       ct = new_mem(sizeof *ct);
153       ct->platform = new_str (type);
154       if(strcmp (type, "sun4u") == 0)
155         ct->architecture = arch_sparc64;
156       else
157         ct->architecture = arch_sparc;
158
159       ct->model_name = new_str(cpu_id);
160       hd_data->boot = boot_silo;
161
162       hd = add_hd_entry(hd_data, __LINE__, 0);
163       hd->base_class = bc_internal;
164       hd->sub_class = sc_int_cpu;
165       hd->slot = u;
166       hd->detail = new_mem(sizeof *hd->detail);
167       hd->detail->type = hd_detail_cpu;
168       hd->detail->cpu.data = ct;
169     }
170   }
171 #endif  /* sparc */
172
173
174 #ifdef __i386__
175   *model_id = *vendor_id = *features = 0;
176   bogo = mhz = cache = family = model = stepping = 0;
177
178   for(sl = hd_data->cpu; sl; sl = sl->next) {
179     if(sscanf(sl->str, "model name : %79[^\n]", model_id) == 1);
180     if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1);
181     if(sscanf(sl->str, "flags : %255[^\n]", features) == 1);
182     if(sscanf(sl->str, "bogomips : %u", &bogo) == 1);
183     if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1);
184     if(sscanf(sl->str, "cache size : %u KB", &cache) == 1);
185
186     if(sscanf(sl->str, "cpu family : %u", &family) == 1);
187     if(sscanf(sl->str, "model : %u", &model) == 1);
188     if(sscanf(sl->str, "stepping : %u", &stepping) == 1);
189
190     if(strstr(sl->str, "processor") == sl->str || !sl->next) {          /* EOF */
191       if(*model_id || *vendor_id) {     /* at least one of those */
192         ct = new_mem(sizeof *ct);
193         ct->architecture = arch_intel;
194         if(model_id) ct->model_name = new_str(model_id);
195         if(vendor_id) ct->vend_name = new_str(vendor_id);
196         ct->family = family;
197         ct->model = model;
198         ct->stepping = stepping;
199         ct->cache = cache;
200         hd_data->boot = boot_lilo;
201
202         /* round clock to typical values */
203         if(mhz >= 38 && mhz <= 42)
204           mhz = 40;
205         else if(mhz >= 88 && mhz <= 92)
206           mhz = 90;
207         else {
208           unsigned u, v;
209
210           u = (mhz + 2) % 100;
211           v = (mhz + 2) / 100;
212           if(u <= 4)
213             u = 2;
214           else if(u >= 25 && u <= 29)
215             u = 25 + 2;
216           else if(u >= 33 && u <= 37)
217             u = 33 + 2;
218           else if(u >= 50 && u <= 54)
219             u = 50 + 2;
220           else if(u >= 66 && u <= 70)
221             u = 66 + 2;
222           else if(u >= 75 && u <= 79)
223             u = 75 + 2;
224           else if(u >= 80 && u <= 84)   /* there are 180MHz PPros */
225             u = 80 + 2;
226           u -= 2;
227           mhz = v * 100 + u;
228         }
229
230         ct->clock = mhz;
231
232         hd = add_hd_entry(hd_data, __LINE__, 0);
233         hd->base_class = bc_internal;
234         hd->sub_class = sc_int_cpu;
235         hd->slot = cpus;
236         hd->detail = new_mem(sizeof *hd->detail);
237         hd->detail->type = hd_detail_cpu;
238         hd->detail->cpu.data = ct;
239
240         if(*features) {
241           for(t0 = features; (t = strsep(&t0, " ")); ) {
242             add_str_list(&ct->features, t);
243           }
244         }
245
246         *model_id = *vendor_id = 0;
247         bogo = mhz = cache = family = model= 0;
248         cpus++;
249       }
250     }
251   }
252 #endif /* __i386__  */
253
254
255 #ifdef __PPC__
256   *model_id = *vendor_id = *motherboard = 0;
257   bogo = mhz = cache = family = model = stepping = 0;
258
259   for(sl = hd_data->cpu; sl; sl = sl->next) {
260     if(sscanf(sl->str, "machine : %79[^\n]", vendor_id) == 1);
261   }
262
263   for(sl = hd_data->cpu; sl; sl = sl->next) {
264     if(sscanf(sl->str, "cpu : %79[^\n]", model_id) == 1);
265     if(sscanf(sl->str, "motherboard : %79[^\n]", motherboard) == 1);
266     if(sscanf(sl->str, "bogomips : %u", &bogo) == 1);
267     if(sscanf(sl->str, "clock : %u", &mhz) == 1);
268     if(sscanf(sl->str, "L2 cache : %u KB", &cache) == 1);
269
270     if(strstr(sl->str, "processor") == sl->str || !sl->next) {          /* EOF */
271       if(*model_id) {   /* at least one of those */
272         ct = new_mem(sizeof *ct);
273         ct->architecture = arch_ppc;
274         if(model_id) ct->model_name = new_str(model_id);
275         if(vendor_id) ct->vend_name = new_str(vendor_id);
276         if(motherboard) ct->platform = new_str(motherboard);
277         ct->family = family;
278         ct->model = model;
279         ct->stepping = stepping;
280         ct->cache = cache;
281         hd_data->boot = boot_ppc;
282         ct->clock = mhz;
283
284         hd = add_hd_entry(hd_data, __LINE__, 0);
285         hd->base_class = bc_internal;
286         hd->sub_class = sc_int_cpu;
287         hd->slot = cpus;
288         hd->detail = new_mem(sizeof *hd->detail);
289         hd->detail->type = hd_detail_cpu;
290         hd->detail->cpu.data = ct;
291
292         if(ct->vend_name && !strcmp(ct->vend_name, "PowerBook") && !hd_data->color_code) {
293           hd_data->color_code = 7;      // black
294         }
295         
296         *model_id = 0;
297         bogo = mhz = cache = family = model= 0;
298         cpus++;
299       }
300     }
301   }
302 #endif /* __PPC__  */
303
304
305 #ifdef __ia64__
306   *model_id = *vendor_id = *features = 0;
307   mhz = stepping = 0;
308
309   for(sl = hd_data->cpu; sl; sl = sl->next) {
310     if(sscanf(sl->str, "model : %79[^\n]", model_id) == 1);
311     if(sscanf(sl->str, "vendor : %79[^\n]", vendor_id) == 1);
312     if(sscanf(sl->str, "features : %255[^\n]", features) == 1);
313     if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1);
314     if(sscanf(sl->str, "revision : %u", &stepping) == 1);
315
316     if(strstr(sl->str, "processor") == sl->str || !sl->next) {          /* EOF */
317       if(*model_id || *vendor_id) {     /* at least one of those */
318         ct = new_mem(sizeof *ct);
319         ct->architecture = arch_ia64;
320         if(model_id) ct->model_name = new_str(model_id);
321         if(vendor_id) ct->vend_name = new_str(vendor_id);
322         ct->stepping = stepping;
323         hd_data->boot = boot_ia64;
324
325         /* round clock to typical values */
326         if(mhz >= 38 && mhz <= 42)
327           mhz = 40;
328         else if(mhz >= 88 && mhz <= 92)
329           mhz = 90;
330         else {
331           unsigned u, v;
332
333           u = (mhz + 2) % 100;
334           v = (mhz + 2) / 100;
335           if(u <= 4)
336             u = 2;
337           else if(u >= 25 && u <= 29)
338             u = 25 + 2;
339           else if(u >= 33 && u <= 37)
340             u = 33 + 2;
341           else if(u >= 50 && u <= 54)
342             u = 50 + 2;
343           else if(u >= 66 && u <= 70)
344             u = 66 + 2;
345           else if(u >= 75 && u <= 79)
346             u = 75 + 2;
347           else if(u >= 80 && u <= 84)   /* there are 180MHz PPros */
348             u = 80 + 2;
349           u -= 2;
350           mhz = v * 100 + u;
351         }
352
353         ct->clock = mhz;
354
355         hd = add_hd_entry(hd_data, __LINE__, 0);
356         hd->base_class = bc_internal;
357         hd->sub_class = sc_int_cpu;
358         hd->slot = cpus;
359         hd->detail = new_mem(sizeof *hd->detail);
360         hd->detail->type = hd_detail_cpu;
361         hd->detail->cpu.data = ct;
362
363         if(*features) {
364           for(t0 = features; (t = strsep(&t0, " ")); ) {
365             add_str_list(&ct->features, t);
366           }
367         }
368
369         *model_id = *vendor_id = 0;
370         mhz = 0;
371         cpus++;
372       }
373     }
374   }
375 #endif /* __ia64__  */
376
377
378 #ifdef __s390__
379   *vendor_id = 0;
380   bogo = 0;
381
382   for(sl = hd_data->cpu; sl; sl = sl->next) {
383     if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1);
384     if(sscanf(sl->str, "bogomips per cpu : %u", &bogo) == 1);
385   }
386
387   for(sl = hd_data->cpu; sl; sl = sl->next) {
388     if(
389       sscanf(sl->str, "processor %u : version = %u , identification = %u , machine = %u", &u0, &u1, &u2, &u3) == 4
390     ) {
391       ct = new_mem(sizeof *ct);
392       ct->architecture = arch_s390;
393       if(vendor_id) ct->vend_name = new_str(vendor_id);
394       ct->stepping = u1;
395       hd_data->boot = boot_s390;
396
397       hd = add_hd_entry(hd_data, __LINE__, 0);
398       hd->base_class = bc_internal;
399       hd->sub_class = sc_int_cpu;
400       hd->slot = cpus;
401       hd->detail = new_mem(sizeof *hd->detail);
402       hd->detail->type = hd_detail_cpu;
403       hd->detail->cpu.data = ct;
404
405       bogo = 0;
406       cpus++;
407     }
408   }
409 #endif /* __s390__  */
410 }
411
412
413 /*
414  * Add some cpu data to the global log.
415  */
416 void dump_cpu_data(hd_data_t *hd_data)
417 {
418   str_list_t *sl;
419
420   ADD2LOG("----- /proc/cpuinfo -----\n");
421   for(sl = hd_data->cpu; sl; sl = sl->next) {
422     ADD2LOG("  %s", sl->str);
423   }
424   ADD2LOG("----- /proc/cpuinfo end -----\n");
425 }
426