at v2.6.33 5.7 kB view raw
1/* 2 * sound/oss/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#include "sound_config.h" 17 18struct audio_operations *audio_devs[MAX_AUDIO_DEV]; 19EXPORT_SYMBOL(audio_devs); 20 21int num_audiodevs; 22EXPORT_SYMBOL(num_audiodevs); 23 24struct mixer_operations *mixer_devs[MAX_MIXER_DEV]; 25EXPORT_SYMBOL(mixer_devs); 26 27int num_mixers; 28EXPORT_SYMBOL(num_mixers); 29 30struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; 31EXPORT_SYMBOL(synth_devs); 32 33int num_synths; 34 35struct midi_operations *midi_devs[MAX_MIDI_DEV]; 36EXPORT_SYMBOL(midi_devs); 37 38int num_midis; 39EXPORT_SYMBOL(num_midis); 40 41struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { 42 &default_sound_timer, NULL 43}; 44EXPORT_SYMBOL(sound_timer_devs); 45 46int num_sound_timers = 1; 47 48 49static int sound_alloc_audiodev(void); 50 51int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, 52 int driver_size, int flags, unsigned int format_mask, 53 void *devc, int dma1, int dma2) 54{ 55 struct audio_driver *d; 56 struct audio_operations *op; 57 int num; 58 59 if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) { 60 printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); 61 return -(EINVAL); 62 } 63 num = sound_alloc_audiodev(); 64 65 if (num == -1) { 66 printk(KERN_ERR "sound: Too many audio drivers\n"); 67 return -(EBUSY); 68 } 69 d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); 70 sound_nblocks++; 71 if (sound_nblocks >= MAX_MEM_BLOCKS) 72 sound_nblocks = MAX_MEM_BLOCKS - 1; 73 74 op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations))); 75 sound_nblocks++; 76 if (sound_nblocks >= MAX_MEM_BLOCKS) 77 sound_nblocks = MAX_MEM_BLOCKS - 1; 78 79 if (d == NULL || op == NULL) { 80 printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); 81 sound_unload_audiodev(num); 82 return -(ENOMEM); 83 } 84 memset((char *) op, 0, sizeof(struct audio_operations)); 85 init_waitqueue_head(&op->in_sleeper); 86 init_waitqueue_head(&op->out_sleeper); 87 init_waitqueue_head(&op->poll_sleeper); 88 if (driver_size < sizeof(struct audio_driver)) 89 memset((char *) d, 0, sizeof(struct audio_driver)); 90 91 memcpy((char *) d, (char *) driver, driver_size); 92 93 op->d = d; 94 strlcpy(op->name, name, sizeof(op->name)); 95 op->flags = flags; 96 op->format_mask = format_mask; 97 op->devc = devc; 98 99 /* 100 * Hardcoded defaults 101 */ 102 audio_devs[num] = op; 103 104 DMAbuf_init(num, dma1, dma2); 105 106 audio_init_devices(); 107 return num; 108} 109EXPORT_SYMBOL(sound_install_audiodrv); 110 111int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, 112 int driver_size, void *devc) 113{ 114 struct mixer_operations *op; 115 116 int n = sound_alloc_mixerdev(); 117 118 if (n == -1) { 119 printk(KERN_ERR "Sound: Too many mixer drivers\n"); 120 return -EBUSY; 121 } 122 if (vers != MIXER_DRIVER_VERSION || 123 driver_size > sizeof(struct mixer_operations)) { 124 printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); 125 return -EINVAL; 126 } 127 128 /* FIXME: This leaks a mixer_operations struct every time its called 129 until you unload sound! */ 130 131 op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); 132 sound_nblocks++; 133 if (sound_nblocks >= MAX_MEM_BLOCKS) 134 sound_nblocks = MAX_MEM_BLOCKS - 1; 135 136 if (op == NULL) { 137 printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); 138 return -ENOMEM; 139 } 140 memset((char *) op, 0, sizeof(struct mixer_operations)); 141 memcpy((char *) op, (char *) driver, driver_size); 142 143 strlcpy(op->name, name, sizeof(op->name)); 144 op->devc = devc; 145 146 mixer_devs[n] = op; 147 return n; 148} 149EXPORT_SYMBOL(sound_install_mixer); 150 151void sound_unload_audiodev(int dev) 152{ 153 if (dev != -1) { 154 DMAbuf_deinit(dev); 155 audio_devs[dev] = NULL; 156 unregister_sound_dsp((dev<<4)+3); 157 } 158} 159EXPORT_SYMBOL(sound_unload_audiodev); 160 161static int sound_alloc_audiodev(void) 162{ 163 int i = register_sound_dsp(&oss_sound_fops, -1); 164 if(i==-1) 165 return i; 166 i>>=4; 167 if(i>=num_audiodevs) 168 num_audiodevs = i + 1; 169 return i; 170} 171 172int sound_alloc_mididev(void) 173{ 174 int i = register_sound_midi(&oss_sound_fops, -1); 175 if(i==-1) 176 return i; 177 i>>=4; 178 if(i>=num_midis) 179 num_midis = i + 1; 180 return i; 181} 182EXPORT_SYMBOL(sound_alloc_mididev); 183 184int sound_alloc_synthdev(void) 185{ 186 int i; 187 188 for (i = 0; i < MAX_SYNTH_DEV; i++) { 189 if (synth_devs[i] == NULL) { 190 if (i >= num_synths) 191 num_synths++; 192 return i; 193 } 194 } 195 return -1; 196} 197EXPORT_SYMBOL(sound_alloc_synthdev); 198 199int sound_alloc_mixerdev(void) 200{ 201 int i = register_sound_mixer(&oss_sound_fops, -1); 202 if(i==-1) 203 return -1; 204 i>>=4; 205 if(i>=num_mixers) 206 num_mixers = i + 1; 207 return i; 208} 209EXPORT_SYMBOL(sound_alloc_mixerdev); 210 211int sound_alloc_timerdev(void) 212{ 213 int i; 214 215 for (i = 0; i < MAX_TIMER_DEV; i++) { 216 if (sound_timer_devs[i] == NULL) { 217 if (i >= num_sound_timers) 218 num_sound_timers++; 219 return i; 220 } 221 } 222 return -1; 223} 224EXPORT_SYMBOL(sound_alloc_timerdev); 225 226void sound_unload_mixerdev(int dev) 227{ 228 if (dev != -1) { 229 mixer_devs[dev] = NULL; 230 unregister_sound_mixer(dev<<4); 231 num_mixers--; 232 } 233} 234EXPORT_SYMBOL(sound_unload_mixerdev); 235 236void sound_unload_mididev(int dev) 237{ 238 if (dev != -1) { 239 midi_devs[dev] = NULL; 240 unregister_sound_midi((dev<<4)+2); 241 } 242} 243EXPORT_SYMBOL(sound_unload_mididev); 244 245void sound_unload_synthdev(int dev) 246{ 247 if (dev != -1) 248 synth_devs[dev] = NULL; 249} 250EXPORT_SYMBOL(sound_unload_synthdev); 251 252void sound_unload_timerdev(int dev) 253{ 254 if (dev != -1) 255 sound_timer_devs[dev] = NULL; 256} 257EXPORT_SYMBOL(sound_unload_timerdev); 258