audio.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:104k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: audio.c,v 1.62 2001/10/08 22:19:50 davem Exp $
  2.  * drivers/sbus/audio/audio.c
  3.  *
  4.  * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
  5.  * Copyright 1997,1998,1999 Derrick J. Brashear (shadow@dementia.org)
  6.  * Copyright 1997 Brent Baccala (baccala@freesoft.org)
  7.  * 
  8.  * Mixer code adapted from code contributed by and
  9.  * Copyright 1998 Michael Mraka (michael@fi.muni.cz)
  10.  * and with fixes from Michael Shuey (shuey@ecn.purdue.edu)
  11.  * The mixer code cheats; Sparc hardware doesn't generally allow independent
  12.  * line control, and this fakes it badly.
  13.  *
  14.  * SNDCTL_DSP_SETFMT based on code contributed by
  15.  * Ion Badulescu (ionut@moisil.cs.columbia.edu)
  16.  *
  17.  * This is the audio midlayer that sits between the VFS character
  18.  * devices and the low-level audio hardware device drivers.
  19.  */
  20. #include <linux/config.h>
  21. #include <linux/module.h>
  22. #include <linux/errno.h>
  23. #include <linux/fs.h>
  24. #include <linux/kernel.h>
  25. #include <linux/sched.h>
  26. #include <linux/smp_lock.h>
  27. #include <linux/mm.h>
  28. #include <linux/tqueue.h>
  29. #include <linux/major.h>
  30. #include <linux/slab.h>
  31. #include <linux/interrupt.h>
  32. #include <linux/init.h>
  33. #include <linux/soundcard.h>
  34. #include <linux/devfs_fs_kernel.h>
  35. #include <linux/delay.h>
  36. #include <linux/poll.h>
  37. #include <asm/pgtable.h>
  38. #include <asm/uaccess.h>
  39. #include <asm/audioio.h>
  40. #undef __AUDIO_DEBUG
  41. #define __AUDIO_ERROR
  42. #undef __AUDIO_TRACE
  43. #undef __AUDIO_OSSDEBUG
  44. #ifdef __AUDIO_DEBUG
  45. #define dprintk(x) printk x
  46. #else
  47. #define dprintk(x)
  48. #endif
  49. #ifdef __AUDIO_OSSDEBUG
  50. #define oprintk(x) printk x
  51. #else
  52. #define oprintk(x)
  53. #endif
  54. #ifdef __AUDIO_ERROR
  55. #define eprintk(x) printk x
  56. #else
  57. #define eprintk(x)
  58. #endif
  59. #ifdef __AUDIO_TRACE
  60. #define tprintk(x) printk x
  61. #else
  62. #define tprintk(x)
  63. #endif
  64. static short lis_get_elist_ent( strevent_t *list, pid_t pid );
  65. static int lis_add_to_elist( strevent_t **list, pid_t pid, short events );
  66. static int lis_del_from_elist( strevent_t **list, pid_t pid, short events );
  67. static void lis_free_elist( strevent_t **list);
  68. static void kill_procs( struct strevent *elist, int sig, short e);
  69. static struct sparcaudio_driver *drivers[SPARCAUDIO_MAX_DEVICES];
  70. static devfs_handle_t devfs_handle;
  71.  
  72. void sparcaudio_output_done(struct sparcaudio_driver * drv, int status)
  73. {
  74.         /* If !status, just restart current output.
  75.          * If status & 1, a buffer is finished; make it available again.
  76.          * If status & 2, a buffer was claimed for DMA and is still in use.
  77.          *
  78.          * The playing_count for non-DMA hardware should never be non-zero.
  79.          * Value of status for non-DMA hardware should always be 1.
  80.          */
  81.         if (status & 1) {
  82.                 if (drv->playing_count) {
  83.                         drv->playing_count--;
  84.                 } else {
  85.                         drv->output_count--;
  86.                         drv->output_size -= drv->output_sizes[drv->output_front];
  87.                         if (drv->output_notify[drv->output_front] == 1) {
  88.                                 drv->output_eof++;
  89.                                 drv->output_notify[drv->output_front] = 0;
  90.                                 kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  91.                         }
  92.                         drv->output_front = (drv->output_front + 1) % 
  93.                                 drv->num_output_buffers;
  94.                 }
  95.         }
  96.     
  97.         if (status & 2) {
  98.                 drv->output_count--;
  99.                 drv->playing_count++;
  100.                 drv->output_size -= drv->output_sizes[drv->output_front];
  101.                 if (drv->output_notify[drv->output_front] == 1) {
  102.                         drv->output_eof++;
  103.                         drv->output_notify[drv->output_front] = 0;
  104.                         kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  105.                 }
  106.                 drv->output_front = (drv->output_front + 1) % 
  107.                         drv->num_output_buffers;
  108.         }
  109.         /* If we've played everything go inactive. */
  110.         if ((drv->output_count < 1) && (drv->playing_count < 1)) 
  111.                 drv->output_active = 0;
  112.         /* If we got back a buffer, see if anyone wants to write to it */
  113.         if ((status & 1) || ((drv->output_count + drv->playing_count) 
  114.                              < drv->num_output_buffers)) {
  115.                 wake_up_interruptible(&drv->output_write_wait);
  116.         }
  117.         /* If the output queue is empty, shut down the driver. */
  118.         if ((drv->output_count < 1) && (drv->playing_count < 1)) {
  119.                 kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  120.                 /* Stop the lowlevel driver from outputing. */
  121.                 /* drv->ops->stop_output(drv); Should not be necessary  -- DJB 5/25/98 */
  122.                 drv->output_active = 0;
  123.   
  124.                 /* Wake up any waiting writers or syncers and return. */
  125.                 wake_up_interruptible(&drv->output_write_wait);
  126.                 wake_up_interruptible(&drv->output_drain_wait);
  127.                 return;
  128.         }
  129.         /* Start next block of output if we have it */
  130.         if (drv->output_count > 0) {
  131.                 drv->ops->start_output(drv, drv->output_buffers[drv->output_front],
  132.                                        drv->output_sizes[drv->output_front]);
  133.                 drv->output_active = 1;
  134.         } else {
  135.                 drv->output_active = 0;
  136.         }
  137. }
  138. void sparcaudio_input_done(struct sparcaudio_driver * drv, int status)
  139. {
  140.         /* Deal with the weird case here */
  141.         if (drv->duplex == 2) {
  142.                 if (drv->input_count < drv->num_input_buffers)
  143.                         drv->input_count++;
  144.                 drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
  145.                                       drv->input_buffer_size);
  146.                 wake_up_interruptible(&drv->input_read_wait);
  147.                 return;
  148.         } 
  149.         /* If status % 2, they filled a buffer for us. 
  150.          * If status & 2, they took a buffer from us.
  151.          */
  152.         if ((status % 2) == 1) {
  153.                 drv->input_count++;
  154.                 drv->recording_count--;
  155.                 drv->input_size+=drv->input_buffer_size;
  156.         }
  157.         if (status > 1) {
  158.                 drv->recording_count++;
  159.                 drv->input_front = (drv->input_front + 1) % drv->num_input_buffers;
  160.         }
  161.         dprintk(("f%d r%d c%d u%dn",
  162.                  drv->input_front, drv->input_rear,
  163.                  drv->input_count, drv->recording_count));
  164.         /* If the input queue is full, shutdown the driver. */
  165.         if ((drv->input_count + drv->recording_count) == drv->num_input_buffers) {
  166.                 kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  167.                 /* Stop the lowlevel driver from inputing. */
  168.                 drv->ops->stop_input(drv);
  169.                 drv->input_active = 0;
  170.         } else {
  171.                 /* Otherwise, give the driver the next buffer. */
  172.                 drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
  173.                                       drv->input_buffer_size);
  174.         }
  175.         /* Wake up any tasks that are waiting. */
  176.         wake_up_interruptible(&drv->input_read_wait);
  177. }
  178. /*
  179.  * VFS layer interface
  180.  */
  181. static unsigned int sparcaudio_poll(struct file *file, poll_table * wait)
  182. {
  183.         unsigned int mask = 0;
  184.         struct inode *inode = file->f_dentry->d_inode;
  185.         struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
  186.                                                  SPARCAUDIO_DEVICE_SHIFT)];
  187.         poll_wait(file, &drv->input_read_wait, wait);
  188.         poll_wait(file, &drv->output_write_wait, wait);
  189.         if (((!file->f_flags & O_NONBLOCK) && drv->input_count) ||
  190.             (drv->input_size > drv->buffer_size)) {
  191.                 mask |= POLLIN | POLLRDNORM;
  192.         }
  193.         if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) {
  194.                 mask |= POLLOUT | POLLWRNORM;
  195.         }
  196.         return mask;
  197. }
  198. static ssize_t sparcaudio_read(struct file * file, char *buf, 
  199.                                size_t count, loff_t *ppos)
  200. {
  201.         struct inode *inode = file->f_dentry->d_inode;
  202.         struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
  203.                                                  SPARCAUDIO_DEVICE_SHIFT)];
  204.         int bytes_to_copy, bytes_read = 0, err;
  205.         if (! (file->f_mode & FMODE_READ))
  206.                 return -EINVAL;
  207.         if ((file->f_flags & O_NONBLOCK) && (drv->input_size < count))
  208.                 return -EAGAIN;
  209.     
  210.         while (count > 0) {
  211.                 if (drv->input_count == 0) {
  212.                         /* This *should* never happen. */
  213.                         if (file->f_flags & O_NONBLOCK) {
  214.                                 printk("Warning: audio input leak!n");
  215.                                 return -EAGAIN;
  216.                         }
  217.                         interruptible_sleep_on(&drv->input_read_wait);
  218.                         if (signal_pending(current))
  219.                                 return -EINTR;
  220.                 }
  221.   
  222.                 bytes_to_copy = drv->input_buffer_size - drv->input_offset;
  223.                 if (bytes_to_copy > count)
  224.                         bytes_to_copy = count;
  225.                 err = verify_area(VERIFY_WRITE, buf, bytes_to_copy);
  226.                 if (err)
  227.                         return err;
  228.                 copy_to_user(buf, drv->input_buffers[drv->input_rear]+drv->input_offset, 
  229.                              bytes_to_copy);
  230.                 drv->input_offset += bytes_to_copy;
  231.                 drv->input_size -= bytes_to_copy;
  232.                 buf += bytes_to_copy;
  233.                 count -= bytes_to_copy;
  234.                 bytes_read += bytes_to_copy;
  235.                 if (drv->input_offset >= drv->input_buffer_size) {
  236.                         drv->input_rear = (drv->input_rear + 1) % 
  237.                                 drv->num_input_buffers;
  238.                         drv->input_count--;
  239.                         drv->input_offset = 0;
  240.                 }
  241.                 /* If we're in "loop audio" mode, try waking up the other side
  242.                  * in case they're waiting for us to eat a block. 
  243.                  */
  244.                 if (drv->duplex == 2)
  245.                         wake_up_interruptible(&drv->output_write_wait);
  246.         }
  247.         return bytes_read;
  248. }
  249. static void sparcaudio_sync_output(struct sparcaudio_driver * drv)
  250. {
  251.         unsigned long flags;
  252.         /* If the low-level driver is not active, activate it. */
  253.         save_and_cli(flags);
  254.         if ((!drv->output_active) && (drv->output_count > 0)) {
  255.                 drv->ops->start_output(drv, 
  256.                                        drv->output_buffers[drv->output_front],
  257.                                        drv->output_sizes[drv->output_front]);
  258.                 drv->output_active = 1;
  259.         }
  260.         restore_flags(flags);
  261. }
  262. static ssize_t sparcaudio_write(struct file * file, const char *buf,
  263.                                 size_t count, loff_t *ppos)
  264. {
  265.         struct inode *inode = file->f_dentry->d_inode;
  266.         struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
  267.                                                  SPARCAUDIO_DEVICE_SHIFT)];
  268.         int bytes_written = 0, bytes_to_copy, err;
  269.   
  270.         if (! (file->f_mode & FMODE_WRITE))
  271.                 return -EINVAL;
  272.         /* A signal they want notification when this is processed. Too bad
  273.          * sys_write doesn't tell us unless you patch it, in 2.0 kernels.
  274.          */
  275.         if (count == 0) {
  276. #ifndef notdef
  277.                 drv->output_eof++;
  278.                 kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  279. #else
  280.                 /* Nice code, but the world isn't ready yet... */
  281.                 drv->output_notify[drv->output_rear] = 1;
  282. #endif
  283.         }
  284.         /* Loop until all output is written to device. */
  285.         while (count > 0) {
  286.                 /* Check to make sure that an output buffer is available. */
  287.                 if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) {
  288.                         /* We need buffers, so... */
  289.                         sparcaudio_sync_output(drv);
  290.                         if (file->f_flags & O_NONBLOCK)
  291.                                 return -EAGAIN;
  292.                         interruptible_sleep_on(&drv->output_write_wait);
  293.                         if (signal_pending(current))
  294.                                 return bytes_written > 0 ? bytes_written : -EINTR;
  295.                 }
  296.                 /* No buffers were freed. Go back to sleep */
  297.                 if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) 
  298.                         continue;
  299.                 /* Deal with the weird case of a reader in the write area by trying to
  300.                  * let them keep ahead of us... Go to sleep until they start servicing.
  301.                  */
  302.                 if ((drv->duplex == 2) && (drv->flags & SDF_OPEN_READ) &&
  303.                     (drv->output_rear == drv->input_rear) && (drv->input_count > 0)) {
  304.                         if (file->f_flags & O_NONBLOCK)
  305.                                 return -EAGAIN;
  306.                         interruptible_sleep_on(&drv->output_write_wait);
  307.                         if (signal_pending(current))
  308.                                 return bytes_written > 0 ? bytes_written : -EINTR;
  309.                 }
  310.                 /* Determine how much we can copy in this iteration. */
  311.                 bytes_to_copy = count;
  312.                 if (bytes_to_copy > drv->output_buffer_size - drv->output_offset)
  313.                         bytes_to_copy = drv->output_buffer_size - drv->output_offset;
  314.     
  315.                 err = verify_area(VERIFY_READ, buf, bytes_to_copy);
  316.                 if (err)
  317.                         return err;
  318.                 copy_from_user(drv->output_buffers[drv->output_rear]+drv->output_offset,
  319.                                buf, bytes_to_copy);
  320.     
  321.                 /* Update the queue pointers. */
  322.                 buf += bytes_to_copy;
  323.                 count -= bytes_to_copy;
  324.                 bytes_written += bytes_to_copy;
  325.                 /* A block can get orphaned in a flush and not cleaned up. */
  326.                 if (drv->output_offset)
  327.                         drv->output_sizes[drv->output_rear] += bytes_to_copy;
  328.                 else
  329.                         drv->output_sizes[drv->output_rear] = bytes_to_copy;
  330.                 drv->output_notify[drv->output_rear] = 0;
  331.                 if (drv->output_sizes[drv->output_rear] == drv->output_buffer_size) {
  332.                         drv->output_rear = (drv->output_rear + 1) 
  333.                                 % drv->num_output_buffers;
  334.                         drv->output_count++;
  335.                         drv->output_offset = 0;
  336.                 } else {
  337.                         drv->output_offset += bytes_to_copy;
  338.                 }
  339.                 drv->output_size += bytes_to_copy;
  340.         }
  341.         sparcaudio_sync_output(drv);
  342.   
  343.         /* Return the number of bytes written to the caller. */
  344.         return bytes_written;
  345. }
  346. /* Add these in as new devices are supported. Belongs in audioio.h, actually */
  347. #define MONO_DEVICES (SOUND_MASK_SPEAKER | SOUND_MASK_MIC)
  348. static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file,
  349.                                   unsigned int cmd, unsigned int *arg)
  350. {
  351.         struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
  352.                                                  SPARCAUDIO_DEVICE_SHIFT)];
  353.         unsigned long i = 0, j = 0, l = 0, m = 0;
  354.         unsigned int k = 0;
  355.         if (_SIOC_DIR(cmd) & _SIOC_WRITE)
  356.                 drv->mixer_modify_counter++;
  357.         if(cmd == SOUND_MIXER_INFO) {
  358.                 audio_device_t tmp;
  359.                 mixer_info info;
  360.                 int retval = -EINVAL;
  361.                 if(drv->ops->sunaudio_getdev) {
  362.                         drv->ops->sunaudio_getdev(drv, &tmp);
  363.                         memset(&info, 0, sizeof(info));
  364.                         strncpy(info.id, tmp.name, sizeof(info.id));
  365.                         strncpy(info.name, "Sparc Audio", sizeof(info.name));
  366.                         info.modify_counter = drv->mixer_modify_counter;
  367.                         if(copy_to_user((char *)arg, &info, sizeof(info)))
  368.                                 retval = -EFAULT;
  369.                         else
  370.                                 retval = 0;
  371.                 }
  372.                 return retval;
  373.   }
  374.         switch (cmd) {
  375.         case SOUND_MIXER_WRITE_RECLEV:
  376.                 if (get_user(k, (int *)arg))
  377.                         return -EFAULT;
  378.         iretry:
  379.                 oprintk(("setting input volume (0x%x)", k));
  380.                 if (drv->ops->get_input_channels)
  381.                         j = drv->ops->get_input_channels(drv);
  382.                 if (drv->ops->get_input_volume)
  383.                         l = drv->ops->get_input_volume(drv);
  384.                 if (drv->ops->get_input_balance)
  385.                         m = drv->ops->get_input_balance(drv);
  386.                 i = OSS_TO_GAIN(k);
  387.                 j = OSS_TO_BAL(k);
  388.                 oprintk((" for stereo to do %d (bal %d):", i, j));
  389.                 if (drv->ops->set_input_volume)
  390.                         drv->ops->set_input_volume(drv, i);
  391.                 if (drv->ops->set_input_balance)
  392.                         drv->ops->set_input_balance(drv, j);
  393.         case SOUND_MIXER_READ_RECLEV:
  394.                 if (drv->ops->get_input_volume)
  395.                         i = drv->ops->get_input_volume(drv);
  396.                 if (drv->ops->get_input_balance)
  397.                         j = drv->ops->get_input_balance(drv);
  398.                 oprintk((" got (0x%x)n", BAL_TO_OSS(i,j)));
  399.                 i = BAL_TO_OSS(i,j);
  400.                 /* Try to be reasonable about volume changes */
  401.                 if ((cmd == SOUND_MIXER_WRITE_RECLEV) && (i != k) && 
  402.                     (i == BAL_TO_OSS(l,m))) {
  403.                         k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;
  404.                         k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;
  405.                         oprintk((" try 0x%xn", k));
  406.                         goto iretry;
  407.                 }
  408.                 return put_user(i, (int *)arg);
  409.         case SOUND_MIXER_WRITE_VOLUME:
  410.                 if (get_user(k, (int *)arg))
  411.                         return -EFAULT;
  412.                 if (drv->ops->get_output_muted && drv->ops->set_output_muted) {
  413.                         i = drv->ops->get_output_muted(drv);
  414.                         if ((k == 0) || ((i == 0) && (OSS_LEFT(k) < 100)))
  415.                                 drv->ops->set_output_muted(drv, 1);
  416.                         else
  417.                                 drv->ops->set_output_muted(drv, 0);
  418.                 }
  419.         case SOUND_MIXER_READ_VOLUME:
  420.                 if (drv->ops->get_output_muted) 
  421.                         i = drv->ops->get_output_muted(drv);
  422.                 k = 0x6464 * (1 - i);
  423.                 return put_user(k, (int *)arg);
  424.         case SOUND_MIXER_WRITE_PCM:
  425.                 if (get_user(k, (int *)arg))
  426.                         return -EFAULT;
  427.         oretry:
  428.                 oprintk(("setting output volume (0x%x)n", k));
  429.                 if (drv->ops->get_output_channels)
  430.                         j = drv->ops->get_output_channels(drv);
  431.                 if (drv->ops->get_output_volume)
  432.                         l = drv->ops->get_output_volume(drv);
  433.                 if (drv->ops->get_output_balance)
  434.                         m = drv->ops->get_output_balance(drv);
  435.                 oprintk((" started as (0x%x)n", BAL_TO_OSS(l,m)));
  436.                 i = OSS_TO_GAIN(k);
  437.                 j = OSS_TO_BAL(k);
  438.                 oprintk((" for stereo to %d (bal %d)n", i, j));
  439.                 if (drv->ops->set_output_volume)
  440.                         drv->ops->set_output_volume(drv, i);
  441.                 if (drv->ops->set_output_balance)
  442.                         drv->ops->set_output_balance(drv, j);
  443.         case SOUND_MIXER_READ_PCM:
  444.                 if (drv->ops->get_output_volume)
  445.                         i = drv->ops->get_output_volume(drv);
  446.                 if (drv->ops->get_output_balance)
  447.                         j = drv->ops->get_output_balance(drv);
  448.                 oprintk((" got 0x%xn", BAL_TO_OSS(i,j)));
  449.                 i = BAL_TO_OSS(i,j);
  450.                 /* Try to be reasonable about volume changes */
  451.                 if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) && 
  452.                     (i == BAL_TO_OSS(l,m))) {
  453.                         k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;
  454.                         k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;
  455.                         oprintk((" try 0x%xn", k));
  456.                         goto oretry;
  457.                 }
  458.                 return put_user(i, (int *)arg);
  459.         case SOUND_MIXER_READ_SPEAKER:
  460.                 k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER);
  461.                 return put_user(k, (int *)arg);
  462.         case SOUND_MIXER_READ_MIC:
  463.                 k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE);
  464.                 return put_user(k, (int *)arg);
  465.         case SOUND_MIXER_READ_CD:
  466.                 k = OSS_IPORT_AUDIO(drv, AUDIO_CD);
  467.                 return put_user(k, (int *)arg);
  468.         case SOUND_MIXER_READ_LINE:
  469.                 k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN);
  470.                 return put_user(k, (int *)arg);
  471.         case SOUND_MIXER_READ_LINE1:
  472.                 k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE);
  473.                 return put_user(k, (int *)arg);
  474.         case SOUND_MIXER_READ_LINE2:
  475.                 k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT);
  476.                 return put_user(k, (int *)arg);
  477.         case SOUND_MIXER_WRITE_MIC:
  478.         case SOUND_MIXER_WRITE_CD:
  479.         case SOUND_MIXER_WRITE_LINE:
  480.         case SOUND_MIXER_WRITE_LINE1:
  481.         case SOUND_MIXER_WRITE_LINE2:
  482.         case SOUND_MIXER_WRITE_SPEAKER:
  483.                 if (get_user(k, (int *)arg))
  484.                         return -EFAULT;
  485.                 OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k);
  486.                 OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k);
  487.                 OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k);
  488.                 OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k);
  489.                 OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k);
  490.                 OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k);
  491.                 return put_user(k, (int *)arg);
  492.         case SOUND_MIXER_READ_RECSRC: 
  493.                 if (drv->ops->get_input_port)
  494.                         i = drv->ops->get_input_port(drv);
  495.                 /* only one should ever be selected */
  496.                 if (i & AUDIO_CD) j = SOUND_MASK_CD;
  497.                 if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE;
  498.                 if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC;
  499.     
  500.                 return put_user(j, (int *)arg);
  501.   case SOUND_MIXER_WRITE_RECSRC: 
  502.           if (!drv->ops->set_input_port)
  503.                   return -EINVAL;
  504.           if (get_user(k, (int *)arg))
  505.                   return -EFAULT;
  506.           /* only one should ever be selected */
  507.           if (k & SOUND_MASK_CD) j = AUDIO_CD;
  508.           if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN;
  509.           if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE;
  510.           oprintk(("setting inport to %dn", j));
  511.           i = drv->ops->set_input_port(drv, j);
  512.     
  513.           return put_user(i, (int *)arg);
  514.         case SOUND_MIXER_READ_RECMASK: 
  515.                 if (drv->ops->get_input_ports)
  516.                         i = drv->ops->get_input_ports(drv);
  517.                 /* what do we support? */
  518.                 if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC;
  519.                 if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE;
  520.                 if (i & AUDIO_CD) j |= SOUND_MASK_CD;
  521.     
  522.                 return put_user(j, (int *)arg);
  523.         case SOUND_MIXER_READ_CAPS: /* mixer capabilities */
  524.                 i = SOUND_CAP_EXCL_INPUT;
  525.                 return put_user(i, (int *)arg);
  526.         case SOUND_MIXER_READ_DEVMASK: /* all supported devices */
  527.                 if (drv->ops->get_input_ports)
  528.                         i = drv->ops->get_input_ports(drv);
  529.                 /* what do we support? */
  530.                 if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC;
  531.                 if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE;
  532.                 if (i & AUDIO_CD) j |= SOUND_MASK_CD;
  533.     
  534.                 if (drv->ops->get_output_ports)
  535.                         i = drv->ops->get_output_ports(drv);
  536.                 if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER;
  537.                 if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE1;
  538.                 if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE2;
  539.                 j |= SOUND_MASK_VOLUME;
  540.         case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */
  541.                 j |= SOUND_MASK_PCM|SOUND_MASK_RECLEV;
  542.                 if (cmd == SOUND_MIXER_READ_STEREODEVS)
  543.                         j &= ~(MONO_DEVICES);
  544.                 return put_user(j, (int *)arg);
  545.         default:
  546.                 return -EINVAL;
  547.         };
  548. }
  549. /* AUDIO_SETINFO uses these to set values if possible. */
  550. static __inline__ int 
  551. __sparcaudio_if_set_do(struct sparcaudio_driver *drv, 
  552.        int (*set_function)(struct sparcaudio_driver *, int), 
  553.        int (*get_function)(struct sparcaudio_driver *), 
  554.        unsigned int value)
  555. {
  556.         if (set_function && Modify(value))
  557.                 return (int) set_function(drv, value);
  558.         else if (get_function)
  559.                 return (int) get_function(drv);
  560.         else 
  561.                 return 0;
  562. }
  563. static __inline__ int 
  564. __sparcaudio_if_setc_do(struct sparcaudio_driver *drv, 
  565. int (*set_function)(struct sparcaudio_driver *, int), 
  566. int (*get_function)(struct sparcaudio_driver *), 
  567. unsigned char value)
  568. {
  569.         if (set_function && Modifyc(value))
  570.                 return (char) set_function(drv, (int)value);
  571.         else if (get_function)
  572.                 return (char) get_function(drv);
  573.         else 
  574.                 return 0;
  575. }
  576. /* I_FLUSH, I_{G,S}ETSIG, I_NREAD provided for SunOS compatibility
  577.  *
  578.  * I must admit I'm quite ashamed of the state of the ioctl handling,
  579.  * but I do have several optimizations which I'm planning. -- DJB
  580.  */
  581. static int sparcaudio_ioctl(struct inode * inode, struct file * file,
  582.     unsigned int cmd, unsigned long arg)
  583. {
  584. int retval = 0, i, j, k;
  585. int minor = MINOR(inode->i_rdev);
  586. struct audio_info ainfo;
  587. audio_buf_info binfo;
  588. count_info cinfo;
  589. struct sparcaudio_driver *drv = 
  590.                 drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
  591. switch (minor & 0xf) {
  592. case SPARCAUDIO_MIXER_MINOR:
  593.                 return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg);
  594. case SPARCAUDIO_DSP16_MINOR:
  595.         case SPARCAUDIO_DSP_MINOR:
  596. case SPARCAUDIO_AUDIO_MINOR:
  597. case SPARCAUDIO_AUDIOCTL_MINOR:
  598.                 /* According to the OSS prog int, you can mixer ioctl /dev/dsp */
  599.                 if (_IOC_TYPE(cmd) == 'M')
  600.                         return sparcaudio_mixer_ioctl(inode, 
  601.                                                       file, cmd, (unsigned int *)arg);
  602.                 switch (cmd) {
  603.                 case I_GETSIG:
  604.                 case I_GETSIG_SOLARIS:
  605.                         j = (int) lis_get_elist_ent(drv->sd_siglist,current->pid);
  606.                         put_user(j, (int *)arg);
  607.                         retval = drv->input_count;
  608.                         break;
  609.                 case I_SETSIG:
  610.                 case I_SETSIG_SOLARIS:
  611.                         if ((minor & 0xf) == SPARCAUDIO_AUDIOCTL_MINOR) {
  612.                                 if (!arg) {
  613.                                         if (lis_del_from_elist(&(drv->sd_siglist),
  614.                                                                current->pid,S_ALL)) {
  615.                                                 retval = -EINVAL;
  616.                                         } else if (!drv->sd_siglist) {
  617.                                                 drv->sd_sigflags=0;
  618.                                         }
  619.                                 } else if (lis_add_to_elist(&(drv->sd_siglist),
  620.                                                             current->pid,
  621.                                                             (short)arg)) {
  622.                                         retval = -EAGAIN;
  623.                                 } else {
  624.                                         ((drv->sd_sigflags) |= (arg));
  625.                                 }
  626.                         }
  627.                         break;
  628.                 case I_NREAD:
  629.                 case I_NREAD_SOLARIS:
  630.                         /* According to the Solaris man page, this copies out
  631.                          * the size of the first streams buffer and returns 
  632.                          * the number of streams messages on the read queue as
  633.                          * as its retval. (streamio(7I)) This should work.
  634.                          */
  635.                         j = (drv->input_count > 0) ? drv->input_buffer_size : 0;
  636.                         put_user(j, (int *)arg);
  637.                         retval = drv->input_count;
  638.                         break;
  639.                         /* A poor substitute until we do true resizable buffers. */
  640.                 case SNDCTL_DSP_GETISPACE:
  641.                         binfo.fragstotal = drv->num_input_buffers;
  642.                         binfo.fragments = drv->num_input_buffers - 
  643.                                 (drv->input_count + drv->recording_count);
  644.                         binfo.fragsize = drv->input_buffer_size;
  645.                         binfo.bytes = binfo.fragments*binfo.fragsize;
  646.     
  647.                         retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));
  648.                         if (retval)
  649.                                 break;
  650.                         copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));
  651.                         break;
  652.                 case SNDCTL_DSP_GETOSPACE:
  653.                         binfo.fragstotal = drv->num_output_buffers;
  654.                         binfo.fragments = drv->num_output_buffers - 
  655.                                 (drv->output_count + drv->playing_count + 
  656.                                  (drv->output_offset ? 1 : 0));
  657.                         binfo.fragsize = drv->output_buffer_size;
  658.                         binfo.bytes = binfo.fragments*binfo.fragsize + 
  659.                                 (drv->output_buffer_size - drv->output_offset);
  660.     
  661.                         retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));
  662.                         if (retval)
  663.                                 break;
  664.                         copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));
  665.                         break;
  666.                 case SNDCTL_DSP_GETIPTR:
  667.                 case SNDCTL_DSP_GETOPTR:
  668.                         /* int bytes (number of bytes read/written since last)
  669.                          * int blocks (number of frags read/wrote since last call)
  670.                          * int ptr (current position of dma in buffer)
  671.                          */
  672.                         retval = 0;
  673.                         cinfo.bytes = 0;
  674.                         cinfo.ptr = 0;
  675.                         cinfo.blocks = 0;
  676.                         cinfo.bytes += cinfo.ptr;
  677.     
  678.                         retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(cinfo));
  679.                         if (retval)
  680.                                 break;
  681.                         copy_to_user(&((char *)arg)[0], (char *)&cinfo, sizeof(cinfo));
  682.                         break;
  683.                 case SNDCTL_DSP_SETFRAGMENT:
  684.                         /* XXX Small hack to get ESD/Enlightenment to work.  --DaveM */
  685.                         retval = 0;
  686.                         break;
  687.                 case SNDCTL_DSP_SUBDIVIDE:
  688.                         /* I don't understand what I need to do yet. */
  689.                         retval = -EINVAL;
  690.                         break;
  691.                 case SNDCTL_DSP_SETTRIGGER:
  692.                         /* This may not be 100% correct */
  693.                         if ((arg & PCM_ENABLE_INPUT) && drv->ops->get_input_pause &&
  694.                             drv->ops->set_input_pause) {
  695.                                 if (drv->ops->get_input_pause(drv))
  696.                                         drv->ops->set_input_pause(drv, 0);
  697.                         } else {
  698.                                 if (!drv->ops->get_input_pause(drv))
  699.                                         drv->ops->set_input_pause(drv, 1);
  700.                         }
  701.                         if ((arg & PCM_ENABLE_OUTPUT) && drv->ops->get_output_pause &&
  702.                             drv->ops->set_output_pause) {
  703.                                 if (drv->ops->get_output_pause(drv))
  704.                                         drv->ops->set_output_pause(drv, 0);
  705.                         } else {
  706.                                 if (!drv->ops->get_output_pause(drv))
  707.                                         drv->ops->set_output_pause(drv, 1);
  708.                         }
  709.                         break;
  710.                 case SNDCTL_DSP_GETTRIGGER:
  711.                         j = 0;
  712.                         if (drv->ops->get_input_pause) {
  713.                                 if (drv->ops->get_input_pause(drv))
  714.                                         j = PCM_ENABLE_INPUT;
  715.                         }
  716.                         if (drv->ops->get_output_pause) {
  717.                                 if (drv->ops->get_output_pause(drv))
  718.                                         j |= PCM_ENABLE_OUTPUT;
  719.                         }
  720.                         put_user(j, (int *)arg);
  721.                         break;
  722.                 case SNDCTL_DSP_GETBLKSIZE:
  723.                         j = drv->input_buffer_size;
  724.                         put_user(j, (int *)arg);
  725.                         break;
  726.                 case SNDCTL_DSP_SPEED:
  727.                         if ((!drv->ops->set_output_rate) && 
  728.                             (!drv->ops->set_input_rate)) {
  729.                                 retval = -EINVAL;
  730.                                 break;
  731.                         }
  732.                         get_user(i, (int *)arg)
  733.                         tprintk(("setting speed to %dn", i));
  734.                         drv->ops->set_input_rate(drv, i);
  735.                         drv->ops->set_output_rate(drv, i);
  736.                         j = drv->ops->get_output_rate(drv);
  737.                         put_user(j, (int *)arg);
  738.                         break;
  739.                 case SNDCTL_DSP_GETCAPS:
  740.                         /* All Sparc audio hardware is full duplex.
  741.                          * 4231 supports DMA pointer reading, 7930 is byte at a time.
  742.                          * Pause functionality emulates trigger
  743.                          */
  744.                         j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME;
  745.                         put_user(j, (int *)arg);
  746.                         break;
  747.                 case SNDCTL_DSP_GETFMTS:
  748.                         if (drv->ops->get_formats) {
  749.                                 j = drv->ops->get_formats(drv);
  750.                                 put_user(j, (int *)arg);
  751.                         } else {
  752.                                 retval = -EINVAL;
  753.                         }
  754.                         break;
  755.                 case SNDCTL_DSP_SETFMT:
  756.                         /* need to decode into encoding, precision */
  757.                         get_user(i, (int *)arg);
  758.     
  759.                         /* handle special case here */
  760.                         if (i == AFMT_QUERY) {
  761.                                 j = drv->ops->get_output_encoding(drv);
  762.                                 k = drv->ops->get_output_precision(drv);
  763.                                 if (j == AUDIO_ENCODING_DVI) {
  764.                                         i = AFMT_IMA_ADPCM;
  765.                                 } else if (k == 8) {
  766.                                         switch (j) {
  767.                                         case AUDIO_ENCODING_ULAW:
  768.                                                 i = AFMT_MU_LAW;
  769.                                                 break;
  770.                                         case AUDIO_ENCODING_ALAW:
  771.                                                 i = AFMT_A_LAW;
  772.                                                 break;
  773.                                         case AUDIO_ENCODING_LINEAR8:
  774.                                                 i = AFMT_U8;
  775.                                                 break;
  776.                                         };
  777.                                 } else if (k == 16) {
  778.                                         switch (j) {
  779.                                         case AUDIO_ENCODING_LINEAR:
  780.                                                 i = AFMT_S16_BE;
  781.                                                 break;
  782.                                         case AUDIO_ENCODING_LINEARLE:
  783.                                                 i = AFMT_S16_LE;
  784.                                                 break;
  785.                                         };
  786.                                 } 
  787.                                 put_user(i, (int *)arg);
  788.                                 break;
  789.                         }
  790.                         /* Without these there's no point in trying */
  791.                         if (!drv->ops->set_input_precision ||
  792.                             !drv->ops->set_input_encoding ||
  793.                             !drv->ops->set_output_precision ||
  794.                             !drv->ops->set_output_encoding) {
  795.                                 eprintk(("missing set routines: failedn"));
  796.                                 retval = -EINVAL;
  797.                                 break;
  798.                         }
  799.                         if (drv->ops->get_formats) {
  800.                                 if (!(drv->ops->get_formats(drv) & i)) {
  801.                                         dprintk(("format not supportedn"));
  802.                                         return -EINVAL;
  803.                                 }
  804.                         }
  805.                         switch (i) {
  806.                         case AFMT_S16_LE:
  807.                                 ainfo.record.precision = ainfo.play.precision = 16;
  808.                                 ainfo.record.encoding = ainfo.play.encoding =
  809.                                         AUDIO_ENCODING_LINEARLE;
  810.                                 break;
  811.                         case AFMT_S16_BE:
  812.                                 ainfo.record.precision = ainfo.play.precision = 16;
  813.                                 ainfo.record.encoding = ainfo.play.encoding =
  814.                                         AUDIO_ENCODING_LINEAR;
  815.                                 break;
  816.                         case AFMT_MU_LAW:
  817.                                 ainfo.record.precision = ainfo.play.precision = 8;
  818.                                 ainfo.record.encoding = ainfo.play.encoding =
  819.                                         AUDIO_ENCODING_ULAW;
  820.                                 break;
  821.                         case AFMT_A_LAW:
  822.                                 ainfo.record.precision = ainfo.play.precision = 8;
  823.                                 ainfo.record.encoding = ainfo.play.encoding =
  824.                                         AUDIO_ENCODING_ALAW;
  825.                                 break;
  826.                         case AFMT_U8:
  827.                                 ainfo.record.precision = ainfo.play.precision = 8;
  828.                                 ainfo.record.encoding = ainfo.play.encoding =
  829.                                         AUDIO_ENCODING_LINEAR8;
  830.                                 break;
  831.                         };
  832.                         tprintk(("setting fmt to enc %d pr %dn",
  833.                                  ainfo.play.encoding,
  834.                                  ainfo.play.precision));
  835.                         if ((drv->ops->set_input_precision(drv,
  836.                                                            ainfo.record.precision) 
  837.                              < 0) ||
  838.                             (drv->ops->set_output_precision(drv,
  839.                                                             ainfo.play.precision)  
  840.                              < 0) ||
  841.                             (drv->ops->set_input_encoding(drv,
  842.                                                           ainfo.record.encoding)
  843.                              < 0) ||
  844.                             (drv->ops->set_output_encoding(drv,
  845.                                                            ainfo.play.encoding)
  846.                              < 0)) {
  847.                                 dprintk(("setting format: failedn"));
  848.                                 return -EINVAL;
  849.                         }
  850.                         put_user(i, (int *)arg);
  851.                         break;
  852.                 case SNDCTL_DSP_CHANNELS:
  853.                         if ((!drv->ops->set_output_channels) && 
  854.                             (!drv->ops->set_input_channels)) {
  855.                                 retval = -EINVAL;
  856.                                 break;
  857.                         }
  858.                         get_user(i, (int *)arg);
  859.                         drv->ops->set_input_channels(drv, i);
  860.                         drv->ops->set_output_channels(drv, i);
  861.                         i = drv->ops->get_output_channels(drv);
  862.                         put_user(i, (int *)arg);
  863.                         break;
  864.                 case SNDCTL_DSP_STEREO:
  865.                         if ((!drv->ops->set_output_channels) && 
  866.                             (!drv->ops->set_input_channels)) {
  867.                                 retval = -EINVAL;
  868.                                 break;
  869.                         }
  870.                         get_user(i, (int *)arg);
  871.                         drv->ops->set_input_channels(drv, (i + 1));
  872.                         drv->ops->set_output_channels(drv, (i + 1));
  873.                         i = ((drv->ops->get_output_channels(drv)) - 1);
  874.                         put_user(i, (int *)arg);
  875.                         break;
  876.                 case SNDCTL_DSP_POST:
  877.                 case SNDCTL_DSP_SYNC:
  878.                 case AUDIO_DRAIN:
  879.                         /* Deal with weirdness so we can fill buffers */
  880.                         if (drv->output_offset) {
  881.                                 drv->output_offset = 0;
  882.                                 drv->output_rear = (drv->output_rear + 1)
  883.                                         % drv->num_output_buffers;
  884.                                 drv->output_count++;
  885.                         }
  886.                         if (drv->output_count > 0) {
  887.                                 sparcaudio_sync_output(drv);
  888.                                 /* Only pause for DRAIN/SYNC, not POST */
  889.                                 if (cmd != SNDCTL_DSP_POST) {
  890.                                         interruptible_sleep_on(&drv->output_drain_wait);
  891.                                         retval = (signal_pending(current)) ? -EINTR : 0;
  892.                                 }
  893.                         }
  894.                         break;
  895.                 case I_FLUSH:
  896.                 case I_FLUSH_SOLARIS:
  897.                         if (((unsigned int)arg == FLUSHW) || 
  898.                             ((unsigned int)arg == FLUSHRW)) {
  899.                                 if (file->f_mode & FMODE_WRITE) {
  900.                                         sparcaudio_sync_output(drv);
  901.                                         if (drv->output_active) {
  902.                                                 wake_up_interruptible(&drv->output_write_wait);
  903.                                                 drv->ops->stop_output(drv);
  904.                                         }
  905.                                         drv->output_offset = 0;
  906.                                         drv->output_active = 0;
  907.                                         drv->output_front = 0;
  908.                                         drv->output_rear = 0;
  909.                                         drv->output_count = 0;
  910.                                         drv->output_size = 0;
  911.                                         drv->playing_count = 0;
  912.                                         drv->output_eof = 0;
  913.                                 }
  914.                         }
  915.                         if (((unsigned int)arg == FLUSHR) || 
  916.                             ((unsigned int)arg == FLUSHRW)) {
  917.                                 if (drv->input_active && (file->f_mode & FMODE_READ)) {
  918.                                         wake_up_interruptible(&drv->input_read_wait);
  919.                                         drv->ops->stop_input(drv);
  920.                                         drv->input_active = 0;
  921.                                         drv->input_front = 0;
  922.                                         drv->input_rear = 0;
  923.                                         drv->input_count = 0;
  924.                                         drv->input_size = 0;
  925.                                         drv->input_offset = 0;
  926.                                         drv->recording_count = 0;
  927.                                 }
  928.                                 if ((file->f_mode & FMODE_READ) && 
  929.                                     (drv->flags & SDF_OPEN_READ)) {
  930.                                         if (drv->duplex == 2)
  931.                                                 drv->input_count = drv->output_count;
  932.                                         drv->ops->start_input(drv, 
  933.                                                               drv->input_buffers[drv->input_front],
  934.                                                               drv->input_buffer_size);
  935.                                         drv->input_active = 1;
  936.                                 }
  937.                         }
  938.                         if (((unsigned int)arg == FLUSHW) || 
  939.                             ((unsigned int)arg == FLUSHRW)) {
  940.                                 if ((file->f_mode & FMODE_WRITE) && 
  941.                                     !(drv->flags & SDF_OPEN_WRITE)) {
  942.                                         kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  943.                                         sparcaudio_sync_output(drv);
  944.                                 }
  945.                         }
  946.                         break;
  947.                 case SNDCTL_DSP_RESET:
  948.                 case AUDIO_FLUSH:
  949.                         if (drv->output_active && (file->f_mode & FMODE_WRITE)) {
  950.                                 wake_up_interruptible(&drv->output_write_wait);
  951.                                 drv->ops->stop_output(drv);
  952.                                 drv->output_active = 0;
  953.                                 drv->output_front = 0;
  954.                                 drv->output_rear = 0;
  955.                                 drv->output_count = 0;
  956.                                 drv->output_size = 0;
  957.                                 drv->playing_count = 0;
  958.                                 drv->output_offset = 0;
  959.                                 drv->output_eof = 0;
  960.                         }
  961.                         if (drv->input_active && (file->f_mode & FMODE_READ)) {
  962.                                 wake_up_interruptible(&drv->input_read_wait);
  963.                                 drv->ops->stop_input(drv);
  964.                                 drv->input_active = 0;
  965.                                 drv->input_front = 0;
  966.                                 drv->input_rear = 0;
  967.                                 drv->input_count = 0;
  968.                                 drv->input_size = 0;
  969.                                 drv->input_offset = 0;
  970.                                 drv->recording_count = 0;
  971.                         }
  972.                         if ((file->f_mode & FMODE_READ) && 
  973.                             !(drv->flags & SDF_OPEN_READ)) {
  974.                                 drv->ops->start_input(drv, 
  975.                                                       drv->input_buffers[drv->input_front],
  976.                                                       drv->input_buffer_size);
  977.                                 drv->input_active = 1;
  978.                         }
  979.                         if ((file->f_mode & FMODE_WRITE) && 
  980.                             !(drv->flags & SDF_OPEN_WRITE)) {
  981.                                 sparcaudio_sync_output(drv);
  982.                         }
  983.                         break;
  984.                 case AUDIO_GETDEV:
  985.                         if (drv->ops->sunaudio_getdev) {
  986.                                 audio_device_t tmp;
  987.       
  988.                                 retval = verify_area(VERIFY_WRITE, (void *)arg, 
  989.                                                      sizeof(audio_device_t));
  990.                                 if (!retval)
  991.                                         drv->ops->sunaudio_getdev(drv, &tmp);
  992.                                 copy_to_user((audio_device_t *)arg, &tmp, sizeof(tmp));
  993.                         } else {
  994.                                 retval = -EINVAL;
  995.                         }
  996.                         break;
  997.                 case AUDIO_GETDEV_SUNOS:
  998.                         if (drv->ops->sunaudio_getdev_sunos) {
  999.                                 int tmp = drv->ops->sunaudio_getdev_sunos(drv);
  1000.                                 retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
  1001.                                 if (!retval)
  1002.                                         copy_to_user((int *)arg, &tmp, sizeof(tmp));
  1003.                         } else {
  1004.                                 retval = -EINVAL;
  1005.                         }
  1006.                         break;
  1007.                 case AUDIO_GETINFO:
  1008.                         AUDIO_INITINFO(&ainfo);
  1009.                         if (drv->ops->get_input_rate)
  1010.                                 ainfo.record.sample_rate =
  1011.                                         drv->ops->get_input_rate(drv);
  1012.                         else
  1013.                                 ainfo.record.sample_rate = (8000);
  1014.                         if (drv->ops->get_input_channels)
  1015.                                 ainfo.record.channels =
  1016.                                         drv->ops->get_input_channels(drv);
  1017.                         else
  1018.                                 ainfo.record.channels = (1);
  1019.                         if (drv->ops->get_input_precision)
  1020.                                 ainfo.record.precision =
  1021.                                         drv->ops->get_input_precision(drv);
  1022.                         else
  1023.                                 ainfo.record.precision = (8);
  1024.                         if (drv->ops->get_input_encoding)
  1025.                                 ainfo.record.encoding =
  1026.                                         drv->ops->get_input_encoding(drv);
  1027.                         else
  1028.                                 ainfo.record.encoding = (AUDIO_ENCODING_ULAW);
  1029.                         if (drv->ops->get_input_volume)
  1030.                                 ainfo.record.gain =
  1031.                                         drv->ops->get_input_volume(drv);
  1032.                         else
  1033.                                 ainfo.record.gain = (0);
  1034.                         if (drv->ops->get_input_port)
  1035.                                 ainfo.record.port =
  1036.                                         drv->ops->get_input_port(drv);
  1037.                         else
  1038.                                 ainfo.record.port = (0);
  1039.                         if (drv->ops->get_input_ports)
  1040.                                 ainfo.record.avail_ports = 
  1041.                                         drv->ops->get_input_ports(drv);
  1042.                         else
  1043.                                 ainfo.record.avail_ports = (0);
  1044.                         /* To make e.g. vat happy, we let them think they control this */
  1045.                         ainfo.record.buffer_size = drv->buffer_size;
  1046.                         if (drv->ops->get_input_samples)
  1047.                                 ainfo.record.samples = drv->ops->get_input_samples(drv);
  1048.                         else
  1049.                                 ainfo.record.samples = 0;
  1050.                         /* This is undefined in the record context in Solaris */
  1051.                         ainfo.record.eof = 0;
  1052.                         if (drv->ops->get_input_pause)
  1053.                                 ainfo.record.pause =
  1054.                                         drv->ops->get_input_pause(drv);
  1055.                         else
  1056.                                 ainfo.record.pause = 0;
  1057.                         if (drv->ops->get_input_error)
  1058.                                 ainfo.record.error = 
  1059.                                         (unsigned char) drv->ops->get_input_error(drv);
  1060.                         else
  1061.                                 ainfo.record.error = 0;
  1062.                         ainfo.record.waiting = 0;
  1063.                         if (drv->ops->get_input_balance)
  1064.                                 ainfo.record.balance =
  1065.                                         (unsigned char) drv->ops->get_input_balance(drv);
  1066.                         else
  1067.                                 ainfo.record.balance = (unsigned char)(AUDIO_MID_BALANCE);
  1068.                         ainfo.record.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT);
  1069.                         ainfo.record.open = (drv->flags & SDF_OPEN_READ);
  1070.                         ainfo.record.active = 0;
  1071.                         if (drv->ops->get_output_rate)
  1072.                                 ainfo.play.sample_rate =
  1073.                                         drv->ops->get_output_rate(drv);
  1074.                         else
  1075.                                 ainfo.play.sample_rate = (8000);
  1076.                         if (drv->ops->get_output_channels)
  1077.                                 ainfo.play.channels =
  1078.                                         drv->ops->get_output_channels(drv);
  1079.                         else
  1080.                                 ainfo.play.channels = (1);
  1081.                         if (drv->ops->get_output_precision)
  1082.                                 ainfo.play.precision =
  1083.                                         drv->ops->get_output_precision(drv);
  1084.                         else
  1085.                                 ainfo.play.precision = (8);
  1086.                         if (drv->ops->get_output_encoding)
  1087.                                 ainfo.play.encoding =
  1088.                                         drv->ops->get_output_encoding(drv);
  1089.                         else
  1090.                                 ainfo.play.encoding = (AUDIO_ENCODING_ULAW);
  1091.                         if (drv->ops->get_output_volume)
  1092.                                 ainfo.play.gain =
  1093.                                         drv->ops->get_output_volume(drv);
  1094.                         else
  1095.                                 ainfo.play.gain = (0);
  1096.                         if (drv->ops->get_output_port)
  1097.                                 ainfo.play.port =
  1098.                                         drv->ops->get_output_port(drv);
  1099.                         else
  1100.                                 ainfo.play.port = (0);
  1101.                         if (drv->ops->get_output_ports)
  1102.                                 ainfo.play.avail_ports = 
  1103.                                         drv->ops->get_output_ports(drv);
  1104.                         else
  1105.                                 ainfo.play.avail_ports = (0);
  1106.                         /* This is not defined in the play context in Solaris */
  1107.                         ainfo.play.buffer_size = 0;
  1108.                         if (drv->ops->get_output_samples)
  1109.                                 ainfo.play.samples = drv->ops->get_output_samples(drv);
  1110.                         else
  1111.                                 ainfo.play.samples = 0;
  1112.                         ainfo.play.eof = drv->output_eof;
  1113.                         if (drv->ops->get_output_pause)
  1114.                                 ainfo.play.pause =
  1115.                                         drv->ops->get_output_pause(drv);
  1116.                         else
  1117.                                 ainfo.play.pause = 0;
  1118.                         if (drv->ops->get_output_error)
  1119.                                 ainfo.play.error =
  1120.                                         (unsigned char)drv->ops->get_output_error(drv);
  1121.                         else
  1122.                                 ainfo.play.error = 0;
  1123.                         ainfo.play.waiting = waitqueue_active(&drv->open_wait);
  1124.                         if (drv->ops->get_output_balance)
  1125.                                 ainfo.play.balance =
  1126.                                         (unsigned char)drv->ops->get_output_balance(drv);
  1127.                         else
  1128.                                 ainfo.play.balance = (unsigned char)(AUDIO_MID_BALANCE);
  1129.                         ainfo.play.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT);
  1130.                         ainfo.play.open = (drv->flags & SDF_OPEN_WRITE);
  1131.                         ainfo.play.active = drv->output_active;
  1132.     
  1133.                         if (drv->ops->get_monitor_volume)
  1134.                                 ainfo.monitor_gain =
  1135.                                         drv->ops->get_monitor_volume(drv);
  1136.                         else
  1137.                                 ainfo.monitor_gain = (0);
  1138.                         if (drv->ops->get_output_muted)
  1139.                                 ainfo.output_muted = 
  1140.                                         (unsigned char)drv->ops->get_output_muted(drv);
  1141.                         else
  1142.                                 ainfo.output_muted = (unsigned char)(0);
  1143.                         retval = verify_area(VERIFY_WRITE, (void *)arg,
  1144.                                              sizeof(struct audio_info));
  1145.                         if (retval < 0)
  1146.                                 break;
  1147.                         copy_to_user((struct audio_info *)arg, &ainfo, sizeof(ainfo));
  1148.                         break;
  1149.                 case AUDIO_SETINFO:
  1150.                 {
  1151.                         audio_info_t curinfo, newinfo;
  1152.       
  1153.                         if (verify_area(VERIFY_READ, (audio_info_t *)arg, 
  1154.                                         sizeof(audio_info_t))) {
  1155.                                 dprintk(("verify_area failedn"));
  1156.                                 return -EINVAL;
  1157.                         }
  1158.                         copy_from_user(&ainfo, (audio_info_t *)arg, sizeof(audio_info_t));
  1159.                         /* Without these there's no point in trying */
  1160.                         if (!drv->ops->get_input_precision ||
  1161.                             !drv->ops->get_input_channels ||
  1162.                             !drv->ops->get_input_rate ||
  1163.                             !drv->ops->get_input_encoding ||
  1164.                             !drv->ops->get_output_precision ||
  1165.                             !drv->ops->get_output_channels ||
  1166.                             !drv->ops->get_output_rate ||
  1167.                             !drv->ops->get_output_encoding) {
  1168.                                 eprintk(("missing get routines: failedn"));
  1169.                                 retval = -EINVAL;
  1170.                                 break;
  1171.                         }
  1172.                         /* Do bounds checking for things which always apply.
  1173.                          * Follow with enforcement of basic tenets of certain
  1174.                          * encodings. Everything over and above generic is
  1175.                          * enforced by the driver, which can assume that
  1176.                          * Martian cases are taken care of here.
  1177.                          */
  1178.                         if (Modify(ainfo.play.gain) && 
  1179.                             ((ainfo.play.gain > AUDIO_MAX_GAIN) || 
  1180.                              (ainfo.play.gain < AUDIO_MIN_GAIN))) {
  1181.                                 /* Need to differentiate this from e.g. the above error */
  1182.                                 eprintk(("play gain bounds: failed %dn", ainfo.play.gain));
  1183.                                 retval = -EINVAL;
  1184.                                 break;
  1185.                         }
  1186.                         if (Modify(ainfo.record.gain) &&
  1187.                             ((ainfo.record.gain > AUDIO_MAX_GAIN) ||
  1188.                              (ainfo.record.gain < AUDIO_MIN_GAIN))) {
  1189.                                 eprintk(("rec gain bounds: failed %dn", ainfo.record.gain));
  1190.                                 retval = -EINVAL;
  1191.                                 break;
  1192.                         }
  1193.                         if (Modify(ainfo.monitor_gain) &&
  1194.                             ((ainfo.monitor_gain > AUDIO_MAX_GAIN) ||
  1195.                              (ainfo.monitor_gain < AUDIO_MIN_GAIN))) {
  1196.                                 eprintk(("monitor gain bounds: failedn"));
  1197.                                 retval = -EINVAL;
  1198.                                 break;
  1199.                         }
  1200.                         /* Don't need to check less than zero on these */
  1201.                         if (Modifyc(ainfo.play.balance) &&
  1202.                             (ainfo.play.balance > AUDIO_RIGHT_BALANCE)) {
  1203.                                 eprintk(("play balance bounds: %d failedn", 
  1204.                                          (int)ainfo.play.balance));
  1205.                                 retval = -EINVAL;
  1206.                                 break;
  1207.                         }
  1208.                         if (Modifyc(ainfo.record.balance) &&
  1209.                             (ainfo.record.balance > AUDIO_RIGHT_BALANCE)) {
  1210.                                 eprintk(("rec balance bounds: failedn"));
  1211.                                 retval = -EINVAL;
  1212.                                 break;
  1213.                         }
  1214.       
  1215.                         /* If any of these changed, record them all, then make
  1216.                          * changes atomically. If something fails, back it all out.
  1217.                          */
  1218.                         if (Modify(ainfo.record.precision) || 
  1219.                             Modify(ainfo.record.sample_rate) ||
  1220.                             Modify(ainfo.record.channels) ||
  1221.                             Modify(ainfo.record.encoding) || 
  1222.                             Modify(ainfo.play.precision) || 
  1223.                             Modify(ainfo.play.sample_rate) ||
  1224.                             Modify(ainfo.play.channels) ||
  1225.                             Modify(ainfo.play.encoding)) {
  1226.                                 /* If they're trying to change something we
  1227.                                  * have no routine for, they lose.
  1228.                                  */
  1229.                                 if ((!drv->ops->set_input_encoding && 
  1230.                                      Modify(ainfo.record.encoding)) ||
  1231.                                     (!drv->ops->set_input_rate && 
  1232.                                      Modify(ainfo.record.sample_rate)) ||
  1233.                                     (!drv->ops->set_input_precision && 
  1234.                                      Modify(ainfo.record.precision)) ||
  1235.                                     (!drv->ops->set_input_channels && 
  1236.                                      Modify(ainfo.record.channels))) {
  1237.                                         eprintk(("rec set no routines: failedn"));
  1238.                                         retval = -EINVAL;
  1239.                                         break;
  1240.                                 }   
  1241.   
  1242.                                 curinfo.record.encoding = 
  1243.                                         drv->ops->get_input_encoding(drv);
  1244.                                 curinfo.record.sample_rate = 
  1245.                                         drv->ops->get_input_rate(drv);    
  1246.                                 curinfo.record.precision = 
  1247.                                         drv->ops->get_input_precision(drv);    
  1248.                                 curinfo.record.channels = 
  1249.                                         drv->ops->get_input_channels(drv);    
  1250.                                 newinfo.record.encoding =
  1251.                                         Modify(ainfo.record.encoding) ? 
  1252.                                         ainfo.record.encoding :
  1253.                                         curinfo.record.encoding;
  1254.                                 newinfo.record.sample_rate =
  1255.                                         Modify(ainfo.record.sample_rate) ?
  1256.                                         ainfo.record.sample_rate :
  1257.                                         curinfo.record.sample_rate;
  1258.                                 newinfo.record.precision =
  1259.                                         Modify(ainfo.record.precision) ? 
  1260.                                         ainfo.record.precision :
  1261.                                         curinfo.record.precision;
  1262.                                 newinfo.record.channels =
  1263.                                         Modify(ainfo.record.channels) ? 
  1264.                                         ainfo.record.channels :
  1265.                                         curinfo.record.channels;
  1266.     
  1267.                                 switch (newinfo.record.encoding) {
  1268.                                 case AUDIO_ENCODING_ALAW:
  1269.                                 case AUDIO_ENCODING_ULAW:
  1270.                                         if (newinfo.record.precision != 8) {
  1271.                                                 eprintk(("rec law precision bounds: "
  1272.                                                          "failedn"));
  1273.                                                 retval = -EINVAL;
  1274.                                                 break;
  1275.                                         }
  1276.                                         if (newinfo.record.channels != 1) {
  1277.                                                 eprintk(("rec law channel bounds: "
  1278.                                                          "failedn"));
  1279.                                                 retval = -EINVAL;
  1280.                                                 break;
  1281.                                         }
  1282.                                         break;
  1283.                                 case AUDIO_ENCODING_LINEAR:
  1284.                                 case AUDIO_ENCODING_LINEARLE:
  1285.                                         if (newinfo.record.precision != 16) {
  1286.                                                 eprintk(("rec lin precision bounds: "
  1287.                                                          "failedn"));
  1288.                                                 retval = -EINVAL;
  1289.                                                 break;
  1290.                                         }
  1291.                                         if (newinfo.record.channels != 1 &&
  1292.                                             newinfo.record.channels != 2) {
  1293.                                                 eprintk(("rec lin channel bounds: "
  1294.                                                          "failedn"));
  1295.                                                 retval = -EINVAL;
  1296.                                                 break;
  1297.                                         }
  1298.                                         break;
  1299.                                 case AUDIO_ENCODING_LINEAR8:
  1300.                                         if (newinfo.record.precision != 8) {
  1301.                                                 eprintk(("rec lin8 precision bounds: "
  1302.                                                          "failedn"));
  1303.                                                 retval = -EINVAL;
  1304.                                                 break;
  1305.                                         }
  1306.                                         if (newinfo.record.channels != 1 && 
  1307.                                             newinfo.record.channels != 2) {
  1308.                                                 eprintk(("rec lin8 channel bounds: "
  1309.                                                          "failedn"));
  1310.                                                 retval = -EINVAL;
  1311.                                                 break;
  1312.                                         }
  1313.                                 };
  1314.   
  1315.                                 if (retval < 0)
  1316.                                         break;
  1317.   
  1318.                                 /* If they're trying to change something we
  1319.                                  * have no routine for, they lose.
  1320.                                  */
  1321.                                 if ((!drv->ops->set_output_encoding && 
  1322.                                      Modify(ainfo.play.encoding)) ||
  1323.                                     (!drv->ops->set_output_rate && 
  1324.                                      Modify(ainfo.play.sample_rate)) ||
  1325.                                     (!drv->ops->set_output_precision && 
  1326.                                      Modify(ainfo.play.precision)) ||
  1327.                                     (!drv->ops->set_output_channels && 
  1328.                                      Modify(ainfo.play.channels))) {
  1329.                                         eprintk(("play set no routine: failedn"));
  1330.                                         retval = -EINVAL;
  1331.                                         break;
  1332.                                 }   
  1333.   
  1334.                                 curinfo.play.encoding = 
  1335.                                         drv->ops->get_output_encoding(drv);
  1336.                                 curinfo.play.sample_rate = 
  1337.                                         drv->ops->get_output_rate(drv);    
  1338.                                 curinfo.play.precision = 
  1339.                                         drv->ops->get_output_precision(drv);    
  1340.                                 curinfo.play.channels = 
  1341.                                         drv->ops->get_output_channels(drv);    
  1342.                                 newinfo.play.encoding =
  1343.                                         Modify(ainfo.play.encoding) ? 
  1344.                                         ainfo.play.encoding :
  1345.                                                 curinfo.play.encoding;
  1346.                                 newinfo.play.sample_rate =
  1347.                                         Modify(ainfo.play.sample_rate) ? 
  1348.                                         ainfo.play.sample_rate :
  1349.                                                 curinfo.play.sample_rate;
  1350.                                 newinfo.play.precision =
  1351.                                         Modify(ainfo.play.precision) ? 
  1352.                                         ainfo.play.precision :
  1353.                                                 curinfo.play.precision;
  1354.                                 newinfo.play.channels =
  1355.                                         Modify(ainfo.play.channels) ? 
  1356.                                         ainfo.play.channels :
  1357.                                                 curinfo.play.channels;
  1358.   
  1359.                                 switch (newinfo.play.encoding) {
  1360.                                 case AUDIO_ENCODING_ALAW:
  1361.                                 case AUDIO_ENCODING_ULAW:
  1362.                                         if (newinfo.play.precision != 8) {
  1363.                                                 eprintk(("play law precision bounds: "
  1364.                                                          "failedn"));
  1365.                                                 retval = -EINVAL;
  1366.                                                 break;
  1367.                                         }
  1368.                                         if (newinfo.play.channels != 1) {
  1369.                                                 eprintk(("play law channel bounds: "
  1370.                                                          "failedn"));
  1371.                                                 retval = -EINVAL;
  1372.                                                 break;
  1373.                                         }
  1374.                                         break;
  1375.                                 case AUDIO_ENCODING_LINEAR:
  1376.                                 case AUDIO_ENCODING_LINEARLE:
  1377.                                         if (newinfo.play.precision != 16) {
  1378.                                                 eprintk(("play lin precision bounds: "
  1379.                                                          "failedn"));
  1380.                                                 retval = -EINVAL;
  1381.                                                 break;
  1382.                                         }
  1383.                                         if (newinfo.play.channels != 1 && 
  1384.                                             newinfo.play.channels != 2) {
  1385.                                                 eprintk(("play lin channel bounds: "
  1386.                                                          "failedn"));
  1387.                                                 retval = -EINVAL;
  1388.                                                 break;
  1389.                                         }
  1390.                                         break;
  1391.                                 case AUDIO_ENCODING_LINEAR8:
  1392.                                         if (newinfo.play.precision != 8) {
  1393.                                                 eprintk(("play lin8 precision bounds: "
  1394.                                                          "failedn"));
  1395.                                                 retval = -EINVAL;
  1396.                                                 break;
  1397.                                         }
  1398.                                         if (newinfo.play.channels != 1 && 
  1399.                                             newinfo.play.channels != 2) {
  1400.                                                 eprintk(("play lin8 channel bounds: "
  1401.                                                          "failedn"));
  1402.                                                 retval = -EINVAL;
  1403.                                                 break;
  1404.                                         }
  1405.                                 };
  1406.   
  1407.                                 if (retval < 0)
  1408.                                         break;
  1409.   
  1410.                                 /* If we got this far, we're at least sane with
  1411.                                  * respect to generics. Try the changes.
  1412.                                  */
  1413.                                 if ((drv->ops->set_input_channels &&
  1414.                                      (drv->ops->set_input_channels(drv, 
  1415.                                                                    newinfo.record.channels)
  1416.                                       < 0)) ||
  1417.                                     (drv->ops->set_output_channels &&
  1418.                                      (drv->ops->set_output_channels(drv, 
  1419.                                                                     newinfo.play.channels)
  1420.                                       < 0)) ||
  1421.                                     (drv->ops->set_input_rate &&
  1422.                                      (drv->ops->set_input_rate(drv, 
  1423.                                                                newinfo.record.sample_rate) 
  1424.                                       < 0)) ||
  1425.                                     (drv->ops->set_output_rate &&
  1426.                                      (drv->ops->set_output_rate(drv, 
  1427.                                                                 newinfo.play.sample_rate) 
  1428.                                       < 0)) ||
  1429.                                     (drv->ops->set_input_precision &&
  1430.                                      (drv->ops->set_input_precision(drv, 
  1431.                                                                     newinfo.record.precision)
  1432.                                       < 0)) ||
  1433.                                     (drv->ops->set_output_precision &&
  1434.                                      (drv->ops->set_output_precision(drv, 
  1435.                                                                      newinfo.play.precision)
  1436.                                       < 0)) ||
  1437.                                     (drv->ops->set_input_encoding &&
  1438.                                      (drv->ops->set_input_encoding(drv, 
  1439.                                                                    newinfo.record.encoding)
  1440.                                       < 0)) ||
  1441.                                     (drv->ops->set_output_encoding &&
  1442.                                      (drv->ops->set_output_encoding(drv, 
  1443.                                                                     newinfo.play.encoding)
  1444.                                       < 0))) 
  1445.                                 {
  1446.                                         dprintk(("setting format: failedn"));
  1447.                                         /* Pray we can set it all back. If not, uh... */
  1448.                                         if (drv->ops->set_input_channels)
  1449.                                                 drv->ops->set_input_channels(drv, 
  1450.      curinfo.record.channels);
  1451.                                         if (drv->ops->set_output_channels)
  1452.                                                 drv->ops->set_output_channels(drv, 
  1453.                                                                               curinfo.play.channels);
  1454.                                         if (drv->ops->set_input_rate)
  1455.                                                 drv->ops->set_input_rate(drv, 
  1456.                                                                          curinfo.record.sample_rate);
  1457.                                         if (drv->ops->set_output_rate)
  1458.                                                 drv->ops->set_output_rate(drv, 
  1459.                                                                           curinfo.play.sample_rate);
  1460.                                         if (drv->ops->set_input_precision)
  1461.                                                 drv->ops->set_input_precision(drv, 
  1462.                                                                               curinfo.record.precision);
  1463.                                         if (drv->ops->set_output_precision)
  1464.                                                 drv->ops->set_output_precision(drv, 
  1465.                                                                                curinfo.play.precision);
  1466.                                         if (drv->ops->set_input_encoding)
  1467.                                                 drv->ops->set_input_encoding(drv, 
  1468.                                                                              curinfo.record.encoding);
  1469.                                         if (drv->ops->set_output_encoding)
  1470.                                                 drv->ops->set_output_encoding(drv, 
  1471.                                                                               curinfo.play.encoding);
  1472.                                         retval = -EINVAL;
  1473.                                         break;
  1474.                                 }
  1475.                         }
  1476.                         
  1477.                         if (retval < 0)
  1478.                                 break;
  1479.                         
  1480.                         newinfo.record.balance =
  1481.                                 __sparcaudio_if_setc_do(drv, 
  1482.                                                         drv->ops->set_input_balance, 
  1483.                                                         drv->ops->get_input_balance,
  1484.                                                         ainfo.record.balance);
  1485.                         newinfo.play.balance =
  1486.                                 __sparcaudio_if_setc_do(drv, 
  1487.                                                         drv->ops->set_output_balance, 
  1488.                                                         drv->ops->get_output_balance,
  1489.                                                         ainfo.play.balance);
  1490.                         newinfo.record.error =
  1491.                                 __sparcaudio_if_setc_do(drv, 
  1492.                                                         drv->ops->set_input_error, 
  1493.                                                         drv->ops->get_input_error,
  1494.                                                         ainfo.record.error);
  1495.                         newinfo.play.error =
  1496.                                 __sparcaudio_if_setc_do(drv, 
  1497.                                                         drv->ops->set_output_error, 
  1498.                                                         drv->ops->get_output_error,
  1499.                                                         ainfo.play.error);
  1500.                         newinfo.output_muted =
  1501.                                 __sparcaudio_if_setc_do(drv, 
  1502.                                                         drv->ops->set_output_muted, 
  1503.                                                         drv->ops->get_output_muted,
  1504.                                                         ainfo.output_muted);
  1505.                         newinfo.record.gain =
  1506.                                 __sparcaudio_if_set_do(drv, 
  1507.                                                        drv->ops->set_input_volume, 
  1508.                                                        drv->ops->get_input_volume,
  1509.                                                        ainfo.record.gain);
  1510.                         newinfo.play.gain =
  1511.                                 __sparcaudio_if_set_do(drv, 
  1512.                                                        drv->ops->set_output_volume, 
  1513.                                                        drv->ops->get_output_volume,
  1514.                                                        ainfo.play.gain);
  1515.                         newinfo.record.port =
  1516.                                 __sparcaudio_if_set_do(drv, 
  1517.                                                        drv->ops->set_input_port, 
  1518.                                                        drv->ops->get_input_port,
  1519.                                                        ainfo.record.port);
  1520.                         newinfo.play.port =
  1521.                                 __sparcaudio_if_set_do(drv, 
  1522.                                                        drv->ops->set_output_port, 
  1523.                                                        drv->ops->get_output_port,
  1524.                                                        ainfo.play.port);
  1525.                         newinfo.record.samples =
  1526.                                 __sparcaudio_if_set_do(drv, 
  1527.                                                        drv->ops->set_input_samples, 
  1528.                                                        drv->ops->get_input_samples,
  1529.                                                        ainfo.record.samples);
  1530.                         newinfo.play.samples =
  1531.                                 __sparcaudio_if_set_do(drv, 
  1532.                                                        drv->ops->set_output_samples, 
  1533.                                                        drv->ops->get_output_samples,
  1534.                                                        ainfo.play.samples);
  1535.                         newinfo.monitor_gain =
  1536.                                 __sparcaudio_if_set_do(drv, 
  1537.                                                        drv->ops->set_monitor_volume, 
  1538.                                                        drv->ops->get_monitor_volume,
  1539.                                                        ainfo.monitor_gain);
  1540.                         if (Modify(ainfo.record.buffer_size)) {
  1541.                                 /* Should sanity check this */
  1542.                                 newinfo.record.buffer_size = ainfo.record.buffer_size;
  1543.                                 drv->buffer_size = ainfo.record.buffer_size;
  1544.                         } else {
  1545.                                 newinfo.record.buffer_size = drv->buffer_size;
  1546.                         }
  1547.                         if (Modify(ainfo.play.eof)) {
  1548.                                 ainfo.play.eof = newinfo.play.eof;
  1549.                                 newinfo.play.eof = drv->output_eof;
  1550.                                 drv->output_eof = ainfo.play.eof;
  1551.                         } else {
  1552.                                 newinfo.play.eof = drv->output_eof;
  1553.                         }
  1554.                         if (drv->flags & SDF_OPEN_READ) {
  1555.                                 newinfo.record.pause =
  1556.                                         __sparcaudio_if_setc_do(drv, 
  1557.                                                                 drv->ops->set_input_pause, 
  1558.                                                                 drv->ops->get_input_pause,
  1559.                                                                 ainfo.record.pause);
  1560.                         } else if (drv->ops->get_input_pause) {
  1561.                                 newinfo.record.pause = drv->ops->get_input_pause(drv);
  1562.                         } else {
  1563.                                 newinfo.record.pause = 0;
  1564.                         }
  1565.                         if (drv->flags & SDF_OPEN_WRITE) {
  1566.                                 newinfo.play.pause =
  1567.                                         __sparcaudio_if_setc_do(drv, 
  1568.                                                                 drv->ops->set_output_pause, 
  1569.                                                                 drv->ops->get_output_pause,
  1570.                                                                 ainfo.play.pause);
  1571.                         } else if (drv->ops->get_output_pause) {
  1572.                                 newinfo.play.pause = drv->ops->get_output_pause(drv);
  1573.                         } else {
  1574.                                 newinfo.play.pause = 0;
  1575.                         }
  1576.       
  1577.                         retval = verify_area(VERIFY_WRITE, (void *)arg,
  1578.                                              sizeof(struct audio_info));
  1579.                         /* Even if we fail, if we made changes let's try notification */
  1580.                         if (!retval) 
  1581.                                 copy_to_user((struct audio_info *)arg, &newinfo, 
  1582.                                              sizeof(newinfo));
  1583.     
  1584. #ifdef REAL_AUDIO_SIGNALS
  1585.                         kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  1586. #endif
  1587.                         break;
  1588.                 }
  1589.   
  1590.                 default:
  1591.                         if (drv->ops->ioctl)
  1592.                                 retval = drv->ops->ioctl(inode,file,cmd,arg,drv);
  1593.                         else
  1594.                                 retval = -EINVAL;
  1595.                 };
  1596.                 break;
  1597. case SPARCAUDIO_STATUS_MINOR:
  1598.                 eprintk(("status minor not yet implementedn"));
  1599.                 retval = -EINVAL;
  1600. default:
  1601.                 eprintk(("unknown minor device numbern"));
  1602.                 retval = -EINVAL;
  1603. }
  1604. return retval;
  1605. }
  1606. static struct file_operations sparcaudioctl_fops = {
  1607. owner: THIS_MODULE,
  1608. poll: sparcaudio_poll,
  1609. ioctl: sparcaudio_ioctl,
  1610. };
  1611. static int sparcaudio_open(struct inode * inode, struct file * file)
  1612. {
  1613.         int minor = MINOR(inode->i_rdev);
  1614. struct sparcaudio_driver *drv = 
  1615.                 drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
  1616. int err;
  1617. /* A low-level audio driver must exist. */
  1618. if (!drv)
  1619. return -ENODEV;
  1620. #ifdef S_ZERO_WR
  1621.         /* This is how 2.0 ended up dealing with 0 len writes */
  1622.         inode->i_flags |= S_ZERO_WR;
  1623. #endif
  1624. switch (minor & 0xf) {
  1625. case SPARCAUDIO_AUDIOCTL_MINOR:
  1626.                 file->f_op = &sparcaudioctl_fops;
  1627.                 break;
  1628. case SPARCAUDIO_DSP16_MINOR:
  1629. case SPARCAUDIO_DSP_MINOR:
  1630. case SPARCAUDIO_AUDIO_MINOR:
  1631.                 /* If the driver is busy, then wait to get through. */
  1632.         retry_open:
  1633.          if (file->f_mode & FMODE_READ && drv->flags & SDF_OPEN_READ) {
  1634.                         if (file->f_flags & O_NONBLOCK)
  1635.                                 return -EBUSY;
  1636.                         /* If something is now waiting, signal control device */
  1637.                         kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  1638.                         interruptible_sleep_on(&drv->open_wait);
  1639.                         if (signal_pending(current))
  1640.                                 return -EINTR;
  1641.                         goto retry_open;
  1642.                 }
  1643.                 if (file->f_mode & FMODE_WRITE && drv->flags & SDF_OPEN_WRITE) {
  1644.                         if (file->f_flags & O_NONBLOCK)
  1645.                                 return -EBUSY;
  1646.     
  1647.                         /* If something is now waiting, signal control device */
  1648.                         kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  1649.                         interruptible_sleep_on(&drv->open_wait);
  1650.                         if (signal_pending(current))
  1651.                                 return -EINTR;
  1652.                         goto retry_open;
  1653.                 }
  1654.                 /* Allow the low-level driver to initialize itself. */
  1655.                 if (drv->ops->open) {
  1656.                         err = drv->ops->open(inode,file,drv);
  1657.                         if (err < 0)
  1658.                                 return err;
  1659.                 }
  1660.                 /* Mark the driver as locked for read and/or write. */
  1661.                 if (file->f_mode & FMODE_READ) {
  1662.                         drv->input_offset = 0;
  1663.                         drv->input_front = 0;
  1664.                         drv->input_rear = 0;
  1665.                         drv->input_count = 0;
  1666.                         drv->input_size = 0;
  1667.                         drv->recording_count = 0;
  1668.                         /* Clear pause */
  1669.                         if (drv->ops->set_input_pause)
  1670.                                 drv->ops->set_input_pause(drv, 0); 
  1671.                         drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
  1672.                                               drv->input_buffer_size);
  1673.                         drv->input_active = 1;
  1674.                         drv->flags |= SDF_OPEN_READ;
  1675.                 }
  1676.                 if (file->f_mode & FMODE_WRITE) {
  1677.                         drv->output_offset = 0;
  1678.                         drv->output_eof = 0;
  1679.                         drv->playing_count = 0;
  1680.                         drv->output_size = 0;
  1681.                         drv->output_front = 0;
  1682.                         drv->output_rear = 0;
  1683.                         drv->output_count = 0;
  1684.                         drv->output_active = 0;
  1685.                         /* Clear pause */
  1686.                         if (drv->ops->set_output_pause)
  1687.                                 drv->ops->set_output_pause(drv, 0); 
  1688.                         drv->flags |= SDF_OPEN_WRITE;
  1689.                 }  
  1690.                 break;
  1691. case SPARCAUDIO_MIXER_MINOR:     
  1692.                 file->f_op = &sparcaudioctl_fops;
  1693.                 break;
  1694. default:
  1695.                 return -ENXIO;
  1696. };
  1697.         /* From the dbri driver:
  1698.          * SunOS 5.5.1 audio(7I) man page says:
  1699.          * "Upon the initial open() of the audio device, the driver
  1700.          *  will reset the data format of the device to the default
  1701.          *  state of 8-bit, 8KHz, mono u-law data."
  1702.          *
  1703.          * Of course, we only do this for /dev/audio, and assume
  1704.          * OSS semantics on /dev/dsp
  1705.          */
  1706. if ((minor & 0xf) == SPARCAUDIO_AUDIO_MINOR) {
  1707.                 if (file->f_mode & FMODE_WRITE) {
  1708.                         if (drv->ops->set_output_channels)
  1709.                                 drv->ops->set_output_channels(drv, 1);
  1710.                         if (drv->ops->set_output_encoding)
  1711.                                 drv->ops->set_output_encoding(drv, AUDIO_ENCODING_ULAW);
  1712.                         if (drv->ops->set_output_rate)
  1713.                                 drv->ops->set_output_rate(drv, 8000);
  1714.                 }          
  1715.                 if (file->f_mode & FMODE_READ) {
  1716.                         if (drv->ops->set_input_channels)
  1717.                                 drv->ops->set_input_channels(drv, 1);
  1718.                         if (drv->ops->set_input_encoding)
  1719.                                 drv->ops->set_input_encoding(drv, AUDIO_ENCODING_ULAW);
  1720.                         if (drv->ops->set_input_rate)
  1721.                                 drv->ops->set_input_rate(drv, 8000);
  1722.                 }          
  1723.         }
  1724. /* Success! */
  1725. return 0;
  1726. }
  1727. static int sparcaudio_release(struct inode * inode, struct file * file)
  1728. {
  1729.         struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
  1730.                                                  SPARCAUDIO_DEVICE_SHIFT)];
  1731. lock_kernel();
  1732.         if (file->f_mode & FMODE_READ) {
  1733.                 /* Stop input */
  1734.                 drv->ops->stop_input(drv);
  1735.                 drv->input_active = 0;
  1736.         }
  1737.         if (file->f_mode & FMODE_WRITE) {
  1738.                 /* Anything in the queue? */
  1739.                 if (drv->output_offset) {
  1740.                         drv->output_offset = 0;
  1741.                         drv->output_rear = (drv->output_rear + 1)
  1742.                                 % drv->num_output_buffers;
  1743.                         drv->output_count++;
  1744.                 }
  1745.                 sparcaudio_sync_output(drv);
  1746.                 /* Wait for any output still in the queue to be played. */
  1747.                 if ((drv->output_count > 0) || (drv->playing_count > 0))
  1748.                         interruptible_sleep_on(&drv->output_drain_wait);
  1749.                 /* Force any output to be stopped. */
  1750.                 drv->ops->stop_output(drv);
  1751.                 drv->output_active = 0;
  1752.                 drv->playing_count = 0;
  1753.                 drv->output_eof = 0;
  1754.         }
  1755.         /* Let the low-level driver do any release processing. */
  1756.         if (drv->ops->release)
  1757.                 drv->ops->release(inode,file,drv);
  1758.         if (file->f_mode & FMODE_READ)
  1759.                 drv->flags &= ~(SDF_OPEN_READ);
  1760.         if (file->f_mode & FMODE_WRITE) 
  1761.                 drv->flags &= ~(SDF_OPEN_WRITE);
  1762.         /* Status changed. Signal control device */
  1763.         kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
  1764.         wake_up_interruptible(&drv->open_wait);
  1765. unlock_kernel();
  1766.         return 0;
  1767. }
  1768. static struct file_operations sparcaudio_fops = {
  1769. owner: THIS_MODULE,
  1770. llseek: no_llseek,
  1771. read: sparcaudio_read,
  1772. write: sparcaudio_write,
  1773. poll: sparcaudio_poll,
  1774. ioctl: sparcaudio_ioctl,
  1775. open: sparcaudio_open,
  1776. release: sparcaudio_release,
  1777. };
  1778. static struct {
  1779. unsigned short minor;
  1780. char *name;
  1781. umode_t mode;
  1782. } dev_list[] = {
  1783. { SPARCAUDIO_MIXER_MINOR, "mixer", S_IWUSR | S_IRUGO },
  1784. { SPARCAUDIO_DSP_MINOR, "dsp", S_IWUGO | S_IRUSR | S_IRGRP },
  1785. { SPARCAUDIO_AUDIO_MINOR, "audio", S_IWUGO | S_IRUSR | S_IRGRP },
  1786. { SPARCAUDIO_DSP16_MINOR, "dspW", S_IWUGO | S_IRUSR | S_IRGRP },
  1787. { SPARCAUDIO_STATUS_MINOR, "status", S_IRUGO },
  1788. { SPARCAUDIO_AUDIOCTL_MINOR, "audioctl", S_IRUGO }
  1789. };
  1790. static void sparcaudio_mkname (char *buf, char *name, int dev)
  1791. {
  1792.         if (dev)
  1793.                 sprintf (buf, "%s%d", name, dev);
  1794.         else
  1795.                 sprintf (buf, "%s", name);
  1796. }
  1797. int register_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
  1798. {
  1799. int i, dev;
  1800. unsigned short minor;
  1801. char name_buf[32];
  1802. /* If we've used up SPARCAUDIO_MAX_DEVICES, fail */
  1803. for (dev = 0; dev < SPARCAUDIO_MAX_DEVICES; dev++) {
  1804.                 if (drivers[dev] == NULL)
  1805.                         break;
  1806. }
  1807. if (drivers[dev])
  1808.                 return -EIO;
  1809. /* Ensure that the driver has a proper operations structure. */
  1810. if (!drv->ops || !drv->ops->start_output || !drv->ops->stop_output ||
  1811.     !drv->ops->start_input || !drv->ops->stop_input)
  1812. return -EINVAL;
  1813.         /* Register ourselves with devfs */
  1814. for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) {
  1815. sparcaudio_mkname (name_buf, dev_list[i].name, dev);
  1816. minor = (dev << SPARCAUDIO_DEVICE_SHIFT) | dev_list[i].minor;
  1817. devfs_register (devfs_handle, name_buf, DEVFS_FL_NONE,
  1818. SOUND_MAJOR, minor, S_IFCHR | dev_list[i].mode,
  1819. &sparcaudio_fops, NULL);
  1820. }
  1821.         /* Setup the circular queues of output and input buffers
  1822.          *
  1823.          * Each buffer is a single page, but output buffers might
  1824.          * be partially filled (by a write with count < output_buffer_size),
  1825.          * so each output buffer also has a paired output size.
  1826.          *
  1827.          * Input buffers, on the other hand, always fill completely,
  1828.          * so we don't need input counts - each contains input_buffer_size
  1829.          * bytes of audio data.
  1830.          *
  1831.          * TODO: Make number of input/output buffers tunable parameters
  1832.          */
  1833.         init_waitqueue_head(&drv->open_wait);
  1834.         init_waitqueue_head(&drv->output_write_wait);
  1835.         init_waitqueue_head(&drv->output_drain_wait);
  1836.         init_waitqueue_head(&drv->input_read_wait);
  1837.         drv->num_output_buffers = 8;
  1838. drv->output_buffer_size = (4096 * 2);
  1839. drv->playing_count = 0;
  1840. drv->output_offset = 0;
  1841. drv->output_eof = 0;
  1842.         drv->output_front = 0;
  1843.         drv->output_rear = 0;
  1844.         drv->output_count = 0;
  1845.         drv->output_active = 0;
  1846.         drv->output_buffers = kmalloc(drv->num_output_buffers * 
  1847.       sizeof(__u8 *), GFP_KERNEL);
  1848.         drv->output_sizes = kmalloc(drv->num_output_buffers * 
  1849.     sizeof(size_t), GFP_KERNEL);
  1850.         drv->output_notify = kmalloc(drv->num_output_buffers * 
  1851.     sizeof(char), GFP_KERNEL);
  1852.         if (!drv->output_buffers || !drv->output_sizes || !drv->output_notify)
  1853.                 goto kmalloc_failed1;
  1854. drv->output_buffer = kmalloc((drv->output_buffer_size * 
  1855.                                       drv->num_output_buffers),
  1856.                                      GFP_KERNEL);
  1857. if (!drv->output_buffer)
  1858.                 goto kmalloc_failed2;
  1859.         /* Allocate the pages for each output buffer. */
  1860.         for (i = 0; i < drv->num_output_buffers; i++) {
  1861.         drv->output_buffers[i] = (void *)(drv->output_buffer + 
  1862.                                                   (i * drv->output_buffer_size));
  1863. drv->output_sizes[i] = 0;
  1864. drv->output_notify[i] = 0;
  1865.         }
  1866.         /* Setup the circular queue of input buffers. */
  1867.         drv->num_input_buffers = 8;
  1868. drv->input_buffer_size = (4096 * 2);
  1869. drv->recording_count = 0;
  1870.         drv->input_front = 0;
  1871.         drv->input_rear = 0;
  1872.         drv->input_count = 0;
  1873. drv->input_offset = 0;
  1874.         drv->input_size = 0;
  1875.         drv->input_active = 0;
  1876.         drv->input_buffers = kmalloc(drv->num_input_buffers * sizeof(__u8 *),
  1877.      GFP_KERNEL);
  1878.         drv->input_sizes = kmalloc(drv->num_input_buffers * 
  1879.                                    sizeof(size_t), GFP_KERNEL);
  1880.         if (!drv->input_buffers || !drv->input_sizes)
  1881.                 goto kmalloc_failed3;
  1882.         /* Allocate the pages for each input buffer. */
  1883. if (duplex == 1) {
  1884.                 drv->input_buffer = kmalloc((drv->input_buffer_size * 
  1885.                                              drv->num_input_buffers), 
  1886.                                             GFP_DMA);
  1887.                 if (!drv->input_buffer)
  1888.                         goto kmalloc_failed4;
  1889.                 for (i = 0; i < drv->num_input_buffers; i++)
  1890.                         drv->input_buffers[i] = (void *)(drv->input_buffer + 
  1891.                                                          (i * drv->input_buffer_size));
  1892. } else {
  1893.                 if (duplex == 2) {
  1894.                         drv->input_buffer = drv->output_buffer;
  1895.                         drv->input_buffer_size = drv->output_buffer_size;
  1896.                         drv->num_input_buffers = drv->num_output_buffers;
  1897.                         for (i = 0; i < drv->num_input_buffers; i++) 
  1898.                                 drv->input_buffers[i] = drv->output_buffers[i];
  1899.                 } else {
  1900.                         for (i = 0; i < drv->num_input_buffers; i++) 
  1901.                                 drv->input_buffers[i] = NULL;
  1902.                 }
  1903. }
  1904. /* Take note of our duplexity */
  1905. drv->duplex = duplex;
  1906. /* Ensure that the driver is marked as not being open. */
  1907. drv->flags = 0;
  1908. MOD_INC_USE_COUNT;
  1909. /* Take driver slot, note which we took */
  1910. drv->index = dev;
  1911. drivers[dev] = drv;
  1912. return 0;
  1913. kmalloc_failed4:
  1914. kfree(drv->input_buffer);
  1915. kmalloc_failed3:
  1916.         if (drv->input_sizes)
  1917.                 kfree(drv->input_sizes);
  1918.         if (drv->input_buffers)
  1919.                 kfree(drv->input_buffers);
  1920.         i = drv->num_output_buffers;
  1921. kmalloc_failed2:
  1922. kfree(drv->output_buffer);
  1923. kmalloc_failed1:
  1924.         if (drv->output_buffers)
  1925.                 kfree(drv->output_buffers);
  1926.         if (drv->output_sizes)
  1927.                 kfree(drv->output_sizes);
  1928.         if (drv->output_notify)
  1929.                 kfree(drv->output_notify);
  1930.         return -ENOMEM;
  1931. }
  1932. int unregister_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
  1933. {
  1934. devfs_handle_t de;
  1935. int i;
  1936. char name_buf[32];
  1937. /* Figure out which driver is unregistering */
  1938. if (drivers[drv->index] != drv)
  1939. return -EIO;
  1940. /* Deallocate the queue of output buffers. */
  1941. kfree(drv->output_buffer);
  1942. kfree(drv->output_buffers);
  1943. kfree(drv->output_sizes);
  1944. kfree(drv->output_notify);
  1945. /* Deallocate the queue of input buffers. */
  1946. if (duplex == 1) {
  1947.                 kfree(drv->input_buffer);
  1948.                 kfree(drv->input_sizes);
  1949. }
  1950. kfree(drv->input_buffers);
  1951. if (&(drv->sd_siglist) != NULL)
  1952.                 lis_free_elist( &(drv->sd_siglist) );
  1953. /* Unregister ourselves with devfs */
  1954. for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) {
  1955. sparcaudio_mkname (name_buf, dev_list[i].name, drv->index);
  1956. de = devfs_find_handle (devfs_handle, name_buf, 0, 0,
  1957. DEVFS_SPECIAL_CHR, 0);
  1958. devfs_unregister (de);
  1959. }
  1960. MOD_DEC_USE_COUNT;
  1961. /* Null the appropriate driver */
  1962. drivers[drv->index] = NULL;
  1963. return 0;
  1964. }
  1965. EXPORT_SYMBOL(register_sparcaudio_driver);
  1966. EXPORT_SYMBOL(unregister_sparcaudio_driver);
  1967. EXPORT_SYMBOL(sparcaudio_output_done);
  1968. EXPORT_SYMBOL(sparcaudio_input_done);
  1969. static int __init sparcaudio_init(void)
  1970. {
  1971. /* Register our character device driver with the VFS. */
  1972. if (devfs_register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops))
  1973. return -EIO;
  1974. devfs_handle = devfs_mk_dir (NULL, "sound", NULL);
  1975. return 0;
  1976. }
  1977. static void __exit sparcaudio_exit(void)
  1978. {
  1979. devfs_unregister_chrdev(SOUND_MAJOR, "sparcaudio");
  1980. devfs_unregister (devfs_handle);
  1981. }
  1982. module_init(sparcaudio_init);
  1983. module_exit(sparcaudio_exit);
  1984. MODULE_LICENSE("GPL");
  1985. /*
  1986.  * Code from Linux Streams, Copyright 1995 by
  1987.  * Graham Wheeler, Francisco J. Ballesteros, Denis Froschauer
  1988.  * and available under GPL 
  1989.  */
  1990. static int
  1991. lis_add_to_elist( strevent_t **list, pid_t pid, short events )
  1992. {
  1993.         strevent_t *ev = NULL;
  1994.         if (*list != NULL) {
  1995.                 for (ev = (*list)->se_next;
  1996.                      ev != *list && ev->se_pid < pid;
  1997.                      ev = ev->se_next)
  1998.                         ;
  1999.         }
  2000.         if (ev == NULL || ev == *list) {             /* no slot for pid in list */
  2001.                 ev = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL);
  2002.                 if (ev == NULL)
  2003.                         return(-ENOMEM);
  2004.                 if (!*list) {                   /* create dummy head node */
  2005.                         strevent_t *hd;
  2006.                         hd = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL);
  2007.                         if (hd == NULL) {
  2008.                                 kfree(ev);
  2009.                                 return(-ENOMEM);
  2010.                         }
  2011.                         (*list = hd)->se_pid = 0;
  2012.                         hd->se_next = hd->se_prev = hd;         /* empty list */
  2013.                 }
  2014.                 /* link node last in the list */
  2015.                 ev->se_prev = (*list)->se_prev;
  2016.                 (*list)->se_prev->se_next = ev;
  2017.                 ((*list)->se_prev = ev)->se_next = *list;
  2018.                 ev->se_pid = pid;
  2019.                 ev->se_evs = 0;
  2020.         } else if (ev->se_pid != pid) {  /* link node in the middle of the list */
  2021.                 strevent_t *new;
  2022.                 new = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL);
  2023.                 if (new == NULL)
  2024.                         return -ENOMEM;
  2025.                 new->se_prev = ev->se_prev;
  2026.                 new->se_next = ev;
  2027.                 ev->se_prev->se_next = new;
  2028.                 ev->se_prev = new;
  2029.                 ev = new;                              /* use new element */
  2030.                 ev->se_pid = pid;
  2031.                 ev->se_evs = 0;
  2032.         }
  2033.         ev->se_evs |= events;
  2034.         return 0;
  2035. }
  2036. static int
  2037. lis_del_from_elist( strevent_t **list, pid_t pid, short events )
  2038. {
  2039.         strevent_t *ev = NULL;     
  2040.         if (*list != NULL) {
  2041.                 for (ev = (*list)->se_next;
  2042.                      ev != *list && ev->se_pid < pid;
  2043.                      ev = ev->se_next)
  2044.                         ;
  2045.         }
  2046.         if (ev == NULL || ev == *list || ev->se_pid != pid)
  2047.                 return 1;
  2048.         if ((ev->se_evs &= ~events) == 0) {        /* unlink */
  2049.                 if (ev->se_next)                        /* should always be true */
  2050.                         ev->se_next->se_prev = ev->se_prev;
  2051.                 if (ev->se_prev)                        /* should always be true */
  2052.                         ev->se_prev->se_next = ev->se_next;
  2053.                 kfree(ev);
  2054.         }
  2055.         return 0;
  2056. }
  2057. static void
  2058. lis_free_elist( strevent_t **list )
  2059. {
  2060.         strevent_t  *ev;     
  2061.         strevent_t  *nxt;
  2062.         for (ev = *list; ev != NULL; ) {
  2063.                 nxt = ev->se_next;
  2064.                 kfree(ev);
  2065.                 ev = nxt;
  2066.                 if (ev == *list)
  2067.                         break;                /* all done */
  2068.         }
  2069.         *list = NULL;
  2070. }
  2071. static short
  2072. lis_get_elist_ent( strevent_t *list, pid_t pid )
  2073. {
  2074.         strevent_t *ev = NULL;
  2075.         if (list == NULL)
  2076.                 return 0;
  2077.         for(ev = list->se_next ; ev != list && ev->se_pid < pid; ev = ev->se_next)
  2078.                 ;
  2079.         if (ev != list && ev->se_pid == pid)
  2080.                 return ev->se_evs;
  2081.         else
  2082.                 return 0;
  2083. }
  2084. static void 
  2085. kill_procs( struct strevent *elist, int sig, short e)
  2086. {
  2087.         strevent_t *ev;
  2088.         int res;
  2089.         if (elist) {
  2090.                 for(ev = elist->se_next ; ev != elist; ev = ev->se_next)
  2091.                         if ((ev->se_evs & e) != 0) {
  2092.                                 res = kill_proc(ev->se_pid, SIGPOLL, 1);
  2093.                                 if (res < 0) {
  2094.                                         if (res == -3) {
  2095.                                                 lis_del_from_elist(&elist,
  2096.                                                                    ev->se_pid,
  2097.                                                                    S_ALL);
  2098.                                                 continue;
  2099.                                         }
  2100.                                         dprintk(("kill_proc: errno %dn",res));
  2101.                                 }
  2102.                         }
  2103.         }
  2104. }
  2105. /*
  2106.  * Overrides for Emacs so that we follow Linus's tabbing style.
  2107.  * Emacs will notice this stuff at the end of the file and automatically
  2108.  * adjust the settings for this buffer only.  This must remain at the end
  2109.  * of the file.
  2110.  * ---------------------------------------------------------------------------
  2111.  * Local variables:
  2112.  * c-indent-level: 4
  2113.  * c-brace-imaginary-offset: 0
  2114.  * c-brace-offset: -4
  2115.  * c-argdecl-indent: 4
  2116.  * c-label-offset: -4
  2117.  * c-continued-statement-offset: 4
  2118.  * c-continued-brace-offset: 0
  2119.  * indent-tabs-mode: nil
  2120.  * tab-width: 8
  2121.  * End:
  2122.  */