Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / c / CPUInfo / x86 / AMD / main.c
blobf91c41d8dac80441e71d9ec5a63016bb299814d7
1 /*
2 Copyright © 2000, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Probe installed AMD 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
17 *****************************************************************************************************/
19 #include "../x86.h"
21 /********************************************
22 Structures
23 ********************************************/
25 #define i386_amd_MAXBRANDS 7
26 char *i386_amd_Brands[i386_amd_MAXBRANDS] = {
27 "engineering sample NN (NN=xxxxxb)",
28 "AMD Athlon 64 XX00+ (XX=22+xxxxxb)",
29 "AMD Athlon 64 XX00+ (XX=22+xxxxxb) mobile",
30 "AMD Opteron UP 1YY (YY=38+2*xxxxxb)",
31 "AMD Opteron DP 2YY (YY=38+2*xxxxxb)",
32 "AMD Opteron MP 8YY (YY=38+2*xxxxxb)",
33 "AMD Athlon 64 FX-ZZ (ZZ=24+xxxxxb)",
36 /********************************************
37 AMD CPU Features
38 ********************************************/
40 char *AMD_feature_flags[] = {
41 "FPU : Floating Point Unit",
42 "VME : Virtual Mode Extensions",
43 "DE : Debugging Extensions",
44 "PSE : Page Size Extensions",
45 "TSC : Time Stamp Counter (with RDTSC and CR4 disable bit)",
46 "MSR : Model Specific Registers with i386_rdmsr & WRMSR",
47 "PAE : Page Address Extensions",
48 "MCE : Machine Check Exception",
49 "CX8 : COMPXCHG8B Instruction",
50 "APIC : On-chip Advanced Programmable Interrupt Controller present and enabled",
51 "10 : Reserved",
52 "SEP : SYSCALL/SYSRET or SYSENTER/SYSEXIT instructions",
53 "MTRR : Memory Type Range Registers",
54 "PGE : Global paging extension",
55 "MCA : Machine Check Architecture",
56 "CMOV : Conditional Move Instruction",
57 "PAT : Page Attribute Table",
58 "PSE-36 : Page Size Extensions",
59 "18 : Reserved",
60 "19 : Reserved",
61 "20 : Reserved",
62 "21 : Reserved",
63 "22 : AMD MMX Instruction Extensions",
64 "MMX : MMX instructions",
65 "FXSR : FXSAVE/FXRSTOR",
66 "25 : Reserved",
67 "26 : Reserved",
68 "27 : Reserved",
69 "28 : Reserved",
70 "29 : Reserved",
71 "30 : 3DNow! Instruction Extensions",
72 "31 : 3DNow instructions",
75 char *Assoc[] = {
76 "L2 off",
77 "Direct mapped",
78 "2-way",
79 "Reserved",
80 "4-way",
81 "Reserved",
82 "8-way",
83 "Reserved",
84 "16-way",
85 "Reserved",
86 "Reserved",
87 "Reserved",
88 "Reserved",
89 "Reserved",
90 "Reserved",
91 "FULL",
94 /********************************************
95 Data for FSB detection
96 ********************************************/
98 int amd64cm[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x4, 0x6, 0xB, 0xA, 0xC, 0xE, 0x10, 0x12, 0x14};
99 float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5};
100 float athloncoef2[] = {12, 19.0, 12, 20.0, 13.0, 13.5, 14.0, 21.0, 15, 22, 16, 16.5, 17, 18.0, 23, 24};
102 /********************************************
103 AMD-specific information
104 ********************************************/
106 void i386_poll_AMD32_FSB ( ULONG extclock, struct i386_compat_intern * CPUi386 )
108 unsigned int mcgsrl;
109 unsigned int mcgsth;
110 unsigned long temp;
111 double dramclock;
112 float coef;
114 //if (CPUi386->x86_capability & X86_FEATURE_TSC)
116 // coef = 10;
118 // i386_rdmsr(MSR_K7_HWCR, mcgsrl, mcgsth); /* First, got the FID */
119 // temp = (mcgsrl >> 24)&0x0F;
121 // if ((mcgsrl >> 19)&1) { coef = athloncoef2[temp]; }
122 // else { coef = athloncoef[temp]; }
124 // if (coef == 0) { coef = 1; };
126 // dramclock = (extclock /1000) / coef; /* Compute the final FSB Clock */
128 /* ...and print */
129 // printf(" Settings: FSB : %d Mhz (DDR) %d ", dramclock, (dramclock*2));
131 //else printf("\n WARNING! CPU doesnt support RDMSR - could not obtain FSB speed.\n");
134 /********************************************/
136 BOOL i386_AMD_isMobile ( int maxi )
138 unsigned long eax, ebx, ecx, edx;
140 if ( maxi >= 0x80000007 )
142 i386_cpuid( 0x80000007, eax, ebx, ecx, edx );
143 if ((edx & (1<<1|1<<2)) == 0) return FALSE;
144 else return TRUE;
146 else return FALSE;
149 /********************************************/
151 void i386_AMD_Athlon_Parse_MSR ( void )
153 printf("\t\t\t\t31 23 15 7 \n");
154 i386_Parse_MSR( 0x2A, 32 );
155 i386_Parse_MSR( MSR_K6_EFER, 32 );
156 i386_Parse_MSR( 0xC0010010, 32 );
157 i386_Parse_MSR( MSR_K7_HWCR, 32 );
158 i386_Parse_MSR( 0xC001001B, 32 );
159 printf ("\n");
162 /********************************************/
164 void i386_AMD_K6_Parse_MSR ( int family, int model, int stepping )
166 unsigned long msrvala=0,msrvalb=0;
168 printf("\t\t\t\t31 23 15 7 \n");
169 i386_Parse_MSR( MSR_K6_WHCR, 32 );
171 if ( ( model < 8 ) || ( ( model==8 ) && ( stepping <8 ) ) ) /* Original K6 or K6-2 (old core). */
173 i386_rdmsr( MSR_K6_WHCR, msrvala, msrvalb )
174 if ( ( ( msrvalb << 32 ) | msrvala ) == 1 )
176 printf ("Write allocate enable limit: %dMbytes\n", (int) ( ( ( ( msrvalb << 32 ) | msrvala ) & 0x7e ) >>1 ) * 4 );
177 printf ("Write allocate 15-16M bytes: %s\n", ( ( msrvalb << 32 ) | msrvala ) & 1 ? "enabled" : "disabled" );
179 else printf ("Couldn't read WHCR register.\n");
183 if ( ( model > 8 ) || ( ( model == 8 ) && ( stepping >= 8 ) ) ) /* K6-2 core (Stepping 8-F), K6-III or later. */
185 i386_rdmsr( MSR_K6_WHCR, msrvala, msrvalb );
186 if ( ( ( msrvalb << 32 ) | msrvala ) == 1)
188 if (!( ( ( msrvalb << 32 ) | msrvala ) & ( 0x3ff << 22 ) ) ) printf (" Write allocate disabled\n");
189 else
191 printf (" Write allocate enable limit: %dMbytes\n", (int) ( ( ( ( msrvalb << 32 ) | msrvala ) >> 22) & 0x3ff ) * 4 );
192 printf (" Write allocate 15-16M bytes: %s\n", ( ( msrvalb << 32 ) | msrvala ) & (1<<16) ? "enabled" : "disabled" );
195 else printf (" Couldn't read WHCR register.\n");
199 if ( ( family == 5 ) && ( model >= 8 ) ) /* Dump EWBE register on K6-2 & K6-3 */
201 i386_rdmsr( MSR_K6_EFER, msrvala, msrvalb );
202 if ( ( ( msrvalb << 32 ) | msrvala ) == 1 )
204 if ( ( ( msrvalb << 32 ) | msrvala ) & ( 1 << 0 ) ) printf ("System call extension present.\n");
205 if ( ( ( msrvalb << 32 ) | msrvala ) & ( 1 << 1 ) ) printf ("Data prefetch enabled.\n");
206 else printf (" Data prefetch disabled.\n");
208 printf (" EWBE mode: ");
209 switch ( ( ( ( msrvalb << 32 ) | msrvala ) & ( 1 << 2 | 1 << 3 | 1 << 4 ) ) >> 2 )
211 case 0: printf (" strong ordering (slowest performance)\n");
212 break;
213 case 1: printf (" speculative disable (close to best performance)\n");
214 break;
215 case 2: printf (" invalid\n");
216 break;
217 case 3: printf (" global disable (best performance)\n");
218 break;
221 else printf (" Couldn't read EFER register.\n");
224 printf ("\n");
227 /********************************************/
230 /********************************************/
232 void parse_i386_AMD ( int maxi, struct i386_compat_intern * CPUi386 )
234 struct CPU_INTERN_DATA *global;
235 ULONG speed, maxei,unused,connection;
236 char *BUFF_STR, *AMD_CPU_NAME, *AMD_CPU_IDENTITY, *AMD_CPU_FEATURES, *AMD_CPU_CACHE, *AMD_CPU_ADDR;
237 int AMD_CPU_NAME_cnt, AMD_CPU_IDENTITY_cnt, AMD_CPU_FEATURES_cnt, AMD_CPU_CACHE_cnt, AMD_CPU_ADDR_cnt;
238 int stepping,model,reserved;
239 int family = 0;
241 if ( ( global = AllocMem( sizeof( struct CPU_INTERN_DATA ), MEMF_PUBLIC|MEMF_CLEAR ) ) )
243 AMD_CPU_NAME = global->CPU_NAME;
244 AMD_CPU_IDENTITY = global->CPU_IDENTITY;
245 AMD_CPU_FEATURES = global->CPU_FEATURES;
246 AMD_CPU_CACHE = global->CPU_CACHE;
247 AMD_CPU_ADDR = global->CPU_ADDR;
248 BUFF_STR = global->CPU_BUFF;
250 AMD_CPU_NAME_cnt = AMD_CPU_IDENTITY_cnt = AMD_CPU_FEATURES_cnt = AMD_CPU_CACHE_cnt = AMD_CPU_ADDR_cnt = 0;
252 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " AMD-specific functions\n");
254 if ( maxi >= 1 ) /* Do standard stuff */
256 unsigned long eax,ebx,edx,unused,extended_family;
258 i386_cpuid( 1, eax, ebx, unused, edx);
260 stepping = eax & 0xf;
261 model = ( eax >> 4 ) & 0xf;
262 family = ( eax >> 8 ) & 0xf;
263 reserved = eax >> 12;
265 if ( family == 15 )
267 extended_family = (eax >> 20) & 0xff;
268 sprintf( BUFF_STR," Extended family %d",extended_family);
269 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, BUFF_STR);
271 switch ( extended_family )
273 case 0:
274 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "AMD K8" );
275 break;
280 sprintf( BUFF_STR," Version %08lx:\n",eax);
281 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, BUFF_STR );
282 sprintf( BUFF_STR," Family: %d Model: %d [",family,model);
283 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, BUFF_STR );
284 switch(family)
286 case 4:
287 connection = CONN_SOCKET_3;
288 switch ( model )
290 case 3:
291 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "486DX2" );
292 break;
293 case 7:
294 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "486DX2-WB" );
295 break;
296 case 8:
297 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "486DX4");
298 break;
299 case 9:
300 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "486DX4-WB");
301 break;
302 case 10:
303 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Elan SC400");
304 break;
305 case 14:
306 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "5x86");
307 break;
308 case 15:
309 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "5x86-WB");
310 break;
312 break;
313 case 5:
314 connection = CONN_SOCKET_7;
315 switch ( model )
317 case 0:
318 connection = CONN_SOCKET_5_7;
319 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "SSA5 (PR75/90/100)");
320 break;
321 case 1:
322 connection = CONN_SOCKET_5_7;
323 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "5k86 (PR120/133)");
324 break;
325 case 2:
326 connection = CONN_SOCKET_5_7;
327 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "5k86 (PR166)");
328 break;
329 case 3:
330 connection = CONN_SOCKET_5_7;
331 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "5k86 (PR200)");
332 break;
333 case 6:
334 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "K6 Model 6 (0.30 µm)");
335 break;
336 case 7:
337 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "K6 Model 7 (0.25 µm)");
338 break;
339 case 8:
340 connection = CONN_SUPER_SOCKET_7;
341 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "K6-2");
342 break;
343 case 9:
344 connection = CONN_SUPER_SOCKET_7;
345 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "K6-III");
346 break;
347 case 11:
348 connection = CONN_SUPER_SOCKET_7;
349 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "K6-2+ (0.18 µm)");
350 break;
351 case 13:
352 connection = CONN_SUPER_SOCKET_7;
353 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "K6-2+ or K6-III+ (0.18 µm)");
354 break;
355 default:
356 sprintf( BUFF_STR,"K5/K6 model %d",model);
357 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, BUFF_STR);
358 break;
360 break;
361 case 6:
362 connection = CONN_SOCKET_A;
363 if ( ( model > 4) && ( i386_AMD_isMobile( maxi ) == TRUE ) ) AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Mobile ");
364 switch ( model )
366 case 1:
367 connection = CONN_SLOT_A;
368 switch ( CPUi386->x86 )
370 case 1:
371 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [C1] (0.25 µm)");
372 break;
373 case 2:
374 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [C2] (0.25 µm)");
375 break;
377 break;
378 case 2:
379 connection = CONN_SLOT_A;
380 switch ( CPUi386->x86 )
382 case 1:
383 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [A1] (0.18 µm)");
384 break;
385 case 2:
386 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [A2] (0.18 µm)");
387 break;
389 break;
390 case 3:
391 switch ( CPUi386->x86 )
393 case 0:
394 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Duron Model [A0] (0.18 µm)(SF Core)");
395 break;
396 case 1:
397 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Duron Model [A2] (0.18 µm)(SF Core)");
398 break;
400 break;
401 case 4:
402 switch ( CPUi386->x86 )
404 case 0:
405 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [A1] (0.18 µm) (TB Core)");
406 break;
407 case 1:
408 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [A2] (0.18 µm) (TB Core)");
409 break;
410 case 2:
411 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [A4-A8] (0.18 µm) (TB Core)");
412 break;
413 case 3:
414 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model [A9] (0.18 µm) (TB Core)");
415 break;
417 break;
418 case 6:
419 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon MP/Mobile Athlon Model 6 (0.18 µm) (PM Core)");
420 break;
421 case 7:
422 switch ( CPUi386->x86 )
424 case 0:
425 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Duron Model [A0] (MG Core)");
426 break;
427 case 1:
428 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Duron Model [A1] (MG Core)");
429 break;
431 break;
432 case 8:
433 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model 8 (TH/AP Core)");
434 break;
435 case 10:
436 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon Model 10 (BT Core)");
437 break;
438 default:
439 sprintf( BUFF_STR,"Duron/Athlon model %d",model);
440 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, BUFF_STR);
441 break;
443 break;
444 case 15:
445 switch ( model )
447 case 4:
448 connection = CONN_SOCKET_754;
449 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon 64 (0.13 µm)");
450 break;
451 case 5:
452 connection = CONN_SOCKET_754;
453 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Athlon 64 FX or Opteron (0.13 µm)");
454 break;
455 default:
456 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Unknown 64bit Model!");
457 break;
459 break;
461 default:
462 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "Unknown Model!");
463 break;
466 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, "]\n");
468 int i;
470 sprintf( BUFF_STR," Standard feature flags [%08lx]:\n",edx);
471 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, BUFF_STR);
472 for(i=0;i<32;i++)
474 if(family == 5 && model == 0)
476 if(i == 9) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Global Paging Extensions\n");
477 else if(i == 13) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, "13 - reserved\n");
479 else if(edx & (1<<i))
481 sprintf( BUFF_STR," %s\n",AMD_feature_flags[i]);
482 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, BUFF_STR);
486 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, "\n");
490 i386_cpuid( 0x80000000, maxei, unused, unused, unused ); /* Check for presence of extended info */
492 if ( maxei == 0 ) return;
494 int stepping,model,generation,reserved;
496 if ( maxei >= 0x80000001 )
498 unsigned long eax,ebx,ecx,edx;
499 int i;
501 i386_cpuid(0x80000001,eax,ebx,ecx,edx);
502 stepping = eax & 0xf;
503 model = (eax >> 4) & 0xf;
504 generation = (eax >> 8) & 0xf;
505 reserved = eax >> 12;
507 sprintf( BUFF_STR," Generation: %d Model: %d\n\n",generation,model);
508 AMD_CPU_IDENTITY_cnt = AddBufferLine( AMD_CPU_IDENTITY_cnt, AMD_CPU_IDENTITY, BUFF_STR);
509 sprintf( BUFF_STR," Extended feature flags [%08lx]:\n",edx);
510 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, BUFF_STR);
511 for(i=0;i<32;i++)
513 if(family == 5 && model == 0 && i == 9) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Global Paging Extensions\n");
514 else if(edx & (1<<i))
516 sprintf( BUFF_STR," %s\n",AMD_feature_flags[i]);
517 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, BUFF_STR);
522 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, "\n");
523 if ( maxei >= 0x80000002 ) /* Processor identification string */
525 int j;
526 AMD_CPU_NAME_cnt = AddBufferLine( AMD_CPU_NAME_cnt, AMD_CPU_NAME, " Processor name string: ");
527 for(j=0x80000002;j<=0x80000004;j++)
529 unsigned long eax,ebx,ecx,edx;
531 i386_cpuid(j,eax,ebx,ecx,edx);
532 AMD_CPU_NAME_cnt = i386_sprintregs(AMD_CPU_NAME_cnt, AMD_CPU_NAME, eax,ebx,ecx,edx);
534 AMD_CPU_NAME_cnt = AddBufferLine( AMD_CPU_NAME_cnt, AMD_CPU_NAME, "\n");
537 if ( maxei >= 0x80000005 ) /* TLB and cache info */
540 unsigned long eax,ebx,ecx,edx;
542 i386_cpuid(0x80000005,eax,ebx,ecx,edx);
543 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " L1 Cache Information:\n");
545 if(family >= 6)
547 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " 2/4-MB Pages:\n");
548 sprintf( BUFF_STR," Data TLB: associativity %ld-way #entries %ld\n", (eax >> 24) & 0xff,(eax >> 16) & 0xff);
549 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
550 sprintf( BUFF_STR," Instruction TLB: associativity %ld-way #entries %ld\n", (eax >> 8) & 0xff,eax & 0xff);
551 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
554 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " 4-KB Pages:\n");
555 sprintf( BUFF_STR," Data TLB: associativity %ld-way #entries %ld\n", (ebx >> 24) & 0xff,(ebx >> 16) & 0xff);
556 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
557 sprintf( BUFF_STR," Instruction TLB: associativity %ld-way #entries %ld\n", (ebx >> 8) & 0xff,ebx & 0xff);
558 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
560 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " L1 Data cache:\n");
561 sprintf( BUFF_STR," size %ld KB associativity %lx-way lines per tag %ld line size %ld\n", ecx >> 24,(ecx>>16) & 0xff,(ecx >> 8)&0xff,ecx&0xff);
562 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
564 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " L1 Instruction cache:\n");
565 sprintf( BUFF_STR," size %ld KB associativity %lx-way lines per tag %ld line size %ld\n\n", edx >> 24,(edx>>16) & 0xff,(edx >> 8)&0xff,edx&0xff);
566 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
569 if ( maxei >= 0x80000006 ) /* check K6-III (and later?) on-chip L2 cache size */
571 unsigned long eax,ebx,ecx,unused;
572 int assoc;
574 i386_cpuid(0x80000006,eax,ebx,ecx,unused);
575 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " L2 Cache Information:\n");
577 if(family >= 6)
579 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " 2/4-MB Pages:\n");
580 assoc = (eax >> 24) & 0xff;
582 if(assoc == 6) assoc = 8;
584 sprintf( BUFF_STR," Data TLB: associativity %s #entries %ld\n", Assoc[(eax >> 24) & 0xf],(eax >> 16) & 0xff);
585 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
586 assoc = (eax >> 16) & 0xff;
587 sprintf( BUFF_STR," Instruction TLB: associativity %s #entries %ld\n", Assoc[(eax >> 8) & 0xf],eax & 0xff);
588 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
590 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, " 4-KB Pages:\n");
591 sprintf( BUFF_STR," Data TLB: associativity %s #entries %ld\n", Assoc[(ebx >> 24) & 0xf],(ebx >> 16) & 0xff);
592 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
593 sprintf( BUFF_STR," Instruction TLB: associativity %s #entries %ld\n", Assoc[(ebx >> 8) & 0xf],ebx & 0xff);
594 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
596 sprintf( BUFF_STR," size %ld KB associativity %s lines per tag %ld line size %ld\n", ecx >> 24,Assoc[(ecx>>16) & 0xf],(ecx >> 8)&0xff,ecx&0xff);
597 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, BUFF_STR);
599 AMD_CPU_CACHE_cnt = AddBufferLine( AMD_CPU_CACHE_cnt, AMD_CPU_CACHE, "\n");
602 if ( maxei >= 0x80000007 ) /* Check power management feature flags */
604 unsigned long unused,edx;
606 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Advanced Power Management (PowerNOW!) Feature Flags\n");
608 i386_cpuid(0x80000007,unused,unused,unused,edx);
609 if(edx & 1) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Temperature Sensing Diode\n");
610 if(edx & 2) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Supports Frequency ID control\n");
611 if(edx & 4) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Supports Voltage ID control\n");
612 if(edx & 8) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Supports Thermal Trip\n");
613 if(edx & 16) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Supports Thermal Monitoring\n");
614 if(edx & 31) AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, " Supports Software Thermal Control\n");
615 AMD_CPU_FEATURES_cnt = AddBufferLine( AMD_CPU_FEATURES_cnt, AMD_CPU_FEATURES, "\n");
618 if ( maxei >= 0x80000008 ) /* Check phys address & linear address size */
620 unsigned long unused,eax;
622 i386_cpuid(0x80000008,eax,unused,unused,unused);
623 sprintf( BUFF_STR," Maximum LINEAR address: %ld; Maximum PHYSICAL address %ld\n\n", (eax>>8) & 0xff,eax&0xff);
624 AMD_CPU_ADDR_cnt = AddBufferLine( AMD_CPU_ADDR_cnt, AMD_CPU_ADDR, BUFF_STR);
627 /** DUMP ALL THE INFORMATION WE HAVE GATHERED **/
629 if ( AMD_CPU_NAME_cnt > 0 ) printf( AMD_CPU_NAME ); /* CPUs Retail Name */
631 speed = i386_approx_mhz();
633 i386_poll_AMD32_FSB( speed, CPUi386 ); /* Calculate FSB .. */
636 if ( AMD_CPU_IDENTITY_cnt > 0 ) printf( AMD_CPU_IDENTITY ); /* CPUs Internal Name */
637 if ( AMD_CPU_FEATURES_cnt > 0 ) printf( AMD_CPU_FEATURES ); /* CPUs Feature Set */
638 if ( AMD_CPU_ADDR_cnt > 0 ) printf( AMD_CPU_ADDR ); /* CPUs Address Range */
639 if ( AMD_CPU_CACHE_cnt > 0 ) printf( AMD_CPU_CACHE ); /* CPUs Cache Details */
641 /*if ( family == 5 ) i386_AMD_K6_Parse_MSR( family, model, stepping );
642 if ( family == 6 ) i386_AMD_Athlon_Parse_MSR(); */
644 else
646 printf( "ERROR: Couldn't allocate memory to parse CPU information .." );
647 return;
649 FreeMem(global,sizeof(struct CPU_INTERN_DATA));