Пример #1
0
static int
mlx_pci_attach(device_t dev)
{
    struct mlx_softc	*sc;
    struct mlx_ident	*m;
    int			error;

    debug_called(1);

    pci_enable_busmaster(dev);

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

    /*
     * Work out what sort of adapter this is (we need to know this in order
     * to map the appropriate interface resources).
     */
    m = mlx_pci_match(dev);
    if (m == NULL)		/* shouldn't happen */
	return(ENXIO);
    sc->mlx_iftype = m->iftype;

    mtx_init(&sc->mlx_io_lock, "mlx I/O", NULL, MTX_DEF);
    sx_init(&sc->mlx_config_lock, "mlx config");
    callout_init_mtx(&sc->mlx_timeout, &sc->mlx_io_lock, 0);

    /*
     * Allocate the PCI register window.
     */
    
    /* type 2/3 adapters have an I/O region we don't prefer at base 0 */
    switch(sc->mlx_iftype) {
    case MLX_IFTYPE_2:
    case MLX_IFTYPE_3:
	sc->mlx_mem_type = SYS_RES_MEMORY;
	sc->mlx_mem_rid = MLX_CFG_BASE1;
	sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type,
		&sc->mlx_mem_rid, RF_ACTIVE);
	if (sc->mlx_mem == NULL) {
	    sc->mlx_mem_type = SYS_RES_IOPORT;
	    sc->mlx_mem_rid = MLX_CFG_BASE0;
	    sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type,
		&sc->mlx_mem_rid, RF_ACTIVE);
	}
	break;
    case MLX_IFTYPE_4:
    case MLX_IFTYPE_5:
	sc->mlx_mem_type = SYS_RES_MEMORY;
	sc->mlx_mem_rid = MLX_CFG_BASE0;
	sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type,
		&sc->mlx_mem_rid, RF_ACTIVE);
	break;
    }
    if (sc->mlx_mem == NULL) {
	device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n");
	mlx_free(sc);
	return(ENXIO);
    }

    /*
     * Allocate the parent bus DMA tag appropriate for PCI.
     */
    error = bus_dma_tag_create(bus_get_dma_tag(dev),	/* PCI parent */
			       1, 0, 			/* alignment, boundary */
			       BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
			       BUS_SPACE_MAXADDR, 	/* highaddr */
			       NULL, NULL, 		/* filter, filterarg */
			       BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
			       BUS_DMA_ALLOCNOW,	/* flags */
			       NULL,			/* lockfunc */
			       NULL,			/* lockarg */
			       &sc->mlx_parent_dmat);
    if (error != 0) {
	device_printf(dev, "can't allocate parent DMA tag\n");
	mlx_free(sc);
	return(ENOMEM);
    }

    /*
     * Do bus-independant initialisation.
     */
    error = mlx_attach(sc);
    if (error != 0) {
	mlx_free(sc);
	return(error);
    }
    
    /*
     * Start the controller.
     */
    mlx_startup(sc);
    return(0);
}
Пример #2
0
static int
ida_eisa_attach(device_t dev)
{
	struct ida_softc	*ida;
	struct ida_board	*board;
	int			error;
	int			rid;

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

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

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

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

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

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

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

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

	return (0);
}
Пример #3
0
static int
ath_ahb_attach(device_t dev)
{
    struct ath_ahb_softc *psc = device_get_softc(dev);
    struct ath_softc *sc = &psc->sc_sc;
    int error = ENXIO;
    int rid;
    long eepromaddr;
    uint8_t *p;

    sc->sc_dev = dev;

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

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

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

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

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

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

    ATH_LOCK_INIT(sc);

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

    ATH_LOCK_DESTROY(sc);
    bus_dma_tag_destroy(sc->sc_dmat);
bad3:
    bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
bad2:
    bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
bad1:
    bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom);
bad0:
    bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr);
bad:
    /* XXX?! */
    if (sc->sc_eepromdata)
        free(sc->sc_eepromdata, M_TEMP);
    return (error);
}
Пример #4
0
static int
dpt_pci_attach (device_t dev)
{
	dpt_softc_t *	dpt;
	int		error = 0;

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

#ifdef DPT_ALLOW_MMIO
	dpt->io_rid = DPT_PCI_MEMADDR;
	dpt->io_type = SYS_RES_MEMORY;
	dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type,
	    &dpt->io_rid, RF_ACTIVE);
#endif
	if (dpt->io_res == NULL) {
		dpt->io_rid = DPT_PCI_IOADDR;
		dpt->io_type = SYS_RES_IOPORT;
		dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type,
						     &dpt->io_rid, RF_ACTIVE);
	}

	if (dpt->io_res == NULL) {
		device_printf(dev, "can't allocate register resources\n");
		error = ENOMEM;
		goto bad;
	}
	dpt->io_offset = 0x10;

	dpt->irq_rid = 0;
	dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid,
					      RF_ACTIVE | RF_SHAREABLE);
	if (dpt->irq_res == NULL) {
		device_printf(dev, "No irq?!\n");
		error = ENOMEM;
		goto bad;
	}

	/* Ensure busmastering is enabled */
	pci_enable_busmaster(dev);

	if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) {
#ifdef DPT_DEBUG_WARN
		device_printf(dev, "Mapped as an IDE controller.  "
				   "Disabling SCSI setup\n");
#endif
		error = ENXIO;
		goto bad;
	}

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

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

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

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

	return (error);

bad:
	dpt_release_resources(dev);

	dpt_free(dpt);

	return (error);
}
Пример #5
0
static int
fm801_pci_attach(device_t dev)
{
	struct ac97_info 	*codec = 0;
	struct fm801_info 	*fm801;
	int 			i;
	int 			mapped = 0;
	char 			status[SND_STATUSLEN];

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

	pci_enable_busmaster(dev);

	for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
		fm801->regid = PCIR_BAR(i);
		fm801->regtype = SYS_RES_MEMORY;
		fm801->reg = bus_alloc_resource_any(dev, fm801->regtype,
						    &fm801->regid, RF_ACTIVE);
		if(!fm801->reg)
		{
			fm801->regtype = SYS_RES_IOPORT;
			fm801->reg = bus_alloc_resource_any(dev, 
							    fm801->regtype,
							    &fm801->regid,
							    RF_ACTIVE);
		}

		if(fm801->reg) {
			fm801->st = rman_get_bustag(fm801->reg);
			fm801->sh = rman_get_bushandle(fm801->reg);
			mapped++;
		}
	}

	if (mapped == 0) {
		device_printf(dev, "unable to map register space\n");
		goto oops;
	}

	fm801->bufsz = pcm_getbuffersize(dev, 4096, FM801_DEFAULT_BUFSZ, 65536);

	fm801_init(fm801);

	codec = AC97_CREATE(dev, fm801, fm801_ac97);
	if (codec == NULL) goto oops;

	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops;

	fm801->irqid = 0;
	fm801->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fm801->irqid,
					    RF_ACTIVE | RF_SHAREABLE);
	if (!fm801->irq || snd_setup_intr(dev, fm801->irq, 0, fm801_intr, fm801, &fm801->ih)) {
		device_printf(dev, "unable to map interrupt\n");
		goto oops;
	}

	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*/fm801->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0, /*lockfunc*/busdma_lock_mutex,
		/*lockarg*/&Giant, &fm801->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto oops;
	}

	snprintf(status, 64, "at %s 0x%jx irq %jd %s",
		(fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
		rman_get_start(fm801->reg), rman_get_start(fm801->irq),PCM_KLDSTRING(snd_fm801));

#define FM801_MAXPLAYCH	1
	if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops;
	pcm_addchan(dev, PCMDIR_PLAY, &fm801ch_class, fm801);
	pcm_addchan(dev, PCMDIR_REC, &fm801ch_class, fm801);
	pcm_setstatus(dev, status);

	fm801->radio = device_add_child(dev, "radio", -1);
	bus_generic_attach(dev);

	return 0;

oops:
	if (codec) ac97_destroy(codec);
	if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
	if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih);
	if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
	if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat);
	free(fm801, M_DEVBUF);
	return ENXIO;
}
Пример #6
0
/*
 * Attach all the sub-devices we can find
 */
static int
aha_isa_attach(device_t dev)
{
	struct	aha_softc *aha = device_get_softc(dev);
	bus_dma_filter_t *filter;
	void		 *filter_arg;
	bus_addr_t	 lowaddr;
	void		 *ih;
	int		 error = ENOMEM;
	int		 aha_free_needed = 0;

	aha->dev = dev;
	aha->portrid = 0;
	aha->port = bus_alloc_resource(dev, SYS_RES_IOPORT, &aha->portrid,
	    0, ~0, 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 */
	filter = NULL;
	filter_arg = NULL;
	lowaddr = BUS_SPACE_MAXADDR_24BIT;

	if (bus_dma_tag_create(	/* parent	*/ bus_get_dma_tag(dev),
				/* alignemnt	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ lowaddr,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ filter,
				/* filterarg	*/ filter_arg,
				/* maxsize	*/ BUS_SPACE_MAXSIZE_24BIT,
				/* nsegments	*/ ~0,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ busdma_lock_mutex,
				/* lockarg	*/ &Giant,
				&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;
	}
	aha_free_needed++;
	
	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,
	    NULL, aha_intr, aha, &ih);
	if (error) {
		device_printf(dev, "Unable to register interrupt handler\n");
                goto fail;
	}

	return (0);
fail: ;
	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);
	if (aha_free_needed)
		aha_free(aha);
	return (error);
}
Пример #7
0
static int
dma_setup(struct dwmmc_softc *sc)
{
	int error;
	int nidx;
	int idx;

	/*
	 * Set up TX descriptor ring, descriptors, and dma maps.
	 */
	error = bus_dma_tag_create(
	    bus_get_dma_tag(sc->dev),	/* Parent tag. */
	    4096, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    DESC_SIZE, 1, 		/* maxsize, nsegments */
	    DESC_SIZE,			/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->desc_tag);
	if (error != 0) {
		device_printf(sc->dev,
		    "could not create ring DMA tag.\n");
		return (1);
	}

	error = bus_dmamem_alloc(sc->desc_tag, (void**)&sc->desc_ring,
	    BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
	    &sc->desc_map);
	if (error != 0) {
		device_printf(sc->dev,
		    "could not allocate descriptor ring.\n");
		return (1);
	}

	error = bus_dmamap_load(sc->desc_tag, sc->desc_map,
	    sc->desc_ring, DESC_SIZE, dwmmc_get1paddr,
	    &sc->desc_ring_paddr, 0);
	if (error != 0) {
		device_printf(sc->dev,
		    "could not load descriptor ring map.\n");
		return (1);
	}

	for (idx = 0; idx < sc->desc_count; idx++) {
		sc->desc_ring[idx].des0 = DES0_CH;
		sc->desc_ring[idx].des1 = 0;
		nidx = (idx + 1) % sc->desc_count;
		sc->desc_ring[idx].des3 = sc->desc_ring_paddr + \
		    (nidx * sizeof(struct idmac_desc));
	}

	error = bus_dma_tag_create(
	    bus_get_dma_tag(sc->dev),	/* Parent tag. */
	    4096, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    sc->desc_count * MMC_SECTOR_SIZE, /* maxsize */
	    sc->desc_count,		/* nsegments */
	    MMC_SECTOR_SIZE,		/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->buf_tag);
	if (error != 0) {
		device_printf(sc->dev,
		    "could not create ring DMA tag.\n");
		return (1);
	}

	error = bus_dmamap_create(sc->buf_tag, 0,
	    &sc->buf_map);
	if (error != 0) {
		device_printf(sc->dev,
		    "could not create TX buffer DMA map.\n");
		return (1);
	}

	return (0);
}
Пример #8
0
static int
bcm2835_cpufreq_attach(device_t dev)
{
	struct bcm2835_cpufreq_softc *sc;
	struct sysctl_oid *oid;
	int err;

	/* set self dev */
	sc = device_get_softc(dev);
	sc->dev = dev;

	/* initial values */
	sc->arm_max_freq = -1;
	sc->arm_min_freq = -1;
	sc->core_max_freq = -1;
	sc->core_min_freq = -1;
	sc->sdram_max_freq = -1;
	sc->sdram_min_freq = -1;
	sc->max_voltage_core = 0;
	sc->min_voltage_core = 0;

	/* create VC mbox buffer */
	sc->dma_size = PAGE_SIZE;
	err = bus_dma_tag_create(
	    bus_get_dma_tag(sc->dev),
	    PAGE_SIZE, 0,		/* alignment, boundary */
	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    sc->dma_size, 1,		/* maxsize, nsegments */
	    sc->dma_size, 0,		/* maxsegsize, flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->dma_tag);
	if (err) {
		device_printf(dev, "can't create DMA tag\n");
		return (ENXIO);
	}

	err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->dma_buf, 0,
	    &sc->dma_map);
	if (err) {
		bus_dma_tag_destroy(sc->dma_tag);
		device_printf(dev, "can't allocate dmamem\n");
		return (ENXIO);
	}

	err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->dma_buf,
	    sc->dma_size, bcm2835_cpufreq_cb, &sc->dma_phys, 0);
	if (err) {
		bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map);
		bus_dma_tag_destroy(sc->dma_tag);
		device_printf(dev, "can't load DMA map\n");
		return (ENXIO);
	}
	/* OK, ready to use VC buffer */

	/* setup sysctl at first device */
	if (device_get_unit(dev) == 0) {
		sysctl_ctx_init(&bcm2835_sysctl_ctx);
		/* create node for hw.cpufreq */
		oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx,
		    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq",
		    CTLFLAG_RD, NULL, "");

		/* Frequency (Hz) */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "arm_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_arm_freq, "IU",
		    "ARM frequency (Hz)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "core_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_core_freq, "IU",
		    "Core frequency (Hz)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "sdram_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_sdram_freq, "IU",
		    "SDRAM frequency (Hz)");

		/* Turbo state */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "turbo", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_turbo, "IU",
		    "Disables dynamic clocking");

		/* Voltage (offset from 1.2V in units of 0.025V) */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_core", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_voltage_core, "I",
		    "ARM/GPU core voltage"
		    "(offset from 1.2V in units of 0.025V)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram", CTLTYPE_INT | CTLFLAG_WR, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram, "I",
		    "SDRAM voltage (offset from 1.2V in units of 0.025V)");

		/* Voltage individual SDRAM */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram_c", CTLTYPE_INT | CTLFLAG_RW, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I",
		    "SDRAM controller voltage"
		    "(offset from 1.2V in units of 0.025V)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram_i", CTLTYPE_INT | CTLFLAG_RW, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I",
		    "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram_p", CTLTYPE_INT | CTLFLAG_RW, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I",
		    "SDRAM phy voltage (offset from 1.2V in units of 0.025V)");

		/* Temperature */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
		    sysctl_bcm2835_cpufreq_temperature, "I",
		    "SoC temperature (thousandths of a degree C)");
	}

	/* ARM->VC lock */
	sema_init(&vc_sema, 1, "vcsema");

	/* register callback for using mbox when interrupts are enabled */
	sc->init_hook.ich_func = bcm2835_cpufreq_init;
	sc->init_hook.ich_arg = sc;

	if (config_intrhook_establish(&sc->init_hook) != 0) {
		bus_dmamap_unload(sc->dma_tag, sc->dma_map);
		bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map);
		bus_dma_tag_destroy(sc->dma_tag);
		device_printf(dev, "config_intrhook_establish failed\n");
		return (ENOMEM);
	}

	/* this device is controlled by cpufreq(4) */
	cpufreq_register(dev);

	return (0);
}
Пример #9
0
static int
ahbattach(device_t dev)
{
	/*
	 * find unit and check we have that many defined
	 */
	struct	    ahb_softc *ahb;
	struct	    ecb* next_ecb;
	struct	    resource *io = 0;
	struct	    resource *irq = 0;
	int	    rid;
	void	    *ih;

	rid = 0;
	io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
	if (!io) {
		device_printf(dev, "No I/O space?!\n");
		return ENOMEM;
	}

	if ((ahb = ahballoc(dev, io)) == NULL) {
		goto error_exit2;
	}

	if (ahbreset(ahb) != 0)
		goto error_exit;

	rid = 0;
	irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
	if (!irq) {
		device_printf(dev, "Can't allocate interrupt\n");
		goto error_exit;
	}

	/*
	 * Create our DMA tags.  These tags define the kinds of device
	 * accessible memory allocations and memory mappings we will 
	 * need to perform during normal operation.
	 */
	/* DMA tag for mapping buffers into device visible space. */
	if (bus_dma_tag_create(	/* parent	*/ bus_get_dma_tag(dev),
				/* alignment	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ BUS_SPACE_MAXADDR_32BIT,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ MAXBSIZE,
				/* nsegments	*/ AHB_NSEG,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* flags	*/ BUS_DMA_ALLOCNOW,
				/* lockfunc	*/ busdma_lock_mutex,
				/* lockarg	*/ &Giant,
				&ahb->buffer_dmat) != 0)
		goto error_exit;

	ahb->init_level++;

	/* DMA tag for our ccb structures and ha inquiry data */
	if (bus_dma_tag_create(	/* parent	*/ bus_get_dma_tag(dev),
				/* alignment	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ BUS_SPACE_MAXADDR_32BIT,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ (AHB_NECB *
						    sizeof(struct ecb))
						    + sizeof(*ahb->ha_inq_data),
				/* nsegments	*/ 1,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ busdma_lock_mutex,
				/* lockarg	*/ &Giant,
				&ahb->ecb_dmat) != 0)
		goto error_exit;

	ahb->init_level++;

	/* Allocation for our ccbs */
	if (bus_dmamem_alloc(ahb->ecb_dmat, (void **)&ahb->ecb_array,
			     BUS_DMA_NOWAIT, &ahb->ecb_dmamap) != 0)
		goto error_exit;

	ahb->ha_inq_data = (struct ha_inquiry_data *)&ahb->ecb_array[AHB_NECB];

	ahb->init_level++;

	/* And permanently map them */
	bus_dmamap_load(ahb->ecb_dmat, ahb->ecb_dmamap,
			ahb->ecb_array, AHB_NSEG * sizeof(struct ecb),
			ahbmapecbs, ahb, /*flags*/0);

	ahb->init_level++;

	/* Allocate the buffer dmamaps for each of our ECBs */
	bzero(ahb->ecb_array, (AHB_NECB * sizeof(struct ecb))
	      + sizeof(*ahb->ha_inq_data));
	next_ecb = ahb->ecb_array;
	while (ahb->num_ecbs < AHB_NECB) {
		u_int32_t ecb_paddr;

		if (bus_dmamap_create(ahb->buffer_dmat, /*flags*/0,
				      &next_ecb->dmamap))
			break;
		ecb_paddr = ahbecbvtop(ahb, next_ecb);
		next_ecb->hecb.status_ptr = ahbstatuspaddr(ecb_paddr);
		next_ecb->hecb.sense_ptr = ahbsensepaddr(ecb_paddr);
		ahb->num_ecbs++;
		ahbecbfree(ahb, next_ecb);
		next_ecb++;
	}

	if (ahb->num_ecbs == 0)
		goto error_exit;

	ahb->init_level++;

	/*
	 * Now that we know we own the resources we need, register
	 * our bus with the XPT.
	 */
	if (ahbxptattach(ahb))
		goto error_exit;

	/* Enable our interrupt */
	if (bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, NULL, ahbintr, 
	    ahb, &ih) != 0)
		goto error_exit;

	return (0);

error_exit:
	/*
	 * The board's IRQ line will not be left enabled
	 * if we can't intialize correctly, so its safe
	 * to release the irq.
	 */
	ahbfree(ahb);
error_exit2:
	if (io)
		bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
	if (irq)
		bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
	return (-1);
}
Пример #10
0
static int
hdspe_alloc_resources(struct sc_info *sc)
{

	/* Allocate resource. */
	sc->csid = PCIR_BAR(0);
	sc->cs = bus_alloc_resource(sc->dev, SYS_RES_MEMORY,
	    &sc->csid, 0, ~0, 1, RF_ACTIVE);

	if (!sc->cs) {
		device_printf(sc->dev, "Unable to map SYS_RES_MEMORY.\n");
		return (ENXIO);
	}
	sc->cst = rman_get_bustag(sc->cs);
	sc->csh = rman_get_bushandle(sc->cs);


	/* Allocate interrupt resource. */
	sc->irqid = 0;
	sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
	    0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);

	if (!sc->irq ||
	    bus_setup_intr(sc->dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV,
		NULL, hdspe_intr, sc, &sc->ih)) {
		device_printf(sc->dev, "Unable to alloc interrupt resource.\n");
		return (ENXIO);
	}

	/* Allocate DMA resources. */
	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
		/*alignment*/4,
		/*boundary*/0,
		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
		/*highaddr*/BUS_SPACE_MAXADDR,
		/*filter*/NULL,
		/*filterarg*/NULL,
		/*maxsize*/2 * HDSPE_DMASEGSIZE,
		/*nsegments*/2,
		/*maxsegsz*/HDSPE_DMASEGSIZE,
		/*flags*/0,
		/*lockfunc*/busdma_lock_mutex,
		/*lockarg*/&Giant,
		/*dmatag*/&sc->dmat) != 0) {
		device_printf(sc->dev, "Unable to create dma tag.\n");
		return (ENXIO);
	}

	sc->bufsize = HDSPE_DMASEGSIZE;

	/* pbuf (play buffer). */
	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf,
		BUS_DMA_NOWAIT, &sc->pmap)) {
		device_printf(sc->dev, "Can't alloc pbuf.\n");
		return (ENXIO);
	}

	if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize,
		hdspe_dmapsetmap, sc, 0)) {
		device_printf(sc->dev, "Can't load pbuf.\n");
		return (ENXIO);
	}

	/* rbuf (rec buffer). */
	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf,
		BUS_DMA_NOWAIT, &sc->rmap)) {
		device_printf(sc->dev, "Can't alloc rbuf.\n");
		return (ENXIO);
	}

	if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize,
		hdspe_dmapsetmap, sc, 0)) {
		device_printf(sc->dev, "Can't load rbuf.\n");
		return (ENXIO);
	}

	bzero(sc->pbuf, sc->bufsize);
	bzero(sc->rbuf, sc->bufsize);

	return (0);
}
Пример #11
0
static int
sbus_attach(device_t dev)
{
	struct sbus_softc *sc;
	struct sbus_devinfo *sdi;
	struct sbus_icarg *sica;
	struct sbus_ranges *range;
	struct resource *res;
	struct resource_list *rl;
	device_t cdev;
	bus_addr_t intrclr, intrmap, phys;
	bus_size_t size;
	u_long vec;
	phandle_t child, node;
	uint32_t prop;
	int i, j;

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

	i = 0;
	sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
	    RF_ACTIVE);
	if (sc->sc_sysio_res == NULL)
		panic("%s: cannot allocate device memory", __func__);

	if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1)
		panic("%s: cannot get IGN", __func__);
	sc->sc_ign = INTIGN(prop);
	sc->sc_cbustag = sbus_alloc_bustag(sc);

	/*
	 * Record clock frequency for synchronous SCSI.
	 * IS THIS THE CORRECT DEFAULT??
	 */
	if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1)
		prop = 25000000;
	sc->sc_clockfreq = prop;
	prop /= 1000;
	device_printf(dev, "clock %d.%03d MHz\n", prop / 1000, prop % 1000);

	/*
	 * Collect address translations from the OBP.
	 */
	if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges",
	    sizeof(*range), (void **)&range)) == -1) {
		panic("%s: error getting ranges property", __func__);
	}
	sc->sc_rd = (struct sbus_rd *)malloc(sizeof(*sc->sc_rd) * sc->sc_nrange,
	    M_DEVBUF, M_NOWAIT);
	if (sc->sc_rd == NULL)
		panic("%s: cannot allocate rmans", __func__);
	/*
	 * Preallocate all space that the SBus bridge decodes, so that nothing
	 * else gets in the way; set up rmans etc.
	 */
	rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
	for (i = 0; i < sc->sc_nrange; i++) {
		phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32);
		size = range[i].size;
		sc->sc_rd[i].rd_slot = range[i].cspace;
		sc->sc_rd[i].rd_coffset = range[i].coffset;
		sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size;
		j = resource_list_add_next(rl, SYS_RES_MEMORY, phys,
		    phys + size - 1, size);
		if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j,
		    RF_ACTIVE)) == NULL)
			panic("%s: cannot allocate decoded range", __func__);
		sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res);
		sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY;
		sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory";
		if (rman_init(&sc->sc_rd[i].rd_rman) != 0 ||
		    rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0)
			panic("%s: failed to set up memory rman", __func__);
		sc->sc_rd[i].rd_poffset = phys;
		sc->sc_rd[i].rd_pend = phys + size;
		sc->sc_rd[i].rd_res = res;
	}
	free(range, M_OFWPROP);

	/*
	 * Get the SBus burst transfer size if burst transfers are supported.
	 */
	if (OF_getprop(node, "up-burst-sizes", &sc->sc_burst,
	    sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0)
		sc->sc_burst =
		    (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF;


	/* initalise the IOMMU */

	/* punch in our copies */
	sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS);
	sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res);
	sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res);
	sc->sc_is.is_iommu = SBR_IOMMU;
	sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG;
	sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG;
	sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG;
	sc->sc_is.is_dva = SBR_IOMMU_SVADIAG;
	sc->sc_is.is_dtcmp = 0;
	sc->sc_is.is_sb[0] = SBR_STRBUF;
	sc->sc_is.is_sb[1] = 0;

	/*
	 * Note: the SBus IOMMU ignores the high bits of an address, so a NULL
	 * DMA pointer will be translated by the first page of the IOTSB.
	 * To detect bugs we'll allocate and ignore the first entry.
	 */
	iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1);

	/* Create the DMA tag. */
	if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
	    sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr,
	    0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0)
		panic("%s: bus_dma_tag_create failed", __func__);
	/* Customize the tag. */
	sc->sc_cdmatag->dt_cookie = &sc->sc_is;
	sc->sc_cdmatag->dt_mt = &iommu_dma_methods;

 	/*
	 * Hunt through all the interrupt mapping regs and register our
	 * interrupt controller for the corresponding interrupt vectors.
	 * We do this early in order to be able to catch stray interrupts.
	 */
	for (i = 0; i <= SBUS_MAX_INO; i++) {
		if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0)
			continue;
		sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT);
		if (sica == NULL)
			panic("%s: could not allocate interrupt controller "
			    "argument", __func__);
		sica->sica_sc = sc;
		sica->sica_map = intrmap;
		sica->sica_clr = intrclr;
#ifdef SBUS_DEBUG
		device_printf(dev,
		    "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n",
		    i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO",
		    (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap),
		    (u_long)intrclr);
#endif
		j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i),
		    &sbus_ic, sica);
		if (j != 0)
			device_printf(dev, "could not register interrupt "
			    "controller for INO %d (%d)\n", i, j);
	}

	/* Enable the over-temperature and power-fail interrupts. */
	i = 4;
	sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
	    RF_ACTIVE);
	if (sc->sc_ot_ires == NULL ||
	    INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign ||
	    INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec ||
	    intr_vectors[vec].iv_ic != &sbus_ic ||
	    bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_FAST,
	    NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0)
		panic("%s: failed to set up temperature interrupt", __func__);
	i = 3;
	sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
	    RF_ACTIVE);
	if (sc->sc_pf_ires == NULL ||
	    INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign ||
	    INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec ||
	    intr_vectors[vec].iv_ic != &sbus_ic ||
	    bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_FAST,
	    NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0)
		panic("%s: failed to set up power fail interrupt", __func__);

	/* Initialize the counter-timer. */
	sparc64_counter_init(device_get_nameunit(dev),
	    rman_get_bustag(sc->sc_sysio_res),
	    rman_get_bushandle(sc->sc_sysio_res), SBR_TC0);

	/*
	 * Loop through ROM children, fixing any relative addresses
	 * and then configuring each device.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL)
			continue;
		/*
		 * For devices where there are variants that are actually
		 * split into two SBus devices (as opposed to the first
		 * half of the device being a SBus device and the second
		 * half hanging off of the first one) like 'auxio' and
		 * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device
		 * which is a prerequisite to the driver attaching to the
		 * second one with a lower order. Saves us from dealing
		 * with different probe orders in the respective device
		 * drivers which generally is more hackish.
		 */
		cdev = device_add_child_ordered(dev, (OF_child(child) == 0 &&
		    sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ?
		    SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev,
			    "<%s>: device_add_child_ordered failed\n",
			    sdi->sdi_obdinfo.obd_name);
			sbus_destroy_dinfo(sdi);
			continue;
		}
		device_set_ivars(cdev, sdi);
	}
	return (bus_generic_attach(dev));
}
Пример #12
0
static int
ath_ahb_attach(device_t dev)
{
	struct ath_ahb_softc *psc = device_get_softc(dev);
	struct ath_softc *sc = &psc->sc_sc;
	int error = ENXIO;
	int rid;
	long eepromaddr;
	int eepromsize;
	uint8_t *p;
	int device_id, vendor_id;

	sc->sc_dev = dev;

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

	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "eepromaddr", &eepromaddr) != 0) {
		device_printf(dev, "cannot fetch 'eepromaddr' from hints\n");
		goto bad0;
	}

	/*
	 * The default EEPROM size is 2048 * 16 bit words.
	 * Later EEPROM/OTP/flash regions may be quite a bit bigger.
	 */
	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
	    "eepromsize", &eepromsize) != 0) {
		eepromsize = ATH_EEPROM_DATA_SIZE * 2;
	}

	rid = 0;
	device_printf(sc->sc_dev, "eeprom @ %p (%d bytes)\n",
	    (void *) eepromaddr, eepromsize);
	/*
	 * XXX this assumes that the parent device is the nexus
	 * and will just pass through requests for all of memory.
	 *
	 * Later on, when this has to attach off of the actual
	 * AHB, this won't work.
	 *
	 * Ideally this would be done in machdep code in mips/atheros/
	 * and it'd expose the EEPROM via the firmware interface,
	 * so the ath/ath_ahb drivers can be loaded as modules
	 * after boot-time.
	 */
	psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &rid, (uintptr_t) eepromaddr,
	    (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE);
	if (psc->sc_eeprom == NULL) {
		device_printf(dev, "cannot map eeprom space\n");
		goto bad0;
	}

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

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

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

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

	/*
	 * Check if a device/vendor ID is provided in hints.
	 */
	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
	    "vendor_id", &vendor_id) != 0) {
		vendor_id = VENDOR_ATHEROS;
	}

	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
	    "device_id", &device_id) != 0) {
		device_id = AR9130_DEVID;
	}

	ATH_LOCK_INIT(sc);
	ATH_PCU_LOCK_INIT(sc);
	ATH_RX_LOCK_INIT(sc);
	ATH_TX_LOCK_INIT(sc);
	ATH_TX_IC_LOCK_INIT(sc);
	ATH_TXSTATUS_LOCK_INIT(sc);

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

	ATH_TXSTATUS_LOCK_DESTROY(sc);
	ATH_RX_LOCK_DESTROY(sc);
	ATH_TX_LOCK_DESTROY(sc);
	ATH_TX_IC_LOCK_DESTROY(sc);
	ATH_PCU_LOCK_DESTROY(sc);
	ATH_LOCK_DESTROY(sc);
	bus_dma_tag_destroy(sc->sc_dmat);
bad3:
	bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
bad2:
	bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
bad1:
	bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom);
bad0:
	bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr);
bad:
	/* XXX?! */
	if (sc->sc_eepromdata)
		free(sc->sc_eepromdata, M_TEMP);
	return (error);
}
Пример #13
0
static int
adv_isa_probe(device_t dev)
{
	int	port_index;
	int	max_port_index;
	u_long	iobase, iocount, irq;
	int	user_iobase = 0;
	int	rid = 0;
	void	*ih;
	struct resource	*iores, *irqres;

	/*
	 * We don't know of any PnP ID's for these cards.
	 */
	if (isa_get_logicalid(dev) != 0)
		return (ENXIO);

	/*
	 * Default to scanning all possible device locations.
	 */
	port_index = 0;
	max_port_index = MAX_ISA_IOPORT_INDEX;

	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, &iocount) == 0) {
		user_iobase = 1;
		for (;port_index <= max_port_index; port_index++)
			if (iobase <= adv_isa_ioports[port_index])
				break;
		if ((port_index > max_port_index)
		 || (iobase != adv_isa_ioports[port_index])) {
			if (bootverbose)
				device_printf(dev,
				    "Invalid baseport of 0x%lx specified. "
				    "Nearest valid baseport is 0x%x.  Failing "
				    "probe.\n", iobase,
				    (port_index <= max_port_index) ?
				    adv_isa_ioports[port_index] :
				    adv_isa_ioports[max_port_index]);
			return ENXIO;
		}
		max_port_index = port_index;
	}

	/* Perform the actual probing */
	adv_set_isapnp_wait_for_key();
	for (;port_index <= max_port_index; port_index++) {
		u_int16_t port_addr = adv_isa_ioports[port_index];
		bus_size_t maxsegsz;
		bus_size_t maxsize;
		bus_addr_t lowaddr;
		int error;
		struct adv_softc *adv;

		if (port_addr == 0)
			/* Already been attached */
			continue;
		
		if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port_addr, 1))
			continue;

		/* XXX what is the real portsize? */
		iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
					       RF_ACTIVE);
		if (iores == NULL)
			continue;

		if (adv_find_signature(iores) == 0) {
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			continue;
		}

		/*
		 * Got one.  Now allocate our softc
		 * and see if we can initialize the card.
		 */
		adv = adv_alloc(dev, iores, 0);
		if (adv == NULL) {
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		/*
		 * Stop the chip.
		 */
		ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
		ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
		/*
		 * Determine the chip version.
		 */
		adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
		if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL)
		    && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) {
			adv->type = ADV_VL;
			maxsegsz = ADV_VL_MAX_DMA_COUNT;
			maxsize = BUS_SPACE_MAXSIZE_32BIT;
			lowaddr = ADV_VL_MAX_DMA_ADDR;
			bus_delete_resource(dev, SYS_RES_DRQ, 0);
		} else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA)
			   && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) {
			if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) {
				adv->type = ADV_ISAPNP;
				ADV_OUTB(adv, ADV_REG_IFC,
					 ADV_IFC_INIT_DEFAULT);
			} else {
				adv->type = ADV_ISA;
			}
			maxsegsz = ADV_ISA_MAX_DMA_COUNT;
			maxsize = BUS_SPACE_MAXSIZE_24BIT;
			lowaddr = ADV_ISA_MAX_DMA_ADDR;
			adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED;
			adv->isa_dma_channel = adv_get_isa_dma_channel(adv);
			bus_set_resource(dev, SYS_RES_DRQ, 0,
					 adv->isa_dma_channel, 1);
		} else {
			panic("advisaprobe: Unknown card revision\n");
		}

		/*
		 * Allocate a parent dmatag for all tags created
		 * by the MI portions of the advansys driver
		 */
		error = bus_dma_tag_create(
				/* parent	*/ bus_get_dma_tag(dev),
				/* alignemnt	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ lowaddr,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ maxsize,
				/* nsegments	*/ ~0,
				/* maxsegsz	*/ maxsegsz,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&adv->parent_dmat); 

		if (error != 0) {
			device_printf(dev,
			    "Could not allocate DMA tag - error %d\n", error);
			adv_free(adv); 
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		adv->init_level += 2;

		if (overrun_buf == NULL) {
			/* Need to allocate our overrun buffer */
			if (bus_dma_tag_create(
				/* parent	*/ adv->parent_dmat,
				/* alignment	*/ 8,
				/* boundary	*/ 0,
				/* lowaddr	*/ ADV_ISA_MAX_DMA_ADDR,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ ADV_OVERRUN_BSIZE,
				/* nsegments	*/ 1,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&overrun_dmat) != 0) {
				adv_free(adv);
				bus_release_resource(dev, SYS_RES_IOPORT, 0,
						     iores);
				break;
			}
			if (bus_dmamem_alloc(overrun_dmat,
					     (void **)&overrun_buf,
					     BUS_DMA_NOWAIT,
					     &overrun_dmamap) != 0) {
				bus_dma_tag_destroy(overrun_dmat);
				adv_free(adv);
				bus_release_resource(dev, SYS_RES_IOPORT, 0,
						     iores);
				break;
			}
			/* And permanently map it in */  
			bus_dmamap_load(overrun_dmat, overrun_dmamap,
					overrun_buf, ADV_OVERRUN_BSIZE,
					adv_map, &overrun_physbase,
					/*flags*/0);
		}

		adv->overrun_physbase = overrun_physbase;

		if (adv_init(adv) != 0) {
			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
			bus_dmamem_free(overrun_dmat, overrun_buf,
			    overrun_dmamap);
			bus_dma_tag_destroy(overrun_dmat);
			adv_free(adv);
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		switch (adv->type) {
		case ADV_ISAPNP:
			if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG) {
				adv->bug_fix_control
				    |= ADV_BUG_FIX_ASYN_USE_SYN;
				adv->fix_asyn_xfer = ~0;
			}
			/* Fall Through */
		case ADV_ISA:
			adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT;
			adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR;
			adv_set_isa_dma_settings(adv);
			break;

		case ADV_VL:
			adv->max_dma_count = ADV_VL_MAX_DMA_COUNT;
			adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR;
			break;
		default:
			panic("advisaprobe: Invalid card type\n");
		}
			
		/* Determine our IRQ */
		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL))
			bus_set_resource(dev, SYS_RES_IRQ, 0,
					 adv_get_chip_irq(adv), 1);
		else
			adv_set_chip_irq(adv, irq);

		irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
						RF_ACTIVE);
		if (irqres == NULL ||
		    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|
		    INTR_MPSAFE, NULL, adv_intr, adv, &ih) != 0) {
			if (irqres != NULL)
				bus_release_resource(dev, SYS_RES_IRQ, rid,
				    irqres);
			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
			bus_dmamem_free(overrun_dmat, overrun_buf,
			    overrun_dmamap);
			bus_dma_tag_destroy(overrun_dmat);
			adv_free(adv);
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		/* Mark as probed */
		adv_isa_ioports[port_index] = 0;
		return 0;
	}

	if (user_iobase)
		bus_set_resource(dev, SYS_RES_IOPORT, 0, iobase, iocount);
	else
		bus_delete_resource(dev, SYS_RES_IOPORT, 0);

	return ENXIO;
}
Пример #14
0
int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller)
{
	int error;
	device_t device =  controller->isci->device;
	uint32_t max_segment_size = isci_io_request_get_max_io_size();
	uint32_t status = 0;
	struct ISCI_MEMORY *uncached_controller_memory =
	    &controller->uncached_controller_memory;
	struct ISCI_MEMORY *cached_controller_memory =
	    &controller->cached_controller_memory;
	struct ISCI_MEMORY *request_memory =
	    &controller->request_memory;
	POINTER_UINT virtual_address;
	bus_addr_t physical_address;

	controller->mdl = sci_controller_get_memory_descriptor_list_handle(
	    controller->scif_controller_handle);

	uncached_controller_memory->size = sci_mdl_decorator_get_memory_size(
	    controller->mdl, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS);

	error = isci_allocate_dma_buffer(device, uncached_controller_memory);

	if (error != 0)
	    return (error);

	sci_mdl_decorator_assign_memory( controller->mdl,
	    SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS,
	    uncached_controller_memory->virtual_address,
	    uncached_controller_memory->physical_address);

	cached_controller_memory->size = sci_mdl_decorator_get_memory_size(
	    controller->mdl,
	    SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
	);

	error = isci_allocate_dma_buffer(device, cached_controller_memory);

	if (error != 0)
	    return (error);

	sci_mdl_decorator_assign_memory(controller->mdl,
	    SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS,
	    cached_controller_memory->virtual_address,
	    cached_controller_memory->physical_address);

	request_memory->size =
	    controller->queue_depth * isci_io_request_get_object_size();

	error = isci_allocate_dma_buffer(device, request_memory);

	if (error != 0)
	    return (error);

	/* For STP PIO testing, we want to ensure we can force multiple SGLs
	 *  since this has been a problem area in SCIL.  This tunable parameter
	 *  will allow us to force DMA segments to a smaller size, ensuring
	 *  that even if a physically contiguous buffer is attached to this
	 *  I/O, the DMA subsystem will pass us multiple segments in our DMA
	 *  load callback.
	 */
	TUNABLE_INT_FETCH("hw.isci.max_segment_size", &max_segment_size);

	/* Create DMA tag for our I/O requests.  Then we can create DMA maps based off
	 *  of this tag and store them in each of our ISCI_IO_REQUEST objects.  This
	 *  will enable better performance than creating the DMA maps every time we get
	 *  an I/O.
	 */
	status = bus_dma_tag_create(bus_get_dma_tag(device), 0x1, 0x0,
	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
	    isci_io_request_get_max_io_size(),
	    SCI_MAX_SCATTER_GATHER_ELEMENTS, max_segment_size, 0, NULL, NULL,
	    &controller->buffer_dma_tag);

	sci_pool_initialize(controller->request_pool);

	virtual_address = request_memory->virtual_address;
	physical_address = request_memory->physical_address;

	for (int i = 0; i < controller->queue_depth; i++) {
		struct ISCI_REQUEST *request =
		    (struct ISCI_REQUEST *)virtual_address;

		isci_request_construct(request,
		    controller->scif_controller_handle,
		    controller->buffer_dma_tag, physical_address);

		sci_pool_put(controller->request_pool, request);

		virtual_address += isci_request_get_object_size();
		physical_address += isci_request_get_object_size();
	}

	uint32_t remote_device_size = sizeof(struct ISCI_REMOTE_DEVICE) +
	    scif_remote_device_get_object_size();

	controller->remote_device_memory = (uint8_t *) malloc(
	    remote_device_size * SCI_MAX_REMOTE_DEVICES, M_ISCI,
	    M_NOWAIT | M_ZERO);

	sci_pool_initialize(controller->remote_device_pool);

	uint8_t *remote_device_memory_ptr = controller->remote_device_memory;

	for (int i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
		struct ISCI_REMOTE_DEVICE *remote_device =
		    (struct ISCI_REMOTE_DEVICE *)remote_device_memory_ptr;

		controller->remote_device[i] = NULL;
		remote_device->index = i;
		remote_device->is_resetting = FALSE;
		remote_device->frozen_lun_mask = 0;
		sci_fast_list_element_init(remote_device,
		    &remote_device->pending_device_reset_element);
		TAILQ_INIT(&remote_device->queued_ccbs);
		remote_device->release_queued_ccb = FALSE;
		remote_device->queued_ccb_in_progress = NULL;

		/*
		 * For the first SCI_MAX_DOMAINS device objects, do not put
		 *  them in the pool, rather assign them to each domain.  This
		 *  ensures that any device attached directly to port "i" will
		 *  always get CAM target id "i".
		 */
		if (i < SCI_MAX_DOMAINS)
			controller->domain[i].da_remote_device = remote_device;
		else
			sci_pool_put(controller->remote_device_pool,
			    remote_device);
		remote_device_memory_ptr += remote_device_size;
	}

	return (0);
}
Пример #15
0
static int
iir_pci_attach(device_t dev)
{
    struct gdt_softc    *gdt;
    struct resource     *io = NULL, *irq = NULL;
    int                 retries, rid, error = 0;
    void                *ih;
    u_int8_t            protocol;  
 
    /* map DPMEM */
    rid = PCI_DPMEM;
    io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
    if (io == 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 = device_get_softc(dev);
    gdt->sc_devnode = dev;
    gdt->sc_init_level = 0;
    gdt->sc_dpmemt = rman_get_bustag(io);
    gdt->sc_dpmemh = rman_get_bushandle(io);
    gdt->sc_dpmembase = rman_get_start(io);
    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_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC,
                      htole32(GDT_MPR_MAGIC));
    if (bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC) !=
        htole32(GDT_MPR_MAGIC)) {
        printf("cannot access DPMEM at 0x%jx (shadowed?)\n",
               (uintmax_t)gdt->sc_dpmembase);
        error = ENXIO;
        goto err;
    }
    bus_space_set_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_I960_SZ, htole32(0),
                           GDT_MPR_SZ >> 2);

    /* Disable everything */
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN,
                      bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 
                                       GDT_EDOOR_EN) | 4);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS,
                      0);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_CMD_INDEX,
                      0);

    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO,
                      htole32(gdt->sc_dpmembase));
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX,
                      0xff);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1);

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

    protocol = (uint8_t)le32toh(bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                                                  GDT_MPR_IC + GDT_S_INFO));
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS,
                      0);
    if (protocol != GDT_PROTOCOL_VERSION) {
        printf("unsupported protocol %d\n", protocol);
        error = ENXIO;
        goto err;
    }
    
    /* special commnd to controller BIOS */
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO,
                      htole32(0));
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                      GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0));
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                      GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t),
                      htole32(1));
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                      GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t),
                      htole32(0));
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX,
                      0xfe);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1);

    DELAY(20);
    retries = GDT_RETRIES;
    while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh,
                            GDT_MPR_IC + GDT_S_STATUS) != 0xfe) {
        if (--retries == 0) {
            printf("initialization error\n");
            error = ENXIO;
            goto err;
        }
        DELAY(1);
    }

    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 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*/GDT_MAXSG,
                           /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
			   /*flags*/0, /*lockfunc*/busdma_lock_mutex,
			   /*lockarg*/&Giant, &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, 
                        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 (io)
        bus_release_resource( dev, SYS_RES_MEMORY, rid, io );
*/
    return (error);
}
Пример #16
0
static int
malo_pci_attach(device_t dev)
{
	int error = ENXIO, i, msic, reg;
	struct malo_pci_softc *psc = device_get_softc(dev);
	struct malo_softc *sc = &psc->malo_sc;

	sc->malo_dev = dev;
	
	pci_enable_busmaster(dev);

	/* 
	 * Setup memory-mapping of PCI registers.
	 */
	psc->malo_mem_spec = malo_res_spec_mem;
	error = bus_alloc_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);
	if (error) {
		device_printf(dev, "couldn't allocate memory resources\n");
		return (ENXIO);
	}

	/*
	 * Arrange and allocate interrupt line.
	 */
	sc->malo_invalid = 1;

	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
		msic = pci_msi_count(dev);
		if (bootverbose)
			device_printf(dev, "MSI count : %d\n", msic);
	} else
		msic = 0;

	psc->malo_irq_spec = malo_res_spec_legacy;
	if (msic == MALO_MSI_MESSAGES && msi_disable == 0) {
		if (pci_alloc_msi(dev, &msic) == 0) {
			if (msic == MALO_MSI_MESSAGES) {
				device_printf(dev, "Using %d MSI messages\n",
				    msic);
				psc->malo_irq_spec = malo_res_spec_msi;
				psc->malo_msi = 1;
			} else
				pci_release_msi(dev);
		}
	}

	error = bus_alloc_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
	if (error) {
		device_printf(dev, "couldn't allocate IRQ resources\n");
		goto bad;
	}

	if (psc->malo_msi == 0)
		error = bus_setup_intr(dev, psc->malo_res_irq[0],
		    INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc,
		    &psc->malo_intrhand[0]);
	else {
		for (i = 0; i < MALO_MSI_MESSAGES; i++) {
			error = bus_setup_intr(dev, psc->malo_res_irq[i],
			    INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc,
			    &psc->malo_intrhand[i]);
			if (error != 0)
				break;
		}
	}

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

	sc->malo_io0t = rman_get_bustag(psc->malo_res_mem[0]);
	sc->malo_io0h = rman_get_bushandle(psc->malo_res_mem[0]);
	sc->malo_io1t = rman_get_bustag(psc->malo_res_mem[1]);
	sc->malo_io1h = rman_get_bushandle(psc->malo_res_mem[1]);

	error = malo_attach(pci_get_device(dev), sc);

	if (error != 0)
		goto bad2;

	return (error);

bad2:
	bus_dma_tag_destroy(sc->malo_dmat);
bad1:
	if (psc->malo_msi == 0)
		bus_teardown_intr(dev, psc->malo_res_irq[0],
		    psc->malo_intrhand[0]);
	else {
		for (i = 0; i < MALO_MSI_MESSAGES; i++)
			bus_teardown_intr(dev, psc->malo_res_irq[i],
			    psc->malo_intrhand[i]);
	}
	bus_release_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
bad:
	if (psc->malo_msi != 0)
		pci_release_msi(dev);
	bus_release_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);

	return (error);
}
Пример #17
0
static int
dma_attach(device_t dev)
{
	struct dma_softc *dsc;
	struct lsi64854_softc *lsc;
	struct dma_devinfo *ddi;
	device_t cdev;
	const char *name;
	char *cabletype;
	uint32_t csr;
	phandle_t child, node;
	int error, i;

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

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

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

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

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

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

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

 fail_lres:
	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
	    lsc->sc_res);
	return (error);
}
Пример #18
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);
}
Пример #19
0
static int
adv_pci_attach(device_t dev)
{
	struct		adv_softc *adv;
	u_int32_t	id;
	u_int32_t	command;
	int		error, rid, irqrid;
	void		*ih;
	struct resource	*iores, *irqres;

	/*
	 * Determine the chip version.
	 */
	id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4);
	command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);

	/*
	 * These cards do not allow memory mapped accesses, so we must
	 * ensure that I/O accesses are available or we won't be able
	 * to talk to them.
	 */
	if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN))
	 != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) {
		command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN;
		pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1);
	}

	/*
	 * Early chips can't handle non-zero latency timer settings.
	 */
	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
		pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1);
	}

	rid = PCI_BASEADR0;
	iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
				       RF_ACTIVE);
	if (iores == NULL)
		return ENXIO;

	if (adv_find_signature(rman_get_bustag(iores),
			       rman_get_bushandle(iores)) == 0) {
		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
		return ENXIO;
	}

	adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores));
	if (adv == NULL) {
		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
		return ENXIO;
	}

	/* Allocate a dmatag for our transfer DMA maps */
	error = bus_dma_tag_create(
			/* parent	*/ bus_get_dma_tag(dev),
			/* alignment	*/ 1,
			/* boundary	*/ 0,
			/* lowaddr	*/ ADV_PCI_MAX_DMA_ADDR,
			/* highaddr	*/ BUS_SPACE_MAXADDR,
			/* filter	*/ NULL,
			/* filterarg	*/ NULL,
			/* maxsize	*/ BUS_SPACE_MAXSIZE_32BIT,
			/* nsegments	*/ ~0,
			/* maxsegsz	*/ ADV_PCI_MAX_DMA_COUNT,
			/* flags	*/ 0,
			/* lockfunc	*/ busdma_lock_mutex,
			/* lockarg	*/ &Giant,
			&adv->parent_dmat);
 
	if (error != 0) {
		printf("%s: Could not allocate DMA tag - error %d\n",
		       adv_name(adv), error);
		adv_free(adv);
		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
		return ENXIO;
	}

	adv->init_level++;

	if (overrun_buf == NULL) {
		/* Need to allocate our overrun buffer */
		if (bus_dma_tag_create(
				/* parent	*/ adv->parent_dmat,
				/* alignment	*/ 8,
				/* boundary	*/ 0,
				/* lowaddr	*/ ADV_PCI_MAX_DMA_ADDR,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ ADV_OVERRUN_BSIZE,
				/* nsegments	*/ 1,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ busdma_lock_mutex,
				/* lockarg	*/ &Giant,
				&overrun_dmat) != 0) {
			bus_dma_tag_destroy(adv->parent_dmat);
			adv_free(adv);
			bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
			return ENXIO;
       		}
		if (bus_dmamem_alloc(overrun_dmat,
				     &overrun_buf,
				     BUS_DMA_NOWAIT,
				     &overrun_dmamap) != 0) {
			bus_dma_tag_destroy(overrun_dmat);
			bus_dma_tag_destroy(adv->parent_dmat);
			adv_free(adv);
			bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
			return ENXIO;
		}
		/* And permanently map it in */  
		bus_dmamap_load(overrun_dmat, overrun_dmamap,
				overrun_buf, ADV_OVERRUN_BSIZE,
				adv_map, &overrun_physbase,
				/*flags*/0);
	}

	adv->overrun_physbase = overrun_physbase;
			
	/*
	 * Stop the chip.
	 */
	ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
	ADV_OUTW(adv, ADV_CHIP_STATUS, 0);

	adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
	adv->type = ADV_PCI;
	
	/*
	 * Setup active negation and signal filtering.
	 */
	{
		u_int8_t extra_cfg;

		if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150)
			adv->type |= ADV_ULTRA;
		if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050)
			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER;
		else
			extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE;
		ADV_OUTB(adv, ADV_REG_IFC, extra_cfg);
	}

	if (adv_init(adv) != 0) {
		adv_free(adv);
		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
		return ENXIO;
	}

	adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT;
	adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR;

#if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT
	{
		u_int16_t config_msw;

		config_msw = ADV_INW(adv, ADV_CONFIG_MSW);
		config_msw &= 0xFFC0;
		ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); 
	}
#endif
 
	if (id == PCI_DEVICE_ID_ADVANSYS_1200A
	 || id == PCI_DEVICE_ID_ADVANSYS_1200B) {
		adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB;
		adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN;
		adv->fix_asyn_xfer = ~0;
	}

	irqrid = 0;
	irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid,
					RF_SHAREABLE | RF_ACTIVE);
	if (irqres == NULL ||
	    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, NULL, 
	        adv_intr, adv, &ih)) {
		adv_free(adv);
		bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
		return ENXIO;
	}

	adv_attach(adv);
	return 0;
}
Пример #20
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;
}
Пример #21
0
static int
ath_pci_attach(device_t dev)
{
	struct ath_pci_softc *psc = device_get_softc(dev);
	struct ath_softc *sc = &psc->sc_sc;
	int error = ENXIO;
	int rid;
#ifdef	ATH_EEPROM_FIRMWARE
	const struct firmware *fw = NULL;
	const char *buf;
#endif

	sc->sc_dev = dev;

	/*
	 * Enable bus mastering.
	 */
	pci_enable_busmaster(dev);

	/*
	 * Setup other PCI bus configuration parameters.
	 */
	ath_pci_setup(dev);

	/* 
	 * Setup memory-mapping of PCI registers.
	 */
	rid = BS_BAR;
	psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
					    RF_ACTIVE);
	if (psc->sc_sr == NULL) {
		device_printf(dev, "cannot map register space\n");
		goto bad;
	}
	/* XXX uintptr_t is a bandaid for ia64; to be fixed */
	sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr);
	sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr);
	/*
	 * Mark device invalid so any interrupts (shared or otherwise)
	 * that arrive before the HAL is setup are discarded.
	 */
	sc->sc_invalid = 1;

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

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

#ifdef	ATH_EEPROM_FIRMWARE
	/*
	 * If there's an EEPROM firmware image, load that in.
	 */
	if (resource_string_value(device_get_name(dev), device_get_unit(dev),
	    "eeprom_firmware", &buf) == 0) {
		if (bootverbose)
			device_printf(dev, "%s: looking up firmware @ '%s'\n",
			    __func__, buf);

		fw = firmware_get(buf);
		if (fw == NULL) {
			device_printf(dev, "%s: couldn't find firmware\n",
			    __func__);
			goto bad3;
		}

		device_printf(dev, "%s: EEPROM firmware @ %p\n",
		    __func__, fw->data);
		sc->sc_eepromdata =
		    malloc(fw->datasize, M_TEMP, M_WAITOK | M_ZERO);
		if (! sc->sc_eepromdata) {
			device_printf(dev, "%s: can't malloc eepromdata\n",
			    __func__);
			goto bad3;
		}
		memcpy(sc->sc_eepromdata, fw->data, fw->datasize);
		firmware_put(fw, 0);
	}
#endif /* ATH_EEPROM_FIRMWARE */

	ATH_LOCK_INIT(sc);
	ATH_PCU_LOCK_INIT(sc);
	ATH_RX_LOCK_INIT(sc);
	ATH_TX_LOCK_INIT(sc);
	ATH_TX_IC_LOCK_INIT(sc);
	ATH_TXSTATUS_LOCK_INIT(sc);

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

	ATH_TXSTATUS_LOCK_DESTROY(sc);
	ATH_PCU_LOCK_DESTROY(sc);
	ATH_RX_LOCK_DESTROY(sc);
	ATH_TX_IC_LOCK_DESTROY(sc);
	ATH_TX_LOCK_DESTROY(sc);
	ATH_LOCK_DESTROY(sc);
	bus_dma_tag_destroy(sc->sc_dmat);
bad3:
	bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
bad2:
	bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
bad1:
	bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr);
bad:
	return (error);
}
Пример #22
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);
}
Пример #23
0
/*
 * Function name:	tw_osli_alloc_mem
 * Description:		Allocates memory needed both by CL and OSL.
 *
 * Input:		sc	-- OSL internal controller context
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
static TW_INT32
tw_osli_alloc_mem(struct twa_softc *sc)
{
	struct tw_osli_req_context	*req;
	TW_UINT32			max_sg_elements;
	TW_UINT32			non_dma_mem_size;
	TW_UINT32			dma_mem_size;
	TW_INT32			error;
	TW_INT32			i;

	tw_osli_dbg_dprintf(3, sc, "entered");

	sc->flags |= (sizeof(bus_addr_t) == 8) ? TW_CL_64BIT_ADDRESSES : 0;
	sc->flags |= (sizeof(bus_size_t) == 8) ? TW_CL_64BIT_SG_LENGTH : 0;

	max_sg_elements = (sizeof(bus_addr_t) == 8) ?
		TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS;

	if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags,
			sc->device_id, TW_OSLI_MAX_NUM_REQUESTS,  TW_OSLI_MAX_NUM_AENS,
			&(sc->alignment), &(sc->sg_size_factor),
			&non_dma_mem_size, &dma_mem_size
			))) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2008,
			"Can't get Common Layer's memory requirements",
			error);
		return(error);
	}

	if ((sc->non_dma_mem = malloc(non_dma_mem_size, TW_OSLI_MALLOC_CLASS,
				M_WAITOK)) == NULL) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2009,
			"Can't allocate non-dma memory",
			ENOMEM);
		return(ENOMEM);
	}

	/* Create the parent dma tag. */
	if (bus_dma_tag_create(bus_get_dma_tag(sc->bus_dev), /* parent */
				sc->alignment,		/* alignment */
				0,			/* boundary */
				BUS_SPACE_MAXADDR,	/* lowaddr */
				BUS_SPACE_MAXADDR, 	/* highaddr */
				NULL, NULL, 		/* filter, filterarg */
				TW_CL_MAX_IO_SIZE,	/* maxsize */
				max_sg_elements,	/* nsegments */
				TW_CL_MAX_IO_SIZE,	/* maxsegsize */
				0,			/* flags */
				NULL,			/* lockfunc */
				NULL,			/* lockfuncarg */
				&sc->parent_tag		/* tag */)) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x200A,
			"Can't allocate parent DMA tag",
			ENOMEM);
		return(ENOMEM);
	}

	/* Create a dma tag for Common Layer's DMA'able memory (dma_mem). */
	if (bus_dma_tag_create(sc->parent_tag,		/* parent */
				sc->alignment,		/* alignment */
				0,			/* boundary */
				BUS_SPACE_MAXADDR,	/* lowaddr */
				BUS_SPACE_MAXADDR, 	/* highaddr */
				NULL, NULL, 		/* filter, filterarg */
				dma_mem_size,		/* maxsize */
				1,			/* nsegments */
				BUS_SPACE_MAXSIZE,	/* maxsegsize */
				0,			/* flags */
				NULL,			/* lockfunc */
				NULL,			/* lockfuncarg */
				&sc->cmd_tag		/* tag */)) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x200B,
			"Can't allocate DMA tag for Common Layer's "
			"DMA'able memory",
			ENOMEM);
		return(ENOMEM);
	}

	if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
		BUS_DMA_NOWAIT, &sc->cmd_map)) {
		/* Try a second time. */
		if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
			BUS_DMA_NOWAIT, &sc->cmd_map)) {
			tw_osli_printf(sc, "error = %d",
				TW_CL_SEVERITY_ERROR_STRING,
				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
				0x200C,
				"Can't allocate DMA'able memory for the"
				"Common Layer",
				ENOMEM);
			return(ENOMEM);
		}
	}

	bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem,
		dma_mem_size, twa_map_load_callback,
		&sc->dma_mem_phys, 0);

	/*
	 * Create a dma tag for data buffers; size will be the maximum
	 * possible I/O size (128kB).
	 */
	if (bus_dma_tag_create(sc->parent_tag,		/* parent */
				sc->alignment,		/* alignment */
				0,			/* boundary */
				BUS_SPACE_MAXADDR,	/* lowaddr */
				BUS_SPACE_MAXADDR, 	/* highaddr */
				NULL, NULL, 		/* filter, filterarg */
				TW_CL_MAX_IO_SIZE,	/* maxsize */
				max_sg_elements,	/* nsegments */
				TW_CL_MAX_IO_SIZE,	/* maxsegsize */
				BUS_DMA_ALLOCNOW,	/* flags */
				twa_busdma_lock,	/* lockfunc */
				sc->io_lock,		/* lockfuncarg */
				&sc->dma_tag		/* tag */)) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x200F,
			"Can't allocate DMA tag for data buffers",
			ENOMEM);
		return(ENOMEM);
	}

	/*
	 * Create a dma tag for ioctl data buffers; size will be the maximum
	 * possible I/O size (128kB).
	 */
	if (bus_dma_tag_create(sc->parent_tag,		/* parent */
				sc->alignment,		/* alignment */
				0,			/* boundary */
				BUS_SPACE_MAXADDR,	/* lowaddr */
				BUS_SPACE_MAXADDR, 	/* highaddr */
				NULL, NULL, 		/* filter, filterarg */
				TW_CL_MAX_IO_SIZE,	/* maxsize */
				max_sg_elements,	/* nsegments */
				TW_CL_MAX_IO_SIZE,	/* maxsegsize */
				BUS_DMA_ALLOCNOW,	/* flags */
				twa_busdma_lock,	/* lockfunc */
				sc->io_lock,		/* lockfuncarg */
				&sc->ioctl_tag		/* tag */)) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2010,
			"Can't allocate DMA tag for ioctl data buffers",
			ENOMEM);
		return(ENOMEM);
	}

	/* Create just one map for all ioctl request data buffers. */
	if (bus_dmamap_create(sc->ioctl_tag, 0, &sc->ioctl_map)) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2011,
			"Can't create ioctl map",
			ENOMEM);
		return(ENOMEM);
	}


	/* Initialize request queues. */
	tw_osli_req_q_init(sc, TW_OSLI_FREE_Q);
	tw_osli_req_q_init(sc, TW_OSLI_BUSY_Q);

	if ((sc->req_ctx_buf = (struct tw_osli_req_context *)
			malloc((sizeof(struct tw_osli_req_context) *
				TW_OSLI_MAX_NUM_REQUESTS),
				TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2012,
			"Failed to allocate request packets",
			ENOMEM);
		return(ENOMEM);
	}
	bzero(sc->req_ctx_buf,
		sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_REQUESTS);

	for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
		req = &(sc->req_ctx_buf[i]);
		req->ctlr = sc;
		if (bus_dmamap_create(sc->dma_tag, 0, &req->dma_map)) {
			tw_osli_printf(sc, "request # = %d, error = %d",
				TW_CL_SEVERITY_ERROR_STRING,
				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
				0x2013,
				"Can't create dma map",
				i, ENOMEM);
			return(ENOMEM);
		}

		/* Initialize the ioctl wakeup/ timeout mutex */
		req->ioctl_wake_timeout_lock = &(req->ioctl_wake_timeout_lock_handle);
		mtx_init(req->ioctl_wake_timeout_lock, "tw_ioctl_wake_timeout_lock", NULL, MTX_DEF);

		/* Insert request into the free queue. */
		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
	}

	return(0);
}
Пример #24
0
/********************************************************************************
 * Allocate resources, initialise the controller.
 */
static int
twe_attach(device_t dev)
{
    struct twe_softc	*sc;
    struct sysctl_oid	*sysctl_tree;
    int			rid, error;

    debug_called(4);

    /*
     * Initialise the softc structure.
     */
    sc = device_get_softc(dev);
    sc->twe_dev = dev;
    mtx_init(&sc->twe_io_lock, "twe I/O", NULL, MTX_DEF);
    sx_init(&sc->twe_config_lock, "twe config");

    /*
     * XXX: This sysctl tree must stay at hw.tweX rather than using
     * the device_get_sysctl_tree() created by new-bus because
     * existing 3rd party binary tools such as tw_cli and 3dm2 use the
     * existence of this sysctl node to discover controllers.
     */
    sysctl_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev),
	SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
	device_get_nameunit(dev), CTLFLAG_RD, 0, "");
    if (sysctl_tree == NULL) {
	twe_printf(sc, "cannot add sysctl tree node\n");
	return (ENXIO);
    }
    SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(sysctl_tree),
	OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0,
	"TWE driver version");

    /*
     * Force the busmaster enable bit on, in case the BIOS forgot.
     */
    pci_enable_busmaster(dev);

    /*
     * Allocate the PCI register window.
     */
    rid = TWE_IO_CONFIG_REG;
    if ((sc->twe_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 
        RF_ACTIVE)) == NULL) {
	twe_printf(sc, "can't allocate register window\n");
	twe_free(sc);
	return(ENXIO);
    }

    /*
     * 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 */
			   BUS_SPACE_MAXADDR_32BIT, 		/* lowaddr */
			   BUS_SPACE_MAXADDR, 			/* highaddr */
			   NULL, NULL, 				/* filter, filterarg */
			   MAXBSIZE, TWE_MAX_SGL_LENGTH,	/* maxsize, nsegments */
			   BUS_SPACE_MAXSIZE_32BIT,		/* maxsegsize */
			   0,					/* flags */
			   NULL,				/* lockfunc */
			   NULL,				/* lockarg */
			   &sc->twe_parent_dmat)) {
	twe_printf(sc, "can't allocate parent DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }

    /* 
     * Allocate and connect our interrupt.
     */
    rid = 0;
    if ((sc->twe_irq = bus_alloc_resource_any(sc->twe_dev, SYS_RES_IRQ,
        &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
	twe_printf(sc, "can't allocate interrupt\n");
	twe_free(sc);
	return(ENXIO);
    }
    if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE,  
		       NULL, twe_pci_intr, sc, &sc->twe_intr)) {
	twe_printf(sc, "can't set up interrupt\n");
	twe_free(sc);
	return(ENXIO);
    }

    /*
     * Create DMA tag for mapping command's into controller-addressable space.
     */
    if (bus_dma_tag_create(sc->twe_parent_dmat, 	/* parent */
			   1, 0, 			/* alignment, boundary */
			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			   BUS_SPACE_MAXADDR, 		/* highaddr */
			   NULL, NULL, 			/* filter, filterarg */
			   sizeof(TWE_Command) *
			   TWE_Q_LENGTH, 1,		/* maxsize, nsegments */
			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
			   0,				/* flags */
			   NULL,			/* lockfunc */
			   NULL,			/* lockarg */
			   &sc->twe_cmd_dmat)) {
	twe_printf(sc, "can't allocate data buffer DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }
    /*
     * Allocate memory and make it available for DMA.
     */
    if (bus_dmamem_alloc(sc->twe_cmd_dmat, (void **)&sc->twe_cmd,
			 BUS_DMA_NOWAIT, &sc->twe_cmdmap)) {
	twe_printf(sc, "can't allocate command memory\n");
	return(ENOMEM);
    }
    bus_dmamap_load(sc->twe_cmd_dmat, sc->twe_cmdmap, sc->twe_cmd,
		    sizeof(TWE_Command) * TWE_Q_LENGTH,
		    twe_setup_request_dmamap, sc, 0);
    bzero(sc->twe_cmd, sizeof(TWE_Command) * TWE_Q_LENGTH);

    /*
     * Create DMA tag for mapping objects into controller-addressable space.
     */
    if (bus_dma_tag_create(sc->twe_parent_dmat, 	/* parent */
			   1, 0, 			/* alignment, boundary */
			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			   BUS_SPACE_MAXADDR, 		/* highaddr */
			   NULL, NULL, 			/* filter, filterarg */
			   MAXBSIZE, TWE_MAX_SGL_LENGTH,/* maxsize, nsegments */
			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
			   BUS_DMA_ALLOCNOW,		/* flags */
			   busdma_lock_mutex,		/* lockfunc */
			   &sc->twe_io_lock,		/* lockarg */
			   &sc->twe_buffer_dmat)) {
	twe_printf(sc, "can't allocate data buffer DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }

    /*
     * Create DMA tag for mapping objects into controller-addressable space.
     */
    if (bus_dma_tag_create(sc->twe_parent_dmat, 	/* parent */
			   1, 0, 			/* alignment, boundary */
			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			   BUS_SPACE_MAXADDR, 		/* highaddr */
			   NULL, NULL, 			/* filter, filterarg */
			   MAXBSIZE, 1,			/* maxsize, nsegments */
			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
			   0,				/* flags */
			   NULL,			/* lockfunc */
			   NULL,			/* lockarg */
			   &sc->twe_immediate_dmat)) {
	twe_printf(sc, "can't allocate data buffer DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }
    /*
     * Allocate memory for requests which cannot sleep or support continuation.
     */
     if (bus_dmamem_alloc(sc->twe_immediate_dmat, (void **)&sc->twe_immediate,
			  BUS_DMA_NOWAIT, &sc->twe_immediate_map)) {
	twe_printf(sc, "can't allocate memory for immediate requests\n");
	return(ENOMEM);
     }

    /*
     * Initialise the controller and driver core.
     */
    if ((error = twe_setup(sc))) {
	twe_free(sc);
	return(error);
    }

    /*
     * Print some information about the controller and configuration.
     */
    twe_describe_controller(sc);

    /*
     * Create the control device.
     */
    sc->twe_dev_t = make_dev(&twe_cdevsw, device_get_unit(sc->twe_dev), UID_ROOT, GID_OPERATOR,
			     S_IRUSR | S_IWUSR, "twe%d", device_get_unit(sc->twe_dev));
    sc->twe_dev_t->si_drv1 = sc;
    /*
     * Schedule ourselves to bring the controller up once interrupts are available.
     * This isn't strictly necessary, since we disable interrupts while probing the
     * controller, but it is more in keeping with common practice for other disk 
     * devices.
     */
    sc->twe_ich.ich_func = twe_intrhook;
    sc->twe_ich.ich_arg = sc;
    if (config_intrhook_establish(&sc->twe_ich) != 0) {
	twe_printf(sc, "can't establish configuration hook\n");
	twe_free(sc);
	return(ENXIO);
    }

    return(0);
}
Пример #25
0
static int
tws_init(struct tws_softc *sc)
{

    u_int32_t max_sg_elements;
    u_int32_t dma_mem_size;
    int error;
    u_int32_t reg;

    sc->seq_id = 0;
    if ( tws_queue_depth > TWS_MAX_REQS )
        tws_queue_depth = TWS_MAX_REQS;
    if (tws_queue_depth < TWS_RESERVED_REQS+1)
        tws_queue_depth = TWS_RESERVED_REQS+1;
    sc->is64bit = (sizeof(bus_addr_t) == 8) ? true : false;
    max_sg_elements = (sc->is64bit && !tws_use_32bit_sgls) ? 
                                 TWS_MAX_64BIT_SG_ELEMENTS : 
                                 TWS_MAX_32BIT_SG_ELEMENTS;
    dma_mem_size = (sizeof(struct tws_command_packet) * tws_queue_depth) +
                             (TWS_SECTOR_SIZE) ;
    if ( bus_dma_tag_create(bus_get_dma_tag(sc->tws_dev), /* PCI parent */ 
                            TWS_ALIGNMENT,           /* alignment */
                            0,                       /* boundary */
                            BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
                            BUS_SPACE_MAXADDR,       /* highaddr */
                            NULL, NULL,              /* filter, filterarg */
                            BUS_SPACE_MAXSIZE,       /* maxsize */
                            max_sg_elements,         /* numsegs */
                            BUS_SPACE_MAXSIZE,       /* maxsegsize */
                            0,                       /* flags */
                            NULL, NULL,              /* lockfunc, lockfuncarg */
                            &sc->parent_tag          /* tag */
                           )) {
        TWS_TRACE_DEBUG(sc, "DMA parent tag Create fail", max_sg_elements, 
                                                    sc->is64bit);
        return(ENOMEM);
    }
    /* In bound message frame requires 16byte alignment.
     * Outbound MF's can live with 4byte alignment - for now just 
     * use 16 for both.
     */
    if ( bus_dma_tag_create(sc->parent_tag,       /* parent */          
                            TWS_IN_MF_ALIGNMENT,  /* alignment */
                            0,                    /* boundary */
                            BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
                            BUS_SPACE_MAXADDR,    /* highaddr */
                            NULL, NULL,           /* filter, filterarg */
                            dma_mem_size,         /* maxsize */
                            1,                    /* numsegs */
                            BUS_SPACE_MAXSIZE,    /* maxsegsize */
                            0,                    /* flags */
                            NULL, NULL,           /* lockfunc, lockfuncarg */
                            &sc->cmd_tag          /* tag */
                           )) {
        TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit);
        return(ENOMEM);
    }

    if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
                    BUS_DMA_NOWAIT, &sc->cmd_map)) {
        TWS_TRACE_DEBUG(sc, "DMA mem alloc fail", max_sg_elements, sc->is64bit);
        return(ENOMEM);
    }

    /* if bus_dmamem_alloc succeeds then bus_dmamap_load will succeed */
    sc->dma_mem_phys=0;
    error = bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem,
                    dma_mem_size, tws_dmamap_cmds_load_cbfn,
                    &sc->dma_mem_phys, 0);

   /*
    * Create a dma tag for data buffers; size will be the maximum
    * possible I/O size (128kB).
    */
    if (bus_dma_tag_create(sc->parent_tag,         /* parent */
                           TWS_ALIGNMENT,          /* alignment */
                           0,                      /* boundary */
                           BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
                           BUS_SPACE_MAXADDR,      /* highaddr */
                           NULL, NULL,             /* filter, filterarg */
                           TWS_MAX_IO_SIZE,        /* maxsize */
                           max_sg_elements,        /* nsegments */
                           TWS_MAX_IO_SIZE,        /* maxsegsize */
                           BUS_DMA_ALLOCNOW,       /* flags */
                           busdma_lock_mutex,      /* lockfunc */
                           &sc->io_lock,           /* lockfuncarg */
                           &sc->data_tag           /* tag */)) {
        TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit);
        return(ENOMEM);
    }

    sc->reqs = malloc(sizeof(struct tws_request) * tws_queue_depth, M_TWS,
                      M_WAITOK | M_ZERO);
    if ( sc->reqs == NULL ) {
        TWS_TRACE_DEBUG(sc, "malloc failed", 0, sc->is64bit);
        return(ENOMEM);
    }
    sc->sense_bufs = malloc(sizeof(struct tws_sense) * tws_queue_depth, M_TWS,
                      M_WAITOK | M_ZERO);
    if ( sc->sense_bufs == NULL ) {
        TWS_TRACE_DEBUG(sc, "sense malloc failed", 0, sc->is64bit);
        return(ENOMEM);
    }
    sc->scan_ccb = malloc(sizeof(union ccb), M_TWS, M_WAITOK | M_ZERO);
    if ( sc->scan_ccb == NULL ) {
        TWS_TRACE_DEBUG(sc, "ccb malloc failed", 0, sc->is64bit);
        return(ENOMEM);
    }
    if (bus_dmamem_alloc(sc->data_tag, (void **)&sc->ioctl_data_mem,
            (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &sc->ioctl_data_map)) {
        device_printf(sc->tws_dev, "Cannot allocate ioctl data mem\n");
        return(ENOMEM);
    }

    if ( !tws_ctlr_ready(sc) )
        if( !tws_ctlr_reset(sc) )
            return(FAILURE);
    
    bzero(&sc->stats, sizeof(struct tws_stats));
    tws_init_qs(sc);
    tws_turn_off_interrupts(sc);

    /* 
     * enable pull mode by setting bit1 .
     * setting bit0 to 1 will enable interrupt coalesing 
     * will revisit. 
     */

#ifdef TWS_PULL_MODE_ENABLE

    reg = tws_read_reg(sc, TWS_I2O0_CTL, 4);
    TWS_TRACE_DEBUG(sc, "i20 ctl", reg, TWS_I2O0_CTL);
    tws_write_reg(sc, TWS_I2O0_CTL, reg | TWS_BIT1, 4);

#endif

    TWS_TRACE_DEBUG(sc, "dma_mem_phys", sc->dma_mem_phys, TWS_I2O0_CTL);
    if ( tws_init_reqs(sc, dma_mem_size) == FAILURE )
        return(FAILURE);
    if ( tws_init_aen_q(sc) == FAILURE )
        return(FAILURE);

    return(SUCCESS);
    
} 
Пример #26
0
static int
via_attach(device_t dev)
{
	struct via_info *via = 0;
	char status[SND_STATUSLEN];
	u_int32_t data, cnt;

	via = malloc(sizeof(*via), M_DEVBUF, M_WAITOK | M_ZERO);
	via->lock = snd_mtxcreate(device_get_nameunit(dev),
	    "snd_via82c686 softc");

	pci_enable_busmaster(dev);

	/* Wake up and reset AC97 if necessary */
	data = pci_read_config(dev, VIA_AC97STATUS, 1);

	if ((data & VIA_AC97STATUS_RDY) == 0) {
		/* Cold reset per ac97r2.3 spec (page 95) */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Assert low */
		DELAY(100);									/* Wait T_rst_low */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_NRST, 1);	/* Assert high */
		DELAY(5);									/* Wait T_rst2clk */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Assert low */
	} else {
		/* Warm reset */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Force no sync */
		DELAY(100);
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_SYNC, 1);	/* Sync */
		DELAY(5);									/* Wait T_sync_high */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Force no sync */
		DELAY(5);									/* Wait T_sync2clk */
	}

	/* Power everything up */
	pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);	

	/* Wait for codec to become ready (largest reported delay here 310ms) */
	for (cnt = 0; cnt < 2000; cnt++) {
		data = pci_read_config(dev, VIA_AC97STATUS, 1);
		if (data & VIA_AC97STATUS_RDY) 
			break;
		DELAY(5000);
	}

	via->regid = PCIR_BAR(0);
	via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
		&via->regid, RF_ACTIVE);
	if (!via->reg) {
		device_printf(dev, "cannot allocate bus resource.");
		goto bad;
	}
	via->st = rman_get_bustag(via->reg);
	via->sh = rman_get_bushandle(via->reg);

	via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);

	via->irqid = 0;
	via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
		RF_ACTIVE | RF_SHAREABLE);
	if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) {
		device_printf(dev, "unable to map interrupt\n");
		goto bad;
	}

	via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
	via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);

	via->codec = AC97_CREATE(dev, via, via_ac97);
	if (!via->codec)
		goto bad;

	if (mixer_init(dev, ac97_getmixerclass(), via->codec))
		goto bad;

	via->codec_caps = ac97_getextcaps(via->codec);
	ac97_setextmode(via->codec, 
			via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));

	/* DMA tag for buffers */
	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*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0, /*lockfunc*/NULL,
		/*lockarg*/NULL, &via->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	/*
	 *  DMA tag for SGD table.  The 686 uses scatter/gather DMA and
	 *  requires a list in memory of work to do.  We need only 16 bytes
	 *  for this list, and it is wasteful to allocate 16K.
	 */
	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*/NSEGS * sizeof(struct via_dma_op),
		/*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0, /*lockfunc*/NULL,
		/*lockarg*/NULL, &via->sgd_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
	    BUS_DMA_NOWAIT, &via->sgd_dmamap) != 0)
		goto bad;
	if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
	    NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0) != 0)
		goto bad;

	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
		 rman_get_start(via->reg), rman_get_start(via->irq),
		 PCM_KLDSTRING(snd_via82c686));

	/* Register */
	if (pcm_register(dev, via, 1, 1)) goto bad;
	pcm_addchan(dev, PCMDIR_PLAY, &viachan_class, via);
	pcm_addchan(dev, PCMDIR_REC, &viachan_class, via);
	pcm_setstatus(dev, status);
	return 0;
bad:
	if (via->codec) ac97_destroy(via->codec);
	if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
	if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
	if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
	if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
	if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
	if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
	if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
	if (via->lock) snd_mtxfree(via->lock);
	if (via) free(via, M_DEVBUF);
	return ENXIO;
}
Пример #27
0
static int
mpt_dma_mem_alloc(struct mpt_softc *mpt)
{
	size_t len;
	struct mpt_map_info mi;

	/* Check if we alreay have allocated the reply memory */
	if (mpt->reply_phys != 0) {
		return 0;
	}

	len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt);
	mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
	if (mpt->request_pool == NULL) {
		mpt_prt(mpt, "cannot allocate request pool\n");
		return (1);
	}

	/*
	 * Create a parent dma tag for this device.
	 *
	 * Align at byte boundaries,
	 * Limit to 32-bit addressing for request/reply queues.
	 */
	if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev),
	    /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR,
	    /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL,
	    /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
	    /*nsegments*/BUS_SPACE_UNRESTRICTED,
	    /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0,
	    &mpt->parent_dmat) != 0) {
		mpt_prt(mpt, "cannot create parent dma tag\n");
		return (1);
	}

	/* Create a child tag for reply buffers */
	if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
	    NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
	    &mpt->reply_dmat) != 0) {
		mpt_prt(mpt, "cannot create a dma tag for replies\n");
		return (1);
	}

	/* Allocate some DMA accessible memory for replies */
	if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply,
	    BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) {
		mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n",
		    (u_long) (2 * PAGE_SIZE));
		return (1);
	}

	mi.mpt = mpt;
	mi.error = 0;

	/* Load and lock it into "bus space" */
	bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply,
	    2 * PAGE_SIZE, mpt_map_rquest, &mi, 0);

	if (mi.error) {
		mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n",
		    mi.error);
		return (1);
	}
	mpt->reply_phys = mi.phys;

	return (0);
}
Пример #28
0
static int
ahc_pci_attach(device_t dev)
{
	struct	 ahc_pci_identity *entry;
	struct	 ahc_softc *ahc;
	char	*name;
	int	 error;

	entry = ahc_find_pci_device(dev);
	if (entry == NULL)
		return (ENXIO);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, device_get_nameunit(dev));
	ahc = ahc_alloc(dev, name);
	if (ahc == NULL)
		return (ENOMEM);

	ahc_set_unit(ahc, device_get_unit(dev));

	/*
	 * Should we bother disabling 39Bit addressing
	 * based on installed memory?
	 */
	if (sizeof(bus_addr_t) > 4)
                ahc->flags |= AHC_39BIT_ADDRESSING;

	/* Allocate a dmatag for our SCB DMA maps */
	error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev),
				   /*alignment*/1, /*boundary*/0,
				   (ahc->flags & AHC_39BIT_ADDRESSING)
				   ? 0x7FFFFFFFFFLL
				   : BUS_SPACE_MAXADDR_32BIT,
				   /*highaddr*/BUS_SPACE_MAXADDR,
				   /*filter*/NULL, /*filterarg*/NULL,
				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
				   /*nsegments*/AHC_NSEG,
				   /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
				   /*flags*/0,
				   &ahc->parent_dmat);

	if (error != 0) {
		printf("ahc_pci_attach: Could not allocate DMA tag "
		       "- error %d\n", error);
		ahc_free(ahc);
		return (ENOMEM);
	}
	ahc->dev_softc = dev;
	error = ahc_pci_config(ahc, entry);
	if (error != 0) {
		ahc_free(ahc);
		return (error);
	}

	ahc_attach(ahc);
	return (0);
}
Пример #29
0
static int
dpt_isa_attach (device_t dev)
{
	dpt_softc_t *	dpt;
	int		error = 0;

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

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

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

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

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

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

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

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

	return (error);

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

	dpt_release_resources(dev);

	if (dpt)
		dpt_free(dpt);

	return (error);
}
Пример #30
0
static int
ahc_isa_attach(device_t dev)
{
	struct	 aic7770_identity *entry;
	bus_space_tag_t	    tag;
	bus_space_handle_t  bsh;
	struct	  resource *regs;
	struct	  ahc_softc *ahc;
	char	 *name;
	int	  zero;
	int	  error;

	zero = 0;
	regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &zero, RF_ACTIVE);
	if (regs == NULL)
		return (ENOMEM);

	tag = rman_get_bustag(regs);
	bsh = rman_get_bushandle(regs);
	entry = ahc_isa_find_device(tag, bsh);
	bus_release_resource(dev, SYS_RES_IOPORT, zero, regs);
	if (entry == NULL)
		return (ENODEV);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, device_get_nameunit(dev));
	ahc = ahc_alloc(dev, name);
	if (ahc == NULL)
		return (ENOMEM);

	ahc_set_unit(ahc, device_get_unit(dev));

	/* Allocate a dmatag for our SCB DMA maps */
	error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev),
				   /*alignment*/1, /*boundary*/0,
				   /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
				   /*highaddr*/BUS_SPACE_MAXADDR,
				   /*filter*/NULL, /*filterarg*/NULL,
				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
				   /*nsegments*/AHC_NSEG,
				   /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
				   /*flags*/0,
				   &ahc->parent_dmat);

	if (error != 0) {
		printf("ahc_isa_attach: Could not allocate DMA tag "
		       "- error %d\n", error);
		ahc_free(ahc);
		return (ENOMEM);
	}
	ahc->dev_softc = dev;
	error = aic7770_config(ahc, entry, /*unused ioport arg*/0);
	if (error != 0) {
		ahc_free(ahc);
		return (error);
	}

	ahc_attach(ahc);
	return (0);
}