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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * Sun audio(4I) and mixer(4I) personality.
27 *
28 * There are some "undocumented" details of how legacy Sun audio
29 * interfaces work. The following "rules" were derived from reading the
30 * legacy Sun mixer code, and to the best of our knowledge are not
31 * documented elsewhere.
32 *
33 * - We create a "fake" audio device, which behaves like a classic
34 * exclusive audio device, for each PID, as determined during open(2).
35 *
36 * - Different processes don't interfere with each other. Even though
37 * they are running concurrently, they each think they have exclusive
38 * control over the audio device.
39 *
40 * - Read and write directions operate independent of each other. That
41 * is, a device open for reading won't intefere with a future open for
42 * writing, and vice versa. This is true even within the same process.
43 *
44 * - Because the virtualization is by PID, strange behavior may occur
45 * if a process tries to open an audio device at the same time it
46 * has already received a file descriptor from another process (such
47 * through inheritence via fork()).
48 *
49 * - The "fake" audio device has no control over physical settings.
50 * It sees only the software attenuation-based volumes for play and
51 * record, and has no support for alternate input or output ports or
52 * access to the monitoring features of the hardware.
53 *
54 * - Explicit notificaton signals (SIGPOLL) are only ever sent up the
55 * audioctl node -- never up a regular audio node. (The stream head
56 * may still issue SIGPOLL based on readability/writability of
57 * course.)
58 *
59 * - Corollary: processes that want asynch. notifications will open
60 * /dev/audioctl as well as /dev/audio.
61 *
62 * - We don't support the MIXER mode at all.
63 *
64 * - By corollary, a process is only allowed to open /dev/audio once
65 * (in each direction.)
66 *
67 * - Attempts to open /dev/audio in duplex mode (O_RDWR) fail (EBUSY)
68 * if the device cannot support duplex operation.
69 *
70 * - Attempts to open a device with FREAD set fail if the device is not
71 * capable of recording. (Likewise for FWRITE and playback.)
72 *
73 * - No data transfer is permitted for audioctl nodes. (No actual
74 * record or play.)
75 *
76 * - Sun audio does not support any formats other than linear and
77 * ULAW/ALAW. I.e. it will never support AC3 or other "opaque"
78 * streams which require special handling.
79 *
80 * - Sun audio only supports stereo or monophonic data streams.
81 */
82
83 #include <sys/types.h>
84 #include <sys/open.h>
85 #include <sys/errno.h>
86 #include <sys/audio.h>
87 #include <sys/mixer.h>
88 #include <sys/file.h>
89 #include <sys/stropts.h>
90 #include <sys/strsun.h>
91 #include <sys/sysmacros.h>
92 #include <sys/list.h>
93 #include <sys/note.h>
94 #include <sys/stat.h>
95 #include <sys/ddi.h>
96 #include <sys/sunddi.h>
97 #include "audio_client.h"
98
99 typedef struct daclient daclient_t;
100 typedef struct dadev dadev_t;
101 typedef struct daproc daproc_t;
102
103 /* common structure shared between both audioctl and audio nodes */
104 struct daclient {
105 daproc_t *dc_proc;
106 dadev_t *dc_dev;
107 audio_client_t *dc_client;
108 queue_t *dc_wq;
109 unsigned dc_eof;
110 list_t dc_eofcnt;
111 kmutex_t dc_lock;
112 mblk_t *dc_draining;
113 };
114
115 struct eofcnt {
116 list_node_t linkage;
117 uint64_t tail;
118 };
119
120 struct dadev {
121 audio_dev_t *d_dev;
122
123 list_t d_procs;
124 kmutex_t d_mx;
125 kcondvar_t d_cv;
126 };
127
128 struct daproc {
129 pid_t p_id;
130 struct audio_info p_info;
131 int p_refcnt;
132 int p_oflag;
133 list_node_t p_linkage;
134 dadev_t *p_dev;
135 audio_client_t *p_writer;
136 audio_client_t *p_reader;
137 };
138
139 int devaudio_proc_hold(audio_client_t *, int);
140 void devaudio_proc_release(audio_client_t *);
141 static void devaudio_proc_update(daproc_t *);
142
143
144 static int
devaudio_compose_format(audio_prinfo_t * prinfo)145 devaudio_compose_format(audio_prinfo_t *prinfo)
146 {
147 switch (prinfo->precision) {
148 case 8:
149 switch (prinfo->encoding) {
150 case AUDIO_ENCODING_ULAW:
151 return (AUDIO_FORMAT_ULAW);
152 case AUDIO_ENCODING_ALAW:
153 return (AUDIO_FORMAT_ALAW);
154 case AUDIO_ENCODING_LINEAR8:
155 return (AUDIO_FORMAT_U8);
156 case AUDIO_ENCODING_LINEAR:
157 return (AUDIO_FORMAT_S8);
158 }
159 break;
160 case 16:
161 if (prinfo->encoding == AUDIO_ENCODING_LINEAR)
162 return (AUDIO_FORMAT_S16_NE);
163 break;
164 case 32:
165 if (prinfo->encoding == AUDIO_ENCODING_LINEAR)
166 return (AUDIO_FORMAT_S32_NE);
167 break;
168 }
169 return (AUDIO_FORMAT_NONE);
170
171 }
172
173 static void
devaudio_decompose_format(audio_prinfo_t * prinfo,int afmt)174 devaudio_decompose_format(audio_prinfo_t *prinfo, int afmt)
175 {
176 int e, p;
177
178 /*
179 * N.B.: Even though some of the formats below can't be set by
180 * this personality, reporting them (using the closest match)
181 * allows this personality to roughly approximate settings for
182 * other streams. It would be incredibly poor form for any
183 * personality to modify the format settings for a different
184 * personality, so we don't worry about that case.
185 */
186
187 switch (afmt) {
188 case AUDIO_FORMAT_ULAW:
189 e = AUDIO_ENCODING_ULAW;
190 p = 8;
191 break;
192
193 case AUDIO_FORMAT_ALAW:
194 e = AUDIO_ENCODING_ALAW;
195 p = 8;
196 break;
197
198 case AUDIO_FORMAT_U8:
199 e = AUDIO_ENCODING_LINEAR8;
200 p = 8;
201 break;
202
203 case AUDIO_FORMAT_S8:
204 e = AUDIO_ENCODING_LINEAR;
205 p = 8;
206 break;
207
208 case AUDIO_FORMAT_S16_NE:
209 case AUDIO_FORMAT_S16_OE:
210 case AUDIO_FORMAT_U16_NE:
211 case AUDIO_FORMAT_U16_OE:
212 e = AUDIO_ENCODING_LINEAR;
213 p = 16;
214 break;
215
216 case AUDIO_FORMAT_S24_NE:
217 case AUDIO_FORMAT_S24_OE:
218 case AUDIO_FORMAT_S24_PACKED:
219 e = AUDIO_ENCODING_LINEAR;
220 p = 24;
221 break;
222
223 case AUDIO_FORMAT_S32_NE:
224 case AUDIO_FORMAT_S32_OE:
225 e = AUDIO_ENCODING_LINEAR;
226 p = 32;
227 break;
228
229 default:
230 /* all other formats (e.g. AC3) are uninterpreted */
231 e = AUDIO_ENCODING_NONE;
232 p = 32;
233 break;
234 }
235
236 prinfo->encoding = e;
237 prinfo->precision = p;
238 }
239
240 static daproc_t *
devaudio_proc_alloc(audio_client_t * c)241 devaudio_proc_alloc(audio_client_t *c)
242 {
243 audio_info_t *info;
244 audio_prinfo_t *prinfo;
245 uint32_t caps;
246 daproc_t *proc;
247
248 if ((proc = kmem_zalloc(sizeof (*proc), KM_NOSLEEP)) == NULL) {
249 return (NULL);
250 }
251 info = &proc->p_info;
252
253 /*
254 * audio(4I) says: Upon the initial open() of the audio
255 * device, the driver resets the data format of the device to
256 * the default state of 8-bit, 8Khz, mono u-Law data.
257 */
258 prinfo = &info->play;
259 prinfo->channels = 1;
260 prinfo->sample_rate = 8000;
261 prinfo->encoding = AUDIO_ENCODING_ULAW;
262 prinfo->precision = 8;
263 prinfo->gain = AUDIO_MAX_GAIN;
264 prinfo->balance = AUDIO_MID_BALANCE;
265 prinfo->buffer_size = 8192;
266 prinfo->pause = B_FALSE;
267 prinfo->waiting = B_FALSE;
268 prinfo->open = B_FALSE;
269 prinfo->active = B_FALSE;
270 prinfo->samples = 0;
271 prinfo->eof = 0;
272 prinfo->error = 0;
273 prinfo->minordev = 0;
274 prinfo->port = AUDIO_SPEAKER;
275 prinfo->avail_ports = AUDIO_SPEAKER;
276 prinfo->mod_ports = AUDIO_NONE;
277 prinfo->_xxx = 0;
278
279 prinfo = &info->record;
280 prinfo->channels = 1;
281 prinfo->sample_rate = 8000;
282 prinfo->encoding = AUDIO_ENCODING_ULAW;
283 prinfo->precision = 8;
284 prinfo->gain = AUDIO_MAX_GAIN;
285 prinfo->balance = AUDIO_MID_BALANCE;
286 prinfo->buffer_size = 8192;
287 prinfo->waiting = B_FALSE;
288 prinfo->open = B_FALSE;
289 prinfo->active = B_FALSE;
290 prinfo->samples = 0;
291 prinfo->eof = 0;
292 prinfo->error = 0;
293 prinfo->minordev = 0;
294 prinfo->port = AUDIO_MICROPHONE;
295 prinfo->avail_ports = AUDIO_MICROPHONE;
296 prinfo->mod_ports = AUDIO_MICROPHONE;
297
298 info->output_muted = B_FALSE;
299 /* pretend we don't have a software mixer - we don't support the API */
300 info->hw_features = 0;
301 info->sw_features = 0;
302 info->sw_features_enabled = 0;
303
304 caps = auclnt_get_dev_capab(auclnt_get_dev(c));
305 if (caps & AUDIO_CLIENT_CAP_PLAY)
306 info->hw_features |= AUDIO_HWFEATURE_PLAY;
307 if (caps & AUDIO_CLIENT_CAP_RECORD)
308 info->hw_features |= AUDIO_HWFEATURE_RECORD;
309 if (caps & AUDIO_CLIENT_CAP_DUPLEX)
310 info->hw_features |= AUDIO_HWFEATURE_DUPLEX;
311
312 return (proc);
313 }
314
315 static void
devaudio_proc_free(daproc_t * proc)316 devaudio_proc_free(daproc_t *proc)
317 {
318 kmem_free(proc, sizeof (*proc));
319 }
320
321 int
devaudio_proc_hold(audio_client_t * c,int oflag)322 devaudio_proc_hold(audio_client_t *c, int oflag)
323 {
324 pid_t pid;
325 daproc_t *proc;
326 dadev_t *dev;
327 daclient_t *dc;
328 list_t *l;
329 audio_dev_t *adev;
330 int rv;
331
332 adev = auclnt_get_dev(c);
333
334 /* first allocate and initialize the daclient private data */
335 if ((dc = kmem_zalloc(sizeof (*dc), KM_NOSLEEP)) == NULL) {
336 return (ENOMEM);
337 }
338
339 mutex_init(&dc->dc_lock, NULL, MUTEX_DRIVER, NULL);
340 list_create(&dc->dc_eofcnt, sizeof (struct eofcnt),
341 offsetof(struct eofcnt, linkage));
342 auclnt_set_private(c, dc);
343
344 dev = auclnt_get_dev_minor_data(adev, AUDIO_MINOR_DEVAUDIO);
345 l = &dev->d_procs;
346 pid = auclnt_get_pid(c);
347
348 /* set a couple of common fields */
349 dc->dc_client = c;
350 dc->dc_dev = dev;
351
352 mutex_enter(&dev->d_mx);
353 for (proc = list_head(l); proc != NULL; proc = list_next(l, proc)) {
354 if (proc->p_id == pid) {
355 proc->p_refcnt++;
356 break;
357 }
358 }
359 if (proc == NULL) {
360 if ((proc = devaudio_proc_alloc(c)) == NULL) {
361 rv = ENOMEM;
362 goto failed;
363 }
364 proc->p_refcnt = 1;
365 proc->p_id = pid;
366 proc->p_dev = dev;
367 list_insert_tail(l, proc);
368 }
369
370 while (proc->p_oflag & oflag) {
371
372 if (oflag & (FNDELAY|FNONBLOCK)) {
373 rv = EBUSY;
374 goto failed;
375 }
376 if (oflag & FWRITE)
377 proc->p_info.play.waiting++;
378 if (oflag & FREAD)
379 proc->p_info.record.waiting++;
380 if (cv_wait_sig(&dev->d_cv, &dev->d_mx) == 0) {
381 /* interrupted! */
382 if (oflag & FWRITE)
383 proc->p_info.play.waiting--;
384 if (oflag & FREAD)
385 proc->p_info.record.waiting--;
386 rv = EINTR;
387 goto failed;
388 }
389 if (oflag & FWRITE)
390 proc->p_info.play.waiting--;
391 if (oflag & FREAD)
392 proc->p_info.record.waiting--;
393 }
394
395 if (oflag & FWRITE) {
396 audio_prinfo_t *play = &proc->p_info.play;
397 audio_stream_t *sp = auclnt_output_stream(c);
398
399 if (((rv = auclnt_set_rate(sp, 8000)) != 0) ||
400 ((rv = auclnt_set_format(sp, AUDIO_FORMAT_ULAW)) != 0) ||
401 ((rv = auclnt_set_channels(sp, 1)) != 0)) {
402 goto failed;
403 }
404
405 auclnt_set_samples(sp, 0);
406 auclnt_set_errors(sp, 0);
407 play->eof = 0;
408 play->buffer_size = 8192;
409
410 auclnt_set_gain(sp, ((play->gain * 100) / AUDIO_MAX_GAIN));
411 auclnt_set_muted(sp, proc->p_info.output_muted);
412 play->open = B_TRUE;
413 proc->p_writer = c;
414 proc->p_oflag |= FWRITE;
415 }
416
417 if (oflag & FREAD) {
418 audio_prinfo_t *rec = &proc->p_info.record;
419 audio_stream_t *sp = auclnt_input_stream(c);
420
421 if (((rv = auclnt_set_rate(sp, 8000)) != 0) ||
422 ((rv = auclnt_set_format(sp, AUDIO_FORMAT_ULAW)) != 0) ||
423 ((rv = auclnt_set_channels(sp, 1)) != 0)) {
424 goto failed;
425 }
426
427 auclnt_set_samples(sp, 0);
428 auclnt_set_errors(sp, 0);
429 rec->eof = 0;
430 rec->buffer_size = 8192;
431
432 auclnt_set_gain(sp, ((rec->gain * 100) / AUDIO_MAX_GAIN));
433 rec->open = B_TRUE;
434 proc->p_reader = c;
435 proc->p_oflag |= FREAD;
436 }
437
438
439 dc->dc_wq = auclnt_get_wq(c);
440
441 /* we update the s_proc last to avoid a race */
442 dc->dc_proc = proc;
443
444 devaudio_proc_update(proc);
445
446 mutex_exit(&dev->d_mx);
447
448 return (0);
449
450 failed:
451 mutex_exit(&dev->d_mx);
452 devaudio_proc_release(c);
453 return (rv);
454
455 }
456
457 static void
devaudio_clear_eof(audio_client_t * c)458 devaudio_clear_eof(audio_client_t *c)
459 {
460 struct eofcnt *eof;
461 daclient_t *dc;
462
463 dc = auclnt_get_private(c);
464 mutex_enter(&dc->dc_lock);
465 while ((eof = list_remove_head(&dc->dc_eofcnt)) != NULL) {
466 kmem_free(eof, sizeof (*eof));
467 }
468 mutex_exit(&dc->dc_lock);
469 }
470
471 void
devaudio_proc_release(audio_client_t * c)472 devaudio_proc_release(audio_client_t *c)
473 {
474 daproc_t *proc;
475 dadev_t *dev;
476 mblk_t *mp;
477 daclient_t *dc;
478
479 dc = auclnt_get_private(c);
480 proc = dc->dc_proc;
481 dev = dc->dc_dev;
482 dc->dc_proc = NULL;
483
484 mutex_enter(&dev->d_mx);
485
486 if (proc != NULL) {
487 proc->p_refcnt--;
488 ASSERT(proc->p_refcnt >= 0);
489
490 if (c == proc->p_writer) {
491 proc->p_oflag &= ~FWRITE;
492 proc->p_writer = NULL;
493 }
494 if (c == proc->p_reader) {
495 proc->p_oflag &= ~FREAD;
496 proc->p_reader = NULL;
497 }
498 cv_broadcast(&dev->d_cv);
499
500 if (proc->p_refcnt == 0) {
501 list_remove(&dev->d_procs, proc);
502 devaudio_proc_free(proc);
503 }
504 dc->dc_proc = NULL;
505 }
506
507 mutex_exit(&dev->d_mx);
508
509 devaudio_clear_eof(c);
510
511 while ((mp = dc->dc_draining) != NULL) {
512 dc->dc_draining = mp->b_next;
513 mp->b_next = NULL;
514 freemsg(mp);
515 }
516
517 mutex_destroy(&dc->dc_lock);
518 list_destroy(&dc->dc_eofcnt);
519 kmem_free(dc, sizeof (*dc));
520 }
521
522 static void
devaudio_input(audio_client_t * c)523 devaudio_input(audio_client_t *c)
524 {
525 audio_stream_t *sp = auclnt_input_stream(c);
526 daclient_t *dc = auclnt_get_private(c);
527 unsigned framesz = auclnt_get_framesz(sp);
528 queue_t *rq = auclnt_get_rq(c);
529 mblk_t *mp;
530 unsigned nbytes = dc->dc_proc->p_info.record.buffer_size;
531 unsigned count = nbytes / framesz;
532
533 /*
534 * Potentially send a message upstream with the record data.
535 * We collect this up in chunks of the buffer size requested
536 * by the client.
537 */
538
539 while (auclnt_get_count(sp) >= count) {
540
541 if ((!canput(rq)) ||
542 ((mp = allocb(nbytes, BPRI_MED)) == NULL)) {
543 /*
544 * This will apply back pressure to the
545 * buffer. We haven't yet lost any data, we
546 * just can't send it up. The point at which
547 * we have an unrecoverable overrun is in the
548 * buffer, not in the streams queue. So, no
549 * need to do anything right now.
550 *
551 * Note that since recording is enabled, we
552 * expect that the callback routine will be
553 * called repeatedly & regularly, so we don't
554 * have to worry about leaving data orphaned
555 * in the queue.
556 */
557 break;
558 }
559
560 (void) auclnt_consume_data(sp, (caddr_t)mp->b_wptr, count);
561 mp->b_wptr += nbytes;
562 (void) putq(rq, mp);
563 }
564 }
565
566 static void
devaudio_proc_update(daproc_t * proc)567 devaudio_proc_update(daproc_t *proc)
568 {
569 audio_info_t *info;
570 audio_stream_t *sp;
571 audio_client_t *c;
572
573 info = &proc->p_info;
574
575 ASSERT(mutex_owned(&proc->p_dev->d_mx));
576
577 if ((c = proc->p_writer) != NULL) {
578 sp = auclnt_output_stream(c);
579
580 info->play.sample_rate = auclnt_get_rate(sp);
581 info->play.channels = auclnt_get_channels(sp);
582 devaudio_decompose_format(&info->play, auclnt_get_format(sp));
583
584 info->play.gain =
585 (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100;
586 info->play.pause = auclnt_is_paused(sp);
587 info->play.active = auclnt_is_running(sp);
588 info->play.samples = auclnt_get_samples(sp);
589 info->play.error = auclnt_get_errors(sp) ? B_TRUE : B_FALSE;
590 info->output_muted = auclnt_get_muted(sp);
591 } else {
592 info->play.encoding = AUDIO_ENCODING_NONE;
593 info->play.precision = 0;
594 info->play.sample_rate = 0;
595 info->play.pause = B_FALSE;
596 info->play.active = B_FALSE;
597 info->play.error = B_FALSE;
598 info->play.samples = 0;
599 }
600
601 if ((c = proc->p_reader) != NULL) {
602 sp = auclnt_input_stream(c);
603
604 info->record.sample_rate = auclnt_get_rate(sp);
605 info->record.channels = auclnt_get_channels(sp);
606 devaudio_decompose_format(&info->record, auclnt_get_format(sp));
607
608 info->record.gain =
609 (auclnt_get_gain(sp) * AUDIO_MAX_GAIN) / 100;
610 info->record.pause = auclnt_is_paused(sp);
611 info->record.active = auclnt_is_running(sp);
612 info->record.samples = auclnt_get_samples(sp);
613 info->record.error = auclnt_get_errors(sp) ? B_TRUE : B_FALSE;
614 } else {
615 info->record.encoding = AUDIO_ENCODING_NONE;
616 info->record.precision = 0;
617 info->record.sample_rate = 0;
618 info->record.pause = B_FALSE;
619 info->record.active = B_FALSE;
620 info->record.error = B_FALSE;
621 info->record.samples = 0;
622 }
623 }
624
625 static void
devaudio_ioc_getinfo(queue_t * wq,audio_client_t * c,mblk_t * mp)626 devaudio_ioc_getinfo(queue_t *wq, audio_client_t *c, mblk_t *mp)
627 {
628 daclient_t *dc = auclnt_get_private(c);
629 daproc_t *proc = dc->dc_proc;
630 mblk_t *bcont;
631
632 if ((bcont = allocb(sizeof (audio_info_t), BPRI_MED)) == NULL) {
633 miocnak(wq, mp, 0, ENOMEM);
634 return;
635 }
636
637 mutex_enter(&dc->dc_dev->d_mx);
638 devaudio_proc_update(proc);
639 bcopy(&proc->p_info, bcont->b_wptr, sizeof (audio_info_t));
640 mutex_exit(&dc->dc_dev->d_mx);
641
642 bcont->b_wptr += sizeof (audio_info_t);
643
644 mcopyout(mp, NULL, sizeof (audio_info_t), NULL, bcont);
645 qreply(wq, mp);
646 }
647
648 #define CHANGED(new, old, field) \
649 ((new->field != ((uint32_t)~0)) && (new->field != old->field))
650 #define CHANGED8(new, old, field) \
651 ((new->field != ((uint8_t)~0)) && (new->field != old->field))
652
653 static void
devaudio_ioc_setinfo(queue_t * wq,audio_client_t * c,mblk_t * mp)654 devaudio_ioc_setinfo(queue_t *wq, audio_client_t *c, mblk_t *mp)
655 {
656 daclient_t *dc;
657 daproc_t *proc;
658 audio_info_t *oinfo;
659 audio_info_t *ninfo;
660 audio_prinfo_t *npr;
661 audio_prinfo_t *opr;
662
663 int pfmt = AUDIO_FORMAT_NONE;
664 int rfmt = AUDIO_FORMAT_NONE;
665
666 boolean_t reader;
667 boolean_t writer;
668 boolean_t isctl;
669 audio_stream_t *sp;
670 int rv;
671 caddr_t uaddr;
672 mblk_t *bcont;
673
674 struct copyresp *csp;
675
676 if (DB_TYPE(mp) == M_IOCTL) {
677 /* the special value "1" indicates that this is a copyin */
678 uaddr = *(caddr_t *)(void *)mp->b_cont->b_rptr;
679
680 mcopyin(mp, uaddr, sizeof (audio_info_t), NULL);
681 qreply(wq, mp);
682 return;
683 }
684
685 ASSERT(DB_TYPE(mp) == M_IOCDATA);
686 if (((bcont = mp->b_cont) == NULL) ||
687 (MBLKL(mp->b_cont) != sizeof (audio_info_t))) {
688 miocnak(wq, mp, 0, EINVAL);
689 return;
690 }
691
692 mp->b_cont = NULL;
693 csp = (void *)mp->b_rptr;
694 uaddr = (void *)csp->cp_private;
695 dc = auclnt_get_private(c);
696 ninfo = (void *)bcont->b_rptr;
697
698 mutex_enter(&dc->dc_dev->d_mx);
699
700 proc = dc->dc_proc;
701 oinfo = &proc->p_info;
702
703 if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) {
704 /* control node can do both read and write fields */
705 isctl = B_TRUE;
706 reader = B_TRUE;
707 writer = B_TRUE;
708 } else {
709 isctl = B_FALSE;
710 writer = (c == proc->p_writer);
711 reader = (c == proc->p_reader);
712 }
713
714 /*
715 * Start by validating settings.
716 */
717 npr = &ninfo->play;
718 opr = &oinfo->play;
719
720 if (writer && CHANGED(npr, opr, sample_rate)) {
721 if ((isctl) ||
722 (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) {
723 rv = EINVAL;
724 goto err;
725 }
726 }
727 if (writer && CHANGED(npr, opr, channels)) {
728 if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) {
729 rv = EINVAL;
730 goto err;
731 }
732 }
733 if (writer &&
734 (CHANGED(npr, opr, encoding) || CHANGED(npr, opr, precision))) {
735 if (npr->encoding == (uint32_t)~0)
736 npr->encoding = opr->encoding;
737 if (npr->precision == (uint32_t)~0)
738 npr->precision = opr->precision;
739 pfmt = devaudio_compose_format(npr);
740 if ((isctl) || (pfmt == AUDIO_FORMAT_NONE)) {
741 rv = EINVAL;
742 goto err;
743 }
744 }
745
746 /* play fields that anyone can modify */
747 if (CHANGED(npr, opr, gain)) {
748 if (npr->gain > AUDIO_MAX_GAIN) {
749 rv = EINVAL;
750 goto err;
751 }
752 }
753
754
755 npr = &ninfo->record;
756 opr = &oinfo->record;
757
758 if (reader && CHANGED(npr, opr, sample_rate)) {
759 if ((isctl) ||
760 (npr->sample_rate < 5500) || (npr->sample_rate > 48000)) {
761 rv = EINVAL;
762 goto err;
763 }
764 }
765 if (reader && CHANGED(npr, opr, channels)) {
766 if ((isctl) || (npr->channels < 1) || (npr->channels > 2)) {
767 rv = EINVAL;
768 goto err;
769 }
770 }
771 if (reader &&
772 (CHANGED(npr, opr, encoding) || CHANGED(npr, opr, precision))) {
773 if (npr->encoding == (uint32_t)~0)
774 npr->encoding = opr->encoding;
775 if (npr->precision == (uint32_t)~0)
776 npr->precision = opr->precision;
777 rfmt = devaudio_compose_format(npr);
778 if ((isctl) || (rfmt == AUDIO_FORMAT_NONE)) {
779 rv = EINVAL;
780 goto err;
781 }
782 }
783 if (reader && CHANGED(npr, opr, buffer_size)) {
784 if (isctl) {
785 rv = EINVAL;
786 goto err;
787 }
788 /* make sure we can support 16-bit stereo samples */
789 if ((npr->buffer_size % 4) != 0) {
790 npr->buffer_size = (npr->buffer_size + 3) & ~3;
791 }
792 /* limit the maximum buffer size somewhat */
793 if (npr->buffer_size > 16384) {
794 npr->buffer_size = 16384;
795 }
796 }
797
798 /* record fields that anyone can modify */
799 if (CHANGED(npr, opr, gain)) {
800 if (npr->gain > AUDIO_MAX_GAIN) {
801 rv = EINVAL;
802 goto err;
803 }
804 }
805
806 /*
807 * Now apply the changes.
808 */
809 if (proc->p_writer != NULL) {
810 sp = auclnt_output_stream(proc->p_writer);
811 npr = &ninfo->play;
812 opr = &oinfo->play;
813
814 if (CHANGED(npr, opr, sample_rate)) {
815 if ((rv = auclnt_set_rate(sp, npr->sample_rate)) != 0)
816 goto err;
817 }
818 if (CHANGED(npr, opr, channels)) {
819 if ((rv = auclnt_set_channels(sp, npr->channels)) != 0)
820 goto err;
821 }
822 if (pfmt != AUDIO_FORMAT_NONE) {
823 if ((rv = auclnt_set_format(sp, pfmt)) != 0)
824 goto err;
825 }
826 if (CHANGED(npr, opr, samples)) {
827 auclnt_set_samples(sp, npr->samples);
828 }
829 if (CHANGED(npr, opr, eof)) {
830 /*
831 * This ugly special case code is required to
832 * prevent problems with realaudio.
833 */
834 if (npr->eof == 0) {
835 devaudio_clear_eof(proc->p_writer);
836 }
837 opr->eof = npr->eof;
838 }
839 if (CHANGED8(npr, opr, pause)) {
840 if (npr->pause) {
841 auclnt_set_paused(sp);
842 } else {
843 auclnt_clear_paused(sp);
844
845 /* qenable to start up the playback */
846 qenable(auclnt_get_wq(proc->p_writer));
847 }
848 }
849 if (CHANGED8(npr, opr, waiting) && (npr->waiting)) {
850 opr->waiting = npr->waiting;
851 }
852 if (CHANGED8(npr, opr, error)) {
853 auclnt_set_errors(sp, npr->error);
854 }
855 if (CHANGED(npr, opr, gain)) {
856 auclnt_set_gain(sp, (npr->gain * 100) / AUDIO_MAX_GAIN);
857 }
858 if (CHANGED8(ninfo, oinfo, output_muted)) {
859 auclnt_set_muted(sp, ninfo->output_muted);
860 }
861 if (CHANGED(npr, opr, buffer_size)) {
862 /*
863 * No checks on the buffer size are performed
864 * for play side. The value of the buffer size
865 * is meaningless for play side anyway.
866 */
867 opr->buffer_size = npr->buffer_size;
868 }
869 } else {
870 /* these values are preserved even if /dev/audio not open */
871 if (CHANGED(npr, opr, gain)) {
872 opr->gain = npr->gain;
873 }
874 if (CHANGED8(ninfo, oinfo, output_muted)) {
875 oinfo->output_muted = ninfo->output_muted;
876 }
877 }
878
879 if (proc->p_reader != NULL) {
880 sp = auclnt_input_stream(proc->p_reader);
881 npr = &ninfo->record;
882 opr = &oinfo->record;
883
884 if (CHANGED(npr, opr, sample_rate)) {
885 if ((rv = auclnt_set_rate(sp, npr->sample_rate)) != 0)
886 goto err;
887 }
888 if (CHANGED(npr, opr, channels)) {
889 if ((rv = auclnt_set_channels(sp, npr->channels)) != 0)
890 goto err;
891 }
892 if (rfmt != AUDIO_FORMAT_NONE) {
893 if ((rv = auclnt_set_format(sp, rfmt)) != 0)
894 goto err;
895 }
896 if (CHANGED(npr, opr, samples)) {
897 auclnt_set_samples(sp, npr->samples);
898 }
899 if (CHANGED(npr, opr, eof)) {
900 opr->eof = npr->eof;
901 }
902 if (CHANGED8(npr, opr, pause)) {
903 if (npr->pause) {
904 auclnt_set_paused(sp);
905 } else {
906 auclnt_clear_paused(sp);
907 auclnt_start(sp);
908 }
909 }
910 if (CHANGED8(npr, opr, waiting) && (npr->waiting)) {
911 opr->waiting = npr->waiting;
912 }
913 if (CHANGED8(npr, opr, error)) {
914 auclnt_set_errors(sp, npr->error);
915 }
916 if (CHANGED(npr, opr, buffer_size)) {
917 opr->buffer_size = npr->buffer_size;
918 }
919 if (CHANGED(npr, opr, gain)) {
920 auclnt_set_gain(sp, (npr->gain * 100) / AUDIO_MAX_GAIN);
921 }
922 } else {
923 /* these values are preserved even if /dev/audio not open */
924 if (CHANGED(npr, opr, gain)) {
925 opr->gain = npr->gain;
926 }
927 }
928
929 devaudio_proc_update(dc->dc_proc);
930 bcopy(&dc->dc_proc->p_info, ninfo, sizeof (*ninfo));
931
932 mutex_exit(&dc->dc_dev->d_mx);
933 mcopyout(mp, NULL, sizeof (audio_info_t), uaddr, bcont);
934 qreply(wq, mp);
935 return;
936
937 err:
938 mutex_exit(&dc->dc_dev->d_mx);
939 miocnak(wq, mp, 0, rv);
940 }
941
942 static void
devaudio_ioc_getdev(queue_t * wq,audio_client_t * c,mblk_t * mp)943 devaudio_ioc_getdev(queue_t *wq, audio_client_t *c, mblk_t *mp)
944 {
945 audio_dev_t *d = auclnt_get_dev(c);
946 mblk_t *bcont;
947 audio_device_t *a;
948
949 if ((bcont = allocb(sizeof (*a), BPRI_MED)) == NULL) {
950 miocnak(wq, mp, 0, ENOMEM);
951 return;
952 }
953
954 a = (void *)bcont->b_wptr;
955 (void) snprintf(a->name, sizeof (a->name),
956 "SUNW,%s", auclnt_get_dev_name(d));
957 (void) strlcpy(a->config,
958 auclnt_get_dev_description(d), sizeof (a->config));
959 (void) strlcpy(a->version,
960 auclnt_get_dev_version(d), sizeof (a->version));
961 bcont->b_wptr += sizeof (*a);
962
963 mcopyout(mp, NULL, sizeof (*a), NULL, bcont);
964 qreply(wq, mp);
965 }
966
967 static int
devaudio_sigpoll(audio_client_t * c,void * arg)968 devaudio_sigpoll(audio_client_t *c, void *arg)
969 {
970 pid_t pid = (pid_t)(uintptr_t)arg;
971
972 if (auclnt_get_minor_type(c) == AUDIO_MINOR_DEVAUDIOCTL) {
973 /* we only need to notify peers in our own process */
974 if (auclnt_get_pid(c) == pid) {
975 (void) putctl1(auclnt_get_rq(c), M_PCSIG, SIGPOLL);
976 }
977 }
978 return (AUDIO_WALK_CONTINUE);
979 }
980
981 static void
devaudio_drain(audio_client_t * c)982 devaudio_drain(audio_client_t *c)
983 {
984 daclient_t *dc = auclnt_get_private(c);
985 mblk_t *mplist, *mp;
986
987 mutex_enter(&dc->dc_lock);
988 mplist = dc->dc_draining;
989 dc->dc_draining = NULL;
990 mutex_exit(&dc->dc_lock);
991
992 while ((mp = mplist) != NULL) {
993 mplist = mp->b_next;
994 mp->b_next = NULL;
995 mioc2ack(mp, NULL, 0, 0);
996 (void) putq(auclnt_get_rq(c), mp);
997 }
998 }
999
1000 static void
devaudio_output(audio_client_t * c)1001 devaudio_output(audio_client_t *c)
1002 {
1003 daclient_t *dc = auclnt_get_private(c);
1004 daproc_t *proc = dc->dc_proc;
1005 uint64_t tail;
1006 struct eofcnt *eof;
1007 int eofs = 0;
1008
1009 tail = auclnt_get_tail(auclnt_output_stream(c));
1010
1011 /* get more data! (do this early) */
1012 qenable(auclnt_get_wq(c));
1013
1014 mutex_enter(&dc->dc_lock);
1015 while (((eof = list_head(&dc->dc_eofcnt)) != NULL) &&
1016 (eof->tail <= tail)) {
1017 list_remove(&dc->dc_eofcnt, eof);
1018 kmem_free(eof, sizeof (*eof));
1019 eofs++;
1020 }
1021 proc->p_info.play.eof += eofs;
1022 mutex_exit(&dc->dc_lock);
1023
1024 if (eofs) {
1025 auclnt_dev_walk_clients(auclnt_get_dev(c),
1026 devaudio_sigpoll, (void *)(uintptr_t)auclnt_get_pid(c));
1027 }
1028 }
1029
1030 static void *
devaudio_init(audio_dev_t * adev)1031 devaudio_init(audio_dev_t *adev)
1032 {
1033 dadev_t *dev;
1034 unsigned cap;
1035
1036 cap = auclnt_get_dev_capab(adev);
1037 /* if not a play or record device, don't bother initializing it */
1038 if ((cap & (AUDIO_CLIENT_CAP_PLAY | AUDIO_CLIENT_CAP_RECORD)) == 0) {
1039 return (NULL);
1040 }
1041
1042 dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
1043 dev->d_dev = adev;
1044 mutex_init(&dev->d_mx, NULL, MUTEX_DRIVER, NULL);
1045 cv_init(&dev->d_cv, NULL, CV_DRIVER, NULL);
1046 list_create(&dev->d_procs, sizeof (struct daproc),
1047 offsetof(struct daproc, p_linkage));
1048
1049 return (dev);
1050 }
1051
1052 static void
devaudio_fini(void * arg)1053 devaudio_fini(void *arg)
1054 {
1055 dadev_t *dev = arg;
1056
1057 if (dev != NULL) {
1058
1059 mutex_destroy(&dev->d_mx);
1060 cv_destroy(&dev->d_cv);
1061 list_destroy(&dev->d_procs);
1062 kmem_free(dev, sizeof (*dev));
1063 }
1064 }
1065
1066 static int
devaudio_open(audio_client_t * c,int oflag)1067 devaudio_open(audio_client_t *c, int oflag)
1068 {
1069 int rv;
1070
1071 if ((rv = auclnt_open(c, oflag)) != 0) {
1072 return (rv);
1073 }
1074
1075 if ((rv = devaudio_proc_hold(c, oflag)) != 0) {
1076 auclnt_close(c);
1077 return (rv);
1078 }
1079
1080 /* start up the input */
1081 if (oflag & FREAD) {
1082 auclnt_start(auclnt_input_stream(c));
1083 }
1084
1085 return (0);
1086 }
1087
1088 static int
devaudioctl_open(audio_client_t * c,int oflag)1089 devaudioctl_open(audio_client_t *c, int oflag)
1090 {
1091 int rv;
1092
1093 _NOTE(ARGUNUSED(oflag));
1094
1095 oflag &= ~(FWRITE | FREAD);
1096
1097 if ((rv = auclnt_open(c, 0)) != 0) {
1098 return (rv);
1099 }
1100
1101 if ((rv = devaudio_proc_hold(c, oflag)) != 0) {
1102 auclnt_close(c);
1103 return (rv);
1104 }
1105
1106 return (0);
1107 }
1108
1109 static void
devaudio_close(audio_client_t * c)1110 devaudio_close(audio_client_t *c)
1111 {
1112 auclnt_stop(auclnt_output_stream(c));
1113 auclnt_stop(auclnt_input_stream(c));
1114
1115 auclnt_close(c);
1116 devaudio_proc_release(c);
1117 }
1118
1119 static void
devaudioctl_close(audio_client_t * c)1120 devaudioctl_close(audio_client_t *c)
1121 {
1122 auclnt_close(c);
1123 devaudio_proc_release(c);
1124 }
1125
1126 static void
devaudio_miocdata(audio_client_t * c,mblk_t * mp)1127 devaudio_miocdata(audio_client_t *c, mblk_t *mp)
1128 {
1129 struct copyresp *csp;
1130 queue_t *wq;
1131
1132 csp = (void *)mp->b_rptr;
1133 wq = auclnt_get_wq(c);
1134
1135 /*
1136 * If a transfer error occurred, the framework already
1137 * MIOCNAK'd it.
1138 */
1139 if (csp->cp_rval != 0) {
1140 freemsg(mp);
1141 return;
1142 }
1143
1144 /*
1145 * If no state, then this is a response to M_COPYOUT, and we
1146 * are done. (Audio ioctls just copyout a single structure at
1147 * completion of work.)
1148 */
1149 if (csp->cp_private == NULL) {
1150 miocack(wq, mp, 0, 0);
1151 return;
1152 }
1153
1154 /* now, call the handler ioctl */
1155 switch (csp->cp_cmd) {
1156 case AUDIO_SETINFO:
1157 devaudio_ioc_setinfo(wq, c, mp);
1158 break;
1159 default:
1160 miocnak(wq, mp, 0, EINVAL);
1161 break;
1162 }
1163 }
1164
1165 static void
devaudio_mioctl(audio_client_t * c,mblk_t * mp)1166 devaudio_mioctl(audio_client_t *c, mblk_t *mp)
1167 {
1168 struct iocblk *iocp = (void *)mp->b_rptr;
1169 queue_t *wq = auclnt_get_wq(c);
1170
1171 /* BSD legacy here: we only support transparent ioctls */
1172 if (iocp->ioc_count != TRANSPARENT) {
1173 miocnak(wq, mp, 0, EINVAL);
1174 return;
1175 }
1176
1177 switch (iocp->ioc_cmd) {
1178 case AUDIO_GETINFO:
1179 devaudio_ioc_getinfo(wq, c, mp);
1180 break;
1181
1182 case AUDIO_SETINFO:
1183 devaudio_ioc_setinfo(wq, c, mp);
1184 break;
1185
1186 case AUDIO_GETDEV:
1187 devaudio_ioc_getdev(wq, c, mp);
1188 break;
1189
1190 case AUDIO_DIAG_LOOPBACK:
1191 /* we don't support this one */
1192 miocnak(wq, mp, 0, ENOTTY);
1193 break;
1194
1195 case AUDIO_MIXERCTL_GET_MODE:
1196 case AUDIO_MIXERCTL_SET_MODE:
1197 case AUDIO_MIXERCTL_GET_CHINFO:
1198 case AUDIO_MIXERCTL_SET_CHINFO:
1199 case AUDIO_MIXERCTL_GETINFO:
1200 case AUDIO_MIXERCTL_SETINFO:
1201 case AUDIO_GET_NUM_CHS:
1202 case AUDIO_GET_CH_NUMBER:
1203 case AUDIO_GET_CH_TYPE:
1204 case AUDIO_MIXER_SINGLE_OPEN:
1205 case AUDIO_MIXER_MULTIPLE_OPEN:
1206 case AUDIO_MIXER_GET_SAMPLE_RATES:
1207 default:
1208 miocnak(wq, mp, 0, EINVAL);
1209 break;
1210 }
1211 }
1212
1213 static void
devaudioctl_wput(audio_client_t * c,mblk_t * mp)1214 devaudioctl_wput(audio_client_t *c, mblk_t *mp)
1215 {
1216 queue_t *wq = auclnt_get_wq(c);
1217
1218 switch (DB_TYPE(mp)) {
1219 case M_IOCTL:
1220 /* Drain ioctl needs to be handled on the service queue */
1221 devaudio_mioctl(c, mp);
1222 break;
1223
1224 case M_IOCDATA:
1225 devaudio_miocdata(c, mp);
1226 break;
1227
1228 case M_FLUSH:
1229 /*
1230 * We don't flush the engine. The reason is that
1231 * other streams might be using the engine. This is
1232 * fundamentally no different from the case where the
1233 * engine hardware has data buffered in an
1234 * inaccessible FIFO.
1235 *
1236 * Clients that want to ensure no more data is coming
1237 * should stop the stream before flushing.
1238 */
1239 if (*mp->b_rptr & FLUSHW) {
1240 *mp->b_rptr &= ~FLUSHW;
1241 }
1242 if (*mp->b_rptr & FLUSHR) {
1243 qreply(wq, mp);
1244 } else {
1245 freemsg(mp);
1246 }
1247 break;
1248
1249 case M_DATA:
1250 /*
1251 * No audio data on control nodes!
1252 */
1253
1254 default:
1255 freemsg(mp);
1256 break;
1257 }
1258 }
1259
1260 static void
devaudio_wput(audio_client_t * c,mblk_t * mp)1261 devaudio_wput(audio_client_t *c, mblk_t *mp)
1262 {
1263 queue_t *wq = auclnt_get_wq(c);
1264
1265 switch (DB_TYPE(mp)) {
1266 case M_IOCTL:
1267 /* Drain ioctl needs to be handled on the service queue */
1268 if (*(int *)(void *)mp->b_rptr == AUDIO_DRAIN) {
1269 (void) putq(wq, mp);
1270 } else {
1271 devaudio_mioctl(c, mp);
1272 }
1273 break;
1274
1275 case M_IOCDATA:
1276 devaudio_miocdata(c, mp);
1277 break;
1278
1279 case M_FLUSH:
1280 /*
1281 * We don't flush the engine. The reason is that
1282 * other streams might be using the engine. This is
1283 * fundamentally no different from the case where the
1284 * engine hardware has data buffered in an
1285 * inaccessible FIFO.
1286 *
1287 * Clients that want to ensure no more data is coming
1288 * should stop the stream before flushing.
1289 */
1290 if (*mp->b_rptr & FLUSHW) {
1291 flushq(wq, FLUSHALL);
1292 auclnt_flush(auclnt_output_stream(c));
1293 *mp->b_rptr &= ~FLUSHW;
1294 }
1295 if (*mp->b_rptr & FLUSHR) {
1296 flushq(RD(wq), FLUSHALL);
1297 auclnt_flush(auclnt_input_stream(c));
1298 qreply(wq, mp);
1299 } else {
1300 freemsg(mp);
1301 }
1302 break;
1303
1304 case M_DATA:
1305 /*
1306 * Defer processing to the queue. This keeps the data
1307 * ordered, and allows the wsrv routine to gather
1308 * multiple mblks at once.
1309 */
1310 if (mp->b_cont != NULL) {
1311
1312 /*
1313 * If we need to pullup, do it here to
1314 * simplify the rest of the processing later.
1315 * This should rarely (if ever) be necessary.
1316 */
1317 mblk_t *nmp;
1318
1319 if ((nmp = msgpullup(mp, -1)) == NULL) {
1320 freemsg(mp);
1321 } else {
1322 freemsg(mp);
1323 (void) putq(wq, nmp);
1324 }
1325 } else {
1326 (void) putq(wq, mp);
1327 }
1328 break;
1329
1330 default:
1331 freemsg(mp);
1332 break;
1333 }
1334 }
1335
1336 static void
devaudio_rsrv(audio_client_t * c)1337 devaudio_rsrv(audio_client_t *c)
1338 {
1339 queue_t *rq = auclnt_get_rq(c);
1340 mblk_t *mp;
1341
1342 while ((mp = getq(rq)) != NULL) {
1343
1344 if ((queclass(mp) != QPCTL) && (!canputnext(rq))) {
1345 /*
1346 * Put it back in the queue so we can apply
1347 * backpressure properly.
1348 */
1349 (void) putbq(rq, mp);
1350 return;
1351 }
1352 putnext(rq, mp);
1353 }
1354 }
1355
1356 static void
devaudio_wsrv(audio_client_t * c)1357 devaudio_wsrv(audio_client_t *c)
1358 {
1359 queue_t *wq = auclnt_get_wq(c);
1360 daclient_t *dc = auclnt_get_private(c);
1361 audio_stream_t *sp;
1362 mblk_t *mp;
1363 unsigned framesz;
1364
1365 sp = auclnt_output_stream(c);
1366
1367 framesz = auclnt_get_framesz(sp);
1368
1369 while ((mp = getq(wq)) != NULL) {
1370
1371 unsigned count;
1372
1373 /* got a message */
1374
1375 /* if its a drain ioctl, we need to process it here */
1376 if (DB_TYPE(mp) == M_IOCTL) {
1377 ASSERT((*(int *)(void *)mp->b_rptr) == AUDIO_DRAIN);
1378 mutex_enter(&dc->dc_lock);
1379 mp->b_next = dc->dc_draining;
1380 dc->dc_draining = mp;
1381 mutex_exit(&dc->dc_lock);
1382
1383 if (auclnt_start_drain(c) != 0) {
1384 devaudio_drain(c);
1385 }
1386 continue;
1387 }
1388
1389 ASSERT(DB_TYPE(mp) == M_DATA);
1390
1391 /*
1392 * Empty mblk require special handling, since they
1393 * indicate EOF. We treat them separate from the main
1394 * processing loop.
1395 */
1396 if (MBLKL(mp) == 0) {
1397 struct eofcnt *eof;
1398
1399 eof = kmem_zalloc(sizeof (*eof), KM_NOSLEEP);
1400 if (eof != NULL) {
1401 eof->tail = auclnt_get_head(sp);
1402 mutex_enter(&dc->dc_lock);
1403 list_insert_tail(&dc->dc_eofcnt, eof);
1404 mutex_exit(&dc->dc_lock);
1405 }
1406 freemsg(mp);
1407 continue;
1408 }
1409
1410 count = auclnt_produce_data(sp, (caddr_t)mp->b_rptr,
1411 MBLKL(mp) / framesz);
1412
1413 mp->b_rptr += count * framesz;
1414
1415 if (MBLKL(mp) >= framesz) {
1416 (void) putbq(wq, mp);
1417 break;
1418 } else {
1419 freemsg(mp);
1420 }
1421 }
1422
1423 /* if the stream isn't running yet, start it up */
1424 if (!auclnt_is_paused(sp))
1425 auclnt_start(sp);
1426 }
1427
1428 static struct audio_client_ops devaudio_ops = {
1429 "sound,audio",
1430 devaudio_init,
1431 devaudio_fini,
1432 devaudio_open,
1433 devaudio_close,
1434 NULL, /* read */
1435 NULL, /* write */
1436 NULL, /* ioctl */
1437 NULL, /* chpoll */
1438 NULL, /* mmap */
1439 devaudio_input,
1440 devaudio_output,
1441 devaudio_drain,
1442 devaudio_wput,
1443 devaudio_wsrv,
1444 devaudio_rsrv
1445 };
1446
1447 static struct audio_client_ops devaudioctl_ops = {
1448 "sound,audioctl",
1449 NULL, /* dev_init */
1450 NULL, /* dev_fini */
1451 devaudioctl_open,
1452 devaudioctl_close,
1453 NULL, /* read */
1454 NULL, /* write */
1455 NULL, /* ioctl */
1456 NULL, /* chpoll */
1457 NULL, /* mmap */
1458 NULL, /* output */
1459 NULL, /* input */
1460 NULL, /* drain */
1461 devaudioctl_wput,
1462 NULL,
1463 devaudio_rsrv
1464 };
1465
1466 void
auimpl_sun_init(void)1467 auimpl_sun_init(void)
1468 {
1469 auclnt_register_ops(AUDIO_MINOR_DEVAUDIO, &devaudio_ops);
1470 auclnt_register_ops(AUDIO_MINOR_DEVAUDIOCTL, &devaudioctl_ops);
1471 }
1472