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
19int 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
81int 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
100	op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations)));
101
102	if (sound_nblocks < 1024)
103		sound_nblocks++;
104	if (op == NULL) {
105		printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name);
106		return -ENOMEM;
107	}
108	memset((char *) op, 0, sizeof(struct mixer_operations));
109	memcpy((char *) op, (char *) driver, driver_size);
110
111	l = strlen(name) + 1;
112	if (l > sizeof(op->name))
113		l = sizeof(op->name);
114	strncpy(op->name, name, l);
115	op->name[l - 1] = 0;
116	op->devc = devc;
117
118	mixer_devs[n] = op;
119	return n;
120}
121
122void sound_unload_audiodev(int dev)
123{
124	if (dev != -1) {
125		DMAbuf_deinit(dev);
126		audio_devs[dev] = NULL;
127		unregister_sound_dsp((dev<<4)+3);
128	}
129}
130
131int sound_alloc_audiodev(void)
132{
133	int i = register_sound_dsp(&oss_sound_fops, -1);
134	if(i==-1)
135		return i;
136	i>>=4;
137	if(i>=num_audiodevs)
138		num_audiodevs = i + 1;
139	return i;
140}
141
142int sound_alloc_mididev(void)
143{
144	int i = register_sound_midi(&oss_sound_fops, -1);
145	if(i==-1)
146		return i;
147	i>>=4;
148	if(i>=num_midis)
149		num_midis = i + 1;
150	return i;
151}
152
153int sound_alloc_synthdev(void)
154{
155	int i;
156
157	for (i = 0; i < MAX_SYNTH_DEV; i++) {
158		if (synth_devs[i] == NULL) {
159			if (i >= num_synths)
160				num_synths++;
161			return i;
162		}
163	}
164	return -1;
165}
166
167int sound_alloc_mixerdev(void)
168{
169	int i = register_sound_mixer(&oss_sound_fops, -1);
170	if(i==-1)
171		return -1;
172	i>>=4;
173	if(i>=num_mixers)
174		num_mixers = i + 1;
175	return i;
176}
177
178int sound_alloc_timerdev(void)
179{
180	int i;
181
182	for (i = 0; i < MAX_TIMER_DEV; i++) {
183		if (sound_timer_devs[i] == NULL) {
184			if (i >= num_sound_timers)
185				num_sound_timers++;
186			return i;
187		}
188	}
189	return -1;
190}
191
192void sound_unload_mixerdev(int dev)
193{
194	if (dev != -1) {
195		mixer_devs[dev] = NULL;
196		unregister_sound_mixer(dev<<4);
197		num_mixers--;
198	}
199}
200
201void sound_unload_mididev(int dev)
202{
203	if (dev != -1) {
204		midi_devs[dev] = NULL;
205		unregister_sound_midi((dev<<4)+2);
206	}
207}
208
209void sound_unload_synthdev(int dev)
210{
211	if (dev != -1)
212		synth_devs[dev] = NULL;
213}
214
215void sound_unload_timerdev(int dev)
216{
217	if (dev != -1)
218		sound_timer_devs[dev] = NULL;
219}
220