2 Copyright © 2000, The AROS Development Team. All rights reserved.
5 Desc: Probe installed x86 compatable CPUs and display relevant information
9 /* BIG TO DO - SEPERATE THE INDIVIDUAL PROCESSOR FAMILY "PROBES" INTO RUNTIME SHARED LIBS OR SIMILAR */
11 /****************************************************************************************************
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
23 Transmeta Crusoe TM3x00 and TM5x00
24 National Semiconductor Geode
30 *****************************************************************************************************/
34 /********************************************
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
)
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
)
61 i386_getregs( out
, eax
, ebx
, ecx
, edx
);
65 /********************************************/
67 int i386_sprintregs ( int buffpos
, char *buffer
, int eax
,int ebx
,int ecx
,int edx
) /* returns buffer position */
72 i386_getregs( out
, eax
, ebx
, ecx
, edx
);
74 AddBufferLine( buffpos
, buffer
, out
);
76 return ( buffpos
+= size
);
79 /********************************************/
81 void Convert32 (unsigned long value
)
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(' ');
94 /********************************************/
96 void Convert64(unsigned long long value
)
98 Convert32 ( value
>> 32 );
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
);
115 printf ( "MSR: 0x%08x=0x%08llx : ", msr
, msrres
);
116 if ( size
== 32 ) Convert32( msrres
);
117 if ( size
== 64 ) Convert64( msrres
);
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 )
136 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
138 outb(TICKS
& 0xff, 0x42);
139 outb(TICKS
>> 8, 0x42);
141 asm("rdtsc":"=a" (st_low
),"=d" (st_high
));
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
) );
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 )
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 */
174 speed
+= 50; /* for rounding */
176 printf("%d.%02d Mhz\n",speed
/1000,(speed
/100)%10);
180 speed
+= 500; /* for rounding */
181 printf("%d Mhz\n",speed
/1000);
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
;
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.. */
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
245 case 0x68747541: /* AMD processor */
246 parse_i386_AMD(maxi
, CPUi386
);
253 parse_i386_Intel(maxi
, CPUi386
); /* Intel processor */
256 parse_i386_Transmeta(maxi
, CPUi386
); /* Transmeta processor */
260 case 0x69727943: /* Cyrix processor */
261 parse_i386_Cyrix(maxi
, CPUi386
);
264 //case 0x68747541: /* UMC processor */
265 // parse_i386_UMC(maxi, CPUi386);
268 //case 0x756e6547: /* NexGen processor */
269 // parse_i386_NexGen(maxi, CPUi386);
272 //case 0x69727943: /* Centaur processor */
273 // parse_i386_Centaur(maxi, CPUi386);
276 //case 0x68747541: /* Rise Technology processor */
277 // parse_i386_Rise(maxi, CPUi386);
280 //case 0x756e6547: /* SiS processor */
281 // parse_i386_SiS(maxi, CPUi386);
284 //case 0x69727943: /* National Semiconductor processor */
285 // parse_i386_NSC(maxi, CPUi386);
289 printf("Unknown vendor\n");
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");
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
);
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
;
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();
349 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
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
;
368 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
370 speed
= i386_approx_mhz();
374 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
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
;
393 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
395 speed
= i386_approx_mhz();
399 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
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
;
418 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
420 speed
= i386_approx_mhz();
424 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
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
;
443 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
445 speed
= i386_approx_mhz();
449 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
452 FreeMem(global
,sizeof(struct CPU_INTERN_DATA
));