コード例 #1
0
ファイル: ahciem.c プロジェクト: 2asoft/freebsd
static int
ahci_em_attach(device_t dev)
{
	device_t parent = device_get_parent(dev);
	struct ahci_controller *ctlr = device_get_softc(parent);
	struct ahci_enclosure *enc = device_get_softc(dev);
	struct cam_devq *devq;
	int i, c, rid, error;
	char buf[32];

	enc->dev = dev;
	enc->quirks = ctlr->quirks;
	enc->channels = ctlr->channels;
	enc->ichannels = ctlr->ichannels;
	mtx_init(&enc->mtx, "AHCI enclosure lock", NULL, MTX_DEF);
	rid = 0;
	if (!(enc->r_memc = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &rid, RF_ACTIVE))) {
		mtx_destroy(&enc->mtx);
		return (ENXIO);
	}
	enc->capsem = ATA_INL(enc->r_memc, 0);
	rid = 1;
	if (!(enc->r_memt = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &rid, RF_ACTIVE))) {
		error = ENXIO;
		goto err0;
	}
	if ((enc->capsem & (AHCI_EM_XMT | AHCI_EM_SMB)) == 0) {
		rid = 2;
		if (!(enc->r_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
		    &rid, RF_ACTIVE))) {
			error = ENXIO;
			goto err0;
		}
	} else
		enc->r_memr = NULL;
	mtx_lock(&enc->mtx);
	if (ahci_em_reset(dev) != 0) {
	    error = ENXIO;
	    goto err1;
	}
	rid = ATA_IRQ_RID;
	/* Create the device queue for our SIM. */
	devq = cam_simq_alloc(1);
	if (devq == NULL) {
		device_printf(dev, "Unable to allocate SIM queue\n");
		error = ENOMEM;
		goto err1;
	}
	/* Construct SIM entry */
	enc->sim = cam_sim_alloc(ahciemaction, ahciempoll, "ahciem", enc,
	    device_get_unit(dev), &enc->mtx,
	    1, 0, devq);
	if (enc->sim == NULL) {
		cam_simq_free(devq);
		device_printf(dev, "Unable to allocate SIM\n");
		error = ENOMEM;
		goto err1;
	}
	if (xpt_bus_register(enc->sim, dev, 0) != CAM_SUCCESS) {
		device_printf(dev, "unable to register xpt bus\n");
		error = ENXIO;
		goto err2;
	}
	if (xpt_create_path(&enc->path, /*periph*/NULL, cam_sim_path(enc->sim),
	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
		device_printf(dev, "Unable to create path\n");
		error = ENXIO;
		goto err3;
	}
	mtx_unlock(&enc->mtx);
	if (bootverbose) {
		device_printf(dev, "Caps:%s%s%s%s%s%s%s%s\n",
		    (enc->capsem & AHCI_EM_PM) ? " PM":"",
		    (enc->capsem & AHCI_EM_ALHD) ? " ALHD":"",
		    (enc->capsem & AHCI_EM_XMT) ? " XMT":"",
		    (enc->capsem & AHCI_EM_SMB) ? " SMB":"",
		    (enc->capsem & AHCI_EM_SGPIO) ? " SGPIO":"",
		    (enc->capsem & AHCI_EM_SES2) ? " SES-2":"",
		    (enc->capsem & AHCI_EM_SAFTE) ? " SAF-TE":"",
		    (enc->capsem & AHCI_EM_LED) ? " LED":"");
	}
	if ((enc->capsem & AHCI_EM_LED)) {
		for (c = 0; c < enc->channels; c++) {
			if ((enc->ichannels & (1 << c)) == 0)
				continue;
			for (i = 0; i < AHCI_NUM_LEDS; i++) {
				enc->leds[c * AHCI_NUM_LEDS + i].dev = dev;
				enc->leds[c * AHCI_NUM_LEDS + i].num =
				    c * AHCI_NUM_LEDS + i;
			}
			if ((enc->capsem & AHCI_EM_ALHD) == 0) {
				snprintf(buf, sizeof(buf), "%s.%d.act",
				    device_get_nameunit(parent), c);
				enc->leds[c * AHCI_NUM_LEDS + 0].led =
				    led_create(ahci_em_led,
				    &enc->leds[c * AHCI_NUM_LEDS + 0], buf);
			}
			snprintf(buf, sizeof(buf), "%s.%d.locate",
			    device_get_nameunit(parent), c);
			enc->leds[c * AHCI_NUM_LEDS + 1].led =
			    led_create(ahci_em_led,
			    &enc->leds[c * AHCI_NUM_LEDS + 1], buf);
			snprintf(buf, sizeof(buf), "%s.%d.fault",
			    device_get_nameunit(parent), c);
			enc->leds[c * AHCI_NUM_LEDS + 2].led =
			    led_create(ahci_em_led,
			    &enc->leds[c * AHCI_NUM_LEDS + 2], buf);
		}
	}
	return (0);

err3:
	xpt_bus_deregister(cam_sim_path(enc->sim));
err2:
	cam_sim_free(enc->sim, /*free_devq*/TRUE);
err1:
	mtx_unlock(&enc->mtx);
	if (enc->r_memr)
		bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
err0:
	if (enc->r_memt)
		bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt);
	bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
	mtx_destroy(&enc->mtx);
	return (error);
}
コード例 #2
0
ファイル: if_ath_ahb.c プロジェクト: yunxiaoxiao110/haiku
static int
ath_ahb_attach(device_t dev)
{
    struct ath_ahb_softc *psc = device_get_softc(dev);
    struct ath_softc *sc = &psc->sc_sc;
    int error = ENXIO;
    int rid;
    long eepromaddr;
    uint8_t *p;

    sc->sc_dev = dev;

    rid = 0;
    psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
    if (psc->sc_sr == NULL) {
        device_printf(dev, "cannot map register space\n");
        goto bad;
    }

    if (resource_long_value(device_get_name(dev), device_get_unit(dev),
                            "eepromaddr", &eepromaddr) != 0) {
        device_printf(dev, "cannot fetch 'eepromaddr' from hints\n");
        goto bad0;
    }
    rid = 0;
    device_printf(sc->sc_dev, "eeprom @ %p\n", (void *) eepromaddr);
    psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr,
                                        (uintptr_t) eepromaddr + (uintptr_t) ((ATH_EEPROM_DATA_SIZE * 2) - 1), 0, RF_ACTIVE);
    if (psc->sc_eeprom == NULL) {
        device_printf(dev, "cannot map eeprom space\n");
        goto bad0;
    }

    /* XXX uintptr_t is a bandaid for ia64; to be fixed */
    sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr);
    sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr);
    /*
     * Mark device invalid so any interrupts (shared or otherwise)
     * that arrive before the HAL is setup are discarded.
     */
    sc->sc_invalid = 1;

    /* Copy the EEPROM data out */
    sc->sc_eepromdata = malloc(ATH_EEPROM_DATA_SIZE * 2, M_TEMP, M_NOWAIT | M_ZERO);
    if (sc->sc_eepromdata == NULL) {
        device_printf(dev, "cannot allocate memory for eeprom data\n");
        goto bad1;
    }
    device_printf(sc->sc_dev, "eeprom data @ %p\n", (void *) rman_get_bushandle(psc->sc_eeprom));
    /* XXX why doesn't this work? -adrian */
#if 0
    bus_space_read_multi_1(
        rman_get_bustag(psc->sc_eeprom),
        rman_get_bushandle(psc->sc_eeprom),
        0, (u_int8_t *) sc->sc_eepromdata, ATH_EEPROM_DATA_SIZE * 2);
#endif
    p = (void *) rman_get_bushandle(psc->sc_eeprom);
    memcpy(sc->sc_eepromdata, p, ATH_EEPROM_DATA_SIZE * 2);

    /*
     * Arrange interrupt line.
     */
    rid = 0;
    psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE);
    if (psc->sc_irq == NULL) {
        device_printf(dev, "could not map interrupt\n");
        goto bad1;
    }
    if (bus_setup_intr(dev, psc->sc_irq,
                       INTR_TYPE_NET | INTR_MPSAFE,
                       NULL, ath_intr, sc, &psc->sc_ih)) {
        device_printf(dev, "could not establish interrupt\n");
        goto bad2;
    }

    /*
     * Setup DMA descriptor area.
     */
    if (bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
                           1, 0,			/* alignment, bounds */
                           BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
                           BUS_SPACE_MAXADDR,	/* highaddr */
                           NULL, NULL,		/* filter, filterarg */
                           0x3ffff,			/* maxsize XXX */
                           ATH_MAX_SCATTER,		/* nsegments */
                           0x3ffff,			/* maxsegsize XXX */
                           BUS_DMA_ALLOCNOW,	/* flags */
                           NULL,			/* lockfunc */
                           NULL,			/* lockarg */
                           &sc->sc_dmat)) {
        device_printf(dev, "cannot allocate DMA tag\n");
        goto bad3;
    }

    ATH_LOCK_INIT(sc);

    error = ath_attach(AR9130_DEVID, sc);
    if (error == 0)					/* success */
        return 0;

    ATH_LOCK_DESTROY(sc);
    bus_dma_tag_destroy(sc->sc_dmat);
bad3:
    bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
bad2:
    bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
bad1:
    bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom);
bad0:
    bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr);
bad:
    /* XXX?! */
    if (sc->sc_eepromdata)
        free(sc->sc_eepromdata, M_TEMP);
    return (error);
}
コード例 #3
0
static int
ida_pci_attach(device_t dev)
{
	struct ida_board *board = ida_pci_match(dev);
	u_int32_t id = pci_get_devid(dev);
	struct ida_softc *ida;
	u_int command;
	int error, rid;

	command = pci_read_config(dev, PCIR_COMMAND, 1);

	/*
	 * it appears that this board only does MEMIO access.
	 */
	if ((command & PCIM_CMD_MEMEN) == 0) {
	        device_printf(dev, "Only memory mapped I/O is supported\n");
		return (ENXIO);
	}

	ida = (struct ida_softc *)device_get_softc(dev);
	ida->dev = dev;
	ida->cmd = *board->accessor;
	ida->flags = board->flags;

	ida->regs_res_type = SYS_RES_MEMORY;
	ida->regs_res_id = IDA_PCI_MEMADDR;
	if (id == IDA_DEVICEID_DEC_SMART)
		ida->regs_res_id = PCIR_BAR(0);

	ida->regs = bus_alloc_resource_any(dev, ida->regs_res_type,
	    &ida->regs_res_id, RF_ACTIVE);
	if (ida->regs == NULL) {
		device_printf(dev, "can't allocate memory resources\n");
		return (ENOMEM);
	}

	error = bus_dma_tag_create(
		/* parent	*/ NULL,
		/* alignment	*/ 1,
		/* boundary	*/ 0,
		/* lowaddr	*/ BUS_SPACE_MAXADDR_32BIT,
		/* highaddr	*/ BUS_SPACE_MAXADDR,
		/* filter	*/ NULL,
		/* filterarg	*/ NULL,
		/* maxsize	*/ MAXBSIZE,
		/* nsegments	*/ IDA_NSEG,
		/* maxsegsize	*/ BUS_SPACE_MAXSIZE_32BIT,
		/* flags	*/ BUS_DMA_ALLOCNOW,
		/* lockfunc	*/ NULL,
		/* lockarg	*/ NULL,
		&ida->parent_dmat);
	if (error != 0) {
		device_printf(dev, "can't allocate DMA tag\n");
		ida_free(ida);
		return (ENOMEM);
	}

	rid = 0;
	ida->irq_res_type = SYS_RES_IRQ;
	ida->irq = bus_alloc_resource_any(dev, ida->irq_res_type, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (ida->irq == NULL) {
	        ida_free(ida);
	        return (ENOMEM);
	}
	error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY,
	    NULL, ida_intr, ida, &ida->ih);
	if (error) {
		device_printf(dev, "can't setup interrupt\n");
		ida_free(ida);
		return (ENOMEM);
	}

	error = ida_init(ida);
	if (error) {
	        ida_free(ida);
	        return (error);
	}
	ida_attach(ida);
	ida->flags |= IDA_ATTACHED;

	return (0);
}
コード例 #4
0
ファイル: nfc_rb.c プロジェクト: hmatyschok/MeshBSD
static int
rb_nand_attach(device_t dev)
{
	struct rb_nand_softc *sc;
	phandle_t node;
	uint32_t ale[2],cle[2],nce[2],rdy[2];
	u_long size,start;
	int err;

	sc = device_get_softc(dev);
	node = ofw_bus_get_node(dev);

	if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) {
		return (ENXIO);
	}
	if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) {
		return (ENXIO);
	}
	if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) {
		return (ENXIO);
	}
	if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) {
		return (ENXIO);
	}

	if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) {
		device_printf(dev, "GPIO handles for signals must match.\n");
		return (ENXIO);
	}
	sc->sc_ale_pin = ale[1];
	sc->sc_cle_pin = cle[1];
	sc->sc_nce_pin = nce[1];
	sc->sc_rdy_pin = rdy[1];

	sc->sc_gpio = OF_device_from_xref(ale[0]);
	if (sc->sc_gpio == NULL) {
		device_printf(dev, "No GPIO resource found!\n");
		return (ENXIO);
	}

	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
	    RF_ACTIVE);
	if (sc->sc_mem == NULL) {
		device_printf(dev, "could not allocate resources!\n");
		return (ENXIO);
	}

	start = rman_get_start(sc->sc_mem);
	size = rman_get_size(sc->sc_mem);
	if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) {
		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem);
		device_printf(dev, "could not allocate local address window.\n");
		return (ENXIO);
	}

	nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);

	err = nandbus_create(dev);

	return (err);
}
コード例 #5
0
ファイル: pccbb_pci.c プロジェクト: cyrilmagsuci/freebsd
static int
cbb_pci_attach(device_t brdev)
{
#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS))
	static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */
	uint32_t pribus;
#endif
	struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev);
	struct sysctl_ctx_list *sctx;
	struct sysctl_oid *soid;
	int rid;
	device_t parent;

	parent = device_get_parent(brdev);
	mtx_init(&sc->mtx, device_get_nameunit(brdev), "cbb", MTX_DEF);
	sc->chipset = cbb_chipset(pci_get_devid(brdev), NULL);
	sc->dev = brdev;
	sc->cbdev = NULL;
	sc->exca[0].pccarddev = NULL;
	sc->domain = pci_get_domain(brdev);
	sc->pribus = pcib_get_bus(parent);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
	pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
	pcib_setup_secbus(brdev, &sc->bus, 1);
#else
	sc->bus.sec = pci_read_config(brdev, PCIR_SECBUS_2, 1);
	sc->bus.sub = pci_read_config(brdev, PCIR_SUBBUS_2, 1);
#endif
	SLIST_INIT(&sc->rl);

	rid = CBBR_SOCKBASE;
	sc->base_res = bus_alloc_resource_any(brdev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->base_res) {
		device_printf(brdev, "Could not map register memory\n");
		mtx_destroy(&sc->mtx);
		return (ENOMEM);
	} else {
		DEVPRINTF((brdev, "Found memory at %08lx\n",
		    rman_get_start(sc->base_res)));
	}

	sc->bst = rman_get_bustag(sc->base_res);
	sc->bsh = rman_get_bushandle(sc->base_res);
	exca_init(&sc->exca[0], brdev, sc->bst, sc->bsh, CBB_EXCA_OFFSET);
	sc->exca[0].flags |= EXCA_HAS_MEMREG_WIN;
	sc->exca[0].chipset = EXCA_CARDBUS;
	sc->chipinit = cbb_chipinit;
	sc->chipinit(sc);

	/*Sysctls*/
	sctx = device_get_sysctl_ctx(brdev);
	soid = device_get_sysctl_tree(brdev);
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "domain",
	    CTLFLAG_RD, &sc->domain, 0, "Domain number");
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus",
	    CTLFLAG_RD, &sc->pribus, 0, "Primary bus number");
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus",
	    CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number");
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
	    CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number");
#if 0
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "memory",
	    CTLFLAG_RD, &sc->subbus, 0, "Memory window open");
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "premem",
	    CTLFLAG_RD, &sc->subbus, 0, "Prefetch memroy window open");
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "io1",
	    CTLFLAG_RD, &sc->subbus, 0, "io range 1 open");
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "io2",
	    CTLFLAG_RD, &sc->subbus, 0, "io range 2 open");
#endif

#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS))
	/*
	 * This is a gross hack.  We should be scanning the entire pci
	 * tree, assigning bus numbers in a way such that we (1) can
	 * reserve 1 extra bus just in case and (2) all sub busses
	 * are in an appropriate range.
	 */
	DEVPRINTF((brdev, "Secondary bus is %d\n", sc->bus.sec));
	pribus = pci_read_config(brdev, PCIR_PRIBUS_2, 1);
	if (sc->bus.sec == 0 || sc->pribus != pribus) {
		if (curr_bus_number <= sc->pribus)
			curr_bus_number = sc->pribus + 1;
		if (pribus != sc->pribus) {
			DEVPRINTF((brdev, "Setting primary bus to %d\n",
			    sc->pribus));
			pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
		}
		sc->bus.sec = curr_bus_number++;
		sc->bus.sub = curr_bus_number++;
		DEVPRINTF((brdev, "Secondary bus set to %d subbus %d\n",
		    sc->bus.sec, sc->bus.sub));
		pci_write_config(brdev, PCIR_SECBUS_2, sc->bus.sec, 1);
		pci_write_config(brdev, PCIR_SUBBUS_2, sc->bus.sub, 1);
	}
#endif

	/* attach children */
	sc->cbdev = device_add_child(brdev, "cardbus", -1);
	if (sc->cbdev == NULL)
		DEVPRINTF((brdev, "WARNING: cannot add cardbus bus.\n"));
	else if (device_probe_and_attach(sc->cbdev) != 0)
		DEVPRINTF((brdev, "WARNING: cannot attach cardbus bus!\n"));

	sc->exca[0].pccarddev = device_add_child(brdev, "pccard", -1);
	if (sc->exca[0].pccarddev == NULL)
		DEVPRINTF((brdev, "WARNING: cannot add pccard bus.\n"));
	else if (device_probe_and_attach(sc->exca[0].pccarddev) != 0)
		DEVPRINTF((brdev, "WARNING: cannot attach pccard bus.\n"));

	/* Map and establish the interrupt. */
	rid = 0;
	sc->irq_res = bus_alloc_resource_any(brdev, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->irq_res == NULL) {
		device_printf(brdev, "Unable to map IRQ...\n");
		goto err;
	}

	if (bus_setup_intr(brdev, sc->irq_res, INTR_TYPE_AV | INTR_MPSAFE,
	    cbb_pci_filt, NULL, sc, &sc->intrhand)) {
		device_printf(brdev, "couldn't establish interrupt\n");
		goto err;
	}

	/* reset 16-bit pcmcia bus */
	exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);

	/* turn off power */
	cbb_power(brdev, CARD_OFF);

	/* CSC Interrupt: Card detect interrupt on */
	cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);

	/* reset interrupt */
	cbb_set(sc, CBB_SOCKET_EVENT, cbb_get(sc, CBB_SOCKET_EVENT));

	if (bootverbose)
		cbb_print_config(brdev);

	/* Start the thread */
	if (kproc_create(cbb_event_thread, sc, &sc->event_thread, 0, 0,
	    "%s event thread", device_get_nameunit(brdev))) {
		device_printf(brdev, "unable to create event thread.\n");
		panic("cbb_create_event_thread");
	}
	sc->sc_root_token = root_mount_hold(device_get_nameunit(sc->dev));
	return (0);
err:
	if (sc->irq_res)
		bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res);
	if (sc->base_res) {
		bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE,
		    sc->base_res);
	}
	mtx_destroy(&sc->mtx);
	return (ENOMEM);
}
コード例 #6
0
ファイル: bcm2835_bsc.c プロジェクト: cyrilmagsuci/freebsd
static int
bcm_bsc_attach(device_t dev)
{
    struct bcm_bsc_softc *sc;
    unsigned long start;
    device_t gpio;
    int i, rid;

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

    rid = 0;
    sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
                                            RF_ACTIVE);
    if (!sc->sc_mem_res) {
        device_printf(dev, "cannot allocate memory window\n");
        return (ENXIO);
    }

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

    /* Check the unit we are attaching by its base address. */
    start = rman_get_start(sc->sc_mem_res);
    for (i = 0; i < nitems(bcm_bsc_pins); i++) {
        if (bcm_bsc_pins[i].start == (start & BCM_BSC_BASE_MASK))
            break;
    }
    if (i == nitems(bcm_bsc_pins)) {
        device_printf(dev, "only bsc0 and bsc1 are supported\n");
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        return (ENXIO);
    }

    /*
     * Configure the GPIO pins to ALT0 function to enable BSC control
     * over the pins.
     */
    gpio = devclass_get_device(devclass_find("gpio"), 0);
    if (!gpio) {
        device_printf(dev, "cannot find gpio0\n");
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        return (ENXIO);
    }
    bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].sda, BCM_GPIO_ALT0);
    bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].scl, BCM_GPIO_ALT0);

    rid = 0;
    sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                            RF_ACTIVE | RF_SHAREABLE);
    if (!sc->sc_irq_res) {
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot allocate interrupt\n");
        return (ENXIO);
    }

    /* Hook up our interrupt handler. */
    if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
                       NULL, bcm_bsc_intr, sc, &sc->sc_intrhand)) {
        bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot setup the interrupt handler\n");
        return (ENXIO);
    }

    mtx_init(&sc->sc_mtx, "bcm_bsc", NULL, MTX_DEF);

    bcm_bsc_sysctl_init(sc);

    /* Enable the BSC controller.  Flush the FIFO. */
    BCM_BSC_LOCK(sc);
    bcm_bsc_reset(sc);
    BCM_BSC_UNLOCK(sc);

    sc->sc_iicbus = device_add_child(dev, "iicbus", -1);
    if (sc->sc_iicbus == NULL) {
        bcm_bsc_detach(dev);
        return (ENXIO);
    }

    return (bus_generic_attach(dev));
}
コード例 #7
0
ファイル: gpio.c プロジェクト: FreeBSDFoundation/freebsd
static int
mv_gpio_attach(device_t dev)
{
	int i, rv;
	struct mv_gpio_softc *sc;
	phandle_t node;
	pcell_t pincnt = 0;

	sc = (struct mv_gpio_softc *)device_get_softc(dev);
	if (sc == NULL)
		return (ENXIO);

	node = ofw_bus_get_node(dev);
	sc->dev = dev;

	if (OF_getencprop(node, "pin-count", &pincnt, sizeof(pcell_t)) >= 0 ||
	    OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t)) >= 0) {
		sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
		if (bootverbose)
			device_printf(dev, "%d pins available\n", sc->pin_num);
	} else {
		device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
		return (ENXIO);
	}

	if (OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset)) == -1)
		sc->offset = 0;

	/* Assign generic capabilities to every gpio pin */
	for(i = 0; i < sc->pin_num; i++)
		sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;

	mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN);

	sc->mem_rid = 0;
	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
		 RF_ACTIVE | RF_SHAREABLE );

	if (!sc->mem_res) {
		mtx_destroy(&sc->mutex);
		device_printf(dev, "could not allocate memory window\n");
		return (ENXIO);
	}

	sc->bst = rman_get_bustag(sc->mem_res);
	sc->bsh = rman_get_bushandle(sc->mem_res);

	rv = mv_gpio_setup_interrupts(sc, node);
	if (rv != 0)
		return (rv);

	sc->sc_busdev = gpiobus_attach_bus(dev);
	if (sc->sc_busdev == NULL) {
		mtx_destroy(&sc->mutex);
		bus_release_resource(dev, SYS_RES_IRQ,
			sc->irq_rid[i], sc->irq_res[i]);
		return (ENXIO);
	}

	return (0);
}
コード例 #8
0
ファイル: rtc.c プロジェクト: dcui/FreeBSD-9.3_kernel
static int
rtc_attach(device_t dev)
{
	struct timespec ts;
	struct mc146818_softc *sc;
	struct resource *res;
	int ebus, error, rid;

	sc = device_get_softc(dev);

	mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN);

	ebus = 0;
	if (strcmp(device_get_name(device_get_parent(dev)), "ebus") == 0)
		ebus = 1;

	rid = 0;
	res = bus_alloc_resource_any(dev, ebus ? SYS_RES_MEMORY :
	    SYS_RES_IOPORT, &rid, RF_ACTIVE);
	if (res == NULL) {
		device_printf(dev, "cannot allocate resources\n");
		error = ENXIO;
		goto fail_mtx;
	}
	sc->sc_bst = rman_get_bustag(res);
	sc->sc_bsh = rman_get_bushandle(res);

	sc->sc_mcread = RTC_READ;
	sc->sc_mcwrite = RTC_WRITE;
	/* The TOD clock year 0 is 0. */
	sc->sc_year0 = 0;
	/*
	 * For ISA use the default century get/set functions, for EBus we
	 * provide our own versions.
	 */
	sc->sc_flag = MC146818_NO_CENT_ADJUST;
	if (ebus) {
		/*
		 * Make sure the CR is at the default location (also used
		 * by Solaris).
		 */
		RTC_WRITE(dev, MC_REGA, PC87317_APC);
		RTC_WRITE(dev, PC87317_APC_CADDR, PC87317_APC_CADDR_BANK1 |
		    PC87317_RTC_CR);
		RTC_WRITE(dev, MC_REGA, PC87317_COMMON);
		sc->sc_getcent = pc87317_getcent;
		sc->sc_setcent = pc87317_setcent;
	}
	if ((error = mc146818_attach(dev)) != 0) {
		device_printf(dev, "cannot attach time of day clock\n");
		goto fail_res;
	}

	if (bootverbose) {
		if (mc146818_gettime(dev, &ts) != 0)
			device_printf(dev, "invalid time");
		else
			device_printf(dev, "current time: %ld.%09ld\n",
			    (long)ts.tv_sec, ts.tv_nsec);
	}

	return (0);

 fail_res:
	bus_release_resource(dev, ebus ? SYS_RES_MEMORY : SYS_RES_IOPORT, rid,
	    res);
 fail_mtx:
	mtx_destroy(&sc->sc_mtx);

	return (error);
}
コード例 #9
0
ファイル: uhci_pci.c プロジェクト: ele7enxxh/dtrace-pf
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;

	/* 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_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);
}
コード例 #10
0
ファイル: xhci_pci.c プロジェクト: alexandermerritt/dragonfly
static int
xhci_pci_attach(device_t self)
{
	struct xhci_softc *sc = device_get_softc(self);
	int count, err, rid;
	uint8_t usedma32;

	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");
		return (ENOMEM);
	}
	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);

	/* check for USB 3.0 controllers which don't support 64-bit DMA */
	switch (pci_get_devid(self)) {
	case 0x01941033:	/* NEC uPD720200 USB 3.0 controller */
		usedma32 = 1;
		break;
	default:
		usedma32 = 0;
		break;
	}

	if (xhci_init(sc, self, usedma32)) {
		device_printf(self, "Could not initialize softc\n");
		bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
		    sc->sc_io_res);
		return (ENXIO);
	}

	pci_enable_busmaster(self);

	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_lock, 0);

	rid = 0;
	if (xhci_use_msi) {
		count = pci_msi_count(self);
		if (count >= 1) {
			count = 1;
			if (pci_alloc_msi(self, &rid, 1, count) == 0) {
				if (bootverbose)
					device_printf(self, "MSI enabled\n");
				sc->sc_irq_rid = 1;
			}
		}
	}
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ,
	    &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		pci_release_msi(self);
		device_printf(self, "Could not allocate IRQ\n");
		/* goto error; FALLTHROUGH - use polling */
	}
	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));

	if (sc->sc_irq_res != NULL) {
		err = bus_setup_intr(self, sc->sc_irq_res, INTR_MPSAFE,
		    (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl, NULL);
		if (err != 0) {
			bus_release_resource(self, SYS_RES_IRQ,
			    rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
			sc->sc_irq_res = NULL;
			pci_release_msi(self);
			device_printf(self, "Could not setup IRQ, err=%d\n", err);
			sc->sc_intr_hdl = NULL;
		}
	}
	if (sc->sc_irq_res == NULL || sc->sc_intr_hdl == NULL) {
		if (xhci_use_polling() != 0) {
			device_printf(self, "Interrupt polling at %dHz\n", hz);
			USB_BUS_LOCK(&sc->sc_bus);
			xhci_interrupt_poll(sc);
			USB_BUS_UNLOCK(&sc->sc_bus);
		} else
			goto error;
	}

	/* On Intel chipsets reroute ports from EHCI to XHCI controller. */
	switch (pci_get_devid(self)) {
	case 0x0f358086:	/* BayTrail */
	case 0x9c318086:	/* Panther Point */
	case 0x1e318086:	/* Panther Point */
	case 0x8c318086:	/* Lynx Point */
	case 0x8cb18086:	/* Wildcat Point */
		sc->sc_port_route = &xhci_pci_port_route;
		sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP;
		break;
	default:
		break;
	}

	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);
}
コード例 #11
0
static int
ebus_pci_attach(device_t dev)
{
	struct ebus_softc *sc;
	struct ebus_rinfo *eri;
	struct resource *res;
	struct isa_ranges *range;
	phandle_t node;
	int i, rnum, rid;

	sc = device_get_softc(dev);
	sc->sc_flags |= EBUS_PCI;

	pci_write_config(dev, PCIR_COMMAND,
	    pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_SERRESPEN |
	    PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 2);
	pci_write_config(dev, PCIR_CACHELNSZ, 16 /* 64 bytes */, 1);
	pci_write_config(dev, PCIR_LATTIMER, 64 /* 64 PCI cycles */, 1);

	node = ofw_bus_get_node(dev);
	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
	    sizeof(struct isa_ranges), &sc->sc_range);
	if (sc->sc_nrange == -1) {
		device_printf(dev, "could not get ranges property\n");
		return (ENXIO);
	}

	sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF,
	    M_WAITOK | M_ZERO);

	/* For every range, there must be a matching resource. */
	for (rnum = 0; rnum < sc->sc_nrange; rnum++) {
		eri = &sc->sc_rinfo[rnum];
		range = &((struct isa_ranges *)sc->sc_range)[rnum];
		eri->eri_rtype = ofw_isa_range_restype(range);
		rid = PCIR_BAR(rnum);
		res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid,
		    RF_ACTIVE);
		if (res == NULL) {
			device_printf(dev,
			    "could not allocate range resource %d\n", rnum);
			goto fail;
		}
		if (rman_get_start(res) != ISA_RANGE_PHYS(range)) {
			device_printf(dev,
			    "mismatch in start of range %d (0x%lx/0x%lx)\n",
			    rnum, rman_get_start(res), ISA_RANGE_PHYS(range));
			goto fail;
		}
		if (rman_get_size(res) != range->size) {
			device_printf(dev,
			    "mismatch in size of range %d (0x%lx/0x%x)\n",
			    rnum, rman_get_size(res), range->size);
			goto fail;
		}
		eri->eri_res = res;
		eri->eri_rman.rm_type = RMAN_ARRAY;
		eri->eri_rman.rm_descr = "EBus range";
		if (rman_init_from_resource(&eri->eri_rman, res) != 0) {
			device_printf(dev,
			    "could not initialize rman for range %d", rnum);
			goto fail;
		}
	}
	return (ebus_attach(dev, sc, node));

 fail:
	for (i = rnum; i >= 0; i--) {
		eri = &sc->sc_rinfo[i];
		if (i < rnum)
			rman_fini(&eri->eri_rman);
		if (eri->eri_res != 0) {
			bus_release_resource(dev, eri->eri_rtype,
			    PCIR_BAR(rnum), eri->eri_res);
		}
	}
	free(sc->sc_rinfo, M_DEVBUF);
	free(sc->sc_range, M_OFWPROP);
	return (ENXIO);
}
コード例 #12
0
ファイル: intpm.c プロジェクト: 2asoft/freebsd
static int
intsmb_attach(device_t dev)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error, rid, value;
	int intr;
	char *str;

	sc->dev = dev;

	mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF);

	sc->cfg_irq9 = 0;
#ifndef NO_CHANGE_PCICONF
	switch (pci_get_devid(dev)) {
	case 0x71138086:	/* Intel 82371AB */
	case 0x719b8086:	/* Intel 82443MX */
		/* Changing configuration is allowed. */
		sc->cfg_irq9 = 1;
		break;
	}
#endif

	rid = PCI_BASE_ADDR_SMB;
	sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
	    RF_ACTIVE);
	if (sc->io_res == NULL) {
		device_printf(dev, "Could not allocate I/O space\n");
		error = ENXIO;
		goto fail;
	}

	if (sc->cfg_irq9) {
		pci_write_config(dev, PCIR_INTLINE, 0x9, 1);
		pci_write_config(dev, PCI_HST_CFG_SMB,
		    PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1);
	}
	value = pci_read_config(dev, PCI_HST_CFG_SMB, 1);
	sc->poll = (value & PCI_INTR_SMB_ENABLE) == 0;
	intr = value & PCI_INTR_SMB_MASK;
	switch (intr) {
	case PCI_INTR_SMB_SMI:
		str = "SMI";
		break;
	case PCI_INTR_SMB_IRQ9:
		str = "IRQ 9";
		break;
	case PCI_INTR_SMB_IRQ_PCI:
		str = "PCI IRQ";
		break;
	default:
		str = "BOGUS";
	}

	device_printf(dev, "intr %s %s ", str,
	    sc->poll == 0 ? "enabled" : "disabled");
	printf("revision %d\n", pci_read_config(dev, PCI_REVID_SMB, 1));

	if (!sc->poll && intr == PCI_INTR_SMB_SMI) {
		device_printf(dev,
		    "using polling mode when configured interrupt is SMI\n");
		sc->poll = 1;
	}

	if (sc->poll)
	    goto no_intr;

	if (intr != PCI_INTR_SMB_IRQ9 && intr != PCI_INTR_SMB_IRQ_PCI) {
		device_printf(dev, "Unsupported interrupt mode\n");
		error = ENXIO;
		goto fail;
	}

	/* Force IRQ 9. */
	rid = 0;
	if (sc->cfg_irq9)
		bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1);

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

	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, intsmb_rawintr, sc, &sc->irq_hand);
	if (error) {
		device_printf(dev, "Failed to map intr\n");
		goto fail;
	}

no_intr:
	sc->isbusy = 0;
	sc->smbus = device_add_child(dev, "smbus", -1);
	if (sc->smbus == NULL) {
		error = ENXIO;
		goto fail;
	}
	error = device_probe_and_attach(sc->smbus);
	if (error)
		goto fail;

#ifdef ENABLE_ALART
	/* Enable Arart */
	bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN);
#endif
	return (0);

fail:
	intsmb_detach(dev);
	return (error);
}
コード例 #13
0
ファイル: ida_eisa.c プロジェクト: 2asoft/freebsd
static int
ida_eisa_attach(device_t dev)
{
	struct ida_softc	*ida;
	struct ida_board	*board;
	int			error;
	int			rid;

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

	board = ida_eisa_match(eisa_get_id(dev));
	ida->cmd = *board->accessor;
	ida->flags = board->flags;
	mtx_init(&ida->lock, "ida", NULL, MTX_DEF);
	callout_init_mtx(&ida->ch, &ida->lock, 0);

	ida->regs_res_type = SYS_RES_IOPORT;
	ida->regs_res_id = 0;
	ida->regs = bus_alloc_resource_any(dev, ida->regs_res_type,
	    &ida->regs_res_id, RF_ACTIVE);
	if (ida->regs == NULL) {
		device_printf(dev, "can't allocate register resources\n");
		return (ENOMEM);
	}

	error = bus_dma_tag_create(
		/* parent	*/	bus_get_dma_tag(dev),
		/* alignment	*/	1,
		/* boundary	*/	0,
		/* lowaddr	*/	BUS_SPACE_MAXADDR_32BIT,
		/* highaddr	*/	BUS_SPACE_MAXADDR,
		/* filter	*/	NULL,
		/* filterarg	*/	NULL,
		/* maxsize	*/	BUS_SPACE_MAXSIZE_32BIT,
		/* nsegments	*/	BUS_SPACE_UNRESTRICTED,
		/* maxsegsize	*/	BUS_SPACE_MAXSIZE_32BIT,
		/* flags	*/	BUS_DMA_ALLOCNOW,
		/* lockfunc	*/	NULL,
		/* lockarg	*/	NULL,
		&ida->parent_dmat);

	if (error != 0) {
		device_printf(dev, "can't allocate DMA tag\n");
		ida_free(ida);
		return (ENOMEM);
	}

	rid = 0;
	ida->irq_res_type = SYS_RES_IRQ;
	ida->irq = bus_alloc_resource_any(dev, ida->irq_res_type, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (ida->irq == NULL) {
		ida_free(ida);
		return (ENOMEM);
	}

	error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE,
	    NULL, ida_intr, ida, &ida->ih);
	if (error) {
		device_printf(dev, "can't setup interrupt\n");
		ida_free(ida);
		return (ENOMEM);
	}

	error = ida_setup(ida);
	if (error) {
		ida_free(ida);
		return (error);
	}

	return (0);
}
コード例 #14
0
static int
tsec_fdt_attach(device_t dev)
{
	struct tsec_softc *sc;
	int error = 0;

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

	/* XXX add comment on weird FSL's MII registers access design */
	if (device_get_unit(dev) == 0)
		tsec0_sc = sc;

	/* Get phy address from fdt */
	if (fdt_get_phyaddr(sc->node, &sc->phyaddr) != 0)
		return (ENXIO);

	/* Init timer */
	callout_init(&sc->tsec_callout, 1);

	/* Init locks */
	mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "TSEC TX lock",
	    MTX_DEF);
	mtx_init(&sc->receive_lock, device_get_nameunit(dev), "TSEC RX lock",
	    MTX_DEF);
	mtx_init(&sc->ic_lock, device_get_nameunit(dev), "TSEC IC lock",
	    MTX_DEF);

	/* Allocate IO memory for TSEC registers */
	sc->sc_rrid = 0;
	sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
	    RF_ACTIVE);
	if (sc->sc_rres == NULL) {
		device_printf(dev, "could not allocate IO memory range!\n");
		goto fail1;
	}
	sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
	sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);

	/* TSEC attach */
	if (tsec_attach(sc) != 0) {
		device_printf(dev, "could not be configured\n");
		goto fail2;
	}

	/* Set up interrupts (TX/RX/ERR) */
	sc->sc_transmit_irid = TSEC_RID_TXIRQ;
	error = tsec_setup_intr(sc, &sc->sc_transmit_ires,
	    &sc->sc_transmit_ihand, &sc->sc_transmit_irid,
	    tsec_transmit_intr, "TX");
	if (error)
		goto fail2;

	sc->sc_receive_irid = TSEC_RID_RXIRQ;
	error = tsec_setup_intr(sc, &sc->sc_receive_ires,
	    &sc->sc_receive_ihand, &sc->sc_receive_irid,
	    tsec_receive_intr, "RX");
	if (error)
		goto fail3;

	sc->sc_error_irid = TSEC_RID_ERRIRQ;
	error = tsec_setup_intr(sc, &sc->sc_error_ires,
	    &sc->sc_error_ihand, &sc->sc_error_irid,
	    tsec_error_intr, "ERR");
	if (error)
		goto fail4;

	return (0);

fail4:
	tsec_release_intr(sc, sc->sc_receive_ires, sc->sc_receive_ihand,
	    sc->sc_receive_irid, "RX");
fail3:
	tsec_release_intr(sc, sc->sc_transmit_ires, sc->sc_transmit_ihand,
	    sc->sc_transmit_irid, "TX");
fail2:
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
fail1:
	mtx_destroy(&sc->receive_lock);
	mtx_destroy(&sc->transmit_lock);
	return (ENXIO);
}
コード例 #15
0
int
quicc_bfe_attach(device_t dev)
{
	struct quicc_device *qd;
	struct quicc_softc *sc;
	struct resource_list_entry *rle;
	const char *sep;
	rman_res_t size, start;
	int error;

	sc = device_get_softc(dev);

	/*
	 * Re-allocate. We expect that the softc contains the information
	 * collected by quicc_bfe_probe() intact.
	 */
	sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid,
	    RF_ACTIVE);
	if (sc->sc_rres == NULL)
		return (ENXIO);

	start = rman_get_start(sc->sc_rres);
	size = rman_get_size(sc->sc_rres);

	sc->sc_rman.rm_start = start;
	sc->sc_rman.rm_end = start + size - 1;
	sc->sc_rman.rm_type = RMAN_ARRAY;
	sc->sc_rman.rm_descr = "QUICC resources";
	error = rman_init(&sc->sc_rman);
	if (!error)
		error = rman_manage_region(&sc->sc_rman, start,
		    start + size - 1);
	if (error) {
		bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid,
		    sc->sc_rres);
		return (error);
	}

	/*
	 * Allocate interrupt resource.
	 */
	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, quicc_bfe_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 *)quicc_bfe_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)
		sc->sc_polled = 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");
	}

	sc->sc_device = qd = malloc(sizeof(struct quicc_device), M_QUICC,
	    M_WAITOK | M_ZERO);

	qd->qd_devtype = QUICC_DEVTYPE_SCC;
	qd->qd_rman = &sc->sc_rman;
	resource_list_init(&qd->qd_rlist);

	resource_list_add(&qd->qd_rlist, sc->sc_rtype, 0, start,
	    start + size - 1, size);

	resource_list_add(&qd->qd_rlist, SYS_RES_IRQ, 0, 0xf00, 0xf00, 1);
	rle = resource_list_find(&qd->qd_rlist, SYS_RES_IRQ, 0);
	rle->res = sc->sc_ires;

	qd->qd_dev = device_add_child(dev, NULL, -1);
	device_set_ivars(qd->qd_dev, (void *)qd);
	error = device_probe_and_attach(qd->qd_dev);

	/* Enable all SCC interrupts. */
	quicc_write4(sc->sc_rres, QUICC_REG_SIMR_L, 0x00f00000);

	/* Clear all pending interrupts. */
	quicc_write4(sc->sc_rres, QUICC_REG_SIPNR_H, ~0);
	quicc_write4(sc->sc_rres, QUICC_REG_SIPNR_L, ~0);
	return (error);
}
コード例 #16
0
ファイル: ehci_fsl.c プロジェクト: ChaosJohn/freebsd
static int
fsl_ehci_attach(device_t self)
{
	ehci_softc_t *sc;
	int rid;
	int err;
	bus_space_handle_t ioh;
	bus_space_tag_t iot;

	sc = device_get_softc(self);
	rid = 0;

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

	if (usb_bus_mem_alloc_all(&sc->sc_bus,
	    USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc))
		return (ENOMEM);

	/* Allocate io resource for EHCI */
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->sc_io_res == NULL) {
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}
	iot = rman_get_bustag(sc->sc_io_res);

	/*
	 * Set handle to USB related registers subregion used by generic
	 * EHCI driver
	 */
	ioh = rman_get_bushandle(sc->sc_io_res);

	err = bus_space_subregion(iot, ioh, FSL_EHCI_REG_OFF, FSL_EHCI_REG_SIZE,
	    &sc->sc_io_hdl);
	if (err != 0) {
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	/* Set little-endian tag for use by the generic EHCI driver */
	sc->sc_io_tag = &bs_le_tag;

	/* Allocate irq */
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	/* Setup interrupt handler */
	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO,
	    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;
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	/* Add USB device */
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENOMEM);
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	sc->sc_id_vendor = 0x1234;
	strlcpy(sc->sc_vendor, "Freescale", sizeof(sc->sc_vendor));

	/* Enable USB */
	err = ehci_reset(sc);
	if (err) {
		device_printf(self, "Could not reset the controller\n");
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (ENXIO);
	}

	enable_usb(self, iot, ioh);
	set_snooping(iot, ioh);
	set_to_host_mode(sc);
	set_32b_prefetch(iot, ioh);

	/*
	 * If usb subsystem is enabled in U-Boot, port power has to be turned
	 * off to allow proper discovery of devices during boot up.
	 */
	clear_port_power(sc);

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

	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(self, "USB init failed err=%d\n", err);
		err = fsl_ehci_detach(self);
		if (err) {
			device_printf(self,
			    "Detach of the driver failed with error %d\n",
			    err);
		}
		return (EIO);
	}

	return (0);
}
コード例 #17
0
ファイル: ata-via.c プロジェクト: 2asoft/freebsd
static int
ata_via_chipinit(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);

    if (ata_setup_interrupt(dev, ata_generic_intr))
	return ENXIO;

    /* 2 SATA with "SATA registers" at PCI config space + PATA on secondary */
    if (ctlr->chip->cfg2 & VIASATA) {
	ctlr->ch_attach = ata_via_sata_ch_attach;
	ctlr->setmode = ata_via_sata_setmode;
	ctlr->getrev = ata_via_sata_getrev;
	ctlr->reset = ata_via_sata_reset;
	return 0;
    }
    /* Legacy SATA/SATA+PATA with SATA registers in BAR(5). */
    if (ctlr->chip->max_dma >= ATA_SA150) {
	ctlr->r_type2 = SYS_RES_IOPORT;
	ctlr->r_rid2 = PCIR_BAR(5);
	if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
						   &ctlr->r_rid2, RF_ACTIVE))) {
	    ctlr->ch_attach = ata_via_ch_attach;
	    ctlr->ch_detach = ata_via_ch_detach;
	    ctlr->reset = ata_via_reset;
	}
	if (ctlr->chip->cfg2 & VIABAR) {
	    ctlr->channels = 3;
	    ctlr->setmode = ata_via_new_setmode;
	} else
	    ctlr->setmode = ata_sata_setmode;
	ctlr->getrev = ata_sata_getrev;
	return 0;
    }

    /* prepare for ATA-66 on the 82C686a and 82C596b */
    if (ctlr->chip->cfg2 & VIACLK)
	pci_write_config(dev, 0x50, 0x030b030b, 4);       

    /* the southbridge might need the data corruption fix */
    if (ctlr->chip->cfg2 & VIABUG)
	ata_via_southbridge_fixup(dev);

    /* set fifo configuration half'n'half */
    pci_write_config(dev, 0x43, 
		     (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1);

    /* set status register read retry */
    pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1);

    /* set DMA read & end-of-sector fifo flush */
    pci_write_config(dev, 0x46, 
		     (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1);

    /* set sector size */
    pci_write_config(dev, 0x60, DEV_BSIZE, 2);
    pci_write_config(dev, 0x68, DEV_BSIZE, 2);

    ctlr->setmode = ata_via_old_setmode;
    return 0;
}
コード例 #18
0
static int
le_lebuffer_attach(device_t dev)
{
	struct le_lebuffer_softc *lesc;
	struct lance_softc *sc;
	int error, i;

	lesc = device_get_softc(dev);
	sc = &lesc->sc_am7990.lsc;

	LE_LOCK_INIT(sc, device_get_nameunit(dev));

	/*
	 * The "register space" of the parent is just a buffer where the
	 * the LANCE descriptor rings and the RX/TX buffers can be stored.
	 */
	i = 0;
	lesc->sc_bres = bus_alloc_resource_any(device_get_parent(dev),
	    SYS_RES_MEMORY, &i, RF_ACTIVE);
	if (lesc->sc_bres == NULL) {
		device_printf(dev, "cannot allocate LANCE buffer\n");
		error = ENXIO;
		goto fail_mtx;
	}

	/* Allocate LANCE registers. */
	i = 0;
	lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (lesc->sc_rres == NULL) {
		device_printf(dev, "cannot allocate LANCE registers\n");
		error = ENXIO;
		goto fail_bres;
	}

	/* Allocate LANCE interrupt. */
	i = 0;
	if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		device_printf(dev, "cannot allocate interrupt\n");
		error = ENXIO;
		goto fail_rres;
	}

	/*
	 * LANCE view is offset by buffer location.
	 * Note that we don't use sc->sc_mem.
	 */
	sc->sc_addr = 0;
	sc->sc_memsize = rman_get_size(lesc->sc_bres);
	sc->sc_flags = 0;

	/* That old black magic... */
	if (OF_getprop(ofw_bus_get_node(dev), "busmaster-regval",
	    &sc->sc_conf3, sizeof(sc->sc_conf3)) == -1)
		sc->sc_conf3 = LE_C3_ACON | LE_C3_BCON;
	/*
	 * Make sure LE_C3_BSWP is cleared so that for cards where
	 * that flag actually works le_lebuffer_copy{from,to}buf()
	 * don't fail...
	 */
	sc->sc_conf3 &= ~LE_C3_BSWP;

	OF_getetheraddr(dev, sc->sc_enaddr);

	sc->sc_copytodesc = le_lebuffer_copytodesc;
	sc->sc_copyfromdesc = le_lebuffer_copyfromdesc;
	sc->sc_copytobuf = le_lebuffer_copytobuf;
	sc->sc_copyfrombuf = le_lebuffer_copyfrombuf;
	sc->sc_zerobuf = le_lebuffer_zerobuf;

	sc->sc_rdcsr = le_lebuffer_rdcsr;
	sc->sc_wrcsr = le_lebuffer_wrcsr;
	sc->sc_hwreset = NULL;
	sc->sc_hwinit = NULL;
	sc->sc_hwintr = NULL;
	sc->sc_nocarrier = NULL;
	sc->sc_mediachange = NULL;
	sc->sc_mediastatus = NULL;
	sc->sc_supmedia = le_lebuffer_media;
	sc->sc_nsupmedia = NLEMEDIA;
	sc->sc_defaultmedia = le_lebuffer_media[0];

	error = am7990_config(&lesc->sc_am7990, device_get_name(dev),
	    device_get_unit(dev));
	if (error != 0) {
		device_printf(dev, "cannot attach Am7990\n");
		goto fail_ires;
	}

	error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
	    NULL, am7990_intr, sc, &lesc->sc_ih);
	if (error != 0) {
		device_printf(dev, "cannot set up interrupt\n");
		goto fail_am7990;
	}

	return (0);

 fail_am7990:
	am7990_detach(&lesc->sc_am7990);
 fail_ires:
	bus_release_resource(dev, SYS_RES_IRQ,
	    rman_get_rid(lesc->sc_ires), lesc->sc_ires);
 fail_rres:
	bus_release_resource(dev, SYS_RES_MEMORY,
	    rman_get_rid(lesc->sc_rres), lesc->sc_rres);
 fail_bres:
	bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY,
	    rman_get_rid(lesc->sc_bres), lesc->sc_bres);
 fail_mtx:
	LE_LOCK_DESTROY(sc);
	return (error);
}
コード例 #19
0
ファイル: gpio.c プロジェクト: FreeBSDFoundation/freebsd
static int
mv_gpio_setup_interrupts(struct mv_gpio_softc *sc, phandle_t node)
{
	phandle_t iparent;
	pcell_t irq_cells;
	int i, size;

	/* Find root interrupt controller */
	iparent = ofw_bus_find_iparent(node);
	if (iparent == 0) {
		device_printf(sc->dev, "No interrupt-parrent found. "
				"Error in DTB\n");
		return (ENXIO);
	} else {
		/* While at parent - store interrupt cells prop */
		if (OF_searchencprop(OF_node_from_xref(iparent),
		    "#interrupt-cells", &irq_cells, sizeof(irq_cells)) == -1) {
			device_printf(sc->dev, "DTB: Missing #interrupt-cells "
			    "property in interrupt parent node\n");
			return (ENXIO);
		}
	}

	size = OF_getproplen(node, "interrupts");
	if (size != -1) {
		size = size / sizeof(pcell_t);
		size = size / irq_cells;
		sc->irq_num = size;
		device_printf(sc->dev, "%d IRQs available\n", sc->irq_num);
	} else {
		device_printf(sc->dev, "ERROR: no interrupts entry found!\n");
		return (ENXIO);
	}

	for (i = 0; i < sc->irq_num; i++) {
		sc->irq_rid[i] = i;
		sc->irq_res[i] = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
			&sc->irq_rid[i], RF_ACTIVE);
		if (!sc->irq_res[i]) {
			mtx_destroy(&sc->mutex);
			device_printf(sc->dev,
			    "could not allocate gpio%d interrupt\n", i+1);
			return (ENXIO);
		}
	}

	device_printf(sc->dev, "Disable interrupts (offset = %x + EDGE(0x18)\n", sc->offset);
	/* Disable all interrupts */
	bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_EDGE_MASK, 0);
	device_printf(sc->dev, "Disable interrupts (offset = %x + LEV(0x1C))\n", sc->offset);
	bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_LEV_MASK, 0);

	for (i = 0; i < sc->irq_num; i++) {
		device_printf(sc->dev, "Setup intr %d\n", i);
		if (bus_setup_intr(sc->dev, sc->irq_res[i],
		    INTR_TYPE_MISC,
		    (driver_filter_t *)mv_gpio_intr, NULL,
		    sc, &sc->ih_cookie[i]) != 0) {
			mtx_destroy(&sc->mutex);
			bus_release_resource(sc->dev, SYS_RES_IRQ,
				sc->irq_rid[i], sc->irq_res[i]);
			device_printf(sc->dev, "could not set up intr %d\n", i);
			return (ENXIO);
		}
	}

	/* Clear interrupt status. */
	device_printf(sc->dev, "Clear int status (offset = %x)\n", sc->offset);
	bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_CAUSE, 0);

	sc->debounce_callouts = (struct callout **)malloc(sc->pin_num *
	    sizeof(struct callout *), M_DEVBUF, M_WAITOK | M_ZERO);
	if (sc->debounce_callouts == NULL)
		return (ENOMEM);

	sc->debounce_counters = (int *)malloc(sc->pin_num * sizeof(int),
	    M_DEVBUF, M_WAITOK);
	if (sc->debounce_counters == NULL)
		return (ENOMEM);

	return (0);
}
コード例 #20
0
ファイル: ehci_ixp4xx.c プロジェクト: hmatyschok/MeshBSD
static int
ehci_ixp_attach(device_t self)
{
	struct ixp_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);
	}

	/* 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.  Also, since
	 * we're already intercepting bus space ops we handle
	 * the register window offset that could otherwise be
	 * done with bus_space_subregion.
	 */
	isc->iot = rman_get_bustag(sc->sc_io_res);
	isc->tag.bs_privdata = isc->iot;
	/* read single */
	isc->tag.bs_r_1	= ehci_bs_r_1,
	isc->tag.bs_r_2	= ehci_bs_r_2,
	isc->tag.bs_r_4	= ehci_bs_r_4,
	/* write (single) */
	isc->tag.bs_w_1	= ehci_bs_w_1,
	isc->tag.bs_w_2	= ehci_bs_w_2,
	isc->tag.bs_w_4	= ehci_bs_w_4,

	sc->sc_io_tag = &isc->tag;
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = IXP435_USB1_SIZE - 0x100;

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    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, "Intel");


	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;
	}

	/*
	 * 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_TT
		     | EHCI_SCFLG_BIGEDESC
		     | EHCI_SCFLG_NORESTERM
		     ;

	/* Setup callbacks. */
	sc->sc_vendor_post_reset = ehci_ixp_post_reset;
	sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;

	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_ixp_detach(self);
	return (ENXIO);
}
コード例 #21
0
ファイル: if_atse_nexus.c プロジェクト: OpenKod/src
static int
atse_attach_nexus(device_t dev)
{
	struct atse_softc *sc;
	int error;

	sc = device_get_softc(dev);
	sc->atse_dev = dev;
	sc->atse_unit = device_get_unit(dev);

	/* Get RX and TX IRQ and FIFO information from hints. */
	error = atse_resource_int(dev, "rx_irq", &sc->atse_rx_irq);
	error += atse_resource_long(dev, "rx_maddr", &sc->atse_rx_maddr);
	error += atse_resource_long(dev, "rx_msize", &sc->atse_rx_msize);
	error += atse_resource_long(dev, "rxc_maddr", &sc->atse_rxc_maddr);
	error += atse_resource_long(dev, "rxc_msize", &sc->atse_rxc_msize);
	error += atse_resource_int(dev, "tx_irq", &sc->atse_tx_irq);
	error += atse_resource_long(dev, "tx_maddr", &sc->atse_tx_maddr);
	error += atse_resource_long(dev, "tx_msize", &sc->atse_tx_msize);
	error += atse_resource_long(dev, "txc_maddr", &sc->atse_txc_maddr);
	error += atse_resource_long(dev, "txc_msize", &sc->atse_txc_msize);
	if (error != 0)
		return (error);

	/* Avalon-MM, atse management register region. */
	sc->atse_mem_rid = 0;
	sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &sc->atse_mem_rid, RF_ACTIVE);
	if (sc->atse_mem_res == NULL) {
		device_printf(dev, "failed to map memory for ctrl region\n");
		return (ENXIO);
	}

	/*
	 * (Optional) RX IRQ and memory mapped regions.
	 * 0x00: 2 * 32bit FIFO data,
	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave.
	 */
	sc->atse_rx_irq_rid = 0;
	sc->atse_rx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
	    &sc->atse_rx_irq_rid, sc->atse_rx_irq, sc->atse_rx_irq, 1,
	    RF_ACTIVE | RF_SHAREABLE);

	sc->atse_rx_mem_rid = 0;
	sc->atse_rx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->atse_rx_mem_rid, sc->atse_rx_maddr, sc->atse_rx_maddr +
	    sc->atse_rx_msize, sc->atse_rx_msize, RF_ACTIVE);
	if (sc->atse_rx_mem_res == NULL) {
		device_printf(dev, "failed to map memory for RX\n");
		goto err;
        }
	sc->atse_rxc_mem_rid = 0;
	sc->atse_rxc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->atse_rxc_mem_rid, sc->atse_rxc_maddr, sc->atse_rxc_maddr +
	    sc->atse_rxc_msize, sc->atse_rxc_msize, RF_ACTIVE);
	if (sc->atse_rxc_mem_res == NULL) {
		device_printf(dev, "failed to map memory for RX control\n");
		goto err;
        }

	/*
	 * (Optional) TX IRQ and memory mapped regions.
	 * 0x00: 2 * 32bit FIFO data,
	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source.
	 */
	sc->atse_tx_irq_rid = 0;
	sc->atse_tx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
	    &sc->atse_tx_irq_rid, sc->atse_tx_irq, sc->atse_tx_irq, 1,
	    RF_ACTIVE | RF_SHAREABLE);

	sc->atse_tx_mem_rid = 0;
	sc->atse_tx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->atse_tx_mem_rid, sc->atse_tx_maddr, sc->atse_tx_maddr +
	    sc->atse_tx_msize, sc->atse_tx_msize, RF_ACTIVE);
	if (sc->atse_tx_mem_res == NULL) {
		device_printf(dev, "failed to map memory for TX\n");
		goto err;
	}
	sc->atse_txc_mem_rid = 0;
	sc->atse_txc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->atse_txc_mem_rid, sc->atse_txc_maddr, sc->atse_txc_maddr +
	    sc->atse_txc_msize, sc->atse_txc_msize, RF_ACTIVE);
	if (sc->atse_txc_mem_res == NULL) {
		device_printf(dev, "failed to map memory for TX control\n");
		goto err;
	}

	error = atse_attach(dev);
	if (error)
		goto err;

	return (0);

err:
	/* Cleanup. */
	atse_detach_resources(dev);

	return (error);
}
コード例 #22
0
ファイル: mpt_pci.c プロジェクト: coyizumi/cs111
static int
mpt_pci_attach(device_t dev)
{
	struct mpt_softc *mpt;
	int		  iqd;
	uint32_t	  val;
	int		  mpt_io_bar, mpt_mem_bar;

	mpt  = (struct mpt_softc*)device_get_softc(dev);

	switch (pci_get_device(dev)) {
	case MPI_MANUFACTPAGE_DEVICEID_FC909_FB:
	case MPI_MANUFACTPAGE_DEVICEID_FC909:
	case MPI_MANUFACTPAGE_DEVICEID_FC919:
	case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB:
	case MPI_MANUFACTPAGE_DEVICEID_FC929:
	case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
	case MPI_MANUFACTPAGE_DEVICEID_FC929X:
	case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB:
	case MPI_MANUFACTPAGE_DEVICEID_FC919X:
	case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB:
	case MPI_MANUFACTPAGE_DEVICEID_FC949E:
	case MPI_MANUFACTPAGE_DEVICEID_FC949X:
		mpt->is_fc = 1;
		break;
	case MPI_MANUFACTPAGE_DEVID_SAS1078:
	case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB:
		mpt->is_1078 = 1;
		/* FALLTHROUGH */
	case MPI_MANUFACTPAGE_DEVID_SAS1064:
	case MPI_MANUFACTPAGE_DEVID_SAS1064A:
	case MPI_MANUFACTPAGE_DEVID_SAS1064E:
	case MPI_MANUFACTPAGE_DEVID_SAS1066:
	case MPI_MANUFACTPAGE_DEVID_SAS1066E:
	case MPI_MANUFACTPAGE_DEVID_SAS1068:
	case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB:
	case MPI_MANUFACTPAGE_DEVID_SAS1068E:
	case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB:
		mpt->is_sas = 1;
		break;
	default:
		mpt->is_spi = 1;
		break;
	}
	mpt->dev = dev;
	mpt->unit = device_get_unit(dev);
	mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT;
	mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT;
	mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT;
	mpt->verbose = MPT_PRT_NONE;
	mpt->role = MPT_ROLE_NONE;
	mpt->mpt_ini_id = MPT_INI_ID_NONE;
#ifdef __sparc64__
	if (mpt->is_spi)
		mpt->mpt_ini_id = OF_getscsinitid(dev);
#endif
	mpt_set_options(mpt);
	if (mpt->verbose == MPT_PRT_NONE) {
		mpt->verbose = MPT_PRT_WARN;
		/* Print INFO level (if any) if bootverbose is set */
		mpt->verbose += (bootverbose != 0)? 1 : 0;
	}

	/*
	 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set.
	 */
	val = pci_read_config(dev, PCIR_COMMAND, 2);
	val |= PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN |
	    PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
	pci_write_config(dev, PCIR_COMMAND, val, 2);

	/*
	 * Make sure we've disabled the ROM.
	 */
	val = pci_read_config(dev, PCIR_BIOS, 4);
	val &= ~PCIM_BIOS_ENABLE;
	pci_write_config(dev, PCIR_BIOS, val, 4);

#if 0
	/*
	 * Is this part a dual?
	 * If so, link with our partner (around yet)
	 */
	switch (pci_get_device(dev)) {
	case MPI_MANUFACTPAGE_DEVICEID_FC929:
	case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
	case MPI_MANUFACTPAGE_DEVICEID_FC949E:
	case MPI_MANUFACTPAGE_DEVICEID_FC949X:
	case MPI_MANUFACTPAGE_DEVID_53C1030:
	case MPI_MANUFACTPAGE_DEVID_53C1030ZC:
		mpt_link_peer(mpt);
		break;
	default:
		break;
	}
#endif

	/*
	 * Figure out which are the I/O and MEM Bars
	 */
	val = pci_read_config(dev, PCIR_BAR(0), 4);
	if (PCI_BAR_IO(val)) {
		/* BAR0 is IO, BAR1 is memory */
		mpt_io_bar = 0;
		mpt_mem_bar = 1;
	} else {
		/* BAR0 is memory, BAR1 is IO */
		mpt_mem_bar = 0;
		mpt_io_bar = 1;
	}

	/*
	 * Set up register access.  PIO mode is required for
	 * certain reset operations (but must be disabled for
	 * some cards otherwise).
	 */
	mpt_io_bar = PCIR_BAR(mpt_io_bar);
	mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
	    &mpt_io_bar, RF_ACTIVE);
	if (mpt->pci_pio_reg == NULL) {
		if (bootverbose) {
			device_printf(dev,
			    "unable to map registers in PIO mode\n");
		}
	} else {
		mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
		mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
	}

	mpt_mem_bar = PCIR_BAR(mpt_mem_bar);
	mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &mpt_mem_bar, RF_ACTIVE);
	if (mpt->pci_reg == NULL) {
		if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) {
			device_printf(dev,
			    "Unable to memory map registers.\n");
		}
		if (mpt->is_sas || mpt->pci_pio_reg == NULL) {
			device_printf(dev, "Giving Up.\n");
			goto bad;
		}
		if (bootverbose) {
			device_printf(dev, "Falling back to PIO mode.\n");
		}
		mpt->pci_st = mpt->pci_pio_st;
		mpt->pci_sh = mpt->pci_pio_sh;
	} else {
		mpt->pci_st = rman_get_bustag(mpt->pci_reg);
		mpt->pci_sh = rman_get_bushandle(mpt->pci_reg);
	}

	/* Get a handle to the interrupt */
	iqd = 0;
	if (mpt->msi_enable) {
		/*
		 * First try to alloc an MSI-X message.  If that
		 * fails, then try to alloc an MSI message instead.
		 */
		val = 1;
		if (pci_alloc_msix(dev, &val) == 0)
			iqd = 1;
		val = 1;
		if (iqd == 0 && pci_alloc_msi(dev, &val) == 0)
			iqd = 1;
	}
	mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
	    RF_ACTIVE | (iqd != 0 ? 0 : RF_SHAREABLE));
	if (mpt->pci_irq == NULL) {
		device_printf(dev, "could not allocate interrupt\n");
		goto bad;
	}

	MPT_LOCK_SETUP(mpt);

	/* Disable interrupts at the part */
	mpt_disable_ints(mpt);

	/* Register the interrupt handler */
	if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr,
	    mpt, &mpt->ih)) {
		device_printf(dev, "could not setup interrupt\n");
		goto bad;
	}

	/* Allocate dma memory */
	if (mpt_dma_mem_alloc(mpt)) {
		mpt_prt(mpt, "Could not allocate DMA memory\n");
		goto bad;
	}

#if 0
	/*
	 * Save the PCI config register values
 	 *
	 * Hard resets are known to screw up the BAR for diagnostic
	 * memory accesses (Mem1).
	 *
	 * Using Mem1 is known to make the chip stop responding to 
	 * configuration space transfers, so we need to save it now
	 */

	mpt_read_config_regs(mpt);
#endif

	/*
	 * Disable PIO until we need it
	 */
	if (mpt->is_sas) {
		pci_disable_io(dev, SYS_RES_IOPORT);
	}

	/* Initialize the hardware */
	if (mpt->disabled == 0) {
		if (mpt_attach(mpt) != 0) {
			goto bad;
		}
	} else {
		mpt_prt(mpt, "device disabled at user request\n");
		goto bad;
	}

	mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown,
	    dev, SHUTDOWN_PRI_LAST);

	if (mpt->eh == NULL) {
		mpt_prt(mpt, "shutdown event registration failed\n");
		mpt_disable_ints(mpt);
		(void) mpt_detach(mpt);
		mpt_reset(mpt, /*reinit*/FALSE);
		mpt_raid_free_mem(mpt);
		goto bad;
	}
	return (0);

bad:
	mpt_dma_mem_free(mpt);
	mpt_free_bus_resources(mpt);
#if 0
	mpt_unlink_peer(mpt);
#endif

	MPT_LOCK_DESTROY(mpt);

	/*
	 * but return zero to preserve unit numbering
	 */
	return (0);
}
コード例 #23
0
ファイル: bcm2835_spi.c プロジェクト: 2trill2spill/freebsd
static int
bcm_spi_attach(device_t dev)
{
	struct bcm_spi_softc *sc;
	device_t gpio;
	int i, rid;

	if (device_get_unit(dev) != 0) {
		device_printf(dev, "only one SPI controller supported\n");
		return (ENXIO);
	}

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

	/* Configure the GPIO pins to ALT0 function to enable SPI the pins. */
	gpio = devclass_get_device(devclass_find("gpio"), 0);
	if (!gpio) {
		device_printf(dev, "cannot find gpio0\n");
		return (ENXIO);
	}
	for (i = 0; i < nitems(bcm_spi_pins); i++)
		bcm_gpio_set_alternate(gpio, bcm_spi_pins[i], BCM_GPIO_ALT0);

	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		return (ENXIO);
	}

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

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!sc->sc_irq_res) {
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot allocate interrupt\n");
		return (ENXIO);
	}

	/* Hook up our interrupt handler. */
	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, bcm_spi_intr, sc, &sc->sc_intrhand)) {
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot setup the interrupt handler\n");
		return (ENXIO);
	}

	mtx_init(&sc->sc_mtx, "bcm_spi", NULL, MTX_DEF);

	/* Add sysctl nodes. */
	bcm_spi_sysctl_init(sc);

#ifdef	BCM_SPI_DEBUG
	bcm_spi_printr(dev);
#endif

	/*
	 * Enable the SPI controller.  Clear the rx and tx FIFO.
	 * Defaults to SPI mode 0.
	 */
	BCM_SPI_WRITE(sc, SPI_CS, SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);

	/* Set the SPI clock to 500Khz. */
	BCM_SPI_WRITE(sc, SPI_CLK, SPI_CORE_CLK / 500000);

#ifdef	BCM_SPI_DEBUG
	bcm_spi_printr(dev);
#endif

	device_add_child(dev, "spibus", -1);

	return (bus_generic_attach(dev));
}
コード例 #24
0
ファイル: imx6_usbphy.c プロジェクト: 2asoft/freebsd
static int
usbphy_attach(device_t dev)
{
	struct usbphy_softc *sc;
	int err, regoff, rid;

	sc = device_get_softc(dev);
	err = 0;

	/* Allocate bus_space resources. */
	rid = 0;
	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->mem_res == NULL) {
		device_printf(dev, "Cannot allocate memory resources\n");
		err = ENXIO;
		goto out;
	}

	/*
	 * XXX Totally lame way to get the unit number (but not quite as lame as
	 * adding an ad-hoc property to the fdt data).  This works as long as
	 * this driver is used for imx6 only.
	 */
	const uint32_t PWD_PHY1_REG_PHYSADDR = 0x020c9000;
	if (BUS_SPACE_PHYSADDR(sc->mem_res, 0) == PWD_PHY1_REG_PHYSADDR) {
		sc->phy_num = 0;
		regoff = 0;
	} else {
		sc->phy_num = 1;
		regoff = 0x60;
	}

	/*
	 * Based on a note in the u-boot source code, disable charger detection
	 * to avoid degrading the differential signaling on the DP line.  Note
	 * that this disables (by design) both charger detection and contact
	 * detection, because of the screwball mix of active-high and active-low
	 * bits in this register.
	 */
	imx6_anatop_write_4(IMX6_ANALOG_USB1_CHRG_DETECT + regoff, 
	    IMX6_ANALOG_USB_CHRG_DETECT_N_ENABLE | 
	    IMX6_ANALOG_USB_CHRG_DETECT_N_CHK_CHRG);

	imx6_anatop_write_4(IMX6_ANALOG_USB1_CHRG_DETECT + regoff, 
	    IMX6_ANALOG_USB_CHRG_DETECT_N_ENABLE | 
	    IMX6_ANALOG_USB_CHRG_DETECT_N_CHK_CHRG);

	/* XXX Configure the overcurrent detection here. */

	/*
	 * Turn on the phy clocks.
	 */
	imx_ccm_usbphy_enable(dev);

	/*
	 * Set the software reset bit, then clear both it and the clock gate bit
	 * to bring the device out of reset with the clock running.
	 */
	bus_write_4(sc->mem_res, CTRL_SET_REG, CTRL_SFTRST);
	bus_write_4(sc->mem_res, CTRL_CLR_REG, CTRL_SFTRST | CTRL_CLKGATE);

	/* Power up: clear all bits in the powerdown register. */
	bus_write_4(sc->mem_res, PWD_REG, 0);

	err = 0;

out:

	if (err != 0)
		usbphy_detach(dev);

	return (err);
}
コード例 #25
0
ファイル: digi_pci.c プロジェクト: ele7enxxh/dtrace-pf
static int
digi_pci_attach(device_t dev)
{
	struct digi_softc *sc;
	u_int32_t device_id;
#ifdef DIGI_INTERRUPT
	int retVal = 0;
#endif

	sc = device_get_softc(dev);
	KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n",
	    device_get_unit(dev)));

	bzero(sc, sizeof(*sc));
	sc->dev = dev;
	sc->res.unit = device_get_unit(dev);

	device_id = pci_get_devid(dev);
	switch (device_id >> 16) {
	case PCI_DEVICE_EPC:
		sc->name = "Digiboard PCI EPC/X ASIC";
		sc->res.mrid = 0x10;
		sc->model = PCIEPCX;
		sc->module = "EPCX_PCI";
		break;
	case PCI_DEVICE_XEM:
		sc->name = "Digiboard PCI PC/Xem ASIC";
		sc->res.mrid = 0x10;
		sc->model = PCXEM;
		sc->module = "Xem";
		break;
	case PCI_DEVICE_XR:
		sc->name = "Digiboard PCI PC/Xr ASIC";
		sc->res.mrid = 0x10;
		sc->model = PCIXR;
		sc->module = "Xr";
		break;
	case PCI_DEVICE_CX:
		sc->name = "Digiboard PCI C/X ASIC";
		sc->res.mrid = 0x10;
		sc->model = PCCX;
		sc->module = "CX_PCI";
		break;
	case PCI_DEVICE_XRJ:
		sc->name = "Digiboard PCI PC/Xr PLX";
		sc->res.mrid = 0x18;
		sc->model = PCIXR;
		sc->module = "Xr";
		break;
	case PCI_DEVICE_EPCJ:
		sc->name = "Digiboard PCI EPC/X PLX";
		sc->res.mrid = 0x18;
		sc->model = PCIEPCX;
		sc->module = "EPCX_PCI";
		break;
	case PCI_DEVICE_920_4:			/* Digi PCI4r 920 */
		sc->name = "Digiboard PCI4r 920";
		sc->res.mrid = 0x10;
		sc->model = PCIXR;
		sc->module = "Xr";
		break;
	case PCI_DEVICE_920_8:			/* Digi PCI8r 920 */
		sc->name = "Digiboard PCI8r 920";
		sc->res.mrid = 0x10;
		sc->model = PCIXR;
		sc->module = "Xr";
		break;
	case PCI_DEVICE_920_2:			/* Digi PCI2r 920 */
		sc->name = "Digiboard PCI2r 920";
		sc->res.mrid = 0x10;
		sc->model = PCIXR;
		sc->module = "Xr";
		break;
	default:
		device_printf(dev, "Unknown device id = %08x\n", device_id);
		return (ENXIO);
	}

	pci_write_config(dev, 0x40, 0, 4);
	pci_write_config(dev, 0x46, 0, 4);

	sc->res.mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->res.mrid,
	    RF_ACTIVE);

#ifdef DIGI_INTERRUPT
	sc->res.irqrid = 0;
	sc->res.irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->res.irqrid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->res.irq == NULL) {
		device_printf(dev, "couldn't map interrupt\n");
		return (ENXIO);
	}
	retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY,
	    digiintr, sc, &sc->res.irqHandler);
#else
	DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n"));
#endif

	sc->vmem = rman_get_virtual(sc->res.mem);
	sc->pmem = vtophys(sc->vmem);
	sc->pcibus = 1;
	sc->win_size = 0x200000;
	sc->win_bits = 21;
	sc->csigs = &digi_normal_signals;
	sc->status = DIGI_STATUS_NOTINIT;
	callout_handle_init(&sc->callout);
	callout_handle_init(&sc->inttest);
	sc->setwin = digi_pci_setwin;
	sc->hidewin = digi_pci_hidewin;
	sc->towin = digi_pci_towin;

	PCIPORT = FEPRST;

	return (digi_attach(sc));
}
コード例 #26
0
ファイル: ata-siliconimage.c プロジェクト: jamesbjackson/src
int
ata_sii_chipinit(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);

    if (ata_setup_interrupt(dev, ata_generic_intr))
	return ENXIO;

    switch (ctlr->chip->cfg1) {
    case SII_PRBIO:
	ctlr->r_type1 = SYS_RES_MEMORY;
	ctlr->r_rid1 = PCIR_BAR(0);
	if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
						    &ctlr->r_rid1, RF_ACTIVE)))
	    return ENXIO;

	ctlr->r_rid2 = PCIR_BAR(2);
	ctlr->r_type2 = SYS_RES_MEMORY;
	if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
						    &ctlr->r_rid2, RF_ACTIVE))){
	    bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
	    return ENXIO;
	}
#ifdef __sparc64__
	if (!bus_space_map(rman_get_bustag(ctlr->r_res2),
	    rman_get_bushandle(ctlr->r_res2), rman_get_size(ctlr->r_res2),
	    BUS_SPACE_MAP_LINEAR, NULL)) {
	    	bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,
		    ctlr->r_res1);
		bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2,
		    ctlr->r_res2);
		return (ENXIO);
	}
#endif
	ctlr->ch_attach = ata_siiprb_ch_attach;
	ctlr->ch_detach = ata_siiprb_ch_detach;
	ctlr->reset = ata_siiprb_reset;
	ctlr->setmode = ata_sata_setmode;
	ctlr->getrev = ata_sata_getrev;
	ctlr->channels = (ctlr->chip->cfg2 == SII_4CH) ? 4 : 2;

	/* reset controller */
	ATA_OUTL(ctlr->r_res1, 0x0040, 0x80000000);
	DELAY(10000);
	ATA_OUTL(ctlr->r_res1, 0x0040, 0x0000000f);
	break;

    case SII_MEMIO:
	ctlr->r_type2 = SYS_RES_MEMORY;
	ctlr->r_rid2 = PCIR_BAR(5);
	if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
						    &ctlr->r_rid2, RF_ACTIVE))){
	    if (ctlr->chip->chipid != ATA_SII0680 ||
			    (pci_read_config(dev, 0x8a, 1) & 1))
		return ENXIO;
	}

	if (ctlr->chip->cfg2 & SII_SETCLK) {
	    if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
		pci_write_config(dev, 0x8a,
				 (pci_read_config(dev, 0x8a, 1) & 0xcf)|0x10,1);
	    if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
		device_printf(dev, "%s could not set ATA133 clock\n",
			      ctlr->chip->text);
	}

	/* if we have 4 channels enable the second set */
	if (ctlr->chip->cfg2 & SII_4CH) {
	    ATA_OUTL(ctlr->r_res2, 0x0200, 0x00000002);
	    ctlr->channels = 4;
	}

	/* dont block interrupts from any channel */
	pci_write_config(dev, 0x48,
			 (pci_read_config(dev, 0x48, 4) & ~0x03c00000), 4);

	/* enable PCI interrupt as BIOS might not */
	pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);

	if (ctlr->r_res2) {
	    ctlr->ch_attach = ata_sii_ch_attach;
	    ctlr->ch_detach = ata_sii_ch_detach;
	}

	if (ctlr->chip->max_dma >= ATA_SA150) {
	    ctlr->reset = ata_sii_reset;
	    ctlr->setmode = ata_sata_setmode;
	    ctlr->getrev = ata_sata_getrev;
	}
	else
	    ctlr->setmode = ata_sii_setmode;
	break;
    
    default:
	if ((pci_read_config(dev, 0x51, 1) & 0x08) != 0x08) {
	    device_printf(dev, "HW has secondary channel disabled\n");
	    ctlr->channels = 1;
	}    

	/* enable interrupt as BIOS might not */
	pci_write_config(dev, 0x71, 0x01, 1);

	ctlr->ch_attach = ata_cmd_ch_attach;
	ctlr->ch_detach = ata_pci_ch_detach;
	ctlr->setmode = ata_cmd_setmode;
	break;
    }
    return 0;
}
コード例 #27
0
int
ppc_probe(device_t dev, int rid)
{
#ifdef __i386__
	static short next_bios_ppc = 0;
#ifdef PC98
	unsigned int pc98_ieee_mode = 0x00;
	unsigned int tmp;
#endif
#endif
	struct ppc_data *ppc;
	int error;
	rman_res_t port;

	/*
	 * Allocate the ppc_data structure.
	 */
	ppc = DEVTOSOFTC(dev);
	bzero(ppc, sizeof(struct ppc_data));

	ppc->rid_ioport = rid;

	/* retrieve ISA parameters */
	error = bus_get_resource(dev, SYS_RES_IOPORT, rid, &port, NULL);

#ifdef __i386__
	/*
	 * If port not specified, use bios list.
	 */
	if (error) {
#ifdef PC98
		if (next_bios_ppc == 0) {
			/* Use default IEEE-1284 port of NEC PC-98x1 */
			port = PC98_IEEE_1284_PORT;
			next_bios_ppc += 1;
			if (bootverbose)
				device_printf(dev,
				    "parallel port found at 0x%lx\n", port);
		}
#else
		if ((next_bios_ppc < BIOS_MAX_PPC) &&
		    (*(BIOS_PORTS + next_bios_ppc) != 0)) {
			port = *(BIOS_PORTS + next_bios_ppc++);
			if (bootverbose)
				device_printf(dev,
				    "parallel port found at 0x%lx\n", port);
		} else {
			device_printf(dev, "parallel port not found.\n");
			return (ENXIO);
		}
#endif	/* PC98 */
		bus_set_resource(dev, SYS_RES_IOPORT, rid, port,
				 IO_LPTSIZE_EXTENDED);
	}
#endif

	/* IO port is mandatory */

	/* Try "extended" IO port range...*/
	ppc->res_ioport = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
						      &ppc->rid_ioport,
						      IO_LPTSIZE_EXTENDED,
						      RF_ACTIVE);

	if (ppc->res_ioport != 0) {
		if (bootverbose)
			device_printf(dev, "using extended I/O port range\n");
	} else {
		/* Failed? If so, then try the "normal" IO port range... */
		 ppc->res_ioport = bus_alloc_resource_anywhere(dev,
		 	 				       SYS_RES_IOPORT,
							       &ppc->rid_ioport,
							       IO_LPTSIZE_NORMAL,
							       RF_ACTIVE);
		if (ppc->res_ioport != 0) {
			if (bootverbose)
				device_printf(dev, "using normal I/O port range\n");
		} else {
			device_printf(dev, "cannot reserve I/O port range\n");
			goto error;
		}
	}

 	ppc->ppc_base = rman_get_start(ppc->res_ioport);

	ppc->ppc_flags = device_get_flags(dev);

	if (!(ppc->ppc_flags & 0x20)) {
		ppc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
						      &ppc->rid_irq,
						      RF_SHAREABLE);
		ppc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
						      &ppc->rid_drq,
						      RF_ACTIVE);
	}

	if (ppc->res_irq)
		ppc->ppc_irq = rman_get_start(ppc->res_irq);
	if (ppc->res_drq)
		ppc->ppc_dmachan = rman_get_start(ppc->res_drq);

	ppc->ppc_dev = dev;
	ppc->ppc_model = GENERIC;

	ppc->ppc_mode = PPB_COMPATIBLE;
	ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4;

	ppc->ppc_type = PPC_TYPE_GENERIC;

#if defined(__i386__) && defined(PC98)
	/*
	 * IEEE STD 1284 Function Check and Enable
	 * for default IEEE-1284 port of NEC PC-98x1
	 */
	if (ppc->ppc_base == PC98_IEEE_1284_PORT &&
	    !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) {
		tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
		pc98_ieee_mode = tmp;
		if ((tmp & 0x10) == 0x10) {
			outb(ppc->ppc_base + PPC_1284_ENABLE, tmp & ~0x10);
			tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
			if ((tmp & 0x10) == 0x10)
				goto error;
		} else {
			outb(ppc->ppc_base + PPC_1284_ENABLE, tmp | 0x10);
			tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
			if ((tmp & 0x10) != 0x10)
				goto error;
		}
		outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode | 0x10);
	}
#endif

	/*
	 * Try to detect the chipset and its mode.
	 */
	if (ppc_detect(ppc, ppc->ppc_flags & 0xf))
		goto error;

	return (0);

error:
#if defined(__i386__) && defined(PC98)
	if (ppc->ppc_base == PC98_IEEE_1284_PORT &&
	    !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) {
		outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode);
	}
#endif
	if (ppc->res_irq != 0) {
		bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
				     ppc->res_irq);
	}
	if (ppc->res_ioport != 0) {
		bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
				     ppc->res_ioport);
	}
	if (ppc->res_drq != 0) {
		bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
				     ppc->res_drq);
	}
	return (ENXIO);
}
コード例 #28
0
ファイル: ehci_pci.c プロジェクト: AhmadTux/freebsd
static int
ehci_pci_attach(device_t self)
{
	ehci_softc_t *sc = device_get_softc(self);
	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;

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

	pci_enable_busmaster(self);

	switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) {
	case PCI_USB_REV_PRE_1_0:
	case PCI_USB_REV_1_0:
	case PCI_USB_REV_1_1:
		/*
		 * NOTE: some EHCI USB controllers have the wrong USB
		 * revision number. It appears those controllers are
		 * fully compliant so we just ignore this value in
		 * some common cases.
		 */
		device_printf(self, "pre-2.0 USB revision (ignored)\n");
		/* fallthrough */
	case PCI_USB_REV_2_0:
		break;
	default:
		/* Quirk for Parallels Desktop 4.0 */
		device_printf(self, "USB revision is unknown. Assuming v2.0.\n");
		break;
	}

	rid = PCI_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) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	/*
	 * ehci_pci_match will never return NULL if ehci_pci_probe
	 * succeeded
	 */
	device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self));
	switch (pci_get_vendor(self)) {
	case PCI_EHCI_VENDORID_ACERLABS:
		sprintf(sc->sc_vendor, "AcerLabs");
		break;
	case PCI_EHCI_VENDORID_AMD:
		sprintf(sc->sc_vendor, "AMD");
		break;
	case PCI_EHCI_VENDORID_APPLE:
		sprintf(sc->sc_vendor, "Apple");
		break;
	case PCI_EHCI_VENDORID_ATI:
		sprintf(sc->sc_vendor, "ATI");
		break;
	case PCI_EHCI_VENDORID_CMDTECH:
		sprintf(sc->sc_vendor, "CMDTECH");
		break;
	case PCI_EHCI_VENDORID_INTEL:
		sprintf(sc->sc_vendor, "Intel");
		break;
	case PCI_EHCI_VENDORID_NEC:
		sprintf(sc->sc_vendor, "NEC");
		break;
	case PCI_EHCI_VENDORID_OPTI:
		sprintf(sc->sc_vendor, "OPTi");
		break;
	case PCI_EHCI_VENDORID_PHILIPS:
		sprintf(sc->sc_vendor, "Philips");
		break;
	case PCI_EHCI_VENDORID_SIS:
		sprintf(sc->sc_vendor, "SiS");
		break;
	case PCI_EHCI_VENDORID_NVIDIA:
	case PCI_EHCI_VENDORID_NVIDIA2:
		sprintf(sc->sc_vendor, "nVidia");
		break;
	case PCI_EHCI_VENDORID_VIA:
		sprintf(sc->sc_vendor, "VIA");
		break;
	default:
		if (bootverbose)
			device_printf(self, "(New EHCI DeviceId=0x%08x)\n",
			    pci_get_devid(self));
		sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
	}

#if (__FreeBSD_version >= 700031)
	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);
#else
	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
	    (driver_intr_t *)ehci_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;
	}
	ehci_pci_take_controller(self);

	/* Undocumented quirks taken from Linux */

	switch (pci_get_vendor(self)) {
	case PCI_EHCI_VENDORID_ATI:
		/* SB600 and SB700 EHCI quirk */
		switch (pci_get_device(self)) {
		case 0x4386:
			ehci_pci_ati_quirk(self, 0);
			break;
		case 0x4396:
			ehci_pci_ati_quirk(self, 1);
			break;
		default:
			break;
		}
		break;

	case PCI_EHCI_VENDORID_VIA:
		ehci_pci_via_quirk(self);
		break;

	default:
		break;
	}

	/* Dropped interrupts workaround */
	switch (pci_get_vendor(self)) {
	case PCI_EHCI_VENDORID_ATI:
	case PCI_EHCI_VENDORID_VIA:
		sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
		if (bootverbose)
			device_printf(self,
			    "Dropped interrupts workaround enabled\n");
		break;
	default:
		break;
	}

	/* Doorbell feature workaround */
	switch (pci_get_vendor(self)) {
	case PCI_EHCI_VENDORID_NVIDIA:
	case PCI_EHCI_VENDORID_NVIDIA2:
		sc->sc_flags |= EHCI_SCFLG_IAADBUG;
		if (bootverbose)
			device_printf(self,
			    "Doorbell workaround enabled\n");
		break;
	default:
		break;
	}

	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_pci_detach(self);
	return (ENXIO);
}
コード例 #29
0
static int
dpt_isa_attach (device_t dev)
{
	dpt_softc_t *	dpt;
	int		error = 0;

	dpt = device_get_softc(dev);
	dpt->dev = dev;
	dpt_alloc(dev);

	dpt->io_rid = 0;
	dpt->io_type = SYS_RES_IOPORT;
	dpt->irq_rid = 0;

	error = dpt_alloc_resources(dev);
	if (error) {
		goto bad;
	}

	dpt->drq_rid = 0;
	dpt->drq_res = bus_alloc_resource_any(dev, SYS_RES_DRQ, &dpt->drq_rid,
					RF_ACTIVE);
	if (!dpt->drq_res) {
		device_printf(dev, "No DRQ!\n");
		error = ENOMEM;
		goto bad;
	}
	isa_dma_acquire(rman_get_start(dpt->drq_res));
	isa_dmacascade(rman_get_start(dpt->drq_res));

	/* Allocate a dmatag representing the capabilities of this attachment */
	if (bus_dma_tag_create( /* parent    */	bus_get_dma_tag(dev),
				/* alignemnt */	1,
				/* boundary  */	0,
				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
				/* highaddr  */	BUS_SPACE_MAXADDR,
				/* filter    */	NULL,
				/* filterarg */	NULL,
				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
				/* nsegments */	~0,
				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
				/* flags     */	0,
				/* lockfunc  */ NULL,
				/* lockarg   */ NULL,
				&dpt->parent_dmat) != 0) {
		error = ENXIO;
		goto bad;
	}

	if (dpt_init(dpt) != 0) {
		error = ENXIO;
		goto bad;
	}

	/* Register with the XPT */
	dpt_attach(dpt);

	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY |
	    INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) {
		device_printf(dev, "Unable to register interrupt handler\n");
		error = ENXIO;
		goto bad;
	}

	return (error);

 bad:
	if (dpt->drq_res) {
		isa_dma_release(rman_get_start(dpt->drq_res));
	}

	dpt_release_resources(dev);

	if (dpt)
		dpt_free(dpt);

	return (error);
}
コード例 #30
0
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);
}