Пример #1
0
static int
fdt_localbus_reg_decode(phandle_t node, struct localbus_softc *sc,
    struct localbus_devinfo *di)
{
	u_long start, end, count;
	pcell_t *reg, *regptr;
	pcell_t addr_cells, size_cells;
	int tuple_size, tuples;
	int i, rv, bank;

	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
		return (ENXIO);

	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
	tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
	debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
	debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
	if (tuples <= 0)
		/* No 'reg' property in this node. */
		return (0);

	regptr = reg;
	for (i = 0; i < tuples; i++) {

		bank = fdt_data_get((void *)regptr, 1);

		if (bank >= MV_LOCALBUS_MAX_BANKS) {
			device_printf(sc->sc_dev, "bank number [%d] out of "
			    "range\n", bank);
			continue;
		}

		/*
		 * If device doesn't have virtual to physical mapping don't add
		 * resources
		 */
		if (!(sc->sc_banks[bank].mapped)) {
			device_printf(sc->sc_dev, "device [%d]: missing memory "
			    "mapping\n", bank);
			continue;
		}

		di->di_bank = bank;
		regptr += 1;

		/* Get address/size. */
		rv = fdt_data_to_res(regptr, addr_cells - 1, size_cells, &start,
		    &count);
		if (rv != 0) {
			resource_list_free(&di->di_res);
			goto out;
		}

		/* Check if enough amount of memory is mapped */
		if (sc->sc_banks[bank].size < count) {
			device_printf(sc->sc_dev, "device [%d]: not enough "
			    "memory reserved\n", bank);
			continue;
		}

		regptr += addr_cells - 1 + size_cells;

		/* Calculate address range relative to VA base. */
		start = sc->sc_banks[bank].va + start;
		end = start + count - 1;

		debugf("reg addr bank = %d, start = %lx, end = %lx, "
		    "count = %lx\n", bank, start, end, count);

		/* Use bank (CS) cell as rid. */
		resource_list_add(&di->di_res, SYS_RES_MEMORY, di->di_bank,
		    start, end, count);
	}
	rv = 0;
out:
	free(reg, M_OFWPROP);
	return (rv);
}
Пример #2
0
static int
usie_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
	struct usie_softc *sc = ifp->if_softc;
	struct ieee80211req *ireq;
	struct ieee80211req_sta_info si;
	struct ifmediareq *ifmr;

	switch (cmd) {
	case SIOCSIFFLAGS:
		if (ifp->if_flags & IFF_UP) {
			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
				usie_if_init(sc);
		} else {
			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
				usie_if_stop(sc);
		}
		break;

	case SIOCSIFCAP:
		if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
			device_printf(sc->sc_dev,
			    "Connect to the network first.\n");
			break;
		}
		mtx_lock(&sc->sc_mtx);
		usie_cns_req(sc, USIE_CNS_ID_RSSI, USIE_CNS_OB_RSSI);
		mtx_unlock(&sc->sc_mtx);
		break;

	case SIOCG80211:
		ireq = (struct ieee80211req *)data;

		if (ireq->i_type != IEEE80211_IOC_STA_INFO)
			break;

		memset(&si, 0, sizeof(si));
		si.isi_len = sizeof(si);
		/*
		 * ifconfig expects RSSI in 0.5dBm units
		 * relative to the noise floor.
		 */
		si.isi_rssi = 2 * sc->sc_rssi;
		if (copyout(&si, (uint8_t *)ireq->i_data + 8,
		    sizeof(struct ieee80211req_sta_info)))
			DPRINTF("copyout failed\n");
		DPRINTF("80211\n");
		break;

	case SIOCGIFMEDIA:		/* to fool ifconfig */
		ifmr = (struct ifmediareq *)data;
		ifmr->ifm_count = 1;
		DPRINTF("media\n");
		break;

	case SIOCSIFADDR:
		break;

	default:
		return (EINVAL);
	}
	return (0);
}
Пример #3
0
int
cfi_attach(device_t dev)
{
    struct cfi_softc *sc;
    u_int blksz, blocks;
    u_int r, u;

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

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

    sc->sc_tag = rman_get_bustag(sc->sc_res);
    sc->sc_handle = rman_get_bushandle(sc->sc_res);

    /* Get time-out values for erase and write. */
    sc->sc_write_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_WRITE);
    sc->sc_erase_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_ERASE);
    sc->sc_write_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_WRITE);
    sc->sc_erase_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_ERASE);

    /* Get erase regions. */
    sc->sc_regions = cfi_read_qry(sc, CFI_QRY_NREGIONS);
    sc->sc_region = malloc(sc->sc_regions * sizeof(struct cfi_region),
                           M_TEMP, M_WAITOK | M_ZERO);
    for (r = 0; r < sc->sc_regions; r++) {
        blocks = cfi_read_qry(sc, CFI_QRY_REGION(r)) |
                 (cfi_read_qry(sc, CFI_QRY_REGION(r) + 1) << 8);
        sc->sc_region[r].r_blocks = blocks + 1;

        blksz = cfi_read_qry(sc, CFI_QRY_REGION(r) + 2) |
                (cfi_read_qry(sc, CFI_QRY_REGION(r) + 3) << 8);
        sc->sc_region[r].r_blksz = (blksz == 0) ? 128 :
                                   blksz * 256;
    }

    /* Reset the device to a default state. */
    cfi_write(sc, 0, CFI_BCS_CLEAR_STATUS);

    if (bootverbose) {
        device_printf(dev, "[");
        for (r = 0; r < sc->sc_regions; r++) {
            printf("%ux%s%s", sc->sc_region[r].r_blocks,
                   cfi_fmtsize(sc->sc_region[r].r_blksz),
                   (r == sc->sc_regions - 1) ? "]\n" : ",");
        }
    }

    u = device_get_unit(dev);
    sc->sc_nod = make_dev(&cfi_cdevsw, u, UID_ROOT, GID_WHEEL, 0600,
                          "%s%u", cfi_driver_name, u);
    sc->sc_nod->si_drv1 = sc;

    device_add_child(dev, "cfid", -1);
    bus_generic_attach(dev);

    return (0);
}
Пример #4
0
void
acpi_install_wakeup_handler(struct acpi_softc *sc)
{
	static void	*wakeaddr = NULL;
#ifdef __amd64__
	uint64_t	*pt4, *pt3, *pt2;
	int		i;
#endif

	if (wakeaddr != NULL)
		return;

	wakeaddr = acpi_alloc_wakeup_handler();
	if (wakeaddr == NULL)
		return;

	sc->acpi_wakeaddr = (vm_offset_t)wakeaddr;
	sc->acpi_wakephys = vtophys(wakeaddr);

	bcopy(wakecode, (void *)WAKECODE_VADDR(sc), sizeof(wakecode));

	/* Patch GDT base address, ljmp targets. */
	WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t,
	    WAKECODE_PADDR(sc) + bootgdt);
	WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t,
	    WAKECODE_PADDR(sc) + wakeup_32);
#ifdef __amd64__
	WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
	    WAKECODE_PADDR(sc) + wakeup_64);
	WAKECODE_FIXUP(wakeup_pagetables, uint32_t, sc->acpi_wakephys);
#endif

	/* Save pointers to some global data. */
	WAKECODE_FIXUP(wakeup_ret, void *, resumectx);
#ifndef __amd64__
#if defined(PAE) || defined(PAE_TABLES)
	WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdpt));
#else
	WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdir));
#endif

#else
	/* Build temporary page tables below realmode code. */
	pt4 = wakeaddr;
	pt3 = pt4 + (PAGE_SIZE) / sizeof(uint64_t);
	pt2 = pt3 + (PAGE_SIZE) / sizeof(uint64_t);

	/* Create the initial 1GB replicated page tables */
	for (i = 0; i < 512; i++) {
		/*
		 * Each slot of the level 4 pages points
		 * to the same level 3 page
		 */
		pt4[i] = (uint64_t)(sc->acpi_wakephys + PAGE_SIZE);
		pt4[i] |= PG_V | PG_RW | PG_U;

		/*
		 * Each slot of the level 3 pages points
		 * to the same level 2 page
		 */
		pt3[i] = (uint64_t)(sc->acpi_wakephys + (2 * PAGE_SIZE));
		pt3[i] |= PG_V | PG_RW | PG_U;

		/* The level 2 page slots are mapped with 2MB pages for 1GB. */
		pt2[i] = i * (2 * 1024 * 1024);
		pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
	}
#endif

	if (bootverbose)
		device_printf(sc->acpi_dev, "wakeup code va %#jx pa %#jx\n",
		    (uintmax_t)sc->acpi_wakeaddr, (uintmax_t)sc->acpi_wakephys);
}
Пример #5
0
static int
nf10bmac_attach_fdt(device_t dev)
{
	struct nf10bmac_softc *sc;
	int error;

	sc = device_get_softc(dev);
	sc->nf10bmac_dev = dev;
	sc->nf10bmac_unit = device_get_unit(dev);

	/*
	 * FDT lists our resources.  For convenience we use three different
	 * mappings.  We need to attach them in the oder specified in .dts:
	 * LOOP (size 0x1f), TX (0x2f), RX (0x2f), INTR (0xf).
	 */

	/*
	 * LOOP memory region (this could be a general control region).
	 * 0x00: 32/64bit register to enable a Y-"lopback".
	 */
        sc->nf10bmac_ctrl_rid = 0;
        sc->nf10bmac_ctrl_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
            &sc->nf10bmac_ctrl_rid, RF_ACTIVE);
        if (sc->nf10bmac_ctrl_res == NULL) {
                device_printf(dev, "failed to map memory for CTRL region\n");
                error = ENXIO;
                goto err;
        } 
        if (bootverbose)
                device_printf(sc->nf10bmac_dev, "CTRL region at mem %p-%p\n",
                    (void *)rman_get_start(sc->nf10bmac_ctrl_res),
                    (void *)(rman_get_start(sc->nf10bmac_ctrl_res) + 
                    rman_get_size(sc->nf10bmac_ctrl_res)));

        /*
         * TX and TX metadata FIFO memory region.
         * 0x00: 32/64bit FIFO data,
	 * 0x08: 32/64bit FIFO metadata,
         * 0x10: 32/64bit packet length.
         */
        sc->nf10bmac_tx_mem_rid = 1;
        sc->nf10bmac_tx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
            &sc->nf10bmac_tx_mem_rid, RF_ACTIVE);
        if (sc->nf10bmac_tx_mem_res == NULL) {
                device_printf(dev, "failed to map memory for TX FIFO\n");
                error = ENXIO;
                goto err;
        }
        if (bootverbose)
                device_printf(sc->nf10bmac_dev, "TX FIFO at mem %p-%p\n",
                    (void *)rman_get_start(sc->nf10bmac_tx_mem_res),
                    (void *)(rman_get_start(sc->nf10bmac_tx_mem_res) +
                    rman_get_size(sc->nf10bmac_tx_mem_res)));

        /*
         * RX and RXC metadata FIFO memory region.
         * 0x00: 32/64bit FIFO data,
	 * 0x08: 32/64bit FIFO metadata,
         * 0x10: 32/64bit packet length.
         */
        sc->nf10bmac_rx_mem_rid = 2;
        sc->nf10bmac_rx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
            &sc->nf10bmac_rx_mem_rid, RF_ACTIVE);
        if (sc->nf10bmac_rx_mem_res == NULL) {
                device_printf(dev, "failed to map memory for RX FIFO\n");
                error = ENXIO;
                goto err;
        } 
        if (bootverbose)
                device_printf(sc->nf10bmac_dev, "RX FIFO at mem %p-%p\n",
                    (void *)rman_get_start(sc->nf10bmac_rx_mem_res),
                    (void *)(rman_get_start(sc->nf10bmac_rx_mem_res) + 
                    rman_get_size(sc->nf10bmac_rx_mem_res)));

	/*
	 * Interrupt handling registers.
	 * 0x00: 32/64bit register to clear (and disable) the RX interrupt.
	 * 0x08: 32/64bit register to enable or disable the RX interrupt.
	 */
        sc->nf10bmac_intr_rid = 3;
        sc->nf10bmac_intr_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
            &sc->nf10bmac_intr_rid, RF_ACTIVE);
        if (sc->nf10bmac_intr_res == NULL) {
                device_printf(dev, "failed to map memory for INTR region\n");
                error = ENXIO;
                goto err;
        } 
        if (bootverbose)
                device_printf(sc->nf10bmac_dev, "INTR region at mem %p-%p\n",
                    (void *)rman_get_start(sc->nf10bmac_intr_res),
                    (void *)(rman_get_start(sc->nf10bmac_intr_res) + 
                    rman_get_size(sc->nf10bmac_intr_res)));

	/* (Optional) RX and TX IRQ. */
	sc->nf10bmac_rx_irq_rid = 0;
	sc->nf10bmac_rx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &sc->nf10bmac_rx_irq_rid, RF_ACTIVE | RF_SHAREABLE);

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

	return (0);

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

	return (error);
}
Пример #6
0
static int
aw_usbclk_attach(device_t dev)
{
	struct aw_usbclk_softc *sc;
	struct clkdom *clkdom;
	const char **names;
	int index, nout, error;
	enum aw_usbclk_type type;
	uint32_t *indices;
	clk_t clk_parent;
	bus_size_t psize;
	phandle_t node;

	sc = device_get_softc(dev);
	node = ofw_bus_get_node(dev);
	indices = NULL;
	type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;

	if (ofw_reg_to_paddr(node, 0, &sc->reg, &psize, NULL) != 0) {
		device_printf(dev, "cannot parse 'reg' property\n");
		return (ENXIO);
	}

	clkdom = clkdom_create(dev);

	nout = clk_parse_ofw_out_names(dev, node, &names, &indices);
	if (nout == 0) {
		device_printf(dev, "no clock outputs found\n");
		error = ENOENT;
		goto fail;
	}

	if (indices == NULL && type == AW_A10_USBCLK)
		indices = aw_usbclk_indices_a10;

	error = clk_get_by_ofw_index(dev, 0, &clk_parent);
	if (error != 0) {
		device_printf(dev, "cannot parse clock parent\n");
		return (ENXIO);
	}

	for (index = 0; index < nout; index++) {
		error = aw_usbclk_create(dev, sc->reg, clkdom,
		    clk_get_name(clk_parent), names[index],
		    indices != NULL ? indices[index] : index);
		if (error)
			goto fail;
	}

	if (clkdom_finit(clkdom) != 0) {
		device_printf(dev, "cannot finalize clkdom initialization\n");
		error = ENXIO;
		goto fail;
	}

	if (bootverbose)
		clkdom_dump(clkdom);

	hwreset_register_ofw_provider(dev);

	return (0);

fail:
	return (error);
}
Пример #7
0
static int
le_dma_attach(device_t dev)
{
	struct le_dma_softc *lesc;
	struct lsi64854_softc *dma;
	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));

	/*
	 * Establish link to `ledma' device.
	 * XXX hackery.
	 */
	dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev));
	lesc->sc_dma = dma;
	lesc->sc_dma->sc_client = lesc;

	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 registers\n");
		error = ENXIO;
		goto fail_mtx;
	}

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

	/* Attach the DMA engine. */
	error = lsi64854_attach(dma);
	if (error != 0) {
		device_printf(dev, "lsi64854_attach failed\n");
		goto fail_ires;
	}

	sc->sc_memsize = LEDMA_MEMSIZE;
	error = bus_dma_tag_create(
	    dma->sc_parent_dmat,	/* parent */
	    LEDMA_ALIGNMENT,		/* alignment */
	    LEDMA_BOUNDARY,		/* boundary */
	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    sc->sc_memsize,		/* maxsize */
	    1,				/* nsegments */
	    sc->sc_memsize,		/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &lesc->sc_dmat);
	if (error != 0) {
		device_printf(dev, "cannot allocate buffer DMA tag\n");
		goto fail_lsi;
	}

	error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
	    BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
	if (error != 0) {
		device_printf(dev, "cannot allocate DMA buffer memory\n");
		goto fail_dtag;
	}

	lesc->sc_laddr = 0;
	error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
	    sc->sc_memsize, le_dma_dma_callback, lesc, 0);
	if (error != 0 || lesc->sc_laddr == 0) {
		device_printf(dev, "cannot load DMA buffer map\n");
		goto fail_dmem;
	}

	sc->sc_addr = lesc->sc_laddr & 0xffffff;
	sc->sc_flags = 0;
	sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;

	sc->sc_mediachange = le_dma_supmediachange;
	sc->sc_mediastatus = le_dma_supmediastatus;
	sc->sc_supmedia = le_dma_supmedia;
	sc->sc_nsupmedia = nitems(le_dma_supmedia);
	sc->sc_defaultmedia = le_dma_supmedia[0];

	OF_getetheraddr(dev, sc->sc_enaddr);

	sc->sc_copytodesc = lance_copytobuf_contig;
	sc->sc_copyfromdesc = lance_copyfrombuf_contig;
	sc->sc_copytobuf = lance_copytobuf_contig;
	sc->sc_copyfrombuf = lance_copyfrombuf_contig;
	sc->sc_zerobuf = lance_zerobuf_contig;

	sc->sc_rdcsr = le_dma_rdcsr;
	sc->sc_wrcsr = le_dma_wrcsr;
	sc->sc_hwreset = le_dma_hwreset;
	sc->sc_hwintr = le_dma_hwintr;
	sc->sc_nocarrier = le_dma_nocarrier;

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

	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_dmap:
	bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
 fail_dmem:
	bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
 fail_dtag:
	bus_dma_tag_destroy(lesc->sc_dmat);
 fail_lsi:
	lsi64854_detach(dma);
 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_mtx:
	LE_LOCK_DESTROY(sc);
	return (error);
}
Пример #8
0
/*
 * The probe routine.
 */
static int
fwohci_pci_probe( device_t dev )
{
	uint32_t id;

	id = pci_get_devid(dev);
	if (id == (FW_VENDORID_NATSEMI | FW_DEVICE_CS4210)) {
		device_set_desc(dev, "National Semiconductor CS4210");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) {
		device_set_desc(dev, "NEC uPD72861");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD871)) {
		device_set_desc(dev, "NEC uPD72871/2");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72870)) {
		device_set_desc(dev, "NEC uPD72870");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72873)) {
		device_set_desc(dev, "NEC uPD72873");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72874)) {
		device_set_desc(dev, "NEC uPD72874");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_SIS | FW_DEVICE_7007)) {
		/* It has no real identifier, using device id. */
		device_set_desc(dev, "SiS 7007");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) {
		device_set_desc(dev, "Texas Instruments TSB12LV22");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) {
		device_set_desc(dev, "Texas Instruments TSB12LV23");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) {
		device_set_desc(dev, "Texas Instruments TSB12LV26");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) {
		device_set_desc(dev, "Texas Instruments TSB43AA22");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) {
		device_set_desc(dev, "Texas Instruments TSB43AB22/A");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB21)) {
		device_set_desc(dev, "Texas Instruments TSB43AB21/A/AI/A-EP");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB23)) {
		device_set_desc(dev, "Texas Instruments TSB43AB23");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB82AA2)) {
		device_set_desc(dev, "Texas Instruments TSB82AA2");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) {
		device_set_desc(dev, "Texas Instruments PCI4450");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) {
		device_set_desc(dev, "Texas Instruments PCI4410A");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4451)) {
		device_set_desc(dev, "Texas Instruments PCI4451");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD1947)) {
		device_printf(dev, "Sony i.LINK (CXD1947) not supported\n");
		return ENXIO;
	}
	if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD3222)) {
		device_set_desc(dev, "Sony i.LINK (CXD3222)");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) {
		device_set_desc(dev, "VIA Fire II (VT6306)");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C551)) {
		device_set_desc(dev, "Ricoh R5C551");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) {
		device_set_desc(dev, "Ricoh R5C552");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) {
		device_set_desc(dev, "Apple Pangea");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH)) {
		device_set_desc(dev, "Apple UniNorth");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) {
		device_set_desc(dev, "Lucent FW322/323");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_INTEL | FW_DEVICE_82372FB)) {
		device_set_desc(dev, "Intel 82372FB");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_ADAPTEC | FW_DEVICE_AIC5800)) {
		device_set_desc(dev, "Adaptec AHA-894x/AIC-5800");
		return BUS_PROBE_DEFAULT;
	}
	if (id == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW)) {
		device_set_desc(dev, "Sun PCIO-2");
		return BUS_PROBE_DEFAULT;
	}
	if (pci_get_class(dev) == PCIC_SERIALBUS
			&& pci_get_subclass(dev) == PCIS_SERIALBUS_FW
			&& pci_get_progif(dev) == PCI_INTERFACE_OHCI) {
		if (bootverbose)
			device_printf(dev, "vendor=%x, dev=%x\n",
			    pci_get_vendor(dev), pci_get_device(dev));
		device_set_desc(dev, "1394 Open Host Controller Interface");
		return BUS_PROBE_DEFAULT;
	}

	return ENXIO;
}
Пример #9
0
/*
 * Install interface into kernel networking data structures
 */
int
ed_attach(device_t dev)
{
	struct ed_softc *sc = device_get_softc(dev);
	struct ifnet *ifp;

	sc->dev = dev;
	ED_LOCK_INIT(sc);
	ifp = sc->ifp = if_alloc(IFT_ETHER);
	if (ifp == NULL) {
		device_printf(dev, "can not if_alloc()\n");
		ED_LOCK_DESTROY(sc);
		return (ENOSPC);
	}

	if (sc->readmem == NULL) {
		if (sc->mem_shared) {
			if (sc->isa16bit)
				sc->readmem = ed_shmem_readmem16;
			else
				sc->readmem = ed_shmem_readmem8;
		} else {
			sc->readmem = ed_pio_readmem;
		}
	}
	if (sc->sc_write_mbufs == NULL) {
		device_printf(dev, "No write mbufs routine set\n");
		return (ENXIO);
	}

	callout_init_mtx(&sc->tick_ch, ED_MUTEX(sc), 0);
	/*
	 * Set interface to stopped condition (reset)
	 */
	ed_stop_hw(sc);

	/*
	 * Initialize ifnet structure
	 */
	ifp->if_softc = sc;
	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
	ifp->if_start = ed_start;
	ifp->if_ioctl = ed_ioctl;
	ifp->if_init = ed_init;
	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
	IFQ_SET_READY(&ifp->if_snd);
	ifp->if_linkmib = &sc->mibdata;
	ifp->if_linkmiblen = sizeof sc->mibdata;
	/*
	 * XXX - should do a better job.
	 */
	if (sc->chip_type == ED_CHIP_TYPE_WD790)
		sc->mibdata.dot3StatsEtherChipSet =
			DOT3CHIPSET(dot3VendorWesternDigital,
				    dot3ChipSetWesternDigital83C790);
	else
		sc->mibdata.dot3StatsEtherChipSet =
			DOT3CHIPSET(dot3VendorNational, 
				    dot3ChipSetNational8390);
	sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS;

	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
	/*
	 * Set default state for LINK2 flag (used to disable the 
	 * tranceiver for AUI operation), based on config option.
	 * We only set this flag before we attach the device, so there's
	 * no race.  It is convenient to allow users to turn this off
	 * by default in the kernel config, but given our more advanced
	 * boot time configuration options, this might no longer be needed.
	 */
	if (device_get_flags(dev) & ED_FLAGS_DISABLE_TRANCEIVER)
		ifp->if_flags |= IFF_LINK2;

	/*
	 * Attach the interface
	 */
	ether_ifattach(ifp, sc->enaddr);
	/* device attach does transition from UNCONFIGURED to IDLE state */

	sc->tx_mem = sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
	sc->rx_mem = (sc->rec_page_stop - sc->rec_page_start) * ED_PAGE_SIZE;
	SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev),
	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
	    0, "type", CTLFLAG_RD, sc->type_str, 0,
	    "Type of chip in card");
	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
	    1, "TxMem", CTLFLAG_RD, &sc->tx_mem, 0,
	    "Memory set aside for transmitting packets");
	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
	    2, "RxMem", CTLFLAG_RD, &sc->rx_mem, 0,
	    "Memory  set aside for receiving packets");
	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
	    3, "Mem", CTLFLAG_RD, &sc->mem_size, 0,
	    "Total Card Memory");
	if (bootverbose) {
		if (sc->type_str && (*sc->type_str != 0))
			device_printf(dev, "type %s ", sc->type_str);
		else
			device_printf(dev, "type unknown (0x%x) ", sc->type);

#ifdef ED_HPP
		if (sc->vendor == ED_VENDOR_HP)
			printf("(%s %s IO)",
			    (sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS) ?
			    "16-bit" : "32-bit",
			    sc->hpp_mem_start ? "memory mapped" : "regular");
		else
#endif
			printf("%s", sc->isa16bit ? "(16 bit)" : "(8 bit)");

#if defined(ED_HPP) || defined(ED_3C503)
		printf("%s", (((sc->vendor == ED_VENDOR_3COM) ||
				    (sc->vendor == ED_VENDOR_HP)) &&
			   (ifp->if_flags & IFF_LINK2)) ?
		    " tranceiver disabled" : "");
#endif
		printf("\n");
	}
	return (0);
}
Пример #10
0
static int
kr_dma_alloc(struct kr_softc *sc)
{
	struct kr_dmamap_arg	ctx;
	struct kr_txdesc	*txd;
	struct kr_rxdesc	*rxd;
	int			error, i;

	/* Create parent DMA tag. */
	error = bus_dma_tag_create(
	    bus_get_dma_tag(sc->kr_dev),	/* parent */
	    1, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR_32BIT,	/* 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,			/* lockfunc, lockarg */
	    &sc->kr_cdata.kr_parent_tag);
	if (error != 0) {
		device_printf(sc->kr_dev, "failed to create parent DMA tag\n");
		goto fail;
	}
	/* Create tag for Tx ring. */
	error = bus_dma_tag_create(
	    sc->kr_cdata.kr_parent_tag,	/* parent */
	    KR_RING_ALIGN, 0,		/* alignment, boundary */
	    BUS_SPACE_MAXADDR,		/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    KR_TX_RING_SIZE,		/* maxsize */
	    1,				/* nsegments */
	    KR_TX_RING_SIZE,		/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->kr_cdata.kr_tx_ring_tag);
	if (error != 0) {
		device_printf(sc->kr_dev, "failed to create Tx ring DMA tag\n");
		goto fail;
	}

	/* Create tag for Rx ring. */
	error = bus_dma_tag_create(
	    sc->kr_cdata.kr_parent_tag,	/* parent */
	    KR_RING_ALIGN, 0,		/* alignment, boundary */
	    BUS_SPACE_MAXADDR,		/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    KR_RX_RING_SIZE,		/* maxsize */
	    1,				/* nsegments */
	    KR_RX_RING_SIZE,		/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->kr_cdata.kr_rx_ring_tag);
	if (error != 0) {
		device_printf(sc->kr_dev, "failed to create Rx ring DMA tag\n");
		goto fail;
	}

	/* Create tag for Tx buffers. */
	error = bus_dma_tag_create(
	    sc->kr_cdata.kr_parent_tag,	/* parent */
	    sizeof(uint32_t), 0,	/* alignment, boundary */
	    BUS_SPACE_MAXADDR,		/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    MCLBYTES * KR_MAXFRAGS,	/* maxsize */
	    KR_MAXFRAGS,		/* nsegments */
	    MCLBYTES,			/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->kr_cdata.kr_tx_tag);
	if (error != 0) {
		device_printf(sc->kr_dev, "failed to create Tx DMA tag\n");
		goto fail;
	}

	/* Create tag for Rx buffers. */
	error = bus_dma_tag_create(
	    sc->kr_cdata.kr_parent_tag,	/* parent */
	    KR_RX_ALIGN, 0,		/* alignment, boundary */
	    BUS_SPACE_MAXADDR,		/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    MCLBYTES,			/* maxsize */
	    1,				/* nsegments */
	    MCLBYTES,			/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->kr_cdata.kr_rx_tag);
	if (error != 0) {
		device_printf(sc->kr_dev, "failed to create Rx DMA tag\n");
		goto fail;
	}

	/* Allocate DMA'able memory and load the DMA map for Tx ring. */
	error = bus_dmamem_alloc(sc->kr_cdata.kr_tx_ring_tag,
	    (void **)&sc->kr_rdata.kr_tx_ring, BUS_DMA_WAITOK |
	    BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->kr_cdata.kr_tx_ring_map);
	if (error != 0) {
		device_printf(sc->kr_dev,
		    "failed to allocate DMA'able memory for Tx ring\n");
		goto fail;
	}

	ctx.kr_busaddr = 0;
	error = bus_dmamap_load(sc->kr_cdata.kr_tx_ring_tag,
	    sc->kr_cdata.kr_tx_ring_map, sc->kr_rdata.kr_tx_ring,
	    KR_TX_RING_SIZE, kr_dmamap_cb, &ctx, 0);
	if (error != 0 || ctx.kr_busaddr == 0) {
		device_printf(sc->kr_dev,
		    "failed to load DMA'able memory for Tx ring\n");
		goto fail;
	}
	sc->kr_rdata.kr_tx_ring_paddr = ctx.kr_busaddr;

	/* Allocate DMA'able memory and load the DMA map for Rx ring. */
	error = bus_dmamem_alloc(sc->kr_cdata.kr_rx_ring_tag,
	    (void **)&sc->kr_rdata.kr_rx_ring, BUS_DMA_WAITOK |
	    BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->kr_cdata.kr_rx_ring_map);
	if (error != 0) {
		device_printf(sc->kr_dev,
		    "failed to allocate DMA'able memory for Rx ring\n");
		goto fail;
	}

	ctx.kr_busaddr = 0;
	error = bus_dmamap_load(sc->kr_cdata.kr_rx_ring_tag,
	    sc->kr_cdata.kr_rx_ring_map, sc->kr_rdata.kr_rx_ring,
	    KR_RX_RING_SIZE, kr_dmamap_cb, &ctx, 0);
	if (error != 0 || ctx.kr_busaddr == 0) {
		device_printf(sc->kr_dev,
		    "failed to load DMA'able memory for Rx ring\n");
		goto fail;
	}
	sc->kr_rdata.kr_rx_ring_paddr = ctx.kr_busaddr;

	/* Create DMA maps for Tx buffers. */
	for (i = 0; i < KR_TX_RING_CNT; i++) {
		txd = &sc->kr_cdata.kr_txdesc[i];
		txd->tx_m = NULL;
		txd->tx_dmamap = NULL;
		error = bus_dmamap_create(sc->kr_cdata.kr_tx_tag, 0,
		    &txd->tx_dmamap);
		if (error != 0) {
			device_printf(sc->kr_dev,
			    "failed to create Tx dmamap\n");
			goto fail;
		}
	}
	/* Create DMA maps for Rx buffers. */
	if ((error = bus_dmamap_create(sc->kr_cdata.kr_rx_tag, 0,
	    &sc->kr_cdata.kr_rx_sparemap)) != 0) {
		device_printf(sc->kr_dev,
		    "failed to create spare Rx dmamap\n");
		goto fail;
	}
	for (i = 0; i < KR_RX_RING_CNT; i++) {
		rxd = &sc->kr_cdata.kr_rxdesc[i];
		rxd->rx_m = NULL;
		rxd->rx_dmamap = NULL;
		error = bus_dmamap_create(sc->kr_cdata.kr_rx_tag, 0,
		    &rxd->rx_dmamap);
		if (error != 0) {
			device_printf(sc->kr_dev,
			    "failed to create Rx dmamap\n");
			goto fail;
		}
	}

fail:
	return (error);
}
Пример #11
0
static int
fwohci_pci_attach(device_t self)
{
	fwohci_softc_t *sc = device_get_softc(self);
	int err;
	int rid;

#if 0
	if (bootverbose)
		firewire_debug = bootverbose;
#endif

	mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF);
	fwohci_pci_init(self);

	rid = PCI_CBMEM;
	sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
	if (!sc->bsr) {
		device_printf(self, "Could not map memory\n");
		return ENXIO;
        }

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

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

	err = bus_setup_intr(self, sc->irq_res,
				INTR_TYPE_NET | INTR_MPSAFE,
				NULL, (driver_intr_t *) fwohci_intr,
				sc, &sc->ih);

	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		fwohci_pci_detach(self);
		return ENXIO;
	}

	err = bus_dma_tag_create(
				/*parent*/bus_get_dma_tag(self),
				/*alignment*/1,
				/*boundary*/0,
#if BOUNCE_BUFFER_TEST
				/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
#else
				/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
#endif
				/*highaddr*/BUS_SPACE_MAXADDR,
				/*filter*/NULL, /*filterarg*/NULL,
				/*maxsize*/0x100000,
				/*nsegments*/0x20,
				/*maxsegsz*/0x8000,
				/*flags*/BUS_DMA_ALLOCNOW,
				/*lockfunc*/busdma_lock_mutex,
				/*lockarg*/FW_GMTX(&sc->fc),
				&sc->fc.dmat);
	if (err != 0) {
		printf("fwohci_pci_attach: Could not allocate DMA tag "
			"- error %d\n", err);
			return (ENOMEM);
	}

	err = fwohci_init(sc, self);

	if (err) {
		device_printf(self, "fwohci_init failed with err=%d\n", err);
		fwohci_pci_detach(self);
		return EIO;
	}

	/* probe and attach a child device(firewire) */
	bus_generic_probe(self);
	bus_generic_attach(self);

	return 0;
}
Пример #12
0
static void
kr_init_locked(struct kr_softc *sc)
{
	struct ifnet		*ifp = sc->kr_ifp;
	struct mii_data		*mii;

	KR_LOCK_ASSERT(sc);

	mii = device_get_softc(sc->kr_miibus);

	kr_stop(sc);
	kr_reset(sc);

	CSR_WRITE_4(sc, KR_ETHINTFC, ETH_INTFC_EN);

	/* Init circular RX list. */
	if (kr_rx_ring_init(sc) != 0) {
		device_printf(sc->kr_dev,
		    "initialization failed: no memory for rx buffers\n");
		kr_stop(sc);
		return;
	}

	/* Init tx descriptors. */
	kr_tx_ring_init(sc);

	KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_S, 0);
	KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_NDPTR, 0);
	KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_DPTR, 
	    sc->kr_rdata.kr_rx_ring_paddr);


	KR_DMA_CLEARBITS_REG(KR_DMA_RXCHAN, DMA_SM, 
	    DMA_SM_H | DMA_SM_E | DMA_SM_D) ;

	KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_S, 0);
	KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_NDPTR, 0);
	KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_DPTR, 0);
	KR_DMA_CLEARBITS_REG(KR_DMA_TXCHAN, DMA_SM, 
	    DMA_SM_F | DMA_SM_E);


	/* Accept only packets destined for THIS Ethernet device address */
	CSR_WRITE_4(sc, KR_ETHARC, 1);

	/* 
	 * Set all Ethernet address registers to the same initial values
	 * set all four addresses to 66-88-aa-cc-dd-ee 
	 */
	CSR_WRITE_4(sc, KR_ETHSAL0, 0x42095E6B);
	CSR_WRITE_4(sc, KR_ETHSAH0, 0x0000000C);

	CSR_WRITE_4(sc, KR_ETHSAL1, 0x42095E6B);
	CSR_WRITE_4(sc, KR_ETHSAH1, 0x0000000C);

	CSR_WRITE_4(sc, KR_ETHSAL2, 0x42095E6B);
	CSR_WRITE_4(sc, KR_ETHSAH2, 0x0000000C);

	CSR_WRITE_4(sc, KR_ETHSAL3, 0x42095E6B);
	CSR_WRITE_4(sc, KR_ETHSAH3, 0x0000000C);

	CSR_WRITE_4(sc, KR_ETHMAC2, 
	    KR_ETH_MAC2_PEN | KR_ETH_MAC2_CEN | KR_ETH_MAC2_FD);

	CSR_WRITE_4(sc, KR_ETHIPGT, KR_ETHIPGT_FULL_DUPLEX);
	CSR_WRITE_4(sc, KR_ETHIPGR, 0x12); /* minimum value */

	CSR_WRITE_4(sc, KR_MIIMCFG, KR_MIIMCFG_R);
	DELAY(1000);
	CSR_WRITE_4(sc, KR_MIIMCFG, 0);

	/* TODO: calculate prescale */
	CSR_WRITE_4(sc, KR_ETHMCP, (165000000 / (1250000 + 1)) & ~1);

	/* FIFO Tx threshold level */
	CSR_WRITE_4(sc, KR_ETHFIFOTT, 0x30);

	CSR_WRITE_4(sc, KR_ETHMAC1, KR_ETH_MAC1_RE);

	sc->kr_link_status = 0;
	mii_mediachg(mii);

	ifp->if_drv_flags |= IFF_DRV_RUNNING;
	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;

	callout_reset(&sc->kr_stat_callout, hz, kr_tick, sc);
}
Пример #13
0
static int
kr_attach(device_t dev)
{
	uint8_t			eaddr[ETHER_ADDR_LEN];
	struct ifnet		*ifp;
	struct kr_softc		*sc;
	int			error = 0, rid;
	int			unit;

	sc = device_get_softc(dev);
	unit = device_get_unit(dev);
	sc->kr_dev = dev;

	mtx_init(&sc->kr_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
	    MTX_DEF);
	callout_init_mtx(&sc->kr_stat_callout, &sc->kr_mtx, 0);
	TASK_INIT(&sc->kr_link_task, 0, kr_link_task, sc);
	pci_enable_busmaster(dev);

	/* Map control/status registers. */
	sc->kr_rid = 0;
	sc->kr_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->kr_rid, 
	    RF_ACTIVE);

	if (sc->kr_res == NULL) {
		device_printf(dev, "couldn't map memory\n");
		error = ENXIO;
		goto fail;
	}

	sc->kr_btag = rman_get_bustag(sc->kr_res);
	sc->kr_bhandle = rman_get_bushandle(sc->kr_res);

	/* Allocate interrupts */
	rid = 0;
	sc->kr_rx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_RX_IRQ,
	    KR_RX_IRQ, 1, RF_SHAREABLE | RF_ACTIVE);

	if (sc->kr_rx_irq == NULL) {
		device_printf(dev, "couldn't map rx interrupt\n");
		error = ENXIO;
		goto fail;
	}

	rid = 0;
	sc->kr_tx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_TX_IRQ,
	    KR_TX_IRQ, 1, RF_SHAREABLE | RF_ACTIVE);

	if (sc->kr_tx_irq == NULL) {
		device_printf(dev, "couldn't map tx interrupt\n");
		error = ENXIO;
		goto fail;
	}

	rid = 0;
	sc->kr_rx_und_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 
	    KR_RX_UND_IRQ, KR_RX_UND_IRQ, 1, RF_SHAREABLE | RF_ACTIVE);

	if (sc->kr_rx_und_irq == NULL) {
		device_printf(dev, "couldn't map rx underrun interrupt\n");
		error = ENXIO;
		goto fail;
	}

	rid = 0;
	sc->kr_tx_ovr_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 
	    KR_TX_OVR_IRQ, KR_TX_OVR_IRQ, 1, RF_SHAREABLE | RF_ACTIVE);

	if (sc->kr_tx_ovr_irq == NULL) {
		device_printf(dev, "couldn't map tx overrun interrupt\n");
		error = ENXIO;
		goto fail;
	}

	/* Allocate ifnet structure. */
	ifp = sc->kr_ifp = if_alloc(IFT_ETHER);

	if (ifp == NULL) {
		device_printf(dev, "couldn't allocate ifnet structure\n");
		error = ENOSPC;
		goto fail;
	}
	ifp->if_softc = sc;
	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
	ifp->if_ioctl = kr_ioctl;
	ifp->if_start = kr_start;
	ifp->if_init = kr_init;

	/* XXX: add real size */
	IFQ_SET_MAXLEN(&ifp->if_snd, 9);
	ifp->if_snd.ifq_maxlen = 9;
	IFQ_SET_READY(&ifp->if_snd);

	ifp->if_capenable = ifp->if_capabilities;

	eaddr[0] = 0x00;
	eaddr[1] = 0x0C;
	eaddr[2] = 0x42;
	eaddr[3] = 0x09;
	eaddr[4] = 0x5E;
	eaddr[5] = 0x6B;

	if (kr_dma_alloc(sc) != 0) {
		error = ENXIO;
		goto fail;
	}

	/* TODO: calculate prescale */
	CSR_WRITE_4(sc, KR_ETHMCP, (165000000 / (1250000 + 1)) & ~1);

	CSR_WRITE_4(sc, KR_MIIMCFG, KR_MIIMCFG_R);
	DELAY(1000);
	CSR_WRITE_4(sc, KR_MIIMCFG, 0);

	/* Do MII setup. */
	error = mii_attach(dev, &sc->kr_miibus, ifp, kr_ifmedia_upd,
	    kr_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
	if (error != 0) {
		device_printf(dev, "attaching PHYs failed\n");
		goto fail;
	}

	/* Call MI attach routine. */
	ether_ifattach(ifp, eaddr);

	/* Hook interrupt last to avoid having to lock softc */
	error = bus_setup_intr(dev, sc->kr_rx_irq, INTR_TYPE_NET | INTR_MPSAFE,
	    NULL, kr_rx_intr, sc, &sc->kr_rx_intrhand);

	if (error) {
		device_printf(dev, "couldn't set up rx irq\n");
		ether_ifdetach(ifp);
		goto fail;
	}

	error = bus_setup_intr(dev, sc->kr_tx_irq, INTR_TYPE_NET | INTR_MPSAFE,
	    NULL, kr_tx_intr, sc, &sc->kr_tx_intrhand);

	if (error) {
		device_printf(dev, "couldn't set up tx irq\n");
		ether_ifdetach(ifp);
		goto fail;
	}

	error = bus_setup_intr(dev, sc->kr_rx_und_irq, 
	    INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_rx_und_intr, sc, 
	    &sc->kr_rx_und_intrhand);

	if (error) {
		device_printf(dev, "couldn't set up rx underrun irq\n");
		ether_ifdetach(ifp);
		goto fail;
	}

	error = bus_setup_intr(dev, sc->kr_tx_ovr_irq, 
	    INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_tx_ovr_intr, sc, 
	    &sc->kr_tx_ovr_intrhand);

	if (error) {
		device_printf(dev, "couldn't set up tx overrun irq\n");
		ether_ifdetach(ifp);
		goto fail;
	}

fail:
	if (error) 
		kr_detach(dev);

	return (error);
}
Пример #14
0
static void
kr_rx(struct kr_softc *sc)
{
	struct kr_rxdesc	*rxd;
	struct ifnet		*ifp = sc->kr_ifp;
	int			cons, prog, packet_len, count, error;
	struct kr_desc		*cur_rx;
	struct mbuf		*m;

	KR_LOCK_ASSERT(sc);

	cons = sc->kr_cdata.kr_rx_cons;

	bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag,
	    sc->kr_cdata.kr_rx_ring_map,
	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

	for (prog = 0; prog < KR_RX_RING_CNT; KR_INC(cons, KR_RX_RING_CNT)) {
		cur_rx = &sc->kr_rdata.kr_rx_ring[cons];
		rxd = &sc->kr_cdata.kr_rxdesc[cons];
		m = rxd->rx_m;

		if ((cur_rx->kr_ctl & KR_CTL_D) == 0)
		       break;	

		prog++;

		packet_len = KR_PKTSIZE(cur_rx->kr_devcs);
		count = m->m_len - KR_DMASIZE(cur_rx->kr_ctl);
		/* Assume it's error */
		error = 1;

		if (packet_len != count)
			ifp->if_ierrors++;
		else if (count < 64)
			ifp->if_ierrors++;
		else if ((cur_rx->kr_devcs & KR_DMARX_DEVCS_LD) == 0)
			ifp->if_ierrors++;
		else if ((cur_rx->kr_devcs & KR_DMARX_DEVCS_ROK) != 0) {
			error = 0;
			bus_dmamap_sync(sc->kr_cdata.kr_rx_tag, rxd->rx_dmamap,
			    BUS_DMASYNC_PREREAD);
			m = rxd->rx_m;
			kr_fixup_rx(m);
			m->m_pkthdr.rcvif = ifp;
			/* Skip 4 bytes of CRC */
			m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN;
			ifp->if_ipackets++;

			KR_UNLOCK(sc);
			(*ifp->if_input)(ifp, m);
			KR_LOCK(sc);
		}

		if (error) {
			/* Restore CONTROL and CA values, reset DEVCS */
			cur_rx->kr_ctl = rxd->saved_ctl;
			cur_rx->kr_ca = rxd->saved_ca;
			cur_rx->kr_devcs = 0;
		}
		else {
			/* Reinit descriptor */
			cur_rx->kr_ctl = KR_CTL_IOD;
			if (cons == KR_RX_RING_CNT - 1)
				cur_rx->kr_ctl |= KR_CTL_COD;
			cur_rx->kr_devcs = 0;
			cur_rx->kr_ca = 0;
			if (kr_newbuf(sc, cons) != 0) {
				device_printf(sc->kr_dev, 
				    "Failed to allocate buffer\n");
				break;
			}
		}

		bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag,
		    sc->kr_cdata.kr_rx_ring_map,
		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

	}

	if (prog > 0) {
		sc->kr_cdata.kr_rx_cons = cons;

		bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag,
		    sc->kr_cdata.kr_rx_ring_map,
		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
	}
}
Пример #15
0
static int
xhci_pci_attach(device_t self)
{
	struct xhci_softc *sc = device_get_softc(self);
	int count, err, 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);

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

	sc->sc_irq_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) {
		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));

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

	/* On Intel chipsets reroute ports from EHCI to XHCI controller. */
	switch (pci_get_devid(self)) {
	case 0x1e318086:	/* Panther Point */
	case 0x8c318086:	/* Lynx Point */
		sc->sc_port_route = &xhci_pci_port_route;
		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);
}
Пример #16
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(dev, SYS_RES_IOPORT, &rid, 0, ~0,
					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;
    }

    mtx_init(&ctlr->bank_mtx, "ATA cbus bank lock", NULL, MTX_DEF);
    ctlr->hardware_bank = -1;
    ctlr->locked_bank = -1;
    ctlr->restart_bank = -1;

    for (unit = 0; unit < 2; 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);
}
Пример #17
0
int
dwc_otg_attach(device_t dev)
{
	struct dwc_otg_fdt_softc *sc = device_get_softc(dev);
	char usb_mode[24];
	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;
	sc->sc_otg.sc_bus.dma_bits = 32;

	/* get USB mode, if any */
	if (OF_getprop(ofw_bus_get_node(dev), "dr_mode",
	    &usb_mode, sizeof(usb_mode)) > 0) {

		/* ensure proper zero termination */
		usb_mode[sizeof(usb_mode) - 1] = 0;

		if (strcasecmp(usb_mode, "host") == 0)
			sc->sc_otg.sc_mode = DWC_MODE_HOST;
		else if (strcasecmp(usb_mode, "peripheral") == 0)
			sc->sc_otg.sc_mode = DWC_MODE_DEVICE;
		else if (strcasecmp(usb_mode, "otg") != 0) {
			device_printf(dev, "Invalid FDT dr_mode: %s\n",
			    usb_mode);
		}
	}

	/* 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_TTY | INTR_MPSAFE,
	    &dwc_otg_filter_interrupt, &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);
}
Пример #18
0
/**
 * Using the generic PCI bridge hardware configuration, allocate, initialize
 * and return a new bhndb_pci probe state instance.
 * 
 * On success, the caller assumes ownership of the returned probe instance, and
 * is responsible for releasing this reference using bhndb_pci_probe_free().
 * 
 * @param[out]	probe		On success, the newly allocated probe instance.
 * @param	dev		The bhndb_pci bridge device.
 * @param	hostb_devclass	The expected device class of the bridge core.
 *
 * @retval 0		success
 * @retval non-zero	if allocating the probe state fails, a regular
 * 			unix error code will be returned.
 * 
 * @note This function requires exclusive ownership over allocating and 
 * configuring host bridge resources, and should only be called prior to
 * completion of device attach and full configuration of the bridge.
 */
static int
bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe, device_t dev,
    bhnd_devclass_t hostb_devclass)
{
	struct bhndb_pci_probe		*p;
	struct bhnd_erom_io		*eio;
	const struct bhndb_hwcfg	*hwcfg;
	const struct bhnd_chipid	*hint;
	device_t			 parent_dev;
	int				 error;

	parent_dev = device_get_parent(dev);
	eio = NULL;

	p = malloc(sizeof(*p), M_BHND, M_ZERO|M_WAITOK);
	p->dev = dev;
	p->pci_dev = parent_dev;

	/* Our register window mapping state must be initialized at this point,
	 * as bhndb_pci_eio will begin making calls into
	 * bhndb_pci_probe_(read|write|get_mapping) */
	p->m_win = NULL;
	p->m_res = NULL;
	p->m_valid = false;

	bhndb_pci_eio_init(&p->erom_io, p);
	eio = &p->erom_io.eio;

	/* Fetch our chipid hint (if any) and generic hardware configuration */
	hwcfg = BHNDB_BUS_GET_GENERIC_HWCFG(parent_dev, dev);
	hint = BHNDB_BUS_GET_CHIPID(parent_dev, dev);

	/* Allocate our host resources */
	error = bhndb_alloc_host_resources(&p->hr, dev, parent_dev, hwcfg);
	if (error) {
		p->hr = NULL;
		goto failed;
	}

	/* Map the first bus core from our bridged bhnd(4) bus */
	error = bhnd_erom_io_map(eio, BHND_DEFAULT_CHIPC_ADDR,
	    BHND_DEFAULT_CORE_SIZE);
	if (error)
		goto failed;

	/* Probe for a usable EROM class, and read the chip identifier */
	p->erom_class = bhnd_erom_probe_driver_classes(
	    device_get_devclass(dev), eio, hint, &p->cid);
	if (p->erom_class == NULL) {
		device_printf(dev, "device enumeration unsupported; no "
		    "compatible driver found\n");

		error = ENXIO;
		goto failed;
	}

	/* Allocate EROM parser */
	p->erom = bhnd_erom_alloc(p->erom_class, &p->cid, eio);
	if (p->erom == NULL) {
		device_printf(dev, "failed to allocate device enumeration "
		    "table parser\n");
		error = ENXIO;
		goto failed;
	}

	/* The EROM I/O instance is now owned by our EROM parser */
	eio = NULL;

	/* Read the full core table */
	error = bhnd_erom_get_core_table(p->erom, &p->cores, &p->ncores);
	if (error) {
		device_printf(p->dev, "error fetching core table: %d\n",
		    error);

		p->cores = NULL;
		goto failed;
	}

	/* Identify the host bridge core */
	error = bhndb_find_hostb_core(p->cores, p->ncores, hostb_devclass,
	    &p->hostb_core);
	if (error) {
		device_printf(dev, "failed to identify the host bridge "
		    "core: %d\n", error);

		goto failed;
	}

	*probe = p;
	return (0);

failed:
	if (eio != NULL) {
		KASSERT(p->erom == NULL, ("I/O instance will be freed by "
		    "its owning parser"));

		bhnd_erom_io_fini(eio);
	}

	if (p->erom != NULL) {
		if (p->cores != NULL)
			bhnd_erom_free_core_table(p->erom, p->cores);

		bhnd_erom_free(p->erom);
	} else {
		KASSERT(p->cores == NULL, ("cannot free erom-owned core table "
		    "without erom reference"));
	}

	if (p->hr != NULL)
		bhndb_release_host_resources(p->hr);

	free(p, M_BHND);

	return (error);
}
Пример #19
0
static int
bt3c_pccard_attach(device_t dev)
{
	bt3c_softc_p	sc = (bt3c_softc_p) device_get_softc(dev);

	/* Allocate I/O ports */
	sc->iobase_rid = 0;
	sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->iobase_rid, 
			0, ~0, 8, RF_ACTIVE);
	if (sc->iobase == NULL) {
		device_printf(dev, "Could not allocate I/O ports\n");
		goto bad;
	}
	sc->iot = rman_get_bustag(sc->iobase);
	sc->ioh = rman_get_bushandle(sc->iobase);

	/* Allocate IRQ */
	sc->irq_rid = 0;
	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
			RF_ACTIVE);
	if (sc->irq == NULL) {
		device_printf(dev, "Could not allocate IRQ\n");
		goto bad;
	}

	sc->irq_cookie = NULL;
	if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, NULL, bt3c_intr, sc,
			&sc->irq_cookie) != 0) {
		device_printf(dev, "Could not setup ISR\n");
		goto bad;
	}

	/* Attach handler to TTY SWI thread */
	sc->ith = NULL;
	if (swi_add(&tty_intr_event, device_get_nameunit(dev),
			bt3c_swi_intr, sc, SWI_TTY, 0, &sc->ith) < 0) {
		device_printf(dev, "Could not setup SWI ISR\n");
		goto bad;
	}

	/* Create Netgraph node */
	if (ng_make_node_common(&typestruct, &sc->node) != 0) {
		device_printf(dev, "Could not create Netgraph node\n");
		sc->node = NULL;
		goto bad;
	}

	/* Name Netgraph node */
	if (ng_name_node(sc->node, device_get_nameunit(dev)) != 0) {
		device_printf(dev, "Could not name Netgraph node\n");
		NG_NODE_UNREF(sc->node);
		sc->node = NULL;
		goto bad;
	}

	sc->dev = dev;
	sc->debug = NG_BT3C_WARN_LEVEL;

	sc->inq.ifq_maxlen = sc->outq.ifq_maxlen = BT3C_DEFAULTQLEN;
	mtx_init(&sc->inq.ifq_mtx, "BT3C inq", NULL, MTX_DEF);
	mtx_init(&sc->outq.ifq_mtx, "BT3C outq", NULL, MTX_DEF);

	sc->state = NG_BT3C_W4_PKT_IND;
	sc->want = 1;

	NG_NODE_SET_PRIVATE(sc->node, sc);

	return (0);
bad:
	if (sc->ith != NULL) {
		swi_remove(sc->ith);
		sc->ith = NULL;
	}

	if (sc->irq != NULL) {
		if (sc->irq_cookie != NULL)
			bus_teardown_intr(dev, sc->irq, sc->irq_cookie);

		bus_release_resource(dev, SYS_RES_IRQ,
			sc->irq_rid, sc->irq);

		sc->irq = NULL;
		sc->irq_rid = 0;
	}

	if (sc->iobase != NULL) {
		bus_release_resource(dev, SYS_RES_IOPORT,
			sc->iobase_rid, sc->iobase);

		sc->iobase = NULL;
		sc->iobase_rid = 0;
	}

	return (ENXIO);
} /* bt3c_pccacd_attach */
Пример #20
0
/**
 * Attempt to adjust the dynamic register window backing @p probe to permit
 * accessing @p size bytes at @p addr.
 * 
 * @param	probe		The bhndb_pci probe state to be modified.
 * @param	addr		The address at which @p size bytes will mapped.
 * @param	size		The number of bytes to be mapped.
 * @param[out]	res		On success, will be set to the host resource
 *				mapping @p size bytes at @p addr.
 * @param[out]	res_offset	On success, will be set to the offset of @addr
 *				within @p res.
 * 
 * @retval 0		success
 * @retval non-zero	if an error occurs adjusting the backing dynamic
 *			register window.
 */
static int
bhndb_pci_probe_map(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
    bhnd_size_t offset, bhnd_size_t size, struct resource **res,
    bus_size_t *res_offset)
{
	const struct bhndb_regwin	*regwin, *regwin_table;
	struct resource			*regwin_res;
	bhnd_addr_t			 target;
	int				 error;

	/* Determine the absolute address */
	if (BHND_SIZE_MAX - offset < addr) {
		device_printf(probe->dev, "invalid offset %#jx+%#jx\n", addr,
		    offset);
		return (ENXIO);
	}

	addr += offset;

	/* Can we use the existing mapping? */
	if (bhndb_pci_probe_has_mapping(probe, addr, size)) {
		*res = probe->m_res;
		*res_offset = (addr - probe->m_target) +
		    probe->m_win->win_offset;

		return (0);
	}

	/* Locate a useable dynamic register window */
	regwin_table = probe->hr->cfg->register_windows;
	regwin = bhndb_regwin_find_type(regwin_table,
	    BHNDB_REGWIN_T_DYN, size);
	if (regwin == NULL) {
		device_printf(probe->dev, "unable to map %#jx+%#jx; no "
		    "usable dynamic register window found\n", addr,
		    size);
		return (ENXIO);
	}

	/* Locate the host resource mapping our register window */
	regwin_res = bhndb_host_resource_for_regwin(probe->hr, regwin);
	if (regwin_res == NULL) {
		device_printf(probe->dev, "unable to map %#jx+%#jx; no "
		    "usable register resource found\n", addr, size);
		return (ENXIO);
	}

	/* Page-align the target address */
	target = addr - (addr % regwin->win_size);

	/* Configure the register window */
	error = bhndb_pci_compat_setregwin(probe->dev, probe->pci_dev,
	    regwin, target);
	if (error) {
		device_printf(probe->dev, "failed to configure dynamic "
		    "register window: %d\n", error);
		return (error);
	}

	/* Update our mapping state */
	probe->m_win = regwin;
	probe->m_res = regwin_res;
	probe->m_addr = addr;
	probe->m_size = size;
	probe->m_target = target;
	probe->m_valid = true;

	*res = regwin_res;
	*res_offset = (addr - target) + regwin->win_offset;

	return (0);
}
Пример #21
0
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
	ACPI_STATUS	status;
	struct pcb	*pcb;

	if (sc->acpi_wakeaddr == 0ul)
		return (-1);	/* couldn't alloc wake memory */

#ifdef SMP
	suspcpus = all_cpus;
	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
#endif

	if (acpi_resume_beep != 0)
		timer_spkr_acquire();

	AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));

	intr_suspend();

	pcb = &susppcbs[0]->sp_pcb;
	if (savectx(pcb)) {
#ifdef __amd64__
		fpususpend(susppcbs[0]->sp_fpususpend);
#elif defined(DEV_NPX)
		npxsuspend(susppcbs[0]->sp_fpususpend);
#endif
#ifdef SMP
		if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) {
			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
			return (0);	/* couldn't sleep */
		}
#endif

		WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));

#ifndef __amd64__
		WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4);
#endif
		WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
		WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);

		/* Call ACPICA to enter the desired sleep state */
		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
			status = AcpiEnterSleepStateS4bios();
		else
			status = AcpiEnterSleepState(state);
		if (ACPI_FAILURE(status)) {
			device_printf(sc->acpi_dev,
			    "AcpiEnterSleepState failed - %s\n",
			    AcpiFormatException(status));
			return (0);	/* couldn't sleep */
		}

		for (;;)
			ia32_pause();
	} else {
#ifdef __amd64__
		fpuresume(susppcbs[0]->sp_fpususpend);
#elif defined(DEV_NPX)
		npxresume(susppcbs[0]->sp_fpususpend);
#endif
	}

	return (1);	/* wakeup successfully */
}
Пример #22
0
static int
bhndb_pci_attach(device_t dev)
{
	struct bhndb_pci_softc	*sc;
	struct bhnd_chipid	 cid;
	struct bhnd_core_info	*cores, hostb_core;
	bhnd_erom_class_t	*erom_class;
	struct bhndb_pci_probe	*probe;
	u_int			 ncores;
	int			 irq_rid;
	int			 error;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->parent = device_get_parent(dev);
	sc->pci_devclass = bhndb_expected_pci_devclass(dev);
	sc->pci_quirks = 0;
	sc->set_regwin = NULL;

	BHNDB_PCI_LOCK_INIT(sc);

	probe = NULL;
	cores = NULL;

	/* Enable PCI bus mastering */
	pci_enable_busmaster(sc->parent);

	/* Enable clocks (if required by this hardware) */
	if ((error = bhndb_enable_pci_clocks(sc->dev)))
		goto cleanup;

	/* Identify the chip and enumerate the bridged cores */
	error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass);
	if (error)
		goto cleanup;

	sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid,
	    &probe->hostb_core);

	/* Select the appropriate register window handler */
	if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) {
		sc->set_regwin = bhndb_pci_compat_setregwin;
	} else {
		sc->set_regwin = bhndb_pci_fast_setregwin;
	}

	/*
	 * Fix up our PCI base address in the SPROM shadow, if necessary.
	 * 
	 * This must be done prior to accessing any static register windows
	 * that map the PCI core.
	 */
	if ((error = bhndb_pci_srsh_pi_war(sc, probe)))
		goto cleanup;

	/* Set up PCI interrupt handling */
	if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) {
		/* MSI uses resource IDs starting at 1 */
		irq_rid = 1;

		device_printf(dev, "Using MSI interrupts on %s\n",
		    device_get_nameunit(sc->parent));
	} else {
		sc->msi_count = 0;
		irq_rid = 0;

		device_printf(dev, "Using INTx interrupts on %s\n",
		    device_get_nameunit(sc->parent));
	}

	sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->isrc == NULL) {
		device_printf(sc->dev, "failed to allocate interrupt "
		    "resource\n");
		error = ENXIO;
		goto cleanup;
	}

	/*
	 * Copy out the probe results and then free our probe state, releasing
	 * its exclusive ownership of host bridge resources.
	 * 
	 * This must be done prior to full configuration of the bridge via
	 * bhndb_attach().
	 */
	cid = probe->cid;
	erom_class = probe->erom_class;
	hostb_core = probe->hostb_core;

	error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores);
	if (error) {
		cores = NULL;
		goto cleanup;
	}

	bhndb_pci_probe_free(probe);
	probe = NULL;

	/* Perform bridge attach */
	error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class);
	if (error)
		goto cleanup;

	/* Add any additional child devices */
	if ((error = bhndb_pci_add_children(sc)))
		goto cleanup;

	/* Probe and attach our children */
	if ((error = bus_generic_attach(dev)))
		goto cleanup;

	bhndb_pci_probe_free_core_table(cores);

	return (0);

cleanup:
	device_delete_children(dev);

	if (sc->isrc != NULL)
		bhndb_free_intr_isrc(sc->isrc);

	if (sc->msi_count > 0)
		pci_release_msi(sc->parent);

	if (cores != NULL)
		bhndb_pci_probe_free_core_table(cores);

	if (probe != NULL)
		bhndb_pci_probe_free(probe);

	bhndb_disable_pci_clocks(sc->dev);

	pci_disable_busmaster(sc->parent);

	BHNDB_PCI_LOCK_DESTROY(sc);

	return (error);
}
Пример #23
0
int
rk_cru_attach(device_t dev)
{
	struct rk_cru_softc *sc;
	phandle_t node;
	int	i;

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

	node = ofw_bus_get_node(dev);

	if (bus_alloc_resources(dev, rk_cru_spec, &sc->res) != 0) {
		device_printf(dev, "cannot allocate resources for device\n");
		return (ENXIO);
	}

	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);

	sc->clkdom = clkdom_create(dev);
	if (sc->clkdom == NULL)
		panic("Cannot create clkdom\n");

	for (i = 0; i < sc->nclks; i++) {
		switch (sc->clks[i].type) {
		case RK_CLK_UNDEFINED:
			break;
		case RK_CLK_PLL:
			rk_clk_pll_register(sc->clkdom, sc->clks[i].clk.pll);
			break;
		case RK_CLK_COMPOSITE:
			rk_clk_composite_register(sc->clkdom,
			    sc->clks[i].clk.composite);
			break;
		case RK_CLK_MUX:
			rk_clk_mux_register(sc->clkdom, sc->clks[i].clk.mux);
			break;
		case RK_CLK_ARMCLK:
			rk_clk_armclk_register(sc->clkdom, sc->clks[i].clk.armclk);
			break;
		default:
			device_printf(dev, "Unknown clock type\n");
			return (ENXIO);
			break;
		}
	}
	if (sc->gates)
		rk_cru_register_gates(sc);

	if (clkdom_finit(sc->clkdom) != 0)
		panic("cannot finalize clkdom initialization\n");

	if (bootverbose)
		clkdom_dump(sc->clkdom);

	clk_set_assigned(dev, node);

	/* If we have resets, register our self as a reset provider */
	if (sc->resets)
		hwreset_register_ofw_provider(dev);

	return (0);
}
Пример #24
0
static int
amr_pci_attach(device_t dev)
{
    struct amr_softc	*sc;
    struct amr_ident	*id;
    int			rid, rtype, error;

    debug_called(1);

    /*
     * Initialise softc.
     */
    sc = device_get_softc(dev);
    bzero(sc, sizeof(*sc));
    sc->amr_dev = dev;

    /* assume failure is 'not configured' */
    error = ENXIO;

    /*
     * Determine board type.
     */
    if ((id = amr_find_ident(dev)) == NULL)
	return (ENXIO);

    if (id->flags & AMR_ID_QUARTZ) {
	sc->amr_type |= AMR_TYPE_QUARTZ;
    }

    if ((amr_force_sg32 == 0) && (id->flags & AMR_ID_DO_SG64) &&
	(sizeof(vm_paddr_t) > 4)) {
	device_printf(dev, "Using 64-bit DMA\n");
	sc->amr_type |= AMR_TYPE_SG64;
    }

    /* force the busmaster enable bit on */
    pci_enable_busmaster(dev);

    /*
     * Allocate the PCI register window.
     */
    rid = PCIR_BAR(0);
    rtype = AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT;
    sc->amr_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
    if (sc->amr_reg == NULL) {
	device_printf(sc->amr_dev, "can't allocate register window\n");
	goto out;
    }
    sc->amr_btag = rman_get_bustag(sc->amr_reg);
    sc->amr_bhandle = rman_get_bushandle(sc->amr_reg);

    /*
     * Allocate and connect our interrupt.
     */
    rid = 0;
    sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid,
        RF_SHAREABLE | RF_ACTIVE);
    if (sc->amr_irq == NULL) {
        device_printf(sc->amr_dev, "can't allocate interrupt\n");
	goto out;
    }
    if (bus_setup_intr(sc->amr_dev, sc->amr_irq,
	INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, amr_pci_intr,
	sc, &sc->amr_intr)) {
        device_printf(sc->amr_dev, "can't set up interrupt\n");
	goto out;
    }

    debug(2, "interrupt attached");

    /* assume failure is 'out of memory' */
    error = ENOMEM;

    /*
     * Allocate the parent bus DMA tag appropriate for PCI.
     */
    if (bus_dma_tag_create(bus_get_dma_tag(dev),	/* PCI parent */
			   1, 0, 			/* alignment,boundary */
			   AMR_IS_SG64(sc) ?
			   BUS_SPACE_MAXADDR :
			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			   BUS_SPACE_MAXADDR, 		/* highaddr */
			   NULL, NULL, 			/* filter, filterarg */
			   MAXBSIZE, AMR_NSEG,		/* maxsize, nsegments */
			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
			   0,				/* flags */
			   NULL, NULL,			/* lockfunc, lockarg */
			   &sc->amr_parent_dmat)) {
	device_printf(dev, "can't allocate parent DMA tag\n");
	goto out;
    }

    /*
     * Create DMA tag for mapping buffers into controller-addressable space.
     */
    if (bus_dma_tag_create(sc->amr_parent_dmat,		/* parent */
			   1, 0,			/* alignment,boundary */
			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			   BUS_SPACE_MAXADDR,		/* highaddr */
			   NULL, NULL,			/* filter, filterarg */
			   MAXBSIZE, AMR_NSEG,		/* maxsize, nsegments */
			   MAXBSIZE,			/* maxsegsize */
			   0,		/* flags */
			   busdma_lock_mutex,		/* lockfunc */
			   &sc->amr_list_lock,		/* lockarg */
			   &sc->amr_buffer_dmat)) {
        device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
	goto out;
    }

    if (bus_dma_tag_create(sc->amr_parent_dmat,		/* parent */
			   1, 0,			/* alignment,boundary */
			   BUS_SPACE_MAXADDR,		/* lowaddr */
			   BUS_SPACE_MAXADDR,		/* highaddr */
			   NULL, NULL,			/* filter, filterarg */
			   MAXBSIZE, AMR_NSEG,		/* maxsize, nsegments */
			   MAXBSIZE,			/* maxsegsize */
			   0,		/* flags */
			   busdma_lock_mutex,		/* lockfunc */
			   &sc->amr_list_lock,		/* lockarg */
			   &sc->amr_buffer64_dmat)) {
        device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
	goto out;
    }

    debug(2, "dma tag done");

    /*
     * Allocate and set up mailbox in a bus-visible fashion.
     */
    mtx_init(&sc->amr_list_lock, "AMR List Lock", NULL, MTX_DEF);
    mtx_init(&sc->amr_hw_lock, "AMR HW Lock", NULL, MTX_DEF);
    if ((error = amr_setup_mbox(sc)) != 0)
	goto out;

    debug(2, "mailbox setup");

    /*
     * Build the scatter/gather buffers.
     */
    if ((error = amr_sglist_map(sc)) != 0)
	goto out;
    debug(2, "s/g list mapped");

    if ((error = amr_ccb_map(sc)) != 0)
	goto out;
    debug(2, "ccb mapped");


    /*
     * Do bus-independant initialisation, bring controller online.
     */
    error = amr_attach(sc);

out:
    if (error)
	amr_pci_free(sc);
    return(error);
}
Пример #25
0
static void
usie_if_status_cb(void *arg, int pending)
{
	struct usie_softc *sc = arg;
	struct ifnet *ifp = sc->sc_ifp;
	struct usb_device_request req;
	struct usie_hip *hip;
	struct usie_lsi *lsi;
	uint16_t actlen;
	uint8_t ntries;
	uint8_t pad;

	mtx_lock(&sc->sc_mtx);

	req.bmRequestType = UT_READ_CLASS_INTERFACE;
	req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
	USETW(req.wValue, 0);
	USETW(req.wIndex, sc->sc_if_ifnum);
	USETW(req.wLength, sizeof(sc->sc_status_temp));

	for (ntries = 0; ntries != 10; ntries++) {
		int err;

		err = usbd_do_request_flags(sc->sc_udev,
		    &sc->sc_mtx, &req, sc->sc_status_temp, USB_SHORT_XFER_OK,
		    &actlen, USB_DEFAULT_TIMEOUT);

		if (err == 0)
			break;

		DPRINTF("Control request failed: %s %d/10\n",
		    usbd_errstr(err), ntries);

		usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(10));
	}

	if (ntries == 10) {
		mtx_unlock(&sc->sc_mtx);
		DPRINTF("Timeout\n");
		return;
	}

	hip = (struct usie_hip *)sc->sc_status_temp;

	pad = (hip->id & USIE_HIP_PAD) ? 1 : 0;

	DPRINTF("hip.id=%x hip.len=%d actlen=%u pad=%d\n",
	    hip->id, be16toh(hip->len), actlen, pad);

	switch (hip->id & USIE_HIP_MASK) {
	case USIE_HIP_SYNC2H:
		usie_if_cmd(sc, USIE_HIP_SYNC2M);
		break;
	case USIE_HIP_RESTR:
		usb_callout_stop(&sc->sc_if_sync_ch);
		break;
	case USIE_HIP_UMTS:
		lsi = (struct usie_lsi *)(
		    sc->sc_status_temp + sizeof(struct usie_hip) + pad);

		DPRINTF("lsi.proto=%x lsi.len=%d\n", lsi->proto,
		    be16toh(lsi->len));

		if (lsi->proto != USIE_LSI_UMTS)
			break;

		if (lsi->area == USIE_LSI_AREA_NO ||
		    lsi->area == USIE_LSI_AREA_NODATA) {
			device_printf(sc->sc_dev, "no service available\n");
			break;
		}
		if (lsi->state == USIE_LSI_STATE_IDLE) {
			DPRINTF("lsi.state=%x\n", lsi->state);
			break;
		}
		DPRINTF("ctx=%x\n", hip->param);
		sc->sc_txd.hip.param = hip->param;

		sc->sc_net.addr_len = lsi->pdp_addr_len;
		memcpy(&sc->sc_net.dns1_addr, &lsi->dns1_addr, 16);
		memcpy(&sc->sc_net.dns2_addr, &lsi->dns2_addr, 16);
		memcpy(sc->sc_net.pdp_addr, lsi->pdp_addr, 16);
		memcpy(sc->sc_net.gw_addr, lsi->gw_addr, 16);
		ifp->if_flags |= IFF_UP;
		ifp->if_drv_flags |= IFF_DRV_RUNNING;

		device_printf(sc->sc_dev, "IP Addr=%d.%d.%d.%d\n",
		    *lsi->pdp_addr, *(lsi->pdp_addr + 1),
		    *(lsi->pdp_addr + 2), *(lsi->pdp_addr + 3));
		device_printf(sc->sc_dev, "Gateway Addr=%d.%d.%d.%d\n",
		    *lsi->gw_addr, *(lsi->gw_addr + 1),
		    *(lsi->gw_addr + 2), *(lsi->gw_addr + 3));
		device_printf(sc->sc_dev, "Prim NS Addr=%d.%d.%d.%d\n",
		    *lsi->dns1_addr, *(lsi->dns1_addr + 1),
		    *(lsi->dns1_addr + 2), *(lsi->dns1_addr + 3));
		device_printf(sc->sc_dev, "Scnd NS Addr=%d.%d.%d.%d\n",
		    *lsi->dns2_addr, *(lsi->dns2_addr + 1),
		    *(lsi->dns2_addr + 2), *(lsi->dns2_addr + 3));

		usie_cns_req(sc, USIE_CNS_ID_RSSI, USIE_CNS_OB_RSSI);
		break;

	case USIE_HIP_RCGI:
		/* ignore, workaround for sloppy windows */
		break;
	default:
		DPRINTF("undefined msgid: %x\n", hip->id);
		break;
	}

	mtx_unlock(&sc->sc_mtx);
}
Пример #26
0
static int
amr_sglist_map(struct amr_softc *sc)
{
    size_t	segsize;
    void	*p;
    int		error;

    debug_called(1);

    /*
     * Create a single tag describing a region large enough to hold all of
     * the s/g lists we will need.
     *
     * Note that we could probably use AMR_LIMITCMD here, but that may become
     * tunable.
     */
    if (AMR_IS_SG64(sc))
	segsize = sizeof(struct amr_sg64entry) * AMR_NSEG * AMR_MAXCMD;
    else
	segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD;

    error = bus_dma_tag_create(sc->amr_parent_dmat, 	/* parent */
			       512, 0, 			/* alignment,boundary */
			       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			       BUS_SPACE_MAXADDR, 	/* highaddr */
			       NULL, NULL, 		/* filter, filterarg */
			       segsize, 1,		/* maxsize, nsegments */
			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
			       0,			/* flags */
			       NULL, NULL,		/* lockfunc, lockarg */
			       &sc->amr_sg_dmat);
    if (error != 0) {
	device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n");
	return(ENOMEM);
    }

    /*
     * Allocate enough s/g maps for all commands and permanently map them into
     * controller-visible space.
     *	
     * XXX this assumes we can get enough space for all the s/g maps in one 
     * contiguous slab.  We may need to switch to a more complex arrangement
     * where we allocate in smaller chunks and keep a lookup table from slot
     * to bus address.
     *
     * XXX HACK ALERT:	at least some controllers don't like the s/g memory
     *			being allocated below 0x2000.  We leak some memory if
     *			we get some below this mark and allocate again.  We
     *			should be able to avoid this with the tag setup, but
     *			that does't seem to work.
     */
retry:
    error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&p, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap);
    if (error) {
	device_printf(sc->amr_dev, "can't allocate s/g table\n");
	return(ENOMEM);
    }
    bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0);
    if (sc->amr_sgbusaddr < 0x2000) {
	debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr);
	goto retry;
    }

    if (AMR_IS_SG64(sc))
	sc->amr_sg64table = (struct amr_sg64entry *)p;
    sc->amr_sgtable = (struct amr_sgentry *)p;

    return(0);
}
Пример #27
0
static int
usie_attach(device_t self)
{
	struct usie_softc *sc = device_get_softc(self);
	struct usb_attach_arg *uaa = device_get_ivars(self);
	struct ifnet *ifp;
	struct usb_interface *iface;
	struct usb_interface_descriptor *id;
	struct usb_device_request req;
	int err;
	uint16_t fwattr;
	uint8_t iface_index;
	uint8_t ifidx;
	uint8_t start;

	device_set_usb_desc(self);
	sc->sc_udev = uaa->device;
	sc->sc_dev = self;

	mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF);
	ucom_ref(&sc->sc_super_ucom);

	TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc);
	TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc);

	usb_callout_init_mtx(&sc->sc_if_sync_ch, &sc->sc_mtx, 0);

	mtx_lock(&sc->sc_mtx);

	/* set power mode to D0 */
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = USIE_POWER;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 0);
	if (usie_do_request(sc, &req, NULL)) {
		mtx_unlock(&sc->sc_mtx);
		goto detach;
	}
	/* read fw attr */
	fwattr = 0;
	req.bmRequestType = UT_READ_VENDOR_DEVICE;
	req.bRequest = USIE_FW_ATTR;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, sizeof(fwattr));
	if (usie_do_request(sc, &req, &fwattr)) {
		mtx_unlock(&sc->sc_mtx);
		goto detach;
	}
	mtx_unlock(&sc->sc_mtx);

	/* check DHCP supports */
	DPRINTF("fwattr=%x\n", fwattr);
	if (!(fwattr & USIE_FW_DHCP)) {
		device_printf(self, "DHCP is not supported. A firmware upgrade might be needed.\n");
	}

	/* find available interfaces */
	sc->sc_nucom = 0;
	for (ifidx = 0; ifidx < USIE_IFACE_MAX; ifidx++) {
		iface = usbd_get_iface(uaa->device, ifidx);
		if (iface == NULL)
			break;

		id = usbd_get_interface_descriptor(iface);
		if ((id == NULL) || (id->bInterfaceClass != UICLASS_VENDOR))
			continue;

		/* setup Direct IP transfer */
		if (id->bInterfaceNumber >= 7 && id->bNumEndpoints == 3) {
			sc->sc_if_ifnum = id->bInterfaceNumber;
			iface_index = ifidx;

			DPRINTF("ifnum=%d, ifidx=%d\n",
			    sc->sc_if_ifnum, ifidx);

			err = usbd_transfer_setup(uaa->device,
			    &iface_index, sc->sc_if_xfer, usie_if_config,
			    USIE_IF_N_XFER, sc, &sc->sc_mtx);

			if (err == 0)
				continue;

			device_printf(self,
			    "could not allocate USB transfers on "
			    "iface_index=%d, err=%s\n",
			    iface_index, usbd_errstr(err));
			goto detach;
		}

		/* setup ucom */
		if (sc->sc_nucom >= USIE_UCOM_MAX)
			continue;

		usbd_set_parent_iface(uaa->device, ifidx,
		    uaa->info.bIfaceIndex);

		DPRINTF("NumEndpoints=%d bInterfaceNumber=%d\n",
		    id->bNumEndpoints, id->bInterfaceNumber);

		if (id->bNumEndpoints == 2) {
			sc->sc_uc_xfer[sc->sc_nucom][0] = NULL;
			start = 1;
		} else
			start = 0;

		err = usbd_transfer_setup(uaa->device, &ifidx,
		    sc->sc_uc_xfer[sc->sc_nucom] + start,
		    usie_uc_config + start, USIE_UC_N_XFER - start,
		    &sc->sc_ucom[sc->sc_nucom], &sc->sc_mtx);

		if (err != 0) {
			DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(err));
			continue;
		}

		mtx_lock(&sc->sc_mtx);
		for (; start < USIE_UC_N_XFER; start++)
			usbd_xfer_set_stall(sc->sc_uc_xfer[sc->sc_nucom][start]);
		mtx_unlock(&sc->sc_mtx);

		sc->sc_uc_ifnum[sc->sc_nucom] = id->bInterfaceNumber;

		sc->sc_nucom++;		/* found a port */
	}

	if (sc->sc_nucom == 0) {
		device_printf(self, "no comports found\n");
		goto detach;
	}

	err = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
	    sc->sc_nucom, sc, &usie_uc_callback, &sc->sc_mtx);

	if (err != 0) {
		DPRINTF("ucom_attach failed\n");
		goto detach;
	}
	DPRINTF("Found %d interfaces.\n", sc->sc_nucom);

	/* setup ifnet (Direct IP) */
	sc->sc_ifp = ifp = if_alloc(IFT_OTHER);

	if (ifp == NULL) {
		device_printf(self, "Could not allocate a network interface\n");
		goto detach;
	}
	if_initname(ifp, "usie", device_get_unit(self));

	ifp->if_softc = sc;
	ifp->if_mtu = USIE_MTU_MAX;
	ifp->if_flags |= IFF_NOARP;
	ifp->if_init = usie_if_init;
	ifp->if_ioctl = usie_if_ioctl;
	ifp->if_start = usie_if_start;
	ifp->if_output = usie_if_output;
	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
	IFQ_SET_READY(&ifp->if_snd);

	if_attach(ifp);
	bpfattach(ifp, DLT_RAW, 0);

	if (fwattr & USIE_PM_AUTO) {
		usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE);
		DPRINTF("enabling automatic suspend and resume\n");
	} else {
		usbd_set_power_mode(uaa->device, USB_POWER_MODE_ON);
		DPRINTF("USB power is always ON\n");
	}

	DPRINTF("device attached\n");
	return (0);

detach:
	usie_detach(self);
	return (ENOMEM);
}
Пример #28
0
void
acpi_install_wakeup_handler(struct acpi_softc *sc)
{
	static void	*wakeaddr = NULL;
	uint64_t	*pt4, *pt3, *pt2;
	int		i;

	if (wakeaddr != NULL)
		return;

	wakeaddr = acpi_alloc_wakeup_handler();
	if (wakeaddr == NULL)
		return;

	sc->acpi_wakeaddr = (vm_offset_t)wakeaddr;
	sc->acpi_wakephys = vtophys(wakeaddr);

	bcopy(wakecode, (void *)WAKECODE_VADDR(sc), sizeof(wakecode));

	/* Patch GDT base address, ljmp targets and page table base address. */
	WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t,
	    WAKECODE_PADDR(sc) + bootgdt);
	WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t,
	    WAKECODE_PADDR(sc) + wakeup_32);
	WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
	    WAKECODE_PADDR(sc) + wakeup_64);
	WAKECODE_FIXUP(wakeup_pagetables, uint32_t, sc->acpi_wakephys);

	/* Save pointers to some global data. */
	WAKECODE_FIXUP(wakeup_retaddr, void *, acpi_restorecpu);
	WAKECODE_FIXUP(wakeup_kpml4, uint64_t, KPML4phys);
	WAKECODE_FIXUP(wakeup_ctx, vm_offset_t,
	    WAKECODE_VADDR(sc) + wakeup_ctx);
	WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER));
	WAKECODE_FIXUP(wakeup_star, uint64_t, rdmsr(MSR_STAR));
	WAKECODE_FIXUP(wakeup_lstar, uint64_t, rdmsr(MSR_LSTAR));
	WAKECODE_FIXUP(wakeup_cstar, uint64_t, rdmsr(MSR_CSTAR));
	WAKECODE_FIXUP(wakeup_sfmask, uint64_t, rdmsr(MSR_SF_MASK));
	WAKECODE_FIXUP(wakeup_xsmask, uint64_t, xsave_mask);

	/* Build temporary page tables below realmode code. */
	pt4 = wakeaddr;
	pt3 = pt4 + (PAGE_SIZE) / sizeof(uint64_t);
	pt2 = pt3 + (PAGE_SIZE) / sizeof(uint64_t);

	/* Create the initial 1GB replicated page tables */
	for (i = 0; i < 512; i++) {
		/*
		 * Each slot of the level 4 pages points
		 * to the same level 3 page
		 */
		pt4[i] = (uint64_t)(sc->acpi_wakephys + PAGE_SIZE);
		pt4[i] |= PG_V | PG_RW | PG_U;

		/*
		 * Each slot of the level 3 pages points
		 * to the same level 2 page
		 */
		pt3[i] = (uint64_t)(sc->acpi_wakephys + (2 * PAGE_SIZE));
		pt3[i] |= PG_V | PG_RW | PG_U;

		/* The level 2 page slots are mapped with 2MB pages for 1GB. */
		pt2[i] = i * (2 * 1024 * 1024);
		pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
	}

	if (bootverbose)
		device_printf(sc->acpi_dev, "wakeup code va %p pa %p\n",
		    (void *)sc->acpi_wakeaddr, (void *)sc->acpi_wakephys);
}
Пример #29
0
static int
clkbrd_attach(device_t dev)
{
	struct clkbrd_softc *sc;
	int i, slots;
	uint8_t r;

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

	for (i = CLKBRD_CF; i <= CLKBRD_CLKVER; i++) {
		sc->sc_rid[i] = i;
		sc->sc_res[i] = bus_alloc_resource_any(sc->sc_dev,
		    SYS_RES_MEMORY, &sc->sc_rid[i], RF_ACTIVE);
		if (sc->sc_res[i] == NULL) {
			if (i != CLKBRD_CLKVER) {
				device_printf(sc->sc_dev,
				    "could not allocate resource %d\n", i);
				goto fail;
			}
			continue;
		}
		sc->sc_bt[i] = rman_get_bustag(sc->sc_res[i]);
		sc->sc_bh[i] = rman_get_bushandle(sc->sc_res[i]);
		if (i == CLKBRD_CLKVER)
			sc->sc_flags |= CLKBRD_HAS_CLKVER;
	}

	slots = 4;
	r = bus_space_read_1(sc->sc_bt[CLKBRD_CLK], sc->sc_bh[CLKBRD_CLK],
	    CLK_STS1);
	switch (r & CLK_STS1_SLOTS_MASK) {
	case CLK_STS1_SLOTS_16:
		slots = 16;
		break;
	case CLK_STS1_SLOTS_8:
		slots = 8;
		break;
	case CLK_STS1_SLOTS_4:
		if (sc->sc_flags & CLKBRD_HAS_CLKVER) {
			r = bus_space_read_1(sc->sc_bt[CLKBRD_CLKVER],
			    sc->sc_bh[CLKBRD_CLKVER], CLKVER_SLOTS);
			if (r != 0 &&
			    (r & CLKVER_SLOTS_MASK) == CLKVER_SLOTS_PLUS)
				slots = 5;
		}
	}

	device_printf(sc->sc_dev, "Sun Enterprise Exx00 machine: %d slots\n",
	    slots);

	sc->sc_clk_ctrl = bus_space_read_1(sc->sc_bt[CLKBRD_CLK],
	    sc->sc_bh[CLKBRD_CLK], CLK_CTRL);
	sc->sc_led_dev = led_create(clkbrd_led_func, sc, "clockboard");

	return (0);

 fail:
	clkbrd_free_resources(sc);

	return (ENXIO);
}
Пример #30
0
static int
ti_mbox_attach(device_t dev)
{
	struct ti_mbox_softc *sc;
	int rid, delay, chan;
	uint32_t rev, sysconfig;

	if (ti_prcm_clk_enable(MAILBOX0_CLK) != 0) {
		device_printf(dev, "could not enable MBOX clock\n");
		return (ENXIO);
	}
	sc = device_get_softc(dev);
	rid = 0;
	mtx_init(&sc->sc_mtx, "TI mbox", NULL, MTX_DEF);
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (sc->sc_mem_res == NULL) {
		device_printf(dev, "could not allocate memory resource\n");
		return (ENXIO);
	}
	sc->sc_bt = rman_get_bustag(sc->sc_mem_res);
	sc->sc_bh = 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 == NULL) {
		device_printf(dev, "could not allocate interrupt resource\n");
		ti_mbox_detach(dev);
		return (ENXIO);
	}
	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE | INTR_TYPE_MISC,
	    NULL, ti_mbox_intr, sc, &sc->sc_intr) != 0) {
		device_printf(dev, "unable to setup the interrupt handler\n");
		ti_mbox_detach(dev);
		return (ENXIO);
	}
	/*
	 * Reset the controller.
	 */
	sysconfig = ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG);
	DPRINTF("initial sysconfig %d\n", sysconfig);
	sysconfig |= TI_MBOX_SYSCONFIG_SOFTRST;
	delay = 100;
	while (ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) & 
	    TI_MBOX_SYSCONFIG_SOFTRST) {
		delay--;
		DELAY(10);
	}
	if (delay == 0) {
		device_printf(dev, "controller reset failed\n");
		ti_mbox_detach(dev);
		return (ENXIO);
	}
	/*
	 * Enable smart idle mode.
	 */
	ti_mbox_reg_write(sc, TI_MBOX_SYSCONFIG,
	    ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) | TI_MBOX_SYSCONFIG_SMARTIDLE);
	rev = ti_mbox_reg_read(sc, TI_MBOX_REVISION);
	DPRINTF("rev %d\n", rev);
	device_printf(dev, "revision %d.%d\n", (rev >> 8) & 0x4, rev & 0x40);
	/*
	 * Enable message interrupts.
	 */
	for (chan = 0; chan < 8; chan++)
		ti_mbox_reg_write(sc, TI_MBOX_IRQENABLE_SET(chan), 1);

	return (0);
}