|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1993 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*-
27: * Copyright (c) 1991, 1992 The Regents of the University of California.
28: * All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the Computer Systems
41: * Engineering Group at Lawrence Berkeley Laboratory.
42: * 4. The name of the Laboratory may not be used to endorse or promote
43: * products derived from this software without specific prior written
44: * permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: */
58:
59: #include <audio.h>
60: #if NAUDIO > 0
61:
62: #include <mach_kdb.h>
63: #include <platforms.h>
64:
65: #include <mach/std_types.h>
66: #include <machine/machspl.h>
67: #include <kern/kalloc.h>
68: #include <kern/sched_prim.h>
69: #include <chips/busses.h>
70:
71: #include <device/device_types.h>
72: #include <device/io_req.h>
73: #include <device/ds_routines.h>
74: #include <device/audio_status.h> /* user interface */
75: #include <chips/audio_defs.h> /* chip interface */
76: #include <chips/audio_config.h> /* machdep config */
77:
78: #define private static
79:
80: /*
81: * Exported functions and data structures
82: * [see header file for listing]
83: */
84: int audio_blocksize = DEFBLKSIZE; /* patchable */
85: int audio_backlog = 400; /* 50ms in samples */
86:
87: /*
88: * Software state, per AMD79C30 audio chip.
89: */
90: private
91: struct audio_softc {
92: void *hw; /* chip status */
93: audio_switch_t *ops; /* chip operations */
94: au_io_t *sc_au; /* recv and xmit buffers, etc */
95:
96:
97: unsigned int sc_wseek; /* timestamp of last frame written */
98: unsigned int sc_rseek; /* timestamp of last frame read */
99: #if 0
100: struct selinfo sc_wsel; /* write selector */
101: struct selinfo sc_rsel; /* read selector */
102: #endif
103:
104: } audio_softc_data[NAUDIO];
105:
106: #define unit_to_softc(u) &audio_softc_data[u]
107:
108:
109: /* forward declarations */
110: private int audio_sleep (au_cb_t *cb, int thresh);
111: private void audio_swintr (struct audio_softc *sc);
112:
113: /*
114: * Audio chip found.
115: */
116: void
117: audio_attach(
118: void *hw, /* IN, chip status */
119: audio_switch_t *ops,
120: void **audio_status) /* OUT, audio status */
121: {
122: register struct audio_softc *sc;
123: static int next = 0;
124:
125: if (next >= NAUDIO)
126: panic("Please configure more than %d audio devices\n", NAUDIO);
127: sc = &audio_softc_data[next++];
128:
129: printf(" audio");
130:
131: sc->hw = hw;
132: sc->ops = ops;
133:
134: *audio_status = (void *)sc;
135: }
136:
137:
138: private int audio_setinfo (struct audio_softc *, audio_info_t *);
139: private int audio_getinfo (struct audio_softc *, audio_info_t *);
140:
141: io_return_t
142: audio_open(
143: int unit,
144: int mode,
145: io_req_t req)
146: {
147: register struct audio_softc *sc;
148: register au_io_t *au;
149:
150: sc = unit_to_softc(unit);
151: if (unit > NAUDIO || (!sc->hw))
152: return (D_NO_SUCH_DEVICE);
153:
154: if (!sc->sc_au) {
155: sc->sc_au = (au_io_t *) kalloc(sizeof(au_io_t));
156: bzero(sc->sc_au, sizeof(au_io_t));
157: }
158: au = sc->sc_au;
159:
160: au->au_lowat = audio_blocksize;
161: au->au_hiwat = AUCB_SIZE - au->au_lowat;
162: au->au_blksize = audio_blocksize;
163: au->au_backlog = audio_backlog;
164:
165: /* set up read and write blocks and `dead sound' zero value. */
166: AUCB_INIT(&au->au_rb);
167: au->au_rb.cb_thresh = AUCB_SIZE;
168: AUCB_INIT(&au->au_wb);
169: au->au_wb.cb_thresh = -1;
170:
171: /* nothing read or written yet */
172: sc->sc_rseek = 0;
173: sc->sc_wseek = 0;
174:
175: (*sc->ops->init)(sc->hw);
176:
177: return (0);
178: }
179:
180: private int
181: audio_drain(
182: register au_io_t *au)
183: {
184: register int error;
185:
186: while (!AUCB_EMPTY(&au->au_wb))
187: if ((error = audio_sleep(&au->au_wb, 0)) != 0)
188: return (error);
189: return (0);
190: }
191:
192: /*
193: * Close an audio chip.
194: */
195: /* ARGSUSED */
196: io_return_t
197: audio_close(
198: int unit)
199: {
200: register struct audio_softc *sc = unit_to_softc(unit);
201: register au_cb_t *cb;
202: register spl_t s;
203:
204: /*
205: * Block until output drains, but allow ^C interrupt.
206: */
207: sc->sc_au->au_lowat = 0; /* avoid excessive wakeups */
208:
209: /*
210: * If there is pending output, let it drain (unless
211: * the output is paused).
212: */
213: cb = &sc->sc_au->au_wb;
214: s = splaudio();
215: if (!AUCB_EMPTY(cb) && !cb->cb_pause)
216: (void)audio_drain(sc->sc_au);
217: /*
218: * Disable interrupts, and done.
219: */
220: (*sc->ops->close)(sc->hw);
221: splx(s);
222: return (D_SUCCESS);
223: }
224:
225: private int
226: audio_sleep(
227: register au_cb_t *cb,
228: register int thresh)
229: {
230: register spl_t s = splaudio();
231:
232: cb->cb_thresh = thresh;
233: assert_wait((event_t)cb, TRUE);
234: splx(s);
235: thread_block((void (*)()) 0);
236: return (0); /* XXXX */
237: }
238:
239: io_return_t
240: audio_read(
241: int unit,
242: io_req_t ior)
243: {
244: register struct audio_softc *sc = unit_to_softc(unit);
245: register au_cb_t *cb;
246: register int n, head, taildata;
247: register int blocksize = sc->sc_au->au_blksize;
248: io_return_t rc;
249: unsigned char *data;
250:
251: /*
252: * Allocate read buffer
253: */
254: rc = device_read_alloc(ior, (vm_size_t)ior->io_count);
255: if (rc != KERN_SUCCESS)
256: return rc;
257: data = (unsigned char *) ior->io_data;
258: ior->io_residual = ior->io_count;
259:
260: cb = &sc->sc_au->au_rb;
261: cb->cb_drops = 0;
262: sc->sc_rseek = sc->sc_au->au_stamp - AUCB_LEN(cb);
263: do {
264: while (AUCB_LEN(cb) < blocksize) {
265:
266: if (ior->io_mode & D_NODELAY)
267: return (D_WOULD_BLOCK);
268:
269: if ((rc = audio_sleep(cb, blocksize)) != 0)
270: return(rc);
271: }
272: /*
273: * The space calculation can only err on the short
274: * side if an interrupt occurs during processing:
275: * only cb_tail is altered in the interrupt code.
276: */
277: head = cb->cb_head;
278: if ((n = AUCB_LEN(cb)) > ior->io_residual)
279: n = ior->io_residual;
280: taildata = AUCB_SIZE - head;
281:
282: if (n > taildata) {
283: bcopy(cb->cb_data + head, data, taildata);
284: bcopy(cb->cb_data, data + taildata, n - taildata);
285: } else
286: bcopy(cb->cb_data + head, data, n);
287: data += n;
288: ior->io_residual -= n;
289:
290: head = AUCB_MOD(head + n);
291: cb->cb_head = head;
292: } while (ior->io_residual >= blocksize);
293:
294: return (rc);
295: }
296:
297: io_return_t
298: audio_write(
299: int unit,
300: io_req_t ior)
301: {
302: register struct audio_softc *sc = unit_to_softc(unit);
303: register au_io_t *au = sc->sc_au;
304: register au_cb_t *cb = &au->au_wb;
305: register int n, tail, tailspace, first, watermark;
306: io_return_t rc;
307: unsigned char *data;
308: vm_offset_t addr = 0;
309:
310: if (!(ior->io_op & IO_INBAND)) {
311: /*
312: * Copy out-of-line data into kernel address space.
313: * Since data is copied as page list, it will be
314: * accessible.
315: */
316: vm_map_copy_t copy = (vm_map_copy_t) ior->io_data;
317: kern_return_t kr;
318:
319: kr = vm_map_copyout(device_io_map, &addr, copy);
320: if (kr != KERN_SUCCESS)
321: return kr;
322: data = (unsigned char *) addr;
323: } else
324: data = (unsigned char *) ior->io_data;
325: ior->io_residual = ior->io_count;
326:
327: rc = D_SUCCESS;
328: first = 1;
329: while (ior->io_residual > 0) {
330: watermark = au->au_hiwat;
331: while (AUCB_LEN(cb) > watermark) {
332:
333: if (ior->io_mode & D_NODELAY) {
334: rc = D_WOULD_BLOCK;
335: goto out;
336: }
337:
338: if ((rc = audio_sleep(cb, watermark)) != 0)
339: goto out;
340:
341: watermark = au->au_lowat;
342: }
343: /*
344: * The only value that can change on an interrupt is
345: * cb->cb_head. We only pull that out once to decide
346: * how much to write into cb_data; if we lose a race
347: * and cb_head changes, we will merely be overly
348: * conservative. For a legitimate time stamp,
349: * however, we need to synchronize the accesses to
350: * au_stamp and cb_head at a high ipl below.
351: */
352: tail = cb->cb_tail;
353: if ((n = (AUCB_SIZE - 1) - AUCB_LEN(cb)) > ior->io_residual) {
354: n = ior->io_residual;
355: if (cb->cb_head == tail &&
356: n <= au->au_blksize &&
357: au->au_stamp - sc->sc_wseek > 400) {
358: /*
359: * the write is 'small', the buffer is empty
360: * and we have been silent for at least 50ms
361: * so we might be dealing with an application
362: * that writes frames synchronously with
363: * reading them. If so, we need an output
364: * backlog to cover scheduling delays or
365: * there will be gaps in the sound output.
366: * Also take this opportunity to reset the
367: * buffer pointers in case we ended up on
368: * a bad boundary (odd byte, blksize bytes
369: * from end, etc.).
370: */
371: register unsigned long *ip;
372: register unsigned long muzero;
373: spl_t s;
374: register int i;
375:
376: s = splaudio();
377: cb->cb_head = cb->cb_tail = 0;
378: splx(s);
379:
380: tail = au->au_backlog;
381: ip = (unsigned long *)cb->cb_data;
382: muzero = sample_rpt_long(0x7fL);
383: for (i = tail / sizeof muzero; --i >= 0; )
384: *ip++ = muzero;
385: }
386: }
387: tailspace = AUCB_SIZE - tail;
388: if (n > tailspace) {
389: /* write first part at tail and rest at head */
390: bcopy(data, cb->cb_data + tail, tailspace);
391: bcopy(data + tailspace, cb->cb_data,
392: n - tailspace);
393: } else
394: bcopy(data, cb->cb_data + tail, n);
395: data += n;
396: ior->io_residual -= n;
397:
398: tail = AUCB_MOD(tail + n);
399: if (first) {
400: register spl_t s = splaudio();
401: sc->sc_wseek = AUCB_LEN(cb) + au->au_stamp + 1;
402: /*
403: * To guarantee that a write is contiguous in the
404: * sample space, we clear the drop count the first
405: * time through. If we later get drops, we will
406: * break out of the loop below, before writing
407: * a new frame.
408: */
409: cb->cb_drops = 0;
410: cb->cb_tail = tail;
411: splx(s);
412: first = 0;
413: } else {
414: #if 0
415: if (cb->cb_drops != 0)
416: break;
417: #endif
418: cb->cb_tail = tail;
419: }
420: }
421: out:
422: if (!(ior->io_op & IO_INBAND))
423: (void) vm_deallocate(device_io_map, addr, ior->io_count);
424: return (rc);
425: }
426:
427: #include <sys/ioctl.h>
428:
429: io_return_t
430: audio_get_status(
431: int unit,
432: dev_flavor_t flavor,
433: dev_status_t status,
434: natural_t *status_count)
435: {
436: register struct audio_softc *sc = unit_to_softc(unit);
437: register au_io_t *au = sc->sc_au;
438: io_return_t rc = D_SUCCESS;
439: spl_t s;
440:
441: switch (flavor) {
442:
443: case AUDIO_GETMAP:
444: case AUDIOGETREG:
445: rc = (*sc->ops->getstate)(sc->hw, flavor,
446: (void *)status, status_count);
447: break;
448:
449: /*
450: * Number of read samples dropped. We don't know where or
451: * when they were dropped.
452: */
453: case AUDIO_RERROR:
454: *(int *)status = au->au_rb.cb_drops;
455: *status_count = 1;
456: break;
457:
458: case AUDIO_WERROR:
459: *(int *)status = au->au_wb.cb_drops;
460: *status_count = 1;
461: break;
462:
463: /*
464: * How many samples will elapse until mike hears the first
465: * sample of what we last wrote?
466: */
467: case AUDIO_WSEEK:
468: s = splaudio();
469: *(unsigned int *)status = sc->sc_wseek - au->au_stamp
470: + AUCB_LEN(&au->au_rb);
471: splx(s);
472: *status_count = 1;
473: break;
474:
475: case AUDIO_GETINFO:
476: rc = audio_getinfo(sc, (audio_info_t *)status);
477: *status_count = sizeof(audio_info_t) / sizeof(int);
478: break;
479:
480: default:
481: rc = D_INVALID_OPERATION;
482: break;
483: }
484: return (rc);
485: }
486:
487: io_return_t
488: audio_set_status(
489: int unit,
490: dev_flavor_t flavor,
491: dev_status_t status,
492: natural_t status_count)
493: {
494: register struct audio_softc *sc = unit_to_softc(unit);
495: register au_io_t *au = sc->sc_au;
496: io_return_t rc = D_SUCCESS;
497: spl_t s;
498:
499: switch (flavor) {
500:
501: case AUDIO_SETMAP:
502: case AUDIOSETREG:
503: rc = (*sc->ops->setstate)(sc->hw, flavor,
504: (void *)status, status_count);
505: break;
506:
507: case AUDIO_FLUSH:
508: s = splaudio();
509: AUCB_INIT(&au->au_rb);
510: AUCB_INIT(&au->au_wb);
511: au->au_stamp = 0;
512: splx(s);
513: sc->sc_wseek = 0;
514: sc->sc_rseek = 0;
515: break;
516:
517: case AUDIO_SETINFO:
518: rc = audio_setinfo(sc, (audio_info_t *)status);
519: break;
520:
521: case AUDIO_DRAIN:
522: rc = audio_drain(au);
523: break;
524:
525: default:
526: rc = D_INVALID_OPERATION;
527: break;
528: }
529: return (rc);
530: }
531:
532:
533: /*
534: * Interrupt routine
535: */
536: boolean_t
537: audio_hwintr(
538: void *status,
539: unsigned int s_in,
540: unsigned int *s_out)
541: {
542: register au_io_t *au = ((struct audio_softc *) status)->sc_au;
543: register au_cb_t *cb;
544: register int h, t, k;
545: register boolean_t wakeit = FALSE;
546:
547: ++au->au_stamp;
548:
549: /* receive incoming data */
550: cb = &au->au_rb;
551: h = cb->cb_head;
552: t = cb->cb_tail;
553: k = AUCB_MOD(t + 1);
554: if (h == k)
555: cb->cb_drops++;
556: else if (cb->cb_pause != 0)
557: cb->cb_pdrops++;
558: else {
559: cb->cb_data[t] = s_in;
560: cb->cb_tail = t = k;
561: }
562: if (AUCB_MOD(t - h) >= cb->cb_thresh) {
563: cb->cb_thresh = AUCB_SIZE;
564: cb->cb_waking = 1;
565: wakeit = TRUE;
566: }
567: /* send outgoing data */
568: cb = &au->au_wb;
569: h = cb->cb_head;
570: t = cb->cb_tail;
571: k = 0;
572: if (h == t)
573: cb->cb_drops++;
574: else if (cb->cb_pause != 0)
575: cb->cb_pdrops++;
576: else {
577: cb->cb_head = h = AUCB_MOD(h + 1);
578: *s_out = cb->cb_data[h];
579: k = 1;
580: }
581: if (AUCB_MOD(t - h) <= cb->cb_thresh) {
582: cb->cb_thresh = -1;
583: cb->cb_waking = 1;
584: wakeit = TRUE;
585: }
586: if (wakeit)
587: audio_swintr((struct audio_softc *) status);
588: return (k == 1);
589: }
590:
591: private void
592: audio_swintr(
593: register struct audio_softc *sc)
594: {
595: register au_io_t *au = sc->sc_au;
596:
597: if (au->au_rb.cb_waking != 0) {
598: au->au_rb.cb_waking = 0;
599: wakeup(&au->au_rb);
600: }
601: if (au->au_wb.cb_waking != 0) {
602: au->au_wb.cb_waking = 0;
603: wakeup(&au->au_wb);
604: }
605: }
606:
607: private int
608: audio_setinfo(
609: struct audio_softc *sc,
610: audio_info_t *ai)
611: {
612: struct audio_prinfo *r = &ai->record, *p = &ai->play;
613: register int bsize;
614: register au_io_t *au = sc->sc_au;
615: spl_t s;
616:
617: (*sc->ops->setgains)(sc->hw, p->gain, r->gain, ai->monitor_gain );
618:
619: if (p->pause != (unsigned char)~0)
620: au->au_wb.cb_pause = p->pause;
621: if (r->pause != (unsigned char)~0)
622: au->au_rb.cb_pause = r->pause;
623:
624: if (p->port != ~0)
625: (*sc->ops->setport)(sc->hw, p->port);
626:
627: if (ai->blocksize != ~0) {
628: if (ai->blocksize == 0)
629: bsize = ai->blocksize = DEFBLKSIZE;
630: else if (ai->blocksize > MAXBLKSIZE)
631: bsize = ai->blocksize = MAXBLKSIZE;
632: else
633: bsize = ai->blocksize;
634:
635: s = splaudio();
636: au->au_blksize = bsize;
637: /* AUDIO_FLUSH */
638: AUCB_INIT(&au->au_rb);
639: AUCB_INIT(&au->au_wb);
640: splx(s);
641:
642: }
643: if (ai->hiwat != ~0 && (unsigned)ai->hiwat < AUCB_SIZE)
644: au->au_hiwat = ai->hiwat;
645: if (ai->lowat != ~0 && ai->lowat < AUCB_SIZE)
646: au->au_lowat = ai->lowat;
647: if (ai->backlog != ~0 && ai->backlog < (AUCB_SIZE/2))
648: au->au_backlog = ai->backlog;
649:
650: return (0);
651: }
652:
653: private int
654: audio_getinfo(
655: struct audio_softc *sc,
656: audio_info_t *ai)
657: {
658: struct audio_prinfo *r = &ai->record, *p = &ai->play;
659: register au_io_t *au = sc->sc_au;
660:
661: p->sample_rate = r->sample_rate = 8000;
662: p->channels = r->channels = 1;
663: p->precision = r->precision = 8;
664: p->encoding = r->encoding = AUDIO_ENCODING_ULAW;
665:
666: (*sc->ops->getgains)(sc->hw, &p->gain, &r->gain, &ai->monitor_gain );
667:
668: r->port = AUDIO_MIKE;
669: p->port = (*sc->ops->getport)(sc->hw);
670:
671: p->pause = au->au_wb.cb_pause;
672: r->pause = au->au_rb.cb_pause;
673: p->error = au->au_wb.cb_drops != 0;
674: r->error = au->au_rb.cb_drops != 0;
675:
676: /* Now this is funny. If you got here it means you must have
677: opened the device, so how could it possibly be closed ?
678: Unless we upgrade the berkeley code to check if the chip
679: is currently playing and/or recording... Later. */
680: p->open = TRUE;
681: r->open = TRUE;
682:
683: p->samples = au->au_stamp - au->au_wb.cb_pdrops;
684: r->samples = au->au_stamp - au->au_rb.cb_pdrops;
685:
686: p->seek = sc->sc_wseek;
687: r->seek = sc->sc_rseek;
688:
689: ai->blocksize = au->au_blksize;
690: ai->hiwat = au->au_hiwat;
691: ai->lowat = au->au_lowat;
692: ai->backlog = au->au_backlog;
693:
694: return (0);
695: }
696:
697: #if MACH_KDB
698: #include <ddb/db_output.h>
699:
700: void audio_queue_status( au_cb_t *cb, char *logo)
701: {
702: db_printf("%s ring status:\n", logo);
703: db_printf(" h %x t %x sh %x w %d p %d d %x pd %x\n",
704: cb->cb_head, cb->cb_tail, cb->cb_thresh,
705: cb->cb_waking, cb->cb_pause, (long)cb->cb_drops,
706: (long)cb->cb_pdrops);
707: }
708:
709: int audio_status(int unit)
710: {
711: struct audio_softc *sc = unit_to_softc(unit);
712: au_io_t *au;
713:
714: if (!sc) {
715: db_printf("No such thing\n");
716: return 0;
717: }
718: db_printf("@%lx: wseek %d rseek %d, au @%lx\n",
719: sc, sc->sc_wseek, sc->sc_rseek, sc->sc_au);
720: if (!(au = sc->sc_au)) return 0;
721:
722: db_printf("au: stamp %x lo %x hi %x blk %x blg %x\n",
723: au->au_stamp, au->au_lowat, au->au_hiwat,
724: au->au_blksize, au->au_backlog);
725: audio_queue_status(&au->au_rb, "read");
726: audio_queue_status(&au->au_wb, "write");
727:
728: return 0;
729: }
730: #endif /* MACH_KDB */
731:
732: #endif /* NAUDIO > 0 */
733:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.