Merge branches 'slab/documentation', 'slab/fixes', 'slob/cleanups' and 'slub/fixes...
[pandora-kernel.git] / sound / core / oss / pcm_oss.c
1 /*
2  *  Digital Audio (PCM) abstract layer / OSS compatible
3  *  Copyright (c) by Jaroslav Kysela <perex@perex.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 <linux/init.h>
30 #include <linux/slab.h>
31 #include <linux/time.h>
32 #include <linux/vmalloc.h>
33 #include <linux/moduleparam.h>
34 #include <linux/math64.h>
35 #include <linux/string.h>
36 #include <sound/core.h>
37 #include <sound/minors.h>
38 #include <sound/pcm.h>
39 #include <sound/pcm_params.h>
40 #include "pcm_plugin.h"
41 #include <sound/info.h>
42 #include <linux/soundcard.h>
43 #include <sound/initval.h>
44
45 #define OSS_ALSAEMULVER         _SIOR ('M', 249, int)
46
47 static int dsp_map[SNDRV_CARDS];
48 static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
49 static int nonblock_open = 1;
50
51 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.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, NULL, 0444);
55 MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device.");
56 module_param_array(adsp_map, int, NULL, 0444);
57 MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device.");
58 module_param(nonblock_open, bool, 0644);
59 MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
60 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
61 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
62
63 extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg);
64 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
65 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
66 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
67
68 static inline mm_segment_t snd_enter_user(void)
69 {
70         mm_segment_t fs = get_fs();
71         set_fs(get_ds());
72         return fs;
73 }
74
75 static inline void snd_leave_user(mm_segment_t fs)
76 {
77         set_fs(fs);
78 }
79
80 /*
81  * helper functions to process hw_params
82  */
83 static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
84 {
85         int changed = 0;
86         if (i->min < min) {
87                 i->min = min;
88                 i->openmin = openmin;
89                 changed = 1;
90         } else if (i->min == min && !i->openmin && openmin) {
91                 i->openmin = 1;
92                 changed = 1;
93         }
94         if (i->integer) {
95                 if (i->openmin) {
96                         i->min++;
97                         i->openmin = 0;
98                 }
99         }
100         if (snd_interval_checkempty(i)) {
101                 snd_interval_none(i);
102                 return -EINVAL;
103         }
104         return changed;
105 }
106
107 static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
108 {
109         int changed = 0;
110         if (i->max > max) {
111                 i->max = max;
112                 i->openmax = openmax;
113                 changed = 1;
114         } else if (i->max == max && !i->openmax && openmax) {
115                 i->openmax = 1;
116                 changed = 1;
117         }
118         if (i->integer) {
119                 if (i->openmax) {
120                         i->max--;
121                         i->openmax = 0;
122                 }
123         }
124         if (snd_interval_checkempty(i)) {
125                 snd_interval_none(i);
126                 return -EINVAL;
127         }
128         return changed;
129 }
130
131 static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
132 {
133         struct snd_interval t;
134         t.empty = 0;
135         t.min = t.max = val;
136         t.openmin = t.openmax = 0;
137         t.integer = 1;
138         return snd_interval_refine(i, &t);
139 }
140
141 /**
142  * snd_pcm_hw_param_value_min
143  * @params: the hw_params instance
144  * @var: parameter to retrieve
145  * @dir: pointer to the direction (-1,0,1) or NULL
146  *
147  * Return the minimum value for field PAR.
148  */
149 static unsigned int
150 snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
151                            snd_pcm_hw_param_t var, int *dir)
152 {
153         if (hw_is_mask(var)) {
154                 if (dir)
155                         *dir = 0;
156                 return snd_mask_min(hw_param_mask_c(params, var));
157         }
158         if (hw_is_interval(var)) {
159                 const struct snd_interval *i = hw_param_interval_c(params, var);
160                 if (dir)
161                         *dir = i->openmin;
162                 return snd_interval_min(i);
163         }
164         return -EINVAL;
165 }
166
167 /**
168  * snd_pcm_hw_param_value_max
169  * @params: the hw_params instance
170  * @var: parameter to retrieve
171  * @dir: pointer to the direction (-1,0,1) or NULL
172  *
173  * Return the maximum value for field PAR.
174  */
175 static unsigned int
176 snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
177                            snd_pcm_hw_param_t var, int *dir)
178 {
179         if (hw_is_mask(var)) {
180                 if (dir)
181                         *dir = 0;
182                 return snd_mask_max(hw_param_mask_c(params, var));
183         }
184         if (hw_is_interval(var)) {
185                 const struct snd_interval *i = hw_param_interval_c(params, var);
186                 if (dir)
187                         *dir = - (int) i->openmax;
188                 return snd_interval_max(i);
189         }
190         return -EINVAL;
191 }
192
193 static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
194                                   snd_pcm_hw_param_t var,
195                                   const struct snd_mask *val)
196 {
197         int changed;
198         changed = snd_mask_refine(hw_param_mask(params, var), val);
199         if (changed) {
200                 params->cmask |= 1 << var;
201                 params->rmask |= 1 << var;
202         }
203         return changed;
204 }
205
206 static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm,
207                                  struct snd_pcm_hw_params *params,
208                                  snd_pcm_hw_param_t var,
209                                  const struct snd_mask *val)
210 {
211         int changed = _snd_pcm_hw_param_mask(params, var, val);
212         if (changed < 0)
213                 return changed;
214         if (params->rmask) {
215                 int err = snd_pcm_hw_refine(pcm, params);
216                 if (err < 0)
217                         return err;
218         }
219         return 0;
220 }
221
222 static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
223                                  snd_pcm_hw_param_t var, unsigned int val,
224                                  int dir)
225 {
226         int changed;
227         int open = 0;
228         if (dir) {
229                 if (dir > 0) {
230                         open = 1;
231                 } else if (dir < 0) {
232                         if (val > 0) {
233                                 open = 1;
234                                 val--;
235                         }
236                 }
237         }
238         if (hw_is_mask(var))
239                 changed = snd_mask_refine_min(hw_param_mask(params, var),
240                                               val + !!open);
241         else if (hw_is_interval(var))
242                 changed = snd_interval_refine_min(hw_param_interval(params, var),
243                                                   val, open);
244         else
245                 return -EINVAL;
246         if (changed) {
247                 params->cmask |= 1 << var;
248                 params->rmask |= 1 << var;
249         }
250         return changed;
251 }
252
253 /**
254  * snd_pcm_hw_param_min
255  * @pcm: PCM instance
256  * @params: the hw_params instance
257  * @var: parameter to retrieve
258  * @val: minimal value
259  * @dir: pointer to the direction (-1,0,1) or NULL
260  *
261  * Inside configuration space defined by PARAMS remove from PAR all 
262  * values < VAL. Reduce configuration space accordingly.
263  * Return new minimum or -EINVAL if the configuration space is empty
264  */
265 static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm,
266                                 struct snd_pcm_hw_params *params,
267                                 snd_pcm_hw_param_t var, unsigned int val,
268                                 int *dir)
269 {
270         int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
271         if (changed < 0)
272                 return changed;
273         if (params->rmask) {
274                 int err = snd_pcm_hw_refine(pcm, params);
275                 if (err < 0)
276                         return err;
277         }
278         return snd_pcm_hw_param_value_min(params, var, dir);
279 }
280
281 static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
282                                  snd_pcm_hw_param_t var, unsigned int val,
283                                  int dir)
284 {
285         int changed;
286         int open = 0;
287         if (dir) {
288                 if (dir < 0) {
289                         open = 1;
290                 } else if (dir > 0) {
291                         open = 1;
292                         val++;
293                 }
294         }
295         if (hw_is_mask(var)) {
296                 if (val == 0 && open) {
297                         snd_mask_none(hw_param_mask(params, var));
298                         changed = -EINVAL;
299                 } else
300                         changed = snd_mask_refine_max(hw_param_mask(params, var),
301                                                       val - !!open);
302         } else if (hw_is_interval(var))
303                 changed = snd_interval_refine_max(hw_param_interval(params, var),
304                                                   val, open);
305         else
306                 return -EINVAL;
307         if (changed) {
308                 params->cmask |= 1 << var;
309                 params->rmask |= 1 << var;
310         }
311         return changed;
312 }
313
314 /**
315  * snd_pcm_hw_param_max
316  * @pcm: PCM instance
317  * @params: the hw_params instance
318  * @var: parameter to retrieve
319  * @val: maximal value
320  * @dir: pointer to the direction (-1,0,1) or NULL
321  *
322  * Inside configuration space defined by PARAMS remove from PAR all 
323  *  values >= VAL + 1. Reduce configuration space accordingly.
324  *  Return new maximum or -EINVAL if the configuration space is empty
325  */
326 static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm,
327                                 struct snd_pcm_hw_params *params,
328                                 snd_pcm_hw_param_t var, unsigned int val,
329                                 int *dir)
330 {
331         int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
332         if (changed < 0)
333                 return changed;
334         if (params->rmask) {
335                 int err = snd_pcm_hw_refine(pcm, params);
336                 if (err < 0)
337                         return err;
338         }
339         return snd_pcm_hw_param_value_max(params, var, dir);
340 }
341
342 static int boundary_sub(int a, int adir,
343                         int b, int bdir,
344                         int *c, int *cdir)
345 {
346         adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
347         bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
348         *c = a - b;
349         *cdir = adir - bdir;
350         if (*cdir == -2) {
351                 (*c)--;
352         } else if (*cdir == 2) {
353                 (*c)++;
354         }
355         return 0;
356 }
357
358 static int boundary_lt(unsigned int a, int adir,
359                        unsigned int b, int bdir)
360 {
361         if (adir < 0) {
362                 a--;
363                 adir = 1;
364         } else if (adir > 0)
365                 adir = 1;
366         if (bdir < 0) {
367                 b--;
368                 bdir = 1;
369         } else if (bdir > 0)
370                 bdir = 1;
371         return a < b || (a == b && adir < bdir);
372 }
373
374 /* Return 1 if min is nearer to best than max */
375 static int boundary_nearer(int min, int mindir,
376                            int best, int bestdir,
377                            int max, int maxdir)
378 {
379         int dmin, dmindir;
380         int dmax, dmaxdir;
381         boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
382         boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
383         return boundary_lt(dmin, dmindir, dmax, dmaxdir);
384 }
385
386 /**
387  * snd_pcm_hw_param_near
388  * @pcm: PCM instance
389  * @params: the hw_params instance
390  * @var: parameter to retrieve
391  * @best: value to set
392  * @dir: pointer to the direction (-1,0,1) or NULL
393  *
394  * Inside configuration space defined by PARAMS set PAR to the available value
395  * nearest to VAL. Reduce configuration space accordingly.
396  * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
397  * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
398  * Return the value found.
399   */
400 static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
401                                  struct snd_pcm_hw_params *params,
402                                  snd_pcm_hw_param_t var, unsigned int best,
403                                  int *dir)
404 {
405         struct snd_pcm_hw_params *save = NULL;
406         int v;
407         unsigned int saved_min;
408         int last = 0;
409         int min, max;
410         int mindir, maxdir;
411         int valdir = dir ? *dir : 0;
412         /* FIXME */
413         if (best > INT_MAX)
414                 best = INT_MAX;
415         min = max = best;
416         mindir = maxdir = valdir;
417         if (maxdir > 0)
418                 maxdir = 0;
419         else if (maxdir == 0)
420                 maxdir = -1;
421         else {
422                 maxdir = 1;
423                 max--;
424         }
425         save = kmalloc(sizeof(*save), GFP_KERNEL);
426         if (save == NULL)
427                 return -ENOMEM;
428         *save = *params;
429         saved_min = min;
430         min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
431         if (min >= 0) {
432                 struct snd_pcm_hw_params *params1;
433                 if (max < 0)
434                         goto _end;
435                 if ((unsigned int)min == saved_min && mindir == valdir)
436                         goto _end;
437                 params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
438                 if (params1 == NULL) {
439                         kfree(save);
440                         return -ENOMEM;
441                 }
442                 *params1 = *save;
443                 max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
444                 if (max < 0) {
445                         kfree(params1);
446                         goto _end;
447                 }
448                 if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
449                         *params = *params1;
450                         last = 1;
451                 }
452                 kfree(params1);
453         } else {
454                 *params = *save;
455                 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
456                 if (max < 0)
457                         return max;
458                 last = 1;
459         }
460  _end:
461         kfree(save);
462         if (last)
463                 v = snd_pcm_hw_param_last(pcm, params, var, dir);
464         else
465                 v = snd_pcm_hw_param_first(pcm, params, var, dir);
466         snd_BUG_ON(v < 0);
467         return v;
468 }
469
470 static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
471                                  snd_pcm_hw_param_t var, unsigned int val,
472                                  int dir)
473 {
474         int changed;
475         if (hw_is_mask(var)) {
476                 struct snd_mask *m = hw_param_mask(params, var);
477                 if (val == 0 && dir < 0) {
478                         changed = -EINVAL;
479                         snd_mask_none(m);
480                 } else {
481                         if (dir > 0)
482                                 val++;
483                         else if (dir < 0)
484                                 val--;
485                         changed = snd_mask_refine_set(hw_param_mask(params, var), val);
486                 }
487         } else if (hw_is_interval(var)) {
488                 struct snd_interval *i = hw_param_interval(params, var);
489                 if (val == 0 && dir < 0) {
490                         changed = -EINVAL;
491                         snd_interval_none(i);
492                 } else if (dir == 0)
493                         changed = snd_interval_refine_set(i, val);
494                 else {
495                         struct snd_interval t;
496                         t.openmin = 1;
497                         t.openmax = 1;
498                         t.empty = 0;
499                         t.integer = 0;
500                         if (dir < 0) {
501                                 t.min = val - 1;
502                                 t.max = val;
503                         } else {
504                                 t.min = val;
505                                 t.max = val+1;
506                         }
507                         changed = snd_interval_refine(i, &t);
508                 }
509         } else
510                 return -EINVAL;
511         if (changed) {
512                 params->cmask |= 1 << var;
513                 params->rmask |= 1 << var;
514         }
515         return changed;
516 }
517
518 /**
519  * snd_pcm_hw_param_set
520  * @pcm: PCM instance
521  * @params: the hw_params instance
522  * @var: parameter to retrieve
523  * @val: value to set
524  * @dir: pointer to the direction (-1,0,1) or NULL
525  *
526  * Inside configuration space defined by PARAMS remove from PAR all 
527  * values != VAL. Reduce configuration space accordingly.
528  *  Return VAL or -EINVAL if the configuration space is empty
529  */
530 static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
531                                 struct snd_pcm_hw_params *params,
532                                 snd_pcm_hw_param_t var, unsigned int val,
533                                 int dir)
534 {
535         int changed = _snd_pcm_hw_param_set(params, var, val, dir);
536         if (changed < 0)
537                 return changed;
538         if (params->rmask) {
539                 int err = snd_pcm_hw_refine(pcm, params);
540                 if (err < 0)
541                         return err;
542         }
543         return snd_pcm_hw_param_value(params, var, NULL);
544 }
545
546 static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
547                                         snd_pcm_hw_param_t var)
548 {
549         int changed;
550         changed = snd_interval_setinteger(hw_param_interval(params, var));
551         if (changed) {
552                 params->cmask |= 1 << var;
553                 params->rmask |= 1 << var;
554         }
555         return changed;
556 }
557         
558 /*
559  * plugin
560  */
561
562 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
563 static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
564 {
565         struct snd_pcm_runtime *runtime = substream->runtime;
566         struct snd_pcm_plugin *plugin, *next;
567         
568         plugin = runtime->oss.plugin_first;
569         while (plugin) {
570                 next = plugin->next;
571                 snd_pcm_plugin_free(plugin);
572                 plugin = next;
573         }
574         runtime->oss.plugin_first = runtime->oss.plugin_last = NULL;
575         return 0;
576 }
577
578 static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin)
579 {
580         struct snd_pcm_runtime *runtime = plugin->plug->runtime;
581         plugin->next = runtime->oss.plugin_first;
582         plugin->prev = NULL;
583         if (runtime->oss.plugin_first) {
584                 runtime->oss.plugin_first->prev = plugin;
585                 runtime->oss.plugin_first = plugin;
586         } else {
587                 runtime->oss.plugin_last =
588                 runtime->oss.plugin_first = plugin;
589         }
590         return 0;
591 }
592
593 int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin)
594 {
595         struct snd_pcm_runtime *runtime = plugin->plug->runtime;
596         plugin->next = NULL;
597         plugin->prev = runtime->oss.plugin_last;
598         if (runtime->oss.plugin_last) {
599                 runtime->oss.plugin_last->next = plugin;
600                 runtime->oss.plugin_last = plugin;
601         } else {
602                 runtime->oss.plugin_last =
603                 runtime->oss.plugin_first = plugin;
604         }
605         return 0;
606 }
607 #endif /* CONFIG_SND_PCM_OSS_PLUGINS */
608
609 static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
610 {
611         struct snd_pcm_runtime *runtime = substream->runtime;
612         long buffer_size = snd_pcm_lib_buffer_bytes(substream);
613         long bytes = frames_to_bytes(runtime, frames);
614         if (buffer_size == runtime->oss.buffer_bytes)
615                 return bytes;
616 #if BITS_PER_LONG >= 64
617         return runtime->oss.buffer_bytes * bytes / buffer_size;
618 #else
619         {
620                 u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
621                 return div_u64(bsize, buffer_size);
622         }
623 #endif
624 }
625
626 static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes)
627 {
628         struct snd_pcm_runtime *runtime = substream->runtime;
629         long buffer_size = snd_pcm_lib_buffer_bytes(substream);
630         if (buffer_size == runtime->oss.buffer_bytes)
631                 return bytes_to_frames(runtime, bytes);
632         return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
633 }
634
635 /* define extended formats in the recent OSS versions (if any) */
636 /* linear formats */
637 #define AFMT_S32_LE      0x00001000
638 #define AFMT_S32_BE      0x00002000
639 #define AFMT_S24_LE      0x00008000
640 #define AFMT_S24_BE      0x00010000
641 #define AFMT_S24_PACKED  0x00040000
642
643 /* other supported formats */
644 #define AFMT_FLOAT       0x00004000
645 #define AFMT_SPDIF_RAW   0x00020000
646
647 /* unsupported formats */
648 #define AFMT_AC3         0x00000400
649 #define AFMT_VORBIS      0x00000800
650
651 static int snd_pcm_oss_format_from(int format)
652 {
653         switch (format) {
654         case AFMT_MU_LAW:       return SNDRV_PCM_FORMAT_MU_LAW;
655         case AFMT_A_LAW:        return SNDRV_PCM_FORMAT_A_LAW;
656         case AFMT_IMA_ADPCM:    return SNDRV_PCM_FORMAT_IMA_ADPCM;
657         case AFMT_U8:           return SNDRV_PCM_FORMAT_U8;
658         case AFMT_S16_LE:       return SNDRV_PCM_FORMAT_S16_LE;
659         case AFMT_S16_BE:       return SNDRV_PCM_FORMAT_S16_BE;
660         case AFMT_S8:           return SNDRV_PCM_FORMAT_S8;
661         case AFMT_U16_LE:       return SNDRV_PCM_FORMAT_U16_LE;
662         case AFMT_U16_BE:       return SNDRV_PCM_FORMAT_U16_BE;
663         case AFMT_MPEG:         return SNDRV_PCM_FORMAT_MPEG;
664         case AFMT_S32_LE:       return SNDRV_PCM_FORMAT_S32_LE;
665         case AFMT_S32_BE:       return SNDRV_PCM_FORMAT_S32_BE;
666         case AFMT_S24_LE:       return SNDRV_PCM_FORMAT_S24_LE;
667         case AFMT_S24_BE:       return SNDRV_PCM_FORMAT_S24_BE;
668         case AFMT_S24_PACKED:   return SNDRV_PCM_FORMAT_S24_3LE;
669         case AFMT_FLOAT:        return SNDRV_PCM_FORMAT_FLOAT;
670         case AFMT_SPDIF_RAW:    return SNDRV_PCM_FORMAT_IEC958_SUBFRAME;
671         default:                return SNDRV_PCM_FORMAT_U8;
672         }
673 }
674
675 static int snd_pcm_oss_format_to(int format)
676 {
677         switch (format) {
678         case SNDRV_PCM_FORMAT_MU_LAW:   return AFMT_MU_LAW;
679         case SNDRV_PCM_FORMAT_A_LAW:    return AFMT_A_LAW;
680         case SNDRV_PCM_FORMAT_IMA_ADPCM:        return AFMT_IMA_ADPCM;
681         case SNDRV_PCM_FORMAT_U8:               return AFMT_U8;
682         case SNDRV_PCM_FORMAT_S16_LE:   return AFMT_S16_LE;
683         case SNDRV_PCM_FORMAT_S16_BE:   return AFMT_S16_BE;
684         case SNDRV_PCM_FORMAT_S8:               return AFMT_S8;
685         case SNDRV_PCM_FORMAT_U16_LE:   return AFMT_U16_LE;
686         case SNDRV_PCM_FORMAT_U16_BE:   return AFMT_U16_BE;
687         case SNDRV_PCM_FORMAT_MPEG:             return AFMT_MPEG;
688         case SNDRV_PCM_FORMAT_S32_LE:   return AFMT_S32_LE;
689         case SNDRV_PCM_FORMAT_S32_BE:   return AFMT_S32_BE;
690         case SNDRV_PCM_FORMAT_S24_LE:   return AFMT_S24_LE;
691         case SNDRV_PCM_FORMAT_S24_BE:   return AFMT_S24_BE;
692         case SNDRV_PCM_FORMAT_S24_3LE:  return AFMT_S24_PACKED;
693         case SNDRV_PCM_FORMAT_FLOAT:    return AFMT_FLOAT;
694         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME: return AFMT_SPDIF_RAW;
695         default:                        return -EINVAL;
696         }
697 }
698
699 static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, 
700                                    struct snd_pcm_hw_params *oss_params,
701                                    struct snd_pcm_hw_params *slave_params)
702 {
703         size_t s;
704         size_t oss_buffer_size, oss_period_size, oss_periods;
705         size_t min_period_size, max_period_size;
706         struct snd_pcm_runtime *runtime = substream->runtime;
707         size_t oss_frame_size;
708
709         oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) *
710                          params_channels(oss_params) / 8;
711
712         oss_buffer_size = snd_pcm_plug_client_size(substream,
713                                                    snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
714         oss_buffer_size = 1 << ld2(oss_buffer_size);
715         if (atomic_read(&substream->mmap_count)) {
716                 if (oss_buffer_size > runtime->oss.mmap_bytes)
717                         oss_buffer_size = runtime->oss.mmap_bytes;
718         }
719
720         if (substream->oss.setup.period_size > 16)
721                 oss_period_size = substream->oss.setup.period_size;
722         else if (runtime->oss.fragshift) {
723                 oss_period_size = 1 << runtime->oss.fragshift;
724                 if (oss_period_size > oss_buffer_size / 2)
725                         oss_period_size = oss_buffer_size / 2;
726         } else {
727                 int sd;
728                 size_t bytes_per_sec = params_rate(oss_params) * snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8;
729
730                 oss_period_size = oss_buffer_size;
731                 do {
732                         oss_period_size /= 2;
733                 } while (oss_period_size > bytes_per_sec);
734                 if (runtime->oss.subdivision == 0) {
735                         sd = 4;
736                         if (oss_period_size / sd > 4096)
737                                 sd *= 2;
738                         if (oss_period_size / sd < 4096)
739                                 sd = 1;
740                 } else
741                         sd = runtime->oss.subdivision;
742                 oss_period_size /= sd;
743                 if (oss_period_size < 16)
744                         oss_period_size = 16;
745         }
746
747         min_period_size = snd_pcm_plug_client_size(substream,
748                                                    snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
749         min_period_size *= oss_frame_size;
750         min_period_size = 1 << (ld2(min_period_size - 1) + 1);
751         if (oss_period_size < min_period_size)
752                 oss_period_size = min_period_size;
753
754         max_period_size = snd_pcm_plug_client_size(substream,
755                                                    snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
756         max_period_size *= oss_frame_size;
757         max_period_size = 1 << ld2(max_period_size);
758         if (oss_period_size > max_period_size)
759                 oss_period_size = max_period_size;
760
761         oss_periods = oss_buffer_size / oss_period_size;
762
763         if (substream->oss.setup.periods > 1)
764                 oss_periods = substream->oss.setup.periods;
765
766         s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
767         if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
768                 s = runtime->oss.maxfrags;
769         if (oss_periods > s)
770                 oss_periods = s;
771
772         s = snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
773         if (s < 2)
774                 s = 2;
775         if (oss_periods < s)
776                 oss_periods = s;
777
778         while (oss_period_size * oss_periods > oss_buffer_size)
779                 oss_period_size /= 2;
780
781         if (oss_period_size < 16)
782                 return -EINVAL;
783         runtime->oss.period_bytes = oss_period_size;
784         runtime->oss.period_frames = 1;
785         runtime->oss.periods = oss_periods;
786         return 0;
787 }
788
789 static int choose_rate(struct snd_pcm_substream *substream,
790                        struct snd_pcm_hw_params *params, unsigned int best_rate)
791 {
792         struct snd_interval *it;
793         struct snd_pcm_hw_params *save;
794         unsigned int rate, prev;
795
796         save = kmalloc(sizeof(*save), GFP_KERNEL);
797         if (save == NULL)
798                 return -ENOMEM;
799         *save = *params;
800         it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE);
801
802         /* try multiples of the best rate */
803         rate = best_rate;
804         for (;;) {
805                 if (it->max < rate || (it->max == rate && it->openmax))
806                         break;
807                 if (it->min < rate || (it->min == rate && !it->openmin)) {
808                         int ret;
809                         ret = snd_pcm_hw_param_set(substream, params,
810                                                    SNDRV_PCM_HW_PARAM_RATE,
811                                                    rate, 0);
812                         if (ret == (int)rate) {
813                                 kfree(save);
814                                 return rate;
815                         }
816                         *params = *save;
817                 }
818                 prev = rate;
819                 rate += best_rate;
820                 if (rate <= prev)
821                         break;
822         }
823
824         /* not found, use the nearest rate */
825         kfree(save);
826         return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
827 }
828
829 static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
830 {
831         struct snd_pcm_runtime *runtime = substream->runtime;
832         struct snd_pcm_hw_params *params, *sparams;
833         struct snd_pcm_sw_params *sw_params;
834         ssize_t oss_buffer_size, oss_period_size;
835         size_t oss_frame_size;
836         int err;
837         int direct;
838         int format, sformat, n;
839         struct snd_mask sformat_mask;
840         struct snd_mask mask;
841
842         if (mutex_lock_interruptible(&runtime->oss.params_lock))
843                 return -EINTR;
844         sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
845         params = kmalloc(sizeof(*params), GFP_KERNEL);
846         sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
847         if (!sw_params || !params || !sparams) {
848                 snd_printd("No memory\n");
849                 err = -ENOMEM;
850                 goto failure;
851         }
852
853         if (atomic_read(&substream->mmap_count))
854                 direct = 1;
855         else
856                 direct = substream->oss.setup.direct;
857
858         _snd_pcm_hw_params_any(sparams);
859         _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
860         _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
861         snd_mask_none(&mask);
862         if (atomic_read(&substream->mmap_count))
863                 snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
864         else {
865                 snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
866                 if (!direct)
867                         snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
868         }
869         err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
870         if (err < 0) {
871                 snd_printd("No usable accesses\n");
872                 err = -EINVAL;
873                 goto failure;
874         }
875         choose_rate(substream, sparams, runtime->oss.rate);
876         snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL);
877
878         format = snd_pcm_oss_format_from(runtime->oss.format);
879
880         sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
881         if (direct)
882                 sformat = format;
883         else
884                 sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
885
886         if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) {
887                 for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) {
888                         if (snd_mask_test(&sformat_mask, sformat) &&
889                             snd_pcm_oss_format_to(sformat) >= 0)
890                                 break;
891                 }
892                 if (sformat > SNDRV_PCM_FORMAT_LAST) {
893                         snd_printd("Cannot find a format!!!\n");
894                         err = -EINVAL;
895                         goto failure;
896                 }
897         }
898         err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0);
899         if (err < 0)
900                 goto failure;
901
902         if (direct) {
903                 memcpy(params, sparams, sizeof(*params));
904         } else {
905                 _snd_pcm_hw_params_any(params);
906                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
907                                       SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
908                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
909                                       snd_pcm_oss_format_from(runtime->oss.format), 0);
910                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
911                                       runtime->oss.channels, 0);
912                 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
913                                       runtime->oss.rate, 0);
914                 pdprintf("client: access = %i, format = %i, channels = %i, rate = %i\n",
915                          params_access(params), params_format(params),
916                          params_channels(params), params_rate(params));
917         }
918         pdprintf("slave: access = %i, format = %i, channels = %i, rate = %i\n",
919                  params_access(sparams), params_format(sparams),
920                  params_channels(sparams), params_rate(sparams));
921
922         oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
923                          params_channels(params) / 8;
924
925 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
926         snd_pcm_oss_plugin_clear(substream);
927         if (!direct) {
928                 /* add necessary plugins */
929                 snd_pcm_oss_plugin_clear(substream);
930                 if ((err = snd_pcm_plug_format_plugins(substream,
931                                                        params, 
932                                                        sparams)) < 0) {
933                         snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err);
934                         snd_pcm_oss_plugin_clear(substream);
935                         goto failure;
936                 }
937                 if (runtime->oss.plugin_first) {
938                         struct snd_pcm_plugin *plugin;
939                         if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) {
940                                 snd_printd("snd_pcm_plugin_build_io failed: %i\n", err);
941                                 snd_pcm_oss_plugin_clear(substream);
942                                 goto failure;
943                         }
944                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
945                                 err = snd_pcm_plugin_append(plugin);
946                         } else {
947                                 err = snd_pcm_plugin_insert(plugin);
948                         }
949                         if (err < 0) {
950                                 snd_pcm_oss_plugin_clear(substream);
951                                 goto failure;
952                         }
953                 }
954         }
955 #endif
956
957         err = snd_pcm_oss_period_size(substream, params, sparams);
958         if (err < 0)
959                 goto failure;
960
961         n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size);
962         err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL);
963         if (err < 0)
964                 goto failure;
965
966         err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS,
967                                      runtime->oss.periods, NULL);
968         if (err < 0)
969                 goto failure;
970
971         snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
972
973         if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) {
974                 snd_printd("HW_PARAMS failed: %i\n", err);
975                 goto failure;
976         }
977
978         memset(sw_params, 0, sizeof(*sw_params));
979         if (runtime->oss.trigger) {
980                 sw_params->start_threshold = 1;
981         } else {
982                 sw_params->start_threshold = runtime->boundary;
983         }
984         if (atomic_read(&substream->mmap_count) ||
985             substream->stream == SNDRV_PCM_STREAM_CAPTURE)
986                 sw_params->stop_threshold = runtime->boundary;
987         else
988                 sw_params->stop_threshold = runtime->buffer_size;
989         sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
990         sw_params->period_step = 1;
991         sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
992                 1 : runtime->period_size;
993         if (atomic_read(&substream->mmap_count) ||
994             substream->oss.setup.nosilence) {
995                 sw_params->silence_threshold = 0;
996                 sw_params->silence_size = 0;
997         } else {
998                 snd_pcm_uframes_t frames;
999                 frames = runtime->period_size + 16;
1000                 if (frames > runtime->buffer_size)
1001                         frames = runtime->buffer_size;
1002                 sw_params->silence_threshold = frames;
1003                 sw_params->silence_size = frames;
1004         }
1005
1006         if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) {
1007                 snd_printd("SW_PARAMS failed: %i\n", err);
1008                 goto failure;
1009         }
1010
1011         runtime->oss.periods = params_periods(sparams);
1012         oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
1013         if (oss_period_size < 0) {
1014                 err = -EINVAL;
1015                 goto failure;
1016         }
1017 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1018         if (runtime->oss.plugin_first) {
1019                 err = snd_pcm_plug_alloc(substream, oss_period_size);
1020                 if (err < 0)
1021                         goto failure;
1022         }
1023 #endif
1024         oss_period_size *= oss_frame_size;
1025
1026         oss_buffer_size = oss_period_size * runtime->oss.periods;
1027         if (oss_buffer_size < 0) {
1028                 err = -EINVAL;
1029                 goto failure;
1030         }
1031
1032         runtime->oss.period_bytes = oss_period_size;
1033         runtime->oss.buffer_bytes = oss_buffer_size;
1034
1035         pdprintf("oss: period bytes = %i, buffer bytes = %i\n",
1036                  runtime->oss.period_bytes,
1037                  runtime->oss.buffer_bytes);
1038         pdprintf("slave: period_size = %i, buffer_size = %i\n",
1039                  params_period_size(sparams),
1040                  params_buffer_size(sparams));
1041
1042         runtime->oss.format = snd_pcm_oss_format_to(params_format(params));
1043         runtime->oss.channels = params_channels(params);
1044         runtime->oss.rate = params_rate(params);
1045
1046         runtime->oss.params = 0;
1047         runtime->oss.prepare = 1;
1048         vfree(runtime->oss.buffer);
1049         runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
1050         runtime->oss.buffer_used = 0;
1051         if (runtime->dma_area)
1052                 snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
1053
1054         runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
1055
1056         err = 0;
1057 failure:
1058         kfree(sw_params);
1059         kfree(params);
1060         kfree(sparams);
1061         mutex_unlock(&runtime->oss.params_lock);
1062         return err;
1063 }
1064
1065 static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream)
1066 {
1067         int idx, err;
1068         struct snd_pcm_substream *asubstream = NULL, *substream;
1069
1070         for (idx = 0; idx < 2; idx++) {
1071                 substream = pcm_oss_file->streams[idx];
1072                 if (substream == NULL)
1073                         continue;
1074                 if (asubstream == NULL)
1075                         asubstream = substream;
1076                 if (substream->runtime->oss.params) {
1077                         err = snd_pcm_oss_change_params(substream);
1078                         if (err < 0)
1079                                 return err;
1080                 }
1081         }
1082         if (!asubstream)
1083                 return -EIO;
1084         if (r_substream)
1085                 *r_substream = asubstream;
1086         return 0;
1087 }
1088
1089 static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
1090 {
1091         int err;
1092         struct snd_pcm_runtime *runtime = substream->runtime;
1093
1094         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
1095         if (err < 0) {
1096                 snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");
1097                 return err;
1098         }
1099         runtime->oss.prepare = 0;
1100         runtime->oss.prev_hw_ptr_interrupt = 0;
1101         runtime->oss.period_ptr = 0;
1102         runtime->oss.buffer_used = 0;
1103
1104         return 0;
1105 }
1106
1107 static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
1108 {
1109         struct snd_pcm_runtime *runtime;
1110         int err;
1111
1112         if (substream == NULL)
1113                 return 0;
1114         runtime = substream->runtime;
1115         if (runtime->oss.params) {
1116                 err = snd_pcm_oss_change_params(substream);
1117                 if (err < 0)
1118                         return err;
1119         }
1120         if (runtime->oss.prepare) {
1121                 err = snd_pcm_oss_prepare(substream);
1122                 if (err < 0)
1123                         return err;
1124         }
1125         return 0;
1126 }
1127
1128 static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay)
1129 {
1130         struct snd_pcm_runtime *runtime;
1131         snd_pcm_uframes_t frames;
1132         int err = 0;
1133
1134         while (1) {
1135                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay);
1136                 if (err < 0)
1137                         break;
1138                 runtime = substream->runtime;
1139                 if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size)
1140                         break;
1141                 /* in case of overrun, skip whole periods like OSS/Linux driver does */
1142                 /* until avail(delay) <= buffer_size */
1143                 frames = (*delay - runtime->buffer_size) + runtime->period_size - 1;
1144                 frames /= runtime->period_size;
1145                 frames *= runtime->period_size;
1146                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames);
1147                 if (err < 0)
1148                         break;
1149         }
1150         return err;
1151 }
1152
1153 snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
1154 {
1155         struct snd_pcm_runtime *runtime = substream->runtime;
1156         int ret;
1157         while (1) {
1158                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1159                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1160 #ifdef OSS_DEBUG
1161                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1162                                 printk(KERN_DEBUG "pcm_oss: write: "
1163                                        "recovering from XRUN\n");
1164                         else
1165                                 printk(KERN_DEBUG "pcm_oss: write: "
1166                                        "recovering from SUSPEND\n");
1167 #endif
1168                         ret = snd_pcm_oss_prepare(substream);
1169                         if (ret < 0)
1170                                 break;
1171                 }
1172                 if (in_kernel) {
1173                         mm_segment_t fs;
1174                         fs = snd_enter_user();
1175                         ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
1176                         snd_leave_user(fs);
1177                 } else {
1178                         ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
1179                 }
1180                 if (ret != -EPIPE && ret != -ESTRPIPE)
1181                         break;
1182                 /* test, if we can't store new data, because the stream */
1183                 /* has not been started */
1184                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
1185                         return -EAGAIN;
1186         }
1187         return ret;
1188 }
1189
1190 snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
1191 {
1192         struct snd_pcm_runtime *runtime = substream->runtime;
1193         snd_pcm_sframes_t delay;
1194         int ret;
1195         while (1) {
1196                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1197                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1198 #ifdef OSS_DEBUG
1199                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1200                                 printk(KERN_DEBUG "pcm_oss: read: "
1201                                        "recovering from XRUN\n");
1202                         else
1203                                 printk(KERN_DEBUG "pcm_oss: read: "
1204                                        "recovering from SUSPEND\n");
1205 #endif
1206                         ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1207                         if (ret < 0)
1208                                 break;
1209                 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
1210                         ret = snd_pcm_oss_prepare(substream);
1211                         if (ret < 0)
1212                                 break;
1213                 }
1214                 ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
1215                 if (ret < 0)
1216                         break;
1217                 if (in_kernel) {
1218                         mm_segment_t fs;
1219                         fs = snd_enter_user();
1220                         ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
1221                         snd_leave_user(fs);
1222                 } else {
1223                         ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
1224                 }
1225                 if (ret == -EPIPE) {
1226                         if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
1227                                 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1228                                 if (ret < 0)
1229                                         break;
1230                         }
1231                         continue;
1232                 }
1233                 if (ret != -ESTRPIPE)
1234                         break;
1235         }
1236         return ret;
1237 }
1238
1239 snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
1240 {
1241         struct snd_pcm_runtime *runtime = substream->runtime;
1242         int ret;
1243         while (1) {
1244                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1245                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1246 #ifdef OSS_DEBUG
1247                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1248                                 printk(KERN_DEBUG "pcm_oss: writev: "
1249                                        "recovering from XRUN\n");
1250                         else
1251                                 printk(KERN_DEBUG "pcm_oss: writev: "
1252                                        "recovering from SUSPEND\n");
1253 #endif
1254                         ret = snd_pcm_oss_prepare(substream);
1255                         if (ret < 0)
1256                                 break;
1257                 }
1258                 if (in_kernel) {
1259                         mm_segment_t fs;
1260                         fs = snd_enter_user();
1261                         ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
1262                         snd_leave_user(fs);
1263                 } else {
1264                         ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
1265                 }
1266                 if (ret != -EPIPE && ret != -ESTRPIPE)
1267                         break;
1268
1269                 /* test, if we can't store new data, because the stream */
1270                 /* has not been started */
1271                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
1272                         return -EAGAIN;
1273         }
1274         return ret;
1275 }
1276         
1277 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
1278 {
1279         struct snd_pcm_runtime *runtime = substream->runtime;
1280         int ret;
1281         while (1) {
1282                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1283                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1284 #ifdef OSS_DEBUG
1285                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1286                                 printk(KERN_DEBUG "pcm_oss: readv: "
1287                                        "recovering from XRUN\n");
1288                         else
1289                                 printk(KERN_DEBUG "pcm_oss: readv: "
1290                                        "recovering from SUSPEND\n");
1291 #endif
1292                         ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1293                         if (ret < 0)
1294                                 break;
1295                 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
1296                         ret = snd_pcm_oss_prepare(substream);
1297                         if (ret < 0)
1298                                 break;
1299                 }
1300                 if (in_kernel) {
1301                         mm_segment_t fs;
1302                         fs = snd_enter_user();
1303                         ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
1304                         snd_leave_user(fs);
1305                 } else {
1306                         ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
1307                 }
1308                 if (ret != -EPIPE && ret != -ESTRPIPE)
1309                         break;
1310         }
1311         return ret;
1312 }
1313
1314 static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
1315 {
1316         struct snd_pcm_runtime *runtime = substream->runtime;
1317         snd_pcm_sframes_t frames, frames1;
1318 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1319         if (runtime->oss.plugin_first) {
1320                 struct snd_pcm_plugin_channel *channels;
1321                 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
1322                 if (!in_kernel) {
1323                         if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
1324                                 return -EFAULT;
1325                         buf = runtime->oss.buffer;
1326                 }
1327                 frames = bytes / oss_frame_bytes;
1328                 frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels);
1329                 if (frames1 < 0)
1330                         return frames1;
1331                 frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1);
1332                 if (frames1 <= 0)
1333                         return frames1;
1334                 bytes = frames1 * oss_frame_bytes;
1335         } else
1336 #endif
1337         {
1338                 frames = bytes_to_frames(runtime, bytes);
1339                 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
1340                 if (frames1 <= 0)
1341                         return frames1;
1342                 bytes = frames_to_bytes(runtime, frames1);
1343         }
1344         return bytes;
1345 }
1346
1347 static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
1348 {
1349         size_t xfer = 0;
1350         ssize_t tmp;
1351         struct snd_pcm_runtime *runtime = substream->runtime;
1352
1353         if (atomic_read(&substream->mmap_count))
1354                 return -ENXIO;
1355
1356         if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1357                 return tmp;
1358         mutex_lock(&runtime->oss.params_lock);
1359         while (bytes > 0) {
1360                 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
1361                         tmp = bytes;
1362                         if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
1363                                 tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
1364                         if (tmp > 0) {
1365                                 if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
1366                                         tmp = -EFAULT;
1367                                         goto err;
1368                                 }
1369                         }
1370                         runtime->oss.buffer_used += tmp;
1371                         buf += tmp;
1372                         bytes -= tmp;
1373                         xfer += tmp;
1374                         if (substream->oss.setup.partialfrag ||
1375                             runtime->oss.buffer_used == runtime->oss.period_bytes) {
1376                                 tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 
1377                                                          runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
1378                                 if (tmp <= 0)
1379                                         goto err;
1380                                 runtime->oss.bytes += tmp;
1381                                 runtime->oss.period_ptr += tmp;
1382                                 runtime->oss.period_ptr %= runtime->oss.period_bytes;
1383                                 if (runtime->oss.period_ptr == 0 ||
1384                                     runtime->oss.period_ptr == runtime->oss.buffer_used)
1385                                         runtime->oss.buffer_used = 0;
1386                                 else if ((substream->f_flags & O_NONBLOCK) != 0) {
1387                                         tmp = -EAGAIN;
1388                                         goto err;
1389                                 }
1390                         }
1391                 } else {
1392                         tmp = snd_pcm_oss_write2(substream,
1393                                                  (const char __force *)buf,
1394                                                  runtime->oss.period_bytes, 0);
1395                         if (tmp <= 0)
1396                                 goto err;
1397                         runtime->oss.bytes += tmp;
1398                         buf += tmp;
1399                         bytes -= tmp;
1400                         xfer += tmp;
1401                         if ((substream->f_flags & O_NONBLOCK) != 0 &&
1402                             tmp != runtime->oss.period_bytes)
1403                                 break;
1404                 }
1405         }
1406         mutex_unlock(&runtime->oss.params_lock);
1407         return xfer;
1408
1409  err:
1410         mutex_unlock(&runtime->oss.params_lock);
1411         return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
1412 }
1413
1414 static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel)
1415 {
1416         struct snd_pcm_runtime *runtime = substream->runtime;
1417         snd_pcm_sframes_t frames, frames1;
1418 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1419         char __user *final_dst = (char __user *)buf;
1420         if (runtime->oss.plugin_first) {
1421                 struct snd_pcm_plugin_channel *channels;
1422                 size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
1423                 if (!in_kernel)
1424                         buf = runtime->oss.buffer;
1425                 frames = bytes / oss_frame_bytes;
1426                 frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels);
1427                 if (frames1 < 0)
1428                         return frames1;
1429                 frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1);
1430                 if (frames1 <= 0)
1431                         return frames1;
1432                 bytes = frames1 * oss_frame_bytes;
1433                 if (!in_kernel && copy_to_user(final_dst, buf, bytes))
1434                         return -EFAULT;
1435         } else
1436 #endif
1437         {
1438                 frames = bytes_to_frames(runtime, bytes);
1439                 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
1440                 if (frames1 <= 0)
1441                         return frames1;
1442                 bytes = frames_to_bytes(runtime, frames1);
1443         }
1444         return bytes;
1445 }
1446
1447 static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes)
1448 {
1449         size_t xfer = 0;
1450         ssize_t tmp;
1451         struct snd_pcm_runtime *runtime = substream->runtime;
1452
1453         if (atomic_read(&substream->mmap_count))
1454                 return -ENXIO;
1455
1456         if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1457                 return tmp;
1458         mutex_lock(&runtime->oss.params_lock);
1459         while (bytes > 0) {
1460                 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
1461                         if (runtime->oss.buffer_used == 0) {
1462                                 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
1463                                 if (tmp <= 0)
1464                                         goto err;
1465                                 runtime->oss.bytes += tmp;
1466                                 runtime->oss.period_ptr = tmp;
1467                                 runtime->oss.buffer_used = tmp;
1468                         }
1469                         tmp = bytes;
1470                         if ((size_t) tmp > runtime->oss.buffer_used)
1471                                 tmp = runtime->oss.buffer_used;
1472                         if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) {
1473                                 tmp = -EFAULT;
1474                                 goto err;
1475                         }
1476                         buf += tmp;
1477                         bytes -= tmp;
1478                         xfer += tmp;
1479                         runtime->oss.buffer_used -= tmp;
1480                 } else {
1481                         tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
1482                                                 runtime->oss.period_bytes, 0);
1483                         if (tmp <= 0)
1484                                 goto err;
1485                         runtime->oss.bytes += tmp;
1486                         buf += tmp;
1487                         bytes -= tmp;
1488                         xfer += tmp;
1489                 }
1490         }
1491         mutex_unlock(&runtime->oss.params_lock);
1492         return xfer;
1493
1494  err:
1495         mutex_unlock(&runtime->oss.params_lock);
1496         return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
1497 }
1498
1499 static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
1500 {
1501         struct snd_pcm_substream *substream;
1502
1503         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1504         if (substream != NULL) {
1505                 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1506                 substream->runtime->oss.prepare = 1;
1507         }
1508         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1509         if (substream != NULL) {
1510                 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1511                 substream->runtime->oss.prepare = 1;
1512         }
1513         return 0;
1514 }
1515
1516 static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
1517 {
1518         struct snd_pcm_substream *substream;
1519         int err;
1520
1521         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1522         if (substream != NULL) {
1523                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1524                         return err;
1525                 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
1526         }
1527         /* note: all errors from the start action are ignored */
1528         /* OSS apps do not know, how to handle them */
1529         return 0;
1530 }
1531
1532 static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
1533 {
1534         struct snd_pcm_runtime *runtime;
1535         ssize_t result = 0;
1536         long res;
1537         wait_queue_t wait;
1538
1539         runtime = substream->runtime;
1540         init_waitqueue_entry(&wait, current);
1541         add_wait_queue(&runtime->sleep, &wait);
1542 #ifdef OSS_DEBUG
1543         printk(KERN_DEBUG "sync1: size = %li\n", size);
1544 #endif
1545         while (1) {
1546                 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
1547                 if (result > 0) {
1548                         runtime->oss.buffer_used = 0;
1549                         result = 0;
1550                         break;
1551                 }
1552                 if (result != 0 && result != -EAGAIN)
1553                         break;
1554                 result = 0;
1555                 set_current_state(TASK_INTERRUPTIBLE);
1556                 snd_pcm_stream_lock_irq(substream);
1557                 res = runtime->status->state;
1558                 snd_pcm_stream_unlock_irq(substream);
1559                 if (res != SNDRV_PCM_STATE_RUNNING) {
1560                         set_current_state(TASK_RUNNING);
1561                         break;
1562                 }
1563                 res = schedule_timeout(10 * HZ);
1564                 if (signal_pending(current)) {
1565                         result = -ERESTARTSYS;
1566                         break;
1567                 }
1568                 if (res == 0) {
1569                         snd_printk(KERN_ERR "OSS sync error - DMA timeout\n");
1570                         result = -EIO;
1571                         break;
1572                 }
1573         }
1574         remove_wait_queue(&runtime->sleep, &wait);
1575         return result;
1576 }
1577
1578 static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
1579 {
1580         int err = 0;
1581         unsigned int saved_f_flags;
1582         struct snd_pcm_substream *substream;
1583         struct snd_pcm_runtime *runtime;
1584         snd_pcm_format_t format;
1585         unsigned long width;
1586         size_t size;
1587
1588         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1589         if (substream != NULL) {
1590                 runtime = substream->runtime;
1591                 if (atomic_read(&substream->mmap_count))
1592                         goto __direct;
1593                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1594                         return err;
1595                 format = snd_pcm_oss_format_from(runtime->oss.format);
1596                 width = snd_pcm_format_physical_width(format);
1597                 mutex_lock(&runtime->oss.params_lock);
1598                 if (runtime->oss.buffer_used > 0) {
1599 #ifdef OSS_DEBUG
1600                         printk(KERN_DEBUG "sync: buffer_used\n");
1601 #endif
1602                         size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
1603                         snd_pcm_format_set_silence(format,
1604                                                    runtime->oss.buffer + runtime->oss.buffer_used,
1605                                                    size);
1606                         err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
1607                         if (err < 0) {
1608                                 mutex_unlock(&runtime->oss.params_lock);
1609                                 return err;
1610                         }
1611                 } else if (runtime->oss.period_ptr > 0) {
1612 #ifdef OSS_DEBUG
1613                         printk(KERN_DEBUG "sync: period_ptr\n");
1614 #endif
1615                         size = runtime->oss.period_bytes - runtime->oss.period_ptr;
1616                         snd_pcm_format_set_silence(format,
1617                                                    runtime->oss.buffer,
1618                                                    size * 8 / width);
1619                         err = snd_pcm_oss_sync1(substream, size);
1620                         if (err < 0) {
1621                                 mutex_unlock(&runtime->oss.params_lock);
1622                                 return err;
1623                         }
1624                 }
1625                 /*
1626                  * The ALSA's period might be a bit large than OSS one.
1627                  * Fill the remain portion of ALSA period with zeros.
1628                  */
1629                 size = runtime->control->appl_ptr % runtime->period_size;
1630                 if (size > 0) {
1631                         size = runtime->period_size - size;
1632                         if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
1633                                 size = (runtime->frame_bits * size) / 8;
1634                                 while (size > 0) {
1635                                         mm_segment_t fs;
1636                                         size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
1637                                         size -= size1;
1638                                         size1 *= 8;
1639                                         size1 /= runtime->sample_bits;
1640                                         snd_pcm_format_set_silence(runtime->format,
1641                                                                    runtime->oss.buffer,
1642                                                                    size1);
1643                                         size1 /= runtime->channels; /* frames */
1644                                         fs = snd_enter_user();
1645                                         snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
1646                                         snd_leave_user(fs);
1647                                 }
1648                         } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
1649                                 void __user *buffers[runtime->channels];
1650                                 memset(buffers, 0, runtime->channels * sizeof(void *));
1651                                 snd_pcm_lib_writev(substream, buffers, size);
1652                         }
1653                 }
1654                 mutex_unlock(&runtime->oss.params_lock);
1655                 /*
1656                  * finish sync: drain the buffer
1657                  */
1658               __direct:
1659                 saved_f_flags = substream->f_flags;
1660                 substream->f_flags &= ~O_NONBLOCK;
1661                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1662                 substream->f_flags = saved_f_flags;
1663                 if (err < 0)
1664                         return err;
1665                 runtime->oss.prepare = 1;
1666         }
1667
1668         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1669         if (substream != NULL) {
1670                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1671                         return err;
1672                 runtime = substream->runtime;
1673                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1674                 if (err < 0)
1675                         return err;
1676                 runtime->oss.buffer_used = 0;
1677                 runtime->oss.prepare = 1;
1678         }
1679         return 0;
1680 }
1681
1682 static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate)
1683 {
1684         int idx;
1685
1686         for (idx = 1; idx >= 0; --idx) {
1687                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1688                 struct snd_pcm_runtime *runtime;
1689                 if (substream == NULL)
1690                         continue;
1691                 runtime = substream->runtime;
1692                 if (rate < 1000)
1693                         rate = 1000;
1694                 else if (rate > 192000)
1695                         rate = 192000;
1696                 if (runtime->oss.rate != rate) {
1697                         runtime->oss.params = 1;
1698                         runtime->oss.rate = rate;
1699                 }
1700         }
1701         return snd_pcm_oss_get_rate(pcm_oss_file);
1702 }
1703
1704 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file)
1705 {
1706         struct snd_pcm_substream *substream;
1707         int err;
1708         
1709         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1710                 return err;
1711         return substream->runtime->oss.rate;
1712 }
1713
1714 static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels)
1715 {
1716         int idx;
1717         if (channels < 1)
1718                 channels = 1;
1719         if (channels > 128)
1720                 return -EINVAL;
1721         for (idx = 1; idx >= 0; --idx) {
1722                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1723                 struct snd_pcm_runtime *runtime;
1724                 if (substream == NULL)
1725                         continue;
1726                 runtime = substream->runtime;
1727                 if (runtime->oss.channels != channels) {
1728                         runtime->oss.params = 1;
1729                         runtime->oss.channels = channels;
1730                 }
1731         }
1732         return snd_pcm_oss_get_channels(pcm_oss_file);
1733 }
1734
1735 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file)
1736 {
1737         struct snd_pcm_substream *substream;
1738         int err;
1739         
1740         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1741                 return err;
1742         return substream->runtime->oss.channels;
1743 }
1744
1745 static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file)
1746 {
1747         struct snd_pcm_substream *substream;
1748         int err;
1749         
1750         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1751                 return err;
1752         return substream->runtime->oss.period_bytes;
1753 }
1754
1755 static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
1756 {
1757         struct snd_pcm_substream *substream;
1758         int err;
1759         int direct;
1760         struct snd_pcm_hw_params *params;
1761         unsigned int formats = 0;
1762         struct snd_mask format_mask;
1763         int fmt;
1764
1765         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1766                 return err;
1767         if (atomic_read(&substream->mmap_count))
1768                 direct = 1;
1769         else
1770                 direct = substream->oss.setup.direct;
1771         if (!direct)
1772                 return AFMT_MU_LAW | AFMT_U8 |
1773                        AFMT_S16_LE | AFMT_S16_BE |
1774                        AFMT_S8 | AFMT_U16_LE |
1775                        AFMT_U16_BE |
1776                         AFMT_S32_LE | AFMT_S32_BE |
1777                         AFMT_S24_LE | AFMT_S24_BE |
1778                         AFMT_S24_PACKED;
1779         params = kmalloc(sizeof(*params), GFP_KERNEL);
1780         if (!params)
1781                 return -ENOMEM;
1782         _snd_pcm_hw_params_any(params);
1783         err = snd_pcm_hw_refine(substream, params);
1784         format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 
1785         kfree(params);
1786         if (err < 0)
1787                 return err;
1788         for (fmt = 0; fmt < 32; ++fmt) {
1789                 if (snd_mask_test(&format_mask, fmt)) {
1790                         int f = snd_pcm_oss_format_to(fmt);
1791                         if (f >= 0)
1792                                 formats |= f;
1793                 }
1794         }
1795         return formats;
1796 }
1797
1798 static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
1799 {
1800         int formats, idx;
1801         
1802         if (format != AFMT_QUERY) {
1803                 formats = snd_pcm_oss_get_formats(pcm_oss_file);
1804                 if (formats < 0)
1805                         return formats;
1806                 if (!(formats & format))
1807                         format = AFMT_U8;
1808                 for (idx = 1; idx >= 0; --idx) {
1809                         struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1810                         struct snd_pcm_runtime *runtime;
1811                         if (substream == NULL)
1812                                 continue;
1813                         runtime = substream->runtime;
1814                         if (runtime->oss.format != format) {
1815                                 runtime->oss.params = 1;
1816                                 runtime->oss.format = format;
1817                         }
1818                 }
1819         }
1820         return snd_pcm_oss_get_format(pcm_oss_file);
1821 }
1822
1823 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file)
1824 {
1825         struct snd_pcm_substream *substream;
1826         int err;
1827         
1828         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1829                 return err;
1830         return substream->runtime->oss.format;
1831 }
1832
1833 static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide)
1834 {
1835         struct snd_pcm_runtime *runtime;
1836
1837         if (substream == NULL)
1838                 return 0;
1839         runtime = substream->runtime;
1840         if (subdivide == 0) {
1841                 subdivide = runtime->oss.subdivision;
1842                 if (subdivide == 0)
1843                         subdivide = 1;
1844                 return subdivide;
1845         }
1846         if (runtime->oss.subdivision || runtime->oss.fragshift)
1847                 return -EINVAL;
1848         if (subdivide != 1 && subdivide != 2 && subdivide != 4 &&
1849             subdivide != 8 && subdivide != 16)
1850                 return -EINVAL;
1851         runtime->oss.subdivision = subdivide;
1852         runtime->oss.params = 1;
1853         return subdivide;
1854 }
1855
1856 static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide)
1857 {
1858         int err = -EINVAL, idx;
1859
1860         for (idx = 1; idx >= 0; --idx) {
1861                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1862                 if (substream == NULL)
1863                         continue;
1864                 if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
1865                         return err;
1866         }
1867         return err;
1868 }
1869
1870 static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val)
1871 {
1872         struct snd_pcm_runtime *runtime;
1873
1874         if (substream == NULL)
1875                 return 0;
1876         runtime = substream->runtime;
1877         if (runtime->oss.subdivision || runtime->oss.fragshift)
1878                 return -EINVAL;
1879         runtime->oss.fragshift = val & 0xffff;
1880         runtime->oss.maxfrags = (val >> 16) & 0xffff;
1881         if (runtime->oss.fragshift < 4)         /* < 16 */
1882                 runtime->oss.fragshift = 4;
1883         if (runtime->oss.maxfrags < 2)
1884                 runtime->oss.maxfrags = 2;
1885         runtime->oss.params = 1;
1886         return 0;
1887 }
1888
1889 static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val)
1890 {
1891         int err = -EINVAL, idx;
1892
1893         for (idx = 1; idx >= 0; --idx) {
1894                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1895                 if (substream == NULL)
1896                         continue;
1897                 if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
1898                         return err;
1899         }
1900         return err;
1901 }
1902
1903 static int snd_pcm_oss_nonblock(struct file * file)
1904 {
1905         spin_lock(&file->f_lock);
1906         file->f_flags |= O_NONBLOCK;
1907         spin_unlock(&file->f_lock);
1908         return 0;
1909 }
1910
1911 static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res)
1912 {
1913
1914         if (substream == NULL) {
1915                 res &= ~DSP_CAP_DUPLEX;
1916                 return res;
1917         }
1918 #ifdef DSP_CAP_MULTI
1919         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1920                 if (substream->pstr->substream_count > 1)
1921                         res |= DSP_CAP_MULTI;
1922 #endif
1923         /* DSP_CAP_REALTIME is set all times: */
1924         /* all ALSA drivers can return actual pointer in ring buffer */
1925 #if defined(DSP_CAP_REALTIME) && 0
1926         {
1927                 struct snd_pcm_runtime *runtime = substream->runtime;
1928                 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))
1929                         res &= ~DSP_CAP_REALTIME;
1930         }
1931 #endif
1932         return res;
1933 }
1934
1935 static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file)
1936 {
1937         int result, idx;
1938         
1939         result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME;
1940         for (idx = 0; idx < 2; idx++) {
1941                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1942                 result = snd_pcm_oss_get_caps1(substream, result);
1943         }
1944         result |= 0x0001;       /* revision - same as SB AWE 64 */
1945         return result;
1946 }
1947
1948 static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr)
1949 {
1950         struct snd_pcm_runtime *runtime = substream->runtime;
1951         snd_pcm_uframes_t appl_ptr;
1952         appl_ptr = hw_ptr + runtime->buffer_size;
1953         appl_ptr %= runtime->boundary;
1954         runtime->control->appl_ptr = appl_ptr;
1955 }
1956
1957 static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger)
1958 {
1959         struct snd_pcm_runtime *runtime;
1960         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
1961         int err, cmd;
1962
1963 #ifdef OSS_DEBUG
1964         printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
1965 #endif
1966         
1967         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1968         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1969
1970         if (psubstream) {
1971                 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
1972                         return err;
1973         }
1974         if (csubstream) {
1975                 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
1976                         return err;
1977         }
1978         if (psubstream) {
1979                 runtime = psubstream->runtime;
1980                 if (trigger & PCM_ENABLE_OUTPUT) {
1981                         if (runtime->oss.trigger)
1982                                 goto _skip1;
1983                         if (atomic_read(&psubstream->mmap_count))
1984                                 snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);
1985                         runtime->oss.trigger = 1;
1986                         runtime->start_threshold = 1;
1987                         cmd = SNDRV_PCM_IOCTL_START;
1988                 } else {
1989                         if (!runtime->oss.trigger)
1990                                 goto _skip1;
1991                         runtime->oss.trigger = 0;
1992                         runtime->start_threshold = runtime->boundary;
1993                         cmd = SNDRV_PCM_IOCTL_DROP;
1994                         runtime->oss.prepare = 1;
1995                 }
1996                 err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
1997                 if (err < 0)
1998                         return err;
1999         }
2000  _skip1:
2001         if (csubstream) {
2002                 runtime = csubstream->runtime;
2003                 if (trigger & PCM_ENABLE_INPUT) {
2004                         if (runtime->oss.trigger)
2005                                 goto _skip2;
2006                         runtime->oss.trigger = 1;
2007                         runtime->start_threshold = 1;
2008                         cmd = SNDRV_PCM_IOCTL_START;
2009                 } else {
2010                         if (!runtime->oss.trigger)
2011                                 goto _skip2;
2012                         runtime->oss.trigger = 0;
2013                         runtime->start_threshold = runtime->boundary;
2014                         cmd = SNDRV_PCM_IOCTL_DROP;
2015                         runtime->oss.prepare = 1;
2016                 }
2017                 err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
2018                 if (err < 0)
2019                         return err;
2020         }
2021  _skip2:
2022         return 0;
2023 }
2024
2025 static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
2026 {
2027         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2028         int result = 0;
2029
2030         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2031         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2032         if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
2033                 result |= PCM_ENABLE_OUTPUT;
2034         if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
2035                 result |= PCM_ENABLE_INPUT;
2036         return result;
2037 }
2038
2039 static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
2040 {
2041         struct snd_pcm_substream *substream;
2042         struct snd_pcm_runtime *runtime;
2043         snd_pcm_sframes_t delay;
2044         int err;
2045
2046         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2047         if (substream == NULL)
2048                 return -EINVAL;
2049         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2050                 return err;
2051         runtime = substream->runtime;
2052         if (runtime->oss.params || runtime->oss.prepare)
2053                 return 0;
2054         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
2055         if (err == -EPIPE)
2056                 delay = 0;      /* hack for broken OSS applications */
2057         else if (err < 0)
2058                 return err;
2059         return snd_pcm_oss_bytes(substream, delay);
2060 }
2061
2062 static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info)
2063 {       
2064         struct snd_pcm_substream *substream;
2065         struct snd_pcm_runtime *runtime;
2066         snd_pcm_sframes_t delay;
2067         int fixup;
2068         struct count_info info;
2069         int err;
2070
2071         if (_info == NULL)
2072                 return -EFAULT;
2073         substream = pcm_oss_file->streams[stream];
2074         if (substream == NULL)
2075                 return -EINVAL;
2076         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2077                 return err;
2078         runtime = substream->runtime;
2079         if (runtime->oss.params || runtime->oss.prepare) {
2080                 memset(&info, 0, sizeof(info));
2081                 if (copy_to_user(_info, &info, sizeof(info)))
2082                         return -EFAULT;
2083                 return 0;
2084         }
2085         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2086                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
2087                 if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) {
2088                         err = 0;
2089                         delay = 0;
2090                         fixup = 0;
2091                 } else {
2092                         fixup = runtime->oss.buffer_used;
2093                 }
2094         } else {
2095                 err = snd_pcm_oss_capture_position_fixup(substream, &delay);
2096                 fixup = -runtime->oss.buffer_used;
2097         }
2098         if (err < 0)
2099                 return err;
2100         info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
2101         if (atomic_read(&substream->mmap_count)) {
2102                 snd_pcm_sframes_t n;
2103                 n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;
2104                 if (n < 0)
2105                         n += runtime->boundary;
2106                 info.blocks = n / runtime->period_size;
2107                 runtime->oss.prev_hw_ptr_interrupt = delay;
2108                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2109                         snd_pcm_oss_simulate_fill(substream, delay);
2110                 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
2111         } else {
2112                 delay = snd_pcm_oss_bytes(substream, delay);
2113                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2114                         if (substream->oss.setup.buggyptr)
2115                                 info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
2116                         else
2117                                 info.blocks = (delay + fixup) / runtime->oss.period_bytes;
2118                         info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
2119                 } else {
2120                         delay += fixup;
2121                         info.blocks = delay / runtime->oss.period_bytes;
2122                         info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
2123                 }
2124         }
2125         if (copy_to_user(_info, &info, sizeof(info)))
2126                 return -EFAULT;
2127         return 0;
2128 }
2129
2130 static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info)
2131 {
2132         struct snd_pcm_substream *substream;
2133         struct snd_pcm_runtime *runtime;
2134         snd_pcm_sframes_t avail;
2135         int fixup;
2136         struct audio_buf_info info;
2137         int err;
2138
2139         if (_info == NULL)
2140                 return -EFAULT;
2141         substream = pcm_oss_file->streams[stream];
2142         if (substream == NULL)
2143                 return -EINVAL;
2144         runtime = substream->runtime;
2145
2146         if (runtime->oss.params &&
2147             (err = snd_pcm_oss_change_params(substream)) < 0)
2148                 return err;
2149
2150         info.fragsize = runtime->oss.period_bytes;
2151         info.fragstotal = runtime->periods;
2152         if (runtime->oss.prepare) {
2153                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2154                         info.bytes = runtime->oss.period_bytes * runtime->oss.periods;
2155                         info.fragments = runtime->oss.periods;
2156                 } else {
2157                         info.bytes = 0;
2158                         info.fragments = 0;
2159                 }
2160         } else {
2161                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2162                         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
2163                         if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) {
2164                                 avail = runtime->buffer_size;
2165                                 err = 0;
2166                                 fixup = 0;
2167                         } else {
2168                                 avail = runtime->buffer_size - avail;
2169                                 fixup = -runtime->oss.buffer_used;
2170                         }
2171                 } else {
2172                         err = snd_pcm_oss_capture_position_fixup(substream, &avail);
2173                         fixup = runtime->oss.buffer_used;
2174                 }
2175                 if (err < 0)
2176                         return err;
2177                 info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup;
2178                 info.fragments = info.bytes / runtime->oss.period_bytes;
2179         }
2180
2181 #ifdef OSS_DEBUG
2182         printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
2183                "fragstotal = %i, fragsize = %i\n",
2184                info.bytes, info.fragments, info.fragstotal, info.fragsize);
2185 #endif
2186         if (copy_to_user(_info, &info, sizeof(info)))
2187                 return -EFAULT;
2188         return 0;
2189 }
2190
2191 static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info)
2192 {
2193         // it won't be probably implemented
2194         // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n");
2195         return -EINVAL;
2196 }
2197
2198 static const char *strip_task_path(const char *path)
2199 {
2200         const char *ptr, *ptrl = NULL;
2201         for (ptr = path; *ptr; ptr++) {
2202                 if (*ptr == '/')
2203                         ptrl = ptr + 1;
2204         }
2205         return ptrl;
2206 }
2207
2208 static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
2209                                       const char *task_name,
2210                                       struct snd_pcm_oss_setup *rsetup)
2211 {
2212         struct snd_pcm_oss_setup *setup;
2213
2214         mutex_lock(&pcm->streams[stream].oss.setup_mutex);
2215         do {
2216                 for (setup = pcm->streams[stream].oss.setup_list; setup;
2217                      setup = setup->next) {
2218                         if (!strcmp(setup->task_name, task_name))
2219                                 goto out;
2220                 }
2221         } while ((task_name = strip_task_path(task_name)) != NULL);
2222  out:
2223         if (setup)
2224                 *rsetup = *setup;
2225         mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
2226 }
2227
2228 static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
2229 {
2230         struct snd_pcm_runtime *runtime;
2231         runtime = substream->runtime;
2232         vfree(runtime->oss.buffer);
2233         runtime->oss.buffer = NULL;
2234 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2235         snd_pcm_oss_plugin_clear(substream);
2236 #endif
2237         substream->oss.oss = 0;
2238 }
2239
2240 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
2241                                        struct snd_pcm_oss_setup *setup,
2242                                        int minor)
2243 {
2244         struct snd_pcm_runtime *runtime;
2245
2246         substream->oss.oss = 1;
2247         substream->oss.setup = *setup;
2248         if (setup->nonblock)
2249                 substream->f_flags |= O_NONBLOCK;
2250         else if (setup->block)
2251                 substream->f_flags &= ~O_NONBLOCK;
2252         runtime = substream->runtime;
2253         runtime->oss.params = 1;
2254         runtime->oss.trigger = 1;
2255         runtime->oss.rate = 8000;
2256         mutex_init(&runtime->oss.params_lock);
2257         switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
2258         case SNDRV_MINOR_OSS_PCM_8:
2259                 runtime->oss.format = AFMT_U8;
2260                 break;
2261         case SNDRV_MINOR_OSS_PCM_16:
2262                 runtime->oss.format = AFMT_S16_LE;
2263                 break;
2264         default:
2265                 runtime->oss.format = AFMT_MU_LAW;
2266         }
2267         runtime->oss.channels = 1;
2268         runtime->oss.fragshift = 0;
2269         runtime->oss.maxfrags = 0;
2270         runtime->oss.subdivision = 0;
2271         substream->pcm_release = snd_pcm_oss_release_substream;
2272 }
2273
2274 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
2275 {
2276         int cidx;
2277         if (!pcm_oss_file)
2278                 return 0;
2279         for (cidx = 0; cidx < 2; ++cidx) {
2280                 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
2281                 if (substream)
2282                         snd_pcm_release_substream(substream);
2283         }
2284         kfree(pcm_oss_file);
2285         return 0;
2286 }
2287
2288 static int snd_pcm_oss_open_file(struct file *file,
2289                                  struct snd_pcm *pcm,
2290                                  struct snd_pcm_oss_file **rpcm_oss_file,
2291                                  int minor,
2292                                  struct snd_pcm_oss_setup *setup)
2293 {
2294         int idx, err;
2295         struct snd_pcm_oss_file *pcm_oss_file;
2296         struct snd_pcm_substream *substream;
2297         fmode_t f_mode = file->f_mode;
2298
2299         if (rpcm_oss_file)
2300                 *rpcm_oss_file = NULL;
2301
2302         pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
2303         if (pcm_oss_file == NULL)
2304                 return -ENOMEM;
2305
2306         if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
2307             (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
2308                 f_mode = FMODE_WRITE;
2309
2310         file->f_flags &= ~O_APPEND;
2311         for (idx = 0; idx < 2; idx++) {
2312                 if (setup[idx].disable)
2313                         continue;
2314                 if (! pcm->streams[idx].substream_count)
2315                         continue; /* no matching substream */
2316                 if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
2317                         if (! (f_mode & FMODE_WRITE))
2318                                 continue;
2319                 } else {
2320                         if (! (f_mode & FMODE_READ))
2321                                 continue;
2322                 }
2323                 err = snd_pcm_open_substream(pcm, idx, file, &substream);
2324                 if (err < 0) {
2325                         snd_pcm_oss_release_file(pcm_oss_file);
2326                         return err;
2327                 }
2328
2329                 pcm_oss_file->streams[idx] = substream;
2330                 substream->file = pcm_oss_file;
2331                 snd_pcm_oss_init_substream(substream, &setup[idx], minor);
2332         }
2333         
2334         if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
2335                 snd_pcm_oss_release_file(pcm_oss_file);
2336                 return -EINVAL;
2337         }
2338
2339         file->private_data = pcm_oss_file;
2340         if (rpcm_oss_file)
2341                 *rpcm_oss_file = pcm_oss_file;
2342         return 0;
2343 }
2344
2345
2346 static int snd_task_name(struct task_struct *task, char *name, size_t size)
2347 {
2348         unsigned int idx;
2349
2350         if (snd_BUG_ON(!task || !name || size < 2))
2351                 return -EINVAL;
2352         for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++)
2353                 name[idx] = task->comm[idx];
2354         name[idx] = '\0';
2355         return 0;
2356 }
2357
2358 static int snd_pcm_oss_open(struct inode *inode, struct file *file)
2359 {
2360         int err;
2361         char task_name[32];
2362         struct snd_pcm *pcm;
2363         struct snd_pcm_oss_file *pcm_oss_file;
2364         struct snd_pcm_oss_setup setup[2];
2365         int nonblock;
2366         wait_queue_t wait;
2367
2368         pcm = snd_lookup_oss_minor_data(iminor(inode),
2369                                         SNDRV_OSS_DEVICE_TYPE_PCM);
2370         if (pcm == NULL) {
2371                 err = -ENODEV;
2372                 goto __error1;
2373         }
2374         err = snd_card_file_add(pcm->card, file);
2375         if (err < 0)
2376                 goto __error1;
2377         if (!try_module_get(pcm->card->module)) {
2378                 err = -EFAULT;
2379                 goto __error2;
2380         }
2381         if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {
2382                 err = -EFAULT;
2383                 goto __error;
2384         }
2385         memset(setup, 0, sizeof(setup));
2386         if (file->f_mode & FMODE_WRITE)
2387                 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
2388                                            task_name, &setup[0]);
2389         if (file->f_mode & FMODE_READ)
2390                 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
2391                                            task_name, &setup[1]);
2392
2393         nonblock = !!(file->f_flags & O_NONBLOCK);
2394         if (!nonblock)
2395                 nonblock = nonblock_open;
2396
2397         init_waitqueue_entry(&wait, current);
2398         add_wait_queue(&pcm->open_wait, &wait);
2399         mutex_lock(&pcm->open_mutex);
2400         while (1) {
2401                 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
2402                                             iminor(inode), setup);
2403                 if (err >= 0)
2404                         break;
2405                 if (err == -EAGAIN) {
2406                         if (nonblock) {
2407                                 err = -EBUSY;
2408                                 break;
2409                         }
2410                 } else
2411                         break;
2412                 set_current_state(TASK_INTERRUPTIBLE);
2413                 mutex_unlock(&pcm->open_mutex);
2414                 schedule();
2415                 mutex_lock(&pcm->open_mutex);
2416                 if (signal_pending(current)) {
2417                         err = -ERESTARTSYS;
2418                         break;
2419                 }
2420         }
2421         remove_wait_queue(&pcm->open_wait, &wait);
2422         mutex_unlock(&pcm->open_mutex);
2423         if (err < 0)
2424                 goto __error;
2425         return err;
2426
2427       __error:
2428         module_put(pcm->card->module);
2429       __error2:
2430         snd_card_file_remove(pcm->card, file);
2431       __error1:
2432         return err;
2433 }
2434
2435 static int snd_pcm_oss_release(struct inode *inode, struct file *file)
2436 {
2437         struct snd_pcm *pcm;
2438         struct snd_pcm_substream *substream;
2439         struct snd_pcm_oss_file *pcm_oss_file;
2440
2441         pcm_oss_file = file->private_data;
2442         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2443         if (substream == NULL)
2444                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2445         if (snd_BUG_ON(!substream))
2446                 return -ENXIO;
2447         pcm = substream->pcm;
2448         if (!pcm->card->shutdown)
2449                 snd_pcm_oss_sync(pcm_oss_file);
2450         mutex_lock(&pcm->open_mutex);
2451         snd_pcm_oss_release_file(pcm_oss_file);
2452         mutex_unlock(&pcm->open_mutex);
2453         wake_up(&pcm->open_wait);
2454         module_put(pcm->card->module);
2455         snd_card_file_remove(pcm->card, file);
2456         return 0;
2457 }
2458
2459 static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2460 {
2461         struct snd_pcm_oss_file *pcm_oss_file;
2462         int __user *p = (int __user *)arg;
2463         int res;
2464
2465         pcm_oss_file = file->private_data;
2466         if (cmd == OSS_GETVERSION)
2467                 return put_user(SNDRV_OSS_VERSION, p);
2468         if (cmd == OSS_ALSAEMULVER)
2469                 return put_user(1, p);
2470 #if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
2471         if (((cmd >> 8) & 0xff) == 'M') {       /* mixer ioctl - for OSS compatibility */
2472                 struct snd_pcm_substream *substream;
2473                 int idx;
2474                 for (idx = 0; idx < 2; ++idx) {
2475                         substream = pcm_oss_file->streams[idx];
2476                         if (substream != NULL)
2477                                 break;
2478                 }
2479                 if (snd_BUG_ON(idx >= 2))
2480                         return -ENXIO;
2481                 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);
2482         }
2483 #endif
2484         if (((cmd >> 8) & 0xff) != 'P')
2485                 return -EINVAL;
2486 #ifdef OSS_DEBUG
2487         printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
2488 #endif
2489         switch (cmd) {
2490         case SNDCTL_DSP_RESET:
2491                 return snd_pcm_oss_reset(pcm_oss_file);
2492         case SNDCTL_DSP_SYNC:
2493                 return snd_pcm_oss_sync(pcm_oss_file);
2494         case SNDCTL_DSP_SPEED:
2495                 if (get_user(res, p))
2496                         return -EFAULT;
2497                 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)
2498                         return res;
2499                 return put_user(res, p);
2500         case SOUND_PCM_READ_RATE:
2501                 res = snd_pcm_oss_get_rate(pcm_oss_file);
2502                 if (res < 0)
2503                         return res;
2504                 return put_user(res, p);
2505         case SNDCTL_DSP_STEREO:
2506                 if (get_user(res, p))
2507                         return -EFAULT;
2508                 res = res > 0 ? 2 : 1;
2509                 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)
2510                         return res;
2511                 return put_user(--res, p);
2512         case SNDCTL_DSP_GETBLKSIZE:
2513                 res = snd_pcm_oss_get_block_size(pcm_oss_file);
2514                 if (res < 0)
2515                         return res;
2516                 return put_user(res, p);
2517         case SNDCTL_DSP_SETFMT:
2518                 if (get_user(res, p))
2519                         return -EFAULT;
2520                 res = snd_pcm_oss_set_format(pcm_oss_file, res);
2521                 if (res < 0)
2522                         return res;
2523                 return put_user(res, p);
2524         case SOUND_PCM_READ_BITS:
2525                 res = snd_pcm_oss_get_format(pcm_oss_file);
2526                 if (res < 0)
2527                         return res;
2528                 return put_user(res, p);
2529         case SNDCTL_DSP_CHANNELS:
2530                 if (get_user(res, p))
2531                         return -EFAULT;
2532                 res = snd_pcm_oss_set_channels(pcm_oss_file, res);
2533                 if (res < 0)
2534                         return res;
2535                 return put_user(res, p);
2536         case SOUND_PCM_READ_CHANNELS:
2537                 res = snd_pcm_oss_get_channels(pcm_oss_file);
2538                 if (res < 0)
2539                         return res;
2540                 return put_user(res, p);
2541         case SOUND_PCM_WRITE_FILTER:
2542         case SOUND_PCM_READ_FILTER:
2543                 return -EIO;
2544         case SNDCTL_DSP_POST:
2545                 return snd_pcm_oss_post(pcm_oss_file);
2546         case SNDCTL_DSP_SUBDIVIDE:
2547                 if (get_user(res, p))
2548                         return -EFAULT;
2549                 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);
2550                 if (res < 0)
2551                         return res;
2552                 return put_user(res, p);
2553         case SNDCTL_DSP_SETFRAGMENT:
2554                 if (get_user(res, p))
2555                         return -EFAULT;
2556                 return snd_pcm_oss_set_fragment(pcm_oss_file, res);
2557         case SNDCTL_DSP_GETFMTS:
2558                 res = snd_pcm_oss_get_formats(pcm_oss_file);
2559                 if (res < 0)
2560                         return res;
2561                 return put_user(res, p);
2562         case SNDCTL_DSP_GETOSPACE:
2563         case SNDCTL_DSP_GETISPACE:
2564                 return snd_pcm_oss_get_space(pcm_oss_file,
2565                         cmd == SNDCTL_DSP_GETISPACE ?
2566                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2567                         (struct audio_buf_info __user *) arg);
2568         case SNDCTL_DSP_NONBLOCK:
2569                 return snd_pcm_oss_nonblock(file);
2570         case SNDCTL_DSP_GETCAPS:
2571                 res = snd_pcm_oss_get_caps(pcm_oss_file);
2572                 if (res < 0)
2573                         return res;
2574                 return put_user(res, p);
2575         case SNDCTL_DSP_GETTRIGGER:
2576                 res = snd_pcm_oss_get_trigger(pcm_oss_file);
2577                 if (res < 0)
2578                         return res;
2579                 return put_user(res, p);
2580         case SNDCTL_DSP_SETTRIGGER:
2581                 if (get_user(res, p))
2582                         return -EFAULT;
2583                 return snd_pcm_oss_set_trigger(pcm_oss_file, res);
2584         case SNDCTL_DSP_GETIPTR:
2585         case SNDCTL_DSP_GETOPTR:
2586                 return snd_pcm_oss_get_ptr(pcm_oss_file,
2587                         cmd == SNDCTL_DSP_GETIPTR ?
2588                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2589                         (struct count_info __user *) arg);
2590         case SNDCTL_DSP_MAPINBUF:
2591         case SNDCTL_DSP_MAPOUTBUF:
2592                 return snd_pcm_oss_get_mapbuf(pcm_oss_file,
2593                         cmd == SNDCTL_DSP_MAPINBUF ?
2594                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2595                         (struct buffmem_desc __user *) arg);
2596         case SNDCTL_DSP_SETSYNCRO:
2597                 /* stop DMA now.. */
2598                 return 0;
2599         case SNDCTL_DSP_SETDUPLEX:
2600                 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX)
2601                         return 0;
2602                 return -EIO;
2603         case SNDCTL_DSP_GETODELAY:
2604                 res = snd_pcm_oss_get_odelay(pcm_oss_file);
2605                 if (res < 0) {
2606                         /* it's for sure, some broken apps don't check for error codes */
2607                         put_user(0, p);
2608                         return res;
2609                 }
2610                 return put_user(res, p);
2611         case SNDCTL_DSP_PROFILE:
2612                 return 0;       /* silently ignore */
2613         default:
2614                 snd_printd("pcm_oss: unknown command = 0x%x\n", cmd);
2615         }
2616         return -EINVAL;
2617 }
2618
2619 #ifdef CONFIG_COMPAT
2620 /* all compatible */
2621 #define snd_pcm_oss_ioctl_compat        snd_pcm_oss_ioctl
2622 #else
2623 #define snd_pcm_oss_ioctl_compat        NULL
2624 #endif
2625
2626 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
2627 {
2628         struct snd_pcm_oss_file *pcm_oss_file;
2629         struct snd_pcm_substream *substream;
2630
2631         pcm_oss_file = file->private_data;
2632         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2633         if (substream == NULL)
2634                 return -ENXIO;
2635         substream->f_flags = file->f_flags & O_NONBLOCK;
2636 #ifndef OSS_DEBUG
2637         return snd_pcm_oss_read1(substream, buf, count);
2638 #else
2639         {
2640                 ssize_t res = snd_pcm_oss_read1(substream, buf, count);
2641                 printk(KERN_DEBUG "pcm_oss: read %li bytes "
2642                        "(returned %li bytes)\n", (long)count, (long)res);
2643                 return res;
2644         }
2645 #endif
2646 }
2647
2648 static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
2649 {
2650         struct snd_pcm_oss_file *pcm_oss_file;
2651         struct snd_pcm_substream *substream;
2652         long result;
2653
2654         pcm_oss_file = file->private_data;
2655         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2656         if (substream == NULL)
2657                 return -ENXIO;
2658         substream->f_flags = file->f_flags & O_NONBLOCK;
2659         result = snd_pcm_oss_write1(substream, buf, count);
2660 #ifdef OSS_DEBUG
2661         printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
2662                (long)count, (long)result);
2663 #endif
2664         return result;
2665 }
2666
2667 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
2668 {
2669         struct snd_pcm_runtime *runtime = substream->runtime;
2670         if (atomic_read(&substream->mmap_count))
2671                 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
2672         else
2673                 return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
2674 }
2675
2676 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
2677 {
2678         struct snd_pcm_runtime *runtime = substream->runtime;
2679         if (atomic_read(&substream->mmap_count))
2680                 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
2681         else
2682                 return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
2683 }
2684
2685 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
2686 {
2687         struct snd_pcm_oss_file *pcm_oss_file;
2688         unsigned int mask;
2689         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2690         
2691         pcm_oss_file = file->private_data;
2692
2693         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2694         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2695
2696         mask = 0;
2697         if (psubstream != NULL) {
2698                 struct snd_pcm_runtime *runtime = psubstream->runtime;
2699                 poll_wait(file, &runtime->sleep, wait);
2700                 snd_pcm_stream_lock_irq(psubstream);
2701                 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
2702                     (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
2703                      snd_pcm_oss_playback_ready(psubstream)))
2704                         mask |= POLLOUT | POLLWRNORM;
2705                 snd_pcm_stream_unlock_irq(psubstream);
2706         }
2707         if (csubstream != NULL) {
2708                 struct snd_pcm_runtime *runtime = csubstream->runtime;
2709                 snd_pcm_state_t ostate;
2710                 poll_wait(file, &runtime->sleep, wait);
2711                 snd_pcm_stream_lock_irq(csubstream);
2712                 if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||
2713                     snd_pcm_oss_capture_ready(csubstream))
2714                         mask |= POLLIN | POLLRDNORM;
2715                 snd_pcm_stream_unlock_irq(csubstream);
2716                 if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
2717                         struct snd_pcm_oss_file ofile;
2718                         memset(&ofile, 0, sizeof(ofile));
2719                         ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2720                         runtime->oss.trigger = 0;
2721                         snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
2722                 }
2723         }
2724
2725         return mask;
2726 }
2727
2728 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
2729 {
2730         struct snd_pcm_oss_file *pcm_oss_file;
2731         struct snd_pcm_substream *substream = NULL;
2732         struct snd_pcm_runtime *runtime;
2733         int err;
2734
2735 #ifdef OSS_DEBUG
2736         printk(KERN_DEBUG "pcm_oss: mmap begin\n");
2737 #endif
2738         pcm_oss_file = file->private_data;
2739         switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
2740         case VM_READ | VM_WRITE:
2741                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2742                 if (substream)
2743                         break;
2744                 /* Fall through */
2745         case VM_READ:
2746                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2747                 break;
2748         case VM_WRITE:
2749                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2750                 break;
2751         default:
2752                 return -EINVAL;
2753         }
2754         /* set VM_READ access as well to fix memset() routines that do
2755            reads before writes (to improve performance) */
2756         area->vm_flags |= VM_READ;
2757         if (substream == NULL)
2758                 return -ENXIO;
2759         runtime = substream->runtime;
2760         if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID))
2761                 return -EIO;
2762         if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED)
2763                 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
2764         else
2765                 return -EIO;
2766         
2767         if (runtime->oss.params) {
2768                 if ((err = snd_pcm_oss_change_params(substream)) < 0)
2769                         return err;
2770         }
2771 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2772         if (runtime->oss.plugin_first != NULL)
2773                 return -EIO;
2774 #endif
2775
2776         if (area->vm_pgoff != 0)
2777                 return -EINVAL;
2778
2779         err = snd_pcm_mmap_data(substream, file, area);
2780         if (err < 0)
2781                 return err;
2782         runtime->oss.mmap_bytes = area->vm_end - area->vm_start;
2783         runtime->silence_threshold = 0;
2784         runtime->silence_size = 0;
2785 #ifdef OSS_DEBUG
2786         printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
2787                runtime->oss.mmap_bytes);
2788 #endif
2789         /* In mmap mode we never stop */
2790         runtime->stop_threshold = runtime->boundary;
2791
2792         return 0;
2793 }
2794
2795 #ifdef CONFIG_SND_VERBOSE_PROCFS
2796 /*
2797  *  /proc interface
2798  */
2799
2800 static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
2801                                   struct snd_info_buffer *buffer)
2802 {
2803         struct snd_pcm_str *pstr = entry->private_data;
2804         struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
2805         mutex_lock(&pstr->oss.setup_mutex);
2806         while (setup) {
2807                 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
2808                             setup->task_name,
2809                             setup->periods,
2810                             setup->period_size,
2811                             setup->disable ? " disable" : "",
2812                             setup->direct ? " direct" : "",
2813                             setup->block ? " block" : "",
2814                             setup->nonblock ? " non-block" : "",
2815                             setup->partialfrag ? " partial-frag" : "",
2816                             setup->nosilence ? " no-silence" : "");
2817                 setup = setup->next;
2818         }
2819         mutex_unlock(&pstr->oss.setup_mutex);
2820 }
2821
2822 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
2823 {
2824         struct snd_pcm_oss_setup *setup, *setupn;
2825
2826         for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
2827              setup; setup = setupn) {
2828                 setupn = setup->next;
2829                 kfree(setup->task_name);
2830                 kfree(setup);
2831         }
2832         pstr->oss.setup_list = NULL;
2833 }
2834
2835 static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
2836                                    struct snd_info_buffer *buffer)
2837 {
2838         struct snd_pcm_str *pstr = entry->private_data;
2839         char line[128], str[32], task_name[32], *ptr;
2840         int idx1;
2841         struct snd_pcm_oss_setup *setup, *setup1, template;
2842
2843         while (!snd_info_get_line(buffer, line, sizeof(line))) {
2844                 mutex_lock(&pstr->oss.setup_mutex);
2845                 memset(&template, 0, sizeof(template));
2846                 ptr = snd_info_get_str(task_name, line, sizeof(task_name));
2847                 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
2848                         snd_pcm_oss_proc_free_setup_list(pstr);
2849                         mutex_unlock(&pstr->oss.setup_mutex);
2850                         continue;
2851                 }
2852                 for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
2853                         if (!strcmp(setup->task_name, task_name)) {
2854                                 template = *setup;
2855                                 break;
2856                         }
2857                 }
2858                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2859                 template.periods = simple_strtoul(str, NULL, 10);
2860                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2861                 template.period_size = simple_strtoul(str, NULL, 10);
2862                 for (idx1 = 31; idx1 >= 0; idx1--)
2863                         if (template.period_size & (1 << idx1))
2864                                 break;
2865                 for (idx1--; idx1 >= 0; idx1--)
2866                         template.period_size &= ~(1 << idx1);
2867                 do {
2868                         ptr = snd_info_get_str(str, ptr, sizeof(str));
2869                         if (!strcmp(str, "disable")) {
2870                                 template.disable = 1;
2871                         } else if (!strcmp(str, "direct")) {
2872                                 template.direct = 1;
2873                         } else if (!strcmp(str, "block")) {
2874                                 template.block = 1;
2875                         } else if (!strcmp(str, "non-block")) {
2876                                 template.nonblock = 1;
2877                         } else if (!strcmp(str, "partial-frag")) {
2878                                 template.partialfrag = 1;
2879                         } else if (!strcmp(str, "no-silence")) {
2880                                 template.nosilence = 1;
2881                         } else if (!strcmp(str, "buggy-ptr")) {
2882                                 template.buggyptr = 1;
2883                         }
2884                 } while (*str);
2885                 if (setup == NULL) {
2886                         setup = kmalloc(sizeof(*setup), GFP_KERNEL);
2887                         if (! setup) {
2888                                 buffer->error = -ENOMEM;
2889                                 mutex_unlock(&pstr->oss.setup_mutex);
2890                                 return;
2891                         }
2892                         if (pstr->oss.setup_list == NULL)
2893                                 pstr->oss.setup_list = setup;
2894                         else {
2895                                 for (setup1 = pstr->oss.setup_list;
2896                                      setup1->next; setup1 = setup1->next);
2897                                 setup1->next = setup;
2898                         }
2899                         template.task_name = kstrdup(task_name, GFP_KERNEL);
2900                         if (! template.task_name) {
2901                                 kfree(setup);
2902                                 buffer->error = -ENOMEM;
2903                                 mutex_unlock(&pstr->oss.setup_mutex);
2904                                 return;
2905                         }
2906                 }
2907                 *setup = template;
2908                 mutex_unlock(&pstr->oss.setup_mutex);
2909         }
2910 }
2911
2912 static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
2913 {
2914         int stream;
2915         for (stream = 0; stream < 2; ++stream) {
2916                 struct snd_info_entry *entry;
2917                 struct snd_pcm_str *pstr = &pcm->streams[stream];
2918                 if (pstr->substream_count == 0)
2919                         continue;
2920                 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
2921                         entry->content = SNDRV_INFO_CONTENT_TEXT;
2922                         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
2923                         entry->c.text.read = snd_pcm_oss_proc_read;
2924                         entry->c.text.write = snd_pcm_oss_proc_write;
2925                         entry->private_data = pstr;
2926                         if (snd_info_register(entry) < 0) {
2927                                 snd_info_free_entry(entry);
2928                                 entry = NULL;
2929                         }
2930                 }
2931                 pstr->oss.proc_entry = entry;
2932         }
2933 }
2934
2935 static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
2936 {
2937         int stream;
2938         for (stream = 0; stream < 2; ++stream) {
2939                 struct snd_pcm_str *pstr = &pcm->streams[stream];
2940                 snd_info_free_entry(pstr->oss.proc_entry);
2941                 pstr->oss.proc_entry = NULL;
2942                 snd_pcm_oss_proc_free_setup_list(pstr);
2943         }
2944 }
2945 #else /* !CONFIG_SND_VERBOSE_PROCFS */
2946 #define snd_pcm_oss_proc_init(pcm)
2947 #define snd_pcm_oss_proc_done(pcm)
2948 #endif /* CONFIG_SND_VERBOSE_PROCFS */
2949
2950 /*
2951  *  ENTRY functions
2952  */
2953
2954 static const struct file_operations snd_pcm_oss_f_reg =
2955 {
2956         .owner =        THIS_MODULE,
2957         .read =         snd_pcm_oss_read,
2958         .write =        snd_pcm_oss_write,
2959         .open =         snd_pcm_oss_open,
2960         .release =      snd_pcm_oss_release,
2961         .poll =         snd_pcm_oss_poll,
2962         .unlocked_ioctl =       snd_pcm_oss_ioctl,
2963         .compat_ioctl = snd_pcm_oss_ioctl_compat,
2964         .mmap =         snd_pcm_oss_mmap,
2965 };
2966
2967 static void register_oss_dsp(struct snd_pcm *pcm, int index)
2968 {
2969         char name[128];
2970         sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
2971         if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2972                                     pcm->card, index, &snd_pcm_oss_f_reg,
2973                                     pcm, name) < 0) {
2974                 snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
2975                            pcm->card->number, pcm->device);
2976         }
2977 }
2978
2979 static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
2980 {
2981         pcm->oss.reg = 0;
2982         if (dsp_map[pcm->card->number] == (int)pcm->device) {
2983                 char name[128];
2984                 int duplex;
2985                 register_oss_dsp(pcm, 0);
2986                 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 
2987                               pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 
2988                               !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
2989                 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
2990 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
2991                 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
2992                                       pcm->card->number,
2993                                       name);
2994 #endif
2995                 pcm->oss.reg++;
2996                 pcm->oss.reg_mask |= 1;
2997         }
2998         if (adsp_map[pcm->card->number] == (int)pcm->device) {
2999                 register_oss_dsp(pcm, 1);
3000                 pcm->oss.reg++;
3001                 pcm->oss.reg_mask |= 2;
3002         }
3003
3004         if (pcm->oss.reg)
3005                 snd_pcm_oss_proc_init(pcm);
3006
3007         return 0;
3008 }
3009
3010 static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm)
3011 {
3012         if (pcm->oss.reg) {
3013                 if (pcm->oss.reg_mask & 1) {
3014                         pcm->oss.reg_mask &= ~1;
3015                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3016                                                   pcm->card, 0);
3017                 }
3018                 if (pcm->oss.reg_mask & 2) {
3019                         pcm->oss.reg_mask &= ~2;
3020                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3021                                                   pcm->card, 1);
3022                 }
3023                 if (dsp_map[pcm->card->number] == (int)pcm->device) {
3024 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
3025                         snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
3026 #endif
3027                 }
3028                 pcm->oss.reg = 0;
3029         }
3030         return 0;
3031 }
3032
3033 static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm)
3034 {
3035         snd_pcm_oss_disconnect_minor(pcm);
3036         snd_pcm_oss_proc_done(pcm);
3037         return 0;
3038 }
3039
3040 static struct snd_pcm_notify snd_pcm_oss_notify =
3041 {
3042         .n_register =   snd_pcm_oss_register_minor,
3043         .n_disconnect = snd_pcm_oss_disconnect_minor,
3044         .n_unregister = snd_pcm_oss_unregister_minor,
3045 };
3046
3047 static int __init alsa_pcm_oss_init(void)
3048 {
3049         int i;
3050         int err;
3051
3052         /* check device map table */
3053         for (i = 0; i < SNDRV_CARDS; i++) {
3054                 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) {
3055                         snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n",
3056                                    i, dsp_map[i]);
3057                         dsp_map[i] = 0;
3058                 }
3059                 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) {
3060                         snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n",
3061                                    i, adsp_map[i]);
3062                         adsp_map[i] = 1;
3063                 }
3064         }
3065         if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0)
3066                 return err;
3067         return 0;
3068 }
3069
3070 static void __exit alsa_pcm_oss_exit(void)
3071 {
3072         snd_pcm_notify(&snd_pcm_oss_notify, 1);
3073 }
3074
3075 module_init(alsa_pcm_oss_init)
3076 module_exit(alsa_pcm_oss_exit)