• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 struct audio_operations *audio_devs[MAX_AUDIO_DEV];
19 EXPORT_SYMBOL(audio_devs);
20 
21 int num_audiodevs;
22 EXPORT_SYMBOL(num_audiodevs);
23 
24 struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
25 EXPORT_SYMBOL(mixer_devs);
26 
27 int num_mixers;
28 EXPORT_SYMBOL(num_mixers);
29 
30 struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV];
31 EXPORT_SYMBOL(synth_devs);
32 
33 int num_synths;
34 
35 struct midi_operations *midi_devs[MAX_MIDI_DEV];
36 EXPORT_SYMBOL(midi_devs);
37 
38 int num_midis;
39 EXPORT_SYMBOL(num_midis);
40 
41 struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {
42 	&default_sound_timer, NULL
43 };
44 EXPORT_SYMBOL(sound_timer_devs);
45 
46 int num_sound_timers = 1;
47 
48 
49 static int sound_alloc_audiodev(void);
50 
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)51 int 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] = vzalloc(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 	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 }
108 EXPORT_SYMBOL(sound_install_audiodrv);
109 
sound_install_mixer(int vers,char * name,struct mixer_operations * driver,int driver_size,void * devc)110 int 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 	/* FIXME: This leaks a mixer_operations struct every time its called
128 	   until you unload sound! */
129 
130 	op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct mixer_operations)));
131 	sound_nblocks++;
132 	if (sound_nblocks >= MAX_MEM_BLOCKS)
133 		sound_nblocks = MAX_MEM_BLOCKS - 1;
134 
135 	if (op == NULL) {
136 		printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name);
137 		return -ENOMEM;
138 	}
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 }
147 EXPORT_SYMBOL(sound_install_mixer);
148 
sound_unload_audiodev(int dev)149 void 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 }
157 EXPORT_SYMBOL(sound_unload_audiodev);
158 
sound_alloc_audiodev(void)159 static 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 
sound_alloc_mididev(void)170 int 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 }
180 EXPORT_SYMBOL(sound_alloc_mididev);
181 
sound_alloc_synthdev(void)182 int 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 }
195 EXPORT_SYMBOL(sound_alloc_synthdev);
196 
sound_alloc_mixerdev(void)197 int 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 }
207 EXPORT_SYMBOL(sound_alloc_mixerdev);
208 
sound_alloc_timerdev(void)209 int 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 }
222 EXPORT_SYMBOL(sound_alloc_timerdev);
223 
sound_unload_mixerdev(int dev)224 void 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 }
232 EXPORT_SYMBOL(sound_unload_mixerdev);
233 
sound_unload_mididev(int dev)234 void sound_unload_mididev(int dev)
235 {
236 	if (dev != -1) {
237 		midi_devs[dev] = NULL;
238 		unregister_sound_midi((dev<<4)+2);
239 	}
240 }
241 EXPORT_SYMBOL(sound_unload_mididev);
242 
sound_unload_synthdev(int dev)243 void sound_unload_synthdev(int dev)
244 {
245 	if (dev != -1)
246 		synth_devs[dev] = NULL;
247 }
248 EXPORT_SYMBOL(sound_unload_synthdev);
249 
sound_unload_timerdev(int dev)250 void sound_unload_timerdev(int dev)
251 {
252 	if (dev != -1)
253 		sound_timer_devs[dev] = NULL;
254 }
255 EXPORT_SYMBOL(sound_unload_timerdev);
256 
257