patch-2.3.99-pre1 linux/drivers/sbus/audio/audio.c

Next file: linux/drivers/sbus/char/sab82532.c
Previous file: linux/drivers/pcmcia/yenta.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.51/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
@@ -1,4 +1,4 @@
-/* $Id: audio.c,v 1.49 2000/02/17 05:52:41 davem Exp $
+/* $Id: audio.c,v 1.50 2000/03/13 03:54:07 davem Exp $
  * drivers/sbus/audio/audio.c
  *
  * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -70,7 +70,8 @@
 static void kill_procs( struct strevent *elist, int sig, short e);
 
 static struct sparcaudio_driver *drivers[SPARCAUDIO_MAX_DEVICES] = {NULL};
-
+static devfs_handle_t devfs_handle = NULL;
+ 
 /* This crap to be pulled off into a local include file */
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
 
@@ -92,185 +93,6 @@
 
 #endif
 
-int register_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
-{
-	int i, dev;
-
-	/* If we've used up SPARCAUDIO_MAX_DEVICES, fail */
-	for (dev = 0; dev < SPARCAUDIO_MAX_DEVICES; dev++) {
-                if (drivers[dev] == NULL)
-                        break;
-	}
-
-	if (drivers[dev])
-                return -EIO;
-
-	/* Ensure that the driver has a proper operations structure. */
-	if (!drv->ops || !drv->ops->start_output || !drv->ops->stop_output ||
-	    !drv->ops->start_input || !drv->ops->stop_input)
-		return -EINVAL;
-
-        /* Setup the circular queues of output and input buffers
-         *
-         * Each buffer is a single page, but output buffers might
-         * be partially filled (by a write with count < output_buffer_size),
-         * so each output buffer also has a paired output size.
-         *
-         * Input buffers, on the other hand, always fill completely,
-         * so we don't need input counts - each contains input_buffer_size
-         * bytes of audio data.
-         *
-         * TODO: Make number of input/output buffers tunable parameters
-         */
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x202ff
-        init_waitqueue_head(&drv->open_wait);
-        init_waitqueue_head(&drv->output_write_wait);
-        init_waitqueue_head(&drv->output_drain_wait);
-        init_waitqueue_head(&drv->input_read_wait);
-#endif
-
-        drv->num_output_buffers = 8;
-	drv->output_buffer_size = (4096 * 2);
-	drv->playing_count = 0;
-	drv->output_offset = 0;
-	drv->output_eof = 0;
-        drv->output_front = 0;
-        drv->output_rear = 0;
-        drv->output_count = 0;
-        drv->output_active = 0;
-        drv->output_buffers = kmalloc(drv->num_output_buffers * 
-				      sizeof(__u8 *), GFP_KERNEL);
-        drv->output_sizes = kmalloc(drv->num_output_buffers * 
-				    sizeof(size_t), GFP_KERNEL);
-        drv->output_notify = kmalloc(drv->num_output_buffers * 
-				    sizeof(char), GFP_KERNEL);
-        if (!drv->output_buffers || !drv->output_sizes || !drv->output_notify)
-                goto kmalloc_failed1;
-
-	drv->output_buffer = kmalloc((drv->output_buffer_size * 
-                                      drv->num_output_buffers),
-                                     GFP_KERNEL);
-	if (!drv->output_buffer)
-                goto kmalloc_failed2;
-
-        /* Allocate the pages for each output buffer. */
-        for (i = 0; i < drv->num_output_buffers; i++) {
-	        drv->output_buffers[i] = (void *)(drv->output_buffer + 
-                                                  (i * drv->output_buffer_size));
-		drv->output_sizes[i] = 0;
-		drv->output_notify[i] = 0;
-        }
-
-        /* Setup the circular queue of input buffers. */
-        drv->num_input_buffers = 8;
-	drv->input_buffer_size = (4096 * 2);
-	drv->recording_count = 0;
-        drv->input_front = 0;
-        drv->input_rear = 0;
-        drv->input_count = 0;
-	drv->input_offset = 0;
-        drv->input_size = 0;
-        drv->input_active = 0;
-        drv->input_buffers = kmalloc(drv->num_input_buffers * sizeof(__u8 *),
-				     GFP_KERNEL);
-        drv->input_sizes = kmalloc(drv->num_input_buffers * 
-                                   sizeof(size_t), GFP_KERNEL);
-        if (!drv->input_buffers || !drv->input_sizes)
-                goto kmalloc_failed3;
-
-        /* Allocate the pages for each input buffer. */
-	if (duplex == 1) {
-                drv->input_buffer = kmalloc((drv->input_buffer_size * 
-                                             drv->num_input_buffers), 
-                                            GFP_DMA);
-                if (!drv->input_buffer)
-                        goto kmalloc_failed4;
-
-                for (i = 0; i < drv->num_input_buffers; i++)
-                        drv->input_buffers[i] = (void *)(drv->input_buffer + 
-                                                         (i * drv->input_buffer_size));
-	} else {
-                if (duplex == 2) {
-                        drv->input_buffer = drv->output_buffer;
-                        drv->input_buffer_size = drv->output_buffer_size;
-                        drv->num_input_buffers = drv->num_output_buffers;
-                        for (i = 0; i < drv->num_input_buffers; i++) 
-                                drv->input_buffers[i] = drv->output_buffers[i];
-                } else {
-                        for (i = 0; i < drv->num_input_buffers; i++) 
-                                drv->input_buffers[i] = NULL;
-                }
-	}
-
-	/* Take note of our duplexity */
-	drv->duplex = duplex;
-
-	/* Ensure that the driver is marked as not being open. */
-	drv->flags = 0;
-
-	MOD_INC_USE_COUNT;
-
-	/* Take driver slot, note which we took */
-	drv->index = dev;
-	drivers[dev] = drv;
-
-	return 0;
-
-kmalloc_failed4:
-	kfree(drv->input_buffer);
-
-kmalloc_failed3:
-        if (drv->input_sizes)
-                kfree(drv->input_sizes);
-        if (drv->input_buffers)
-                kfree(drv->input_buffers);
-        i = drv->num_output_buffers;
-
-kmalloc_failed2:
-	kfree(drv->output_buffer);
-
-kmalloc_failed1:
-        if (drv->output_buffers)
-                kfree(drv->output_buffers);
-        if (drv->output_sizes)
-                kfree(drv->output_sizes);
-        if (drv->output_notify)
-                kfree(drv->output_notify);
-
-        return -ENOMEM;
-}
-
-int unregister_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
-{
-	/* Figure out which driver is unregistering */
-	if (drivers[drv->index] != drv)
-		return -EIO;
-
-	/* Deallocate the queue of output buffers. */
-	kfree(drv->output_buffer);
-	kfree(drv->output_buffers);
-	kfree(drv->output_sizes);
-	kfree(drv->output_notify);
-
-	/* Deallocate the queue of input buffers. */
-	if (duplex == 1) {
-                kfree(drv->input_buffer);
-                kfree(drv->input_sizes);
-	}
-	kfree(drv->input_buffers);
-
-	if (&(drv->sd_siglist) != NULL)
-                lis_free_elist( &(drv->sd_siglist) );
-
-	MOD_DEC_USE_COUNT;
-
-	/* Null the appropriate driver */
-	drivers[drv->index] = NULL;
-
-	return 0;
-}
-
 void sparcaudio_output_done(struct sparcaudio_driver * drv, int status)
 {
         /* If !status, just restart current output.
@@ -2171,6 +1993,229 @@
 	release:	sparcaudio_release,
 };
 
+static struct {
+	unsigned short minor;
+	char *name;
+	umode_t mode;
+} dev_list[] = {
+	{ SPARCAUDIO_MIXER_MINOR, "mixer", S_IWUSR | S_IRUGO },
+	{ SPARCAUDIO_DSP_MINOR, "dsp", S_IWUGO | S_IRUSR | S_IRGRP },
+	{ SPARCAUDIO_AUDIO_MINOR, "audio", S_IWUGO | S_IRUSR | S_IRGRP },
+	{ SPARCAUDIO_DSP16_MINOR, "dspW", S_IWUGO | S_IRUSR | S_IRGRP },
+	{ SPARCAUDIO_STATUS_MINOR, "status", S_IRUGO },
+	{ SPARCAUDIO_AUDIOCTL_MINOR, "audioctl", S_IRUGO }
+};
+
+static void sparcaudio_mkname (char *buf, char *name, int dev)
+{
+        if (dev)
+                sprintf (buf, "%s%d", name, dev);
+        else
+                sprintf (buf, "%s", name);
+}
+
+int register_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
+{
+	int i, dev;
+	unsigned short minor;
+	char name_buf[32];
+
+	/* If we've used up SPARCAUDIO_MAX_DEVICES, fail */
+	for (dev = 0; dev < SPARCAUDIO_MAX_DEVICES; dev++) {
+                if (drivers[dev] == NULL)
+                        break;
+	}
+
+	if (drivers[dev])
+                return -EIO;
+
+	/* Ensure that the driver has a proper operations structure. */
+	if (!drv->ops || !drv->ops->start_output || !drv->ops->stop_output ||
+	    !drv->ops->start_input || !drv->ops->stop_input)
+		return -EINVAL;
+
+        /* Register ourselves with devfs */
+	for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) {
+		sparcaudio_mkname (name_buf, dev_list[i].name, dev);
+		minor = (dev << SPARCAUDIO_DEVICE_SHIFT) | dev_list[i].minor;
+		devfs_register (devfs_handle, name_buf, 0, DEVFS_FL_NONE,
+				SOUND_MAJOR, minor, S_IFCHR | dev_list[i].mode,
+				0, 0, &sparcaudio_fops, NULL);
+	}
+
+        /* Setup the circular queues of output and input buffers
+         *
+         * Each buffer is a single page, but output buffers might
+         * be partially filled (by a write with count < output_buffer_size),
+         * so each output buffer also has a paired output size.
+         *
+         * Input buffers, on the other hand, always fill completely,
+         * so we don't need input counts - each contains input_buffer_size
+         * bytes of audio data.
+         *
+         * TODO: Make number of input/output buffers tunable parameters
+         */
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x202ff
+        init_waitqueue_head(&drv->open_wait);
+        init_waitqueue_head(&drv->output_write_wait);
+        init_waitqueue_head(&drv->output_drain_wait);
+        init_waitqueue_head(&drv->input_read_wait);
+#endif
+
+        drv->num_output_buffers = 8;
+	drv->output_buffer_size = (4096 * 2);
+	drv->playing_count = 0;
+	drv->output_offset = 0;
+	drv->output_eof = 0;
+        drv->output_front = 0;
+        drv->output_rear = 0;
+        drv->output_count = 0;
+        drv->output_active = 0;
+        drv->output_buffers = kmalloc(drv->num_output_buffers * 
+				      sizeof(__u8 *), GFP_KERNEL);
+        drv->output_sizes = kmalloc(drv->num_output_buffers * 
+				    sizeof(size_t), GFP_KERNEL);
+        drv->output_notify = kmalloc(drv->num_output_buffers * 
+				    sizeof(char), GFP_KERNEL);
+        if (!drv->output_buffers || !drv->output_sizes || !drv->output_notify)
+                goto kmalloc_failed1;
+
+	drv->output_buffer = kmalloc((drv->output_buffer_size * 
+                                      drv->num_output_buffers),
+                                     GFP_KERNEL);
+	if (!drv->output_buffer)
+                goto kmalloc_failed2;
+
+        /* Allocate the pages for each output buffer. */
+        for (i = 0; i < drv->num_output_buffers; i++) {
+	        drv->output_buffers[i] = (void *)(drv->output_buffer + 
+                                                  (i * drv->output_buffer_size));
+		drv->output_sizes[i] = 0;
+		drv->output_notify[i] = 0;
+        }
+
+        /* Setup the circular queue of input buffers. */
+        drv->num_input_buffers = 8;
+	drv->input_buffer_size = (4096 * 2);
+	drv->recording_count = 0;
+        drv->input_front = 0;
+        drv->input_rear = 0;
+        drv->input_count = 0;
+	drv->input_offset = 0;
+        drv->input_size = 0;
+        drv->input_active = 0;
+        drv->input_buffers = kmalloc(drv->num_input_buffers * sizeof(__u8 *),
+				     GFP_KERNEL);
+        drv->input_sizes = kmalloc(drv->num_input_buffers * 
+                                   sizeof(size_t), GFP_KERNEL);
+        if (!drv->input_buffers || !drv->input_sizes)
+                goto kmalloc_failed3;
+
+        /* Allocate the pages for each input buffer. */
+	if (duplex == 1) {
+                drv->input_buffer = kmalloc((drv->input_buffer_size * 
+                                             drv->num_input_buffers), 
+                                            GFP_DMA);
+                if (!drv->input_buffer)
+                        goto kmalloc_failed4;
+
+                for (i = 0; i < drv->num_input_buffers; i++)
+                        drv->input_buffers[i] = (void *)(drv->input_buffer + 
+                                                         (i * drv->input_buffer_size));
+	} else {
+                if (duplex == 2) {
+                        drv->input_buffer = drv->output_buffer;
+                        drv->input_buffer_size = drv->output_buffer_size;
+                        drv->num_input_buffers = drv->num_output_buffers;
+                        for (i = 0; i < drv->num_input_buffers; i++) 
+                                drv->input_buffers[i] = drv->output_buffers[i];
+                } else {
+                        for (i = 0; i < drv->num_input_buffers; i++) 
+                                drv->input_buffers[i] = NULL;
+                }
+	}
+
+	/* Take note of our duplexity */
+	drv->duplex = duplex;
+
+	/* Ensure that the driver is marked as not being open. */
+	drv->flags = 0;
+
+	MOD_INC_USE_COUNT;
+
+	/* Take driver slot, note which we took */
+	drv->index = dev;
+	drivers[dev] = drv;
+
+	return 0;
+
+kmalloc_failed4:
+	kfree(drv->input_buffer);
+
+kmalloc_failed3:
+        if (drv->input_sizes)
+                kfree(drv->input_sizes);
+        if (drv->input_buffers)
+                kfree(drv->input_buffers);
+        i = drv->num_output_buffers;
+
+kmalloc_failed2:
+	kfree(drv->output_buffer);
+
+kmalloc_failed1:
+        if (drv->output_buffers)
+                kfree(drv->output_buffers);
+        if (drv->output_sizes)
+                kfree(drv->output_sizes);
+        if (drv->output_notify)
+                kfree(drv->output_notify);
+
+        return -ENOMEM;
+}
+
+int unregister_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
+{
+	devfs_handle_t de;
+	int i;
+	char name_buf[32];
+
+	/* Figure out which driver is unregistering */
+	if (drivers[drv->index] != drv)
+		return -EIO;
+
+	/* Deallocate the queue of output buffers. */
+	kfree(drv->output_buffer);
+	kfree(drv->output_buffers);
+	kfree(drv->output_sizes);
+	kfree(drv->output_notify);
+
+	/* Deallocate the queue of input buffers. */
+	if (duplex == 1) {
+                kfree(drv->input_buffer);
+                kfree(drv->input_sizes);
+	}
+	kfree(drv->input_buffers);
+
+	if (&(drv->sd_siglist) != NULL)
+                lis_free_elist( &(drv->sd_siglist) );
+
+	/* Unregister ourselves with devfs */
+	for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) {
+		sparcaudio_mkname (name_buf, dev_list[i].name, drv->index);
+		de = devfs_find_handle (devfs_handle, name_buf, 0, 0, 0,
+					DEVFS_SPECIAL_CHR, 0);
+		devfs_unregister (de);
+	}
+
+	MOD_DEC_USE_COUNT;
+
+	/* Null the appropriate driver */
+	drivers[drv->index] = NULL;
+
+	return 0;
+}
+
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
 static struct symbol_table sparcaudio_syms = {
 #include <linux/symtab_begin.h>
@@ -2201,6 +2246,8 @@
 	/* Register our character device driver with the VFS. */
 	if (devfs_register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops))
 		return -EIO;
+
+	devfs_handle = devfs_mk_dir (NULL, "sound", 0, NULL);
 	
 #ifdef CONFIG_SPARCAUDIO_AMD7930
 	amd7930_init();
@@ -2222,6 +2269,7 @@
 void cleanup_module(void)
 {
 	devfs_unregister_chrdev(SOUND_MAJOR, "sparcaudio");
+	devfs_unregister (devfs_handle);
 }
 #endif
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)