ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / oss / 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 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         strlcpy(op->name, name, sizeof(op->name));
62         op->flags = flags;
63         op->format_mask = format_mask;
64         op->devc = devc;
65
66         /*
67          *    Hardcoded defaults
68          */
69         audio_devs[num] = op;
70
71         DMAbuf_init(num, dma1, dma2);
72
73         audio_init_devices();
74         return num;
75 }
76
77 int sound_install_mixer(int vers, char *name, struct mixer_operations *driver,
78         int driver_size, void *devc)
79 {
80         struct mixer_operations *op;
81
82         int n = sound_alloc_mixerdev();
83
84         if (n == -1) {
85                 printk(KERN_ERR "Sound: Too many mixer drivers\n");
86                 return -EBUSY;
87         }
88         if (vers != MIXER_DRIVER_VERSION ||
89                 driver_size > sizeof(struct mixer_operations)) {
90                 printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name);
91                 return -EINVAL;
92         }
93         
94         /* FIXME: This leaks a mixer_operations struct every time its called
95            until you unload sound! */
96            
97         op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations)));
98
99         if (sound_nblocks < 1024)
100                 sound_nblocks++;
101         if (op == NULL) {
102                 printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name);
103                 return -ENOMEM;
104         }
105         memset((char *) op, 0, sizeof(struct mixer_operations));
106         memcpy((char *) op, (char *) driver, driver_size);
107
108         strlcpy(op->name, name, sizeof(op->name));
109         op->devc = devc;
110
111         mixer_devs[n] = op;
112         return n;
113 }
114
115 void sound_unload_audiodev(int dev)
116 {
117         if (dev != -1) {
118                 DMAbuf_deinit(dev);
119                 audio_devs[dev] = NULL;
120                 unregister_sound_dsp((dev<<4)+3);
121         }
122 }
123
124 int sound_alloc_audiodev(void)
125
126         int i = register_sound_dsp(&oss_sound_fops, -1);
127         if(i==-1)
128                 return i;
129         i>>=4;
130         if(i>=num_audiodevs)
131                 num_audiodevs = i + 1;
132         return i;
133 }
134
135 int sound_alloc_mididev(void)
136 {
137         int i = register_sound_midi(&oss_sound_fops, -1);
138         if(i==-1)
139                 return i;
140         i>>=4;
141         if(i>=num_midis)
142                 num_midis = i + 1;
143         return i;
144 }
145
146 int sound_alloc_synthdev(void)
147 {
148         int i;
149
150         for (i = 0; i < MAX_SYNTH_DEV; i++) {
151                 if (synth_devs[i] == NULL) {
152                         if (i >= num_synths)
153                                 num_synths++;
154                         return i;
155                 }
156         }
157         return -1;
158 }
159
160 int sound_alloc_mixerdev(void)
161 {
162         int i = register_sound_mixer(&oss_sound_fops, -1);
163         if(i==-1)
164                 return -1;
165         i>>=4;
166         if(i>=num_mixers)
167                 num_mixers = i + 1;
168         return i;
169 }
170
171 int sound_alloc_timerdev(void)
172 {
173         int i;
174
175         for (i = 0; i < MAX_TIMER_DEV; i++) {
176                 if (sound_timer_devs[i] == NULL) {
177                         if (i >= num_sound_timers)
178                                 num_sound_timers++;
179                         return i;
180                 }
181         }
182         return -1;
183 }
184
185 void sound_unload_mixerdev(int dev)
186 {
187         if (dev != -1) {
188                 mixer_devs[dev] = NULL;
189                 unregister_sound_mixer(dev<<4);
190                 num_mixers--;
191         }
192 }
193
194 void sound_unload_mididev(int dev)
195 {
196         if (dev != -1) {
197                 midi_devs[dev] = NULL;
198                 unregister_sound_midi((dev<<4)+2);
199         }
200 }
201
202 void sound_unload_synthdev(int dev)
203 {
204         if (dev != -1)
205                 synth_devs[dev] = NULL;
206 }
207
208 void sound_unload_timerdev(int dev)
209 {
210         if (dev != -1)
211                 sound_timer_devs[dev] = NULL;
212 }