xref: /freebsd/usr.sbin/mptable/mptable.c (revision 8c489d725d4e4fc90a8c949482420c8a68b85cd1)
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