File: /usr/src/linux/drivers/sound/dev_table.c

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     
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     
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     
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     
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     
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     
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     
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     
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     
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     
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     
211     void sound_unload_synthdev(int dev)
212     {
213     	if (dev != -1)
214     		synth_devs[dev] = NULL;
215     }
216     
217     void sound_unload_timerdev(int dev)
218     {
219     	if (dev != -1)
220     		sound_timer_devs[dev] = NULL;
221     }
222