Fix the interrupt code, broken 7 months ago. The interrupt framework

already supported nested PICs, but was limited to having a nested
AT-PIC only. With G5 support the need for nested OpenPIC controllers
needed to be added. This was done the wrong way and broke the MPC8555
eval system in the process.

OFW, as well as FDT, describe the interrupt routing in terms of a
controller and an interrupt pin on it. This needs to be mapped to a
flat and global resource: the IRQ. The IRQ is the same as the PCI
intline and as such needs to be representable in 8 bits. Secondly,
ISA support pretty much dictates that IRQ 0-15 should be reserved
for ISA interrupts, because of the internal workins of south bridges.
Both were broken.

This change reverts revision 209298 for a big part and re-implements
it simpler. In particular:
o   The id() method of the PIC I/F is removed again. It's not needed.
o   The openpic_attach() function has been changed to take the OFW
    or FDT phandle of the controller as a second argument. All bus
    attachments that previously used openpic_attach() as the attach
    method of the device I/F now implement as bus-specific method
    and pass the phandle_t to the renamed openpic_attach().
o   Change powerpc_register_pic() to take a few more arguments. In
    particular:
    -   Pass the number of IPIs specificly. The number of IRQs carved
	out for a PIC is the sum of the number of int. pins and IPIs.
    -   Pass a flag indicating whether the PIC is an AT-PIC or not.
	This tells the interrupt framework whether to assign IRQ 0-15
	or some other range.
o   Until we implement proper multi-pass bus enumeration, we have to
    handle the case where we need to map from PIC+pin to IRQ *before*
    the PIC gets registered. This is done in a similar way as before,
    but rather than carving out 256 IRQs per PIC, we carve out 128
    IRQs (124 pins + 4 IPIs). This is supposed to handle the G5 case,
    but should really be fixed properly using multiple passes.
o   Have the interrupt framework set root_pic in most cases and not
    put that burden in PIC drivers (for the most part).
o   Remove powerpc_ign_lookup() and replace it with powerpc_get_irq().
    Remove IGN_SHIFT, INTR_INTLINE and INTR_IGN.

Related to the above, fix the Freescale PCI controller driver, broken
by the FDT code. Besides not attaching properly, bus numbers were
assigned improperly and enumeration was broken in general. This
prevented the AT PIC from being discovered and interrupt routing to
work properly. Consequently, the ata(4) controller stopped functioning.

Fix the driver, and FDT PCI support, enough to get the MPC8555CDS
going again. The FDT PCI code needs a whole lot more work.

No breakages are expected, but lackiong G5 hardware, it's possible
that there are unpleasant side-effects. At least MPC85xx support is
back to where it was 7 months ago -- it's amazing how badly support
can be broken in just 7 months...

Sponsored by: Juniper Networks
This commit is contained in:
marcel 2011-01-29 20:58:38 +00:00
parent f9d6eb1e75
commit d129fb0e44
15 changed files with 162 additions and 202 deletions

View File

@ -29,13 +29,9 @@
#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))
#define MAX_PICS 5
#define INTR_VEC(node, pin) powerpc_get_irq(node, pin)
/*
* Default base address for MSI messages on PowerPC
@ -50,8 +46,8 @@ driver_filter_t powerpc_ipi_handler;
void intrcnt_add(const char *name, u_long **countp);
void powerpc_register_pic(device_t, u_int);
int powerpc_ign_lookup(uint32_t pic_id);
void powerpc_register_pic(device_t, uint32_t, u_int, u_int, u_int);
u_int powerpc_get_irq(uint32_t, u_int);
void powerpc_dispatch_intr(u_int, struct trapframe *);
int powerpc_enable_intr(void);

View File

@ -52,7 +52,7 @@ extern devclass_t openpic_devclass;
/*
* Bus-independent attach i/f
*/
int openpic_attach(device_t);
int openpic_common_attach(device_t, uint32_t);
/*
* PIC interface.

View File

@ -56,12 +56,11 @@ __FBSDID("$FreeBSD$");
* Mambo interface
*/
static int openpic_mambo_probe(device_t);
static uint32_t openpic_mambo_id(device_t dev);
static int openpic_mambo_attach(device_t);
static int openpicbus_mambo_probe(device_t dev);
static int openpicbus_mambo_attach(device_t dev);
static struct resource *openpicbus_alloc_resource(device_t bus, device_t dev,
int type, int *rid, u_long start, u_long end, u_long count,
u_int flags);
static struct resource *openpicbus_alloc_resource(device_t bus, device_t dev,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
static device_method_t openpicbus_mambo_methods[] = {
/* Device interface */
@ -87,7 +86,7 @@ static driver_t openpicbus_mambo_driver = {
static device_method_t openpic_mambo_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_mambo_probe),
DEVMETHOD(device_attach, openpic_attach),
DEVMETHOD(device_attach, openpic_mambo_attach),
/* PIC interface */
DEVMETHOD(pic_config, openpic_config),
@ -97,7 +96,6 @@ static device_method_t openpic_mambo_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask),
DEVMETHOD(pic_id, openpic_mambo_id),
{ 0, 0 },
};
@ -167,14 +165,15 @@ openpicbus_alloc_resource(device_t bus, device_t dev, int type, int *rid,
static int
openpic_mambo_probe(device_t dev)
{
device_set_desc(dev, OPENPIC_DEVSTR);
return (0);
}
static uint32_t
openpic_mambo_id(device_t dev)
static int
openpic_mambo_attach(device_t dev)
{
return (ofw_bus_get_node(device_get_parent(dev)));
return (openpic_common_attach(dev,
ofw_bus_get_node(device_get_parent(dev))));
}

View File

@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr_machdep.h>
#include <machine/ocpbus.h>
#include <machine/pio.h>
#include <powerpc/mpc85xx/mpc85xx.h>
@ -79,7 +78,6 @@ 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_method_t atpic_isa_methods[] = {
/* Device interface */
@ -95,7 +93,6 @@ 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 },
};
@ -154,7 +151,7 @@ atpic_isa_identify(driver_t *drv, device_t parent)
bus_set_resource(child, SYS_RES_IOPORT, ATPIC_SLAVE, IO_ICU2, 2);
/* ISA interrupts are routed through external interrupt 0. */
bus_set_resource(child, SYS_RES_IRQ, 0, PIC_IRQ_EXT(0), 1);
bus_set_resource(child, SYS_RES_IRQ, 0, 16, 1);
}
static int
@ -221,7 +218,7 @@ atpic_isa_attach(device_t dev)
atpic_init(sc, ATPIC_SLAVE);
atpic_init(sc, ATPIC_MASTER);
powerpc_register_pic(dev, 0x10);
powerpc_register_pic(dev, 0, 16, 0, TRUE);
return (0);
fail:
@ -328,11 +325,3 @@ 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);
}

View File

@ -33,15 +33,12 @@ __FBSDID("$FreeBSD$");
#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)
{
@ -62,10 +59,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
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;
start = ISA_IRQ(start);
break;
case SYS_RES_IRQ: rids = ISA_PNP_NIRQ; break;
case SYS_RES_MEMORY: rids = ISA_PNP_NMEM; break;
default: rids = 0; break;
}

View File

@ -45,12 +45,12 @@ __FBSDID("$FreeBSD$");
#include "pic_if.h"
static int openpic_fdt_probe(device_t);
static uint32_t openpic_fdt_id(device_t);
static int openpic_fdt_attach(device_t);
static device_method_t openpic_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_fdt_probe),
DEVMETHOD(device_attach, openpic_attach),
DEVMETHOD(device_attach, openpic_fdt_attach),
/* PIC interface */
DEVMETHOD(pic_bind, openpic_bind),
@ -61,7 +61,6 @@ static device_method_t openpic_fdt_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask),
DEVMETHOD(pic_id, openpic_fdt_id),
{ 0, 0 },
};
@ -85,9 +84,9 @@ openpic_fdt_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
static uint32_t
openpic_fdt_id(device_t dev)
static int
openpic_fdt_attach(device_t dev)
{
return (ofw_bus_get_node(dev));
return (openpic_common_attach(dev, ofw_bus_get_node(dev)));
}

View File

@ -136,7 +136,7 @@ static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *);
static void fsl_pcib_err_init(device_t);
static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, u_long,
u_long, u_long);
static int fsl_pcib_init(struct fsl_pcib_softc *, int, int, int);
static int fsl_pcib_init(struct fsl_pcib_softc *, int, int);
static int fsl_pcib_intr_info(phandle_t, struct fsl_pcib_softc *);
static int fsl_pcib_set_range(struct fsl_pcib_softc *, int, int, u_long,
u_long);
@ -160,8 +160,6 @@ static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
uint32_t, int);
static int next_busnr = 0;
/* Configuration r/w mutex. */
struct mtx pcicfg_mtx;
static int mtx_initialized = 0;
@ -215,23 +213,17 @@ DRIVER_MODULE(pcib, fdtbus, fsl_pcib_driver, pcib_devclass, 0, 0);
static int
fsl_pcib_probe(device_t dev)
{
phandle_t parnode;
phandle_t node;
/*
* The PCI subnode does not have the 'compatible' property, so we need
* to check in the parent PCI node. However the parent is not
* represented by a separate ofw_bus child, and therefore
* ofw_bus_is_compatible() cannot be used, but direct fdt equivalent.
*/
parnode = OF_parent(ofw_bus_get_node(dev));
if (parnode == 0)
node = ofw_bus_get_node(dev);
if (!fdt_is_type(node, "pci"))
return (ENXIO);
if (!(fdt_is_compatible(parnode, "fsl,mpc8548-pcie") ||
fdt_is_compatible(parnode, "fsl,mpc8548-pcie")))
if (!(fdt_is_compatible(node, "fsl,mpc8540-pci") ||
fdt_is_compatible(node, "fsl,mpc8548-pcie")))
return (ENXIO);
device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller");
return (BUS_PROBE_DEFAULT);
}
@ -241,7 +233,7 @@ fsl_pcib_attach(device_t dev)
struct fsl_pcib_softc *sc;
phandle_t node;
uint32_t cfgreg;
int maxslot, subbus;
int maxslot;
uint8_t ltssm, capptr;
sc = device_get_softc(dev);
@ -304,23 +296,13 @@ fsl_pcib_attach(device_t dev)
sc->sc_devfn_tundra = -1;
sc->sc_devfn_via_ide = -1;
maxslot = (sc->sc_pcie) ? 1 : 31;
/*
* Scan bus using firmware configured, 0 based bus numbering,
* let fsl_pcib_init() shift bus number by next_busnr offset.
* Scan bus using firmware configured, 0 based bus numbering.
*/
sc->sc_busnr = 1;
subbus = fsl_pcib_init(sc, 0, next_busnr, maxslot);
if (bootverbose)
printf("PCI: domain %d, busnr = %d, next_busnr = %d\n",
device_get_unit(dev), next_busnr + 1,
next_busnr + subbus + 1);
/* Set final busnr */
sc->sc_busnr = next_busnr + 1;
next_busnr += subbus + 1;
sc->sc_busnr = 0;
maxslot = (sc->sc_pcie) ? 0 : PCI_SLOTMAX;
fsl_pcib_init(sc, sc->sc_busnr, maxslot);
if (sc->sc_pcie) {
ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
@ -455,7 +437,7 @@ fsl_pcib_maxslots(device_t dev)
{
struct fsl_pcib_softc *sc = device_get_softc(dev);
return ((sc->sc_pcie) ? 1 : 31);
return ((sc->sc_pcie) ? 0 : PCI_SLOTMAX);
}
static uint32_t
@ -572,14 +554,11 @@ fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
devfn = DEVFN(bus, slot, func);
if (devfn == sc->sc_devfn_via_ide)
#if 0
intline = INTR_VEC(ATPIC_ID, 14);
intline = INTR_VEC(0, 14);
else if (devfn == sc->sc_devfn_via_ide + 1)
intline = INTR_VEC(ATPIC_ID, 10);
intline = INTR_VEC(0, 10);
else if (devfn == sc->sc_devfn_via_ide + 2)
intline = INTR_VEC(ATPIC_ID, 10);
#endif
;
intline = INTR_VEC(0, 10);
else {
if (intpin != 0)
err = fdt_pci_route_intr(bus, slot, func, intpin,
@ -596,10 +575,9 @@ fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
}
static int
fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
int maxslot)
fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
{
int secbus, subbus;
int secbus;
int old_pribus, old_secbus, old_subbus;
int new_pribus, new_secbus, new_subbus;
int slot, func, maxfunc;
@ -608,11 +586,10 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
uint8_t command, hdrtype, class, subclass;
uint8_t intline, intpin;
subbus = bus;
secbus = bus;
for (slot = 0; slot <= maxslot; slot++) {
maxfunc = 0;
for (func = 0; func <= maxfunc; func++) {
hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot,
func, PCIR_HDRTYPE, 1);
@ -667,19 +644,14 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
func, PCIR_CLASS, 1);
subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
func, PCIR_SUBCLASS, 1);
#if 0
/* Allow only proper PCI-PCI briges */
if (class != PCIC_BRIDGE)
continue;
if (subclass != PCIS_BRIDGE_PCI)
continue;
#endif
/* Allow all DEVTYPE 1 devices */
if (hdrtype != PCIM_HDRTYPE_BRIDGE)
continue;
subbus++;
secbus = subbus;
secbus++;
/* Program I/O decoder. */
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
@ -718,31 +690,20 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
if (bootverbose)
printf("PCI: reading firmware bus numbers for "
"secbus = %d (bus/sec/sub) = (%d/%d/%d)\n",
secbus + busnr_offset, old_pribus,
old_secbus, old_subbus);
secbus, old_pribus, old_secbus, old_subbus);
/* Skip unconfigured devices */
if ((old_pribus == 0) &&
(old_secbus == 0) && (old_subbus == 0))
continue;
new_pribus = bus;
new_secbus = secbus;
subbus += fsl_pcib_init(sc, secbus, busnr_offset,
(subclass == PCIS_BRIDGE_PCI) ? 31 : 1);
secbus = fsl_pcib_init(sc, secbus,
(subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0);
new_pribus = bus + busnr_offset;
new_secbus = secbus + busnr_offset;
new_subbus = subbus + busnr_offset;
/* Fixup pribus for MPC8572 PCIE controller */
if ((vendor == 0x1957) && ((device = 0x0040) ||
(device == 0x0041)))
new_pribus = 0;
new_subbus = secbus;
if (bootverbose)
printf("PCI: translate firmware bus numbers for "
"secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
secbus + busnr_offset,
old_pribus, old_secbus, old_subbus,
printf("PCI: translate firmware bus numbers "
"for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
secbus, old_pribus, old_secbus, old_subbus,
new_pribus, new_secbus, new_subbus);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
@ -754,11 +715,7 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
}
}
if (bootverbose)
printf("PCI: bus %d, #subbus = %d\n",
bus + busnr_offset, subbus - bus);
return (subbus - bus);
return (secbus);
}
static void
@ -938,12 +895,10 @@ fsl_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
va = sc->sc_iomem_va;
break;
case SYS_RES_IRQ:
#if 0
if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) {
if (start < 16) {
device_printf(dev, "%s requested ISA interrupt %lu\n",
device_get_nameunit(child), start);
}
#endif
flags |= RF_SHAREABLE;
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));

View File

@ -757,7 +757,6 @@ static void openpic_cpcht_config(device_t, u_int irq,
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 */
@ -773,7 +772,6 @@ static device_method_t openpic_cpcht_methods[] = {
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,9 +806,11 @@ static int
openpic_cpcht_attach(device_t dev)
{
struct openpic_cpcht_softc *sc;
phandle_t node;
int err, irq;
err = openpic_attach(dev);
node = ofw_bus_get_node(dev);
err = openpic_common_attach(dev, node);
if (err != 0)
return (err);
@ -839,9 +839,8 @@ openpic_cpcht_attach(device_t dev)
* be necessary, but Linux does it, and I cannot find any U3 machines
* with MSI devices to test.
*/
if (dev == root_pic)
cpcht_msipic = PIC_ID(dev);
cpcht_msipic = node;
return (0);
}
@ -981,10 +980,3 @@ openpic_cpcht_eoi(device_t dev, u_int irq)
openpic_eoi(dev, irq);
}
static uint32_t
openpic_cpcht_id(device_t dev)
{
return (ofw_bus_get_node(dev));
}

View File

@ -69,7 +69,6 @@ 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,7 +79,6 @@ 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,9 +167,7 @@ hrowpic_attach(device_t dev)
hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0);
hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff);
powerpc_register_pic(dev, 64);
root_pic = dev; /* Heathrow systems have only one PIC */
powerpc_register_pic(dev, ofw_bus_get_node(dev), 64, 0, FALSE);
return (0);
}
@ -282,10 +278,3 @@ 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));
}

View File

@ -58,12 +58,12 @@ __FBSDID("$FreeBSD$");
* MacIO interface
*/
static int openpic_macio_probe(device_t);
static uint32_t openpic_macio_id(device_t);
static int openpic_macio_attach(device_t);
static device_method_t openpic_macio_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_macio_probe),
DEVMETHOD(device_attach, openpic_attach),
DEVMETHOD(device_attach, openpic_macio_attach),
/* PIC interface */
DEVMETHOD(pic_bind, openpic_bind),
@ -74,7 +74,6 @@ static device_method_t openpic_macio_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask),
DEVMETHOD(pic_id, openpic_macio_id),
{ 0, 0 },
};
@ -99,9 +98,9 @@ openpic_macio_probe(device_t dev)
return (0);
}
static uint32_t
openpic_macio_id(device_t dev)
static int
openpic_macio_attach(device_t dev)
{
return (ofw_bus_get_node(dev));
return (openpic_common_attach(dev, ofw_bus_get_node(dev)));
}

View File

@ -60,6 +60,8 @@
* $FreeBSD$
*/
#include "opt_isa.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@ -102,9 +104,11 @@ struct powerpc_intr {
};
struct pic {
device_t pic;
uint32_t pic_id;
int ipi_irq;
device_t dev;
uint32_t node;
u_int irqs;
u_int ipis;
int base;
};
static u_int intrcnt_index = 0;
@ -113,6 +117,11 @@ 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 */
#ifdef DEV_ISA
static u_int nirqs = 16; /* Allocated IRQS (ISA pre-allocated). */
#else
static u_int nirqs = 0; /* Allocated IRQs. */
#endif
static u_int stray_count;
device_t root_pic;
@ -142,7 +151,6 @@ smp_intr_init(void *dummy __unused)
PIC_BIND(i->pic, i->intline, i->cpu);
}
}
SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
#endif
@ -231,9 +239,21 @@ intr_lookup(u_int irq)
static int
powerpc_map_irq(struct powerpc_intr *i)
{
struct pic *p;
u_int cnt;
int idx;
i->intline = INTR_INTLINE(i->irq);
i->pic = piclist[INTR_IGN(i->irq)].pic;
for (idx = 0; idx < npics; idx++) {
p = &piclist[idx];
cnt = p->irqs + p->ipis;
if (i->irq >= p->base && i->irq < p->base + cnt)
break;
}
if (idx == npics)
return (EINVAL);
i->intline = i->irq - p->base;
i->pic = p->dev;
/* Try a best guess if that failed */
if (i->pic == NULL)
@ -288,46 +308,76 @@ powerpc_assign_intr_cpu(void *arg, u_char cpu)
}
void
powerpc_register_pic(device_t dev, u_int ipi)
powerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis,
u_int atpic)
{
int i;
struct pic *p;
u_int irq;
int idx;
mtx_lock(&intr_table_lock);
for (i = 0; i < npics; i++) {
if (piclist[i].pic_id == PIC_ID(dev))
/* XXX see powerpc_get_irq(). */
for (idx = 0; idx < npics; idx++) {
p = &piclist[idx];
if (p->node != node)
continue;
if (node != 0 || p->dev == dev)
break;
}
piclist[i].pic = dev;
piclist[i].pic_id = PIC_ID(dev);
piclist[i].ipi_irq = ipi;
if (i == npics)
p = &piclist[idx];
p->dev = dev;
p->node = node;
p->irqs = irqs;
p->ipis = ipis;
if (idx == npics) {
#ifdef DEV_ISA
p->base = (atpic) ? 0 : nirqs;
#else
p->base = nirqs;
#endif
irq = p->base + irqs + ipis;
nirqs = MAX(nirqs, irq);
npics++;
}
mtx_unlock(&intr_table_lock);
}
int
powerpc_ign_lookup(uint32_t pic_id)
u_int
powerpc_get_irq(uint32_t node, u_int pin)
{
int i;
int idx;
if (node == 0)
return (pin);
mtx_lock(&intr_table_lock);
for (i = 0; i < npics; i++) {
if (piclist[i].pic_id == pic_id) {
for (idx = 0; idx < npics; idx++) {
if (piclist[idx].node == node) {
mtx_unlock(&intr_table_lock);
return (i);
return (piclist[idx].base + pin);
}
}
piclist[i].pic = NULL;
piclist[i].pic_id = pic_id;
piclist[i].ipi_irq = 0;
/*
* XXX we should never encounter an unregistered PIC, but that
* can only be done when we properly support bus enumeration
* using multiple passes. Until then, fake an entry and give it
* some adhoc maximum number of IRQs and IPIs.
*/
piclist[idx].dev = NULL;
piclist[idx].node = node;
piclist[idx].irqs = 124;
piclist[idx].ipis = 4;
piclist[idx].base = nirqs;
nirqs += 128;
npics++;
mtx_unlock(&intr_table_lock);
return (i);
return (piclist[idx].base + pin);
}
int
@ -342,15 +392,18 @@ powerpc_enable_intr(void)
if (npics == 0)
panic("no PIC detected\n");
if (root_pic == NULL)
root_pic = piclist[0].dev;
#ifdef SMP
/* Install an IPI handler. */
for (n = 0; n < npics; n++) {
if (piclist[n].pic != root_pic)
if (piclist[n].dev != root_pic)
continue;
KASSERT(piclist[n].ipis != 0, ("%s", __func__));
error = powerpc_setup_intr("IPI",
INTR_VEC(piclist[n].pic_id, piclist[n].ipi_irq),
INTR_VEC(piclist[n].node, piclist[n].irqs),
powerpc_ipi_handler, NULL, NULL,
INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie);
if (error) {
@ -373,6 +426,9 @@ powerpc_enable_intr(void)
i->pol != INTR_POLARITY_CONFORM)
PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
if (i != NULL && i->pic == root_pic)
PIC_BIND(i->pic, i->intline, i->cpu);
if (i->event != NULL)
PIC_ENABLE(i->pic, i->intline, vector);
}

View File

@ -83,7 +83,7 @@ openpic_set_priority(struct openpic_softc *sc, int pri)
}
int
openpic_attach(device_t dev)
openpic_common_attach(device_t dev, uint32_t node)
{
struct openpic_softc *sc;
u_int cpu, ipi, irq;
@ -217,7 +217,7 @@ openpic_attach(device_t dev)
for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
powerpc_register_pic(dev, sc->sc_nirq);
powerpc_register_pic(dev, node, sc->sc_nirq, 4, FALSE);
/* If this is not a cascaded PIC, it must be the root PIC */
if (sc->sc_intr == NULL)
@ -285,7 +285,6 @@ openpic_dispatch(device_t dev, struct trapframe *tf)
cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
sc = device_get_softc(dev);
while (1) {
vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
vector &= OPENPIC_VECTOR_MASK;

View File

@ -66,10 +66,6 @@ METHOD void ipi {
u_int cpu;
};
METHOD uint32_t id {
device_t dev;
};
METHOD void mask {
device_t dev;
u_int irq;

View File

@ -54,7 +54,6 @@ static void ps3pic_eoi(device_t, u_int);
static void ps3pic_ipi(device_t, u_int);
static void ps3pic_mask(device_t, u_int);
static void ps3pic_unmask(device_t, u_int);
static uint32_t ps3pic_id(device_t dev);
struct ps3pic_softc {
uint64_t *bitmap_thread0;
@ -76,7 +75,6 @@ static device_method_t ps3pic_methods[] = {
DEVMETHOD(pic_dispatch, ps3pic_dispatch),
DEVMETHOD(pic_enable, ps3pic_enable),
DEVMETHOD(pic_eoi, ps3pic_eoi),
DEVMETHOD(pic_id, ps3pic_id),
DEVMETHOD(pic_ipi, ps3pic_ipi),
DEVMETHOD(pic_mask, ps3pic_mask),
DEVMETHOD(pic_unmask, ps3pic_unmask),
@ -146,9 +144,7 @@ ps3pic_attach(device_t dev)
sc->sc_ipi_outlet[1], 0);
#endif
powerpc_register_pic(dev, sc->sc_ipi_outlet[0]);
root_pic = dev; /* PS3s have only one PIC */
powerpc_register_pic(dev, 0, sc->sc_ipi_outlet[0], 1, FALSE);
return (0);
}
@ -245,10 +241,3 @@ ps3pic_unmask(device_t dev, u_int irq)
lv1_did_update_interrupt_mask(ppe, 0);
lv1_did_update_interrupt_mask(ppe, 1);
}
static uint32_t
ps3pic_id(device_t dev)
{
return (0);
}

View File

@ -62,11 +62,12 @@ __FBSDID("$FreeBSD$");
* PSIM IOBus interface
*/
static int openpic_iobus_probe(device_t);
static int openpic_iobus_attach(device_t);
static device_method_t openpic_iobus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, openpic_iobus_probe),
DEVMETHOD(device_attach, openpic_attach),
DEVMETHOD(device_attach, openpic_iobus_attach),
/* PIC interface */
DEVMETHOD(pic_config, openpic_config),
@ -109,3 +110,10 @@ openpic_iobus_probe(device_t dev)
return (0);
}
static int
openpic_iobus_attach(device_t dev)
{
return (openpic_common_attach(dev, 0));
}