Esempio n. 1
0
int
ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 
		   int flags, driver_filter_t *filter, driver_intr_t *function, 
		   void *argument, void **cookiep)
{
	struct ata_pci_controller *controller = device_get_softc(dev);

	if (controller->legacy) {
		return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
			      flags, filter, function, argument, cookiep);
	} else {
		struct ata_pci_controller *controller = device_get_softc(dev);
		int unit;

	    	if (filter != NULL) {
			printf("ata-pci.c: we cannot use a filter here\n");
			return (EINVAL);
		}
		if (device_get_devclass(child) == ata_devclass)
			unit = ((struct ata_channel *)device_get_softc(child))->unit;
		else
			unit = ATA_PCI_MAX_CH - 1;
		controller->interrupt[unit].function = function;
		controller->interrupt[unit].argument = argument;
		*cookiep = controller;
		return 0;
	}
}
Esempio n. 2
0
File: ppc.c Progetto: MarginC/kame
/*
 * Resource is useless here since ppbus devices' interrupt handlers are
 * multiplexed to the same resource initially allocated by ppc
 */
int
ppc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
			void (*ihand)(void *), void *arg, void **cookiep)
{
	int error;
	struct ppc_data *ppc = DEVTOSOFTC(bus);

	if (ppc->ppc_registered) {
		/* XXX refuse registration if DMA is in progress */

		/* first, unregister the default interrupt handler */
		if ((error = BUS_TEARDOWN_INTR(device_get_parent(bus),
				bus, ppc->res_irq, ppc->intr_cookie)))
			return (error);

/* 		bus_deactivate_resource(bus, SYS_RES_IRQ, ppc->rid_irq, */
/* 					ppc->res_irq); */

		/* DMA/FIFO operation won't be possible anymore */
		ppc->ppc_registered = 0;
	}

	/* pass registration to the upper layer, ignore the incoming resource */
	return (BUS_SETUP_INTR(device_get_parent(bus), child,
			       r, flags, ihand, arg, cookiep));
}
Esempio n. 3
0
static int
vga_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
    int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
    void **cookiep)
{
	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
	    filter, intr, arg, cookiep));
}
Esempio n. 4
0
static int
gt_setup_intr(device_t dev, device_t child,
    struct resource *ires, int flags, driver_filter_t *filt, 
    driver_intr_t *intr, void *arg, void **cookiep)
{
	return BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, 
	    filt, intr, arg, cookiep);
}
Esempio n. 5
0
/*
 * We can't use the bus_generic_* versions of these methods because those
 * methods always pass the bus param as the requesting device, and we need
 * to pass the child (the i386 nexus knows about this and is prepared to
 * deal).
 */
int
isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
	       void (*ihand)(void *), void *arg,
	       void **cookiep, lwkt_serialize_t serializer)
{
	return (BUS_SETUP_INTR(device_get_parent(bus), child, r, flags,
			       ihand, arg, cookiep, serializer, NULL));
}
Esempio n. 6
0
/*
 * We can't use the bus_generic_* versions of these methods because those
 * methods always pass the bus param as the requesting device, and we need
 * to pass the child (the i386 nexus knows about this and is prepared to
 * deal).
 */
int
isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
	       driver_filter_t filter, void (*ihand)(void *), void *arg, 
	       void **cookiep)
{
	return (BUS_SETUP_INTR(device_get_parent(bus), child, r, flags,
			       filter, ihand, arg, cookiep));
}
Esempio n. 7
0
/* proxying to the parent */
static int
siba_bwn_setup_intr(device_t dev, device_t child, struct resource *irq,
    int flags, driver_intr_t *intr, void *arg, void **cookiep,
    lwkt_serialize_t serializer)
{

	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
	    intr, arg, cookiep, serializer, NULL));
}
Esempio n. 8
0
int
puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
    int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep)
{
	struct puc_port *port;
	struct puc_softc *sc;
	device_t originator;
	int i, isrc, serdev;

	sc = device_get_softc(dev);

	/* Get our immediate child. */
	originator = child;
	while (child != NULL && device_get_parent(child) != dev)
		child = device_get_parent(child);
	if (child == NULL)
		return (EINVAL);

	port = device_get_ivars(child);
	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));

	if (cookiep == NULL || res != port->p_ires)
		return (EINVAL);
	/* We demand that serdev devices use filter_only interrupts. */
	if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL)
		return (ENXIO);
	if (rman_get_device(port->p_ires) != originator)
		return (ENXIO);

	/*
	 * Have non-serdev ports handled by the bus implementation. It
	 * supports multiple handlers for a single interrupt as it is,
	 * so we wouldn't add value if we did it ourselves.
	 */
	serdev = 0;
	if (port->p_type == PUC_TYPE_SERIAL) {
		i = 0, isrc = SER_INT_OVERRUN;
		while (i < PUC_ISRCCNT) {
			port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc);
			if (port->p_ihsrc[i] != NULL)
				serdev = 1;
			i++, isrc <<= 1;
		}
	}
	if (!serdev)
		return (BUS_SETUP_INTR(device_get_parent(dev), originator,
		    sc->sc_ires, flags, filt, ihand, arg, cookiep));

	sc->sc_serdevs |= 1UL << (port->p_nr - 1);

	port->p_hasintr = 1;
	port->p_iharg = arg;

	*cookiep = port;
	return (0);
}
Esempio n. 9
0
static int
iq80321_setup_intr(device_t dev, device_t child,
    struct resource *ires, int flags, driver_filter_t *filt, 
    driver_intr_t *intr, void *arg, void **cookiep)
{
	BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, intr, 
	    arg, cookiep);
	intr_enabled |= 1 << rman_get_start(ires);
	i80321_set_intrmask();
	
	return (0);
}
Esempio n. 10
0
File: isa.c Progetto: MarginC/kame
int
isa_setup_intr(device_t dev, device_t child,
	       struct resource *irq, int flags,
	       driver_intr_t *intr, void *arg, void **cookiep)
{

	/*
	 * Just pass through. This is going to be handled by either one of
	 * the parent PCI buses or the nexus device.
	 * The interrupt was routed at allocation time.
	 */
	return (BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, intr,
	    arg, cookiep));
}
Esempio n. 11
0
static int
ixp425_setup_intr(device_t dev, device_t child,
    struct resource *res, int flags, driver_filter_t *filt, 
    driver_intr_t *intr, void *arg, void **cookiep)    
{
	uint32_t mask, mask2;

	BUS_SETUP_INTR(device_get_parent(dev), child, res, flags, filt, intr,
	     arg, cookiep);

	get_masks(res, &mask, &mask2);
	update_masks(intr_enabled | mask, intr_enabled2 | mask2);

	return (0);
}
Esempio n. 12
0
static int
at91_setup_intr(device_t dev, device_t child,
    struct resource *ires, int flags, driver_filter_t *filt, 
    driver_intr_t *intr, void *arg, void **cookiep)    
{
	struct at91_softc *sc = device_get_softc(dev);

	if (rman_get_start(ires) == AT91RM92_IRQ_SYSTEM && filt == NULL)
		panic("All system interrupt ISRs must be FILTER");
	BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, 
	    intr, arg, cookiep);
	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IECR,
	    1 << rman_get_start(ires));
	return (0);
}
Esempio n. 13
0
/*
 * These can disappear when I update the pci code to use the new
 * device framework.
 */
struct intrec *
intr_create(void *dev_instance, int irq, inthand2_t handler, void *arg,
	    intrmask_t *maskptr, int flags)
{
	struct resource *res;
	device_t pcib = chipset.intrdev;
	int zero = 0;
	void *cookie;

	res = BUS_ALLOC_RESOURCE(pcib, NULL, SYS_RES_IRQ, &zero,
				irq, irq, 1, RF_SHAREABLE | RF_ACTIVE);
	if (BUS_SETUP_INTR(pcib, pcib, res, (driver_intr_t *)handler, arg, &cookie))
		return 0;

	return (struct intrec *)cookie;
}
Esempio n. 14
0
static int
at91_setup_intr(device_t dev, device_t child,
                struct resource *ires, int flags, driver_filter_t *filt,
                driver_intr_t *intr, void *arg, void **cookiep)
{
    int error;

    if (rman_get_start(ires) == AT91_IRQ_SYSTEM && filt == NULL)
        panic("All system interrupt ISRs must be FILTER");
    error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
                           filt, intr, arg, cookiep);
    if (error)
        return (error);

    return (0);
}
Esempio n. 15
0
static int
pxa_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
    driver_filter_t *filter, driver_intr_t *ithread, void *arg, void **cookiep)
{
	struct	obio_softc *sc;
	int error;

	sc = (struct obio_softc *)device_get_softc(dev);

	error = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags,
	    filter, ithread, arg, cookiep);
	if (error)
		return (error);
	arm_unmask_irq(rman_get_start(irq));
	return (0);
}
Esempio n. 16
0
/**
 *	omap_setup_intr - initialises and unmasks the IRQ.
 *
 *	RETURNS:
 *	0 on success
 */
int
omap_setup_intr(device_t dev, device_t child,
                struct resource *res, int flags, driver_filter_t *filt, 
                driver_intr_t *intr, void *arg, void **cookiep)    
{
	unsigned int i;

	BUS_SETUP_INTR(device_get_parent(dev), child, res, flags, filt, intr,
				   arg, cookiep);

	/* Enable all the interrupts in the range ... will probably be only one */
	for (i = rman_get_start(res); (i < NIRQ) && (i <= rman_get_end(res)); i++) {
		arm_unmask_irq(i);
	}
	
	return (0);
}
Esempio n. 17
0
static int
pckbdattach(device_t dev)
{
	keyboard_t	*kbd;
	void		*ih;
	struct resource	*res;
	int		zero = 0;

	pckbd_attach_unit(device_get_unit(dev), &kbd, isa_get_port(dev),
			  (1 << isa_get_irq(dev)), device_get_flags(dev));

	res = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, 0ul, ~0ul, 1,
				 RF_SHAREABLE | RF_ACTIVE);
	BUS_SETUP_INTR(device_get_parent(dev), dev, res, INTR_TYPE_TTY,
				   pckbd_isa_intr, kbd, &ih);

	return (0);
}
Esempio n. 18
0
File: ppc.c Progetto: MarginC/kame
int
ppc_attach(device_t dev)
{
	struct ppc_data *ppc = DEVTOSOFTC(dev);

	device_t ppbus;
	device_t parent = device_get_parent(dev);

	device_printf(dev, "%s chipset (%s) in %s mode%s\n",
		      ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm],
		      ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
		      ppc_epp_protocol[ppc->ppc_epp] : "");
	
	if (ppc->ppc_fifo)
		device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n",
			      ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr);

	if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) {
		/* acquire the DMA channel forever */	/* XXX */
		isa_dma_acquire(ppc->ppc_dmachan);
		isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */
	}

	/* add ppbus as a child of this isa to parallel bridge */
	ppbus = device_add_child(dev, "ppbus", -1);

	/*
	 * Probe the ppbus and attach devices found.
	 */
	device_probe_and_attach(ppbus);

	/* register the ppc interrupt handler as default */
	if (ppc->res_irq) {
		/* default to the tty mask for registration */	/* XXX */
		if (BUS_SETUP_INTR(parent, dev, ppc->res_irq, INTR_TYPE_TTY,
					    ppcintr, dev, &ppc->intr_cookie) == 0) {

			/* remember the ppcintr is registered */
			ppc->ppc_registered = 1;
		}
	}

	return (0);
}
Esempio n. 19
0
static int
s3c24x0_setup_intr(device_t dev, device_t child,
        struct resource *ires,  int flags, driver_filter_t *filt,
	driver_intr_t *intr, void *arg, void **cookiep)
{
	int error, irq;

	error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
	    intr, arg, cookiep);
	if (error != 0)
		return (error);

	for (irq = rman_get_start(ires); irq <= rman_get_end(ires); irq++) {
		if (irq >= S3C24X0_EXTIRQ_MIN && irq <= S3C24X0_EXTIRQ_MAX) {
			/* Enable the external interrupt pin */
			s3c24x0_enable_ext_intr(irq - S3C24X0_EXTIRQ_MIN);
		}
	}
	return (0);
}
Esempio n. 20
0
int
ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 
		   int flags, driver_intr_t *function, void *argument,
		   void **cookiep)
{
    struct ata_pci_controller *controller = device_get_softc(dev);

    if (controller->legacy) {
	return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
			      flags, function, argument, cookiep, NULL, NULL);
    }
    else {
	struct ata_pci_controller *controller = device_get_softc(dev);
	int unit = ((struct ata_channel *)device_get_softc(child))->unit;

	controller->interrupt[unit].function = function;
	controller->interrupt[unit].argument = argument;
	*cookiep = controller;
	return 0;
    }
}
Esempio n. 21
0
static int
sa1110_setup_intr(device_t dev, device_t child,
        struct resource *ires,  int flags, driver_filter_t *filt, 
	driver_intr_t *intr, void *arg, void **cookiep)
{
	int saved_cpsr;
	
	if (flags & INTR_TYPE_TTY) 
		rman_set_start(ires, 15);
	else if (flags & INTR_TYPE_CLK) {
		if (rman_get_start(ires) == 0)
			rman_set_start(ires, 26);
		else
			rman_set_start(ires, 27);
	}
	saved_cpsr = SetCPSR(I32_bit, I32_bit);                 

	SetCPSR(I32_bit, saved_cpsr & I32_bit);
	BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, 
	    intr, arg, cookiep);
	return (0);
}
Esempio n. 22
0
File: ppc.c Progetto: MarginC/kame
/*
 * When no underlying device has a registered interrupt, register the ppc
 * layer one
 */
int
ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih)
{
	int error;
	struct ppc_data *ppc = DEVTOSOFTC(bus);
	device_t parent = device_get_parent(bus);

	/* pass unregistration to the upper layer */
	if ((error = BUS_TEARDOWN_INTR(parent, child, r, ih)))
		return (error);

	/* default to the tty mask for registration */		/* XXX */
	if (ppc->ppc_irq &&
		!(error = BUS_SETUP_INTR(parent, bus, ppc->res_irq,
			INTR_TYPE_TTY, ppcintr, bus, &ppc->intr_cookie))) {

		/* remember the ppcintr is registered */
		ppc->ppc_registered = 1;
	}

	return (error);
}
Esempio n. 23
0
static int
pcf_attach(device_t pcfdev)
{
	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
	device_t parent = device_get_parent(pcfdev);
	int error = 0;

	if (pcf->res_irq) {
		/* default to the tty mask for registration */	/* XXX */
		error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq,
					0, pcfintr, pcfdev,
					&pcf->intr_cookie, NULL, NULL);
		if (error)
			return (error);
	}

	pcf->iicbus = device_add_child(pcfdev, "iicbus", -1);

	/* probe and attach the iicbus */
	bus_generic_attach(pcfdev);

	return (0);
}
Esempio n. 24
0
static int
envctrl_attach(device_t dev)
{
	struct pcf_softc *sc;
	int rv = ENXIO;

	sc = DEVTOSOFTC(dev);
	bzero(sc, sizeof(struct pcf_softc));

	/* IO port is mandatory */
	sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
						&sc->rid_ioport, RF_ACTIVE);
	if (sc->res_ioport == 0) {
		device_printf(dev, "cannot reserve I/O port range\n");
		goto error;
	}
	sc->bt_ioport = rman_get_bustag(sc->res_ioport);
	sc->bh_ioport = rman_get_bushandle(sc->res_ioport);

	sc->pcf_flags = device_get_flags(dev);

	if (!(sc->pcf_flags & IIC_POLLED)) {
		sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq,
						     RF_ACTIVE);
		if (sc->res_irq == 0) {
			device_printf(dev, "can't reserve irq, polled mode.\n");
			sc->pcf_flags |= IIC_POLLED;
		}
	}

	/* reset the chip */
	pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);

	rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq,
			    INTR_TYPE_NET /* | INTR_ENTROPY */,
			    pcf_intr, sc, &sc->intr_cookie);
	if (rv) {
		device_printf(dev, "could not setup IRQ\n");
		goto error;
	}

	if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL)
		device_printf(dev, "could not allocate iicbus instance\n");

	/* probe and attach the iicbus */
	bus_generic_attach(dev);

	return (0);

error:
	if (sc->res_irq != 0) {
		bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq,
					sc->res_irq);
		bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq,
				     sc->res_irq);
	}
	if (sc->res_ioport != 0) {
		bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport,
					sc->res_ioport);
		bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport,
				     sc->res_ioport);
	}
	return (rv);
}
Esempio n. 25
0
static int
ohci_pci_attach(device_t self)
{
	device_t parent = device_get_parent(self);
	ohci_softc_t *sc = device_get_softc(self);
	int err;
	int rid;
	struct resource *io_res, *irq_res;
	void *ih;
	int intr;

	/* For the moment, put in a message stating what is wrong */
	intr = pci_read_config(self, PCIR_INTLINE, 1);
	if (intr == 0 || intr == 255) {
		device_printf(self, "Invalid irq %d\n", intr);
		device_printf(self, "Please switch on USB support and switch PNP-OS to 'No' in BIOS\n");
		return ENXIO;
	}

	/* XXX where does it say so in the spec? */
	sc->sc_bus.usbrev = USBREV_1_0;

	rid = PCI_CBMEM;
	io_res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid,
				    0, ~0, 1, RF_ACTIVE);
	if (!io_res) {
		device_printf(self, "could not map memory\n");
		return ENXIO;
        }

	sc->iot = rman_get_bustag(io_res);
	sc->ioh = rman_get_bushandle(io_res);

	rid = 0;
	irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1,
				     RF_SHAREABLE | RF_ACTIVE);
	if (irq_res == NULL) {
		device_printf(self, "could not allocate irq\n");
		err = ENOMEM;
		goto bad1;
	}

	sc->sc_bus.bdev = device_add_child(self, "usb", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "could not add USB device\n");
		err = ENOMEM;
		goto bad2;
	}
	device_set_ivars(sc->sc_bus.bdev, sc);

	switch (pci_get_devid(self)) {
	case PCI_OHCI_DEVICEID_ALADDIN_V:
		device_set_desc(sc->sc_bus.bdev, ohci_device_aladdin_v);
		sprintf(sc->sc_vendor, "AcerLabs");
		break;
	case PCI_OHCI_DEVICEID_AMD756:
		device_set_desc(sc->sc_bus.bdev, ohci_device_amd756);
		sprintf(sc->sc_vendor, "AMD");
		break;
	case PCI_OHCI_DEVICEID_FIRELINK:
		device_set_desc(sc->sc_bus.bdev, ohci_device_firelink);
		sprintf(sc->sc_vendor, "OPTi");
		break;
	case PCI_OHCI_DEVICEID_NEC:
		device_set_desc(sc->sc_bus.bdev, ohci_device_nec);
		sprintf(sc->sc_vendor, "NEC");
		break;
	case PCI_OHCI_DEVICEID_USB0670:
		device_set_desc(sc->sc_bus.bdev, ohci_device_usb0670);
		sprintf(sc->sc_vendor, "CMDTECH");
		break;
	case PCI_OHCI_DEVICEID_USB0673:
		device_set_desc(sc->sc_bus.bdev, ohci_device_usb0673);
		sprintf(sc->sc_vendor, "CMDTECH");
		break;
	default:
		if (bootverbose)
			device_printf(self, "(New OHCI DeviceId=0x%08x)\n",
				      pci_get_devid(self));
		device_set_desc(sc->sc_bus.bdev, ohci_device_generic);
		sprintf(sc->sc_vendor, "(unknown)");
	}

	err = BUS_SETUP_INTR(parent, self, irq_res, INTR_TYPE_BIO,
			     (driver_intr_t *) ohci_intr, sc, &ih);
	if (err) {
		device_printf(self, "could not setup irq, %d\n", err);
		goto bad3;
	}

	err = ohci_init(sc);
	if (!err)
		err = device_probe_and_attach(sc->sc_bus.bdev);

	if (err) {
		device_printf(self, "USB init failed\n");
		err = EIO;
		goto bad4;
	}

	return 0;
bad4:
	/* disable interrupts that might have been switched on
	 * in ohci_init
	 */
	bus_space_write_4(sc->iot, sc->ioh,
			  OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);

	err = BUS_TEARDOWN_INTR(parent, self, irq_res, ih);
	if (err)
		/* XXX or should we panic? */
		device_printf(self, "could not tear down irq, %d\n", err);
bad3:
	device_delete_child(self, sc->sc_bus.bdev);
bad2:
	bus_release_resource(self, SYS_RES_IOPORT, 0, irq_res);
bad1:
	bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, io_res);
	return err;
}
Esempio n. 26
0
int
pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg,
                  intrmask_t *maskptr, u_int intflags)
{
    int error;
#ifdef APIC_IO
    int nextpin, muxcnt;
#endif
    if (cfg->intpin != 0) {
        int irq = cfg->intline;
        int rid = 0;
        struct resource *res;
        int flags = 0;
        int resflags = RF_SHAREABLE|RF_ACTIVE;
        void *ih;

#ifdef INTR_FAST
        if (intflags & INTR_FAST)
            flags |= INTR_TYPE_FAST;
        if (intflags & INTR_EXCL)
            resflags &= ~RF_SHAREABLE;
#endif

        res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid,
                                 irq, irq, 1, resflags);
        if (!res) {
            printf("pci_map_int: can't allocate interrupt\n");
            return 0;
        }

        /*
         * This is ugly. Translate the mask into an interrupt type.
         */
        if (maskptr == &tty_imask)
            flags |= INTR_TYPE_TTY;
        else if (maskptr == &bio_imask)
            flags |= INTR_TYPE_BIO;
        else if (maskptr == &net_imask)
            flags |= INTR_TYPE_NET;
        else if (maskptr == &cam_imask)
            flags |= INTR_TYPE_CAM;

        error = BUS_SETUP_INTR(device_get_parent(cfg->dev), cfg->dev,
                               res, flags, handler, arg, &ih);
        if (error != 0)
            return 0;

#ifdef NEW_BUS_PCI
        /*
         * XXX this apic stuff looks totally busted.  It should
         * move to the nexus code which actually registers the
         * interrupt.
         */
#endif

#ifdef APIC_IO
        nextpin = next_apic_irq(irq);

        if (nextpin < 0)
            return 1;

        /*
         * Attempt handling of some broken mp tables.
         *
         * It's OK to yell (since the mp tables are broken).
         *
         * Hanging in the boot is not OK
         */

        muxcnt = 2;
        nextpin = next_apic_irq(nextpin);
        while (muxcnt < 5 && nextpin >= 0) {
            muxcnt++;
            nextpin = next_apic_irq(nextpin);
        }
        if (muxcnt >= 5) {
            printf("bogus MP table, more than 4 IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n");
            return 0;
        }

        printf("bogus MP table, %d IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n", muxcnt);

        nextpin = next_apic_irq(irq);
        while (nextpin >= 0) {
            rid = 0;
            res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid,
                                     nextpin, nextpin, 1,
                                     resflags);
            if (!res) {
                printf("pci_map_int: can't allocate extra interrupt\n");
                return 0;
            }
            error = BUS_SETUP_INTR(device_get_parent(cfg->dev),
                                   cfg->dev, res, flags,
                                   handler, arg, &ih);
            if (error != 0) {
                printf("pci_map_int: BUS_SETUP_INTR failed\n");
                return 0;
            }
            printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq);
            nextpin = next_apic_irq(nextpin);
        }
#endif
    }
    return (1);
}
Esempio n. 27
0
File: sbus.c Progetto: MarginC/kame
static int
sbus_setup_intr(device_t dev, device_t child,
    struct resource *ires,  int flags, driver_intr_t *intr, void *arg,
    void **cookiep)
{
	struct sbus_softc *sc;
	struct sbus_clr *scl;
	bus_addr_t intrmapptr, intrclrptr, intrptr;
	u_int64_t intrmap;
	u_int32_t inr, slot;
	int error, i;
	long vec = rman_get_start(ires);

	sc = (struct sbus_softc *)device_get_softc(dev);
	scl = (struct sbus_clr *)malloc(sizeof(*scl), M_DEVBUF, M_NOWAIT);
	if (scl == NULL)
		return (NULL);
	intrptr = intrmapptr = intrclrptr = 0;
	intrmap = 0;
	inr = INTVEC(vec);
	if ((inr & INTMAP_OBIO_MASK) == 0) {
		/*
		 * We're in an SBUS slot, register the map and clear
		 * intr registers.
		 */
		slot = INTSLOT(vec);
		intrmapptr = SBR_SLOT0_INT_MAP + slot * 8;
		intrclrptr = SBR_SLOT0_INT_CLR +
		    (slot * 8 * 8) + (INTPRI(vec) * 8);
		/* Enable the interrupt, insert IGN. */
		intrmap = inr | sc->sc_ign;
	} else {
		intrptr = SBR_SCSI_INT_MAP;
		/* Insert IGN */
		inr |= sc->sc_ign;
		for (i = 0; intrptr <= SBR_RESERVED_INT_MAP &&
			 INTVEC(intrmap = SYSIO_READ8(sc, intrptr)) !=
			 INTVEC(inr); intrptr += 8, i++)
			;
		if (INTVEC(intrmap) == INTVEC(inr)) {
			/* Register the map and clear intr registers */
			intrmapptr = intrptr;
			intrclrptr = SBR_SCSI_INT_CLR + i * 8;
			/* Enable the interrupt */
		} else
			panic("sbus_setup_intr: IRQ not found!");
	}

	scl->scl_sc = sc;
	scl->scl_arg = arg;
	scl->scl_handler = intr;
	scl->scl_clr = intrclrptr;
	/* Disable the interrupt while we fiddle with it */
	SYSIO_WRITE8(sc, intrmapptr, intrmap);
	error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
	    sbus_intr_stub, scl, cookiep);
	if (error != 0) {
		free(scl, M_DEVBUF);
		return (error);
	}
	scl->scl_cookie = *cookiep;
	*cookiep = scl;

	/*
	 * Clear the interrupt, it might have been triggered before it was
	 * set up.
	 */
	SYSIO_WRITE8(sc, intrclrptr, 0);
	/*
	 * Enable the interrupt and program the target module now we have the
	 * handler installed.
	 */
	SYSIO_WRITE8(sc, intrmapptr, INTMAP_ENABLE(intrmap, PCPU_GET(mid)));
	return (error);
}