- improved CPU code on axp & ppc
[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];
29   unsigned bogo, mhz, cache, family, model, stepping;
30 #endif
31
32 #ifdef __alpha__
33   char model_id[80], system_id[80], serial_number[80], platform[80];
34   unsigned cpu_variation, cpu_revision, u, hz;
35   cpu_info_t *ct1;
36 #endif
37
38 #ifdef __PPC__
39   char model_id[80], vendor_id[80], motherboard[80];
40   unsigned bogo, mhz, cache, family, model, stepping;
41 #endif
42
43   if(!hd_probe_feature(hd_data, pr_cpu)) return;
44
45   hd_data->module = mod_cpu;
46
47   /* some clean-up */
48   remove_hd_entries(hd_data);
49   hd_data->cpu = NULL;
50
51   PROGRESS(1, 0, "cpuinfo");
52
53   hd_data->cpu = read_file(PROC_CPUINFO, 0, 0);
54   if((hd_data->debug & HD_DEB_CPU)) dump_cpu_data(hd_data);
55   if(!hd_data->cpu) return;
56
57 #ifdef __alpha__
58   *model_id = *system_id = *serial_number = *platform = 0;
59   cpu_variation = cpu_revision = hz = 0;
60
61   for(sl = hd_data->cpu; sl; sl = sl->next) {
62     if(sscanf(sl->str, "cpu model : %79[^\n]", model_id) == 1) continue;
63     if(sscanf(sl->str, "system type : %79[^\n]", system_id) == 1) continue;
64     if(sscanf(sl->str, "cpu variation : %u", &cpu_variation) == 1) continue;
65     if(sscanf(sl->str, "cpu revision : %u", &cpu_revision) == 1) continue;
66     if(sscanf(sl->str, "system serial number : %79[^\n]", serial_number) == 1) continue;
67     if(sscanf(sl->str, "cpus detected : %u", &cpus) == 1) continue;
68     if(sscanf(sl->str, "cycle frequency [Hz] : %u", &hz) == 1) continue;
69     if(sscanf(sl->str, "platform string : %79[^\n]", platform) == 1) continue;
70   }
71
72   if(*model_id || *system_id) { /* at least one of those */
73     ct = new_mem(sizeof *ct);
74     ct->architecture = arch_alpha;
75     if(model_id) ct->model_name = new_str(model_id);
76     if(system_id) ct->vend_name = new_str(system_id);
77     if(strncmp(serial_number, "MILO", 4) == 0)
78       hd_data->boot = boot_milo;
79     else
80       hd_data->boot = boot_aboot;
81
82     ct->family = cpu_variation;
83     ct->model = cpu_revision;
84     ct->stepping = 0;
85     ct->cache = 0;
86     ct->clock = (hz + 500000) / 1000000;
87
88     if(platform) {
89       if(strcmp(platform, "N/A")) ct->platform = new_str(platform);
90     }
91
92     if(!cpus) cpus = 1;         /* at least 1 machine had a "cpus: 0" entry... */
93     for(u = 0; u < cpus; u++) {
94       hd = add_hd_entry(hd_data, __LINE__, 0);
95       hd->base_class = bc_internal;
96       hd->sub_class = sc_int_cpu;
97       hd->slot = u;
98       hd->detail = new_mem(sizeof *hd->detail);
99       hd->detail->type = hd_detail_cpu;
100       if(u) {
101         hd->detail->cpu.data = ct1 = new_mem(sizeof *ct);
102         *ct1 = *ct;
103         ct1->model_name = new_str(ct1->model_name);
104         ct1->vend_name = new_str(ct1->vend_name);
105       }
106       else {
107         hd->detail->cpu.data = ct;
108       }
109     }
110
111   }
112 #endif
113
114 #ifdef __sparc__
115 #endif
116
117
118 /* Intel code  */
119
120 #ifdef __i386__
121   *model_id = *vendor_id = 0;
122   bogo = mhz = cache = family = model = stepping = 0;
123
124   for(sl = hd_data->cpu; sl; sl = sl->next) {
125     if(sscanf(sl->str, "model name : %79[^\n]", model_id) == 1) continue;
126     if(sscanf(sl->str, "vendor_id : %79[^\n]", vendor_id) == 1) continue;
127     if(sscanf(sl->str, "bogomips : %u", &bogo) == 1) continue;
128     if(sscanf(sl->str, "cpu MHz : %u", &mhz) == 1) continue;
129     if(sscanf(sl->str, "cache size : %u KB", &cache) == 1) continue;
130
131     if(sscanf(sl->str, "cpu family : %u", &family) == 1) continue;
132     if(sscanf(sl->str, "model : %u", &model) == 1) continue;
133     if(sscanf(sl->str, "stepping : %u", &stepping) == 1) continue;
134
135     if(strstr(sl->str, "processor") == sl->str || !sl->next) {          /* EOF */
136       if(*model_id || *vendor_id) {     /* at least one of those */
137         ct = new_mem(sizeof *ct);
138         ct->architecture = arch_intel;
139         if(model_id) ct->model_name = new_str(model_id);
140         if(vendor_id) ct->vend_name = new_str(vendor_id);
141         ct->family = family;
142         ct->model = model;
143         ct->stepping = stepping;
144         ct->cache = cache;
145         hd_data->boot = boot_lilo;
146
147         /* round clock to typical values */
148         if(mhz >= 38 && mhz <= 42)
149           mhz = 40;
150         else if(mhz >= 88 && mhz <= 92)
151           mhz = 90;
152         else {
153           unsigned u, v;
154
155           u = (mhz + 2) % 100;
156           v = (mhz + 2) / 100;
157           if(u <= 4)
158             u = 2;
159           else if(u >= 25 && u <= 29)
160             u = 25 + 2;
161           else if(u >= 33 && u <= 37)
162             u = 33 + 2;
163           else if(u >= 50 && u <= 54)
164             u = 50 + 2;
165           else if(u >= 66 && u <= 70)
166             u = 66 + 2;
167           else if(u >= 75 && u <= 79)
168             u = 75 + 2;
169           else if(u >= 80 && u <= 84)   /* there are 180MHz PPros */
170             u = 80 + 2;
171           u -= 2;
172           mhz = v * 100 + u;
173         }
174
175         ct->clock = mhz;
176
177         hd = add_hd_entry(hd_data, __LINE__, 0);
178         hd->base_class = bc_internal;
179         hd->sub_class = sc_int_cpu;
180         hd->slot = cpus;
181         hd->detail = new_mem(sizeof *hd->detail);
182         hd->detail->type = hd_detail_cpu;
183         hd->detail->cpu.data = ct;
184         
185         *model_id = *vendor_id = 0;
186         bogo = mhz = cache = family = model= 0;
187         cpus++;
188       }
189     }
190   }
191 #endif /* __i386__  */
192
193 #ifdef __PPC__
194   *model_id = *vendor_id = *motherboard = 0;
195   bogo = mhz = cache = family = model = stepping = 0;
196
197   for(sl = hd_data->cpu; sl; sl = sl->next) {
198     if(sscanf(sl->str, "cpu : %79[^\n]", model_id) == 1) continue;
199     if(sscanf(sl->str, "machine : %79[^\n]", vendor_id) == 1) continue;
200     if(sscanf(sl->str, "motherboard : %79[^\n]", motherboard) == 1) continue;
201     if(sscanf(sl->str, "bogomips : %u", &bogo) == 1) continue;
202     if(sscanf(sl->str, "clock : %u", &mhz) == 1) continue;
203     if(sscanf(sl->str, "L2 cache : %u KB", &cache) == 1) continue;
204
205     if(strstr(sl->str, "processor") == sl->str || !sl->next) {          /* EOF */
206       if(*model_id || *vendor_id) {     /* at least one of those */
207         ct = new_mem(sizeof *ct);
208         ct->architecture = arch_ppc;
209         if(model_id) ct->model_name = new_str(model_id);
210         if(vendor_id) ct->vend_name = new_str(vendor_id);
211         if(motherboard) ct->platform = new_str(motherboard);
212         ct->family = family;
213         ct->model = model;
214         ct->stepping = stepping;
215         ct->cache = cache;
216         hd_data->boot = boot_ppc;
217         ct->clock = mhz;
218
219         hd = add_hd_entry(hd_data, __LINE__, 0);
220         hd->base_class = bc_internal;
221         hd->sub_class = sc_int_cpu;
222         hd->slot = cpus;
223         hd->detail = new_mem(sizeof *hd->detail);
224         hd->detail->type = hd_detail_cpu;
225         hd->detail->cpu.data = ct;
226         
227         *model_id = *vendor_id = 0;
228         bogo = mhz = cache = family = model= 0;
229         cpus++;
230       }
231     }
232   }
233 #endif /* __PPC__  */
234
235 }
236
237
238 /*
239  * Add some cpu data to the global log.
240  */
241 void dump_cpu_data(hd_data_t *hd_data)
242 {
243   str_list_t *sl;
244
245   ADD2LOG("----- /proc/cpuinfo -----\n");
246   for(sl = hd_data->cpu; sl; sl = sl->next) {
247     ADD2LOG("  %s", sl->str);
248   }
249   ADD2LOG("----- /proc/cpuinfo end -----\n");
250 }
251