Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / c / CPUInfo / x86 / main.c
blob11f5110c519ed64e0900f7f375715ed590192ba6
1 /*
2 Copyright © 2000, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Probe installed x86 compatable CPUs and display relevant information
6 Lang: english
7 */
9 /* BIG TO DO - SEPERATE THE INDIVIDUAL PROCESSOR FAMILY "PROBES" INTO RUNTIME SHARED LIBS OR SIMILAR */
11 /****************************************************************************************************
12 Currently Supports:
14 i386 compatable families...
15 AMD 486/5x86/K5/K6/K6-II/K6-III/Athlon/Duron/Opteron/Athlon64
16 Intel P5/P54C/P55C/P24T/P6/P2/P3/PM/Itanium(IA-64)
17 Cyrix 5x86/M1/MediaGX/M2
18 UMC
19 NexGen Nx586
20 Centaur C6/C2/C3
21 Rise Technology mP6
22 SiS 55x
23 Transmeta Crusoe TM3x00 and TM5x00
24 National Semiconductor Geode
26 Soon....
28 PPC?
30 *****************************************************************************************************/
32 #include "x86.h"
34 /********************************************
35 Variables
36 ********************************************/
38 ULONG st_low, st_high, end_low, end_high;
40 /********************************************/
42 void i386_getregs ( char *out, int eax,int ebx,int ecx,int edx )
44 int loop;
46 out[16] = '\0';
47 for( loop = 0 ; loop < 4 ; loop++ )
49 out[loop] = eax >> (8*loop);
50 out[loop+4] = ebx >> (8*loop);
51 out[loop+8] = ecx >> (8*loop);
52 out[loop+12] = edx >> (8*loop);
56 /********************************************/
58 void i386_printregs ( int eax,int ebx,int ecx,int edx )
60 char *out[17];
61 i386_getregs( out, eax, ebx, ecx, edx );
62 printf( out );
65 /********************************************/
67 int i386_sprintregs ( int buffpos, char *buffer, int eax,int ebx,int ecx,int edx) /* returns buffer position */
69 char *out[17];
70 ULONG size;
72 i386_getregs( out, eax, ebx, ecx, edx );
73 size = strlen( out );
74 AddBufferLine( buffpos, buffer, out );
76 return ( buffpos += size );
79 /********************************************/
81 void Convert32 (unsigned long value)
83 int loop;
85 for( loop=0 ; loop<32 ; loop++, value <<= 1 )
87 putchar( ( 1 << 31 & value ) ? '1' : '0' );
89 if ( loop == 23 || loop == 15 || loop == 7 ) putchar(' ');
91 putchar('\n');
94 /********************************************/
96 void Convert64(unsigned long long value)
98 Convert32 ( value >> 32 );
99 printf (" ");
100 Convert32 ( value );
103 /********************************************/
105 void i386_Parse_MSR ( unsigned int msr, int size)
107 unsigned long msrvala=0,msrvalb=0;
108 unsigned long long msrres;
110 i386_rdmsr( msr, msrvala, msrvalb );
111 msrres = ( ( msrvalb << 32 ) | msrvala );
113 if ( msrres == 1 )
115 printf ( "MSR: 0x%08x=0x%08llx : ", msr, msrres );
116 if ( size == 32 ) Convert32( msrres );
117 if ( size == 64 ) Convert64( msrres );
118 return;
120 printf (" Couldn't read MSR 0x%x\n", msr );
123 /********************************************/
125 #define TICKS (65536 - 8271)
127 /* Returns CPU clock in khz */
129 int i386_cpuspeed ( void )
131 int loops;
133 Forbid();
135 /* Setup timer */
136 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
137 outb(0xb0, 0x43);
138 outb(TICKS & 0xff, 0x42);
139 outb(TICKS >> 8, 0x42);
141 asm("rdtsc":"=a" (st_low),"=d" (st_high));
143 loops = 0;
145 do loops++;
146 while ((inb(0x61) & 0x20) == 0);
148 asm( "rdtsc\n\t" "subl st_low,%%eax\n\t" "subl st_high,%%edx\n\t" :"=a" (end_low), "=d" (end_high) );
150 Permit();
152 if (loops < 4 || end_low < 50000) return(-1); /* Make sure we have a credible result */
154 return( end_low/48 );
157 /********************************************/
159 ULONG i386_approx_mhz ( void )
161 ULONG speed;
163 printf(" Approximate Clock Frequency = ");
165 if ((speed = i386_cpuspeed()) > 0)
167 speed += i386_cpuspeed();
168 speed += i386_cpuspeed();
170 speed /= 3; /* get an average for better results */
172 if (speed < 1000000)
174 speed += 50; /* for rounding */
176 printf("%d.%02d Mhz\n",speed/1000,(speed/100)%10);
178 else
180 speed += 500; /* for rounding */
181 printf("%d Mhz\n",speed/1000);
184 return speed;
187 /********************************************
188 PARSE INTEL 386 COMPATABLEs
189 ********************************************/
191 void parse_i386 ( struct i386_compat_intern * CPUi386, ULONG CPU_ID )
193 unsigned long li,maxi,maxei,ebx,ecx,edx,unused;
194 char *strVendor;
195 int i;
197 /* . Display what we know from the CPUs i386 private structure .. */
198 printf("\nProcessor internal (private) for i386 compatable\n");
199 printf("(stored @ %p)\n\n",CPUi386);
201 /* printf(" intern.x86 : %p\n",CPUi386->x86);
202 printf(" intern.x86_vendor : %p\n",CPUi386->x86_vendor);
203 printf(" intern.x86_model : %p\n",CPUi386->x86_model);
204 printf(" intern.x86_mask : %08x\n",CPUi386->x86_mask);
205 printf(" intern.x86_hard_math : %p\n",CPUi386->x86_hard_math);
206 printf(" intern.x86_cpuid : %08x\n",CPUi386->x86_cpuid);
207 printf(" intern.x86_capability : %08x\n",CPUi386->x86_capability); */
209 strVendor = &CPUi386->x86_vendor_id;
211 #warning TODO: Insert code to verify CPUID instruction availability
213 i386_cpuid(0,maxi,unused,unused,unused);
214 maxi &= 0xffff; /* The high-order word is non-zero on some Cyrix CPUs */
216 /* Max CPUID level supported & Vendor Name */
217 i386_cpuid(0,unused,ebx,ecx,edx);
219 printf(" Vendor ID: \"");
220 for(i=0;i<4;i++) putchar(ebx >> (8*i));
221 for(i=0;i<4;i++) putchar(edx >> (8*i));
222 for(i=0;i<4;i++) putchar(ecx >> (8*i));
223 printf("\"; CPUID level %ld\n\n",maxi);
225 /* Use the first 4 letters of the vender string to ID our processor.. */
229 EBX-EDX-ECX Vendor
231 "AuthenticAMD" AMD processor
232 "GenuineIntel" Intel processor
233 "CyrixInstead" Cyrix processor
234 "UMC UMC UMC " UMC processor
235 "NexGenDriven" NexGen processor
236 "CentaurHauls" Centaur processor
237 "RiseRiseRise" Rise Technology processor
238 "SiS SiS SiS " SiS processor
239 "GenuineTMx86" Transmeta processor
240 "Geode by NSC" National Semiconductor processor
243 switch(ebx)
245 case 0x68747541: /* AMD processor */
246 parse_i386_AMD(maxi, CPUi386);
247 break;
249 case 0x756e6547:
250 switch(ecx)
252 case 0x6c65746e:
253 parse_i386_Intel(maxi, CPUi386); /* Intel processor */
254 break;
255 case 0x756e6547:
256 parse_i386_Transmeta(maxi, CPUi386); /* Transmeta processor */
257 break;
260 case 0x69727943: /* Cyrix processor */
261 parse_i386_Cyrix(maxi, CPUi386);
262 break;
264 //case 0x68747541: /* UMC processor */
265 // parse_i386_UMC(maxi, CPUi386);
266 // break;
268 //case 0x756e6547: /* NexGen processor */
269 // parse_i386_NexGen(maxi, CPUi386);
270 // break;
272 //case 0x69727943: /* Centaur processor */
273 // parse_i386_Centaur(maxi, CPUi386);
274 // break;
276 //case 0x68747541: /* Rise Technology processor */
277 // parse_i386_Rise(maxi, CPUi386);
278 // break;
280 //case 0x756e6547: /* SiS processor */
281 // parse_i386_SiS(maxi, CPUi386);
282 // break;
284 //case 0x69727943: /* National Semiconductor processor */
285 // parse_i386_NSC(maxi, CPUi386);
286 // break;
288 default:
289 printf("Unknown vendor\n");
290 break;
293 /* Dump all the CPUID results in raw hex */
294 printf("\n Raw CPUID Dump:\n ---------------\n\n");
295 printf(" eax in eax ebx ecx edx\n");
297 for(i=0;i<=maxi;i++)
299 unsigned long eax,ebx,ecx,edx;
301 i386_cpuid(i,eax,ebx,ecx,edx);
302 printf(" %08x %08lx %08lx %08lx %08lx\n",i,eax,ebx,ecx,edx);
305 i386_cpuid(0x80000000,maxei,unused,unused,unused);
307 for(li=0x80000000;li<=maxei;li++)
309 unsigned long eax,ebx,ecx,edx;
311 i386_cpuid(li,eax,ebx,ecx,edx);
312 printf(" %08lx %08lx %08lx %08lx %08lx\n",li,eax,ebx,ecx,edx);
314 printf("\n");
317 /********************************************
318 Transmeta specific information
319 ********************************************/
321 void parse_i386_Transmeta( int maxi, struct i386_compat_intern * CPUi386 )
324 struct CPU_INTERN_DATA *global;
325 ULONG speed, maxei,unused;
326 int family = 0;
327 char *BUFF_STR;
329 if ((global = AllocMem(sizeof(struct CPU_INTERN_DATA),MEMF_PUBLIC|MEMF_CLEAR)))
331 //if ( maxi >= 3 ) /* Crusoe CPU serial number */
333 // unsigned long signature,unused,ebx;
335 // i386_cpuid(3,unused,ebx,unused,unused);
337 // Intel_CPU_NAME_cnt = AddBufferLine(Intel_CPU_NAME_cnt, Intel_CPU_NAME, " Processor serial: ");
339 // sprintf( BUFF_STR,"-%04lX",ebx >> 16);
340 // Intel_CPU_NAME_cnt = AddBufferLine(Intel_CPU_NAME_cnt, Intel_CPU_NAME, BUFF_STR);
341 // sprintf( BUFF_STR,"-%04lX",ebx & 0xffff);
342 // Intel_CPU_NAME_cnt = AddBufferLine(Intel_CPU_NAME_cnt, Intel_CPU_NAME, BUFF_STR);
345 speed = i386_approx_mhz();
347 else
349 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
350 return;
352 FreeMem(global,sizeof(struct CPU_INTERN_DATA));
356 /********************************************
357 UMC specific information
358 ********************************************/
360 void parse_i386_UMC( int maxi, struct i386_compat_intern * CPUi386 )
363 struct CPU_INTERN_DATA *global;
364 ULONG speed, maxei,unused;
365 int family = 0;
366 char *BUFF_STR;
368 if ((global = AllocMem(sizeof(struct CPU_INTERN_DATA),MEMF_PUBLIC|MEMF_CLEAR)))
370 speed = i386_approx_mhz();
372 else
374 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
375 return;
377 FreeMem(global,sizeof(struct CPU_INTERN_DATA));
381 /********************************************
382 NexGen specific information
383 ********************************************/
385 void parse_i386_NexGen( int maxi, struct i386_compat_intern * CPUi386 )
388 struct CPU_INTERN_DATA *global;
389 ULONG speed, maxei,unused;
390 int family = 0;
391 char *BUFF_STR;
393 if ((global = AllocMem(sizeof(struct CPU_INTERN_DATA),MEMF_PUBLIC|MEMF_CLEAR)))
395 speed = i386_approx_mhz();
397 else
399 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
400 return;
402 FreeMem(global,sizeof(struct CPU_INTERN_DATA));
406 /********************************************
407 Centaur specific information
408 ********************************************/
410 void parse_i386_Centaur( int maxi, struct i386_compat_intern * CPUi386 )
413 struct CPU_INTERN_DATA *global;
414 ULONG speed, maxei,unused;
415 int family = 0;
416 char *BUFF_STR;
418 if ((global = AllocMem(sizeof(struct CPU_INTERN_DATA),MEMF_PUBLIC|MEMF_CLEAR)))
420 speed = i386_approx_mhz();
422 else
424 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
425 return;
427 FreeMem(global,sizeof(struct CPU_INTERN_DATA));
431 /********************************************
432 SiS specific information
433 ********************************************/
435 void parse_i386_SiS( int maxi, struct i386_compat_intern * CPUi386 )
438 struct CPU_INTERN_DATA *global;
439 ULONG speed, maxei,unused;
440 int family = 0;
441 char *BUFF_STR;
443 if ((global = AllocMem(sizeof(struct CPU_INTERN_DATA),MEMF_PUBLIC|MEMF_CLEAR)))
445 speed = i386_approx_mhz();
447 else
449 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
450 return;
452 FreeMem(global,sizeof(struct CPU_INTERN_DATA));