4 * Device file manager for /dev/audio
6 * Copyright by Hannu Savolainen 1993
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 2.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <i386/isa/sound/sound_config.h>
34 #include <i386/isa/sound/ulaw.h>
35 #include <i386/isa/sound/coproc.h>
40 DMAbuf_poll(int dev, struct fileinfo * file, int events, select_table * wait);
43 audio_poll(int dev, struct fileinfo * file, int events, select_table * wait);
45 static int wr_buff_no[MAX_AUDIO_DEV];
46 /* != -1, if there is a incomplete output block in the queue. */
47 static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
49 static int audio_mode[MAX_AUDIO_DEV];
50 static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in noblocking mode */
56 static char *wr_dma_buf[MAX_AUDIO_DEV];
57 static int audio_format[MAX_AUDIO_DEV];
58 static int local_conversion[MAX_AUDIO_DEV];
61 set_format(int dev, int fmt)
63 if (fmt != AFMT_QUERY) {
65 local_conversion[dev] = 0;
67 if (!(audio_devs[dev]->format_mask & fmt)) { /* Not supported */
68 if (fmt == AFMT_MU_LAW) {
70 local_conversion[dev] = AFMT_MU_LAW;
72 fmt = AFMT_U8; /* This is always supported */
74 audio_format[dev] = DMAbuf_ioctl(dev, SNDCTL_DSP_SETFMT,
77 if (local_conversion[dev]) /* This shadows the HW format */
78 return local_conversion[dev];
80 return audio_format[dev];
84 audio_open(int dev, struct fileinfo * file)
88 int dev_type = dev & 0x0f;
89 int mode = file->mode & O_ACCMODE;
93 bits = (dev_type == SND_DEV_DSP16) ? 16 : 8 ;
95 if ((ret = DMAbuf_open(dev, mode)) < 0)
98 if (audio_devs[dev]->coproc)
99 if ((ret = audio_devs[dev]->coproc->
100 open(audio_devs[dev]->coproc->devc, COPR_PCM)) < 0) {
101 audio_release(dev, file);
102 printf("Sound: Can't access coprocessor device\n");
106 local_conversion[dev] = 0;
108 if (DMAbuf_ioctl(dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits) {
109 audio_release(dev, file);
113 set_format(dev, (dev_type == SND_DEV_AUDIO) ? AFMT_MU_LAW : bits ) ;
115 wr_buff_no[dev] = -1;
116 audio_mode[dev] = AM_NONE;
117 wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
124 audio_release(int dev, struct fileinfo * file)
129 mode = file->mode & O_ACCMODE;
131 if (wr_buff_no[dev] >= 0) {
132 DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
133 wr_buff_no[dev] = -1;
135 if (audio_devs[dev]->coproc)
136 audio_devs[dev]->coproc->close(audio_devs[dev]->coproc->devc,COPR_PCM);
137 DMAbuf_release(dev, mode);
138 audio_devs[dev]->dmap_out->mapping_flags &= ~DMA_MAP_MAPPED ;
143 translate_bytes(const u_char *table, u_char *buff, int n)
150 for (i = 0; i < n; ++i)
151 buff[i] = table[buff[i]];
155 audio_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
164 if ((audio_mode[dev] & AM_READ) &&
165 !(audio_devs[dev]->flags & DMA_DUPLEX)) { /* Direction change */
166 wr_buff_no[dev] = -1;
168 if (audio_devs[dev]->flags & DMA_DUPLEX)
169 audio_mode[dev] |= AM_WRITE;
171 audio_mode[dev] = AM_WRITE;
173 if (!count) { /* Flush output */
174 if (wr_buff_no[dev] >= 0) {
175 DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
176 wr_buff_no[dev] = -1;
180 while (c) { /* Perform output blocking */
181 if (wr_buff_no[dev] < 0) {
182 /* There is no incomplete buffers */
183 if ((wr_buff_no[dev] = DMAbuf_getwrbuffer(dev,
184 &wr_dma_buf[dev], &wr_buff_size[dev],
185 dev_nblock[dev])) < 0) {
186 /* Handle nonblocking mode */
187 if (dev_nblock[dev] && wr_buff_no[dev] == -(EAGAIN))
188 return p; /* No more space. Return # of accepted bytes */
189 return wr_buff_no[dev];
191 wr_buff_ptr[dev] = 0;
194 if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
195 l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
197 if (!audio_devs[dev]->copy_from_user) { /* No device specific
200 if (uiomove(&wr_dma_buf[dev][wr_buff_ptr[dev]], l, buf)) {
201 printf("sb: Bad copyin()!\n");
204 audio_devs[dev]->copy_from_user(dev,
205 wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
209 * Insert local processing here
212 if (local_conversion[dev] == AFMT_MU_LAW) {
213 translate_bytes(ulaw_dsp,
214 (u_char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
218 wr_buff_ptr[dev] += l;
220 if (wr_buff_ptr[dev] >= wr_buff_size[dev]) {
221 if ((err = DMAbuf_start_output(dev, wr_buff_no[dev],
222 wr_buff_ptr[dev])) < 0) {
225 wr_buff_no[dev] = -1;
232 audio_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
241 if ((audio_mode[dev] & AM_WRITE) &&
242 !(audio_devs[dev]->flags & DMA_DUPLEX)) {
243 if (wr_buff_no[dev] >= 0) {
244 DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
246 if (!(audio_devs[dev]->flags & DMA_DUPLEX))
247 wr_buff_no[dev] = -1;
250 if (audio_devs[dev]->flags & DMA_DUPLEX)
251 audio_mode[dev] |= AM_READ;
253 audio_mode[dev] = AM_READ;
256 if ((buff_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l,
257 dev_nblock[dev])) < 0) {
259 * Nonblocking mode handling. Return current # of bytes
262 if (dev_nblock[dev] && buff_no == -(EAGAIN))
271 * Insert any local processing here.
274 if (local_conversion[dev] == AFMT_MU_LAW) {
275 translate_bytes(dsp_ulaw, (u_char *) dmabuf, l);
277 if (uiomove(dmabuf, l, buf)) {
278 printf("sb: Bad copyout()!\n");
281 DMAbuf_rmchars(dev, buff_no, l);
290 audio_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
293 if (((cmd >> 8) & 0xff) == 'C') {
294 if (audio_devs[dev]->coproc) /* Coprocessor ioctl */
295 return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0);
297 printf("/dev/dsp%d: No coprocessor for this device\n", dev);
303 case SNDCTL_DSP_SYNC:
304 if (wr_buff_no[dev] >= 0) {
305 DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
306 wr_buff_no[dev] = -1;
308 return DMAbuf_ioctl(dev, cmd, arg, 0);
311 case SNDCTL_DSP_POST:
312 if (wr_buff_no[dev] >= 0) {
313 DMAbuf_start_output(dev, wr_buff_no[dev], wr_buff_ptr[dev]);
314 wr_buff_no[dev] = -1;
319 case SNDCTL_DSP_RESET:
320 wr_buff_no[dev] = -1;
321 audio_mode[dev] = AM_NONE;
322 return DMAbuf_ioctl(dev, cmd, arg, 0);
325 case SNDCTL_DSP_GETFMTS:
326 return *(int *) arg = audio_devs[dev]->format_mask;
329 case SNDCTL_DSP_SETFMT:
330 return *(int *) arg = set_format(dev, (*(int *) arg));
332 case SNDCTL_DSP_GETISPACE:
333 if ((audio_mode[dev] & AM_WRITE) &&
334 !(audio_devs[dev]->flags & DMA_DUPLEX))
339 int err = DMAbuf_ioctl(dev, cmd, (ioctl_arg) & info, 1);
344 bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
348 case SNDCTL_DSP_GETOSPACE:
349 if ((audio_mode[dev] & AM_READ) &&
350 !(audio_devs[dev]->flags & DMA_DUPLEX))
354 int err = DMAbuf_ioctl(dev, cmd, (ioctl_arg) & info, 1);
359 if (wr_buff_no[dev] != -1)
360 info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
362 bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
366 case SNDCTL_DSP_NONBLOCK:
371 case SNDCTL_DSP_GETCAPS:
373 int info = 1; /* Revision level of this ioctl() */
375 if (audio_devs[dev]->flags & DMA_DUPLEX)
376 info |= DSP_CAP_DUPLEX;
378 if (audio_devs[dev]->coproc)
379 info |= DSP_CAP_COPROC;
381 if (audio_devs[dev]->local_qlen) /* Dev. has hidden buffs */
382 info |= DSP_CAP_BATCH;
384 if (audio_devs[dev]->trigger) /* Supports SETTRIGGER */
385 info |= DSP_CAP_TRIGGER;
387 info |= DSP_CAP_MMAP;
388 bcopy((char *) &info, &(((char *) arg)[0]), sizeof(info));
395 return *(int *) arg = 1;
398 return *(int *) arg = 1;
401 return DMAbuf_ioctl(dev, cmd, arg, 0);
407 * XXX should we use spltty() in the select calls ? - lr970714
412 audio_poll(int dev, struct fileinfo * file, int events, select_table * wait)
416 if (events & (POLLIN | POLLRDNORM)) {
417 if ((audio_mode[dev] & AM_WRITE) &&
418 !(audio_devs[dev]->flags & DMA_DUPLEX))
419 return 0; /* Not recording */
422 return (DMAbuf_poll(dev, file, events, wait));
425 if (events & (POLLOUT | POLLWRNORM)) {
426 if ((audio_mode[dev] & AM_READ) &&
427 !(audio_devs[dev]->flags & DMA_DUPLEX))
428 return 0; /* Wrong direction */
430 if (wr_buff_no[dev] != -1)
431 return 1; /* There is space in the current buffer */
433 return ( DMAbuf_poll(dev, file, events, wait) );
438 #endif /* ALLOW_POLL */