Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[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         vfree(runtime->oss.buffer);
1047         runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
1048         if (!runtime->oss.buffer) {
1049                 err = -ENOMEM;
1050                 goto failure;
1051         }
1052
1053         runtime->oss.params = 0;
1054         runtime->oss.prepare = 1;
1055         runtime->oss.buffer_used = 0;
1056         if (runtime->dma_area)
1057                 snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
1058
1059         runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
1060
1061         err = 0;
1062 failure:
1063         kfree(sw_params);
1064         kfree(params);
1065         kfree(sparams);
1066         mutex_unlock(&runtime->oss.params_lock);
1067         return err;
1068 }
1069
1070 static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream)
1071 {
1072         int idx, err;
1073         struct snd_pcm_substream *asubstream = NULL, *substream;
1074
1075         for (idx = 0; idx < 2; idx++) {
1076                 substream = pcm_oss_file->streams[idx];
1077                 if (substream == NULL)
1078                         continue;
1079                 if (asubstream == NULL)
1080                         asubstream = substream;
1081                 if (substream->runtime->oss.params) {
1082                         err = snd_pcm_oss_change_params(substream);
1083                         if (err < 0)
1084                                 return err;
1085                 }
1086         }
1087         if (!asubstream)
1088                 return -EIO;
1089         if (r_substream)
1090                 *r_substream = asubstream;
1091         return 0;
1092 }
1093
1094 static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
1095 {
1096         int err;
1097         struct snd_pcm_runtime *runtime = substream->runtime;
1098
1099         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
1100         if (err < 0) {
1101                 snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");
1102                 return err;
1103         }
1104         runtime->oss.prepare = 0;
1105         runtime->oss.prev_hw_ptr_interrupt = 0;
1106         runtime->oss.period_ptr = 0;
1107         runtime->oss.buffer_used = 0;
1108
1109         return 0;
1110 }
1111
1112 static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
1113 {
1114         struct snd_pcm_runtime *runtime;
1115         int err;
1116
1117         if (substream == NULL)
1118                 return 0;
1119         runtime = substream->runtime;
1120         if (runtime->oss.params) {
1121                 err = snd_pcm_oss_change_params(substream);
1122                 if (err < 0)
1123                         return err;
1124         }
1125         if (runtime->oss.prepare) {
1126                 err = snd_pcm_oss_prepare(substream);
1127                 if (err < 0)
1128                         return err;
1129         }
1130         return 0;
1131 }
1132
1133 static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay)
1134 {
1135         struct snd_pcm_runtime *runtime;
1136         snd_pcm_uframes_t frames;
1137         int err = 0;
1138
1139         while (1) {
1140                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay);
1141                 if (err < 0)
1142                         break;
1143                 runtime = substream->runtime;
1144                 if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size)
1145                         break;
1146                 /* in case of overrun, skip whole periods like OSS/Linux driver does */
1147                 /* until avail(delay) <= buffer_size */
1148                 frames = (*delay - runtime->buffer_size) + runtime->period_size - 1;
1149                 frames /= runtime->period_size;
1150                 frames *= runtime->period_size;
1151                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames);
1152                 if (err < 0)
1153                         break;
1154         }
1155         return err;
1156 }
1157
1158 snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
1159 {
1160         struct snd_pcm_runtime *runtime = substream->runtime;
1161         int ret;
1162         while (1) {
1163                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1164                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1165 #ifdef OSS_DEBUG
1166                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1167                                 printk(KERN_DEBUG "pcm_oss: write: "
1168                                        "recovering from XRUN\n");
1169                         else
1170                                 printk(KERN_DEBUG "pcm_oss: write: "
1171                                        "recovering from SUSPEND\n");
1172 #endif
1173                         ret = snd_pcm_oss_prepare(substream);
1174                         if (ret < 0)
1175                                 break;
1176                 }
1177                 if (in_kernel) {
1178                         mm_segment_t fs;
1179                         fs = snd_enter_user();
1180                         ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
1181                         snd_leave_user(fs);
1182                 } else {
1183                         ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
1184                 }
1185                 if (ret != -EPIPE && ret != -ESTRPIPE)
1186                         break;
1187                 /* test, if we can't store new data, because the stream */
1188                 /* has not been started */
1189                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
1190                         return -EAGAIN;
1191         }
1192         return ret;
1193 }
1194
1195 snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
1196 {
1197         struct snd_pcm_runtime *runtime = substream->runtime;
1198         snd_pcm_sframes_t delay;
1199         int ret;
1200         while (1) {
1201                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1202                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1203 #ifdef OSS_DEBUG
1204                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1205                                 printk(KERN_DEBUG "pcm_oss: read: "
1206                                        "recovering from XRUN\n");
1207                         else
1208                                 printk(KERN_DEBUG "pcm_oss: read: "
1209                                        "recovering from SUSPEND\n");
1210 #endif
1211                         ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1212                         if (ret < 0)
1213                                 break;
1214                 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
1215                         ret = snd_pcm_oss_prepare(substream);
1216                         if (ret < 0)
1217                                 break;
1218                 }
1219                 ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
1220                 if (ret < 0)
1221                         break;
1222                 if (in_kernel) {
1223                         mm_segment_t fs;
1224                         fs = snd_enter_user();
1225                         ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
1226                         snd_leave_user(fs);
1227                 } else {
1228                         ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
1229                 }
1230                 if (ret == -EPIPE) {
1231                         if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
1232                                 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1233                                 if (ret < 0)
1234                                         break;
1235                         }
1236                         continue;
1237                 }
1238                 if (ret != -ESTRPIPE)
1239                         break;
1240         }
1241         return ret;
1242 }
1243
1244 snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
1245 {
1246         struct snd_pcm_runtime *runtime = substream->runtime;
1247         int ret;
1248         while (1) {
1249                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1250                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1251 #ifdef OSS_DEBUG
1252                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1253                                 printk(KERN_DEBUG "pcm_oss: writev: "
1254                                        "recovering from XRUN\n");
1255                         else
1256                                 printk(KERN_DEBUG "pcm_oss: writev: "
1257                                        "recovering from SUSPEND\n");
1258 #endif
1259                         ret = snd_pcm_oss_prepare(substream);
1260                         if (ret < 0)
1261                                 break;
1262                 }
1263                 if (in_kernel) {
1264                         mm_segment_t fs;
1265                         fs = snd_enter_user();
1266                         ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
1267                         snd_leave_user(fs);
1268                 } else {
1269                         ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
1270                 }
1271                 if (ret != -EPIPE && ret != -ESTRPIPE)
1272                         break;
1273
1274                 /* test, if we can't store new data, because the stream */
1275                 /* has not been started */
1276                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
1277                         return -EAGAIN;
1278         }
1279         return ret;
1280 }
1281         
1282 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
1283 {
1284         struct snd_pcm_runtime *runtime = substream->runtime;
1285         int ret;
1286         while (1) {
1287                 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
1288                     runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1289 #ifdef OSS_DEBUG
1290                         if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
1291                                 printk(KERN_DEBUG "pcm_oss: readv: "
1292                                        "recovering from XRUN\n");
1293                         else
1294                                 printk(KERN_DEBUG "pcm_oss: readv: "
1295                                        "recovering from SUSPEND\n");
1296 #endif
1297                         ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1298                         if (ret < 0)
1299                                 break;
1300                 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
1301                         ret = snd_pcm_oss_prepare(substream);
1302                         if (ret < 0)
1303                                 break;
1304                 }
1305                 if (in_kernel) {
1306                         mm_segment_t fs;
1307                         fs = snd_enter_user();
1308                         ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
1309                         snd_leave_user(fs);
1310                 } else {
1311                         ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
1312                 }
1313                 if (ret != -EPIPE && ret != -ESTRPIPE)
1314                         break;
1315         }
1316         return ret;
1317 }
1318
1319 static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
1320 {
1321         struct snd_pcm_runtime *runtime = substream->runtime;
1322         snd_pcm_sframes_t frames, frames1;
1323 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1324         if (runtime->oss.plugin_first) {
1325                 struct snd_pcm_plugin_channel *channels;
1326                 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
1327                 if (!in_kernel) {
1328                         if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
1329                                 return -EFAULT;
1330                         buf = runtime->oss.buffer;
1331                 }
1332                 frames = bytes / oss_frame_bytes;
1333                 frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels);
1334                 if (frames1 < 0)
1335                         return frames1;
1336                 frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1);
1337                 if (frames1 <= 0)
1338                         return frames1;
1339                 bytes = frames1 * oss_frame_bytes;
1340         } else
1341 #endif
1342         {
1343                 frames = bytes_to_frames(runtime, bytes);
1344                 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
1345                 if (frames1 <= 0)
1346                         return frames1;
1347                 bytes = frames_to_bytes(runtime, frames1);
1348         }
1349         return bytes;
1350 }
1351
1352 static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
1353 {
1354         size_t xfer = 0;
1355         ssize_t tmp;
1356         struct snd_pcm_runtime *runtime = substream->runtime;
1357
1358         if (atomic_read(&substream->mmap_count))
1359                 return -ENXIO;
1360
1361         if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1362                 return tmp;
1363         mutex_lock(&runtime->oss.params_lock);
1364         while (bytes > 0) {
1365                 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
1366                         tmp = bytes;
1367                         if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
1368                                 tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
1369                         if (tmp > 0) {
1370                                 if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
1371                                         tmp = -EFAULT;
1372                                         goto err;
1373                                 }
1374                         }
1375                         runtime->oss.buffer_used += tmp;
1376                         buf += tmp;
1377                         bytes -= tmp;
1378                         xfer += tmp;
1379                         if (substream->oss.setup.partialfrag ||
1380                             runtime->oss.buffer_used == runtime->oss.period_bytes) {
1381                                 tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 
1382                                                          runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
1383                                 if (tmp <= 0)
1384                                         goto err;
1385                                 runtime->oss.bytes += tmp;
1386                                 runtime->oss.period_ptr += tmp;
1387                                 runtime->oss.period_ptr %= runtime->oss.period_bytes;
1388                                 if (runtime->oss.period_ptr == 0 ||
1389                                     runtime->oss.period_ptr == runtime->oss.buffer_used)
1390                                         runtime->oss.buffer_used = 0;
1391                                 else if ((substream->f_flags & O_NONBLOCK) != 0) {
1392                                         tmp = -EAGAIN;
1393                                         goto err;
1394                                 }
1395                         }
1396                 } else {
1397                         tmp = snd_pcm_oss_write2(substream,
1398                                                  (const char __force *)buf,
1399                                                  runtime->oss.period_bytes, 0);
1400                         if (tmp <= 0)
1401                                 goto err;
1402                         runtime->oss.bytes += tmp;
1403                         buf += tmp;
1404                         bytes -= tmp;
1405                         xfer += tmp;
1406                         if ((substream->f_flags & O_NONBLOCK) != 0 &&
1407                             tmp != runtime->oss.period_bytes)
1408                                 break;
1409                 }
1410         }
1411         mutex_unlock(&runtime->oss.params_lock);
1412         return xfer;
1413
1414  err:
1415         mutex_unlock(&runtime->oss.params_lock);
1416         return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
1417 }
1418
1419 static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel)
1420 {
1421         struct snd_pcm_runtime *runtime = substream->runtime;
1422         snd_pcm_sframes_t frames, frames1;
1423 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
1424         char __user *final_dst = (char __user *)buf;
1425         if (runtime->oss.plugin_first) {
1426                 struct snd_pcm_plugin_channel *channels;
1427                 size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
1428                 if (!in_kernel)
1429                         buf = runtime->oss.buffer;
1430                 frames = bytes / oss_frame_bytes;
1431                 frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels);
1432                 if (frames1 < 0)
1433                         return frames1;
1434                 frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1);
1435                 if (frames1 <= 0)
1436                         return frames1;
1437                 bytes = frames1 * oss_frame_bytes;
1438                 if (!in_kernel && copy_to_user(final_dst, buf, bytes))
1439                         return -EFAULT;
1440         } else
1441 #endif
1442         {
1443                 frames = bytes_to_frames(runtime, bytes);
1444                 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
1445                 if (frames1 <= 0)
1446                         return frames1;
1447                 bytes = frames_to_bytes(runtime, frames1);
1448         }
1449         return bytes;
1450 }
1451
1452 static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes)
1453 {
1454         size_t xfer = 0;
1455         ssize_t tmp;
1456         struct snd_pcm_runtime *runtime = substream->runtime;
1457
1458         if (atomic_read(&substream->mmap_count))
1459                 return -ENXIO;
1460
1461         if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1462                 return tmp;
1463         mutex_lock(&runtime->oss.params_lock);
1464         while (bytes > 0) {
1465                 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
1466                         if (runtime->oss.buffer_used == 0) {
1467                                 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
1468                                 if (tmp <= 0)
1469                                         goto err;
1470                                 runtime->oss.bytes += tmp;
1471                                 runtime->oss.period_ptr = tmp;
1472                                 runtime->oss.buffer_used = tmp;
1473                         }
1474                         tmp = bytes;
1475                         if ((size_t) tmp > runtime->oss.buffer_used)
1476                                 tmp = runtime->oss.buffer_used;
1477                         if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) {
1478                                 tmp = -EFAULT;
1479                                 goto err;
1480                         }
1481                         buf += tmp;
1482                         bytes -= tmp;
1483                         xfer += tmp;
1484                         runtime->oss.buffer_used -= tmp;
1485                 } else {
1486                         tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
1487                                                 runtime->oss.period_bytes, 0);
1488                         if (tmp <= 0)
1489                                 goto err;
1490                         runtime->oss.bytes += tmp;
1491                         buf += tmp;
1492                         bytes -= tmp;
1493                         xfer += tmp;
1494                 }
1495         }
1496         mutex_unlock(&runtime->oss.params_lock);
1497         return xfer;
1498
1499  err:
1500         mutex_unlock(&runtime->oss.params_lock);
1501         return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
1502 }
1503
1504 static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
1505 {
1506         struct snd_pcm_substream *substream;
1507
1508         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1509         if (substream != NULL) {
1510                 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1511                 substream->runtime->oss.prepare = 1;
1512         }
1513         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1514         if (substream != NULL) {
1515                 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1516                 substream->runtime->oss.prepare = 1;
1517         }
1518         return 0;
1519 }
1520
1521 static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
1522 {
1523         struct snd_pcm_substream *substream;
1524         int err;
1525
1526         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1527         if (substream != NULL) {
1528                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1529                         return err;
1530                 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
1531         }
1532         /* note: all errors from the start action are ignored */
1533         /* OSS apps do not know, how to handle them */
1534         return 0;
1535 }
1536
1537 static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
1538 {
1539         struct snd_pcm_runtime *runtime;
1540         ssize_t result = 0;
1541         long res;
1542         wait_queue_t wait;
1543
1544         runtime = substream->runtime;
1545         init_waitqueue_entry(&wait, current);
1546         add_wait_queue(&runtime->sleep, &wait);
1547 #ifdef OSS_DEBUG
1548         printk(KERN_DEBUG "sync1: size = %li\n", size);
1549 #endif
1550         while (1) {
1551                 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
1552                 if (result > 0) {
1553                         runtime->oss.buffer_used = 0;
1554                         result = 0;
1555                         break;
1556                 }
1557                 if (result != 0 && result != -EAGAIN)
1558                         break;
1559                 result = 0;
1560                 set_current_state(TASK_INTERRUPTIBLE);
1561                 snd_pcm_stream_lock_irq(substream);
1562                 res = runtime->status->state;
1563                 snd_pcm_stream_unlock_irq(substream);
1564                 if (res != SNDRV_PCM_STATE_RUNNING) {
1565                         set_current_state(TASK_RUNNING);
1566                         break;
1567                 }
1568                 res = schedule_timeout(10 * HZ);
1569                 if (signal_pending(current)) {
1570                         result = -ERESTARTSYS;
1571                         break;
1572                 }
1573                 if (res == 0) {
1574                         snd_printk(KERN_ERR "OSS sync error - DMA timeout\n");
1575                         result = -EIO;
1576                         break;
1577                 }
1578         }
1579         remove_wait_queue(&runtime->sleep, &wait);
1580         return result;
1581 }
1582
1583 static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
1584 {
1585         int err = 0;
1586         unsigned int saved_f_flags;
1587         struct snd_pcm_substream *substream;
1588         struct snd_pcm_runtime *runtime;
1589         snd_pcm_format_t format;
1590         unsigned long width;
1591         size_t size;
1592
1593         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1594         if (substream != NULL) {
1595                 runtime = substream->runtime;
1596                 if (atomic_read(&substream->mmap_count))
1597                         goto __direct;
1598                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1599                         return err;
1600                 format = snd_pcm_oss_format_from(runtime->oss.format);
1601                 width = snd_pcm_format_physical_width(format);
1602                 mutex_lock(&runtime->oss.params_lock);
1603                 if (runtime->oss.buffer_used > 0) {
1604 #ifdef OSS_DEBUG
1605                         printk(KERN_DEBUG "sync: buffer_used\n");
1606 #endif
1607                         size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
1608                         snd_pcm_format_set_silence(format,
1609                                                    runtime->oss.buffer + runtime->oss.buffer_used,
1610                                                    size);
1611                         err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
1612                         if (err < 0) {
1613                                 mutex_unlock(&runtime->oss.params_lock);
1614                                 return err;
1615                         }
1616                 } else if (runtime->oss.period_ptr > 0) {
1617 #ifdef OSS_DEBUG
1618                         printk(KERN_DEBUG "sync: period_ptr\n");
1619 #endif
1620                         size = runtime->oss.period_bytes - runtime->oss.period_ptr;
1621                         snd_pcm_format_set_silence(format,
1622                                                    runtime->oss.buffer,
1623                                                    size * 8 / width);
1624                         err = snd_pcm_oss_sync1(substream, size);
1625                         if (err < 0) {
1626                                 mutex_unlock(&runtime->oss.params_lock);
1627                                 return err;
1628                         }
1629                 }
1630                 /*
1631                  * The ALSA's period might be a bit large than OSS one.
1632                  * Fill the remain portion of ALSA period with zeros.
1633                  */
1634                 size = runtime->control->appl_ptr % runtime->period_size;
1635                 if (size > 0) {
1636                         size = runtime->period_size - size;
1637                         if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
1638                                 size = (runtime->frame_bits * size) / 8;
1639                                 while (size > 0) {
1640                                         mm_segment_t fs;
1641                                         size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
1642                                         size -= size1;
1643                                         size1 *= 8;
1644                                         size1 /= runtime->sample_bits;
1645                                         snd_pcm_format_set_silence(runtime->format,
1646                                                                    runtime->oss.buffer,
1647                                                                    size1);
1648                                         size1 /= runtime->channels; /* frames */
1649                                         fs = snd_enter_user();
1650                                         snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
1651                                         snd_leave_user(fs);
1652                                 }
1653                         } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
1654                                 void __user *buffers[runtime->channels];
1655                                 memset(buffers, 0, runtime->channels * sizeof(void *));
1656                                 snd_pcm_lib_writev(substream, buffers, size);
1657                         }
1658                 }
1659                 mutex_unlock(&runtime->oss.params_lock);
1660                 /*
1661                  * finish sync: drain the buffer
1662                  */
1663               __direct:
1664                 saved_f_flags = substream->f_flags;
1665                 substream->f_flags &= ~O_NONBLOCK;
1666                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
1667                 substream->f_flags = saved_f_flags;
1668                 if (err < 0)
1669                         return err;
1670                 runtime->oss.prepare = 1;
1671         }
1672
1673         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1674         if (substream != NULL) {
1675                 if ((err = snd_pcm_oss_make_ready(substream)) < 0)
1676                         return err;
1677                 runtime = substream->runtime;
1678                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
1679                 if (err < 0)
1680                         return err;
1681                 runtime->oss.buffer_used = 0;
1682                 runtime->oss.prepare = 1;
1683         }
1684         return 0;
1685 }
1686
1687 static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate)
1688 {
1689         int idx;
1690
1691         for (idx = 1; idx >= 0; --idx) {
1692                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1693                 struct snd_pcm_runtime *runtime;
1694                 if (substream == NULL)
1695                         continue;
1696                 runtime = substream->runtime;
1697                 if (rate < 1000)
1698                         rate = 1000;
1699                 else if (rate > 192000)
1700                         rate = 192000;
1701                 if (runtime->oss.rate != rate) {
1702                         runtime->oss.params = 1;
1703                         runtime->oss.rate = rate;
1704                 }
1705         }
1706         return snd_pcm_oss_get_rate(pcm_oss_file);
1707 }
1708
1709 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file)
1710 {
1711         struct snd_pcm_substream *substream;
1712         int err;
1713         
1714         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1715                 return err;
1716         return substream->runtime->oss.rate;
1717 }
1718
1719 static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels)
1720 {
1721         int idx;
1722         if (channels < 1)
1723                 channels = 1;
1724         if (channels > 128)
1725                 return -EINVAL;
1726         for (idx = 1; idx >= 0; --idx) {
1727                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1728                 struct snd_pcm_runtime *runtime;
1729                 if (substream == NULL)
1730                         continue;
1731                 runtime = substream->runtime;
1732                 if (runtime->oss.channels != channels) {
1733                         runtime->oss.params = 1;
1734                         runtime->oss.channels = channels;
1735                 }
1736         }
1737         return snd_pcm_oss_get_channels(pcm_oss_file);
1738 }
1739
1740 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file)
1741 {
1742         struct snd_pcm_substream *substream;
1743         int err;
1744         
1745         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1746                 return err;
1747         return substream->runtime->oss.channels;
1748 }
1749
1750 static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file)
1751 {
1752         struct snd_pcm_substream *substream;
1753         int err;
1754         
1755         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1756                 return err;
1757         return substream->runtime->oss.period_bytes;
1758 }
1759
1760 static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
1761 {
1762         struct snd_pcm_substream *substream;
1763         int err;
1764         int direct;
1765         struct snd_pcm_hw_params *params;
1766         unsigned int formats = 0;
1767         struct snd_mask format_mask;
1768         int fmt;
1769
1770         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1771                 return err;
1772         if (atomic_read(&substream->mmap_count))
1773                 direct = 1;
1774         else
1775                 direct = substream->oss.setup.direct;
1776         if (!direct)
1777                 return AFMT_MU_LAW | AFMT_U8 |
1778                        AFMT_S16_LE | AFMT_S16_BE |
1779                        AFMT_S8 | AFMT_U16_LE |
1780                        AFMT_U16_BE |
1781                         AFMT_S32_LE | AFMT_S32_BE |
1782                         AFMT_S24_LE | AFMT_S24_BE |
1783                         AFMT_S24_PACKED;
1784         params = kmalloc(sizeof(*params), GFP_KERNEL);
1785         if (!params)
1786                 return -ENOMEM;
1787         _snd_pcm_hw_params_any(params);
1788         err = snd_pcm_hw_refine(substream, params);
1789         format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 
1790         kfree(params);
1791         if (err < 0)
1792                 return err;
1793         for (fmt = 0; fmt < 32; ++fmt) {
1794                 if (snd_mask_test(&format_mask, fmt)) {
1795                         int f = snd_pcm_oss_format_to(fmt);
1796                         if (f >= 0)
1797                                 formats |= f;
1798                 }
1799         }
1800         return formats;
1801 }
1802
1803 static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
1804 {
1805         int formats, idx;
1806         
1807         if (format != AFMT_QUERY) {
1808                 formats = snd_pcm_oss_get_formats(pcm_oss_file);
1809                 if (formats < 0)
1810                         return formats;
1811                 if (!(formats & format))
1812                         format = AFMT_U8;
1813                 for (idx = 1; idx >= 0; --idx) {
1814                         struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1815                         struct snd_pcm_runtime *runtime;
1816                         if (substream == NULL)
1817                                 continue;
1818                         runtime = substream->runtime;
1819                         if (runtime->oss.format != format) {
1820                                 runtime->oss.params = 1;
1821                                 runtime->oss.format = format;
1822                         }
1823                 }
1824         }
1825         return snd_pcm_oss_get_format(pcm_oss_file);
1826 }
1827
1828 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file)
1829 {
1830         struct snd_pcm_substream *substream;
1831         int err;
1832         
1833         if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
1834                 return err;
1835         return substream->runtime->oss.format;
1836 }
1837
1838 static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide)
1839 {
1840         struct snd_pcm_runtime *runtime;
1841
1842         if (substream == NULL)
1843                 return 0;
1844         runtime = substream->runtime;
1845         if (subdivide == 0) {
1846                 subdivide = runtime->oss.subdivision;
1847                 if (subdivide == 0)
1848                         subdivide = 1;
1849                 return subdivide;
1850         }
1851         if (runtime->oss.subdivision || runtime->oss.fragshift)
1852                 return -EINVAL;
1853         if (subdivide != 1 && subdivide != 2 && subdivide != 4 &&
1854             subdivide != 8 && subdivide != 16)
1855                 return -EINVAL;
1856         runtime->oss.subdivision = subdivide;
1857         runtime->oss.params = 1;
1858         return subdivide;
1859 }
1860
1861 static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide)
1862 {
1863         int err = -EINVAL, idx;
1864
1865         for (idx = 1; idx >= 0; --idx) {
1866                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1867                 if (substream == NULL)
1868                         continue;
1869                 if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
1870                         return err;
1871         }
1872         return err;
1873 }
1874
1875 static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val)
1876 {
1877         struct snd_pcm_runtime *runtime;
1878
1879         if (substream == NULL)
1880                 return 0;
1881         runtime = substream->runtime;
1882         if (runtime->oss.subdivision || runtime->oss.fragshift)
1883                 return -EINVAL;
1884         runtime->oss.fragshift = val & 0xffff;
1885         runtime->oss.maxfrags = (val >> 16) & 0xffff;
1886         if (runtime->oss.fragshift < 4)         /* < 16 */
1887                 runtime->oss.fragshift = 4;
1888         if (runtime->oss.maxfrags < 2)
1889                 runtime->oss.maxfrags = 2;
1890         runtime->oss.params = 1;
1891         return 0;
1892 }
1893
1894 static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val)
1895 {
1896         int err = -EINVAL, idx;
1897
1898         for (idx = 1; idx >= 0; --idx) {
1899                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1900                 if (substream == NULL)
1901                         continue;
1902                 if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
1903                         return err;
1904         }
1905         return err;
1906 }
1907
1908 static int snd_pcm_oss_nonblock(struct file * file)
1909 {
1910         spin_lock(&file->f_lock);
1911         file->f_flags |= O_NONBLOCK;
1912         spin_unlock(&file->f_lock);
1913         return 0;
1914 }
1915
1916 static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res)
1917 {
1918
1919         if (substream == NULL) {
1920                 res &= ~DSP_CAP_DUPLEX;
1921                 return res;
1922         }
1923 #ifdef DSP_CAP_MULTI
1924         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1925                 if (substream->pstr->substream_count > 1)
1926                         res |= DSP_CAP_MULTI;
1927 #endif
1928         /* DSP_CAP_REALTIME is set all times: */
1929         /* all ALSA drivers can return actual pointer in ring buffer */
1930 #if defined(DSP_CAP_REALTIME) && 0
1931         {
1932                 struct snd_pcm_runtime *runtime = substream->runtime;
1933                 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))
1934                         res &= ~DSP_CAP_REALTIME;
1935         }
1936 #endif
1937         return res;
1938 }
1939
1940 static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file)
1941 {
1942         int result, idx;
1943         
1944         result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME;
1945         for (idx = 0; idx < 2; idx++) {
1946                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1947                 result = snd_pcm_oss_get_caps1(substream, result);
1948         }
1949         result |= 0x0001;       /* revision - same as SB AWE 64 */
1950         return result;
1951 }
1952
1953 static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr)
1954 {
1955         struct snd_pcm_runtime *runtime = substream->runtime;
1956         snd_pcm_uframes_t appl_ptr;
1957         appl_ptr = hw_ptr + runtime->buffer_size;
1958         appl_ptr %= runtime->boundary;
1959         runtime->control->appl_ptr = appl_ptr;
1960 }
1961
1962 static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger)
1963 {
1964         struct snd_pcm_runtime *runtime;
1965         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
1966         int err, cmd;
1967
1968 #ifdef OSS_DEBUG
1969         printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
1970 #endif
1971         
1972         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
1973         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
1974
1975         if (psubstream) {
1976                 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
1977                         return err;
1978         }
1979         if (csubstream) {
1980                 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
1981                         return err;
1982         }
1983         if (psubstream) {
1984                 runtime = psubstream->runtime;
1985                 if (trigger & PCM_ENABLE_OUTPUT) {
1986                         if (runtime->oss.trigger)
1987                                 goto _skip1;
1988                         if (atomic_read(&psubstream->mmap_count))
1989                                 snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);
1990                         runtime->oss.trigger = 1;
1991                         runtime->start_threshold = 1;
1992                         cmd = SNDRV_PCM_IOCTL_START;
1993                 } else {
1994                         if (!runtime->oss.trigger)
1995                                 goto _skip1;
1996                         runtime->oss.trigger = 0;
1997                         runtime->start_threshold = runtime->boundary;
1998                         cmd = SNDRV_PCM_IOCTL_DROP;
1999                         runtime->oss.prepare = 1;
2000                 }
2001                 err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
2002                 if (err < 0)
2003                         return err;
2004         }
2005  _skip1:
2006         if (csubstream) {
2007                 runtime = csubstream->runtime;
2008                 if (trigger & PCM_ENABLE_INPUT) {
2009                         if (runtime->oss.trigger)
2010                                 goto _skip2;
2011                         runtime->oss.trigger = 1;
2012                         runtime->start_threshold = 1;
2013                         cmd = SNDRV_PCM_IOCTL_START;
2014                 } else {
2015                         if (!runtime->oss.trigger)
2016                                 goto _skip2;
2017                         runtime->oss.trigger = 0;
2018                         runtime->start_threshold = runtime->boundary;
2019                         cmd = SNDRV_PCM_IOCTL_DROP;
2020                         runtime->oss.prepare = 1;
2021                 }
2022                 err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
2023                 if (err < 0)
2024                         return err;
2025         }
2026  _skip2:
2027         return 0;
2028 }
2029
2030 static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
2031 {
2032         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2033         int result = 0;
2034
2035         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2036         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2037         if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
2038                 result |= PCM_ENABLE_OUTPUT;
2039         if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
2040                 result |= PCM_ENABLE_INPUT;
2041         return result;
2042 }
2043
2044 static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
2045 {
2046         struct snd_pcm_substream *substream;
2047         struct snd_pcm_runtime *runtime;
2048         snd_pcm_sframes_t delay;
2049         int err;
2050
2051         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2052         if (substream == NULL)
2053                 return -EINVAL;
2054         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2055                 return err;
2056         runtime = substream->runtime;
2057         if (runtime->oss.params || runtime->oss.prepare)
2058                 return 0;
2059         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
2060         if (err == -EPIPE)
2061                 delay = 0;      /* hack for broken OSS applications */
2062         else if (err < 0)
2063                 return err;
2064         return snd_pcm_oss_bytes(substream, delay);
2065 }
2066
2067 static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info)
2068 {       
2069         struct snd_pcm_substream *substream;
2070         struct snd_pcm_runtime *runtime;
2071         snd_pcm_sframes_t delay;
2072         int fixup;
2073         struct count_info info;
2074         int err;
2075
2076         if (_info == NULL)
2077                 return -EFAULT;
2078         substream = pcm_oss_file->streams[stream];
2079         if (substream == NULL)
2080                 return -EINVAL;
2081         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2082                 return err;
2083         runtime = substream->runtime;
2084         if (runtime->oss.params || runtime->oss.prepare) {
2085                 memset(&info, 0, sizeof(info));
2086                 if (copy_to_user(_info, &info, sizeof(info)))
2087                         return -EFAULT;
2088                 return 0;
2089         }
2090         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2091                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
2092                 if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) {
2093                         err = 0;
2094                         delay = 0;
2095                         fixup = 0;
2096                 } else {
2097                         fixup = runtime->oss.buffer_used;
2098                 }
2099         } else {
2100                 err = snd_pcm_oss_capture_position_fixup(substream, &delay);
2101                 fixup = -runtime->oss.buffer_used;
2102         }
2103         if (err < 0)
2104                 return err;
2105         info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
2106         if (atomic_read(&substream->mmap_count)) {
2107                 snd_pcm_sframes_t n;
2108                 n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;
2109                 if (n < 0)
2110                         n += runtime->boundary;
2111                 info.blocks = n / runtime->period_size;
2112                 runtime->oss.prev_hw_ptr_interrupt = delay;
2113                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2114                         snd_pcm_oss_simulate_fill(substream, delay);
2115                 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
2116         } else {
2117                 delay = snd_pcm_oss_bytes(substream, delay);
2118                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2119                         if (substream->oss.setup.buggyptr)
2120                                 info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
2121                         else
2122                                 info.blocks = (delay + fixup) / runtime->oss.period_bytes;
2123                         info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
2124                 } else {
2125                         delay += fixup;
2126                         info.blocks = delay / runtime->oss.period_bytes;
2127                         info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
2128                 }
2129         }
2130         if (copy_to_user(_info, &info, sizeof(info)))
2131                 return -EFAULT;
2132         return 0;
2133 }
2134
2135 static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info)
2136 {
2137         struct snd_pcm_substream *substream;
2138         struct snd_pcm_runtime *runtime;
2139         snd_pcm_sframes_t avail;
2140         int fixup;
2141         struct audio_buf_info info;
2142         int err;
2143
2144         if (_info == NULL)
2145                 return -EFAULT;
2146         substream = pcm_oss_file->streams[stream];
2147         if (substream == NULL)
2148                 return -EINVAL;
2149         runtime = substream->runtime;
2150
2151         if (runtime->oss.params &&
2152             (err = snd_pcm_oss_change_params(substream)) < 0)
2153                 return err;
2154
2155         info.fragsize = runtime->oss.period_bytes;
2156         info.fragstotal = runtime->periods;
2157         if (runtime->oss.prepare) {
2158                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2159                         info.bytes = runtime->oss.period_bytes * runtime->oss.periods;
2160                         info.fragments = runtime->oss.periods;
2161                 } else {
2162                         info.bytes = 0;
2163                         info.fragments = 0;
2164                 }
2165         } else {
2166                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2167                         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
2168                         if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) {
2169                                 avail = runtime->buffer_size;
2170                                 err = 0;
2171                                 fixup = 0;
2172                         } else {
2173                                 avail = runtime->buffer_size - avail;
2174                                 fixup = -runtime->oss.buffer_used;
2175                         }
2176                 } else {
2177                         err = snd_pcm_oss_capture_position_fixup(substream, &avail);
2178                         fixup = runtime->oss.buffer_used;
2179                 }
2180                 if (err < 0)
2181                         return err;
2182                 info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup;
2183                 info.fragments = info.bytes / runtime->oss.period_bytes;
2184         }
2185
2186 #ifdef OSS_DEBUG
2187         printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
2188                "fragstotal = %i, fragsize = %i\n",
2189                info.bytes, info.fragments, info.fragstotal, info.fragsize);
2190 #endif
2191         if (copy_to_user(_info, &info, sizeof(info)))
2192                 return -EFAULT;
2193         return 0;
2194 }
2195
2196 static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info)
2197 {
2198         // it won't be probably implemented
2199         // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n");
2200         return -EINVAL;
2201 }
2202
2203 static const char *strip_task_path(const char *path)
2204 {
2205         const char *ptr, *ptrl = NULL;
2206         for (ptr = path; *ptr; ptr++) {
2207                 if (*ptr == '/')
2208                         ptrl = ptr + 1;
2209         }
2210         return ptrl;
2211 }
2212
2213 static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
2214                                       const char *task_name,
2215                                       struct snd_pcm_oss_setup *rsetup)
2216 {
2217         struct snd_pcm_oss_setup *setup;
2218
2219         mutex_lock(&pcm->streams[stream].oss.setup_mutex);
2220         do {
2221                 for (setup = pcm->streams[stream].oss.setup_list; setup;
2222                      setup = setup->next) {
2223                         if (!strcmp(setup->task_name, task_name))
2224                                 goto out;
2225                 }
2226         } while ((task_name = strip_task_path(task_name)) != NULL);
2227  out:
2228         if (setup)
2229                 *rsetup = *setup;
2230         mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
2231 }
2232
2233 static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
2234 {
2235         struct snd_pcm_runtime *runtime;
2236         runtime = substream->runtime;
2237         vfree(runtime->oss.buffer);
2238         runtime->oss.buffer = NULL;
2239 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2240         snd_pcm_oss_plugin_clear(substream);
2241 #endif
2242         substream->oss.oss = 0;
2243 }
2244
2245 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
2246                                        struct snd_pcm_oss_setup *setup,
2247                                        int minor)
2248 {
2249         struct snd_pcm_runtime *runtime;
2250
2251         substream->oss.oss = 1;
2252         substream->oss.setup = *setup;
2253         if (setup->nonblock)
2254                 substream->f_flags |= O_NONBLOCK;
2255         else if (setup->block)
2256                 substream->f_flags &= ~O_NONBLOCK;
2257         runtime = substream->runtime;
2258         runtime->oss.params = 1;
2259         runtime->oss.trigger = 1;
2260         runtime->oss.rate = 8000;
2261         mutex_init(&runtime->oss.params_lock);
2262         switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
2263         case SNDRV_MINOR_OSS_PCM_8:
2264                 runtime->oss.format = AFMT_U8;
2265                 break;
2266         case SNDRV_MINOR_OSS_PCM_16:
2267                 runtime->oss.format = AFMT_S16_LE;
2268                 break;
2269         default:
2270                 runtime->oss.format = AFMT_MU_LAW;
2271         }
2272         runtime->oss.channels = 1;
2273         runtime->oss.fragshift = 0;
2274         runtime->oss.maxfrags = 0;
2275         runtime->oss.subdivision = 0;
2276         substream->pcm_release = snd_pcm_oss_release_substream;
2277 }
2278
2279 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
2280 {
2281         int cidx;
2282         if (!pcm_oss_file)
2283                 return 0;
2284         for (cidx = 0; cidx < 2; ++cidx) {
2285                 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
2286                 if (substream)
2287                         snd_pcm_release_substream(substream);
2288         }
2289         kfree(pcm_oss_file);
2290         return 0;
2291 }
2292
2293 static int snd_pcm_oss_open_file(struct file *file,
2294                                  struct snd_pcm *pcm,
2295                                  struct snd_pcm_oss_file **rpcm_oss_file,
2296                                  int minor,
2297                                  struct snd_pcm_oss_setup *setup)
2298 {
2299         int idx, err;
2300         struct snd_pcm_oss_file *pcm_oss_file;
2301         struct snd_pcm_substream *substream;
2302         fmode_t f_mode = file->f_mode;
2303
2304         if (rpcm_oss_file)
2305                 *rpcm_oss_file = NULL;
2306
2307         pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
2308         if (pcm_oss_file == NULL)
2309                 return -ENOMEM;
2310
2311         if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
2312             (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
2313                 f_mode = FMODE_WRITE;
2314
2315         file->f_flags &= ~O_APPEND;
2316         for (idx = 0; idx < 2; idx++) {
2317                 if (setup[idx].disable)
2318                         continue;
2319                 if (! pcm->streams[idx].substream_count)
2320                         continue; /* no matching substream */
2321                 if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
2322                         if (! (f_mode & FMODE_WRITE))
2323                                 continue;
2324                 } else {
2325                         if (! (f_mode & FMODE_READ))
2326                                 continue;
2327                 }
2328                 err = snd_pcm_open_substream(pcm, idx, file, &substream);
2329                 if (err < 0) {
2330                         snd_pcm_oss_release_file(pcm_oss_file);
2331                         return err;
2332                 }
2333
2334                 pcm_oss_file->streams[idx] = substream;
2335                 substream->file = pcm_oss_file;
2336                 snd_pcm_oss_init_substream(substream, &setup[idx], minor);
2337         }
2338         
2339         if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
2340                 snd_pcm_oss_release_file(pcm_oss_file);
2341                 return -EINVAL;
2342         }
2343
2344         file->private_data = pcm_oss_file;
2345         if (rpcm_oss_file)
2346                 *rpcm_oss_file = pcm_oss_file;
2347         return 0;
2348 }
2349
2350
2351 static int snd_task_name(struct task_struct *task, char *name, size_t size)
2352 {
2353         unsigned int idx;
2354
2355         if (snd_BUG_ON(!task || !name || size < 2))
2356                 return -EINVAL;
2357         for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++)
2358                 name[idx] = task->comm[idx];
2359         name[idx] = '\0';
2360         return 0;
2361 }
2362
2363 static int snd_pcm_oss_open(struct inode *inode, struct file *file)
2364 {
2365         int err;
2366         char task_name[32];
2367         struct snd_pcm *pcm;
2368         struct snd_pcm_oss_file *pcm_oss_file;
2369         struct snd_pcm_oss_setup setup[2];
2370         int nonblock;
2371         wait_queue_t wait;
2372
2373         pcm = snd_lookup_oss_minor_data(iminor(inode),
2374                                         SNDRV_OSS_DEVICE_TYPE_PCM);
2375         if (pcm == NULL) {
2376                 err = -ENODEV;
2377                 goto __error1;
2378         }
2379         err = snd_card_file_add(pcm->card, file);
2380         if (err < 0)
2381                 goto __error1;
2382         if (!try_module_get(pcm->card->module)) {
2383                 err = -EFAULT;
2384                 goto __error2;
2385         }
2386         if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {
2387                 err = -EFAULT;
2388                 goto __error;
2389         }
2390         memset(setup, 0, sizeof(setup));
2391         if (file->f_mode & FMODE_WRITE)
2392                 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
2393                                            task_name, &setup[0]);
2394         if (file->f_mode & FMODE_READ)
2395                 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
2396                                            task_name, &setup[1]);
2397
2398         nonblock = !!(file->f_flags & O_NONBLOCK);
2399         if (!nonblock)
2400                 nonblock = nonblock_open;
2401
2402         init_waitqueue_entry(&wait, current);
2403         add_wait_queue(&pcm->open_wait, &wait);
2404         mutex_lock(&pcm->open_mutex);
2405         while (1) {
2406                 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
2407                                             iminor(inode), setup);
2408                 if (err >= 0)
2409                         break;
2410                 if (err == -EAGAIN) {
2411                         if (nonblock) {
2412                                 err = -EBUSY;
2413                                 break;
2414                         }
2415                 } else
2416                         break;
2417                 set_current_state(TASK_INTERRUPTIBLE);
2418                 mutex_unlock(&pcm->open_mutex);
2419                 schedule();
2420                 mutex_lock(&pcm->open_mutex);
2421                 if (signal_pending(current)) {
2422                         err = -ERESTARTSYS;
2423                         break;
2424                 }
2425         }
2426         remove_wait_queue(&pcm->open_wait, &wait);
2427         mutex_unlock(&pcm->open_mutex);
2428         if (err < 0)
2429                 goto __error;
2430         return err;
2431
2432       __error:
2433         module_put(pcm->card->module);
2434       __error2:
2435         snd_card_file_remove(pcm->card, file);
2436       __error1:
2437         return err;
2438 }
2439
2440 static int snd_pcm_oss_release(struct inode *inode, struct file *file)
2441 {
2442         struct snd_pcm *pcm;
2443         struct snd_pcm_substream *substream;
2444         struct snd_pcm_oss_file *pcm_oss_file;
2445
2446         pcm_oss_file = file->private_data;
2447         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2448         if (substream == NULL)
2449                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2450         if (snd_BUG_ON(!substream))
2451                 return -ENXIO;
2452         pcm = substream->pcm;
2453         if (!pcm->card->shutdown)
2454                 snd_pcm_oss_sync(pcm_oss_file);
2455         mutex_lock(&pcm->open_mutex);
2456         snd_pcm_oss_release_file(pcm_oss_file);
2457         mutex_unlock(&pcm->open_mutex);
2458         wake_up(&pcm->open_wait);
2459         module_put(pcm->card->module);
2460         snd_card_file_remove(pcm->card, file);
2461         return 0;
2462 }
2463
2464 static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2465 {
2466         struct snd_pcm_oss_file *pcm_oss_file;
2467         int __user *p = (int __user *)arg;
2468         int res;
2469
2470         pcm_oss_file = file->private_data;
2471         if (cmd == OSS_GETVERSION)
2472                 return put_user(SNDRV_OSS_VERSION, p);
2473         if (cmd == OSS_ALSAEMULVER)
2474                 return put_user(1, p);
2475 #if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
2476         if (((cmd >> 8) & 0xff) == 'M') {       /* mixer ioctl - for OSS compatibility */
2477                 struct snd_pcm_substream *substream;
2478                 int idx;
2479                 for (idx = 0; idx < 2; ++idx) {
2480                         substream = pcm_oss_file->streams[idx];
2481                         if (substream != NULL)
2482                                 break;
2483                 }
2484                 if (snd_BUG_ON(idx >= 2))
2485                         return -ENXIO;
2486                 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);
2487         }
2488 #endif
2489         if (((cmd >> 8) & 0xff) != 'P')
2490                 return -EINVAL;
2491 #ifdef OSS_DEBUG
2492         printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
2493 #endif
2494         switch (cmd) {
2495         case SNDCTL_DSP_RESET:
2496                 return snd_pcm_oss_reset(pcm_oss_file);
2497         case SNDCTL_DSP_SYNC:
2498                 return snd_pcm_oss_sync(pcm_oss_file);
2499         case SNDCTL_DSP_SPEED:
2500                 if (get_user(res, p))
2501                         return -EFAULT;
2502                 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)
2503                         return res;
2504                 return put_user(res, p);
2505         case SOUND_PCM_READ_RATE:
2506                 res = snd_pcm_oss_get_rate(pcm_oss_file);
2507                 if (res < 0)
2508                         return res;
2509                 return put_user(res, p);
2510         case SNDCTL_DSP_STEREO:
2511                 if (get_user(res, p))
2512                         return -EFAULT;
2513                 res = res > 0 ? 2 : 1;
2514                 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)
2515                         return res;
2516                 return put_user(--res, p);
2517         case SNDCTL_DSP_GETBLKSIZE:
2518                 res = snd_pcm_oss_get_block_size(pcm_oss_file);
2519                 if (res < 0)
2520                         return res;
2521                 return put_user(res, p);
2522         case SNDCTL_DSP_SETFMT:
2523                 if (get_user(res, p))
2524                         return -EFAULT;
2525                 res = snd_pcm_oss_set_format(pcm_oss_file, res);
2526                 if (res < 0)
2527                         return res;
2528                 return put_user(res, p);
2529         case SOUND_PCM_READ_BITS:
2530                 res = snd_pcm_oss_get_format(pcm_oss_file);
2531                 if (res < 0)
2532                         return res;
2533                 return put_user(res, p);
2534         case SNDCTL_DSP_CHANNELS:
2535                 if (get_user(res, p))
2536                         return -EFAULT;
2537                 res = snd_pcm_oss_set_channels(pcm_oss_file, res);
2538                 if (res < 0)
2539                         return res;
2540                 return put_user(res, p);
2541         case SOUND_PCM_READ_CHANNELS:
2542                 res = snd_pcm_oss_get_channels(pcm_oss_file);
2543                 if (res < 0)
2544                         return res;
2545                 return put_user(res, p);
2546         case SOUND_PCM_WRITE_FILTER:
2547         case SOUND_PCM_READ_FILTER:
2548                 return -EIO;
2549         case SNDCTL_DSP_POST:
2550                 return snd_pcm_oss_post(pcm_oss_file);
2551         case SNDCTL_DSP_SUBDIVIDE:
2552                 if (get_user(res, p))
2553                         return -EFAULT;
2554                 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);
2555                 if (res < 0)
2556                         return res;
2557                 return put_user(res, p);
2558         case SNDCTL_DSP_SETFRAGMENT:
2559                 if (get_user(res, p))
2560                         return -EFAULT;
2561                 return snd_pcm_oss_set_fragment(pcm_oss_file, res);
2562         case SNDCTL_DSP_GETFMTS:
2563                 res = snd_pcm_oss_get_formats(pcm_oss_file);
2564                 if (res < 0)
2565                         return res;
2566                 return put_user(res, p);
2567         case SNDCTL_DSP_GETOSPACE:
2568         case SNDCTL_DSP_GETISPACE:
2569                 return snd_pcm_oss_get_space(pcm_oss_file,
2570                         cmd == SNDCTL_DSP_GETISPACE ?
2571                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2572                         (struct audio_buf_info __user *) arg);
2573         case SNDCTL_DSP_NONBLOCK:
2574                 return snd_pcm_oss_nonblock(file);
2575         case SNDCTL_DSP_GETCAPS:
2576                 res = snd_pcm_oss_get_caps(pcm_oss_file);
2577                 if (res < 0)
2578                         return res;
2579                 return put_user(res, p);
2580         case SNDCTL_DSP_GETTRIGGER:
2581                 res = snd_pcm_oss_get_trigger(pcm_oss_file);
2582                 if (res < 0)
2583                         return res;
2584                 return put_user(res, p);
2585         case SNDCTL_DSP_SETTRIGGER:
2586                 if (get_user(res, p))
2587                         return -EFAULT;
2588                 return snd_pcm_oss_set_trigger(pcm_oss_file, res);
2589         case SNDCTL_DSP_GETIPTR:
2590         case SNDCTL_DSP_GETOPTR:
2591                 return snd_pcm_oss_get_ptr(pcm_oss_file,
2592                         cmd == SNDCTL_DSP_GETIPTR ?
2593                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2594                         (struct count_info __user *) arg);
2595         case SNDCTL_DSP_MAPINBUF:
2596         case SNDCTL_DSP_MAPOUTBUF:
2597                 return snd_pcm_oss_get_mapbuf(pcm_oss_file,
2598                         cmd == SNDCTL_DSP_MAPINBUF ?
2599                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2600                         (struct buffmem_desc __user *) arg);
2601         case SNDCTL_DSP_SETSYNCRO:
2602                 /* stop DMA now.. */
2603                 return 0;
2604         case SNDCTL_DSP_SETDUPLEX:
2605                 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX)
2606                         return 0;
2607                 return -EIO;
2608         case SNDCTL_DSP_GETODELAY:
2609                 res = snd_pcm_oss_get_odelay(pcm_oss_file);
2610                 if (res < 0) {
2611                         /* it's for sure, some broken apps don't check for error codes */
2612                         put_user(0, p);
2613                         return res;
2614                 }
2615                 return put_user(res, p);
2616         case SNDCTL_DSP_PROFILE:
2617                 return 0;       /* silently ignore */
2618         default:
2619                 snd_printd("pcm_oss: unknown command = 0x%x\n", cmd);
2620         }
2621         return -EINVAL;
2622 }
2623
2624 #ifdef CONFIG_COMPAT
2625 /* all compatible */
2626 #define snd_pcm_oss_ioctl_compat        snd_pcm_oss_ioctl
2627 #else
2628 #define snd_pcm_oss_ioctl_compat        NULL
2629 #endif
2630
2631 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
2632 {
2633         struct snd_pcm_oss_file *pcm_oss_file;
2634         struct snd_pcm_substream *substream;
2635
2636         pcm_oss_file = file->private_data;
2637         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2638         if (substream == NULL)
2639                 return -ENXIO;
2640         substream->f_flags = file->f_flags & O_NONBLOCK;
2641 #ifndef OSS_DEBUG
2642         return snd_pcm_oss_read1(substream, buf, count);
2643 #else
2644         {
2645                 ssize_t res = snd_pcm_oss_read1(substream, buf, count);
2646                 printk(KERN_DEBUG "pcm_oss: read %li bytes "
2647                        "(returned %li bytes)\n", (long)count, (long)res);
2648                 return res;
2649         }
2650 #endif
2651 }
2652
2653 static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
2654 {
2655         struct snd_pcm_oss_file *pcm_oss_file;
2656         struct snd_pcm_substream *substream;
2657         long result;
2658
2659         pcm_oss_file = file->private_data;
2660         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2661         if (substream == NULL)
2662                 return -ENXIO;
2663         substream->f_flags = file->f_flags & O_NONBLOCK;
2664         result = snd_pcm_oss_write1(substream, buf, count);
2665 #ifdef OSS_DEBUG
2666         printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
2667                (long)count, (long)result);
2668 #endif
2669         return result;
2670 }
2671
2672 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
2673 {
2674         struct snd_pcm_runtime *runtime = substream->runtime;
2675         if (atomic_read(&substream->mmap_count))
2676                 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
2677         else
2678                 return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
2679 }
2680
2681 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
2682 {
2683         struct snd_pcm_runtime *runtime = substream->runtime;
2684         if (atomic_read(&substream->mmap_count))
2685                 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
2686         else
2687                 return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
2688 }
2689
2690 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
2691 {
2692         struct snd_pcm_oss_file *pcm_oss_file;
2693         unsigned int mask;
2694         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2695         
2696         pcm_oss_file = file->private_data;
2697
2698         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2699         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2700
2701         mask = 0;
2702         if (psubstream != NULL) {
2703                 struct snd_pcm_runtime *runtime = psubstream->runtime;
2704                 poll_wait(file, &runtime->sleep, wait);
2705                 snd_pcm_stream_lock_irq(psubstream);
2706                 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
2707                     (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
2708                      snd_pcm_oss_playback_ready(psubstream)))
2709                         mask |= POLLOUT | POLLWRNORM;
2710                 snd_pcm_stream_unlock_irq(psubstream);
2711         }
2712         if (csubstream != NULL) {
2713                 struct snd_pcm_runtime *runtime = csubstream->runtime;
2714                 snd_pcm_state_t ostate;
2715                 poll_wait(file, &runtime->sleep, wait);
2716                 snd_pcm_stream_lock_irq(csubstream);
2717                 if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||
2718                     snd_pcm_oss_capture_ready(csubstream))
2719                         mask |= POLLIN | POLLRDNORM;
2720                 snd_pcm_stream_unlock_irq(csubstream);
2721                 if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
2722                         struct snd_pcm_oss_file ofile;
2723                         memset(&ofile, 0, sizeof(ofile));
2724                         ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2725                         runtime->oss.trigger = 0;
2726                         snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
2727                 }
2728         }
2729
2730         return mask;
2731 }
2732
2733 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
2734 {
2735         struct snd_pcm_oss_file *pcm_oss_file;
2736         struct snd_pcm_substream *substream = NULL;
2737         struct snd_pcm_runtime *runtime;
2738         int err;
2739
2740 #ifdef OSS_DEBUG
2741         printk(KERN_DEBUG "pcm_oss: mmap begin\n");
2742 #endif
2743         pcm_oss_file = file->private_data;
2744         switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
2745         case VM_READ | VM_WRITE:
2746                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2747                 if (substream)
2748                         break;
2749                 /* Fall through */
2750         case VM_READ:
2751                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2752                 break;
2753         case VM_WRITE:
2754                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2755                 break;
2756         default:
2757                 return -EINVAL;
2758         }
2759         /* set VM_READ access as well to fix memset() routines that do
2760            reads before writes (to improve performance) */
2761         area->vm_flags |= VM_READ;
2762         if (substream == NULL)
2763                 return -ENXIO;
2764         runtime = substream->runtime;
2765         if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID))
2766                 return -EIO;
2767         if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED)
2768                 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
2769         else
2770                 return -EIO;
2771         
2772         if (runtime->oss.params) {
2773                 if ((err = snd_pcm_oss_change_params(substream)) < 0)
2774                         return err;
2775         }
2776 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2777         if (runtime->oss.plugin_first != NULL)
2778                 return -EIO;
2779 #endif
2780
2781         if (area->vm_pgoff != 0)
2782                 return -EINVAL;
2783
2784         err = snd_pcm_mmap_data(substream, file, area);
2785         if (err < 0)
2786                 return err;
2787         runtime->oss.mmap_bytes = area->vm_end - area->vm_start;
2788         runtime->silence_threshold = 0;
2789         runtime->silence_size = 0;
2790 #ifdef OSS_DEBUG
2791         printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
2792                runtime->oss.mmap_bytes);
2793 #endif
2794         /* In mmap mode we never stop */
2795         runtime->stop_threshold = runtime->boundary;
2796
2797         return 0;
2798 }
2799
2800 #ifdef CONFIG_SND_VERBOSE_PROCFS
2801 /*
2802  *  /proc interface
2803  */
2804
2805 static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
2806                                   struct snd_info_buffer *buffer)
2807 {
2808         struct snd_pcm_str *pstr = entry->private_data;
2809         struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
2810         mutex_lock(&pstr->oss.setup_mutex);
2811         while (setup) {
2812                 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
2813                             setup->task_name,
2814                             setup->periods,
2815                             setup->period_size,
2816                             setup->disable ? " disable" : "",
2817                             setup->direct ? " direct" : "",
2818                             setup->block ? " block" : "",
2819                             setup->nonblock ? " non-block" : "",
2820                             setup->partialfrag ? " partial-frag" : "",
2821                             setup->nosilence ? " no-silence" : "");
2822                 setup = setup->next;
2823         }
2824         mutex_unlock(&pstr->oss.setup_mutex);
2825 }
2826
2827 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
2828 {
2829         struct snd_pcm_oss_setup *setup, *setupn;
2830
2831         for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
2832              setup; setup = setupn) {
2833                 setupn = setup->next;
2834                 kfree(setup->task_name);
2835                 kfree(setup);
2836         }
2837         pstr->oss.setup_list = NULL;
2838 }
2839
2840 static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
2841                                    struct snd_info_buffer *buffer)
2842 {
2843         struct snd_pcm_str *pstr = entry->private_data;
2844         char line[128], str[32], task_name[32];
2845         const char *ptr;
2846         int idx1;
2847         struct snd_pcm_oss_setup *setup, *setup1, template;
2848
2849         while (!snd_info_get_line(buffer, line, sizeof(line))) {
2850                 mutex_lock(&pstr->oss.setup_mutex);
2851                 memset(&template, 0, sizeof(template));
2852                 ptr = snd_info_get_str(task_name, line, sizeof(task_name));
2853                 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
2854                         snd_pcm_oss_proc_free_setup_list(pstr);
2855                         mutex_unlock(&pstr->oss.setup_mutex);
2856                         continue;
2857                 }
2858                 for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
2859                         if (!strcmp(setup->task_name, task_name)) {
2860                                 template = *setup;
2861                                 break;
2862                         }
2863                 }
2864                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2865                 template.periods = simple_strtoul(str, NULL, 10);
2866                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2867                 template.period_size = simple_strtoul(str, NULL, 10);
2868                 for (idx1 = 31; idx1 >= 0; idx1--)
2869                         if (template.period_size & (1 << idx1))
2870                                 break;
2871                 for (idx1--; idx1 >= 0; idx1--)
2872                         template.period_size &= ~(1 << idx1);
2873                 do {
2874                         ptr = snd_info_get_str(str, ptr, sizeof(str));
2875                         if (!strcmp(str, "disable")) {
2876                                 template.disable = 1;
2877                         } else if (!strcmp(str, "direct")) {
2878                                 template.direct = 1;
2879                         } else if (!strcmp(str, "block")) {
2880                                 template.block = 1;
2881                         } else if (!strcmp(str, "non-block")) {
2882                                 template.nonblock = 1;
2883                         } else if (!strcmp(str, "partial-frag")) {
2884                                 template.partialfrag = 1;
2885                         } else if (!strcmp(str, "no-silence")) {
2886                                 template.nosilence = 1;
2887                         } else if (!strcmp(str, "buggy-ptr")) {
2888                                 template.buggyptr = 1;
2889                         }
2890                 } while (*str);
2891                 if (setup == NULL) {
2892                         setup = kmalloc(sizeof(*setup), GFP_KERNEL);
2893                         if (! setup) {
2894                                 buffer->error = -ENOMEM;
2895                                 mutex_unlock(&pstr->oss.setup_mutex);
2896                                 return;
2897                         }
2898                         if (pstr->oss.setup_list == NULL)
2899                                 pstr->oss.setup_list = setup;
2900                         else {
2901                                 for (setup1 = pstr->oss.setup_list;
2902                                      setup1->next; setup1 = setup1->next);
2903                                 setup1->next = setup;
2904                         }
2905                         template.task_name = kstrdup(task_name, GFP_KERNEL);
2906                         if (! template.task_name) {
2907                                 kfree(setup);
2908                                 buffer->error = -ENOMEM;
2909                                 mutex_unlock(&pstr->oss.setup_mutex);
2910                                 return;
2911                         }
2912                 }
2913                 *setup = template;
2914                 mutex_unlock(&pstr->oss.setup_mutex);
2915         }
2916 }
2917
2918 static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
2919 {
2920         int stream;
2921         for (stream = 0; stream < 2; ++stream) {
2922                 struct snd_info_entry *entry;
2923                 struct snd_pcm_str *pstr = &pcm->streams[stream];
2924                 if (pstr->substream_count == 0)
2925                         continue;
2926                 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
2927                         entry->content = SNDRV_INFO_CONTENT_TEXT;
2928                         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
2929                         entry->c.text.read = snd_pcm_oss_proc_read;
2930                         entry->c.text.write = snd_pcm_oss_proc_write;
2931                         entry->private_data = pstr;
2932                         if (snd_info_register(entry) < 0) {
2933                                 snd_info_free_entry(entry);
2934                                 entry = NULL;
2935                         }
2936                 }
2937                 pstr->oss.proc_entry = entry;
2938         }
2939 }
2940
2941 static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
2942 {
2943         int stream;
2944         for (stream = 0; stream < 2; ++stream) {
2945                 struct snd_pcm_str *pstr = &pcm->streams[stream];
2946                 snd_info_free_entry(pstr->oss.proc_entry);
2947                 pstr->oss.proc_entry = NULL;
2948                 snd_pcm_oss_proc_free_setup_list(pstr);
2949         }
2950 }
2951 #else /* !CONFIG_SND_VERBOSE_PROCFS */
2952 #define snd_pcm_oss_proc_init(pcm)
2953 #define snd_pcm_oss_proc_done(pcm)
2954 #endif /* CONFIG_SND_VERBOSE_PROCFS */
2955
2956 /*
2957  *  ENTRY functions
2958  */
2959
2960 static const struct file_operations snd_pcm_oss_f_reg =
2961 {
2962         .owner =        THIS_MODULE,
2963         .read =         snd_pcm_oss_read,
2964         .write =        snd_pcm_oss_write,
2965         .open =         snd_pcm_oss_open,
2966         .release =      snd_pcm_oss_release,
2967         .poll =         snd_pcm_oss_poll,
2968         .unlocked_ioctl =       snd_pcm_oss_ioctl,
2969         .compat_ioctl = snd_pcm_oss_ioctl_compat,
2970         .mmap =         snd_pcm_oss_mmap,
2971 };
2972
2973 static void register_oss_dsp(struct snd_pcm *pcm, int index)
2974 {
2975         char name[128];
2976         sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
2977         if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2978                                     pcm->card, index, &snd_pcm_oss_f_reg,
2979                                     pcm, name) < 0) {
2980                 snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
2981                            pcm->card->number, pcm->device);
2982         }
2983 }
2984
2985 static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
2986 {
2987         pcm->oss.reg = 0;
2988         if (dsp_map[pcm->card->number] == (int)pcm->device) {
2989                 char name[128];
2990                 int duplex;
2991                 register_oss_dsp(pcm, 0);
2992                 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 
2993                               pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 
2994                               !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
2995                 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
2996 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
2997                 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
2998                                       pcm->card->number,
2999                                       name);
3000 #endif
3001                 pcm->oss.reg++;
3002                 pcm->oss.reg_mask |= 1;
3003         }
3004         if (adsp_map[pcm->card->number] == (int)pcm->device) {
3005                 register_oss_dsp(pcm, 1);
3006                 pcm->oss.reg++;
3007                 pcm->oss.reg_mask |= 2;
3008         }
3009
3010         if (pcm->oss.reg)
3011                 snd_pcm_oss_proc_init(pcm);
3012
3013         return 0;
3014 }
3015
3016 static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm)
3017 {
3018         if (pcm->oss.reg) {
3019                 if (pcm->oss.reg_mask & 1) {
3020                         pcm->oss.reg_mask &= ~1;
3021                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3022                                                   pcm->card, 0);
3023                 }
3024                 if (pcm->oss.reg_mask & 2) {
3025                         pcm->oss.reg_mask &= ~2;
3026                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3027                                                   pcm->card, 1);
3028                 }
3029                 if (dsp_map[pcm->card->number] == (int)pcm->device) {
3030 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
3031                         snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
3032 #endif
3033                 }
3034                 pcm->oss.reg = 0;
3035         }
3036         return 0;
3037 }
3038
3039 static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm)
3040 {
3041         snd_pcm_oss_disconnect_minor(pcm);
3042         snd_pcm_oss_proc_done(pcm);
3043         return 0;
3044 }
3045
3046 static struct snd_pcm_notify snd_pcm_oss_notify =
3047 {
3048         .n_register =   snd_pcm_oss_register_minor,
3049         .n_disconnect = snd_pcm_oss_disconnect_minor,
3050         .n_unregister = snd_pcm_oss_unregister_minor,
3051 };
3052
3053 static int __init alsa_pcm_oss_init(void)
3054 {
3055         int i;
3056         int err;
3057
3058         /* check device map table */
3059         for (i = 0; i < SNDRV_CARDS; i++) {
3060                 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) {
3061                         snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n",
3062                                    i, dsp_map[i]);
3063                         dsp_map[i] = 0;
3064                 }
3065                 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) {
3066                         snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n",
3067                                    i, adsp_map[i]);
3068                         adsp_map[i] = 1;
3069                 }
3070         }
3071         if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0)
3072                 return err;
3073         return 0;
3074 }
3075
3076 static void __exit alsa_pcm_oss_exit(void)
3077 {
3078         snd_pcm_notify(&snd_pcm_oss_notify, 1);
3079 }
3080
3081 module_init(alsa_pcm_oss_init)
3082 module_exit(alsa_pcm_oss_exit)