Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Sep 2002 00:21:35 -0700 (PDT)
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 17835 for review
Message-ID:  <200209210721.g8L7LZT7077163@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=17835

Change 17835 by peter@peter_overcee on 2002/09/21 00:21:20

	gut the pcibios code. We cannot use it in any form on hammer.
	("MUST NOT call the bios after starting long mode")

Affected files ...

.. //depot/projects/hammer/sys/x86_64/pci/pci_cfgreg.c#3 edit

Differences ...

==== //depot/projects/hammer/sys/x86_64/pci/pci_cfgreg.c#3 (text+ko) ====

@@ -26,7 +26,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/pci/pci_cfgreg.c,v 1.94 2002/09/20 19:16:41 jhb Exp $
- *
  */
 
 #include <sys/param.h>		/* XXX trim includes */
@@ -42,87 +41,16 @@
 #include <dev/pci/pcireg.h>
 #include <isa/isavar.h>
 #include <machine/pci_cfgreg.h>
-#include <machine/segments.h>
-#include <machine/pc/bios.h>
 
 #include "pcib_if.h"
 
-#define PRVERB(a) printf a
-
 static int cfgmech;
 static int devmax;
-static int usebios;
-static int enable_pcibios = 0;
-
-TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios);
 
-static int	pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
-static int	pci_cfgintr_unique(struct PIR_entry *pe, int pin);
-static int	pci_cfgintr_linked(struct PIR_entry *pe, int pin);
-static int	pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
-static int	pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
-
-static void	pci_print_irqmask(u_int16_t irqs);
-static void	pci_print_route_table(struct PIR_table *prt, int size);
-static int	pcibios_cfgread(int bus, int slot, int func, int reg, int bytes);
-static void	pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
-static int	pcibios_cfgopen(void);
 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
 static int	pcireg_cfgopen(void);
 
-static struct PIR_table *pci_route_table;
-static int pci_route_count;
-
-/*
- * Some BIOS writers seem to want to ignore the spec and put
- * 0 in the intline rather than 255 to indicate none.  Some use
- * numbers in the range 128-254 to indicate something strange and
- * apparently undocumented anywhere.  Assume these are completely bogus
- * and map them to 255, which means "none".
- */
-static __inline__ int 
-pci_i386_map_intline(int line)
-{
-	if (line == 0 || line >= 128)
-		return (PCI_INVALID_IRQ);
-	return (line);
-}
-
-int
-pci_pcibios_active(void)
-{
-	return (usebios);
-}
-
-int
-pci_kill_pcibios(void)
-{
-	usebios = 0;
-	return (pcireg_cfgopen() != 0);
-}
-
-static u_int16_t
-pcibios_get_version(void)
-{
-	struct bios_regs args;
-
-	if (PCIbios.ventry == 0) {
-		PRVERB(("pcibios: No call entry point\n"));
-		return (0);
-	}
-	args.eax = PCIBIOS_BIOS_PRESENT;
-	if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
-		PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
-		return (0);
-	}
-	if (args.edx != 0x20494350) {
-		PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
-		return (0);
-	}
-	return (args.ebx & 0xffff);
-}
-
 /* 
  * Initialise access to PCI configuration space 
  */
@@ -130,56 +58,13 @@
 pci_cfgregopen(void)
 {
 	static int		opened = 0;
-	u_long			sigaddr;
-	static struct PIR_table	*pt;
-	u_int8_t		ck, *cv;
-	int			i;
 
 	if (opened)
-		return(1);
-
-	if (pcibios_cfgopen() != 0)
-		usebios = 1;
-	else if (pcireg_cfgopen() != 0)
-		usebios = 0;
-	else
-		return(0);
-
-	/*
-	 * Look for the interrupt routing table.
-	 *
-	 * We use PCI BIOS's PIR table if it's available $PIR is the
-	 * standard way to do this.  Sadly, some machines are not
-	 * standards conforming and have _PIR instead.  We shrug and cope
-	 * by looking for both.
-	 */
-	if (pcibios_get_version() >= 0x0210 && pt == NULL) {
-		sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0);
-		if (sigaddr == 0)
-			sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0);
-		if (sigaddr != 0) {
-			pt = (struct PIR_table *)(uintptr_t)
-			    BIOS_PADDRTOVADDR(sigaddr);
-			for (cv = (u_int8_t *)pt, ck = 0, i = 0;
-			     i < (pt->pt_header.ph_length); i++) {
-				ck += cv[i];
-			}
-			if (ck == 0 && pt->pt_header.ph_length >
-			    sizeof(struct PIR_header)) {
-				pci_route_table = pt;
-				pci_route_count = (pt->pt_header.ph_length -
-				    sizeof(struct PIR_header)) / 
-				    sizeof(struct PIR_entry);
-				printf("Using $PIR table, %d entries at %p\n",
-				    pci_route_count, pci_route_table);
-				if (bootverbose)
-					pci_print_route_table(pci_route_table,
-					    pci_route_count);
-			}
-		}
-	}
+		return (1);
+	if (pcireg_cfgopen() == 0)
+		return (0);
 	opened = 1;
-	return(1);
+	return (1);
 }
 
 /* 
@@ -188,9 +73,8 @@
 static u_int32_t
 pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
 {
-	return(usebios ? 
-	    pcibios_cfgread(bus, slot, func, reg, bytes) : 
-	    pcireg_cfgread(bus, slot, func, reg, bytes));
+
+	return (pcireg_cfgread(bus, slot, func, reg, bytes);
 }
 
 u_int32_t
@@ -200,14 +84,19 @@
 
 	/*
 	 * Some BIOS writers seem to want to ignore the spec and put
-	 * 0 in the intline rather than 255 to indicate none.  The rest of
-	 * the code uses 255 as an invalid IRQ.
+	 * 0 in the intline rather than 255 to indicate none.  Some use
+	 * numbers in the range 128-254 to indicate something strange and
+	 * apparently undocumented anywhere.  Assume these are completely bogus
+	 * and map them to 255, which the rest of the PCI code recognizes as
+	 * as an invalid IRQ.
 	 */
 	if (reg == PCIR_INTLINE && bytes == 1) {
 		line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
-		return pci_i386_map_intline(line);
+		if (line == 0 || line >= 128)
+			line = PCI_INVALID_IRQ;
+		return (line);
 	}
-	return(pci_do_cfgregread(bus, slot, func, reg, bytes));
+	return (pci_do_cfgregread(bus, slot, func, reg, bytes));
 }
 
 /* 
@@ -216,410 +105,22 @@
 void
 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
 {
-    return (usebios ? 
-	pcibios_cfgwrite(bus, slot, func, reg, data, bytes) : 
-	pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
+
+	return (pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
 }
 
 /*
  * Route a PCI interrupt
- *
- * XXX we don't do anything "right" with the function number in the PIR table
- *     (because the consumer isn't currently passing it in).  We don't care
- *     anyway, due to the way PCI interrupts are assigned.
  */
 int
 pci_cfgintr(int bus, int device, int pin, int oldirq)
 {
-	struct PIR_entry	*pe;
-	int			i, irq;
-	struct bios_regs	args;
-	u_int16_t		v;
-	int already = 0;
-    
-	v = pcibios_get_version();
-	if (v < 0x0210) {
-		PRVERB((
-		"pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
-		    (v & 0xff00) >> 8, v & 0xff));
-		return (PCI_INVALID_IRQ);
-	}
-	if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
-	    (pin < 1) || (pin > 4))
-		return(PCI_INVALID_IRQ);
 
-	/*
-	 * Scan the entry table for a contender
-	 */
-	for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; 
-	     i++, pe++) {
-		if ((bus != pe->pe_bus) || (device != pe->pe_device))
-			continue;
-		/*
-		 * A link of 0 means that this intpin is not connected to
-		 * any other device's interrupt pins and is not connected to
-		 * any of the Interrupt Router's interrupt pins, so we can't
-		 * route it.
-		 */
-		if (pe->pe_intpin[pin - 1].link == 0)
-			continue;
-
-		if (pci_cfgintr_valid(pe, pin, oldirq)) {
-			printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
-			    device, 'A' + pin - 1, oldirq);
-			return (oldirq);
-		}
-		irq = pci_cfgintr_linked(pe, pin);
-		if (irq == PCI_INVALID_IRQ)
-			irq = pci_cfgintr_unique(pe, pin);
-		if (irq != PCI_INVALID_IRQ)
-			already = 1;
-		if (irq == PCI_INVALID_IRQ)
-			irq = pci_cfgintr_virgin(pe, pin);
-		if (irq == PCI_INVALID_IRQ)
-			break;
-
-		/*
-		 * Ask the BIOS to route the interrupt
-		 */
-		args.eax = PCIBIOS_ROUTE_INTERRUPT;
-		args.ebx = (bus << 8) | (device << 3);
-		/* pin value is 0xa - 0xd */
-		args.ecx = (irq << 8) | (0xa + pin - 1);
-		if (!already &&
-		    bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
-			/*
-			 * XXX if it fails, we should try to smack the router
-			 * hardware directly.
-			 * XXX Also, there may be other choices that we can
-			 * try that will work.
-			 */
-			PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
-			return(PCI_INVALID_IRQ);
-		}
-		printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, 
-		    device, 'A' + pin - 1, irq);
-		return(irq);
-	}
-
-	PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, 
-	    device, 'A' + pin - 1));
-	return(PCI_INVALID_IRQ);
-}
-
-/*
- * Check to see if an existing IRQ setting is valid.
- */
-static int
-pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
-{
-	uint32_t irqmask;
-
-	if (!PCI_INTERRUPT_VALID(irq))
-		return (0);
-	irqmask = pe->pe_intpin[pin - 1].irqs;
-	if (irqmask & (1 << irq)) {
-		PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
-		return (1);
-	}
-	return (0);
-}
-
-/*
- * Look to see if the routing table claims this pin is uniquely routed.
- */
-static int
-pci_cfgintr_unique(struct PIR_entry *pe, int pin)
-{
-	int		irq;
-	uint32_t	irqmask;
-    
-	irqmask = pe->pe_intpin[pin - 1].irqs;
-	if (irqmask != 0 && powerof2(irqmask)) {
-		irq = ffs(irqmask) - 1;
-		PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
-		return(irq);
-	}
-	return(PCI_INVALID_IRQ);
-}
-
-/*
- * Look for another device which shares the same link byte and
- * already has a unique IRQ, or which has had one routed already.
- */
-static int
-pci_cfgintr_linked(struct PIR_entry *pe, int pin)
-{
-	struct PIR_entry	*oe;
-	struct PIR_intpin	*pi;
-	int			i, j, irq;
-
-	/*
-	 * Scan table slots.
-	 */
-	for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count;
-	     i++, oe++) {
-		/* scan interrupt pins */
-		for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
-
-			/* don't look at the entry we're trying to match */
-			if ((pe == oe) && (i == (pin - 1)))
-				continue;
-			/* compare link bytes */
-			if (pi->link != pe->pe_intpin[pin - 1].link)
-				continue;
-			/* link destination mapped to a unique interrupt? */
-			if (pi->irqs != 0 && powerof2(pi->irqs)) {
-				irq = ffs(pi->irqs) - 1;
-				PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
-				    pi->link, irq));
-				return(irq);
-			} 
-
-			/* 
-			 * look for the real PCI device that matches this 
-			 * table entry 
-			 */
-			irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device,
-			    j, pin);
-			if (irq != PCI_INVALID_IRQ)
-				return(irq);
-		}
-	}
-	return(PCI_INVALID_IRQ);
-}
-
-/*
- * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and
- * see if it has already been assigned an interrupt.
- */
-static int
-pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin)
-{
-	devclass_t		pci_devclass;
-	device_t		*pci_devices;
-	int			pci_count;
-	device_t		*pci_children;
-	int			pci_childcount;
-	device_t		*busp, *childp;
-	int			i, j, irq;
-
-	/*
-	 * Find all the PCI busses.
-	 */
-	pci_count = 0;
-	if ((pci_devclass = devclass_find("pci")) != NULL)
-		devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
-
-	/*
-	 * Scan all the PCI busses/devices looking for this one.
-	 */
-	irq = PCI_INVALID_IRQ;
-	for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ);
-	     i++, busp++) {
-		pci_childcount = 0;
-		device_get_children(*busp, &pci_children, &pci_childcount);
-		
-		for (j = 0, childp = pci_children; j < pci_childcount; j++, 
-		    childp++) {
-			if ((pci_get_bus(*childp) == bus) &&
-			    (pci_get_slot(*childp) == device) &&
-			    (pci_get_intpin(*childp) == matchpin)) {
-				irq = pci_i386_map_intline(pci_get_irq(*childp));
-				if (irq != PCI_INVALID_IRQ)
-					PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
-					    pe->pe_intpin[pin - 1].link, irq,
-					    pci_get_bus(*childp),
-					    pci_get_slot(*childp), 
-					    pci_get_function(*childp)));
-				break;
-			}
-		}
-		if (pci_children != NULL)
-			free(pci_children, M_TEMP);
-	}
-	if (pci_devices != NULL)
-		free(pci_devices, M_TEMP);
-	return(irq);
-}
-
-/*
- * Pick a suitable IRQ from those listed as routable to this device.
- */
-static int
-pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
-{
-	int		irq, ibit;
-    
-	/*
-	 * first scan the set of PCI-only interrupts and see if any of these 
-	 * are routable
-	 */ 
-	for (irq = 0; irq < 16; irq++) {
-		ibit = (1 << irq);
-
-		/* can we use this interrupt? */
-		if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
-		    (pe->pe_intpin[pin - 1].irqs & ibit)) {
-			PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
-			return(irq);
-		}
-	}
-    
-	/* life is tough, so just pick an interrupt */
-	for (irq = 0; irq < 16; irq++) {
-		ibit = (1 << irq);
-		if (pe->pe_intpin[pin - 1].irqs & ibit) {
-			PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
-			return(irq);
-		}
-	}
-	return(PCI_INVALID_IRQ);
-}
-
-static void
-pci_print_irqmask(u_int16_t irqs)
-{
-	int i, first;
-
-	if (irqs == 0) {
-		printf("none");
-		return;
-	}
-	first = 1;
-	for (i = 0; i < 16; i++, irqs >>= 1)
-		if (irqs & 1) {
-			if (!first)
-				printf(" ");
-			else
-				first = 0;
-			printf("%d", i);
-		}
-}
-
-/*
- * Dump the contents of a PCI BIOS Interrupt Routing Table to the console.
- */
-static void
-pci_print_route_table(struct PIR_table *prt, int size)
-{
-	struct PIR_entry *entry;
-	struct PIR_intpin *intpin;
-	int i, pin;
-
-	printf("PCI-Only Interrupts: ");
-	pci_print_irqmask(prt->pt_header.ph_pci_irqs);
-	printf("\nLocation  Bus Device Pin  Link  IRQs\n");
-	entry = &prt->pt_entry[0];
-	for (i = 0; i < size; i++, entry++) {
-		intpin = &entry->pe_intpin[0];
-		for (pin = 0; pin < 4; pin++, intpin++)
-			if (intpin->link != 0) {
-				if (entry->pe_slot == 0)
-					printf("embedded ");
-				else
-					printf("slot %-3d ", entry->pe_slot);
-				printf(" %3d  %3d    %c   0x%02x  ",
-				    entry->pe_bus, entry->pe_device,
-				    'A' + pin, intpin->link);
-				pci_print_irqmask(intpin->irqs);
-				printf("\n");
-			}
-	}
-}
-
-/*
- * See if any interrupts for a given PCI bus are routed in the PIR.  Don't
- * even bother looking if the BIOS doesn't support routing anyways.
- */
-int
-pci_probe_route_table(int bus)
-{
-	int i;
-	u_int16_t v;
-
-	v = pcibios_get_version();
-	if (v < 0x0210)
-		return (0);
-	for (i = 0; i < pci_route_count; i++)
-		if (pci_route_table->pt_entry[i].pe_bus == bus)
-			return (1);
-	return (0);
+	printf("pci_cfgintr: can't route an interrupt to %d:%d INT%c without ACPI\n", bus, 
+	    device, 'A' + pin - 1);
+	return (PCI_INVALID_IRQ);
 }
 
-/*
- * Config space access using BIOS functions 
- */
-static int
-pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
-{
-	struct bios_regs args;
-	u_int mask;
-
-	switch(bytes) {
-	case 1:
-		args.eax = PCIBIOS_READ_CONFIG_BYTE;
-		mask = 0xff;
-		break;
-	case 2:
-		args.eax = PCIBIOS_READ_CONFIG_WORD;
-		mask = 0xffff;
-		break;
-	case 4:
-		args.eax = PCIBIOS_READ_CONFIG_DWORD;
-		mask = 0xffffffff;
-		break;
-	default:
-		return(-1);
-	}
-	args.ebx = (bus << 8) | (slot << 3) | func;
-	args.edi = reg;
-	bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
-	/* check call results? */
-	return(args.ecx & mask);
-}
-
-static void
-pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
-{
-	struct bios_regs args;
-
-	switch(bytes) {
-	case 1:
-		args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
-		break;
-	case 2:
-		args.eax = PCIBIOS_WRITE_CONFIG_WORD;
-		break;
-	case 4:
-		args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
-		break;
-	default:
-		return;
-	}
-	args.ebx = (bus << 8) | (slot << 3) | func;
-	args.ecx = data;
-	args.edi = reg;
-	bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
-}
-
-/*
- * Determine whether there is a PCI BIOS present
- */
-static int
-pcibios_cfgopen(void)
-{
-	u_int16_t		v = 0;
-    
-	if (PCIbios.ventry != 0 && enable_pcibios) {
-		v = pcibios_get_version();
-		if (v > 0)
-			printf("pcibios: BIOS version %x.%02x\n",
-			    (v & 0xff00) >> 8, v & 0xff);
-	}
-	return (v > 0);
-}
-
 /* 
  * Configuration space access using direct register operations
  */
@@ -838,4 +339,3 @@
 	devmax = 0;
 	return (cfgmech);
 }
-

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200209210721.g8L7LZT7077163>