Exemple #1
0
static int
uhci_pci_attach(device_t self)
{
	uhci_softc_t *sc = device_get_softc(self);
	int rid;
	int err;

	/* initialise some bus fields */
	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = UHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
	    &uhci_iterate_hw_softc)) {
		return ENOMEM;
	}
	sc->sc_dev = self;

	pci_enable_busmaster(self);

	rid = PCI_UHCI_BASE_REG;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_IOPORT, &rid,
	    RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map ports\n");
		goto error;
	}
	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	/* disable interrupts */
	bus_space_write_2(sc->sc_io_tag, sc->sc_io_hdl, UHCI_INTR, 0);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	/*
	 * uhci_pci_match must never return NULL if uhci_pci_probe
	 * succeeded
	 */
	device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self));
	switch (pci_get_vendor(self)) {
	case PCI_UHCI_VENDORID_INTEL:
		sprintf(sc->sc_vendor, "Intel");
		break;
	case PCI_UHCI_VENDORID_HP:
		sprintf(sc->sc_vendor, "HP");
		break;
	case PCI_UHCI_VENDORID_VIA:
		sprintf(sc->sc_vendor, "VIA");
		break;
	default:
		if (bootverbose) {
			device_printf(self, "(New UHCI DeviceId=0x%08x)\n",
			    pci_get_devid(self));
		}
		sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
	}

	switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) {
	case PCI_USB_REV_PRE_1_0:
		sc->sc_bus.usbrev = USB_REV_PRE_1_0;
		break;
	case PCI_USB_REV_1_0:
		sc->sc_bus.usbrev = USB_REV_1_0;
		break;
	default:
		/* Quirk for Parallels Desktop 4.0 */
		device_printf(self, "USB revision is unknown. Assuming v1.1.\n");
		sc->sc_bus.usbrev = USB_REV_1_1;
		break;
	}

#if (__FreeBSD_version >= 700031)
	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl);
#else
	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl);
#endif

	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}
	/*
	 * Set the PIRQD enable bit and switch off all the others. We don't
	 * want legacy support to interfere with us XXX Does this also mean
	 * that the BIOS won't touch the keyboard anymore if it is connected
	 * to the ports of the root hub?
	 */
#ifdef USB_DEBUG
	if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN) {
		device_printf(self, "LegSup = 0x%04x\n",
		    pci_read_config(self, PCI_LEGSUP, 2));
	}
#endif
	pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);

	err = uhci_init(sc);
	if (!err) {
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(self, "USB init failed\n");
		goto error;
	}
	return (0);

error:
	uhci_pci_detach(self);
	return (ENXIO);
}
Exemple #2
0
static int
simplebus_attach(device_t dev)
{
	device_t dev_child;
	struct simplebus_devinfo *di;
	struct simplebus_softc *sc;
	phandle_t dt_node, dt_child;

	sc = device_get_softc(dev);

	/*
	 * Walk simple-bus and add direct subordinates as our children.
	 */
	dt_node = ofw_bus_get_node(dev);
	for (dt_child = OF_child(dt_node); dt_child != 0;
	    dt_child = OF_peer(dt_child)) {

		/* Check and process 'status' property. */
		if (!(fdt_is_enabled(dt_child)))
			continue;

		if (!(fdt_pm_is_enabled(dt_child)))
			continue;

		di = malloc(sizeof(*di), M_SIMPLEBUS, M_WAITOK | M_ZERO);

		if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) {
			free(di, M_SIMPLEBUS);
			device_printf(dev, "could not set up devinfo\n");
			continue;
		}

		resource_list_init(&di->di_res);
		if (fdt_reg_to_rl(dt_child, &di->di_res)) {
			device_printf(dev,
			    "%s: could not process 'reg' "
			    "property\n", di->di_ofw.obd_name);
			/* XXX should unmap */
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_SIMPLEBUS);
			continue;
		}

		if (fdt_intr_to_rl(dt_child, &di->di_res, di->di_intr_sl)) {
			device_printf(dev, "%s: could not process "
			    "'interrupts' property\n", di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			/* XXX should unmap */
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_SIMPLEBUS);
			continue;
		}

		/* Add newbus device for this FDT node */
		dev_child = device_add_child(dev, NULL, -1);
		if (dev_child == NULL) {
			device_printf(dev, "could not add child: %s\n",
			    di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			/* XXX should unmap */
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_SIMPLEBUS);
			continue;
		}
#ifdef DEBUG
		device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name);
#endif
		device_set_ivars(dev_child, di);
	}

	return (bus_generic_attach(dev));
}
Exemple #3
0
static int
ohci_ec_attach(device_t dev)
{
	struct ec_ohci_softc *sc = device_get_softc(dev);
	bus_space_handle_t bsh;
	int err;
	int rid;

	/* initialise some bus fields */
	sc->sc_ohci.sc_bus.parent = dev;
	sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
	sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
	    USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) {
		return (ENOMEM);
	}
	sc->sc_ohci.sc_dev = dev;

	rid = MEM_RID;

	sc->sc_ohci.sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &rid, RF_ACTIVE);

	if (!(sc->sc_ohci.sc_io_res)) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_ohci.sc_io_tag = rman_get_bustag(sc->sc_ohci.sc_io_res);
	bsh = rman_get_bushandle(sc->sc_ohci.sc_io_res);
	/* Undocumented magic initialization */
	bus_space_write_4((sc)->sc_ohci.sc_io_tag, bsh,0x04, 0x146);

	bus_space_write_4((sc)->sc_ohci.sc_io_tag, bsh,0x44, 0x0200);

	DELAY(1000);

	sc->sc_ohci.sc_io_size = rman_get_size(sc->sc_ohci.sc_io_res);

	if (bus_space_subregion(sc->sc_ohci.sc_io_tag, bsh, 0x4000000,
	    sc->sc_ohci.sc_io_size, &sc->sc_ohci.sc_io_hdl) != 0)
		panic("%s: unable to subregion USB host registers",
		    device_get_name(dev));

	rid = 0;
	sc->sc_ohci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!(sc->sc_ohci.sc_irq_res)) {
		goto error;
	}
	sc->sc_ohci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!(sc->sc_ohci.sc_bus.bdev)) {
		goto error;
	}
	device_set_ivars(sc->sc_ohci.sc_bus.bdev, &sc->sc_ohci.sc_bus);

	strlcpy(sc->sc_ohci.sc_vendor, "Cavium",
		sizeof(sc->sc_ohci.sc_vendor));

#if (__FreeBSD_version >= 700031)
	err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res,
	    INTR_TYPE_BIO | INTR_MPSAFE,  NULL,
	    (driver_intr_t *)ohci_interrupt, sc,
	    &sc->sc_ohci.sc_intr_hdl);
#else
	err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res,
	    INTR_TYPE_BIO | INTR_MPSAFE,
	    (driver_intr_t *)ohci_interrupt, sc,
	    &sc->sc_ohci.sc_intr_hdl);
#endif
	if (err) {
		sc->sc_ohci.sc_intr_hdl = NULL;
		goto error;
	}

	bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
	    OHCI_CONTROL, 0);

	err = ohci_init(&sc->sc_ohci);
	if (!err) {
		err = device_probe_and_attach(sc->sc_ohci.sc_bus.bdev);
	}
	if (err) {
		goto error;
	}
	return (0);

error:
	ohci_ec_detach(dev);
	return (ENXIO);
}
Exemple #4
0
static int
ofw_iicbus_attach(device_t dev)
{
	struct iicbus_softc *sc = IICBUS_SOFTC(dev);
	struct ofw_iicbus_devinfo *dinfo;
	phandle_t child, node, root;
	pcell_t freq, paddr;
	device_t childdev;
	ssize_t compatlen;
	char compat[255];
	char *curstr;
	u_int iic_addr_8bit = 0;

	sc->dev = dev;
	mtx_init(&sc->lock, "iicbus", NULL, MTX_DEF);

	/*
	 * If there is a clock-frequency property for the device node, use it as
	 * the starting value for the bus frequency.  Then call the common
	 * routine that handles the tunable/sysctl which allows the FDT value to
	 * be overridden by the user.
	 */
	node = ofw_bus_get_node(dev);
	freq = 0;
	OF_getencprop(node, "clock-frequency", &freq, sizeof(freq));
	iicbus_init_frequency(dev, freq);
	
	iicbus_reset(dev, IIC_FASTEST, 0, NULL);

	bus_generic_probe(dev);
	bus_enumerate_hinted_children(dev);

	/*
	 * Check if we're running on a PowerMac, needed for the I2C
	 * address below.
	 */
	root = OF_peer(0);
	compatlen = OF_getprop(root, "compatible", compat,
				sizeof(compat));
	if (compatlen != -1) {
	    for (curstr = compat; curstr < compat + compatlen;
		curstr += strlen(curstr) + 1) {
		if (strncmp(curstr, "MacRISC", 7) == 0)
		    iic_addr_8bit = 1;
	    }
	}

	/*
	 * Attach those children represented in the device tree.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		/*
		 * Try to get the I2C address first from the i2c-address
		 * property, then try the reg property.  It moves around
		 * on different systems.
		 */
		if (OF_getencprop(child, "i2c-address", &paddr,
		    sizeof(paddr)) == -1)
			if (OF_getencprop(child, "reg", &paddr,
			    sizeof(paddr)) == -1)
				continue;

		/*
		 * Now set up the I2C and OFW bus layer devinfo and add it
		 * to the bus.
		 */
		dinfo = malloc(sizeof(struct ofw_iicbus_devinfo), M_DEVBUF,
		    M_NOWAIT | M_ZERO);
		if (dinfo == NULL)
			continue;
		/*
		 * FreeBSD drivers expect I2C addresses to be expressed as
		 * 8-bit values.  Apple OFW data contains 8-bit values, but
		 * Linux FDT data contains 7-bit values, so shift them up to
		 * 8-bit format.
		 */
		if (iic_addr_8bit)
		    dinfo->opd_dinfo.addr = paddr;
		else
		    dinfo->opd_dinfo.addr = paddr << 1;

		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
		    0) {
			free(dinfo, M_DEVBUF);
			continue;
		}

		childdev = device_add_child(dev, NULL, -1);
		resource_list_init(&dinfo->opd_dinfo.rl);
		ofw_bus_intr_to_rl(childdev, child,
					&dinfo->opd_dinfo.rl, NULL);
		device_set_ivars(childdev, dinfo);
	}

	/* Register bus */
	OF_device_register_xref(OF_xref_from_node(node), dev);
	return (bus_generic_attach(dev));
}
Exemple #5
0
static int
ehci_ps3_attach(device_t dev)
{
	ehci_softc_t *sc = device_get_softc(dev);
	int rid, err;

	sc->sc_bus.parent = dev;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc))
		return (ENOMEM);

	rid = 1;
	sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &rid, RF_ACTIVE);

	if (!sc->sc_io_res) {
		device_printf(dev, "Could not map memory\n");
		goto error;
	}

	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	rid = 1;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);

	if (sc->sc_irq_res == NULL) {
		device_printf(dev, "Could not allocate irq\n");
		return (ENXIO);
	}

	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(dev, "Could not add USB device\n");
		return (ENXIO);
	}

	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	sprintf(sc->sc_vendor, "Sony");

	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(dev, "Could not setup error irq, %d\n", err);
		goto error;
	}

	sc->sc_vendor_post_reset = ehci_ps3_post_reset;
	err = ehci_init(sc);
	if (err) {
		device_printf(dev, "USB init failed err=%d\n", err);
		goto error;
	}

	err = device_probe_and_attach(sc->sc_bus.bdev);
	if (err == 0)
		return (0);

error:
	return (ENXIO);
}
Exemple #6
0
static int
ar71xx_ohci_attach(device_t dev)
{
	struct ar71xx_ohci_softc *sc = device_get_softc(dev);
	int err;
	int rid;

	/* initialise some bus fields */
	sc->sc_ohci.sc_bus.parent = dev;
	sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
	sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
	sc->sc_ohci.sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
	    USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) {
		return (ENOMEM);
	}

	sc->sc_ohci.sc_dev = dev;

	rid = 0;
	sc->sc_ohci.sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->sc_ohci.sc_io_res == NULL) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_ohci.sc_io_tag = rman_get_bustag(sc->sc_ohci.sc_io_res);
	sc->sc_ohci.sc_io_hdl = rman_get_bushandle(sc->sc_ohci.sc_io_res);
	sc->sc_ohci.sc_io_size = rman_get_size(sc->sc_ohci.sc_io_res);

	rid = 0;
	sc->sc_ohci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (sc->sc_ohci.sc_irq_res == NULL) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_ohci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (sc->sc_ohci.sc_bus.bdev == NULL) {
		err = ENOMEM;
		goto error;
	}
	device_set_ivars(sc->sc_ohci.sc_bus.bdev, &sc->sc_ohci.sc_bus);

	err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, 
	    INTR_TYPE_BIO | INTR_MPSAFE, NULL, 
	    ar71xx_ohci_intr, sc, &sc->sc_ohci.sc_intr_hdl);
	if (err) {
		err = ENXIO;
		goto error;
	}

	strlcpy(sc->sc_ohci.sc_vendor, "Atheros", sizeof(sc->sc_ohci.sc_vendor));

	bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl, OHCI_CONTROL, 0);

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

	if (err)
		goto error;
	return (0);

error:
	if (err) {
		ar71xx_ohci_detach(dev);
		return (err);
	}
	return (err);
}
Exemple #7
0
static int
ata_cbus_attach(device_t dev)
{
    struct ata_cbus_controller *ctlr = device_get_softc(dev);
    device_t child;
    int rid, unit;

    /* allocate resources */
    rid = ATA_IOADDR_RID;
    if (!(ctlr->io = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &rid,
						 ATA_PC98_IOSIZE, RF_ACTIVE)))
       return ENOMEM;

    rid = ATA_PC98_CTLADDR_RID;
    if (!(ctlr->ctlio = 
	  bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
			     rman_get_start(ctlr->io) + ATA_PC98_CTLOFFSET, ~0,
			     ATA_CTLIOSIZE, RF_ACTIVE))) {
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io);
	return ENOMEM;
    }

    rid = ATA_PC98_BANKADDR_RID;
    if (!(ctlr->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
					    ATA_PC98_BANK, ~0,
					    ATA_PC98_BANKIOSIZE, RF_ACTIVE))) {
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io);
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlr->ctlio);
	return ENOMEM;
    }

    rid = ATA_IRQ_RID;
    if (!(ctlr->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
					     RF_ACTIVE | RF_SHAREABLE))) {
	device_printf(dev, "unable to alloc interrupt\n");
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io);
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlr->ctlio);
	bus_release_resource(dev, SYS_RES_IOPORT, 
			     ATA_PC98_BANKADDR_RID, ctlr->bankio);
	return ENXIO;
    }

    if ((bus_setup_intr(dev, ctlr->irq, ATA_INTR_FLAGS,
			NULL, ata_cbus_intr, ctlr, &ctlr->ih))) {
	device_printf(dev, "unable to setup interrupt\n");
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io);
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlr->ctlio);
	bus_release_resource(dev, SYS_RES_IOPORT, 
			     ATA_PC98_BANKADDR_RID, ctlr->bankio);
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IRQ_RID, ctlr->irq);
	return ENXIO;
    }

	/* Work around the lack of channel serialization in ATA_CAM. */
	ctlr->channels = 1;
	device_printf(dev, "second channel ignored\n");

    for (unit = 0; unit < ctlr->channels; unit++) {
	child = device_add_child(dev, "ata", unit);
	if (child == NULL)
	    device_printf(dev, "failed to add ata child device\n");
	else
	    device_set_ivars(child, (void *)(intptr_t)unit);
    }

    bus_generic_attach(dev);
    return (0);
}
Exemple #8
0
static int
gusisa_probe(device_t dev)
{
	device_t child;
	struct resource *res, *res2;
	int base, rid, rid2, s, flags;
	unsigned char val;

	base = isa_get_port(dev);
	flags = device_get_flags(dev);
	rid = 1;
	res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, base + 0x100,
				 base + 0x107, 8, RF_ACTIVE);

	if (res == NULL)
		return ENXIO;

	res2 = NULL;

	/*
	 * Check for the presence of some GUS card.  Reset the card,
	 * then see if we can access the memory on it.
	 */

	port_wr(res, 3, 0x4c);
	port_wr(res, 5, 0);
	DELAY(30 * 1000);

	port_wr(res, 3, 0x4c);
	port_wr(res, 5, 1);
	DELAY(30 * 1000);

	s = splhigh();

	/* Write to DRAM.  */

	port_wr(res, 3, 0x43);		/* Register select */
	port_wr(res, 4, 0);		/* Low addr */
	port_wr(res, 5, 0);		/* Med addr */

	port_wr(res, 3, 0x44);		/* Register select */
	port_wr(res, 4, 0);		/* High addr */
	port_wr(res, 7, 0x55);		/* DRAM */

	/* Read from DRAM.  */

	port_wr(res, 3, 0x43);		/* Register select */
	port_wr(res, 4, 0);		/* Low addr */
	port_wr(res, 5, 0);		/* Med addr */

	port_wr(res, 3, 0x44);		/* Register select */
	port_wr(res, 4, 0);		/* High addr */
	val = port_rd(res, 7);		/* DRAM */

	splx(s);

	if (val != 0x55)
		goto fail;

	rid2 = 0;
	res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid2, base, base, 1,
				  RF_ACTIVE);

	if (res2 == NULL)
		goto fail;

	s = splhigh();
	port_wr(res2, 0x0f, 0x20);
	val = port_rd(res2, 0x0f);
	splx(s);

	if (val == 0xff || (val & 0x06) == 0)
		val = 0;
	else {
		val = port_rd(res2, 0x506);	/* XXX Out of range.  */
		if (val == 0xff)
			val = 0;
	}

	bus_release_resource(dev, SYS_RES_IOPORT, rid2, res2);
	bus_release_resource(dev, SYS_RES_IOPORT, rid, res);

	if (val >= 10) {
		struct sndcard_func *func;

		/* Looks like a GUS MAX.  Set the rest of the resources.  */

		bus_set_resource(dev, SYS_RES_IOPORT, 2, base + 0x10c, 8);

		if (flags & DV_F_DUAL_DMA)
			bus_set_resource(dev, SYS_RES_DRQ, 1,
					 flags & DV_F_DRQ_MASK, 1);

		/* We can support the CS4231 and MIDI devices.  */

		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
		if (func == NULL)
			return ENOMEM;
		func->func = SCF_MIDI;
		child = device_add_child(dev, "midi", -1);
		device_set_ivars(child, func);

		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
		if (func == NULL)
			printf("xxx: gus pcm not attached, out of memory\n");
		else {
			func->func = SCF_PCM;
			child = device_add_child(dev, "pcm", -1);
			device_set_ivars(child, func);
		}
		device_set_desc(dev, "Gravis UltraSound MAX");
		return 0;
	} else {

		/*
		 * TODO: Support even older GUS cards.  MIDI should work on
		 * all models.
		 */
		return ENXIO;
	}

fail:
	bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
	return ENXIO;
}
Exemple #9
0
static int
tegra_xhci_attach(device_t dev)
{
	struct tegra_xhci_softc *sc;
	struct xhci_softc *xsc;
	int rv, rid;
	phandle_t node;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->fw_name = "tegra124_xusb_fw";
	node = ofw_bus_get_node(dev);
	xsc = &sc->xhci_softc;
	LOCK_INIT(sc);

	rv = get_fdt_resources(sc, node);
	if (rv != 0) {
		rv = ENXIO;
		goto error;
	}
	rv = enable_fdt_resources(sc);
	if (rv != 0) {
		rv = ENXIO;
		goto error;
	}

	/* Allocate resources. */
	rid = 0;
	xsc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (xsc->sc_io_res == NULL) {
		device_printf(dev,
		    "Could not allocate HCD memory resources\n");
		rv = ENXIO;
		goto error;
	}
	rid = 1;
	sc->mem_res_fpci = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->mem_res_fpci == NULL) {
		device_printf(dev,
		    "Could not allocate FPCI memory resources\n");
		rv = ENXIO;
		goto error;
	}
	rid = 2;
	sc->mem_res_ipfs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->mem_res_ipfs == NULL) {
		device_printf(dev,
		    "Could not allocate IPFS memory resources\n");
		rv = ENXIO;
		goto error;
	}

	rid = 0;
	xsc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (xsc->sc_irq_res == NULL) {
		device_printf(dev, "Could not allocate HCD IRQ resources\n");
		rv = ENXIO;
		goto error;
	}
	rid = 1;
	sc->irq_res_mbox = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (sc->irq_res_mbox == NULL) {
		device_printf(dev, "Could not allocate MBOX IRQ resources\n");
		rv = ENXIO;
		goto error;
	}

	rv = init_hw(sc);
	if (rv != 0) {
		device_printf(dev, "Could not initialize  XUSB hardware\n");
		goto error;
	}

	/* Wakeup and enable firmaware */
	rv = mbox_send_cmd(sc, MBOX_CMD_MSG_ENABLED, 0);
	if (rv != 0) {
		device_printf(sc->dev, "Could not enable XUSB firmware\n");
		goto error;
	}

	/* Fill data for XHCI driver. */
	xsc->sc_bus.parent = dev;
	xsc->sc_bus.devices = xsc->sc_devices;
	xsc->sc_bus.devices_max = XHCI_MAX_DEVICES;

	xsc->sc_io_tag = rman_get_bustag(xsc->sc_io_res);
	xsc->sc_io_hdl = rman_get_bushandle(xsc->sc_io_res);
	xsc->sc_io_size = rman_get_size(xsc->sc_io_res);
	strlcpy(xsc->sc_vendor, "Nvidia", sizeof(xsc->sc_vendor));

	/* Add USB bus device. */
	xsc->sc_bus.bdev = device_add_child(sc->dev, "usbus", -1);
	if (xsc->sc_bus.bdev == NULL) {
		device_printf(sc->dev, "Could not add USB device\n");
		rv = ENXIO;
		goto error;
	}
	device_set_ivars(xsc->sc_bus.bdev, &xsc->sc_bus);
	device_set_desc(xsc->sc_bus.bdev, "Nvidia USB 3.0 controller");

	rv = xhci_init(xsc, sc->dev, 1);
	if (rv != 0) {
		device_printf(sc->dev, "USB init failed: %d\n", rv);
		goto error;
	}
	sc->xhci_inited = true;
	rv = xhci_start_controller(xsc);
	if (rv != 0) {
		device_printf(sc->dev,
		    "Could not start XHCI controller: %d\n", rv);
		goto error;
	}

	rv = bus_setup_intr(dev, sc->irq_res_mbox, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, intr_mbox, sc, &sc->irq_hdl_mbox);
	if (rv != 0) {
		device_printf(dev, "Could not setup error IRQ: %d\n",rv);
		xsc->sc_intr_hdl = NULL;
		goto error;
	}

	rv = bus_setup_intr(dev, xsc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)xhci_interrupt, xsc, &xsc->sc_intr_hdl);
	if (rv != 0) {
		device_printf(dev, "Could not setup error IRQ: %d\n",rv);
		xsc->sc_intr_hdl = NULL;
		goto error;
	}

	/* Probe the bus. */
	rv = device_probe_and_attach(xsc->sc_bus.bdev);
	if (rv != 0) {
		device_printf(sc->dev, "Could not initialize USB: %d\n", rv);
		goto error;
	}

	return (0);

error:
panic("XXXXX");
	tegra_xhci_detach(dev);
	return (rv);
}
Exemple #10
0
static int
mv_pcib_ofw_bus_attach(device_t dev)
{
	struct mv_pcib_ctrl_devinfo *di;
	struct mv_pcib_ctrl_softc *sc;
	device_t child;
	phandle_t parent, node;
	get_rl_t get_rl;

	parent = ofw_bus_get_node(dev);
	sc = device_get_softc(dev);
	if (parent > 0) {
		sc->addr_cells = 1;
		if (OF_getencprop(parent, "#address-cells", &(sc->addr_cells),
		    sizeof(sc->addr_cells)) <= 0)
			return(ENXIO);

		sc->size_cells = 1;
		if (OF_getencprop(parent, "#size-cells", &(sc->size_cells),
		    sizeof(sc->size_cells)) <= 0)
			return(ENXIO);

		for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
			di = malloc(sizeof(*di), M_PCIB_CTRL, M_WAITOK | M_ZERO);
			if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node)) {
				if (bootverbose) {
					device_printf(dev,
					    "Could not set up devinfo for PCI\n");
				}
				free(di, M_PCIB_CTRL);
				continue;
			}

			child = device_add_child(dev, NULL, -1);
			if (child == NULL) {
				if (bootverbose) {
					device_printf(dev,
					    "Could not add child: %s\n",
					    di->di_dinfo.obd_name);
				}
				ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
				free(di, M_PCIB_CTRL);
				continue;
			}

			resource_list_init(&di->di_rl);
			get_rl = (get_rl_t) ofw_bus_search_compatible(dev,
			    mv_pcib_ctrl_compat)->ocd_data;
			if (get_rl != NULL)
				get_rl(child, node, sc->addr_cells,
				    sc->size_cells, &di->di_rl);

			device_set_ivars(child, di);
		}
	}

	if (mv_pcib_ctrl_fill_ranges(parent, sc) < 0) {
		device_printf(dev, "could not get ranges\n");
		return (ENXIO);
	}

	return (0);
}
Exemple #11
0
static int
iobus_attach(device_t dev)
{
	struct iobus_softc *sc;
        struct iobus_devinfo *dinfo;
        phandle_t  root;
        phandle_t  child;
        device_t   cdev;
        char *name;
	u_int reg[2];
	int size;

	sc = device_get_softc(dev);
	sc->sc_node = ofw_bus_get_node(dev);

	/*
	 * Find the base addr/size of the iobus, and initialize the
	 * resource manager
	 */
	size = OF_getprop(sc->sc_node, "reg", reg, sizeof(reg));
	if (size == sizeof(reg)) {
		sc->sc_addr = reg[0];
		sc->sc_size = reg[1];
	} else {
		return (ENXIO);
	}

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
        sc->sc_mem_rman.rm_descr = "IOBus Device Memory";
        if (rman_init(&sc->sc_mem_rman) != 0) {
		device_printf(dev,
                    "failed to init mem range resources\n");
                return (ENXIO);
	}
	rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);

        /*
         * Iterate through the sub-devices
         */
        root = sc->sc_node;

        for (child = OF_child(root); child != 0; child = OF_peer(child)) {
                OF_getprop_alloc(child, "name", 1, (void **)&name);

                cdev = device_add_child(dev, NULL, -1);
                if (cdev != NULL) {
                        dinfo = malloc(sizeof(*dinfo), M_IOBUS, M_WAITOK);
			memset(dinfo, 0, sizeof(*dinfo));
			resource_list_init(&dinfo->id_resources);
                        dinfo->id_node = child;
                        dinfo->id_name = name;
			iobus_add_intr(child, dinfo);
			iobus_add_reg(child, dinfo, sc->sc_addr);
                        device_set_ivars(cdev, dinfo);
                } else {
                        free(name, M_OFWPROP);
                }
        }

        return (bus_generic_attach(dev));
}
Exemple #12
0
int
scc_bfe_attach(device_t dev, u_int ipc)
{
	struct resource_list_entry *rle;
	struct scc_chan *ch;
	struct scc_class *cl;
	struct scc_mode *m;
	struct scc_softc *sc, *sc0;
	const char *sep;
	bus_space_handle_t bh;
	u_long base, size, start, sz;
	int c, error, mode, sysdev;

	/*
	 * The sc_class field defines the type of SCC we're going to work
	 * with and thus the size of the softc. Replace the generic softc
	 * with one that matches the SCC now that we're certain we handle
	 * the device.
	 */
	sc0 = device_get_softc(dev);
	cl = sc0->sc_class;
	if (cl->size > sizeof(*sc)) {
		sc = malloc(cl->size, M_SCC, M_WAITOK|M_ZERO);
		bcopy(sc0, sc, sizeof(*sc));
		device_set_softc(dev, sc);
	} else
		sc = sc0;

	size = abs(cl->cl_range) << sc->sc_bas.regshft;

	mtx_init(&sc->sc_hwmtx, "scc_hwmtx", NULL, MTX_SPIN);

	/*
	 * Re-allocate. We expect that the softc contains the information
	 * collected by scc_bfe_probe() intact.
	 */
	sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
	    0, ~0, cl->cl_channels * size, RF_ACTIVE);
	if (sc->sc_rres == NULL)
		return (ENXIO);
	sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
	sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);

	/*
	 * Allocate interrupt resources. There may be a different interrupt
	 * per channel. We allocate them all...
	 */
	sc->sc_chan = malloc(sizeof(struct scc_chan) * cl->cl_channels,
	    M_SCC, M_WAITOK | M_ZERO);
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		/*
		 * XXX temporary hack. If we have more than 1 interrupt
		 * per channel, allocate the first for the channel. At
		 * this time only the macio bus front-end has more than
		 * 1 interrupt per channel and we don't use the 2nd and
		 * 3rd, because we don't support DMA yet.
		 */
		ch->ch_irid = c * ipc;
		ch->ch_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		    &ch->ch_irid, RF_ACTIVE | RF_SHAREABLE);
		if (ipc == 0)
			break;
	}

	/*
	 * Create the control structures for our children. Probe devices
	 * and query them to see if we can reset the hardware.
	 */
	sysdev = 0;
	base = rman_get_start(sc->sc_rres);
	sz = (size != 0) ? size : rman_get_size(sc->sc_rres);
	start = base + ((cl->cl_range < 0) ? size * (cl->cl_channels - 1) : 0);
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		resource_list_init(&ch->ch_rlist);
		ch->ch_nr = c + 1;

		if (!SCC_ENABLED(sc, ch))
			goto next;

		ch->ch_enabled = 1;
		resource_list_add(&ch->ch_rlist, sc->sc_rtype, 0, start,
		    start + sz - 1, sz);
		rle = resource_list_find(&ch->ch_rlist, sc->sc_rtype, 0);
		rle->res = &ch->ch_rres;
		bus_space_subregion(rman_get_bustag(sc->sc_rres),
		    rman_get_bushandle(sc->sc_rres), start - base, sz, &bh);
		rman_set_bushandle(rle->res, bh);
		rman_set_bustag(rle->res, rman_get_bustag(sc->sc_rres));

		resource_list_add(&ch->ch_rlist, SYS_RES_IRQ, 0, c, c, 1);
		rle = resource_list_find(&ch->ch_rlist, SYS_RES_IRQ, 0);
		rle->res = (ch->ch_ires != NULL) ? ch->ch_ires :
			    sc->sc_chan[0].ch_ires;

		for (mode = 0; mode < SCC_NMODES; mode++) {
			m = &ch->ch_mode[mode];
			m->m_chan = ch;
			m->m_mode = 1U << mode;
			if ((cl->cl_modes & m->m_mode) == 0 || ch->ch_sysdev)
				continue;
			m->m_dev = device_add_child(dev, NULL, -1);
			device_set_ivars(m->m_dev, (void *)m);
			error = device_probe_child(dev, m->m_dev);
			if (!error) {
				m->m_probed = 1;
				m->m_sysdev = SERDEV_SYSDEV(m->m_dev) ? 1 : 0;
				ch->ch_sysdev |= m->m_sysdev;
			}
		}

	 next:
		start += (cl->cl_range < 0) ? -size : size;
		sysdev |= ch->ch_sysdev;
	}

	/*
	 * Have the hardware driver initialize the hardware. Tell it
	 * whether or not a hardware reset should be performed.
	 */
	if (bootverbose) {
		device_printf(dev, "%sresetting hardware\n",
		    (sysdev) ? "not " : "");
	}
	error = SCC_ATTACH(sc, !sysdev);
	if (error)
		goto fail;

	/*
	 * Setup our interrupt handler. Make it FAST under the assumption
	 * that our children's are fast as well. We make it MPSAFE as soon
	 * as a child sets up a MPSAFE interrupt handler.
	 * Of course, if we can't setup a fast handler, we make it MPSAFE
	 * right away.
	 */
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		if (ch->ch_ires == NULL)
			continue;
		error = bus_setup_intr(dev, ch->ch_ires,
		    INTR_TYPE_TTY, scc_bfe_intr, NULL, sc,
		    &ch->ch_icookie);
		if (error) {
			error = bus_setup_intr(dev, ch->ch_ires,
			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
			    (driver_intr_t *)scc_bfe_intr, sc, &ch->ch_icookie);
		} else
			sc->sc_fastintr = 1;

		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
			    ch->ch_ires);
			ch->ch_ires = NULL;
		}
	}
	sc->sc_polled = 1;
	for (c = 0; c < cl->cl_channels; c++) {
		if (sc->sc_chan[0].ch_ires != NULL)
			sc->sc_polled = 0;
	}

	/*
	 * Attach all child devices that were probed successfully.
	 */
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		for (mode = 0; mode < SCC_NMODES; mode++) {
			m = &ch->ch_mode[mode];
			if (!m->m_probed)
				continue;
			error = device_attach(m->m_dev);
			if (error)
				continue;
			m->m_attached = 1;
		}
	}

	if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
		sep = "";
		device_print_prettyname(dev);
		if (sc->sc_fastintr) {
			printf("%sfast interrupt", sep);
			sep = ", ";
		}
		if (sc->sc_polled) {
			printf("%spolled mode", sep);
			sep = ", ";
		}
		printf("\n");
	}

	return (0);

 fail:
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		if (ch->ch_ires == NULL)
			continue;
		bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
		    ch->ch_ires);
	}
	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
	return (error);
}
Exemple #13
0
static int
musbotg_attach(device_t dev)
{
	struct musbotg_super_softc *sc = device_get_softc(dev);
	int err;
	int rid;

	/* setup MUSB OTG USB controller interface softc */
	sc->sc_otg.sc_clocks_on = &musbotg_clocks_on;
	sc->sc_otg.sc_clocks_off = &musbotg_clocks_off;
	sc->sc_otg.sc_clocks_arg = sc;

	/* initialise some bus fields */
	sc->sc_otg.sc_bus.parent = dev;
	sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
	sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
	    USB_GET_DMA_TAG(dev), NULL)) {
		return (ENOMEM);
	}
	rid = 0;
	sc->sc_otg.sc_io_res =
	    bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);

	if (!(sc->sc_otg.sc_io_res)) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res);
	sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res);
	sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res);

	rid = 0;
	sc->sc_otg.sc_irq_res =
	    bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
	if (!(sc->sc_otg.sc_irq_res)) {
		goto error;
	}
	sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!(sc->sc_otg.sc_bus.bdev)) {
		goto error;
	}
	device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);

#if (__FreeBSD_version >= 700031)
	err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
#else
	err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
#endif
	if (err) {
		sc->sc_otg.sc_intr_hdl = NULL;
		goto error;
	}
	err = musbotg_init(&sc->sc_otg);
	if (!err) {
		err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev);
	}
	if (err) {
		goto error;
	} else {
		/* poll VBUS one time */
		musbotg_vbus_poll(sc);
	}
	return (0);

error:
	musbotg_detach(dev);
	return (ENXIO);
}
Exemple #14
0
static int
ehci_xls_attach(device_t self)
{
	ehci_softc_t *sc = device_get_softc(self);
	int err;
	int rid;

	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
		return (ENOMEM);
	}

	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}
	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	printf("IO Resource tag %lx, hdl %lx, size %lx\n",
	       (u_long)sc->sc_io_tag, (u_long)sc->sc_io_hdl, 
	       (u_long)sc->sc_io_size);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid,
	    PIC_USB_IRQ, PIC_USB_IRQ, 1, RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}

	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, xlr_usb_dev_desc);

	sprintf(sc->sc_vendor, xlr_vendor_desc);

	err = bus_setup_intr(self, sc->sc_irq_res,
	    INTR_TYPE_BIO | INTR_MPSAFE, NULL,
	    (driver_intr_t *) ehci_interrupt, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}

	err = ehci_init(sc);
	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		goto error;
	}

	err = device_probe_and_attach(sc->sc_bus.bdev);
	if (err) {
		device_printf(self, "USB probe and attach failed err=%d\n", err);
		goto error;
	}

	return (0);

error:
	ehci_xls_detach(self);
	return (ENXIO);
}
static int
dma_attach(device_t dev)
{
	struct dma_softc *dsc;
	struct lsi64854_softc *lsc;
	struct dma_devinfo *ddi;
	device_t cdev;
	const char *name;
	char *cabletype;
	uint32_t csr;
	phandle_t child, node;
	int error, i;

	dsc = device_get_softc(dev);
	lsc = &dsc->sc_lsi64854;

	name = ofw_bus_get_name(dev);
	node = ofw_bus_get_node(dev);
	dsc->sc_ign = sbus_get_ign(dev);
	dsc->sc_slot = sbus_get_slot(dev);

	i = 0;
	lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
	    RF_ACTIVE);
	if (lsc->sc_res == NULL) {
		device_printf(dev, "cannot allocate resources\n");
		return (ENXIO);
	}

	if (strcmp(name, "espdma") == 0 || strcmp(name, "dma") == 0)
		lsc->sc_channel = L64854_CHANNEL_SCSI;
	else if (strcmp(name, "ledma") == 0) {
		/*
		 * Check to see which cable type is currently active and
		 * set the appropriate bit in the ledma csr so that it
		 * gets used. If we didn't netboot, the PROM won't have
		 * the "cable-selection" property; default to TP and then
		 * the user can change it via a "media" option to ifconfig.
		 */
		csr = L64854_GCSR(lsc);
		if ((OF_getprop_alloc(node, "cable-selection", 1,
		    (void **)&cabletype)) == -1) {
			/* assume TP if nothing there */
			csr |= E_TP_AUI;
		} else {
			if (strcmp(cabletype, "aui") == 0)
				csr &= ~E_TP_AUI;
			else
				csr |= E_TP_AUI;
			free(cabletype, M_OFWPROP);
		}
		L64854_SCSR(lsc, csr);
		DELAY(20000);	/* manual says we need a 20ms delay */
		lsc->sc_channel = L64854_CHANNEL_ENET;
	} else {
		device_printf(dev, "unsupported DMA channel\n");
		error = ENXIO;
		goto fail_lres;
	}

	error = bus_dma_tag_create(
	    bus_get_dma_tag(dev),	/* parent */
	    1, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR,		/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
	    0,				/* nsegments */
	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* no locking */
	    &lsc->sc_parent_dmat);
	if (error != 0) {
		device_printf(dev, "cannot allocate parent DMA tag\n");
		goto fail_lres;
	}

	i = sbus_get_burstsz(dev);
	lsc->sc_burst = (i & SBUS_BURST_32) ? 32 :
	    (i & SBUS_BURST_16) ? 16 : 0;
	lsc->sc_dev = dev;

	/* Attach children. */
	i = 0;
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if ((ddi = dma_setup_dinfo(dev, dsc, child)) == NULL)
			continue;
		if (i != 0) {
			device_printf(dev,
			    "<%s>: only one child per DMA channel supported\n",
			    ddi->ddi_obdinfo.obd_name);
			dma_destroy_dinfo(ddi);
			continue;
		}
		if ((cdev = device_add_child(dev, NULL, -1)) == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    ddi->ddi_obdinfo.obd_name);
			dma_destroy_dinfo(ddi);
			continue;
		}
		device_set_ivars(cdev, ddi);
		i++;
	}
	return (bus_generic_attach(dev));

 fail_lres:
	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
	    lsc->sc_res);
	return (error);
}
Exemple #16
0
static int
at91_udp_attach(device_t dev)
{
	struct at91_udp_softc *sc = device_get_softc(dev);
	int err;
	int rid;

	/* setup AT9100 USB device controller interface softc */

	sc->sc_dci.sc_clocks_on = &at91_udp_clocks_on;
	sc->sc_dci.sc_clocks_off = &at91_udp_clocks_off;
	sc->sc_dci.sc_clocks_arg = sc;
	sc->sc_dci.sc_pull_up = &at91_udp_pull_up;
	sc->sc_dci.sc_pull_down = &at91_udp_pull_down;
	sc->sc_dci.sc_pull_arg = sc;

	/* initialise some bus fields */
	sc->sc_dci.sc_bus.parent = dev;
	sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
	sc->sc_dci.sc_bus.devices_max = AT91_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
	    USB_GET_DMA_TAG(dev), NULL)) {
		return (ENOMEM);
	}
	callout_init_mtx(&sc->sc_vbus, &sc->sc_dci.sc_bus.bus_mtx, 0);

	/*
	 * configure VBUS input pin, enable deglitch and enable
	 * interrupt :
	 */
	at91_pio_use_gpio(VBUS_BASE, VBUS_MASK);
	at91_pio_gpio_input(VBUS_BASE, VBUS_MASK);
	at91_pio_gpio_set_deglitch(VBUS_BASE, VBUS_MASK, 1);
	at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 0);

	/*
	 * configure PULLUP output pin :
	 */
	at91_pio_use_gpio(PULLUP_BASE, PULLUP_MASK);
	at91_pio_gpio_output(PULLUP_BASE, PULLUP_MASK, 0);

	at91_udp_pull_down(sc);

	/* wait 10ms for pulldown to stabilise */
	usb_pause_mtx(NULL, hz / 100);

	sc->sc_mclk = at91_pmc_clock_ref("mck");
	sc->sc_iclk = at91_pmc_clock_ref("udc_clk");
	sc->sc_fclk = at91_pmc_clock_ref("udpck");

	rid = MEM_RID;
	sc->sc_dci.sc_io_res =
	    bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);

	if (!(sc->sc_dci.sc_io_res)) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_dci.sc_io_tag = rman_get_bustag(sc->sc_dci.sc_io_res);
	sc->sc_dci.sc_io_hdl = rman_get_bushandle(sc->sc_dci.sc_io_res);
	sc->sc_dci.sc_io_size = rman_get_size(sc->sc_dci.sc_io_res);

	rid = 0;
	sc->sc_dci.sc_irq_res =
	    bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
	if (!(sc->sc_dci.sc_irq_res)) {
		goto error;
	}
	sc->sc_dci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!(sc->sc_dci.sc_bus.bdev)) {
		goto error;
	}
	device_set_ivars(sc->sc_dci.sc_bus.bdev, &sc->sc_dci.sc_bus);

	err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_TTY | INTR_MPSAFE,
	    at91dci_filter_interrupt, at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
	if (err) {
		sc->sc_dci.sc_intr_hdl = NULL;
		goto error;
	}

	err = at91dci_init(&sc->sc_dci);
	if (!err) {
		err = device_probe_and_attach(sc->sc_dci.sc_bus.bdev);
	}
	if (err) {
		goto error;
	} else {
		/* poll VBUS one time */
		USB_BUS_LOCK(&sc->sc_dci.sc_bus);
		at91_vbus_poll(sc);
		USB_BUS_UNLOCK(&sc->sc_dci.sc_bus);
	}
	return (0);

error:
	at91_udp_detach(dev);
	return (ENXIO);
}
Exemple #17
0
static int
ehci_obio_attach(device_t self)
{
	ehci_softc_t *sc = device_get_softc(self);
	uint32_t reg;
	int err;
	int rid;

	/* setup controller interface softc */
	reg = rt305x_sysctl_get(SYSCTL_SYSCFG1);
	reg |= SYSCTL_SYSCFG1_USB0_HOST_MODE;
	rt305x_sysctl_set(SYSCTL_SYSCFG1, reg);

	reg = rt305x_sysctl_get(SYSCTL_CLKCFG1);
	reg |= SYSCTL_CLKCFG1_UPHY0_CLK_EN;
#ifdef MT7620
	reg |= SYSCTL_CLKCFG1_UPHY1_CLK_EN;
#endif
	rt305x_sysctl_set(SYSCTL_CLKCFG1, reg);

	reg = rt305x_sysctl_get(SYSCTL_RSTCTRL);
	reg |= SYSCTL_RSTCTRL_UPHY0 | SYSCTL_RSTCTRL_UPHY1;
	rt305x_sysctl_set(SYSCTL_RSTCTRL, reg);
	reg &= ~(SYSCTL_RSTCTRL_UPHY0 | SYSCTL_RSTCTRL_UPHY1);
	DELAY(100000);
	rt305x_sysctl_set(SYSCTL_RSTCTRL, reg);
	DELAY(100000);

	/* initialise some bus fields */
	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
		printf("No mem\n");
		return (ENOMEM);
	}

	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
				RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}
	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
		RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}

	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!(sc->sc_bus.bdev)) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);

	sprintf(sc->sc_vendor, "Ralink");

	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
		NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}

	err = ehci_init(sc);
	if (!err) {
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	ehci_obio_detach(self);
	return (ENXIO);
}
Exemple #18
0
static device_t
newbus_pci_create(device_t dev_par, phandle_t dt_node, u_long par_base,
    u_long par_size)
{
	pcell_t reg[3 + 2];
	device_t dev_child;
	u_long start, end, count;
	struct fdtbus_devinfo *di;
	char *name, *type, *compat;
	int len;

	OF_getprop_alloc(dt_node, "device_type", 1, (void **)&type);
	if (!(type != NULL && strcmp(type, "pci") == 0)) {
		/* Only process 'pci' subnodes. */
		free(type, M_OFWPROP);
		return (NULL);
	}

	OF_getprop_alloc(dt_node, "name", 1, (void **)&name);
	OF_getprop_alloc(OF_parent(dt_node), "compatible", 1,
	    (void **)&compat);

	dev_child = device_add_child(dev_par, NULL, -1);
	if (dev_child == NULL) {
		free(name, M_OFWPROP);
		free(type, M_OFWPROP);
		free(compat, M_OFWPROP);
		return (NULL);
	}

	di = malloc(sizeof(*di), M_FDTBUS, M_WAITOK);
	di->di_node = dt_node;
	di->di_name = name;
	di->di_type = type;
	di->di_compat = compat;

	resource_list_init(&di->di_res);

	/*
	 * Produce and set SYS_RES_MEMORY resources.
	 */
	start = 0;
	count = 0;

	len = OF_getprop(dt_node, "reg", &reg, sizeof(reg));
	if (len > 0) {
		if (fdt_data_verify((void *)&reg[1], 2) != 0) {
			device_printf(dev_child, "'reg' address value out of "
			    "range\n");
			newbus_device_destroy(dev_child);
			dev_child = NULL;
			goto out;
		}
		start = fdt_data_get((void *)&reg[1], 2);

		if (fdt_data_verify((void *)&reg[3], 2) != 0) {
			device_printf(dev_child, "'reg' size value out of "
			    "range\n");
			newbus_device_destroy(dev_child);
			dev_child = NULL;
			goto out;
		}
		count = fdt_data_get((void *)&reg[3], 2);
	}

	/* Calculate address range relative to base. */
	par_base &= 0x000ffffful;
	start &= 0x000ffffful;
	start += par_base + fdt_immr_va;
	if (count == 0)
		count = par_size;
	end = start + count - 1;

	debugf("start = 0x%08lx, end = 0x%08lx, count = 0x%08lx\n",
	    start, end, count);

	if (count > par_size) {
		device_printf(dev_child, "'reg' size value out of range\n");
		newbus_device_destroy(dev_child);
		dev_child = NULL;
		goto out;
	}

	resource_list_add(&di->di_res, SYS_RES_MEMORY, 0, start, end, count);

	/*
	 * Set SYS_RES_IRQ resources.
	 */
	if (fdt_intr_to_rl(OF_parent(dt_node), &di->di_res, di->di_intr_sl)) {
		device_printf(dev_child, "could not process 'interrupts' "
		    "property\n");
		newbus_device_destroy(dev_child);
		dev_child = NULL;
		goto out;
	}

	device_set_ivars(dev_child, di);
	debugf("added child name='%s', node=%p\n", name,
	    (void *)dt_node);

out:
	return (dev_child);
}
Exemple #19
0
int
iodi_attach(device_t dev)
{
	device_t tmpd;
	int i;

	/*
	 * Attach each devices
	 */
	device_add_child(dev, "uart", 0);
	device_add_child(dev, "xlr_i2c", 0);
	device_add_child(dev, "xlr_i2c", 1);
	device_add_child(dev, "pcib", 0);
	device_add_child(dev, "rmisec", -1);

	if (xlr_board_info.usb)
		device_add_child(dev, "ehci", 0);

	if (xlr_board_info.cfi)
		device_add_child(dev, "cfi", 0);

	if (xlr_board_info.ata)
		device_add_child(dev, "ata", 0);

	if (xlr_board_info.gmac_block[0].enabled) {
		tmpd = device_add_child(dev, "rge", 0);
		device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);

		tmpd = device_add_child(dev, "rge", 1);
		device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);

		tmpd = device_add_child(dev, "rge", 2);
		device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);

		tmpd = device_add_child(dev, "rge", 3);
		device_set_ivars(tmpd, &xlr_board_info.gmac_block[0]);
	}
	if (xlr_board_info.gmac_block[1].enabled) {
		if (xlr_board_info.gmac_block[1].type == XLR_GMAC) {
			tmpd = device_add_child(dev, "rge", 4);
			device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);

			tmpd = device_add_child(dev, "rge", 5);
			device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);

			if (xlr_board_info.gmac_block[1].enabled & 0x4) {
				tmpd = device_add_child(dev, "rge", 6);
				device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
			}

			if (xlr_board_info.gmac_block[1].enabled & 0x8) {
				tmpd = device_add_child(dev, "rge", 7);
				device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
			}
		} else if (xlr_board_info.gmac_block[1].type == XLR_XGMAC) {
#if 0				/* XGMAC not yet */
			tmpd = device_add_child(dev, "rge", 4);
			device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);

			tmpd = device_add_child(dev, "rge", 5);
			device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
#endif
		} else 
			device_printf(dev, "Unknown type of gmac 1\n"); 
	}

	/* This is to add the new GMAC driver. The above adds the old driver,
	   which has been retained for now as the new driver is stabilized.
	   The new driver is enabled with "option nlge". Make sure that only
	   one of rge or nlge is enabled in the conf file. */
	for (i = 0; i < 3; i++) {
		if (xlr_board_info.gmac_block[i].enabled == 0)
			continue;
		tmpd = device_add_child(dev, "nlna", i);
		device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]);
	}
	bus_generic_probe(dev);
	bus_generic_attach(dev);
	return 0;
}
Exemple #20
0
static int
dwc_otg_attach(device_t dev)
{
	struct dwc_otg_super_softc *sc = device_get_softc(dev);
	int err;
	int rid;

	/* initialise some bus fields */
	sc->sc_otg.sc_bus.parent = dev;
	sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
	sc->sc_otg.sc_bus.devices_max = DWC_OTG_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
	    USB_GET_DMA_TAG(dev), NULL)) {
		return (ENOMEM);
	}
	rid = 0;
	sc->sc_otg.sc_io_res =
	    bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);

	if (!(sc->sc_otg.sc_io_res)) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res);
	sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res);
	sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res);

	rid = 0;
	sc->sc_otg.sc_irq_res =
	    bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
	if (sc->sc_otg.sc_irq_res == NULL)
		goto error;

	sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (sc->sc_otg.sc_bus.bdev == NULL)
		goto error;

	device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);

	err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)dwc_otg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
	if (err) {
		sc->sc_otg.sc_intr_hdl = NULL;
		goto error;
	}
	err = dwc_otg_init(&sc->sc_otg);
	if (err == 0) {
		err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev);
	}
	if (err)
		goto error;


	return (0);

error:
	dwc_otg_detach(dev);
	return (ENXIO);
}
Exemple #21
0
static int
octusb_octeon_attach(device_t dev)
{
    struct octusb_octeon_softc *sc = device_get_softc(dev);
    int err;
    int rid;
    int nports;
    int i;

    /* setup controller interface softc */

    /* initialise some bus fields */
    sc->sc_dci.sc_bus.parent = dev;
    sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
    sc->sc_dci.sc_bus.devices_max = OCTUSB_MAX_DEVICES;

    /* get all DMA memory */
    if (usb_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
                              USB_GET_DMA_TAG(dev), NULL)) {
        return (ENOMEM);
    }
    nports = cvmx_usb_get_num_ports();
    if (nports > OCTUSB_MAX_PORTS)
        panic("octusb: too many USB ports %d", nports);
    for (i = 0; i < nports; i++) {
        rid = 0;
        sc->sc_dci.sc_irq_res[i] =
            bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
                               OCTEON_IRQ_USB0 + i, OCTEON_IRQ_USB0 + i, 1, RF_ACTIVE);
        if (!(sc->sc_dci.sc_irq_res[i])) {
            goto error;
        }

#if (__FreeBSD_version >= 700031)
        err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res[i], INTR_TYPE_BIO | INTR_MPSAFE,
                             NULL, (driver_intr_t *)octusb_interrupt, sc, &sc->sc_dci.sc_intr_hdl[i]);
#else
        err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res[i], INTR_TYPE_BIO | INTR_MPSAFE,
                             (driver_intr_t *)octusb_interrupt, sc, &sc->sc_dci.sc_intr_hdl[i]);
#endif
        if (err) {
            sc->sc_dci.sc_intr_hdl[i] = NULL;
            goto error;
        }
    }

    sc->sc_dci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
    if (!(sc->sc_dci.sc_bus.bdev)) {
        goto error;
    }
    device_set_ivars(sc->sc_dci.sc_bus.bdev, &sc->sc_dci.sc_bus);


    err = octusb_init(&sc->sc_dci);
    if (!err) {
        err = device_probe_and_attach(sc->sc_dci.sc_bus.bdev);
    }
    if (err) {
        goto error;
    }
    return (0);

error:
    octusb_octeon_detach(dev);
    return (ENXIO);
}
Exemple #22
0
static int
ar71xx_ehci_attach(device_t self)
{
	struct ar71xx_ehci_softc *isc = device_get_softc(self);
	ehci_softc_t *sc = &isc->base;
	int err;
	int rid;

	/* initialise some bus fields */
	sc->sc_bus.parent = self;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
		return (ENOMEM);
	}

	sc->sc_bus.usbrev = USB_REV_2_0;

	/* NB: hints fix the memory location and irq */

	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}

	/*
	 * Craft special resource for bus space ops that handle
	 * byte-alignment of non-word addresses.  
	 */
	sc->sc_io_tag = ar71xx_bus_space_reversed;
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		goto error;
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);

	sprintf(sc->sc_vendor, "Atheros");

	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, ar71xx_ehci_intr, sc, &sc->sc_intr_hdl);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}

	/*
	 * Arrange to force Host mode, select big-endian byte alignment,
	 * and arrange to not terminate reset operations (the adapter
	 * will ignore it if we do but might as well save a reg write).
	 * Also, the controller has an embedded Transaction Translator
	 * which means port speed must be read from the Port Status
	 * register following a port enable.
	 */
	sc->sc_flags = EHCI_SCFLG_SETMODE;

	switch (ar71xx_soc) {
		case AR71XX_SOC_AR7241:
		case AR71XX_SOC_AR7242:
		case AR71XX_SOC_AR9130:
		case AR71XX_SOC_AR9132:
		case AR71XX_SOC_AR9330:
		case AR71XX_SOC_AR9331:
		case AR71XX_SOC_AR9341:
		case AR71XX_SOC_AR9342:
		case AR71XX_SOC_AR9344:
		case AR71XX_SOC_QCA9533:
		case AR71XX_SOC_QCA9533_V2:
		case AR71XX_SOC_QCA9556:
		case AR71XX_SOC_QCA9558:
			sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
			break;
		default:
			/* fallthrough */
			break;
	}

	/*
	 * ehci_reset() needs the correct offset to access the host controller
	 * registers. The AR724x/AR913x offsets aren't 0.
	*/
	sc->sc_offs = EHCI_CAPLENGTH(EREAD4(sc, EHCI_CAPLEN_HCIVERSION));

	(void) ehci_reset(sc);

	err = ehci_init(sc);
	if (!err) {
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	ar71xx_ehci_detach(self);
	return (ENXIO);
}
Exemple #23
0
static int
vybrid_ehci_attach(device_t dev)
{
	struct vybrid_ehci_softc *esc;
	ehci_softc_t *sc;
	bus_space_handle_t bsh;
	int err;
	int reg;

	esc = device_get_softc(dev);
	esc->dev = dev;

	sc = &esc->base;
	sc->sc_bus.parent = dev;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;

	if (bus_alloc_resources(dev, vybrid_ehci_spec, esc->res)) {
		device_printf(dev, "could not allocate resources\n");
		return (ENXIO);
	}

	/* EHCI registers */
	sc->sc_io_tag = rman_get_bustag(esc->res[0]);
	bsh = rman_get_bushandle(esc->res[0]);
	sc->sc_io_size = rman_get_size(esc->res[0]);

	esc->bst_usbc = rman_get_bustag(esc->res[1]);
	esc->bsh_usbc = rman_get_bushandle(esc->res[1]);

	esc->bst_phy = rman_get_bustag(esc->res[2]);
	esc->bsh_phy = rman_get_bushandle(esc->res[2]);

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
		&ehci_iterate_hw_softc))
		return (ENXIO);

#if 0
	printf("USBx_HCSPARAMS is 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_HCSPARAMS));
	printf("USB_ID == 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_ID));
	printf("USB_HWGENERAL == 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_HWGENERAL));
	printf("USB_HWHOST == 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_HWHOST));
	printf("USB_HWDEVICE == 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_HWDEVICE));
	printf("USB_HWTXBUF == 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_HWTXBUF));
	printf("USB_HWRXBUF == 0x%08x\n",
	    bus_space_read_4(sc->sc_io_tag, bsh, USB_HWRXBUF));
#endif

	if (phy_init(esc)) {
		device_printf(dev, "Could not setup PHY\n");
		return (1);
	}

	/*
	 * Set handle to USB related registers subregion used by
	 * generic EHCI driver.
	 */
	err = bus_space_subregion(sc->sc_io_tag, bsh, 0x100,
	    sc->sc_io_size, &sc->sc_io_hdl);
	if (err != 0)
		return (ENXIO);

	/* Setup interrupt handler */
	err = bus_setup_intr(dev, esc->res[3], INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)ehci_interrupt, sc,
	    &sc->sc_intr_hdl);
	if (err) {
		device_printf(dev, "Could not setup irq, "
		    "%d\n", err);
		return (1);
	}

	/* Add USB device */
	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(dev, "Could not add USB device\n");
		err = bus_teardown_intr(dev, esc->res[5],
		    sc->sc_intr_hdl);
		if (err)
			device_printf(dev, "Could not tear down irq,"
			    " %d\n", err);
		return (1);
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	strlcpy(sc->sc_vendor, "Freescale", sizeof(sc->sc_vendor));

	/* Set host mode */
	reg = bus_space_read_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8);
	reg |= 0x3;
	bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8, reg);

	/* Set flags */
	sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_NORESTERM;

	err = ehci_init(sc);
	if (!err) {
		sc->sc_flags |= EHCI_SCFLG_DONEINIT;
		err = device_probe_and_attach(sc->sc_bus.bdev);
	} else {
		device_printf(dev, "USB init failed err=%d\n", err);

		device_delete_child(dev, sc->sc_bus.bdev);
		sc->sc_bus.bdev = NULL;

		err = bus_teardown_intr(dev, esc->res[5],
		    sc->sc_intr_hdl);
		if (err)
			device_printf(dev, "Could not tear down irq,"
			    " %d\n", err);
		return (1);
	}
	return (0);
}
Exemple #24
0
static int
exynos_ehci_attach(device_t dev)
{
	struct exynos_ehci_softc *esc;
	ehci_softc_t *sc;
	bus_space_handle_t bsh;
	int err;

	esc = device_get_softc(dev);
	esc->dev = dev;
	sc = &esc->base;
	sc->sc_bus.parent = dev;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;

	if (bus_alloc_resources(dev, exynos_ehci_spec, esc->res)) {
		device_printf(dev, "could not allocate resources\n");
		return (ENXIO);
	}

	/* EHCI registers */
	sc->sc_io_tag = rman_get_bustag(esc->res[0]);
	bsh = rman_get_bushandle(esc->res[0]);
	sc->sc_io_size = rman_get_size(esc->res[0]);

	/* EHCI HOST ctrl registers */
	esc->host_bst = rman_get_bustag(esc->res[1]);
	esc->host_bsh = rman_get_bushandle(esc->res[1]);

	/* PWR registers */
	esc->pwr_bst = rman_get_bustag(esc->res[2]);
	esc->pwr_bsh = rman_get_bushandle(esc->res[2]);

	/* SYSREG */
	esc->sysreg_bst = rman_get_bustag(esc->res[3]);
	esc->sysreg_bsh = rman_get_bushandle(esc->res[3]);

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
		&ehci_iterate_hw_softc))
		return (ENXIO);

	/*
	 * Set handle to USB related registers subregion used by
	 * generic EHCI driver.
	 */
	err = bus_space_subregion(sc->sc_io_tag, bsh, 0x0,
	    sc->sc_io_size, &sc->sc_io_hdl);
	if (err != 0)
		return (ENXIO);

	phy_init(esc);

	/* Setup interrupt handler */
	err = bus_setup_intr(dev, esc->res[4], INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)ehci_interrupt, sc,
	    &sc->sc_intr_hdl);
	if (err) {
		device_printf(dev, "Could not setup irq, "
		    "%d\n", err);
		return (1);
	}

	/* Add USB device */
	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(dev, "Could not add USB device\n");
		err = bus_teardown_intr(dev, esc->res[4],
		    sc->sc_intr_hdl);
		if (err)
			device_printf(dev, "Could not tear down irq,"
			    " %d\n", err);
		return (1);
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	strlcpy(sc->sc_vendor, "Samsung", sizeof(sc->sc_vendor));

	err = ehci_init(sc);
	if (!err) {
		sc->sc_flags |= EHCI_SCFLG_DONEINIT;
		err = device_probe_and_attach(sc->sc_bus.bdev);
	} else {
		device_printf(dev, "USB init failed err=%d\n", err);

		device_delete_child(dev, sc->sc_bus.bdev);
		sc->sc_bus.bdev = NULL;

		err = bus_teardown_intr(dev, esc->res[4],
		    sc->sc_intr_hdl);
		if (err)
			device_printf(dev, "Could not tear down irq,"
			    " %d\n", err);
		return (1);
	}
	return (0);
}
Exemple #25
0
static int
lbc_attach(device_t dev)
{
	struct lbc_softc *sc;
	struct lbc_devinfo *di;
	struct rman *rm;
	u_long offset, start, size;
	device_t cdev;
	phandle_t node, child;
	pcell_t *ranges, *rangesptr;
	int tuple_size, tuples;
	int par_addr_cells;
	int bank, error, i;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	sc->sc_mrid = 0;
	sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
	    RF_ACTIVE);
	if (sc->sc_mres == NULL)
		return (ENXIO);

	sc->sc_bst = rman_get_bustag(sc->sc_mres);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mres);

	for (bank = 0; bank < LBC_DEV_MAX; bank++) {
		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
	}

	/*
	 * Initialize configuration register:
	 * - enable Local Bus
	 * - set data buffer control signal function
	 * - disable parity byte select
	 * - set ECC parity type
	 * - set bus monitor timing and timer prescale
	 */
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);

	/*
	 * Initialize clock ratio register:
	 * - disable PLL bypass mode
	 * - configure LCLK delay cycles for the assertion of LALE
	 * - set system clock divider
	 */
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);

	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);

	sc->sc_irid = 0;
	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->sc_ires != NULL) {
		error = bus_setup_intr(dev, sc->sc_ires,
		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
		    &sc->sc_icookie);
		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
			    sc->sc_ires);
			sc->sc_ires = NULL;
		}
	}

	sc->sc_ltesr = ~0;

	rangesptr = NULL;

	rm = &sc->sc_rman;
	rm->rm_type = RMAN_ARRAY;
	rm->rm_descr = "Local Bus Space";
	rm->rm_start = 0UL;
	rm->rm_end = ~0UL;
	error = rman_init(rm);
	if (error)
		goto fail;

	error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
	if (error) {
		rman_fini(rm);
		goto fail;
	}

	/*
	 * Process 'ranges' property.
	 */
	node = ofw_bus_get_node(dev);
	if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
	    &sc->sc_size_cells)) != 0) {
		error = ENXIO;
		goto fail;
	}

	par_addr_cells = fdt_parent_addr_cells(node);
	if (par_addr_cells > 2) {
		device_printf(dev, "unsupported parent #addr-cells\n");
		error = ERANGE;
		goto fail;
	}
	tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
	    sc->sc_size_cells);

	tuples = OF_getprop_alloc(node, "ranges", tuple_size,
	    (void **)&ranges);
	if (tuples < 0) {
		device_printf(dev, "could not retrieve 'ranges' property\n");
		error = ENXIO;
		goto fail;
	}
	rangesptr = ranges;

	debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
	    "tuple_size = %d, tuples = %d\n", par_addr_cells,
	    sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);

	start = 0;
	size = 0;
	for (i = 0; i < tuples; i++) {

		/* The first cell is the bank (chip select) number. */
		bank = fdt_data_get((void *)ranges, 1);
		if (bank < 0 || bank > LBC_DEV_MAX) {
			device_printf(dev, "bank out of range: %d\n", bank);
			error = ERANGE;
			goto fail;
		}
		ranges += 1;

		/*
		 * Remaining cells of the child address define offset into
		 * this CS.
		 */
		offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1);
		ranges += sc->sc_addr_cells - 1;

		/* Parent bus start address of this bank. */
		start = fdt_data_get((void *)ranges, par_addr_cells);
		ranges += par_addr_cells;

		size = fdt_data_get((void *)ranges, sc->sc_size_cells);
		ranges += sc->sc_size_cells;
		debugf("bank = %d, start = %lx, size = %lx\n", bank,
		    start, size);

		sc->sc_banks[bank].addr = start + offset;
		sc->sc_banks[bank].size = size;

		/*
		 * Attributes for the bank.
		 *
		 * XXX Note there are no DT bindings defined for them at the
		 * moment, so we need to provide some defaults.
		 */
		sc->sc_banks[bank].width = 16;
		sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
		sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
		sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
		sc->sc_banks[bank].wp = 0;
	}

	/*
	 * Initialize mem-mappings for the LBC banks (i.e. chip selects).
	 */
	error = lbc_banks_map(sc);
	if (error)
		goto fail;

	/*
	 * Walk the localbus and add direct subordinates as our children.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {

		di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);

		if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
			free(di, M_LBC);
			device_printf(dev, "could not set up devinfo\n");
			continue;
		}

		resource_list_init(&di->di_res);

		if (fdt_lbc_reg_decode(child, sc, di)) {
			device_printf(dev, "could not process 'reg' "
			    "property\n");
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_LBC);
			continue;
		}

		fdt_lbc_fixup(child, sc, di);

		/* Add newbus device for this FDT node */
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "could not add child: %s\n",
			    di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_LBC);
			continue;
		}
		debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name,
		    (void *)child);
		device_set_ivars(cdev, di);
	}

	/*
	 * Enable the LBC.
	 */
	lbc_banks_enable(sc);

	free(rangesptr, M_OFWPROP);
	return (bus_generic_attach(dev));

fail:
	free(rangesptr, M_OFWPROP);
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
	return (error);
}
Exemple #26
0
static int
zy7_ehci_attach(device_t dev)
{
	ehci_softc_t *sc = device_get_softc(dev);
	bus_space_handle_t bsh;
	int err, rid;
	
	/* initialize some bus fields */
	sc->sc_bus.parent = dev;
	sc->sc_bus.devices = sc->sc_devices;
	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
	sc->sc_bus.dma_bits = 32;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc))
		return (ENOMEM);

	/* Allocate memory. */
	rid = 0;
	sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
					       &rid, RF_ACTIVE);
	if (sc->sc_io_res == NULL) {
		device_printf(dev, "Can't allocate memory");
		zy7_ehci_detach(dev);
		return (ENOMEM);
	}

	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	bsh = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = EHCI_REG_SIZE;

	if (bus_space_subregion(sc->sc_io_tag, bsh, EHCI_REG_OFFSET,
				sc->sc_io_size, &sc->sc_io_hdl) != 0)
		panic("%s: unable to subregion USB host registers",
		      device_get_name(dev));

	/* Allocate IRQ. */
	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
						RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(dev, "Can't allocate IRQ\n");
		zy7_ehci_detach(dev);
		return (ENOMEM);
	}

	/* Add USB device */
	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(dev, "Could not add USB device\n");
		zy7_ehci_detach(dev);
		return (ENXIO);
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
	device_set_desc(sc->sc_bus.bdev, "Zynq-7000 ehci USB 2.0 controller");

	strcpy(sc->sc_vendor, "Xilinx"); /* or IP vendor? */

	/* Activate the interrupt */
	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
			     NULL, (driver_intr_t *)ehci_interrupt, sc,
			     &sc->sc_intr_hdl);
	if (err) {
		device_printf(dev, "Cannot setup IRQ\n");
		zy7_ehci_detach(dev);
		return (err);
	}

	/* Customization. */
	sc->sc_flags |= EHCI_SCFLG_TT |	EHCI_SCFLG_NORESTERM;
	sc->sc_vendor_post_reset = zy7_ehci_post_reset;
	sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;

	/* Modify FIFO burst threshold from 2 to 8. */
	bus_space_write_4(sc->sc_io_tag, bsh,
			  ZY7_USB_TXFILLTUNING,
			  8 << ZY7_USB_TXFILLTUNING_TXFIFOTHRES_SHFT);

	/* Handle PHY options. */
	if (zy7_phy_config(dev, sc->sc_io_tag, bsh) < 0) {
		device_printf(dev, "Cannot config phy!\n");
		zy7_ehci_detach(dev);
		return (EIO);
	}

	/* Init ehci. */
	err = ehci_init(sc);
	if (!err) {
		sc->sc_flags |= EHCI_SCFLG_DONEINIT;
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}
	if (err) {
		device_printf(dev, "USB init failed err=%d\n", err);
		zy7_ehci_detach(dev);
		return (err);
	}

	return (0);
}
Exemple #27
0
int
puc_bfe_attach(device_t dev)
{
	char buffer[64];
	struct puc_bar *bar;
	struct puc_port *port;
	struct puc_softc *sc;
	struct rman *rm;
	intptr_t res;
	bus_addr_t ofs, start;
	bus_size_t size;
	bus_space_handle_t bsh;
	bus_space_tag_t bst;
	int error, idx;

	sc = device_get_softc(dev);

	for (idx = 0; idx < PUC_PCI_BARS; idx++)
		sc->sc_bar[idx].b_rid = -1;

	do {
		sc->sc_ioport.rm_type = RMAN_ARRAY;
		error = rman_init(&sc->sc_ioport);
		if (!error) {
			sc->sc_iomem.rm_type = RMAN_ARRAY;
			error = rman_init(&sc->sc_iomem);
			if (!error) {
				sc->sc_irq.rm_type = RMAN_ARRAY;
				error = rman_init(&sc->sc_irq);
				if (!error)
					break;
				rman_fini(&sc->sc_iomem);
			}
			rman_fini(&sc->sc_ioport);
		}
		return (error);
	} while (0);

	snprintf(buffer, sizeof(buffer), "%s I/O port mapping",
	    device_get_nameunit(dev));
	sc->sc_ioport.rm_descr = strdup(buffer, M_PUC);
	snprintf(buffer, sizeof(buffer), "%s I/O memory mapping",
	    device_get_nameunit(dev));
	sc->sc_iomem.rm_descr = strdup(buffer, M_PUC);
	snprintf(buffer, sizeof(buffer), "%s port numbers",
	    device_get_nameunit(dev));
	sc->sc_irq.rm_descr = strdup(buffer, M_PUC);

	error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res);
	KASSERT(error == 0, ("%s %d", __func__, __LINE__));
	sc->sc_nports = (int)res;
	sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port),
	    M_PUC, M_WAITOK|M_ZERO);

	error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports);
	if (error)
		goto fail;

	error = puc_config(sc, PUC_CFG_SETUP, 0, &res);
	if (error)
		goto fail;

	for (idx = 0; idx < sc->sc_nports; idx++) {
		port = &sc->sc_port[idx];
		port->p_nr = idx + 1;
		error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res);
		if (error)
			goto fail;
		port->p_type = res;
		error = puc_config(sc, PUC_CFG_GET_RID, idx, &res);
		if (error)
			goto fail;
		bar = puc_get_bar(sc, res);
		if (bar == NULL) {
			error = ENXIO;
			goto fail;
		}
		port->p_bar = bar;
		start = rman_get_start(bar->b_res);
		error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res);
		if (error)
			goto fail;
		ofs = res;
		error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res);
		if (error)
			goto fail;
		size = res;
		rm = (bar->b_type == SYS_RES_IOPORT)
		    ? &sc->sc_ioport: &sc->sc_iomem;
		port->p_rres = rman_reserve_resource(rm, start + ofs,
		    start + ofs + size - 1, size, 0, NULL);
		if (port->p_rres != NULL) {
			bsh = rman_get_bushandle(bar->b_res);
			bst = rman_get_bustag(bar->b_res);
			bus_space_subregion(bst, bsh, ofs, size, &bsh);
			rman_set_bushandle(port->p_rres, bsh);
			rman_set_bustag(port->p_rres, bst);
		}
		port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr,
		    port->p_nr, 1, 0, NULL);
		if (port->p_ires == NULL) {
			error = ENXIO;
			goto fail;
		}
		error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res);
		if (error)
			goto fail;
		port->p_rclk = res;

		port->p_dev = device_add_child(dev, NULL, -1);
		if (port->p_dev != NULL)
			device_set_ivars(port->p_dev, (void *)port);
	}

	error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res);
	if (error)
		goto fail;
	sc->sc_ilr = res;
	if (bootverbose && sc->sc_ilr != 0)
		device_printf(dev, "using interrupt latch register\n");

	sc->sc_irid = 0;
	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
	    RF_ACTIVE|RF_SHAREABLE);
	if (sc->sc_ires != NULL) {
		error = bus_setup_intr(dev, sc->sc_ires,
		    INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie);
		if (error)
			error = bus_setup_intr(dev, sc->sc_ires,
			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
			    (driver_intr_t *)puc_intr, sc, &sc->sc_icookie);
		else
			sc->sc_fastintr = 1;

		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
			    sc->sc_ires);
			sc->sc_ires = NULL;
		}
	}
	if (sc->sc_ires == NULL) {
		/* XXX no interrupt resource. Force polled mode. */
		sc->sc_polled = 1;
	}

	/* Probe and attach our children. */
	for (idx = 0; idx < sc->sc_nports; idx++) {
		port = &sc->sc_port[idx];
		if (port->p_dev == NULL)
			continue;
		error = device_probe_and_attach(port->p_dev);
		if (error) {
			device_delete_child(dev, port->p_dev);
			port->p_dev = NULL;
		}
	}

	/*
	 * If there are no serdev devices, then our interrupt handler
	 * will do nothing. Tear it down.
	 */
	if (sc->sc_serdevs == 0UL)
		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);

	return (0);

fail:
	for (idx = 0; idx < sc->sc_nports; idx++) {
		port = &sc->sc_port[idx];
		if (port->p_dev != NULL)
			device_delete_child(dev, port->p_dev);
		if (port->p_rres != NULL)
			rman_release_resource(port->p_rres);
		if (port->p_ires != NULL)
			rman_release_resource(port->p_ires);
	}
	for (idx = 0; idx < PUC_PCI_BARS; idx++) {
		bar = &sc->sc_bar[idx];
		if (bar->b_res != NULL)
			bus_release_resource(sc->sc_dev, bar->b_type,
			    bar->b_rid, bar->b_res);
	}
	rman_fini(&sc->sc_irq);
	free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
	rman_fini(&sc->sc_iomem);
	free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
	rman_fini(&sc->sc_ioport);
	free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
	free(sc->sc_port, M_PUC);
	return (error);
}
Exemple #28
0
static int
xhci_pci_attach(device_t self)
{
	struct xhci_softc *sc = device_get_softc(self);
	int err;
	int rid;

	/* XXX check for 64-bit capability */

	if (xhci_init(sc, self)) {
		device_printf(self, "Could not initialize softc\n");
		goto error;
	}

	pci_enable_busmaster(self);

	rid = PCI_XHCI_CBMEM;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		goto error;
	}
	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(self, "Could not allocate IRQ\n");
		goto error;
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (sc->sc_bus.bdev == NULL) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	ksprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(self));

	err = bus_setup_intr(self, sc->sc_irq_res, INTR_MPSAFE,
	    (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl, NULL);
	
	if (err) {
		device_printf(self, "Could not setup IRQ, err=%d\n", err);
		sc->sc_intr_hdl = NULL;
		goto error;
	}
	xhci_pci_take_controller(self);

	err = xhci_halt_controller(sc);

	if (err == 0)
		err = xhci_start_controller(sc);

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

	if (err) {
		device_printf(self, "XHCI halt/start/probe failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	xhci_pci_detach(self);
	return (ENXIO);
}
static int
atmegadci_attach(device_t dev)
{
	struct atmegadci_super_softc *sc = device_get_softc(dev);
	int err;
	int rid;

	/* setup MUSB OTG USB controller interface softc */
	sc->sc_otg.sc_clocks_on = &atmegadci_clocks_on;
	sc->sc_otg.sc_clocks_off = &atmegadci_clocks_off;

	/* initialise some bus fields */
	sc->sc_otg.sc_bus.parent = dev;
	sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
	sc->sc_otg.sc_bus.devices_max = ATMEGA_MAX_DEVICES;

	/* get all DMA memory */
	if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
	    USB_GET_DMA_TAG(dev), NULL)) {
		return (ENOMEM);
	}
	rid = 0;
	sc->sc_otg.sc_io_res =
	    bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);

	if (!(sc->sc_otg.sc_io_res)) {
		err = ENOMEM;
		goto error;
	}
	sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res);
	sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res);

	rid = 0;
	sc->sc_otg.sc_irq_res =
	    bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
	if (!(sc->sc_otg.sc_irq_res)) {
		goto error;
	}
	sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1);
	if (!(sc->sc_otg.sc_bus.bdev)) {
		goto error;
	}
	device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);

	err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    NULL, (driver_intr_t *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
	if (err) {
		sc->sc_otg.sc_intr_hdl = NULL;
		goto error;
	}
	err = atmegadci_init(&sc->sc_otg);
	if (!err) {
		err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev);
	}
	if (err) {
		goto error;
	}
	return (0);

error:
	atmegadci_detach(dev);
	return (ENXIO);
}
Exemple #30
0
static int
mvs_attach(device_t dev)
{
	struct mvs_controller *ctlr = device_get_softc(dev);
	device_t child;
	int	error, unit, i;
	uint32_t devid, revid;

	soc_id(&devid, &revid);
	ctlr->dev = dev;
	i = 0;
	while (mvs_ids[i].id != 0 &&
	    (mvs_ids[i].id != devid ||
	     mvs_ids[i].rev > revid))
		i++;
	ctlr->channels = mvs_ids[i].ports;
	ctlr->quirks = mvs_ids[i].quirks;
	resource_int_value(device_get_name(dev),
	    device_get_unit(dev), "ccc", &ctlr->ccc);
	ctlr->cccc = 8;
	resource_int_value(device_get_name(dev),
	    device_get_unit(dev), "cccc", &ctlr->cccc);
	if (ctlr->ccc == 0 || ctlr->cccc == 0) {
		ctlr->ccc = 0;
		ctlr->cccc = 0;
	}
	if (ctlr->ccc > 100000)
		ctlr->ccc = 100000;
	device_printf(dev,
	    "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
	    ((ctlr->quirks & MVS_Q_GENI) ? "I" :
	     ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
	    ctlr->channels,
	    ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
	    ((ctlr->quirks & MVS_Q_GENI) ?
	    "not supported" : "supported"),
	    ((ctlr->quirks & MVS_Q_GENIIE) ?
	    " with FBS" : ""));
	mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF);
	/* We should have a memory BAR(0). */
	ctlr->r_rid = 0;
	if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &ctlr->r_rid, RF_ACTIVE)))
		return ENXIO;
	if (ATA_INL(ctlr->r_mem, PORT_BASE(0) + SATA_PHYCFG_OFS) != 0)
		ctlr->quirks |= MVS_Q_SOC65;
	/* Setup our own memory management for channels. */
	ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
	ctlr->sc_iomem.rm_end = rman_get_end(ctlr->r_mem);
	ctlr->sc_iomem.rm_type = RMAN_ARRAY;
	ctlr->sc_iomem.rm_descr = "I/O memory addresses";
	if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
		return (error);
	}
	if ((error = rman_manage_region(&ctlr->sc_iomem,
	    rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
		rman_fini(&ctlr->sc_iomem);
		return (error);
	}
	mvs_ctlr_setup(dev);
	/* Setup interrupts. */
	if (mvs_setup_interrupt(dev)) {
		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
		rman_fini(&ctlr->sc_iomem);
		return ENXIO;
	}
	/* Attach all channels on this controller */
	for (unit = 0; unit < ctlr->channels; unit++) {
		child = device_add_child(dev, "mvsch", -1);
		if (child == NULL)
			device_printf(dev, "failed to add channel device\n");
		else
			device_set_ivars(child, (void *)(intptr_t)unit);
	}
	bus_generic_attach(dev);
	return 0;
}