#include <machine/nexusvar.h>
#include <machine/smp.h>
-#include <machine_base/apic/mpapic.h>
+#include <machine/intr_machdep.h>
+#include <machine_base/apic/ioapic.h>
#define I386_BUS_SPACE_IO 0 /* space is i/o space */
#define I386_BUS_SPACE_MEM 1 /* space is mem space */
#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev))
-static struct rman irq_rman, drq_rman, port_rman, mem_rman;
+static struct rman irq_rman[MAXCPU], drq_rman, port_rman, mem_rman;
static int nexus_probe(device_t);
static int nexus_attach(device_t);
static device_t nexus_add_child(device_t bus, device_t parent, int order,
const char *name, int unit);
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
- u_long, u_long, u_long, u_int);
+ u_long, u_long, u_long, u_int, int);
static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
static int nexus_activate_resource(device_t, device_t, int, int,
void **, lwkt_serialize_t);
static int nexus_teardown_intr(device_t, device_t, struct resource *,
void *);
-static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long);
+static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long,
+ int);
static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *);
static void nexus_delete_resource(device_t, device_t, int, int);
};
static devclass_t nexus_devclass;
-DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, NULL, NULL);
static int
nexus_probe(device_t dev)
{
+ int cpuid;
+
device_quiet(dev); /* suppress attach message for neatness */
- /*
- * IRQ's are on the mainboard on old systems, but on the ISA part
- * of PCI->ISA bridges. There would be multiple sets of IRQs on
- * multi-ISA-bus systems. PCI interrupts are routed to the ISA
- * component, so in a way, PCI can be a partial child of an ISA bus(!).
- * APIC interrupts are global though.
- * In the non-APIC case, disallow the use of IRQ 2.
- */
- irq_rman.rm_start = 0;
- irq_rman.rm_type = RMAN_ARRAY;
- irq_rman.rm_descr = "Interrupt request lines";
-#ifdef SMP /* APIC-IO */
-if (apic_io_enable) {
- irq_rman.rm_end = APIC_INTMAPSIZE - 1;
- if (rman_init(&irq_rman)
- || rman_manage_region(&irq_rman,
- irq_rman.rm_start, irq_rman.rm_end))
- panic("nexus_probe irq_rman");
-} else {
-#endif
- irq_rman.rm_end = 15;
- if (rman_init(&irq_rman)
- || rman_manage_region(&irq_rman, irq_rman.rm_start, 1)
- || rman_manage_region(&irq_rman, 3, irq_rman.rm_end))
- panic("nexus_probe irq_rman");
-#ifdef SMP /* APIC-IO */
-}
-#endif
+ for (cpuid = 0; cpuid < ncpus; ++cpuid) {
+ struct rman *rm = &irq_rman[cpuid];
+
+ rm->rm_start = 0;
+ rm->rm_end = IDT_HWI_VECTORS - 1;
+ rm->rm_type = RMAN_ARRAY;
+ rm->rm_descr = "Interrupt request lines";
+
+ if (rman_init(rm, cpuid))
+ panic("nexus_probe rman_init");
+ MachIntrABI.rman_setup(rm);
+ }
/*
* ISA DMA on PCI systems is implemented in the ISA part of each
drq_rman.rm_type = RMAN_ARRAY;
drq_rman.rm_descr = "DMA request lines";
/* XXX drq 0 not available on some machines */
- if (rman_init(&drq_rman)
+ if (rman_init(&drq_rman, -1)
|| rman_manage_region(&drq_rman,
drq_rman.rm_start, drq_rman.rm_end))
panic("nexus_probe drq_rman");
port_rman.rm_end = 0xffff;
port_rman.rm_type = RMAN_ARRAY;
port_rman.rm_descr = "I/O ports";
- if (rman_init(&port_rman)
+ if (rman_init(&port_rman, -1)
|| rman_manage_region(&port_rman, 0, 0xffff))
panic("nexus_probe port_rman");
mem_rman.rm_end = ~0u;
mem_rman.rm_type = RMAN_ARRAY;
mem_rman.rm_descr = "I/O memory addresses";
- if (rman_init(&mem_rman)
+ if (rman_init(&mem_rman, -1)
|| rman_manage_region(&mem_rman, 0, ~0))
panic("nexus_probe mem_rman");
bus_generic_attach(dev);
/*
- * And if we didn't see EISA or ISA on a pci bridge, create some
- * connection points now so they show up "on motherboard".
+ * And if we didn't see ISA on a pci bridge, create a
+ * connection point now so it shows up "on motherboard".
*/
- if (!devclass_get_device(devclass_find("eisa"), 0)) {
- child = BUS_ADD_CHILD(dev, dev, 0, "eisa", 0);
- if (child == NULL)
- panic("nexus_attach eisa");
- device_probe_and_attach(child);
- }
if (!devclass_get_device(devclass_find("isa"), 0)) {
child = BUS_ADD_CHILD(dev, dev, 0, "isa", 0);
if (child == NULL)
*/
static struct resource *
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
+ u_long start, u_long end, u_long count, u_int flags, int cpuid)
{
struct nexus_device *ndev = DEVTONX(child);
struct resource *rv;
start = rle->start;
end = rle->end;
count = rle->count;
+ cpuid = rle->cpuid;
}
flags &= ~RF_ACTIVE;
switch (type) {
case SYS_RES_IRQ:
- rm = &irq_rman;
+ KASSERT(cpuid >= 0 || cpuid < ncpus,
+ ("nexus invalid cpuid %d:\n", cpuid));
+ rm = &irq_rman[cpuid];
break;
case SYS_RES_DRQ:
*/
*cookiep = register_int(irq->r_start, (inthand2_t *)ihand, arg,
device_get_nameunit(child), serializer,
- icflags);
+ icflags, rman_get_cpuid(irq));
if (*cookiep == NULL)
error = EINVAL;
return (error);
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
if (ih) {
- unregister_int(ih);
+ unregister_int(ih, rman_get_cpuid(r));
return (0);
}
return(-1);
}
static int
-nexus_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
+nexus_set_resource(device_t dev, device_t child, int type, int rid,
+ u_long start, u_long count, int cpuid)
{
struct nexus_device *ndev = DEVTONX(child);
struct resource_list *rl = &ndev->nx_resources;
/* XXX this should return a success/failure indicator */
- resource_list_add(rl, type, rid, start, start + count - 1, count);
+ resource_list_add(rl, type, rid, start, start + count - 1, count,
+ cpuid);
return(0);
}