audio_sun.c revision 9484:fbd5ddc28e96
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Sun audio(7I) and mixer(7I) personality.
28 *
29 * There are some "undocumented" details of how legacy Sun audio
30 * interfaces work.  The following "rules" were derived from reading the
31 * legacy Sun mixer code, and to the best of our knowledge are not
32 * documented elsewhere.
33 *
34 * - We create a "fake" audio device, which behaves like a classic
35 *   exclusive audio device, for each PID, as determined during open(2).
36 *
37 * - Different processes don't interfere with each other.  Even though
38 *   they are running concurrently, they each think they have exclusive
39 *   control over the audio device.
40 *
41 * - Read and write directions operate independent of each other.  That
42 *   is, a device open for reading won't intefere with a future open for
43 *   writing, and vice versa.  This is true even within the same process.
44 *
45 * - Because the virtualization is by PID, strange behavior may occur
46 *   if a process tries to open an audio device at the same time it
47 *   has already received a file descriptor from another process (such
48 *   through inheritence via fork()).
49 *
50 * - The "fake" audio device has no control over physical settings.
51 *   It sees only the software attenuation-based volumes for play and
52 *   record, and has no support for alternate input or output ports or
53 *   access to the monitoring features of the hardware.
54 *
55 * - Explicit notificaton signals (SIGPOLL) are only ever sent up the
56 *   audioctl node -- never up a regular audio node.  (The stream head
57 *   may still issue SIGPOLL based on readability/writability of
58 *   course.)
59 *
60 * - Corollary: processes that want asynch. notifications will open
61 *   /dev/audioctl as well as /dev/audio.
62 *
63 * - We don't support the MIXER mode at all.
64 *
65 * - By corollary, a process is only allowed to open /dev/audio once
66 *   (in each direction.)
67 *
68 * - Attempts to open /dev/audio in duplex mode (O_RDWR) fail (EBUSY)
69 *   if the device cannot support duplex operation.
70 *
71 * - Attempts to open a device with FREAD set fail if the device is not
72 *   capable of recording.  (Likewise for FWRITE and playback.)
73 *
74 * - No data transfer is permitted for audioctl nodes.  (No actual
75 *   record or play.)
76 *
77 * - Sun audio does not support any formats other than linear and
78 *   ULAW/ALAW.  I.e. it will never support AC3 or other "opaque"
79 *   streams which require special handling.
80 *
81 * - Sun audio only supports stereo or monophonic data streams.
82 */
83
84#include <sys/types.h>
85#include <sys/open.h>
86#include <sys/errno.h>
87#include <sys/audio.h>
88#include <sys/mixer.h>
89#include <sys/file.h>
90#include <sys/stropts.h>
91#include <sys/strsun.h>
92#include <sys/sysmacros.h>
93#include <sys/list.h>
94#include <sys/note.h>
95#include <sys/stat.h>
96#include <sys/ddi.h>
97#include <sys/sunddi.h>
98#include "audio_client.h"
99
100typedef struct sclient sclient_t;
101typedef struct sdev sdev_t;
102typedef struct sproc sproc_t;
103typedef struct sioc sioc_t;
104
105typedef enum {
106	COPYIN,
107	COPYOUT,
108	IOCTL,
109	ACK,
110	NAK,
111	FINI
112} sioc_state_t;
113
114struct sioc {
115	sclient_t		*i_sc;
116	int			i_cmd;
117	size_t			i_size;
118	void			*i_data;
119	mblk_t			*i_bcont;
120	int			i_step;
121	uint_t			i_model;
122	sioc_state_t		i_state;
123	mblk_t			*i_mp;
124	caddr_t			i_addr;
125	int			i_error;
126};
127
128/* common structure shared between both audioctl and audio nodes */
129struct sclient {
130	sproc_t			*s_proc;
131	sdev_t			*s_sdev;
132	audio_client_t		*s_client;
133	queue_t			*s_rq;
134	queue_t			*s_wq;
135	ldi_handle_t		s_lh;
136	unsigned		s_eof;
137	list_t			s_eofcnt;
138	kmutex_t		s_lock;
139	mblk_t			*s_draining;
140};
141
142struct eofcnt {
143	list_node_t		linkage;
144	uint64_t		tail;
145};
146
147struct sdev {
148	audio_dev_t		*d_dev;
149
150	list_t			d_procs;
151	kmutex_t		d_mx;
152	kcondvar_t		d_cv;
153};
154
155struct sproc {
156	pid_t			p_id;
157	struct audio_info	p_info;
158	int			p_refcnt;
159	int			p_oflag;
160	list_node_t		p_linkage;
161	sdev_t			*p_sdev;
162	sclient_t		*p_writer;
163	sclient_t		*p_reader;
164};
165
166int sproc_hold(audio_client_t *, int);
167void sproc_release(sclient_t *);
168static void sproc_update(sproc_t *);
169
170
171static kmutex_t	sdev_lock;
172static dev_info_t *sdev_dip;
173
174/*
175 * Alloc extra room for ioctl buffer, in case none was supplied or copyin was
176 * shorter than we need for the whole struct.  On failure, returns an
177 * appropriate errno, zero on success.  Any original data is preserved.
178 */
179static int
180sioc_alloc(sioc_t *ip, size_t size)
181{
182	mblk_t			*nmp;
183
184	/* if we already have enough, just use what we've got */
185	if (ip->i_size >= size)
186		return (0);
187
188	if ((nmp = allocb(size, BPRI_MED)) == NULL) {
189		ip->i_state = NAK;
190		ip->i_error = ENOMEM;
191		return (ENOMEM);
192	}
193	bzero(nmp->b_rptr, size);
194
195	/* if there was already some data present, preserve it */
196	if (ip->i_size != 0) {
197		bcopy(ip->i_data, nmp->b_rptr, ip->i_size);
198		freemsg(ip->i_bcont);
199	}
200	ip->i_bcont = nmp;
201	ip->i_data = nmp->b_rptr;
202	ip->i_size = size;
203
204	return (0);
205}
206
207static void
208sioc_copyin(sioc_t *ip, size_t size)
209{
210	ip->i_state = COPYIN;
211	ip->i_size = size;
212	if (ip->i_bcont != NULL) {
213		freemsg(ip->i_bcont);
214		ip->i_bcont = NULL;
215	}
216
217	mcopyin(ip->i_mp, ip, size, ip->i_addr);
218}
219
220static void
221sioc_copyout(sioc_t *ip, size_t size)
222{
223	mblk_t			*bcont;
224
225	ASSERT(ip->i_size >= size);
226
227	bcont = ip->i_bcont;
228
229	ip->i_state = COPYOUT;
230	ip->i_bcont = NULL;
231
232	mcopyout(ip->i_mp, ip, size, ip->i_addr, bcont);
233}
234
235static void
236sioc_error(sioc_t *ip, int error)
237{
238	ip->i_state = NAK;
239	ip->i_error = error;
240}
241
242static void
243sioc_success(sioc_t *ip)
244{
245	ip->i_state = ACK;
246}
247
248static void
249sioc_fini(sioc_t *ip)
250{
251	if (ip->i_bcont != NULL)
252		freemsg(ip->i_bcont);
253
254	kmem_free(ip, sizeof (*ip));
255}
256
257static void
258sioc_finish(sioc_t *ip)
259{
260	mblk_t		*mp;
261	sclient_t	*sc;
262
263	sc = ip->i_sc;
264	mp = ip->i_mp;
265	ip->i_mp = NULL;
266
267	switch (ip->i_state) {
268	case ACK:
269		miocack(sc->s_wq, mp, 0, 0);
270		break;
271
272	case IOCTL:	/* caller didn't use sioc_success */
273		ip->i_error = ECANCELED;
274		miocnak(sc->s_wq, mp, 0, ip->i_error);
275		break;
276
277	case NAK:
278		miocnak(sc->s_wq, mp, 0, ip->i_error);
279		break;
280
281	case COPYOUT:
282	case COPYIN:
283		/* data copy to be done */
284		qreply(sc->s_wq, mp);
285		return;
286
287	case FINI:
288		if (mp != NULL) {
289			freemsg(mp);
290		}
291		break;
292	}
293
294	sioc_fini(ip);
295}
296
297static int
298sun_compose_format(audio_prinfo_t *prinfo)
299{
300	switch (prinfo->precision) {
301	case 8:
302		switch (prinfo->encoding) {
303		case AUDIO_ENCODING_ULAW:
304			return (AUDIO_FORMAT_ULAW);
305		case AUDIO_ENCODING_ALAW:
306			return (AUDIO_FORMAT_ALAW);
307		case AUDIO_ENCODING_LINEAR8:
308			return (AUDIO_FORMAT_U8);
309		case AUDIO_ENCODING_LINEAR:
310			return (AUDIO_FORMAT_S8);
311		}
312		break;
313	case 16:
314		if (prinfo->encoding == AUDIO_ENCODING_LINEAR)
315			return (AUDIO_FORMAT_S16_NE);
316		break;
317	case 32:
318		if (prinfo->encoding == AUDIO_ENCODING_LINEAR)
319			return (AUDIO_FORMAT_S32_NE);
320		break;
321	}
322	return (AUDIO_FORMAT_NONE);
323
324}
325
326static void
327sun_decompose_format(audio_prinfo_t *prinfo, int afmt)
328{
329	int	e, p;
330
331	/*
332	 * N.B.: Even though some of the formats below can't be set by
333	 * this personality, reporting them (using the closest match)
334	 * allows this personality to roughly approximate settings for
335	 * other streams.  It would be incredibly poor form for any
336	 * personality to modify the format settings for a different
337	 * personality, so we don't worry about that case.
338	 */
339
340	switch (afmt) {
341	case AUDIO_FORMAT_ULAW:
342		e = AUDIO_ENCODING_ULAW;
343		p = 8;
344		break;
345
346	case AUDIO_FORMAT_ALAW:
347		e = AUDIO_ENCODING_ALAW;
348		p = 8;
349		break;
350
351	case AUDIO_FORMAT_U8:
352		e = AUDIO_ENCODING_LINEAR8;
353		p = 8;
354		break;
355
356	case AUDIO_FORMAT_S8:
357		e = AUDIO_ENCODING_LINEAR;
358		p = 8;
359		break;
360
361	case AUDIO_FORMAT_S16_NE:
362	case AUDIO_FORMAT_S16_OE:
363	case AUDIO_FORMAT_U16_NE:
364	case AUDIO_FORMAT_U16_OE:
365		e = AUDIO_ENCODING_LINEAR;
366		p = 16;
367		break;
368
369	case AUDIO_FORMAT_S24_NE:
370	case AUDIO_FORMAT_S24_OE:
371	case AUDIO_FORMAT_S24_PACKED:
372		e = AUDIO_ENCODING_LINEAR;
373		p = 24;
374		break;
375
376	case AUDIO_FORMAT_S32_NE:
377	case AUDIO_FORMAT_S32_OE:
378		e = AUDIO_ENCODING_LINEAR;
379		p = 32;
380		break;
381
382	default:
383		/* all other formats (e.g. AC3) are uninterpreted */
384		e = AUDIO_ENCODING_NONE;
385		p = 32;
386		break;
387	}
388
389	prinfo->encoding = e;
390	prinfo->precision = p;
391}
392
393static sproc_t *
394sproc_alloc(sclient_t *sc)
395{
396	audio_client_t	*c;
397	audio_info_t	*info;
398	audio_prinfo_t	*prinfo;
399	uint32_t	caps;
400	sproc_t		*proc;
401
402	c = sc->s_client;
403	if ((proc = kmem_zalloc(sizeof (*proc), KM_NOSLEEP)) == NULL) {
404		return (NULL);
405	}
406	info = &proc->p_info;
407
408	/*
409	 * audio(7I) says: Upon the initial open() of the audio
410	 * device, the driver resets the data format of the device to
411	 * the default state of 8-bit, 8Khz, mono u-Law data.
412	 */
413	prinfo = &info->play;
414	prinfo->channels =	1;
415	prinfo->sample_rate =	8000;
416	prinfo->encoding =	AUDIO_ENCODING_ULAW;
417	prinfo->precision =	8;
418	prinfo->gain =		AUDIO_MAX_GAIN;
419	prinfo->balance =	AUDIO_MID_BALANCE;
420	prinfo->buffer_size =	8192;
421	prinfo->pause =		B_FALSE;
422	prinfo->waiting =	B_FALSE;
423	prinfo->open =		B_FALSE;
424	prinfo->active =	B_FALSE;
425	prinfo->samples =	0;
426	prinfo->eof =		0;
427	prinfo->error =		0;
428	prinfo->minordev =	0;
429	prinfo->port =		AUDIO_SPEAKER;
430	prinfo->avail_ports =	AUDIO_SPEAKER;
431	prinfo->mod_ports =	AUDIO_NONE;
432	prinfo->_xxx =		0;
433
434	prinfo = &info->record;
435	prinfo->channels =	1;
436	prinfo->sample_rate =	8000;
437	prinfo->encoding =	AUDIO_ENCODING_ULAW;
438	prinfo->precision =	8;
439	prinfo->gain =		AUDIO_MAX_GAIN;
440	prinfo->balance =	AUDIO_MID_BALANCE;
441	prinfo->buffer_size =	8192;
442	prinfo->waiting =	B_FALSE;
443	prinfo->open =  	B_FALSE;
444	prinfo->active =	B_FALSE;
445	prinfo->samples =	0;
446	prinfo->eof =		0;
447	prinfo->error =		0;
448	prinfo->minordev =	0;
449	prinfo->port =		AUDIO_MICROPHONE;
450	prinfo->avail_ports =	AUDIO_MICROPHONE;
451	prinfo->mod_ports =	AUDIO_MICROPHONE;
452
453	info->output_muted =	B_FALSE;
454	/* pretend we don't have a software mixer - we don't support the API */
455	info->hw_features =	0;
456	info->sw_features =	0;
457	info->sw_features_enabled = 0;
458
459	caps = auclnt_get_dev_capab(auclnt_get_dev(c));
460	if (caps & AUDIO_CLIENT_CAP_PLAY)
461		info->hw_features |= AUDIO_HWFEATURE_PLAY;
462	if (caps & AUDIO_CLIENT_CAP_RECORD)
463		info->hw_features |= AUDIO_HWFEATURE_RECORD;
464	if (caps & AUDIO_CLIENT_CAP_DUPLEX)
465		info->hw_features |= AUDIO_HWFEATURE_DUPLEX;
466
467	return (proc);
468}
469
470static void
471sproc_free(sproc_t *proc)
472{
473	kmem_free(proc, sizeof (*proc));
474}
475
476int
477sproc_hold(audio_client_t *c, int oflag)
478{
479	pid_t		pid;
480	sproc_t		*proc;
481	sdev_t		*sdev;
482	sclient_t	*sc;
483	list_t		*l;
484	audio_dev_t	*adev;
485	int		rv;
486
487	adev = auclnt_get_dev(c);
488
489	/* first allocate and initialize the sclient private data */
490	if ((sc = kmem_zalloc(sizeof (*sc), KM_NOSLEEP)) == NULL) {
491		return (ENOMEM);
492	}
493
494	mutex_init(&sc->s_lock, NULL, MUTEX_DRIVER, NULL);
495	list_create(&sc->s_eofcnt, sizeof (struct eofcnt),
496	    offsetof(struct eofcnt, linkage));
497	auclnt_set_private(c, sc);
498
499	sdev = auclnt_get_dev_minor_data(adev, AUDIO_MINOR_DEVAUDIO);
500	l = &sdev->d_procs;
501	pid = auclnt_get_pid(c);
502
503	/* set a couple of common fields */
504	sc->s_client = c;
505	sc->s_sdev = sdev;
506
507	mutex_enter(&sdev->d_mx);
508	for (proc = list_head(l); proc != NULL; proc = list_next(l, proc)) {
509		if (proc->p_id == pid) {
510			proc->p_refcnt++;
511			break;
512		}
513	}
514	if (proc == NULL) {
515		if ((proc = sproc_alloc(sc)) == NULL) {
516			rv = ENOMEM;
517			goto failed;
518		}
519		proc->p_refcnt = 1;
520		proc->p_id = pid;
521		proc->p_sdev = sdev;
522		list_insert_tail(l, proc);
523	}
524
525	sc->s_proc = proc;
526
527	while (proc->p_oflag & oflag) {
528
529		if (oflag & (FNDELAY|FNONBLOCK)) {
530			rv = EBUSY;
531			goto failed;
532		}
533		if (oflag & FWRITE)
534			proc->p_info.play.waiting++;
535		if (oflag & FREAD)
536			proc->p_info.record.waiting++;
537		if (cv_wait_sig(&sdev->d_cv, &sdev->d_mx) == 0) {
538			/* interrupted! */
539			if (oflag & FWRITE)
540				proc->p_info.play.waiting--;
541			if (oflag & FREAD)
542				proc->p_info.record.waiting--;
543			rv = EINTR;
544			goto failed;
545		}
546		if (oflag & FWRITE)
547			proc->p_info.play.waiting--;
548		if (oflag & FREAD)
549			proc->p_info.record.waiting--;
550	}
551
552	if (oflag & FWRITE) {
553		audio_prinfo_t	*play = &proc->p_info.play;
554		audio_stream_t	*sp = auclnt_output_stream(c);
555
556		if (((rv = auclnt_set_rate(sp, 8000)) != 0) ||
557		    ((rv = auclnt_set_format(sp, AUDIO_FORMAT_ULAW)) != 0) ||
558		    ((rv = auclnt_set_channels(sp, 1)) != 0)) {
559			goto failed;
560		}
561
562		auclnt_set_samples(sp, 0);
563		auclnt_set_errors(sp, 0);
564		play->eof = 0;
565		play->buffer_size = 8192;
566
567		auclnt_set_gain(sp, ((play->gain * 100) / AUDIO_MAX_GAIN));
568		auclnt_set_muted(sp, proc->p_info.output_muted);
569		play->open = B_TRUE;
570		proc->p_writer = sc;
571		proc->p_oflag |= FWRITE;
572	}
573
574	if (oflag & FREAD) {
575		audio_prinfo_t	*rec = &proc->p_info.record;
576		audio_stream_t	*sp = auclnt_input_stream(c);
577
578		if (((rv = auclnt_set_rate(sp, 8000)) != 0) ||
579		    ((rv = auclnt_set_format(sp, AUDIO_FORMAT_ULAW)) != 0) ||
580		    ((rv = auclnt_set_channels(sp, 1)) != 0)) {
581			goto failed;
582		}
583
584		auclnt_set_samples(sp, 0);
585		auclnt_set_errors(sp, 0);
586		rec->eof = 0;
587		rec->buffer_size = 8192;
588
589		auclnt_set_gain(sp, ((rec->gain * 100) / AUDIO_MAX_GAIN));
590		rec->open = B_TRUE;
591		proc->p_reader = sc;
592		proc->p_oflag |= FREAD;
593	}
594
595	sproc_update(proc);
596
597	mutex_exit(&sdev->d_mx);
598
599	return (0);
600
601failed:
602	mutex_exit(&sdev->d_mx);
603	sproc_release(sc);
604	return (rv);
605
606}
607
608static void
609sun_clear_eof(sclient_t *sc)
610{
611	struct eofcnt *eof;
612	mutex_enter(&sc->s_lock);
613	while ((eof = list_remove_head(&sc->s_eofcnt)) != NULL) {
614		kmem_free(eof, sizeof (*eof));
615	}
616	mutex_exit(&sc->s_lock);
617}
618
619void
620sproc_release(sclient_t *sc)
621{
622	sproc_t		*proc;
623	sdev_t		*sdev;
624	mblk_t		*mp;
625
626	proc = sc->s_proc;
627	sdev = sc->s_sdev;
628	sc->s_proc = NULL;
629
630	mutex_enter(&sdev->d_mx);
631
632	if (proc != NULL) {
633		proc->p_refcnt--;
634		ASSERT(proc->p_refcnt >= 0);
635
636		if (sc == proc->p_writer) {
637			proc->p_oflag &= ~FWRITE;
638			proc->p_writer = NULL;
639		}
640		if (sc == proc->p_reader) {
641			proc->p_oflag &= ~FREAD;
642			proc->p_reader = NULL;
643		}
644		cv_broadcast(&sdev->d_cv);
645
646		if (proc->p_refcnt == 0) {
647			list_remove(&sdev->d_procs, proc);
648			sproc_free(proc);
649		}
650		sc->s_proc = NULL;
651	}
652
653	mutex_exit(&sdev->d_mx);
654
655	sun_clear_eof(sc);
656
657	while ((mp = sc->s_draining) != NULL) {
658		sc->s_draining = mp->b_next;
659		mp->b_next = NULL;
660		freemsg(mp);
661	}
662
663	mutex_destroy(&sc->s_lock);
664	list_destroy(&sc->s_eofcnt);
665	kmem_free(sc, sizeof (*sc));
666}
667
668static void
669sun_sendup(audio_client_t *c)
670{
671	audio_stream_t	*sp = auclnt_input_stream(c);
672	sclient_t	*sc = auclnt_get_private(c);
673	unsigned	framesz = auclnt_get_framesz(sp);
674	queue_t		*rq = sc->s_rq;
675	mblk_t		*mp;
676	unsigned	nbytes = sc->s_proc->p_info.record.buffer_size;
677	unsigned	count = nbytes / framesz;
678
679	/*
680	 * Potentially send a message upstream with the record data.
681	 * We collect this up in chunks of the buffer size requested
682	 * by the client.
683	 */
684
685	while (auclnt_get_count(sp) >= count) {
686
687		if ((!canputnext(rq)) ||
688		    ((mp = allocb(nbytes, BPRI_MED)) == NULL)) {
689			/*
690			 * This will apply back pressure to the
691			 * buffer.  We haven't yet lost any data, we
692			 * just can't send it up.  The point at which
693			 * we have an unrecoverable overrun is in the
694			 * buffer, not in the streams queue.  So, no
695			 * need to do anything right now.
696			 *
697			 * Note that since recording is enabled, we
698			 * expect that the callback routine will be
699			 * called repeatedly & regularly, so we don't
700			 * have to worry about leaving data orphaned
701			 * in the queue.
702			 */
703			break;
704		}
705
706		(void) auclnt_consume_data(sp, (caddr_t)mp->b_wptr, count);
707		mp->b_wptr += nbytes;
708		putnext(rq, mp);
709	}
710}
711
712static int
713sun_open(audio_client_t *c, int oflag)
714{
715	_NOTE(ARGUNUSED(c));
716	_NOTE(ARGUNUSED(oflag));
717	return (0);
718}
719
720static void
721sun_close(audio_client_t *c)
722{
723	_NOTE(ARGUNUSED(c));
724}
725
726static void
727sproc_update(sproc_t *proc)
728{
729	audio_info_t	*info;
730	audio_stream_t	*sp;
731	sclient_t	*sc;
732
733	info = &proc->p_info;
734
735	ASSERT(mutex_owned(&proc->p_sdev->d_mx));
736
737	if ((sc = proc->p_writer) != NULL) {
738		sp = auclnt_output_stream(sc->s_client);
739
740		info->play.sample_rate = auclnt_get_rate(sp);
741		info->play.channels = auclnt_get_channels(sp);
742		sun_decompose_format(&info->play, auclnt_get_format(sp));
743
744		info->play.gain =
745		    (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100;
746		info->play.pause = auclnt_is_paused(sp);
747		info->play.active = !info->play.pause;
748		info->play.samples = auclnt_get_samples(sp);
749		info->play.error = auclnt_get_errors(sp) ? B_TRUE : B_FALSE;
750		info->output_muted = auclnt_get_muted(sp);
751	}
752
753	if ((sc = proc->p_reader) != NULL) {
754		sp = auclnt_input_stream(sc->s_client);
755
756		info->record.sample_rate = auclnt_get_rate(sp);
757		info->record.channels = auclnt_get_channels(sp);
758		sun_decompose_format(&info->record, auclnt_get_format(sp));
759
760		info->record.gain =
761		    (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100;
762		info->record.pause = auclnt_is_paused(sp);
763		info->record.active = !info->record.pause;
764		info->record.samples = auclnt_get_samples(sp);
765		info->record.error = auclnt_get_errors(sp) ? B_TRUE : B_FALSE;
766	}
767}
768
769static void
770sioc_getinfo(sioc_t *ip)
771{
772	sclient_t	*sc = ip->i_sc;
773	sproc_t		*proc = sc->s_proc;
774	int		rv;
775
776	switch (ip->i_step) {
777	case 0:
778		if ((rv = sioc_alloc(ip, sizeof (audio_info_t))) != 0) {
779			sioc_error(ip, rv);
780			break;
781		}
782
783		mutex_enter(&sc->s_sdev->d_mx);
784		sproc_update(proc);
785		mutex_exit(&sc->s_sdev->d_mx);
786
787		bcopy(&proc->p_info, ip->i_data, sizeof (audio_info_t));
788		sioc_copyout(ip, sizeof (audio_info_t));
789		break;
790	case 1:
791		sioc_success(ip);
792		break;
793	}
794
795	ip->i_step++;
796	sioc_finish(ip);
797}
798
799#define	CHANGED(new, old, field)			\
800	((new->field != ((uint32_t)~0)) && (new->field != old->field))
801#define	CHANGED8(new, old, field)			\
802	((new->field != ((uint8_t)~0)) && (new->field != old->field))
803
804static int
805sun_setinfo(sclient_t *sc, audio_info_t *ninfo)
806{
807	sproc_t		*proc = sc->s_proc;
808	audio_info_t	*oinfo = &proc->p_info;
809	audio_prinfo_t	*npr;
810	audio_prinfo_t	*opr;
811
812	int		pfmt = AUDIO_FORMAT_NONE;
813	int		rfmt = AUDIO_FORMAT_NONE;
814
815	boolean_t	reader;
816	boolean_t	writer;
817	boolean_t	isctl;
818	audio_stream_t	*sp;
819	int		rv;
820
821	if (auclnt_get_minor_type(sc->s_client) == AUDIO_MINOR_DEVAUDIOCTL) {
822		/* control node can do both read and write fields */
823		isctl = B_TRUE;
824		reader = B_TRUE;
825		writer = B_TRUE;
826	} else {
827		isctl = B_FALSE;
828		writer = sc == proc->p_writer;
829		reader = sc == proc->p_reader;
830	}
831
832	/*
833	 * Start by validating settings.
834	 */
835	npr = &ninfo->play;
836	opr = &oinfo->play;
837
838	if (writer && CHANGED(npr, opr, sample_rate)) {
839		if ((isctl) ||
840		    (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) {
841			return (EINVAL);
842		}
843	}
844	if (writer && CHANGED(npr, opr, channels)) {
845		if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) {
846			return (EINVAL);
847		}
848	}
849	if (writer &&
850	    (CHANGED(npr, opr, encoding) || CHANGED(npr, opr, precision))) {
851		if (npr->encoding == (uint32_t)~0)
852			npr->encoding = opr->encoding;
853		if (npr->precision == (uint32_t)~0)
854			npr->precision = opr->precision;
855		pfmt = sun_compose_format(npr);
856		if ((isctl) || (pfmt == AUDIO_FORMAT_NONE)) {
857			return (EINVAL);
858		}
859	}
860
861	/* play fields that anyone can modify */
862	if (CHANGED(npr, opr, gain)) {
863		if (npr->gain > AUDIO_MAX_GAIN) {
864			return (EINVAL);
865		}
866	}
867
868
869	npr = &ninfo->record;
870	opr = &oinfo->record;
871
872	if (reader && CHANGED(npr, opr, sample_rate)) {
873		if ((isctl) ||
874		    (npr->sample_rate < 5500) ||
875		    (npr->sample_rate > 48000)) {
876			return (EINVAL);
877		}
878	}
879	if (reader && CHANGED(npr, opr, channels)) {
880		if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) {
881			return (EINVAL);
882		}
883	}
884	if (reader &&
885	    (CHANGED(npr, opr, encoding) || CHANGED(npr, opr, precision))) {
886		if (npr->encoding == (uint32_t)~0)
887			npr->encoding = opr->encoding;
888		if (npr->precision == (uint32_t)~0)
889			npr->precision = opr->precision;
890		rfmt = sun_compose_format(npr);
891		if ((isctl) || (rfmt == AUDIO_FORMAT_NONE)) {
892			return (EINVAL);
893		}
894	}
895	if (reader && CHANGED(npr, opr, buffer_size)) {
896		if (isctl) {
897			return (EINVAL);
898		}
899		/* make sure we can support 16-bit stereo samples */
900		if ((npr->buffer_size % 4) != 0) {
901			npr->buffer_size = (npr->buffer_size + 3) & ~3;
902		}
903		/* limit the maximum buffer size somewhat */
904		if (npr->buffer_size > 16384) {
905			npr->buffer_size = 16384;
906		}
907	}
908
909	/* record fields that anyone can modify */
910	if (CHANGED(npr, opr, gain)) {
911		if (npr->gain > AUDIO_MAX_GAIN) {
912			return (EINVAL);
913		}
914	}
915
916	/*
917	 * Now apply the changes.
918	 */
919	if (proc->p_writer != NULL) {
920		sp = auclnt_output_stream(proc->p_writer->s_client);
921		npr = &ninfo->play;
922		opr = &oinfo->play;
923
924		if (CHANGED(npr, opr, sample_rate)) {
925			rv = auclnt_set_rate(sp, npr->sample_rate);
926			if (rv != 0)
927				return (rv);
928		}
929		if (CHANGED(npr, opr, channels)) {
930			rv = auclnt_set_channels(sp, npr->channels);
931			if (rv != 0)
932				return (rv);
933		}
934		if (pfmt != AUDIO_FORMAT_NONE) {
935			rv = auclnt_set_format(sp, pfmt);
936			if (rv != 0)
937				return (rv);
938		}
939		if (CHANGED(npr, opr, samples)) {
940			auclnt_set_samples(sp, npr->samples);
941		}
942		if (CHANGED(npr, opr, eof)) {
943			/*
944			 * This ugly special case code is required to
945			 * prevent problems with realaudio.
946			 */
947			if (npr->eof == 0) {
948				sun_clear_eof(proc->p_writer);
949			}
950			opr->eof = npr->eof;
951		}
952		if (CHANGED8(npr, opr, pause)) {
953			if (npr->pause) {
954				auclnt_set_paused(sp);
955			} else {
956				auclnt_clear_paused(sp);
957				/* qenable to start up the playback */
958				qenable(proc->p_writer->s_wq);
959			}
960		}
961		if (CHANGED8(npr, opr, waiting) && (npr->waiting)) {
962			opr->waiting = npr->waiting;
963		}
964		if (CHANGED8(npr, opr, error)) {
965			auclnt_set_errors(sp, npr->error);
966		}
967		if (CHANGED(npr, opr, gain)) {
968			auclnt_set_gain(sp, (npr->gain * 100) / AUDIO_MAX_GAIN);
969		}
970		if (CHANGED8(ninfo, oinfo, output_muted)) {
971			auclnt_set_muted(sp, ninfo->output_muted);
972		}
973		if (CHANGED(npr, opr, buffer_size)) {
974			/*
975			 * No checks on the buffer size are performed
976			 * for play side.  The value of the buffer size
977			 * is meaningless for play side anyway.
978			 */
979			opr->buffer_size = npr->buffer_size;
980		}
981	} else {
982		/* these vaalues are preserved even if /dev/audio not open */
983		if (CHANGED(npr, opr, gain)) {
984			opr->gain = npr->gain;
985		}
986		if (CHANGED8(ninfo, oinfo, output_muted)) {
987			oinfo->output_muted = ninfo->output_muted;
988		}
989	}
990
991	if (proc->p_reader != NULL) {
992		sp = auclnt_input_stream(proc->p_reader->s_client);
993		npr = &ninfo->record;
994		opr = &oinfo->record;
995
996		if (CHANGED(npr, opr, sample_rate)) {
997			rv = auclnt_set_rate(sp, npr->sample_rate);
998			if (rv != 0)
999				return (rv);
1000		}
1001		if (CHANGED(npr, opr, channels)) {
1002			rv = auclnt_set_channels(sp, npr->channels);
1003			if (rv != 0)
1004				return (rv);
1005		}
1006		if (rfmt != AUDIO_FORMAT_NONE) {
1007			rv = auclnt_set_format(sp, rfmt);
1008			if (rv != 0)
1009				return (rv);
1010		}
1011		if (CHANGED(npr, opr, samples)) {
1012			auclnt_set_samples(sp, npr->samples);
1013		}
1014		if (CHANGED(npr, opr, eof)) {
1015			opr->eof = npr->eof;
1016		}
1017		if (CHANGED8(npr, opr, pause)) {
1018			if (npr->pause) {
1019				auclnt_set_paused(sp);
1020			} else {
1021				auclnt_clear_paused(sp);
1022				auclnt_start(sp);
1023			}
1024		}
1025		if (CHANGED8(npr, opr, waiting) && (npr->waiting)) {
1026			opr->waiting = npr->waiting;
1027		}
1028		if (CHANGED8(npr, opr, error)) {
1029			auclnt_set_errors(sp, npr->error);
1030		}
1031		if (CHANGED(npr, opr, buffer_size)) {
1032			opr->buffer_size = npr->buffer_size;
1033		}
1034		if (CHANGED(npr, opr, gain)) {
1035			auclnt_set_gain(sp, (npr->gain * 100) / AUDIO_MAX_GAIN);
1036		}
1037	} else {
1038		/* these values are preserved even if /dev/audio not open */
1039		if (CHANGED(npr, opr, gain)) {
1040			opr->gain = npr->gain;
1041		}
1042	}
1043
1044	return (0);
1045}
1046
1047static void
1048sioc_setinfo(sioc_t *ip)
1049{
1050	int		rv;
1051	sclient_t	*sc = ip->i_sc;
1052	audio_info_t	*ninfo;
1053
1054	switch (ip->i_step) {
1055	case 0:
1056		sioc_copyin(ip, sizeof (audio_info_t));
1057		break;
1058
1059	case 1:
1060		ninfo = (audio_info_t *)ip->i_data;
1061
1062		mutex_enter(&sc->s_sdev->d_mx);
1063		rv = sun_setinfo(ip->i_sc, ninfo);
1064
1065		if (rv != 0) {
1066			sioc_error(ip, rv);
1067		} else {
1068			sproc_update(sc->s_proc);
1069
1070			bcopy(&sc->s_proc->p_info, ninfo, sizeof (*ninfo));
1071			sioc_copyout(ip, sizeof (audio_info_t));
1072		}
1073		mutex_exit(&sc->s_sdev->d_mx);
1074		break;
1075
1076	case 2:
1077		sioc_success(ip);
1078		break;
1079	}
1080
1081	ip->i_step++;
1082	sioc_finish(ip);
1083}
1084
1085static void
1086sioc_getdev(sioc_t *ip)
1087{
1088	int		rv;
1089	sclient_t	*sc = ip->i_sc;
1090	audio_client_t	*c = sc->s_client;
1091	audio_dev_t	*d = auclnt_get_dev(c);
1092
1093	switch (ip->i_step) {
1094	case 0:
1095		rv = sioc_alloc(ip, sizeof (audio_device_t));
1096		if (rv == 0) {
1097			audio_device_t *a = ip->i_data;
1098
1099			(void) snprintf(a->name, sizeof (a->name),
1100			    "SUNW,%s", auclnt_get_dev_name(d));
1101			(void) strlcpy(a->config,
1102			    auclnt_get_dev_description(d), sizeof (a->config));
1103			(void) strlcpy(a->version,
1104			    auclnt_get_dev_version(d),  sizeof (a->version));
1105			sioc_copyout(ip, sizeof (*a));
1106		} else {
1107			sioc_error(ip, rv);
1108		}
1109		break;
1110
1111	case 1:
1112		sioc_success(ip);
1113		break;
1114	}
1115
1116	ip->i_step++;
1117	sioc_finish(ip);
1118}
1119
1120static void
1121sunstr_ioctl(sioc_t *ip)
1122{
1123	switch (ip->i_cmd) {
1124	case AUDIO_GETINFO:
1125		sioc_getinfo(ip);
1126		break;
1127
1128	case AUDIO_SETINFO:
1129		sioc_setinfo(ip);
1130		break;
1131
1132	case AUDIO_GETDEV:
1133		sioc_getdev(ip);
1134		break;
1135
1136	case AUDIO_DIAG_LOOPBACK:
1137		/* we don't support this one */
1138		sioc_error(ip, ENOTTY);
1139		sioc_finish(ip);
1140		break;
1141
1142	case AUDIO_MIXERCTL_GET_MODE:
1143	case AUDIO_MIXERCTL_SET_MODE:
1144	case AUDIO_MIXERCTL_GET_CHINFO:
1145	case AUDIO_MIXERCTL_SET_CHINFO:
1146	case AUDIO_MIXERCTL_GETINFO:
1147	case AUDIO_MIXERCTL_SETINFO:
1148	case AUDIO_GET_NUM_CHS:
1149	case AUDIO_GET_CH_NUMBER:
1150	case AUDIO_GET_CH_TYPE:
1151	case AUDIO_MIXER_SINGLE_OPEN:
1152	case AUDIO_MIXER_MULTIPLE_OPEN:
1153	case AUDIO_MIXER_GET_SAMPLE_RATES:
1154	default:
1155		sioc_error(ip, EINVAL);
1156		sioc_finish(ip);
1157		break;
1158	}
1159}
1160
1161static int
1162sun_sigpoll(audio_client_t *c, void *arg)
1163{
1164	sproc_t		*proc = arg;
1165	sclient_t	*sc;
1166
1167	if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) {
1168		sc = auclnt_get_private(c);
1169		/* we only need to notify peers in our own process */
1170		if ((sc != NULL) && (sc->s_proc == proc)) {
1171			(void) putnextctl1(sc->s_rq, M_PCSIG, SIGPOLL);
1172		}
1173	}
1174	return (AUDIO_WALK_CONTINUE);
1175}
1176
1177static void
1178sun_drain(audio_client_t *c)
1179{
1180	sclient_t	*sc = auclnt_get_private(c);
1181	mblk_t		*mplist, *mp;
1182
1183	mutex_enter(&sc->s_lock);
1184	mplist = sc->s_draining;
1185	sc->s_draining = NULL;
1186	mutex_exit(&sc->s_lock);
1187
1188	while ((mp = mplist) != NULL) {
1189		mplist = mp->b_next;
1190		mp->b_next = NULL;
1191		miocack(sc->s_wq, mp, 0, 0);
1192	}
1193}
1194
1195static void
1196sun_output(audio_client_t *c)
1197{
1198	sclient_t	*sc = auclnt_get_private(c);
1199	sproc_t		*proc = sc->s_proc;
1200	uint64_t	tail;
1201	struct eofcnt	*eof;
1202	int		eofs = 0;
1203
1204	tail = auclnt_get_tail(auclnt_output_stream(c));
1205
1206	/* get more data! (do this early) */
1207	qenable(sc->s_wq);
1208
1209	mutex_enter(&sc->s_lock);
1210	while (((eof = list_head(&sc->s_eofcnt)) != NULL) &&
1211	    (eof->tail < tail)) {
1212		list_remove(&sc->s_eofcnt, eof);
1213		kmem_free(eof, sizeof (*eof));
1214		eofs++;
1215	}
1216	proc->p_info.play.eof += eofs;
1217	mutex_exit(&sc->s_lock);
1218
1219	if (eofs) {
1220		auclnt_dev_walk_clients(auclnt_get_dev(c),
1221		    sun_sigpoll, proc);
1222	}
1223}
1224
1225static void
1226sun_input(audio_client_t *c)
1227{
1228	sun_sendup(c);
1229}
1230
1231static int
1232sun_create_minors(audio_dev_t *adev, void *notused)
1233{
1234	char		path[MAXPATHLEN];
1235	minor_t		minor;
1236	int		inst;
1237	int		index;
1238	const char	*driver;
1239	unsigned	cap;
1240
1241	_NOTE(ARGUNUSED(notused));
1242
1243	ASSERT(mutex_owned(&sdev_lock));
1244
1245	/* don't create device nodes for sndstat device */
1246	cap = auclnt_get_dev_capab(adev);
1247	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
1248		return (AUDIO_WALK_CONTINUE);
1249	}
1250
1251	index = auclnt_get_dev_index(adev);
1252	inst = auclnt_get_dev_instance(adev);
1253	driver = auclnt_get_dev_driver(adev);
1254
1255	if (sdev_dip != NULL) {
1256
1257		minor = AUDIO_MKMN(index, AUDIO_MINOR_DEVAUDIO);
1258		(void) snprintf(path, sizeof (path), "sound,%s,audio%d",
1259		    driver, inst);
1260		(void) ddi_create_minor_node(sdev_dip, path, S_IFCHR, minor,
1261		    DDI_NT_AUDIO, 0);
1262
1263		minor = AUDIO_MKMN(index, AUDIO_MINOR_DEVAUDIOCTL);
1264		(void) snprintf(path, sizeof (path), "sound,%s,audioctl%d",
1265		    driver, inst);
1266		(void) ddi_create_minor_node(sdev_dip, path, S_IFCHR, minor,
1267		    DDI_NT_AUDIO, 0);
1268	}
1269
1270	return (AUDIO_WALK_CONTINUE);
1271}
1272
1273static int
1274sun_remove_minors(audio_dev_t *adev, void *notused)
1275{
1276	char		path[MAXPATHLEN];
1277	int		inst;
1278	const char	*driver;
1279	unsigned	cap;
1280
1281	_NOTE(ARGUNUSED(notused));
1282
1283	ASSERT(mutex_owned(&sdev_lock));
1284
1285	cap = auclnt_get_dev_capab(adev);
1286	/* if not a play or record device, don't bother creating minors */
1287	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
1288		return (AUDIO_WALK_CONTINUE);
1289	}
1290
1291	inst = auclnt_get_dev_instance(adev);
1292	driver = auclnt_get_dev_driver(adev);
1293
1294	if (sdev_dip != NULL) {
1295
1296		(void) snprintf(path, sizeof (path), "sound,%s,audio%d",
1297		    driver, inst);
1298		ddi_remove_minor_node(sdev_dip, path);
1299
1300		(void) snprintf(path, sizeof (path), "sound,%s,audioctl%d",
1301		    driver, inst);
1302		ddi_remove_minor_node(sdev_dip, path);
1303	}
1304
1305	return (AUDIO_WALK_CONTINUE);
1306}
1307
1308static void *
1309sun_dev_init(audio_dev_t *adev)
1310{
1311	sdev_t		*sdev;
1312	unsigned	cap;
1313
1314	cap = auclnt_get_dev_capab(adev);
1315	/* if not a play or record device, don't bother initializing it */
1316	if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
1317		return (NULL);
1318	}
1319
1320	sdev = kmem_zalloc(sizeof (*sdev), KM_SLEEP);
1321	sdev->d_dev = adev;
1322	mutex_init(&sdev->d_mx, NULL, MUTEX_DRIVER, NULL);
1323	cv_init(&sdev->d_cv, NULL, CV_DRIVER, NULL);
1324	list_create(&sdev->d_procs, sizeof (struct sproc),
1325	    offsetof(struct sproc, p_linkage));
1326
1327	mutex_enter(&sdev_lock);
1328	(void) sun_create_minors(adev, NULL);
1329	mutex_exit(&sdev_lock);
1330
1331	return (sdev);
1332}
1333
1334static void
1335sun_dev_fini(void *arg)
1336{
1337	sdev_t	*sdev = arg;
1338
1339	if (sdev != NULL) {
1340
1341		/* remove minor nodes */
1342		mutex_enter(&sdev_lock);
1343		(void) sun_remove_minors(sdev->d_dev, NULL);
1344		mutex_exit(&sdev_lock);
1345
1346		mutex_destroy(&sdev->d_mx);
1347		cv_destroy(&sdev->d_cv);
1348		list_destroy(&sdev->d_procs);
1349		kmem_free(sdev, sizeof (*sdev));
1350	}
1351}
1352
1353static struct audio_client_ops sun_ops = {
1354	"internal,audio",
1355	sun_dev_init,
1356	sun_dev_fini,
1357	sun_open,
1358	sun_close,
1359	NULL,	/* read */
1360	NULL,	/* write */
1361	NULL,	/* ioctl */
1362	NULL,	/* chpoll */
1363	NULL,	/* mmap */
1364	sun_input,
1365	sun_output,
1366	NULL,	/* notify */
1367	sun_drain,
1368};
1369
1370static struct audio_client_ops sunctl_ops = {
1371	"internal,audioctl",
1372	NULL,	/* dev_init */
1373	NULL,	/* dev_fini */
1374	sun_open,
1375	sun_close,
1376	NULL,	/* read */
1377	NULL,	/* write */
1378	NULL,	/* ioctl */
1379	NULL,	/* chpoll */
1380	NULL,	/* mmap */
1381	NULL,	/* output */
1382	NULL,	/* input */
1383	NULL,	/* notify */
1384	NULL,	/* drain */
1385};
1386
1387void
1388auimpl_sun_init(void)
1389{
1390	mutex_init(&sdev_lock, NULL, MUTEX_DRIVER, NULL);
1391	sdev_dip = NULL;
1392	auclnt_register_ops(AUDIO_MINOR_DEVAUDIO, &sun_ops);
1393	auclnt_register_ops(AUDIO_MINOR_DEVAUDIOCTL, &sunctl_ops);
1394}
1395
1396/*
1397 * This is the operations entry points that are streams specific...
1398 * We map "instance" numbers.
1399 */
1400
1401static int
1402sunstr_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *cr)
1403{
1404	int			rv;
1405	minor_t			minor;
1406	minor_t			index;
1407	minor_t			type;
1408	dev_t			physdev;
1409	ldi_ident_t		lid;
1410	ldi_handle_t		lh = NULL;
1411	audio_client_t		*c = NULL;
1412	sclient_t		*sc = NULL;
1413	audio_dev_t		*adev;
1414	unsigned		fmt;
1415	int			oflag;
1416	boolean_t		isopen = B_FALSE;
1417
1418	if (sflag != 0) {
1419		/* no direct clone or module opens */
1420		return (EINVAL);
1421	}
1422
1423	/*
1424	 * NB: We reuse the partitioning that the core framework is
1425	 * using for instance numbering.  This does mean that we are
1426	 * limited to at most AUDIO_MN_INST_MASK devices, but this
1427	 * number is sufficiently large (8192) that not to be a concern.
1428	 */
1429
1430	minor = getminor(*devp);
1431	index = (minor >> AUDIO_MN_INST_SHIFT) & AUDIO_MN_INST_MASK;
1432	type = (minor >> AUDIO_MN_TYPE_SHIFT) & AUDIO_MN_TYPE_MASK;
1433
1434	/* can't directly open a cloned node! */
1435	if (minor & AUDIO_MN_CLONE_MASK) {
1436		return (ENXIO);
1437	}
1438
1439	switch (type) {
1440	case AUDIO_MINOR_DEVAUDIOCTL:
1441		fmt = AUDIO_FORMAT_NONE;
1442		oflag = flag & ~(FWRITE | FREAD);
1443		break;
1444	case AUDIO_MINOR_DEVAUDIO:
1445		fmt = AUDIO_FORMAT_PCM;
1446		oflag = flag;
1447		break;
1448	default:
1449		/* these minor types are not legal */
1450		return (ENXIO);
1451	}
1452
1453	/* look up and hold the matching audio device */
1454	adev = auclnt_hold_dev_by_index(index);
1455	if (adev == NULL) {
1456		return (ENXIO);
1457	}
1458	/* find the matching physical devt */
1459	physdev = makedevice(ddi_driver_major(auclnt_get_dev_devinfo(adev)),
1460	    AUDIO_MKMN(auclnt_get_dev_instance(adev), type));
1461
1462	if ((rv = ldi_ident_from_stream(rq, &lid)) == 0) {
1463		rv = ldi_open_by_dev(&physdev, OTYP_CHR, flag, cr, &lh, lid);
1464	}
1465
1466	/* ldi open is done, lh holds device, and we can release our hold */
1467	auclnt_release_dev(adev);
1468
1469	if (rv != 0) {
1470		goto fail;
1471	}
1472	/* phys layer clones a device for us */
1473	ASSERT((getminor(physdev) & AUDIO_MN_CLONE_MASK) != 0);
1474
1475	c = auclnt_hold_by_devt(physdev);
1476	ASSERT(c != NULL);
1477	if ((rv = auclnt_open(c, fmt, oflag)) != 0) {
1478		goto fail;
1479	}
1480	isopen = B_TRUE;
1481
1482	if ((rv = sproc_hold(c, oflag)) != 0) {
1483		goto fail;
1484	}
1485
1486	sc = auclnt_get_private(c);
1487	WR(rq)->q_ptr = rq->q_ptr = sc;
1488	sc->s_lh = lh;
1489	sc->s_rq = rq;
1490	sc->s_wq = WR(rq);
1491
1492	/* start up the input */
1493	if (oflag & FREAD) {
1494		auclnt_start(auclnt_input_stream(c));
1495	}
1496
1497	auclnt_release(c);
1498
1499	/* we just reuse same minor number that phys layer used */
1500	*devp = makedevice(getmajor(*devp), getminor(physdev));
1501
1502	qprocson(rq);
1503
1504	return (0);
1505
1506fail:
1507	if (sc != NULL) {
1508		sproc_release(sc);
1509	}
1510	if (isopen) {
1511		auclnt_close(c);
1512	}
1513	if (lh != NULL) {
1514		auclnt_release(c);
1515		(void) ldi_close(lh, flag, cr);
1516	}
1517
1518	return (rv);
1519}
1520
1521static int
1522sunstr_close(queue_t *rq, int flag, cred_t *cr)
1523{
1524	sclient_t	*sc;
1525	audio_client_t	*c;
1526	int		rv;
1527
1528	sc = rq->q_ptr;
1529	c = sc->s_client;
1530
1531	if ((auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIO) &&
1532	    (ddi_can_receive_sig() || (ddi_get_pid() == 0))) {
1533		rv = auclnt_drain(c);
1534	}
1535
1536	auclnt_stop(auclnt_output_stream(c));
1537	auclnt_stop(auclnt_input_stream(c));
1538
1539	auclnt_close(c);
1540
1541	qprocsoff(rq);
1542
1543	(void) ldi_close(sc->s_lh, flag, cr);
1544
1545	sproc_release(sc);
1546
1547	return (rv);
1548}
1549
1550static void
1551sunstr_miocdata(sclient_t *sc, mblk_t *mp)
1552{
1553	struct copyresp		*csp;
1554	sioc_t			*ip;
1555	mblk_t			*bcont;
1556
1557	csp = (void *)mp->b_rptr;
1558
1559	/*
1560	 * If no state, then something "bad" has happened.
1561	 */
1562	if (((ip = (void *)csp->cp_private) == NULL) || (ip->i_sc != sc)) {
1563		miocnak(sc->s_wq, mp, 0, EFAULT);
1564		return;
1565	}
1566
1567	/*
1568	 * If we failed to transfer data to/from userland, then we are
1569	 * done.  (Stream head will have notified userland.)
1570	 */
1571	if (csp->cp_rval != 0) {
1572		ip->i_state = FINI;
1573		ip->i_mp = mp;
1574		sioc_finish(ip);
1575		return;
1576	}
1577
1578	/*
1579	 * Buffer area for ioctl is attached to chain.
1580	 * For an ioctl that didn't have any data to copyin,
1581	 * we might need to allocate a new buffer area.
1582	 */
1583	bcont = mp->b_cont;
1584	ip->i_bcont = bcont;
1585	mp->b_cont = NULL;
1586
1587	if (bcont != NULL) {
1588		ip->i_data = bcont->b_rptr;
1589	}
1590
1591	/*
1592	 * Meaty part of data processing.
1593	 */
1594	ip->i_state = IOCTL;
1595	ip->i_mp = mp;
1596
1597	/* now, call the handler ioctl */
1598	sunstr_ioctl(ip);
1599}
1600
1601static void
1602sunstr_mioctl(sclient_t *sc, mblk_t *mp)
1603{
1604	struct iocblk	*iocp = (void *)mp->b_rptr;
1605	sioc_t		*ip;
1606
1607	/* BSD legacy here: we only support transparent ioctls */
1608	if (iocp->ioc_count != TRANSPARENT) {
1609		miocnak(sc->s_wq, mp, 0, EINVAL);
1610		return;
1611	}
1612
1613	ip = kmem_zalloc(sizeof (*ip), KM_NOSLEEP);
1614	if (ip == NULL) {
1615		miocnak(sc->s_wq, mp, 0, ENOMEM);
1616		return;
1617	}
1618
1619	/* make sure everything is setup in case we need to do copyin/out */
1620	ip->i_sc = sc;
1621	ip->i_model = iocp->ioc_flag;
1622	ip->i_cmd = iocp->ioc_cmd;
1623	ip->i_addr = *(caddr_t *)(void *)mp->b_cont->b_rptr;
1624	ip->i_state = IOCTL;
1625	ip->i_mp = mp;
1626	freemsg(mp->b_cont);
1627	mp->b_cont = NULL;
1628
1629	/* now, call the handler ioctl */
1630	sunstr_ioctl(ip);
1631}
1632
1633static int
1634sunstr_wput(queue_t *wq, mblk_t *mp)
1635{
1636	sclient_t	*sc = wq->q_ptr;
1637	struct iocblk	*iocp;
1638
1639	switch (DB_TYPE(mp)) {
1640	case M_IOCTL:
1641		/* Drain ioctl needs to be handled on the service queue */
1642		iocp = (void *)mp->b_rptr;
1643		if (iocp->ioc_cmd == AUDIO_DRAIN) {
1644			if (auclnt_get_minor_type(sc->s_client) ==
1645			    AUDIO_MINOR_DEVAUDIO) {
1646				(void) putq(wq, mp);
1647			} else {
1648				miocnak(wq, mp, 0, EINVAL);
1649			}
1650		} else {
1651			sunstr_mioctl(sc, mp);
1652		}
1653		break;
1654
1655	case M_IOCDATA:
1656		sunstr_miocdata(sc, mp);
1657		break;
1658
1659	case M_FLUSH:
1660		/*
1661		 * We don't flush the engine.  The reason is that
1662		 * other streams might be using the engine.  This is
1663		 * fundamentally no different from the case where the
1664		 * engine hardware has data buffered in an
1665		 * inaccessible FIFO.
1666		 *
1667		 * Clients that want to ensure no more data is coming
1668		 * should stop the stream before flushing.
1669		 */
1670		if (*mp->b_rptr & FLUSHW) {
1671			flushq(wq, FLUSHALL);
1672			auclnt_flush(auclnt_output_stream(sc->s_client));
1673			*mp->b_rptr &= ~FLUSHW;
1674		}
1675		if (*mp->b_rptr & FLUSHR) {
1676			flushq(RD(wq), FLUSHALL);
1677			auclnt_flush(auclnt_input_stream(sc->s_client));
1678			qreply(wq, mp);
1679		} else {
1680			freemsg(mp);
1681		}
1682		break;
1683
1684	case M_DATA:
1685		/*
1686		 * If we don't have an engine, then we can't accept
1687		 * write() data.  audio(7i) says we just ignore it,
1688		 * so we toss it.
1689		 */
1690		if (auclnt_get_minor_type(sc->s_client) !=
1691		    AUDIO_MINOR_DEVAUDIO) {
1692			freemsg(mp);
1693		} else {
1694			/*
1695			 * Defer processing to the queue.  This keeps
1696			 * the data ordered, and allows the wsrv
1697			 * routine to gather multiple mblks at once.
1698			 */
1699			if (mp->b_cont != NULL) {
1700
1701				/*
1702				 * If we need to pullup, do it here to
1703				 * simplify the rest of the processing
1704				 * later.  This should rarely (if
1705				 * ever) be necessary.
1706				 */
1707				mblk_t	*nmp;
1708
1709				if ((nmp = msgpullup(mp, -1)) == NULL) {
1710					freemsg(mp);
1711				} else {
1712					freemsg(mp);
1713					(void) putq(wq, nmp);
1714				}
1715			} else {
1716				(void) putq(wq, mp);
1717			}
1718		}
1719		break;
1720
1721	default:
1722		freemsg(mp);
1723		break;
1724	}
1725	return (0);
1726}
1727
1728static int
1729sunstr_wsrv(queue_t *wq)
1730{
1731	sclient_t	*sc = wq->q_ptr;
1732	audio_client_t	*c = sc->s_client;
1733	audio_stream_t	*sp;
1734	mblk_t		*mp;
1735	unsigned	framesz;
1736
1737	sp = auclnt_output_stream(c);
1738
1739	framesz = auclnt_get_framesz(sp);
1740
1741	while ((mp = getq(wq)) != NULL) {
1742
1743		unsigned	count;
1744
1745		/* got a message */
1746
1747		/* if its a drain ioctl, we need to process it here */
1748		if (DB_TYPE(mp) == M_IOCTL) {
1749			ASSERT((*(int *)(void *)mp->b_rptr) == AUDIO_DRAIN);
1750			mutex_enter(&sc->s_lock);
1751			mp->b_next = sc->s_draining;
1752			sc->s_draining = mp;
1753			mutex_exit(&sc->s_lock);
1754
1755			if (auclnt_start_drain(c) != 0) {
1756				sun_drain(c);
1757			}
1758			continue;
1759		}
1760
1761		ASSERT(DB_TYPE(mp) == M_DATA);
1762
1763		/*
1764		 * Empty mblk require special handling, since they
1765		 * indicate EOF.  We treat them separate from the main
1766		 * processing loop.
1767		 */
1768		if (MBLKL(mp) == 0) {
1769			struct eofcnt	*eof;
1770
1771			eof = kmem_zalloc(sizeof (*eof), KM_NOSLEEP);
1772			if (eof != NULL) {
1773				eof->tail = auclnt_get_head(sp);
1774				mutex_enter(&sc->s_lock);
1775				list_insert_tail(&sc->s_eofcnt, eof);
1776				mutex_exit(&sc->s_lock);
1777			}
1778			freemsg(mp);
1779			continue;
1780		}
1781
1782		count = auclnt_produce_data(sp, (caddr_t)mp->b_rptr,
1783		    MBLKL(mp) / framesz);
1784
1785		mp->b_rptr += count * framesz;
1786
1787		if (MBLKL(mp) >= framesz) {
1788			(void) putbq(wq, mp);
1789			break;
1790		} else {
1791			freemsg(mp);
1792		}
1793	}
1794
1795	/* if the stream isn't running yet, start it up */
1796	if (!auclnt_is_paused(sp))
1797		auclnt_start(sp);
1798
1799	return (0);
1800}
1801
1802static int
1803sunstr_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1804{
1805	if ((cmd != DDI_ATTACH) || (dip == NULL)) {
1806		return (DDI_FAILURE);
1807	}
1808	if (ddi_get_instance(dip) != 0) {
1809		return (DDI_FAILURE);
1810	}
1811
1812	mutex_enter(&sdev_lock);
1813	sdev_dip = dip;
1814	auclnt_walk_devs(sun_create_minors, NULL);
1815	mutex_exit(&sdev_lock);
1816	ddi_report_dev(dip);
1817
1818	return (0);
1819}
1820
1821static int
1822sunstr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1823{
1824	if ((cmd != DDI_DETACH) || (dip == NULL)) {
1825		return (DDI_FAILURE);
1826	}
1827	if (ddi_get_instance(dip) != 0) {
1828		return (DDI_FAILURE);
1829	}
1830
1831	mutex_enter(&sdev_lock);
1832	/* remove all minors */
1833	auclnt_walk_devs(sun_remove_minors, NULL);
1834	sdev_dip = NULL;
1835	mutex_exit(&sdev_lock);
1836
1837	return (0);
1838}
1839
1840static int
1841sunstr_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1842{
1843	int		error;
1844
1845	_NOTE(ARGUNUSED(dip));
1846	_NOTE(ARGUNUSED(arg));
1847
1848	switch (cmd) {
1849	case DDI_INFO_DEVT2DEVINFO:
1850		*result = sdev_dip;
1851		error = DDI_SUCCESS;
1852		break;
1853	case DDI_INFO_DEVT2INSTANCE:
1854		*result = 0;
1855		error = DDI_SUCCESS;
1856		break;
1857	default:
1858		*result = NULL;
1859		error = DDI_FAILURE;
1860	}
1861	return (error);
1862}
1863
1864static struct module_info sunstr_minfo = {
1865	0,		/* used for strlog(1M) only, which we don't use */
1866	"austr",
1867	0,		/* min pkt size */
1868	2048,		/* max pkt size */
1869	65536,		/* hi water */
1870	32768,		/* lo water */
1871};
1872
1873static struct qinit sunstr_rqinit = {
1874	NULL,		/* qi_putp */
1875	NULL,		/* qi_srvp */
1876	sunstr_open,	/* qi_qopen */
1877	sunstr_close,	/* qi_qclose */
1878	NULL,		/* qi_qadmin */
1879	&sunstr_minfo,	/* qi_minfo */
1880	NULL,		/* qi_mstat */
1881};
1882
1883static struct qinit sunstr_wqinit = {
1884	sunstr_wput,	/* qi_putp */
1885	sunstr_wsrv,	/* qi_srvp */
1886	NULL,		/* qi_qopen */
1887	NULL,		/* qi_qclose */
1888	NULL,		/* qi_qadmin */
1889	&sunstr_minfo,	/* qi_minfo */
1890	NULL,		/* qi_mstat */
1891};
1892
1893static struct streamtab sunstr_strtab = {
1894	&sunstr_rqinit,
1895	&sunstr_wqinit,
1896	NULL,
1897	NULL
1898};
1899
1900struct cb_ops sunstr_cb_ops = {
1901	nodev,		/* open */
1902	nodev,		/* close */
1903	nodev,		/* strategy */
1904	nodev,		/* print */
1905	nodev,		/* dump */
1906	nodev,		/* read */
1907	nodev,		/* write */
1908	nodev,		/* ioctl */
1909	nodev,		/* devmap */
1910	nodev,		/* mmap */
1911	nodev,		/* segmap */
1912	nochpoll,	/* chpoll */
1913	ddi_prop_op,	/* prop_op */
1914	&sunstr_strtab,	/* str */
1915	D_MP,		/* flag */
1916	CB_REV, 	/* rev */
1917	nodev,		/* aread */
1918	nodev,		/* awrite */
1919};
1920
1921static struct dev_ops sunstr_dev_ops = {
1922	DEVO_REV,		/* rev */
1923	0,			/* refcnt */
1924	sunstr_getinfo,		/* getinfo */
1925	nulldev,		/* identify */
1926	nulldev,		/* probe */
1927	sunstr_attach,		/* attach */
1928	sunstr_detach,		/* detach */
1929	nodev,			/* reset */
1930	&sunstr_cb_ops,		/* cb_ops */
1931	NULL,			/* bus_ops */
1932	NULL,			/* power */
1933};
1934
1935static struct modldrv sunstr_modldrv = {
1936	&mod_driverops,
1937	"Audio Streams Support",
1938	&sunstr_dev_ops,
1939};
1940
1941static struct modlinkage sunstr_modlinkage = {
1942	MODREV_1,			/* MODREV_1 indicated by manual */
1943	&sunstr_modldrv,
1944	NULL
1945};
1946
1947int
1948sunstr_init(void)
1949{
1950	/*
1951	 * NB: This *must* be called after the "audio" module's
1952	 * _init routine has called auimpl_sun_init().
1953	 */
1954	return (mod_install(&sunstr_modlinkage));
1955}
1956
1957int
1958sunstr_fini(void)
1959{
1960	return (mod_remove(&sunstr_modlinkage));
1961}
1962
1963int
1964sunstr_info(struct modinfo *modinfop)
1965{
1966	return (mod_info(&sunstr_modlinkage, modinfop));
1967}
1968