at v2.6.14 4.5 kB view raw
1/* 2 * sound/dev_table.c 3 * 4 * Device call tables. 5 * 6 * 7 * Copyright (C) by Hannu Savolainen 1993-1997 8 * 9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) 10 * Version 2 (June 1991). See the "COPYING" file distributed with this software 11 * for more info. 12 */ 13 14#include <linux/init.h> 15 16#define _DEV_TABLE_C_ 17#include "sound_config.h" 18 19static int sound_alloc_audiodev(void); 20 21int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, 22 int driver_size, int flags, unsigned int format_mask, 23 void *devc, int dma1, int dma2) 24{ 25 struct audio_driver *d; 26 struct audio_operations *op; 27 int num; 28 29 if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) { 30 printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); 31 return -(EINVAL); 32 } 33 num = sound_alloc_audiodev(); 34 35 if (num == -1) { 36 printk(KERN_ERR "sound: Too many audio drivers\n"); 37 return -(EBUSY); 38 } 39 d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); 40 41 if (sound_nblocks < 1024) 42 sound_nblocks++; 43 44 op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations))); 45 46 if (sound_nblocks < 1024) 47 sound_nblocks++; 48 if (d == NULL || op == NULL) { 49 printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); 50 sound_unload_audiodev(num); 51 return -(ENOMEM); 52 } 53 memset((char *) op, 0, sizeof(struct audio_operations)); 54 init_waitqueue_head(&op->in_sleeper); 55 init_waitqueue_head(&op->out_sleeper); 56 init_waitqueue_head(&op->poll_sleeper); 57 if (driver_size < sizeof(struct audio_driver)) 58 memset((char *) d, 0, sizeof(struct audio_driver)); 59 60 memcpy((char *) d, (char *) driver, driver_size); 61 62 op->d = d; 63 strlcpy(op->name, name, sizeof(op->name)); 64 op->flags = flags; 65 op->format_mask = format_mask; 66 op->devc = devc; 67 68 /* 69 * Hardcoded defaults 70 */ 71 audio_devs[num] = op; 72 73 DMAbuf_init(num, dma1, dma2); 74 75 audio_init_devices(); 76 return num; 77} 78 79int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, 80 int driver_size, void *devc) 81{ 82 struct mixer_operations *op; 83 84 int n = sound_alloc_mixerdev(); 85 86 if (n == -1) { 87 printk(KERN_ERR "Sound: Too many mixer drivers\n"); 88 return -EBUSY; 89 } 90 if (vers != MIXER_DRIVER_VERSION || 91 driver_size > sizeof(struct mixer_operations)) { 92 printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); 93 return -EINVAL; 94 } 95 96 /* FIXME: This leaks a mixer_operations struct every time its called 97 until you unload sound! */ 98 99 op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); 100 101 if (sound_nblocks < 1024) 102 sound_nblocks++; 103 if (op == NULL) { 104 printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); 105 return -ENOMEM; 106 } 107 memset((char *) op, 0, sizeof(struct mixer_operations)); 108 memcpy((char *) op, (char *) driver, driver_size); 109 110 strlcpy(op->name, name, sizeof(op->name)); 111 op->devc = devc; 112 113 mixer_devs[n] = op; 114 return n; 115} 116 117void sound_unload_audiodev(int dev) 118{ 119 if (dev != -1) { 120 DMAbuf_deinit(dev); 121 audio_devs[dev] = NULL; 122 unregister_sound_dsp((dev<<4)+3); 123 } 124} 125 126static int sound_alloc_audiodev(void) 127{ 128 int i = register_sound_dsp(&oss_sound_fops, -1); 129 if(i==-1) 130 return i; 131 i>>=4; 132 if(i>=num_audiodevs) 133 num_audiodevs = i + 1; 134 return i; 135} 136 137int sound_alloc_mididev(void) 138{ 139 int i = register_sound_midi(&oss_sound_fops, -1); 140 if(i==-1) 141 return i; 142 i>>=4; 143 if(i>=num_midis) 144 num_midis = i + 1; 145 return i; 146} 147 148int sound_alloc_synthdev(void) 149{ 150 int i; 151 152 for (i = 0; i < MAX_SYNTH_DEV; i++) { 153 if (synth_devs[i] == NULL) { 154 if (i >= num_synths) 155 num_synths++; 156 return i; 157 } 158 } 159 return -1; 160} 161 162int sound_alloc_mixerdev(void) 163{ 164 int i = register_sound_mixer(&oss_sound_fops, -1); 165 if(i==-1) 166 return -1; 167 i>>=4; 168 if(i>=num_mixers) 169 num_mixers = i + 1; 170 return i; 171} 172 173int sound_alloc_timerdev(void) 174{ 175 int i; 176 177 for (i = 0; i < MAX_TIMER_DEV; i++) { 178 if (sound_timer_devs[i] == NULL) { 179 if (i >= num_sound_timers) 180 num_sound_timers++; 181 return i; 182 } 183 } 184 return -1; 185} 186 187void sound_unload_mixerdev(int dev) 188{ 189 if (dev != -1) { 190 mixer_devs[dev] = NULL; 191 unregister_sound_mixer(dev<<4); 192 num_mixers--; 193 } 194} 195 196void sound_unload_mididev(int dev) 197{ 198 if (dev != -1) { 199 midi_devs[dev] = NULL; 200 unregister_sound_midi((dev<<4)+2); 201 } 202} 203 204void sound_unload_synthdev(int dev) 205{ 206 if (dev != -1) 207 synth_devs[dev] = NULL; 208} 209 210void sound_unload_timerdev(int dev) 211{ 212 if (dev != -1) 213 sound_timer_devs[dev] = NULL; 214}