patch-1.3.9 linux/drivers/sound/audio.c
Next file: linux/drivers/sound/configure.c
Previous file: linux/drivers/sound/aedsp16.c
Back to the patch index
Back to the overall index
- Lines: 284
- Date:
Mon Jul 10 01:45:04 1995
- Orig file:
v1.3.8/linux/drivers/sound/audio.c
- Orig date:
Mon Jul 18 09:50:55 1994
diff -u --recursive --new-file v1.3.8/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
@@ -33,11 +33,13 @@
#ifndef EXCLUDE_AUDIO
#include "ulaw.h"
+#include "coproc.h"
#define ON 1
#define OFF 0
static int wr_buff_no[MAX_AUDIO_DEV]; /*
+
* != -1, if there is
* a incomplete output
* block in the queue.
@@ -45,6 +47,7 @@
static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
static int audio_mode[MAX_AUDIO_DEV];
+static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in noblocking mode */
#define AM_NONE 0
#define AM_WRITE 1
@@ -98,6 +101,16 @@
if ((ret = DMAbuf_open (dev, mode)) < 0)
return ret;
+ if (audio_devs[dev]->coproc)
+ if ((ret = audio_devs[dev]->coproc->
+ open (audio_devs[dev]->coproc->devc, COPR_PCM)) < 0)
+ {
+ audio_release (dev, file);
+ printk ("Sound: Can't access coprocessor device\n");
+
+ return ret;
+ }
+
local_conversion[dev] = 0;
if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
@@ -115,6 +128,8 @@
wr_buff_no[dev] = -1;
audio_mode[dev] = AM_NONE;
+ wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
+ dev_nblock[dev] = 0;
return ret;
}
@@ -134,6 +149,8 @@
wr_buff_no[dev] = -1;
}
+ if (audio_devs[dev]->coproc)
+ audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM);
DMAbuf_release (dev, mode);
}
@@ -155,9 +172,9 @@
"1:\tlodsb\n\t"
"xlatb\n\t"
"stosb\n\t"
- "loop 1b\n\t":
- :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
- :"bx", "cx", "di", "si", "ax");
+"loop 1b\n\t":
+: "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
+: "bx", "cx", "di", "si", "ax");
}
#endif
@@ -203,8 +220,13 @@
* There is no incomplete buffers
*/
{
- if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)
+ if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev],
+ &wr_buff_size[dev],
+ dev_nblock[dev])) < 0)
{
+ /* Handle nonblocking mode */
+ if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EAGAIN))
+ return p; /* No more space. Return # of accepted bytes */
return wr_buff_no[dev];
}
wr_buff_ptr[dev] = 0;
@@ -284,8 +306,16 @@
while (c)
{
- if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l)) < 0)
- return buff_no;
+ if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
+ dev_nblock[dev])) < 0)
+ {
+ /* Nonblocking mode handling. Return current # of bytes */
+
+ if (dev_nblock[dev] && buff_no == RET_ERROR (EAGAIN))
+ return p;
+
+ return buff_no;
+ }
if (l > c)
l = c;
@@ -324,56 +354,149 @@
dev = dev >> 4;
- switch (cmd)
+ if (((cmd >> 8) & 0xff) == 'C')
{
- case SNDCTL_DSP_SYNC:
- if (wr_buff_no[dev] >= 0)
+ if (audio_devs[dev]->coproc) /* Coprocessor ioctl */
+ return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
+ else
+ printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
+
+ return RET_ERROR (EREMOTEIO);
+ }
+ else
+ switch (cmd)
+ {
+ case SNDCTL_DSP_SYNC:
+ if (wr_buff_no[dev] >= 0)
+ {
+ DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+
+ wr_buff_no[dev] = -1;
+ }
+ return DMAbuf_ioctl (dev, cmd, arg, 0);
+ break;
+
+ case SNDCTL_DSP_POST:
+ if (wr_buff_no[dev] >= 0)
+ {
+ DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+
+ wr_buff_no[dev] = -1;
+ }
+ return 0;
+ break;
+
+ case SNDCTL_DSP_RESET:
+ wr_buff_no[dev] = -1;
+ return DMAbuf_ioctl (dev, cmd, arg, 0);
+ break;
+
+ case SNDCTL_DSP_GETFMTS:
+ return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
+ break;
+
+ case SNDCTL_DSP_SETFMT:
+ return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
+
+ case SNDCTL_DSP_GETISPACE:
+ if (audio_mode[dev] == AM_WRITE)
+ return RET_ERROR (EBUSY);
+
{
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ audio_buf_info info;
- wr_buff_no[dev] = -1;
+ int err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
+
+ if (err < 0)
+ return err;
+
+ if (wr_buff_no[dev] != -1)
+ info.bytes += wr_buff_ptr[dev];
+
+ IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
+ return 0;
}
- return DMAbuf_ioctl (dev, cmd, arg, 0);
- break;
- case SNDCTL_DSP_POST:
- if (wr_buff_no[dev] >= 0)
+ case SNDCTL_DSP_GETOSPACE:
+ if (audio_mode[dev] == AM_READ)
+ return RET_ERROR (EBUSY);
+
{
- DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
+ audio_buf_info info;
- wr_buff_no[dev] = -1;
- }
- return 0;
- break;
+ int err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
- case SNDCTL_DSP_RESET:
- wr_buff_no[dev] = -1;
- return DMAbuf_ioctl (dev, cmd, arg, 0);
- break;
+ if (err < 0)
+ return err;
- case SNDCTL_DSP_GETFMTS:
- return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
- break;
+ if (wr_buff_no[dev] != -1)
+ info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
- case SNDCTL_DSP_SETFMT:
- return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
+ IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
+ return 0;
+ }
- default:
- return DMAbuf_ioctl (dev, cmd, arg, 0);
- break;
- }
+ case SNDCTL_DSP_NONBLOCK:
+ dev_nblock[dev] = 1;
+ return 0;
+ break;
+
+ default:
+ return DMAbuf_ioctl (dev, cmd, arg, 0);
+ }
}
long
audio_init (long mem_start)
{
/*
- * NOTE! This routine could be called several times during boot.
- */
+ * NOTE! This routine could be called several times during boot.
+ */
return mem_start;
}
-#else
+#ifdef ALLOW_SELECT
+int
+audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+{
+ int l;
+ char *dmabuf;
+
+ dev = dev >> 4;
+
+ switch (sel_type)
+ {
+ case SEL_IN:
+ if (audio_mode[dev] != AM_READ) /* Wrong direction */
+ return 0;
+
+ if (DMAbuf_getrdbuffer (dev, &dmabuf, &l,
+ 1 /* Don't block */ ) >= 0)
+ return 1; /* We have data */
+
+ return DMAbuf_select (dev, file, sel_type, wait);
+ break;
+
+ case SEL_OUT:
+ if (audio_mode[dev] != AM_WRITE) /* Wrong direction */
+ return 0;
+
+ if (wr_buff_no[dev] != -1)
+ return 1; /* There is space in the current buffer */
+
+ return DMAbuf_select (dev, file, sel_type, wait);
+ break;
+
+ case SEL_EX:
+ return 0;
+ }
+
+ return 0;
+}
+
+#endif /* ALLOW_SELECT */
+
+#else /* EXCLUDE_AUDIO */
/*
* Stub versions
*/
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this