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