12b33a0f9SSteve Passe /* 22b33a0f9SSteve Passe * Copyright (c) 1996, by Steve Passe 32b33a0f9SSteve Passe * All rights reserved. 42b33a0f9SSteve Passe * 52b33a0f9SSteve Passe * Redistribution and use in source and binary forms, with or without 62b33a0f9SSteve Passe * modification, are permitted provided that the following conditions 72b33a0f9SSteve Passe * are met: 82b33a0f9SSteve Passe * 1. Redistributions of source code must retain the above copyright 92b33a0f9SSteve Passe * notice, this list of conditions and the following disclaimer. 102b33a0f9SSteve Passe * 2. The name of the developer may NOT be used to endorse or promote products 112b33a0f9SSteve Passe * derived from this software without specific prior written permission. 122b33a0f9SSteve Passe * 132b33a0f9SSteve Passe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 142b33a0f9SSteve Passe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 152b33a0f9SSteve Passe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 162b33a0f9SSteve Passe * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 172b33a0f9SSteve Passe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 182b33a0f9SSteve Passe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 192b33a0f9SSteve Passe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 202b33a0f9SSteve Passe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 212b33a0f9SSteve Passe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 222b33a0f9SSteve Passe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 232b33a0f9SSteve Passe * SUCH DAMAGE. 242b33a0f9SSteve Passe */ 252b33a0f9SSteve Passe 262b33a0f9SSteve Passe /* 272b33a0f9SSteve Passe * mptable.c 282b33a0f9SSteve Passe */ 292b33a0f9SSteve Passe 30ec175cedSPhilippe Charnier #ifndef lint 31ec175cedSPhilippe Charnier static const char rcsid[] = 3297d92980SPeter Wemm "$FreeBSD$"; 33ec175cedSPhilippe Charnier #endif /* not lint */ 34ec175cedSPhilippe Charnier 352b33a0f9SSteve Passe #define VMAJOR 2 362b33a0f9SSteve Passe #define VMINOR 0 37fb42160fSSteve Passe #define VDELTA 15 382b33a0f9SSteve Passe 392b33a0f9SSteve Passe /* 402b33a0f9SSteve Passe * this will cause the raw mp table to be dumped to /tmp/mpdump 412b33a0f9SSteve Passe * 422b33a0f9SSteve Passe #define RAW_DUMP 432b33a0f9SSteve Passe */ 442b33a0f9SSteve Passe 452b33a0f9SSteve Passe #define MP_SIG 0x5f504d5f /* _MP_ */ 462b33a0f9SSteve Passe #define EXTENDED_PROCESSING_READY 472b33a0f9SSteve Passe #define OEM_PROCESSING_READY_NOT 482b33a0f9SSteve Passe 497ffc1f40SBruce Evans #include <sys/types.h> 50ec175cedSPhilippe Charnier #include <err.h> 512b33a0f9SSteve Passe #include <fcntl.h> 521a37aa56SDavid E. O'Brien #include <paths.h> 53ec175cedSPhilippe Charnier #include <stdio.h> 54ec175cedSPhilippe Charnier #include <stdlib.h> 55ec175cedSPhilippe Charnier #include <string.h> 562b33a0f9SSteve Passe #include <unistd.h> 572b33a0f9SSteve Passe 582b33a0f9SSteve Passe #define SEP_LINE \ 592b33a0f9SSteve Passe "\n-------------------------------------------------------------------------------\n" 602b33a0f9SSteve Passe 612b33a0f9SSteve Passe #define SEP_LINE2 \ 622b33a0f9SSteve Passe "\n===============================================================================\n" 632b33a0f9SSteve Passe 642b33a0f9SSteve Passe /* EBDA is @ 40:0e in real-mode terms */ 652b33a0f9SSteve Passe #define EBDA_POINTER 0x040e /* location of EBDA pointer */ 662b33a0f9SSteve Passe 672b33a0f9SSteve Passe /* CMOS 'top of mem' is @ 40:13 in real-mode terms */ 682b33a0f9SSteve Passe #define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */ 692b33a0f9SSteve Passe 702b33a0f9SSteve Passe #define DEFAULT_TOPOFMEM 0xa0000 712b33a0f9SSteve Passe 722b33a0f9SSteve Passe #define BIOS_BASE 0xf0000 732b33a0f9SSteve Passe #define BIOS_BASE2 0xe0000 742b33a0f9SSteve Passe #define BIOS_SIZE 0x10000 752b33a0f9SSteve Passe #define ONE_KBYTE 1024 762b33a0f9SSteve Passe 772b33a0f9SSteve Passe #define GROPE_AREA1 0x80000 782b33a0f9SSteve Passe #define GROPE_AREA2 0x90000 792b33a0f9SSteve Passe #define GROPE_SIZE 0x10000 802b33a0f9SSteve Passe 812b33a0f9SSteve Passe #define PROCENTRY_FLAG_EN 0x01 822b33a0f9SSteve Passe #define PROCENTRY_FLAG_BP 0x02 832b33a0f9SSteve Passe #define IOAPICENTRY_FLAG_EN 0x01 842b33a0f9SSteve Passe 852b33a0f9SSteve Passe #define MAXPNSTR 132 862b33a0f9SSteve Passe 872b33a0f9SSteve Passe enum busTypes { 882b33a0f9SSteve Passe CBUS = 1, 892b33a0f9SSteve Passe CBUSII = 2, 902b33a0f9SSteve Passe EISA = 3, 912b33a0f9SSteve Passe ISA = 6, 922b33a0f9SSteve Passe PCI = 13, 932b33a0f9SSteve Passe XPRESS = 18, 942b33a0f9SSteve Passe MAX_BUSTYPE = 18, 952b33a0f9SSteve Passe UNKNOWN_BUSTYPE = 0xff 962b33a0f9SSteve Passe }; 972b33a0f9SSteve Passe 982b33a0f9SSteve Passe typedef struct BUSTYPENAME { 992b33a0f9SSteve Passe u_char type; 1002b33a0f9SSteve Passe char name[ 7 ]; 1012b33a0f9SSteve Passe } busTypeName; 1022b33a0f9SSteve Passe 1032b33a0f9SSteve Passe static busTypeName busTypeTable[] = 1042b33a0f9SSteve Passe { 1052b33a0f9SSteve Passe { CBUS, "CBUS" }, 1062b33a0f9SSteve Passe { CBUSII, "CBUSII" }, 1072b33a0f9SSteve Passe { EISA, "EISA" }, 1082b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1092b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1102b33a0f9SSteve Passe { ISA, "ISA" }, 1112b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1122b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1132b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1142b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1152b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1162b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1172b33a0f9SSteve Passe { PCI, "PCI" }, 1182b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1192b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1202b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1212b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1222b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1232b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" } 1242b33a0f9SSteve Passe }; 1252b33a0f9SSteve Passe 1268c489d72SPeter Wemm const char* whereStrings[] = { 1272b33a0f9SSteve Passe "Extended BIOS Data Area", 1282b33a0f9SSteve Passe "BIOS top of memory", 1292b33a0f9SSteve Passe "Default top of memory", 1302b33a0f9SSteve Passe "BIOS", 1312b33a0f9SSteve Passe "Extended BIOS", 1322b33a0f9SSteve Passe "GROPE AREA #1", 1332b33a0f9SSteve Passe "GROPE AREA #2" 1342b33a0f9SSteve Passe }; 1352b33a0f9SSteve Passe 1362b33a0f9SSteve Passe typedef struct TABLE_ENTRY { 1372b33a0f9SSteve Passe u_char type; 1382b33a0f9SSteve Passe u_char length; 1392b33a0f9SSteve Passe char name[ 32 ]; 1402b33a0f9SSteve Passe } tableEntry; 1412b33a0f9SSteve Passe 1422b33a0f9SSteve Passe tableEntry basetableEntryTypes[] = 1432b33a0f9SSteve Passe { 1442b33a0f9SSteve Passe { 0, 20, "Processor" }, 1452b33a0f9SSteve Passe { 1, 8, "Bus" }, 1462b33a0f9SSteve Passe { 2, 8, "I/O APIC" }, 1472b33a0f9SSteve Passe { 3, 8, "I/O INT" }, 1482b33a0f9SSteve Passe { 4, 8, "Local INT" } 1492b33a0f9SSteve Passe }; 1502b33a0f9SSteve Passe 1512b33a0f9SSteve Passe tableEntry extendedtableEntryTypes[] = 1522b33a0f9SSteve Passe { 1532b33a0f9SSteve Passe { 128, 20, "System Address Space" }, 1542b33a0f9SSteve Passe { 129, 8, "Bus Heirarchy" }, 1552b33a0f9SSteve Passe { 130, 8, "Compatibility Bus Address" } 1562b33a0f9SSteve Passe }; 1572b33a0f9SSteve Passe 1582b33a0f9SSteve Passe /* MP Floating Pointer Structure */ 1592b33a0f9SSteve Passe typedef struct MPFPS { 1602b33a0f9SSteve Passe char signature[ 4 ]; 1618c489d72SPeter Wemm u_int32_t pap; 1622b33a0f9SSteve Passe u_char length; 1632b33a0f9SSteve Passe u_char spec_rev; 1642b33a0f9SSteve Passe u_char checksum; 1652b33a0f9SSteve Passe u_char mpfb1; 1662b33a0f9SSteve Passe u_char mpfb2; 1672b33a0f9SSteve Passe u_char mpfb3; 1682b33a0f9SSteve Passe u_char mpfb4; 1692b33a0f9SSteve Passe u_char mpfb5; 1702b33a0f9SSteve Passe } mpfps_t; 1712b33a0f9SSteve Passe 1722b33a0f9SSteve Passe /* MP Configuration Table Header */ 1732b33a0f9SSteve Passe typedef struct MPCTH { 1742b33a0f9SSteve Passe char signature[ 4 ]; 1752b33a0f9SSteve Passe u_short base_table_length; 1762b33a0f9SSteve Passe u_char spec_rev; 1772b33a0f9SSteve Passe u_char checksum; 1782b33a0f9SSteve Passe u_char oem_id[ 8 ]; 1792b33a0f9SSteve Passe u_char product_id[ 12 ]; 1808c489d72SPeter Wemm u_int32_t oem_table_pointer; 1812b33a0f9SSteve Passe u_short oem_table_size; 1822b33a0f9SSteve Passe u_short entry_count; 1838c489d72SPeter Wemm u_int32_t apic_address; 1842b33a0f9SSteve Passe u_short extended_table_length; 1852b33a0f9SSteve Passe u_char extended_table_checksum; 1862b33a0f9SSteve Passe u_char reserved; 1872b33a0f9SSteve Passe } mpcth_t; 1882b33a0f9SSteve Passe 1892b33a0f9SSteve Passe 1902b33a0f9SSteve Passe typedef struct PROCENTRY { 1912b33a0f9SSteve Passe u_char type; 1922b33a0f9SSteve Passe u_char apicID; 1932b33a0f9SSteve Passe u_char apicVersion; 1942b33a0f9SSteve Passe u_char cpuFlags; 1958c489d72SPeter Wemm u_int32_t cpuSignature; 1968c489d72SPeter Wemm u_int32_t featureFlags; 1978c489d72SPeter Wemm u_int32_t reserved1; 1988c489d72SPeter Wemm u_int32_t reserved2; 1992b33a0f9SSteve Passe } ProcEntry; 2002b33a0f9SSteve Passe 2012b33a0f9SSteve Passe typedef struct BUSENTRY { 2022b33a0f9SSteve Passe u_char type; 2032b33a0f9SSteve Passe u_char busID; 2042b33a0f9SSteve Passe char busType[ 6 ]; 2052b33a0f9SSteve Passe } BusEntry; 2062b33a0f9SSteve Passe 2072b33a0f9SSteve Passe typedef struct IOAPICENTRY { 2082b33a0f9SSteve Passe u_char type; 2092b33a0f9SSteve Passe u_char apicID; 2102b33a0f9SSteve Passe u_char apicVersion; 2112b33a0f9SSteve Passe u_char apicFlags; 2128c489d72SPeter Wemm u_int32_t apicAddress; 2132b33a0f9SSteve Passe } IOApicEntry; 2142b33a0f9SSteve Passe 2152b33a0f9SSteve Passe typedef struct INTENTRY { 2162b33a0f9SSteve Passe u_char type; 2172b33a0f9SSteve Passe u_char intType; 2182b33a0f9SSteve Passe u_short intFlags; 2192b33a0f9SSteve Passe u_char srcBusID; 2202b33a0f9SSteve Passe u_char srcBusIRQ; 2212b33a0f9SSteve Passe u_char dstApicID; 2222b33a0f9SSteve Passe u_char dstApicINT; 2232b33a0f9SSteve Passe } IntEntry; 2242b33a0f9SSteve Passe 2252b33a0f9SSteve Passe 2262b33a0f9SSteve Passe /* 2272b33a0f9SSteve Passe * extended entry type structures 2282b33a0f9SSteve Passe */ 2292b33a0f9SSteve Passe 2302b33a0f9SSteve Passe typedef struct SASENTRY { 2312b33a0f9SSteve Passe u_char type; 2322b33a0f9SSteve Passe u_char length; 2332b33a0f9SSteve Passe u_char busID; 2342b33a0f9SSteve Passe u_char addressType; 2352b33a0f9SSteve Passe u_int64_t addressBase; 2362b33a0f9SSteve Passe u_int64_t addressLength; 2378c489d72SPeter Wemm } __attribute__((__packed__)) SasEntry; 2382b33a0f9SSteve Passe 2392b33a0f9SSteve Passe 2402b33a0f9SSteve Passe typedef struct BHDENTRY { 2412b33a0f9SSteve Passe u_char type; 2422b33a0f9SSteve Passe u_char length; 2432b33a0f9SSteve Passe u_char busID; 2442b33a0f9SSteve Passe u_char busInfo; 2452b33a0f9SSteve Passe u_char busParent; 2462b33a0f9SSteve Passe u_char reserved[ 3 ]; 2472b33a0f9SSteve Passe } BhdEntry; 2482b33a0f9SSteve Passe 2492b33a0f9SSteve Passe 2502b33a0f9SSteve Passe typedef struct CBASMENTRY { 2512b33a0f9SSteve Passe u_char type; 2522b33a0f9SSteve Passe u_char length; 2532b33a0f9SSteve Passe u_char busID; 2542b33a0f9SSteve Passe u_char addressMod; 2552b33a0f9SSteve Passe u_int predefinedRange; 2562b33a0f9SSteve Passe } CbasmEntry; 2572b33a0f9SSteve Passe 2582b33a0f9SSteve Passe 2592b33a0f9SSteve Passe 2608c489d72SPeter Wemm static void apic_probe( u_int32_t* paddr, int* where ); 2612b33a0f9SSteve Passe 2622b33a0f9SSteve Passe static void MPConfigDefault( int featureByte ); 2632b33a0f9SSteve Passe 2648c489d72SPeter Wemm static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps ); 2658c489d72SPeter Wemm static void MPConfigTableHeader( u_int32_t pap ); 2662b33a0f9SSteve Passe 2672b33a0f9SSteve Passe static int readType( void ); 2688c489d72SPeter Wemm static void seekEntry( u_int32_t addr ); 2692b33a0f9SSteve Passe static void readEntry( void* entry, int size ); 2702b33a0f9SSteve Passe 2712b33a0f9SSteve Passe static void processorEntry( void ); 2722b33a0f9SSteve Passe static void busEntry( void ); 2732b33a0f9SSteve Passe static void ioApicEntry( void ); 2742b33a0f9SSteve Passe static void intEntry( void ); 2752b33a0f9SSteve Passe 2762b33a0f9SSteve Passe static void sasEntry( void ); 2772b33a0f9SSteve Passe static void bhdEntry( void ); 2782b33a0f9SSteve Passe static void cbasmEntry( void ); 2792b33a0f9SSteve Passe 2802b33a0f9SSteve Passe static void doDmesg( void ); 2812b33a0f9SSteve Passe static void pnstr( char* s, int c ); 2822b33a0f9SSteve Passe 2832b33a0f9SSteve Passe /* global data */ 2842b33a0f9SSteve Passe int pfd; /* physical /dev/mem fd */ 2852b33a0f9SSteve Passe 2862b33a0f9SSteve Passe int busses[ 16 ]; 2872b33a0f9SSteve Passe int apics[ 16 ]; 2882b33a0f9SSteve Passe 2892b33a0f9SSteve Passe int ncpu; 2902b33a0f9SSteve Passe int nbus; 2912b33a0f9SSteve Passe int napic; 2922b33a0f9SSteve Passe int nintr; 2932b33a0f9SSteve Passe 2942b33a0f9SSteve Passe int dmesg; 2952b33a0f9SSteve Passe int grope; 2962b33a0f9SSteve Passe int verbose; 2972b33a0f9SSteve Passe 2982b33a0f9SSteve Passe static void 2992b33a0f9SSteve Passe usage( void ) 3002b33a0f9SSteve Passe { 301ec175cedSPhilippe Charnier fprintf( stderr, "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n" ); 3022b33a0f9SSteve Passe exit( 0 ); 3032b33a0f9SSteve Passe } 3042b33a0f9SSteve Passe 3052b33a0f9SSteve Passe /* 3062b33a0f9SSteve Passe * 3072b33a0f9SSteve Passe */ 3082b33a0f9SSteve Passe int 3092b33a0f9SSteve Passe main( int argc, char *argv[] ) 3102b33a0f9SSteve Passe { 3118c489d72SPeter Wemm u_int32_t paddr; 3122b33a0f9SSteve Passe int where; 3132b33a0f9SSteve Passe mpfps_t mpfps; 3142b33a0f9SSteve Passe int defaultConfig; 3152b33a0f9SSteve Passe 3162b33a0f9SSteve Passe int ch; 3172b33a0f9SSteve Passe 3182b33a0f9SSteve Passe /* announce ourselves */ 3192b33a0f9SSteve Passe puts( SEP_LINE2 ); 3202b33a0f9SSteve Passe 3212b33a0f9SSteve Passe printf( "MPTable, version %d.%d.%d\n", VMAJOR, VMINOR, VDELTA ); 3222b33a0f9SSteve Passe 323b790f1b6SWarner Losh while ((ch = getopt(argc, argv, "d:g:h:v:")) != -1) { 3242b33a0f9SSteve Passe switch(ch) { 3252b33a0f9SSteve Passe case 'd': 3262b33a0f9SSteve Passe if ( strcmp( optarg, "mesg") == 0 ) 3272b33a0f9SSteve Passe dmesg = 1; 3282b33a0f9SSteve Passe else 3292b33a0f9SSteve Passe dmesg = 0; 3302b33a0f9SSteve Passe break; 3312b33a0f9SSteve Passe case 'h': 3322b33a0f9SSteve Passe if ( strcmp( optarg, "elp") == 0 ) 3332b33a0f9SSteve Passe usage(); 3342b33a0f9SSteve Passe break; 3352b33a0f9SSteve Passe case 'g': 3369d35fde7SSteve Passe if ( strcmp( optarg, "rope") == 0 ) 3372b33a0f9SSteve Passe grope = 1; 3382b33a0f9SSteve Passe break; 3392b33a0f9SSteve Passe case 'v': 3402b33a0f9SSteve Passe if ( strcmp( optarg, "erbose") == 0 ) 3412b33a0f9SSteve Passe verbose = 1; 3422b33a0f9SSteve Passe break; 3432b33a0f9SSteve Passe default: 3442b33a0f9SSteve Passe usage(); 3452b33a0f9SSteve Passe } 3462b33a0f9SSteve Passe argc -= optind; 3472b33a0f9SSteve Passe argv += optind; 3482b33a0f9SSteve Passe optreset = 1; 3492b33a0f9SSteve Passe optind = 0; 3502b33a0f9SSteve Passe } 3512b33a0f9SSteve Passe 3522b33a0f9SSteve Passe /* open physical memory for access to MP structures */ 3531a37aa56SDavid E. O'Brien if ( (pfd = open( _PATH_MEM, O_RDONLY )) < 0 ) 354ec175cedSPhilippe Charnier err( 1, "mem open" ); 3552b33a0f9SSteve Passe 3562b33a0f9SSteve Passe /* probe for MP structures */ 3572b33a0f9SSteve Passe apic_probe( &paddr, &where ); 3582b33a0f9SSteve Passe if ( where <= 0 ) { 3592b33a0f9SSteve Passe fprintf( stderr, "\n MP FPS NOT found,\n" ); 3602b33a0f9SSteve Passe fprintf( stderr, " suggest trying -grope option!!!\n\n" ); 3612b33a0f9SSteve Passe return 1; 3622b33a0f9SSteve Passe } 3632b33a0f9SSteve Passe 3642b33a0f9SSteve Passe if ( verbose ) 3652b33a0f9SSteve Passe printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n", 3662b33a0f9SSteve Passe whereStrings[ where - 1 ], paddr ); 3672b33a0f9SSteve Passe 3682b33a0f9SSteve Passe puts( SEP_LINE ); 3692b33a0f9SSteve Passe 3702b33a0f9SSteve Passe /* analyze the MP Floating Pointer Structure */ 3712b33a0f9SSteve Passe MPFloatingPointer( paddr, where, &mpfps ); 3722b33a0f9SSteve Passe 3732b33a0f9SSteve Passe puts( SEP_LINE ); 3742b33a0f9SSteve Passe 3752b33a0f9SSteve Passe /* check whether an MP config table exists */ 376ec175cedSPhilippe Charnier if ( (defaultConfig = mpfps.mpfb1) ) 3772b33a0f9SSteve Passe MPConfigDefault( defaultConfig ); 3782b33a0f9SSteve Passe else 3792b33a0f9SSteve Passe MPConfigTableHeader( mpfps.pap ); 3802b33a0f9SSteve Passe 3812b33a0f9SSteve Passe /* do a dmesg output */ 3822b33a0f9SSteve Passe if ( dmesg ) 3832b33a0f9SSteve Passe doDmesg(); 3842b33a0f9SSteve Passe 3852b33a0f9SSteve Passe puts( SEP_LINE2 ); 3862b33a0f9SSteve Passe 3872b33a0f9SSteve Passe return 0; 3882b33a0f9SSteve Passe } 3892b33a0f9SSteve Passe 3902b33a0f9SSteve Passe 3912b33a0f9SSteve Passe /* 3922b33a0f9SSteve Passe * set PHYSICAL address of MP floating pointer structure 3932b33a0f9SSteve Passe */ 3942b33a0f9SSteve Passe #define NEXT(X) ((X) += 4) 3952b33a0f9SSteve Passe static void 3968c489d72SPeter Wemm apic_probe( u_int32_t* paddr, int* where ) 3972b33a0f9SSteve Passe { 3982b33a0f9SSteve Passe /* 3992b33a0f9SSteve Passe * c rewrite of apic_probe() by Jack F. Vogel 4002b33a0f9SSteve Passe */ 4012b33a0f9SSteve Passe 4022b33a0f9SSteve Passe int x; 4032b33a0f9SSteve Passe u_short segment; 4048c489d72SPeter Wemm u_int32_t target; 4052b33a0f9SSteve Passe u_int buffer[ BIOS_SIZE / sizeof( int ) ]; 4062b33a0f9SSteve Passe 4072b33a0f9SSteve Passe if ( verbose ) 4082b33a0f9SSteve Passe printf( "\n" ); 4092b33a0f9SSteve Passe 4102b33a0f9SSteve Passe /* search Extended Bios Data Area, if present */ 4112b33a0f9SSteve Passe if ( verbose ) 4122b33a0f9SSteve Passe printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER ); 4138c489d72SPeter Wemm seekEntry( (u_int32_t)EBDA_POINTER ); 4142b33a0f9SSteve Passe readEntry( &segment, 2 ); 4152b33a0f9SSteve Passe if ( segment ) { /* search EBDA */ 4168c489d72SPeter Wemm target = (u_int32_t)segment << 4; 4172b33a0f9SSteve Passe if ( verbose ) 4182b33a0f9SSteve Passe printf( "found, searching EBDA @ 0x%08x\n", target ); 4192b33a0f9SSteve Passe seekEntry( target ); 4202b33a0f9SSteve Passe readEntry( buffer, ONE_KBYTE ); 4212b33a0f9SSteve Passe 4228c489d72SPeter Wemm for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 4232b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 4242b33a0f9SSteve Passe *where = 1; 4252b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + target; 4262b33a0f9SSteve Passe return; 4272b33a0f9SSteve Passe } 4282b33a0f9SSteve Passe } 4292b33a0f9SSteve Passe } 4302b33a0f9SSteve Passe else { 4312b33a0f9SSteve Passe if ( verbose ) 4322b33a0f9SSteve Passe printf( "NOT found\n" ); 4332b33a0f9SSteve Passe } 4342b33a0f9SSteve Passe 4352b33a0f9SSteve Passe /* read CMOS for real top of mem */ 4368c489d72SPeter Wemm seekEntry( (u_int32_t)TOPOFMEM_POINTER ); 4372b33a0f9SSteve Passe readEntry( &segment, 2 ); 4382b33a0f9SSteve Passe --segment; /* less ONE_KBYTE */ 4392b33a0f9SSteve Passe target = segment * 1024; 4402b33a0f9SSteve Passe if ( verbose ) 4412b33a0f9SSteve Passe printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n", 4422b33a0f9SSteve Passe target, segment ); 4432b33a0f9SSteve Passe seekEntry( target ); 4442b33a0f9SSteve Passe readEntry( buffer, ONE_KBYTE ); 4452b33a0f9SSteve Passe 4468c489d72SPeter Wemm for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 4472b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 4482b33a0f9SSteve Passe *where = 2; 4492b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + target; 4502b33a0f9SSteve Passe return; 4512b33a0f9SSteve Passe } 4522b33a0f9SSteve Passe } 4532b33a0f9SSteve Passe 4542b33a0f9SSteve Passe /* we don't necessarily believe CMOS, check base of the last 1K of 640K */ 4552b33a0f9SSteve Passe if ( target != (DEFAULT_TOPOFMEM - 1024)) { 4562b33a0f9SSteve Passe target = (DEFAULT_TOPOFMEM - 1024); 4572b33a0f9SSteve Passe if ( verbose ) 4582b33a0f9SSteve Passe printf( " searching default 'top of mem' @ 0x%08x (%dK)\n", 4592b33a0f9SSteve Passe target, (target / 1024) ); 4602b33a0f9SSteve Passe seekEntry( target ); 4612b33a0f9SSteve Passe readEntry( buffer, ONE_KBYTE ); 4622b33a0f9SSteve Passe 4638c489d72SPeter Wemm for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 4642b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 4652b33a0f9SSteve Passe *where = 3; 4662b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + target; 4672b33a0f9SSteve Passe return; 4682b33a0f9SSteve Passe } 4692b33a0f9SSteve Passe } 4702b33a0f9SSteve Passe } 4712b33a0f9SSteve Passe 4722b33a0f9SSteve Passe /* search the BIOS */ 4732b33a0f9SSteve Passe if ( verbose ) 4742b33a0f9SSteve Passe printf( " searching BIOS @ 0x%08x\n", BIOS_BASE ); 4752b33a0f9SSteve Passe seekEntry( BIOS_BASE ); 4762b33a0f9SSteve Passe readEntry( buffer, BIOS_SIZE ); 4772b33a0f9SSteve Passe 4788c489d72SPeter Wemm for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 4792b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 4802b33a0f9SSteve Passe *where = 4; 4812b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + BIOS_BASE; 4822b33a0f9SSteve Passe return; 4832b33a0f9SSteve Passe } 4842b33a0f9SSteve Passe } 4852b33a0f9SSteve Passe 4862b33a0f9SSteve Passe /* search the extended BIOS */ 4872b33a0f9SSteve Passe if ( verbose ) 4882b33a0f9SSteve Passe printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 ); 4892b33a0f9SSteve Passe seekEntry( BIOS_BASE2 ); 4902b33a0f9SSteve Passe readEntry( buffer, BIOS_SIZE ); 4912b33a0f9SSteve Passe 4928c489d72SPeter Wemm for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 4932b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 4942b33a0f9SSteve Passe *where = 5; 4952b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2; 4962b33a0f9SSteve Passe return; 4972b33a0f9SSteve Passe } 4982b33a0f9SSteve Passe } 4992b33a0f9SSteve Passe 5002b33a0f9SSteve Passe if ( grope ) { 5012b33a0f9SSteve Passe /* search additional memory */ 5022b33a0f9SSteve Passe target = GROPE_AREA1; 5032b33a0f9SSteve Passe if ( verbose ) 5042b33a0f9SSteve Passe printf( " groping memory @ 0x%08x\n", target ); 5052b33a0f9SSteve Passe seekEntry( target ); 5062b33a0f9SSteve Passe readEntry( buffer, GROPE_SIZE ); 5072b33a0f9SSteve Passe 5088c489d72SPeter Wemm for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 5092b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 5102b33a0f9SSteve Passe *where = 6; 5112b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + GROPE_AREA1; 5122b33a0f9SSteve Passe return; 5132b33a0f9SSteve Passe } 5142b33a0f9SSteve Passe } 5152b33a0f9SSteve Passe 5162b33a0f9SSteve Passe target = GROPE_AREA2; 5172b33a0f9SSteve Passe if ( verbose ) 5182b33a0f9SSteve Passe printf( " groping memory @ 0x%08x\n", target ); 5192b33a0f9SSteve Passe seekEntry( target ); 5202b33a0f9SSteve Passe readEntry( buffer, GROPE_SIZE ); 5212b33a0f9SSteve Passe 5228c489d72SPeter Wemm for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 5232b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 5242b33a0f9SSteve Passe *where = 7; 5252b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + GROPE_AREA2; 5262b33a0f9SSteve Passe return; 5272b33a0f9SSteve Passe } 5282b33a0f9SSteve Passe } 5292b33a0f9SSteve Passe } 5302b33a0f9SSteve Passe 5312b33a0f9SSteve Passe *where = 0; 5328c489d72SPeter Wemm *paddr = (u_int32_t)0; 5332b33a0f9SSteve Passe } 5342b33a0f9SSteve Passe 5352b33a0f9SSteve Passe 5362b33a0f9SSteve Passe /* 5372b33a0f9SSteve Passe * 5382b33a0f9SSteve Passe */ 539ec175cedSPhilippe Charnier static void 5408c489d72SPeter Wemm MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps ) 5412b33a0f9SSteve Passe { 5422b33a0f9SSteve Passe 5432b33a0f9SSteve Passe /* read in mpfps structure*/ 5442b33a0f9SSteve Passe seekEntry( paddr ); 5452b33a0f9SSteve Passe readEntry( mpfps, sizeof( mpfps_t ) ); 5462b33a0f9SSteve Passe 5472b33a0f9SSteve Passe /* show its contents */ 5482b33a0f9SSteve Passe printf( "MP Floating Pointer Structure:\n\n" ); 5492b33a0f9SSteve Passe 550ec175cedSPhilippe Charnier printf( " location:\t\t\t" ); 5512b33a0f9SSteve Passe switch ( where ) 5522b33a0f9SSteve Passe { 5532b33a0f9SSteve Passe case 1: 5542b33a0f9SSteve Passe printf( "EBDA\n" ); 5552b33a0f9SSteve Passe break; 5562b33a0f9SSteve Passe case 2: 5572b33a0f9SSteve Passe printf( "BIOS base memory\n" ); 5582b33a0f9SSteve Passe break; 5592b33a0f9SSteve Passe case 3: 5602b33a0f9SSteve Passe printf( "DEFAULT base memory (639K)\n" ); 5612b33a0f9SSteve Passe break; 5622b33a0f9SSteve Passe case 4: 5632b33a0f9SSteve Passe printf( "BIOS\n" ); 5642b33a0f9SSteve Passe break; 5652b33a0f9SSteve Passe case 5: 5662b33a0f9SSteve Passe printf( "Extended BIOS\n" ); 5672b33a0f9SSteve Passe break; 5682b33a0f9SSteve Passe 5692b33a0f9SSteve Passe case 0: 5702b33a0f9SSteve Passe printf( "NOT found!\n" ); 5712b33a0f9SSteve Passe exit( 1 ); 5722b33a0f9SSteve Passe default: 5732b33a0f9SSteve Passe printf( "BOGUS!\n" ); 5742b33a0f9SSteve Passe exit( 1 ); 5752b33a0f9SSteve Passe } 5762b33a0f9SSteve Passe printf( " physical address:\t\t0x%08x\n", paddr ); 5772b33a0f9SSteve Passe 5782b33a0f9SSteve Passe printf( " signature:\t\t\t'" ); 5792b33a0f9SSteve Passe pnstr( mpfps->signature, 4 ); 5802b33a0f9SSteve Passe printf( "'\n" ); 5812b33a0f9SSteve Passe 5822b33a0f9SSteve Passe printf( " length:\t\t\t%d bytes\n", mpfps->length * 16 ); 5832b33a0f9SSteve Passe printf( " version:\t\t\t1.%1d\n", mpfps->spec_rev ); 5842b33a0f9SSteve Passe printf( " checksum:\t\t\t0x%02x\n", mpfps->checksum ); 5852b33a0f9SSteve Passe 5862b33a0f9SSteve Passe /* bits 0:6 are RESERVED */ 5872b33a0f9SSteve Passe if ( mpfps->mpfb2 & 0x7f ) { 588ec175cedSPhilippe Charnier printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 ); 5892b33a0f9SSteve Passe } 5902b33a0f9SSteve Passe 5912b33a0f9SSteve Passe /* bit 7 is IMCRP */ 5922b33a0f9SSteve Passe printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ? 5932b33a0f9SSteve Passe "PIC" : "Virtual Wire" ); 5942b33a0f9SSteve Passe 5952b33a0f9SSteve Passe /* MP feature bytes 3-5 are expected to be ZERO */ 5962b33a0f9SSteve Passe if ( mpfps->mpfb3 ) 5972b33a0f9SSteve Passe printf( " warning, MP feature byte 3 NONZERO!\n" ); 5982b33a0f9SSteve Passe if ( mpfps->mpfb4 ) 5992b33a0f9SSteve Passe printf( " warning, MP feature byte 4 NONZERO!\n" ); 6002b33a0f9SSteve Passe if ( mpfps->mpfb5 ) 6012b33a0f9SSteve Passe printf( " warning, MP feature byte 5 NONZERO!\n" ); 6022b33a0f9SSteve Passe } 6032b33a0f9SSteve Passe 6042b33a0f9SSteve Passe 6052b33a0f9SSteve Passe /* 6062b33a0f9SSteve Passe * 6072b33a0f9SSteve Passe */ 6082b33a0f9SSteve Passe static void 6092b33a0f9SSteve Passe MPConfigDefault( int featureByte ) 6102b33a0f9SSteve Passe { 6112b33a0f9SSteve Passe printf( " MP default config type: %d\n\n", featureByte ); 6122b33a0f9SSteve Passe switch ( featureByte ) { 6132b33a0f9SSteve Passe case 1: 6142b33a0f9SSteve Passe printf( " bus: ISA, APIC: 82489DX\n" ); 6152b33a0f9SSteve Passe break; 6162b33a0f9SSteve Passe case 2: 6172b33a0f9SSteve Passe printf( " bus: EISA, APIC: 82489DX\n" ); 6182b33a0f9SSteve Passe break; 6192b33a0f9SSteve Passe case 3: 6202b33a0f9SSteve Passe printf( " bus: EISA, APIC: 82489DX\n" ); 6212b33a0f9SSteve Passe break; 6222b33a0f9SSteve Passe case 4: 6232b33a0f9SSteve Passe printf( " bus: MCA, APIC: 82489DX\n" ); 6242b33a0f9SSteve Passe break; 6252b33a0f9SSteve Passe case 5: 6262b33a0f9SSteve Passe printf( " bus: ISA+PCI, APIC: Integrated\n" ); 6272b33a0f9SSteve Passe break; 6282b33a0f9SSteve Passe case 6: 6292b33a0f9SSteve Passe printf( " bus: EISA+PCI, APIC: Integrated\n" ); 6302b33a0f9SSteve Passe break; 6312b33a0f9SSteve Passe case 7: 6322b33a0f9SSteve Passe printf( " bus: MCA+PCI, APIC: Integrated\n" ); 6332b33a0f9SSteve Passe break; 6342b33a0f9SSteve Passe default: 6352b33a0f9SSteve Passe printf( " future type\n" ); 6362b33a0f9SSteve Passe break; 6372b33a0f9SSteve Passe } 6382b33a0f9SSteve Passe 6392b33a0f9SSteve Passe switch ( featureByte ) { 6402b33a0f9SSteve Passe case 1: 6412b33a0f9SSteve Passe case 2: 6422b33a0f9SSteve Passe case 3: 6432b33a0f9SSteve Passe case 4: 6442b33a0f9SSteve Passe nbus = 1; 6452b33a0f9SSteve Passe break; 6462b33a0f9SSteve Passe case 5: 6472b33a0f9SSteve Passe case 6: 6482b33a0f9SSteve Passe case 7: 6492b33a0f9SSteve Passe nbus = 2; 6502b33a0f9SSteve Passe break; 6512b33a0f9SSteve Passe default: 6522b33a0f9SSteve Passe printf( " future type\n" ); 6532b33a0f9SSteve Passe break; 6542b33a0f9SSteve Passe } 6552b33a0f9SSteve Passe 6562b33a0f9SSteve Passe ncpu = 2; 6572b33a0f9SSteve Passe napic = 1; 6582b33a0f9SSteve Passe nintr = 16; 6592b33a0f9SSteve Passe } 6602b33a0f9SSteve Passe 6612b33a0f9SSteve Passe 6622b33a0f9SSteve Passe /* 6632b33a0f9SSteve Passe * 6642b33a0f9SSteve Passe */ 6652b33a0f9SSteve Passe static void 6668c489d72SPeter Wemm MPConfigTableHeader( u_int32_t pap ) 6672b33a0f9SSteve Passe { 6688c489d72SPeter Wemm u_int32_t paddr; 6692b33a0f9SSteve Passe mpcth_t cth; 670ec175cedSPhilippe Charnier int x; 6714a3e427fSPeter Wemm int totalSize; 6722b33a0f9SSteve Passe int count, c; 6732b33a0f9SSteve Passe int type; 6744a3e427fSPeter Wemm int oldtype, entrytype; 6752b33a0f9SSteve Passe 6762b33a0f9SSteve Passe if ( pap == 0 ) { 6772b33a0f9SSteve Passe printf( "MP Configuration Table Header MISSING!\n" ); 6782b33a0f9SSteve Passe exit( 1 ); 6792b33a0f9SSteve Passe } 6802b33a0f9SSteve Passe 6812b33a0f9SSteve Passe /* convert physical address to virtual address */ 6828c489d72SPeter Wemm paddr = pap; 6832b33a0f9SSteve Passe 6842b33a0f9SSteve Passe /* read in cth structure */ 6852b33a0f9SSteve Passe seekEntry( paddr ); 6862b33a0f9SSteve Passe readEntry( &cth, sizeof( cth ) ); 6872b33a0f9SSteve Passe 6882b33a0f9SSteve Passe printf( "MP Config Table Header:\n\n" ); 6892b33a0f9SSteve Passe 6902b33a0f9SSteve Passe printf( " physical address:\t\t0x%08x\n", pap ); 6912b33a0f9SSteve Passe 6922b33a0f9SSteve Passe printf( " signature:\t\t\t'" ); 6932b33a0f9SSteve Passe pnstr( cth.signature, 4 ); 6942b33a0f9SSteve Passe printf( "'\n" ); 6952b33a0f9SSteve Passe 6962b33a0f9SSteve Passe printf( " base table length:\t\t%d\n", cth.base_table_length ); 6972b33a0f9SSteve Passe 6982b33a0f9SSteve Passe printf( " version:\t\t\t1.%1d\n", cth.spec_rev ); 6992b33a0f9SSteve Passe printf( " checksum:\t\t\t0x%02x\n", cth.checksum ); 7002b33a0f9SSteve Passe 7012b33a0f9SSteve Passe printf( " OEM ID:\t\t\t'" ); 7022b33a0f9SSteve Passe pnstr( cth.oem_id, 8 ); 7032b33a0f9SSteve Passe printf( "'\n" ); 7042b33a0f9SSteve Passe 7052b33a0f9SSteve Passe printf( " Product ID:\t\t\t'" ); 7062b33a0f9SSteve Passe pnstr( cth.product_id, 12 ); 7072b33a0f9SSteve Passe printf( "'\n" ); 7082b33a0f9SSteve Passe 7092b33a0f9SSteve Passe printf( " OEM table pointer:\t\t0x%08x\n", cth.oem_table_pointer ); 7102b33a0f9SSteve Passe printf( " OEM table size:\t\t%d\n", cth.oem_table_size ); 7112b33a0f9SSteve Passe 7122b33a0f9SSteve Passe printf( " entry count:\t\t\t%d\n", cth.entry_count ); 7132b33a0f9SSteve Passe 7142b33a0f9SSteve Passe printf( " local APIC address:\t\t0x%08x\n", cth.apic_address ); 7152b33a0f9SSteve Passe 7162b33a0f9SSteve Passe printf( " extended table length:\t%d\n", cth.extended_table_length ); 7172b33a0f9SSteve Passe printf( " extended table checksum:\t%d\n", cth.extended_table_checksum ); 7182b33a0f9SSteve Passe 7192b33a0f9SSteve Passe totalSize = cth.base_table_length - sizeof( struct MPCTH ); 7202b33a0f9SSteve Passe count = cth.entry_count; 7212b33a0f9SSteve Passe 7222b33a0f9SSteve Passe puts( SEP_LINE ); 7232b33a0f9SSteve Passe 7242b33a0f9SSteve Passe printf( "MP Config Base Table Entries:\n\n" ); 7252b33a0f9SSteve Passe 7262b33a0f9SSteve Passe /* initialze tables */ 7272b33a0f9SSteve Passe for ( x = 0; x < 16; ++x ) { 7282b33a0f9SSteve Passe busses[ x ] = apics[ x ] = 0xff; 7292b33a0f9SSteve Passe } 7302b33a0f9SSteve Passe 7312b33a0f9SSteve Passe ncpu = 0; 7322b33a0f9SSteve Passe nbus = 0; 7332b33a0f9SSteve Passe napic = 0; 7342b33a0f9SSteve Passe nintr = 0; 7352b33a0f9SSteve Passe 7364a3e427fSPeter Wemm oldtype = -1; 7374a3e427fSPeter Wemm for (c = count; c; c--) { 7384a3e427fSPeter Wemm entrytype = readType(); 7394a3e427fSPeter Wemm if (entrytype != oldtype) 7404a3e427fSPeter Wemm printf("--\n"); 7414a3e427fSPeter Wemm if (entrytype < oldtype) 7424a3e427fSPeter Wemm printf("MPTABLE OUT OF ORDER!\n"); 7434a3e427fSPeter Wemm switch (entrytype) { 7444a3e427fSPeter Wemm case 0: 7454a3e427fSPeter Wemm if (oldtype != 0) 7464a3e427fSPeter Wemm printf( "Processors:\tAPIC ID\tVersion\tState" 7472b33a0f9SSteve Passe "\t\tFamily\tModel\tStep\tFlags\n" ); 7484a3e427fSPeter Wemm oldtype = 0; 7492b33a0f9SSteve Passe processorEntry(); 7504a3e427fSPeter Wemm break; 7512b33a0f9SSteve Passe 7524a3e427fSPeter Wemm case 1: 7534a3e427fSPeter Wemm if (oldtype != 1) 7544a3e427fSPeter Wemm printf( "Bus:\t\tBus ID\tType\n" ); 7554a3e427fSPeter Wemm oldtype = 1; 7562b33a0f9SSteve Passe busEntry(); 7574a3e427fSPeter Wemm break; 7582b33a0f9SSteve Passe 7594a3e427fSPeter Wemm case 2: 7604a3e427fSPeter Wemm if (oldtype != 2) 7614a3e427fSPeter Wemm printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" ); 7624a3e427fSPeter Wemm oldtype = 2; 7632b33a0f9SSteve Passe ioApicEntry(); 7644a3e427fSPeter Wemm break; 7652b33a0f9SSteve Passe 7664a3e427fSPeter Wemm case 3: 7674a3e427fSPeter Wemm if (oldtype != 3) 7684a3e427fSPeter Wemm printf( "I/O Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 7694a3e427fSPeter Wemm oldtype = 3; 7702b33a0f9SSteve Passe intEntry(); 7714a3e427fSPeter Wemm break; 7722b33a0f9SSteve Passe 7734a3e427fSPeter Wemm case 4: 7744a3e427fSPeter Wemm if (oldtype != 4) 7754a3e427fSPeter Wemm printf( "Local Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 7764a3e427fSPeter Wemm oldtype = 4; 7772b33a0f9SSteve Passe intEntry(); 7784a3e427fSPeter Wemm break; 7794a3e427fSPeter Wemm 7804a3e427fSPeter Wemm default: 7814a3e427fSPeter Wemm printf("MPTABLE HOSED! record type = %d\n", entrytype); 7824a3e427fSPeter Wemm exit(1); 7834a3e427fSPeter Wemm } 7842b33a0f9SSteve Passe } 7852b33a0f9SSteve Passe 7862b33a0f9SSteve Passe 7872b33a0f9SSteve Passe #if defined( EXTENDED_PROCESSING_READY ) 7882b33a0f9SSteve Passe /* process any extended data */ 789ec175cedSPhilippe Charnier if ( (totalSize = cth.extended_table_length) ) { 7902b33a0f9SSteve Passe puts( SEP_LINE ); 7912b33a0f9SSteve Passe 7922b33a0f9SSteve Passe printf( "MP Config Extended Table Entries:\n\n" ); 7932b33a0f9SSteve Passe 7942b33a0f9SSteve Passe while ( totalSize > 0 ) { 7952b33a0f9SSteve Passe switch ( type = readType() ) { 7962b33a0f9SSteve Passe case 128: 7972b33a0f9SSteve Passe sasEntry(); 7982b33a0f9SSteve Passe break; 7992b33a0f9SSteve Passe case 129: 8002b33a0f9SSteve Passe bhdEntry(); 8012b33a0f9SSteve Passe break; 8022b33a0f9SSteve Passe case 130: 8032b33a0f9SSteve Passe cbasmEntry(); 8042b33a0f9SSteve Passe break; 8052b33a0f9SSteve Passe default: 8062b33a0f9SSteve Passe printf( "Extended Table HOSED!\n" ); 8072b33a0f9SSteve Passe exit( 1 ); 8082b33a0f9SSteve Passe } 8092b33a0f9SSteve Passe 8102b33a0f9SSteve Passe totalSize -= extendedtableEntryTypes[ type-128 ].length; 8112b33a0f9SSteve Passe } 8122b33a0f9SSteve Passe } 8132b33a0f9SSteve Passe #endif /* EXTENDED_PROCESSING_READY */ 8142b33a0f9SSteve Passe 8152b33a0f9SSteve Passe /* process any OEM data */ 8162b33a0f9SSteve Passe if ( cth.oem_table_pointer && (cth.oem_table_size > 0) ) { 8172b33a0f9SSteve Passe #if defined( OEM_PROCESSING_READY ) 8182b33a0f9SSteve Passe # error your on your own here! 8192b33a0f9SSteve Passe /* convert OEM table pointer to virtual address */ 8208c489d72SPeter Wemm poemtp = (u_int32_t)cth.oem_table_pointer; 8212b33a0f9SSteve Passe 8222b33a0f9SSteve Passe /* read in oem table structure */ 823ec175cedSPhilippe Charnier if ( (oemdata = (void*)malloc( cth.oem_table_size )) == NULL ) 824ec175cedSPhilippe Charnier err( 1, "oem malloc" ); 8252b33a0f9SSteve Passe 8262b33a0f9SSteve Passe seekEntry( poemtp ); 8272b33a0f9SSteve Passe readEntry( oemdata, cth.oem_table_size ); 8282b33a0f9SSteve Passe 8292b33a0f9SSteve Passe /** process it */ 8302b33a0f9SSteve Passe 8312b33a0f9SSteve Passe free( oemdata ); 8322b33a0f9SSteve Passe #else 8332b33a0f9SSteve Passe printf( "\nyou need to modify the source to handle OEM data!\n\n" ); 8342b33a0f9SSteve Passe #endif /* OEM_PROCESSING_READY */ 8352b33a0f9SSteve Passe } 8362b33a0f9SSteve Passe 8372b33a0f9SSteve Passe fflush( stdout ); 8382b33a0f9SSteve Passe 8392b33a0f9SSteve Passe #if defined( RAW_DUMP ) 8402b33a0f9SSteve Passe { 8412b33a0f9SSteve Passe int ofd; 8422b33a0f9SSteve Passe u_char dumpbuf[ 4096 ]; 8432b33a0f9SSteve Passe 8442b33a0f9SSteve Passe ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR ); 8452b33a0f9SSteve Passe seekEntry( paddr ); 8462b33a0f9SSteve Passe readEntry( dumpbuf, 1024 ); 8472b33a0f9SSteve Passe write( ofd, dumpbuf, 1024 ); 8482b33a0f9SSteve Passe close( ofd ); 8492b33a0f9SSteve Passe } 8502b33a0f9SSteve Passe #endif /* RAW_DUMP */ 8512b33a0f9SSteve Passe } 8522b33a0f9SSteve Passe 8532b33a0f9SSteve Passe 8542b33a0f9SSteve Passe /* 8552b33a0f9SSteve Passe * 8562b33a0f9SSteve Passe */ 8572b33a0f9SSteve Passe static int 8582b33a0f9SSteve Passe readType( void ) 8592b33a0f9SSteve Passe { 8602b33a0f9SSteve Passe u_char type; 8612b33a0f9SSteve Passe 862ec175cedSPhilippe Charnier if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) ) 863ec175cedSPhilippe Charnier err( 1, "type read; pfd: %d", pfd ); 8642b33a0f9SSteve Passe 865ec175cedSPhilippe Charnier if ( lseek( pfd, -1, SEEK_CUR ) < 0 ) 866ec175cedSPhilippe Charnier err( 1, "type seek" ); 8672b33a0f9SSteve Passe 8682b33a0f9SSteve Passe return (int)type; 8692b33a0f9SSteve Passe } 8702b33a0f9SSteve Passe 8712b33a0f9SSteve Passe 8722b33a0f9SSteve Passe /* 8732b33a0f9SSteve Passe * 8742b33a0f9SSteve Passe */ 8752b33a0f9SSteve Passe static void 8768c489d72SPeter Wemm seekEntry( u_int32_t addr ) 8772b33a0f9SSteve Passe { 878ec175cedSPhilippe Charnier if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 ) 8791a37aa56SDavid E. O'Brien err( 1, "%s seek", _PATH_MEM ); 8802b33a0f9SSteve Passe } 8812b33a0f9SSteve Passe 8822b33a0f9SSteve Passe 8832b33a0f9SSteve Passe /* 8842b33a0f9SSteve Passe * 8852b33a0f9SSteve Passe */ 8862b33a0f9SSteve Passe static void 8872b33a0f9SSteve Passe readEntry( void* entry, int size ) 8882b33a0f9SSteve Passe { 889ec175cedSPhilippe Charnier if ( read( pfd, entry, size ) != size ) 890ec175cedSPhilippe Charnier err( 1, "readEntry" ); 8912b33a0f9SSteve Passe } 8922b33a0f9SSteve Passe 8932b33a0f9SSteve Passe 8942b33a0f9SSteve Passe static void 8952b33a0f9SSteve Passe processorEntry( void ) 8962b33a0f9SSteve Passe { 8972b33a0f9SSteve Passe ProcEntry entry; 8982b33a0f9SSteve Passe 8992b33a0f9SSteve Passe /* read it into local memory */ 9002b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 9012b33a0f9SSteve Passe 9022b33a0f9SSteve Passe /* count it */ 9032b33a0f9SSteve Passe ++ncpu; 9042b33a0f9SSteve Passe 9052b33a0f9SSteve Passe printf( "\t\t%2d", entry.apicID ); 9062b33a0f9SSteve Passe printf( "\t 0x%2x", entry.apicVersion ); 9072b33a0f9SSteve Passe 9082b33a0f9SSteve Passe printf( "\t %s, %s", 9092b33a0f9SSteve Passe (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP", 9102b33a0f9SSteve Passe (entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" ); 9112b33a0f9SSteve Passe 9122b33a0f9SSteve Passe printf( "\t %d\t %d\t %d", 9132b33a0f9SSteve Passe (entry.cpuSignature >> 8) & 0x0f, 9142b33a0f9SSteve Passe (entry.cpuSignature >> 4) & 0x0f, 9152b33a0f9SSteve Passe entry.cpuSignature & 0x0f ); 9162b33a0f9SSteve Passe 9172b33a0f9SSteve Passe printf( "\t 0x%04x\n", entry.featureFlags ); 9182b33a0f9SSteve Passe } 9192b33a0f9SSteve Passe 9202b33a0f9SSteve Passe 9212b33a0f9SSteve Passe /* 9222b33a0f9SSteve Passe * 9232b33a0f9SSteve Passe */ 9242b33a0f9SSteve Passe static int 9252b33a0f9SSteve Passe lookupBusType( char* name ) 9262b33a0f9SSteve Passe { 9272b33a0f9SSteve Passe int x; 9282b33a0f9SSteve Passe 9292b33a0f9SSteve Passe for ( x = 0; x < MAX_BUSTYPE; ++x ) 9302b33a0f9SSteve Passe if ( strcmp( busTypeTable[ x ].name, name ) == 0 ) 9312b33a0f9SSteve Passe return busTypeTable[ x ].type; 9322b33a0f9SSteve Passe 9332b33a0f9SSteve Passe return UNKNOWN_BUSTYPE; 9342b33a0f9SSteve Passe } 9352b33a0f9SSteve Passe 9362b33a0f9SSteve Passe 9372b33a0f9SSteve Passe static void 9382b33a0f9SSteve Passe busEntry( void ) 9392b33a0f9SSteve Passe { 9402b33a0f9SSteve Passe int x; 9412b33a0f9SSteve Passe char name[ 8 ]; 9422b33a0f9SSteve Passe char c; 9432b33a0f9SSteve Passe BusEntry entry; 9442b33a0f9SSteve Passe 9452b33a0f9SSteve Passe /* read it into local memory */ 9462b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 9472b33a0f9SSteve Passe 9482b33a0f9SSteve Passe /* count it */ 9492b33a0f9SSteve Passe ++nbus; 9502b33a0f9SSteve Passe 9512b33a0f9SSteve Passe printf( "\t\t%2d", entry.busID ); 9522b33a0f9SSteve Passe printf( "\t " ); pnstr( entry.busType, 6 ); printf( "\n" ); 9532b33a0f9SSteve Passe 9542b33a0f9SSteve Passe for ( x = 0; x < 6; ++x ) { 9552b33a0f9SSteve Passe if ( (c = entry.busType[ x ]) == ' ' ) 9562b33a0f9SSteve Passe break; 9572b33a0f9SSteve Passe name[ x ] = c; 9582b33a0f9SSteve Passe } 9592b33a0f9SSteve Passe name[ x ] = '\0'; 9602b33a0f9SSteve Passe busses[ entry.busID ] = lookupBusType( name ); 9612b33a0f9SSteve Passe } 9622b33a0f9SSteve Passe 9632b33a0f9SSteve Passe 9642b33a0f9SSteve Passe static void 9652b33a0f9SSteve Passe ioApicEntry( void ) 9662b33a0f9SSteve Passe { 9672b33a0f9SSteve Passe IOApicEntry entry; 9682b33a0f9SSteve Passe 9692b33a0f9SSteve Passe /* read it into local memory */ 9702b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 9712b33a0f9SSteve Passe 9722b33a0f9SSteve Passe /* count it */ 9732b33a0f9SSteve Passe ++napic; 9742b33a0f9SSteve Passe 9752b33a0f9SSteve Passe printf( "\t\t%2d", entry.apicID ); 9762b33a0f9SSteve Passe printf( "\t 0x%02x", entry.apicVersion ); 9772b33a0f9SSteve Passe printf( "\t %s", 9782b33a0f9SSteve Passe (entry.apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" ); 9792b33a0f9SSteve Passe printf( "\t\t 0x%x\n", entry.apicAddress ); 9802b33a0f9SSteve Passe 9812b33a0f9SSteve Passe apics[ entry.apicID ] = entry.apicID; 9822b33a0f9SSteve Passe } 9832b33a0f9SSteve Passe 9842b33a0f9SSteve Passe 9858c489d72SPeter Wemm const char* intTypes[] = { 9862b33a0f9SSteve Passe "INT", "NMI", "SMI", "ExtINT" 9872b33a0f9SSteve Passe }; 9882b33a0f9SSteve Passe 9898c489d72SPeter Wemm const char* polarityMode[] = { 9902b33a0f9SSteve Passe "conforms", "active-hi", "reserved", "active-lo" 9912b33a0f9SSteve Passe }; 9928c489d72SPeter Wemm const char* triggerMode[] = { 9932b33a0f9SSteve Passe "conforms", "edge", "reserved", "level" 9942b33a0f9SSteve Passe }; 9952b33a0f9SSteve Passe 9962b33a0f9SSteve Passe static void 9972b33a0f9SSteve Passe intEntry( void ) 9982b33a0f9SSteve Passe { 9992b33a0f9SSteve Passe IntEntry entry; 10002b33a0f9SSteve Passe 10012b33a0f9SSteve Passe /* read it into local memory */ 10022b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 10032b33a0f9SSteve Passe 10042b33a0f9SSteve Passe /* count it */ 10052b33a0f9SSteve Passe if ( (int)entry.type == 3 ) 10062b33a0f9SSteve Passe ++nintr; 10072b33a0f9SSteve Passe 10082b33a0f9SSteve Passe printf( "\t\t%s", intTypes[ (int)entry.intType ] ); 10092b33a0f9SSteve Passe 10102b33a0f9SSteve Passe printf( "\t%9s", polarityMode[ (int)entry.intFlags & 0x03 ] ); 10112b33a0f9SSteve Passe printf( "%12s", triggerMode[ ((int)entry.intFlags >> 2) & 0x03 ] ); 10122b33a0f9SSteve Passe 10132b33a0f9SSteve Passe printf( "\t %5d", (int)entry.srcBusID ); 10142b33a0f9SSteve Passe if ( busses[ (int)entry.srcBusID ] == PCI ) 10152b33a0f9SSteve Passe printf( "\t%2d:%c", 10162b33a0f9SSteve Passe ((int)entry.srcBusIRQ >> 2) & 0x1f, 10172b33a0f9SSteve Passe ((int)entry.srcBusIRQ & 0x03) + 'A' ); 10182b33a0f9SSteve Passe else 10192b33a0f9SSteve Passe printf( "\t %3d", (int)entry.srcBusIRQ ); 10202b33a0f9SSteve Passe printf( "\t %6d", (int)entry.dstApicID ); 10212b33a0f9SSteve Passe printf( "\t %3d\n", (int)entry.dstApicINT ); 10222b33a0f9SSteve Passe } 10232b33a0f9SSteve Passe 10242b33a0f9SSteve Passe 10252b33a0f9SSteve Passe static void 10262b33a0f9SSteve Passe sasEntry( void ) 10272b33a0f9SSteve Passe { 10282b33a0f9SSteve Passe SasEntry entry; 10292b33a0f9SSteve Passe 10302b33a0f9SSteve Passe /* read it into local memory */ 10312b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 10322b33a0f9SSteve Passe 1033386fd026STor Egge printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); 10342b33a0f9SSteve Passe printf( " bus ID: %d", entry.busID ); 10352b33a0f9SSteve Passe printf( " address type: " ); 10362b33a0f9SSteve Passe switch ( entry.addressType ) { 10372b33a0f9SSteve Passe case 0: 10382b33a0f9SSteve Passe printf( "I/O address\n" ); 10392b33a0f9SSteve Passe break; 10402b33a0f9SSteve Passe case 1: 10412b33a0f9SSteve Passe printf( "memory address\n" ); 10422b33a0f9SSteve Passe break; 10432b33a0f9SSteve Passe case 2: 10442b33a0f9SSteve Passe printf( "prefetch address\n" ); 10452b33a0f9SSteve Passe break; 10462b33a0f9SSteve Passe default: 10472b33a0f9SSteve Passe printf( "UNKNOWN type\n" ); 10482b33a0f9SSteve Passe break; 10492b33a0f9SSteve Passe } 10502b33a0f9SSteve Passe 10518c489d72SPeter Wemm printf( " address base: 0x%llx\n", (long long)entry.addressBase ); 10528c489d72SPeter Wemm printf( " address range: 0x%llx\n", (long long)entry.addressLength ); 10532b33a0f9SSteve Passe } 10542b33a0f9SSteve Passe 10552b33a0f9SSteve Passe 10562b33a0f9SSteve Passe static void 10572b33a0f9SSteve Passe bhdEntry( void ) 10582b33a0f9SSteve Passe { 10592b33a0f9SSteve Passe BhdEntry entry; 10602b33a0f9SSteve Passe 10612b33a0f9SSteve Passe /* read it into local memory */ 10622b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 10632b33a0f9SSteve Passe 1064386fd026STor Egge printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); 10652b33a0f9SSteve Passe printf( " bus ID: %d", entry.busID ); 10662b33a0f9SSteve Passe printf( " bus info: 0x%02x", entry.busInfo ); 1067386fd026STor Egge printf( " parent bus ID: %d\n", entry.busParent ); 10682b33a0f9SSteve Passe } 10692b33a0f9SSteve Passe 10702b33a0f9SSteve Passe 10712b33a0f9SSteve Passe static void 10722b33a0f9SSteve Passe cbasmEntry( void ) 10732b33a0f9SSteve Passe { 10742b33a0f9SSteve Passe CbasmEntry entry; 10752b33a0f9SSteve Passe 10762b33a0f9SSteve Passe /* read it into local memory */ 10772b33a0f9SSteve Passe readEntry( &entry, sizeof( entry ) ); 10782b33a0f9SSteve Passe 1079386fd026STor Egge printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); 10802b33a0f9SSteve Passe printf( " bus ID: %d", entry.busID ); 10812b33a0f9SSteve Passe printf( " address modifier: %s\n", (entry.addressMod & 0x01) ? 10822b33a0f9SSteve Passe "subtract" : "add" ); 1083386fd026STor Egge printf( " predefined range: 0x%08x\n", entry.predefinedRange ); 10842b33a0f9SSteve Passe } 10852b33a0f9SSteve Passe 10862b33a0f9SSteve Passe 10872b33a0f9SSteve Passe /* 10882b33a0f9SSteve Passe * do a dmesg output 10892b33a0f9SSteve Passe */ 10902b33a0f9SSteve Passe static void 10912b33a0f9SSteve Passe doDmesg( void ) 10922b33a0f9SSteve Passe { 10932b33a0f9SSteve Passe puts( SEP_LINE ); 10942b33a0f9SSteve Passe 10952b33a0f9SSteve Passe printf( "dmesg output:\n\n" ); 10962b33a0f9SSteve Passe fflush( stdout ); 10972b33a0f9SSteve Passe system( "dmesg" ); 10982b33a0f9SSteve Passe } 10992b33a0f9SSteve Passe 11002b33a0f9SSteve Passe 11012b33a0f9SSteve Passe /* 11022b33a0f9SSteve Passe * 11032b33a0f9SSteve Passe */ 11042b33a0f9SSteve Passe static void 11052b33a0f9SSteve Passe pnstr( char* s, int c ) 11062b33a0f9SSteve Passe { 11072b33a0f9SSteve Passe char string[ MAXPNSTR + 1 ]; 11082b33a0f9SSteve Passe 11092b33a0f9SSteve Passe if ( c > MAXPNSTR ) 11102b33a0f9SSteve Passe c = MAXPNSTR; 11112b33a0f9SSteve Passe strncpy( string, s, c ); 11122b33a0f9SSteve Passe string[ c ] = '\0'; 11132b33a0f9SSteve Passe printf( "%s", string ); 11142b33a0f9SSteve Passe } 1115