Ejemplo n.º 1
0
static
int
ig4iic_acpi_detach(device_t dev)
{
	ig4iic_softc_t *sc = device_get_softc(dev);
	int error;

	if (sc->pci_attached) {
		error = ig4iic_detach(sc);
		if (error)
			return error;
		sc->pci_attached = 0;
	}

	if (sc->intr_res) {
		bus_release_resource(dev, SYS_RES_IRQ,
				     sc->intr_rid, sc->intr_res);
		sc->intr_res = NULL;
	}
	if (sc->regs_res) {
		bus_release_resource(dev, SYS_RES_MEMORY,
				     sc->regs_rid, sc->regs_res);
		sc->regs_res = NULL;
	}
	sc->regs_t = 0;
	sc->regs_h = 0;

	pci_set_powerstate(dev, PCI_POWERSTATE_D3);

	return 0;
}
Ejemplo n.º 2
0
static int
atiixp_pci_suspend(device_t dev)
{
	struct atiixp_info *sc = pcm_getdevinfo(dev);
	uint32_t value;

	/* quickly disable interrupts and save channels active state */
	atiixp_lock(sc);
	atiixp_disable_interrupts(sc);
	value = atiixp_rd(sc, ATI_REG_CMD);
	sc->pch.active = (value & ATI_REG_CMD_SEND_EN) ? 1 : 0;
	sc->rch.active = (value & ATI_REG_CMD_RECEIVE_EN) ? 1 : 0;
	atiixp_unlock(sc);

	/* stop everything */
	if (sc->pch.channel && sc->pch.active)
		atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
	if (sc->rch.channel && sc->rch.active)
		atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);

	/* power down aclink and pci bus */
	atiixp_lock(sc);
	value = atiixp_rd(sc, ATI_REG_CMD);
	value |= ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET;
	atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN);
	pci_set_powerstate(dev, PCI_POWERSTATE_D3);
	atiixp_unlock(sc);

	return 0;
}
Ejemplo n.º 3
0
static int
vga_pci_set_powerstate(device_t dev, device_t child, int state)
{

	device_printf(dev, "child %s requested pci_set_powerstate\n",
	    device_get_nameunit(child));
	return (pci_set_powerstate(dev, state));
}
Ejemplo n.º 4
0
static int
rtw_pci_attach(device_t dev)
{
	struct rtw_softc *sc = device_get_softc(dev);
	struct rtw_regs *regs = &sc->sc_regs;
	int i, error;

	/*
	 * No power management hooks.
	 * XXX Maybe we should add some!
	 */
	sc->sc_flags |= RTW_F_ENABLED;

	sc->sc_rev = pci_get_revid(dev);

#ifndef BURN_BRIDGES
	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
		uint32_t mem, port, irq;
						
		mem = pci_read_config(dev, RTW_PCI_MMBA, 4);
		port = pci_read_config(dev, RTW_PCI_IOBA, 4);
		irq = pci_read_config(dev, PCIR_INTLINE, 4);
		
		device_printf(dev, "chip is in D%d power mode "
		    "-- setting to D0\n", pci_get_powerstate(dev));

		pci_set_powerstate(dev, PCI_POWERSTATE_D0);

		pci_write_config(dev, RTW_PCI_MMBA, mem, 4);
		pci_write_config(dev, RTW_PCI_IOBA, port, 4);
		pci_write_config(dev, PCIR_INTLINE, irq, 4);
	}
#endif	/* !BURN_BRIDGES */

	/* Enable PCI bus master */
	pci_enable_busmaster(dev);

	/* Allocate IO memory/port */
	for (i = 0; i < NELEM(rtw_pci_regs); ++i) {
		regs->r_rid = rtw_pci_regs[i].reg_rid;
		regs->r_type = rtw_pci_regs[i].reg_type;
		regs->r_res = bus_alloc_resource_any(dev, regs->r_type,
						     &regs->r_rid, RF_ACTIVE);
		if (regs->r_res != NULL)
			break;
	}
	if (regs->r_res == NULL) {
		device_printf(dev, "can't allocate IO mem/port\n");
		return ENXIO;
	}
	regs->r_bh = rman_get_bushandle(regs->r_res);
	regs->r_bt = rman_get_bustag(regs->r_res);

	error = rtw_attach(dev);
	if (error)
		rtw_pci_detach(dev);
	return error;
}
Ejemplo n.º 5
0
static int
ral_pci_attach(device_t dev)
{
	struct ral_pci_softc *psc = device_get_softc(dev);
	struct rt2560_softc *sc = &psc->u.sc_rt2560;
	int error;

	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
		device_printf(dev, "chip is in D%d power mode "
		    "-- setting to D0\n", pci_get_powerstate(dev));
		pci_set_powerstate(dev, PCI_POWERSTATE_D0);
	}

	/* enable bus-mastering */
	pci_enable_busmaster(dev);

	psc->sc_opns = (pci_get_device(dev) == 0x0201) ? &ral_rt2560_opns :
	    &ral_rt2661_opns;

	psc->mem_rid = RAL_PCI_BAR0;
	psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &psc->mem_rid,
	    RF_ACTIVE);
	if (psc->mem == NULL) {
		device_printf(dev, "could not allocate memory resource\n");
		return ENXIO;
	}

	sc->sc_st = rman_get_bustag(psc->mem);
	sc->sc_sh = rman_get_bushandle(psc->mem);
	sc->sc_invalid = 1;
	
	psc->irq_rid = 0;
	psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &psc->irq_rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (psc->irq == NULL) {
		device_printf(dev, "could not allocate interrupt resource\n");
		return ENXIO;
	}

	error = (*psc->sc_opns->attach)(dev, pci_get_device(dev));
	if (error != 0)
		return error;

	/*
	 * Hook our interrupt after all initialization is complete.
	 */
	error = bus_setup_intr(dev, psc->irq, INTR_TYPE_NET | INTR_MPSAFE,
	    NULL, psc->sc_opns->intr, psc, &psc->sc_ih);
	if (error != 0) {
		device_printf(dev, "could not set up interrupt\n");
		return error;
	}
	sc->sc_invalid = 0;
	
	return 0;
}
Ejemplo n.º 6
0
void
rtsx_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct rtsx_pci_softc *sc = (struct rtsx_pci_softc *)self;
	struct pci_attach_args *pa = aux;
	pci_intr_handle_t ih;
	char const *intrstr;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	bus_size_t size;
	int flags;

	if ((pci_conf_read(pa->pa_pc, pa->pa_tag, RTSX_CFG_PCI)
	    & RTSX_CFG_ASIC) != 0) {
		printf("%s: no asic\n", sc->sc.sc_dev.dv_xname);
		return;
	}

	if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) {
		printf(": can't map interrupt\n");
		return;
	}

	intrstr = pci_intr_string(pa->pa_pc, ih);
	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC,
	    rtsx_intr, sc, sc->sc.sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": can't establish interrupt\n");
		return;
	}
	printf(": %s\n", intrstr);

	if (pci_mem_find(pa->pa_pc, pa->pa_tag, RTSX_PCI_BAR,
	    NULL, NULL, NULL) != 0) {
		printf("%s: can't find registers\n", sc->sc.sc_dev.dv_xname);
	    	return;
	}

	if (pci_mapreg_map(pa, RTSX_PCI_BAR, PCI_MAPREG_TYPE_MEM, 0,
	    &iot, &ioh, NULL, &size, 0)) {
		printf("%s: can't map registers\n", sc->sc.sc_dev.dv_xname);
		return;
	}

	pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209)
		flags = RTSX_F_5209;
	else
		flags = RTSX_F_5229;

	if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat, flags) != 0)
		printf("%s: can't initialize chip\n", sc->sc.sc_dev.dv_xname);
}
Ejemplo n.º 7
0
int
acpi_pci_suspend(device_t dev)
{
    int dstate, error, i, numdevs;
    device_t acpi_dev, child, *devlist;
    struct pci_devinfo *dinfo;

    acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
    device_get_children(dev, &devlist, &numdevs);

    /*
     * Save the PCI configuration space for each child and set the
     * device in the appropriate power state for this sleep state.
     */
    for (i = 0; i < numdevs; i++) {
        child = devlist[i];
        dinfo = (struct pci_devinfo *)device_get_ivars(child);
        pci_cfg_save(child, dinfo, 0);
    }

    /*
     * Suspend devices before potentially powering them down.
     */
    error = bus_generic_suspend(dev);
    if (error) {
        kfree(devlist, M_TEMP);
        return (error);
    }

    /*
     * Always set the device to D3.  If ACPI suggests a different
     * power state, use it instead.  If ACPI is not present, the
     * firmware is responsible for managing device power.  Skip
     * children who aren't attached since they are powered down
     * separately.  Only manage type 0 devices for now.
     */
    for (i = 0; acpi_dev && i < numdevs; i++) {
        child = devlist[i];
        dinfo = (struct pci_devinfo *)device_get_ivars(child);
        if (device_is_attached(child) && dinfo->cfg.hdrtype == 0) {
            dstate = PCI_POWERSTATE_D3;
            ACPI_PWR_FOR_SLEEP(acpi_dev, child, &dstate);
            pci_set_powerstate(child, dstate);
        }
    }

    kfree(devlist, M_TEMP);
    return (0);
}
Ejemplo n.º 8
0
static int
ohci_pci_take_controller(device_t self)
{
	uint32_t reg;
	uint32_t int_line;

	if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) {
		device_printf(self, "chip is in D%d mode "
		    "-- setting to D0\n", pci_get_powerstate(self));
		reg = pci_read_config(self, PCI_CBMEM, 4);
		int_line = pci_read_config(self, PCIR_INTLINE, 4);
		pci_set_powerstate(self, PCI_POWERSTATE_D0);
		pci_write_config(self, PCI_CBMEM, reg, 4);
		pci_write_config(self, PCIR_INTLINE, int_line, 4);
	}
	return (0);
}
Ejemplo n.º 9
0
static int
atiixp_pci_resume(device_t dev)
{
	struct atiixp_info *sc = pcm_getdevinfo(dev);

	atiixp_lock(sc);
	/* power up pci bus */
	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
	pci_enable_io(dev, SYS_RES_MEMORY);
	pci_enable_busmaster(dev);
	/* reset / power up aclink */
	atiixp_reset_aclink(sc);
	atiixp_unlock(sc);

	if (mixer_reinit(dev) == -1) {
		device_printf(dev, "unable to reinitialize the mixer\n");
		return ENXIO;
	}

	/*
	 * Resume channel activities. Reset channel format regardless
	 * of its previous state.
	 */
	if (sc->pch.channel) {
		if (sc->pch.fmt)
			atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
		if (sc->pch.active)
			atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
	}
	if (sc->rch.channel) {
		if (sc->rch.fmt)
			atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
		if (sc->rch.active)
			atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
	}

	/* enable interrupts */
	atiixp_lock(sc);
	atiixp_enable_interrupts(sc);
	atiixp_unlock(sc);

	return 0;
}
Ejemplo n.º 10
0
static int
ohci_pci_resume(device_t self)
{
	ohci_softc_t *sc = device_get_softc(self);
	uint32_t reg, int_line;

	if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) {
		device_printf(self, "chip is in D%d mode "
		    "-- setting to D0\n", pci_get_powerstate(self));
		reg = pci_read_config(self, PCI_CBMEM, 4);
		int_line = pci_read_config(self, PCIR_INTLINE, 4);
		pci_set_powerstate(self, PCI_POWERSTATE_D0);
		pci_write_config(self, PCI_CBMEM, reg, 4);
		pci_write_config(self, PCIR_INTLINE, int_line, 4);
	}
	ohci_resume(sc);

	bus_generic_resume(self);
	return (0);
}
Ejemplo n.º 11
0
static
int
ig4iic_acpi_attach(device_t dev)
{
	ig4iic_softc_t *sc = device_get_softc(dev);
	int error;

	lwkt_serialize_init(&sc->slz);

	sc->dev = dev;
	/* All the HIDs matched are Atom SOCs. */
	sc->version = IG4_ATOM;
	sc->regs_rid = 0;
	sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
					  &sc->regs_rid, RF_ACTIVE);
	if (sc->regs_res == NULL) {
		device_printf(dev, "unable to map registers");
		ig4iic_acpi_detach(dev);
		return (ENXIO);
	}
	sc->intr_rid = 0;
	sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
					  &sc->intr_rid, RF_ACTIVE);
	if (sc->intr_res == NULL) {
		device_printf(dev, "unable to map interrupt");
		ig4iic_acpi_detach(dev);
		return (ENXIO);
	}
	sc->regs_t = rman_get_bustag(sc->regs_res);
	sc->regs_h = rman_get_bushandle(sc->regs_res);
	sc->pci_attached = 1;

	/* power up the controller */
	pci_set_powerstate(dev, PCI_POWERSTATE_D0);

	error = ig4iic_attach(sc);
	if (error)
		ig4iic_acpi_detach(dev);

	return error;
}
Ejemplo n.º 12
0
/*
 * Still need this because the pci code only does power for type 0
 * header devices.
 */
static void
cbb_powerstate_d0(device_t dev)
{
	u_int32_t membase, irq;

	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
		/* Save important PCI config data. */
		membase = pci_read_config(dev, CBBR_SOCKBASE, 4);
		irq = pci_read_config(dev, PCIR_INTLINE, 4);

		/* Reset the power state. */
		device_printf(dev, "chip is in D%d power mode "
		    "-- setting to D0\n", pci_get_powerstate(dev));

		pci_set_powerstate(dev, PCI_POWERSTATE_D0);

		/* Restore PCI config data. */
		pci_write_config(dev, CBBR_SOCKBASE, membase, 4);
		pci_write_config(dev, PCIR_INTLINE, irq, 4);
	}
}
Ejemplo n.º 13
0
void
pcidevdetached(device_t self, device_t child)
{
	struct pci_softc *sc = device_private(self);
	int d, f;
	pcitag_t tag;
	struct pci_child *c;

	d = device_locator(child, PCICF_DEV);
	f = device_locator(child, PCICF_FUNCTION);

	c = &sc->PCI_SC_DEVICESC(d, f);

	KASSERT(c->c_dev == child);

	tag = pci_make_tag(sc->sc_pc, sc->sc_bus, d, f);
	if (c->c_psok)
		pci_set_powerstate(sc->sc_pc, tag, c->c_powerstate);
	pci_conf_restore(sc->sc_pc, tag, &c->c_conf);
	c->c_dev = NULL;
}
Ejemplo n.º 14
0
int
pci_activate(pci_chipset_tag_t pc, pcitag_t tag, device_t dev,
    int (*wakefun)(pci_chipset_tag_t, pcitag_t, device_t, pcireg_t))
{
	pcireg_t pmode;
	int error;

	if ((error = pci_get_powerstate(pc, tag, &pmode)))
		return error;

	switch (pmode) {
	case PCI_PMCSR_STATE_D0:
		break;
	case PCI_PMCSR_STATE_D3:
		if (wakefun == NULL) {
			/*
			 * The card has lost all configuration data in
			 * this state, so punt.
			 */
			aprint_error_dev(dev,
			    "unable to wake up from power state D3\n");
			return EOPNOTSUPP;
		}
		/*FALLTHROUGH*/
	default:
		if (wakefun) {
			error = (*wakefun)(pc, tag, dev, pmode);
			if (error)
				return error;
		}
		aprint_normal_dev(dev, "waking up from power state D%d\n",
		    pmode);
		if ((error = pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0)))
			return error;
	}
	return 0;
}
Ejemplo n.º 15
0
static int
ohci_pci_resume(device_t self)
{
	ohci_softc_t *sc = device_get_softc(self);

#ifndef BURN_BRIDGES
	uint32_t reg, int_line;

	if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) {
		device_printf(self, "chip is in D%d mode "
		        "-- setting to D0\n", pci_get_powerstate(self));
		reg = pci_read_config(self, PCI_CBMEM, 4);
		int_line = pci_read_config(self, PCIR_INTLINE, 4);
		pci_set_powerstate(self, PCI_POWERSTATE_D0);
		pci_write_config(self, PCI_CBMEM, reg, 4);
		pci_write_config(self, PCIR_INTLINE, int_line, 4);
	}
#endif	/* !BURN_BRIDGES */

	ohci_power(PWR_RESUME, sc);
	bus_generic_resume(self);

	return 0;
}
Ejemplo n.º 16
0
int
acpi_pci_resume(device_t dev)
{
    int i, numdevs;
    device_t acpi_dev, child, *devlist;
    struct pci_devinfo *dinfo;

    acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
    device_get_children(dev, &devlist, &numdevs);

    /*
     * Set each child to D0 and restore its PCI configuration space.
     */
    for (i = 0; i < numdevs; i++) {
        /*
         * Notify ACPI we're going to D0 but ignore the result.  If
         * ACPI is not present, the firmware is responsible for
         * managing device power.  Only manage type 0 devices for now.
         */
        child = devlist[i];
        dinfo = (struct pci_devinfo *) device_get_ivars(child);
        if (acpi_dev && device_is_attached(child) &&
                dinfo->cfg.hdrtype == 0) {
            ACPI_PWR_FOR_SLEEP(acpi_dev, child, NULL);
            pci_set_powerstate(child, PCI_POWERSTATE_D0);
        }

        /*
         * Now the device is powered up, restore its config space.
         */
        pci_cfg_restore(child, dinfo);
    }

    kfree(devlist, M_TEMP);
    return (bus_generic_resume(dev));
}
Ejemplo n.º 17
0
static int
atiixp_pci_attach(device_t dev)
{
	struct atiixp_info *sc;
	int i;

	sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
	sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
	sc->dev = dev;
	/*
	 * Default DMA segments per playback / recording channel
	 */
	sc->dma_segs = ATI_IXP_DMA_CHSEGS;

	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
	pci_enable_busmaster(dev);

	sc->regid = PCIR_BAR(0);
	sc->regtype = SYS_RES_MEMORY;
	sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
								RF_ACTIVE);

	if (!sc->reg) {
		device_printf(dev, "unable to allocate register space\n");
		goto bad;
	}

	sc->st = rman_get_bustag(sc->reg);
	sc->sh = rman_get_bushandle(sc->reg);

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

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

	/*
	 * Let the user choose the best DMA segments.
	 */
	 if (resource_int_value(device_get_name(dev),
			device_get_unit(dev), "dma_segs",
			&i) == 0) {
		if (i < ATI_IXP_DMA_CHSEGS_MIN)
			i = ATI_IXP_DMA_CHSEGS_MIN;
		if (i > ATI_IXP_DMA_CHSEGS_MAX)
			i = ATI_IXP_DMA_CHSEGS_MAX;
		sc->dma_segs = i;
	}

	/*
	 * round the value to the nearest ^2
	 */
	i = 0;
	while (sc->dma_segs >> i)
		i++;
	sc->dma_segs = 1 << (i - 1);
	if (sc->dma_segs < ATI_IXP_DMA_CHSEGS_MIN)
		sc->dma_segs = ATI_IXP_DMA_CHSEGS_MIN;
	else if (sc->dma_segs > ATI_IXP_DMA_CHSEGS_MAX)
		sc->dma_segs = ATI_IXP_DMA_CHSEGS_MAX;

	/*
	 * DMA tag for scatter-gather buffers and link pointers
	 */
	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
		/*highaddr*/BUS_SPACE_MAXADDR,
		/*filter*/NULL, /*filterarg*/NULL,
		/*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0,
		&sc->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
		/*highaddr*/BUS_SPACE_MAXADDR,
		/*filter*/NULL, /*filterarg*/NULL,
		/*maxsize*/sc->dma_segs * ATI_IXP_NCHANS *
						sizeof(struct atiixp_dma_op),
		/*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0,
		&sc->sgd_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table, 
				BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1)
		goto bad;

	if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table, 
				sc->dma_segs * ATI_IXP_NCHANS *
						sizeof(struct atiixp_dma_op),
				atiixp_dma_cb, sc, 0))
		goto bad;


	atiixp_chip_pre_init(sc);

	sc->delayed_attach.ich_func = atiixp_chip_post_init;
	sc->delayed_attach.ich_arg = sc;
	sc->delayed_attach.ich_desc = "snd_atiixp";
	if (cold == 0 ||
			config_intrhook_establish(&sc->delayed_attach) != 0) {
		sc->delayed_attach.ich_func = NULL;
		atiixp_chip_post_init(sc);
	}

	return 0;

bad:
	atiixp_release_resource(sc);
	return ENXIO;
}
Ejemplo n.º 18
0
void
sf_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct sf_pci_softc *psc = (void *) self;
	struct sf_softc *sc = &psc->sc_starfire;
	struct pci_attach_args *pa = aux;
	pci_intr_handle_t ih;
	const char *intrstr = NULL;
	bus_space_tag_t iot, memt;
	bus_space_handle_t ioh, memh;
	int state, ioh_valid, memh_valid;
	bus_size_t iosize, memsize;
	pcireg_t reg;

	state = pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
	if (state == PCI_PMCSR_STATE_D3) {
		printf(": unable to wake up from power state D3, "
		    "reboot required.\n");
		return;
	}

	/*
	 * Map the device.
	 */
	reg = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SF_PCI_MEMBA);
	switch (reg) {
	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
		memh_valid = (pci_mapreg_map(pa, SF_PCI_MEMBA,
		    reg, 0, &memt, &memh, &memsize, NULL, 0) == 0);
		break;
	default:
		memh_valid = 0;
	}

	ioh_valid = (pci_mapreg_map(pa,
	    (reg == (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT)) ?
		SF_PCI_IOBA : SF_PCI_IOBA - 0x04,
	    PCI_MAPREG_TYPE_IO, 0,
	    &iot, &ioh, &iosize, NULL, 0) == 0);

	if (memh_valid) {
		sc->sc_st = memt;
		sc->sc_sh = memh;
		sc->sc_iomapped = 0;
	} else if (ioh_valid) {
		sc->sc_st = iot;
		sc->sc_sh = ioh;
		sc->sc_iomapped = 1;
	} else {
		printf(": unable to map device registers\n");
		return;
	}

	sc->sc_dmat = pa->pa_dmat;

	/*
	 * Map and establish our interrupt.
	 */
	if (pci_intr_map(pa, &ih)) {
		printf(": unable to map interrupt\n");
		goto out;
	}
	intrstr = pci_intr_string(pa->pa_pc, ih);
	psc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, sf_intr, sc,
	    self->dv_xname);
	if (psc->sc_ih == NULL) {
		printf(": unable to establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		goto out;
	}
	printf(": %s", intrstr);

	/*
	 * Finish off the attach.
	 */
	sf_attach(sc);
	return;

 out:
	if (ioh_valid)
		bus_space_unmap(iot, ioh, iosize);
	if (memh_valid)
		bus_space_unmap(memt, memh, memsize);
}
Ejemplo n.º 19
0
void
rtw_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct rtw_pci_softc *psc = (void *) self;
	struct rtw_softc *sc = &psc->psc_rtw;
	struct rtw_regs *regs = &sc->sc_regs;
	struct pci_attach_args *pa = aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	const char *intrstr = NULL;
	bus_space_tag_t iot, memt;
	bus_space_handle_t ioh, memh;
	bus_size_t iosize, memsize;
	int ioh_valid, memh_valid;

	psc->psc_pc = pa->pa_pc;
	psc->psc_pcitag = pa->pa_tag;

	/*
	 * No power management hooks.
	 * XXX Maybe we should add some!
	 */
	sc->sc_flags |= RTW_F_ENABLED;

	/*
	 * Get revision info, and set some chip-specific variables.
	 */
	sc->sc_rev = PCI_REVISION(pa->pa_class);

	pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	/*
	 * Map the device.
	 */
	ioh_valid = (pci_mapreg_map(pa, RTW_PCI_IOBA,
	    PCI_MAPREG_TYPE_IO, 0,
	    &iot, &ioh, NULL, &iosize, 0) == 0);
	memh_valid = (pci_mapreg_map(pa, RTW_PCI_MMBA,
	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &memt, &memh, NULL, &memsize, 0) == 0);

	if (memh_valid) {
		regs->r_bt = memt;
		regs->r_bh = memh;
		psc->psc_mapsize = memsize;
	} else if (ioh_valid) {
		regs->r_bt = iot;
		regs->r_bh = ioh;
		psc->psc_mapsize = iosize;
	} else {
		printf(": unable to map device registers\n");
		return;
	}

	sc->sc_dmat = pa->pa_dmat;

	/*
	 * Map and establish our interrupt.
	 */
	if (pci_intr_map(pa, &psc->psc_ih)) {
		printf(": unable to map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pc, psc->psc_ih); 
	psc->psc_intrcookie = pci_intr_establish(pc, psc->psc_ih, IPL_NET,
	    rtw_intr, sc, sc->sc_dev.dv_xname);
	if (psc->psc_intrcookie == NULL) {
		printf(": unable to establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}

	printf(": %s\n", intrstr);

	sc->sc_enable = rtw_pci_enable;
	sc->sc_disable = rtw_pci_disable;

	/*
	 * Finish off the attach.
	 */
	rtw_attach(sc);
}
Ejemplo n.º 20
0
void
stge_attach(struct device *parent, struct device *self, void *aux)
{
	struct stge_softc *sc = (struct stge_softc *) self;
	struct pci_attach_args *pa = aux;
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	pci_chipset_tag_t pc = pa->pa_pc;
	pci_intr_handle_t ih;
	const char *intrstr = NULL;
	bus_space_tag_t iot, memt;
	bus_space_handle_t ioh, memh;
	bus_dma_segment_t seg;
	bus_size_t iosize;
	int ioh_valid, memh_valid;
	int i, rseg, error;

	timeout_set(&sc->sc_timeout, stge_tick, sc);

	sc->sc_rev = PCI_REVISION(pa->pa_class);

	/*
	 * Map the device.
	 */
	ioh_valid = (pci_mapreg_map(pa, STGE_PCI_IOBA,
	    PCI_MAPREG_TYPE_IO, 0,
	    &iot, &ioh, NULL, &iosize, 0) == 0);
	memh_valid = (pci_mapreg_map(pa, STGE_PCI_MMBA,
	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &memt, &memh, NULL, &iosize, 0) == 0);

	if (memh_valid) {
		sc->sc_st = memt;
		sc->sc_sh = memh;
	} else if (ioh_valid) {
		sc->sc_st = iot;
		sc->sc_sh = ioh;
	} else {
		printf(": unable to map device registers\n");
		return;
	}

	sc->sc_dmat = pa->pa_dmat;

	/* Get it out of power save mode if needed. */
	pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	/*
	 * Map and establish our interrupt.
	 */
	if (pci_intr_map(pa, &ih)) {
		printf(": unable to map interrupt\n");
		goto fail_0;
	}
	intrstr = pci_intr_string(pc, ih);
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, stge_intr, sc,
				       sc->sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": unable to establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		goto fail_0;
	}
	printf(": %s", intrstr);

	/*
	 * Allocate the control data structures, and create and load the
	 * DMA map for it.
	 */
	if ((error = bus_dmamem_alloc(sc->sc_dmat,
	    sizeof(struct stge_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,
	    0)) != 0) {
		printf("%s: unable to allocate control data, error = %d\n",
		    sc->sc_dev.dv_xname, error);
		goto fail_0;
	}

	if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
	    sizeof(struct stge_control_data), (caddr_t *)&sc->sc_control_data,
	    BUS_DMA_COHERENT)) != 0) {
		printf("%s: unable to map control data, error = %d\n",
		    sc->sc_dev.dv_xname, error);
		goto fail_1;
	}

	if ((error = bus_dmamap_create(sc->sc_dmat,
	    sizeof(struct stge_control_data), 1,
	    sizeof(struct stge_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
		printf("%s: unable to create control data DMA map, "
		    "error = %d\n", sc->sc_dev.dv_xname, error);
		goto fail_2;
	}

	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
	    sc->sc_control_data, sizeof(struct stge_control_data), NULL,
	    0)) != 0) {
		printf("%s: unable to load control data DMA map, error = %d\n",
		    sc->sc_dev.dv_xname, error);
		goto fail_3;
	}

	/*
	 * Create the transmit buffer DMA maps.  Note that rev B.3
	 * and earlier seem to have a bug regarding multi-fragment
	 * packets.  We need to limit the number of Tx segments on
	 * such chips to 1.
	 */
	for (i = 0; i < STGE_NTXDESC; i++) {
		if ((error = bus_dmamap_create(sc->sc_dmat,
		    STGE_JUMBO_FRAMELEN, STGE_NTXFRAGS, MCLBYTES, 0, 0,
		    &sc->sc_txsoft[i].ds_dmamap)) != 0) {
			printf("%s: unable to create tx DMA map %d, "
			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
			goto fail_4;
		}
	}

	/*
	 * Create the receive buffer DMA maps.
	 */
	for (i = 0; i < STGE_NRXDESC; i++) {
		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
		    MCLBYTES, 0, 0, &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
			printf("%s: unable to create rx DMA map %d, "
			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
			goto fail_5;
		}
		sc->sc_rxsoft[i].ds_mbuf = NULL;
	}

	/*
	 * Determine if we're copper or fiber.  It affects how we
	 * reset the card.
	 */
	if (CSR_READ_4(sc, STGE_AsicCtrl) & AC_PhyMedia)
		sc->sc_usefiber = 1;
	else
		sc->sc_usefiber = 0;

	/*
	 * Reset the chip to a known state.
	 */
	stge_reset(sc);

	/*
	 * Reading the station address from the EEPROM doesn't seem
	 * to work, at least on my sample boards.  Instead, since
	 * the reset sequence does AutoInit, read it from the station
	 * address registers. For Sundance 1023 you can only read it
	 * from EEPROM.
	 */
	if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_SUNDANCE_ST1023) {
		sc->sc_arpcom.ac_enaddr[0] = CSR_READ_2(sc,
		    STGE_StationAddress0) & 0xff;
		sc->sc_arpcom.ac_enaddr[1] = CSR_READ_2(sc,
		    STGE_StationAddress0) >> 8;
		sc->sc_arpcom.ac_enaddr[2] = CSR_READ_2(sc,
		    STGE_StationAddress1) & 0xff;
		sc->sc_arpcom.ac_enaddr[3] = CSR_READ_2(sc,
		    STGE_StationAddress1) >> 8;
		sc->sc_arpcom.ac_enaddr[4] = CSR_READ_2(sc,
		    STGE_StationAddress2) & 0xff;
		sc->sc_arpcom.ac_enaddr[5] = CSR_READ_2(sc,
		    STGE_StationAddress2) >> 8;
		sc->sc_stge1023 = 0;
	} else {
Ejemplo n.º 21
0
static int
cs4281_pci_attach(device_t dev)
{
    struct sc_info *sc;
    struct ac97_info *codec = NULL;
    u_int32_t data;
    char status[SND_STATUSLEN];

    if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
	device_printf(dev, "cannot allocate softc\n");
	return ENXIO;
    }

    bzero(sc, sizeof(*sc));
    sc->dev = dev;
    sc->type = pci_get_devid(dev);

    data = pci_read_config(dev, PCIR_COMMAND, 2);
    data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
    pci_write_config(dev, PCIR_COMMAND, data, 2);

    data = pci_read_config(dev, PCIR_COMMAND, 2);

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

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

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

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

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

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

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

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

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

    mixer_init(dev, ac97_getmixerclass(), codec);

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

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

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

    return 0;

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

    return ENXIO;
}
Ejemplo n.º 22
0
int
ppbactivate(struct device *self, int act)
{
	struct ppb_softc *sc = (void *)self;
	pci_chipset_tag_t pc = sc->sc_pc;
	pcitag_t tag = sc->sc_tag;
	pcireg_t blr, reg;
	int off, rv = 0;

	switch (act) {
	case DVACT_QUIESCE:
		rv = config_activate_children(self, act);
		break;
	case DVACT_SUSPEND:
		rv = config_activate_children(self, act);

		/* Save registers that may get lost. */
		sc->sc_csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
		sc->sc_bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
		sc->sc_bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
		sc->sc_bcr = pci_conf_read(pc, tag, PPB_REG_BRIDGECONTROL);
		sc->sc_int = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
		if (sc->sc_cap_off)
			sc->sc_slcsr = pci_conf_read(pc, tag,
			    sc->sc_cap_off + PCI_PCIE_SLCSR);

		if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg)) {
			sc->sc_msi_ma = pci_conf_read(pc, tag,
			    off + PCI_MSI_MA);
			if (reg & PCI_MSI_MC_C64) {
				sc->sc_msi_mau32 = pci_conf_read(pc, tag,
				    off + PCI_MSI_MAU32);
				sc->sc_msi_md = pci_conf_read(pc, tag,
				    off + PCI_MSI_MD64);
			} else {
				sc->sc_msi_md = pci_conf_read(pc, tag,
				    off + PCI_MSI_MD32);
			}
			sc->sc_msi_mc = reg;
		}

		if (pci_dopm) {	
			/* Place the bridge into D3. */
			sc->sc_pmcsr_state = pci_get_powerstate(pc, tag);
			pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D3);
		}
		break;
	case DVACT_RESUME:
		if (pci_dopm) {
			/* Restore power. */
			pci_set_powerstate(pc, tag, sc->sc_pmcsr_state);
		}

		/* Restore the registers saved above. */
		pci_conf_write(pc, tag, PCI_BHLC_REG, sc->sc_bhlcr);
		pci_conf_write(pc, tag, PPB_REG_BUSINFO, sc->sc_bir);
		pci_conf_write(pc, tag, PPB_REG_BRIDGECONTROL, sc->sc_bcr);
		pci_conf_write(pc, tag, PCI_INTERRUPT_REG, sc->sc_int);
		if (sc->sc_cap_off)
			pci_conf_write(pc, tag,
			    sc->sc_cap_off + PCI_PCIE_SLCSR, sc->sc_slcsr);

		/* Restore I/O window. */
		blr = pci_conf_read(pc, tag, PPB_REG_IOSTATUS);
		blr &= 0xffff0000;
		blr |= sc->sc_iolimit & PPB_IO_MASK;
		blr |= (sc->sc_iobase >> PPB_IO_SHIFT);
		pci_conf_write(pc, tag, PPB_REG_IOSTATUS, blr);
		blr = (sc->sc_iobase & 0xffff0000) >> 16;
		blr |= sc->sc_iolimit & 0xffff0000;
		pci_conf_write(pc, tag, PPB_REG_IO_HI, blr);

		/* Restore memory mapped I/O window. */
		blr = sc->sc_memlimit & PPB_MEM_MASK;
		blr |= (sc->sc_membase >> PPB_MEM_SHIFT);
		pci_conf_write(pc, tag, PPB_REG_MEM, blr);

		/* Restore prefetchable MMI/O window. */
		blr = sc->sc_pmemlimit & PPB_MEM_MASK;
		blr |= (sc->sc_pmembase >> PPB_MEM_SHIFT);
		pci_conf_write(pc, tag, PPB_REG_PREFMEM, blr);
#ifdef __LP64__
		pci_conf_write(pc, tag, PPB_REG_PREFBASE_HI32,
		    sc->sc_pmembase >> 32);
		pci_conf_write(pc, tag, PPB_REG_PREFLIM_HI32,
		    sc->sc_pmemlimit >> 32);
#endif

		if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg)) {
			pci_conf_write(pc, tag, off + PCI_MSI_MA,
			    sc->sc_msi_ma);
			if (reg & PCI_MSI_MC_C64) {
				pci_conf_write(pc, tag, off + PCI_MSI_MAU32,
				    sc->sc_msi_mau32);
				pci_conf_write(pc, tag, off + PCI_MSI_MD64,
				    sc->sc_msi_md);
			} else {
				pci_conf_write(pc, tag, off + PCI_MSI_MD32,
				    sc->sc_msi_md);
			}
			pci_conf_write(pc, tag, off + PCI_MSI_MC,
			    sc->sc_msi_mc);
		}

		/*
		 * Restore command register last to avoid exposing
		 * uninitialised windows.
		 */
		reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
		    (reg & 0xffff0000) | (sc->sc_csr & 0x0000ffff));

		rv = config_activate_children(self, act);
		break;
	}
	return (rv);
}
Ejemplo n.º 23
0
static int
via_attach(device_t dev)
{
	struct via_info *via = NULL;
	char status[SND_STATUSLEN];
	int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum;
	uint32_t revid;

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

	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
	pci_enable_busmaster(dev);

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

	/* DMA tag for buffers */
	if (bus_dma_tag_create(/*parent*/NULL, /*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,
		&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*/NULL, /*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,
		&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) == -1)
		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))
		goto bad;

	if (via_chip_init(dev))
		goto bad;

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

	mixer_init(dev, ac97_getmixerclass(), via->codec);

	via->codec_caps = ac97_getextcaps(via->codec);

	/* Try to set VRA without generating an error, VRM not reqrd yet */
	if (via->codec_caps & 
	    (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) {
		u_int16_t ext = ac97_getextmode(via->codec);
		ext |= (via->codec_caps & 
			(AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
		ext &= ~AC97_EXTCAP_DRA;
		ac97_setextmode(via->codec, ext);
	}

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

	revid = pci_get_revid(dev);

	/*
	 * VIA8251 lost its interrupt after DMA EOL, and need
	 * a gentle spank on its face within interrupt handler.
	 */
	if (revid == VIA8233_REV_ID_8251)
		via->dma_eol_wake = 1;
	else
		via->dma_eol_wake = 0;

	/*
	 * Decide whether DXS had to be disabled or not
	 */
	if (revid == VIA8233_REV_ID_8233A) {
		/*
		 * DXS channel is disabled.  Reports from multiple users
		 * that it plays at half-speed.  Do not see this behaviour
		 * on available 8233C or when emulating 8233A register set
		 * on 8233C (either with or without ac97 VRA).
		 */
		via_dxs_disabled = 1;
	} else if (resource_int_value(device_get_name(dev),
			device_get_unit(dev), "via_dxs_disabled",
			&via_dxs_disabled) == 0)
		via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0;
	else
		via_dxs_disabled = 0;

	if (via_dxs_disabled) {
		via_dxs_chnum = 0;
		via_sgd_chnum = 1;
	} else {
		if (resource_int_value(device_get_name(dev),
				device_get_unit(dev), "via_dxs_channels",
				&via_dxs_chnum) != 0)
			via_dxs_chnum = NDXSCHANS;
		if (resource_int_value(device_get_name(dev),
				device_get_unit(dev), "via_sgd_channels",
				&via_sgd_chnum) != 0)
			via_sgd_chnum = NMSGDCHANS;
	}
	if (via_dxs_chnum > NDXSCHANS)
		via_dxs_chnum = NDXSCHANS;
	else if (via_dxs_chnum < 0)
		via_dxs_chnum = 0;
	if (via_sgd_chnum > NMSGDCHANS)
		via_sgd_chnum = NMSGDCHANS;
	else if (via_sgd_chnum < 0)
		via_sgd_chnum = 0;
	if (via_dxs_chnum + via_sgd_chnum < 1) {
		/* Minimalist ? */
		via_dxs_chnum = 1;
		via_sgd_chnum = 0;
	}
	if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev),
			device_get_unit(dev), "via_dxs_src",
			&via_dxs_src) == 0)
		via->dxs_src = (via_dxs_src > 0) ? 1 : 0;
	else
		via->dxs_src = 0;
	/* Register */
	if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS))
	      goto bad;
	for (i = 0; i < via_dxs_chnum; i++)
	      pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
	for (i = 0; i < via_sgd_chnum; i++)
	      pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
	for (i = 0; i < NWRCHANS; i++)
	      pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
	if (via_dxs_chnum > 0)
		via_init_sysctls(dev);
	device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n",
		(via_dxs_chnum > 0) ? "En" : "Dis",
		(via->dxs_src) ? "(SRC)" : "",
		via_dxs_chnum, via_sgd_chnum, NWRCHANS);

	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) kfree(via, M_DEVBUF);
	return ENXIO;
}
Ejemplo n.º 24
0
/*
 * Attach the interface. Allocate softc structures, do ifmedia
 * setup and ethernet/BPF attach.
 */
void
dc_pci_attach(struct device *parent, struct device *self, void *aux)
{
	const char		*intrstr = NULL;
	pcireg_t		command;
	struct dc_pci_softc	*psc = (struct dc_pci_softc *)self;
	struct dc_softc		*sc = &psc->psc_softc;
	struct pci_attach_args	*pa = aux;
	pci_chipset_tag_t	pc = pa->pa_pc;
	pci_intr_handle_t	ih;
	int			found = 0;

	psc->psc_pc = pa->pa_pc;
	sc->sc_dmat = pa->pa_dmat;

	pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);

	/*
	 * Map control/status registers.
	 */
#ifdef DC_USEIOSPACE
	if (pci_mapreg_map(pa, DC_PCI_CFBIO,
	    PCI_MAPREG_TYPE_IO, 0,
	    &sc->dc_btag, &sc->dc_bhandle, NULL, &psc->psc_mapsize, 0)) {
		printf(": can't map i/o space\n");
		return;
	}
#else
	if (pci_mapreg_map(pa, DC_PCI_CFBMA,
	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->dc_btag, &sc->dc_bhandle, NULL, &psc->psc_mapsize, 0)) {
		printf(": can't map mem space\n");
		return;
	}
#endif

	/* Allocate interrupt */
	if (pci_intr_map(pa, &ih)) {
		printf(": couldn't map interrupt\n");
		goto fail_1;
	}
	intrstr = pci_intr_string(pc, ih);
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc,
	    self->dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": couldn't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		goto fail_1;
	}
	printf(": %s", intrstr);

	/* Need this info to decide on a chip type. */
	sc->dc_revision = PCI_REVISION(pa->pa_class);

	/* Get the eeprom width, if possible */
	if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LITEON &&
	      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC))
		;	/* PNIC has non-standard eeprom */
	else if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_XIRCOM &&
	      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143))
		;	/* XIRCOM has non-standard eeprom */
	else
		dc_eeprom_width(sc);

	switch (PCI_VENDOR(pa->pa_id)) {
	case PCI_VENDOR_DEC:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21140 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) {
			found = 1;
			sc->dc_type = DC_TYPE_21143;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_REDUCED_MII_POLL;
			dc_read_srom(sc, sc->dc_romwidth);
		}
		break;
	case PCI_VENDOR_INTEL:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_21145) {
			found = 1;
			sc->dc_type = DC_TYPE_21145;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_REDUCED_MII_POLL;
			dc_read_srom(sc, sc->dc_romwidth);
		}
		break;
	case PCI_VENDOR_DAVICOM:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9009) {
			found = 1;
			sc->dc_type = DC_TYPE_DM9102;
			sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS;
			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD;
			sc->dc_flags |= DC_TX_ALIGN;
			sc->dc_pmode = DC_PMODE_MII;

			/* Increase the latency timer value. */
			command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFLT);
			command &= 0xFFFF00FF;
			command |= 0x00008000;
			pci_conf_write(pc, pa->pa_tag, DC_PCI_CFLT, command);
		}
		break;
	case PCI_VENDOR_ADMTEK:
	case PCI_VENDOR_3COM:
	case PCI_VENDOR_MICROSOFT:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) {
			found = 1;
			sc->dc_type = DC_TYPE_AL981;
			sc->dc_flags |= DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_TX_ADMTEK_WAR;
			sc->dc_pmode = DC_PMODE_MII;
			dc_read_srom(sc, sc->dc_romwidth);
		}
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_ADM9511 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_ADM9513 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3COM_3CSHO100BTX ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MICROSOFT_MN130) {
			found = 1;
			sc->dc_type = DC_TYPE_AN983;
			sc->dc_flags |= DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_TX_ADMTEK_WAR;
			sc->dc_flags |= DC_64BIT_HASH;
			sc->dc_pmode = DC_PMODE_MII;
			/* Don't read SROM for - auto-loaded on reset */
		}
		break;
	case PCI_VENDOR_MACRONIX:
	case PCI_VENDOR_ACCTON:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN2242) {
			found = 1;
			sc->dc_type = DC_TYPE_AN983;
			sc->dc_flags |= DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_TX_ADMTEK_WAR;
			sc->dc_flags |= DC_64BIT_HASH;
			sc->dc_pmode = DC_PMODE_MII;
			/* Don't read SROM for - auto-loaded on reset */
		}
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) {
			found = 1;
			if (sc->dc_revision < DC_REVISION_98713A)
				sc->dc_type = DC_TYPE_98713;
			if (sc->dc_revision >= DC_REVISION_98713A) {
				sc->dc_type = DC_TYPE_98713A;
				sc->dc_flags |= DC_21143_NWAY;
			}
			sc->dc_flags |= DC_REDUCED_MII_POLL;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
		}
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 ||
		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) {
			found = 1;
			if (sc->dc_revision >= DC_REVISION_98715AEC_C &&
			    sc->dc_revision < DC_REVISION_98725)
				sc->dc_flags |= DC_128BIT_HASH;
			sc->dc_type = DC_TYPE_987x5;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
		}
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98727) {
			found = 1;
			sc->dc_type = DC_TYPE_987x5;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
		}
		break;
	case PCI_VENDOR_COMPEX:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) {
			found = 1;
			if (sc->dc_revision < DC_REVISION_98713A) {
				sc->dc_type = DC_TYPE_98713;
				sc->dc_flags |= DC_REDUCED_MII_POLL;
			}
			if (sc->dc_revision >= DC_REVISION_98713A)
				sc->dc_type = DC_TYPE_98713A;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
		}
		break;
	case PCI_VENDOR_LITEON:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) {
			found = 1;
			sc->dc_type = DC_TYPE_PNICII;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY;
			sc->dc_flags |= DC_128BIT_HASH;
		}
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) {
			found = 1;
			sc->dc_type = DC_TYPE_PNIC;
			sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS;
			sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
			sc->dc_pnic_rx_buf = malloc(ETHER_MAX_DIX_LEN * 5, M_DEVBUF,
			    M_NOWAIT);
			if (sc->dc_pnic_rx_buf == NULL)
				panic("dc_pci_attach");
			if (sc->dc_revision < DC_REVISION_82C169)
				sc->dc_pmode = DC_PMODE_SYM;
		}
		break;
	case PCI_VENDOR_ASIX:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) {
			found = 1;
			sc->dc_type = DC_TYPE_ASIX;
			sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG;
			sc->dc_flags |= DC_REDUCED_MII_POLL;
			sc->dc_pmode = DC_PMODE_MII;
		}
		break;
	case PCI_VENDOR_CONEXANT:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONEXANT_RS7112) {
			found = 1;
			sc->dc_type = DC_TYPE_CONEXANT;
			sc->dc_flags |= DC_TX_INTR_ALWAYS;
			sc->dc_flags |= DC_REDUCED_MII_POLL;
			sc->dc_pmode = DC_PMODE_MII;
			dc_read_srom(sc, sc->dc_romwidth);
		}
		break;
	case PCI_VENDOR_XIRCOM:
		if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143) {
			found = 1;
			sc->dc_type = DC_TYPE_XIRCOM;
			sc->dc_flags |= DC_TX_INTR_ALWAYS;
			sc->dc_flags |= DC_TX_COALESCE;
			sc->dc_flags |= DC_TX_ALIGN;
			sc->dc_pmode = DC_PMODE_MII;
		}
		break;
	}
	if (found == 0) {
		/* This shouldn't happen if probe has done its job... */
		printf(": unknown device: %x:%x\n",
		    PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id));
		goto fail_2;
	}

	/* Save the cache line size. */
	if (DC_IS_DAVICOM(sc))
		sc->dc_cachesize = 0;
	else
		sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag,
		    DC_PCI_CFLT) & 0xFF;

	/* Reset the adapter. */
	dc_reset(sc);

	/* Take 21143 out of snooze mode */
	if (DC_IS_INTEL(sc) || DC_IS_XIRCOM(sc)) {
		command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD);
		command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE);
		pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command);
	}

	/*
	 * If we discover later (in dc_attach) that we have an
	 * MII with no PHY, we need to have the 21143 drive the LEDs.
	 * Except there are some systems like the NEC VersaPro NoteBook PC
	 * which have no LEDs, and twiddling these bits has adverse effects
	 * on them. (I.e. you suddenly can't get a link.)
	 *
	 * If mii_attach() returns an error, we leave the DC_TULIP_LEDS
	 * bit set, else we clear it. Since our dc(4) driver is split into
	 * bus-dependent and bus-independent parts, we must do set this bit
	 * here while we are able to do PCI configuration reads.
	 */
	if (DC_IS_INTEL(sc)) {
		if (pci_conf_read(pc, pa->pa_tag, DC_PCI_CSID) != 0x80281033)
			sc->dc_flags |= DC_TULIP_LEDS;
	}

	/*
	 * Try to learn something about the supported media.
	 * We know that ASIX and ADMtek and Davicom devices
	 * will *always* be using MII media, so that's a no-brainer.
	 * The tricky ones are the Macronix/PNIC II and the
	 * Intel 21143.
	 */
	if (DC_IS_INTEL(sc))
		dc_parse_21143_srom(sc);
	else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
		if (sc->dc_type == DC_TYPE_98713)
			sc->dc_pmode = DC_PMODE_MII;
		else
			sc->dc_pmode = DC_PMODE_SYM;
	} else if (!sc->dc_pmode)
		sc->dc_pmode = DC_PMODE_MII;

#ifdef __sparc64__
	{
		extern void myetheraddr(u_char *);

		if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address",
		    sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0)
			myetheraddr(sc->sc_arpcom.ac_enaddr);
		if (sc->sc_arpcom.ac_enaddr[0] == 0x00 &&
		    sc->sc_arpcom.ac_enaddr[1] == 0x03 &&
		    sc->sc_arpcom.ac_enaddr[2] == 0xcc)
			sc->dc_flags |= DC_MOMENCO_BOTCH;
		sc->sc_hasmac = 1;
	}
#endif

#ifdef SRM_MEDIA
	sc->dc_srm_media = 0;

	/* Remember the SRM console media setting */
	if (DC_IS_INTEL(sc)) {
		command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD);
		command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE);
		switch ((command >> 8) & 0xff) {
		case 3: 
			sc->dc_srm_media = IFM_10_T;
			break;
		case 4: 
			sc->dc_srm_media = IFM_10_T | IFM_FDX;
			break;
		case 5: 
			sc->dc_srm_media = IFM_100_TX;
			break;
		case 6: 
			sc->dc_srm_media = IFM_100_TX | IFM_FDX;
			break;
		}
		if (sc->dc_srm_media)
			sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER;
	}
#endif
	dc_attach(sc);

	return;

fail_2:
	pci_intr_disestablish(pc, sc->sc_ih);

fail_1:
	bus_space_unmap(sc->dc_btag, sc->dc_bhandle, psc->psc_mapsize);
}
Ejemplo n.º 25
0
void
rtwn_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct rtwn_pci_softc *sc = (struct rtwn_pci_softc*)self;
	struct pci_attach_args *pa = aux;
	struct ifnet *ifp;
	int i, error;
	pcireg_t memtype;
	pci_intr_handle_t ih;
	const char *intrstr;

	sc->sc_dmat = pa->pa_dmat;
	sc->sc_pc = pa->pa_pc;
	sc->sc_tag = pa->pa_tag;

	timeout_set(&sc->calib_to, rtwn_calib_to, sc);
	timeout_set(&sc->scan_to, rtwn_scan_to, sc);

	pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	/* Map control/status registers. */
	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RTWN_PCI_MMBA);
	error = pci_mapreg_map(pa, RTWN_PCI_MMBA, memtype, 0, &sc->sc_st,
	    &sc->sc_sh, NULL, &sc->sc_mapsize, 0);
	if (error != 0) {
		printf(": can't map mem space\n");
		return;
	}

	if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) {
		printf(": can't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(sc->sc_pc, ih);
	sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET,
	    rtwn_intr, sc, sc->sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": can't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}
	printf(": %s\n", intrstr);

	/* Disable PCIe Active State Power Management (ASPM). */
	if (pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_PCIEXPRESS,
	    &sc->sc_cap_off, NULL)) {
		uint32_t lcsr = pci_conf_read(sc->sc_pc, sc->sc_tag,
		    sc->sc_cap_off + PCI_PCIE_LCSR);
		lcsr &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1);
		pci_conf_write(sc->sc_pc, sc->sc_tag,
		    sc->sc_cap_off + PCI_PCIE_LCSR, lcsr);
	}

	/* Allocate Tx/Rx buffers. */
	error = rtwn_alloc_rx_list(sc);
	if (error != 0) {
		printf("%s: could not allocate Rx buffers\n",
		    sc->sc_dev.dv_xname);
		return;
	}
	for (i = 0; i < RTWN_NTXQUEUES; i++) {
		error = rtwn_alloc_tx_list(sc, i);
		if (error != 0) {
			printf("%s: could not allocate Tx buffers\n",
			    sc->sc_dev.dv_xname);
			rtwn_free_rx_list(sc);
			return;
		}
	}

	/* Attach the bus-agnostic driver. */
	sc->sc_sc.sc_ops.cookie = sc;
	sc->sc_sc.sc_ops.write_1 = rtwn_pci_write_1;
	sc->sc_sc.sc_ops.write_2 = rtwn_pci_write_2;
	sc->sc_sc.sc_ops.write_4 = rtwn_pci_write_4;
	sc->sc_sc.sc_ops.read_1 = rtwn_pci_read_1;
	sc->sc_sc.sc_ops.read_2 = rtwn_pci_read_2;
	sc->sc_sc.sc_ops.read_4 = rtwn_pci_read_4;
	sc->sc_sc.sc_ops.tx = rtwn_tx;
	sc->sc_sc.sc_ops.power_on = rtwn_power_on;
	sc->sc_sc.sc_ops.dma_init = rtwn_dma_init;
	sc->sc_sc.sc_ops.load_firmware = rtwn_pci_load_firmware;
	sc->sc_sc.sc_ops.fw_loadpage = rtwn_fw_loadpage;
	sc->sc_sc.sc_ops.mac_init = rtwn_mac_init;
	sc->sc_sc.sc_ops.bb_init = rtwn_bb_init;
	sc->sc_sc.sc_ops.alloc_buffers = rtwn_alloc_buffers;
	sc->sc_sc.sc_ops.init = rtwn_pci_init;
	sc->sc_sc.sc_ops.stop = rtwn_pci_stop;
	sc->sc_sc.sc_ops.is_oactive = rtwn_is_oactive;
	sc->sc_sc.sc_ops.next_calib = rtwn_next_calib;
	sc->sc_sc.sc_ops.cancel_calib = rtwn_cancel_calib;
	sc->sc_sc.sc_ops.next_scan = rtwn_pci_next_scan;
	sc->sc_sc.sc_ops.cancel_scan = rtwn_cancel_scan;
	sc->sc_sc.sc_ops.wait_async = rtwn_wait_async;
	error = rtwn_attach(&sc->sc_dev, &sc->sc_sc,
	    RTWN_CHIP_88C | RTWN_CHIP_PCI);
	if (error != 0) {
		rtwn_free_rx_list(sc);
		for (i = 0; i < RTWN_NTXQUEUES; i++)
			rtwn_free_tx_list(sc, i);
		return;
	}

	/* ifp is now valid */
	ifp = &sc->sc_sc.sc_ic.ic_if;
#if NBPFILTER > 0
	bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
	    sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);

	sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
	sc->sc_rxtap.wr_ihdr.it_present = htole32(RTWN_RX_RADIOTAP_PRESENT);

	sc->sc_txtap_len = sizeof(sc->sc_txtapu);
	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
	sc->sc_txtap.wt_ihdr.it_present = htole32(RTWN_TX_RADIOTAP_PRESENT);
#endif
}
Ejemplo n.º 26
0
static void
rtsx_pci_attach(device_t parent, device_t self, void *aux)
{
	struct rtsx_pci_softc *sc = device_private(self);
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;
	pcireg_t reg;
	char const *intrstr;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	bus_size_t size;
	uint32_t flags;
	char intrbuf[PCI_INTRSTR_LEN];

	sc->sc.sc_dev = self;
	sc->sc_pc = pc;

	pci_aprint_devinfo(pa, NULL);

	if ((pci_conf_read(pc, tag, RTSX_CFG_PCI) & RTSX_CFG_ASIC) != 0) {
		aprint_error_dev(self, "no asic\n");
		return;
	}

	if (pci_mapreg_map(pa, RTSX_PCI_BAR, PCI_MAPREG_TYPE_MEM, 0,
	    &iot, &ioh, NULL, &size)) {
		aprint_error_dev(self, "couldn't map registers\n");
		return;
	}

	if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pc, sc->sc_pihp[0], intrbuf, sizeof(intrbuf));
	sc->sc_ih = pci_intr_establish(pc, sc->sc_pihp[0], IPL_SDMMC,
	    rtsx_intr, &sc->sc);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "couldn't establish interrupt\n");
		return;
	}
	aprint_normal_dev(self, "interrupting at %s\n", intrstr);

	/* Enable the device */
	reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_MASTER_ENABLE;
	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg);

	/* Power up the device */
	pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0);

	switch (PCI_PRODUCT(pa->pa_id)) {
	case PCI_PRODUCT_REALTEK_RTS5209:
		flags = RTSX_F_5209;
		break;
	case PCI_PRODUCT_REALTEK_RTS5227:
		flags = RTSX_F_5227;
		break;
	case PCI_PRODUCT_REALTEK_RTS5229:
		flags = RTSX_F_5229;
		break;
	case PCI_PRODUCT_REALTEK_RTL8402:
		flags = RTSX_F_8402;
		break;
	case PCI_PRODUCT_REALTEK_RTL8411:
		flags = RTSX_F_8411;
		break;
	case PCI_PRODUCT_REALTEK_RTL8411B:
		flags = RTSX_F_8411B;
		break;
	default:
		flags = 0;
		break;
	}

	if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat, flags) != 0) {
		aprint_error_dev(self, "couldn't initialize chip\n");
		return;
	}

	if (!pmf_device_register1(self, rtsx_suspend, rtsx_resume,
	    rtsx_shutdown))
		aprint_error_dev(self, "couldn't establish powerhook\n");
}
Ejemplo n.º 27
0
static int
cs4281_pci_attach(device_t dev)
{
    struct sc_info *sc;
    struct ac97_info *codec = NULL;
    char status[SND_STATUSLEN];

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

    pci_enable_busmaster(dev);

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

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

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

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

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

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

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

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

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

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

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

    mixer_init(dev, ac97_getmixerclass(), codec);

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

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

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

    return 0;

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

    return ENXIO;
}
Ejemplo n.º 28
0
void
cs4280_attach(struct device *parent, struct device *self, void *aux)
{
	struct cs4280_softc *sc = (struct cs4280_softc *) self;
	struct pci_attach_args *pa = (struct pci_attach_args *) aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	char const *intrstr;
	pci_intr_handle_t ih;
	u_int32_t mem;
    
	/* Map I/O register */
	if (pci_mapreg_map(pa, CSCC_PCI_BA0, 
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) {
		printf(": can't map BA0 space\n");
		return;
	}
	if (pci_mapreg_map(pa, CSCC_PCI_BA1,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) {
		printf(": can't map BA1 space\n");
		return;
	}

	sc->sc_dmatag = pa->pa_dmat;

	/* Get out of power save mode if needed. */
	pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	/* LATENCY_TIMER setting */
	mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
	if ( PCI_LATTIMER(mem) < 32 ) {
		mem &= 0xffff00ff;
		mem |= 0x00002000;
		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem);
	}
	
	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		printf(": couldn't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pc, ih);

	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
	    cs4280_intr, sc, sc->sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": couldn't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}
	printf(": %s\n", intrstr);

	/* Initialization */
	if (cs4280_init(sc, 1) != 0)
		return;

	mountroothook_establish(cs4280_attachhook, sc);

	/* AC 97 attachement */
	sc->host_if.arg = sc;
	sc->host_if.attach = cs4280_attach_codec;
	sc->host_if.read   = cs4280_read_codec;
	sc->host_if.write  = cs4280_write_codec;
	sc->host_if.reset  = cs4280_reset_codec;

	if (ac97_attach(&sc->host_if) != 0) {
		printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
		return;
	}
}