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 71 if (sound_nblocks < 1024) 72 sound_nblocks++; 73 74 op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations))); 75 76 if (sound_nblocks < 1024) 77 sound_nblocks++; 78 if (d == NULL || op == NULL) { 79 printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); 80 sound_unload_audiodev(num); 81 return -(ENOMEM); 82 } 83 memset((char *) op, 0, sizeof(struct audio_operations)); 84 init_waitqueue_head(&op->in_sleeper); 85 init_waitqueue_head(&op->out_sleeper); 86 init_waitqueue_head(&op->poll_sleeper); 87 if (driver_size < sizeof(struct audio_driver)) 88 memset((char *) d, 0, sizeof(struct audio_driver)); 89 90 memcpy((char *) d, (char *) driver, driver_size); 91 92 op->d = d; 93 strlcpy(op->name, name, sizeof(op->name)); 94 op->flags = flags; 95 op->format_mask = format_mask; 96 op->devc = devc; 97 98 /* 99 * Hardcoded defaults 100 */ 101 audio_devs[num] = op; 102 103 DMAbuf_init(num, dma1, dma2); 104 105 audio_init_devices(); 106 return num; 107} 108EXPORT_SYMBOL(sound_install_audiodrv); 109 110int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, 111 int driver_size, void *devc) 112{ 113 struct mixer_operations *op; 114 115 int n = sound_alloc_mixerdev(); 116 117 if (n == -1) { 118 printk(KERN_ERR "Sound: Too many mixer drivers\n"); 119 return -EBUSY; 120 } 121 if (vers != MIXER_DRIVER_VERSION || 122 driver_size > sizeof(struct mixer_operations)) { 123 printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); 124 return -EINVAL; 125 } 126 127 128 op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); 129 130 if (sound_nblocks < 1024) 131 sound_nblocks++; 132 if (op == NULL) { 133 printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); 134 return -ENOMEM; 135 } 136 memset((char *) op, 0, sizeof(struct mixer_operations)); 137 memcpy((char *) op, (char *) driver, driver_size); 138 139 strlcpy(op->name, name, sizeof(op->name)); 140 op->devc = devc; 141 142 mixer_devs[n] = op; 143 return n; 144} 145EXPORT_SYMBOL(sound_install_mixer); 146 147void sound_unload_audiodev(int dev) 148{ 149 if (dev != -1) { 150 DMAbuf_deinit(dev); 151 audio_devs[dev] = NULL; 152 unregister_sound_dsp((dev<<4)+3); 153 } 154} 155EXPORT_SYMBOL(sound_unload_audiodev); 156 157static int sound_alloc_audiodev(void) 158{ 159 int i = register_sound_dsp(&oss_sound_fops, -1); 160 if(i==-1) 161 return i; 162 i>>=4; 163 if(i>=num_audiodevs) 164 num_audiodevs = i + 1; 165 return i; 166} 167 168int sound_alloc_mididev(void) 169{ 170 int i = register_sound_midi(&oss_sound_fops, -1); 171 if(i==-1) 172 return i; 173 i>>=4; 174 if(i>=num_midis) 175 num_midis = i + 1; 176 return i; 177} 178EXPORT_SYMBOL(sound_alloc_mididev); 179 180int sound_alloc_synthdev(void) 181{ 182 int i; 183 184 for (i = 0; i < MAX_SYNTH_DEV; i++) { 185 if (synth_devs[i] == NULL) { 186 if (i >= num_synths) 187 num_synths++; 188 return i; 189 } 190 } 191 return -1; 192} 193EXPORT_SYMBOL(sound_alloc_synthdev); 194 195int sound_alloc_mixerdev(void) 196{ 197 int i = register_sound_mixer(&oss_sound_fops, -1); 198 if(i==-1) 199 return -1; 200 i>>=4; 201 if(i>=num_mixers) 202 num_mixers = i + 1; 203 return i; 204} 205EXPORT_SYMBOL(sound_alloc_mixerdev); 206 207int sound_alloc_timerdev(void) 208{ 209 int i; 210 211 for (i = 0; i < MAX_TIMER_DEV; i++) { 212 if (sound_timer_devs[i] == NULL) { 213 if (i >= num_sound_timers) 214 num_sound_timers++; 215 return i; 216 } 217 } 218 return -1; 219} 220EXPORT_SYMBOL(sound_alloc_timerdev); 221 222void sound_unload_mixerdev(int dev) 223{ 224 if (dev != -1) { 225 mixer_devs[dev] = NULL; 226 unregister_sound_mixer(dev<<4); 227 num_mixers--; 228 } 229} 230EXPORT_SYMBOL(sound_unload_mixerdev); 231 232void sound_unload_mididev(int dev) 233{ 234 if (dev != -1) { 235 midi_devs[dev] = NULL; 236 unregister_sound_midi((dev<<4)+2); 237 } 238} 239EXPORT_SYMBOL(sound_unload_mididev); 240 241void sound_unload_synthdev(int dev) 242{ 243 if (dev != -1) 244 synth_devs[dev] = NULL; 245} 246EXPORT_SYMBOL(sound_unload_synthdev); 247 248void sound_unload_timerdev(int dev) 249{ 250 if (dev != -1) 251 sound_timer_devs[dev] = NULL; 252} 253EXPORT_SYMBOL(sound_unload_timerdev); 254