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 129 op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); 130 sound_nblocks++; 131 if (sound_nblocks >= MAX_MEM_BLOCKS) 132 sound_nblocks = MAX_MEM_BLOCKS - 1; 133 134 if (op == NULL) { 135 printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); 136 return -ENOMEM; 137 } 138 memset((char *) op, 0, sizeof(struct mixer_operations)); 139 memcpy((char *) op, (char *) driver, driver_size); 140 141 strlcpy(op->name, name, sizeof(op->name)); 142 op->devc = devc; 143 144 mixer_devs[n] = op; 145 return n; 146} 147EXPORT_SYMBOL(sound_install_mixer); 148 149void sound_unload_audiodev(int dev) 150{ 151 if (dev != -1) { 152 DMAbuf_deinit(dev); 153 audio_devs[dev] = NULL; 154 unregister_sound_dsp((dev<<4)+3); 155 } 156} 157EXPORT_SYMBOL(sound_unload_audiodev); 158 159static int sound_alloc_audiodev(void) 160{ 161 int i = register_sound_dsp(&oss_sound_fops, -1); 162 if(i==-1) 163 return i; 164 i>>=4; 165 if(i>=num_audiodevs) 166 num_audiodevs = i + 1; 167 return i; 168} 169 170int sound_alloc_mididev(void) 171{ 172 int i = register_sound_midi(&oss_sound_fops, -1); 173 if(i==-1) 174 return i; 175 i>>=4; 176 if(i>=num_midis) 177 num_midis = i + 1; 178 return i; 179} 180EXPORT_SYMBOL(sound_alloc_mididev); 181 182int sound_alloc_synthdev(void) 183{ 184 int i; 185 186 for (i = 0; i < MAX_SYNTH_DEV; i++) { 187 if (synth_devs[i] == NULL) { 188 if (i >= num_synths) 189 num_synths++; 190 return i; 191 } 192 } 193 return -1; 194} 195EXPORT_SYMBOL(sound_alloc_synthdev); 196 197int sound_alloc_mixerdev(void) 198{ 199 int i = register_sound_mixer(&oss_sound_fops, -1); 200 if(i==-1) 201 return -1; 202 i>>=4; 203 if(i>=num_mixers) 204 num_mixers = i + 1; 205 return i; 206} 207EXPORT_SYMBOL(sound_alloc_mixerdev); 208 209int sound_alloc_timerdev(void) 210{ 211 int i; 212 213 for (i = 0; i < MAX_TIMER_DEV; i++) { 214 if (sound_timer_devs[i] == NULL) { 215 if (i >= num_sound_timers) 216 num_sound_timers++; 217 return i; 218 } 219 } 220 return -1; 221} 222EXPORT_SYMBOL(sound_alloc_timerdev); 223 224void sound_unload_mixerdev(int dev) 225{ 226 if (dev != -1) { 227 mixer_devs[dev] = NULL; 228 unregister_sound_mixer(dev<<4); 229 num_mixers--; 230 } 231} 232EXPORT_SYMBOL(sound_unload_mixerdev); 233 234void sound_unload_mididev(int dev) 235{ 236 if (dev != -1) { 237 midi_devs[dev] = NULL; 238 unregister_sound_midi((dev<<4)+2); 239 } 240} 241EXPORT_SYMBOL(sound_unload_mididev); 242 243void sound_unload_synthdev(int dev) 244{ 245 if (dev != -1) 246 synth_devs[dev] = NULL; 247} 248EXPORT_SYMBOL(sound_unload_synthdev); 249 250void sound_unload_timerdev(int dev) 251{ 252 if (dev != -1) 253 sound_timer_devs[dev] = NULL; 254} 255EXPORT_SYMBOL(sound_unload_timerdev); 256