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 /* 362b33a0f9SSteve Passe * this will cause the raw mp table to be dumped to /tmp/mpdump 372b33a0f9SSteve Passe * 382b33a0f9SSteve Passe #define RAW_DUMP 392b33a0f9SSteve Passe */ 402b33a0f9SSteve Passe 412b33a0f9SSteve Passe #define MP_SIG 0x5f504d5f /* _MP_ */ 422b33a0f9SSteve Passe #define EXTENDED_PROCESSING_READY 432b33a0f9SSteve Passe #define OEM_PROCESSING_READY_NOT 442b33a0f9SSteve Passe 45d72323d1SNeel Natu #include <sys/param.h> 46*a61a3b33SJohn Baldwin #include <sys/mman.h> 47*a61a3b33SJohn Baldwin #include <x86/mptable.h> 48ec175cedSPhilippe Charnier #include <err.h> 492b33a0f9SSteve Passe #include <fcntl.h> 501a37aa56SDavid E. O'Brien #include <paths.h> 51*a61a3b33SJohn Baldwin #include <stdint.h> 52ec175cedSPhilippe Charnier #include <stdio.h> 53ec175cedSPhilippe Charnier #include <stdlib.h> 54ec175cedSPhilippe Charnier #include <string.h> 552b33a0f9SSteve Passe #include <unistd.h> 562b33a0f9SSteve Passe 572b33a0f9SSteve Passe #define SEP_LINE \ 582b33a0f9SSteve Passe "\n-------------------------------------------------------------------------------\n" 592b33a0f9SSteve Passe 602b33a0f9SSteve Passe #define SEP_LINE2 \ 612b33a0f9SSteve Passe "\n===============================================================================\n" 622b33a0f9SSteve Passe 632b33a0f9SSteve Passe /* EBDA is @ 40:0e in real-mode terms */ 642b33a0f9SSteve Passe #define EBDA_POINTER 0x040e /* location of EBDA pointer */ 652b33a0f9SSteve Passe 662b33a0f9SSteve Passe /* CMOS 'top of mem' is @ 40:13 in real-mode terms */ 672b33a0f9SSteve Passe #define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */ 682b33a0f9SSteve Passe 692b33a0f9SSteve Passe #define DEFAULT_TOPOFMEM 0xa0000 702b33a0f9SSteve Passe 712b33a0f9SSteve Passe #define BIOS_BASE 0xf0000 722b33a0f9SSteve Passe #define BIOS_BASE2 0xe0000 732b33a0f9SSteve Passe #define BIOS_SIZE 0x10000 742b33a0f9SSteve Passe #define ONE_KBYTE 1024 752b33a0f9SSteve Passe 762b33a0f9SSteve Passe #define GROPE_AREA1 0x80000 772b33a0f9SSteve Passe #define GROPE_AREA2 0x90000 782b33a0f9SSteve Passe #define GROPE_SIZE 0x10000 792b33a0f9SSteve Passe 802b33a0f9SSteve Passe #define MAXPNSTR 132 812b33a0f9SSteve Passe 822b33a0f9SSteve Passe typedef struct BUSTYPENAME { 832b33a0f9SSteve Passe u_char type; 842b33a0f9SSteve Passe char name[ 7 ]; 852b33a0f9SSteve Passe } busTypeName; 862b33a0f9SSteve Passe 8760bd06daSEd Schouten static const busTypeName busTypeTable[] = 882b33a0f9SSteve Passe { 892b33a0f9SSteve Passe { CBUS, "CBUS" }, 902b33a0f9SSteve Passe { CBUSII, "CBUSII" }, 912b33a0f9SSteve Passe { EISA, "EISA" }, 922b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 932b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 942b33a0f9SSteve Passe { ISA, "ISA" }, 952b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 962b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 972b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 982b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 992b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1002b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1012b33a0f9SSteve Passe { PCI, "PCI" }, 1022b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1032b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1042b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1052b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1062b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" }, 1072b33a0f9SSteve Passe { UNKNOWN_BUSTYPE, "---" } 1082b33a0f9SSteve Passe }; 1092b33a0f9SSteve Passe 11060bd06daSEd Schouten static const char *whereStrings[] = { 1112b33a0f9SSteve Passe "Extended BIOS Data Area", 1122b33a0f9SSteve Passe "BIOS top of memory", 1132b33a0f9SSteve Passe "Default top of memory", 1142b33a0f9SSteve Passe "BIOS", 1152b33a0f9SSteve Passe "Extended BIOS", 1162b33a0f9SSteve Passe "GROPE AREA #1", 1172b33a0f9SSteve Passe "GROPE AREA #2" 1182b33a0f9SSteve Passe }; 1192b33a0f9SSteve Passe 1208c489d72SPeter Wemm static void apic_probe( u_int32_t* paddr, int* where ); 1212b33a0f9SSteve Passe 1222b33a0f9SSteve Passe static void MPConfigDefault( int featureByte ); 1232b33a0f9SSteve Passe 124*a61a3b33SJohn Baldwin static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp ); 1258c489d72SPeter Wemm static void MPConfigTableHeader( u_int32_t pap ); 1262b33a0f9SSteve Passe 1278c489d72SPeter Wemm static void seekEntry( u_int32_t addr ); 1282b33a0f9SSteve Passe static void readEntry( void* entry, int size ); 129*a61a3b33SJohn Baldwin static void *mapEntry( u_int32_t addr, int size ); 1302b33a0f9SSteve Passe 131*a61a3b33SJohn Baldwin static void processorEntry( proc_entry_ptr entry ); 132*a61a3b33SJohn Baldwin static void busEntry( bus_entry_ptr entry ); 133*a61a3b33SJohn Baldwin static void ioApicEntry( io_apic_entry_ptr entry ); 134*a61a3b33SJohn Baldwin static void intEntry( int_entry_ptr entry ); 1352b33a0f9SSteve Passe 136*a61a3b33SJohn Baldwin static void sasEntry( sas_entry_ptr entry ); 137*a61a3b33SJohn Baldwin static void bhdEntry( bhd_entry_ptr entry ); 138*a61a3b33SJohn Baldwin static void cbasmEntry( cbasm_entry_ptr entry ); 1392b33a0f9SSteve Passe 1402b33a0f9SSteve Passe static void doDmesg( void ); 1412b33a0f9SSteve Passe static void pnstr( char* s, int c ); 1422b33a0f9SSteve Passe 1432b33a0f9SSteve Passe /* global data */ 14460bd06daSEd Schouten static int pfd; /* physical /dev/mem fd */ 1452b33a0f9SSteve Passe 1465b87feb6SNeel Natu static int busses[256]; 1475b87feb6SNeel Natu static int apics[256]; 1482b33a0f9SSteve Passe 14960bd06daSEd Schouten static int ncpu; 15060bd06daSEd Schouten static int nbus; 15160bd06daSEd Schouten static int napic; 15260bd06daSEd Schouten static int nintr; 1532b33a0f9SSteve Passe 15460bd06daSEd Schouten static int dmesg; 15560bd06daSEd Schouten static int grope; 15660bd06daSEd Schouten static int verbose; 1572b33a0f9SSteve Passe 1582b33a0f9SSteve Passe static void 1592b33a0f9SSteve Passe usage( void ) 1602b33a0f9SSteve Passe { 161ec175cedSPhilippe Charnier fprintf( stderr, "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n" ); 1622b33a0f9SSteve Passe exit( 0 ); 1632b33a0f9SSteve Passe } 1642b33a0f9SSteve Passe 1652b33a0f9SSteve Passe /* 1662b33a0f9SSteve Passe * 1672b33a0f9SSteve Passe */ 1682b33a0f9SSteve Passe int 1692b33a0f9SSteve Passe main( int argc, char *argv[] ) 1702b33a0f9SSteve Passe { 1718c489d72SPeter Wemm u_int32_t paddr; 1722b33a0f9SSteve Passe int where; 1732b33a0f9SSteve Passe mpfps_t mpfps; 1742b33a0f9SSteve Passe int defaultConfig; 1752b33a0f9SSteve Passe 1762b33a0f9SSteve Passe int ch; 1772b33a0f9SSteve Passe 1782b33a0f9SSteve Passe /* announce ourselves */ 1792b33a0f9SSteve Passe puts( SEP_LINE2 ); 1802b33a0f9SSteve Passe 1810446a99eSDavid E. O'Brien printf( "MPTable\n" ); 1822b33a0f9SSteve Passe 183b790f1b6SWarner Losh while ((ch = getopt(argc, argv, "d:g:h:v:")) != -1) { 1842b33a0f9SSteve Passe switch(ch) { 1852b33a0f9SSteve Passe case 'd': 1862b33a0f9SSteve Passe if ( strcmp( optarg, "mesg") == 0 ) 1872b33a0f9SSteve Passe dmesg = 1; 1882b33a0f9SSteve Passe else 1892b33a0f9SSteve Passe dmesg = 0; 1902b33a0f9SSteve Passe break; 1912b33a0f9SSteve Passe case 'h': 1922b33a0f9SSteve Passe if ( strcmp( optarg, "elp") == 0 ) 1932b33a0f9SSteve Passe usage(); 1942b33a0f9SSteve Passe break; 1952b33a0f9SSteve Passe case 'g': 1969d35fde7SSteve Passe if ( strcmp( optarg, "rope") == 0 ) 1972b33a0f9SSteve Passe grope = 1; 1982b33a0f9SSteve Passe break; 1992b33a0f9SSteve Passe case 'v': 2002b33a0f9SSteve Passe if ( strcmp( optarg, "erbose") == 0 ) 2012b33a0f9SSteve Passe verbose = 1; 2022b33a0f9SSteve Passe break; 2032b33a0f9SSteve Passe default: 2042b33a0f9SSteve Passe usage(); 2052b33a0f9SSteve Passe } 2062b33a0f9SSteve Passe argc -= optind; 2072b33a0f9SSteve Passe argv += optind; 2082b33a0f9SSteve Passe optreset = 1; 2092b33a0f9SSteve Passe optind = 0; 2102b33a0f9SSteve Passe } 2112b33a0f9SSteve Passe 2122b33a0f9SSteve Passe /* open physical memory for access to MP structures */ 2131a37aa56SDavid E. O'Brien if ( (pfd = open( _PATH_MEM, O_RDONLY )) < 0 ) 214ec175cedSPhilippe Charnier err( 1, "mem open" ); 2152b33a0f9SSteve Passe 2162b33a0f9SSteve Passe /* probe for MP structures */ 2172b33a0f9SSteve Passe apic_probe( &paddr, &where ); 2182b33a0f9SSteve Passe if ( where <= 0 ) { 2192b33a0f9SSteve Passe fprintf( stderr, "\n MP FPS NOT found,\n" ); 2202b33a0f9SSteve Passe fprintf( stderr, " suggest trying -grope option!!!\n\n" ); 2212b33a0f9SSteve Passe return 1; 2222b33a0f9SSteve Passe } 2232b33a0f9SSteve Passe 2242b33a0f9SSteve Passe if ( verbose ) 2252b33a0f9SSteve Passe printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n", 2262b33a0f9SSteve Passe whereStrings[ where - 1 ], paddr ); 2272b33a0f9SSteve Passe 2282b33a0f9SSteve Passe puts( SEP_LINE ); 2292b33a0f9SSteve Passe 2302b33a0f9SSteve Passe /* analyze the MP Floating Pointer Structure */ 2312b33a0f9SSteve Passe MPFloatingPointer( paddr, where, &mpfps ); 2322b33a0f9SSteve Passe 2332b33a0f9SSteve Passe puts( SEP_LINE ); 2342b33a0f9SSteve Passe 2352b33a0f9SSteve Passe /* check whether an MP config table exists */ 236*a61a3b33SJohn Baldwin if ( (defaultConfig = mpfps->config_type) ) 2372b33a0f9SSteve Passe MPConfigDefault( defaultConfig ); 2382b33a0f9SSteve Passe else 239*a61a3b33SJohn Baldwin MPConfigTableHeader( mpfps->pap ); 2402b33a0f9SSteve Passe 2412b33a0f9SSteve Passe /* do a dmesg output */ 2422b33a0f9SSteve Passe if ( dmesg ) 2432b33a0f9SSteve Passe doDmesg(); 2442b33a0f9SSteve Passe 2452b33a0f9SSteve Passe puts( SEP_LINE2 ); 2462b33a0f9SSteve Passe 2472b33a0f9SSteve Passe return 0; 2482b33a0f9SSteve Passe } 2492b33a0f9SSteve Passe 2502b33a0f9SSteve Passe 2512b33a0f9SSteve Passe /* 2522b33a0f9SSteve Passe * set PHYSICAL address of MP floating pointer structure 2532b33a0f9SSteve Passe */ 2542b33a0f9SSteve Passe #define NEXT(X) ((X) += 4) 2552b33a0f9SSteve Passe static void 2568c489d72SPeter Wemm apic_probe( u_int32_t* paddr, int* where ) 2572b33a0f9SSteve Passe { 2582b33a0f9SSteve Passe /* 2592b33a0f9SSteve Passe * c rewrite of apic_probe() by Jack F. Vogel 2602b33a0f9SSteve Passe */ 2612b33a0f9SSteve Passe 2622b33a0f9SSteve Passe int x; 2632b33a0f9SSteve Passe u_short segment; 2648c489d72SPeter Wemm u_int32_t target; 2652b33a0f9SSteve Passe u_int buffer[ BIOS_SIZE / sizeof( int ) ]; 2662b33a0f9SSteve Passe 2672b33a0f9SSteve Passe if ( verbose ) 2682b33a0f9SSteve Passe printf( "\n" ); 2692b33a0f9SSteve Passe 2702b33a0f9SSteve Passe /* search Extended Bios Data Area, if present */ 2712b33a0f9SSteve Passe if ( verbose ) 2722b33a0f9SSteve Passe printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER ); 2738c489d72SPeter Wemm seekEntry( (u_int32_t)EBDA_POINTER ); 2742b33a0f9SSteve Passe readEntry( &segment, 2 ); 2752b33a0f9SSteve Passe if ( segment ) { /* search EBDA */ 2768c489d72SPeter Wemm target = (u_int32_t)segment << 4; 2772b33a0f9SSteve Passe if ( verbose ) 2782b33a0f9SSteve Passe printf( "found, searching EBDA @ 0x%08x\n", target ); 2792b33a0f9SSteve Passe seekEntry( target ); 2802b33a0f9SSteve Passe readEntry( buffer, ONE_KBYTE ); 2812b33a0f9SSteve Passe 2828c489d72SPeter Wemm for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 2832b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 2842b33a0f9SSteve Passe *where = 1; 2852b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + target; 2862b33a0f9SSteve Passe return; 2872b33a0f9SSteve Passe } 2882b33a0f9SSteve Passe } 2892b33a0f9SSteve Passe } 2902b33a0f9SSteve Passe else { 2912b33a0f9SSteve Passe if ( verbose ) 2922b33a0f9SSteve Passe printf( "NOT found\n" ); 2932b33a0f9SSteve Passe } 2942b33a0f9SSteve Passe 2952b33a0f9SSteve Passe /* read CMOS for real top of mem */ 2968c489d72SPeter Wemm seekEntry( (u_int32_t)TOPOFMEM_POINTER ); 2972b33a0f9SSteve Passe readEntry( &segment, 2 ); 2982b33a0f9SSteve Passe --segment; /* less ONE_KBYTE */ 2992b33a0f9SSteve Passe target = segment * 1024; 3002b33a0f9SSteve Passe if ( verbose ) 3012b33a0f9SSteve Passe printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n", 3022b33a0f9SSteve Passe target, segment ); 3032b33a0f9SSteve Passe seekEntry( target ); 3042b33a0f9SSteve Passe readEntry( buffer, ONE_KBYTE ); 3052b33a0f9SSteve Passe 3068c489d72SPeter Wemm for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 3072b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 3082b33a0f9SSteve Passe *where = 2; 3092b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + target; 3102b33a0f9SSteve Passe return; 3112b33a0f9SSteve Passe } 3122b33a0f9SSteve Passe } 3132b33a0f9SSteve Passe 3142b33a0f9SSteve Passe /* we don't necessarily believe CMOS, check base of the last 1K of 640K */ 3152b33a0f9SSteve Passe if ( target != (DEFAULT_TOPOFMEM - 1024)) { 3162b33a0f9SSteve Passe target = (DEFAULT_TOPOFMEM - 1024); 3172b33a0f9SSteve Passe if ( verbose ) 3182b33a0f9SSteve Passe printf( " searching default 'top of mem' @ 0x%08x (%dK)\n", 3192b33a0f9SSteve Passe target, (target / 1024) ); 3202b33a0f9SSteve Passe seekEntry( target ); 3212b33a0f9SSteve Passe readEntry( buffer, ONE_KBYTE ); 3222b33a0f9SSteve Passe 3238c489d72SPeter Wemm for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 3242b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 3252b33a0f9SSteve Passe *where = 3; 3262b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + target; 3272b33a0f9SSteve Passe return; 3282b33a0f9SSteve Passe } 3292b33a0f9SSteve Passe } 3302b33a0f9SSteve Passe } 3312b33a0f9SSteve Passe 3322b33a0f9SSteve Passe /* search the BIOS */ 3332b33a0f9SSteve Passe if ( verbose ) 3342b33a0f9SSteve Passe printf( " searching BIOS @ 0x%08x\n", BIOS_BASE ); 3352b33a0f9SSteve Passe seekEntry( BIOS_BASE ); 3362b33a0f9SSteve Passe readEntry( buffer, BIOS_SIZE ); 3372b33a0f9SSteve Passe 3388c489d72SPeter Wemm for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 3392b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 3402b33a0f9SSteve Passe *where = 4; 3412b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + BIOS_BASE; 3422b33a0f9SSteve Passe return; 3432b33a0f9SSteve Passe } 3442b33a0f9SSteve Passe } 3452b33a0f9SSteve Passe 3462b33a0f9SSteve Passe /* search the extended BIOS */ 3472b33a0f9SSteve Passe if ( verbose ) 3482b33a0f9SSteve Passe printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 ); 3492b33a0f9SSteve Passe seekEntry( BIOS_BASE2 ); 3502b33a0f9SSteve Passe readEntry( buffer, BIOS_SIZE ); 3512b33a0f9SSteve Passe 3528c489d72SPeter Wemm for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 3532b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 3542b33a0f9SSteve Passe *where = 5; 3552b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2; 3562b33a0f9SSteve Passe return; 3572b33a0f9SSteve Passe } 3582b33a0f9SSteve Passe } 3592b33a0f9SSteve Passe 3602b33a0f9SSteve Passe if ( grope ) { 3612b33a0f9SSteve Passe /* search additional memory */ 3622b33a0f9SSteve Passe target = GROPE_AREA1; 3632b33a0f9SSteve Passe if ( verbose ) 3642b33a0f9SSteve Passe printf( " groping memory @ 0x%08x\n", target ); 3652b33a0f9SSteve Passe seekEntry( target ); 3662b33a0f9SSteve Passe readEntry( buffer, GROPE_SIZE ); 3672b33a0f9SSteve Passe 3688c489d72SPeter Wemm for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 3692b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 3702b33a0f9SSteve Passe *where = 6; 3712b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + GROPE_AREA1; 3722b33a0f9SSteve Passe return; 3732b33a0f9SSteve Passe } 3742b33a0f9SSteve Passe } 3752b33a0f9SSteve Passe 3762b33a0f9SSteve Passe target = GROPE_AREA2; 3772b33a0f9SSteve Passe if ( verbose ) 3782b33a0f9SSteve Passe printf( " groping memory @ 0x%08x\n", target ); 3792b33a0f9SSteve Passe seekEntry( target ); 3802b33a0f9SSteve Passe readEntry( buffer, GROPE_SIZE ); 3812b33a0f9SSteve Passe 3828c489d72SPeter Wemm for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 3832b33a0f9SSteve Passe if ( buffer[ x ] == MP_SIG ) { 3842b33a0f9SSteve Passe *where = 7; 3852b33a0f9SSteve Passe *paddr = (x * sizeof( unsigned int )) + GROPE_AREA2; 3862b33a0f9SSteve Passe return; 3872b33a0f9SSteve Passe } 3882b33a0f9SSteve Passe } 3892b33a0f9SSteve Passe } 3902b33a0f9SSteve Passe 3912b33a0f9SSteve Passe *where = 0; 3928c489d72SPeter Wemm *paddr = (u_int32_t)0; 3932b33a0f9SSteve Passe } 3942b33a0f9SSteve Passe 3952b33a0f9SSteve Passe 3962b33a0f9SSteve Passe /* 3972b33a0f9SSteve Passe * 3982b33a0f9SSteve Passe */ 399ec175cedSPhilippe Charnier static void 400*a61a3b33SJohn Baldwin MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp ) 4012b33a0f9SSteve Passe { 402*a61a3b33SJohn Baldwin mpfps_t mpfps; 4032b33a0f9SSteve Passe 404*a61a3b33SJohn Baldwin /* map in mpfps structure*/ 405*a61a3b33SJohn Baldwin *mpfpsp = mpfps = mapEntry( paddr, sizeof( mpfps ) ); 4062b33a0f9SSteve Passe 4072b33a0f9SSteve Passe /* show its contents */ 4082b33a0f9SSteve Passe printf( "MP Floating Pointer Structure:\n\n" ); 4092b33a0f9SSteve Passe 410ec175cedSPhilippe Charnier printf( " location:\t\t\t" ); 4112b33a0f9SSteve Passe switch ( where ) 4122b33a0f9SSteve Passe { 4132b33a0f9SSteve Passe case 1: 4142b33a0f9SSteve Passe printf( "EBDA\n" ); 4152b33a0f9SSteve Passe break; 4162b33a0f9SSteve Passe case 2: 4172b33a0f9SSteve Passe printf( "BIOS base memory\n" ); 4182b33a0f9SSteve Passe break; 4192b33a0f9SSteve Passe case 3: 4202b33a0f9SSteve Passe printf( "DEFAULT base memory (639K)\n" ); 4212b33a0f9SSteve Passe break; 4222b33a0f9SSteve Passe case 4: 4232b33a0f9SSteve Passe printf( "BIOS\n" ); 4242b33a0f9SSteve Passe break; 4252b33a0f9SSteve Passe case 5: 4262b33a0f9SSteve Passe printf( "Extended BIOS\n" ); 4272b33a0f9SSteve Passe break; 4282b33a0f9SSteve Passe 4292b33a0f9SSteve Passe case 0: 4302b33a0f9SSteve Passe printf( "NOT found!\n" ); 4312b33a0f9SSteve Passe exit( 1 ); 4322b33a0f9SSteve Passe default: 4332b33a0f9SSteve Passe printf( "BOGUS!\n" ); 4342b33a0f9SSteve Passe exit( 1 ); 4352b33a0f9SSteve Passe } 4362b33a0f9SSteve Passe printf( " physical address:\t\t0x%08x\n", paddr ); 4372b33a0f9SSteve Passe 4382b33a0f9SSteve Passe printf( " signature:\t\t\t'" ); 4392b33a0f9SSteve Passe pnstr( mpfps->signature, 4 ); 4402b33a0f9SSteve Passe printf( "'\n" ); 4412b33a0f9SSteve Passe 4422b33a0f9SSteve Passe printf( " length:\t\t\t%d bytes\n", mpfps->length * 16 ); 4432b33a0f9SSteve Passe printf( " version:\t\t\t1.%1d\n", mpfps->spec_rev ); 4442b33a0f9SSteve Passe printf( " checksum:\t\t\t0x%02x\n", mpfps->checksum ); 4452b33a0f9SSteve Passe 4462b33a0f9SSteve Passe /* bits 0:6 are RESERVED */ 4472b33a0f9SSteve Passe if ( mpfps->mpfb2 & 0x7f ) { 448ec175cedSPhilippe Charnier printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 ); 4492b33a0f9SSteve Passe } 4502b33a0f9SSteve Passe 4512b33a0f9SSteve Passe /* bit 7 is IMCRP */ 452*a61a3b33SJohn Baldwin printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) ? 4532b33a0f9SSteve Passe "PIC" : "Virtual Wire" ); 4542b33a0f9SSteve Passe 4552b33a0f9SSteve Passe /* MP feature bytes 3-5 are expected to be ZERO */ 4562b33a0f9SSteve Passe if ( mpfps->mpfb3 ) 4572b33a0f9SSteve Passe printf( " warning, MP feature byte 3 NONZERO!\n" ); 4582b33a0f9SSteve Passe if ( mpfps->mpfb4 ) 4592b33a0f9SSteve Passe printf( " warning, MP feature byte 4 NONZERO!\n" ); 4602b33a0f9SSteve Passe if ( mpfps->mpfb5 ) 4612b33a0f9SSteve Passe printf( " warning, MP feature byte 5 NONZERO!\n" ); 4622b33a0f9SSteve Passe } 4632b33a0f9SSteve Passe 4642b33a0f9SSteve Passe 4652b33a0f9SSteve Passe /* 4662b33a0f9SSteve Passe * 4672b33a0f9SSteve Passe */ 4682b33a0f9SSteve Passe static void 4692b33a0f9SSteve Passe MPConfigDefault( int featureByte ) 4702b33a0f9SSteve Passe { 4712b33a0f9SSteve Passe printf( " MP default config type: %d\n\n", featureByte ); 4722b33a0f9SSteve Passe switch ( featureByte ) { 4732b33a0f9SSteve Passe case 1: 4742b33a0f9SSteve Passe printf( " bus: ISA, APIC: 82489DX\n" ); 4752b33a0f9SSteve Passe break; 4762b33a0f9SSteve Passe case 2: 4772b33a0f9SSteve Passe printf( " bus: EISA, APIC: 82489DX\n" ); 4782b33a0f9SSteve Passe break; 4792b33a0f9SSteve Passe case 3: 4802b33a0f9SSteve Passe printf( " bus: EISA, APIC: 82489DX\n" ); 4812b33a0f9SSteve Passe break; 4822b33a0f9SSteve Passe case 4: 4832b33a0f9SSteve Passe printf( " bus: MCA, APIC: 82489DX\n" ); 4842b33a0f9SSteve Passe break; 4852b33a0f9SSteve Passe case 5: 4862b33a0f9SSteve Passe printf( " bus: ISA+PCI, APIC: Integrated\n" ); 4872b33a0f9SSteve Passe break; 4882b33a0f9SSteve Passe case 6: 4892b33a0f9SSteve Passe printf( " bus: EISA+PCI, APIC: Integrated\n" ); 4902b33a0f9SSteve Passe break; 4912b33a0f9SSteve Passe case 7: 4922b33a0f9SSteve Passe printf( " bus: MCA+PCI, APIC: Integrated\n" ); 4932b33a0f9SSteve Passe break; 4942b33a0f9SSteve Passe default: 4952b33a0f9SSteve Passe printf( " future type\n" ); 4962b33a0f9SSteve Passe break; 4972b33a0f9SSteve Passe } 4982b33a0f9SSteve Passe 4992b33a0f9SSteve Passe switch ( featureByte ) { 5002b33a0f9SSteve Passe case 1: 5012b33a0f9SSteve Passe case 2: 5022b33a0f9SSteve Passe case 3: 5032b33a0f9SSteve Passe case 4: 5042b33a0f9SSteve Passe nbus = 1; 5052b33a0f9SSteve Passe break; 5062b33a0f9SSteve Passe case 5: 5072b33a0f9SSteve Passe case 6: 5082b33a0f9SSteve Passe case 7: 5092b33a0f9SSteve Passe nbus = 2; 5102b33a0f9SSteve Passe break; 5112b33a0f9SSteve Passe default: 5122b33a0f9SSteve Passe printf( " future type\n" ); 5132b33a0f9SSteve Passe break; 5142b33a0f9SSteve Passe } 5152b33a0f9SSteve Passe 5162b33a0f9SSteve Passe ncpu = 2; 5172b33a0f9SSteve Passe napic = 1; 5182b33a0f9SSteve Passe nintr = 16; 5192b33a0f9SSteve Passe } 5202b33a0f9SSteve Passe 5212b33a0f9SSteve Passe 5222b33a0f9SSteve Passe /* 5232b33a0f9SSteve Passe * 5242b33a0f9SSteve Passe */ 5252b33a0f9SSteve Passe static void 5268c489d72SPeter Wemm MPConfigTableHeader( u_int32_t pap ) 5272b33a0f9SSteve Passe { 5282b33a0f9SSteve Passe mpcth_t cth; 529ec175cedSPhilippe Charnier int x; 5304a3e427fSPeter Wemm int totalSize; 531*a61a3b33SJohn Baldwin int c; 5324a3e427fSPeter Wemm int oldtype, entrytype; 533*a61a3b33SJohn Baldwin u_int8_t *entry; 5342b33a0f9SSteve Passe 5352b33a0f9SSteve Passe if ( pap == 0 ) { 5362b33a0f9SSteve Passe printf( "MP Configuration Table Header MISSING!\n" ); 5372b33a0f9SSteve Passe exit( 1 ); 5382b33a0f9SSteve Passe } 5392b33a0f9SSteve Passe 540*a61a3b33SJohn Baldwin /* map in cth structure */ 541*a61a3b33SJohn Baldwin cth = mapEntry( pap, sizeof( *cth ) ); 5422b33a0f9SSteve Passe 5432b33a0f9SSteve Passe printf( "MP Config Table Header:\n\n" ); 5442b33a0f9SSteve Passe 5452b33a0f9SSteve Passe printf( " physical address:\t\t0x%08x\n", pap ); 5462b33a0f9SSteve Passe 5472b33a0f9SSteve Passe printf( " signature:\t\t\t'" ); 548*a61a3b33SJohn Baldwin pnstr( cth->signature, 4 ); 5492b33a0f9SSteve Passe printf( "'\n" ); 5502b33a0f9SSteve Passe 551*a61a3b33SJohn Baldwin printf( " base table length:\t\t%d\n", cth->base_table_length ); 5522b33a0f9SSteve Passe 553*a61a3b33SJohn Baldwin printf( " version:\t\t\t1.%1d\n", cth->spec_rev ); 554*a61a3b33SJohn Baldwin printf( " checksum:\t\t\t0x%02x\n", cth->checksum ); 5552b33a0f9SSteve Passe 5562b33a0f9SSteve Passe printf( " OEM ID:\t\t\t'" ); 557*a61a3b33SJohn Baldwin pnstr( cth->oem_id, 8 ); 5582b33a0f9SSteve Passe printf( "'\n" ); 5592b33a0f9SSteve Passe 5602b33a0f9SSteve Passe printf( " Product ID:\t\t\t'" ); 561*a61a3b33SJohn Baldwin pnstr( cth->product_id, 12 ); 5622b33a0f9SSteve Passe printf( "'\n" ); 5632b33a0f9SSteve Passe 564*a61a3b33SJohn Baldwin printf( " OEM table pointer:\t\t0x%08x\n", cth->oem_table_pointer ); 565*a61a3b33SJohn Baldwin printf( " OEM table size:\t\t%d\n", cth->oem_table_size ); 5662b33a0f9SSteve Passe 567*a61a3b33SJohn Baldwin printf( " entry count:\t\t\t%d\n", cth->entry_count ); 5682b33a0f9SSteve Passe 569*a61a3b33SJohn Baldwin printf( " local APIC address:\t\t0x%08x\n", cth->apic_address ); 5702b33a0f9SSteve Passe 571*a61a3b33SJohn Baldwin printf( " extended table length:\t%d\n", cth->extended_table_length ); 572*a61a3b33SJohn Baldwin printf( " extended table checksum:\t%d\n", cth->extended_table_checksum ); 5732b33a0f9SSteve Passe 574*a61a3b33SJohn Baldwin totalSize = cth->base_table_length - sizeof( struct MPCTH ); 5752b33a0f9SSteve Passe 5762b33a0f9SSteve Passe puts( SEP_LINE ); 5772b33a0f9SSteve Passe 5782b33a0f9SSteve Passe printf( "MP Config Base Table Entries:\n\n" ); 5792b33a0f9SSteve Passe 580d72323d1SNeel Natu /* initialize tables */ 581d72323d1SNeel Natu for (x = 0; x < (int)nitems(busses); x++) 582d72323d1SNeel Natu busses[x] = 0xff; 583d72323d1SNeel Natu 584d72323d1SNeel Natu for (x = 0; x < (int)nitems(apics); x++) 585d72323d1SNeel Natu apics[x] = 0xff; 5862b33a0f9SSteve Passe 5872b33a0f9SSteve Passe ncpu = 0; 5882b33a0f9SSteve Passe nbus = 0; 5892b33a0f9SSteve Passe napic = 0; 5902b33a0f9SSteve Passe nintr = 0; 5912b33a0f9SSteve Passe 5924a3e427fSPeter Wemm oldtype = -1; 593*a61a3b33SJohn Baldwin entry = mapEntry(pap + sizeof(*cth), cth->base_table_length); 594*a61a3b33SJohn Baldwin for (c = cth->entry_count; c; c--) { 595*a61a3b33SJohn Baldwin entrytype = *entry; 5964a3e427fSPeter Wemm if (entrytype != oldtype) 5974a3e427fSPeter Wemm printf("--\n"); 5984a3e427fSPeter Wemm if (entrytype < oldtype) 5994a3e427fSPeter Wemm printf("MPTABLE OUT OF ORDER!\n"); 6004a3e427fSPeter Wemm switch (entrytype) { 601*a61a3b33SJohn Baldwin case MPCT_ENTRY_PROCESSOR: 602*a61a3b33SJohn Baldwin if (oldtype != MPCT_ENTRY_PROCESSOR) 6034a3e427fSPeter Wemm printf( "Processors:\tAPIC ID\tVersion\tState" 6042b33a0f9SSteve Passe "\t\tFamily\tModel\tStep\tFlags\n" ); 605*a61a3b33SJohn Baldwin processorEntry((proc_entry_ptr)entry); 606*a61a3b33SJohn Baldwin entry += sizeof(struct PROCENTRY); 6074a3e427fSPeter Wemm break; 6082b33a0f9SSteve Passe 609*a61a3b33SJohn Baldwin case MPCT_ENTRY_BUS: 610*a61a3b33SJohn Baldwin if (oldtype != MPCT_ENTRY_BUS) 6114a3e427fSPeter Wemm printf( "Bus:\t\tBus ID\tType\n" ); 612*a61a3b33SJohn Baldwin busEntry((bus_entry_ptr)entry); 613*a61a3b33SJohn Baldwin entry += sizeof(struct BUSENTRY); 6144a3e427fSPeter Wemm break; 6152b33a0f9SSteve Passe 616*a61a3b33SJohn Baldwin case MPCT_ENTRY_IOAPIC: 617*a61a3b33SJohn Baldwin if (oldtype != MPCT_ENTRY_IOAPIC) 6184a3e427fSPeter Wemm printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" ); 619*a61a3b33SJohn Baldwin ioApicEntry((io_apic_entry_ptr)entry); 620*a61a3b33SJohn Baldwin entry += sizeof(struct IOAPICENTRY); 6214a3e427fSPeter Wemm break; 6222b33a0f9SSteve Passe 623*a61a3b33SJohn Baldwin case MPCT_ENTRY_INT: 624*a61a3b33SJohn Baldwin if (oldtype != MPCT_ENTRY_INT) 6254a3e427fSPeter Wemm printf( "I/O Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 626*a61a3b33SJohn Baldwin intEntry((int_entry_ptr)entry); 627*a61a3b33SJohn Baldwin entry += sizeof(struct INTENTRY); 6284a3e427fSPeter Wemm break; 6292b33a0f9SSteve Passe 630*a61a3b33SJohn Baldwin case MPCT_ENTRY_LOCAL_INT: 631*a61a3b33SJohn Baldwin if (oldtype != MPCT_ENTRY_LOCAL_INT) 6324a3e427fSPeter Wemm printf( "Local Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 633*a61a3b33SJohn Baldwin intEntry((int_entry_ptr)entry); 634*a61a3b33SJohn Baldwin entry += sizeof(struct INTENTRY); 6354a3e427fSPeter Wemm break; 6364a3e427fSPeter Wemm 6374a3e427fSPeter Wemm default: 6384a3e427fSPeter Wemm printf("MPTABLE HOSED! record type = %d\n", entrytype); 6394a3e427fSPeter Wemm exit(1); 6404a3e427fSPeter Wemm } 641*a61a3b33SJohn Baldwin oldtype = entrytype; 6422b33a0f9SSteve Passe } 6432b33a0f9SSteve Passe 6442b33a0f9SSteve Passe 6452b33a0f9SSteve Passe #if defined( EXTENDED_PROCESSING_READY ) 6462b33a0f9SSteve Passe /* process any extended data */ 647*a61a3b33SJohn Baldwin if ( cth->extended_table_length ) { 648*a61a3b33SJohn Baldwin ext_entry_ptr ext_entry, end; 649*a61a3b33SJohn Baldwin 6502b33a0f9SSteve Passe puts( SEP_LINE ); 6512b33a0f9SSteve Passe 6522b33a0f9SSteve Passe printf( "MP Config Extended Table Entries:\n\n" ); 6532b33a0f9SSteve Passe 654*a61a3b33SJohn Baldwin ext_entry = mapEntry(pap + cth->base_table_length, 655*a61a3b33SJohn Baldwin cth->extended_table_length); 656*a61a3b33SJohn Baldwin end = (ext_entry_ptr)((char *)ext_entry + cth->extended_table_length); 657*a61a3b33SJohn Baldwin while (ext_entry < end) { 658*a61a3b33SJohn Baldwin switch (ext_entry->type) { 659*a61a3b33SJohn Baldwin case MPCT_EXTENTRY_SAS: 660*a61a3b33SJohn Baldwin sasEntry((sas_entry_ptr)ext_entry); 6612b33a0f9SSteve Passe break; 662*a61a3b33SJohn Baldwin case MPCT_EXTENTRY_BHD: 663*a61a3b33SJohn Baldwin bhdEntry((bhd_entry_ptr)ext_entry); 6642b33a0f9SSteve Passe break; 665*a61a3b33SJohn Baldwin case MPCT_EXTENTRY_CBASM: 666*a61a3b33SJohn Baldwin cbasmEntry((cbasm_entry_ptr)ext_entry); 6672b33a0f9SSteve Passe break; 6682b33a0f9SSteve Passe default: 6692b33a0f9SSteve Passe printf( "Extended Table HOSED!\n" ); 6702b33a0f9SSteve Passe exit( 1 ); 6712b33a0f9SSteve Passe } 6722b33a0f9SSteve Passe 673*a61a3b33SJohn Baldwin ext_entry = (ext_entry_ptr)((char *)ext_entry + ext_entry->length); 6742b33a0f9SSteve Passe } 6752b33a0f9SSteve Passe } 6762b33a0f9SSteve Passe #endif /* EXTENDED_PROCESSING_READY */ 6772b33a0f9SSteve Passe 6782b33a0f9SSteve Passe /* process any OEM data */ 679*a61a3b33SJohn Baldwin if ( cth->oem_table_pointer && (cth->oem_table_size > 0) ) { 6802b33a0f9SSteve Passe #if defined( OEM_PROCESSING_READY ) 6812b33a0f9SSteve Passe # error your on your own here! 682*a61a3b33SJohn Baldwin /* map in oem table structure */ 683*a61a3b33SJohn Baldwin oemdata = mapEntry( cth->oem_table_pointer, cth->oem_table_size); 6842b33a0f9SSteve Passe 6852b33a0f9SSteve Passe /** process it */ 6862b33a0f9SSteve Passe #else 6872b33a0f9SSteve Passe printf( "\nyou need to modify the source to handle OEM data!\n\n" ); 6882b33a0f9SSteve Passe #endif /* OEM_PROCESSING_READY */ 6892b33a0f9SSteve Passe } 6902b33a0f9SSteve Passe 6912b33a0f9SSteve Passe fflush( stdout ); 6922b33a0f9SSteve Passe 6932b33a0f9SSteve Passe #if defined( RAW_DUMP ) 6942b33a0f9SSteve Passe { 6952b33a0f9SSteve Passe int ofd; 696*a61a3b33SJohn Baldwin void *dumpbuf; 6972b33a0f9SSteve Passe 69824bc5224SPawel Jakub Dawidek ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR, 0666 ); 699*a61a3b33SJohn Baldwin 700*a61a3b33SJohn Baldwin dumpbuf = mapEntry( paddr, 1024 ); 7012b33a0f9SSteve Passe write( ofd, dumpbuf, 1024 ); 7022b33a0f9SSteve Passe close( ofd ); 7032b33a0f9SSteve Passe } 7042b33a0f9SSteve Passe #endif /* RAW_DUMP */ 7052b33a0f9SSteve Passe } 7062b33a0f9SSteve Passe 7072b33a0f9SSteve Passe 7082b33a0f9SSteve Passe /* 7092b33a0f9SSteve Passe * 7102b33a0f9SSteve Passe */ 7112b33a0f9SSteve Passe static void 7128c489d72SPeter Wemm seekEntry( u_int32_t addr ) 7132b33a0f9SSteve Passe { 714ec175cedSPhilippe Charnier if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 ) 7151a37aa56SDavid E. O'Brien err( 1, "%s seek", _PATH_MEM ); 7162b33a0f9SSteve Passe } 7172b33a0f9SSteve Passe 7182b33a0f9SSteve Passe 7192b33a0f9SSteve Passe /* 7202b33a0f9SSteve Passe * 7212b33a0f9SSteve Passe */ 7222b33a0f9SSteve Passe static void 7232b33a0f9SSteve Passe readEntry( void* entry, int size ) 7242b33a0f9SSteve Passe { 725ec175cedSPhilippe Charnier if ( read( pfd, entry, size ) != size ) 726ec175cedSPhilippe Charnier err( 1, "readEntry" ); 7272b33a0f9SSteve Passe } 7282b33a0f9SSteve Passe 729*a61a3b33SJohn Baldwin static void * 730*a61a3b33SJohn Baldwin mapEntry( u_int32_t addr, int size ) 731*a61a3b33SJohn Baldwin { 732*a61a3b33SJohn Baldwin void *p; 733*a61a3b33SJohn Baldwin 734*a61a3b33SJohn Baldwin p = mmap( NULL, size, PROT_READ, MAP_SHARED, pfd, addr ); 735*a61a3b33SJohn Baldwin if (p == MAP_FAILED) 736*a61a3b33SJohn Baldwin err( 1, "mapEntry" ); 737*a61a3b33SJohn Baldwin return (p); 738*a61a3b33SJohn Baldwin } 7392b33a0f9SSteve Passe 7402b33a0f9SSteve Passe static void 741*a61a3b33SJohn Baldwin processorEntry( proc_entry_ptr entry ) 7422b33a0f9SSteve Passe { 7432b33a0f9SSteve Passe 7442b33a0f9SSteve Passe /* count it */ 7452b33a0f9SSteve Passe ++ncpu; 7462b33a0f9SSteve Passe 747*a61a3b33SJohn Baldwin printf( "\t\t%2d", entry->apic_id ); 748*a61a3b33SJohn Baldwin printf( "\t 0x%2x", entry->apic_version ); 7492b33a0f9SSteve Passe 7502b33a0f9SSteve Passe printf( "\t %s, %s", 751*a61a3b33SJohn Baldwin (entry->cpu_flags & PROCENTRY_FLAG_BP) ? "BSP" : "AP", 752*a61a3b33SJohn Baldwin (entry->cpu_flags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" ); 7532b33a0f9SSteve Passe 7542b33a0f9SSteve Passe printf( "\t %d\t %d\t %d", 755*a61a3b33SJohn Baldwin (entry->cpu_signature >> 8) & 0x0f, 756*a61a3b33SJohn Baldwin (entry->cpu_signature >> 4) & 0x0f, 757*a61a3b33SJohn Baldwin entry->cpu_signature & 0x0f ); 7582b33a0f9SSteve Passe 759*a61a3b33SJohn Baldwin printf( "\t 0x%04x\n", entry->feature_flags ); 7602b33a0f9SSteve Passe } 7612b33a0f9SSteve Passe 7622b33a0f9SSteve Passe 7632b33a0f9SSteve Passe /* 7642b33a0f9SSteve Passe * 7652b33a0f9SSteve Passe */ 7662b33a0f9SSteve Passe static int 7672b33a0f9SSteve Passe lookupBusType( char* name ) 7682b33a0f9SSteve Passe { 7692b33a0f9SSteve Passe int x; 7702b33a0f9SSteve Passe 7712b33a0f9SSteve Passe for ( x = 0; x < MAX_BUSTYPE; ++x ) 7722b33a0f9SSteve Passe if ( strcmp( busTypeTable[ x ].name, name ) == 0 ) 7732b33a0f9SSteve Passe return busTypeTable[ x ].type; 7742b33a0f9SSteve Passe 7752b33a0f9SSteve Passe return UNKNOWN_BUSTYPE; 7762b33a0f9SSteve Passe } 7772b33a0f9SSteve Passe 7782b33a0f9SSteve Passe 7792b33a0f9SSteve Passe static void 780*a61a3b33SJohn Baldwin busEntry( bus_entry_ptr entry ) 7812b33a0f9SSteve Passe { 7822b33a0f9SSteve Passe int x; 7832b33a0f9SSteve Passe char name[ 8 ]; 7842b33a0f9SSteve Passe char c; 7852b33a0f9SSteve Passe 7862b33a0f9SSteve Passe /* count it */ 7872b33a0f9SSteve Passe ++nbus; 7882b33a0f9SSteve Passe 789*a61a3b33SJohn Baldwin printf( "\t\t%2d", entry->bus_id ); 790*a61a3b33SJohn Baldwin printf( "\t " ); pnstr( entry->bus_type, 6 ); printf( "\n" ); 7912b33a0f9SSteve Passe 7922b33a0f9SSteve Passe for ( x = 0; x < 6; ++x ) { 793*a61a3b33SJohn Baldwin if ( (c = entry->bus_type[ x ]) == ' ' ) 7942b33a0f9SSteve Passe break; 7952b33a0f9SSteve Passe name[ x ] = c; 7962b33a0f9SSteve Passe } 7972b33a0f9SSteve Passe name[ x ] = '\0'; 798*a61a3b33SJohn Baldwin busses[ entry->bus_id ] = lookupBusType( name ); 7992b33a0f9SSteve Passe } 8002b33a0f9SSteve Passe 8012b33a0f9SSteve Passe 8022b33a0f9SSteve Passe static void 803*a61a3b33SJohn Baldwin ioApicEntry( io_apic_entry_ptr entry ) 8042b33a0f9SSteve Passe { 8052b33a0f9SSteve Passe 8062b33a0f9SSteve Passe /* count it */ 8072b33a0f9SSteve Passe ++napic; 8082b33a0f9SSteve Passe 809*a61a3b33SJohn Baldwin printf( "\t\t%2d", entry->apic_id ); 810*a61a3b33SJohn Baldwin printf( "\t 0x%02x", entry->apic_version ); 8112b33a0f9SSteve Passe printf( "\t %s", 812*a61a3b33SJohn Baldwin (entry->apic_flags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" ); 813*a61a3b33SJohn Baldwin printf( "\t\t 0x%x\n", entry->apic_address ); 8142b33a0f9SSteve Passe 815*a61a3b33SJohn Baldwin apics[ entry->apic_id ] = entry->apic_id; 8162b33a0f9SSteve Passe } 8172b33a0f9SSteve Passe 8182b33a0f9SSteve Passe 81960bd06daSEd Schouten static const char *intTypes[] = { 8202b33a0f9SSteve Passe "INT", "NMI", "SMI", "ExtINT" 8212b33a0f9SSteve Passe }; 8222b33a0f9SSteve Passe 82360bd06daSEd Schouten static const char *polarityMode[] = { 8242b33a0f9SSteve Passe "conforms", "active-hi", "reserved", "active-lo" 8252b33a0f9SSteve Passe }; 82660bd06daSEd Schouten static const char *triggerMode[] = { 8272b33a0f9SSteve Passe "conforms", "edge", "reserved", "level" 8282b33a0f9SSteve Passe }; 8292b33a0f9SSteve Passe 8302b33a0f9SSteve Passe static void 831*a61a3b33SJohn Baldwin intEntry( int_entry_ptr entry ) 8322b33a0f9SSteve Passe { 8332b33a0f9SSteve Passe 8342b33a0f9SSteve Passe /* count it */ 835*a61a3b33SJohn Baldwin if ( entry->type == MPCT_ENTRY_INT ) 8362b33a0f9SSteve Passe ++nintr; 8372b33a0f9SSteve Passe 838*a61a3b33SJohn Baldwin printf( "\t\t%s", intTypes[ entry->int_type ] ); 8392b33a0f9SSteve Passe 840*a61a3b33SJohn Baldwin printf( "\t%9s", polarityMode[ entry->int_flags & INTENTRY_FLAGS_POLARITY ] ); 841*a61a3b33SJohn Baldwin printf( "%12s", triggerMode[ (entry->int_flags & INTENTRY_FLAGS_TRIGGER) >> 2 ] ); 8422b33a0f9SSteve Passe 843*a61a3b33SJohn Baldwin printf( "\t %5d", entry->src_bus_id ); 844*a61a3b33SJohn Baldwin if ( busses[ entry->src_bus_id ] == PCI ) 8452b33a0f9SSteve Passe printf( "\t%2d:%c", 846*a61a3b33SJohn Baldwin (entry->src_bus_irq >> 2) & 0x1f, 847*a61a3b33SJohn Baldwin (entry->src_bus_irq & 0x03) + 'A' ); 8482b33a0f9SSteve Passe else 849*a61a3b33SJohn Baldwin printf( "\t %3d", entry->src_bus_irq ); 850*a61a3b33SJohn Baldwin printf( "\t %6d", entry->dst_apic_id ); 851*a61a3b33SJohn Baldwin printf( "\t %3d\n", entry->dst_apic_int ); 8522b33a0f9SSteve Passe } 8532b33a0f9SSteve Passe 8542b33a0f9SSteve Passe 8552b33a0f9SSteve Passe static void 856*a61a3b33SJohn Baldwin sasEntry( sas_entry_ptr entry ) 8572b33a0f9SSteve Passe { 8582b33a0f9SSteve Passe 859*a61a3b33SJohn Baldwin printf( "--\nSystem Address Space\n"); 860*a61a3b33SJohn Baldwin printf( " bus ID: %d", entry->bus_id ); 8612b33a0f9SSteve Passe printf( " address type: " ); 862*a61a3b33SJohn Baldwin switch ( entry->address_type ) { 863*a61a3b33SJohn Baldwin case SASENTRY_TYPE_IO: 8642b33a0f9SSteve Passe printf( "I/O address\n" ); 8652b33a0f9SSteve Passe break; 866*a61a3b33SJohn Baldwin case SASENTRY_TYPE_MEMORY: 8672b33a0f9SSteve Passe printf( "memory address\n" ); 8682b33a0f9SSteve Passe break; 869*a61a3b33SJohn Baldwin case SASENTRY_TYPE_PREFETCH: 8702b33a0f9SSteve Passe printf( "prefetch address\n" ); 8712b33a0f9SSteve Passe break; 8722b33a0f9SSteve Passe default: 8732b33a0f9SSteve Passe printf( "UNKNOWN type\n" ); 8742b33a0f9SSteve Passe break; 8752b33a0f9SSteve Passe } 8762b33a0f9SSteve Passe 877*a61a3b33SJohn Baldwin printf( " address base: 0x%jx\n", (uintmax_t)entry->address_base ); 878*a61a3b33SJohn Baldwin printf( " address range: 0x%jx\n", (uintmax_t)entry->address_length ); 8792b33a0f9SSteve Passe } 8802b33a0f9SSteve Passe 8812b33a0f9SSteve Passe 8822b33a0f9SSteve Passe static void 883*a61a3b33SJohn Baldwin bhdEntry( bhd_entry_ptr entry ) 8842b33a0f9SSteve Passe { 8852b33a0f9SSteve Passe 886*a61a3b33SJohn Baldwin printf( "--\nBus Hierarchy\n" ); 887*a61a3b33SJohn Baldwin printf( " bus ID: %d", entry->bus_id ); 888*a61a3b33SJohn Baldwin printf( " bus info: 0x%02x", entry->bus_info ); 889*a61a3b33SJohn Baldwin printf( " parent bus ID: %d\n", entry->parent_bus ); 8902b33a0f9SSteve Passe } 8912b33a0f9SSteve Passe 8922b33a0f9SSteve Passe 8932b33a0f9SSteve Passe static void 894*a61a3b33SJohn Baldwin cbasmEntry( cbasm_entry_ptr entry ) 8952b33a0f9SSteve Passe { 8962b33a0f9SSteve Passe 897*a61a3b33SJohn Baldwin printf( "--\nCompatibility Bus Address\n" ); 898*a61a3b33SJohn Baldwin printf( " bus ID: %d", entry->bus_id ); 899*a61a3b33SJohn Baldwin printf( " address modifier: %s\n", 900*a61a3b33SJohn Baldwin (entry->address_mod & CBASMENTRY_ADDRESS_MOD_SUBTRACT) ? 9012b33a0f9SSteve Passe "subtract" : "add" ); 902*a61a3b33SJohn Baldwin printf( " predefined range: 0x%08x\n", entry->predefined_range ); 9032b33a0f9SSteve Passe } 9042b33a0f9SSteve Passe 9052b33a0f9SSteve Passe 9062b33a0f9SSteve Passe /* 9072b33a0f9SSteve Passe * do a dmesg output 9082b33a0f9SSteve Passe */ 9092b33a0f9SSteve Passe static void 9102b33a0f9SSteve Passe doDmesg( void ) 9112b33a0f9SSteve Passe { 9122b33a0f9SSteve Passe puts( SEP_LINE ); 9132b33a0f9SSteve Passe 9142b33a0f9SSteve Passe printf( "dmesg output:\n\n" ); 9152b33a0f9SSteve Passe fflush( stdout ); 9162b33a0f9SSteve Passe system( "dmesg" ); 9172b33a0f9SSteve Passe } 9182b33a0f9SSteve Passe 9192b33a0f9SSteve Passe 9202b33a0f9SSteve Passe /* 9212b33a0f9SSteve Passe * 9222b33a0f9SSteve Passe */ 9232b33a0f9SSteve Passe static void 9242b33a0f9SSteve Passe pnstr( char* s, int c ) 9252b33a0f9SSteve Passe { 9262b33a0f9SSteve Passe char string[ MAXPNSTR + 1 ]; 9272b33a0f9SSteve Passe 9282b33a0f9SSteve Passe if ( c > MAXPNSTR ) 9292b33a0f9SSteve Passe c = MAXPNSTR; 9302b33a0f9SSteve Passe strncpy( string, s, c ); 9312b33a0f9SSteve Passe string[ c ] = '\0'; 9322b33a0f9SSteve Passe printf( "%s", string ); 9332b33a0f9SSteve Passe } 934