patch-1.3.34 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

diff -u --recursive --new-file v1.3.33/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
@@ -74,7 +74,7 @@
 	else
 	  fmt = AFMT_U8;	/* This is always supported */
 
-      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1);
+      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1);
     }
 
   if (local_conversion[dev])	/* This shadows the HW format */
@@ -113,10 +113,10 @@
 
   local_conversion[dev] = 0;
 
-  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
+  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits)
     {
       audio_release (dev, file);
-      return RET_ERROR (ENXIO);
+      return -ENXIO;
     }
 
   if (dev_type == SND_DEV_AUDIO)
@@ -156,31 +156,37 @@
 
 #ifdef NO_INLINE_ASM
 static void
-translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
+translate_bytes (const unsigned char *table, unsigned char *buff, int n)
 {
   unsigned long   i;
 
+  if (n <= 0)
+    return;
+
   for (i = 0; i < n; ++i)
     buff[i] = table[buff[i]];
 }
 
 #else
 extern inline void
-translate_bytes (const void *table, void *buff, unsigned long n)
+translate_bytes (const void *table, void *buff, int n)
 {
-  __asm__ ("cld\n"
-	   "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");
+  if (n > 0)
+    {
+      __asm__ ("cld\n"
+	       "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");
+    }
 }
 
 #endif
 
 int
-audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
   int             c, p, l;
   int             err;
@@ -190,14 +196,15 @@
   p = 0;
   c = count;
 
-  if (audio_mode[dev] == AM_READ)	/*
-					 * Direction changed
-					 */
-    {
+  if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+    {				/* Direction change */
       wr_buff_no[dev] = -1;
     }
 
-  audio_mode[dev] = AM_WRITE;
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    audio_mode[dev] |= AM_WRITE;
+  else
+    audio_mode[dev] = AM_WRITE;
 
   if (!count)			/*
 				 * Flush output
@@ -225,7 +232,7 @@
 						     dev_nblock[dev])) < 0)
 	    {
 	      /* Handle nonblocking mode */
-	      if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EAGAIN))
+	      if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN)
 		return p;	/* No more space. Return # of accepted bytes */
 	      return wr_buff_no[dev];
 	    }
@@ -240,7 +247,7 @@
 	{			/*
 				 * No device specific copy routine
 				 */
-	  COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
+	  memcpy_fromfs ((&wr_dma_buf[dev][wr_buff_ptr[dev]]), &((buf)[p]), (l));
 	}
       else
 	audio_devs[dev]->copy_from_user (dev,
@@ -253,12 +260,10 @@
 
       if (local_conversion[dev] == AFMT_MU_LAW)
 	{
-#ifdef linux
 	  /*
 	   * This just allows interrupts while the conversion is running
 	   */
 	  __asm__ ("sti");
-#endif
 	  translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
 	}
 
@@ -292,17 +297,21 @@
   p = 0;
   c = count;
 
-  if (audio_mode[dev] == AM_WRITE)
+  if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
     {
       if (wr_buff_no[dev] >= 0)
 	{
 	  DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 
-	  wr_buff_no[dev] = -1;
+	  if (!(audio_devs[dev]->flags & DMA_DUPLEX))
+	    wr_buff_no[dev] = -1;
 	}
     }
 
-  audio_mode[dev] = AM_READ;
+  if (audio_devs[dev]->flags & DMA_DUPLEX)
+    audio_mode[dev] |= AM_READ;
+  else
+    audio_mode[dev] = AM_READ;
 
   while (c)
     {
@@ -311,7 +320,7 @@
 	{
 	  /* Nonblocking mode handling. Return current # of bytes */
 
-	  if (dev_nblock[dev] && buff_no == RET_ERROR (EAGAIN))
+	  if (dev_nblock[dev] && buff_no == -EAGAIN)
 	    return p;
 
 	  return buff_no;
@@ -326,17 +335,15 @@
 
       if (local_conversion[dev] == AFMT_MU_LAW)
 	{
-#ifdef linux
 	  /*
 	   * This just allows interrupts while the conversion is running
 	   */
 	  __asm__ ("sti");
-#endif
 
 	  translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 	}
 
-      COPY_TO_USER (buf, p, dmabuf, l);
+      memcpy_tofs (&((buf)[p]), (dmabuf), (l));
 
       DMAbuf_rmchars (dev, buff_no, l);
 
@@ -349,7 +356,7 @@
 
 int
 audio_ioctl (int dev, struct fileinfo *file,
-	     unsigned int cmd, unsigned int arg)
+	     unsigned int cmd, ioctl_arg arg)
 {
 
   dev = dev >> 4;
@@ -361,7 +368,7 @@
       else
 	printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 
-      return RET_ERROR (EREMOTEIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
@@ -388,40 +395,41 @@
 
       case SNDCTL_DSP_RESET:
 	wr_buff_no[dev] = -1;
+	audio_mode[dev] = AM_NONE;
 	return DMAbuf_ioctl (dev, cmd, arg, 0);
 	break;
 
       case SNDCTL_DSP_GETFMTS:
-	return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
+	return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask);
 	break;
 
       case SNDCTL_DSP_SETFMT:
-	return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
+	return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
 
       case SNDCTL_DSP_GETISPACE:
-	if (audio_mode[dev] == AM_WRITE)
-	  return RET_ERROR (EBUSY);
+	if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	  return -EBUSY;
 
 	{
 	  audio_buf_info  info;
 
-	  int             err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
+	  int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 
 	  if (err < 0)
 	    return err;
 
-	  IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
+	  memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
 	  return 0;
 	}
 
       case SNDCTL_DSP_GETOSPACE:
-	if (audio_mode[dev] == AM_READ)
-	  return RET_ERROR (EBUSY);
+	if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	  return -EBUSY;
 
 	{
 	  audio_buf_info  info;
 
-	  int             err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
+	  int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 
 	  if (err < 0)
 	    return err;
@@ -429,7 +437,7 @@
 	  if (wr_buff_no[dev] != -1)
 	    info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
 
-	  IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
+	  memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
 	  return 0;
 	}
 
@@ -438,6 +446,27 @@
 	return 0;
 	break;
 
+      case SNDCTL_DSP_GETCAPS:
+	{
+	  int             info = 1;	/* Revision level of this ioctl() */
+
+	  if (audio_devs[dev]->flags & DMA_DUPLEX)
+	    info |= DSP_CAP_DUPLEX;
+
+	  if (audio_devs[dev]->coproc)
+	    info |= DSP_CAP_COPROC;
+
+	  if (audio_devs[dev]->local_qlen)	/* Device has hidden buffers */
+	    info |= DSP_CAP_BATCH;
+
+	  if (audio_devs[dev]->trigger)		/* Supports SETTRIGGER */
+	    info |= DSP_CAP_TRIGGER;
+
+	  memcpy_tofs (&(((char *) arg)[0]), ((char *) &info), (sizeof (info)));
+	  return 0;
+	}
+	break;
+
       default:
 	return DMAbuf_ioctl (dev, cmd, arg, 0);
       }
@@ -452,31 +481,25 @@
   return mem_start;
 }
 
-#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 (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	return 0;		/* Not recording */
 
-      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_READ)	/* Wrong direction */
-	return 0;
+      if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	return 0;		/* Wrong direction */
 
       if (wr_buff_no[dev] != -1)
 	return 1;		/* There is space in the current buffer */
@@ -491,7 +514,6 @@
   return 0;
 }
 
-#endif /* ALLOW_SELECT */
 
 #else /* EXCLUDE_AUDIO */
 /*
@@ -501,19 +523,19 @@
 int
 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 audio_open (int dev, struct fileinfo *file)
 {
-  return RET_ERROR (ENXIO);
+  return -ENXIO;
 }
 
 void
@@ -524,13 +546,13 @@
 audio_ioctl (int dev, struct fileinfo *file,
 	     unsigned int cmd, unsigned int arg)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 int
 audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
 {
-  return RET_ERROR (EIO);
+  return -EIO;
 }
 
 long

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