Change-Id: I4bc90334c7220512607cd5e777ce1f8cc595e2f0 Signed-off-by: Sven Schnelle <svens@stackframe.org> Reviewed-on: http://review.coreboot.org/1115 Tested-by: build bot (Jenkins)
		
			
				
	
	
		
			1259 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1259 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 1996, by Steve Passe
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  * 2. The name of the developer may NOT be used to endorse or promote products
 | |
|  *    derived from this software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * mptable.c
 | |
|  */
 | |
| 
 | |
| #define VMAJOR			2
 | |
| #define VMINOR			0
 | |
| #define VDELTA			15
 | |
| 
 | |
| /*
 | |
|  * this will cause the raw mp table to be dumped to /tmp/mpdump
 | |
|  *
 | |
| #define RAW_DUMP
 | |
|  */
 | |
| 
 | |
| #define MP_SIG			0x5f504d5f	/* _MP_ */
 | |
| #define EXTENDED_PROCESSING_READY
 | |
| #define OEM_PROCESSING_READY_NOT
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <err.h>
 | |
| #include <fcntl.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <unistd.h>
 | |
| #include <stdint.h>
 | |
| 
 | |
| #define ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
 | |
| #define SEP_LINE \
 | |
| "\n-------------------------------------------------------------------------------\n"
 | |
| 
 | |
| #define SEP_LINE2 \
 | |
| "\n===============================================================================\n"
 | |
| 
 | |
| /* EBDA is @ 40:0e in real-mode terms */
 | |
| #define EBDA_POINTER		0x040e	/* location of EBDA pointer */
 | |
| 
 | |
| /* CMOS 'top of mem' is @ 40:13 in real-mode terms */
 | |
| #define TOPOFMEM_POINTER	0x0413	/* BIOS: base memory size */
 | |
| 
 | |
| #define DEFAULT_TOPOFMEM	0xa0000
 | |
| 
 | |
| #define BIOS_BASE		0xf0000
 | |
| #define BIOS_BASE2		0xe0000
 | |
| #define BIOS_SIZE		0x10000
 | |
| #define ONE_KBYTE		1024
 | |
| 
 | |
| #define GROPE_AREA1		0x80000
 | |
| #define GROPE_AREA2		0x90000
 | |
| #define GROPE_SIZE		0x10000
 | |
| 
 | |
| #define PROCENTRY_FLAG_EN	0x01
 | |
| #define PROCENTRY_FLAG_BP	0x02
 | |
| #define IOAPICENTRY_FLAG_EN	0x01
 | |
| 
 | |
| #define MAXPNSTR		132
 | |
| 
 | |
| #define COREBOOT_MP_TABLE      0
 | |
| 
 | |
| enum busTypes {
 | |
| 	CBUS = 1,
 | |
| 	CBUSII = 2,
 | |
| 	EISA = 3,
 | |
| 	ISA = 6,
 | |
| 	PCI = 13,
 | |
| 	XPRESS = 18,
 | |
| 	MAX_BUSTYPE = 18,
 | |
| 	UNKNOWN_BUSTYPE = 0xff
 | |
| };
 | |
| 
 | |
| typedef struct BUSTYPENAME {
 | |
| 	uint8_t type;
 | |
| 	char name[7];
 | |
| } busTypeName;
 | |
| 
 | |
| static busTypeName busTypeTable[] = {
 | |
| 	{CBUS, "CBUS"},
 | |
| 	{CBUSII, "CBUSII"},
 | |
| 	{EISA, "EISA"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{ISA, "ISA"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{PCI, "PCI"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"},
 | |
| 	{UNKNOWN_BUSTYPE, "---"}
 | |
| };
 | |
| 
 | |
| char *whereStrings[] = {
 | |
| 	"Extended BIOS Data Area",
 | |
| 	"BIOS top of memory",
 | |
| 	"Default top of memory",
 | |
| 	"BIOS",
 | |
| 	"Extended BIOS",
 | |
| 	"GROPE AREA #1",
 | |
| 	"GROPE AREA #2"
 | |
| };
 | |
| 
 | |
| typedef struct TABLE_ENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t length;
 | |
| 	char name[32];
 | |
| } tableEntry;
 | |
| 
 | |
| tableEntry basetableEntryTypes[] = {
 | |
| 	{0, 20, "Processor"},
 | |
| 	{1, 8, "Bus"},
 | |
| 	{2, 8, "I/O APIC"},
 | |
| 	{3, 8, "I/O INT"},
 | |
| 	{4, 8, "Local INT"}
 | |
| };
 | |
| 
 | |
| tableEntry extendedtableEntryTypes[] = {
 | |
| 	{128, 20, "System Address Space"},
 | |
| 	{129, 8, "Bus Heirarchy"},
 | |
| 	{130, 8, "Compatibility Bus Address"}
 | |
| };
 | |
| 
 | |
| /* MP Floating Pointer Structure */
 | |
| typedef struct MPFPS {
 | |
| 	uint8_t signature[4];
 | |
| 	uint32_t pap;
 | |
| 	uint8_t length;
 | |
| 	uint8_t spec_rev;
 | |
| 	uint8_t checksum;
 | |
| 	uint8_t mpfb1;
 | |
| 	uint8_t mpfb2;
 | |
| 	uint8_t mpfb3;
 | |
| 	uint8_t mpfb4;
 | |
| 	uint8_t mpfb5;
 | |
| } mpfps_t;
 | |
| 
 | |
| /* MP Configuration Table Header */
 | |
| typedef struct MPCTH {
 | |
| 	uint8_t signature[4];
 | |
| 	uint16_t base_table_length;
 | |
| 	uint8_t spec_rev;
 | |
| 	uint8_t checksum;
 | |
| 	uint8_t oem_id[8];
 | |
| 	uint8_t product_id[12];
 | |
| 	uint32_t oem_table_pointer;
 | |
| 	uint16_t oem_table_size;
 | |
| 	uint16_t entry_count;
 | |
| 	uint32_t apic_address;
 | |
| 	uint16_t extended_table_length;
 | |
| 	uint8_t extended_table_checksum;
 | |
| 	uint8_t reserved;
 | |
| } mpcth_t;
 | |
| 
 | |
| typedef struct PROCENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t apicID;
 | |
| 	uint8_t apicVersion;
 | |
| 	uint8_t cpuFlags;
 | |
| 	uint32_t cpuSignature;
 | |
| 	uint32_t featureFlags;
 | |
| 	uint32_t reserved1;
 | |
| 	uint32_t reserved2;
 | |
| } ProcEntry;
 | |
| 
 | |
| typedef struct BUSENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t busID;
 | |
| 	uint8_t busType[6];
 | |
| } BusEntry;
 | |
| 
 | |
| typedef struct IOAPICENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t apicID;
 | |
| 	uint8_t apicVersion;
 | |
| 	uint8_t apicFlags;
 | |
| 	uint32_t apicAddress;
 | |
| } IOApicEntry;
 | |
| 
 | |
| typedef struct INTENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t intType;
 | |
| 	uint16_t intFlags;
 | |
| 	uint8_t srcBusID;
 | |
| 	uint8_t srcBusIRQ;
 | |
| 	uint8_t dstApicID;
 | |
| 	uint8_t dstApicINT;
 | |
| } IntEntry;
 | |
| 
 | |
| /*
 | |
|  * extended entry type structures
 | |
|  */
 | |
| 
 | |
| typedef struct SASENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t length;
 | |
| 	uint8_t busID;
 | |
| 	uint8_t addressType;
 | |
| 	uint64_t addressBase;
 | |
| 	uint64_t addressLength;
 | |
| } SasEntry;
 | |
| 
 | |
| typedef struct BHDENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t length;
 | |
| 	uint8_t busID;
 | |
| 	uint8_t busInfo;
 | |
| 	uint8_t busParent;
 | |
| 	uint8_t reserved[3];
 | |
| } BhdEntry;
 | |
| 
 | |
| typedef struct CBASMENTRY {
 | |
| 	uint8_t type;
 | |
| 	uint8_t length;
 | |
| 	uint8_t busID;
 | |
| 	uint8_t addressMod;
 | |
| 	uint32_t predefinedRange;
 | |
| } CbasmEntry;
 | |
| 
 | |
| typedef uint32_t vm_offset_t;
 | |
| 
 | |
| static void apic_probe(vm_offset_t * paddr, int *where);
 | |
| 
 | |
| static void MPConfigDefault(int featureByte);
 | |
| 
 | |
| static void MPFloatingPointer(vm_offset_t paddr, int where, mpfps_t * mpfps);
 | |
| static void MPConfigTableHeader(uint32_t pap);
 | |
| 
 | |
| static int readType(void);
 | |
| static void seekEntry(vm_offset_t addr);
 | |
| static void readEntry(void *entry, int size);
 | |
| 
 | |
| static void processorEntry(void);
 | |
| static void busEntry(void);
 | |
| static void ioApicEntry(void);
 | |
| static void intEntry(void);
 | |
| static void lintEntry(void);
 | |
| 
 | |
| static void sasEntry(void);
 | |
| static void bhdEntry(void);
 | |
| static void cbasmEntry(void);
 | |
| 
 | |
| static void doOptionList(void);
 | |
| static void doDmesg(void);
 | |
| static void pnstr(uint8_t * s, int c);
 | |
| 
 | |
| /* global data */
 | |
| int pfd;			/* physical /dev/mem fd */
 | |
| 
 | |
| int busses[32];
 | |
| int apics[16];
 | |
| 
 | |
| int ncpu;
 | |
| int nbus;
 | |
| int napic;
 | |
| int nintr;
 | |
| 
 | |
| int dmesg = 0;
 | |
| int grope = 0;
 | |
| int verbose = 0;
 | |
| int noisy = 0;
 | |
| /* preamble to the mptable. This is fixed for all coreboots */
 | |
| 
 | |
| char *preamble[] = {
 | |
| 	"#include <console/console.h>",
 | |
| 	"#include <arch/smp/mpspec.h>",
 | |
| 	"#include <arch/ioapic.h>",
 | |
| 	"#include <device/pci.h>",
 | |
| 	"#include <string.h>",
 | |
| 	"#include <stdint.h>",
 | |
| 	"",
 | |
| 	"#define INTA 0x00",
 | |
| 	"#define INTB 0x01",
 | |
| 	"#define INTC 0x02",
 | |
| 	"#define INTD 0x03",
 | |
| 	"",
 | |
| 	"static void *smp_write_config_table(void *v)",
 | |
| 	"{",
 | |
| 	"        struct mp_config_table *mc;",
 | |
| 	"",
 | |
| 	"        mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);",
 | |
| 	"",
 | |
| 	"        mptable_init(mc, \"TODO        \", LOCAL_APIC_ADDR);",
 | |
| 	"",
 | |
| 	"        smp_write_processors(mc);",
 | |
| 	"",
 | |
| 	0
 | |
| };
 | |
| 
 | |
| char *postamble[] = {
 | |
| 	"	/* Compute the checksums. */",
 | |
| 	"	mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);",
 | |
| 	"	mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);",
 | |
| 	"	printk(BIOS_DEBUG, \"Wrote the mp table end at: %p - %p\\n\",",
 | |
| 	"		mc, smp_next_mpe_entry(mc));",
 | |
| 	"	return smp_next_mpe_entry(mc);",
 | |
| 	"}",
 | |
| 	"",
 | |
| 	"unsigned long write_smp_table(unsigned long addr)",
 | |
| 	"{",
 | |
| 	"	void *v;",
 | |
| 	"	v = smp_write_floating_table(addr);",
 | |
| 	"	return (unsigned long)smp_write_config_table(v);",
 | |
| 	"}",
 | |
| 	0
 | |
| };
 | |
| 
 | |
| static void usage(void)
 | |
| {
 | |
| 	fprintf(stderr,
 | |
| 		"usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n");
 | |
| 	exit(0);
 | |
| }
 | |
| 
 | |
| void write_code(char **code)
 | |
| {
 | |
| 	while (*code)
 | |
| 		printf("%s\n", *code++);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| int main(int argc, char *argv[])
 | |
| {
 | |
| 	vm_offset_t paddr;
 | |
| 	int where;
 | |
| 	mpfps_t mpfps;
 | |
| 	int defaultConfig;
 | |
| 
 | |
| 	/* announce ourselves */
 | |
| 
 | |
| 	if (verbose)
 | |
| 		puts(SEP_LINE2);
 | |
| 
 | |
| 	printf("/* generated by MPTable, version %d.%d.%d*/\n", VMAJOR, VMINOR,
 | |
| 	       VDELTA);
 | |
| 	printf("/* as modified by RGM for coreboot */\n");
 | |
| 	write_code(preamble);
 | |
| 
 | |
| 	/* Ron hates getopt() */
 | |
| 
 | |
| 	for (argc--, argv++; argc; argc--, argv++) {
 | |
| 		if (strcmp(argv[0], "-dmesg") == 0) {
 | |
| 			dmesg = 1;
 | |
| 		} else if (strcmp(argv[0], "-help") == 0) {
 | |
| 			usage();
 | |
| 		} else if (strcmp(argv[0], "-grope") == 0) {
 | |
| 			grope = 1;
 | |
| 		} else if (strcmp(argv[0], "-verbose") == 0)
 | |
| 			verbose = 1;
 | |
| 		else if (strcmp(argv[0], "-noisy") == 0)
 | |
| 			noisy = 1;
 | |
| 		else
 | |
| 			usage();
 | |
| 	}
 | |
| 
 | |
| 	/* open physical memory for access to MP structures */
 | |
| 	if ((pfd = open("/dev/mem", O_RDONLY)) < 0)
 | |
| 		err(1, "mem open");
 | |
| 
 | |
| 	/* probe for MP structures */
 | |
| 	apic_probe(&paddr, &where);
 | |
| 	if (where <= 0) {
 | |
| 		fprintf(stderr, "\n MP FPS NOT found,\n");
 | |
| 		fprintf(stderr, " suggest trying -grope option!!!\n\n");
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	if (verbose)
 | |
| 		printf("\n MP FPS found in %s @ physical addr: 0x%08x\n",
 | |
| 		       whereStrings[where - 1], paddr);
 | |
| 
 | |
| 	if (verbose)
 | |
| 		puts(SEP_LINE);
 | |
| 
 | |
| 	/* analyze the MP Floating Pointer Structure */
 | |
| 	MPFloatingPointer(paddr, where, &mpfps);
 | |
| 
 | |
| 	if (verbose)
 | |
| 		puts(SEP_LINE);
 | |
| 
 | |
| 	/* check whether an MP config table exists */
 | |
| 	if ((defaultConfig = mpfps.mpfb1))
 | |
| 		MPConfigDefault(defaultConfig);
 | |
| 	else
 | |
| 		MPConfigTableHeader(mpfps.pap);
 | |
| 
 | |
| 	/* build "options" entries for the kernel config file */
 | |
| 	if (noisy)
 | |
| 		doOptionList();
 | |
| 
 | |
| 	write_code(postamble);
 | |
| 	/* do a dmesg output */
 | |
| 	if (dmesg)
 | |
| 		doDmesg();
 | |
| 
 | |
| 	if (verbose)
 | |
| 		puts(SEP_LINE2);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * set PHYSICAL address of MP floating pointer structure
 | |
|  */
 | |
| #define NEXT(X)		((X) += 4)
 | |
| static void apic_probe(vm_offset_t * paddr, int *where)
 | |
| {
 | |
| 	/*
 | |
| 	 * c rewrite of apic_probe() by Jack F. Vogel
 | |
| 	 */
 | |
| 
 | |
| 	int x;
 | |
| 	u_short segment;
 | |
| 	vm_offset_t target;
 | |
| 	u_int buffer[BIOS_SIZE / sizeof(int)];
 | |
| 
 | |
| 	if (verbose)
 | |
| 		printf("\n");
 | |
| 
 | |
| 	/* search Extended Bios Data Area, if present */
 | |
| 	if (verbose)
 | |
| 		printf(" looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER);
 | |
| 	seekEntry((vm_offset_t) EBDA_POINTER);
 | |
| 	readEntry(&segment, 2);
 | |
| 	if (segment) {		/* search EBDA */
 | |
| 		target = (vm_offset_t) segment << 4;
 | |
| 		if (verbose)
 | |
| 			printf("found, searching EBDA @ 0x%08x\n", target);
 | |
| 		seekEntry(target);
 | |
| 		readEntry(buffer, ONE_KBYTE);
 | |
| 
 | |
| 		for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
 | |
| 			if (buffer[x] == MP_SIG) {
 | |
| 				*where = 1;
 | |
| 				*paddr = (x * sizeof(unsigned int)) + target;
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (verbose)
 | |
| 			printf("NOT found\n");
 | |
| 	}
 | |
| 
 | |
| 	target = 0;
 | |
| 	segment = 0;
 | |
| 	if (verbose)
 | |
| 		printf(" searching for coreboot MP table  @ 0x%08x (%dK)\n",
 | |
| 		       target, segment);
 | |
| 	seekEntry(target);
 | |
| 	readEntry(buffer, ONE_KBYTE);
 | |
| 
 | |
| 	for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
 | |
| 		if (buffer[x] == MP_SIG) {
 | |
| 			*where = 2;
 | |
| 			*paddr = (x * sizeof(unsigned int)) + target;
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* read CMOS for real top of mem */
 | |
| 	seekEntry((vm_offset_t) TOPOFMEM_POINTER);
 | |
| 	readEntry(&segment, 2);
 | |
| 	--segment;		/* less ONE_KBYTE */
 | |
| 	target = segment * 1024;
 | |
| 	if (verbose)
 | |
| 		printf(" searching CMOS 'top of mem' @ 0x%08x (%dK)\n",
 | |
| 		       target, segment);
 | |
| 	seekEntry(target);
 | |
| 	readEntry(buffer, ONE_KBYTE);
 | |
| 
 | |
| 	for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
 | |
| 		if (buffer[x] == MP_SIG) {
 | |
| 			*where = 2;
 | |
| 			*paddr = (x * sizeof(unsigned int)) + target;
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* we don't necessarily believe CMOS, check base of the last 1K of 640K */
 | |
| 	if (target != (DEFAULT_TOPOFMEM - 1024)) {
 | |
| 		target = (DEFAULT_TOPOFMEM - 1024);
 | |
| 		if (verbose)
 | |
| 			printf
 | |
| 			    (" searching default 'top of mem' @ 0x%08x (%dK)\n",
 | |
| 			     target, (target / 1024));
 | |
| 		seekEntry(target);
 | |
| 		readEntry(buffer, ONE_KBYTE);
 | |
| 
 | |
| 		for (x = 0; x < ONE_KBYTE / sizeof(unsigned int); NEXT(x)) {
 | |
| 			if (buffer[x] == MP_SIG) {
 | |
| 				*where = 3;
 | |
| 				*paddr = (x * sizeof(unsigned int)) + target;
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* search the BIOS */
 | |
| 	if (verbose)
 | |
| 		printf(" searching BIOS @ 0x%08x\n", BIOS_BASE);
 | |
| 	seekEntry(BIOS_BASE);
 | |
| 	readEntry(buffer, BIOS_SIZE);
 | |
| 
 | |
| 	for (x = 0; x < BIOS_SIZE / sizeof(unsigned int); NEXT(x)) {
 | |
| 		if (buffer[x] == MP_SIG) {
 | |
| 			*where = 4;
 | |
| 			*paddr = (x * sizeof(unsigned int)) + BIOS_BASE;
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* search the extended BIOS */
 | |
| 	if (verbose)
 | |
| 		printf(" searching extended BIOS @ 0x%08x\n", BIOS_BASE2);
 | |
| 	seekEntry(BIOS_BASE2);
 | |
| 	readEntry(buffer, BIOS_SIZE);
 | |
| 
 | |
| 	for (x = 0; x < BIOS_SIZE / sizeof(unsigned int); NEXT(x)) {
 | |
| 		if (buffer[x] == MP_SIG) {
 | |
| 			*where = 5;
 | |
| 			*paddr = (x * sizeof(unsigned int)) + BIOS_BASE2;
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (grope) {
 | |
| 		/* search additional memory */
 | |
| 		target = GROPE_AREA1;
 | |
| 		if (verbose)
 | |
| 			printf(" groping memory @ 0x%08x\n", target);
 | |
| 		seekEntry(target);
 | |
| 		readEntry(buffer, GROPE_SIZE);
 | |
| 
 | |
| 		for (x = 0; x < GROPE_SIZE / sizeof(unsigned int); NEXT(x)) {
 | |
| 			if (buffer[x] == MP_SIG) {
 | |
| 				*where = 6;
 | |
| 				*paddr =
 | |
| 				    (x * sizeof(unsigned int)) + GROPE_AREA1;
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		target = GROPE_AREA2;
 | |
| 		if (verbose)
 | |
| 			printf(" groping memory @ 0x%08x\n", target);
 | |
| 		seekEntry(target);
 | |
| 		readEntry(buffer, GROPE_SIZE);
 | |
| 
 | |
| 		for (x = 0; x < GROPE_SIZE / sizeof(unsigned int); NEXT(x)) {
 | |
| 			if (buffer[x] == MP_SIG) {
 | |
| 				*where = 7;
 | |
| 				*paddr =
 | |
| 				    (x * sizeof(unsigned int)) + GROPE_AREA2;
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	*where = 0;
 | |
| 	*paddr = (vm_offset_t) 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void MPFloatingPointer(vm_offset_t paddr, int where, mpfps_t * mpfps)
 | |
| {
 | |
| 
 | |
| 	/* read in mpfps structure */
 | |
| 	seekEntry(paddr);
 | |
| 	readEntry(mpfps, sizeof(mpfps_t));
 | |
| 
 | |
| 	/* show its contents */
 | |
| 	if (verbose) {
 | |
| 		printf("MP Floating Pointer Structure:\n\n");
 | |
| 
 | |
| 		printf("  location:\t\t\t");
 | |
| 		switch (where) {
 | |
| 		case 1:
 | |
| 			printf("EBDA\n");
 | |
| 			break;
 | |
| 		case 2:
 | |
| 			printf("BIOS base memory\n");
 | |
| 			break;
 | |
| 		case 3:
 | |
| 			printf("DEFAULT base memory (639K)\n");
 | |
| 			break;
 | |
| 		case 4:
 | |
| 			printf("BIOS\n");
 | |
| 			break;
 | |
| 		case 5:
 | |
| 			printf("Extended BIOS\n");
 | |
| 			break;
 | |
| 
 | |
| 		case 0:
 | |
| 			printf("NOT found!\n");
 | |
| 			exit(1);
 | |
| 		default:
 | |
| 			printf("BOGUS!\n");
 | |
| 			exit(1);
 | |
| 		}
 | |
| 		printf("  physical address:\t\t0x%08x\n", paddr);
 | |
| 
 | |
| 		printf("  signature:\t\t\t'");
 | |
| 		pnstr(mpfps->signature, 4);
 | |
| 		printf("'\n");
 | |
| 
 | |
| 		printf("  length:\t\t\t%d bytes\n", mpfps->length * 16);
 | |
| 		printf("  version:\t\t\t1.%1d\n", mpfps->spec_rev);
 | |
| 		printf("  checksum:\t\t\t0x%02x\n", mpfps->checksum);
 | |
| 
 | |
| 		/* bits 0:6 are RESERVED */
 | |
| 		if (mpfps->mpfb2 & 0x7f) {
 | |
| 			printf(" warning, MP feature byte 2: 0x%02x\n",
 | |
| 			       mpfps->mpfb2);
 | |
| 		}
 | |
| 
 | |
| 		/* bit 7 is IMCRP */
 | |
| 		printf("  mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ?
 | |
| 		       "PIC" : "Virtual Wire");
 | |
| 
 | |
| 		/* MP feature bytes 3-5 are expected to be ZERO */
 | |
| 		if (mpfps->mpfb3)
 | |
| 			printf(" warning, MP feature byte 3 NONZERO!\n");
 | |
| 		if (mpfps->mpfb4)
 | |
| 			printf(" warning, MP feature byte 4 NONZERO!\n");
 | |
| 		if (mpfps->mpfb5)
 | |
| 			printf(" warning, MP feature byte 5 NONZERO!\n");
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void MPConfigDefault(int featureByte)
 | |
| {
 | |
| 	printf("  MP default config type: %d\n\n", featureByte);
 | |
| 	switch (featureByte) {
 | |
| 	case 1:
 | |
| 		printf("   bus: ISA, APIC: 82489DX\n");
 | |
| 		break;
 | |
| 	case 2:
 | |
| 		printf("   bus: EISA, APIC: 82489DX\n");
 | |
| 		break;
 | |
| 	case 3:
 | |
| 		printf("   bus: EISA, APIC: 82489DX\n");
 | |
| 		break;
 | |
| 	case 4:
 | |
| 		printf("   bus: MCA, APIC: 82489DX\n");
 | |
| 		break;
 | |
| 	case 5:
 | |
| 		printf("   bus: ISA+PCI, APIC: Integrated\n");
 | |
| 		break;
 | |
| 	case 6:
 | |
| 		printf("   bus: EISA+PCI, APIC: Integrated\n");
 | |
| 		break;
 | |
| 	case 7:
 | |
| 		printf("   bus: MCA+PCI, APIC: Integrated\n");
 | |
| 		break;
 | |
| 	default:
 | |
| 		printf("   future type\n");
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	switch (featureByte) {
 | |
| 	case 1:
 | |
| 	case 2:
 | |
| 	case 3:
 | |
| 	case 4:
 | |
| 		nbus = 1;
 | |
| 		break;
 | |
| 	case 5:
 | |
| 	case 6:
 | |
| 	case 7:
 | |
| 		nbus = 2;
 | |
| 		break;
 | |
| 	default:
 | |
| 		printf("   future type\n");
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	ncpu = 2;
 | |
| 	napic = 1;
 | |
| 	nintr = 16;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void MPConfigTableHeader(uint32_t pap)
 | |
| {
 | |
| 	vm_offset_t paddr;
 | |
| 	mpcth_t cth;
 | |
| 	int x;
 | |
| 	int totalSize;
 | |
| 	int count, c;
 | |
| 	int type;
 | |
| 
 | |
| 	if (pap == 0) {
 | |
| 		printf("MP Configuration Table Header MISSING!\n");
 | |
| 		exit(1);
 | |
| 	}
 | |
| 
 | |
| 	/* convert physical address to virtual address */
 | |
| 	paddr = (vm_offset_t) pap;
 | |
| 
 | |
| 	/* read in cth structure */
 | |
| 	seekEntry(paddr);
 | |
| 	readEntry(&cth, sizeof(cth));
 | |
| 
 | |
| 	if (verbose) {
 | |
| 		printf("MP Config Table Header:\n\n");
 | |
| 
 | |
| 		printf("  physical address:\t\t0x%08x\n", pap);
 | |
| 
 | |
| 		printf("  signature:\t\t\t'");
 | |
| 		pnstr(cth.signature, 4);
 | |
| 		printf("'\n");
 | |
| 
 | |
| 		printf("  base table length:\t\t%d\n", cth.base_table_length);
 | |
| 
 | |
| 		printf("  version:\t\t\t1.%1d\n", cth.spec_rev);
 | |
| 		printf("  checksum:\t\t\t0x%02x\n", cth.checksum);
 | |
| 
 | |
| 		printf("  OEM ID:\t\t\t'");
 | |
| 		pnstr(cth.oem_id, 8);
 | |
| 		printf("'\n");
 | |
| 
 | |
| 		printf("  Product ID:\t\t\t'");
 | |
| 		pnstr(cth.product_id, 12);
 | |
| 		printf("'\n");
 | |
| 
 | |
| 		printf("  OEM table pointer:\t\t0x%08x\n",
 | |
| 		       cth.oem_table_pointer);
 | |
| 		printf("  OEM table size:\t\t%d\n", cth.oem_table_size);
 | |
| 
 | |
| 		printf("  entry count:\t\t\t%d\n", cth.entry_count);
 | |
| 
 | |
| 		printf("  local APIC address:\t\t0x%08x\n", cth.apic_address);
 | |
| 
 | |
| 		printf("  extended table length:\t%d\n",
 | |
| 		       cth.extended_table_length);
 | |
| 		printf("  extended table checksum:\t%d\n",
 | |
| 		       cth.extended_table_checksum);
 | |
| 	}
 | |
| 
 | |
| 	totalSize = cth.base_table_length - sizeof(struct MPCTH);
 | |
| 	count = cth.entry_count;
 | |
| 
 | |
| 	if (verbose) {
 | |
| 		if (verbose)
 | |
| 			puts(SEP_LINE);
 | |
| 
 | |
| 		printf("MP Config Base Table Entries:\n\n");
 | |
| 	}
 | |
| 
 | |
| 	/* initialze tables */
 | |
| 	for(x = 0; x < ARRAY_SIZE(busses); x++)
 | |
| 		busses[x] = UNKNOWN_BUSTYPE;
 | |
| 	for(x = 0; x < ARRAY_SIZE(apics); x++)
 | |
| 		apics[x] = 0xff;
 | |
| 
 | |
| 	ncpu = 0;
 | |
| 	nbus = 0;
 | |
| 	napic = 0;
 | |
| 	nintr = 0;
 | |
| 
 | |
| 	/* process all the CPUs */
 | |
| 	if (verbose) {
 | |
| 		printf("--\nProcessors:\tAPIC ID\tVersion\tState"
 | |
| 		       "\t\tFamily\tModel\tStep\tFlags\n");
 | |
| 	}
 | |
| 	for (c = count; c; c--) {
 | |
| 		if (readType() == 0)
 | |
| 			processorEntry();
 | |
| 		totalSize -= basetableEntryTypes[0].length;
 | |
| 	}
 | |
| 
 | |
| 	/* process all the busses */
 | |
| 	printf("\t/* Bus: Bus ID  Type */\n");
 | |
| 	for (c = count; c; c--) {
 | |
| 		if (readType() == 1)
 | |
| 			busEntry();
 | |
| 		totalSize -= basetableEntryTypes[1].length;
 | |
| 	}
 | |
| 
 | |
| 	/* process all the apics */
 | |
| 	printf("\t/* I/O APICs: APIC ID  Version  State  Address */\n");
 | |
| 	for (c = count; c; c--) {
 | |
| 		if (readType() == 2)
 | |
| 			ioApicEntry();
 | |
| 		totalSize -= basetableEntryTypes[2].length;
 | |
| 	}
 | |
| 
 | |
| 	/* process all the I/O Ints */
 | |
| 	printf("\t/* I/O Ints: Type  Polarity  Trigger  Bus ID  IRQ  APIC ID  PIN#*/ \n");
 | |
| 	for (c = count; c; c--) {
 | |
| 		if (readType() == 3)
 | |
| 			intEntry();
 | |
| 		totalSize -= basetableEntryTypes[3].length;
 | |
| 	}
 | |
| 
 | |
| 	/* process all the Local Ints */
 | |
| 	printf
 | |
| 	    ("\t/* Local Ints: Type  Polarity  Trigger  Bus ID  IRQ  APIC ID  PIN# */\n");
 | |
| 	for (c = count; c; c--) {
 | |
| 		if (readType() == 4)
 | |
| 			lintEntry();
 | |
| 		totalSize -= basetableEntryTypes[4].length;
 | |
| 	}
 | |
| 
 | |
| #if defined( EXTENDED_PROCESSING_READY )
 | |
| 	/* process any extended data */
 | |
| 	if ((totalSize = cth.extended_table_length)) {
 | |
| 		if (verbose)
 | |
| 			puts(SEP_LINE);
 | |
| 
 | |
| 		printf("MP Config Extended Table Entries:\n\n");
 | |
| 
 | |
| 		while (totalSize > 0) {
 | |
| 			switch (type = readType()) {
 | |
| 			case 128:
 | |
| 				sasEntry();
 | |
| 				break;
 | |
| 			case 129:
 | |
| 				bhdEntry();
 | |
| 				break;
 | |
| 			case 130:
 | |
| 				cbasmEntry();
 | |
| 				break;
 | |
| 			default:
 | |
| 				printf("Extended Table HOSED!\n");
 | |
| 				exit(1);
 | |
| 			}
 | |
| 
 | |
| 			totalSize -= extendedtableEntryTypes[type - 128].length;
 | |
| 		}
 | |
| 	}
 | |
| #endif				/* EXTENDED_PROCESSING_READY */
 | |
| 
 | |
| 	/* process any OEM data */
 | |
| 	if (cth.oem_table_pointer && (cth.oem_table_size > 0)) {
 | |
| #if defined( OEM_PROCESSING_READY )
 | |
| #error your on your own here!
 | |
| 		/* convert OEM table pointer to virtual address */
 | |
| 		poemtp = (vm_offset_t) cth.oem_table_pointer;
 | |
| 
 | |
| 		/* read in oem table structure */
 | |
| 		if ((oemdata = (void *)malloc(cth.oem_table_size)) == NULL)
 | |
| 			err(1, "oem malloc");
 | |
| 
 | |
| 		seekEntry(poemtp);
 | |
| 		readEntry(oemdata, cth.oem_table_size);
 | |
| 
 | |
| 	/** process it */
 | |
| 
 | |
| 		free(oemdata);
 | |
| #else
 | |
| 		printf
 | |
| 		    ("\nyou need to modify the source to handle OEM data!\n\n");
 | |
| #endif				/* OEM_PROCESSING_READY */
 | |
| 	}
 | |
| 
 | |
| 	fflush(stdout);
 | |
| 
 | |
| #if defined( RAW_DUMP )
 | |
| 	{
 | |
| 		int ofd;
 | |
| 		u_char dumpbuf[4096];
 | |
| 
 | |
| 		ofd = open("/tmp/mpdump", O_CREAT | O_RDWR);
 | |
| 		seekEntry(paddr);
 | |
| 		readEntry(dumpbuf, 1024);
 | |
| 		write(ofd, dumpbuf, 1024);
 | |
| 		close(ofd);
 | |
| 	}
 | |
| #endif				/* RAW_DUMP */
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static int readType(void)
 | |
| {
 | |
| 	u_char type;
 | |
| 
 | |
| 	if (read(pfd, &type, sizeof(u_char)) != sizeof(u_char))
 | |
| 		err(1, "type read; pfd: %d", pfd);
 | |
| 
 | |
| 	if (lseek(pfd, -1, SEEK_CUR) < 0)
 | |
| 		err(1, "type seek");
 | |
| 
 | |
| 	return (int)type;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void seekEntry(vm_offset_t addr)
 | |
| {
 | |
| 	if (lseek(pfd, (off_t) addr, SEEK_SET) < 0)
 | |
| 		err(1, "/dev/mem seek");
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void readEntry(void *entry, int size)
 | |
| {
 | |
| 	if (read(pfd, entry, size) != size)
 | |
| 		err(1, "readEntry");
 | |
| }
 | |
| 
 | |
| static void processorEntry(void)
 | |
| {
 | |
| 	ProcEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	/* count it */
 | |
| 	++ncpu;
 | |
| 	if (noisy) {
 | |
| 		printf("\t\t%2d", entry.apicID);
 | |
| 		printf("\t 0x%2x", entry.apicVersion);
 | |
| 
 | |
| 		printf("\t %s, %s",
 | |
| 		       (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
 | |
| 		       (entry.
 | |
| 			cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable");
 | |
| 
 | |
| 		printf("\t %d\t %d\t %d",
 | |
| 		       (entry.cpuSignature >> 8) & 0x0f,
 | |
| 		       (entry.cpuSignature >> 4) & 0x0f,
 | |
| 		       entry.cpuSignature & 0x0f);
 | |
| 
 | |
| 		printf("\t 0x%04x\n", entry.featureFlags);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static int lookupBusType(char *name)
 | |
| {
 | |
| 	int x;
 | |
| 
 | |
| 	for (x = 0; x < MAX_BUSTYPE; ++x)
 | |
| 		if (strcmp(busTypeTable[x].name, name) == 0)
 | |
| 			return busTypeTable[x].type;
 | |
| 
 | |
| 	return UNKNOWN_BUSTYPE;
 | |
| }
 | |
| 
 | |
| static void busEntry(void)
 | |
| {
 | |
| 	char name[8];
 | |
| 	BusEntry entry;
 | |
| 	int i;
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	/* count it */
 | |
| 	++nbus;
 | |
| 
 | |
| 	if (verbose) {
 | |
| 		printf("\t\t%2d", entry.busID);
 | |
| 		printf("\t ");
 | |
| 		pnstr(entry.busType, 6);
 | |
| 		printf("\n");
 | |
| 	}
 | |
| 
 | |
| 	memset(name, '\0', sizeof(name));
 | |
| 	for(i = 0; i < 6; i++) {
 | |
| 		switch(entry.busType[i]) {
 | |
| 		case ' ':
 | |
| 		case '\0':
 | |
| 			break;
 | |
| 		default:
 | |
| 			name[i] = entry.busType[i];
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (entry.busID > ARRAY_SIZE(busses)) {
 | |
| 		fprintf(stderr, "busses array to small!\n");
 | |
| 		exit(1);
 | |
| 	}
 | |
| 
 | |
| 	busses[entry.busID] = lookupBusType(name);
 | |
| 	printf("\tsmp_write_bus(mc, %d, \"", entry.busID);
 | |
| 	pnstr(entry.busType, 6);
 | |
| 	printf("\");\n");
 | |
| }
 | |
| 
 | |
| static void ioApicEntry(void)
 | |
| {
 | |
| 	IOApicEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	/* count it */
 | |
| 	++napic;
 | |
| 
 | |
| 	if (noisy) {
 | |
| 		printf("\t\t%2d", entry.apicID);
 | |
| 		printf("\t 0x%02x", entry.apicVersion);
 | |
| 		printf("\t %s",
 | |
| 		       (entry.
 | |
| 			apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" :
 | |
| 		       "unusable");
 | |
| 		printf("\t\t 0x%x\n", entry.apicAddress);
 | |
| 	}
 | |
| 
 | |
| 	apics[entry.apicID] = entry.apicID;
 | |
| 
 | |
| 	if (entry.apicFlags & IOAPICENTRY_FLAG_EN)
 | |
| 		printf("\tsmp_write_ioapic(mc, 0x%x, 0x%x, 0x%x);\n",
 | |
| 		       entry.apicID, entry.apicVersion, entry.apicAddress);
 | |
| }
 | |
| 
 | |
| char *intTypes[] = {
 | |
| 	"mp_INT", "mp_NMI", "mp_SMI", "mp_ExtINT"
 | |
| };
 | |
| 
 | |
| char *polarityMode[] = {
 | |
| 	"MP_IRQ_POLARITY_DEFAULT", "MP_IRQ_POLARITY_HIGH", "reserved",
 | |
| 	    "MP_IRQ_POLARITY_LOW"
 | |
| };
 | |
| 
 | |
| char *triggerMode[] = {
 | |
| 	"MP_IRQ_TRIGGER_DEFAULT", "MP_IRQ_TRIGGER_EDGE", "reserved",
 | |
| 	    "MP_IRQ_TRIGGER_LEVEL"
 | |
| };
 | |
| 
 | |
| static void intEntry(void)
 | |
| {
 | |
| 	IntEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	/* count it */
 | |
| 	if ((int)entry.type == 3)
 | |
| 		++nintr;
 | |
| 
 | |
| 	if (noisy) {
 | |
| 		printf("\n\t\t%s", intTypes[(int)entry.intType]);
 | |
| 
 | |
| 		printf("\t%9s", polarityMode[(int)entry.intFlags & 0x03]);
 | |
| 		printf("%12s", triggerMode[((int)entry.intFlags >> 2) & 0x03]);
 | |
| 
 | |
| 		printf("\t %5d", (int)entry.srcBusID);
 | |
| 		if (busses[(int)entry.srcBusID] == PCI)
 | |
| 			printf("\t%2d:%c",
 | |
| 			       ((int)entry.srcBusIRQ >> 2) & 0x1f,
 | |
| 			       ((int)entry.srcBusIRQ & 0x03) + 'A');
 | |
| 		else
 | |
| 			printf("\t 0x%x:0x%x(0x%x)",
 | |
| 			       (int)entry.srcBusIRQ >> 2,
 | |
| 			       (int)entry.srcBusIRQ & 3, (int)entry.srcBusIRQ);
 | |
| 		printf("\t %6d", (int)entry.dstApicID);
 | |
| 		printf("\t %3d\n", (int)entry.dstApicINT);
 | |
| 	}
 | |
| 
 | |
| 	if (busses[(int)entry.srcBusID] == PCI) {
 | |
| 		printf("\tsmp_write_intsrc(mc, %s, %s|%s, 0x%x, (0x%02x << 2) | INT%c, 0x%x, 0x%x);\n",
 | |
| 		       intTypes[(int)entry.intType],
 | |
| 		       triggerMode[((int)entry.intFlags >> 2) & 0x03],
 | |
| 		       polarityMode[(int)entry.intFlags & 0x03],
 | |
| 		       (int)entry.srcBusID,
 | |
| 		       (int)entry.srcBusIRQ >> 2,
 | |
| 		       ((int)entry.srcBusIRQ & 3) + 'A',
 | |
| 		       (int)entry.dstApicID, (int)entry.dstApicINT);
 | |
| 	} else {
 | |
| 		printf("\tsmp_write_intsrc(mc, %s, %s|%s, 0x%x, 0x%x, 0x%x, 0x%x);\n",
 | |
| 		       intTypes[(int)entry.intType],
 | |
| 		       triggerMode[((int)entry.intFlags >> 2) & 0x03],
 | |
| 		       polarityMode[(int)entry.intFlags & 0x03],
 | |
| 		       (int)entry.srcBusID,
 | |
| 		       (int)entry.srcBusIRQ,
 | |
| 		       (int)entry.dstApicID, (int)entry.dstApicINT);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void lintEntry(void)
 | |
| {
 | |
| 	IntEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	/* count it */
 | |
| 	if ((int)entry.type == 3)
 | |
| 		++nintr;
 | |
| 
 | |
| 	if (noisy) {
 | |
| 		printf("\t\t%s", intTypes[(int)entry.intType]);
 | |
| 
 | |
| 		printf("\t%9s", polarityMode[(int)entry.intFlags & 0x03]);
 | |
| 		printf("%12s", triggerMode[((int)entry.intFlags >> 2) & 0x03]);
 | |
| 
 | |
| 		printf("\t %5d", (int)entry.srcBusID);
 | |
| 		if (busses[(int)entry.srcBusID] == PCI)
 | |
| 			printf("\t%2d:%c",
 | |
| 			       ((int)entry.srcBusIRQ >> 2) & 0x1f,
 | |
| 			       ((int)entry.srcBusIRQ & 0x03) + 'A');
 | |
| 		else
 | |
| 			printf("\t %3d", (int)entry.srcBusIRQ);
 | |
| 		printf("\t %6d", (int)entry.dstApicID);
 | |
| 		printf("\t %3d\n", (int)entry.dstApicINT);
 | |
| 	}
 | |
| 	printf
 | |
| 	    ("\tsmp_write_lintsrc(mc, %s, %s|%s, 0x%x, 0x%x, MP_APIC_ALL, 0x%x);\n",
 | |
| 	     intTypes[(int)entry.intType],
 | |
| 	     triggerMode[((int)entry.intFlags >> 2) & 0x03],
 | |
| 	     polarityMode[(int)entry.intFlags & 0x03], (int)entry.srcBusID,
 | |
| 	     (int)entry.srcBusIRQ, (int)entry.dstApicINT);
 | |
| 
 | |
| }
 | |
| 
 | |
| static void sasEntry(void)
 | |
| {
 | |
| 	SasEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	printf("--\n%s\n", extendedtableEntryTypes[entry.type - 128].name);
 | |
| 	printf(" bus ID: %d", entry.busID);
 | |
| 	printf(" address type: ");
 | |
| 	switch (entry.addressType) {
 | |
| 	case 0:
 | |
| 		printf("I/O address\n");
 | |
| 		break;
 | |
| 	case 1:
 | |
| 		printf("memory address\n");
 | |
| 		break;
 | |
| 	case 2:
 | |
| 		printf("prefetch address\n");
 | |
| 		break;
 | |
| 	default:
 | |
| 		printf("UNKNOWN type\n");
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	printf(" address base: 0x%lx\n", entry.addressBase);
 | |
| 	printf(" address range: 0x%lx\n", entry.addressLength);
 | |
| }
 | |
| 
 | |
| static void bhdEntry(void)
 | |
| {
 | |
| 	BhdEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	printf("--\n%s\n", extendedtableEntryTypes[entry.type - 128].name);
 | |
| 	printf(" bus ID: %d", entry.busID);
 | |
| 	printf(" bus info: 0x%02x", entry.busInfo);
 | |
| 	printf(" parent bus ID: %d", entry.busParent);
 | |
| }
 | |
| 
 | |
| static void cbasmEntry(void)
 | |
| {
 | |
| 	CbasmEntry entry;
 | |
| 
 | |
| 	/* read it into local memory */
 | |
| 	readEntry(&entry, sizeof(entry));
 | |
| 
 | |
| 	printf("--\n%s\n", extendedtableEntryTypes[entry.type - 128].name);
 | |
| 	printf(" bus ID: %d", entry.busID);
 | |
| 	printf(" address modifier: %s\n", (entry.addressMod & 0x01) ?
 | |
| 	       "subtract" : "add");
 | |
| 	printf(" predefined range: 0x%08x", entry.predefinedRange);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * do a dmesg output
 | |
|  */
 | |
| static void doDmesg(void)
 | |
| {
 | |
| 	if (verbose)
 | |
| 		puts(SEP_LINE);
 | |
| 
 | |
| 	printf("dmesg output:\n\n");
 | |
| 	fflush(stdout);
 | |
| 	system("dmesg");
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *  build "options" entries for the kernel config file
 | |
|  */
 | |
| static void doOptionList(void)
 | |
| {
 | |
| 	if (verbose)
 | |
| 		puts(SEP_LINE);
 | |
| 
 | |
| 	printf("# SMP kernel config file options:\n\n");
 | |
| 	printf("\n# Required:\n");
 | |
| 	printf("options		SMP\t\t\t# Symmetric MultiProcessor Kernel\n");
 | |
| 	printf("options		APIC_IO\t\t\t# Symmetric (APIC) I/O\n");
 | |
| 
 | |
| 	printf("\n# Optional (built-in defaults will work in most cases):\n");
 | |
| 	printf("#options		NCPU=%d\t\t\t# number of CPUs\n", ncpu);
 | |
| 	printf("#options		NBUS=%d\t\t\t# number of busses\n",
 | |
| 	       nbus);
 | |
| 	printf("#options		NAPIC=%d\t\t\t# number of IO APICs\n",
 | |
| 	       napic);
 | |
| 	printf("#options		NINTR=%d\t\t# number of INTs\n",
 | |
| 	       (nintr < 24) ? 24 : nintr);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| static void pnstr(uint8_t * s, int c)
 | |
| {
 | |
| 	uint8_t string[MAXPNSTR + 1];
 | |
| 
 | |
| 	if (c > MAXPNSTR)
 | |
| 		c = MAXPNSTR;
 | |
| 	strncpy((char *)string, (char *)s, c);
 | |
| 	string[c] = '\0';
 | |
| 	printf("%s", string);
 | |
| }
 |