mptable.c revision 33774
125265Sfsmp/*
225265Sfsmp * Copyright (c) 1996, by Steve Passe
325265Sfsmp * All rights reserved.
425265Sfsmp *
525265Sfsmp * Redistribution and use in source and binary forms, with or without
625265Sfsmp * modification, are permitted provided that the following conditions
725265Sfsmp * are met:
825265Sfsmp * 1. Redistributions of source code must retain the above copyright
925265Sfsmp *    notice, this list of conditions and the following disclaimer.
1025265Sfsmp * 2. The name of the developer may NOT be used to endorse or promote products
1125265Sfsmp *    derived from this software without specific prior written permission.
1225265Sfsmp *
1325265Sfsmp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1425265Sfsmp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1525265Sfsmp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1625265Sfsmp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1725265Sfsmp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1825265Sfsmp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1925265Sfsmp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2025265Sfsmp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2125265Sfsmp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2225265Sfsmp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2325265Sfsmp * SUCH DAMAGE.
2425265Sfsmp */
2525265Sfsmp
2625265Sfsmp/*
2725265Sfsmp * mptable.c
2825265Sfsmp */
2925265Sfsmp
3029850Scharnier#ifndef lint
3129850Scharnierstatic const char rcsid[] =
3233774Sbde	"$Id: mptable.c,v 1.9 1997/09/25 06:47:33 charnier Exp $";
3329850Scharnier#endif /* not lint */
3429850Scharnier
3525265Sfsmp#define VMAJOR			2
3625265Sfsmp#define VMINOR			0
3729161Sfsmp#define VDELTA			15
3825265Sfsmp
3925265Sfsmp/*
4025265Sfsmp * this will cause the raw mp table to be dumped to /tmp/mpdump
4125265Sfsmp *
4225265Sfsmp#define RAW_DUMP
4325265Sfsmp */
4425265Sfsmp
4525265Sfsmp#define MP_SIG			0x5f504d5f	/* _MP_ */
4625265Sfsmp#define EXTENDED_PROCESSING_READY
4725265Sfsmp#define OEM_PROCESSING_READY_NOT
4825265Sfsmp
4933774Sbde#include <sys/types.h>
5029850Scharnier#include <err.h>
5129850Scharnier#include <fcntl.h>
5225265Sfsmp#include <stdio.h>
5329850Scharnier#include <stdlib.h>
5429850Scharnier#include <string.h>
5525265Sfsmp#include <unistd.h>
5625265Sfsmp
5725265Sfsmp#define SEP_LINE \
5825265Sfsmp"\n-------------------------------------------------------------------------------\n"
5925265Sfsmp
6025265Sfsmp#define SEP_LINE2 \
6125265Sfsmp"\n===============================================================================\n"
6225265Sfsmp
6325265Sfsmp/* EBDA is @ 40:0e in real-mode terms */
6425265Sfsmp#define EBDA_POINTER		0x040e		/* location of EBDA pointer */
6525265Sfsmp
6625265Sfsmp/* CMOS 'top of mem' is @ 40:13 in real-mode terms */
6725265Sfsmp#define TOPOFMEM_POINTER	0x0413		/* BIOS: base memory size */
6825265Sfsmp
6925265Sfsmp#define DEFAULT_TOPOFMEM	0xa0000
7025265Sfsmp
7125265Sfsmp#define BIOS_BASE		0xf0000
7225265Sfsmp#define BIOS_BASE2		0xe0000
7325265Sfsmp#define BIOS_SIZE		0x10000
7425265Sfsmp#define ONE_KBYTE		1024
7525265Sfsmp
7625265Sfsmp#define GROPE_AREA1		0x80000
7725265Sfsmp#define GROPE_AREA2		0x90000
7825265Sfsmp#define GROPE_SIZE		0x10000
7925265Sfsmp
8025265Sfsmp#define PROCENTRY_FLAG_EN	0x01
8125265Sfsmp#define PROCENTRY_FLAG_BP	0x02
8225265Sfsmp#define IOAPICENTRY_FLAG_EN	0x01
8325265Sfsmp
8425265Sfsmp#define MAXPNSTR		132
8525265Sfsmp
8625265Sfsmpenum busTypes {
8725265Sfsmp    CBUS = 1,
8825265Sfsmp    CBUSII = 2,
8925265Sfsmp    EISA = 3,
9025265Sfsmp    ISA = 6,
9125265Sfsmp    PCI = 13,
9225265Sfsmp    XPRESS = 18,
9325265Sfsmp    MAX_BUSTYPE = 18,
9425265Sfsmp    UNKNOWN_BUSTYPE = 0xff
9525265Sfsmp};
9625265Sfsmp
9725265Sfsmptypedef struct BUSTYPENAME {
9825265Sfsmp    u_char	type;
9925265Sfsmp    char	name[ 7 ];
10025265Sfsmp} busTypeName;
10125265Sfsmp
10225265Sfsmpstatic busTypeName busTypeTable[] =
10325265Sfsmp{
10425265Sfsmp    { CBUS,		"CBUS"   },
10525265Sfsmp    { CBUSII,		"CBUSII" },
10625265Sfsmp    { EISA,		"EISA"   },
10725265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
10825265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
10925265Sfsmp    { ISA,		"ISA"    },
11025265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11125265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11225265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11325265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11425265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11525265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11625265Sfsmp    { PCI,		"PCI"    },
11725265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11825265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11925265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12025265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12125265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12225265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    }
12325265Sfsmp};
12425265Sfsmp
12525265Sfsmpchar* whereStrings[] = {
12625265Sfsmp    "Extended BIOS Data Area",
12725265Sfsmp    "BIOS top of memory",
12825265Sfsmp    "Default top of memory",
12925265Sfsmp    "BIOS",
13025265Sfsmp    "Extended BIOS",
13125265Sfsmp    "GROPE AREA #1",
13225265Sfsmp    "GROPE AREA #2"
13325265Sfsmp};
13425265Sfsmp
13525265Sfsmptypedef struct TABLE_ENTRY {
13625265Sfsmp    u_char	type;
13725265Sfsmp    u_char	length;
13825265Sfsmp    char	name[ 32 ];
13925265Sfsmp} tableEntry;
14025265Sfsmp
14125265SfsmptableEntry basetableEntryTypes[] =
14225265Sfsmp{
14325265Sfsmp    { 0, 20, "Processor" },
14425265Sfsmp    { 1,  8, "Bus" },
14525265Sfsmp    { 2,  8, "I/O APIC" },
14625265Sfsmp    { 3,  8, "I/O INT" },
14725265Sfsmp    { 4,  8, "Local INT" }
14825265Sfsmp};
14925265Sfsmp
15025265SfsmptableEntry extendedtableEntryTypes[] =
15125265Sfsmp{
15225265Sfsmp    { 128, 20, "System Address Space" },
15325265Sfsmp    { 129,  8, "Bus Heirarchy" },
15425265Sfsmp    { 130,  8, "Compatibility Bus Address" }
15525265Sfsmp};
15625265Sfsmp
15725265Sfsmp/* MP Floating Pointer Structure */
15825265Sfsmptypedef struct MPFPS {
15925265Sfsmp    char	signature[ 4 ];
16025265Sfsmp    void*	pap;
16125265Sfsmp    u_char	length;
16225265Sfsmp    u_char	spec_rev;
16325265Sfsmp    u_char	checksum;
16425265Sfsmp    u_char	mpfb1;
16525265Sfsmp    u_char	mpfb2;
16625265Sfsmp    u_char	mpfb3;
16725265Sfsmp    u_char	mpfb4;
16825265Sfsmp    u_char	mpfb5;
16925265Sfsmp} mpfps_t;
17025265Sfsmp
17125265Sfsmp/* MP Configuration Table Header */
17225265Sfsmptypedef struct MPCTH {
17325265Sfsmp    char	signature[ 4 ];
17425265Sfsmp    u_short	base_table_length;
17525265Sfsmp    u_char	spec_rev;
17625265Sfsmp    u_char	checksum;
17725265Sfsmp    u_char	oem_id[ 8 ];
17825265Sfsmp    u_char	product_id[ 12 ];
17925265Sfsmp    void*	oem_table_pointer;
18025265Sfsmp    u_short	oem_table_size;
18125265Sfsmp    u_short	entry_count;
18225265Sfsmp    void*	apic_address;
18325265Sfsmp    u_short	extended_table_length;
18425265Sfsmp    u_char	extended_table_checksum;
18525265Sfsmp    u_char	reserved;
18625265Sfsmp} mpcth_t;
18725265Sfsmp
18825265Sfsmp
18925265Sfsmptypedef struct PROCENTRY {
19025265Sfsmp    u_char	type;
19125265Sfsmp    u_char	apicID;
19225265Sfsmp    u_char	apicVersion;
19325265Sfsmp    u_char	cpuFlags;
19425265Sfsmp    u_long	cpuSignature;
19525265Sfsmp    u_long	featureFlags;
19625265Sfsmp    u_long	reserved1;
19725265Sfsmp    u_long	reserved2;
19825265Sfsmp} ProcEntry;
19925265Sfsmp
20025265Sfsmptypedef struct BUSENTRY {
20125265Sfsmp    u_char	type;
20225265Sfsmp    u_char	busID;
20325265Sfsmp    char	busType[ 6 ];
20425265Sfsmp} BusEntry;
20525265Sfsmp
20625265Sfsmptypedef struct IOAPICENTRY {
20725265Sfsmp    u_char	type;
20825265Sfsmp    u_char	apicID;
20925265Sfsmp    u_char	apicVersion;
21025265Sfsmp    u_char	apicFlags;
21125265Sfsmp    void*	apicAddress;
21225265Sfsmp} IOApicEntry;
21325265Sfsmp
21425265Sfsmptypedef struct INTENTRY {
21525265Sfsmp    u_char	type;
21625265Sfsmp    u_char	intType;
21725265Sfsmp    u_short	intFlags;
21825265Sfsmp    u_char	srcBusID;
21925265Sfsmp    u_char	srcBusIRQ;
22025265Sfsmp    u_char	dstApicID;
22125265Sfsmp    u_char	dstApicINT;
22225265Sfsmp} IntEntry;
22325265Sfsmp
22425265Sfsmp
22525265Sfsmp/*
22625265Sfsmp * extended entry type structures
22725265Sfsmp */
22825265Sfsmp
22925265Sfsmptypedef struct SASENTRY {
23025265Sfsmp    u_char	type;
23125265Sfsmp    u_char	length;
23225265Sfsmp    u_char	busID;
23325265Sfsmp    u_char	addressType;
23425265Sfsmp    u_int64_t	addressBase;
23525265Sfsmp    u_int64_t	addressLength;
23625265Sfsmp} SasEntry;
23725265Sfsmp
23825265Sfsmp
23925265Sfsmptypedef struct BHDENTRY {
24025265Sfsmp    u_char	type;
24125265Sfsmp    u_char	length;
24225265Sfsmp    u_char	busID;
24325265Sfsmp    u_char	busInfo;
24425265Sfsmp    u_char	busParent;
24525265Sfsmp    u_char	reserved[ 3 ];
24625265Sfsmp} BhdEntry;
24725265Sfsmp
24825265Sfsmp
24925265Sfsmptypedef struct CBASMENTRY {
25025265Sfsmp    u_char	type;
25125265Sfsmp    u_char	length;
25225265Sfsmp    u_char	busID;
25325265Sfsmp    u_char	addressMod;
25425265Sfsmp    u_int	predefinedRange;
25525265Sfsmp} CbasmEntry;
25625265Sfsmp
25725265Sfsmp
25825265Sfsmp
25925265Sfsmpstatic void apic_probe( vm_offset_t* paddr, int* where );
26025265Sfsmp
26125265Sfsmpstatic void MPConfigDefault( int featureByte );
26225265Sfsmp
26329850Scharnierstatic void MPFloatingPointer( vm_offset_t paddr, int where, mpfps_t* mpfps );
26425265Sfsmpstatic void MPConfigTableHeader( void* pap );
26525265Sfsmp
26625265Sfsmpstatic int readType( void );
26725265Sfsmpstatic void seekEntry( vm_offset_t addr );
26825265Sfsmpstatic void readEntry( void* entry, int size );
26925265Sfsmp
27025265Sfsmpstatic void processorEntry( void );
27125265Sfsmpstatic void busEntry( void );
27225265Sfsmpstatic void ioApicEntry( void );
27325265Sfsmpstatic void intEntry( void );
27425265Sfsmp
27525265Sfsmpstatic void sasEntry( void );
27625265Sfsmpstatic void bhdEntry( void );
27725265Sfsmpstatic void cbasmEntry( void );
27825265Sfsmp
27925265Sfsmpstatic void doOptionList( void );
28025265Sfsmpstatic void doDmesg( void );
28125265Sfsmpstatic void pnstr( char* s, int c );
28225265Sfsmp
28325265Sfsmp/* global data */
28425265Sfsmpint	pfd;		/* physical /dev/mem fd */
28525265Sfsmp
28625265Sfsmpint	busses[ 16 ];
28725265Sfsmpint	apics[ 16 ];
28825265Sfsmp
28925265Sfsmpint	ncpu;
29025265Sfsmpint	nbus;
29125265Sfsmpint	napic;
29225265Sfsmpint	nintr;
29325265Sfsmp
29425265Sfsmpint	dmesg;
29525265Sfsmpint	grope;
29625265Sfsmpint	verbose;
29725265Sfsmp
29825265Sfsmpstatic void
29925265Sfsmpusage( void )
30025265Sfsmp{
30129850Scharnier    fprintf( stderr, "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n" );
30225265Sfsmp    exit( 0 );
30325265Sfsmp}
30425265Sfsmp
30525265Sfsmp/*
30625265Sfsmp *
30725265Sfsmp */
30825265Sfsmpint
30925265Sfsmpmain( int argc, char *argv[] )
31025265Sfsmp{
31125265Sfsmp    vm_offset_t	paddr;
31225265Sfsmp    int		where;
31325265Sfsmp    mpfps_t	mpfps;
31425265Sfsmp    int		defaultConfig;
31525265Sfsmp
31629850Scharnier    extern int	optreset;
31725265Sfsmp    int		ch;
31825265Sfsmp
31925265Sfsmp    /* announce ourselves */
32025265Sfsmp    puts( SEP_LINE2 );
32125265Sfsmp
32225265Sfsmp    printf( "MPTable, version %d.%d.%d\n", VMAJOR, VMINOR, VDELTA );
32325265Sfsmp
32425265Sfsmp    while ((ch = getopt(argc, argv, "d:g:h:v:")) != EOF) {
32525265Sfsmp	switch(ch) {
32625265Sfsmp	case 'd':
32725265Sfsmp	    if ( strcmp( optarg, "mesg") == 0 )
32825265Sfsmp	        dmesg = 1;
32925265Sfsmp	    else
33025265Sfsmp	        dmesg = 0;
33125265Sfsmp	    break;
33225265Sfsmp	case 'h':
33325265Sfsmp	    if ( strcmp( optarg, "elp") == 0 )
33425265Sfsmp	        usage();
33525265Sfsmp	    break;
33625265Sfsmp	case 'g':
33725326Sfsmp	    if ( strcmp( optarg, "rope") == 0 )
33825265Sfsmp	        grope = 1;
33925265Sfsmp	    break;
34025265Sfsmp	case 'v':
34125265Sfsmp	    if ( strcmp( optarg, "erbose") == 0 )
34225265Sfsmp	        verbose = 1;
34325265Sfsmp	    break;
34425265Sfsmp	default:
34525265Sfsmp	    usage();
34625265Sfsmp	}
34725265Sfsmp	argc -= optind;
34825265Sfsmp	argv += optind;
34925265Sfsmp	optreset = 1;
35025265Sfsmp	optind = 0;
35125265Sfsmp    }
35225265Sfsmp
35325265Sfsmp    /* open physical memory for access to MP structures */
35429850Scharnier    if ( (pfd = open( "/dev/mem", O_RDONLY )) < 0 )
35529850Scharnier        err( 1, "mem open" );
35625265Sfsmp
35725265Sfsmp    /* probe for MP structures */
35825265Sfsmp    apic_probe( &paddr, &where );
35925265Sfsmp    if ( where <= 0 ) {
36025265Sfsmp        fprintf( stderr, "\n MP FPS NOT found,\n" );
36125265Sfsmp        fprintf( stderr, " suggest trying -grope option!!!\n\n" );
36225265Sfsmp        return 1;
36325265Sfsmp    }
36425265Sfsmp
36525265Sfsmp    if ( verbose )
36625265Sfsmp        printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n",
36725265Sfsmp	      whereStrings[ where - 1 ], paddr );
36825265Sfsmp
36925265Sfsmp    puts( SEP_LINE );
37025265Sfsmp
37125265Sfsmp    /* analyze the MP Floating Pointer Structure */
37225265Sfsmp    MPFloatingPointer( paddr, where, &mpfps );
37325265Sfsmp
37425265Sfsmp    puts( SEP_LINE );
37525265Sfsmp
37625265Sfsmp    /* check whether an MP config table exists */
37729850Scharnier    if ( (defaultConfig = mpfps.mpfb1) )
37825265Sfsmp        MPConfigDefault( defaultConfig );
37925265Sfsmp    else
38025265Sfsmp	MPConfigTableHeader( mpfps.pap );
38125265Sfsmp
38225265Sfsmp    /* build "options" entries for the kernel config file */
38325265Sfsmp    doOptionList();
38425265Sfsmp
38525265Sfsmp    /* do a dmesg output */
38625265Sfsmp    if ( dmesg )
38725265Sfsmp        doDmesg();
38825265Sfsmp
38925265Sfsmp    puts( SEP_LINE2 );
39025265Sfsmp
39125265Sfsmp    return 0;
39225265Sfsmp}
39325265Sfsmp
39425265Sfsmp
39525265Sfsmp/*
39625265Sfsmp * set PHYSICAL address of MP floating pointer structure
39725265Sfsmp */
39825265Sfsmp#define NEXT(X)		((X) += 4)
39925265Sfsmpstatic void
40025265Sfsmpapic_probe( vm_offset_t* paddr, int* where )
40125265Sfsmp{
40225265Sfsmp    /*
40325265Sfsmp     * c rewrite of apic_probe() by Jack F. Vogel
40425265Sfsmp     */
40525265Sfsmp
40625265Sfsmp    int		x;
40725265Sfsmp    u_short	segment;
40825265Sfsmp    vm_offset_t	target;
40925265Sfsmp    u_int	buffer[ BIOS_SIZE / sizeof( int ) ];
41025265Sfsmp
41125265Sfsmp    if ( verbose )
41225265Sfsmp        printf( "\n" );
41325265Sfsmp
41425265Sfsmp    /* search Extended Bios Data Area, if present */
41525265Sfsmp    if ( verbose )
41625265Sfsmp        printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER );
41725265Sfsmp    seekEntry( (vm_offset_t)EBDA_POINTER );
41825265Sfsmp    readEntry( &segment, 2 );
41925265Sfsmp    if ( segment ) {		    /* search EBDA */
42025265Sfsmp        target = (vm_offset_t)segment << 4;
42125265Sfsmp	if ( verbose )
42225265Sfsmp	    printf( "found, searching EBDA @ 0x%08x\n", target );
42325265Sfsmp        seekEntry( target );
42425265Sfsmp        readEntry( buffer, ONE_KBYTE );
42525265Sfsmp
42625265Sfsmp        for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) {
42725265Sfsmp            if ( buffer[ x ] == MP_SIG ) {
42825265Sfsmp                *where = 1;
42925265Sfsmp                *paddr = (x * sizeof( unsigned int )) + target;
43025265Sfsmp                return;
43125265Sfsmp            }
43225265Sfsmp        }
43325265Sfsmp    }
43425265Sfsmp    else {
43525265Sfsmp	if ( verbose )
43625265Sfsmp	    printf( "NOT found\n" );
43725265Sfsmp    }
43825265Sfsmp
43925265Sfsmp    /* read CMOS for real top of mem */
44025265Sfsmp    seekEntry( (vm_offset_t)TOPOFMEM_POINTER );
44125265Sfsmp    readEntry( &segment, 2 );
44225265Sfsmp    --segment;						/* less ONE_KBYTE */
44325265Sfsmp    target = segment * 1024;
44425265Sfsmp    if ( verbose )
44525265Sfsmp        printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n",
44625265Sfsmp	        target, segment );
44725265Sfsmp    seekEntry( target );
44825265Sfsmp    readEntry( buffer, ONE_KBYTE );
44925265Sfsmp
45025265Sfsmp    for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) {
45125265Sfsmp        if ( buffer[ x ] == MP_SIG ) {
45225265Sfsmp            *where = 2;
45325265Sfsmp            *paddr = (x * sizeof( unsigned int )) + target;
45425265Sfsmp            return;
45525265Sfsmp        }
45625265Sfsmp    }
45725265Sfsmp
45825265Sfsmp    /* we don't necessarily believe CMOS, check base of the last 1K of 640K */
45925265Sfsmp    if ( target != (DEFAULT_TOPOFMEM - 1024)) {
46025265Sfsmp	target = (DEFAULT_TOPOFMEM - 1024);
46125265Sfsmp	if ( verbose )
46225265Sfsmp	    printf( " searching default 'top of mem' @ 0x%08x (%dK)\n",
46325265Sfsmp		    target, (target / 1024) );
46425265Sfsmp	seekEntry( target );
46525265Sfsmp	readEntry( buffer, ONE_KBYTE );
46625265Sfsmp
46725265Sfsmp	for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) {
46825265Sfsmp	    if ( buffer[ x ] == MP_SIG ) {
46925265Sfsmp		*where = 3;
47025265Sfsmp		*paddr = (x * sizeof( unsigned int )) + target;
47125265Sfsmp		return;
47225265Sfsmp	    }
47325265Sfsmp	}
47425265Sfsmp    }
47525265Sfsmp
47625265Sfsmp    /* search the BIOS */
47725265Sfsmp    if ( verbose )
47825265Sfsmp        printf( " searching BIOS @ 0x%08x\n", BIOS_BASE );
47925265Sfsmp    seekEntry( BIOS_BASE );
48025265Sfsmp    readEntry( buffer, BIOS_SIZE );
48125265Sfsmp
48225265Sfsmp    for ( x = 0; x < BIOS_SIZE / sizeof( unsigned int ); NEXT(x) ) {
48325265Sfsmp        if ( buffer[ x ] == MP_SIG ) {
48425265Sfsmp            *where = 4;
48525265Sfsmp            *paddr = (x * sizeof( unsigned int )) + BIOS_BASE;
48625265Sfsmp            return;
48725265Sfsmp        }
48825265Sfsmp    }
48925265Sfsmp
49025265Sfsmp    /* search the extended BIOS */
49125265Sfsmp    if ( verbose )
49225265Sfsmp        printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 );
49325265Sfsmp    seekEntry( BIOS_BASE2 );
49425265Sfsmp    readEntry( buffer, BIOS_SIZE );
49525265Sfsmp
49625265Sfsmp    for ( x = 0; x < BIOS_SIZE / sizeof( unsigned int ); NEXT(x) ) {
49725265Sfsmp        if ( buffer[ x ] == MP_SIG ) {
49825265Sfsmp            *where = 5;
49925265Sfsmp            *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2;
50025265Sfsmp            return;
50125265Sfsmp        }
50225265Sfsmp    }
50325265Sfsmp
50425265Sfsmp    if ( grope ) {
50525265Sfsmp	/* search additional memory */
50625265Sfsmp	target = GROPE_AREA1;
50725265Sfsmp	if ( verbose )
50825265Sfsmp	    printf( " groping memory @ 0x%08x\n", target );
50925265Sfsmp	seekEntry( target );
51025265Sfsmp	readEntry( buffer, GROPE_SIZE );
51125265Sfsmp
51225265Sfsmp	for ( x = 0; x < GROPE_SIZE / sizeof( unsigned int ); NEXT(x) ) {
51325265Sfsmp	    if ( buffer[ x ] == MP_SIG ) {
51425265Sfsmp		*where = 6;
51525265Sfsmp		*paddr = (x * sizeof( unsigned int )) + GROPE_AREA1;
51625265Sfsmp		return;
51725265Sfsmp	    }
51825265Sfsmp	}
51925265Sfsmp
52025265Sfsmp	target = GROPE_AREA2;
52125265Sfsmp	if ( verbose )
52225265Sfsmp	    printf( " groping memory @ 0x%08x\n", target );
52325265Sfsmp	seekEntry( target );
52425265Sfsmp	readEntry( buffer, GROPE_SIZE );
52525265Sfsmp
52625265Sfsmp	for ( x = 0; x < GROPE_SIZE / sizeof( unsigned int ); NEXT(x) ) {
52725265Sfsmp	    if ( buffer[ x ] == MP_SIG ) {
52825265Sfsmp		*where = 7;
52925265Sfsmp		*paddr = (x * sizeof( unsigned int )) + GROPE_AREA2;
53025265Sfsmp		return;
53125265Sfsmp	    }
53225265Sfsmp	}
53325265Sfsmp    }
53425265Sfsmp
53525265Sfsmp    *where = 0;
53625265Sfsmp    *paddr = (vm_offset_t)0;
53725265Sfsmp}
53825265Sfsmp
53925265Sfsmp
54025265Sfsmp/*
54125265Sfsmp *
54225265Sfsmp */
54329850Scharnierstatic void
54425265SfsmpMPFloatingPointer( vm_offset_t paddr, int where, mpfps_t* mpfps )
54525265Sfsmp{
54625265Sfsmp
54725265Sfsmp    /* read in mpfps structure*/
54825265Sfsmp    seekEntry( paddr );
54925265Sfsmp    readEntry( mpfps, sizeof( mpfps_t ) );
55025265Sfsmp
55125265Sfsmp    /* show its contents */
55225265Sfsmp    printf( "MP Floating Pointer Structure:\n\n" );
55325265Sfsmp
55429850Scharnier    printf( "  location:\t\t\t" );
55525265Sfsmp    switch ( where )
55625265Sfsmp    {
55725265Sfsmp    case 1:
55825265Sfsmp	printf( "EBDA\n" );
55925265Sfsmp	break;
56025265Sfsmp    case 2:
56125265Sfsmp	printf( "BIOS base memory\n" );
56225265Sfsmp	break;
56325265Sfsmp    case 3:
56425265Sfsmp	printf( "DEFAULT base memory (639K)\n" );
56525265Sfsmp	break;
56625265Sfsmp    case 4:
56725265Sfsmp	printf( "BIOS\n" );
56825265Sfsmp	break;
56925265Sfsmp    case 5:
57025265Sfsmp	printf( "Extended BIOS\n" );
57125265Sfsmp	break;
57225265Sfsmp
57325265Sfsmp    case 0:
57425265Sfsmp	printf( "NOT found!\n" );
57525265Sfsmp	exit( 1 );
57625265Sfsmp    default:
57725265Sfsmp	printf( "BOGUS!\n" );
57825265Sfsmp	exit( 1 );
57925265Sfsmp    }
58025265Sfsmp    printf( "  physical address:\t\t0x%08x\n", paddr );
58125265Sfsmp
58225265Sfsmp    printf( "  signature:\t\t\t'" );
58325265Sfsmp    pnstr( mpfps->signature, 4 );
58425265Sfsmp    printf( "'\n" );
58525265Sfsmp
58625265Sfsmp    printf( "  length:\t\t\t%d bytes\n", mpfps->length * 16 );
58725265Sfsmp    printf( "  version:\t\t\t1.%1d\n", mpfps->spec_rev );
58825265Sfsmp    printf( "  checksum:\t\t\t0x%02x\n", mpfps->checksum );
58925265Sfsmp
59025265Sfsmp    /* bits 0:6 are RESERVED */
59125265Sfsmp    if ( mpfps->mpfb2 & 0x7f ) {
59229850Scharnier        printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 );
59325265Sfsmp    }
59425265Sfsmp
59525265Sfsmp    /* bit 7 is IMCRP */
59625265Sfsmp    printf( "  mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ?
59725265Sfsmp            "PIC" : "Virtual Wire" );
59825265Sfsmp
59925265Sfsmp    /* MP feature bytes 3-5 are expected to be ZERO */
60025265Sfsmp    if ( mpfps->mpfb3 )
60125265Sfsmp        printf( " warning, MP feature byte 3 NONZERO!\n" );
60225265Sfsmp    if ( mpfps->mpfb4 )
60325265Sfsmp        printf( " warning, MP feature byte 4 NONZERO!\n" );
60425265Sfsmp    if ( mpfps->mpfb5 )
60525265Sfsmp        printf( " warning, MP feature byte 5 NONZERO!\n" );
60625265Sfsmp}
60725265Sfsmp
60825265Sfsmp
60925265Sfsmp/*
61025265Sfsmp *
61125265Sfsmp */
61225265Sfsmpstatic void
61325265SfsmpMPConfigDefault( int featureByte )
61425265Sfsmp{
61525265Sfsmp    printf( "  MP default config type: %d\n\n", featureByte );
61625265Sfsmp    switch ( featureByte ) {
61725265Sfsmp    case 1:
61825265Sfsmp	printf( "   bus: ISA, APIC: 82489DX\n" );
61925265Sfsmp	break;
62025265Sfsmp    case 2:
62125265Sfsmp	printf( "   bus: EISA, APIC: 82489DX\n" );
62225265Sfsmp	break;
62325265Sfsmp    case 3:
62425265Sfsmp	printf( "   bus: EISA, APIC: 82489DX\n" );
62525265Sfsmp	break;
62625265Sfsmp    case 4:
62725265Sfsmp	printf( "   bus: MCA, APIC: 82489DX\n" );
62825265Sfsmp	break;
62925265Sfsmp    case 5:
63025265Sfsmp	printf( "   bus: ISA+PCI, APIC: Integrated\n" );
63125265Sfsmp	break;
63225265Sfsmp    case 6:
63325265Sfsmp	printf( "   bus: EISA+PCI, APIC: Integrated\n" );
63425265Sfsmp	break;
63525265Sfsmp    case 7:
63625265Sfsmp	printf( "   bus: MCA+PCI, APIC: Integrated\n" );
63725265Sfsmp	break;
63825265Sfsmp    default:
63925265Sfsmp	printf( "   future type\n" );
64025265Sfsmp	break;
64125265Sfsmp    }
64225265Sfsmp
64325265Sfsmp    switch ( featureByte ) {
64425265Sfsmp    case 1:
64525265Sfsmp    case 2:
64625265Sfsmp    case 3:
64725265Sfsmp    case 4:
64825265Sfsmp	nbus = 1;
64925265Sfsmp	break;
65025265Sfsmp    case 5:
65125265Sfsmp    case 6:
65225265Sfsmp    case 7:
65325265Sfsmp	nbus = 2;
65425265Sfsmp	break;
65525265Sfsmp    default:
65625265Sfsmp	printf( "   future type\n" );
65725265Sfsmp	break;
65825265Sfsmp    }
65925265Sfsmp
66025265Sfsmp    ncpu = 2;
66125265Sfsmp    napic = 1;
66225265Sfsmp    nintr = 16;
66325265Sfsmp}
66425265Sfsmp
66525265Sfsmp
66625265Sfsmp/*
66725265Sfsmp *
66825265Sfsmp */
66925265Sfsmpstatic void
67025265SfsmpMPConfigTableHeader( void* pap )
67125265Sfsmp{
67225265Sfsmp    vm_offset_t paddr;
67325265Sfsmp    mpcth_t	cth;
67429850Scharnier    int		x;
67525265Sfsmp    int		totalSize, t;
67625265Sfsmp    int		count, c;
67725265Sfsmp    int		type;
67825265Sfsmp
67925265Sfsmp    if ( pap == 0 ) {
68025265Sfsmp	printf( "MP Configuration Table Header MISSING!\n" );
68125265Sfsmp        exit( 1 );
68225265Sfsmp    }
68325265Sfsmp
68425265Sfsmp    /* convert physical address to virtual address */
68525265Sfsmp    paddr = (vm_offset_t)pap;
68625265Sfsmp
68725265Sfsmp    /* read in cth structure */
68825265Sfsmp    seekEntry( paddr );
68925265Sfsmp    readEntry( &cth, sizeof( cth ) );
69025265Sfsmp
69125265Sfsmp    printf( "MP Config Table Header:\n\n" );
69225265Sfsmp
69325265Sfsmp    printf( "  physical address:\t\t0x%08x\n", pap );
69425265Sfsmp
69525265Sfsmp    printf( "  signature:\t\t\t'" );
69625265Sfsmp    pnstr( cth.signature, 4 );
69725265Sfsmp    printf( "'\n" );
69825265Sfsmp
69925265Sfsmp    printf( "  base table length:\t\t%d\n", cth.base_table_length );
70025265Sfsmp
70125265Sfsmp    printf( "  version:\t\t\t1.%1d\n", cth.spec_rev );
70225265Sfsmp    printf( "  checksum:\t\t\t0x%02x\n", cth.checksum );
70325265Sfsmp
70425265Sfsmp    printf( "  OEM ID:\t\t\t'" );
70525265Sfsmp    pnstr( cth.oem_id, 8 );
70625265Sfsmp    printf( "'\n" );
70725265Sfsmp
70825265Sfsmp    printf( "  Product ID:\t\t\t'" );
70925265Sfsmp    pnstr( cth.product_id, 12 );
71025265Sfsmp    printf( "'\n" );
71125265Sfsmp
71225265Sfsmp    printf( "  OEM table pointer:\t\t0x%08x\n", cth.oem_table_pointer );
71325265Sfsmp    printf( "  OEM table size:\t\t%d\n", cth.oem_table_size );
71425265Sfsmp
71525265Sfsmp    printf( "  entry count:\t\t\t%d\n", cth.entry_count );
71625265Sfsmp
71725265Sfsmp    printf( "  local APIC address:\t\t0x%08x\n", cth.apic_address );
71825265Sfsmp
71925265Sfsmp    printf( "  extended table length:\t%d\n", cth.extended_table_length );
72025265Sfsmp    printf( "  extended table checksum:\t%d\n", cth.extended_table_checksum );
72125265Sfsmp
72225265Sfsmp    totalSize = cth.base_table_length - sizeof( struct MPCTH );
72325265Sfsmp    count = cth.entry_count;
72425265Sfsmp
72525265Sfsmp    puts( SEP_LINE );
72625265Sfsmp
72725265Sfsmp    printf( "MP Config Base Table Entries:\n\n" );
72825265Sfsmp
72925265Sfsmp    /* initialze tables */
73025265Sfsmp    for ( x = 0; x < 16; ++x ) {
73125265Sfsmp	busses[ x ] = apics[ x ] = 0xff;
73225265Sfsmp    }
73325265Sfsmp
73425265Sfsmp    ncpu = 0;
73525265Sfsmp    nbus = 0;
73625265Sfsmp    napic = 0;
73725265Sfsmp    nintr = 0;
73825265Sfsmp
73925265Sfsmp    /* process all the CPUs */
74025265Sfsmp    printf( "--\nProcessors:\tAPIC ID\tVersion\tState"
74125265Sfsmp	    "\t\tFamily\tModel\tStep\tFlags\n" );
74225265Sfsmp    for ( t = totalSize, c = count; c; c-- ) {
74325265Sfsmp	if ( readType() == 0 )
74425265Sfsmp	    processorEntry();
74525265Sfsmp        totalSize -= basetableEntryTypes[ 0 ].length;
74625265Sfsmp    }
74725265Sfsmp
74825265Sfsmp    /* process all the busses */
74925265Sfsmp    printf( "--\nBus:\t\tBus ID\tType\n" );
75025265Sfsmp    for ( t = totalSize, c = count; c; c-- ) {
75125265Sfsmp	if ( readType() == 1 )
75225265Sfsmp	    busEntry();
75325265Sfsmp        totalSize -= basetableEntryTypes[ 1 ].length;
75425265Sfsmp    }
75525265Sfsmp
75625265Sfsmp    /* process all the apics */
75725265Sfsmp    printf( "--\nI/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" );
75825265Sfsmp    for ( t = totalSize, c = count; c; c-- ) {
75925265Sfsmp	if ( readType() == 2 )
76025265Sfsmp	    ioApicEntry();
76125265Sfsmp        totalSize -= basetableEntryTypes[ 2 ].length;
76225265Sfsmp    }
76325265Sfsmp
76425265Sfsmp    /* process all the I/O Ints */
76529161Sfsmp    printf( "--\nI/O Ints:\tType\tPolarity    Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
76625265Sfsmp    for ( t = totalSize, c = count; c; c-- ) {
76725265Sfsmp	if ( readType() == 3 )
76825265Sfsmp	    intEntry();
76925265Sfsmp        totalSize -= basetableEntryTypes[ 3 ].length;
77025265Sfsmp    }
77125265Sfsmp
77225265Sfsmp    /* process all the Local Ints */
77329161Sfsmp    printf( "--\nLocal Ints:\tType\tPolarity    Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
77425265Sfsmp    for ( t = totalSize, c = count; c; c-- ) {
77525265Sfsmp	if ( readType() == 4 )
77625265Sfsmp	    intEntry();
77725265Sfsmp        totalSize -= basetableEntryTypes[ 4 ].length;
77825265Sfsmp    }
77925265Sfsmp
78025265Sfsmp
78125265Sfsmp#if defined( EXTENDED_PROCESSING_READY )
78225265Sfsmp    /* process any extended data */
78329850Scharnier    if ( (totalSize = cth.extended_table_length) ) {
78425265Sfsmp	puts( SEP_LINE );
78525265Sfsmp
78625265Sfsmp        printf( "MP Config Extended Table Entries:\n\n" );
78725265Sfsmp
78825265Sfsmp        while ( totalSize > 0 ) {
78925265Sfsmp            switch ( type = readType() ) {
79025265Sfsmp            case 128:
79125265Sfsmp		sasEntry();
79225265Sfsmp		break;
79325265Sfsmp            case 129:
79425265Sfsmp		bhdEntry();
79525265Sfsmp		break;
79625265Sfsmp            case 130:
79725265Sfsmp		cbasmEntry();
79825265Sfsmp		break;
79925265Sfsmp            default:
80025265Sfsmp                printf( "Extended Table HOSED!\n" );
80125265Sfsmp                exit( 1 );
80225265Sfsmp            }
80325265Sfsmp
80425265Sfsmp            totalSize -= extendedtableEntryTypes[ type-128 ].length;
80525265Sfsmp        }
80625265Sfsmp    }
80725265Sfsmp#endif  /* EXTENDED_PROCESSING_READY */
80825265Sfsmp
80925265Sfsmp    /* process any OEM data */
81025265Sfsmp    if ( cth.oem_table_pointer && (cth.oem_table_size > 0) ) {
81125265Sfsmp#if defined( OEM_PROCESSING_READY )
81225265Sfsmp# error your on your own here!
81325265Sfsmp        /* convert OEM table pointer to virtual address */
81425265Sfsmp        poemtp = (vm_offset_t)cth.oem_table_pointer;
81525265Sfsmp
81625265Sfsmp        /* read in oem table structure */
81729850Scharnier        if ( (oemdata = (void*)malloc( cth.oem_table_size )) == NULL )
81829850Scharnier            err( 1, "oem malloc" );
81925265Sfsmp
82025265Sfsmp        seekEntry( poemtp );
82125265Sfsmp        readEntry( oemdata, cth.oem_table_size );
82225265Sfsmp
82325265Sfsmp        /** process it */
82425265Sfsmp
82525265Sfsmp        free( oemdata );
82625265Sfsmp#else
82725265Sfsmp        printf( "\nyou need to modify the source to handle OEM data!\n\n" );
82825265Sfsmp#endif  /* OEM_PROCESSING_READY */
82925265Sfsmp    }
83025265Sfsmp
83125265Sfsmp    fflush( stdout );
83225265Sfsmp
83325265Sfsmp#if defined( RAW_DUMP )
83425265Sfsmp{
83525265Sfsmp    int		ofd;
83625265Sfsmp    u_char	dumpbuf[ 4096 ];
83725265Sfsmp
83825265Sfsmp    ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR );
83925265Sfsmp    seekEntry( paddr );
84025265Sfsmp    readEntry( dumpbuf, 1024 );
84125265Sfsmp    write( ofd, dumpbuf, 1024 );
84225265Sfsmp    close( ofd );
84325265Sfsmp}
84425265Sfsmp#endif /* RAW_DUMP */
84525265Sfsmp}
84625265Sfsmp
84725265Sfsmp
84825265Sfsmp/*
84925265Sfsmp *
85025265Sfsmp */
85125265Sfsmpstatic int
85225265SfsmpreadType( void )
85325265Sfsmp{
85425265Sfsmp    u_char	type;
85525265Sfsmp
85629850Scharnier    if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) )
85729850Scharnier        err( 1, "type read; pfd: %d", pfd );
85825265Sfsmp
85929850Scharnier    if ( lseek( pfd, -1, SEEK_CUR ) < 0 )
86029850Scharnier        err( 1, "type seek" );
86125265Sfsmp
86225265Sfsmp    return (int)type;
86325265Sfsmp}
86425265Sfsmp
86525265Sfsmp
86625265Sfsmp/*
86725265Sfsmp *
86825265Sfsmp */
86925265Sfsmpstatic void
87025265SfsmpseekEntry( vm_offset_t addr )
87125265Sfsmp{
87229850Scharnier    if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 )
87329850Scharnier        err( 1, "/dev/mem seek" );
87425265Sfsmp}
87525265Sfsmp
87625265Sfsmp
87725265Sfsmp/*
87825265Sfsmp *
87925265Sfsmp */
88025265Sfsmpstatic void
88125265SfsmpreadEntry( void* entry, int size )
88225265Sfsmp{
88329850Scharnier    if ( read( pfd, entry, size ) != size )
88429850Scharnier        err( 1, "readEntry" );
88525265Sfsmp}
88625265Sfsmp
88725265Sfsmp
88825265Sfsmpstatic void
88925265SfsmpprocessorEntry( void )
89025265Sfsmp{
89125265Sfsmp    ProcEntry	entry;
89225265Sfsmp
89325265Sfsmp    /* read it into local memory */
89425265Sfsmp    readEntry( &entry, sizeof( entry ) );
89525265Sfsmp
89625265Sfsmp    /* count it */
89725265Sfsmp    ++ncpu;
89825265Sfsmp
89925265Sfsmp    printf( "\t\t%2d", entry.apicID );
90025265Sfsmp    printf( "\t 0x%2x", entry.apicVersion );
90125265Sfsmp
90225265Sfsmp    printf( "\t %s, %s",
90325265Sfsmp            (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
90425265Sfsmp            (entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" );
90525265Sfsmp
90625265Sfsmp    printf( "\t %d\t %d\t %d",
90725265Sfsmp            (entry.cpuSignature >> 8) & 0x0f,
90825265Sfsmp            (entry.cpuSignature >> 4) & 0x0f,
90925265Sfsmp            entry.cpuSignature & 0x0f );
91025265Sfsmp
91125265Sfsmp    printf( "\t 0x%04x\n", entry.featureFlags );
91225265Sfsmp}
91325265Sfsmp
91425265Sfsmp
91525265Sfsmp/*
91625265Sfsmp *
91725265Sfsmp */
91825265Sfsmpstatic int
91925265SfsmplookupBusType( char* name )
92025265Sfsmp{
92125265Sfsmp    int x;
92225265Sfsmp
92325265Sfsmp    for ( x = 0; x < MAX_BUSTYPE; ++x )
92425265Sfsmp	if ( strcmp( busTypeTable[ x ].name, name ) == 0 )
92525265Sfsmp	    return busTypeTable[ x ].type;
92625265Sfsmp
92725265Sfsmp    return UNKNOWN_BUSTYPE;
92825265Sfsmp}
92925265Sfsmp
93025265Sfsmp
93125265Sfsmpstatic void
93225265SfsmpbusEntry( void )
93325265Sfsmp{
93425265Sfsmp    int		x;
93525265Sfsmp    char	name[ 8 ];
93625265Sfsmp    char	c;
93725265Sfsmp    BusEntry	entry;
93825265Sfsmp
93925265Sfsmp    /* read it into local memory */
94025265Sfsmp    readEntry( &entry, sizeof( entry ) );
94125265Sfsmp
94225265Sfsmp    /* count it */
94325265Sfsmp    ++nbus;
94425265Sfsmp
94525265Sfsmp    printf( "\t\t%2d", entry.busID );
94625265Sfsmp    printf( "\t " ); pnstr( entry.busType, 6 ); printf( "\n" );
94725265Sfsmp
94825265Sfsmp    for ( x = 0; x < 6; ++x ) {
94925265Sfsmp	if ( (c = entry.busType[ x ]) == ' ' )
95025265Sfsmp	    break;
95125265Sfsmp	name[ x ] = c;
95225265Sfsmp    }
95325265Sfsmp    name[ x ] = '\0';
95425265Sfsmp    busses[ entry.busID ] = lookupBusType( name );
95525265Sfsmp}
95625265Sfsmp
95725265Sfsmp
95825265Sfsmpstatic void
95925265SfsmpioApicEntry( void )
96025265Sfsmp{
96125265Sfsmp    IOApicEntry	entry;
96225265Sfsmp
96325265Sfsmp    /* read it into local memory */
96425265Sfsmp    readEntry( &entry, sizeof( entry ) );
96525265Sfsmp
96625265Sfsmp    /* count it */
96725265Sfsmp    ++napic;
96825265Sfsmp
96925265Sfsmp    printf( "\t\t%2d", entry.apicID );
97025265Sfsmp    printf( "\t 0x%02x", entry.apicVersion );
97125265Sfsmp    printf( "\t %s",
97225265Sfsmp            (entry.apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" );
97325265Sfsmp    printf( "\t\t 0x%x\n", entry.apicAddress );
97425265Sfsmp
97525265Sfsmp    apics[ entry.apicID ] = entry.apicID;
97625265Sfsmp}
97725265Sfsmp
97825265Sfsmp
97925265Sfsmpchar* intTypes[] = {
98025265Sfsmp    "INT", "NMI", "SMI", "ExtINT"
98125265Sfsmp};
98225265Sfsmp
98325265Sfsmpchar* polarityMode[] = {
98425265Sfsmp    "conforms", "active-hi", "reserved", "active-lo"
98525265Sfsmp};
98625265Sfsmpchar* triggerMode[] = {
98725265Sfsmp    "conforms", "edge", "reserved", "level"
98825265Sfsmp};
98925265Sfsmp
99025265Sfsmpstatic void
99125265SfsmpintEntry( void )
99225265Sfsmp{
99325265Sfsmp    IntEntry	entry;
99425265Sfsmp
99525265Sfsmp    /* read it into local memory */
99625265Sfsmp    readEntry( &entry, sizeof( entry ) );
99725265Sfsmp
99825265Sfsmp    /* count it */
99925265Sfsmp    if ( (int)entry.type == 3 )
100025265Sfsmp	++nintr;
100125265Sfsmp
100225265Sfsmp    printf( "\t\t%s", intTypes[ (int)entry.intType ] );
100325265Sfsmp
100425265Sfsmp    printf( "\t%9s", polarityMode[ (int)entry.intFlags & 0x03 ] );
100525265Sfsmp    printf( "%12s", triggerMode[ ((int)entry.intFlags >> 2) & 0x03 ] );
100625265Sfsmp
100725265Sfsmp    printf( "\t %5d", (int)entry.srcBusID );
100825265Sfsmp    if ( busses[ (int)entry.srcBusID ] == PCI )
100925265Sfsmp	printf( "\t%2d:%c",
101025265Sfsmp	        ((int)entry.srcBusIRQ >> 2) & 0x1f,
101125265Sfsmp	        ((int)entry.srcBusIRQ & 0x03) + 'A' );
101225265Sfsmp    else
101325265Sfsmp	printf( "\t %3d", (int)entry.srcBusIRQ );
101425265Sfsmp    printf( "\t %6d", (int)entry.dstApicID );
101525265Sfsmp    printf( "\t %3d\n", (int)entry.dstApicINT );
101625265Sfsmp}
101725265Sfsmp
101825265Sfsmp
101925265Sfsmpstatic void
102025265SfsmpsasEntry( void )
102125265Sfsmp{
102225265Sfsmp    SasEntry	entry;
102325265Sfsmp
102425265Sfsmp    /* read it into local memory */
102525265Sfsmp    readEntry( &entry, sizeof( entry ) );
102625265Sfsmp
102725265Sfsmp    printf( "--\n%s\n", extendedtableEntryTypes[ entry.type ].name );
102825265Sfsmp    printf( " bus ID: %d", entry.busID );
102925265Sfsmp    printf( " address type: " );
103025265Sfsmp    switch ( entry.addressType ) {
103125265Sfsmp    case 0:
103225265Sfsmp	printf( "I/O address\n" );
103325265Sfsmp	break;
103425265Sfsmp    case 1:
103525265Sfsmp	printf( "memory address\n" );
103625265Sfsmp	break;
103725265Sfsmp    case 2:
103825265Sfsmp	printf( "prefetch address\n" );
103925265Sfsmp	break;
104025265Sfsmp    default:
104125265Sfsmp	printf( "UNKNOWN type\n" );
104225265Sfsmp	break;
104325265Sfsmp    }
104425265Sfsmp
104525265Sfsmp    printf( " address base: 0x%qx\n", entry.addressBase );
104625265Sfsmp    printf( " address range: 0x%qx\n", entry.addressLength );
104725265Sfsmp}
104825265Sfsmp
104925265Sfsmp
105025265Sfsmpstatic void
105125265SfsmpbhdEntry( void )
105225265Sfsmp{
105325265Sfsmp    BhdEntry	entry;
105425265Sfsmp
105525265Sfsmp    /* read it into local memory */
105625265Sfsmp    readEntry( &entry, sizeof( entry ) );
105725265Sfsmp
105825265Sfsmp    printf( "--\n%s\n", extendedtableEntryTypes[ entry.type ].name );
105925265Sfsmp    printf( " bus ID: %d", entry.busID );
106025265Sfsmp    printf( " bus info: 0x%02x", entry.busInfo );
106125265Sfsmp    printf( " parent bus ID: %d", entry.busParent );
106225265Sfsmp}
106325265Sfsmp
106425265Sfsmp
106525265Sfsmpstatic void
106625265SfsmpcbasmEntry( void )
106725265Sfsmp{
106825265Sfsmp    CbasmEntry	entry;
106925265Sfsmp
107025265Sfsmp    /* read it into local memory */
107125265Sfsmp    readEntry( &entry, sizeof( entry ) );
107225265Sfsmp
107325265Sfsmp    printf( "--\n%s\n", extendedtableEntryTypes[ entry.type ].name );
107425265Sfsmp    printf( " bus ID: %d", entry.busID );
107525265Sfsmp    printf( " address modifier: %s\n", (entry.addressMod & 0x01) ?
107625265Sfsmp                                        "subtract" : "add" );
107725265Sfsmp    printf( " predefined range: 0x%08x", entry.predefinedRange );
107825265Sfsmp}
107925265Sfsmp
108025265Sfsmp
108125265Sfsmp/*
108225265Sfsmp * do a dmesg output
108325265Sfsmp */
108425265Sfsmpstatic void
108525265SfsmpdoDmesg( void )
108625265Sfsmp{
108725265Sfsmp    puts( SEP_LINE );
108825265Sfsmp
108925265Sfsmp    printf( "dmesg output:\n\n" );
109025265Sfsmp    fflush( stdout );
109125265Sfsmp    system( "dmesg" );
109225265Sfsmp}
109325265Sfsmp
109425265Sfsmp
109525265Sfsmp/*
109625265Sfsmp *  build "options" entries for the kernel config file
109725265Sfsmp */
109825265Sfsmpstatic void
109925265SfsmpdoOptionList( void )
110025265Sfsmp{
110125265Sfsmp    puts( SEP_LINE );
110225265Sfsmp
110325265Sfsmp    printf( "# SMP kernel config file options:\n\n" );
110425265Sfsmp    printf( "\n# Required:\n" );
110525265Sfsmp    printf( "options		SMP\t\t\t# Symmetric MultiProcessor Kernel\n" );
110625265Sfsmp    printf( "options		APIC_IO\t\t\t# Symmetric (APIC) I/O\n" );
110725265Sfsmp
110825265Sfsmp    printf( "\n# Optional (built-in defaults will work in most cases):\n" );
110926020Sfsmp    printf( "#options		NCPU=%d\t\t\t# number of CPUs\n", ncpu );
111026020Sfsmp    printf( "#options		NBUS=%d\t\t\t# number of busses\n", nbus );
111126020Sfsmp    printf( "#options		NAPIC=%d\t\t\t# number of IO APICs\n", napic );
111226020Sfsmp    printf( "#options		NINTR=%d\t\t# number of INTs\n",
111326020Sfsmp		(nintr < 24) ? 24 : nintr );
111425265Sfsmp}
111525265Sfsmp
111625265Sfsmp
111725265Sfsmp/*
111825265Sfsmp *
111925265Sfsmp */
112025265Sfsmpstatic void
112125265Sfsmppnstr( char* s, int c )
112225265Sfsmp{
112325265Sfsmp    char string[ MAXPNSTR + 1 ];
112425265Sfsmp
112525265Sfsmp    if ( c > MAXPNSTR )
112625265Sfsmp        c = MAXPNSTR;
112725265Sfsmp    strncpy( string, s, c );
112825265Sfsmp    string[ c ] = '\0';
112925265Sfsmp    printf( "%s", string );
113025265Sfsmp}
1131