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