changeset 10157:4697a9319896

PSARC 2009/407 Remove austr 6858147 remove the austr node 6858152 add improved kstat error reporting to audio
author Garrett D'Amore <gdamore@opensolaris.org>
date Wed, 22 Jul 2009 09:02:10 -0700
parents a1ab3f203504
children 34b6acf6dcb8
files usr/src/cmd/svc/milestone/devices-audio usr/src/pkgdefs/SUNWaudd/postinstall.tmpl usr/src/pkgdefs/SUNWaudd/preremove.tmpl usr/src/pkgdefs/SUNWaudd/prototype_com usr/src/pkgdefs/SUNWaudd/prototype_i386 usr/src/pkgdefs/SUNWaudd/prototype_sparc usr/src/tools/scripts/bfu.sh usr/src/uts/common/Makefile.files usr/src/uts/common/io/audio/impl/audio_client.c usr/src/uts/common/io/audio/impl/audio_client.h usr/src/uts/common/io/audio/impl/audio_ddi.c usr/src/uts/common/io/audio/impl/audio_engine.c usr/src/uts/common/io/audio/impl/audio_impl.h usr/src/uts/common/io/audio/impl/audio_input.c usr/src/uts/common/io/audio/impl/audio_oss.c usr/src/uts/common/io/audio/impl/audio_output.c usr/src/uts/common/io/audio/impl/audio_sun.c usr/src/uts/common/io/audio/impl/austr.c usr/src/uts/common/io/audio/impl/austr.conf usr/src/uts/intel/Makefile.intel.shared usr/src/uts/intel/austr/Makefile usr/src/uts/sparc/Makefile.sparc.shared usr/src/uts/sparc/austr/Makefile
diffstat 23 files changed, 782 insertions(+), 1404 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/svc/milestone/devices-audio	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/cmd/svc/milestone/devices-audio	Wed Jul 22 09:02:10 2009 -0700
@@ -35,10 +35,5 @@
 # need to run some code at boot.  We key this off of the handler in
 # devfsadm for the audio node(s).
 #
-# Additionally, we need to make sure the streams audio module is
-# loaded so that the symbolic links are properly created for STREAMs
-# devices and point to a reasonable device node.
-#
 /usr/sbin/devfsadm -i audio
-/usr/sbin/devfsadm -i austr
 exit $SMF_EXIT_OK
--- a/usr/src/pkgdefs/SUNWaudd/postinstall.tmpl	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/pkgdefs/SUNWaudd/postinstall.tmpl	Wed Jul 22 09:02:10 2009 -0700
@@ -31,7 +31,6 @@
 
 # common drivers first
 pkg_drvadd -n -m '* 0666 root sys' audio || EXIT=1
-pkg_drvadd -n austr || EXIT=1
 pkg_drvadd -n -i '"pci1274,1371" "pci1274,5880"' audioens || EXIT=1
 pkg_drvadd -n -i '"pci1274,5000"' audiopci || EXIT=1
 pkg_drvadd -n -i '"pci10b9,5451"' audiots || EXIT=1
--- a/usr/src/pkgdefs/SUNWaudd/preremove.tmpl	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/pkgdefs/SUNWaudd/preremove.tmpl	Wed Jul 22 09:02:10 2009 -0700
@@ -32,16 +32,15 @@
 case "${ARCH}" in
     sparc)
 	pkg_drvrem audiocs || EXIT=1
-	pkg_drvrem audiots || EXIT=1
-	pkg_drvrem audio1575 || EXIT=1
 	;;
     i386)
 	;;
 esac
 
+pkg_drvrem audiots || EXIT=1
+pkg_drvrem audio1575 || EXIT=1
 pkg_drvrem audioens || EXIT=1
 pkg_drvrem audiopci || EXIT=1
-pkg_drvrem austr || EXIT=1
 pkg_drvrem audio || EXIT=1
 
 exit ${EXIT}
--- a/usr/src/pkgdefs/SUNWaudd/prototype_com	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/pkgdefs/SUNWaudd/prototype_com	Wed Jul 22 09:02:10 2009 -0700
@@ -51,4 +51,3 @@
 f none kernel/drv/audioens.conf 644 root sys
 f none kernel/drv/audiopci.conf 644 root sys
 f none kernel/drv/audiots.conf 644 root sys
-f none kernel/drv/austr.conf 644 root sys
--- a/usr/src/pkgdefs/SUNWaudd/prototype_i386	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/pkgdefs/SUNWaudd/prototype_i386	Wed Jul 22 09:02:10 2009 -0700
@@ -52,11 +52,9 @@
 f none kernel/drv/audioens 755 root sys
 f none kernel/drv/audiopci 755 root sys
 f none kernel/drv/audiots 755 root sys
-f none kernel/drv/austr 755 root sys
 f none kernel/misc/amd64/ac97 755 root sys
 f none kernel/drv/amd64/audio 755 root sys
 f none kernel/drv/amd64/audio1575 755 root sys
 f none kernel/drv/amd64/audioens 755 root sys
 f none kernel/drv/amd64/audiots 755 root sys
 f none kernel/drv/amd64/audiopci 755 root sys
-f none kernel/drv/amd64/austr 755 root sys
--- a/usr/src/pkgdefs/SUNWaudd/prototype_sparc	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/pkgdefs/SUNWaudd/prototype_sparc	Wed Jul 22 09:02:10 2009 -0700
@@ -50,6 +50,5 @@
 f none kernel/drv/sparcv9/audiopci 755 root sys
 f none kernel/drv/sparcv9/audiots 755 root sys
 f none kernel/drv/sparcv9/audio1575 755 root sys
-f none kernel/drv/sparcv9/austr 755 root sys
 d none kernel/misc/sparcv9 755 root sys
 f none kernel/misc/sparcv9/ac97 755 root sys
--- a/usr/src/tools/scripts/bfu.sh	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/tools/scripts/bfu.sh	Wed Jul 22 09:02:10 2009 -0700
@@ -971,7 +971,7 @@
 #
 BOOMER_PRESENT_SYS=false
 BOOMER_PRESENT_BFU=false
-BOOMER_DRIVERS="audio austr"
+BOOMER_DRIVERS="audio"
 
 check_boomer_sys() {
 	typeset root=$1
--- a/usr/src/uts/common/Makefile.files	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/Makefile.files	Wed Jul 22 09:02:10 2009 -0700
@@ -424,8 +424,6 @@
 	   audio_grc3.o audio_output.o audio_input.o \
 	   audio_oss.o audio_sun.o
 
-AUSTR_OBJS += austr.o
-
 AUDIOENS_OBJS += audioens.o
 
 AUDIOVIA823X_OBJS += audiovia823x.o
--- a/usr/src/uts/common/io/audio/impl/audio_client.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_client.c	Wed Jul 22 09:02:10 2009 -0700
@@ -1224,6 +1224,7 @@
 auclnt_release(audio_client_t *c)
 {
 	mutex_enter(&c->c_lock);
+	ASSERT(c->c_refcnt > 0);
 	c->c_refcnt--;
 	if (c->c_refcnt == 0)
 		cv_broadcast(&c->c_cv);
@@ -1340,6 +1341,18 @@
 	return (c->c_origminor & AUDIO_MN_TYPE_MASK);
 }
 
+queue_t *
+auclnt_get_rq(audio_client_t *c)
+{
+	return (c->c_rq);
+}
+
+queue_t *
+auclnt_get_wq(audio_client_t *c)
+{
+	return (c->c_wq);
+}
+
 pid_t
 auclnt_get_pid(audio_client_t *c)
 {
--- a/usr/src/uts/common/io/audio/impl/audio_client.h	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_client.h	Wed Jul 22 09:02:10 2009 -0700
@@ -49,6 +49,9 @@
 	void		(*aco_output)(audio_client_t *);
 	void		(*aco_notify)(audio_client_t *);
 	void		(*aco_drain)(audio_client_t *);
+
+	void		(*aco_wput)(audio_client_t *, mblk_t *);
+	void		(*aco_wsrv)(audio_client_t *);
 } audio_client_ops_t;
 
 void *auclnt_get_private(audio_client_t *);
@@ -117,6 +120,8 @@
 minor_t	auclnt_get_minor(audio_client_t *);
 minor_t auclnt_get_original_minor(audio_client_t *);
 minor_t auclnt_get_minor_type(audio_client_t *);
+queue_t *auclnt_get_rq(audio_client_t *);
+queue_t *auclnt_get_wq(audio_client_t *);
 
 unsigned auclnt_produce(audio_stream_t *, unsigned);
 unsigned auclnt_produce_data(audio_stream_t *, caddr_t, unsigned);
--- a/usr/src/uts/common/io/audio/impl/audio_ddi.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_ddi.c	Wed Jul 22 09:02:10 2009 -0700
@@ -190,6 +190,117 @@
 }
 
 static int
+audio_stropen(queue_t *rq, dev_t *devp, int oflag, int sflag, cred_t *credp)
+{
+	int			rv;
+	audio_client_t		*c;
+
+	if (sflag != 0) {
+		/* no direct clone or module opens */
+		return (ENXIO);
+	}
+
+	/*
+	 * Make sure its a STREAMS personality - only legacy Sun API uses
+	 * STREAMS.
+	 */
+	switch (AUDIO_MN_TYPE_MASK & getminor(*devp)) {
+	case AUDIO_MINOR_DEVAUDIO:
+	case AUDIO_MINOR_DEVAUDIOCTL:
+		break;
+	default:
+		return (ENOSTR);
+	}
+
+	if ((c = auimpl_client_create(*devp)) == NULL) {
+		audio_dev_warn(NULL, "client create failed");
+		return (ENXIO);
+	}
+
+	rq->q_ptr = WR(rq)->q_ptr = c;
+	c->c_omode = oflag;
+	c->c_pid = ddi_get_pid();
+	c->c_cred = credp;
+	c->c_rq = rq;
+	c->c_wq = WR(rq);
+
+	/*
+	 * Call client/personality specific open handler.  Note that
+	 * we "insist" that there is an open.  The personality layer
+	 * will initialize/allocate any engines required.
+	 *
+	 * Hmm... do we need to pass in the cred?
+	 */
+	if ((rv = c->c_open(c, oflag)) != 0) {
+		audio_dev_warn(c->c_dev, "open failed (rv %d)", rv);
+		auimpl_client_destroy(c);
+		return (rv);
+	}
+
+	/* we do device cloning! */
+	*devp = makedevice(c->c_major, c->c_minor);
+
+	mutex_enter(&c->c_lock);
+	c->c_is_open = B_TRUE;
+	mutex_exit(&c->c_lock);
+
+	auclnt_notify_dev(c->c_dev);
+
+	qprocson(rq);
+
+	return (0);
+}
+
+static int
+audio_strclose(queue_t *rq, int flag, cred_t *credp)
+{
+	audio_client_t	*c;
+	audio_dev_t	*d;
+	int		rv;
+
+	_NOTE(ARGUNUSED(flag));
+	_NOTE(ARGUNUSED(credp));
+
+	if ((c = rq->q_ptr) == NULL) {
+		return (ENXIO);
+	}
+	if (ddi_can_receive_sig() || (ddi_get_pid() == 0)) {
+		rv = auclnt_drain(c);
+	}
+
+	mutex_enter(&c->c_lock);
+	c->c_is_open = B_FALSE;
+	mutex_exit(&c->c_lock);
+
+	/*
+	 * Pick up any data sitting around in input buffers.  This
+	 * avoids leaving record data stuck in queues.
+	 */
+	if (c->c_istream.s_engine != NULL)
+		audio_engine_produce(c->c_istream.s_engine);
+
+	/* get a local hold on the device */
+	d = c->c_dev;
+	auimpl_dev_hold(c->c_dev);
+
+	/* Turn off queue processing... */
+	qprocsoff(rq);
+
+	/* Call personality specific close handler */
+	c->c_close(c);
+
+	auimpl_client_destroy(c);
+
+	/* notify peers that a change has occurred */
+	auclnt_notify_dev(d);
+
+	/* now we can drop the release we had on the device */
+	auimpl_dev_release(d);
+
+	return (rv);
+}
+
+static int
 audio_close(dev_t dev, int flag, int otyp, cred_t *credp)
 {
 	audio_client_t	*c;
@@ -200,7 +311,7 @@
 	_NOTE(ARGUNUSED(otyp));
 
 	if ((c = auclnt_hold_by_devt(dev)) == NULL) {
-		audio_dev_warn(NULL, "close on bugs devt %x,%x",
+		audio_dev_warn(NULL, "close on bogus devt %x,%x",
 		    getmajor(dev), getminor(dev));
 		return (ENXIO);
 	}
@@ -306,37 +417,44 @@
 	return (rv);
 }
 
-struct cb_ops audio_cb_ops = {
-	audio_open,		/* open */
-	audio_close,		/* close */
-	nodev,		/* strategy */
-	nodev,		/* print */
-	nodev,		/* dump */
-	audio_read,		/* read */
-	audio_write,		/* write */
-	audio_ioctl,		/* ioctl */
-	nodev,		/* devmap */
-	nodev,		/* mmap */
-	nodev,		/* segmap */
-	audio_chpoll,	/* chpoll */
-	ddi_prop_op,	/* prop_op */
-	NULL,		/* str */
-	D_MP | D_64BIT,		/* flag */
-	CB_REV, 	/* rev */
-	nodev,		/* aread */
-	nodev,		/* awrite */
-};
+static int
+audio_wput(queue_t *wq, mblk_t *mp)
+{
+	audio_client_t	*c;
+
+	c = wq->q_ptr;
+	if (c->c_wput) {
+		c->c_wput(c, mp);
+	} else {
+		freemsg(mp);
+	}
+	return (0);
+}
+
+static int
+audio_wsrv(queue_t *wq)
+{
+	audio_client_t	*c;
+
+	c = wq->q_ptr;
+	if (c->c_wsrv) {
+		c->c_wsrv(c);
+	} else {
+		flushq(wq, FLUSHALL);
+	}
+	return (0);
+}
 
 static struct dev_ops audio_dev_ops = {
 	DEVO_REV,		/* rev */
 	0,			/* refcnt */
-	audio_getinfo,		/* getinfo */
+	NULL,			/* getinfo */
 	nulldev,		/* identify */
 	nulldev,		/* probe */
 	audio_attach,		/* attach */
 	audio_detach,		/* detach */
 	nodev,			/* reset */
-	&audio_cb_ops,		/* cb_ops */
+	NULL,			/* cb_ops */
 	NULL,			/* bus_ops */
 	NULL,			/* power */
 };
@@ -354,18 +472,51 @@
 };
 
 struct audio_ops_helper {
-	struct cb_ops		cbops;
+	struct cb_ops		cbops;	/* NB: must be first */
+	struct streamtab	strtab;
+	struct qinit		rqinit;
+	struct qinit		wqinit;
+	struct module_info	minfo;
+	char			name[MODMAXNAMELEN+1];
 };
 
 void
 audio_init_ops(struct dev_ops *devops, const char *name)
 {
-	_NOTE(ARGUNUSED(name));
-
 	struct audio_ops_helper	*helper;
 
 	helper = kmem_zalloc(sizeof (*helper), KM_SLEEP);
 
+	(void) strlcpy(helper->name, name, sizeof (helper->name));
+
+	helper->minfo.mi_idnum = 0;	/* only for strlog(1M) */
+	helper->minfo.mi_idname = helper->name;
+	helper->minfo.mi_minpsz = 0;
+	helper->minfo.mi_maxpsz = 2048;
+	helper->minfo.mi_hiwat = 65536;
+	helper->minfo.mi_lowat = 32768;
+
+	helper->wqinit.qi_putp = audio_wput;
+	helper->wqinit.qi_srvp = audio_wsrv;
+	helper->wqinit.qi_qopen = NULL;
+	helper->wqinit.qi_qclose = NULL;
+	helper->wqinit.qi_qadmin = NULL;
+	helper->wqinit.qi_minfo = &helper->minfo;
+	helper->wqinit.qi_mstat = NULL;
+
+	helper->rqinit.qi_putp = NULL;
+	helper->rqinit.qi_srvp = NULL;
+	helper->rqinit.qi_qopen = audio_stropen;
+	helper->rqinit.qi_qclose = audio_strclose;
+	helper->rqinit.qi_qadmin = NULL;
+	helper->rqinit.qi_minfo = &helper->minfo;
+	helper->rqinit.qi_mstat = NULL;
+
+	helper->strtab.st_rdinit = &helper->rqinit;
+	helper->strtab.st_wrinit = &helper->wqinit;
+	helper->strtab.st_muxrinit = NULL;
+	helper->strtab.st_muxwinit = NULL;
+
 	helper->cbops.cb_open = audio_open;
 	helper->cbops.cb_close = audio_close;
 	helper->cbops.cb_strategy = nodev;
@@ -379,7 +530,7 @@
 	helper->cbops.cb_segmap = nodev;
 	helper->cbops.cb_chpoll = audio_chpoll;
 	helper->cbops.cb_prop_op = ddi_prop_op;
-	helper->cbops.cb_str = NULL;
+	helper->cbops.cb_str = &helper->strtab;
 	helper->cbops.cb_flag = D_MP | D_64BIT;
 	helper->cbops.cb_rev = CB_REV;
 	helper->cbops.cb_aread = nodev;
@@ -437,7 +588,10 @@
 	auimpl_sun_init();
 	auimpl_oss_init();
 
+	audio_init_ops(&audio_dev_ops, "audio");
+
 	if ((rv = mod_install(&modlinkage)) != 0) {
+		audio_fini_ops(&audio_dev_ops);
 		auimpl_dev_fini();
 		auimpl_client_fini();
 	}
--- a/usr/src/uts/common/io/audio/impl/audio_engine.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_engine.c	Wed Jul 22 09:02:10 2009 -0700
@@ -146,6 +146,7 @@
 	if (e->e_tail > e->e_head) {
 		/* want more data than we have, not much we can do */
 		e->e_errors++;
+		e->e_underruns++;
 	}
 	auimpl_output_callback(e);
 	mutex_exit(&e->e_lock);
@@ -159,6 +160,7 @@
 	if ((e->e_head - e->e_tail) > e->e_nframes) {
 		/* no room for engine data, not much we can do */
 		e->e_errors++;
+		e->e_overruns++;
 	}
 	auimpl_input_callback(e);
 	mutex_exit(&e->e_lock);
@@ -789,6 +791,10 @@
 	st->st_rate.value.ui32 = e->e_rate;
 	st->st_intrs.value.ui32 = e->e_intrs;
 	st->st_errors.value.ui32 = e->e_errors;
+	st->st_engine_underruns.value.ui32 = e->e_underruns;
+	st->st_engine_overruns.value.ui32 = e->e_overruns;
+	st->st_stream_underruns.value.ui32 = e->e_stream_underruns;
+	st->st_stream_overruns.value.ui32 = e->e_stream_overruns;
 	st->st_suspended.value.ui32 = e->e_suspended;
 	mutex_exit(&e->e_lock);
 
@@ -831,6 +837,14 @@
 	kstat_named_init(&st->st_rate, "rate", KSTAT_DATA_UINT32);
 	kstat_named_init(&st->st_intrs, "intrhz", KSTAT_DATA_UINT32);
 	kstat_named_init(&st->st_errors, "errors", KSTAT_DATA_UINT32);
+	kstat_named_init(&st->st_engine_overruns, "engine_overruns",
+	    KSTAT_DATA_UINT32);
+	kstat_named_init(&st->st_engine_underruns, "engine_underruns",
+	    KSTAT_DATA_UINT32);
+	kstat_named_init(&st->st_stream_overruns, "stream_overruns",
+	    KSTAT_DATA_UINT32);
+	kstat_named_init(&st->st_stream_underruns, "stream_underruns",
+	    KSTAT_DATA_UINT32);
 	kstat_named_init(&st->st_suspended, "suspended", KSTAT_DATA_UINT32);
 	kstat_install(e->e_ksp);
 }
--- a/usr/src/uts/common/io/audio/impl/audio_impl.h	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_impl.h	Wed Jul 22 09:02:10 2009 -0700
@@ -171,6 +171,8 @@
 	major_t			c_major;
 	minor_t			c_minor;
 	minor_t			c_origminor;
+	queue_t			*c_rq;
+	queue_t			*c_wq;
 
 	/*
 	 * Linkage for per-device list of clients.
@@ -207,6 +209,8 @@
 #define	c_input			c_ops.aco_input
 #define	c_notify		c_ops.aco_notify
 #define	c_drain			c_ops.aco_drain
+#define	c_wput			c_ops.aco_wput
+#define	c_wsrv			c_ops.aco_wsrv
 
 	struct pollhead		c_pollhead;
 
@@ -232,6 +236,10 @@
 	kstat_named_t		st_rate;
 	kstat_named_t		st_intrs;
 	kstat_named_t		st_errors;
+	kstat_named_t		st_engine_underruns;
+	kstat_named_t		st_engine_overruns;
+	kstat_named_t		st_stream_underruns;
+	kstat_named_t		st_stream_overruns;
 	kstat_named_t		st_suspended;
 };
 
@@ -274,6 +282,10 @@
 
 	int			e_intrs;
 	int			e_errors;
+	int			e_overruns;
+	int			e_underruns;
+	int			e_stream_overruns;
+	int			e_stream_underruns;
 
 	audio_parms_t		e_parms;
 #define	e_format		e_parms.p_format
--- a/usr/src/uts/common/io/audio/impl/audio_input.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_input.c	Wed Jul 22 09:02:10 2009 -0700
@@ -36,10 +36,6 @@
 #include <sys/sysmacros.h>
 #include "audio_impl.h"
 
-#ifdef	DEBUG
-int	audio_overruns = 0;
-#endif
-
 #define	DECL_AUDIO_IMPORT(NAME, TYPE, SWAP, SHIFT)			\
 void									\
 auimpl_import_##NAME(audio_engine_t *eng, audio_stream_t *sp)		\
@@ -191,9 +187,8 @@
 
 			space = sp->s_nframes - (sp->s_head - sp->s_tail);
 			if (count > space) {
-#ifdef	DEBUG
-				audio_overruns++;
-#endif
+				eng->e_stream_overruns++;
+				eng->e_errors++;
 				sp->s_errors += count - space;
 				count = space;
 				overrun = B_TRUE;
--- a/usr/src/uts/common/io/audio/impl/audio_oss.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_oss.c	Wed Jul 22 09:02:10 2009 -0700
@@ -2593,6 +2593,8 @@
 	NULL,   /* output */
 	oss_notify,
 	NULL,	/* drain */
+	NULL,	/* wput */
+	NULL,	/* wsrv */
 };
 
 /* nearly the same as ossxmix; different minor name helps devfsadm */
@@ -2611,6 +2613,8 @@
 	NULL,	/* output */
 	NULL,	/* notify */
 	NULL,	/* drain */
+	NULL,	/* wput */
+	NULL,	/* wsrv */
 };
 
 void
--- a/usr/src/uts/common/io/audio/impl/audio_output.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_output.c	Wed Jul 22 09:02:10 2009 -0700
@@ -36,10 +36,6 @@
 #include <sys/sysmacros.h>
 #include "audio_impl.h"
 
-#ifdef	DEBUG
-int audio_underruns = 0;
-#endif
-
 #define	DECL_AUDIO_EXPORT(NAME, TYPE, SAMPLE)				\
 void									\
 auimpl_export_##NAME(audio_engine_t *eng)				\
@@ -382,11 +378,9 @@
 					drained = B_TRUE;
 				}
 			} else {
-#ifdef	DEBUG
-				audio_underruns++;
-#endif
 				underrun = B_TRUE;
 				sp->s_errors += need;
+				eng->e_stream_underruns++;
 			}
 		}
 
--- a/usr/src/uts/common/io/audio/impl/audio_sun.c	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/common/io/audio/impl/audio_sun.c	Wed Jul 22 09:02:10 2009 -0700
@@ -97,46 +97,20 @@
 #include <sys/sunddi.h>
 #include "audio_client.h"
 
-typedef struct sclient sclient_t;
-typedef struct sdev sdev_t;
-typedef struct sproc sproc_t;
-typedef struct sioc sioc_t;
-
-typedef enum {
-	COPYIN,
-	COPYOUT,
-	IOCTL,
-	ACK,
-	NAK,
-	FINI
-} sioc_state_t;
-
-struct sioc {
-	sclient_t		*i_sc;
-	int			i_cmd;
-	size_t			i_size;
-	void			*i_data;
-	mblk_t			*i_bcont;
-	int			i_step;
-	uint_t			i_model;
-	sioc_state_t		i_state;
-	mblk_t			*i_mp;
-	caddr_t			i_addr;
-	int			i_error;
-};
+typedef struct daclient daclient_t;
+typedef struct dadev dadev_t;
+typedef struct daproc daproc_t;
 
 /* common structure shared between both audioctl and audio nodes */
-struct sclient {
-	sproc_t			*s_proc;
-	sdev_t			*s_sdev;
-	audio_client_t		*s_client;
-	queue_t			*s_rq;
-	queue_t			*s_wq;
-	ldi_handle_t		s_lh;
-	unsigned		s_eof;
-	list_t			s_eofcnt;
-	kmutex_t		s_lock;
-	mblk_t			*s_draining;
+struct daclient {
+	daproc_t		*dc_proc;
+	dadev_t			*dc_dev;
+	audio_client_t		*dc_client;
+	queue_t			*dc_wq;
+	unsigned		dc_eof;
+	list_t			dc_eofcnt;
+	kmutex_t		dc_lock;
+	mblk_t			*dc_draining;
 };
 
 struct eofcnt {
@@ -144,7 +118,7 @@
 	uint64_t		tail;
 };
 
-struct sdev {
+struct dadev {
 	audio_dev_t		*d_dev;
 
 	list_t			d_procs;
@@ -152,150 +126,24 @@
 	kcondvar_t		d_cv;
 };
 
-struct sproc {
+struct daproc {
 	pid_t			p_id;
 	struct audio_info	p_info;
 	int			p_refcnt;
 	int			p_oflag;
 	list_node_t		p_linkage;
-	sdev_t			*p_sdev;
-	sclient_t		*p_writer;
-	sclient_t		*p_reader;
+	dadev_t			*p_dev;
+	audio_client_t		*p_writer;
+	audio_client_t		*p_reader;
 };
 
-int sproc_hold(audio_client_t *, ldi_handle_t, queue_t *, int);
-void sproc_release(sclient_t *);
-static void sproc_update(sproc_t *);
+int devaudio_proc_hold(audio_client_t *, int);
+void devaudio_proc_release(audio_client_t *);
+static void devaudio_proc_update(daproc_t *);
 
 
-static kmutex_t	sdev_lock;
-static dev_info_t *sdev_dip;
-
-/*
- * Alloc extra room for ioctl buffer, in case none was supplied or copyin was
- * shorter than we need for the whole struct.  On failure, returns an
- * appropriate errno, zero on success.  Any original data is preserved.
- */
 static int
-sioc_alloc(sioc_t *ip, size_t size)
-{
-	mblk_t			*nmp;
-
-	/* if we already have enough, just use what we've got */
-	if (ip->i_size >= size)
-		return (0);
-
-	if ((nmp = allocb(size, BPRI_MED)) == NULL) {
-		ip->i_state = NAK;
-		ip->i_error = ENOMEM;
-		return (ENOMEM);
-	}
-	bzero(nmp->b_rptr, size);
-
-	/* if there was already some data present, preserve it */
-	if (ip->i_size != 0) {
-		bcopy(ip->i_data, nmp->b_rptr, ip->i_size);
-		freemsg(ip->i_bcont);
-	}
-	ip->i_bcont = nmp;
-	ip->i_data = nmp->b_rptr;
-	ip->i_size = size;
-
-	return (0);
-}
-
-static void
-sioc_copyin(sioc_t *ip, size_t size)
-{
-	ip->i_state = COPYIN;
-	ip->i_size = size;
-	if (ip->i_bcont != NULL) {
-		freemsg(ip->i_bcont);
-		ip->i_bcont = NULL;
-	}
-
-	mcopyin(ip->i_mp, ip, size, ip->i_addr);
-}
-
-static void
-sioc_copyout(sioc_t *ip, size_t size)
-{
-	mblk_t			*bcont;
-
-	ASSERT(ip->i_size >= size);
-
-	bcont = ip->i_bcont;
-
-	ip->i_state = COPYOUT;
-	ip->i_bcont = NULL;
-
-	mcopyout(ip->i_mp, ip, size, ip->i_addr, bcont);
-}
-
-static void
-sioc_error(sioc_t *ip, int error)
-{
-	ip->i_state = NAK;
-	ip->i_error = error;
-}
-
-static void
-sioc_success(sioc_t *ip)
-{
-	ip->i_state = ACK;
-}
-
-static void
-sioc_fini(sioc_t *ip)
-{
-	if (ip->i_bcont != NULL)
-		freemsg(ip->i_bcont);
-
-	kmem_free(ip, sizeof (*ip));
-}
-
-static void
-sioc_finish(sioc_t *ip)
-{
-	mblk_t		*mp;
-	sclient_t	*sc;
-
-	sc = ip->i_sc;
-	mp = ip->i_mp;
-	ip->i_mp = NULL;
-
-	switch (ip->i_state) {
-	case ACK:
-		miocack(sc->s_wq, mp, 0, 0);
-		break;
-
-	case IOCTL:	/* caller didn't use sioc_success */
-		ip->i_error = ECANCELED;
-		miocnak(sc->s_wq, mp, 0, ip->i_error);
-		break;
-
-	case NAK:
-		miocnak(sc->s_wq, mp, 0, ip->i_error);
-		break;
-
-	case COPYOUT:
-	case COPYIN:
-		/* data copy to be done */
-		qreply(sc->s_wq, mp);
-		return;
-
-	case FINI:
-		if (mp != NULL) {
-			freemsg(mp);
-		}
-		break;
-	}
-
-	sioc_fini(ip);
-}
-
-static int
-sun_compose_format(audio_prinfo_t *prinfo)
+devaudio_compose_format(audio_prinfo_t *prinfo)
 {
 	switch (prinfo->precision) {
 	case 8:
@@ -324,7 +172,7 @@
 }
 
 static void
-sun_decompose_format(audio_prinfo_t *prinfo, int afmt)
+devaudio_decompose_format(audio_prinfo_t *prinfo, int afmt)
 {
 	int	e, p;
 
@@ -390,16 +238,14 @@
 	prinfo->precision = p;
 }
 
-static sproc_t *
-sproc_alloc(sclient_t *sc)
+static daproc_t *
+devaudio_proc_alloc(audio_client_t *c)
 {
-	audio_client_t	*c;
 	audio_info_t	*info;
 	audio_prinfo_t	*prinfo;
 	uint32_t	caps;
-	sproc_t		*proc;
+	daproc_t	*proc;
 
-	c = sc->s_client;
 	if ((proc = kmem_zalloc(sizeof (*proc), KM_NOSLEEP)) == NULL) {
 		return (NULL);
 	}
@@ -468,43 +314,43 @@
 }
 
 static void
-sproc_free(sproc_t *proc)
+devaudio_proc_free(daproc_t *proc)
 {
 	kmem_free(proc, sizeof (*proc));
 }
 
 int
-sproc_hold(audio_client_t *c, ldi_handle_t lh, queue_t *rq, int oflag)
+devaudio_proc_hold(audio_client_t *c, int oflag)
 {
 	pid_t		pid;
-	sproc_t		*proc;
-	sdev_t		*sdev;
-	sclient_t	*sc;
+	daproc_t	*proc;
+	dadev_t		*dev;
+	daclient_t	*dc;
 	list_t		*l;
 	audio_dev_t	*adev;
 	int		rv;
 
 	adev = auclnt_get_dev(c);
 
-	/* first allocate and initialize the sclient private data */
-	if ((sc = kmem_zalloc(sizeof (*sc), KM_NOSLEEP)) == NULL) {
+	/* first allocate and initialize the daclient private data */
+	if ((dc = kmem_zalloc(sizeof (*dc), KM_NOSLEEP)) == NULL) {
 		return (ENOMEM);
 	}
 
-	mutex_init(&sc->s_lock, NULL, MUTEX_DRIVER, NULL);
-	list_create(&sc->s_eofcnt, sizeof (struct eofcnt),
+	mutex_init(&dc->dc_lock, NULL, MUTEX_DRIVER, NULL);
+	list_create(&dc->dc_eofcnt, sizeof (struct eofcnt),
 	    offsetof(struct eofcnt, linkage));
-	auclnt_set_private(c, sc);
+	auclnt_set_private(c, dc);
 
-	sdev = auclnt_get_dev_minor_data(adev, AUDIO_MINOR_DEVAUDIO);
-	l = &sdev->d_procs;
+	dev = auclnt_get_dev_minor_data(adev, AUDIO_MINOR_DEVAUDIO);
+	l = &dev->d_procs;
 	pid = auclnt_get_pid(c);
 
 	/* set a couple of common fields */
-	sc->s_client = c;
-	sc->s_sdev = sdev;
+	dc->dc_client = c;
+	dc->dc_dev = dev;
 
-	mutex_enter(&sdev->d_mx);
+	mutex_enter(&dev->d_mx);
 	for (proc = list_head(l); proc != NULL; proc = list_next(l, proc)) {
 		if (proc->p_id == pid) {
 			proc->p_refcnt++;
@@ -512,13 +358,13 @@
 		}
 	}
 	if (proc == NULL) {
-		if ((proc = sproc_alloc(sc)) == NULL) {
+		if ((proc = devaudio_proc_alloc(c)) == NULL) {
 			rv = ENOMEM;
 			goto failed;
 		}
 		proc->p_refcnt = 1;
 		proc->p_id = pid;
-		proc->p_sdev = sdev;
+		proc->p_dev = dev;
 		list_insert_tail(l, proc);
 	}
 
@@ -532,7 +378,7 @@
 			proc->p_info.play.waiting++;
 		if (oflag & FREAD)
 			proc->p_info.record.waiting++;
-		if (cv_wait_sig(&sdev->d_cv, &sdev->d_mx) == 0) {
+		if (cv_wait_sig(&dev->d_cv, &dev->d_mx) == 0) {
 			/* interrupted! */
 			if (oflag & FWRITE)
 				proc->p_info.play.waiting--;
@@ -565,7 +411,7 @@
 		auclnt_set_gain(sp, ((play->gain * 100) / AUDIO_MAX_GAIN));
 		auclnt_set_muted(sp, proc->p_info.output_muted);
 		play->open = B_TRUE;
-		proc->p_writer = sc;
+		proc->p_writer = c;
 		proc->p_oflag |= FWRITE;
 	}
 
@@ -586,99 +432,103 @@
 
 		auclnt_set_gain(sp, ((rec->gain * 100) / AUDIO_MAX_GAIN));
 		rec->open = B_TRUE;
-		proc->p_reader = sc;
+		proc->p_reader = c;
 		proc->p_oflag |= FREAD;
 	}
 
-	sc->s_lh = lh;
-	sc->s_rq = rq;
-	sc->s_wq = WR(rq);
-	WR(rq)->q_ptr = rq->q_ptr = sc;
+
+	dc->dc_wq = auclnt_get_wq(c);
+
 	/* we update the s_proc last to avoid a race */
-	sc->s_proc = proc;
+	dc->dc_proc = proc;
 
-	sproc_update(proc);
+	devaudio_proc_update(proc);
 
-	mutex_exit(&sdev->d_mx);
+	mutex_exit(&dev->d_mx);
 
 	return (0);
 
 failed:
-	mutex_exit(&sdev->d_mx);
-	sproc_release(sc);
+	mutex_exit(&dev->d_mx);
+	devaudio_proc_release(c);
 	return (rv);
 
 }
 
 static void
-sun_clear_eof(sclient_t *sc)
+devaudio_clear_eof(audio_client_t *c)
 {
-	struct eofcnt *eof;
-	mutex_enter(&sc->s_lock);
-	while ((eof = list_remove_head(&sc->s_eofcnt)) != NULL) {
+	struct eofcnt	*eof;
+	daclient_t	*dc;
+
+	dc = auclnt_get_private(c);
+	mutex_enter(&dc->dc_lock);
+	while ((eof = list_remove_head(&dc->dc_eofcnt)) != NULL) {
 		kmem_free(eof, sizeof (*eof));
 	}
-	mutex_exit(&sc->s_lock);
+	mutex_exit(&dc->dc_lock);
 }
 
 void
-sproc_release(sclient_t *sc)
+devaudio_proc_release(audio_client_t *c)
 {
-	sproc_t		*proc;
-	sdev_t		*sdev;
+	daproc_t	*proc;
+	dadev_t		*dev;
 	mblk_t		*mp;
+	daclient_t	*dc;
 
-	proc = sc->s_proc;
-	sdev = sc->s_sdev;
-	sc->s_proc = NULL;
+	dc = auclnt_get_private(c);
+	proc = dc->dc_proc;
+	dev = dc->dc_dev;
+	dc->dc_proc = NULL;
 
-	mutex_enter(&sdev->d_mx);
+	mutex_enter(&dev->d_mx);
 
 	if (proc != NULL) {
 		proc->p_refcnt--;
 		ASSERT(proc->p_refcnt >= 0);
 
-		if (sc == proc->p_writer) {
+		if (c == proc->p_writer) {
 			proc->p_oflag &= ~FWRITE;
 			proc->p_writer = NULL;
 		}
-		if (sc == proc->p_reader) {
+		if (c == proc->p_reader) {
 			proc->p_oflag &= ~FREAD;
 			proc->p_reader = NULL;
 		}
-		cv_broadcast(&sdev->d_cv);
+		cv_broadcast(&dev->d_cv);
 
 		if (proc->p_refcnt == 0) {
-			list_remove(&sdev->d_procs, proc);
-			sproc_free(proc);
+			list_remove(&dev->d_procs, proc);
+			devaudio_proc_free(proc);
 		}
-		sc->s_proc = NULL;
+		dc->dc_proc = NULL;
 	}
 
-	mutex_exit(&sdev->d_mx);
+	mutex_exit(&dev->d_mx);
 
-	sun_clear_eof(sc);
+	devaudio_clear_eof(c);
 
-	while ((mp = sc->s_draining) != NULL) {
-		sc->s_draining = mp->b_next;
+	while ((mp = dc->dc_draining) != NULL) {
+		dc->dc_draining = mp->b_next;
 		mp->b_next = NULL;
 		freemsg(mp);
 	}
 
-	mutex_destroy(&sc->s_lock);
-	list_destroy(&sc->s_eofcnt);
-	kmem_free(sc, sizeof (*sc));
+	mutex_destroy(&dc->dc_lock);
+	list_destroy(&dc->dc_eofcnt);
+	kmem_free(dc, sizeof (*dc));
 }
 
 static void
-sun_sendup(audio_client_t *c)
+devaudio_input(audio_client_t *c)
 {
 	audio_stream_t	*sp = auclnt_input_stream(c);
-	sclient_t	*sc = auclnt_get_private(c);
+	daclient_t	*dc = auclnt_get_private(c);
 	unsigned	framesz = auclnt_get_framesz(sp);
-	queue_t		*rq = sc->s_rq;
+	queue_t		*rq = auclnt_get_rq(c);
 	mblk_t		*mp;
-	unsigned	nbytes = sc->s_proc->p_info.record.buffer_size;
+	unsigned	nbytes = dc->dc_proc->p_info.record.buffer_size;
 	unsigned	count = nbytes / framesz;
 
 	/*
@@ -714,37 +564,23 @@
 	}
 }
 
-static int
-sun_open(audio_client_t *c, int oflag)
-{
-	_NOTE(ARGUNUSED(c));
-	_NOTE(ARGUNUSED(oflag));
-	return (0);
-}
-
 static void
-sun_close(audio_client_t *c)
-{
-	_NOTE(ARGUNUSED(c));
-}
-
-static void
-sproc_update(sproc_t *proc)
+devaudio_proc_update(daproc_t *proc)
 {
 	audio_info_t	*info;
 	audio_stream_t	*sp;
-	sclient_t	*sc;
+	audio_client_t	*c;
 
 	info = &proc->p_info;
 
-	ASSERT(mutex_owned(&proc->p_sdev->d_mx));
+	ASSERT(mutex_owned(&proc->p_dev->d_mx));
 
-	if ((sc = proc->p_writer) != NULL) {
-		sp = auclnt_output_stream(sc->s_client);
+	if ((c = proc->p_writer) != NULL) {
+		sp = auclnt_output_stream(c);
 
 		info->play.sample_rate = auclnt_get_rate(sp);
 		info->play.channels = auclnt_get_channels(sp);
-		sun_decompose_format(&info->play, auclnt_get_format(sp));
+		devaudio_decompose_format(&info->play, auclnt_get_format(sp));
 
 		info->play.gain =
 		    (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100;
@@ -755,12 +591,12 @@
 		info->output_muted = auclnt_get_muted(sp);
 	}
 
-	if ((sc = proc->p_reader) != NULL) {
-		sp = auclnt_input_stream(sc->s_client);
+	if ((c = proc->p_reader) != NULL) {
+		sp = auclnt_input_stream(c);
 
 		info->record.sample_rate = auclnt_get_rate(sp);
 		info->record.channels = auclnt_get_channels(sp);
-		sun_decompose_format(&info->record, auclnt_get_format(sp));
+		devaudio_decompose_format(&info->record, auclnt_get_format(sp));
 
 		info->record.gain =
 		    (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100;
@@ -772,33 +608,26 @@
 }
 
 static void
-sioc_getinfo(sioc_t *ip)
+devaudio_ioc_getinfo(queue_t *wq, audio_client_t *c, mblk_t *mp)
 {
-	sclient_t	*sc = ip->i_sc;
-	sproc_t		*proc = sc->s_proc;
-	int		rv;
+	daclient_t	*dc = auclnt_get_private(c);
+	daproc_t	*proc = dc->dc_proc;
+	mblk_t		*bcont;
 
-	switch (ip->i_step) {
-	case 0:
-		if ((rv = sioc_alloc(ip, sizeof (audio_info_t))) != 0) {
-			sioc_error(ip, rv);
-			break;
-		}
-
-		mutex_enter(&sc->s_sdev->d_mx);
-		sproc_update(proc);
-		mutex_exit(&sc->s_sdev->d_mx);
-
-		bcopy(&proc->p_info, ip->i_data, sizeof (audio_info_t));
-		sioc_copyout(ip, sizeof (audio_info_t));
-		break;
-	case 1:
-		sioc_success(ip);
-		break;
+	if ((bcont = allocb(sizeof (audio_info_t), BPRI_MED)) == NULL) {
+		miocnak(wq, mp, 0, ENOMEM);
+		return;
 	}
 
-	ip->i_step++;
-	sioc_finish(ip);
+	mutex_enter(&dc->dc_dev->d_mx);
+	devaudio_proc_update(proc);
+	bcopy(&proc->p_info, bcont->b_wptr, sizeof (audio_info_t));
+	mutex_exit(&dc->dc_dev->d_mx);
+
+	bcont->b_wptr += sizeof (audio_info_t);
+
+	mcopyout(mp, NULL, sizeof (audio_info_t), NULL, bcont);
+	qreply(wq, mp);
 }
 
 #define	CHANGED(new, old, field)			\
@@ -806,11 +635,13 @@
 #define	CHANGED8(new, old, field)			\
 	((new->field != ((uint8_t)~0)) && (new->field != old->field))
 
-static int
-sun_setinfo(sclient_t *sc, audio_info_t *ninfo)
+static void
+devaudio_ioc_setinfo(queue_t *wq, audio_client_t *c, mblk_t *mp)
 {
-	sproc_t		*proc = sc->s_proc;
-	audio_info_t	*oinfo = &proc->p_info;
+	daclient_t	*dc;
+	daproc_t	*proc;
+	audio_info_t	*oinfo;
+	audio_info_t	*ninfo;
 	audio_prinfo_t	*npr;
 	audio_prinfo_t	*opr;
 
@@ -822,16 +653,47 @@
 	boolean_t	isctl;
 	audio_stream_t	*sp;
 	int		rv;
+	caddr_t		uaddr;
+	mblk_t		*bcont;
 
-	if (auclnt_get_minor_type(sc->s_client) == AUDIO_MINOR_DEVAUDIOCTL) {
+	struct copyresp	*csp;
+
+	if (DB_TYPE(mp) == M_IOCTL) {
+		/* the special value "1" indicates that this is a copyin */
+		uaddr = *(caddr_t *)(void *)mp->b_cont->b_rptr;
+
+		mcopyin(mp, uaddr, sizeof (audio_info_t), NULL);
+		qreply(wq, mp);
+		return;
+	}
+
+	ASSERT(DB_TYPE(mp) == M_IOCDATA);
+	if (((bcont = mp->b_cont) == NULL) ||
+	    (MBLKL(mp->b_cont) != sizeof (audio_info_t))) {
+		miocnak(wq, mp, 0, EINVAL);
+		return;
+	}
+
+	mp->b_cont = NULL;
+	csp = (void *)mp->b_rptr;
+	uaddr = (void *)csp->cp_private;
+	dc = auclnt_get_private(c);
+	ninfo = (void *)bcont->b_rptr;
+
+	mutex_enter(&dc->dc_dev->d_mx);
+
+	proc = dc->dc_proc;
+	oinfo = &proc->p_info;
+
+	if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) {
 		/* control node can do both read and write fields */
 		isctl = B_TRUE;
 		reader = B_TRUE;
 		writer = B_TRUE;
 	} else {
 		isctl = B_FALSE;
-		writer = sc == proc->p_writer;
-		reader = sc == proc->p_reader;
+		writer = (c == proc->p_writer);
+		reader = (c == proc->p_reader);
 	}
 
 	/*
@@ -843,12 +705,14 @@
 	if (writer && CHANGED(npr, opr, sample_rate)) {
 		if ((isctl) ||
 		    (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 	if (writer && CHANGED(npr, opr, channels)) {
 		if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 	if (writer &&
@@ -857,16 +721,18 @@
 			npr->encoding = opr->encoding;
 		if (npr->precision == (uint32_t)~0)
 			npr->precision = opr->precision;
-		pfmt = sun_compose_format(npr);
+		pfmt = devaudio_compose_format(npr);
 		if ((isctl) || (pfmt == AUDIO_FORMAT_NONE)) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 
 	/* play fields that anyone can modify */
 	if (CHANGED(npr, opr, gain)) {
 		if (npr->gain > AUDIO_MAX_GAIN) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 
@@ -876,14 +742,15 @@
 
 	if (reader && CHANGED(npr, opr, sample_rate)) {
 		if ((isctl) ||
-		    (npr->sample_rate < 5500) ||
-		    (npr->sample_rate > 48000)) {
-			return (EINVAL);
+		    (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) {
+			rv = EINVAL;
+			goto err;
 		}
 	}
 	if (reader && CHANGED(npr, opr, channels)) {
 		if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 	if (reader &&
@@ -892,14 +759,16 @@
 			npr->encoding = opr->encoding;
 		if (npr->precision == (uint32_t)~0)
 			npr->precision = opr->precision;
-		rfmt = sun_compose_format(npr);
+		rfmt = devaudio_compose_format(npr);
 		if ((isctl) || (rfmt == AUDIO_FORMAT_NONE)) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 	if (reader && CHANGED(npr, opr, buffer_size)) {
 		if (isctl) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 		/* make sure we can support 16-bit stereo samples */
 		if ((npr->buffer_size % 4) != 0) {
@@ -914,7 +783,8 @@
 	/* record fields that anyone can modify */
 	if (CHANGED(npr, opr, gain)) {
 		if (npr->gain > AUDIO_MAX_GAIN) {
-			return (EINVAL);
+			rv = EINVAL;
+			goto err;
 		}
 	}
 
@@ -922,24 +792,21 @@
 	 * Now apply the changes.
 	 */
 	if (proc->p_writer != NULL) {
-		sp = auclnt_output_stream(proc->p_writer->s_client);
+		sp = auclnt_output_stream(proc->p_writer);
 		npr = &ninfo->play;
 		opr = &oinfo->play;
 
 		if (CHANGED(npr, opr, sample_rate)) {
-			rv = auclnt_set_rate(sp, npr->sample_rate);
-			if (rv != 0)
-				return (rv);
+			if ((rv = auclnt_set_rate(sp, npr->sample_rate)) != 0)
+				goto err;
 		}
 		if (CHANGED(npr, opr, channels)) {
-			rv = auclnt_set_channels(sp, npr->channels);
-			if (rv != 0)
-				return (rv);
+			if ((rv = auclnt_set_channels(sp, npr->channels)) != 0)
+				goto err;
 		}
 		if (pfmt != AUDIO_FORMAT_NONE) {
-			rv = auclnt_set_format(sp, pfmt);
-			if (rv != 0)
-				return (rv);
+			if ((rv = auclnt_set_format(sp, pfmt)) != 0)
+				goto err;
 		}
 		if (CHANGED(npr, opr, samples)) {
 			auclnt_set_samples(sp, npr->samples);
@@ -950,7 +817,7 @@
 			 * prevent problems with realaudio.
 			 */
 			if (npr->eof == 0) {
-				sun_clear_eof(proc->p_writer);
+				devaudio_clear_eof(proc->p_writer);
 			}
 			opr->eof = npr->eof;
 		}
@@ -959,8 +826,9 @@
 				auclnt_set_paused(sp);
 			} else {
 				auclnt_clear_paused(sp);
+
 				/* qenable to start up the playback */
-				qenable(proc->p_writer->s_wq);
+				qenable(auclnt_get_wq(proc->p_writer));
 			}
 		}
 		if (CHANGED8(npr, opr, waiting) && (npr->waiting)) {
@@ -994,24 +862,21 @@
 	}
 
 	if (proc->p_reader != NULL) {
-		sp = auclnt_input_stream(proc->p_reader->s_client);
+		sp = auclnt_input_stream(proc->p_reader);
 		npr = &ninfo->record;
 		opr = &oinfo->record;
 
 		if (CHANGED(npr, opr, sample_rate)) {
-			rv = auclnt_set_rate(sp, npr->sample_rate);
-			if (rv != 0)
-				return (rv);
+			if ((rv = auclnt_set_rate(sp, npr->sample_rate)) != 0)
+				goto err;
 		}
 		if (CHANGED(npr, opr, channels)) {
-			rv = auclnt_set_channels(sp, npr->channels);
-			if (rv != 0)
-				return (rv);
+			if ((rv = auclnt_set_channels(sp, npr->channels)) != 0)
+				goto err;
 		}
 		if (rfmt != AUDIO_FORMAT_NONE) {
-			rv = auclnt_set_format(sp, rfmt);
-			if (rv != 0)
-				return (rv);
+			if ((rv = auclnt_set_format(sp, rfmt)) != 0)
+				goto err;
 		}
 		if (CHANGED(npr, opr, samples)) {
 			auclnt_set_samples(sp, npr->samples);
@@ -1046,102 +911,271 @@
 		}
 	}
 
+	devaudio_proc_update(dc->dc_proc);
+	bcopy(&dc->dc_proc->p_info, ninfo, sizeof (*ninfo));
+	
+	mutex_exit(&dc->dc_dev->d_mx);
+	mcopyout(mp, NULL, sizeof (audio_info_t), uaddr, bcont);
+	qreply(wq, mp);
+	return;
+
+err:
+	mutex_exit(&dc->dc_dev->d_mx);
+	miocnak(wq, mp, 0, rv);
+}
+
+static void
+devaudio_ioc_getdev(queue_t *wq, audio_client_t *c, mblk_t *mp)
+{
+	audio_dev_t	*d = auclnt_get_dev(c);
+	mblk_t		*bcont;
+	audio_device_t	*a;
+
+	if ((bcont = allocb(sizeof (*a), BPRI_MED)) == NULL) {
+		miocnak(wq, mp, 0, ENOMEM);
+		return;
+	}
+
+	a = (void *)bcont->b_wptr;
+	(void) snprintf(a->name, sizeof (a->name),
+	    "SUNW,%s", auclnt_get_dev_name(d));
+	(void) strlcpy(a->config,
+	    auclnt_get_dev_description(d), sizeof (a->config));
+	(void) strlcpy(a->version,
+	    auclnt_get_dev_version(d),  sizeof (a->version));
+	bcont->b_wptr += sizeof (*a);
+
+	mcopyout(mp, NULL, sizeof (*a), NULL, bcont);
+	qreply(wq, mp);
+}
+
+static int
+devaudio_sigpoll(audio_client_t *c, void *arg)
+{
+	daproc_t	*proc = arg;
+	daclient_t	*dc;
+
+	if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) {
+		dc = auclnt_get_private(c);
+		/* we only need to notify peers in our own process */
+		if ((dc != NULL) && (dc->dc_proc == proc)) {
+			(void) putnextctl1(auclnt_get_rq(c), M_PCSIG, SIGPOLL);
+		}
+	}
+	return (AUDIO_WALK_CONTINUE);
+}
+
+static void
+devaudio_drain(audio_client_t *c)
+{
+	daclient_t	*dc = auclnt_get_private(c);
+	mblk_t		*mplist, *mp;
+
+	mutex_enter(&dc->dc_lock);
+	mplist = dc->dc_draining;
+	dc->dc_draining = NULL;
+	mutex_exit(&dc->dc_lock);
+
+	while ((mp = mplist) != NULL) {
+		mplist = mp->b_next;
+		mp->b_next = NULL;
+		miocack(auclnt_get_wq(c), mp, 0, 0);
+	}
+}
+
+static void
+devaudio_output(audio_client_t *c)
+{
+	daclient_t	*dc = auclnt_get_private(c);
+	daproc_t	*proc = dc->dc_proc;
+	uint64_t	tail;
+	struct eofcnt	*eof;
+	int		eofs = 0;
+
+	tail = auclnt_get_tail(auclnt_output_stream(c));
+
+	/* get more data! (do this early) */
+	qenable(auclnt_get_wq(c));
+
+	mutex_enter(&dc->dc_lock);
+	while (((eof = list_head(&dc->dc_eofcnt)) != NULL) &&
+	    (eof->tail < tail)) {
+		list_remove(&dc->dc_eofcnt, eof);
+		kmem_free(eof, sizeof (*eof));
+		eofs++;
+	}
+	proc->p_info.play.eof += eofs;
+	mutex_exit(&dc->dc_lock);
+
+	if (eofs) {
+		auclnt_dev_walk_clients(auclnt_get_dev(c),
+		    devaudio_sigpoll, proc);
+	}
+}
+
+static void *
+devaudio_init(audio_dev_t *adev)
+{
+	dadev_t		*dev;
+	unsigned	cap;
+
+	cap = auclnt_get_dev_capab(adev);
+	/* if not a play or record device, don't bother initializing it */
+	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
+		return (NULL);
+	}
+
+	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
+	dev->d_dev = adev;
+	mutex_init(&dev->d_mx, NULL, MUTEX_DRIVER, NULL);
+	cv_init(&dev->d_cv, NULL, CV_DRIVER, NULL);
+	list_create(&dev->d_procs, sizeof (struct daproc),
+	    offsetof(struct daproc, p_linkage));
+
+	return (dev);
+}
+
+static void
+devaudio_fini(void *arg)
+{
+	dadev_t	*dev = arg;
+
+	if (dev != NULL) {
+
+		mutex_destroy(&dev->d_mx);
+		cv_destroy(&dev->d_cv);
+		list_destroy(&dev->d_procs);
+		kmem_free(dev, sizeof (*dev));
+	}
+}
+
+static int
+devaudio_open(audio_client_t *c, int oflag)
+{
+	int	rv;
+
+	if ((rv = auclnt_open(c, AUDIO_FORMAT_PCM, oflag)) != 0) {
+		return (rv);
+	}
+
+	if ((rv = devaudio_proc_hold(c, oflag)) != 0) {
+		auclnt_close(c);
+		return (rv);
+	}
+
+	/* start up the input */
+	if (oflag & FREAD) {
+		auclnt_start(auclnt_input_stream(c));
+	}
+
+	return (0);
+}
+
+static int
+devaudioctl_open(audio_client_t *c, int oflag)
+{
+	int	rv;
+
+	_NOTE(ARGUNUSED(oflag));
+
+	oflag &= ~(FWRITE | FREAD);
+
+	if ((rv = auclnt_open(c, AUDIO_FORMAT_NONE, 0)) != 0) {
+		return (rv);
+	}
+
+	if ((rv = devaudio_proc_hold(c, oflag)) != 0) {
+		auclnt_close(c);
+		return (rv);
+	}
+
 	return (0);
 }
 
 static void
-sioc_setinfo(sioc_t *ip)
+devaudio_close(audio_client_t *c)
 {
-	int		rv;
-	sclient_t	*sc = ip->i_sc;
-	audio_info_t	*ninfo;
-
-	switch (ip->i_step) {
-	case 0:
-		sioc_copyin(ip, sizeof (audio_info_t));
-		break;
-
-	case 1:
-		ninfo = (audio_info_t *)ip->i_data;
-
-		mutex_enter(&sc->s_sdev->d_mx);
-		rv = sun_setinfo(ip->i_sc, ninfo);
+	auclnt_stop(auclnt_output_stream(c));
+	auclnt_stop(auclnt_input_stream(c));
 
-		if (rv != 0) {
-			sioc_error(ip, rv);
-		} else {
-			sproc_update(sc->s_proc);
+	auclnt_close(c);
+	devaudio_proc_release(c);
+}
 
-			bcopy(&sc->s_proc->p_info, ninfo, sizeof (*ninfo));
-			sioc_copyout(ip, sizeof (audio_info_t));
-		}
-		mutex_exit(&sc->s_sdev->d_mx);
-		break;
-
-	case 2:
-		sioc_success(ip);
-		break;
-	}
-
-	ip->i_step++;
-	sioc_finish(ip);
+static void
+devaudioctl_close(audio_client_t *c)
+{
+	auclnt_close(c);
+	devaudio_proc_release(c);
 }
 
 static void
-sioc_getdev(sioc_t *ip)
+devaudio_miocdata(audio_client_t *c, mblk_t *mp)
 {
-	int		rv;
-	sclient_t	*sc = ip->i_sc;
-	audio_client_t	*c = sc->s_client;
-	audio_dev_t	*d = auclnt_get_dev(c);
+	struct copyresp		*csp;
+	queue_t			*wq;
+
+	csp = (void *)mp->b_rptr;
+	wq = auclnt_get_wq(c);
 
-	switch (ip->i_step) {
-	case 0:
-		rv = sioc_alloc(ip, sizeof (audio_device_t));
-		if (rv == 0) {
-			audio_device_t *a = ip->i_data;
+	/*
+	 * If a transfer error occurred, the framework already
+	 * MIOCNAK'd it.
+	 */
+	if (csp->cp_rval != 0) {
+		freemsg(mp);
+		return;
+	}
 
-			(void) snprintf(a->name, sizeof (a->name),
-			    "SUNW,%s", auclnt_get_dev_name(d));
-			(void) strlcpy(a->config,
-			    auclnt_get_dev_description(d), sizeof (a->config));
-			(void) strlcpy(a->version,
-			    auclnt_get_dev_version(d),  sizeof (a->version));
-			sioc_copyout(ip, sizeof (*a));
-		} else {
-			sioc_error(ip, rv);
-		}
+	/*
+	 * If no state, then this is a response to M_COPYOUT, and we
+	 * are done.  (Audio ioctls just copyout a single structure at
+	 * completion of work.)
+	 */
+	if (csp->cp_private == NULL) {
+		miocack(wq, mp, 0, 0);
+		return;
+	}
+
+	/* now, call the handler ioctl */
+	switch (csp->cp_cmd) {
+	case AUDIO_SETINFO:
+		devaudio_ioc_setinfo(wq, c, mp);
 		break;
-
-	case 1:
-		sioc_success(ip);
+	default:
+		miocnak(wq, mp, 0, EINVAL);
 		break;
 	}
-
-	ip->i_step++;
-	sioc_finish(ip);
 }
 
 static void
-sunstr_ioctl(sioc_t *ip)
+devaudio_mioctl(audio_client_t *c, mblk_t *mp)
 {
-	switch (ip->i_cmd) {
+	struct iocblk	*iocp = (void *)mp->b_rptr;
+	queue_t		*wq = auclnt_get_wq(c);
+
+	/* BSD legacy here: we only support transparent ioctls */
+	if (iocp->ioc_count != TRANSPARENT) {
+		miocnak(wq, mp, 0, EINVAL);
+		return;
+	}
+
+	switch (iocp->ioc_cmd) {
 	case AUDIO_GETINFO:
-		sioc_getinfo(ip);
+		devaudio_ioc_getinfo(wq, c, mp);
 		break;
 
 	case AUDIO_SETINFO:
-		sioc_setinfo(ip);
+		devaudio_ioc_setinfo(wq, c, mp);
 		break;
 
 	case AUDIO_GETDEV:
-		sioc_getdev(ip);
+		devaudio_ioc_getdev(wq, c, mp);
 		break;
 
 	case AUDIO_DIAG_LOOPBACK:
 		/* we don't support this one */
-		sioc_error(ip, ENOTTY);
-		sioc_finish(ip);
+		miocnak(wq, mp, 0, ENOTTY);
 		break;
 
 	case AUDIO_MIXERCTL_GET_MODE:
@@ -1157,503 +1191,76 @@
 	case AUDIO_MIXER_MULTIPLE_OPEN:
 	case AUDIO_MIXER_GET_SAMPLE_RATES:
 	default:
-		sioc_error(ip, EINVAL);
-		sioc_finish(ip);
+		miocnak(wq, mp, 0, EINVAL);
 		break;
 	}
 }
 
-static int
-sun_sigpoll(audio_client_t *c, void *arg)
-{
-	sproc_t		*proc = arg;
-	sclient_t	*sc;
-
-	if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) {
-		sc = auclnt_get_private(c);
-		/* we only need to notify peers in our own process */
-		if ((sc != NULL) && (sc->s_proc == proc)) {
-			(void) putnextctl1(sc->s_rq, M_PCSIG, SIGPOLL);
-		}
-	}
-	return (AUDIO_WALK_CONTINUE);
-}
-
-static void
-sun_drain(audio_client_t *c)
-{
-	sclient_t	*sc = auclnt_get_private(c);
-	mblk_t		*mplist, *mp;
-
-	mutex_enter(&sc->s_lock);
-	mplist = sc->s_draining;
-	sc->s_draining = NULL;
-	mutex_exit(&sc->s_lock);
-
-	while ((mp = mplist) != NULL) {
-		mplist = mp->b_next;
-		mp->b_next = NULL;
-		miocack(sc->s_wq, mp, 0, 0);
-	}
-}
-
-static void
-sun_output(audio_client_t *c)
-{
-	sclient_t	*sc = auclnt_get_private(c);
-	sproc_t		*proc = sc->s_proc;
-	uint64_t	tail;
-	struct eofcnt	*eof;
-	int		eofs = 0;
-
-	tail = auclnt_get_tail(auclnt_output_stream(c));
-
-	/* get more data! (do this early) */
-	qenable(sc->s_wq);
-
-	mutex_enter(&sc->s_lock);
-	while (((eof = list_head(&sc->s_eofcnt)) != NULL) &&
-	    (eof->tail < tail)) {
-		list_remove(&sc->s_eofcnt, eof);
-		kmem_free(eof, sizeof (*eof));
-		eofs++;
-	}
-	proc->p_info.play.eof += eofs;
-	mutex_exit(&sc->s_lock);
-
-	if (eofs) {
-		auclnt_dev_walk_clients(auclnt_get_dev(c),
-		    sun_sigpoll, proc);
-	}
-}
-
 static void
-sun_input(audio_client_t *c)
-{
-	sun_sendup(c);
-}
-
-static int
-sun_create_minors(audio_dev_t *adev, void *notused)
-{
-	char		path[MAXPATHLEN];
-	minor_t		minor;
-	int		inst;
-	int		index;
-	const char	*driver;
-	unsigned	cap;
-
-	_NOTE(ARGUNUSED(notused));
-
-	ASSERT(mutex_owned(&sdev_lock));
-
-	/* don't create device nodes for sndstat device */
-	cap = auclnt_get_dev_capab(adev);
-	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
-		return (AUDIO_WALK_CONTINUE);
-	}
-
-	index = auclnt_get_dev_index(adev);
-	inst = auclnt_get_dev_instance(adev);
-	driver = auclnt_get_dev_driver(adev);
-
-	if (sdev_dip != NULL) {
-
-		minor = AUDIO_MKMN(index, AUDIO_MINOR_DEVAUDIO);
-		(void) snprintf(path, sizeof (path), "sound,%s,audio%d",
-		    driver, inst);
-		(void) ddi_create_minor_node(sdev_dip, path, S_IFCHR, minor,
-		    DDI_NT_AUDIO, 0);
-
-		minor = AUDIO_MKMN(index, AUDIO_MINOR_DEVAUDIOCTL);
-		(void) snprintf(path, sizeof (path), "sound,%s,audioctl%d",
-		    driver, inst);
-		(void) ddi_create_minor_node(sdev_dip, path, S_IFCHR, minor,
-		    DDI_NT_AUDIO, 0);
-	}
-
-	return (AUDIO_WALK_CONTINUE);
-}
-
-static int
-sun_remove_minors(audio_dev_t *adev, void *notused)
-{
-	char		path[MAXPATHLEN];
-	int		inst;
-	const char	*driver;
-	unsigned	cap;
-
-	_NOTE(ARGUNUSED(notused));
-
-	ASSERT(mutex_owned(&sdev_lock));
-
-	cap = auclnt_get_dev_capab(adev);
-	/* if not a play or record device, don't bother creating minors */
-	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
-		return (AUDIO_WALK_CONTINUE);
-	}
-
-	inst = auclnt_get_dev_instance(adev);
-	driver = auclnt_get_dev_driver(adev);
-
-	if (sdev_dip != NULL) {
-
-		(void) snprintf(path, sizeof (path), "sound,%s,audio%d",
-		    driver, inst);
-		ddi_remove_minor_node(sdev_dip, path);
-
-		(void) snprintf(path, sizeof (path), "sound,%s,audioctl%d",
-		    driver, inst);
-		ddi_remove_minor_node(sdev_dip, path);
-	}
-
-	return (AUDIO_WALK_CONTINUE);
-}
-
-static void *
-sun_dev_init(audio_dev_t *adev)
-{
-	sdev_t		*sdev;
-	unsigned	cap;
-
-	cap = auclnt_get_dev_capab(adev);
-	/* if not a play or record device, don't bother initializing it */
-	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
-		return (NULL);
-	}
-
-	sdev = kmem_zalloc(sizeof (*sdev), KM_SLEEP);
-	sdev->d_dev = adev;
-	mutex_init(&sdev->d_mx, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&sdev->d_cv, NULL, CV_DRIVER, NULL);
-	list_create(&sdev->d_procs, sizeof (struct sproc),
-	    offsetof(struct sproc, p_linkage));
-
-	mutex_enter(&sdev_lock);
-	(void) sun_create_minors(adev, NULL);
-	mutex_exit(&sdev_lock);
-
-	return (sdev);
-}
-
-static void
-sun_dev_fini(void *arg)
-{
-	sdev_t	*sdev = arg;
-
-	if (sdev != NULL) {
-
-		/* remove minor nodes */
-		mutex_enter(&sdev_lock);
-		(void) sun_remove_minors(sdev->d_dev, NULL);
-		mutex_exit(&sdev_lock);
-
-		mutex_destroy(&sdev->d_mx);
-		cv_destroy(&sdev->d_cv);
-		list_destroy(&sdev->d_procs);
-		kmem_free(sdev, sizeof (*sdev));
-	}
-}
-
-static struct audio_client_ops sun_ops = {
-	"internal,audio",
-	sun_dev_init,
-	sun_dev_fini,
-	sun_open,
-	sun_close,
-	NULL,	/* read */
-	NULL,	/* write */
-	NULL,	/* ioctl */
-	NULL,	/* chpoll */
-	NULL,	/* mmap */
-	sun_input,
-	sun_output,
-	NULL,	/* notify */
-	sun_drain,
-};
-
-static struct audio_client_ops sunctl_ops = {
-	"internal,audioctl",
-	NULL,	/* dev_init */
-	NULL,	/* dev_fini */
-	sun_open,
-	sun_close,
-	NULL,	/* read */
-	NULL,	/* write */
-	NULL,	/* ioctl */
-	NULL,	/* chpoll */
-	NULL,	/* mmap */
-	NULL,	/* output */
-	NULL,	/* input */
-	NULL,	/* notify */
-	NULL,	/* drain */
-};
-
-void
-auimpl_sun_init(void)
-{
-	mutex_init(&sdev_lock, NULL, MUTEX_DRIVER, NULL);
-	sdev_dip = NULL;
-	auclnt_register_ops(AUDIO_MINOR_DEVAUDIO, &sun_ops);
-	auclnt_register_ops(AUDIO_MINOR_DEVAUDIOCTL, &sunctl_ops);
-}
-
-/*
- * This is the operations entry points that are streams specific...
- * We map "instance" numbers.
- */
-
-static int
-sunstr_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *cr)
+devaudioctl_wput(audio_client_t *c, mblk_t *mp)
 {
-	int			rv;
-	minor_t			minor;
-	minor_t			index;
-	minor_t			type;
-	dev_t			physdev;
-	ldi_ident_t		lid;
-	ldi_handle_t		lh = NULL;
-	audio_client_t		*c = NULL;
-	audio_dev_t		*adev;
-	unsigned		fmt;
-	int			oflag;
-	boolean_t		isopen = B_FALSE;
-
-	if (sflag != 0) {
-		/* no direct clone or module opens */
-		return (EINVAL);
-	}
-
-	/*
-	 * NB: We reuse the partitioning that the core framework is
-	 * using for instance numbering.  This does mean that we are
-	 * limited to at most AUDIO_MN_INST_MASK devices, but this
-	 * number is sufficiently large (8192) that not to be a concern.
-	 */
-
-	minor = getminor(*devp);
-	index = (minor >> AUDIO_MN_INST_SHIFT) & AUDIO_MN_INST_MASK;
-	type = (minor >> AUDIO_MN_TYPE_SHIFT) & AUDIO_MN_TYPE_MASK;
-
-	/* can't directly open a cloned node! */
-	if (minor & AUDIO_MN_CLONE_MASK) {
-		return (ENXIO);
-	}
-
-	switch (type) {
-	case AUDIO_MINOR_DEVAUDIOCTL:
-		fmt = AUDIO_FORMAT_NONE;
-		oflag = flag & ~(FWRITE | FREAD);
-		break;
-	case AUDIO_MINOR_DEVAUDIO:
-		fmt = AUDIO_FORMAT_PCM;
-		oflag = flag;
-		break;
-	default:
-		/* these minor types are not legal */
-		return (ENXIO);
-	}
-
-	/* look up and hold the matching audio device */
-	adev = auclnt_hold_dev_by_index(index);
-	if (adev == NULL) {
-		return (ENXIO);
-	}
-	/* find the matching physical devt */
-	physdev = makedevice(ddi_driver_major(auclnt_get_dev_devinfo(adev)),
-	    AUDIO_MKMN(auclnt_get_dev_instance(adev), type));
-
-	if ((rv = ldi_ident_from_stream(rq, &lid)) == 0) {
-		rv = ldi_open_by_dev(&physdev, OTYP_CHR, flag, cr, &lh, lid);
-	}
-
-	/* ldi open is done, lh holds device, and we can release our hold */
-	auclnt_release_dev(adev);
-
-	if (rv != 0) {
-		goto fail;
-	}
-	/* phys layer clones a device for us */
-	ASSERT((getminor(physdev) & AUDIO_MN_CLONE_MASK) != 0);
-
-	/*
-	 * Note: We don't need to retain the hold on the client
-	 * structure, because the client is logically "held" by the
-	 * open LDI handle.  We're just using this hold_by_devt to
-	 * locate the associated client.
-	 */
-	c = auclnt_hold_by_devt(physdev);
-	ASSERT(c != NULL);
-	auclnt_release(c);
-
-	if ((rv = auclnt_open(c, fmt, oflag)) != 0) {
-		goto fail;
-	}
-	isopen = B_TRUE;
-
-	if ((rv = sproc_hold(c, lh, rq, oflag)) != 0) {
-		goto fail;
-	}
-
-	/* start up the input */
-	if (oflag & FREAD) {
-		auclnt_start(auclnt_input_stream(c));
-	}
-
-	/* we just reuse same minor number that phys layer used */
-	*devp = makedevice(getmajor(*devp), getminor(physdev));
-
-	qprocson(rq);
-
-	return (0);
-
-fail:
-	if (isopen) {
-		auclnt_close(c);
-	}
-	if (lh != NULL) {
-		(void) ldi_close(lh, flag, cr);
-	}
-
-	return (rv);
-}
-
-static int
-sunstr_close(queue_t *rq, int flag, cred_t *cr)
-{
-	sclient_t	*sc;
-	audio_client_t	*c;
-	int		rv;
-
-	sc = rq->q_ptr;
-	c = sc->s_client;
-
-	if ((auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIO) &&
-	    (ddi_can_receive_sig() || (ddi_get_pid() == 0))) {
-		rv = auclnt_drain(c);
-	}
-
-	auclnt_stop(auclnt_output_stream(c));
-	auclnt_stop(auclnt_input_stream(c));
-
-	auclnt_close(c);
-
-	qprocsoff(rq);
-
-	(void) ldi_close(sc->s_lh, flag, cr);
-
-	sproc_release(sc);
-
-	return (rv);
-}
-
-static void
-sunstr_miocdata(sclient_t *sc, mblk_t *mp)
-{
-	struct copyresp		*csp;
-	sioc_t			*ip;
-	mblk_t			*bcont;
-
-	csp = (void *)mp->b_rptr;
-
-	/*
-	 * If no state, then something "bad" has happened.
-	 */
-	if (((ip = (void *)csp->cp_private) == NULL) || (ip->i_sc != sc)) {
-		miocnak(sc->s_wq, mp, 0, EFAULT);
-		return;
-	}
-
-	/*
-	 * If we failed to transfer data to/from userland, then we are
-	 * done.  (Stream head will have notified userland.)
-	 */
-	if (csp->cp_rval != 0) {
-		ip->i_state = FINI;
-		ip->i_mp = mp;
-		sioc_finish(ip);
-		return;
-	}
-
-	/*
-	 * Buffer area for ioctl is attached to chain.
-	 * For an ioctl that didn't have any data to copyin,
-	 * we might need to allocate a new buffer area.
-	 */
-	bcont = mp->b_cont;
-	ip->i_bcont = bcont;
-	mp->b_cont = NULL;
-
-	if (bcont != NULL) {
-		ip->i_data = bcont->b_rptr;
-	}
-
-	/*
-	 * Meaty part of data processing.
-	 */
-	ip->i_state = IOCTL;
-	ip->i_mp = mp;
-
-	/* now, call the handler ioctl */
-	sunstr_ioctl(ip);
-}
-
-static void
-sunstr_mioctl(sclient_t *sc, mblk_t *mp)
-{
-	struct iocblk	*iocp = (void *)mp->b_rptr;
-	sioc_t		*ip;
-
-	/* BSD legacy here: we only support transparent ioctls */
-	if (iocp->ioc_count != TRANSPARENT) {
-		miocnak(sc->s_wq, mp, 0, EINVAL);
-		return;
-	}
-
-	ip = kmem_zalloc(sizeof (*ip), KM_NOSLEEP);
-	if (ip == NULL) {
-		miocnak(sc->s_wq, mp, 0, ENOMEM);
-		return;
-	}
-
-	/* make sure everything is setup in case we need to do copyin/out */
-	ip->i_sc = sc;
-	ip->i_model = iocp->ioc_flag;
-	ip->i_cmd = iocp->ioc_cmd;
-	ip->i_addr = *(caddr_t *)(void *)mp->b_cont->b_rptr;
-	ip->i_state = IOCTL;
-	ip->i_mp = mp;
-	freemsg(mp->b_cont);
-	mp->b_cont = NULL;
-
-	/* now, call the handler ioctl */
-	sunstr_ioctl(ip);
-}
-
-static int
-sunstr_wput(queue_t *wq, mblk_t *mp)
-{
-	sclient_t	*sc = wq->q_ptr;
-	struct iocblk	*iocp;
+	queue_t		*wq = auclnt_get_wq(c);
 
 	switch (DB_TYPE(mp)) {
 	case M_IOCTL:
 		/* Drain ioctl needs to be handled on the service queue */
-		iocp = (void *)mp->b_rptr;
-		if (iocp->ioc_cmd == AUDIO_DRAIN) {
-			if (auclnt_get_minor_type(sc->s_client) ==
-			    AUDIO_MINOR_DEVAUDIO) {
-				(void) putq(wq, mp);
-			} else {
-				miocnak(wq, mp, 0, EINVAL);
-			}
+		devaudio_mioctl(c, mp);
+		break;
+
+	case M_IOCDATA:
+		devaudio_miocdata(c, mp);
+		break;
+
+	case M_FLUSH:
+		/*
+		 * We don't flush the engine.  The reason is that
+		 * other streams might be using the engine.  This is
+		 * fundamentally no different from the case where the
+		 * engine hardware has data buffered in an
+		 * inaccessible FIFO.
+		 *
+		 * Clients that want to ensure no more data is coming
+		 * should stop the stream before flushing.
+		 */
+		if (*mp->b_rptr & FLUSHW) {
+			*mp->b_rptr &= ~FLUSHW;
+		}
+		if (*mp->b_rptr & FLUSHR) {
+			qreply(wq, mp);
 		} else {
-			sunstr_mioctl(sc, mp);
+			freemsg(mp);
+		}
+		break;
+
+	case M_DATA:
+		/*
+		 * No audio data on control nodes!
+		 */
+		freemsg(mp);
+
+	default:
+		freemsg(mp);
+		break;
+	}
+}
+
+static void
+devaudio_wput(audio_client_t *c, mblk_t *mp)
+{
+	queue_t		*wq = auclnt_get_wq(c);
+
+	switch (DB_TYPE(mp)) {
+	case M_IOCTL:
+		/* Drain ioctl needs to be handled on the service queue */
+		if (*(int *)(void *)mp->b_rptr == AUDIO_DRAIN) {
+			(void) putq(wq, mp);
+		} else {
+			devaudio_mioctl(c, mp);
 		}
 		break;
 
 	case M_IOCDATA:
-		sunstr_miocdata(sc, mp);
+		devaudio_miocdata(c, mp);
 		break;
 
 	case M_FLUSH:
@@ -1669,12 +1276,12 @@
 		 */
 		if (*mp->b_rptr & FLUSHW) {
 			flushq(wq, FLUSHALL);
-			auclnt_flush(auclnt_output_stream(sc->s_client));
+			auclnt_flush(auclnt_output_stream(c));
 			*mp->b_rptr &= ~FLUSHW;
 		}
 		if (*mp->b_rptr & FLUSHR) {
 			flushq(RD(wq), FLUSHALL);
-			auclnt_flush(auclnt_input_stream(sc->s_client));
+			auclnt_flush(auclnt_input_stream(c));
 			qreply(wq, mp);
 		} else {
 			freemsg(mp);
@@ -1683,38 +1290,27 @@
 
 	case M_DATA:
 		/*
-		 * If we don't have an engine, then we can't accept
-		 * write() data.  audio(7i) says we just ignore it,
-		 * so we toss it.
+		 * Defer processing to the queue.  This keeps the data
+		 * ordered, and allows the wsrv routine to gather
+		 * multiple mblks at once.
 		 */
-		if (auclnt_get_minor_type(sc->s_client) !=
-		    AUDIO_MINOR_DEVAUDIO) {
-			freemsg(mp);
-		} else {
-			/*
-			 * Defer processing to the queue.  This keeps
-			 * the data ordered, and allows the wsrv
-			 * routine to gather multiple mblks at once.
-			 */
-			if (mp->b_cont != NULL) {
+		if (mp->b_cont != NULL) {
 
-				/*
-				 * If we need to pullup, do it here to
-				 * simplify the rest of the processing
-				 * later.  This should rarely (if
-				 * ever) be necessary.
-				 */
-				mblk_t	*nmp;
+			/*
+			 * If we need to pullup, do it here to
+			 * simplify the rest of the processing later.
+			 * This should rarely (if ever) be necessary.
+			 */
+			mblk_t	*nmp;
 
-				if ((nmp = msgpullup(mp, -1)) == NULL) {
-					freemsg(mp);
-				} else {
-					freemsg(mp);
-					(void) putq(wq, nmp);
-				}
+			if ((nmp = msgpullup(mp, -1)) == NULL) {
+				freemsg(mp);
 			} else {
-				(void) putq(wq, mp);
+				freemsg(mp);
+				(void) putq(wq, nmp);
 			}
+		} else {
+			(void) putq(wq, mp);
 		}
 		break;
 
@@ -1722,14 +1318,13 @@
 		freemsg(mp);
 		break;
 	}
-	return (0);
 }
 
-static int
-sunstr_wsrv(queue_t *wq)
+static void
+devaudio_wsrv(audio_client_t *c)
 {
-	sclient_t	*sc = wq->q_ptr;
-	audio_client_t	*c = sc->s_client;
+	queue_t		*wq = auclnt_get_wq(c);
+	daclient_t	*dc = auclnt_get_private(c);
 	audio_stream_t	*sp;
 	mblk_t		*mp;
 	unsigned	framesz;
@@ -1747,13 +1342,13 @@
 		/* if its a drain ioctl, we need to process it here */
 		if (DB_TYPE(mp) == M_IOCTL) {
 			ASSERT((*(int *)(void *)mp->b_rptr) == AUDIO_DRAIN);
-			mutex_enter(&sc->s_lock);
-			mp->b_next = sc->s_draining;
-			sc->s_draining = mp;
-			mutex_exit(&sc->s_lock);
+			mutex_enter(&dc->dc_lock);
+			mp->b_next = dc->dc_draining;
+			dc->dc_draining = mp;
+			mutex_exit(&dc->dc_lock);
 
 			if (auclnt_start_drain(c) != 0) {
-				sun_drain(c);
+				devaudio_drain(c);
 			}
 			continue;
 		}
@@ -1771,9 +1366,9 @@
 			eof = kmem_zalloc(sizeof (*eof), KM_NOSLEEP);
 			if (eof != NULL) {
 				eof->tail = auclnt_get_head(sp);
-				mutex_enter(&sc->s_lock);
-				list_insert_tail(&sc->s_eofcnt, eof);
-				mutex_exit(&sc->s_lock);
+				mutex_enter(&dc->dc_lock);
+				list_insert_tail(&dc->dc_eofcnt, eof);
+				mutex_exit(&dc->dc_lock);
 			}
 			freemsg(mp);
 			continue;
@@ -1795,173 +1390,49 @@
 	/* if the stream isn't running yet, start it up */
 	if (!auclnt_is_paused(sp))
 		auclnt_start(sp);
-
-	return (0);
-}
-
-static int
-sunstr_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
-	if ((cmd != DDI_ATTACH) || (dip == NULL)) {
-		return (DDI_FAILURE);
-	}
-	if (ddi_get_instance(dip) != 0) {
-		return (DDI_FAILURE);
-	}
-
-	mutex_enter(&sdev_lock);
-	sdev_dip = dip;
-	auclnt_walk_devs(sun_create_minors, NULL);
-	mutex_exit(&sdev_lock);
-	ddi_report_dev(dip);
-
-	return (0);
-}
-
-static int
-sunstr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
-	if ((cmd != DDI_DETACH) || (dip == NULL)) {
-		return (DDI_FAILURE);
-	}
-	if (ddi_get_instance(dip) != 0) {
-		return (DDI_FAILURE);
-	}
-
-	mutex_enter(&sdev_lock);
-	/* remove all minors */
-	auclnt_walk_devs(sun_remove_minors, NULL);
-	sdev_dip = NULL;
-	mutex_exit(&sdev_lock);
-
-	return (0);
 }
 
-static int
-sunstr_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
-{
-	int		error;
-
-	_NOTE(ARGUNUSED(dip));
-	_NOTE(ARGUNUSED(arg));
-
-	switch (cmd) {
-	case DDI_INFO_DEVT2DEVINFO:
-		*result = sdev_dip;
-		error = DDI_SUCCESS;
-		break;
-	case DDI_INFO_DEVT2INSTANCE:
-		*result = 0;
-		error = DDI_SUCCESS;
-		break;
-	default:
-		*result = NULL;
-		error = DDI_FAILURE;
-	}
-	return (error);
-}
-
-static struct module_info sunstr_minfo = {
-	0,		/* used for strlog(1M) only, which we don't use */
-	"austr",
-	0,		/* min pkt size */
-	2048,		/* max pkt size */
-	65536,		/* hi water */
-	32768,		/* lo water */
-};
-
-static struct qinit sunstr_rqinit = {
-	NULL,		/* qi_putp */
-	NULL,		/* qi_srvp */
-	sunstr_open,	/* qi_qopen */
-	sunstr_close,	/* qi_qclose */
-	NULL,		/* qi_qadmin */
-	&sunstr_minfo,	/* qi_minfo */
-	NULL,		/* qi_mstat */
+static struct audio_client_ops devaudio_ops = {
+	"sound,audio",
+	devaudio_init,
+	devaudio_fini,
+	devaudio_open,
+	devaudio_close,
+	NULL,	/* read */
+	NULL,	/* write */
+	NULL,	/* ioctl */
+	NULL,	/* chpoll */
+	NULL,	/* mmap */
+	devaudio_input,
+	devaudio_output,
+	NULL,	/* notify */
+	devaudio_drain,
+	devaudio_wput,
+	devaudio_wsrv
 };
 
-static struct qinit sunstr_wqinit = {
-	sunstr_wput,	/* qi_putp */
-	sunstr_wsrv,	/* qi_srvp */
-	NULL,		/* qi_qopen */
-	NULL,		/* qi_qclose */
-	NULL,		/* qi_qadmin */
-	&sunstr_minfo,	/* qi_minfo */
-	NULL,		/* qi_mstat */
-};
-
-static struct streamtab sunstr_strtab = {
-	&sunstr_rqinit,
-	&sunstr_wqinit,
+static struct audio_client_ops devaudioctl_ops = {
+	"sound,audioctl",
+	NULL,	/* dev_init */
+	NULL,	/* dev_fini */
+	devaudioctl_open,
+	devaudioctl_close,
+	NULL,	/* read */
+	NULL,	/* write */
+	NULL,	/* ioctl */
+	NULL,	/* chpoll */
+	NULL,	/* mmap */
+	NULL,	/* output */
+	NULL,	/* input */
+	NULL,	/* notify */
+	NULL,	/* drain */
+	devaudioctl_wput,
 	NULL,
-	NULL
-};
-
-struct cb_ops sunstr_cb_ops = {
-	nodev,		/* open */
-	nodev,		/* close */
-	nodev,		/* strategy */
-	nodev,		/* print */
-	nodev,		/* dump */
-	nodev,		/* read */
-	nodev,		/* write */
-	nodev,		/* ioctl */
-	nodev,		/* devmap */
-	nodev,		/* mmap */
-	nodev,		/* segmap */
-	nochpoll,	/* chpoll */
-	ddi_prop_op,	/* prop_op */
-	&sunstr_strtab,	/* str */
-	D_MP,		/* flag */
-	CB_REV, 	/* rev */
-	nodev,		/* aread */
-	nodev,		/* awrite */
 };
 
-static struct dev_ops sunstr_dev_ops = {
-	DEVO_REV,		/* rev */
-	0,			/* refcnt */
-	sunstr_getinfo,		/* getinfo */
-	nulldev,		/* identify */
-	nulldev,		/* probe */
-	sunstr_attach,		/* attach */
-	sunstr_detach,		/* detach */
-	nodev,			/* reset */
-	&sunstr_cb_ops,		/* cb_ops */
-	NULL,			/* bus_ops */
-	NULL,			/* power */
-};
-
-static struct modldrv sunstr_modldrv = {
-	&mod_driverops,
-	"Audio Streams Support",
-	&sunstr_dev_ops,
-};
-
-static struct modlinkage sunstr_modlinkage = {
-	MODREV_1,			/* MODREV_1 indicated by manual */
-	&sunstr_modldrv,
-	NULL
-};
-
-int
-sunstr_init(void)
+void
+auimpl_sun_init(void)
 {
-	/*
-	 * NB: This *must* be called after the "audio" module's
-	 * _init routine has called auimpl_sun_init().
-	 */
-	return (mod_install(&sunstr_modlinkage));
+	auclnt_register_ops(AUDIO_MINOR_DEVAUDIO, &devaudio_ops);
+	auclnt_register_ops(AUDIO_MINOR_DEVAUDIOCTL, &devaudioctl_ops);
 }
-
-int
-sunstr_fini(void)
-{
-	return (mod_remove(&sunstr_modlinkage));
-}
-
-int
-sunstr_info(struct modinfo *modinfop)
-{
-	return (mod_info(&sunstr_modlinkage, modinfop));
-}
--- a/usr/src/uts/common/io/audio/impl/austr.c	Wed Jul 22 15:36:05 2009 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Audio Streams Support driver.  This relies on the common audio module.
- *
- * The entire driver is a tiny shim for the audio framework, and exists
- * solely to provide a device node that we can hang STREAMs minor nodes from,
- * since we can't mix and match STREAMs and character devices in the same
- * driver, due to limitations in the DDI.
- */
-
-#include <sys/types.h>
-#include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-
-/* our entire API with "audio" is miniscule */
-extern int sunstr_init(void);
-extern int sunstr_fini(void);
-extern int sunstr_info(struct modinfo *);
-
-int
-_init(void)
-{
-	return (sunstr_init());
-}
-
-int
-_fini(void)
-{
-	return (sunstr_fini());
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (sunstr_info(modinfop));
-}
--- a/usr/src/uts/common/io/audio/impl/austr.conf	Wed Jul 22 15:36:05 2009 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# Configuration file for the common austr driver.
-#
-
-#
-# We are a pseudo driver.
-#
-name="austr" parent="pseudo" instance=0;
-
-#
-# We want to always be present and never removed.  This is important
-# to ensure that device numbering is not lost due to the driver being
-# forced out of memory automatically.
-#
-ddi-forceattach=1;
-ddi-no-autodetach=1;
--- a/usr/src/uts/intel/Makefile.intel.shared	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/intel/Makefile.intel.shared	Wed Jul 22 09:02:10 2009 -0700
@@ -206,7 +206,6 @@
 DRV_KMODS	+= audiopci
 DRV_KMODS	+= audiots
 DRV_KMODS	+= audiovia823x
-DRV_KMODS	+= austr
 DRV_KMODS	+= bl 
 DRV_KMODS	+= bge
 DRV_KMODS	+= bofi
--- a/usr/src/uts/intel/austr/Makefile	Wed Jul 22 15:36:05 2009 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# uts/intel/austr/Makefile
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#	This makefile drives the production of the audio streams module.
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= austr
-OBJECTS		= $(AUSTR_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(AUSTR_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/common/io/audio/impl
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-#	Depends on drv/audio
-#
-LDFLAGS		+= -dy -Ndrv/audio
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS)
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/sparc/Makefile.sparc.shared	Wed Jul 22 15:36:05 2009 +0800
+++ b/usr/src/uts/sparc/Makefile.sparc.shared	Wed Jul 22 09:02:10 2009 -0700
@@ -263,7 +263,7 @@
 #
 #	Machine Specific Driver Modules (/kernel/drv):
 #
-DRV_KMODS	+= audio audio1575 audioens audiocs audiots audiopci austr
+DRV_KMODS	+= audio audio1575 audioens audiocs audiots audiopci
 DRV_KMODS	+= bge bpp dmfe eri esp fas hme qfe
 DRV_KMODS	+= openeepr options sd ses st
 DRV_KMODS	+= ssd
--- a/usr/src/uts/sparc/austr/Makefile	Wed Jul 22 15:36:05 2009 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# uts/sparc/austr/Makefile
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#	This makefile drives the production of the audio streams module.
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= austr
-OBJECTS		= $(AUSTR_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(AUSTR_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/common/io/audio/impl
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sparc/Makefile.sparc
-
-#
-#	Depends on drv/audio
-#
-LDFLAGS		+= -dy -Ndrv/audio
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS)
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sparc/Makefile.targ