78406d7334bfb64ad7eefbaf5ab1e7af5c8f972f
[linux-flexiantxendom0-3.2.10.git] / sound / core / oss / pcm_oss.c
1 /*
2  *  Digital Audio (PCM) abstract layer / OSS compatible
3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4  *
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  *
20  */
21
22 #if 0
23 #define PLUGIN_DEBUG
24 #endif
25
26 #include <sound/driver.h>
27 #include <linux/version.h>
28 #include <linux/init.h>
29 #include <linux/slab.h>
30 #include <linux/time.h>
31 #include <linux/vmalloc.h>
32 #include <sound/core.h>
33 #include <sound/minors.h>
34 #include <sound/pcm.h>
35 #include <sound/pcm_params.h>
36 #include "pcm_plugin.h"
37 #include <sound/info.h>
38 #include <linux/soundcard.h>
39 #include <sound/initval.h>
40
41 static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0};
42 static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
43 static int nonblock_open;
44
45 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>");
46 MODULE_DESCRIPTION("PCM OSS emulation for ALSA.");
47 MODULE_LICENSE("GPL");
48 MODULE_PARM(dsp_map, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
49 MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device.");
50 MODULE_PARM_SYNTAX(dsp_map, "default:0,skill:advanced");
51 MODULE_PARM(adsp_map, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
52 MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device.");
53 MODULE_PARM_SYNTAX(adsp_map, "default:1,skill:advanced");
54 MODULE_PARM(nonblock_open, "i");
55 MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
56 MODULE_PARM_SYNTAX(nonblock_open, "default:0,skill:advanced");
57
58 extern int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg);
59 static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file);
60 static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file);
61 static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file);
62
63 static inline mm_segment_t snd_enter_user(void)
64 {
65         mm_segment_t fs = get_fs();
66         set_fs(get_ds());
67         return fs;
68 }
69
70 static inline void snd_leave_user(mm_segment_t fs)
71 {
72         set_fs(fs);
73 }
74
75 int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream)
76 {
77         snd_pcm_runtime_t *runtime = substream->runtime;
78         snd_pcm_plugin_t *plugin, *next;
79         
80         plugin = runtime->oss.plugin_first;
81         while (plugin) {
82                 next = plugin->next;
83                 snd_pcm_plugin_free(plugin);
84                 plugin = next;
85         }
86         runtime->oss.plugin_first = runtime->oss.plugin_last = NULL;
87         return 0;
88 }
89
90 int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin)
91 {
92         snd_pcm_runtime_t *runtime = plugin->plug->runtime;
93         plugin->next = runtime->oss.plugin_first;
94         plugin->prev = NULL;
95         if (runtime->oss.plugin_first) {
96                 runtime->oss.plugin_first->prev = plugin;
97                 runtime->oss.plugin_first = plugin;
98         } else {
99                 runtime->oss.plugin_last =
100                 runtime->oss.plugin_first = plugin;
101         }
102         return 0;
103 }
104
105 int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
106 {
107         snd_pcm_runtime_t *runtime = plugin->plug->runtime;
108         plugin->next = NULL;
109         plugin->prev = runtime->oss.plugin_last;
110         if (runtime->oss.plugin_last) {
111                 runtime->oss.plugin_last->next = plugin;
112                 runtime->oss.plugin_last = plugin;
113         } else {
114                 runtime->oss.plugin_last =
115                 runtime->oss.plugin_first = plugin;
116         }
117         return 0;
118 }
119
120 static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
121 {
122         snd_pcm_runtime_t *runtime = substream->runtime;
123         if (runtime->period_size == runtime->oss.period_bytes)
124                 return frames;
125         if (runtime->period_size < runtime->oss.period_bytes)
126                 return frames * (runtime->oss.period_bytes / runtime->period_size);
127         return frames / (runtime->period_size / runtime->oss.period_bytes);
128 }
129
130 static int snd_pcm_oss_format_from(int format)
131 {
132         switch (format) {
133         case AFMT_MU_LAW:       return SNDRV_PCM_FORMAT_MU_LAW;
134         case AFMT_A_LAW:        return SNDRV_PCM_FORMAT_A_LAW;
135         case AFMT_IMA_ADPCM:    return SNDRV_PCM_FORMAT_IMA_ADPCM;
136         case AFMT_U8:           return SNDRV_PCM_FORMAT_U8;
137         case AFMT_S16_LE:       return SNDRV_PCM_FORMAT_S16_LE;
138         case AFMT_S16_BE:       return SNDRV_PCM_FORMAT_S16_BE;
139         case AFMT_S8:           return SNDRV_PCM_FORMAT_S8;
140         case AFMT_U16_LE:       return SNDRV_PCM_FORMAT_U16_LE;
141         case AFMT_U16_BE:       return SNDRV_PCM_FORMAT_U16_BE;
142         case AFMT_MPEG:         return SNDRV_PCM_FORMAT_MPEG;
143         default:                        return SNDRV_PCM_FORMAT_U8;
144         }
145 }
146
147 static int snd_pcm_oss_format_to(int format)
148 {
149         switch (format) {
150         case SNDRV_PCM_FORMAT_MU_LAW:   return AFMT_MU_LAW;
151         case SNDRV_PCM_FORMAT_A_LAW:    return AFMT_A_LAW;
152         case SNDRV_PCM_FORMAT_IMA_ADPCM:        return AFMT_IMA_ADPCM;
153         case SNDRV_PCM_FORMAT_U8:               return AFMT_U8;
154         case SNDRV_PCM_FORMAT_S16_LE:   return AFMT_S16_LE;
155         case SNDRV_PCM_FORMAT_S16_BE:   return AFMT_S16_BE;
156         case SNDRV_PCM_FORMAT_S8:               return AFMT_S8;
157         case SNDRV_PCM_FORMAT_U16_LE:   return AFMT_U16_LE;
158         case SNDRV_PCM_FORMAT_U16_BE:   return AFMT_U16_BE;
159         case SNDRV_PCM_FORMAT_MPEG:             return AFMT_MPEG;
160         default:                        return -EINVAL;
161         }
162 }
163
164 static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream, 
165                                    snd_pcm_hw_params_t *oss_params,
166                                    snd_pcm_hw_params_t *slave_params)
167 {
168         size_t s;
169         size_t oss_buffer_size, oss_period_size, oss_periods;
170         size_t min_period_size, max_period_size;
171         snd_pcm_runtime_t *runtime = substream->runtime;
172         size_t oss_frame_size;
173
174         oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) *
175                          params_channels(oss_params) / 8;
176
177         oss_buffer_size = snd_pcm_plug_client_size(substream,
178                                                    snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0)) * oss_frame_size;
179         oss_buffer_size = 1 << ld2(oss_buffer_size);
180         if (atomic_read(&runtime->mmap_count)) {
181                 if (oss_buffer_size > runtime->oss.mmap_bytes)
182                         oss_buffer_size = runtime->oss.mmap_bytes;
183         }
184
185         if (substream->oss.setup &&
186             substream->oss.setup->period_size > 16)
187                 oss_period_size = substream->oss.setup->period_size;
188         else if (runtime->oss.fragshift) {
189                 oss_period_size = 1 << runtime->oss.fragshift;
190                 if (oss_period_size > oss_buffer_size / 2)
191                         oss_period_size = oss_buffer_size / 2;
192         } else {
193                 int sd;
194                 size_t bytes_per_sec = params_rate(oss_params) * snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8;
195
196                 oss_period_size = oss_buffer_size;
197                 do {
198                         oss_period_size /= 2;
199                 } while (oss_period_size > bytes_per_sec);
200                 if (runtime->oss.subdivision == 0) {
201                         sd = 4;
202                         if (oss_period_size / sd > 4096)
203                                 sd *= 2;
204                         if (oss_period_size / sd < 4096)
205                                 sd = 1;
206                 } else
207                         sd = runtime->oss.subdivision;
208                 oss_period_size /= sd;
209                 if (oss_period_size < 16)
210                         oss_period_size = 16;
211         }
212
213         min_period_size = snd_pcm_plug_client_size(substream,
214                                                    snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 0));
215         min_period_size *= oss_frame_size;
216         min_period_size = 1 << (ld2(min_period_size - 1) + 1);
217         if (oss_period_size < min_period_size)
218                 oss_period_size = min_period_size;
219
220         max_period_size = snd_pcm_plug_client_size(substream,
221                                                    snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 0));
222         max_period_size *= oss_frame_size;
223         max_period_size = 1 << ld2(max_period_size);
224         if (oss_period_size > max_period_size)
225                 oss_period_size = max_period_size;
226
227         oss_periods = oss_buffer_size / oss_period_size;
228
229         if (substream->oss.setup) {
230                 if (substream->oss.setup->periods > 1)
231                         oss_periods = substream->oss.setup->periods;
232         }
233
234         s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, 0);
235         if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
236                 s = runtime->oss.maxfrags;
237         if (oss_periods > s)
238                 oss_periods = s;
239
240         s = snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, 0);
241         if (s < 2)
242                 s = 2;
243         if (oss_periods < s)
244                 oss_periods = s;
245
246         while (oss_period_size * oss_periods > oss_buffer_size)
247                 oss_period_size /= 2;
248
249         snd_assert(oss_period_size >= 16, return -EINVAL);
250         runtime->oss.period_bytes = oss_period_size;
251         runtime->oss.periods = oss_periods;
252         return 0;
253 }
254
255 static int choose_rate(snd_pcm_substream_t *substream,
256                        snd_pcm_hw_params_t *params, unsigned int best_rate)
257 {
258         snd_interval_t *it;
259         snd_pcm_hw_params_t *save;
260         unsigned int rate, prev;
261
262         save = kmalloc(sizeof(*save), GFP_KERNEL);
263         if (save == NULL)
264                 return -ENOMEM;
265         *save = *params;
266         it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE);
267
268         /* try multiples of the best rate */
269         rate = best_rate;
270         for (;;) {
271                 if (it->max < rate || (it->max == rate && it->openmax))
272                         break;
273                 if (it->min < rate || (it->min == rate && !it->openmin)) {
274                         int ret;
275                         ret = snd_pcm_hw_param_set(substream, params,
276                                                    SNDRV_PCM_HW_PARAM_RATE,
277                                                    rate, 0);
278                         if (ret == (int)rate) {
279                                 kfree(save);
280                                 return rate;
281                         }
282                         *params = *save;
283                 }
284                 prev = rate;
285                 rate += best_rate;
286                 if (rate <= prev)
287                         break;
288         }
289
290         /* not found, use the nearest rate */
291         kfree(save);
292         return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, 0);
293 }
294
295 static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
296 {
297         snd_pcm_runtime_t *runtime = substream->runtime;
298         snd_pcm_hw_params_t *params, *sparams;
299         snd_pcm_sw_params_t *sw_params;
300         ssize_t oss_buffer_size, oss_period_size;
301         size_t oss_frame_size;
302         int err;
303         int direct;
304         int format, sformat, n;
305         snd_mask_t sformat_mask;
306         snd_mask_t mask;
307
308         sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
309         params = kmalloc(sizeof(*params), GFP_KERNEL);
310         sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
311         if (!sw_params || !params || !sparams) {
312                 snd_printd("No memory\n");
313                 err = -ENOMEM;
314                 goto failure;
315         }
316
317         if (atomic_read(&runtime->mmap_count)) {
318                 direct = 1;
319         } else {
320                 snd_pcm_oss_setup_t *setup = substream->oss.setup;
321                 direct = (setup != NULL && setup->direct);
322         }
323
324         _snd_pcm_hw_params_any(sparams);
325         _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
326         _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
327         snd_mask_none(&mask);
328         if (atomic_read(&runtime->mmap_count))
329                 snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
330         else {
331                 snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
332                 if (!direct)
333                         snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
334         }
335         err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
336         if (err < 0) {
337                 snd_printd("No usable accesses\n");
338                 err = -EINVAL;
339                 goto failure;
340         }
341         choose_rate(substream, sparams, runtime->oss.rate);
342         snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, 0);
343
344         format = snd_pcm_oss_format_from(runtime->oss.format);
345
346         sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
347         if (direct)
348                 sformat = format;
349         else
350                 sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
351
352         if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) {
353                 for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) {
354                         if (snd_mask_test(&sformat_mask, sformat) &&
355                             snd_pcm_oss_format_to(sformat) >= 0)
356                                 break;
357                 }
358                 if (sformat > SNDRV_PCM_FORMAT_LAST) {
359                         snd_printd("Cannot find a format!!!\n");
360                         err = -EINVAL;
361                         goto failure;
362                 }
363         }
364         err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0);
365         snd_assert(err >= 0, goto failure);
366
367         if (direct) {
368                 memcpy(params, sparams, sizeof(*params));
369         } else {
370                 _snd_pcm_hw_params_any(params);
371                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
372                                       SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
373                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
374                                       snd_pcm_oss_format_from(runtime->oss.format), 0);
375                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
376                                       runtime->oss.channels, 0);
377                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
378                                       runtime->oss.rate, 0);
379                 pdprintf("client: access = %i, format = %i, channels = %i, rate = %i\n",
380                          params_access(params), params_format(params),
381                          params_channels(params), params_rate(params));
382         }
383         pdprintf("slave: access = %i, format = %i, channels = %i, rate = %i\n",
384                  params_access(sparams), params_format(sparams),
385                  params_channels(sparams), params_rate(sparams));
386
387         oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
388                          params_channels(params) / 8;
389
390         snd_pcm_oss_plugin_clear(substream);
391         if (!direct) {
392                 /* add necessary plugins */
393                 snd_pcm_oss_plugin_clear(substream);
394                 if ((err = snd_pcm_plug_format_plugins(substream,
395                                                        params, 
396                                                        sparams)) < 0) {
397                         snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err);
398                         snd_pcm_oss_plugin_clear(substream);
399                         goto failure;
400                 }
401                 if (runtime->oss.plugin_first) {
402                         snd_pcm_plugin_t *plugin;
403                         if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) {
404                                 snd_printd("snd_pcm_plugin_build_io failed: %i\n", err);
405                                 snd_pcm_oss_plugin_clear(substream);
406                                 goto failure;
407                         }
408                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
409                                 err = snd_pcm_plugin_append(plugin);
410                         } else {
411                                 err = snd_pcm_plugin_insert(plugin);
412                         }
413                         if (err < 0) {
414                                 snd_pcm_oss_plugin_clear(substream);
415                                 goto failure;
416                         }
417                 }
418         }
419
420         err = snd_pcm_oss_period_size(substream, params, sparams);
421         if (err < 0)
422                 goto failure;
423
424         n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size);
425         err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, 0);
426         snd_assert(err >= 0, goto failure);
427
428         err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS,
429                                      runtime->oss.periods, 0);
430         snd_assert(err >= 0, goto failure);
431
432         snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
433
434         if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) {
435                 snd_printd("HW_PARAMS failed: %i\n", err);
436                 goto failure;
437         }
438
439         memset(sw_params, 0, sizeof(*sw_params));
440         if (runtime->oss.trigger) {
441                 sw_params->start_threshold = 1;
442         } else {
443                 sw_params->start_threshold = runtime->boundary;
444         }
445         if (atomic_read(&runtime->mmap_count))
446                 sw_params->stop_threshold = runtime->boundary;
447         else
448                 sw_params->stop_threshold = runtime->buffer_size;
449         sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
450         sw_params->period_step = 1;
451         sw_params->sleep_min = 0;
452         sw_params->avail_min = runtime->period_size;
453         sw_params->xfer_align = 1;
454         sw_params->silence_threshold = 0;
455         sw_params->silence_size = 0;
456
457         if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) {
458                 snd_printd("SW_PARAMS failed: %i\n", err);
459                 goto failure;
460         }
461         runtime->control->avail_min = runtime->period_size;
462
463         runtime->oss.periods = params_periods(sparams);
464         oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
465         snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure);
466         if (runtime->oss.plugin_first) {
467                 err = snd_pcm_plug_alloc(substream, oss_period_size);
468                 if (err < 0)
469                         goto failure;
470         }
471         oss_period_size *= oss_frame_size;
472
473         oss_buffer_size = oss_period_size * runtime->oss.periods;
474         snd_assert(oss_buffer_size >= 0, err = -EINVAL; goto failure);
475
476         runtime->oss.period_bytes = oss_period_size;
477         runtime->oss.buffer_bytes = oss_buffer_size;
478
479         pdprintf("oss: period bytes = %i, buffer bytes = %i\n",
480                  runtime->oss.period_bytes,
481                  runtime->oss.buffer_bytes);
482         pdprintf("slave: period_size = %i, buffer_size = %i\n",
483                  params_period_size(sparams),
484                  params_buffer_size(sparams));
485
486         runtime->oss.format = snd_pcm_oss_format_to(params_format(params));
487         runtime->oss.channels = params_channels(params);
488         runtime->oss.rate = params_rate(params);
489
490         runtime->oss.params = 0;
491         runtime->oss.prepare = 1;
492         if (runtime->oss.buffer != NULL)
493                 vfree(runtime->oss.buffer);
494         runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
495         runtime->oss.buffer_used = 0;
496         if (runtime->dma_area)
497                 snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
498
499         err = 0;
500 failure:
501         if (sw_params)
502                 kfree(sw_params);
503         if (params)
504                 kfree(params);
505         if (sparams)
506                 kfree(sparams);
507         return err;
508 }
509
510 static int snd_pcm_oss_get_active_substream(snd_pcm_oss_file_t *pcm_oss_file, snd_pcm_substream_t **r_substream)
511 {
512         int idx, err;
513         snd_pcm_substream_t *asubstream = NULL, *substream;
514
515         for (idx = 0; idx < 2; idx++) {
516                 substream = pcm_oss_file->streams[idx];
517                 if (substream == NULL)
518                         continue;
519                 if (asubstream == NULL)
520                         asubstream = substream;
521                 if (substream->runtime->oss.params) {
522                         err = snd_pcm_oss_change_params(substream);
523                         if (err < 0)
524                                 return err;
525                 }
526         }
527         snd_assert(asubstream != NULL, return -EIO);
528         if (r_substream)
529                 *r_substream = asubstream;
530         return 0;
531 }
532
533 static int snd_pcm_oss_prepare(snd_pcm_substream_t *substream)
534 {
535         int err;
536         snd_pcm_runtime_t *runtime = substream->runtime;
537
538         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, 0);
539         if (err < 0) {
540                 snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");
541                 return err;
542         }
543         runtime->oss.prepare = 0;
544         runtime->oss.prev_hw_ptr_interrupt = 0;
545
546         return 0;
547 }
548
549 static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream)
550 {
551         snd_pcm_runtime_t *runtime;
552         int err;
553
554         if (substream == NULL)
555                 return 0;
556         runtime = substream->runtime;
557         if (runtime->oss.params) {
558                 err = snd_pcm_oss_change_params(substream);
559                 if (err < 0)
560                         return err;
561         }
562         if (runtime->oss.prepare) {
563                 err = snd_pcm_oss_prepare(substream);
564                 if (err < 0)
565                         return err;
566         }
567         return 0;
568 }
569
570 snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
571 {
572         snd_pcm_runtime_t *runtime = substream->runtime;
573         int ret;
574         while (1) {
575                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
576                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
577                         ret = snd_pcm_oss_prepare(substream);
578                         if (ret < 0)
579                                 break;
580                 }
581                 if (in_kernel) {
582                         mm_segment_t fs;
583                         fs = snd_enter_user();
584                         ret = snd_pcm_lib_write(substream, ptr, frames);
585                         snd_leave_user(fs);
586                 } else {
587                         ret = snd_pcm_lib_write(substream, ptr, frames);
588                 }
589                 if (ret != -EPIPE && ret != -ESTRPIPE)
590                         break;
591                 /* test, if we can't store new data, because the stream */
592                 /* has not been started */
593                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
594                         return -EAGAIN;
595         }
596         return ret;
597 }
598
599 snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
600 {
601         snd_pcm_runtime_t *runtime = substream->runtime;
602         int ret;
603         while (1) {
604                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
605                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
606                         ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);
607                         if (ret < 0)
608                                 break;
609                 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
610                         ret = snd_pcm_oss_prepare(substream);
611                         if (ret < 0)
612                                 break;
613                 }
614                 if (in_kernel) {
615                         mm_segment_t fs;
616                         fs = snd_enter_user();
617                         ret = snd_pcm_lib_read(substream, ptr, frames);
618                         snd_leave_user(fs);
619                 } else {
620                         ret = snd_pcm_lib_read(substream, ptr, frames);
621                 }
622                 if (ret == -EPIPE) {
623                         if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
624                                 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
625                                 if (ret < 0)
626                                         break;
627                         }
628                         continue;
629                 }
630                 if (ret != -ESTRPIPE)
631                         break;
632         }
633         return ret;
634 }
635
636 snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
637 {
638         snd_pcm_runtime_t *runtime = substream->runtime;
639         int ret;
640         while (1) {
641                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
642                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
643                         ret = snd_pcm_oss_prepare(substream);
644                         if (ret < 0)
645                                 break;
646                 }
647                 if (in_kernel) {
648                         mm_segment_t fs;
649                         fs = snd_enter_user();
650                         ret = snd_pcm_lib_writev(substream, bufs, frames);
651                         snd_leave_user(fs);
652                 } else {
653                         ret = snd_pcm_lib_writev(substream, bufs, frames);
654                 }
655                 if (ret != -EPIPE && ret != -ESTRPIPE)
656                         break;
657
658                 /* test, if we can't store new data, because the stream */
659                 /* has not been started */
660                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
661                         return -EAGAIN;
662         }
663         return ret;
664 }
665         
666 snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
667 {
668         snd_pcm_runtime_t *runtime = substream->runtime;
669         int ret;
670         while (1) {
671                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
672                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
673                         ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);
674                         if (ret < 0)
675                                 break;
676                 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
677                         ret = snd_pcm_oss_prepare(substream);
678                         if (ret < 0)
679                                 break;
680                 }
681                 if (in_kernel) {
682                         mm_segment_t fs;
683                         fs = snd_enter_user();
684                         ret = snd_pcm_lib_readv(substream, bufs, frames);
685                         snd_leave_user(fs);
686                 } else {
687                         ret = snd_pcm_lib_readv(substream, bufs, frames);
688                 }
689                 if (ret != -EPIPE && ret != -ESTRPIPE)
690                         break;
691         }
692         return ret;
693 }
694
695 static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *buf, size_t bytes, int in_kernel)
696 {
697         snd_pcm_runtime_t *runtime = substream->runtime;
698         snd_pcm_sframes_t frames, frames1;
699         if (runtime->oss.plugin_first) {
700                 snd_pcm_plugin_channel_t *channels;
701                 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
702                 if (!in_kernel) {
703                         if (copy_from_user(runtime->oss.buffer, buf, bytes))
704                                 return -EFAULT;
705                         buf = runtime->oss.buffer;
706                 }
707                 frames = bytes / oss_frame_bytes;
708                 frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels);
709                 if (frames1 < 0)
710                         return frames1;
711                 frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1);
712                 if (frames1 <= 0)
713                         return frames1;
714                 bytes = frames1 * oss_frame_bytes;
715         } else {
716                 frames = bytes_to_frames(runtime, bytes);
717                 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
718                 if (frames1 <= 0)
719                         return frames1;
720                 bytes = frames_to_bytes(runtime, frames1);
721         }
722         return bytes;
723 }
724
725 static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char *buf, size_t bytes)
726 {
727         size_t xfer = 0;
728         ssize_t tmp;
729         snd_pcm_runtime_t *runtime = substream->runtime;
730
731         if (atomic_read(&runtime->mmap_count))
732                 return -ENXIO;
733
734         if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
735                 return tmp;
736         while (bytes > 0) {
737                 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
738                         tmp = bytes;
739                         if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
740                                 tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
741                         if (tmp > 0) {
742                                 if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp))
743                                         return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;
744                         }
745                         runtime->oss.buffer_used += tmp;
746                         buf += tmp;
747                         bytes -= tmp;
748                         xfer += tmp;
749                         if (runtime->oss.buffer_used == runtime->oss.period_bytes) {
750                                 tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
751                                 if (tmp <= 0)
752                                         return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
753                                 runtime->oss.bytes += tmp;
754                                 runtime->oss.buffer_used = 0;
755                         }
756                 } else {
757                         tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0);
758                         if (tmp <= 0)
759                                 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
760                         runtime->oss.bytes += tmp;
761                         buf += tmp;
762                         bytes -= tmp;
763                         xfer += tmp;
764                 }
765         }
766         return xfer;
767 }
768
769 static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size_t bytes, int in_kernel)
770 {
771         snd_pcm_runtime_t *runtime = substream->runtime;
772         snd_pcm_sframes_t frames, frames1;
773         char *final_dst = buf;
774         if (runtime->oss.plugin_first) {
775                 snd_pcm_plugin_channel_t *channels;
776                 size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
777                 if (!in_kernel)
778                         buf = runtime->oss.buffer;
779                 frames = bytes / oss_frame_bytes;
780                 frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels);
781                 if (frames1 < 0)
782                         return frames1;
783                 frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1);
784                 if (frames1 <= 0)
785                         return frames1;
786                 bytes = frames1 * oss_frame_bytes;
787                 if (!in_kernel && copy_to_user(final_dst, buf, bytes))
788                         return -EFAULT;
789         } else {
790                 frames = bytes_to_frames(runtime, bytes);
791                 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
792                 if (frames1 <= 0)
793                         return frames1;
794                 bytes = frames_to_bytes(runtime, frames1);
795         }
796         return bytes;
797 }
798
799 static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char *buf, size_t bytes)
800 {
801         size_t xfer = 0;
802         ssize_t tmp;
803         snd_pcm_runtime_t *runtime = substream->runtime;
804
805         if (atomic_read(&runtime->mmap_count))
806                 return -ENXIO;
807
808         if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
809                 return tmp;
810         while (bytes > 0) {
811                 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
812                         if (runtime->oss.buffer_used == 0) {
813                                 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
814                                 if (tmp <= 0)
815                                         return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
816                                 runtime->oss.bytes += tmp;
817                                 runtime->oss.buffer_used = runtime->oss.period_bytes;
818                         }
819                         tmp = bytes;
820                         if ((size_t) tmp > runtime->oss.buffer_used)
821                                 tmp = runtime->oss.buffer_used;
822                         if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_bytes - runtime->oss.buffer_used), tmp))
823                                 return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;
824                         buf += tmp;
825                         bytes -= tmp;
826                         xfer += tmp;
827                         runtime->oss.buffer_used -= tmp;
828                 } else {
829                         tmp = snd_pcm_oss_read2(substream, (char *)buf, runtime->oss.period_bytes, 0);
830                         if (tmp <= 0)
831                                 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
832                         runtime->oss.bytes += tmp;
833                         buf += tmp;
834                         bytes -= tmp;
835                         xfer += tmp;
836                 }
837         }
838         return xfer;
839 }
840
841 static int snd_pcm_oss_reset(snd_pcm_oss_file_t *pcm_oss_file)
842 {
843         snd_pcm_substream_t *substream;
844
845         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
846         if (substream != NULL) {
847                 snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
848                 substream->runtime->oss.prepare = 1;
849         }
850         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
851         if (substream != NULL) {
852                 snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
853                 substream->runtime->oss.prepare = 1;
854         }
855         return 0;
856 }
857
858 static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
859 {
860         int err = 0;
861         unsigned int saved_f_flags;
862         snd_pcm_substream_t *substream;
863         snd_pcm_runtime_t *runtime;
864         ssize_t result;
865         wait_queue_t wait;
866
867         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
868         if (substream != NULL) {
869                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
870                         return err;
871                 
872                 runtime = substream->runtime;
873                 if (runtime->oss.buffer_used > 0) {
874                         snd_pcm_format_set_silence(runtime->format,
875                                                    runtime->oss.buffer + runtime->oss.buffer_used,
876                                                    bytes_to_samples(runtime, runtime->oss.period_bytes - runtime->oss.buffer_used));
877                         init_waitqueue_entry(&wait, current);
878                         add_wait_queue(&runtime->sleep, &wait);
879                         while (1) {
880                                 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
881                                 if (result > 0) {
882                                         runtime->oss.buffer_used = 0;
883                                         break;
884                                 }
885                                 if (result != 0 && result != -EAGAIN)
886                                         break;
887                                 set_current_state(TASK_INTERRUPTIBLE);
888                                 schedule();
889                                 if (signal_pending(current)) {
890                                         result = -ERESTARTSYS;
891                                         break;
892                                 }
893                         }
894                         set_current_state(TASK_RUNNING);
895                         remove_wait_queue(&runtime->sleep, &wait);
896                         if (result < 0)
897                                 return result;
898                 }
899                 saved_f_flags = substream->ffile->f_flags;
900                 substream->ffile->f_flags &= ~O_NONBLOCK;
901                 err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);
902                 substream->ffile->f_flags = saved_f_flags;
903                 if (err < 0)
904                         return err;
905                 runtime->oss.prepare = 1;
906         }
907
908         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
909         if (substream != NULL) {
910                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
911                         return err;
912                 runtime = substream->runtime;
913                 err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);
914                 if (err < 0)
915                         return err;
916                 runtime->oss.buffer_used = 0;
917                 runtime->oss.prepare = 1;
918         }
919         return 0;
920 }
921
922 static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate)
923 {
924         int idx;
925
926         for (idx = 1; idx >= 0; --idx) {
927                 snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
928                 snd_pcm_runtime_t *runtime;
929                 if (substream == NULL)
930                         continue;
931                 runtime = substream->runtime;
932                 if (rate < 1000)
933                         rate = 1000;
934                 else if (rate > 192000)
935                         rate = 192000;
936                 if (runtime->oss.rate != rate) {
937                         runtime->oss.params = 1;
938                         runtime->oss.rate = rate;
939                 }
940         }
941         return snd_pcm_oss_get_rate(pcm_oss_file);
942 }
943
944 static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file)
945 {
946         snd_pcm_substream_t *substream;
947         int err;
948         
949         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
950                 return err;
951         return substream->runtime->oss.rate;
952 }
953
954 static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned int channels)
955 {
956         int idx;
957         if (channels < 1)
958                 channels = 1;
959         if (channels > 128)
960                 return -EINVAL;
961         for (idx = 1; idx >= 0; --idx) {
962                 snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
963                 snd_pcm_runtime_t *runtime;
964                 if (substream == NULL)
965                         continue;
966                 runtime = substream->runtime;
967                 if (runtime->oss.channels != channels) {
968                         runtime->oss.params = 1;
969                         runtime->oss.channels = channels;
970                 }
971         }
972         return snd_pcm_oss_get_channels(pcm_oss_file);
973 }
974
975 static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file)
976 {
977         snd_pcm_substream_t *substream;
978         int err;
979         
980         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
981                 return err;
982         return substream->runtime->oss.channels;
983 }
984
985 static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file)
986 {
987         snd_pcm_substream_t *substream;
988         int err;
989         
990         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
991                 return err;
992         return substream->runtime->oss.period_bytes;
993 }
994
995 static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
996 {
997         snd_pcm_substream_t *substream;
998         int err;
999         int direct;
1000         snd_pcm_hw_params_t params;
1001         unsigned int formats = 0;
1002         snd_mask_t format_mask;
1003         int fmt;
1004         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1005                 return err;
1006         if (atomic_read(&substream->runtime->mmap_count)) {
1007                 direct = 1;
1008         } else {
1009                 snd_pcm_oss_setup_t *setup = substream->oss.setup;
1010                 direct = (setup != NULL && setup->direct);
1011         }
1012         if (!direct)
1013                 return AFMT_MU_LAW | AFMT_U8 |
1014                        AFMT_S16_LE | AFMT_S16_BE |
1015                        AFMT_S8 | AFMT_U16_LE |
1016                        AFMT_U16_BE;
1017         _snd_pcm_hw_params_any(&params);
1018         err = snd_pcm_hw_refine(substream, &params);
1019         snd_assert(err >= 0, return err);
1020         format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT); 
1021         for (fmt = 0; fmt < 32; ++fmt) {
1022                 if (snd_mask_test(&format_mask, fmt)) {
1023                         int f = snd_pcm_oss_format_to(fmt);
1024                         if (f >= 0)
1025                                 formats |= f;
1026                 }
1027         }
1028         return formats;
1029 }
1030
1031 static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format)
1032 {
1033         int formats, idx;
1034         
1035         if (format != AFMT_QUERY) {
1036                 formats = snd_pcm_oss_get_formats(pcm_oss_file);
1037                 if (!(formats & format))
1038                         format = AFMT_U8;
1039                 for (idx = 1; idx >= 0; --idx) {
1040                         snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
1041                         snd_pcm_runtime_t *runtime;
1042                         if (substream == NULL)
1043                                 continue;
1044                         runtime = substream->runtime;
1045                         if (runtime->oss.format != format) {
1046                                 runtime->oss.params = 1;
1047                                 runtime->oss.format = format;
1048                         }
1049                 }
1050         }
1051         return snd_pcm_oss_get_format(pcm_oss_file);
1052 }
1053
1054 static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file)
1055 {
1056         snd_pcm_substream_t *substream;
1057         int err;
1058         
1059         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1060                 return err;
1061         return substream->runtime->oss.format;
1062 }
1063
1064 static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdivide)
1065 {
1066         snd_pcm_runtime_t *runtime;
1067
1068         if (substream == NULL)
1069                 return 0;
1070         runtime = substream->runtime;
1071         if (subdivide == 0) {
1072                 subdivide = runtime->oss.subdivision;
1073                 if (subdivide == 0)
1074                         subdivide = 1;
1075                 return subdivide;
1076         }
1077         if (runtime->oss.subdivision || runtime->oss.fragshift)
1078                 return -EINVAL;
1079         if (subdivide != 1 && subdivide != 2 && subdivide != 4 &&
1080             subdivide != 8 && subdivide != 16)
1081                 return -EINVAL;
1082         runtime->oss.subdivision = subdivide;
1083         runtime->oss.params = 1;
1084         return subdivide;
1085 }
1086
1087 static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdivide)
1088 {
1089         int err = -EINVAL, idx;
1090
1091         for (idx = 1; idx >= 0; --idx) {
1092                 snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
1093                 if (substream == NULL)
1094                         continue;
1095                 if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
1096                         return err;
1097         }
1098         return err;
1099 }
1100
1101 static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned int val)
1102 {
1103         snd_pcm_runtime_t *runtime;
1104
1105         if (substream == NULL)
1106                 return 0;
1107         runtime = substream->runtime;
1108         if (runtime->oss.subdivision || runtime->oss.fragshift)
1109                 return -EINVAL;
1110         runtime->oss.fragshift = val & 0xffff;
1111         runtime->oss.maxfrags = (val >> 16) & 0xffff;
1112         if (runtime->oss.fragshift < 4)         /* < 16 */
1113                 runtime->oss.fragshift = 4;
1114         if (runtime->oss.maxfrags < 2)
1115                 runtime->oss.maxfrags = 2;
1116         runtime->oss.params = 1;
1117         return 0;
1118 }
1119
1120 static int snd_pcm_oss_set_fragment(snd_pcm_oss_file_t *pcm_oss_file, unsigned int val)
1121 {
1122         int err = -EINVAL, idx;
1123
1124         for (idx = 1; idx >= 0; --idx) {
1125                 snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
1126                 if (substream == NULL)
1127                         continue;
1128                 if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
1129                         return err;
1130         }
1131         return err;
1132 }
1133
1134 static int snd_pcm_oss_nonblock(struct file * file)
1135 {
1136         file->f_flags |= O_NONBLOCK;
1137         return 0;
1138 }
1139
1140 static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res)
1141 {
1142
1143         if (substream == NULL) {
1144                 res &= ~DSP_CAP_DUPLEX;
1145                 return res;
1146         }
1147 #ifdef DSP_CAP_MULTI
1148         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1149                 if (substream->pstr->substream_count > 1)
1150                         res |= DSP_CAP_MULTI;
1151 #endif
1152         /* DSP_CAP_REALTIME is set all times: */
1153         /* all ALSA drivers can return actual pointer in ring buffer */
1154 #if defined(DSP_CAP_REALTIME) && 0
1155         {
1156                 snd_pcm_runtime_t *runtime = substream->runtime;
1157                 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))
1158                         res &= ~DSP_CAP_REALTIME;
1159         }
1160 #endif
1161         return res;
1162 }
1163
1164 static int snd_pcm_oss_get_caps(snd_pcm_oss_file_t *pcm_oss_file)
1165 {
1166         int result, idx;
1167         
1168         result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME;
1169         for (idx = 0; idx < 2; idx++) {
1170                 snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
1171                 result = snd_pcm_oss_get_caps1(substream, result);
1172         }
1173         result |= 0x0001;       /* revision - same as SB AWE 64 */
1174         return result;
1175 }
1176
1177 static void snd_pcm_oss_simulate_fill(snd_pcm_substream_t *substream)
1178 {
1179         snd_pcm_runtime_t *runtime = substream->runtime;
1180         snd_pcm_uframes_t appl_ptr;
1181         appl_ptr = runtime->hw_ptr_interrupt + runtime->buffer_size;
1182         appl_ptr %= runtime->boundary;
1183         runtime->control->appl_ptr = appl_ptr;
1184 }
1185
1186 static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger)
1187 {
1188         snd_pcm_runtime_t *runtime;
1189         snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
1190         int err, cmd;
1191         
1192         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1193         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1194
1195         if (psubstream) {
1196                 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
1197                         return err;
1198                 if (atomic_read(&psubstream->runtime->mmap_count))
1199                         snd_pcm_oss_simulate_fill(psubstream);
1200         }
1201         if (csubstream) {
1202                 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
1203                         return err;
1204         }
1205         if (psubstream) {
1206                 runtime = psubstream->runtime;
1207                 if (trigger & PCM_ENABLE_OUTPUT) {
1208                         if (runtime->oss.trigger)
1209                                 goto _skip1;
1210                         runtime->oss.trigger = 1;
1211                         runtime->start_threshold = 1;
1212                         cmd = SNDRV_PCM_IOCTL_START;
1213                 } else {
1214                         if (!runtime->oss.trigger)
1215                                 goto _skip1;
1216                         runtime->oss.trigger = 0;
1217                         runtime->start_threshold = runtime->boundary;
1218                         cmd = SNDRV_PCM_IOCTL_DROP;
1219                         runtime->oss.prepare = 1;
1220                 }
1221                 err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, 0);
1222                 if (err < 0)
1223                         return err;
1224         }
1225  _skip1:
1226         if (csubstream) {
1227                 runtime = csubstream->runtime;
1228                 if (trigger & PCM_ENABLE_INPUT) {
1229                         if (runtime->oss.trigger)
1230                                 goto _skip2;
1231                         runtime->oss.trigger = 1;
1232                         runtime->start_threshold = 1;
1233                         cmd = SNDRV_PCM_IOCTL_START;
1234                 } else {
1235                         if (!runtime->oss.trigger)
1236                                 goto _skip2;
1237                         runtime->oss.trigger = 0;
1238                         runtime->start_threshold = runtime->boundary;
1239                         cmd = SNDRV_PCM_IOCTL_DROP;
1240                         runtime->oss.prepare = 1;
1241                 }
1242                 err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, 0);
1243                 if (err < 0)
1244                         return err;
1245         }
1246  _skip2:
1247         return 0;
1248 }
1249
1250 static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file)
1251 {
1252         snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
1253         int result = 0;
1254
1255         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1256         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1257         if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
1258                 result |= PCM_ENABLE_OUTPUT;
1259         if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
1260                 result |= PCM_ENABLE_INPUT;
1261         return result;
1262 }
1263
1264 static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file)
1265 {
1266         snd_pcm_substream_t *substream;
1267         snd_pcm_runtime_t *runtime;
1268         snd_pcm_sframes_t delay;
1269         int err;
1270
1271         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1272         if (substream == NULL)
1273                 return -EINVAL;
1274         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1275                 return err;
1276         runtime = substream->runtime;
1277         if (runtime->oss.params || runtime->oss.prepare)
1278                 return 0;
1279         err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
1280         if (err == -EPIPE)
1281                 delay = 0;      /* hack for broken OSS applications */
1282         else if (err < 0)
1283                 return err;
1284         return snd_pcm_oss_bytes(substream, delay);
1285 }
1286
1287 static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct count_info * _info)
1288 {       
1289         snd_pcm_substream_t *substream;
1290         snd_pcm_runtime_t *runtime;
1291         snd_pcm_status_t status;
1292         struct count_info info;
1293         int err;
1294
1295         if (_info == NULL)
1296                 return -EFAULT;
1297         substream = pcm_oss_file->streams[stream];
1298         if (substream == NULL)
1299                 return -EINVAL;
1300         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1301                 return err;
1302         runtime = substream->runtime;
1303         if (runtime->oss.params || runtime->oss.prepare) {
1304                 memset(&info, 0, sizeof(info));
1305                 if (copy_to_user(_info, &info, sizeof(info)))
1306                         return -EFAULT;
1307                 return 0;
1308         }
1309         memset(&status, 0, sizeof(status));
1310         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status);
1311         if (err < 0)
1312                 return err;
1313         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1314                 info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, runtime->buffer_size - status.avail);
1315         } else {
1316                 info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, status.avail);
1317         }
1318         info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
1319         if (atomic_read(&runtime->mmap_count)) {
1320                 snd_pcm_sframes_t n;
1321                 n = runtime->hw_ptr_interrupt - runtime->oss.prev_hw_ptr_interrupt;
1322                 if (n < 0)
1323                         n += runtime->boundary;
1324                 info.blocks = n / runtime->period_size;
1325                 runtime->oss.prev_hw_ptr_interrupt = runtime->hw_ptr_interrupt;
1326                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1327                         snd_pcm_oss_simulate_fill(substream);
1328         } else {
1329                 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1330                         info.blocks = (runtime->buffer_size - status.avail) / runtime->period_size;
1331                 else
1332                         info.blocks = status.avail / runtime->period_size;
1333         }
1334         if (copy_to_user(_info, &info, sizeof(info)))
1335                 return -EFAULT;
1336         return 0;
1337 }
1338
1339 static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct audio_buf_info *_info)
1340 {
1341         snd_pcm_substream_t *substream;
1342         snd_pcm_runtime_t *runtime;
1343         snd_pcm_status_t status;
1344         struct audio_buf_info info;
1345         int err;
1346
1347         if (_info == NULL)
1348                 return -EFAULT;
1349         substream = pcm_oss_file->streams[stream];
1350         if (substream == NULL)
1351                 return -EINVAL;
1352         runtime = substream->runtime;
1353
1354         if (runtime->oss.params &&
1355             (err = snd_pcm_oss_change_params(substream)) < 0)
1356                 return err;
1357
1358         info.fragsize = runtime->oss.period_bytes;
1359         info.fragstotal = runtime->periods;
1360         memset(&status, 0, sizeof(status));
1361         if (runtime->oss.prepare) {
1362                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
1363                         info.bytes = runtime->oss.period_bytes * runtime->periods;
1364                         info.fragments = runtime->periods;
1365                 } else {
1366                         info.bytes = 0;
1367                         info.fragments = 0;
1368                 }
1369         } else {
1370                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status);
1371                 if (err < 0)
1372                         return err;
1373                 info.bytes = snd_pcm_oss_bytes(substream, status.avail);
1374                 info.fragments = status.avail / runtime->period_size;
1375         }
1376
1377 #if 0
1378         /* very experimental stuff to get Quake2 working */
1379         runtime->oss.period = (info.periods - 1) << 16;
1380         for (tmp = info.fragsize; tmp > 1; tmp >>= 1)
1381                 runtime->oss.period++;
1382         runtime->oss.subdivision = 1;   /* disable SUBDIVIDE */
1383 #endif
1384         // printk("space: bytes = %i, periods = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.periods, info.fragstotal, info.fragsize);
1385         if (copy_to_user(_info, &info, sizeof(info)))
1386                 return -EFAULT;
1387         return 0;
1388 }
1389
1390 static int snd_pcm_oss_get_mapbuf(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct buffmem_desc * _info)
1391 {
1392         // it won't be probably implemented
1393         // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n");
1394         return -EINVAL;
1395 }
1396
1397 static snd_pcm_oss_setup_t *snd_pcm_oss_look_for_setup(snd_pcm_t *pcm, int stream, const char *task_name)
1398 {
1399         const char *ptr, *ptrl;
1400         snd_pcm_oss_setup_t *setup;
1401
1402         down(&pcm->streams[stream].oss.setup_mutex);
1403         for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
1404                 if (!strcmp(setup->task_name, task_name)) {
1405                         up(&pcm->streams[stream].oss.setup_mutex);
1406                         return setup;
1407                 }
1408         }
1409         ptr = ptrl = task_name;
1410         while (*ptr) {
1411                 if (*ptr == '/')
1412                         ptrl = ptr + 1;
1413                 ptr++;
1414         }
1415         if (ptrl == task_name) {
1416                 goto __not_found;
1417                 return NULL;
1418         }
1419         for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
1420                 if (!strcmp(setup->task_name, ptrl)) {
1421                         up(&pcm->streams[stream].oss.setup_mutex);
1422                         return setup;
1423                 }
1424         }
1425       __not_found:
1426         up(&pcm->streams[stream].oss.setup_mutex);
1427         return NULL;
1428 }
1429
1430 static void snd_pcm_oss_init_substream(snd_pcm_substream_t *substream,
1431                                        snd_pcm_oss_setup_t *setup,
1432                                        int minor)
1433 {
1434         snd_pcm_runtime_t *runtime;
1435
1436         substream->oss.oss = 1;
1437         substream->oss.setup = setup;
1438         runtime = substream->runtime;
1439         runtime->oss.params = 1;
1440         runtime->oss.trigger = 1;
1441         runtime->oss.rate = 8000;
1442         switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
1443         case SNDRV_MINOR_OSS_PCM_8:
1444                 runtime->oss.format = AFMT_U8;
1445                 break;
1446         case SNDRV_MINOR_OSS_PCM_16:
1447                 runtime->oss.format = AFMT_S16_LE;
1448                 break;
1449         default:
1450                 runtime->oss.format = AFMT_MU_LAW;
1451         }
1452         runtime->oss.channels = 1;
1453         runtime->oss.fragshift = 0;
1454         runtime->oss.maxfrags = 0;
1455         runtime->oss.subdivision = 0;
1456 }
1457
1458 static void snd_pcm_oss_release_substream(snd_pcm_substream_t *substream)
1459 {
1460         snd_pcm_runtime_t *runtime;
1461         runtime = substream->runtime;
1462         if (runtime->oss.buffer)
1463                 vfree(runtime->oss.buffer);
1464         snd_pcm_oss_plugin_clear(substream);
1465         substream->oss.file = NULL;
1466         substream->oss.oss = 0;
1467 }
1468
1469 static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file)
1470 {
1471         int cidx;
1472         snd_assert(pcm_oss_file != NULL, return -ENXIO);
1473         for (cidx = 0; cidx < 2; ++cidx) {
1474                 snd_pcm_substream_t *substream = pcm_oss_file->streams[cidx];
1475                 snd_pcm_runtime_t *runtime;
1476                 if (substream == NULL)
1477                         continue;
1478                 runtime = substream->runtime;
1479                 
1480                 snd_pcm_stream_lock_irq(substream);
1481                 if (snd_pcm_running(substream))
1482                         snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1483                 snd_pcm_stream_unlock_irq(substream);
1484                 if (substream->open_flag) {
1485                         if (substream->ops->hw_free != NULL)
1486                                 substream->ops->hw_free(substream);
1487                         substream->ops->close(substream);
1488                         substream->open_flag = 0;
1489                 }
1490                 substream->ffile = NULL;
1491                 snd_pcm_oss_release_substream(substream);
1492                 snd_pcm_release_substream(substream);
1493         }
1494         snd_magic_kfree(pcm_oss_file);
1495         return 0;
1496 }
1497
1498 static int snd_pcm_oss_open_file(struct file *file,
1499                                  snd_pcm_t *pcm,
1500                                  snd_pcm_oss_file_t **rpcm_oss_file,
1501                                  int minor,
1502                                  snd_pcm_oss_setup_t *psetup,
1503                                  snd_pcm_oss_setup_t *csetup)
1504 {
1505         int err = 0;
1506         snd_pcm_oss_file_t *pcm_oss_file;
1507         snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
1508         unsigned int f_mode = file->f_mode;
1509
1510         snd_assert(rpcm_oss_file != NULL, return -EINVAL);
1511         *rpcm_oss_file = NULL;
1512
1513         pcm_oss_file = snd_magic_kcalloc(snd_pcm_oss_file_t, 0, GFP_KERNEL);
1514         if (pcm_oss_file == NULL)
1515                 return -ENOMEM;
1516
1517         if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
1518             (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
1519                 f_mode = FMODE_WRITE;
1520         if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
1521                 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1522                                                &psubstream)) < 0) {
1523                         snd_pcm_oss_release_file(pcm_oss_file);
1524                         return err;
1525                 }
1526                 pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
1527         }
1528         if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
1529                 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, 
1530                                                &csubstream)) < 0) {
1531                         snd_pcm_oss_release_file(pcm_oss_file);
1532                         return err;
1533                 }
1534                 pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
1535         }
1536         
1537         if (psubstream == NULL && csubstream == NULL) {
1538                 snd_pcm_oss_release_file(pcm_oss_file);
1539                 return -EINVAL;
1540         }
1541         if (psubstream != NULL) {
1542                 psubstream->oss.file = pcm_oss_file;
1543                 err = snd_pcm_hw_constraints_init(psubstream);
1544                 if (err < 0) {
1545                         snd_printd("snd_pcm_hw_constraint_init failed\n");
1546                         snd_pcm_oss_release_file(pcm_oss_file);
1547                         return err;
1548                 }
1549                 if ((err = psubstream->ops->open(psubstream)) < 0) {
1550                         snd_pcm_oss_release_file(pcm_oss_file);
1551                         return err;
1552                 }
1553                 psubstream->open_flag = 1;
1554                 err = snd_pcm_hw_constraints_complete(psubstream);
1555                 if (err < 0) {
1556                         snd_printd("snd_pcm_hw_constraint_complete failed\n");
1557                         snd_pcm_oss_release_file(pcm_oss_file);
1558                         return err;
1559                 }
1560                 psubstream->ffile = file;
1561                 snd_pcm_oss_init_substream(psubstream, psetup, minor);
1562         }
1563         if (csubstream != NULL) {
1564                 csubstream->oss.file = pcm_oss_file;
1565                 err = snd_pcm_hw_constraints_init(csubstream);
1566                 if (err < 0) {
1567                         snd_printd("snd_pcm_hw_constraint_init failed\n");
1568                         snd_pcm_oss_release_file(pcm_oss_file);
1569                         return err;
1570                 }
1571                 if ((err = csubstream->ops->open(csubstream)) < 0) {
1572                         snd_pcm_oss_release_file(pcm_oss_file);
1573                         return err;
1574                 }
1575                 csubstream->open_flag = 1;
1576                 err = snd_pcm_hw_constraints_complete(csubstream);
1577                 if (err < 0) {
1578                         snd_printd("snd_pcm_hw_constraint_complete failed\n");
1579                         snd_pcm_oss_release_file(pcm_oss_file);
1580                         return err;
1581                 }
1582                 csubstream->ffile = file;
1583                 snd_pcm_oss_init_substream(csubstream, csetup, minor);
1584         }
1585
1586         file->private_data = pcm_oss_file;
1587         *rpcm_oss_file = pcm_oss_file;
1588         return 0;
1589 }
1590
1591
1592 static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1593 {
1594         int minor = minor(inode->i_rdev);
1595         int cardnum = SNDRV_MINOR_OSS_CARD(minor);
1596         int device;
1597         int err;
1598         char task_name[32];
1599         snd_pcm_t *pcm;
1600         snd_pcm_oss_file_t *pcm_oss_file;
1601         snd_pcm_oss_setup_t *psetup = NULL, *csetup = NULL;
1602         int nonblock;
1603         wait_queue_t wait;
1604
1605         snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
1606         device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ?
1607                 adsp_map[cardnum] : dsp_map[cardnum];
1608
1609         pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];
1610         if (pcm == NULL) {
1611                 err = -ENODEV;
1612                 goto __error1;
1613         }
1614         err = snd_card_file_add(pcm->card, file);
1615         if (err < 0)
1616                 goto __error1;
1617         if (!try_module_get(pcm->card->module)) {
1618                 err = -EFAULT;
1619                 goto __error2;
1620         }
1621         if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {
1622                 err = -EFAULT;
1623                 goto __error;
1624         }
1625         if (file->f_mode & FMODE_WRITE)
1626                 psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
1627         if (file->f_mode & FMODE_READ)
1628                 csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
1629
1630         nonblock = !!(file->f_flags & O_NONBLOCK);
1631         if (psetup && !psetup->disable) {
1632                 if (psetup->nonblock)
1633                         nonblock = 1;
1634                 else if (psetup->block)
1635                         nonblock = 0;
1636         } else if (csetup && !csetup->disable) {
1637                 if (csetup->nonblock)
1638                         nonblock = 1;
1639                 else if (csetup->block)
1640                         nonblock = 0;
1641         }
1642         if (!nonblock)
1643                 nonblock = nonblock_open;
1644
1645         init_waitqueue_entry(&wait, current);
1646         add_wait_queue(&pcm->open_wait, &wait);
1647         down(&pcm->open_mutex);
1648         while (1) {
1649                 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
1650                                             minor, psetup, csetup);
1651                 if (err >= 0)
1652                         break;
1653                 if (err == -EAGAIN) {
1654                         if (nonblock) {
1655                                 err = -EBUSY;
1656                                 break;
1657                         }
1658                 } else
1659                         break;
1660                 set_current_state(TASK_INTERRUPTIBLE);
1661                 up(&pcm->open_mutex);
1662                 schedule();
1663                 down(&pcm->open_mutex);
1664                 if (signal_pending(current)) {
1665                         err = -ERESTARTSYS;
1666                         break;
1667                 }
1668         }
1669         set_current_state(TASK_RUNNING);
1670         remove_wait_queue(&pcm->open_wait, &wait);
1671         up(&pcm->open_mutex);
1672         if (err < 0)
1673                 goto __error;
1674         return err;
1675
1676       __error:
1677         module_put(pcm->card->module);
1678       __error2:
1679         snd_card_file_remove(pcm->card, file);
1680       __error1:
1681         return err;
1682 }
1683
1684 static int snd_pcm_oss_release(struct inode *inode, struct file *file)
1685 {
1686         snd_pcm_t *pcm;
1687         snd_pcm_substream_t *substream;
1688         snd_pcm_oss_file_t *pcm_oss_file;
1689
1690         pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
1691         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1692         if (substream == NULL)
1693                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1694         snd_assert(substream != NULL, return -ENXIO);
1695         pcm = substream->pcm;
1696         snd_pcm_oss_sync(pcm_oss_file);
1697         down(&pcm->open_mutex);
1698         snd_pcm_oss_release_file(pcm_oss_file);
1699         up(&pcm->open_mutex);
1700         wake_up(&pcm->open_wait);
1701         module_put(pcm->card->module);
1702         snd_card_file_remove(pcm->card, file);
1703         return 0;
1704 }
1705
1706 static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
1707                              unsigned int cmd, unsigned long arg)
1708 {
1709         snd_pcm_oss_file_t *pcm_oss_file;
1710         int res;
1711
1712         pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
1713         if (cmd == OSS_GETVERSION)
1714                 return put_user(SNDRV_OSS_VERSION, (int *)arg) ? -EFAULT : 0;
1715 #if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
1716         if (((cmd >> 8) & 0xff) == 'M') {       /* mixer ioctl - for OSS compatibility */
1717                 snd_pcm_substream_t *substream;
1718                 int idx;
1719                 for (idx = 0; idx < 2; ++idx) {
1720                         substream = pcm_oss_file->streams[idx];
1721                         if (substream != NULL)
1722                                 break;
1723                 }
1724                 snd_assert(substream != NULL, return -ENXIO);
1725                 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);
1726         }
1727 #endif
1728         if (((cmd >> 8) & 0xff) != 'P')
1729                 return -EINVAL;
1730         switch (cmd) {
1731         case SNDCTL_DSP_RESET:
1732                 return snd_pcm_oss_reset(pcm_oss_file);
1733         case SNDCTL_DSP_SYNC:
1734                 return snd_pcm_oss_sync(pcm_oss_file);
1735         case SNDCTL_DSP_SPEED:
1736                 if (get_user(res, (int *)arg))
1737                         return -EFAULT;
1738                 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)
1739                         return res;
1740                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1741         case SOUND_PCM_READ_RATE:
1742                 res = snd_pcm_oss_get_rate(pcm_oss_file);
1743                 if (res < 0)
1744                         return res;
1745                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1746         case SNDCTL_DSP_STEREO:
1747                 if (get_user(res, (int *)arg))
1748                         return -EFAULT;
1749                 res = res > 0 ? 2 : 1;
1750                 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)
1751                         return res;
1752                 return put_user(--res, (int *)arg) ? -EFAULT : 0;
1753         case SNDCTL_DSP_GETBLKSIZE:
1754                 res = snd_pcm_oss_get_block_size(pcm_oss_file);
1755                 if (res < 0)
1756                         return res;
1757                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1758         case SNDCTL_DSP_SETFMT:
1759                 if (get_user(res, (int *)arg))
1760                         return -EFAULT;
1761                 res = snd_pcm_oss_set_format(pcm_oss_file, res);
1762                 if (res < 0)
1763                         return res;
1764                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1765         case SOUND_PCM_READ_BITS:
1766                 res = snd_pcm_oss_get_format(pcm_oss_file);
1767                 if (res < 0)
1768                         return res;
1769                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1770         case SNDCTL_DSP_CHANNELS:
1771                 if (get_user(res, (int *)arg))
1772                         return -EFAULT;
1773                 res = snd_pcm_oss_set_channels(pcm_oss_file, res);
1774                 if (res < 0)
1775                         return res;
1776                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1777         case SOUND_PCM_READ_CHANNELS:
1778                 res = snd_pcm_oss_get_channels(pcm_oss_file);
1779                 if (res < 0)
1780                         return res;
1781                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1782         case SOUND_PCM_WRITE_FILTER:
1783         case SOUND_PCM_READ_FILTER:
1784                 return -EIO;
1785         case SNDCTL_DSP_POST:   /* to do */
1786                 return 0;
1787         case SNDCTL_DSP_SUBDIVIDE:
1788                 if (get_user(res, (int *)arg))
1789                         return -EFAULT;
1790                 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);
1791                 if (res < 0)
1792                         return res;
1793                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1794         case SNDCTL_DSP_SETFRAGMENT:
1795                 if (get_user(res, (int *)arg))
1796                         return -EFAULT;
1797                 return snd_pcm_oss_set_fragment(pcm_oss_file, res);
1798         case SNDCTL_DSP_GETFMTS:
1799                 res = snd_pcm_oss_get_formats(pcm_oss_file);
1800                 if (res < 0)
1801                         return res;
1802                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1803         case SNDCTL_DSP_GETOSPACE:
1804         case SNDCTL_DSP_GETISPACE:
1805                 return snd_pcm_oss_get_space(pcm_oss_file,
1806                         cmd == SNDCTL_DSP_GETISPACE ?
1807                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
1808                         (struct audio_buf_info *) arg);
1809         case SNDCTL_DSP_NONBLOCK:
1810                 return snd_pcm_oss_nonblock(file);
1811         case SNDCTL_DSP_GETCAPS:
1812                 res = snd_pcm_oss_get_caps(pcm_oss_file);
1813                 if (res < 0)
1814                         return res;
1815                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1816         case SNDCTL_DSP_GETTRIGGER:
1817                 res = snd_pcm_oss_get_trigger(pcm_oss_file);
1818                 if (res < 0)
1819                         return res;
1820                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1821         case SNDCTL_DSP_SETTRIGGER:
1822                 if (get_user(res, (int *)arg))
1823                         return -EFAULT;
1824                 return snd_pcm_oss_set_trigger(pcm_oss_file, res);
1825         case SNDCTL_DSP_GETIPTR:
1826         case SNDCTL_DSP_GETOPTR:
1827                 return snd_pcm_oss_get_ptr(pcm_oss_file,
1828                         cmd == SNDCTL_DSP_GETIPTR ?
1829                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
1830                         (struct count_info *) arg);
1831         case SNDCTL_DSP_MAPINBUF:
1832         case SNDCTL_DSP_MAPOUTBUF:
1833                 return snd_pcm_oss_get_mapbuf(pcm_oss_file,
1834                         cmd == SNDCTL_DSP_MAPINBUF ?
1835                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
1836                         (struct buffmem_desc *) arg);
1837         case SNDCTL_DSP_SETSYNCRO:
1838                 /* stop DMA now.. */
1839                 return 0;
1840         case SNDCTL_DSP_SETDUPLEX:
1841                 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX)
1842                         return 0;
1843                 return -EIO;
1844         case SNDCTL_DSP_GETODELAY:
1845                 res = snd_pcm_oss_get_odelay(pcm_oss_file);
1846                 if (res < 0) {
1847                         /* it's for sure, some broken apps don't check for error codes */
1848                         put_user(0, (int *)arg);
1849                         return res;
1850                 }
1851                 return put_user(res, (int *)arg) ? -EFAULT : 0;
1852         case SNDCTL_DSP_PROFILE:
1853                 return 0;       /* silently ignore */
1854         default:
1855                 snd_printd("pcm_oss: unknown command = 0x%x\n", cmd);
1856         }
1857         return -EINVAL;
1858 }
1859
1860 static ssize_t snd_pcm_oss_read(struct file *file, char *buf, size_t count, loff_t *offset)
1861 {
1862         snd_pcm_oss_file_t *pcm_oss_file;
1863         snd_pcm_substream_t *substream;
1864
1865         pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
1866         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1867         if (substream == NULL)
1868                 return -ENXIO;
1869         return snd_pcm_oss_read1(substream, buf, count);
1870 }
1871
1872 static ssize_t snd_pcm_oss_write(struct file *file, const char *buf, size_t count, loff_t *offset)
1873 {
1874         snd_pcm_oss_file_t *pcm_oss_file;
1875         snd_pcm_substream_t *substream;
1876         long result;
1877
1878         pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
1879         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1880         if (substream == NULL)
1881                 return -ENXIO;
1882         up(&file->f_dentry->d_inode->i_sem);
1883         result = snd_pcm_oss_write1(substream, buf, count);
1884         down(&file->f_dentry->d_inode->i_sem);
1885         return result;
1886 }
1887
1888 static int snd_pcm_oss_playback_ready(snd_pcm_substream_t *substream)
1889 {
1890         snd_pcm_runtime_t *runtime = substream->runtime;
1891         if (atomic_read(&runtime->mmap_count))
1892                 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
1893         else
1894                 return snd_pcm_playback_ready(substream);
1895 }
1896
1897 static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream)
1898 {
1899         snd_pcm_runtime_t *runtime = substream->runtime;
1900         if (atomic_read(&runtime->mmap_count))
1901                 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
1902         else
1903                 return snd_pcm_capture_ready(substream);
1904 }
1905
1906 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
1907 {
1908         snd_pcm_oss_file_t *pcm_oss_file;
1909         unsigned int mask;
1910         snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
1911         
1912         pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return 0);
1913
1914         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1915         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1916
1917         mask = 0;
1918         if (psubstream != NULL) {
1919                 snd_pcm_runtime_t *runtime = psubstream->runtime;
1920                 poll_wait(file, &runtime->sleep, wait);
1921                 snd_pcm_stream_lock_irq(psubstream);
1922                 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
1923                     (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
1924                      snd_pcm_oss_playback_ready(psubstream)))
1925                         mask |= POLLOUT | POLLWRNORM;
1926                 snd_pcm_stream_unlock_irq(psubstream);
1927         }
1928         if (csubstream != NULL) {
1929                 snd_pcm_runtime_t *runtime = csubstream->runtime;
1930                 poll_wait(file, &runtime->sleep, wait);
1931                 snd_pcm_stream_lock_irq(csubstream);
1932                 if (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
1933                     snd_pcm_oss_capture_ready(csubstream))
1934                         mask |= POLLIN | POLLRDNORM;
1935                 snd_pcm_stream_unlock_irq(csubstream);
1936         }
1937
1938         return mask;
1939 }
1940
1941 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
1942 {
1943         snd_pcm_oss_file_t *pcm_oss_file;
1944         snd_pcm_substream_t *substream = NULL;
1945         snd_pcm_runtime_t *runtime;
1946         int err;
1947
1948         pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
1949         switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
1950         case VM_READ | VM_WRITE:
1951                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1952                 if (substream)
1953                         break;
1954                 /* Fall through */
1955         case VM_READ:
1956                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1957                 break;
1958         case VM_WRITE:
1959                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1960                 break;
1961         default:
1962                 return -EINVAL;
1963         }
1964         /* set VM_READ access as well to fix memset() routines that do
1965            reads before writes (to improve performance) */
1966         area->vm_flags |= VM_READ;
1967         if (substream == NULL)
1968                 return -ENXIO;
1969         runtime = substream->runtime;
1970         if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID))
1971                 return -EIO;
1972         if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED)
1973                 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
1974         else
1975                 return -EIO;
1976         
1977         if (runtime->oss.params) {
1978                 if ((err = snd_pcm_oss_change_params(substream)) < 0)
1979                         return err;
1980         }
1981         if (runtime->oss.plugin_first != NULL)
1982                 return -EIO;
1983
1984         if (area->vm_pgoff != 0)
1985                 return -EINVAL;
1986
1987         err = snd_pcm_mmap_data(substream, file, area);
1988         if (err < 0)
1989                 return err;
1990         runtime->oss.mmap_bytes = area->vm_end - area->vm_start;
1991         /* In mmap mode we never stop */
1992         runtime->stop_threshold = runtime->boundary;
1993
1994         return 0;
1995 }
1996
1997 /*
1998  *  /proc interface
1999  */
2000
2001 static void snd_pcm_oss_proc_read(snd_info_entry_t *entry,
2002                                   snd_info_buffer_t * buffer)
2003 {
2004         snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
2005         snd_pcm_oss_setup_t *setup = pstr->oss.setup_list;
2006         down(&pstr->oss.setup_mutex);
2007         while (setup) {
2008                 snd_iprintf(buffer, "%s %u %u%s%s%s%s\n",
2009                             setup->task_name,
2010                             setup->periods,
2011                             setup->period_size,
2012                             setup->disable ? " disable" : "",
2013                             setup->direct ? " direct" : "",
2014                             setup->block ? " block" : "",
2015                             setup->nonblock ? " non-block" : "");
2016                 setup = setup->next;
2017         }
2018         up(&pstr->oss.setup_mutex);
2019 }
2020
2021 static void snd_pcm_oss_proc_free_setup_list(snd_pcm_str_t * pstr)
2022 {
2023         unsigned int idx;
2024         snd_pcm_substream_t *substream;
2025         snd_pcm_oss_setup_t *setup, *setupn;
2026
2027         for (idx = 0, substream = pstr->substream;
2028              idx < pstr->substream_count; idx++, substream = substream->next)
2029                 substream->oss.setup = NULL;
2030         for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
2031              setup; setup = setupn) {
2032                 setupn = setup->next;
2033                 kfree(setup->task_name);
2034                 kfree(setup);
2035         }
2036         pstr->oss.setup_list = NULL;
2037 }
2038
2039 static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
2040                                    snd_info_buffer_t * buffer)
2041 {
2042         snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
2043         char line[512], str[32], task_name[32], *ptr;
2044         int idx1;
2045         snd_pcm_oss_setup_t *setup, *setup1, template;
2046
2047         while (!snd_info_get_line(buffer, line, sizeof(line))) {
2048                 down(&pstr->oss.setup_mutex);
2049                 memset(&template, 0, sizeof(template));
2050                 ptr = snd_info_get_str(task_name, line, sizeof(task_name));
2051                 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
2052                         snd_pcm_oss_proc_free_setup_list(pstr);
2053                         up(&pstr->oss.setup_mutex);
2054                         continue;
2055                 }
2056                 for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
2057                         if (!strcmp(setup->task_name, task_name)) {
2058                                 template = *setup;
2059                                 break;
2060                         }
2061                 }
2062                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2063                 template.periods = simple_strtoul(str, NULL, 10);
2064                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2065                 template.period_size = simple_strtoul(str, NULL, 10);
2066                 for (idx1 = 31; idx1 >= 0; idx1--)
2067                         if (template.period_size & (1 << idx1))
2068                                 break;
2069                 for (idx1--; idx1 >= 0; idx1--)
2070                         template.period_size &= ~(1 << idx1);
2071                 do {
2072                         ptr = snd_info_get_str(str, ptr, sizeof(str));
2073                         if (!strcmp(str, "disable")) {
2074                                 template.disable = 1;
2075                         } else if (!strcmp(str, "direct")) {
2076                                 template.direct = 1;
2077                         } else if (!strcmp(str, "block")) {
2078                                 template.block = 1;
2079                         } else if (!strcmp(str, "non-block")) {
2080                                 template.nonblock = 1;
2081                         }
2082                 } while (*str);
2083                 if (setup == NULL) {
2084                         setup = (snd_pcm_oss_setup_t *) kmalloc(sizeof(snd_pcm_oss_setup_t), GFP_KERNEL);
2085                         if (setup) {
2086                                 if (pstr->oss.setup_list == NULL) {
2087                                         pstr->oss.setup_list = setup;
2088                                 } else {
2089                                         for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
2090                                         setup1->next = setup;
2091                                 }
2092                                 template.task_name = snd_kmalloc_strdup(task_name, GFP_KERNEL);
2093                         } else {
2094                                 buffer->error = -ENOMEM;
2095                         }
2096                 }
2097                 if (setup)
2098                         *setup = template;
2099                 up(&pstr->oss.setup_mutex);
2100         }
2101 }
2102
2103 static void snd_pcm_oss_proc_init(snd_pcm_t *pcm)
2104 {
2105         int stream;
2106         for (stream = 0; stream < 2; ++stream) {
2107                 snd_info_entry_t *entry;
2108                 snd_pcm_str_t *pstr = &pcm->streams[stream];
2109                 if (pstr->substream_count == 0)
2110                         continue;
2111                 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
2112                         entry->content = SNDRV_INFO_CONTENT_TEXT;
2113                         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
2114                         entry->c.text.read_size = 8192;
2115                         entry->c.text.read = snd_pcm_oss_proc_read;
2116                         entry->c.text.write_size = 8192;
2117                         entry->c.text.write = snd_pcm_oss_proc_write;
2118                         entry->private_data = pstr;
2119                         if (snd_info_register(entry) < 0) {
2120                                 snd_info_free_entry(entry);
2121                                 entry = NULL;
2122                         }
2123                 }
2124                 pstr->oss.proc_entry = entry;
2125         }
2126 }
2127
2128 static void snd_pcm_oss_proc_done(snd_pcm_t *pcm)
2129 {
2130         int stream;
2131         for (stream = 0; stream < 2; ++stream) {
2132                 snd_pcm_str_t *pstr = &pcm->streams[stream];
2133                 if (pstr->oss.proc_entry) {
2134                         snd_info_unregister(pstr->oss.proc_entry);
2135                         pstr->oss.proc_entry = NULL;
2136                         snd_pcm_oss_proc_free_setup_list(pstr);
2137                 }
2138         }
2139 }
2140
2141 /*
2142  *  ENTRY functions
2143  */
2144
2145 static struct file_operations snd_pcm_oss_f_reg =
2146 {
2147         .owner =        THIS_MODULE,
2148         .read =         snd_pcm_oss_read,
2149         .write =        snd_pcm_oss_write,
2150         .open =         snd_pcm_oss_open,
2151         .release =      snd_pcm_oss_release,
2152         .poll =         snd_pcm_oss_poll,
2153         .ioctl =        snd_pcm_oss_ioctl,
2154         .mmap =         snd_pcm_oss_mmap,
2155 };
2156
2157 static snd_minor_t snd_pcm_oss_reg =
2158 {
2159         .comment =      "digital audio",
2160         .f_ops =        &snd_pcm_oss_f_reg,
2161 };
2162
2163 static void register_oss_dsp(snd_pcm_t *pcm, int index)
2164 {
2165         char name[128];
2166         sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
2167         if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2168                                     pcm->card, index, &snd_pcm_oss_reg,
2169                                     name) < 0) {
2170                 snd_printk("unable to register OSS PCM device %i:%i\n", pcm->card->number, pcm->device);
2171         }
2172 }
2173
2174 static int snd_pcm_oss_register_minor(snd_pcm_t * pcm)
2175 {
2176         pcm->oss.reg = 0;
2177         if (dsp_map[pcm->card->number] == (int)pcm->device) {
2178                 char name[128];
2179                 int duplex;
2180                 register_oss_dsp(pcm, 0);
2181                 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 
2182                               pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 
2183                               !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
2184                 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
2185 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
2186                 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
2187                                       pcm->card->number,
2188                                       name);
2189 #endif
2190                 pcm->oss.reg++;
2191                 pcm->oss.reg_mask |= 1;
2192         }
2193         if (adsp_map[pcm->card->number] == (int)pcm->device) {
2194                 register_oss_dsp(pcm, 1);
2195                 pcm->oss.reg++;
2196                 pcm->oss.reg_mask |= 2;
2197         }
2198
2199         if (pcm->oss.reg)
2200                 snd_pcm_oss_proc_init(pcm);
2201
2202         return 0;
2203 }
2204
2205 static int snd_pcm_oss_disconnect_minor(snd_pcm_t * pcm)
2206 {
2207         if (pcm->oss.reg) {
2208                 if (pcm->oss.reg_mask & 1) {
2209                         pcm->oss.reg_mask &= ~1;
2210                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2211                                                   pcm->card, 0);
2212                 }
2213                 if (pcm->oss.reg_mask & 2) {
2214                         pcm->oss.reg_mask &= ~2;
2215                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2216                                                   pcm->card, 1);
2217                 }
2218         }
2219         return 0;
2220 }
2221
2222 static int snd_pcm_oss_unregister_minor(snd_pcm_t * pcm)
2223 {
2224         snd_pcm_oss_disconnect_minor(pcm);
2225         if (pcm->oss.reg) {
2226                 if (dsp_map[pcm->card->number] == (int)pcm->device) {
2227 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
2228                         snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
2229 #endif
2230                 }
2231                 pcm->oss.reg = 0;
2232                 snd_pcm_oss_proc_done(pcm);
2233         }
2234         return 0;
2235 }
2236
2237 static snd_pcm_notify_t snd_pcm_oss_notify =
2238 {
2239         .n_register =   snd_pcm_oss_register_minor,
2240         .n_disconnect = snd_pcm_oss_disconnect_minor,
2241         .n_unregister = snd_pcm_oss_unregister_minor,
2242 };
2243
2244 static int __init alsa_pcm_oss_init(void)
2245 {
2246         int i;
2247         int err;
2248
2249         /* check device map table */
2250         for (i = 0; i < SNDRV_CARDS; i++) {
2251                 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) {
2252                         snd_printk("invalid dsp_map[%d] = %d\n", i, dsp_map[i]);
2253                         dsp_map[i] = 0;
2254                 }
2255                 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) {
2256                         snd_printk("invalid adsp_map[%d] = %d\n", i, adsp_map[i]);
2257                         adsp_map[i] = 1;
2258                 }
2259         }
2260         if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0)
2261                 return err;
2262         return 0;
2263 }
2264
2265 static void __exit alsa_pcm_oss_exit(void)
2266 {
2267         snd_pcm_notify(&snd_pcm_oss_notify, 1);
2268 }
2269
2270 module_init(alsa_pcm_oss_init)
2271 module_exit(alsa_pcm_oss_exit)