PLEASE REVIEW: Adding a pci_if method to facilitate specialized PCI bus drivers

Thomas Moestl t.moestl at tu-bs.de
Fri Jun 13 16:30:41 PDT 2003


Hi,

I've attached a patch that adds a new pci_if method,
assign_interrupt, and makes the PCI code implement and use
it. This is private to the PCI bus and is only used internally (to
find an interrupt of a child device); it is a method so that derived
PCI bus drivers can override it.

This is very useful for the sparc64 OFW PCI bus driver which I will
commit soon, hopefully. On sparc64, there are some on-board devices
which have special interrupt lines. To route their interrupts, we need
not only know the device to route for, but also an interrupt index
which is stored in the firmware for this device, and which is used to
route on bridges instead of the intpin (in other cases, there's even
the complete interrupt number stored there; for devices in PCI slots,
we (usually) can use the intpin).

This requires us to get this firmware property in the OFW PCI bus
driver before routing the interrupt; that can't be done in the pcib
route_interrupt method, since we don't know whether we are routing for
another bridge (where we use whichever index we get passed) or for a
child device (in which case we would need to look at the firmware
property). Currently, the OFW PCI bus driver solves this by providing
a stub version of the alloc_resource method, trapping the cases where
rerouting is required and doing it before calling the generic PCI bus
routine, but that leads to code duplication and is generally a bit
ugly, as we are second-guessing where the PCI bus routines will want
to route an interrupt.

By moving the actual routing in a method which can be overridden, this
can be solved cleanly, while not complicating the generic PCI bus code
by much.

If there are no objections, I would like to commit this soonish.

Thoughts?

Thanks,
	- Thomas

-- 
Thomas Moestl <t.moestl at tu-bs.de>	http://www.tu-bs.de/~y0015675/
              <tmm at FreeBSD.org>		http://people.FreeBSD.org/~tmm/
PGP fingerprint: 1C97 A604 2BD0 E492 51D0  9C0F 1FE6 4F1D 419C 776C
-------------- next part --------------
Index: dev/acpica/acpi_pci.c
===================================================================
RCS file: /vol/ncvs/src/sys/dev/acpica/acpi_pci.c,v
retrieving revision 1.3
diff -u -r1.3 acpi_pci.c
--- dev/acpica/acpi_pci.c	17 Feb 2003 21:20:34 -0000	1.3
+++ dev/acpica/acpi_pci.c	13 Jun 2003 20:57:13 -0000
@@ -111,6 +111,7 @@
 	/* XXX: We should override these two. */
 	DEVMETHOD(pci_get_powerstate,	pci_get_powerstate_method),
 	DEVMETHOD(pci_set_powerstate,	pci_set_powerstate_method),
+	DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
 
 	{ 0, 0 }
 };
Index: dev/cardbus/cardbus.c
===================================================================
RCS file: /vol/ncvs/src/sys/dev/cardbus/cardbus.c,v
retrieving revision 1.38
diff -u -r1.38 cardbus.c
--- dev/cardbus/cardbus.c	18 Feb 2003 21:24:00 -0000	1.38
+++ dev/cardbus/cardbus.c	13 Jun 2003 21:51:29 -0000
@@ -387,6 +387,7 @@
 	DEVMETHOD(pci_disable_io,	pci_disable_io_method),
 	DEVMETHOD(pci_get_powerstate,	pci_get_powerstate_method),
 	DEVMETHOD(pci_set_powerstate,	pci_set_powerstate_method),
+	DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
 
 	{0,0}
 };
Index: dev/pci/pci.c
===================================================================
RCS file: /vol/ncvs/src/sys/dev/pci/pci.c,v
retrieving revision 1.219
diff -u -r1.219 pci.c
--- dev/pci/pci.c	9 Jun 2003 18:08:46 -0000	1.219
+++ dev/pci/pci.c	13 Jun 2003 21:36:01 -0000
@@ -70,7 +70,8 @@
 static int		pci_memen(device_t pcib, int b, int s, int f);
 static int		pci_add_map(device_t pcib, int b, int s, int f, int reg, 
 				    struct resource_list *rl);
-static void		pci_add_resources(device_t pcib, device_t dev);
+static void		pci_add_resources(device_t pcib, device_t bus,
+					  device_t dev);
 static int		pci_probe(device_t dev);
 static int		pci_attach(device_t dev);
 static void		pci_load_vendor_data(void);
@@ -119,6 +120,7 @@
 	DEVMETHOD(pci_disable_io,	pci_disable_io_method),
 	DEVMETHOD(pci_get_powerstate,	pci_get_powerstate_method),
 	DEVMETHOD(pci_set_powerstate,	pci_set_powerstate_method),
+	DEVMETHOD(pci_assign_interrupt,	pci_assign_interrupt_method),
 
 	{ 0, 0 }
 };
@@ -776,7 +778,7 @@
 }
 
 static void
-pci_add_resources(device_t pcib, device_t dev)
+pci_add_resources(device_t pcib, device_t bus, device_t dev)
 {
 	struct pci_devinfo *dinfo = device_get_ivars(dev);
 	pcicfgregs *cfg = &dinfo->cfg;
@@ -805,7 +807,7 @@
 		 * If the re-route fails, then just stick with what we
 		 * have.
 		 */
-		irq = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin);
+		irq = PCI_ASSIGN_INTERRUPT(bus, dev);
 		if (PCI_INTERRUPT_VALID(irq)) {
 			pci_write_config(dev, PCIR_INTLINE, irq, 1);
 			cfg->intline = irq;
@@ -848,7 +850,7 @@
 	pcib = device_get_parent(bus);
 	dinfo->cfg.dev = device_add_child(bus, NULL, -1);
 	device_set_ivars(dinfo->cfg.dev, dinfo);
-	pci_add_resources(pcib, dinfo->cfg.dev);
+	pci_add_resources(pcib, bus, dinfo->cfg.dev);
 	pci_print_verbose(dinfo);
 }
 
@@ -1347,8 +1351,7 @@
 			 */
 			if (!PCI_INTERRUPT_VALID(cfg->intline) &&
 			    (cfg->intpin != 0)) {
-				cfg->intline = PCIB_ROUTE_INTERRUPT(
-				    device_get_parent(dev), child, cfg->intpin);
+				cfg->intline = PCI_ASSIGN_INTERRUPT(dev, child);
 				if (PCI_INTERRUPT_VALID(cfg->intline)) {
 					pci_write_config(child, PCIR_INTLINE,
 					    cfg->intline, 1);
@@ -1468,6 +1471,16 @@
 	    cfg->subvendor, cfg->subdevice, cfg->baseclass, cfg->subclass,
 	    cfg->progif);
 	return (0);
+}
+
+int
+pci_assign_interrupt_method(device_t dev, device_t child)
+{
+	struct pci_devinfo *dinfo = device_get_ivars(child);
+	pcicfgregs *cfg = &dinfo->cfg;
+
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child,
+	    cfg->intpin));
 }
 
 static int
Index: dev/pci/pci_if.m
===================================================================
RCS file: /vol/ncvs/src/sys/dev/pci/pci_if.m,v
retrieving revision 1.5
diff -u -r1.5 pci_if.m
--- dev/pci/pci_if.m	16 Apr 2003 03:15:08 -0000	1.5
+++ dev/pci/pci_if.m	13 Jun 2003 21:06:02 -0000
@@ -77,3 +77,8 @@
 	device_t	child;
 	int		space;
 };
+
+METHOD int assign_interrupt {
+	device_t	dev;
+	device_t	child;
+};
Index: dev/pci/pci_private.h
===================================================================
RCS file: /vol/ncvs/src/sys/dev/pci/pci_private.h,v
retrieving revision 1.8
diff -u -r1.8 pci_private.h
--- dev/pci/pci_private.h	16 Apr 2003 03:15:08 -0000	1.8
+++ dev/pci/pci_private.h	13 Jun 2003 21:41:53 -0000
@@ -72,4 +72,5 @@
 		    char *buf, size_t buflen);
 int		pci_child_pnpinfo_str_method(device_t cbdev, device_t child,
 		    char *buf, size_t buflen);
+int		pci_assign_interrupt_method(device_t dev, device_t child);
 #endif /* _PCI_PRIVATE_H_ */


More information about the freebsd-hackers mailing list