bzero(p, sizeof(p));
bzero(p, sizeof(*p));
void *auich_allocm __P((void *, u_long, int, int));void auich_freem __P((void *, void *, int));u_long auich_round_buffersize __P((void *, u_long));int auich_mappage __P((void *, void *, int, int));int auich_get_props __P((void *));int auich_trigger_output __P((void *, void *, void *, int, void (*)(void *),    void *, struct audio_params *));int auich_trigger_input __P((void *, void *, void *, int, void (*)(void *),    void *, struct audio_params *));struct audio_hw_if auich_hw_if = {	auich_open,	auich_close,	NULL,			/* drain */	auich_query_encoding,	auich_set_params,	auich_round_blocksize,	NULL,			/* commit_setting */	NULL,			/* init_output */	NULL,			/* init_input */	NULL,			/* start_output */	NULL,			/* start_input */	auich_halt_output,	auich_halt_input,	NULL,			/* speaker_ctl */	auich_getdev,	NULL,			/* getfd */	auich_set_port,	auich_get_port,	auich_query_devinfo,	auich_allocm,	auich_freem,	auich_round_buffersize,	auich_mappage,	auich_get_props,	auich_trigger_output,	auich_trigger_input};int  auich_attach_codec __P((void *, struct ac97_codec_if *));int  auich_read_codec __P((void *, u_int8_t, u_int16_t *));int  auich_write_codec __P((void *, u_int8_t, u_int16_t));void auich_reset_codec __P((void *));intauich_match(parent, match, aux)	struct device *parent;	void *match;	void *aux;{	struct pci_attach_args *pa = aux;	int i;	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)		return 0;	for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)		if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)			return 1;	return 0;}voidauich_attach(parent, self, aux)	struct device *parent, *self;	void *aux;{	struct auich_softc *sc = (struct auich_softc *)self;	struct pci_attach_args *pa = aux;	pci_intr_handle_t ih;	bus_size_t mix_size, aud_size;	pcireg_t csr;	const char *intrstr;	int i;	if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0,			   &sc->iot, &sc->mix_ioh, NULL, &mix_size, 0)) {		printf(": can't map codec i/o space\n");		return;	}	if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0,			   &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {		printf(": can't map device i/o space\n");		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);		return;	}	sc->dmat = pa->pa_dmat;	/* enable bus mastering (should not it be mi?) */	csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,	    csr | PCI_COMMAND_MASTER_ENABLE);	if (pci_intr_map(pa, &ih)) {		printf(": can't map interrupt\n");		bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);		return;	}	intrstr = pci_intr_string(pa->pa_pc, ih);	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auich_intr, sc,				       sc->sc_dev.dv_xname);	if (!sc->sc_ih) {		printf(": can't establish interrupt");		if (intrstr)			printf(" at %s", intrstr);		printf("\n");		bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);		return;	}	for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)		if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)			break;	sprintf(sc->sc_audev.name, "%s AC97", auich_devices[i].name);	sprintf(sc->sc_audev.version, "0x%02x", PCI_REVISION(pa->pa_class));	strcpy(sc->sc_audev.config, sc->sc_dev.dv_xname);	printf(": %s %s\n", intrstr, sc->sc_audev.name);	/* allocate dma lists */#define	a(a)	(void*)(((u_long)(a) + sizeof(*(a)) - 1) & ~(sizeof(*(a))-1))	sc->dmalist_pcmo = sc->dmap_pcmo = a(sc->dmasto_pcmo);	sc->dmalist_pcmi = sc->dmap_pcmi = a(sc->dmasto_pcmi);	sc->dmalist_mici = sc->dmap_mici = a(sc->dmasto_mici);#undef a	DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",	    sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici));	/* Reset codec and AC'97 */	auich_reset_codec(sc);	sc->host_if.arg = sc;	sc->host_if.attach = auich_attach_codec;	sc->host_if.read = auich_read_codec;	sc->host_if.write = auich_write_codec;	sc->host_if.reset = auich_reset_codec;	if (ac97_attach(&sc->host_if) != 0) {		pci_intr_disestablish(pa->pa_pc, sc->sc_ih);		bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);		return;	}	audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);}intauich_read_codec(v, reg, val)	void *v;	u_int8_t reg;	u_int16_t *val;{	struct auich_softc *sc = v;	int i;	/* wait for an access semaphore */	for (i = AUICH_SEMATIMO; i-- &&	    bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));	if (i > 0) {		*val = bus_space_read_2(sc->iot, sc->mix_ioh, reg);		DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n",		    sc->sc_dev.dv_xname, reg, *val));		return 0;	} else {		DPRINTF(AUICH_DEBUG_CODECIO,		    ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));		return -1;	}}intauich_write_codec(v, reg, val)	void *v;	u_int8_t reg;	u_int16_t val;{	struct auich_softc *sc = v;	int i;	/* wait for an access semaphore */	for (i = AUICH_SEMATIMO; i-- &&	    bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));	if (i > 0) {		DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n",		    sc->sc_dev.dv_xname, reg, val));		bus_space_write_2(sc->iot, sc->mix_ioh, reg, val);		return 0;	} else {		DPRINTF(AUICH_DEBUG_CODECIO,		    ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));		return -1;	}}intauich_attach_codec(v, cif)	void *v;	struct ac97_codec_if *cif;{	struct auich_softc *sc = v;	sc->codec_if = cif;	return 0;}voidauich_reset_codec(v)	void *v;{	struct auich_softc *sc = v;	bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, 0);	DELAY(10);	bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, AUICH_CRESET);}intauich_open(v, flags)	void *v;	int flags;{	return 0;}voidauich_close(v)	void *v;{}intauich_query_encoding(v, aep)	void *v;	struct audio_encoding *aep;{	switch (aep->index) {	case 0:		strcpy(aep->name, AudioEulinear);		aep->encoding = AUDIO_ENCODING_ULINEAR;		aep->precision = 8;		aep->flags = 0;		return (0);	case 1:		strcpy(aep->name, AudioEmulaw);		aep->encoding = AUDIO_ENCODING_ULAW;		aep->precision = 8;		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;		return (0);	case 2:		strcpy(aep->name, AudioEalaw);		aep->encoding = AUDIO_ENCODING_ALAW;		aep->precision = 8;		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;		return (0);	case 3:		strcpy(aep->name, AudioEslinear);		aep->encoding = AUDIO_ENCODING_SLINEAR;		aep->precision = 8;		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;		return (0);	case 4:		strcpy(aep->name, AudioEslinear_le);		aep->encoding = AUDIO_ENCODING_SLINEAR_LE;		aep->precision = 16;		aep->flags = 0;		return (0);	case 5:		strcpy(aep->name, AudioEulinear_le);		aep->encoding = AUDIO_ENCODING_ULINEAR_LE;		aep->precision = 16;		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;		return (0);	case 6:		strcpy(aep->name, AudioEslinear_be);		aep->encoding = AUDIO_ENCODING_SLINEAR_BE;		aep->precision = 16;		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;		return (0);	case 7:		strcpy(aep->name, AudioEulinear_be);		aep->encoding = AUDIO_ENCODING_ULINEAR_BE;		aep->precision = 16;		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;		return (0);	default:		return (EINVAL);	}}intauich_set_params(v, setmode, usemode, play, rec)	void *v;	int setmode, usemode;	struct audio_params *play, *rec;{	struct auich_softc *sc = v;	int error;	if (setmode & AUMODE_PLAY) {		play->factor = 1;		play->sw_code = NULL;		switch(play->encoding) {		case AUDIO_ENCODING_ULAW:			play->factor = 2;			play->sw_code = mulaw_to_slinear16;			break;		case AUDIO_ENCODING_SLINEAR_LE:			if (play->precision == 8)				play->sw_code = change_sign8;			break;		case AUDIO_ENCODING_ULINEAR_LE:			if (play->precision == 16)				play->sw_code = change_sign16;			break;		case AUDIO_ENCODING_ALAW:			play->factor = 2;			play->sw_code = alaw_to_slinear16;			break;		case AUDIO_ENCODING_SLINEAR_BE:			if (play->precision == 16)				play->sw_code = swap_bytes;			else				play->sw_code = change_sign8;			break;		case AUDIO_ENCODING_ULINEAR_BE:			if (play->precision == 16)				play->sw_code = change_sign16_swap_bytes;			break;		default:			return (EINVAL);		}		if ((error = ac97_set_rate(sc->codec_if, play, AUMODE_PLAY)))			return (error);	}	if (setmode & AUMODE_RECORD) {		rec->factor = 1;		rec->sw_code = 0;		switch(rec->encoding) {		case AUDIO_ENCODING_ULAW:			rec->sw_code = ulinear8_to_mulaw;			break;		case AUDIO_ENCODING_SLINEAR_LE:			if (rec->precision == 8)				rec->sw_code = change_sign8;			break;		case AUDIO_ENCODING_ULINEAR_LE:			if (rec->precision == 16)				rec->sw_code = change_sign16;			break;		case AUDIO_ENCODING_ALAW:			rec->sw_code = ulinear8_to_alaw;			break;		case AUDIO_ENCODING_SLINEAR_BE:			if (rec->precision == 16)				rec->sw_code = swap_bytes;			else				rec->sw_code = change_sign8;			break;		case AUDIO_ENCODING_ULINEAR_BE:			if (rec->precision == 16)				rec->sw_code = swap_bytes_change_sign16;			break;		default:			return (EINVAL);		}		if ((error = ac97_set_rate(sc->codec_if, rec, AUMODE_RECORD)))			return (error);	}	return (0);}intauich_round_blocksize(v, blk)	void *v;	int blk;{	return blk & ~0x3f;}intauich_halt_output(v)	void *v;{	struct auich_softc *sc = v;	DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, AUICH_RR);	return 0;}intauich_halt_input(v)	void *v;{	struct auich_softc *sc = v;	DPRINTF(AUICH_DEBUG_DMA,	    ("%s: halt_input\n", sc->sc_dev.dv_xname));	/* XXX halt both unless known otherwise */	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);	return 0;}intauich_getdev(v, adp)	void *v;	struct audio_device *adp;{	struct auich_softc *sc = v;	*adp = sc->sc_audev;	return 0;}intauich_set_port(v, cp)	void *v;	mixer_ctrl_t *cp;{	struct auich_softc *sc = v;	return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);}intauich_get_port(v, cp)	void *v;	mixer_ctrl_t *cp;{	struct auich_softc *sc = v;	return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);}intauich_query_devinfo(v, dp)	void *v;	mixer_devinfo_t *dp;{	struct auich_softc *sc = v;	return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);}void *auich_allocm(v, size, pool, flags)	void *v;	u_long size;	int pool, flags;{	struct auich_softc *sc = v;	struct auich_dma *p;	int error;	if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)		return NULL;	p = malloc(sizeof(*p), pool, flags);	if (!p)		return NULL;	bzero(p, sizeof(p));	p->size = size;	if ((error = bus_dmamem_alloc(sc->dmat, p->size, NBPG, 0, p->segs,	    1, &p->nsegs, BUS_DMA_NOWAIT)) != 0) {		printf("%s: unable to allocate dma, error = %d\n",		    sc->sc_dev.dv_xname, error);		free(p, pool);		return NULL;	}	if ((error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,	    &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {		printf("%s: unable to map dma, error = %d\n",		    sc->sc_dev.dv_xname, error);		bus_dmamem_free(sc->dmat, p->segs, p->nsegs);		free(p, pool);		return NULL;	}	if ((error = bus_dmamap_create(sc->dmat, p->size, 1,	    p->size, 0, BUS_DMA_NOWAIT, &p->map)) != 0) {		printf("%s: unable to create dma map, error = %d\n",		    sc->sc_dev.dv_xname, error);		bus_dmamem_unmap(sc->dmat, p->addr, size);		bus_dmamem_free(sc->dmat, p->segs, p->nsegs);		free(p, pool);		return NULL;	}	if ((error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size,	    NULL, BUS_DMA_NOWAIT)) != 0) {		printf("%s: unable to load dma map, error = %d\n",		    sc->sc_dev.dv_xname, error);		bus_dmamap_destroy(sc->dmat, p->map);		bus_dmamem_unmap(sc->dmat, p->addr, size);		bus_dmamem_free(sc->dmat, p->segs, p->nsegs);		free(p, pool);		return NULL;	}	p->next = sc->sc_dmas;	sc->sc_dmas = p;	return p->addr;}