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
= ( ( (unsigned long long)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
= (char *)&CPUi386
->x86_vendor_id
;
211 /* TODO: Insert code to verify CPUID instruction availability */
214 i386_cpuid(0,maxi
,unused
,unused
,unused
);
215 maxi
&= 0xffff; /* The high-order word is non-zero on some Cyrix CPUs */
217 /* Max CPUID level supported & Vendor Name */
218 i386_cpuid(0,unused
,ebx
,ecx
,edx
);
220 printf(" Vendor ID: \"");
221 for(i
=0;i
<4;i
++) putchar(ebx
>> (8*i
));
222 for(i
=0;i
<4;i
++) putchar(edx
>> (8*i
));
223 for(i
=0;i
<4;i
++) putchar(ecx
>> (8*i
));
224 printf("\"; CPUID level %ld\n\n",maxi
);
226 /* Use the first 4 letters of the vender string to ID our processor.. */
232 "AuthenticAMD" AMD processor
233 "GenuineIntel" Intel processor
234 "CyrixInstead" Cyrix processor
235 "UMC UMC UMC " UMC processor
236 "NexGenDriven" NexGen processor
237 "CentaurHauls" Centaur processor
238 "RiseRiseRise" Rise Technology processor
239 "SiS SiS SiS " SiS processor
240 "GenuineTMx86" Transmeta processor
241 "Geode by NSC" National Semiconductor processor
246 case 0x68747541: /* AMD processor */
247 parse_i386_AMD(maxi
, CPUi386
);
254 parse_i386_Intel(maxi
, CPUi386
); /* Intel processor */
257 parse_i386_Transmeta(maxi
, CPUi386
); /* Transmeta processor */
261 case 0x69727943: /* Cyrix processor */
262 parse_i386_Cyrix(maxi
, CPUi386
);
265 //case 0x68747541: /* UMC processor */
266 // parse_i386_UMC(maxi, CPUi386);
269 //case 0x756e6547: /* NexGen processor */
270 // parse_i386_NexGen(maxi, CPUi386);
273 //case 0x69727943: /* Centaur processor */
274 // parse_i386_Centaur(maxi, CPUi386);
277 //case 0x68747541: /* Rise Technology processor */
278 // parse_i386_Rise(maxi, CPUi386);
281 //case 0x756e6547: /* SiS processor */
282 // parse_i386_SiS(maxi, CPUi386);
285 //case 0x69727943: /* National Semiconductor processor */
286 // parse_i386_NSC(maxi, CPUi386);
290 printf("Unknown vendor\n");
294 /* Dump all the CPUID results in raw hex */
295 printf("\n Raw CPUID Dump:\n ---------------\n\n");
296 printf(" eax in eax ebx ecx edx\n");
300 unsigned long eax
,ebx
,ecx
,edx
;
302 i386_cpuid(i
,eax
,ebx
,ecx
,edx
);
303 printf(" %08x %08lx %08lx %08lx %08lx\n",i
,eax
,ebx
,ecx
,edx
);
306 i386_cpuid(0x80000000,maxei
,unused
,unused
,unused
);
308 for(li
=0x80000000;li
<=maxei
;li
++)
310 unsigned long eax
,ebx
,ecx
,edx
;
312 i386_cpuid(li
,eax
,ebx
,ecx
,edx
);
313 printf(" %08lx %08lx %08lx %08lx %08lx\n",li
,eax
,ebx
,ecx
,edx
);
318 /********************************************
319 Transmeta specific information
320 ********************************************/
322 void parse_i386_Transmeta( int maxi
, struct i386_compat_intern
* CPUi386
)
325 struct CPU_INTERN_DATA
*global
;
327 //ULONG maxei,unused;
331 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
333 //if ( maxi >= 3 ) /* Crusoe CPU serial number */
335 // unsigned long signature,unused,ebx;
337 // i386_cpuid(3,unused,ebx,unused,unused);
339 // Intel_CPU_NAME_cnt = AddBufferLine(Intel_CPU_NAME_cnt, Intel_CPU_NAME, " Processor serial: ");
341 // sprintf( BUFF_STR,"-%04lX",ebx >> 16);
342 // Intel_CPU_NAME_cnt = AddBufferLine(Intel_CPU_NAME_cnt, Intel_CPU_NAME, BUFF_STR);
343 // sprintf( BUFF_STR,"-%04lX",ebx & 0xffff);
344 // Intel_CPU_NAME_cnt = AddBufferLine(Intel_CPU_NAME_cnt, Intel_CPU_NAME, BUFF_STR);
347 speed
= i386_approx_mhz();
352 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
355 FreeMem(global
,sizeof(struct CPU_INTERN_DATA
));
359 /********************************************
360 UMC specific information
361 ********************************************/
363 void parse_i386_UMC( int maxi
, struct i386_compat_intern
* CPUi386
)
366 struct CPU_INTERN_DATA
*global
;
369 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
371 speed
= i386_approx_mhz();
376 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
379 FreeMem(global
,sizeof(struct CPU_INTERN_DATA
));
383 /********************************************
384 NexGen specific information
385 ********************************************/
387 void parse_i386_NexGen( int maxi
, struct i386_compat_intern
* CPUi386
)
390 struct CPU_INTERN_DATA
*global
;
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
;
416 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
418 //speed = i386_approx_mhz();
422 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
425 FreeMem(global
,sizeof(struct CPU_INTERN_DATA
));
429 /********************************************
430 SiS specific information
431 ********************************************/
433 void parse_i386_SiS( int maxi
, struct i386_compat_intern
* CPUi386
)
436 struct CPU_INTERN_DATA
*global
;
439 if ((global
= AllocMem(sizeof(struct CPU_INTERN_DATA
),MEMF_PUBLIC
|MEMF_CLEAR
)))
441 speed
= i386_approx_mhz();
446 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
449 FreeMem(global
,sizeof(struct CPU_INTERN_DATA
));