Module Name:    src
Committed By:   isaki
Date:           Sat Sep 12 05:19:16 UTC 2020

Modified Files:
        src/sys/arch/sparc/conf: files.sparc
        src/sys/arch/sparc/dev: audioamd.c
        src/sys/arch/sparc/sparc: genassym.cf
        src/sys/arch/vax/vsa: vsaudio.c
        src/sys/dev/ic: am7930.c am7930var.h
        src/sys/dev/tc: bba.c
Removed Files:
        src/sys/arch/sparc/dev: audioamdvar.h
        src/sys/arch/sparc/include: am7930_machdep.h
        src/sys/arch/sparc/sparc: amd7930intr.s

Log Message:
Improve am7930 family drivers to share more code.
audioamd(4) on sparc, vsaudio(4) on vax, and bba(4) are.
- Remove complex and useless callbacks: onopen, onclose, and
  indirect_{read,write}.  This makes audioamd and vsaudio almost the same.
- Remove (already disabled) assembly fast interrupt path from audioamd(4).
  cf. http://mail-index.netbsd.org/source-changes/2009/12/19/msg004585.html
- Use trigger_* method rather than start_* method.  It's more suitable.
vsaudio(4) was tested by naru@, bba(4) was tested by tsutsui@.


To generate a diff of this commit:
cvs rdiff -u -r1.159 -r1.160 src/sys/arch/sparc/conf/files.sparc
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/sparc/dev/audioamd.c
cvs rdiff -u -r1.4 -r0 src/sys/arch/sparc/dev/audioamdvar.h
cvs rdiff -u -r1.1 -r0 src/sys/arch/sparc/include/am7930_machdep.h
cvs rdiff -u -r1.23 -r0 src/sys/arch/sparc/sparc/amd7930intr.s
cvs rdiff -u -r1.70 -r1.71 src/sys/arch/sparc/sparc/genassym.cf
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/vax/vsa/vsaudio.c
cvs rdiff -u -r1.59 -r1.60 src/sys/dev/ic/am7930.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/ic/am7930var.h
cvs rdiff -u -r1.45 -r1.46 src/sys/dev/tc/bba.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc/conf/files.sparc
diff -u src/sys/arch/sparc/conf/files.sparc:1.159 src/sys/arch/sparc/conf/files.sparc:1.160
--- src/sys/arch/sparc/conf/files.sparc:1.159	Fri Mar  1 02:28:27 2019
+++ src/sys/arch/sparc/conf/files.sparc	Sat Sep 12 05:19:15 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: files.sparc,v 1.159 2019/03/01 02:28:27 macallan Exp $
+#	$NetBSD: files.sparc,v 1.160 2020/09/12 05:19:15 isaki Exp $
 
 # @(#)files.sparc	8.1 (Berkeley) 7/19/93
 # sparc-specific configuration info
@@ -233,7 +233,6 @@ attach	audioamd at mainbus with audioamd
 attach	audioamd at obio with audioamd_obio
 attach	audioamd at sbus with audioamd_sbus
 file	arch/sparc/dev/audioamd.c		audioamd
-file	arch/sparc/sparc/amd7930intr.s		audioamd
 
 device	apc
 attach	apc at sbus

Index: src/sys/arch/sparc/dev/audioamd.c
diff -u src/sys/arch/sparc/dev/audioamd.c:1.29 src/sys/arch/sparc/dev/audioamd.c:1.30
--- src/sys/arch/sparc/dev/audioamd.c:1.29	Wed May  8 13:40:16 2019
+++ src/sys/arch/sparc/dev/audioamd.c	Sat Sep 12 05:19:16 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: audioamd.c,v 1.29 2019/05/08 13:40:16 isaki Exp $	*/
+/*	$NetBSD: audioamd.c,v 1.30 2020/09/12 05:19:16 isaki Exp $	*/
 /*	NetBSD: am7930_sparc.c,v 1.44 1999/03/14 22:29:00 jonathan Exp 	*/
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audioamd.c,v 1.29 2019/05/08 13:40:16 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audioamd.c,v 1.30 2020/09/12 05:19:16 isaki Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
@@ -52,52 +52,14 @@ __KERNEL_RCSID(0, "$NetBSD: audioamd.c,v
 
 #include <dev/ic/am7930reg.h>
 #include <dev/ic/am7930var.h>
-#include <sparc/dev/audioamdvar.h>
 
 #define AUDIO_ROM_NAME "audio"
 
-#ifdef AUDIO_DEBUG
-#define DPRINTF(x)      if (am7930debug) printf x
-#define DPRINTFN(n,x)   if (am7930debug>(n)) printf x
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif	/* AUDIO_DEBUG */
-
-
-/* interrupt interfaces */
-int	am7930hwintr(void *);
-struct auio *auiop;
-void	am7930swintr(void *);
-
-/* from amd7930intr.s: */
-void	amd7930_trap(void);
-
-/*
- * interrupt-handler status
- */
-struct am7930_intrhand {
-	int	(*ih_fun)(void *);
-	void	*ih_arg;
-};
-
 struct audioamd_softc {
 	struct am7930_softc sc_am7930;	/* glue to MI code */
 
 	bus_space_tag_t sc_bt;		/* bus cookie */
 	bus_space_handle_t sc_bh;	/* device registers */
-
-	struct am7930_intrhand	sc_ih;	/* interrupt vector (hw or sw)  */
-	void	(*sc_rintr)(void*);	/* input completion intr handler */
-	void	*sc_rarg;		/* arg for sc_rintr() */
-	void	(*sc_pintr)(void*);	/* output completion intr handler */
-	void	*sc_parg;		/* arg for sc_pintr() */
-
-	/* sc_au is special in that the hardware interrupt handler uses it */
-	struct  auio sc_au;		/* recv and xmit buffers, etc */
-#define sc_intrcnt	sc_au.au_intrcnt	/* statistics */
-	void	*sc_sicookie;		/* softintr(9) cookie */
-	kmutex_t	sc_lock;
 };
 
 int	audioamd_mainbus_match(device_t, cfdata_t, void *);
@@ -121,40 +83,25 @@ CFATTACH_DECL_NEW(audioamd_sbus, sizeof(
  * Define our interface into the am7930 MI driver.
  */
 
-uint8_t	audioamd_codec_iread(struct am7930_softc *, int);
-uint16_t	audioamd_codec_iread16(struct am7930_softc *, int);
-uint8_t	audioamd_codec_dread(struct audioamd_softc *, int);
-void	audioamd_codec_iwrite(struct am7930_softc *, int, uint8_t);
-void	audioamd_codec_iwrite16(struct am7930_softc *, int, uint16_t);
-void	audioamd_codec_dwrite(struct audioamd_softc *, int, uint8_t);
-void	audioamd_onopen(struct am7930_softc *);
-void	audioamd_onclose(struct am7930_softc *);
+uint8_t	audioamd_codec_dread(struct am7930_softc *, int);
+void	audioamd_codec_dwrite(struct am7930_softc *, int, uint8_t);
 
 struct am7930_glue audioamd_glue = {
-	audioamd_codec_iread,
-	audioamd_codec_iwrite,
-	audioamd_codec_iread16,
-	audioamd_codec_iwrite16,
-	audioamd_onopen,
-	audioamd_onclose,
+	audioamd_codec_dread,
+	audioamd_codec_dwrite,
 };
 
 /*
  * Define our interface to the higher level audio driver.
  */
-int	audioamd_start_output(void *, void *, int, void (*)(void *), void *);
-int	audioamd_start_input(void *, void *, int, void (*)(void *), void *);
 int	audioamd_getdev(void *, struct audio_device *);
-void	audioamd_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread);
 
 const struct audio_hw_if sa_hw_if = {
-	.open			= am7930_open,
-	.close			= am7930_close,
 	.query_format		= am7930_query_format,
 	.set_format		= am7930_set_format,
 	.commit_settings	= am7930_commit_settings,
-	.start_output		= audioamd_start_output,	/* md */
-	.start_input		= audioamd_start_input,		/* md */
+	.trigger_output		= am7930_trigger_output,
+	.trigger_input		= am7930_trigger_input,
 	.halt_output		= am7930_halt_output,
 	.halt_input		= am7930_halt_input,
 	.getdev			= audioamd_getdev,
@@ -162,7 +109,7 @@ const struct audio_hw_if sa_hw_if = {
 	.get_port		= am7930_get_port,
 	.query_devinfo		= am7930_query_devinfo,
 	.get_props		= am7930_get_props,
-	.get_locks		= audioamd_get_locks,
+	.get_locks		= am7930_get_locks,
 };
 
 struct audio_device audioamd_device = {
@@ -280,258 +227,42 @@ audioamd_sbus_attach(device_t parent, de
 void
 audioamd_attach(struct audioamd_softc *sc, int pri)
 {
+	struct am7930_softc *amsc = &sc->sc_am7930;
 	device_t self;
 
 	/*
 	 * Set up glue for MI code early; we use some of it here.
 	 */
-	self = sc->sc_am7930.sc_dev;
-	sc->sc_am7930.sc_glue = &audioamd_glue;
-	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
-
-	am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE);
-
-	auiop = &sc->sc_au;
+	amsc->sc_glue = &audioamd_glue;
+	am7930_init(amsc, AUDIOAMD_POLL_MODE);
 
-	/* Copy bus tag & handle for use by am7930_trap */
-	sc->sc_au.au_bt = sc->sc_bt;
-	sc->sc_au.au_bh = sc->sc_bh;
 	(void)bus_intr_establish2(sc->sc_bt, pri, IPL_HIGH,
-				  am7930hwintr, sc,
-#ifdef notyet /* XXX amd7930intr.s needs to be fixed for MI softint(9) */
-				  amd7930_trap
-#else
-				  NULL
-#endif
-				  );
-
-	sc->sc_sicookie = softint_establish(SOFTINT_SERIAL, am7930swintr, sc);
-	if (sc->sc_sicookie == NULL) {
-		printf("\n%s: cannot establish software interrupt\n",
-			device_xname(self));
-		return;
-	}
-
-	printf(" softpri %d\n", IPL_SOFTAUDIO);
+				  am7930_hwintr, sc, NULL);
 
+	printf("\n");
 
-	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
+	self = amsc->sc_dev;
+	evcnt_attach_dynamic(&amsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
 	    device_xname(self), "intr");
 
 	audio_attach_mi(&sa_hw_if, sc, self);
 }
 
 
-void
-audioamd_onopen(struct am7930_softc *sc)
-{
-	struct audioamd_softc *mdsc;
-
-	mdsc = (struct audioamd_softc *)sc;
-
-	/* reset pdma state */
-	mutex_spin_enter(&mdsc->sc_lock);
-	mdsc->sc_rintr = 0;
-	mdsc->sc_rarg = 0;
-	mdsc->sc_pintr = 0;
-	mdsc->sc_parg = 0;
-	mdsc->sc_au.au_rdata = 0;
-	mdsc->sc_au.au_pdata = 0;
-	mutex_spin_exit(&mdsc->sc_lock);
-}
-
-
-void
-audioamd_onclose(struct am7930_softc *sc)
-{
-	/* On sparc, just do the chipset-level halt. */
-	am7930_halt_input(sc);
-	am7930_halt_output(sc);
-}
-
-int
-audioamd_start_output(void *addr, void *p, int cc,
-		      void (*intr)(void *), void *arg)
-{
-	struct audioamd_softc *sc;
-
-	DPRINTFN(1, ("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
-	sc = addr;
-
-	mutex_spin_enter(&sc->sc_lock);
-	audioamd_codec_iwrite(&sc->sc_am7930,
-	    AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
-	sc->sc_pintr = intr;
-	sc->sc_parg = arg;
-	sc->sc_au.au_pdata = p;
-	sc->sc_au.au_pend = (char *)p + cc - 1;
-	mutex_spin_exit(&sc->sc_lock);
-
-	DPRINTF(("sa_start_output: started intrs.\n"));
-	return(0);
-}
-
-int
-audioamd_start_input(void *addr, void *p, int cc,
-		     void (*intr)(void *), void *arg)
-{
-	struct audioamd_softc *sc;
-
-	DPRINTFN(1, ("sa_start_input: cc=%d %p (%p)\n", cc, intr, arg));
-	sc = addr;
-
-	mutex_spin_enter(&sc->sc_lock);
-	audioamd_codec_iwrite(&sc->sc_am7930,
-	    AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
-	sc->sc_rintr = intr;
-	sc->sc_rarg = arg;
-	sc->sc_au.au_rdata = p;
-	sc->sc_au.au_rend = (char *)p + cc -1;
-	mutex_spin_exit(&sc->sc_lock);
-
-	DPRINTF(("sa_start_input: started intrs.\n"));
-
-	return(0);
-}
-
-
-/*
- * Pseudo-DMA support: either C or locore assember.
- */
-
-int
-am7930hwintr(void *v)
-{
-	struct audioamd_softc *sc;
-	struct auio *au;
-	uint8_t *d, *e;
-	int k;
-
-	sc = v;
-	au = &sc->sc_au;
-	mutex_spin_enter(&sc->sc_lock);
-
-	/* clear interrupt */
-	k = audioamd_codec_dread(sc, AM7930_DREG_IR);
-	if ((k & (AM7930_IR_DTTHRSH|AM7930_IR_DRTHRSH|AM7930_IR_DSRI|
-		  AM7930_IR_DERI|AM7930_IR_BBUFF)) == 0) {
-		mutex_spin_exit(&sc->sc_lock);
-		return 0;
-	}
-
-	/* receive incoming data */
-	d = au->au_rdata;
-	e = au->au_rend;
-	if (d && d <= e) {
-		*d = audioamd_codec_dread(sc, AM7930_DREG_BBRB);
-		au->au_rdata++;
-		if (d == e) {
-			DPRINTFN(1, ("am7930hwintr: swintr(r) requested"));
-			softint_schedule(sc->sc_sicookie);
-		}
-	}
-
-	/* send outgoing data */
-	d = au->au_pdata;
-	e = au->au_pend;
-	if (d && d <= e) {
-		audioamd_codec_dwrite(sc, AM7930_DREG_BBTB, *d);
-		au->au_pdata++;
-		if (d == e) {
-			DPRINTFN(1, ("am7930hwintr: swintr(p) requested"));
-			softint_schedule(sc->sc_sicookie);
-		}
-	}
-
-	au->au_intrcnt.ev_count++;
-	mutex_spin_exit(&sc->sc_lock);
-
-	return 1;
-}
-
-void
-am7930swintr(void *sc0)
-{
-	struct audioamd_softc *sc;
-	struct auio *au;
-	bool pint;
-
-	sc = sc0;
-	DPRINTFN(1, ("audiointr: sc=%p\n", sc););
-
-	au = &sc->sc_au;
-
-	mutex_spin_enter(&sc->sc_am7930.sc_lock);
-	if (au->au_rdata > au->au_rend && sc->sc_rintr != NULL) {
-		(*sc->sc_rintr)(sc->sc_rarg);
-	}
-	pint = (au->au_pdata > au->au_pend && sc->sc_pintr != NULL);
-	if (pint)
-		(*sc->sc_pintr)(sc->sc_parg);
-
-	mutex_spin_exit(&sc->sc_am7930.sc_lock);
-}
-
-
-/* indirect write */
-void
-audioamd_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val)
-{
-	struct audioamd_softc *mdsc;
-
-	mdsc = (struct audioamd_softc *)sc;
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val);
-}
-
-void
-audioamd_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val)
-{
-	struct audioamd_softc *mdsc;
-
-	mdsc = (struct audioamd_softc *)sc;
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val);
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val>>8);
-}
-
-
-/* indirect read */
-uint8_t
-audioamd_codec_iread(struct am7930_softc *sc, int reg)
-{
-	struct audioamd_softc *mdsc;
-
-	mdsc = (struct audioamd_softc *)sc;
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
-	return (audioamd_codec_dread(mdsc, AM7930_DREG_DR));
-}
-
-uint16_t
-audioamd_codec_iread16(struct am7930_softc *sc, int reg)
-{
-	struct audioamd_softc *mdsc;
-	uint8_t lo, hi;
-
-	mdsc = (struct audioamd_softc *)sc;
-	audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
-	lo = audioamd_codec_dread(mdsc, AM7930_DREG_DR);
-	hi = audioamd_codec_dread(mdsc, AM7930_DREG_DR);
-	return (hi << 8) | lo;
-}
-
 /* direct read */
 uint8_t
-audioamd_codec_dread(struct audioamd_softc *sc, int reg)
+audioamd_codec_dread(struct am7930_softc *amsc, int reg)
 {
+	struct audioamd_softc *sc = (struct audioamd_softc *)amsc;
 
 	return bus_space_read_1(sc->sc_bt, sc->sc_bh, reg);
 }
 
 /* direct write */
 void
-audioamd_codec_dwrite(struct audioamd_softc *sc, int reg, uint8_t val)
+audioamd_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val)
 {
+	struct audioamd_softc *sc = (struct audioamd_softc *)amsc;
 
 	bus_space_write_1(sc->sc_bt, sc->sc_bh, reg, val);
 }
@@ -544,14 +275,4 @@ audioamd_getdev(void *addr, struct audio
 	return 0;
 }
 
-void
-audioamd_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
-{
-	struct audioamd_softc *asc = opaque;
-	struct am7930_softc *sc = &asc->sc_am7930;
- 
-	*intr = &sc->sc_intr_lock;
-	*thread = &sc->sc_lock;
-}
-
 #endif /* NAUDIO > 0 */

Index: src/sys/arch/sparc/sparc/genassym.cf
diff -u src/sys/arch/sparc/sparc/genassym.cf:1.70 src/sys/arch/sparc/sparc/genassym.cf:1.71
--- src/sys/arch/sparc/sparc/genassym.cf:1.70	Thu Feb 20 08:27:39 2020
+++ src/sys/arch/sparc/sparc/genassym.cf	Sat Sep 12 05:19:16 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.70 2020/02/20 08:27:39 skrll Exp $
+#	$NetBSD: genassym.cf,v 1.71 2020/09/12 05:19:16 isaki Exp $
 
 #
 # Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -97,7 +97,6 @@ include <sparc/dev/zsvar.h>
 endif
 
 include <sys/bus.h>
-include <sparc/dev/audioamdvar.h>
 
 include <sparc/dev/fdreg.h>
 include <sparc/dev/fdvar.h>
@@ -237,14 +236,6 @@ define	ZL_RBUF		offsetof(struct zs_line,
 define	ZSRR1_DO_bit	ffs(ZSRR1_DO) - 1
 endif
 
-# audio trap handler fields
-define	AU_BH		offsetof(struct auio, au_bh)
-define	AU_RDATA	offsetof(struct auio, au_rdata)
-define	AU_REND		offsetof(struct auio, au_rend)
-define	AU_PDATA	offsetof(struct auio, au_pdata)
-define	AU_PEND		offsetof(struct auio, au_pend)
-define	AU_EVCNT	offsetof(struct auio, au_intrcnt.ev_count)
-
 define	PROM_BASE	PROM_BASE
 
 define	PV_MAGIC	offsetof(struct promvec, pv_magic)

Index: src/sys/arch/vax/vsa/vsaudio.c
diff -u src/sys/arch/vax/vsa/vsaudio.c:1.6 src/sys/arch/vax/vsa/vsaudio.c:1.7
--- src/sys/arch/vax/vsa/vsaudio.c:1.6	Wed Aug 26 12:59:28 2020
+++ src/sys/arch/vax/vsa/vsaudio.c	Sat Sep 12 05:19:16 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vsaudio.c,v 1.6 2020/08/26 12:59:28 isaki Exp $	*/
+/*	$NetBSD: vsaudio.c,v 1.7 2020/09/12 05:19:16 isaki Exp $	*/
 /*	$OpenBSD: vsaudio.c,v 1.4 2013/05/15 21:21:11 ratchov Exp $	*/
 
 /*
@@ -82,111 +82,47 @@
 #include <dev/ic/am7930reg.h>
 #include <dev/ic/am7930var.h>
 
-#ifdef AUDIO_DEBUG
-#define DPRINTF(x)	if (am7930debug) printf x
-#define DPRINTFN(n,x)	if (am7930debug>(n)) printf x
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif  /* AUDIO_DEBUG */
-
 /* physical addresses of the AM79C30 chip */
 #define VSAUDIO_CSR			0x200d0000
 #define VSAUDIO_CSR_KA49		0x26800000
 
-/* pdma state */
-struct auio {
-	bus_space_tag_t		au_bt;	/* bus tag */
-	bus_space_handle_t	au_bh;	/* handle to chip registers */
-
-	uint8_t		*au_rdata;	/* record data */
-	uint8_t		*au_rend;	/* end of record data */
-	uint8_t		*au_pdata;	/* play data */
-	uint8_t		*au_pend;	/* end of play data */
-	struct evcnt	au_intrcnt;	/* statistics */
-};
-
-struct am7930_intrhand {
-	int	(*ih_fun)(void *);
-	void	*ih_arg;
-};
-
-
 struct vsaudio_softc {
 	struct am7930_softc sc_am7930;	/* glue to MI code */
+
 	bus_space_tag_t sc_bt;		/* bus cookie */
 	bus_space_handle_t sc_bh;	/* device registers */
-
-	struct am7930_intrhand	sc_ih;	/* interrupt vector (hw or sw)  */
-	void	(*sc_rintr)(void*);	/* input completion intr handler */
-	void	*sc_rarg;		/* arg for sc_rintr() */
-	void	(*sc_pintr)(void*);	/* output completion intr handler */
-	void	*sc_parg;		/* arg for sc_pintr() */
-
-	uint8_t	*sc_rdata;		/* record data */
-	uint8_t	*sc_rend;		/* end of record data */
-	uint8_t	*sc_pdata;		/* play data */
-	uint8_t	*sc_pend;		/* end of play data */
-
-	struct	auio sc_au;		/* recv and xmit buffers, etc */
-#define sc_intrcnt sc_au.au_intrcnt	/* statistics */
-	void	*sc_sicookie;		/* softintr(9) cookie */
-	int	sc_cvec;
-	kmutex_t sc_lock;
 };
 
 static int vsaudio_match(struct device *parent, struct cfdata *match, void *);
 static void vsaudio_attach(device_t parent, device_t self, void *);
 
+static void vsaudio_hwintr(void *);
+
 CFATTACH_DECL_NEW(vsaudio, sizeof(struct vsaudio_softc), vsaudio_match,
 		vsaudio_attach, NULL, NULL);
 
 /*
  * Hardware access routines for the MI code
  */
-uint8_t	vsaudio_codec_iread(struct am7930_softc *, int);
-uint16_t	vsaudio_codec_iread16(struct am7930_softc *, int);
-uint8_t	vsaudio_codec_dread(struct vsaudio_softc *, int);
-void	vsaudio_codec_iwrite(struct am7930_softc *, int, uint8_t);
-void	vsaudio_codec_iwrite16(struct am7930_softc *, int, uint16_t);
-void	vsaudio_codec_dwrite(struct vsaudio_softc *, int, uint8_t);
-void	vsaudio_onopen(struct am7930_softc *);
-void	vsaudio_onclose(struct am7930_softc *);
-
-/*
-static stream_filter_factory_t vsaudio_output_conv;
-static stream_filter_factory_t vsaudio_input_conv;
-static int vsaudio_output_conv_fetch_to(struct audio_softc *,
-		stream_fetcher_t *, audio_stream_t *, int);
-static int vsaudio_input_conv_fetch_to(struct audio_softc *,
-		stream_fetcher_t *, audio_stream_t *, int);
-		*/
+uint8_t	vsaudio_codec_dread(struct am7930_softc *, int);
+void	vsaudio_codec_dwrite(struct am7930_softc *, int, uint8_t);
 
 struct am7930_glue vsaudio_glue = {
-	vsaudio_codec_iread,
-	vsaudio_codec_iwrite,
-	vsaudio_codec_iread16,
-	vsaudio_codec_iwrite16,
-	vsaudio_onopen,
-	vsaudio_onclose,
+	vsaudio_codec_dread,
+	vsaudio_codec_dwrite,
 };
 
 /*
  * Interface to the MI audio layer.
  */
-int	vsaudio_start_output(void *, void *, int, void (*)(void *), void *);
-int	vsaudio_start_input(void *, void *, int, void (*)(void *), void *);
 int	vsaudio_getdev(void *, struct audio_device *);
-void	vsaudio_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread);
 
 struct audio_hw_if vsaudio_hw_if = {
-	.open			= am7930_open,
-	.close			= am7930_close,
 	.query_format		= am7930_query_format,
 	.set_format		= am7930_set_format,
 	.commit_settings	= am7930_commit_settings,
-	.start_output		= vsaudio_start_output,
-	.start_input		= vsaudio_start_input,
+	.trigger_output		= am7930_trigger_output,
+	.trigger_input		= am7930_trigger_input,
 	.halt_output		= am7930_halt_output,
 	.halt_input		= am7930_halt_input,
 	.getdev			= vsaudio_getdev,
@@ -194,7 +130,7 @@ struct audio_hw_if vsaudio_hw_if = {
 	.get_port		= am7930_get_port,
 	.query_devinfo		= am7930_query_devinfo,
 	.get_props		= am7930_get_props,
-	.get_locks		= vsaudio_get_locks,
+	.get_locks		= am7930_get_locks,
 };
 
 
@@ -204,15 +140,10 @@ struct audio_device vsaudio_device = {
 	"vsaudio"
 };
 
-void	vsaudio_hwintr(void *);
-void	vsaudio_swintr(void *);
-struct auio *auiop;
-
 
 static int
 vsaudio_match(struct device *parent, struct cfdata *match, void *aux)
 {
-	struct vsbus_softc *sc  __attribute__((__unused__)) = device_private(parent);
 	struct vsbus_attach_args *va = aux;
 	volatile uint32_t *regs;
 	int i;
@@ -264,6 +195,7 @@ vsaudio_attach(device_t parent, device_t
 {
 	struct vsbus_attach_args *va = aux;
 	struct vsaudio_softc *sc = device_private(self);
+	struct am7930_softc *amsc = &sc->sc_am7930;
 
 	if (bus_space_map(va->va_memt, va->va_paddr, AM7930_DREG_SIZE << 2, 0,
 	    &sc->sc_bh) != 0) {
@@ -271,249 +203,49 @@ vsaudio_attach(device_t parent, device_t
 		return;
 	}
 	sc->sc_bt = va->va_memt;
-	sc->sc_am7930.sc_dev = self;
-	sc->sc_am7930.sc_glue = &vsaudio_glue;
-	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
-	am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE);
-	auiop = &sc->sc_au;
-		/* Copy bus tag & handle for use by am7930_trap */
-	sc->sc_au.au_bt = sc->sc_bt;
-	sc->sc_au.au_bh = sc->sc_bh;
-	scb_vecalloc(va->va_cvec, vsaudio_hwintr, sc, SCB_ISTACK,
-	    &sc->sc_intrcnt);
-	sc->sc_cvec = va->va_cvec;
-	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
+	amsc->sc_dev = self;
+	amsc->sc_glue = &vsaudio_glue;
+	am7930_init(amsc, AUDIOAMD_POLL_MODE);
+	scb_vecalloc(va->va_cvec, vsaudio_hwintr, amsc, SCB_ISTACK,
+	    &amsc->sc_intrcnt);
+	evcnt_attach_dynamic(&amsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
 	    device_xname(self), "intr");
 
-	sc->sc_sicookie = softint_establish(SOFTINT_SERIAL,
-	    &vsaudio_swintr, sc);
-	if (sc->sc_sicookie == NULL) {
-		aprint_normal("\n%s: cannot establish software interrupt\n",
-		    device_xname(self));
-		return;
-	}
-
 	aprint_normal("\n");
 	audio_attach_mi(&vsaudio_hw_if, sc, self);
-
-}
-
-void
-vsaudio_onopen(struct am7930_softc *sc)
-{
-	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;
-
-	mutex_spin_enter(&vssc->sc_lock);
-	/* reset pdma state */
-	vssc->sc_rintr = NULL;
-	vssc->sc_rarg = 0;
-	vssc->sc_pintr = NULL;
-	vssc->sc_parg = 0;
-
-	vssc->sc_rdata = NULL;
-	vssc->sc_pdata = NULL;
-	mutex_spin_exit(&vssc->sc_lock);
 }
 
-void
-vsaudio_onclose(struct am7930_softc *sc)
-{
-	am7930_halt_input(sc);
-	am7930_halt_output(sc);
-}
-
-/*
- * this is called by interrupt code-path, don't lock
- */
-int
-vsaudio_start_output(void *addr, void *p, int cc,
-    void (*intr)(void *), void *arg)
-{
-	struct vsaudio_softc *sc = addr;
-
-	DPRINTFN(1, ("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
-
-	mutex_spin_enter(&sc->sc_lock);
-	vsaudio_codec_iwrite(&sc->sc_am7930,
-	    AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
-	DPRINTF(("sa_start_output: started intrs.\n"));
-	sc->sc_pintr = intr;
-	sc->sc_parg = arg;
-	sc->sc_au.au_pdata = p;
-	sc->sc_au.au_pend = (char *)p + cc - 1;
-	mutex_spin_exit(&sc->sc_lock);
-	return 0;
-}
-
-/*
- * this is called by interrupt code-path, don't lock
- */
-int
-vsaudio_start_input(void *addr, void *p, int cc,
-    void (*intr)(void *), void *arg)
-{
-	struct vsaudio_softc *sc = addr;
-
-	DPRINTFN(1, ("sa_start_input: cc=%d %p (%p)\n", cc, intr, arg));
-
-	mutex_spin_enter(&sc->sc_lock);
-	vsaudio_codec_iwrite(&sc->sc_am7930,
-	    AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
-
-	sc->sc_rintr = intr;
-	sc->sc_rarg = arg;
-	sc->sc_au.au_rdata = p;
-	sc->sc_au.au_rend = (char *)p + cc -1;
-	mutex_spin_exit(&sc->sc_lock);
-	DPRINTF(("sa_start_input: started intrs.\n"));
-	return 0;
-}
-
-
-void
-vsaudio_hwintr(void *v)
-{
-	struct vsaudio_softc *sc;
-	struct auio *au;
-	uint8_t *d, *e;
-	int __attribute__((__unused__)) k;
-
-	sc = v;
-	au = &sc->sc_au;
-	mutex_spin_enter(&sc->sc_lock);
-	/* clear interrupt */
-	k = vsaudio_codec_dread(sc, AM7930_DREG_IR);
-#if 0   /* interrupt is not shared, this shouldn't happen */
-	if ((k & (AM7930_IR_DTTHRSH | AM7930_IR_DRTHRSH | AM7930_IR_DSRI |
-	    AM7930_IR_DERI | AM7930_IR_BBUFF)) == 0) {
-		mtx_leave(&audio_lock);
-		return 0;
-	}
-#endif
-	/* receive incoming data */
-	d = au->au_rdata;
-	e = au->au_rend;
-	if (d != NULL && d <= e) {
-		*d = vsaudio_codec_dread(sc, AM7930_DREG_BBRB);
-		au->au_rdata++;
-		if (d == e) {
-			DPRINTFN(1, ("vsaudio_hwintr: swintr(r) requested"));
-			softint_schedule(sc->sc_sicookie);
-		}
-	}
-
-	/* send outgoing data */
-	d = au->au_pdata;
-	e = au->au_pend;
-	if (d != NULL && d <= e) {
-		vsaudio_codec_dwrite(sc, AM7930_DREG_BBTB, *d);
-		au->au_pdata++;
-		if (d == e) {
-			DPRINTFN(1, ("vsaudio_hwintr: swintr(p) requested"));
-			softint_schedule(sc->sc_sicookie);
-		}
-	}
-	mutex_spin_exit(&sc->sc_lock);
-}
-
-void
-vsaudio_swintr(void *v)
-{
-	struct vsaudio_softc *sc;
-	struct auio *au;
-	int dor, dow;
-
-	sc = v;
-	au = &sc->sc_au;
-
-	DPRINTFN(1, ("audiointr: sc=%p\n", sc));
-
-	dor = dow = 0;
-	mutex_spin_enter(&sc->sc_am7930.sc_intr_lock);
-	if (au->au_rdata > au->au_rend && sc->sc_rintr != NULL)
-		dor = 1;
-	if (au->au_pdata > au->au_pend && sc->sc_pintr != NULL)
-		dow = 1;
-
-	if (dor != 0)
-		(*sc->sc_rintr)(sc->sc_rarg);
-	if (dow != 0)
-		(*sc->sc_pintr)(sc->sc_parg);
-	mutex_spin_exit(&sc->sc_am7930.sc_intr_lock);
-}
-
-
-/* indirect write */
-void
-vsaudio_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val)
-{
-	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;
-
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val);
-}
-
-void
-vsaudio_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val)
-{
-	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;
-
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val);
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val >> 8);
-}
-
-/* indirect read */
-uint8_t
-vsaudio_codec_iread(struct am7930_softc *sc, int reg)
-{
-	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;
-
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
-	return vsaudio_codec_dread(vssc, AM7930_DREG_DR);
-}
-
-uint16_t
-vsaudio_codec_iread16(struct am7930_softc *sc, int reg)
+static void
+vsaudio_hwintr(void *arg)
 {
-	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;
-	uint lo, hi;
 
-	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
-	lo = vsaudio_codec_dread(vssc, AM7930_DREG_DR);
-	hi = vsaudio_codec_dread(vssc, AM7930_DREG_DR);
-	return (hi << 8) | lo;
+	am7930_hwintr(arg);
 }
 
 /* direct read */
 uint8_t
-vsaudio_codec_dread(struct vsaudio_softc *sc, int reg)
+vsaudio_codec_dread(struct am7930_softc *amsc, int reg)
 {
+	struct vsaudio_softc *sc = (struct vsaudio_softc *)amsc;
+
 	return bus_space_read_1(sc->sc_bt, sc->sc_bh, reg << 2);
 }
 
 /* direct write */
 void
-vsaudio_codec_dwrite(struct vsaudio_softc *sc, int reg, uint8_t val)
+vsaudio_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val)
 {
+	struct vsaudio_softc *sc = (struct vsaudio_softc *)amsc;
+
 	bus_space_write_1(sc->sc_bt, sc->sc_bh, reg << 2, val);
 }
 
 int
 vsaudio_getdev(void *addr, struct audio_device *retp)
 {
+
 	*retp = vsaudio_device;
 	return 0;
 }
 
-void
-vsaudio_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
-{
-	struct vsaudio_softc *asc = opaque;
-	struct am7930_softc *sc = &asc->sc_am7930;
-
-	*intr = &sc->sc_intr_lock;
-	*thread = &sc->sc_lock;
-}
-
 #endif /* NAUDIO > 0 */

Index: src/sys/dev/ic/am7930.c
diff -u src/sys/dev/ic/am7930.c:1.59 src/sys/dev/ic/am7930.c:1.60
--- src/sys/dev/ic/am7930.c:1.59	Sat Jun  8 08:02:38 2019
+++ src/sys/dev/ic/am7930.c	Sat Sep 12 05:19:16 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: am7930.c,v 1.59 2019/06/08 08:02:38 isaki Exp $	*/
+/*	$NetBSD: am7930.c,v 1.60 2020/09/12 05:19:16 isaki Exp $	*/
 
 /*
  * Copyright (c) 1995 Rolf Grossmann
@@ -36,13 +36,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: am7930.c,v 1.59 2019/06/08 08:02:38 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: am7930.c,v 1.60 2020/09/12 05:19:16 isaki Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/atomic.h>
 #include <sys/errno.h>
 #include <sys/ioctl.h>
 #include <sys/device.h>
@@ -149,13 +150,58 @@ static const struct audio_format am7930_
 };
 
 /*
+ * Indirect access functions.
+ */
+
+static void
+am7930_iwrite(struct am7930_softc *sc, int reg, uint8_t val)
+{
+
+	AM7930_DWRITE(sc, AM7930_DREG_CR, reg);
+	AM7930_DWRITE(sc, AM7930_DREG_DR, val);
+}
+
+static uint8_t
+am7930_iread(struct am7930_softc *sc, int reg)
+{
+
+	AM7930_DWRITE(sc, AM7930_DREG_CR, reg);
+	return AM7930_DREAD(sc, AM7930_DREG_DR);
+}
+
+static void
+am7930_iwrite16(struct am7930_softc *sc, int reg, uint16_t val)
+{
+
+	AM7930_DWRITE(sc, AM7930_DREG_CR, reg);
+	AM7930_DWRITE(sc, AM7930_DREG_DR, val);
+	AM7930_DWRITE(sc, AM7930_DREG_DR, val >> 8);
+}
+
+static uint16_t __unused
+am7930_iread16(struct am7930_softc *sc, int reg)
+{
+	uint lo, hi;
+
+	AM7930_DWRITE(sc, AM7930_DREG_CR, reg);
+	lo = AM7930_DREAD(sc, AM7930_DREG_DR);
+	hi = AM7930_DREAD(sc, AM7930_DREG_DR);
+	return (hi << 8) | lo;
+}
+
+#define AM7930_IWRITE(sc,r,v)	am7930_iwrite(sc,r,v)
+#define AM7930_IREAD(sc,r)	am7930_iread(sc,r)
+#define AM7930_IWRITE16(sc,r,v)	am7930_iwrite16(sc,r,v)
+#define AM7930_IREAD16(sc,r)	am7930_iread16(sc,r)
+
+/*
  * Reset chip and set boot-time softc defaults.
  */
 void
 am7930_init(struct am7930_softc *sc, int flag)
 {
 
-	DPRINTF(("am7930_init()\n"));
+	DPRINTF(("%s\n", __func__));
 
 	/* set boot defaults */
 	sc->sc_rlevel = 128;
@@ -164,6 +210,9 @@ am7930_init(struct am7930_softc *sc, int
 	sc->sc_out_port = AUDIOAMD_SPEAKER_VOL;
 	sc->sc_mic_mute = 0;
 
+	memset(&sc->sc_p, 0, sizeof(sc->sc_p));
+	memset(&sc->sc_r, 0, sizeof(sc->sc_r));
+
 	/* disable sample interrupts */
 	AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0);
 
@@ -184,6 +233,7 @@ am7930_init(struct am7930_softc *sc, int
 		AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC);
 		AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC);
 
+		mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
 	} else {
 
 		/*
@@ -198,33 +248,18 @@ am7930_init(struct am7930_softc *sc, int
 			(AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA);
 		AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4,
 			AM7930_MCR4_INT_ENABLE);
+
+		mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SOFTSERIAL);
 	}
 
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
-}
 
-int
-am7930_open(void *addr, int flags)
-{
-	struct am7930_softc *sc;
-
-	sc = addr;
-	DPRINTF(("sa_open: unit %p\n", sc));
-	sc->sc_glue->onopen(sc);
-	DPRINTF(("saopen: ok -> sc=%p\n",sc));
-	return 0;
-}
-
-void
-am7930_close(void *addr)
-{
-	struct am7930_softc *sc;
-
-	sc = addr;
-	DPRINTF(("sa_close: sc=%p\n", sc));
-	sc->sc_glue->onclose(sc);
-	DPRINTF(("sa_close: closed.\n"));
+	sc->sc_sicookie = softint_establish(SOFTINT_SERIAL, &am7930_swintr, sc);
+	if (sc->sc_sicookie == NULL) {
+		aprint_error_dev(sc->sc_dev,
+		    "cannot establish software interrupt\n");
+		return;
+	}
 }
 
 int
@@ -258,7 +293,7 @@ am7930_commit_settings(void *addr)
 	uint8_t mmr2, mmr3;
 	int level;
 
-	DPRINTF(("sa_commit.\n"));
+	DPRINTF(("%s\n", __func__));
 	sc = addr;
 	gx = gx_coeff[sc->sc_rlevel];
 	stgr = gx_coeff[sc->sc_mlevel];
@@ -303,14 +338,65 @@ am7930_commit_settings(void *addr)
 }
 
 int
+am7930_trigger_output(void *addr, void *start, void *end, int blksize,
+    void (*intr)(void *), void *arg, const audio_params_t *params)
+{
+	struct am7930_softc *sc;
+
+	DPRINTF(("%s: blksize=%d %p(%p)\n", __func__, blksize, intr, arg));
+	sc = addr;
+	sc->sc_p.intr = intr;
+	sc->sc_p.arg = arg;
+	sc->sc_p.start = start;
+	sc->sc_p.end = end;
+	sc->sc_p.blksize = blksize;
+	sc->sc_p.data = sc->sc_p.start;
+	sc->sc_p.blkend = sc->sc_p.start + sc->sc_p.blksize;
+
+	/* Start if either play or rec start. */
+	if (sc->sc_r.intr == NULL) {
+		AM7930_IWRITE(sc, AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
+		DPRINTF(("%s: started intrs.\n", __func__));
+	}
+	return 0;
+}
+
+int
+am7930_trigger_input(void *addr, void *start, void *end, int blksize,
+    void (*intr)(void *), void *arg, const audio_params_t *params)
+{
+	struct am7930_softc *sc;
+
+	DPRINTF(("%s: blksize=%d %p(%p)\n", __func__, blksize, intr, arg));
+	sc = addr;
+	sc->sc_r.intr = intr;
+	sc->sc_r.arg = arg;
+	sc->sc_r.start = start;
+	sc->sc_r.end = end;
+	sc->sc_r.blksize = blksize;
+	sc->sc_r.data = sc->sc_r.start;
+	sc->sc_r.blkend = sc->sc_r.start + sc->sc_r.blksize;
+
+	/* Start if either play or rec start. */
+	if (sc->sc_p.intr == NULL) {
+		AM7930_IWRITE(sc, AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
+		DPRINTF(("%s: started intrs.\n", __func__));
+	}
+	return 0;
+}
+
+int
 am7930_halt_output(void *addr)
 {
 	struct am7930_softc *sc;
 
 	sc = addr;
-	/* XXX only halt, if input is also halted ?? */
-	AM7930_IWRITE(sc, AM7930_IREG_INIT,
-	    AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
+	sc->sc_p.intr = NULL;
+	/* Halt if both of play and rec halt. */
+	if (sc->sc_r.intr == NULL) {
+		AM7930_IWRITE(sc, AM7930_IREG_INIT,
+		    AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
+	}
 	return 0;
 }
 
@@ -320,12 +406,85 @@ am7930_halt_input(void *addr)
 	struct am7930_softc *sc;
 
 	sc = addr;
-	/* XXX only halt, if output is also halted ?? */
-	AM7930_IWRITE(sc, AM7930_IREG_INIT,
-	    AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
+	sc->sc_r.intr = NULL;
+	/* Halt if both of play and rec halt. */
+	if (sc->sc_p.intr == NULL) {
+		AM7930_IWRITE(sc, AM7930_IREG_INIT,
+		    AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
+	}
 	return 0;
 }
 
+int
+am7930_hwintr(void *arg)
+{
+	struct am7930_softc *sc;
+	int k __unused;
+
+	sc = arg;
+
+	/*
+	 * This hwintr is called as pseudo-DMA.  So don't acquire intr_lock.
+	 */
+
+	/* clear interrupt */
+	k = AM7930_DREAD(sc, AM7930_DREG_IR);
+#if !defined(__vax__)
+	/* On vax, interrupt is not shared, this shouldn't happen */
+	if ((k & (AM7930_IR_DTTHRSH | AM7930_IR_DRTHRSH | AM7930_IR_DSRI |
+	    AM7930_IR_DERI | AM7930_IR_BBUFF)) == 0) {
+		return 0;
+	}
+#endif
+
+	/* receive incoming data */
+	if (sc->sc_r.intr) {
+		*sc->sc_r.data++ = AM7930_DREAD(sc, AM7930_DREG_BBRB);
+		if (sc->sc_r.data == sc->sc_r.blkend) {
+			if (sc->sc_r.blkend == sc->sc_r.end) {
+				sc->sc_r.data = sc->sc_r.start;
+				sc->sc_r.blkend = sc->sc_r.start;
+			}
+			sc->sc_r.blkend += sc->sc_r.blksize;
+			atomic_store_relaxed(&sc->sc_r.intr_pending, 1);
+			softint_schedule(sc->sc_sicookie);
+		}
+	}
+
+	/* send outgoing data */
+	if (sc->sc_p.intr) {
+		AM7930_DWRITE(sc, AM7930_DREG_BBTB, *sc->sc_p.data++);
+		if (sc->sc_p.data == sc->sc_p.blkend) {
+			if (sc->sc_p.blkend == sc->sc_p.end) {
+				sc->sc_p.data = sc->sc_p.start;
+				sc->sc_p.blkend = sc->sc_p.start;
+			}
+			sc->sc_p.blkend += sc->sc_p.blksize;
+			atomic_store_relaxed(&sc->sc_p.intr_pending, 1);
+			softint_schedule(sc->sc_sicookie);
+		}
+	}
+
+	sc->sc_intrcnt.ev_count++;
+	return 1;
+}
+
+void
+am7930_swintr(void *cookie)
+{
+	struct am7930_softc *sc = cookie;
+
+	mutex_enter(&sc->sc_intr_lock);
+	if (atomic_cas_uint(&sc->sc_r.intr_pending, 1, 0) == 1) {
+		(*sc->sc_r.intr)(sc->sc_r.arg);
+	}
+	if (atomic_cas_uint(&sc->sc_p.intr_pending, 1, 0) == 1) {
+		(*sc->sc_p.intr)(sc->sc_p.arg);
+	}
+	mutex_exit(&sc->sc_intr_lock);
+}
+
+
 /*
  * XXX chip is full-duplex, but really attach-dependent.
  * For now we know of no half-duplex attachments.
@@ -346,7 +505,7 @@ am7930_set_port(void *addr, mixer_ctrl_t
 {
 	struct am7930_softc *sc;
 
-	DPRINTF(("am7930_set_port: port=%d", cp->dev));
+	DPRINTF(("%s: port=%d\n", __func__, cp->dev));
 	sc = addr;
 	if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
 		cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
@@ -394,7 +553,7 @@ am7930_get_port(void *addr, mixer_ctrl_t
 {
 	struct am7930_softc *sc;
 
-	DPRINTF(("am7930_get_port: port=%d\n", cp->dev));
+	DPRINTF(("%s: port=%d\n", __func__, cp->dev));
 	sc = addr;
 	if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
 		cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
@@ -441,7 +600,7 @@ int
 am7930_query_devinfo(void *addr, mixer_devinfo_t *dip)
 {
 
-	DPRINTF(("am7930_query_devinfo()\n"));
+	DPRINTF(("%s\n", __func__));
 
 	switch(dip->index) {
 	case AUDIOAMD_MIC_VOL:
@@ -543,4 +702,14 @@ am7930_query_devinfo(void *addr, mixer_d
 	return 0;
 }
 
+void
+am7930_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread)
+{
+	struct am7930_softc *sc;
+
+	sc = addr;
+	*intr = &sc->sc_intr_lock;
+	*thread = &sc->sc_lock;
+}
+
 #endif	/* NAUDIO */

Index: src/sys/dev/ic/am7930var.h
diff -u src/sys/dev/ic/am7930var.h:1.14 src/sys/dev/ic/am7930var.h:1.15
--- src/sys/dev/ic/am7930var.h:1.14	Wed May  8 13:40:18 2019
+++ src/sys/dev/ic/am7930var.h	Sat Sep 12 05:19:16 2020
@@ -1,14 +1,22 @@
-/*	$NetBSD: am7930var.h,v 1.14 2019/05/08 13:40:18 isaki Exp $	*/
+/*	$NetBSD: am7930var.h,v 1.15 2020/09/12 05:19:16 isaki Exp $	*/
 
 struct am7930_softc;
 
 struct am7930_glue {
-	uint8_t	(*codec_iread)(struct am7930_softc *sc, int);
-	void	(*codec_iwrite)(struct am7930_softc *sc, int, uint8_t);
-	uint16_t	(*codec_iread16)(struct am7930_softc *sc, int);
-	void	(*codec_iwrite16)(struct am7930_softc *sc, int, uint16_t);
-	void	(*onopen)(struct am7930_softc *sc);
-	void	(*onclose)(struct am7930_softc *sc);
+	uint8_t	(*codec_dread)(struct am7930_softc *sc, int);
+	void	(*codec_dwrite)(struct am7930_softc *sc, int, uint8_t);
+};
+
+struct am7930_buf {
+	uint8_t *start;
+	uint8_t *end;
+	uint8_t *data;
+	uint8_t *blkend;
+	uint blksize;
+
+	void (*intr)(void *);
+	void *arg;
+	uint intr_pending;
 };
 
 struct am7930_softc {
@@ -21,19 +29,25 @@ struct am7930_softc {
 	uint8_t	sc_mic_mute;
 
 	struct am7930_glue *sc_glue;
+	struct am7930_buf sc_p;	/* for play */
+	struct am7930_buf sc_r;	/* for rec */
 
 	kmutex_t sc_lock;
 	kmutex_t sc_intr_lock;
+	void *sc_sicookie;		/* softint(9) cookie */
+	struct evcnt sc_intrcnt;	/* statistics */
 };
 
 extern int     am7930debug;
 
 void	am7930_init(struct am7930_softc *, int);
+int	am7930_hwintr(void *);
+void	am7930_swintr(void *);
+
+/* direct access functions */
+#define AM7930_DWRITE(x,y,z)	(*(x)->sc_glue->codec_dwrite)((x),(y),(z))
+#define AM7930_DREAD(x,y)	(*(x)->sc_glue->codec_dread)((x),(y))
 
-#define AM7930_IWRITE(x,y,z)	(*(x)->sc_glue->codec_iwrite)((x),(y),(z))
-#define AM7930_IREAD(x,y)	(*(x)->sc_glue->codec_iread)((x),(y))
-#define AM7930_IWRITE16(x,y,z)	(*(x)->sc_glue->codec_iwrite16)((x),(y),(z))
-#define AM7930_IREAD16(x,y)	(*(x)->sc_glue->codec_iread16)((x),(y))
 
 #define AUDIOAMD_POLL_MODE	0
 #define AUDIOAMD_DMA_MODE	1
@@ -61,17 +75,15 @@ void	am7930_init(struct am7930_softc *, 
  * audio(9) MI callbacks from upper-level audio layer.
  */
 
-struct audio_device;
-struct audio_encoding;
-struct audio_params;
-
-int	am7930_open(void *, int);
-void	am7930_close(void *);
 int	am7930_query_format(void *, audio_format_query_t *);
 int	am7930_set_format(void *, int,
 	    const audio_params_t *, const audio_params_t *,
 	    audio_filter_reg_t *, audio_filter_reg_t *);
 int	am7930_commit_settings(void *);
+int	am7930_trigger_output(void *, void *, void *, int, void (*)(void *),
+	    void *, const audio_params_t *);
+int	am7930_trigger_input(void *, void *, void *, int, void (*)(void *),
+	    void *, const audio_params_t *);
 int	am7930_halt_output(void *);
 int	am7930_halt_input(void *);
 int	am7930_getdev(void *, struct audio_device *);
@@ -79,3 +91,4 @@ int	am7930_get_props(void *);
 int	am7930_set_port(void *, mixer_ctrl_t *);
 int	am7930_get_port(void *, mixer_ctrl_t *);
 int	am7930_query_devinfo(void *, mixer_devinfo_t *);
+void	am7930_get_locks(void *, kmutex_t **, kmutex_t **);

Index: src/sys/dev/tc/bba.c
diff -u src/sys/dev/tc/bba.c:1.45 src/sys/dev/tc/bba.c:1.46
--- src/sys/dev/tc/bba.c:1.45	Sat Aug 29 03:24:31 2020
+++ src/sys/dev/tc/bba.c	Sat Sep 12 05:19:16 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: bba.c,v 1.45 2020/08/29 03:24:31 isaki Exp $ */
+/* $NetBSD: bba.c,v 1.46 2020/09/12 05:19:16 isaki Exp $ */
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
 /* maxine/alpha baseboard audio (bba) */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bba.c,v 1.45 2020/08/29 03:24:31 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bba.c,v 1.46 2020/09/12 05:19:16 isaki Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -107,20 +107,12 @@ CFATTACH_DECL_NEW(bba, sizeof(struct bba
  * Define our interface into the am7930 MI driver.
  */
 
-static uint8_t	bba_codec_iread(struct am7930_softc *, int);
-static uint16_t	bba_codec_iread16(struct am7930_softc *, int);
-static void	bba_codec_iwrite(struct am7930_softc *, int, uint8_t);
-static void	bba_codec_iwrite16(struct am7930_softc *, int, uint16_t);
-static void	bba_onopen(struct am7930_softc *);
-static void	bba_onclose(struct am7930_softc *);
+static uint8_t	bba_codec_dread(struct am7930_softc *, int);
+static void	bba_codec_dwrite(struct am7930_softc *, int, uint8_t);
 
 struct am7930_glue bba_glue = {
-	bba_codec_iread,
-	bba_codec_iwrite,
-	bba_codec_iread16,
-	bba_codec_iwrite16,
-	bba_onopen,
-	bba_onclose,
+	bba_codec_dread,
+	bba_codec_dwrite,
 };
 
 /*
@@ -144,12 +136,8 @@ static int	bba_trigger_output(void *, vo
 static int	bba_trigger_input(void *, void *, void *, int,
 				  void (*)(void *), void *,
 				  const audio_params_t *);
-static void	bba_get_locks(void *opaque, kmutex_t **intr,
-			      kmutex_t **thread);
 
 static const struct audio_hw_if sa_hw_if = {
-	.open			= am7930_open,
-	.close			= am7930_close,
 	.query_format		= bba_query_format,
 	.set_format		= bba_set_format,
 	.round_blocksize	= bba_round_blocksize,	/* md */
@@ -166,7 +154,7 @@ static const struct audio_hw_if sa_hw_if
 	.get_props		= am7930_get_props,
 	.trigger_output		= bba_trigger_output,	/* md */
 	.trigger_input		= bba_trigger_input,	/* md */
-	.get_locks		= bba_get_locks,
+	.get_locks		= am7930_get_locks,
 };
 
 static struct audio_device bba_device = {
@@ -188,8 +176,6 @@ static const struct audio_format bba_for
 
 static int	bba_intr(void *);
 static void	bba_reset(struct bba_softc *, int);
-static void	bba_codec_dwrite(struct am7930_softc *, int, uint8_t);
-static uint8_t	bba_codec_dread(struct am7930_softc *, int);
 
 static int
 bba_match(device_t parent, cfdata_t cf, void *aux)
@@ -210,13 +196,13 @@ bba_attach(device_t parent, device_t sel
 {
 	struct ioasicdev_attach_args *ia;
 	struct bba_softc *sc;
-	struct am7930_softc *asc;
+	struct am7930_softc *amsc;
 	struct ioasic_softc *iosc = device_private(parent);
 
 	ia = aux;
 	sc = device_private(self);
-	asc = &sc->sc_am7930;
-	asc->sc_dev = self;
+	amsc = &sc->sc_am7930;
+	amsc->sc_dev = self;
 	sc->sc_bst = iosc->sc_bst;
 	sc->sc_bsh = iosc->sc_bsh;
 	sc->sc_dmat = iosc->sc_dmat;
@@ -235,29 +221,17 @@ bba_attach(device_t parent, device_t sel
 	/*
 	 * Set up glue for MI code early; we use some of it here.
 	 */
-	asc->sc_glue = &bba_glue;
+	amsc->sc_glue = &bba_glue;
 
 	/*
 	 *  MI initialisation.  We will be doing DMA.
 	 */
-	am7930_init(asc, AUDIOAMD_DMA_MODE);
+	am7930_init(amsc, AUDIOAMD_DMA_MODE);
 
 	ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE,
 	    bba_intr, sc);
 
-	audio_attach_mi(&sa_hw_if, asc, self);
-}
-
-
-static void
-bba_onopen(struct am7930_softc *sc)
-{
-}
-
-
-static void
-bba_onclose(struct am7930_softc *sc)
-{
+	audio_attach_mi(&sa_hw_if, sc, self);
 }
 
 
@@ -291,7 +265,7 @@ bba_reset(struct bba_softc *sc, int rese
 static void *
 bba_allocm(void *addr, int direction, size_t size)
 {
-	struct am7930_softc *asc;
+	struct am7930_softc *amsc;
 	struct bba_softc *sc;
 	bus_dma_segment_t seg;
 	int rseg;
@@ -300,20 +274,20 @@ bba_allocm(void *addr, int direction, si
 	int state;
 
 	DPRINTF(("bba_allocm: size = %zu\n", size));
-	asc = addr;
 	sc = addr;
+	amsc = addr;
 	state = 0;
 
 	if (bus_dmamem_alloc(sc->sc_dmat, size, BBA_DMABUF_ALIGN,
 	    BBA_DMABUF_BOUNDARY, &seg, 1, &rseg, BUS_DMA_WAITOK)) {
-		aprint_error_dev(asc->sc_dev, "can't allocate DMA buffer\n");
+		aprint_error_dev(amsc->sc_dev, "can't allocate DMA buffer\n");
 		goto bad;
 	}
 	state |= 1;
 
 	if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
 	    &kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
-		aprint_error_dev(asc->sc_dev, "can't map DMA buffer\n");
+		aprint_error_dev(amsc->sc_dev, "can't map DMA buffer\n");
 		goto bad;
 	}
 	state |= 2;
@@ -569,16 +543,6 @@ bad:
 	return 1;
 }
 
-static void
-bba_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
-{
-	struct bba_softc *bsc = opaque;
-	struct am7930_softc *sc = &bsc->sc_am7930;
- 
-	*intr = &sc->sc_intr_lock;
-	*thread = &sc->sc_lock;
-}
-
 static int
 bba_intr(void *addr)
 {
@@ -647,64 +611,13 @@ bba_round_blocksize(void *addr, int blk,
 }
 
 
-/* indirect write */
-static void
-bba_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val)
-{
-
-	DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n", sc, reg, val));
-	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
-	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
-}
-
-
-static void
-bba_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val)
-{
-
-	DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n", sc, reg, val));
-	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
-	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
-	bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
-}
-
-
-static uint16_t
-bba_codec_iread16(struct am7930_softc *sc, int reg)
-{
-	uint16_t val;
-
-	DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n", sc, reg));
-	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
-	val = bba_codec_dread(sc, AM7930_DREG_DR) << 8;
-	val |= bba_codec_dread(sc, AM7930_DREG_DR);
-
-	return val;
-}
-
-
-/* indirect read */
-static uint8_t
-bba_codec_iread(struct am7930_softc *sc, int reg)
-{
-	uint8_t val;
-
-	DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n", sc, reg));
-	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
-	val = bba_codec_dread(sc, AM7930_DREG_DR);
-
-	DPRINTF(("read 0x%x (%d)\n", val, val));
-
-	return val;
-}
-
 /* direct write */
 static void
-bba_codec_dwrite(struct am7930_softc *asc, int reg, uint8_t val)
+bba_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val)
 {
 	struct bba_softc *sc;
 
-	sc = (struct bba_softc *)asc;
+	sc = (struct bba_softc *)amsc;
 	DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n", sc, reg, val));
 
 #if defined(__alpha__)
@@ -718,11 +631,11 @@ bba_codec_dwrite(struct am7930_softc *as
 
 /* direct read */
 static uint8_t
-bba_codec_dread(struct am7930_softc *asc, int reg)
+bba_codec_dread(struct am7930_softc *amsc, int reg)
 {
 	struct bba_softc *sc;
 
-	sc = (struct bba_softc *)asc;
+	sc = (struct bba_softc *)amsc;
 	DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n", sc, reg));
 
 #if defined(__alpha__)

Reply via email to