mptable.c revision 120590
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[] =
3250479Speter  "$FreeBSD: head/usr.sbin/mptable/mptable.c 120590 2003-09-30 04:09:21Z peter $";
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>
5269793Sobrien#include <paths.h>
5325265Sfsmp#include <stdio.h>
5429850Scharnier#include <stdlib.h>
5529850Scharnier#include <string.h>
5625265Sfsmp#include <unistd.h>
5725265Sfsmp
5825265Sfsmp#define SEP_LINE \
5925265Sfsmp"\n-------------------------------------------------------------------------------\n"
6025265Sfsmp
6125265Sfsmp#define SEP_LINE2 \
6225265Sfsmp"\n===============================================================================\n"
6325265Sfsmp
6425265Sfsmp/* EBDA is @ 40:0e in real-mode terms */
6525265Sfsmp#define EBDA_POINTER		0x040e		/* location of EBDA pointer */
6625265Sfsmp
6725265Sfsmp/* CMOS 'top of mem' is @ 40:13 in real-mode terms */
6825265Sfsmp#define TOPOFMEM_POINTER	0x0413		/* BIOS: base memory size */
6925265Sfsmp
7025265Sfsmp#define DEFAULT_TOPOFMEM	0xa0000
7125265Sfsmp
7225265Sfsmp#define BIOS_BASE		0xf0000
7325265Sfsmp#define BIOS_BASE2		0xe0000
7425265Sfsmp#define BIOS_SIZE		0x10000
7525265Sfsmp#define ONE_KBYTE		1024
7625265Sfsmp
7725265Sfsmp#define GROPE_AREA1		0x80000
7825265Sfsmp#define GROPE_AREA2		0x90000
7925265Sfsmp#define GROPE_SIZE		0x10000
8025265Sfsmp
8125265Sfsmp#define PROCENTRY_FLAG_EN	0x01
8225265Sfsmp#define PROCENTRY_FLAG_BP	0x02
8325265Sfsmp#define IOAPICENTRY_FLAG_EN	0x01
8425265Sfsmp
8525265Sfsmp#define MAXPNSTR		132
8625265Sfsmp
8725265Sfsmpenum busTypes {
8825265Sfsmp    CBUS = 1,
8925265Sfsmp    CBUSII = 2,
9025265Sfsmp    EISA = 3,
9125265Sfsmp    ISA = 6,
9225265Sfsmp    PCI = 13,
9325265Sfsmp    XPRESS = 18,
9425265Sfsmp    MAX_BUSTYPE = 18,
9525265Sfsmp    UNKNOWN_BUSTYPE = 0xff
9625265Sfsmp};
9725265Sfsmp
9825265Sfsmptypedef struct BUSTYPENAME {
9925265Sfsmp    u_char	type;
10025265Sfsmp    char	name[ 7 ];
10125265Sfsmp} busTypeName;
10225265Sfsmp
10325265Sfsmpstatic busTypeName busTypeTable[] =
10425265Sfsmp{
10525265Sfsmp    { CBUS,		"CBUS"   },
10625265Sfsmp    { CBUSII,		"CBUSII" },
10725265Sfsmp    { EISA,		"EISA"   },
10825265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
10925265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11025265Sfsmp    { ISA,		"ISA"    },
11125265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11225265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11325265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11425265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11525265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11625265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11725265Sfsmp    { PCI,		"PCI"    },
11825265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
11925265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12025265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12125265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12225265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    },
12325265Sfsmp    { UNKNOWN_BUSTYPE,	"---"    }
12425265Sfsmp};
12525265Sfsmp
126120590Speterconst char* whereStrings[] = {
12725265Sfsmp    "Extended BIOS Data Area",
12825265Sfsmp    "BIOS top of memory",
12925265Sfsmp    "Default top of memory",
13025265Sfsmp    "BIOS",
13125265Sfsmp    "Extended BIOS",
13225265Sfsmp    "GROPE AREA #1",
13325265Sfsmp    "GROPE AREA #2"
13425265Sfsmp};
13525265Sfsmp
13625265Sfsmptypedef struct TABLE_ENTRY {
13725265Sfsmp    u_char	type;
13825265Sfsmp    u_char	length;
13925265Sfsmp    char	name[ 32 ];
14025265Sfsmp} tableEntry;
14125265Sfsmp
14225265SfsmptableEntry basetableEntryTypes[] =
14325265Sfsmp{
14425265Sfsmp    { 0, 20, "Processor" },
14525265Sfsmp    { 1,  8, "Bus" },
14625265Sfsmp    { 2,  8, "I/O APIC" },
14725265Sfsmp    { 3,  8, "I/O INT" },
14825265Sfsmp    { 4,  8, "Local INT" }
14925265Sfsmp};
15025265Sfsmp
15125265SfsmptableEntry extendedtableEntryTypes[] =
15225265Sfsmp{
15325265Sfsmp    { 128, 20, "System Address Space" },
15425265Sfsmp    { 129,  8, "Bus Heirarchy" },
15525265Sfsmp    { 130,  8, "Compatibility Bus Address" }
15625265Sfsmp};
15725265Sfsmp
15825265Sfsmp/* MP Floating Pointer Structure */
15925265Sfsmptypedef struct MPFPS {
16025265Sfsmp    char	signature[ 4 ];
161120590Speter    u_int32_t	pap;
16225265Sfsmp    u_char	length;
16325265Sfsmp    u_char	spec_rev;
16425265Sfsmp    u_char	checksum;
16525265Sfsmp    u_char	mpfb1;
16625265Sfsmp    u_char	mpfb2;
16725265Sfsmp    u_char	mpfb3;
16825265Sfsmp    u_char	mpfb4;
16925265Sfsmp    u_char	mpfb5;
17025265Sfsmp} mpfps_t;
17125265Sfsmp
17225265Sfsmp/* MP Configuration Table Header */
17325265Sfsmptypedef struct MPCTH {
17425265Sfsmp    char	signature[ 4 ];
17525265Sfsmp    u_short	base_table_length;
17625265Sfsmp    u_char	spec_rev;
17725265Sfsmp    u_char	checksum;
17825265Sfsmp    u_char	oem_id[ 8 ];
17925265Sfsmp    u_char	product_id[ 12 ];
180120590Speter    u_int32_t	oem_table_pointer;
18125265Sfsmp    u_short	oem_table_size;
18225265Sfsmp    u_short	entry_count;
183120590Speter    u_int32_t	apic_address;
18425265Sfsmp    u_short	extended_table_length;
18525265Sfsmp    u_char	extended_table_checksum;
18625265Sfsmp    u_char	reserved;
18725265Sfsmp} mpcth_t;
18825265Sfsmp
18925265Sfsmp
19025265Sfsmptypedef struct PROCENTRY {
19125265Sfsmp    u_char	type;
19225265Sfsmp    u_char	apicID;
19325265Sfsmp    u_char	apicVersion;
19425265Sfsmp    u_char	cpuFlags;
195120590Speter    u_int32_t	cpuSignature;
196120590Speter    u_int32_t	featureFlags;
197120590Speter    u_int32_t	reserved1;
198120590Speter    u_int32_t	reserved2;
19925265Sfsmp} ProcEntry;
20025265Sfsmp
20125265Sfsmptypedef struct BUSENTRY {
20225265Sfsmp    u_char	type;
20325265Sfsmp    u_char	busID;
20425265Sfsmp    char	busType[ 6 ];
20525265Sfsmp} BusEntry;
20625265Sfsmp
20725265Sfsmptypedef struct IOAPICENTRY {
20825265Sfsmp    u_char	type;
20925265Sfsmp    u_char	apicID;
21025265Sfsmp    u_char	apicVersion;
21125265Sfsmp    u_char	apicFlags;
212120590Speter    u_int32_t	apicAddress;
21325265Sfsmp} IOApicEntry;
21425265Sfsmp
21525265Sfsmptypedef struct INTENTRY {
21625265Sfsmp    u_char	type;
21725265Sfsmp    u_char	intType;
21825265Sfsmp    u_short	intFlags;
21925265Sfsmp    u_char	srcBusID;
22025265Sfsmp    u_char	srcBusIRQ;
22125265Sfsmp    u_char	dstApicID;
22225265Sfsmp    u_char	dstApicINT;
22325265Sfsmp} IntEntry;
22425265Sfsmp
22525265Sfsmp
22625265Sfsmp/*
22725265Sfsmp * extended entry type structures
22825265Sfsmp */
22925265Sfsmp
23025265Sfsmptypedef struct SASENTRY {
23125265Sfsmp    u_char	type;
23225265Sfsmp    u_char	length;
23325265Sfsmp    u_char	busID;
23425265Sfsmp    u_char	addressType;
23525265Sfsmp    u_int64_t	addressBase;
23625265Sfsmp    u_int64_t	addressLength;
237120590Speter} __attribute__((__packed__)) SasEntry;
23825265Sfsmp
23925265Sfsmp
24025265Sfsmptypedef struct BHDENTRY {
24125265Sfsmp    u_char	type;
24225265Sfsmp    u_char	length;
24325265Sfsmp    u_char	busID;
24425265Sfsmp    u_char	busInfo;
24525265Sfsmp    u_char	busParent;
24625265Sfsmp    u_char	reserved[ 3 ];
24725265Sfsmp} BhdEntry;
24825265Sfsmp
24925265Sfsmp
25025265Sfsmptypedef struct CBASMENTRY {
25125265Sfsmp    u_char	type;
25225265Sfsmp    u_char	length;
25325265Sfsmp    u_char	busID;
25425265Sfsmp    u_char	addressMod;
25525265Sfsmp    u_int	predefinedRange;
25625265Sfsmp} CbasmEntry;
25725265Sfsmp
25825265Sfsmp
25925265Sfsmp
260120590Speterstatic void apic_probe( u_int32_t* paddr, int* where );
26125265Sfsmp
26225265Sfsmpstatic void MPConfigDefault( int featureByte );
26325265Sfsmp
264120590Speterstatic void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps );
265120590Speterstatic void MPConfigTableHeader( u_int32_t pap );
26625265Sfsmp
26725265Sfsmpstatic int readType( void );
268120590Speterstatic void seekEntry( u_int32_t addr );
26925265Sfsmpstatic void readEntry( void* entry, int size );
27025265Sfsmp
27125265Sfsmpstatic void processorEntry( void );
27225265Sfsmpstatic void busEntry( void );
27325265Sfsmpstatic void ioApicEntry( void );
27425265Sfsmpstatic void intEntry( void );
27525265Sfsmp
27625265Sfsmpstatic void sasEntry( void );
27725265Sfsmpstatic void bhdEntry( void );
27825265Sfsmpstatic void cbasmEntry( void );
27925265Sfsmp
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{
311120590Speter    u_int32_t	paddr;
31225265Sfsmp    int		where;
31325265Sfsmp    mpfps_t	mpfps;
31425265Sfsmp    int		defaultConfig;
31525265Sfsmp
31625265Sfsmp    int		ch;
31725265Sfsmp
31825265Sfsmp    /* announce ourselves */
31925265Sfsmp    puts( SEP_LINE2 );
32025265Sfsmp
32125265Sfsmp    printf( "MPTable, version %d.%d.%d\n", VMAJOR, VMINOR, VDELTA );
32225265Sfsmp
32347442Simp    while ((ch = getopt(argc, argv, "d:g:h:v:")) != -1) {
32425265Sfsmp	switch(ch) {
32525265Sfsmp	case 'd':
32625265Sfsmp	    if ( strcmp( optarg, "mesg") == 0 )
32725265Sfsmp	        dmesg = 1;
32825265Sfsmp	    else
32925265Sfsmp	        dmesg = 0;
33025265Sfsmp	    break;
33125265Sfsmp	case 'h':
33225265Sfsmp	    if ( strcmp( optarg, "elp") == 0 )
33325265Sfsmp	        usage();
33425265Sfsmp	    break;
33525265Sfsmp	case 'g':
33625326Sfsmp	    if ( strcmp( optarg, "rope") == 0 )
33725265Sfsmp	        grope = 1;
33825265Sfsmp	    break;
33925265Sfsmp	case 'v':
34025265Sfsmp	    if ( strcmp( optarg, "erbose") == 0 )
34125265Sfsmp	        verbose = 1;
34225265Sfsmp	    break;
34325265Sfsmp	default:
34425265Sfsmp	    usage();
34525265Sfsmp	}
34625265Sfsmp	argc -= optind;
34725265Sfsmp	argv += optind;
34825265Sfsmp	optreset = 1;
34925265Sfsmp	optind = 0;
35025265Sfsmp    }
35125265Sfsmp
35225265Sfsmp    /* open physical memory for access to MP structures */
35369793Sobrien    if ( (pfd = open( _PATH_MEM, O_RDONLY )) < 0 )
35429850Scharnier        err( 1, "mem open" );
35525265Sfsmp
35625265Sfsmp    /* probe for MP structures */
35725265Sfsmp    apic_probe( &paddr, &where );
35825265Sfsmp    if ( where <= 0 ) {
35925265Sfsmp        fprintf( stderr, "\n MP FPS NOT found,\n" );
36025265Sfsmp        fprintf( stderr, " suggest trying -grope option!!!\n\n" );
36125265Sfsmp        return 1;
36225265Sfsmp    }
36325265Sfsmp
36425265Sfsmp    if ( verbose )
36525265Sfsmp        printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n",
36625265Sfsmp	      whereStrings[ where - 1 ], paddr );
36725265Sfsmp
36825265Sfsmp    puts( SEP_LINE );
36925265Sfsmp
37025265Sfsmp    /* analyze the MP Floating Pointer Structure */
37125265Sfsmp    MPFloatingPointer( paddr, where, &mpfps );
37225265Sfsmp
37325265Sfsmp    puts( SEP_LINE );
37425265Sfsmp
37525265Sfsmp    /* check whether an MP config table exists */
37629850Scharnier    if ( (defaultConfig = mpfps.mpfb1) )
37725265Sfsmp        MPConfigDefault( defaultConfig );
37825265Sfsmp    else
37925265Sfsmp	MPConfigTableHeader( mpfps.pap );
38025265Sfsmp
38125265Sfsmp    /* do a dmesg output */
38225265Sfsmp    if ( dmesg )
38325265Sfsmp        doDmesg();
38425265Sfsmp
38525265Sfsmp    puts( SEP_LINE2 );
38625265Sfsmp
38725265Sfsmp    return 0;
38825265Sfsmp}
38925265Sfsmp
39025265Sfsmp
39125265Sfsmp/*
39225265Sfsmp * set PHYSICAL address of MP floating pointer structure
39325265Sfsmp */
39425265Sfsmp#define NEXT(X)		((X) += 4)
39525265Sfsmpstatic void
396120590Speterapic_probe( u_int32_t* paddr, int* where )
39725265Sfsmp{
39825265Sfsmp    /*
39925265Sfsmp     * c rewrite of apic_probe() by Jack F. Vogel
40025265Sfsmp     */
40125265Sfsmp
40225265Sfsmp    int		x;
40325265Sfsmp    u_short	segment;
404120590Speter    u_int32_t	target;
40525265Sfsmp    u_int	buffer[ BIOS_SIZE / sizeof( int ) ];
40625265Sfsmp
40725265Sfsmp    if ( verbose )
40825265Sfsmp        printf( "\n" );
40925265Sfsmp
41025265Sfsmp    /* search Extended Bios Data Area, if present */
41125265Sfsmp    if ( verbose )
41225265Sfsmp        printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER );
413120590Speter    seekEntry( (u_int32_t)EBDA_POINTER );
41425265Sfsmp    readEntry( &segment, 2 );
41525265Sfsmp    if ( segment ) {		    /* search EBDA */
416120590Speter        target = (u_int32_t)segment << 4;
41725265Sfsmp	if ( verbose )
41825265Sfsmp	    printf( "found, searching EBDA @ 0x%08x\n", target );
41925265Sfsmp        seekEntry( target );
42025265Sfsmp        readEntry( buffer, ONE_KBYTE );
42125265Sfsmp
422120590Speter        for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) {
42325265Sfsmp            if ( buffer[ x ] == MP_SIG ) {
42425265Sfsmp                *where = 1;
42525265Sfsmp                *paddr = (x * sizeof( unsigned int )) + target;
42625265Sfsmp                return;
42725265Sfsmp            }
42825265Sfsmp        }
42925265Sfsmp    }
43025265Sfsmp    else {
43125265Sfsmp	if ( verbose )
43225265Sfsmp	    printf( "NOT found\n" );
43325265Sfsmp    }
43425265Sfsmp
43525265Sfsmp    /* read CMOS for real top of mem */
436120590Speter    seekEntry( (u_int32_t)TOPOFMEM_POINTER );
43725265Sfsmp    readEntry( &segment, 2 );
43825265Sfsmp    --segment;						/* less ONE_KBYTE */
43925265Sfsmp    target = segment * 1024;
44025265Sfsmp    if ( verbose )
44125265Sfsmp        printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n",
44225265Sfsmp	        target, segment );
44325265Sfsmp    seekEntry( target );
44425265Sfsmp    readEntry( buffer, ONE_KBYTE );
44525265Sfsmp
446120590Speter    for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) {
44725265Sfsmp        if ( buffer[ x ] == MP_SIG ) {
44825265Sfsmp            *where = 2;
44925265Sfsmp            *paddr = (x * sizeof( unsigned int )) + target;
45025265Sfsmp            return;
45125265Sfsmp        }
45225265Sfsmp    }
45325265Sfsmp
45425265Sfsmp    /* we don't necessarily believe CMOS, check base of the last 1K of 640K */
45525265Sfsmp    if ( target != (DEFAULT_TOPOFMEM - 1024)) {
45625265Sfsmp	target = (DEFAULT_TOPOFMEM - 1024);
45725265Sfsmp	if ( verbose )
45825265Sfsmp	    printf( " searching default 'top of mem' @ 0x%08x (%dK)\n",
45925265Sfsmp		    target, (target / 1024) );
46025265Sfsmp	seekEntry( target );
46125265Sfsmp	readEntry( buffer, ONE_KBYTE );
46225265Sfsmp
463120590Speter	for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) {
46425265Sfsmp	    if ( buffer[ x ] == MP_SIG ) {
46525265Sfsmp		*where = 3;
46625265Sfsmp		*paddr = (x * sizeof( unsigned int )) + target;
46725265Sfsmp		return;
46825265Sfsmp	    }
46925265Sfsmp	}
47025265Sfsmp    }
47125265Sfsmp
47225265Sfsmp    /* search the BIOS */
47325265Sfsmp    if ( verbose )
47425265Sfsmp        printf( " searching BIOS @ 0x%08x\n", BIOS_BASE );
47525265Sfsmp    seekEntry( BIOS_BASE );
47625265Sfsmp    readEntry( buffer, BIOS_SIZE );
47725265Sfsmp
478120590Speter    for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
47925265Sfsmp        if ( buffer[ x ] == MP_SIG ) {
48025265Sfsmp            *where = 4;
48125265Sfsmp            *paddr = (x * sizeof( unsigned int )) + BIOS_BASE;
48225265Sfsmp            return;
48325265Sfsmp        }
48425265Sfsmp    }
48525265Sfsmp
48625265Sfsmp    /* search the extended BIOS */
48725265Sfsmp    if ( verbose )
48825265Sfsmp        printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 );
48925265Sfsmp    seekEntry( BIOS_BASE2 );
49025265Sfsmp    readEntry( buffer, BIOS_SIZE );
49125265Sfsmp
492120590Speter    for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
49325265Sfsmp        if ( buffer[ x ] == MP_SIG ) {
49425265Sfsmp            *where = 5;
49525265Sfsmp            *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2;
49625265Sfsmp            return;
49725265Sfsmp        }
49825265Sfsmp    }
49925265Sfsmp
50025265Sfsmp    if ( grope ) {
50125265Sfsmp	/* search additional memory */
50225265Sfsmp	target = GROPE_AREA1;
50325265Sfsmp	if ( verbose )
50425265Sfsmp	    printf( " groping memory @ 0x%08x\n", target );
50525265Sfsmp	seekEntry( target );
50625265Sfsmp	readEntry( buffer, GROPE_SIZE );
50725265Sfsmp
508120590Speter	for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
50925265Sfsmp	    if ( buffer[ x ] == MP_SIG ) {
51025265Sfsmp		*where = 6;
51125265Sfsmp		*paddr = (x * sizeof( unsigned int )) + GROPE_AREA1;
51225265Sfsmp		return;
51325265Sfsmp	    }
51425265Sfsmp	}
51525265Sfsmp
51625265Sfsmp	target = GROPE_AREA2;
51725265Sfsmp	if ( verbose )
51825265Sfsmp	    printf( " groping memory @ 0x%08x\n", target );
51925265Sfsmp	seekEntry( target );
52025265Sfsmp	readEntry( buffer, GROPE_SIZE );
52125265Sfsmp
522120590Speter	for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
52325265Sfsmp	    if ( buffer[ x ] == MP_SIG ) {
52425265Sfsmp		*where = 7;
52525265Sfsmp		*paddr = (x * sizeof( unsigned int )) + GROPE_AREA2;
52625265Sfsmp		return;
52725265Sfsmp	    }
52825265Sfsmp	}
52925265Sfsmp    }
53025265Sfsmp
53125265Sfsmp    *where = 0;
532120590Speter    *paddr = (u_int32_t)0;
53325265Sfsmp}
53425265Sfsmp
53525265Sfsmp
53625265Sfsmp/*
53725265Sfsmp *
53825265Sfsmp */
53929850Scharnierstatic void
540120590SpeterMPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps )
54125265Sfsmp{
54225265Sfsmp
54325265Sfsmp    /* read in mpfps structure*/
54425265Sfsmp    seekEntry( paddr );
54525265Sfsmp    readEntry( mpfps, sizeof( mpfps_t ) );
54625265Sfsmp
54725265Sfsmp    /* show its contents */
54825265Sfsmp    printf( "MP Floating Pointer Structure:\n\n" );
54925265Sfsmp
55029850Scharnier    printf( "  location:\t\t\t" );
55125265Sfsmp    switch ( where )
55225265Sfsmp    {
55325265Sfsmp    case 1:
55425265Sfsmp	printf( "EBDA\n" );
55525265Sfsmp	break;
55625265Sfsmp    case 2:
55725265Sfsmp	printf( "BIOS base memory\n" );
55825265Sfsmp	break;
55925265Sfsmp    case 3:
56025265Sfsmp	printf( "DEFAULT base memory (639K)\n" );
56125265Sfsmp	break;
56225265Sfsmp    case 4:
56325265Sfsmp	printf( "BIOS\n" );
56425265Sfsmp	break;
56525265Sfsmp    case 5:
56625265Sfsmp	printf( "Extended BIOS\n" );
56725265Sfsmp	break;
56825265Sfsmp
56925265Sfsmp    case 0:
57025265Sfsmp	printf( "NOT found!\n" );
57125265Sfsmp	exit( 1 );
57225265Sfsmp    default:
57325265Sfsmp	printf( "BOGUS!\n" );
57425265Sfsmp	exit( 1 );
57525265Sfsmp    }
57625265Sfsmp    printf( "  physical address:\t\t0x%08x\n", paddr );
57725265Sfsmp
57825265Sfsmp    printf( "  signature:\t\t\t'" );
57925265Sfsmp    pnstr( mpfps->signature, 4 );
58025265Sfsmp    printf( "'\n" );
58125265Sfsmp
58225265Sfsmp    printf( "  length:\t\t\t%d bytes\n", mpfps->length * 16 );
58325265Sfsmp    printf( "  version:\t\t\t1.%1d\n", mpfps->spec_rev );
58425265Sfsmp    printf( "  checksum:\t\t\t0x%02x\n", mpfps->checksum );
58525265Sfsmp
58625265Sfsmp    /* bits 0:6 are RESERVED */
58725265Sfsmp    if ( mpfps->mpfb2 & 0x7f ) {
58829850Scharnier        printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 );
58925265Sfsmp    }
59025265Sfsmp
59125265Sfsmp    /* bit 7 is IMCRP */
59225265Sfsmp    printf( "  mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ?
59325265Sfsmp            "PIC" : "Virtual Wire" );
59425265Sfsmp
59525265Sfsmp    /* MP feature bytes 3-5 are expected to be ZERO */
59625265Sfsmp    if ( mpfps->mpfb3 )
59725265Sfsmp        printf( " warning, MP feature byte 3 NONZERO!\n" );
59825265Sfsmp    if ( mpfps->mpfb4 )
59925265Sfsmp        printf( " warning, MP feature byte 4 NONZERO!\n" );
60025265Sfsmp    if ( mpfps->mpfb5 )
60125265Sfsmp        printf( " warning, MP feature byte 5 NONZERO!\n" );
60225265Sfsmp}
60325265Sfsmp
60425265Sfsmp
60525265Sfsmp/*
60625265Sfsmp *
60725265Sfsmp */
60825265Sfsmpstatic void
60925265SfsmpMPConfigDefault( int featureByte )
61025265Sfsmp{
61125265Sfsmp    printf( "  MP default config type: %d\n\n", featureByte );
61225265Sfsmp    switch ( featureByte ) {
61325265Sfsmp    case 1:
61425265Sfsmp	printf( "   bus: ISA, APIC: 82489DX\n" );
61525265Sfsmp	break;
61625265Sfsmp    case 2:
61725265Sfsmp	printf( "   bus: EISA, APIC: 82489DX\n" );
61825265Sfsmp	break;
61925265Sfsmp    case 3:
62025265Sfsmp	printf( "   bus: EISA, APIC: 82489DX\n" );
62125265Sfsmp	break;
62225265Sfsmp    case 4:
62325265Sfsmp	printf( "   bus: MCA, APIC: 82489DX\n" );
62425265Sfsmp	break;
62525265Sfsmp    case 5:
62625265Sfsmp	printf( "   bus: ISA+PCI, APIC: Integrated\n" );
62725265Sfsmp	break;
62825265Sfsmp    case 6:
62925265Sfsmp	printf( "   bus: EISA+PCI, APIC: Integrated\n" );
63025265Sfsmp	break;
63125265Sfsmp    case 7:
63225265Sfsmp	printf( "   bus: MCA+PCI, APIC: Integrated\n" );
63325265Sfsmp	break;
63425265Sfsmp    default:
63525265Sfsmp	printf( "   future type\n" );
63625265Sfsmp	break;
63725265Sfsmp    }
63825265Sfsmp
63925265Sfsmp    switch ( featureByte ) {
64025265Sfsmp    case 1:
64125265Sfsmp    case 2:
64225265Sfsmp    case 3:
64325265Sfsmp    case 4:
64425265Sfsmp	nbus = 1;
64525265Sfsmp	break;
64625265Sfsmp    case 5:
64725265Sfsmp    case 6:
64825265Sfsmp    case 7:
64925265Sfsmp	nbus = 2;
65025265Sfsmp	break;
65125265Sfsmp    default:
65225265Sfsmp	printf( "   future type\n" );
65325265Sfsmp	break;
65425265Sfsmp    }
65525265Sfsmp
65625265Sfsmp    ncpu = 2;
65725265Sfsmp    napic = 1;
65825265Sfsmp    nintr = 16;
65925265Sfsmp}
66025265Sfsmp
66125265Sfsmp
66225265Sfsmp/*
66325265Sfsmp *
66425265Sfsmp */
66525265Sfsmpstatic void
666120590SpeterMPConfigTableHeader( u_int32_t pap )
66725265Sfsmp{
668120590Speter    u_int32_t	paddr;
66925265Sfsmp    mpcth_t	cth;
67029850Scharnier    int		x;
67171209Speter    int		totalSize;
67225265Sfsmp    int		count, c;
67325265Sfsmp    int		type;
67471209Speter    int		oldtype, entrytype;
67525265Sfsmp
67625265Sfsmp    if ( pap == 0 ) {
67725265Sfsmp	printf( "MP Configuration Table Header MISSING!\n" );
67825265Sfsmp        exit( 1 );
67925265Sfsmp    }
68025265Sfsmp
68125265Sfsmp    /* convert physical address to virtual address */
682120590Speter    paddr = pap;
68325265Sfsmp
68425265Sfsmp    /* read in cth structure */
68525265Sfsmp    seekEntry( paddr );
68625265Sfsmp    readEntry( &cth, sizeof( cth ) );
68725265Sfsmp
68825265Sfsmp    printf( "MP Config Table Header:\n\n" );
68925265Sfsmp
69025265Sfsmp    printf( "  physical address:\t\t0x%08x\n", pap );
69125265Sfsmp
69225265Sfsmp    printf( "  signature:\t\t\t'" );
69325265Sfsmp    pnstr( cth.signature, 4 );
69425265Sfsmp    printf( "'\n" );
69525265Sfsmp
69625265Sfsmp    printf( "  base table length:\t\t%d\n", cth.base_table_length );
69725265Sfsmp
69825265Sfsmp    printf( "  version:\t\t\t1.%1d\n", cth.spec_rev );
69925265Sfsmp    printf( "  checksum:\t\t\t0x%02x\n", cth.checksum );
70025265Sfsmp
70125265Sfsmp    printf( "  OEM ID:\t\t\t'" );
70225265Sfsmp    pnstr( cth.oem_id, 8 );
70325265Sfsmp    printf( "'\n" );
70425265Sfsmp
70525265Sfsmp    printf( "  Product ID:\t\t\t'" );
70625265Sfsmp    pnstr( cth.product_id, 12 );
70725265Sfsmp    printf( "'\n" );
70825265Sfsmp
70925265Sfsmp    printf( "  OEM table pointer:\t\t0x%08x\n", cth.oem_table_pointer );
71025265Sfsmp    printf( "  OEM table size:\t\t%d\n", cth.oem_table_size );
71125265Sfsmp
71225265Sfsmp    printf( "  entry count:\t\t\t%d\n", cth.entry_count );
71325265Sfsmp
71425265Sfsmp    printf( "  local APIC address:\t\t0x%08x\n", cth.apic_address );
71525265Sfsmp
71625265Sfsmp    printf( "  extended table length:\t%d\n", cth.extended_table_length );
71725265Sfsmp    printf( "  extended table checksum:\t%d\n", cth.extended_table_checksum );
71825265Sfsmp
71925265Sfsmp    totalSize = cth.base_table_length - sizeof( struct MPCTH );
72025265Sfsmp    count = cth.entry_count;
72125265Sfsmp
72225265Sfsmp    puts( SEP_LINE );
72325265Sfsmp
72425265Sfsmp    printf( "MP Config Base Table Entries:\n\n" );
72525265Sfsmp
72625265Sfsmp    /* initialze tables */
72725265Sfsmp    for ( x = 0; x < 16; ++x ) {
72825265Sfsmp	busses[ x ] = apics[ x ] = 0xff;
72925265Sfsmp    }
73025265Sfsmp
73125265Sfsmp    ncpu = 0;
73225265Sfsmp    nbus = 0;
73325265Sfsmp    napic = 0;
73425265Sfsmp    nintr = 0;
73525265Sfsmp
73671209Speter    oldtype = -1;
73771209Speter    for (c = count; c; c--) {
73871209Speter	entrytype = readType();
73971209Speter	if (entrytype != oldtype)
74071209Speter	    printf("--\n");
74171209Speter	if (entrytype < oldtype)
74271209Speter	    printf("MPTABLE OUT OF ORDER!\n");
74371209Speter	switch (entrytype) {
74471209Speter	case 0:
74571209Speter	    if (oldtype != 0)
74671209Speter		printf( "Processors:\tAPIC ID\tVersion\tState"
74771209Speter			"\t\tFamily\tModel\tStep\tFlags\n" );
74871209Speter	    oldtype = 0;
74925265Sfsmp	    processorEntry();
75071209Speter	    break;
75125265Sfsmp
75271209Speter	case 1:
75371209Speter	    if (oldtype != 1)
75471209Speter		printf( "Bus:\t\tBus ID\tType\n" );
75571209Speter	    oldtype = 1;
75625265Sfsmp	    busEntry();
75771209Speter	    break;
75825265Sfsmp
75971209Speter	case 2:
76071209Speter	    if (oldtype != 2)
76171209Speter		printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" );
76271209Speter	    oldtype = 2;
76325265Sfsmp	    ioApicEntry();
76471209Speter	    break;
76525265Sfsmp
76671209Speter	case 3:
76771209Speter	    if (oldtype != 3)
76871209Speter		printf( "I/O Ints:\tType\tPolarity    Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
76971209Speter	    oldtype = 3;
77025265Sfsmp	    intEntry();
77171209Speter	    break;
77225265Sfsmp
77371209Speter	case 4:
77471209Speter	    if (oldtype != 4)
77571209Speter		printf( "Local Ints:\tType\tPolarity    Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
77671209Speter	    oldtype = 4;
77725265Sfsmp	    intEntry();
77871209Speter	    break;
77971209Speter
78071209Speter	default:
78171209Speter	    printf("MPTABLE HOSED! record type = %d\n", entrytype);
78271209Speter	    exit(1);
78371209Speter	}
78425265Sfsmp    }
78525265Sfsmp
78625265Sfsmp
78725265Sfsmp#if defined( EXTENDED_PROCESSING_READY )
78825265Sfsmp    /* process any extended data */
78929850Scharnier    if ( (totalSize = cth.extended_table_length) ) {
79025265Sfsmp	puts( SEP_LINE );
79125265Sfsmp
79225265Sfsmp        printf( "MP Config Extended Table Entries:\n\n" );
79325265Sfsmp
79425265Sfsmp        while ( totalSize > 0 ) {
79525265Sfsmp            switch ( type = readType() ) {
79625265Sfsmp            case 128:
79725265Sfsmp		sasEntry();
79825265Sfsmp		break;
79925265Sfsmp            case 129:
80025265Sfsmp		bhdEntry();
80125265Sfsmp		break;
80225265Sfsmp            case 130:
80325265Sfsmp		cbasmEntry();
80425265Sfsmp		break;
80525265Sfsmp            default:
80625265Sfsmp                printf( "Extended Table HOSED!\n" );
80725265Sfsmp                exit( 1 );
80825265Sfsmp            }
80925265Sfsmp
81025265Sfsmp            totalSize -= extendedtableEntryTypes[ type-128 ].length;
81125265Sfsmp        }
81225265Sfsmp    }
81325265Sfsmp#endif  /* EXTENDED_PROCESSING_READY */
81425265Sfsmp
81525265Sfsmp    /* process any OEM data */
81625265Sfsmp    if ( cth.oem_table_pointer && (cth.oem_table_size > 0) ) {
81725265Sfsmp#if defined( OEM_PROCESSING_READY )
81825265Sfsmp# error your on your own here!
81925265Sfsmp        /* convert OEM table pointer to virtual address */
820120590Speter        poemtp = (u_int32_t)cth.oem_table_pointer;
82125265Sfsmp
82225265Sfsmp        /* read in oem table structure */
82329850Scharnier        if ( (oemdata = (void*)malloc( cth.oem_table_size )) == NULL )
82429850Scharnier            err( 1, "oem malloc" );
82525265Sfsmp
82625265Sfsmp        seekEntry( poemtp );
82725265Sfsmp        readEntry( oemdata, cth.oem_table_size );
82825265Sfsmp
82925265Sfsmp        /** process it */
83025265Sfsmp
83125265Sfsmp        free( oemdata );
83225265Sfsmp#else
83325265Sfsmp        printf( "\nyou need to modify the source to handle OEM data!\n\n" );
83425265Sfsmp#endif  /* OEM_PROCESSING_READY */
83525265Sfsmp    }
83625265Sfsmp
83725265Sfsmp    fflush( stdout );
83825265Sfsmp
83925265Sfsmp#if defined( RAW_DUMP )
84025265Sfsmp{
84125265Sfsmp    int		ofd;
84225265Sfsmp    u_char	dumpbuf[ 4096 ];
84325265Sfsmp
84425265Sfsmp    ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR );
84525265Sfsmp    seekEntry( paddr );
84625265Sfsmp    readEntry( dumpbuf, 1024 );
84725265Sfsmp    write( ofd, dumpbuf, 1024 );
84825265Sfsmp    close( ofd );
84925265Sfsmp}
85025265Sfsmp#endif /* RAW_DUMP */
85125265Sfsmp}
85225265Sfsmp
85325265Sfsmp
85425265Sfsmp/*
85525265Sfsmp *
85625265Sfsmp */
85725265Sfsmpstatic int
85825265SfsmpreadType( void )
85925265Sfsmp{
86025265Sfsmp    u_char	type;
86125265Sfsmp
86229850Scharnier    if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) )
86329850Scharnier        err( 1, "type read; pfd: %d", pfd );
86425265Sfsmp
86529850Scharnier    if ( lseek( pfd, -1, SEEK_CUR ) < 0 )
86629850Scharnier        err( 1, "type seek" );
86725265Sfsmp
86825265Sfsmp    return (int)type;
86925265Sfsmp}
87025265Sfsmp
87125265Sfsmp
87225265Sfsmp/*
87325265Sfsmp *
87425265Sfsmp */
87525265Sfsmpstatic void
876120590SpeterseekEntry( u_int32_t addr )
87725265Sfsmp{
87829850Scharnier    if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 )
87969793Sobrien        err( 1, "%s seek", _PATH_MEM );
88025265Sfsmp}
88125265Sfsmp
88225265Sfsmp
88325265Sfsmp/*
88425265Sfsmp *
88525265Sfsmp */
88625265Sfsmpstatic void
88725265SfsmpreadEntry( void* entry, int size )
88825265Sfsmp{
88929850Scharnier    if ( read( pfd, entry, size ) != size )
89029850Scharnier        err( 1, "readEntry" );
89125265Sfsmp}
89225265Sfsmp
89325265Sfsmp
89425265Sfsmpstatic void
89525265SfsmpprocessorEntry( void )
89625265Sfsmp{
89725265Sfsmp    ProcEntry	entry;
89825265Sfsmp
89925265Sfsmp    /* read it into local memory */
90025265Sfsmp    readEntry( &entry, sizeof( entry ) );
90125265Sfsmp
90225265Sfsmp    /* count it */
90325265Sfsmp    ++ncpu;
90425265Sfsmp
90525265Sfsmp    printf( "\t\t%2d", entry.apicID );
90625265Sfsmp    printf( "\t 0x%2x", entry.apicVersion );
90725265Sfsmp
90825265Sfsmp    printf( "\t %s, %s",
90925265Sfsmp            (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
91025265Sfsmp            (entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" );
91125265Sfsmp
91225265Sfsmp    printf( "\t %d\t %d\t %d",
91325265Sfsmp            (entry.cpuSignature >> 8) & 0x0f,
91425265Sfsmp            (entry.cpuSignature >> 4) & 0x0f,
91525265Sfsmp            entry.cpuSignature & 0x0f );
91625265Sfsmp
91725265Sfsmp    printf( "\t 0x%04x\n", entry.featureFlags );
91825265Sfsmp}
91925265Sfsmp
92025265Sfsmp
92125265Sfsmp/*
92225265Sfsmp *
92325265Sfsmp */
92425265Sfsmpstatic int
92525265SfsmplookupBusType( char* name )
92625265Sfsmp{
92725265Sfsmp    int x;
92825265Sfsmp
92925265Sfsmp    for ( x = 0; x < MAX_BUSTYPE; ++x )
93025265Sfsmp	if ( strcmp( busTypeTable[ x ].name, name ) == 0 )
93125265Sfsmp	    return busTypeTable[ x ].type;
93225265Sfsmp
93325265Sfsmp    return UNKNOWN_BUSTYPE;
93425265Sfsmp}
93525265Sfsmp
93625265Sfsmp
93725265Sfsmpstatic void
93825265SfsmpbusEntry( void )
93925265Sfsmp{
94025265Sfsmp    int		x;
94125265Sfsmp    char	name[ 8 ];
94225265Sfsmp    char	c;
94325265Sfsmp    BusEntry	entry;
94425265Sfsmp
94525265Sfsmp    /* read it into local memory */
94625265Sfsmp    readEntry( &entry, sizeof( entry ) );
94725265Sfsmp
94825265Sfsmp    /* count it */
94925265Sfsmp    ++nbus;
95025265Sfsmp
95125265Sfsmp    printf( "\t\t%2d", entry.busID );
95225265Sfsmp    printf( "\t " ); pnstr( entry.busType, 6 ); printf( "\n" );
95325265Sfsmp
95425265Sfsmp    for ( x = 0; x < 6; ++x ) {
95525265Sfsmp	if ( (c = entry.busType[ x ]) == ' ' )
95625265Sfsmp	    break;
95725265Sfsmp	name[ x ] = c;
95825265Sfsmp    }
95925265Sfsmp    name[ x ] = '\0';
96025265Sfsmp    busses[ entry.busID ] = lookupBusType( name );
96125265Sfsmp}
96225265Sfsmp
96325265Sfsmp
96425265Sfsmpstatic void
96525265SfsmpioApicEntry( void )
96625265Sfsmp{
96725265Sfsmp    IOApicEntry	entry;
96825265Sfsmp
96925265Sfsmp    /* read it into local memory */
97025265Sfsmp    readEntry( &entry, sizeof( entry ) );
97125265Sfsmp
97225265Sfsmp    /* count it */
97325265Sfsmp    ++napic;
97425265Sfsmp
97525265Sfsmp    printf( "\t\t%2d", entry.apicID );
97625265Sfsmp    printf( "\t 0x%02x", entry.apicVersion );
97725265Sfsmp    printf( "\t %s",
97825265Sfsmp            (entry.apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" );
97925265Sfsmp    printf( "\t\t 0x%x\n", entry.apicAddress );
98025265Sfsmp
98125265Sfsmp    apics[ entry.apicID ] = entry.apicID;
98225265Sfsmp}
98325265Sfsmp
98425265Sfsmp
985120590Speterconst char* intTypes[] = {
98625265Sfsmp    "INT", "NMI", "SMI", "ExtINT"
98725265Sfsmp};
98825265Sfsmp
989120590Speterconst char* polarityMode[] = {
99025265Sfsmp    "conforms", "active-hi", "reserved", "active-lo"
99125265Sfsmp};
992120590Speterconst char* triggerMode[] = {
99325265Sfsmp    "conforms", "edge", "reserved", "level"
99425265Sfsmp};
99525265Sfsmp
99625265Sfsmpstatic void
99725265SfsmpintEntry( void )
99825265Sfsmp{
99925265Sfsmp    IntEntry	entry;
100025265Sfsmp
100125265Sfsmp    /* read it into local memory */
100225265Sfsmp    readEntry( &entry, sizeof( entry ) );
100325265Sfsmp
100425265Sfsmp    /* count it */
100525265Sfsmp    if ( (int)entry.type == 3 )
100625265Sfsmp	++nintr;
100725265Sfsmp
100825265Sfsmp    printf( "\t\t%s", intTypes[ (int)entry.intType ] );
100925265Sfsmp
101025265Sfsmp    printf( "\t%9s", polarityMode[ (int)entry.intFlags & 0x03 ] );
101125265Sfsmp    printf( "%12s", triggerMode[ ((int)entry.intFlags >> 2) & 0x03 ] );
101225265Sfsmp
101325265Sfsmp    printf( "\t %5d", (int)entry.srcBusID );
101425265Sfsmp    if ( busses[ (int)entry.srcBusID ] == PCI )
101525265Sfsmp	printf( "\t%2d:%c",
101625265Sfsmp	        ((int)entry.srcBusIRQ >> 2) & 0x1f,
101725265Sfsmp	        ((int)entry.srcBusIRQ & 0x03) + 'A' );
101825265Sfsmp    else
101925265Sfsmp	printf( "\t %3d", (int)entry.srcBusIRQ );
102025265Sfsmp    printf( "\t %6d", (int)entry.dstApicID );
102125265Sfsmp    printf( "\t %3d\n", (int)entry.dstApicINT );
102225265Sfsmp}
102325265Sfsmp
102425265Sfsmp
102525265Sfsmpstatic void
102625265SfsmpsasEntry( void )
102725265Sfsmp{
102825265Sfsmp    SasEntry	entry;
102925265Sfsmp
103025265Sfsmp    /* read it into local memory */
103125265Sfsmp    readEntry( &entry, sizeof( entry ) );
103225265Sfsmp
103364291Stegge    printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name );
103425265Sfsmp    printf( " bus ID: %d", entry.busID );
103525265Sfsmp    printf( " address type: " );
103625265Sfsmp    switch ( entry.addressType ) {
103725265Sfsmp    case 0:
103825265Sfsmp	printf( "I/O address\n" );
103925265Sfsmp	break;
104025265Sfsmp    case 1:
104125265Sfsmp	printf( "memory address\n" );
104225265Sfsmp	break;
104325265Sfsmp    case 2:
104425265Sfsmp	printf( "prefetch address\n" );
104525265Sfsmp	break;
104625265Sfsmp    default:
104725265Sfsmp	printf( "UNKNOWN type\n" );
104825265Sfsmp	break;
104925265Sfsmp    }
105025265Sfsmp
1051120590Speter    printf( " address base: 0x%llx\n", (long long)entry.addressBase );
1052120590Speter    printf( " address range: 0x%llx\n", (long long)entry.addressLength );
105325265Sfsmp}
105425265Sfsmp
105525265Sfsmp
105625265Sfsmpstatic void
105725265SfsmpbhdEntry( void )
105825265Sfsmp{
105925265Sfsmp    BhdEntry	entry;
106025265Sfsmp
106125265Sfsmp    /* read it into local memory */
106225265Sfsmp    readEntry( &entry, sizeof( entry ) );
106325265Sfsmp
106464291Stegge    printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name );
106525265Sfsmp    printf( " bus ID: %d", entry.busID );
106625265Sfsmp    printf( " bus info: 0x%02x", entry.busInfo );
106764291Stegge    printf( " parent bus ID: %d\n", entry.busParent );
106825265Sfsmp}
106925265Sfsmp
107025265Sfsmp
107125265Sfsmpstatic void
107225265SfsmpcbasmEntry( void )
107325265Sfsmp{
107425265Sfsmp    CbasmEntry	entry;
107525265Sfsmp
107625265Sfsmp    /* read it into local memory */
107725265Sfsmp    readEntry( &entry, sizeof( entry ) );
107825265Sfsmp
107964291Stegge    printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name );
108025265Sfsmp    printf( " bus ID: %d", entry.busID );
108125265Sfsmp    printf( " address modifier: %s\n", (entry.addressMod & 0x01) ?
108225265Sfsmp                                        "subtract" : "add" );
108364291Stegge    printf( " predefined range: 0x%08x\n", entry.predefinedRange );
108425265Sfsmp}
108525265Sfsmp
108625265Sfsmp
108725265Sfsmp/*
108825265Sfsmp * do a dmesg output
108925265Sfsmp */
109025265Sfsmpstatic void
109125265SfsmpdoDmesg( void )
109225265Sfsmp{
109325265Sfsmp    puts( SEP_LINE );
109425265Sfsmp
109525265Sfsmp    printf( "dmesg output:\n\n" );
109625265Sfsmp    fflush( stdout );
109725265Sfsmp    system( "dmesg" );
109825265Sfsmp}
109925265Sfsmp
110025265Sfsmp
110125265Sfsmp/*
110225265Sfsmp *
110325265Sfsmp */
110425265Sfsmpstatic void
110525265Sfsmppnstr( char* s, int c )
110625265Sfsmp{
110725265Sfsmp    char string[ MAXPNSTR + 1 ];
110825265Sfsmp
110925265Sfsmp    if ( c > MAXPNSTR )
111025265Sfsmp        c = MAXPNSTR;
111125265Sfsmp    strncpy( string, s, c );
111225265Sfsmp    string[ c ] = '\0';
111325265Sfsmp    printf( "%s", string );
111425265Sfsmp}
1115