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