svn commit: r209298 - in head/sys: dev/iicbus dev/ofw powerpc/aim powerpc/booke powerpc/include powerpc/mpc85xx powerpc/ofw powerpc/powermac powerpc/powerpc sparc64/ebus sparc64/isa sparc64/pci

Nathan Whitehorn nwhitehorn at FreeBSD.org
Fri Jun 18 14:06:28 UTC 2010


Author: nwhitehorn
Date: Fri Jun 18 14:06:27 2010
New Revision: 209298
URL: http://svn.freebsd.org/changeset/base/209298

Log:
  Provide for multiple, cascaded PICs on PowerPC systems, and extend the
  OFW interrupt map interface to also return the device's interrupt parent.
  
  MFC after:	8.1-RELEASE

Modified:
  head/sys/dev/iicbus/iiconf.c
  head/sys/dev/ofw/ofw_bus_subr.c
  head/sys/dev/ofw/ofw_bus_subr.h
  head/sys/powerpc/aim/interrupt.c
  head/sys/powerpc/aim/nexus.c
  head/sys/powerpc/booke/interrupt.c
  head/sys/powerpc/include/intr_machdep.h
  head/sys/powerpc/include/ocpbus.h
  head/sys/powerpc/include/openpicvar.h
  head/sys/powerpc/mpc85xx/atpic.c
  head/sys/powerpc/mpc85xx/isa.c
  head/sys/powerpc/mpc85xx/ocpbus.c
  head/sys/powerpc/mpc85xx/ocpbus.h
  head/sys/powerpc/mpc85xx/opic.c
  head/sys/powerpc/mpc85xx/pci_ocp.c
  head/sys/powerpc/ofw/ofw_pcib_pci.c
  head/sys/powerpc/ofw/ofw_pcibus.c
  head/sys/powerpc/powermac/cpcht.c
  head/sys/powerpc/powermac/grackle.c
  head/sys/powerpc/powermac/hrowpic.c
  head/sys/powerpc/powermac/macgpio.c
  head/sys/powerpc/powermac/macio.c
  head/sys/powerpc/powermac/openpic_macio.c
  head/sys/powerpc/powermac/uninorth.c
  head/sys/powerpc/powermac/uninorthpci.c
  head/sys/powerpc/powerpc/intr_machdep.c
  head/sys/powerpc/powerpc/mp_machdep.c
  head/sys/powerpc/powerpc/openpic.c
  head/sys/powerpc/powerpc/pic_if.m
  head/sys/sparc64/ebus/ebus.c
  head/sys/sparc64/isa/ofw_isa.c
  head/sys/sparc64/pci/fire.c
  head/sys/sparc64/pci/ofw_pcib_subr.c
  head/sys/sparc64/pci/psycho.c
  head/sys/sparc64/pci/schizo.c

Modified: head/sys/dev/iicbus/iiconf.c
==============================================================================
--- head/sys/dev/iicbus/iiconf.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/dev/iicbus/iiconf.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -363,7 +363,7 @@ iicbus_transfer(device_t bus, struct iic
 int
 iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
 {
-	int i, error, lenread, lenwrote, nkid;
+	int i, error, lenread, lenwrote, nkid, rpstart, addr;
 	device_t *children, bus;
 
 	if ((error = device_get_children(dev, &children, &nkid)) != 0)
@@ -373,14 +373,38 @@ iicbus_transfer_gen(device_t dev, struct
 		return (EIO);
 	}
 	bus = children[0];
+	rpstart = 0;
 	free(children, M_TEMP);
 	for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
+		addr = msgs[i].slave;
 		if (msgs[i].flags & IIC_M_RD)
-			error = iicbus_block_read(bus, msgs[i].slave,
-			    msgs[i].buf, msgs[i].len, &lenread);
+			addr |= LSB;
 		else
-			error = iicbus_block_write(bus, msgs[i].slave,
-			    msgs[i].buf, msgs[i].len, &lenwrote);
+			addr &= ~LSB;
+
+		if (!(msgs[i].flags & IIC_M_NOSTART)) {
+			if (rpstart)
+				error = iicbus_repeated_start(bus, addr, 0);
+			else
+				error = iicbus_start(bus, addr, 0);
+		}
+
+		if (error)
+			break;
+
+		if (msgs[i].flags & IIC_M_RD)
+			error = iicbus_read(bus, msgs[i].buf, msgs[i].len,
+			    &lenread, IIC_LAST_READ, 0);
+		else
+			error = iicbus_write(bus, msgs[i].buf, msgs[i].len,
+			    &lenwrote, 0);
+
+		if (!(msgs[i].flags & IIC_M_NOSTOP)) {
+			rpstart = 0;
+			iicbus_stop(bus);
+		} else {
+			rpstart = 1;	/* Next message gets repeated start */
+		}
 	}
 	return (error);
 }

Modified: head/sys/dev/ofw/ofw_bus_subr.c
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/dev/ofw/ofw_bus_subr.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -222,7 +222,7 @@ ofw_bus_setup_iinfo(phandle_t node, stru
 int
 ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg,
     int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz,
-    void *maskbuf)
+    phandle_t *iparent, void *maskbuf)
 {
 	int rv;
 
@@ -236,7 +236,7 @@ ofw_bus_lookup_imap(phandle_t node, stru
 		panic("ofw_bus_lookup_imap: could not get reg property");
 	return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc,
 	    ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr,
-	    mintrsz));
+	    mintrsz, iparent));
 }
 
 /*
@@ -259,7 +259,7 @@ ofw_bus_lookup_imap(phandle_t node, stru
 int
 ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
     void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result,
-    int rintrsz)
+    int rintrsz, phandle_t *iparent)
 {
 	phandle_t parent;
 	uint8_t *ref = maskbuf;
@@ -303,6 +303,9 @@ ofw_bus_search_intrmap(void *intr, int i
 		if (bcmp(ref, mptr, physsz + intrsz) == 0) {
 			bcopy(mptr + physsz + intrsz + sizeof(parent),
 			    result, rintrsz);
+
+			if (iparent != NULL)
+				*iparent = parent;
 			return (1);
 		}
 		mptr += tsz;

Modified: head/sys/dev/ofw/ofw_bus_subr.h
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.h	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/dev/ofw/ofw_bus_subr.h	Fri Jun 18 14:06:27 2010	(r209298)
@@ -63,9 +63,12 @@ bus_child_pnpinfo_str_t	ofw_bus_gen_chil
 /* Routines for processing firmware interrupt maps */
 void	ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
 int	ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
-	    void *, int, void *, int, void *);
+	    void *, int, void *, int, phandle_t *, void *);
 int	ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
-	    void *, void *, int);
+	    void *, void *, int, phandle_t *);
+
+/* Helper to get node's interrupt parent */
+void	ofw_bus_find_iparent(phandle_t);
 
 /* Helper routine for checking compat prop */
 int ofw_bus_is_compatible(device_t, const char *);

Modified: head/sys/powerpc/aim/interrupt.c
==============================================================================
--- head/sys/powerpc/aim/interrupt.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/aim/interrupt.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -81,7 +81,7 @@ powerpc_interrupt(struct trapframe *fram
 	switch (framep->exc) {
 	case EXC_EXI:
 		critical_enter();
-		PIC_DISPATCH(pic, framep);
+		PIC_DISPATCH(root_pic, framep);
 		critical_exit();
 		break;
 

Modified: head/sys/powerpc/aim/nexus.c
==============================================================================
--- head/sys/powerpc/aim/nexus.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/aim/nexus.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -208,7 +208,7 @@ nexus_attach(device_t dev)
 	sc = device_get_softc(dev);
 
 	start = 0;
-	end = INTR_VECTORS - 1;
+	end = MAX_PICS*INTR_VECTORS - 1;
 
 	sc->sc_rman.rm_start = start;
 	sc->sc_rman.rm_end = end;

Modified: head/sys/powerpc/booke/interrupt.c
==============================================================================
--- head/sys/powerpc/booke/interrupt.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/booke/interrupt.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -134,7 +134,7 @@ powerpc_extr_interrupt(struct trapframe 
 {
 
 	critical_enter();
-	PIC_DISPATCH(pic, framep);
+	PIC_DISPATCH(root_pic, framep);
 	critical_exit();
 	framep->srr1 &= ~PSL_WE;
 }

Modified: head/sys/powerpc/include/intr_machdep.h
==============================================================================
--- head/sys/powerpc/include/intr_machdep.h	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/include/intr_machdep.h	Fri Jun 18 14:06:27 2010	(r209298)
@@ -29,26 +29,32 @@
 #define	_MACHINE_INTR_MACHDEP_H_
 
 #define	INTR_VECTORS	256
+#define	MAX_PICS	5
+
+#define	IGN_SHIFT	8
+#define	INTR_INTLINE(irq) (irq & ((1 << IGN_SHIFT) - 1))
+#define	INTR_IGN(irq)	(irq >> IGN_SHIFT)
+
+#define	INTR_VEC(pic_id, irq) ((powerpc_ign_lookup(pic_id) << IGN_SHIFT) | irq)
 
 /*
  * Default base address for MSI messages on PowerPC
  */
 #define	MSI_INTEL_ADDR_BASE		0xfee00000
 
-extern device_t pic;
-extern device_t pic8259;
+extern device_t root_pic;
 
 struct trapframe;
 
 driver_filter_t powerpc_ipi_handler;
 
 void	powerpc_register_pic(device_t, u_int);
-void	powerpc_register_8259(device_t);
+int	powerpc_ign_lookup(uint32_t pic_id);
 
 void	powerpc_dispatch_intr(u_int, struct trapframe *);
 int	powerpc_enable_intr(void);
-int	powerpc_setup_intr(const char *, u_int, driver_filter_t,
-    driver_intr_t, void *, enum intr_type, void **);
+int	powerpc_setup_intr(const char *, u_int, driver_filter_t, driver_intr_t,
+	    void *, enum intr_type, void **);
 int	powerpc_teardown_intr(void *);
 int	powerpc_config_intr(int, enum intr_trigger, enum intr_polarity);
 

Modified: head/sys/powerpc/include/ocpbus.h
==============================================================================
--- head/sys/powerpc/include/ocpbus.h	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/include/ocpbus.h	Fri Jun 18 14:06:27 2010	(r209298)
@@ -44,4 +44,8 @@
 #define	OCPBUS_DEVTYPE_I2C	7
 #define	OCPBUS_DEVTYPE_SEC	8
 
+/* PIC IDs */
+#define	OPIC_ID			0
+#define	ATPIC_ID		1
+
 #endif /* _MACHINE_OCPBUS_H_ */

Modified: head/sys/powerpc/include/openpicvar.h
==============================================================================
--- head/sys/powerpc/include/openpicvar.h	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/include/openpicvar.h	Fri Jun 18 14:06:27 2010	(r209298)
@@ -35,10 +35,13 @@
 struct openpic_softc {
 	device_t	sc_dev;
 	struct resource	*sc_memr;
+	struct resource	*sc_intr;
 	bus_space_tag_t sc_bt;
 	bus_space_handle_t sc_bh;
 	char		*sc_version;
 	int		sc_rid;
+	int		sc_irq;
+	void		*sc_icookie;
 	u_int		sc_ncpu;
 	u_int		sc_nirq;
 	int		sc_psim;

Modified: head/sys/powerpc/mpc85xx/atpic.c
==============================================================================
--- head/sys/powerpc/mpc85xx/atpic.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/mpc85xx/atpic.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/intr.h>
 #include <machine/intr_machdep.h>
+#include <machine/ocpbus.h>
 #include <machine/pio.h>
 
 #include <powerpc/mpc85xx/ocpbus.h>
@@ -79,6 +80,9 @@ static void atpic_eoi(device_t, u_int);
 static void atpic_ipi(device_t, u_int);
 static void atpic_mask(device_t, u_int);
 static void atpic_unmask(device_t, u_int);
+static uint32_t atpic_id (device_t dev);
+
+static device_t pic8259;
 
 static device_method_t atpic_isa_methods[] = {
 	/* Device interface */
@@ -94,6 +98,7 @@ static device_method_t atpic_isa_methods
 	DEVMETHOD(pic_ipi,		atpic_ipi),
 	DEVMETHOD(pic_mask,		atpic_mask),
 	DEVMETHOD(pic_unmask,		atpic_unmask),
+	DEVMETHOD(pic_id,		atpic_id),
 
 	{ 0, 0 },
 };
@@ -219,7 +224,8 @@ atpic_isa_attach(device_t dev)
 	atpic_init(sc, ATPIC_SLAVE);
 	atpic_init(sc, ATPIC_MASTER);
 
-	powerpc_register_8259(dev);
+	powerpc_register_pic(dev, 0x10);
+	pic8259 = dev;
 	return (0);
 
  fail:
@@ -328,3 +334,11 @@ atpic_unmask(device_t dev, u_int irq)
 		atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]);
 	}
 }
+
+static uint32_t
+atpic_id (device_t dev)
+{
+
+	return (ATPIC_ID);
+}
+

Modified: head/sys/powerpc/mpc85xx/isa.c
==============================================================================
--- head/sys/powerpc/mpc85xx/isa.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/mpc85xx/isa.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -32,12 +32,16 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <sys/rman.h>
 
+#include <machine/intr_machdep.h>
+#include <machine/ocpbus.h>
 #include <machine/resource.h>
 
 #include <isa/isareg.h>
 #include <isa/isavar.h>
 #include <isa/isa_common.h>
 
+#include "ocpbus.h"
+
 void
 isa_init(device_t dev)
 {
@@ -58,7 +62,10 @@ isa_alloc_resource(device_t bus, device_
 	    resource_list_find(rl, type, *rid) == NULL) {
 		switch (type) {
 		case SYS_RES_IOPORT:	rids = ISA_PNP_NPORT; break;
-		case SYS_RES_IRQ:	rids = ISA_PNP_NIRQ; break;
+		case SYS_RES_IRQ:
+			rids = ISA_PNP_NIRQ;
+			start = ISA_IRQ(start);
+			break;
 		case SYS_RES_MEMORY:	rids = ISA_PNP_NMEM; break;
 		default:		rids = 0; break;
 		}

Modified: head/sys/powerpc/mpc85xx/ocpbus.c
==============================================================================
--- head/sys/powerpc/mpc85xx/ocpbus.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/mpc85xx/ocpbus.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -277,7 +277,7 @@ ocpbus_attach(device_t dev)
 		    ccsr_read4(OCP85XX_PORDEVSR),
 		    ccsr_read4(OCP85XX_PORDEVSR2));
 
-	for (i = PIC_IRQ_START; i < PIC_IRQ_START + 4; i++)
+	for (i = INTR_VEC(OPIC_ID, 0); i < INTR_VEC(OPIC_ID, 4); i++)
 		powerpc_config_intr(i, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
 
 	return (bus_generic_attach(dev));
@@ -305,35 +305,35 @@ const struct ocp_resource mpc8555_resour
 
 	{OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_MEMORY, 0, OCP85XX_QUICC_OFF,
 	    OCP85XX_QUICC_SIZE},
-	{OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(30), 1},
+	{OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, 30, 1},
 
 	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_MEMORY, 0, OCP85XX_TSEC0_OFF,
 	    OCP85XX_TSEC_SIZE},
-	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(13), 1},
-	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, PIC_IRQ_INT(14), 1},
-	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, PIC_IRQ_INT(18), 1},
+	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, 13, 1},
+	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, 14, 1},
+	{OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, 18, 1},
 	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_MEMORY, 0, OCP85XX_TSEC1_OFF,
 	    OCP85XX_TSEC_SIZE},
-	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(19), 1},
-	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, PIC_IRQ_INT(20), 1},
-	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, PIC_IRQ_INT(24), 1},
+	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, 19, 1},
+	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, 20, 1},
+	{OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, 24, 1},
 	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_MEMORY, 0, OCP85XX_TSEC2_OFF,
 	    OCP85XX_TSEC_SIZE},
-	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, PIC_IRQ_INT(15), 1},
-	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, PIC_IRQ_INT(16), 1},
-	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, PIC_IRQ_INT(17), 1},
+	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, 15, 1},
+	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, 16, 1},
+	{OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, 17, 1},
 	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_MEMORY, 0, OCP85XX_TSEC3_OFF,
 	    OCP85XX_TSEC_SIZE},
-	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, PIC_IRQ_INT(21), 1},
-	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, PIC_IRQ_INT(22), 1},
-	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, PIC_IRQ_INT(23), 1},
+	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, 21, 1},
+	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, 22, 1},
+	{OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, 23, 1},
 
 	{OCPBUS_DEVTYPE_UART, 0, SYS_RES_MEMORY, 0, OCP85XX_UART0_OFF,
 	    OCP85XX_UART_SIZE},
-	{OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(26), 1},
+	{OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, 26, 1},
 	{OCPBUS_DEVTYPE_UART, 1, SYS_RES_MEMORY, 0, OCP85XX_UART1_OFF,
 	    OCP85XX_UART_SIZE},
-	{OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(26), 1},
+	{OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, 26, 1},
 
 	{OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 0, OCP85XX_PCI0_OFF,
 	    OCP85XX_PCI_SIZE},
@@ -357,15 +357,15 @@ const struct ocp_resource mpc8555_resour
 
 	{OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF,
 	    OCP85XX_I2C_SIZE},
-	{OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(27), 1},
+	{OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, 27, 1},
 	{OCPBUS_DEVTYPE_I2C, 1, SYS_RES_MEMORY, 0, OCP85XX_I2C1_OFF,
 	    OCP85XX_I2C_SIZE},
-	{OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(27), 1},
+	{OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, 27, 1},
 
 	{OCPBUS_DEVTYPE_SEC, 0, SYS_RES_MEMORY, 0, OCP85XX_SEC_OFF,
 	    OCP85XX_SEC_SIZE},
-	{OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(29), 1},
-	{OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, PIC_IRQ_INT(42), 1},
+	{OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, 29, 1},
+	{OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, 42, 1},
 
 	{0}
 };
@@ -402,7 +402,7 @@ ocpbus_get_resource(device_t dev, device
 				start = res->sr_offset + CCSRBAR_VA;
 				break;
 			case SYS_RES_IRQ:
-				start = res->sr_offset;
+				start = PIC_IRQ_INT(res->sr_offset);
 				break;
 			default:
 				error = EINVAL;

Modified: head/sys/powerpc/mpc85xx/ocpbus.h
==============================================================================
--- head/sys/powerpc/mpc85xx/ocpbus.h	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/mpc85xx/ocpbus.h	Fri Jun 18 14:06:27 2010	(r209298)
@@ -104,11 +104,9 @@
 /*
  * PIC definitions
  */
-#define	ISA_IRQ_START	0
-#define	PIC_IRQ_START	(ISA_IRQ_START + 16)
 
-#define	ISA_IRQ(n)	(ISA_IRQ_START + (n))
-#define	PIC_IRQ_EXT(n)	(PIC_IRQ_START + (n))
-#define	PIC_IRQ_INT(n)	(PIC_IRQ_START + 16 + (n))
+#define	ISA_IRQ(n)	(INTR_VEC(ATPIC_ID, n))
+#define	PIC_IRQ_EXT(n)	(INTR_VEC(OPIC_ID, (n)))
+#define	PIC_IRQ_INT(n)	(INTR_VEC(OPIC_ID, (16 + (n))))
 
 #endif /* _MACHINE_OCP85XX_H */

Modified: head/sys/powerpc/mpc85xx/opic.c
==============================================================================
--- head/sys/powerpc/mpc85xx/opic.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/mpc85xx/opic.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
  * OpenPIC attachment to ocpbus
  */
 static int	openpic_ocpbus_probe(device_t);
+static uint32_t	openpic_ocpbus_id(device_t);
 
 static device_method_t  openpic_ocpbus_methods[] = {
 	/* Device interface */
@@ -63,6 +64,7 @@ static device_method_t  openpic_ocpbus_m
 	DEVMETHOD(pic_ipi,		openpic_ipi),
 	DEVMETHOD(pic_mask,		openpic_mask),
 	DEVMETHOD(pic_unmask,		openpic_unmask),
+	DEVMETHOD(pic_id,		openpic_ocpbus_id),
 
 	{ 0, 0 },
 };
@@ -93,3 +95,11 @@ openpic_ocpbus_probe (device_t dev)
 	device_set_desc(dev, OPENPIC_DEVSTR);
 	return (BUS_PROBE_DEFAULT);
 }
+
+static uint32_t
+openpic_ocpbus_id (device_t dev)
+{
+	return (OPIC_ID);
+}
+
+

Modified: head/sys/powerpc/mpc85xx/pci_ocp.c
==============================================================================
--- head/sys/powerpc/mpc85xx/pci_ocp.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/mpc85xx/pci_ocp.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -792,7 +792,7 @@ pci_ocp_alloc_resource(device_t dev, dev
 		va = sc->sc_iomem_va;
 		break;
 	case SYS_RES_IRQ:
-		if (start < PIC_IRQ_START) {
+		if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) {
 			device_printf(dev, "%s requested ISA interrupt %lu\n",
 			    device_get_nameunit(child), start);
 		}

Modified: head/sys/powerpc/ofw/ofw_pcib_pci.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pcib_pci.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/ofw/ofw_pcib_pci.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -42,6 +42,8 @@
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcib_private.h>
 
+#include <machine/intr_machdep.h>
+
 #include "pcib_if.h"
 
 static int	ofw_pcib_pci_probe(device_t bus);
@@ -149,6 +151,7 @@ ofw_pcib_pci_route_interrupt(device_t br
 	struct ofw_bus_iinfo *ii;
 	struct ofw_pci_register reg;
 	cell_t pintr, mintr;
+	phandle_t iparent;
 	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
 	sc = device_get_softc(bridge);
@@ -157,13 +160,13 @@ ofw_pcib_pci_route_interrupt(device_t br
 		pintr = intpin;
 		if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
 		    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
-		    maskbuf)) {
+		    &iparent, maskbuf)) {
 			/*
 			 * If we've found a mapping, return it and don't map
 			 * it again on higher levels - that causes problems
 			 * in some cases, and never seems to be required.
 			 */
-			return (mintr);
+			return (INTR_VEC(iparent, mintr));
 		}
 	} else if (intpin >= 1 && intpin <= 4) {
 		/*

Modified: head/sys/powerpc/ofw/ofw_pcibus.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pcibus.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/ofw/ofw_pcibus.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -212,13 +212,16 @@ ofw_pcibus_enum_devtree(device_t dev, u_
 				OF_getprop(iparent, "#interrupt-cells", &icells,
 				    sizeof(icells));
 
+				if (iparent != 0)
+					intr[0] = INTR_VEC(iparent, intr[0]);
+
 				if (iparent != 0 && icells > 1) {
 					powerpc_config_intr(intr[0],
 					    (intr[1] & 1) ? INTR_TRIGGER_LEVEL :
 					    INTR_TRIGGER_EDGE,
 					    INTR_POLARITY_HIGH);
 				}
-		
+
 				resource_list_add(&dinfo->opd_dinfo.resources,
 				    SYS_RES_IRQ, 0, intr[0], intr[0], 1);
 			}
@@ -293,7 +296,7 @@ static int
 ofw_pcibus_assign_interrupt(device_t dev, device_t child)
 {
 	ofw_pci_intr_t intr;
-	phandle_t node;
+	phandle_t node, iparent;
 	int isz;
 
 	node = ofw_bus_get_node(child);
@@ -303,8 +306,8 @@ ofw_pcibus_assign_interrupt(device_t dev
 	
 		/*
 		 * XXX: Right now we don't have anything sensible to do here,
-		 * since the ofw_imap stuff relies on nodes have a reg
-		 * property. There exists ways around this, so the ePAPR
+		 * since the ofw_imap stuff relies on nodes having a reg
+		 * property. There exist ways around this, so the ePAPR
 		 * spec will need to be studied.
 		 */
 
@@ -318,18 +321,29 @@ ofw_pcibus_assign_interrupt(device_t dev
 	}
 	
 	/*
+	 * Try to determine the node's interrupt parent so we know which
+	 * PIC to use.
+	 */
+
+	iparent = -1;
+	if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0)
+		iparent = -1;
+	
+	/*
 	 * Any AAPL,interrupts property gets priority and is
 	 * fully specified (i.e. does not need routing)
 	 */
 
 	isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
-	if (isz == sizeof(intr)) {
-		return (intr);
-	}
+	if (isz == sizeof(intr))
+		return ((iparent == -1) ? intr : INTR_VEC(iparent, intr));
 
 	isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
-	if (isz != sizeof(intr)) {
-		/* No property; our best guess is the intpin. */
+	if (isz == sizeof(intr)) {
+		if (iparent != -1)
+			intr = INTR_VEC(iparent, intr);
+	} else {
+		/* No property: our best guess is the intpin. */
 		intr = pci_get_intpin(child);
 	}
 	

Modified: head/sys/powerpc/powermac/cpcht.c
==============================================================================
--- head/sys/powerpc/powermac/cpcht.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/cpcht.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -595,6 +595,7 @@ static void	openpic_cpcht_config(device_
 static void	openpic_cpcht_enable(device_t, u_int irq, u_int vector);
 static void	openpic_cpcht_unmask(device_t, u_int irq);
 static void	openpic_cpcht_eoi(device_t, u_int irq);
+static uint32_t	openpic_cpcht_id(device_t);
 
 static device_method_t  openpic_cpcht_methods[] = {
 	/* Device interface */
@@ -609,6 +610,7 @@ static device_method_t  openpic_cpcht_me
 	DEVMETHOD(pic_ipi,		openpic_ipi),
 	DEVMETHOD(pic_mask,		openpic_mask),
 	DEVMETHOD(pic_unmask,		openpic_cpcht_unmask),
+	DEVMETHOD(pic_id,		openpic_cpcht_id),
 
 	{ 0, 0 },
 };
@@ -808,3 +810,9 @@ openpic_cpcht_eoi(device_t dev, u_int ir
 	openpic_eoi(dev, irq);
 }
 
+static uint32_t
+openpic_cpcht_id(device_t dev)
+{
+	return (ofw_bus_get_node(dev));
+}
+

Modified: head/sys/powerpc/powermac/grackle.c
==============================================================================
--- head/sys/powerpc/powermac/grackle.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/grackle.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -43,6 +43,7 @@
 #include <dev/pci/pcireg.h>
 
 #include <machine/bus.h>
+#include <machine/intr_machdep.h>
 #include <machine/md_var.h>
 #include <machine/pio.h>
 #include <machine/resource.h>
@@ -341,13 +342,15 @@ grackle_route_interrupt(device_t bus, de
 	struct grackle_softc *sc;
 	struct ofw_pci_register reg;
 	uint32_t pintr, mintr;
+	phandle_t iparent;
 	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
 	sc = device_get_softc(bus);
 	pintr = pin;
 	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
-	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
-		return (mintr);
+	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
+	    &iparent, maskbuf))
+		return (INTR_VEC(iparent, mintr));
 
 	/* Maybe it's a real interrupt, not an intpin */
 	if (pin > 4)

Modified: head/sys/powerpc/powermac/hrowpic.c
==============================================================================
--- head/sys/powerpc/powermac/hrowpic.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/hrowpic.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -70,6 +70,7 @@ static void	hrowpic_eoi(device_t, u_int)
 static void	hrowpic_ipi(device_t, u_int);
 static void	hrowpic_mask(device_t, u_int);
 static void	hrowpic_unmask(device_t, u_int);
+static uint32_t hrowpic_id(device_t dev);
 
 static device_method_t  hrowpic_methods[] = {
 	/* Device interface */
@@ -80,6 +81,7 @@ static device_method_t  hrowpic_methods[
 	DEVMETHOD(pic_dispatch,		hrowpic_dispatch),
 	DEVMETHOD(pic_enable,		hrowpic_enable),
 	DEVMETHOD(pic_eoi,		hrowpic_eoi),
+	DEVMETHOD(pic_id,		hrowpic_id),
 	DEVMETHOD(pic_ipi,		hrowpic_ipi),
 	DEVMETHOD(pic_mask,		hrowpic_mask),
 	DEVMETHOD(pic_unmask,		hrowpic_unmask),
@@ -169,6 +171,8 @@ hrowpic_attach(device_t dev)
 	hrowpic_write_reg(sc, HPIC_CLEAR,  HPIC_SECONDARY, 0xffffffff);
 
 	powerpc_register_pic(dev, 64);
+	root_pic = dev; /* Heathrow systems have only one PIC */
+
 	return (0);
 }
 
@@ -282,3 +286,10 @@ hrowpic_unmask(device_t dev, u_int irq)
 	sc = device_get_softc(dev);
 	hrowpic_toggle_irq(sc, irq, 1);
 }
+
+static uint32_t
+hrowpic_id(device_t dev)
+{
+	return (ofw_bus_get_node(dev));
+}
+

Modified: head/sys/powerpc/powermac/macgpio.c
==============================================================================
--- head/sys/powerpc/powermac/macgpio.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/macgpio.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -35,15 +35,16 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/bus.h>
-#include <machine/bus.h>
 #include <sys/rman.h>
 
-#include <machine/vmparam.h>
 #include <vm/vm.h>
 #include <vm/pmap.h>
-#include <machine/pmap.h>
 
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/pmap.h>
 #include <machine/resource.h>
+#include <machine/vmparam.h>
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
@@ -150,8 +151,7 @@ macgpio_attach(device_t dev)
 {
 	struct macgpio_softc *sc;
         struct macgpio_devinfo *dinfo;
-        phandle_t root;
-	phandle_t child;
+        phandle_t root, child, iparent;
         device_t cdev;
 	uint32_t irq;
 
@@ -186,10 +186,13 @@ macgpio_attach(device_t dev)
 
 		resource_list_init(&dinfo->mdi_resources);
 
-		if (OF_getprop(child,"interrupts",&irq, sizeof(irq)) == 
+		if (OF_getprop(child, "interrupts", &irq, sizeof(irq)) == 
 		    sizeof(irq)) {
+			OF_searchprop(child, "interrupt-parent", &iparent,
+			    sizeof(iparent));
 			resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
-			    0, irq, irq, 1);
+			    0, INTR_VEC(iparent, irq), INTR_VEC(iparent, irq),
+			    1);
 		}
 
 		/* Fix messed-up offsets */

Modified: head/sys/powerpc/powermac/macio.c
==============================================================================
--- head/sys/powerpc/powermac/macio.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/macio.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -37,15 +37,16 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/bus.h>
-#include <machine/bus.h>
 #include <sys/rman.h>
 
-#include <machine/vmparam.h>
 #include <vm/vm.h>
 #include <vm/pmap.h>
-#include <machine/pmap.h>
 
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/pmap.h>
 #include <machine/resource.h>
+#include <machine/vmparam.h>
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
@@ -186,6 +187,7 @@ macio_get_quirks(const char *name)
 static void
 macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo)
 {
+	phandle_t iparent;
 	int	*intr;
 	int	i, nintr;
 	int 	icells;
@@ -211,11 +213,17 @@ macio_add_intr(phandle_t devnode, struct
 	if (intr[0] == -1)
 		return;
 
+	if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
+	    <= 0)
+		panic("Interrupt but no interrupt parent!\n");
+
 	for (i = 0; i < nintr; i+=icells) {
 		resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
-		    dinfo->mdi_ninterrupts, intr[i], intr[i], 1);
+		    dinfo->mdi_ninterrupts, INTR_VEC(iparent, intr[i]),
+		    INTR_VEC(iparent, intr[i]), 1);
 
-		dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = intr[i];
+		dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] =
+		    INTR_VEC(iparent, intr[i]);
 		dinfo->mdi_ninterrupts++;
 	}
 }

Modified: head/sys/powerpc/powermac/openpic_macio.c
==============================================================================
--- head/sys/powerpc/powermac/openpic_macio.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/openpic_macio.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
  * MacIO interface
  */
 static int	openpic_macio_probe(device_t);
+static uint32_t	openpic_macio_id(device_t);
 
 static device_method_t  openpic_macio_methods[] = {
 	/* Device interface */
@@ -73,6 +74,7 @@ static device_method_t  openpic_macio_me
 	DEVMETHOD(pic_ipi,		openpic_ipi),
 	DEVMETHOD(pic_mask,		openpic_mask),
 	DEVMETHOD(pic_unmask,		openpic_unmask),
+	DEVMETHOD(pic_id,		openpic_macio_id),
 
 	{ 0, 0 },
 };
@@ -96,3 +98,10 @@ openpic_macio_probe(device_t dev)
 	device_set_desc(dev, OPENPIC_DEVSTR);
 	return (0);
 }
+
+static uint32_t
+openpic_macio_id(device_t dev)
+{
+	return (ofw_bus_get_node(dev));
+}
+

Modified: head/sys/powerpc/powermac/uninorth.c
==============================================================================
--- head/sys/powerpc/powermac/uninorth.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/uninorth.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -144,9 +144,9 @@ DRIVER_MODULE(unin, nexus, unin_chip_dri
 static void
 unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo)
 {
+	phandle_t iparent;
 	int	*intr;
 	int	i, nintr;
-	phandle_t iparent;
 	int 	icells;
 
 	if (dinfo->udi_ninterrupts >= 6) {
@@ -176,9 +176,17 @@ unin_chip_add_intr(phandle_t devnode, st
 
 	for (i = 0; i < nintr; i+=icells) {
 		resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
-		    dinfo->udi_ninterrupts, intr[i], intr[i], 1);
+		    dinfo->udi_ninterrupts, INTR_VEC(iparent, intr[i]),
+		    INTR_VEC(iparent, intr[i]), 1);
+
+		if (icells > 1) {
+			powerpc_config_intr(INTR_VEC(iparent, intr[i]),
+			    (intr[i+1] & 1) ? INTR_TRIGGER_LEVEL :
+			    INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
+		}
 
-		dinfo->udi_interrupts[dinfo->udi_ninterrupts] = intr[i];
+		dinfo->udi_interrupts[dinfo->udi_ninterrupts] =
+		    INTR_VEC(iparent, intr[i]);
 		dinfo->udi_ninterrupts++;
 	}
 }

Modified: head/sys/powerpc/powermac/uninorthpci.c
==============================================================================
--- head/sys/powerpc/powermac/uninorthpci.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powermac/uninorthpci.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -356,14 +356,15 @@ uninorth_route_interrupt(device_t bus, d
 	struct uninorth_softc *sc;
 	struct ofw_pci_register reg;
 	uint32_t pintr, mintr;
+	phandle_t iparent;
 	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
 	sc = device_get_softc(bus);
 	pintr = pin;
 	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
 	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
-	    maskbuf))
-		return (mintr);
+	    &iparent, maskbuf))
+		return (INTR_VEC(iparent, mintr));
 
 	/* Maybe it's a real interrupt, not an intpin */
 	if (pin > 4)

Modified: head/sys/powerpc/powerpc/intr_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/intr_machdep.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powerpc/intr_machdep.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -85,14 +85,6 @@
 
 #include "pic_if.h"
 
-#ifdef MPC85XX
-#define	ISA_IRQ_COUNT	16
-#endif
-
-#ifndef ISA_IRQ_COUNT
-#define	ISA_IRQ_COUNT	0
-#endif
-
 #define	MAX_STRAY_LOG	5
 
 MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
@@ -108,20 +100,25 @@ struct powerpc_intr {
 	enum intr_polarity pol;
 };
 
+struct pic {
+	device_t pic;
+	uint32_t pic_id;
+	int ipi_irq;
+};
+
 static struct mtx intr_table_lock;
 static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
+static struct pic piclist[MAX_PICS];
 static u_int nvectors;		/* Allocated vectors */
+static u_int npics;		/* PICs registered */
 static u_int stray_count;
 
+device_t root_pic;
+
 #ifdef SMP
 static void *ipi_cookie;
 #endif
 
-static u_int ipi_irq;
-
-device_t pic;
-device_t pic8259;
-
 static void
 intr_init(void *dummy __unused)
 {
@@ -198,21 +195,13 @@ static int
 powerpc_map_irq(struct powerpc_intr *i)
 {
 
-#if ISA_IRQ_COUNT > 0
-	if (i->irq < ISA_IRQ_COUNT) {
-		if (pic8259 == NULL) {
-			i->pic = pic;
-			i->intline = 0;
-			return (ENXIO);
-		}
-		i->pic = pic8259;
-		i->intline = i->irq;
-		return (0);
-	}
-#endif
+	i->intline = INTR_INTLINE(i->irq);
+	i->pic = piclist[INTR_IGN(i->irq)].pic;
+
+	/* Try a best guess if that failed */
+	if (i->pic == NULL)
+		i->pic = root_pic;
 
-	i->pic = pic;
-	i->intline = i->irq - ISA_IRQ_COUNT;
 	return (0);
 }
 
@@ -243,16 +232,44 @@ powerpc_intr_unmask(void *arg)
 void
 powerpc_register_pic(device_t dev, u_int ipi)
 {
+	int i;
+
+	mtx_lock(&intr_table_lock);
 
-	pic = dev;
-	ipi_irq = ipi + ISA_IRQ_COUNT;
+	for (i = 0; i < npics; i++) {
+		if (piclist[i].pic_id == PIC_ID(dev))
+			break;
+	}
+	piclist[i].pic = dev;
+	piclist[i].pic_id = PIC_ID(dev);
+	piclist[i].ipi_irq = ipi;
+	if (i == npics)
+		npics++;
+
+	mtx_unlock(&intr_table_lock);
 }
 
-void
-powerpc_register_8259(device_t dev)
+int
+powerpc_ign_lookup(uint32_t pic_id)
 {
+	int i;
+
+	mtx_lock(&intr_table_lock);
+
+	for (i = 0; i < npics; i++) {
+		if (piclist[i].pic_id == pic_id) {
+			mtx_unlock(&intr_table_lock);
+			return (i);
+		}
+	}
+	piclist[i].pic = NULL;
+	piclist[i].pic_id = pic_id;
+	piclist[i].ipi_irq = 0;
+	npics++;
 
-	pic8259 = dev;
+	mtx_unlock(&intr_table_lock);
+
+	return (i);
 }
 
 int
@@ -260,17 +277,28 @@ powerpc_enable_intr(void)
 {
 	struct powerpc_intr *i;
 	int error, vector;
+#ifdef SMP
+	int n;
+#endif
 
-	if (pic == NULL)
+	if (npics == 0)
 		panic("no PIC detected\n");
 
 #ifdef SMP
 	/* Install an IPI handler. */
-	error = powerpc_setup_intr("IPI", ipi_irq, powerpc_ipi_handler,
-	    NULL, NULL, INTR_TYPE_MISC | INTR_EXCL | INTR_FAST, &ipi_cookie);
-	if (error) {
-		printf("unable to setup IPI handler\n");
-		return (error);
+
+	for (n = 0; n < npics; n++) {
+		if (piclist[n].pic != root_pic)
+			continue;
+
+		error = powerpc_setup_intr("IPI",
+		    INTR_VEC(piclist[n].pic_id, piclist[n].ipi_irq),
+		    powerpc_ipi_handler, NULL, NULL,
+		    INTR_TYPE_MISC | INTR_EXCL | INTR_FAST, &ipi_cookie);
+		if (error) {
+			printf("unable to setup IPI handler\n");
+			return (error);
+		}
 	}
 #endif
 
@@ -295,7 +323,7 @@ powerpc_enable_intr(void)
 }
 
 int
-powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, 
+powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
     driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
 {
 	struct powerpc_intr *i;

Modified: head/sys/powerpc/powerpc/mp_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/mp_machdep.c	Fri Jun 18 11:36:55 2010	(r209297)
+++ head/sys/powerpc/powerpc/mp_machdep.c	Fri Jun 18 14:06:27 2010	(r209298)
@@ -319,7 +319,7 @@ ipi_send(struct pcpu *pc, int ipi)
 	    pc, pc->pc_cpuid, ipi);
 
 	atomic_set_32(&pc->pc_ipimask, (1 << ipi));

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list