Beispiel #1
0
static int
ua_attach(device_t dev)
{
	struct ua_info *ua;
	char status[SND_STATUSLEN];
	unsigned int bufsz;

	ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_NOWAIT);
	if (!ua)
		return ENXIO;
	bzero(ua, sizeof *ua);

	ua->sc_dev = dev;

	bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_PCM_BUFF_SIZE, 65536);

	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*/bufsz, /*nsegments*/1,
				/*maxsegz*/0x3fff, /*flags*/0,
				&ua->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	if (mixer_init(dev, &ua_mixer_class, ua)) {
		return(ENXIO);
	}

	snprintf(status, SND_STATUSLEN, "at addr ?");

	if (pcm_register(dev, ua, 1, 0)) {
		return(ENXIO);
	}

	pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
#ifndef NO_RECORDING
	pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
#endif
	pcm_setstatus(dev, status);

	return 0;
bad:
	if (ua->parent_dmat)
		bus_dma_tag_destroy(ua->parent_dmat);
	free(ua, M_DEVBUF);

	return ENXIO;
}
Beispiel #2
0
static void
bcm2835_audio_delayed_init(void *xsc)
{
    	struct bcm2835_audio_info *sc;
    	char status[SND_STATUSLEN];

	sc = xsc;

	config_intrhook_disestablish(&sc->intr_hook);

	bcm2835_audio_init(sc);
	bcm2835_audio_open(sc);
	sc->volume = 75;
	sc->dest = DEST_AUTO;

    	if (mixer_init(sc->dev, &bcmmixer_class, sc)) {
		device_printf(sc->dev, "mixer_init failed\n");
		goto no;
	}

    	if (pcm_register(sc->dev, sc, 1, 1)) {
		device_printf(sc->dev, "pcm_register failed\n");
		goto no;
	}

	pcm_addchan(sc->dev, PCMDIR_PLAY, &bcmchan_class, sc);
    	snprintf(status, SND_STATUSLEN, "at VCHIQ");
	pcm_setstatus(sc->dev, status);

	bcm2835_audio_reset_channel(&sc->pch);
	bcm2835_audio_create_worker(sc);

	vchi_audio_sysctl_init(sc);

no:
	;
}
Beispiel #3
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;
}
Beispiel #4
0
static int
nm_pci_attach(device_t dev)
{
	struct sc_info *sc;
	struct ac97_info *codec = 0;
	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);

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

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

	if (nm_init(sc) == -1) {
		device_printf(dev, "unable to initialize the card\n");
		goto bad;
	}

	codec = AC97_CREATE(dev, sc, nm_ac97);
	if (codec == NULL) goto bad;
	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;

	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, 0, nm_intr, sc, &sc->ih)) {
		device_printf(dev, "unable to map interrupt\n");
		goto bad;
	}

	snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld %s",
		 rman_get_start(sc->buf), rman_get_start(sc->reg),
		 rman_get_start(sc->irq),PCM_KLDSTRING(snd_neomagic));

	if (pcm_register(dev, sc, 1, 1)) goto bad;
	pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
	pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
	pcm_setstatus(dev, status);

	return 0;

bad:
	if (codec) ac97_destroy(codec);
	if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
	if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
	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);
	free(sc, M_DEVBUF);
	return ENXIO;
}
Beispiel #5
0
static int
ds_pci_attach(device_t dev)
{
	u_int32_t subdev, i;
	struct sc_info *sc;
	struct ac97_info *codec = NULL;
	char 		status[SND_STATUSLEN];

	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
	sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ds1 softc");
	sc->dev = dev;
	subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
	sc->type = ds_finddev(pci_get_devid(dev), subdev);
	sc->rev = pci_get_revid(dev);

	pci_enable_busmaster(dev);

	sc->regid = PCIR_BAR(0);
	sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
					 RF_ACTIVE);
	if (!sc->reg) {
		device_printf(dev, "unable to map 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, DS1_BUFFSIZE, 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*/NULL,
		/*lockarg*/NULL, &sc->buffer_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	sc->regbase = NULL;
	if (ds_init(sc) == -1) {
		device_printf(dev, "unable to initialize the card\n");
		goto bad;
	}

	codec = AC97_CREATE(dev, sc, ds_ac97);
	if (codec == NULL)
		goto bad;
	/*
	 * Turn on inverted external amplifier sense flags for few
	 * 'special' boards.
	 */
	switch (subdev) {
	case 0x81171033:	/* NEC ValueStar (VT550/0) */
		ac97_setflags(codec, ac97_getflags(codec) | AC97_F_EAPD_INV);
		break;
	default:
		break;
	}
	mixer_init(dev, ac97_getmixerclass(), codec);

	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, ds_intr, sc, &sc->ih)) {
		device_printf(dev, "unable to map interrupt\n");
		goto bad;
	}

	snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
		 rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_ds1));

	if (pcm_register(dev, sc, DS1_CHANS, 2))
		goto bad;
	for (i = 0; i < DS1_CHANS; i++)
		pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc);
	for (i = 0; i < 2; i++)
		pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc);
	pcm_setstatus(dev, status);

	return 0;

bad:
	if (codec)
		ac97_destroy(codec);
	if (sc->reg)
		bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
	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->buffer_dmat)
		bus_dma_tag_destroy(sc->buffer_dmat);
	if (sc->control_dmat)
		bus_dma_tag_destroy(sc->control_dmat);
	if (sc->lock)
		snd_mtxfree(sc->lock);
	free(sc, M_DEVBUF);
	return ENXIO;
}
Beispiel #6
0
static void
atiixp_chip_post_init(void *arg)
{
	struct atiixp_info *sc = (struct atiixp_info *)arg;
	uint32_t subdev;
	int i, timeout, found;
	char status[SND_STATUSLEN];

	atiixp_lock(sc);

	if (sc->delayed_attach.ich_func) {
		config_intrhook_disestablish(&sc->delayed_attach);
		sc->delayed_attach.ich_func = NULL;
	}

	/* wait for the interrupts to happen */
	timeout = 100;
	while (--timeout) {
		snd_mtxsleep(sc, sc->lock, 0, "ixpslp", 1);
		if (sc->codec_not_ready_bits)
			break;
	}

	atiixp_disable_interrupts(sc);

	if (timeout == 0) {
		device_printf(sc->dev,
			"WARNING: timeout during codec detection; "
			"codecs might be present but haven't interrupted\n");
		atiixp_unlock(sc);
		goto postinitbad;
	}

	found = 0;

	/*
	 * ATI IXP can have upto 3 codecs, but single codec should be
	 * suffice for now.
	 */
	if (!(sc->codec_not_ready_bits &
				ATI_REG_ISR_CODEC0_NOT_READY)) {
		/* codec 0 present */
		sc->codec_found++;
		sc->codec_idx = 0;
		found++;
	}

	if (!(sc->codec_not_ready_bits &
				ATI_REG_ISR_CODEC1_NOT_READY)) {
		/* codec 1 present */
		sc->codec_found++;
	}

	if (!(sc->codec_not_ready_bits &
				ATI_REG_ISR_CODEC2_NOT_READY)) {
		/* codec 2 present */
		sc->codec_found++;
	}

	atiixp_unlock(sc);

	if (found == 0)
		goto postinitbad;

	/* create/init mixer */
	sc->codec = AC97_CREATE(sc->dev, sc, atiixp_ac97);
	if (sc->codec == NULL)
		goto postinitbad;

	subdev = (pci_get_subdevice(sc->dev) << 16) | pci_get_subvendor(sc->dev);
	switch (subdev) {
	case 0x11831043:	/* ASUS A6R */
	case 0x2043161f:	/* Maxselect x710s - http://maxselect.ru/ */
		ac97_setflags(sc->codec, ac97_getflags(sc->codec) | AC97_F_EAPD_INV);
		break;
	default:
		break;
	}

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

	if (pcm_register(sc->dev, sc, ATI_IXP_NPCHAN, ATI_IXP_NRCHAN))
		goto postinitbad;

	for (i = 0; i < ATI_IXP_NPCHAN; i++)
		pcm_addchan(sc->dev, PCMDIR_PLAY, &atiixp_chan_class, sc);
	for (i = 0; i < ATI_IXP_NRCHAN; i++)
		pcm_addchan(sc->dev, PCMDIR_REC, &atiixp_chan_class, sc);

	ksnprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s", 
			rman_get_start(sc->reg), rman_get_start(sc->irq),
			PCM_KLDSTRING(snd_atiixp));

	pcm_setstatus(sc->dev, status);

	atiixp_lock(sc);
	atiixp_enable_interrupts(sc);
	atiixp_unlock(sc);

	return;

postinitbad:
	atiixp_release_resource(sc);
}
Beispiel #7
0
static int
nm_pci_attach(device_t dev)
{
	snddev_info    *d;
	u_int32_t	data;
	struct sc_info *sc;
	struct ac97_info *codec;
	char 		status[SND_STATUSLEN];

	d = device_get_softc(dev);
	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);

	sc->bufid = PCIR_MAPS;
	sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid,
				     0, ~0, 1, RF_ACTIVE);
	sc->regid = PCIR_MAPS + 4;
	sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid,
				     0, ~0, 1, RF_ACTIVE);

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

	if (nm_init(sc) == -1) {
		device_printf(dev, "unable to initialize the card\n");
		goto bad;
	}

	codec = ac97_create(dev, sc, nm_rdcd, nm_wrcd);
	if (codec == NULL) goto bad;
	mixer_init(d, &ac97_mixer, codec);

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

	snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld",
		 rman_get_start(sc->buf), rman_get_start(sc->reg),
		 rman_get_start(sc->irq));

	if (pcm_register(dev, sc, 1, 1)) goto bad;
	pcm_addchan(dev, PCMDIR_REC, &nm_chantemplate, sc);
	pcm_addchan(dev, PCMDIR_PLAY, &nm_chantemplate, sc);
	pcm_setstatus(dev, status);

	return 0;

bad:
	if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
	if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
	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);
	free(sc, M_DEVBUF);
	return ENXIO;
}
Beispiel #8
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;
}
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;
}
Beispiel #10
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 = kmalloc(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,
		&fm801->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto oops;
	}

	ksnprintf(status, 64, "at %s 0x%lx irq %ld %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);
	kfree(fm801, M_DEVBUF);
	return ENXIO;
}
Beispiel #11
0
/*
 * Attach
 */
static int
au88x0_pci_attach(device_t dev)
{
	struct au88x0_chipset *auc;
	struct au88x0_info *aui = NULL;
	uint32_t config;
	int error;

	aui = kmalloc(sizeof *aui, M_DEVBUF, M_WAITOK | M_ZERO);
	aui->aui_dev = dev;

	/* Model-specific parameters */
	aui->aui_model = pci_get_devid(dev);
	for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc)
		if (auc->auc_pci_id == aui->aui_model)
			aui->aui_chipset = auc;
	if (aui->aui_chipset == NULL)
		panic("%s() called for non-au88x0 device", __func__);

	/* enable pio, mmio, bus-mastering dma */
	config = pci_read_config(dev, PCIR_COMMAND, 2);
	config |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
	pci_write_config(dev, PCIR_COMMAND, config, 2);

	/* register mapping */
	config = pci_read_config(dev, PCIR_COMMAND, 2);
	if (config & PCIM_CMD_MEMEN) {
		/* try memory-mapped I/O */
		aui->aui_regid = PCIR_BAR(0);
		aui->aui_regtype = SYS_RES_MEMORY;
		aui->aui_reg = bus_alloc_resource_any(dev, aui->aui_regtype,
		    &aui->aui_regid, RF_ACTIVE);
	}
	if (aui->aui_reg == NULL && (config & PCIM_CMD_PORTEN)) {
		/* fall back on port I/O */
		aui->aui_regid = PCIR_BAR(0);
		aui->aui_regtype = SYS_RES_IOPORT;
		aui->aui_reg = bus_alloc_resource_any(dev, aui->aui_regtype,
		    &aui->aui_regid, RF_ACTIVE);
	}
	if (aui->aui_reg == NULL) {
		/* both mmio and pio failed... */
		device_printf(dev, "failed to map registers\n");
		goto failed;
	}
	aui->aui_spct = rman_get_bustag(aui->aui_reg);
	aui->aui_spch = rman_get_bushandle(aui->aui_reg);

	/* IRQ mapping */
	aui->aui_irqid = 0;
	aui->aui_irqtype = SYS_RES_IRQ;
	aui->aui_irq = bus_alloc_resource_any(dev, aui->aui_irqtype,
	    &aui->aui_irqid, RF_ACTIVE | RF_SHAREABLE);
	if (aui->aui_irq == 0) {
		device_printf(dev, "failed to map IRQ\n");
		goto failed;
	}

	/* install interrupt handler */
	error = snd_setup_intr(dev, aui->aui_irq, 0, au88x0_intr,
	    aui, &aui->aui_irqh);
	if (error != 0) {
		device_printf(dev, "failed to install interrupt handler\n");
		goto failed;
	}

	/* DMA mapping */
	aui->aui_bufsize = pcm_getbuffersize(dev, AU88X0_BUFSIZE_MIN,
	    AU88X0_BUFSIZE_DFLT, AU88X0_BUFSIZE_MAX);
	error = bus_dma_tag_create(NULL,
	    2, 0, /* 16-bit alignment, no boundary */
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* restrict to 4GB */
	    NULL, NULL, /* no filter */
	    aui->aui_bufsize, 1, aui->aui_bufsize,
	    0, busdma_lock_mutex, &Giant, &aui->aui_dmat);
	if (error != 0) {
		device_printf(dev, "failed to create DMA tag\n");
		goto failed;
	}

	/* initialize the hardware */
	au88x0_init(aui);

	/* initialize the ac97 codec and mixer */
	if ((aui->aui_ac97i = AC97_CREATE(dev, aui, au88x0_ac97)) == NULL) {
		device_printf(dev, "failed to initialize ac97 codec\n");
		goto failed;
	}
	if (mixer_init(dev, ac97_getmixerclass(), aui->aui_ac97i) != 0) {
		device_printf(dev, "failed to initialize ac97 mixer\n");
		goto failed;
	}

	/* register with the pcm driver */
	if (pcm_register(dev, aui, 0, 0))
		goto failed;
	pcm_addchan(dev, PCMDIR_PLAY, &au88x0_chan_class, aui);
#if 0
	pcm_addchan(dev, PCMDIR_REC, &au88x0_chan_class, aui);
#endif
	au88x0_set_status(dev);

	return (0);
failed:
	if (aui->aui_ac97i != NULL)
		ac97_destroy(aui->aui_ac97i);
	if (aui->aui_dmat)
		bus_dma_tag_destroy(aui->aui_dmat);
	if (aui->aui_irqh != NULL)
		bus_teardown_intr(dev, aui->aui_irq, aui->aui_irqh);
	if (aui->aui_irq)
		bus_release_resource(dev, aui->aui_irqtype,
		    aui->aui_irqid, aui->aui_irq);
	if (aui->aui_reg)
		bus_release_resource(dev, aui->aui_regtype,
		    aui->aui_regid, aui->aui_reg);
	kfree(aui, M_DEVBUF);
	return (ENXIO);
}
Beispiel #12
0
static int
via_attach(device_t dev)
{
	struct via_info *via = 0;
	char status[SND_STATUSLEN];
	u_int32_t data, cnt;

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

	/* Get resources */
	data = pci_read_config(dev, PCIR_COMMAND, 2);
	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
	pci_write_config(dev, PCIR_COMMAND, data, 2);
	data = pci_read_config(dev, PCIR_COMMAND, 2);

	/* 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*/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) != 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;

	ksnprintf(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) kfree(via, M_DEVBUF);
	return ENXIO;
}