コード例 #1
0
ファイル: grant_table.c プロジェクト: 2asoft/freebsd
int
gnttab_resume(device_t dev)
{
	unsigned int max_nr_gframes, nr_gframes;

	nr_gframes = nr_grant_frames;
	max_nr_gframes = max_nr_grant_frames();
	if (max_nr_gframes < nr_gframes)
		return (ENOSYS);

	if (!resume_frames) {
		KASSERT(dev != NULL,
		    ("No resume frames and no device provided"));

		gnttab_pseudo_phys_res = xenmem_alloc(dev,
		    &gnttab_pseudo_phys_res_id, PAGE_SIZE * max_nr_gframes);
		if (gnttab_pseudo_phys_res == NULL)
			panic("Unable to reserve physical memory for gnttab");
		resume_frames = rman_get_start(gnttab_pseudo_phys_res);
	}

	return (gnttab_map(0, nr_gframes - 1));
}
コード例 #2
0
static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
    struct resource *r)
{
	void *vaddr;
	vm_paddr_t paddr;
	vm_size_t psize;

	/*
	 * If this is a memory resource, use pmap_mapdev to map it.
	 */
	if (type == SYS_RES_MEMORY) {
		paddr = rman_get_start(r);
		psize = rman_get_size(r);
		vaddr = pmap_mapdev(paddr, psize);

		rman_set_virtual(r, vaddr);
		rman_set_bustag(r, mips_bus_space_generic);
		rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr);
	}

	return (rman_activate_resource(r));
}
コード例 #3
0
ファイル: nexus.c プロジェクト: tomtor/freebsd
static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
	int error;

	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend here on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(res);
	if (error)
		return (error);

#ifdef INTRNG
	error = intr_setup_irq(child, res, filt, intr, arg, flags, cookiep);
#else
	error = arm_setup_intr(device_get_nameunit(child), filt, intr,
	    arg, rman_get_start(res), flags, cookiep);
#endif

	return (error);
}
コード例 #4
0
ファイル: nexus.c プロジェクト: ChaosJohn/freebsd
static int
nexus_activate_resource(device_t bus __unused, device_t child __unused,
    int type, int rid __unused, struct resource *r)
{

	if (type == SYS_RES_MEMORY) {
		vm_offset_t start;
		void *p;

		start = (vm_offset_t) rman_get_start(r);
		if (bootverbose)
			printf("nexus mapdev: start %zx, len %ld\n", start,
			    rman_get_size(r));

		p = pmap_mapdev(start, (vm_size_t) rman_get_size(r));
		if (p == NULL)
			return (ENOMEM);
		rman_set_virtual(r, p);
		rman_set_bustag(r, &bs_be_tag);
		rman_set_bushandle(r, (u_long)p);
	}
	return (rman_activate_resource(r));
}
コード例 #5
0
ファイル: nexus.c プロジェクト: ChaosJohn/freebsd
static int
nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
    void **cookiep)
{
	int error;

	if (r == NULL)
		panic("%s: NULL interrupt resource!", __func__);

	if ((rman_get_flags(r) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend here on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(r);
	if (error)
		return (error);

	error = powerpc_setup_intr(device_get_nameunit(child),
	    rman_get_start(r), filt, intr, arg, flags, cookiep);

	return (error);
}
コード例 #6
0
ファイル: xx.c プロジェクト: FreeBSDFoundation/freebsd
t_Error
XX_FreeIntr(uintptr_t irq)
{
	device_t dev;
	struct resource *r;

	r = (struct resource *)irq;
	dev = rman_get_device(r);
	irq = rman_get_start(r);

	/* Handle preallocated interrupts */
	if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) {
		if (XX_IntrInfo[irq].handler == NULL)
			return (E_INVALID_STATE);

		XX_IntrInfo[irq].handler = NULL;
		XX_IntrInfo[irq].arg = NULL;

		return (E_OK);
	}

	return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie));
}
コード例 #7
0
static int
ndis_alloc_amem(struct ndis_softc *sc)
{
	int error, rid = NDIS_AM_RID;

	sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY,
	    &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE);
	if (sc->ndis_res_am == NULL) {
		device_printf(sc->ndis_dev,
		    "failed to allocate attribute memory\n");
		return (ENXIO);
	}
	sc->ndis_rescnt++;
	resource_list_add(&sc->ndis_rl, SYS_RES_MEMORY, rid,
	    rman_get_start(sc->ndis_res_am), rman_get_end(sc->ndis_res_am),
	    rman_get_size(sc->ndis_res_am));

	error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev),
	    sc->ndis_dev, rid, 0, NULL);
	if (error) {
		device_printf(sc->ndis_dev,
		    "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error);
		return (error);
	}

	error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev),
	    sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR);
	if (error) {
		device_printf(sc->ndis_dev,
		    "CARD_SET_RES_FLAGS() returned 0x%x\n", error);
		return (error);
	}

	sc->ndis_am_rid = rid;

	return (0);
}
コード例 #8
0
static int
ata_isa_probe(device_t dev)
{
    struct resource *io = NULL, *ctlio = NULL;
    u_long tmp;
    int rid;

    /* check isapnp ids */
    if (ISA_PNP_PROBE(device_get_parent(dev), dev, ata_ids) == ENXIO)
	return ENXIO;

    /* allocate the io port range */
    rid = ATA_IOADDR_RID;
    if (!(io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
				  ATA_IOSIZE, RF_ACTIVE)))
	return ENXIO;

    /* set the altport range */
    if (bus_get_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, &tmp, &tmp)) {
	bus_set_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID,
			 rman_get_start(io) + ATA_CTLOFFSET, ATA_CTLIOSIZE);
    }

    /* allocate the altport range */
    rid = ATA_CTLADDR_RID; 
    if (!(ctlio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
				     ATA_CTLIOSIZE, RF_ACTIVE))) {
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
	return ENXIO;
    }

    /* Release resources to reallocate on attach. */
    bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlio);
    bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);

    return (ata_probe(dev));
}
コード例 #9
0
ファイル: simplebus.c プロジェクト: ornarium/freebsd
static int
simplebus_setup_intr(device_t bus, device_t child, struct resource *res,
    int flags, driver_filter_t *filter, driver_intr_t *ihand, void *arg,
    void **cookiep)
{
	struct simplebus_devinfo *di;
	enum intr_trigger trig;
	enum intr_polarity pol;
	int error, rid;

	if (device_get_parent(child) != bus)
		return (ECHILD);

	di = device_get_ivars(child);
	if (di == NULL)
		return (ENXIO);

	if (res == NULL)
		return (EINVAL);

	rid = rman_get_rid(res);
	if (rid >= DI_MAX_INTR_NUM)
		return (ENOENT);

	trig = di->di_intr_sl[rid].trig;
	pol = di->di_intr_sl[rid].pol;
	if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) {
		error = bus_generic_config_intr(bus, rman_get_start(res),
		    trig, pol);
		if (error)
			return (error);
	}

	error = bus_generic_setup_intr(bus, child, res, flags, filter, ihand,
	    arg, cookiep);
	return (error);
}
コード例 #10
0
ファイル: obio.c プロジェクト: JabirTech/Source
static int
obio_setup_intr(device_t dev, device_t child, struct resource *ires,
		int flags, driver_filter_t *filt, driver_intr_t *handler,
		void *arg, void **cookiep)
{
	struct obio_softc *sc = device_get_softc(dev);
	struct intr_event *event;
	int irq, ip_bit, error, mask, mask_register;

	irq = rman_get_start(ires);

	if (irq >= NIRQS)
		panic("%s: bad irq %d", __func__, irq);

	event = sc->sc_eventstab[irq];
	if (event == NULL) {
		error = intr_event_create(&event, (void *)irq, 0, irq, 
		    obio_mask_irq, obio_unmask_irq,
		    NULL, NULL,
		    "obio intr%d:", irq);

		sc->sc_eventstab[irq] = event;
	}

	intr_event_add_handler(event, device_get_nameunit(child), filt,
	    handler, arg, intr_priority(flags), flags, cookiep);

	/* unmask IRQ */
	mask_register = ICU_IRQ_MASK_REG(irq);
	ip_bit = ICU_IP_BIT(irq);

	mask = ICU_REG_READ(mask_register);
	ICU_REG_WRITE(mask_register, mask & ~ip_bit);

	return (0);
}
コード例 #11
0
ファイル: omap.c プロジェクト: christianrodher/freebsd-armv6
/**
 * omap_activate_resource
 *
 * 
 *
 */
static int
omap_activate_resource(device_t dev, device_t child, int type, int rid,
						 struct resource *r)
{

#if 0
	struct omap3_softc *sc = device_get_softc(dev);
	const struct hwvtrans *vtrans;
	uint32_t start = rman_get_start(r);
	uint32_t size = rman_get_size(r);
	
	if (type == SYS_RES_MEMORY) {
		vtrans = omap3_gethwvtrans(start, size);
		if (vtrans == NULL) {		/* NB: should not happen */
			device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n",
						  __func__, start, size);
			return (ENOENT);
		}
		rman_set_bustag(r, sc->sc_iot);
		rman_set_bushandle(r, vtrans->vbase + (start - vtrans->hwbase));
	}
#endif
	return (rman_activate_resource(r));
}
コード例 #12
0
ファイル: iobus.c プロジェクト: AhmadTux/freebsd
static int
iobus_activate_resource(device_t bus, device_t child, int type, int rid,
			   struct resource *res)
{
	struct iobus_softc *sc;
	void    *p;

	sc = device_get_softc(bus);

	if (type == SYS_RES_IRQ)
                return (bus_activate_resource(bus, type, rid, res));

	if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
		p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_addr,
				(vm_size_t)rman_get_size(res));
		if (p == NULL)
			return (ENOMEM);
		rman_set_virtual(res, p);
		rman_set_bustag(res, &bs_le_tag);
		rman_set_bushandle(res, (u_long)p);
	}

	return (rman_activate_resource(res));
}
コード例 #13
0
ファイル: nexus.c プロジェクト: FreeBSDFoundation/freebsd
static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
    struct resource *r)
{
	int err;
	bus_addr_t paddr;
	bus_size_t psize;
	bus_space_handle_t vaddr;

	if ((err = rman_activate_resource(r)) != 0)
		return (err);

	/*
	 * If this is a memory resource, map it into the kernel.
	 */
	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
		paddr = (bus_addr_t)rman_get_start(r);
		psize = (bus_size_t)rman_get_size(r);
		err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr);
		if (err != 0) {
			rman_deactivate_resource(r);
			return (err);
		}
		rman_set_bustag(r, &memmap_bus);
		rman_set_virtual(r, (void *)vaddr);
		rman_set_bushandle(r, vaddr);
	} else if (type == SYS_RES_IRQ) {
		err = intr_activate_irq(child, r);
		if (err != 0) {
			rman_deactivate_resource(r);
			return (err);
		}
	}

	return (0);
}
コード例 #14
0
ファイル: pxa_smi.c プロジェクト: AhmadTux/freebsd
static int
pxa_smi_attach(device_t dev)
{
	int		error, i, dunit;
	const char	*dname;
	struct		pxa_smi_softc *sc;

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

	error = bus_alloc_resources(dev, pxa_smi_spec, sc->ps_res);
	if (error) {
		device_printf(dev, "could not allocate resources\n");
		return (ENXIO);
	}

	sc->ps_mem.rm_type = RMAN_ARRAY;
	sc->ps_mem.rm_descr = device_get_nameunit(dev);
	if (rman_init(&sc->ps_mem) != 0)
		panic("pxa_smi_attach: failed to init mem rman");
	if (rman_manage_region(&sc->ps_mem, 0, PXA2X0_CS_SIZE * 6) != 0)
		panic("pxa_smi_attach: failed ot set up mem rman");

	sc->ps_bst = base_tag;
	sc->ps_base = rman_get_start(sc->ps_res[0]);

	i = 0;
	while (resource_find_match(&i, &dname, &dunit, "at",
	    device_get_nameunit(dev)) == 0) {
		pxa_smi_add_device(dev, dname, dunit);
	}

	bus_generic_probe(dev);
	bus_generic_attach(dev);

	return (0);
}
コード例 #15
0
ファイル: nexus.c プロジェクト: ornarium/freebsd
static int
nexus_setup_intr(device_t bus, device_t child, struct resource *res, int flags,
    driver_filter_t *ifilt, driver_intr_t *ihand, void *arg, void **cookiep)
{
	int error;

	*cookiep = NULL;

	/* somebody tried to setup an irq that failed to allocate! */
	if (res == NULL)
		return (EINVAL);

	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
		flags |= INTR_EXCL;

	/* We depend on rman_activate_resource() being idempotent. */
	error = rman_activate_resource(res);
	if (error)
		return (error);

	error = powerpc_setup_intr(device_get_nameunit(child),
	    rman_get_start(res), ifilt, ihand, arg, flags, cookiep);
	return (error);
}
コード例 #16
0
ファイル: if_smc.c プロジェクト: dcui/FreeBSD-9.3_kernel
int
smc_probe(device_t dev)
{
	int			rid, type, error;
	uint16_t		val;
	struct smc_softc	*sc;
	struct resource		*reg;

	sc = device_get_softc(dev);
	rid = 0;
	type = SYS_RES_IOPORT;
	error = 0;

	if (sc->smc_usemem)
		type = SYS_RES_MEMORY;

	reg = bus_alloc_resource(dev, type, &rid, 0, ~0, 16, RF_ACTIVE);
	if (reg == NULL) {
		if (bootverbose)
			device_printf(dev,
			    "could not allocate I/O resource for probe\n");
		return (ENXIO);
	}

	/* Check for the identification value in the BSR. */
	val = bus_read_2(reg, BSR);
	if ((val & BSR_IDENTIFY_MASK) != BSR_IDENTIFY) {
		if (bootverbose)
			device_printf(dev, "identification value not in BSR\n");
		error = ENXIO;
		goto done;
	}

	/*
	 * Try switching banks and make sure we still get the identification
	 * value.
	 */
	bus_write_2(reg, BSR, 0);
	val = bus_read_2(reg, BSR);
	if ((val & BSR_IDENTIFY_MASK) != BSR_IDENTIFY) {
		if (bootverbose)
			device_printf(dev,
			    "identification value not in BSR after write\n");
		error = ENXIO;
		goto done;
	}

#if 0
	/* Check the BAR. */
	bus_write_2(reg, BSR, 1);
	val = bus_read_2(reg, BAR);
	val = BAR_ADDRESS(val);
	if (rman_get_start(reg) != val) {
		if (bootverbose)
			device_printf(dev, "BAR address %x does not match "
			    "I/O resource address %lx\n", val,
			    rman_get_start(reg));
		error = ENXIO;
		goto done;
	}
#endif

	/* Compare REV against known chip revisions. */
	bus_write_2(reg, BSR, 3);
	val = bus_read_2(reg, REV);
	val = (val & REV_CHIP_MASK) >> REV_CHIP_SHIFT;
	if (smc_chip_ids[val] == NULL) {
		if (bootverbose)
			device_printf(dev, "Unknown chip revision: %d\n", val);
		error = ENXIO;
		goto done;
	}

	device_set_desc(dev, smc_chip_ids[val]);

done:
	bus_release_resource(dev, type, rid, reg);
	return (error);
}
コード例 #17
0
ファイル: aha_isa.c プロジェクト: derekmarcotte/freebsd
/*
 * Attach all the sub-devices we can find
 */
static int
aha_isa_attach(device_t dev)
{
	struct	aha_softc *aha = device_get_softc(dev);
	int		 error = ENOMEM;

	aha->dev = dev;
	aha->portrid = 0;
	aha->port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
	    &aha->portrid, AHA_NREGS, RF_ACTIVE);
	if (!aha->port) {
		device_printf(dev, "Unable to allocate I/O ports\n");
		goto fail;
	}

	aha->irqrid = 0;
	aha->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &aha->irqrid,
	    RF_ACTIVE);
	if (!aha->irq) {
		device_printf(dev, "Unable to allocate excluse use of irq\n");
		goto fail;
	}

	aha->drqrid = 0;
	aha->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &aha->drqrid,
	    RF_ACTIVE);
	if (!aha->drq) {
		device_printf(dev, "Unable to allocate drq\n");
		goto fail;
	}

#if 0				/* is the drq ever unset? */
	if (dev->id_drq != -1)
		isa_dmacascade(dev->id_drq);
#endif
	isa_dmacascade(rman_get_start(aha->drq));

	/* Allocate our parent dmatag */
	if (bus_dma_tag_create(	/* parent	*/ bus_get_dma_tag(dev),
				/* alignemnt	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ BUS_SPACE_MAXADDR_24BIT,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ BUS_SPACE_MAXSIZE_24BIT,
				/* nsegments	*/ ~0,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&aha->parent_dmat) != 0) {
		device_printf(dev, "dma tag create failed.\n");
		goto fail;
        }                              

	if (aha_init(aha)) {
		device_printf(dev, "init failed\n");
		goto fail;
        }
	/*
	 * The 1542A and B look the same.  So we guess based on
	 * the firmware revision.  It appears that only rev 0 is on
	 * the A cards.
	 */
	if (aha->boardid <= BOARD_1542 && aha->fw_major == 0) {
		device_printf(dev, "154xA may not work\n");
		aha->ccb_sg_opcode = INITIATOR_SG_CCB;
		aha->ccb_ccb_opcode = INITIATOR_CCB;
	}
	
	error = aha_attach(aha);
	if (error) {
		device_printf(dev, "attach failed\n");
		goto fail;
	}

	error = bus_setup_intr(dev, aha->irq, INTR_TYPE_CAM|INTR_ENTROPY|
	    INTR_MPSAFE, NULL, aha_intr, aha, &aha->ih);
	if (error) {
		device_printf(dev, "Unable to register interrupt handler\n");
		aha_detach(aha);
                goto fail;
	}

	return (0);
fail: ;
	aha_free(aha);
	bus_free_resource(dev, SYS_RES_IOPORT, aha->port);
	bus_free_resource(dev, SYS_RES_IRQ, aha->irq);
	bus_free_resource(dev, SYS_RES_DRQ, aha->drq);
	return (error);
}
コード例 #18
0
ファイル: aha_isa.c プロジェクト: derekmarcotte/freebsd
/*
 * Check if the device can be found at the port given
 */
static int
aha_isa_probe(device_t dev)
{
	/*
	 * find unit and check we have that many defined
	 */
	struct	aha_softc *aha = device_get_softc(dev);
	int	error;
	u_long	port_start;
	int	port_rid;
	int	drq;
	int	irq;
	config_data_t config_data;

	aha->dev = dev;
	/* Check isapnp ids */
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, aha_ids) == ENXIO)
		return (ENXIO);

	port_rid = 0;
	aha->port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &port_rid,
	    AHA_NREGS, RF_ACTIVE);

	if (aha->port == NULL)
		return (ENXIO);

	port_start = rman_get_start(aha->port);
	aha_alloc(aha);

	/* See if there is really a card present */
	if (aha_probe(aha) || aha_fetch_adapter_info(aha)) {
		aha_free(aha);
		bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port);
		return (ENXIO);
	}

	/*
	 * Determine our IRQ, and DMA settings and
	 * export them to the configuration system.
	 */
	error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
	    (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT);

	if (error != 0) {
		device_printf(dev, "Could not determine IRQ or DMA "
		    "settings for adapter at %#jx.  Failing probe\n",
		    (uintmax_t)port_start);
		aha_free(aha);
		bus_release_resource(dev, SYS_RES_IOPORT, port_rid,
		    aha->port);
		return (ENXIO);
	}

	bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port);
	aha->port = NULL;

	switch (config_data.dma_chan) {
	case DMA_CHAN_5:
		drq = 5;
		break;
	case DMA_CHAN_6:
		drq = 6;
		break;
	case DMA_CHAN_7:
		drq = 7;
		break;
	default:
		device_printf(dev, "Invalid DMA setting for adapter at %#jx.",
		    (uintmax_t)port_start);
		return (ENXIO);
	}
	error = bus_set_resource(dev, SYS_RES_DRQ, 0, drq, 1);
	if (error)
		return error;

	irq = ffs(config_data.irq) + 8;
	error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
	return (error);
}
コード例 #19
0
ファイル: i4b_isic_pnp.c プロジェクト: MarginC/kame
/*---------------------------------------------------------------------------*
 *      attach for ISA PnP cards
 *---------------------------------------------------------------------------*/
static int
isic_pnp_attach(device_t dev)
{
	u_int32_t vend_id = isa_get_vendorid(dev);	/* vendor id */
	unsigned int unit = device_get_unit(dev);	/* get unit */
	const char *name = device_get_desc(dev);	/* get description */
	struct l1_softc *sc = 0;			/* softc */
	void *ih = 0;					/* a dummy */
	int ret;
 
	/* see if we are out of bounds */
	
	if(unit >= ISIC_MAXUNIT)
	{
		printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n", unit, unit, name);
		return ENXIO;
	}

	/* get information structure for this unit */

	sc = &l1_sc[unit];

	/* get io_base */
	if(!(sc->sc_resources.io_base[0] =
			bus_alloc_resource(dev, SYS_RES_IOPORT,
						&sc->sc_resources.io_rid[0],
						0UL, ~0UL, 1, RF_ACTIVE ) ))
	{
		printf("isic_pnp_attach: Couldn't get my io_base.\n");
		return ENXIO;                                       
	}
	
	/* will not be used for pnp devices */

	sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);

	/* get irq, release io_base if we don't get it */

	if(!(sc->sc_resources.irq =
			bus_alloc_resource(dev, SYS_RES_IRQ,
					   &sc->sc_resources.irq_rid,
					   0UL, ~0UL, 1, RF_ACTIVE)))
	{
		printf("isic%d: Could not get irq.\n",unit);
		isic_detach_common(dev);
		return ENXIO;                                       
	}
	
	/* not needed */
	sc->sc_irq = rman_get_start(sc->sc_resources.irq);


	/* set flag so we know what this card is */

	ret = ENXIO;
	
	switch(vend_id)
	{
#if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P) || defined(COMPAQ_M610)
		case VID_TEL163PNP:
			sc->sc_cardtyp = CARD_TYPEP_163P;
			ret = isic_attach_Cs0P(dev);
			break;

		case VID_CREATIXPP:
			sc->sc_cardtyp = CARD_TYPEP_CS0P;
			ret = isic_attach_Cs0P(dev);
			break;

		case VID_COMPAQ_M610:
			sc->sc_cardtyp = CARD_TYPEP_COMPAQ_M610;
			ret = isic_attach_Cs0P(dev);
			break;
#endif
#ifdef DYNALINK
		case VID_DYNALINK:
			sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
			ret = isic_attach_Dyn(dev);
			break;
#endif
#ifdef SEDLBAUER
		case VID_SEDLBAUER:
			sc->sc_cardtyp = CARD_TYPEP_SWS;
			ret = isic_attach_sws(dev);
			break;
#endif
#ifdef DRN_NGO
		case VID_NICCYGO:
			sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
			ret = isic_attach_drnngo(dev);
			break;
#endif
#ifdef ELSA_QS1ISA
		case VID_ELSAQS1P:
			sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
			ret = isic_attach_Eqs1pi(dev);
			break;
#endif
#ifdef ITKIX1
		case VID_ITK0025:
			sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
			ret = isic_attach_itkix1(dev);
			break;
#endif			
#ifdef SIEMENS_ISURF2
		case VID_SIESURF2:
			sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2;
			ret = isic_attach_siemens_isurf(dev);
			break;
#endif
#ifdef ASUSCOM_IPAC
		case VID_ASUSCOM_IPAC:
			sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC;
			ret = isic_attach_asi(dev);
			break;
#endif
#ifdef EICON_DIVA
		case VID_EICON_DIVA_20:
			sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA;
			ret = isic_attach_diva(dev);
			break;
		
		case VID_EICON_DIVA_202:
			sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA;
			ret = isic_attach_diva_ipac(dev);
			break;
#endif
		default:
			printf("isic%d: Error, no driver for %s\n", unit, name);
			ret = ENXIO;
			break;		
	}

	if(ret)
	{
		isic_detach_common(dev);
		return ENXIO;                                       
	}		
		
	if(isic_attach_common(dev))
	{
		/* unset flag */
		sc->sc_cardtyp = CARD_TYPEP_UNK;

		/* free irq here, it hasn't been attached yet */
		bus_release_resource(dev,SYS_RES_IRQ,sc->sc_resources.irq_rid,
					sc->sc_resources.irq);
		sc->sc_resources.irq = 0;
		isic_detach_common(dev);
		return ENXIO;
	}
	else
	{
		/* setup intr routine */
		bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET,
				(void(*)(void*))isicintr,
				sc,&ih);
		return 0;
	}
}
コード例 #20
0
ファイル: pci_user.c プロジェクト: madhavsuresh/DragonFlyBSD
static int
pci_ioctl(struct dev_ioctl_args *ap)
{
	device_t pcidev, brdev;
	void *confdata;
	const char *name;
	struct devlist *devlist_head;
	struct pci_conf_io *cio;
	struct pci_devinfo *dinfo;
	struct pci_io *io;
	struct pci_bar_io *bio;
	struct pci_match_conf *pattern_buf;
	struct resource_list_entry *rle;
	uint32_t value;
	size_t confsz, iolen, pbufsz;
	int error, ionum, i, num_patterns;
#ifdef PRE7_COMPAT
	struct pci_conf_old conf_old;
	struct pci_io iodata;
	struct pci_io_old *io_old;
	struct pci_match_conf_old *pattern_buf_old;

	io_old = NULL;
	pattern_buf_old = NULL;

	if (!(ap->a_fflag & FWRITE) && ap->a_cmd != PCIOCGETBAR &&
	    ap->a_cmd != PCIOCGETCONF && ap->a_cmd != PCIOCGETCONF_OLD)
		return EPERM;
#else
	if (!(ap->a_fflag & FWRITE) && ap->a_cmd != PCIOCGETBAR && ap->a_cmd != PCIOCGETCONF)
		return EPERM;
#endif

	switch(ap->a_cmd) {
#ifdef PRE7_COMPAT
	case PCIOCGETCONF_OLD:
		/* FALLTHROUGH */
#endif
	case PCIOCGETCONF:
		cio = (struct pci_conf_io *)ap->a_data;

		pattern_buf = NULL;
		num_patterns = 0;
		dinfo = NULL;

		cio->num_matches = 0;

		/*
		 * If the user specified an offset into the device list,
		 * but the list has changed since they last called this
		 * ioctl, tell them that the list has changed.  They will
		 * have to get the list from the beginning.
		 */
		if ((cio->offset != 0)
		 && (cio->generation != pci_generation)){
			cio->status = PCI_GETCONF_LIST_CHANGED;
			error = 0;
			break;
		}

		/*
		 * Check to see whether the user has asked for an offset
		 * past the end of our list.
		 */
		if (cio->offset >= pci_numdevs) {
			cio->status = PCI_GETCONF_LAST_DEVICE;
			error = 0;
			break;
		}

		/* get the head of the device queue */
		devlist_head = &pci_devq;

		/*
		 * Determine how much room we have for pci_conf structures.
		 * Round the user's buffer size down to the nearest
		 * multiple of sizeof(struct pci_conf) in case the user
		 * didn't specify a multiple of that size.
		 */
#ifdef PRE7_COMPAT
		if (ap->a_cmd == PCIOCGETCONF_OLD)
			confsz = sizeof(struct pci_conf_old);
		else
#endif
			confsz = sizeof(struct pci_conf);
		iolen = min(cio->match_buf_len - (cio->match_buf_len % confsz),
		    pci_numdevs * confsz);

		/*
		 * Since we know that iolen is a multiple of the size of
		 * the pciconf union, it's okay to do this.
		 */
		ionum = iolen / confsz;

		/*
		 * If this test is true, the user wants the pci_conf
		 * structures returned to match the supplied entries.
		 */
		if ((cio->num_patterns > 0) && (cio->num_patterns < pci_numdevs)
		 && (cio->pat_buf_len > 0)) {
			/*
			 * pat_buf_len needs to be:
			 * num_patterns * sizeof(struct pci_match_conf)
			 * While it is certainly possible the user just
			 * allocated a large buffer, but set the number of
			 * matches correctly, it is far more likely that
			 * their kernel doesn't match the userland utility
			 * they're using.  It's also possible that the user
			 * forgot to initialize some variables.  Yes, this
			 * may be overly picky, but I hazard to guess that
			 * it's far more likely to just catch folks that
			 * updated their kernel but not their userland.
			 */
#ifdef PRE7_COMPAT
			if (ap->a_cmd == PCIOCGETCONF_OLD)
				pbufsz = sizeof(struct pci_match_conf_old);
			else
#endif
				pbufsz = sizeof(struct pci_match_conf);
			if (cio->num_patterns * pbufsz != cio->pat_buf_len) {
				/* The user made a mistake, return an error. */
				cio->status = PCI_GETCONF_ERROR;
				error = EINVAL;
				break;
			}

			/*
			 * Allocate a buffer to hold the patterns.
			 */
#ifdef PRE7_COMPAT
			if (ap->a_cmd == PCIOCGETCONF_OLD) {
				pattern_buf_old = kmalloc(cio->pat_buf_len,
				    M_TEMP, M_WAITOK);
				error = copyin(cio->patterns,
				    pattern_buf_old, cio->pat_buf_len);
			} else
#endif
			{
				pattern_buf = kmalloc(cio->pat_buf_len, M_TEMP,
				    M_WAITOK);
				error = copyin(cio->patterns, pattern_buf,
				    cio->pat_buf_len);
			}
			if (error != 0) {
				error = EINVAL;
				goto getconfexit;
			}
			num_patterns = cio->num_patterns;
		} else if ((cio->num_patterns > 0)
			|| (cio->pat_buf_len > 0)) {
			/*
			 * The user made a mistake, spit out an error.
			 */
			cio->status = PCI_GETCONF_ERROR;
			error = EINVAL;
			break;
		}

		/*
		 * Go through the list of devices and copy out the devices
		 * that match the user's criteria.
		 */
		for (cio->num_matches = 0, error = 0, i = 0,
		     dinfo = STAILQ_FIRST(devlist_head);
		     (dinfo != NULL) && (cio->num_matches < ionum)
		     && (error == 0) && (i < pci_numdevs) && (dinfo != NULL);
		     dinfo = STAILQ_NEXT(dinfo, pci_links), i++) {

			if (i < cio->offset)
				continue;

			/* Populate pd_name and pd_unit */
			name = NULL;
			if (dinfo->cfg.dev)
				name = device_get_name(dinfo->cfg.dev);
			if (name) {
				strncpy(dinfo->conf.pd_name, name,
					sizeof(dinfo->conf.pd_name));
				dinfo->conf.pd_name[PCI_MAXNAMELEN] = 0;
				dinfo->conf.pd_unit =
					device_get_unit(dinfo->cfg.dev);
			} else {
				dinfo->conf.pd_name[0] = '\0';
				dinfo->conf.pd_unit = 0;
			}

#ifdef PRE7_COMPAT
			if ((ap->a_cmd == PCIOCGETCONF_OLD &&
			    (pattern_buf_old == NULL ||
			    pci_conf_match_old(pattern_buf_old, num_patterns,
			    &dinfo->conf) == 0)) ||
			    (ap->a_cmd == PCIOCGETCONF &&
			    (pattern_buf == NULL ||
			    pci_conf_match(pattern_buf, num_patterns,
			    &dinfo->conf) == 0))) {
#else
			if (pattern_buf == NULL ||
			    pci_conf_match(pattern_buf, num_patterns,
			    &dinfo->conf) == 0) {
#endif
				/*
				 * If we've filled up the user's buffer,
				 * break out at this point.  Since we've
				 * got a match here, we'll pick right back
				 * up at the matching entry.  We can also
				 * tell the user that there are more matches
				 * left.
				 */
				if (cio->num_matches >= ionum)
					break;

#ifdef PRE7_COMPAT
				if (ap->a_cmd == PCIOCGETCONF_OLD) {
					conf_old.pc_sel.pc_bus =
					    dinfo->conf.pc_sel.pc_bus;
					conf_old.pc_sel.pc_dev =
					    dinfo->conf.pc_sel.pc_dev;
					conf_old.pc_sel.pc_func =
					    dinfo->conf.pc_sel.pc_func;
					conf_old.pc_hdr = dinfo->conf.pc_hdr;
					conf_old.pc_subvendor =
					    dinfo->conf.pc_subvendor;
					conf_old.pc_subdevice =
					    dinfo->conf.pc_subdevice;
					conf_old.pc_vendor =
					    dinfo->conf.pc_vendor;
					conf_old.pc_device =
					    dinfo->conf.pc_device;
					conf_old.pc_class =
					    dinfo->conf.pc_class;
					conf_old.pc_subclass =
					    dinfo->conf.pc_subclass;
					conf_old.pc_progif =
					    dinfo->conf.pc_progif;
					conf_old.pc_revid =
					    dinfo->conf.pc_revid;
					strncpy(conf_old.pd_name,
					    dinfo->conf.pd_name,
					    sizeof(conf_old.pd_name));
					conf_old.pd_name[PCI_MAXNAMELEN] = 0;
					conf_old.pd_unit =
					    dinfo->conf.pd_unit;
					confdata = &conf_old;
				} else
#endif
					confdata = &dinfo->conf;
				/* Only if we can copy it out do we count it. */
				if (!(error = copyout(confdata,
				    (caddr_t)cio->matches +
				    confsz * cio->num_matches, confsz)))
					cio->num_matches++;
			}
		}

		/*
		 * Set the pointer into the list, so if the user is getting
		 * n records at a time, where n < pci_numdevs,
		 */
		cio->offset = i;

		/*
		 * Set the generation, the user will need this if they make
		 * another ioctl call with offset != 0.
		 */
		cio->generation = pci_generation;

		/*
		 * If this is the last device, inform the user so he won't
		 * bother asking for more devices.  If dinfo isn't NULL, we
		 * know that there are more matches in the list because of
		 * the way the traversal is done.
		 */
		if (dinfo == NULL)
			cio->status = PCI_GETCONF_LAST_DEVICE;
		else
			cio->status = PCI_GETCONF_MORE_DEVS;

getconfexit:
		if (pattern_buf != NULL)
			kfree(pattern_buf, M_TEMP);
#ifdef PRE7_COMPAT
		if (pattern_buf_old != NULL)
			kfree(pattern_buf_old, M_TEMP);
#endif

		break;

#ifdef PRE7_COMPAT
	case PCIOCREAD_OLD:
	case PCIOCWRITE_OLD:
		io_old = (struct pci_io_old *)ap->a_data;
		iodata.pi_sel.pc_domain = 0;
		iodata.pi_sel.pc_bus = io_old->pi_sel.pc_bus;
		iodata.pi_sel.pc_dev = io_old->pi_sel.pc_dev;
		iodata.pi_sel.pc_func = io_old->pi_sel.pc_func;
		iodata.pi_reg = io_old->pi_reg;
		iodata.pi_width = io_old->pi_width;
		iodata.pi_data = io_old->pi_data;
		ap->a_data = (caddr_t)&iodata;
		/* FALLTHROUGH */
#endif
	case PCIOCREAD:
	case PCIOCWRITE:
		io = (struct pci_io *)ap->a_data;
		switch(io->pi_width) {
		case 4:
		case 2:
		case 1:
			/* Make sure register is in bounds and aligned. */
			if (io->pi_reg < 0 ||
			    io->pi_reg + io->pi_width > PCI_REGMAX + 1 ||
			    io->pi_reg & (io->pi_width - 1)) {
				error = EINVAL;
				break;
			}
			/*
			 * Assume that the user-level bus number is
			 * in fact the physical PCI bus number.
			 * Look up the grandparent, i.e. the bridge device,
			 * so that we can issue configuration space cycles.
			 */
			pcidev = pci_find_dbsf(io->pi_sel.pc_domain,
			    io->pi_sel.pc_bus, io->pi_sel.pc_dev,
			    io->pi_sel.pc_func);
			if (pcidev) {
				brdev = device_get_parent(
				    device_get_parent(pcidev));

#ifdef PRE7_COMPAT
				if (ap->a_cmd == PCIOCWRITE || ap->a_cmd == PCIOCWRITE_OLD)
#else
				if (ap->a_cmd == PCIOCWRITE)
#endif
					PCIB_WRITE_CONFIG(brdev,
							  io->pi_sel.pc_bus,
							  io->pi_sel.pc_dev,
							  io->pi_sel.pc_func,
							  io->pi_reg,
							  io->pi_data,
							  io->pi_width);
#ifdef PRE7_COMPAT
				else if (ap->a_cmd == PCIOCREAD_OLD)
					io_old->pi_data =
						PCIB_READ_CONFIG(brdev,
							  io->pi_sel.pc_bus,
							  io->pi_sel.pc_dev,
							  io->pi_sel.pc_func,
							  io->pi_reg,
							  io->pi_width);
#endif
				else
					io->pi_data =
						PCIB_READ_CONFIG(brdev,
							  io->pi_sel.pc_bus,
							  io->pi_sel.pc_dev,
							  io->pi_sel.pc_func,
							  io->pi_reg,
							  io->pi_width);
				error = 0;
			} else {
#ifdef COMPAT_FREEBSD4
				if (cmd == PCIOCREAD_OLD) {
					io_old->pi_data = -1;
					error = 0;
				} else
#endif
					error = ENODEV;
			}
			break;
		default:
			error = EINVAL;
			break;
		}
		break;

	case PCIOCGETBAR:
		bio = (struct pci_bar_io *)ap->a_data;

		/*
		 * Assume that the user-level bus number is
		 * in fact the physical PCI bus number.
		 */
		pcidev = pci_find_dbsf(bio->pbi_sel.pc_domain,
		    bio->pbi_sel.pc_bus, bio->pbi_sel.pc_dev,
		    bio->pbi_sel.pc_func);
		if (pcidev == NULL) {
			error = ENODEV;
			break;
		}
		dinfo = device_get_ivars(pcidev);
		
		/*
		 * Look for a resource list entry matching the requested BAR.
		 *
		 * XXX: This will not find BARs that are not initialized, but
		 * maybe that is ok?
		 */
		rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
		    bio->pbi_reg);
		if (rle == NULL)
			rle = resource_list_find(&dinfo->resources,
			    SYS_RES_IOPORT, bio->pbi_reg);
		if (rle == NULL || rle->res == NULL) {
			error = EINVAL;
			break;
		}

		/*
		 * Ok, we have a resource for this BAR.  Read the lower
		 * 32 bits to get any flags.
		 */
		value = pci_read_config(pcidev, bio->pbi_reg, 4);
		if (PCI_BAR_MEM(value)) {
			if (rle->type != SYS_RES_MEMORY) {
				error = EINVAL;
				break;
			}
			value &= ~PCIM_BAR_MEM_BASE;
		} else {
			if (rle->type != SYS_RES_IOPORT) {
				error = EINVAL;
				break;
			}
			value &= ~PCIM_BAR_IO_BASE;
		}
		bio->pbi_base = rman_get_start(rle->res) | value;
		bio->pbi_length = rman_get_size(rle->res);

		/*
		 * Check the command register to determine if this BAR
		 * is enabled.
		 */
		value = pci_read_config(pcidev, PCIR_COMMAND, 2);
		if (rle->type == SYS_RES_MEMORY)
			bio->pbi_enabled = (value & PCIM_CMD_MEMEN) != 0;
		else
			bio->pbi_enabled = (value & PCIM_CMD_PORTEN) != 0;
		error = 0;
		break;
	default:
		error = ENOTTY;
		break;
	}

	return (error);
}


#define PCI_CDEV        78
struct dev_ops pcic_ops = {
        { "pci", PCI_CDEV, 0 },
        .d_open =       pci_open,
        .d_close =      pci_close,
        .d_ioctl =      pci_ioctl,
};
コード例 #21
0
ファイル: cs4281.c プロジェクト: dcui/FreeBSD-9.3_kernel
static int
cs4281_pci_attach(device_t dev)
{
    struct sc_info *sc;
    struct ac97_info *codec = NULL;
    char status[SND_STATUSLEN];

    sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
    sc->dev = dev;
    sc->type = pci_get_devid(dev);

    pci_enable_busmaster(dev);

#if __FreeBSD_version > 500000
    if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
	/* Reset the power state. */
	device_printf(dev, "chip is in D%d power mode "
		      "-- setting to D0\n", pci_get_powerstate(dev));

	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
    }
#else
    data = pci_read_config(dev, CS4281PCI_PMCS_OFFSET, 4);
    if (data & CS4281PCI_PMCS_PS_MASK) {
	    /* Reset the power state. */
	    device_printf(dev, "chip is in D%d power mode "
			  "-- setting to D0\n",
			  data & CS4281PCI_PMCS_PS_MASK);
	    pci_write_config(dev, CS4281PCI_PMCS_OFFSET,
			     data & ~CS4281PCI_PMCS_PS_MASK, 4);
    }
#endif

    sc->regid   = PCIR_BAR(0);
    sc->regtype = SYS_RES_MEMORY;
    sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
				 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
    if (!sc->reg) {
	sc->regtype = SYS_RES_IOPORT;
	sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
				     0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
	if (!sc->reg) {
	    device_printf(dev, "unable to allocate register space\n");
	    goto bad;
	}
    }
    sc->st = rman_get_bustag(sc->reg);
    sc->sh = rman_get_bushandle(sc->reg);

    sc->memid = PCIR_BAR(1);
    sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0,
				 ~0, CS4281PCI_BA1_SIZE, RF_ACTIVE);
    if (sc->mem == NULL) {
	device_printf(dev, "unable to allocate fifo space\n");
	goto bad;
    }

    sc->irqid = 0;
    sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
				     RF_ACTIVE | RF_SHAREABLE);
    if (!sc->irq) {
	device_printf(dev, "unable to allocate interrupt\n");
	goto bad;
    }

    if (snd_setup_intr(dev, sc->irq, 0, cs4281_intr, sc, &sc->ih)) {
	device_printf(dev, "unable to setup interrupt\n");
	goto bad;
    }

    sc->bufsz = pcm_getbuffersize(dev, 4096, CS4281_DEFAULT_BUFSZ, 65536);

    if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
			   /*boundary*/0,
			   /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
			   /*highaddr*/BUS_SPACE_MAXADDR,
			   /*filter*/NULL, /*filterarg*/NULL,
			   /*maxsize*/sc->bufsz, /*nsegments*/1,
			   /*maxsegz*/0x3ffff,
			   /*flags*/0, /*lockfunc*/busdma_lock_mutex,
			   /*lockarg*/&Giant, &sc->parent_dmat) != 0) {
	device_printf(dev, "unable to create dma tag\n");
	goto bad;
    }

    /* power up */
    cs4281_power(sc, 0);

    /* init chip */
    if (cs4281_init(sc) == -1) {
	device_printf(dev, "unable to initialize the card\n");
	goto bad;
    }

    /* create/init mixer */
    codec = AC97_CREATE(dev, sc, cs4281_ac97);
    if (codec == NULL)
        goto bad;

    mixer_init(dev, ac97_getmixerclass(), codec);

    if (pcm_register(dev, sc, 1, 1))
	goto bad;

    pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc);
    pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc);

    snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
	     (sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
	     rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cs4281));
    pcm_setstatus(dev, status);

    return 0;

 bad:
    if (codec)
	ac97_destroy(codec);
    if (sc->reg)
	bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
    if (sc->mem)
	bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem);
    if (sc->ih)
	bus_teardown_intr(dev, sc->irq, sc->ih);
    if (sc->irq)
	bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
    if (sc->parent_dmat)
	bus_dma_tag_destroy(sc->parent_dmat);
    free(sc, M_DEVBUF);

    return ENXIO;
}
コード例 #22
0
ファイル: ata-all.c プロジェクト: UnitedMarsupials/kame
int
ata_command(struct ata_device *atadev, u_int8_t command,
	   u_int64_t lba, u_int16_t count, u_int8_t feature, int flags)
{
    int error = 0;
#ifdef ATA_DEBUG
    ata_prtdev(atadev, "ata_command: addr=%04lx, cmd=%02x, "
	       "lba=%lld, count=%d, feature=%d, flags=%02x\n",
	       rman_get_start(atadev->channel->r_io), 
	       command, lba, count, feature, flags);
#endif

    /* select device */
    ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit);

    /* disable interrupt from device */
    if (atadev->channel->flags & ATA_QUEUED)
	ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT);

    /* ready to issue command ? */
    if (ata_wait(atadev, 0) < 0) { 
	ata_prtdev(atadev, "timeout sending command=%02x s=%02x e=%02x\n",
		   command, atadev->channel->status, atadev->channel->error);
	return -1;
    }

    /* only use 48bit addressing if needed because of the overhead */
    if ((lba >= 268435455 || count > 256) && atadev->param &&
	atadev->param->support.address48) {
	ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, (feature>>8) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature);
	ATA_OUTB(atadev->channel->r_io, ATA_COUNT, (count>>8) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, (lba>>24) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>32) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>40) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff);
	ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_LBA | atadev->unit);

	/* translate command into 48bit version */
	switch (command) {
	case ATA_C_READ:
	    command = ATA_C_READ48; break;
	case ATA_C_READ_MUL:
	    command = ATA_C_READ_MUL48; break;
	case ATA_C_READ_DMA:
	    command = ATA_C_READ_DMA48; break;
	case ATA_C_READ_DMA_QUEUED:
	    command = ATA_C_READ_DMA_QUEUED48; break;
	case ATA_C_WRITE:
	    command = ATA_C_WRITE48; break;
	case ATA_C_WRITE_MUL:
	    command = ATA_C_WRITE_MUL48; break;
	case ATA_C_WRITE_DMA:
	    command = ATA_C_WRITE_DMA48; break;
	case ATA_C_WRITE_DMA_QUEUED:
	    command = ATA_C_WRITE_DMA_QUEUED48; break;
	case ATA_C_FLUSHCACHE:
	    command = ATA_C_FLUSHCACHE48; break;
	default:
	    ata_prtdev(atadev, "can't translate cmd to 48bit version\n");
	    return -1;
	}
    }
コード例 #23
0
ファイル: ppc.c プロジェクト: MarginC/kame
int
ppc_probe(device_t dev)
{
#ifdef __i386__
	static short next_bios_ppc = 0;
#endif
	struct ppc_data *ppc;
	int error;
	u_long port;

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

	ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0;
	ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0;

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

#ifdef __i386__
	/*
	 * If port not specified, use bios list.
	 */
	if (error) {
		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%x\n",
					(int) port);
		} else {
			device_printf(dev, "parallel port not found.\n");
			return ENXIO;
		}
		bus_set_resource(dev, SYS_RES_IOPORT, 0, port,
				 IO_LPTSIZE_EXTENDED);
	}
#endif
#ifdef __alpha__
	/*
	 * There isn't a bios list on alpha. Put it in the usual place.
	 */
	if (error) {
		bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc,
				 IO_LPTSIZE_NORMAL);
	}
#endif

	/* IO port is mandatory */

	/* Try "extended" IO port range...*/
	ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
					     &ppc->rid_ioport, 0, ~0,
					     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(dev, SYS_RES_IOPORT,
						      &ppc->rid_ioport, 0, ~0,
						      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->bsh = rman_get_bushandle(ppc->res_ioport);
	ppc->bst = rman_get_bustag(ppc->res_ioport);

	ppc->ppc_flags = device_get_flags(dev);

	if (!(ppc->ppc_flags & 0x20)) {
		ppc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ppc->rid_irq,
						  0ul, ~0ul, 1, RF_SHAREABLE);
		ppc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, &ppc->rid_drq,
						  0ul, ~0ul, 1, 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_unit = device_get_unit(dev);
	ppc->ppc_model = GENERIC;

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

	ppc->ppc_type = PPC_TYPE_GENERIC;

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

	return (0);

error:
	if (ppc->res_irq != 0) {
		bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
				     ppc->res_irq);
	}
	if (ppc->res_ioport != 0) {
		bus_deactivate_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
					ppc->res_ioport);
		bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
				     ppc->res_ioport);
	}
	if (ppc->res_drq != 0) {
		bus_deactivate_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
					ppc->res_drq);
		bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
				     ppc->res_drq);
	}
	return (ENXIO);
}
コード例 #24
0
ファイル: agp_nvidia.c プロジェクト: Gwenio/DragonFlyBSD
static int
agp_nvidia_attach (device_t dev)
{
	struct agp_nvidia_softc *sc = device_get_softc(dev);
	struct agp_gatt *gatt;
	u_int32_t apbase;
	u_int32_t aplimit;
	u_int32_t temp;
	int size;
	int i;
	int error;

	switch (pci_get_device(dev)) {
	case NVIDIA_DEVICEID_NFORCE:
		sc->wbc_mask = 0x00010000;
		break;
	case NVIDIA_DEVICEID_NFORCE2:
		sc->wbc_mask = 0x80000000;
		break;
	default:
		device_printf(dev, "Bad chip id\n");
		return (ENODEV);
	}

	/* AGP Controller */
	sc->dev = dev;

	/* Memory Controller 1 */
	sc->mc1_dev = pci_find_bsf(pci_get_bus(dev), 0, 1);
	if (sc->mc1_dev == NULL) {
		device_printf(dev,
			"Unable to find NVIDIA Memory Controller 1.\n");
		return (ENODEV);
	}

	/* Memory Controller 2 */
	sc->mc2_dev = pci_find_bsf(pci_get_bus(dev), 0, 2);
	if (sc->mc2_dev == NULL) {
		device_printf(dev,
			"Unable to find NVIDIA Memory Controller 2.\n");
		return (ENODEV);
	}

	/* AGP Host to PCI Bridge */
	sc->bdev = pci_find_bsf(pci_get_bus(dev), 30, 0);
	if (sc->bdev == NULL) {
		device_printf(dev,
			"Unable to find NVIDIA AGP Host to PCI Bridge.\n");
		return (ENODEV);
	}

	error = agp_generic_attach(dev);
	if (error)
		return (error);

	sc->initial_aperture = AGP_GET_APERTURE(dev);
	if (sc->initial_aperture == 0) {
		device_printf(dev, "bad initial aperture size, disabling\n");
		return ENXIO;
	}

	for (;;) {
		gatt = agp_alloc_gatt(dev);
		if (gatt)
			break;
		/*
		 * Probably contigmalloc failure. Try reducing the
		 * aperture so that the gatt size reduces.
		 */
		if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2))
			goto fail;
	}
	sc->gatt = gatt;

	apbase = rman_get_start(sc->agp.as_aperture);
	aplimit = apbase + AGP_GET_APERTURE(dev) - 1;
	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APBASE, apbase, 4);
	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APLIMIT, aplimit, 4);
	pci_write_config(sc->bdev, AGP_NVIDIA_3_APBASE, apbase, 4);
	pci_write_config(sc->bdev, AGP_NVIDIA_3_APLIMIT, aplimit, 4);

	error = nvidia_init_iorr(apbase, AGP_GET_APERTURE(dev));
	if (error) {
		device_printf(dev, "Failed to setup IORRs\n");
		goto fail;
	}

	/* directory size is 64k */
	size = AGP_GET_APERTURE(dev) / 1024 / 1024;
	sc->num_dirs = size / 64;
	sc->num_active_entries = (size == 32) ? 16384 : ((size * 1024) / 4);
	sc->pg_offset = 0;
	if (sc->num_dirs == 0) {
		sc->num_dirs = 1;
		sc->num_active_entries /= (64 / size);
		sc->pg_offset = (apbase & (64 * 1024 * 1024 - 1) &
				 ~(AGP_GET_APERTURE(dev) - 1)) / PAGE_SIZE;
	}

	/* (G)ATT Base Address */
	for (i = 0; i < 8; i++) {
		pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i),
				 (sc->gatt->ag_physical +
				   (i % sc->num_dirs) * 64 * 1024) | 1, 4);
	}

	/* GTLB Control */
	temp = pci_read_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, 4);
	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, temp | 0x11, 4);

	/* GART Control */
	temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4);
	pci_write_config(sc->dev, AGP_NVIDIA_0_APSIZE, temp | 0x100, 4);

	return (0);
fail:
	agp_generic_detach(dev);
	return (ENOMEM);
}
コード例 #25
0
ファイル: lbc.c プロジェクト: ChaosJohn/freebsd
static struct resource *
lbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
    u_long start, u_long end, u_long count, u_int flags)
{
	struct lbc_softc *sc;
	struct lbc_devinfo *di;
	struct resource_list_entry *rle;
	struct resource *res;
	struct rman *rm;
	int needactivate;

	/* We only support default allocations. */
	if (start != 0ul || end != ~0ul)
		return (NULL);

	sc = device_get_softc(bus);
	if (type == SYS_RES_IRQ)
		return (bus_alloc_resource(bus, type, rid, start, end, count,
		    flags));

	/*
	 * Request for the default allocation with a given rid: use resource
	 * list stored in the local device info.
	 */
	if ((di = device_get_ivars(child)) == NULL)
		return (NULL);

	if (type == SYS_RES_IOPORT)
		type = SYS_RES_MEMORY;

	rid = &di->di_bank;

	rle = resource_list_find(&di->di_res, type, *rid);
	if (rle == NULL) {
		device_printf(bus, "no default resources for "
		    "rid = %d, type = %d\n", *rid, type);
		return (NULL);
	}
	start = rle->start;
	count = rle->count;
	end = start + count - 1;

	sc = device_get_softc(bus);

	needactivate = flags & RF_ACTIVE;
	flags &= ~RF_ACTIVE;

	rm = &sc->sc_rman;

	res = rman_reserve_resource(rm, start, end, count, flags, child);
	if (res == NULL) {
		device_printf(bus, "failed to reserve resource %#lx - %#lx "
		    "(%#lx)\n", start, end, count);
		return (NULL);
	}

	rman_set_rid(res, *rid);
	rman_set_bustag(res, &bs_be_tag);
	rman_set_bushandle(res, rman_get_start(res));

	if (needactivate)
		if (bus_activate_resource(child, type, *rid, res)) {
			device_printf(child, "resource activation failed\n");
			rman_release_resource(res);
			return (NULL);
		}

	return (res);
}
コード例 #26
0
ファイル: iir_pci.c プロジェクト: cyrilmagsuci/freebsd
static int
iir_pci_attach(device_t dev)
{
    struct gdt_softc    *gdt;
    struct resource     *irq = NULL;
    int                 retries, rid, error = 0;
    void                *ih;
    u_int8_t            protocol;  

    gdt = device_get_softc(dev);
    mtx_init(&gdt->sc_lock, "iir", NULL, MTX_DEF);

    /* map DPMEM */
    rid = PCI_DPMEM;
    gdt->sc_dpmem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
    if (gdt->sc_dpmem == NULL) {
        device_printf(dev, "can't allocate register resources\n");
        error = ENOMEM;
        goto err;
    }

    /* get IRQ */
    rid = 0;
    irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                 RF_ACTIVE | RF_SHAREABLE);
    if (irq == NULL) {
        device_printf(dev, "can't find IRQ value\n");
        error = ENOMEM;
        goto err;
    }

    gdt->sc_devnode = dev;
    gdt->sc_init_level = 0;
    gdt->sc_hanum = device_get_unit(dev);
    gdt->sc_bus = pci_get_bus(dev);
    gdt->sc_slot = pci_get_slot(dev);
    gdt->sc_vendor = pci_get_vendor(dev);
    gdt->sc_device = pci_get_device(dev);
    gdt->sc_subdevice = pci_get_subdevice(dev);
    gdt->sc_class = GDT_MPR;
/* no FC ctr.
    if (gdt->sc_device >= GDT_PCI_PRODUCT_FC)
        gdt->sc_class |= GDT_FC;
*/

    /* initialize RP controller */
    /* check and reset interface area */
    bus_write_4(gdt->sc_dpmem, GDT_MPR_IC, htole32(GDT_MPR_MAGIC));
    if (bus_read_4(gdt->sc_dpmem, GDT_MPR_IC) != htole32(GDT_MPR_MAGIC)) {
	device_printf(dev, "cannot access DPMEM at 0x%lx (shadowed?)\n",
	    rman_get_start(gdt->sc_dpmem));
        error = ENXIO;
        goto err;
    }
    bus_set_region_4(gdt->sc_dpmem, GDT_I960_SZ, htole32(0), GDT_MPR_SZ >> 2);

    /* Disable everything */
    bus_write_1(gdt->sc_dpmem, GDT_EDOOR_EN,
	bus_read_1(gdt->sc_dpmem, GDT_EDOOR_EN) | 4);
    bus_write_1(gdt->sc_dpmem, GDT_MPR_EDOOR, 0xff);
    bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0);
    bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_CMD_INDEX, 0);

    bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO,
	htole32(rman_get_start(gdt->sc_dpmem)));
    bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_CMD_INDX, 0xff);
    bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1);

    DELAY(20);
    retries = GDT_RETRIES;
    while (bus_read_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS) != 0xff) {
        if (--retries == 0) {
            device_printf(dev, "DEINIT failed\n");
            error = ENXIO;
            goto err;
        }
        DELAY(1);
    }

    protocol = (uint8_t)le32toh(bus_read_4(gdt->sc_dpmem,
	    GDT_MPR_IC + GDT_S_INFO));
    bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0);
    if (protocol != GDT_PROTOCOL_VERSION) {
        device_printf(dev, "unsupported protocol %d\n", protocol);
        error = ENXIO;
        goto err;
    }
    
    /* special command to controller BIOS */
    bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO, htole32(0));
    bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t),
	htole32(0));
    bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t),
	htole32(1));
    bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t),
	htole32(0));
    bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_CMD_INDX, 0xfe);
    bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1);

    DELAY(20);
    retries = GDT_RETRIES;
    while (bus_read_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS) != 0xfe) {
        if (--retries == 0) {
            device_printf(dev, "initialization error\n");
            error = ENXIO;
            goto err;
        }
        DELAY(1);
    }

    bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0);

    gdt->sc_ic_all_size = GDT_MPR_SZ;
    
    gdt->sc_copy_cmd = gdt_mpr_copy_cmd;
    gdt->sc_get_status = gdt_mpr_get_status;
    gdt->sc_intr = gdt_mpr_intr;
    gdt->sc_release_event = gdt_mpr_release_event;
    gdt->sc_set_sema0 = gdt_mpr_set_sema0;
    gdt->sc_test_busy = gdt_mpr_test_busy;

    /* 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*/BUS_SPACE_UNRESTRICTED,
                           /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
			   /*flags*/0, /*lockfunc*/busdma_lock_mutex,
			   /*lockarg*/&gdt->sc_lock, &gdt->sc_parent_dmat) != 0) {
        error = ENXIO;
        goto err;
    }
    gdt->sc_init_level++;

    if (iir_init(gdt) != 0) {
        iir_free(gdt);
        error = ENXIO;
        goto err;
    }

    /* Register with the XPT */
    iir_attach(gdt);

    /* associate interrupt handler */
    if (bus_setup_intr(dev, irq, INTR_TYPE_CAM | INTR_MPSAFE, 
                        NULL, iir_intr, gdt, &ih )) {
        device_printf(dev, "Unable to register interrupt handler\n");
        error = ENXIO;
        goto err;
    }

    gdt_pci_enable_intr(gdt);
    return (0);
    
err:
    if (irq)
        bus_release_resource( dev, SYS_RES_IRQ, 0, irq );

    if (gdt->sc_dpmem)
        bus_release_resource( dev, SYS_RES_MEMORY, rid, gdt->sc_dpmem );
    mtx_destroy(&gdt->sc_lock);

    return (error);
}
コード例 #27
0
ファイル: puc.c プロジェクト: dcui/FreeBSD-9.3_kernel
int
puc_bfe_attach(device_t dev)
{
	char buffer[64];
	struct puc_bar *bar;
	struct puc_port *port;
	struct puc_softc *sc;
	struct rman *rm;
	intptr_t res;
	bus_addr_t ofs, start;
	bus_size_t size;
	bus_space_handle_t bsh;
	bus_space_tag_t bst;
	int error, idx;

	sc = device_get_softc(dev);

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

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

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

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

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

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

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

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

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

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

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

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

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

	return (0);

fail:
	for (idx = 0; idx < sc->sc_nports; idx++) {
		port = &sc->sc_port[idx];
		if (port->p_dev != NULL)
			device_delete_child(dev, port->p_dev);
		if (port->p_rres != NULL)
			rman_release_resource(port->p_rres);
		if (port->p_ires != NULL)
			rman_release_resource(port->p_ires);
	}
	for (idx = 0; idx < PUC_PCI_BARS; idx++) {
		bar = &sc->sc_bar[idx];
		if (bar->b_res != NULL)
			bus_release_resource(sc->sc_dev, bar->b_type,
			    bar->b_rid, bar->b_res);
	}
	rman_fini(&sc->sc_irq);
	free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC);
	rman_fini(&sc->sc_iomem);
	free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC);
	rman_fini(&sc->sc_ioport);
	free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC);
	free(sc->sc_port, M_PUC);
	return (error);
}
コード例 #28
0
ファイル: cardbus_cis.c プロジェクト: ele7enxxh/dtrace-pf
static struct resource *
cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
    int *rid)
{
	struct resource *res;
	uint32_t space;

	space = *start & PCIM_CIS_ASI_MASK;
	switch (space) {
	case PCIM_CIS_ASI_CONFIG:
		DEVPRINTF((cbdev, "CIS in PCI config space\n"));
		/* CIS in PCI config space need no initialization */
		return (CIS_CONFIG_SPACE);
	case PCIM_CIS_ASI_BAR0:
	case PCIM_CIS_ASI_BAR1:
	case PCIM_CIS_ASI_BAR2:
	case PCIM_CIS_ASI_BAR3:
	case PCIM_CIS_ASI_BAR4:
	case PCIM_CIS_ASI_BAR5:
		*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
		DEVPRINTF((cbdev, "CIS in BAR %#x\n", *rid));
		break;
	case PCIM_CIS_ASI_ROM:
		*rid = PCIR_BIOS;
		DEVPRINTF((cbdev, "CIS in option rom\n"));
		break;
	default:
		device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
		    space);
		return (NULL);
	}

	/* allocate the memory space to read CIS */
	res = bus_alloc_resource_any(child, SYS_RES_MEMORY, rid,
	    rman_make_alignment_flags(4096) | RF_ACTIVE);
	if (res == NULL) {
		device_printf(cbdev, "Unable to allocate resource "
		    "to read CIS.\n");
		return (NULL);
	}
	DEVPRINTF((cbdev, "CIS Mapped to %#lx\n", rman_get_start(res)));

	/* Flip to the right ROM image if CIS is in ROM */
	if (space == PCIM_CIS_ASI_ROM) {
		uint32_t imagesize;
		uint32_t imagebase = 0;
		uint32_t pcidata;
		uint16_t romsig;
		int romnum = 0;
		int imagenum;

		imagenum = (*start & PCIM_CIS_ROM_MASK) >> 28;
		for (romnum = 0;; romnum++) {
			romsig = bus_read_2(res,
			    imagebase + CARDBUS_EXROM_SIGNATURE);
			if (romsig != 0xaa55) {
				device_printf(cbdev, "Bad header in rom %d: "
				    "[%x] %04x\n", romnum, imagebase +
				    CARDBUS_EXROM_SIGNATURE, romsig);
				cardbus_read_tuple_finish(cbdev, child, *rid,
				    res);
				*rid = 0;
				return (NULL);
			}

			/*
			 * If this was the Option ROM image that we were
			 * looking for, then we are done.
			 */
			if (romnum == imagenum)
				break;

			/* Find out where the next Option ROM image is */
			pcidata = imagebase + bus_read_2(res,
			    imagebase + CARDBUS_EXROM_DATA_PTR);
			imagesize = bus_read_2(res,
			    pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);

			if (imagesize == 0) {
				/*
				 * XXX some ROMs seem to have this as zero,
				 * can we assume this means 1 block?
				 */
				device_printf(cbdev, "Warning, size of Option "
				    "ROM image %d is 0 bytes, assuming 512 "
				    "bytes.\n", romnum);
				imagesize = 1;
			}

			/* Image size is in 512 byte units */
			imagesize <<= 9;

			if ((bus_read_1(res, pcidata +
			    CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
				device_printf(cbdev, "Cannot find CIS in "
				    "Option ROM\n");
				cardbus_read_tuple_finish(cbdev, child, *rid,
				    res);
				*rid = 0;
				return (NULL);
			}
			imagebase += imagesize;
		}
		*start = imagebase + (*start & PCIM_CIS_ADDR_MASK);
	} else {
コード例 #29
0
ファイル: if_ed_sic.c プロジェクト: coyizumi/cs111
/*
 * Probe and vendor-specific initialization routine for SIC boards
 */
int
ed_probe_SIC(device_t dev, int port_rid, int flags)
{
    struct ed_softc *sc = device_get_softc(dev);
    int	error;
    int	i;
    u_int	memsize;
    u_long	pmem;
    u_char	sum;

    error = ed_alloc_port(dev, 0, ED_SIC_IO_PORTS);
    if (error)
        return (error);

    sc->asic_offset = ED_SIC_ASIC_OFFSET;
    sc->nic_offset  = ED_SIC_NIC_OFFSET;

    memsize = 16384;
    /* XXX Needs to allow different msize */
    error = ed_alloc_memory(dev, 0, memsize);
    if (error)
        return (error);

    sc->mem_start = 0;
    sc->mem_size  = memsize;

    pmem = rman_get_start(sc->mem_res);
    error = ed_isa_mem_ok(dev, pmem, memsize);
    if (error)
        return (error);

    /* Reset card to force it into a known state. */
    ed_asic_outb(sc, 0, 0x00);
    DELAY(100);

    /*
     * Here we check the card ROM, if the checksum passes, and the
     * type code and ethernet address check out, then we know we have
     * an SIC card.
     */
    ed_asic_outb(sc, 0, 0x81);
    DELAY(100);

    sum = bus_space_read_1(sc->mem_bst, sc->mem_bsh, 6);
    for (i = 0; i < ETHER_ADDR_LEN; i++)
        sum ^= (sc->enaddr[i] =
                    bus_space_read_1(sc->mem_bst, sc->mem_bsh, i));
#ifdef ED_DEBUG
    device_printf(dev, "ed_probe_sic: got address %6D\n",
                  sc->enaddr, ":");
#endif
    if (sum != 0)
        return (ENXIO);
    if ((sc->enaddr[0] | sc->enaddr[1] | sc->enaddr[2]) == 0)
        return (ENXIO);

    sc->vendor   = ED_VENDOR_SIC;
    sc->type_str = "SIC";
    sc->isa16bit = 0;
    sc->cr_proto = 0;

    /*
     * SIC RAM page 0x0000-0x3fff(or 0x7fff)
     */
    ed_asic_outb(sc, 0, 0x80);
    DELAY(100);

    error = ed_clear_memory(dev);
    if (error)
        return (error);

    sc->mem_shared = 1;
    sc->mem_end = sc->mem_start + sc->mem_size;

    /*
     * allocate one xmit buffer if < 16k, two buffers otherwise
     */
    if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
        sc->txb_cnt = 1;
    else
        sc->txb_cnt = 2;
    sc->tx_page_start = 0;

    sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt;
    sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;

    sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;

    sc->sc_write_mbufs = ed_shmem_write_mbufs;
    return (0);
}
コード例 #30
0
ファイル: ata-cbus.c プロジェクト: hmatyschok/MeshBSD
static int
ata_cbus_attach(device_t dev)
{
    struct ata_cbus_controller *ctlr = device_get_softc(dev);
    device_t child;
    int rid, unit;

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

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

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

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

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

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

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

    bus_generic_attach(dev);
    return (0);
}