This source file includes following definitions.
- set_format
- audio_open
- audio_release
- translate_bytes
- translate_bytes
- audio_write
- audio_read
- audio_ioctl
- audio_init
- audio_select
- audio_read
- audio_write
- audio_open
- audio_release
- audio_ioctl
- audio_lseek
- audio_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include "sound_config.h"
31
32 #ifdef CONFIGURE_SOUNDCARD
33 #ifndef EXCLUDE_AUDIO
34
35 #include "ulaw.h"
36 #include "coproc.h"
37
38 #define ON 1
39 #define OFF 0
40
41 static int wr_buff_no[MAX_AUDIO_DEV];
42
43
44
45
46
47 static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
48
49 static int audio_mode[MAX_AUDIO_DEV];
50 static int dev_nblock[MAX_AUDIO_DEV];
51
52 #define AM_NONE 0
53 #define AM_WRITE 1
54 #define AM_READ 2
55
56 static char *wr_dma_buf[MAX_AUDIO_DEV];
57 static int audio_format[MAX_AUDIO_DEV];
58 static int local_conversion[MAX_AUDIO_DEV];
59
60 static int
61 set_format (int dev, int fmt)
62 {
63 if (fmt != AFMT_QUERY)
64 {
65
66 local_conversion[dev] = 0;
67
68 if (!(audio_devs[dev]->format_mask & fmt))
69 if (fmt == AFMT_MU_LAW)
70 {
71 fmt = AFMT_U8;
72 local_conversion[dev] = AFMT_MU_LAW;
73 }
74 else
75 fmt = AFMT_U8;
76
77 audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1);
78 }
79
80 if (local_conversion[dev])
81 return local_conversion[dev];
82
83 return audio_format[dev];
84 }
85
86 int
87 audio_open (int dev, struct fileinfo *file)
88 {
89 int ret;
90 int bits;
91 int dev_type = dev & 0x0f;
92 int mode = file->mode & O_ACCMODE;
93
94 dev = dev >> 4;
95
96 if (dev_type == SND_DEV_DSP16)
97 bits = 16;
98 else
99 bits = 8;
100
101 if ((ret = DMAbuf_open (dev, mode)) < 0)
102 return ret;
103
104 if (audio_devs[dev]->coproc)
105 if ((ret = audio_devs[dev]->coproc->
106 open (audio_devs[dev]->coproc->devc, COPR_PCM)) < 0)
107 {
108 audio_release (dev, file);
109 printk ("Sound: Can't access coprocessor device\n");
110
111 return ret;
112 }
113
114 local_conversion[dev] = 0;
115
116 if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits)
117 {
118 audio_release (dev, file);
119 return -ENXIO;
120 }
121
122 if (dev_type == SND_DEV_AUDIO)
123 {
124 set_format (dev, AFMT_MU_LAW);
125 }
126 else
127 set_format (dev, bits);
128
129 wr_buff_no[dev] = -1;
130 audio_mode[dev] = AM_NONE;
131 wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
132 dev_nblock[dev] = 0;
133
134 return ret;
135 }
136
137 void
138 audio_release (int dev, struct fileinfo *file)
139 {
140 int mode;
141
142 dev = dev >> 4;
143 mode = file->mode & O_ACCMODE;
144
145 if (wr_buff_no[dev] >= 0)
146 {
147 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
148
149 wr_buff_no[dev] = -1;
150 }
151
152 if (audio_devs[dev]->coproc)
153 audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM);
154 DMAbuf_release (dev, mode);
155 }
156
157 #if !defined(i386)
158 static void
159 translate_bytes (const unsigned char *table, unsigned char *buff, int n)
160 {
161 unsigned long i;
162
163 if (n <= 0)
164 return;
165
166 for (i = 0; i < n; ++i)
167 buff[i] = table[buff[i]];
168 }
169
170 #else
171 extern inline void
172 translate_bytes (const void *table, void *buff, int n)
173 {
174 if (n > 0)
175 {
176 __asm__ ("cld\n"
177 "1:\tlodsb\n\t"
178 "xlatb\n\t"
179 "stosb\n\t"
180 "loop 1b\n\t":
181 : "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
182 : "bx", "cx", "di", "si", "ax");
183 }
184 }
185 #endif
186
187 int
188 audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
189 {
190 int c, p, l;
191 int err;
192
193 dev = dev >> 4;
194
195 p = 0;
196 c = count;
197
198 if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
199 {
200 wr_buff_no[dev] = -1;
201 }
202
203 if (audio_devs[dev]->flags & DMA_DUPLEX)
204 audio_mode[dev] |= AM_WRITE;
205 else
206 audio_mode[dev] = AM_WRITE;
207
208 if (!count)
209
210
211 {
212 if (wr_buff_no[dev] >= 0)
213 {
214 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
215
216 wr_buff_no[dev] = -1;
217 }
218 return 0;
219 }
220
221 while (c)
222 {
223
224
225 if (wr_buff_no[dev] < 0)
226
227
228 {
229 if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev],
230 &wr_buff_size[dev],
231 dev_nblock[dev])) < 0)
232 {
233
234 if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN)
235 return p;
236 return wr_buff_no[dev];
237 }
238 wr_buff_ptr[dev] = 0;
239 }
240
241 l = c;
242 if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
243 l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
244
245 if (!audio_devs[dev]->copy_from_user)
246 {
247
248
249 memcpy_fromfs (&wr_dma_buf[dev][wr_buff_ptr[dev]], &((buf)[p]), l);
250 }
251 else
252 audio_devs[dev]->copy_from_user (dev,
253 wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
254
255
256
257
258
259
260 if (local_conversion[dev] == AFMT_MU_LAW)
261 {
262
263
264
265 sti();
266 translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
267 }
268
269 c -= l;
270 p += l;
271 wr_buff_ptr[dev] += l;
272
273 if (wr_buff_ptr[dev] >= wr_buff_size[dev])
274 {
275 if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
276 {
277 return err;
278 }
279
280 wr_buff_no[dev] = -1;
281 }
282
283 }
284
285 return count;
286 }
287
288 int
289 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
290 {
291 int c, p, l;
292 char *dmabuf;
293 int buff_no;
294
295 dev = dev >> 4;
296 p = 0;
297 c = count;
298
299 if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
300 {
301 if (wr_buff_no[dev] >= 0)
302 {
303 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
304
305 if (!(audio_devs[dev]->flags & DMA_DUPLEX))
306 wr_buff_no[dev] = -1;
307 }
308 }
309
310 if (audio_devs[dev]->flags & DMA_DUPLEX)
311 audio_mode[dev] |= AM_READ;
312 else
313 audio_mode[dev] = AM_READ;
314
315 while (c)
316 {
317 if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
318 dev_nblock[dev])) < 0)
319 {
320
321
322 if (dev_nblock[dev] && buff_no == -EAGAIN)
323 return p;
324
325 return buff_no;
326 }
327
328 if (l > c)
329 l = c;
330
331
332
333
334
335 if (local_conversion[dev] == AFMT_MU_LAW)
336 {
337
338
339
340 sti();
341
342 translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
343 }
344
345 memcpy_tofs (&((buf)[p]), dmabuf, l);
346
347 DMAbuf_rmchars (dev, buff_no, l);
348
349 p += l;
350 c -= l;
351 }
352
353 return count - c;
354 }
355
356 int
357 audio_ioctl (int dev, struct fileinfo *file,
358 unsigned int cmd, ioctl_arg arg)
359 {
360
361 dev = dev >> 4;
362
363 if (((cmd >> 8) & 0xff) == 'C')
364 {
365 if (audio_devs[dev]->coproc)
366 return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
367 else
368 printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
369
370 return -ENXIO;
371 }
372 else
373 switch (cmd)
374 {
375 case SNDCTL_DSP_SYNC:
376 if (wr_buff_no[dev] >= 0)
377 {
378 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
379
380 wr_buff_no[dev] = -1;
381 }
382 return DMAbuf_ioctl (dev, cmd, arg, 0);
383 break;
384
385 case SNDCTL_DSP_POST:
386 if (wr_buff_no[dev] >= 0)
387 {
388 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
389
390 wr_buff_no[dev] = -1;
391 }
392 return 0;
393 break;
394
395 case SNDCTL_DSP_RESET:
396 wr_buff_no[dev] = -1;
397 audio_mode[dev] = AM_NONE;
398 return DMAbuf_ioctl (dev, cmd, arg, 0);
399 break;
400
401 case SNDCTL_DSP_GETFMTS:
402 return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask);
403 break;
404
405 case SNDCTL_DSP_SETFMT:
406 return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
407
408 case SNDCTL_DSP_GETISPACE:
409 if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
410 return -EBUSY;
411
412 {
413 audio_buf_info info;
414
415 int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
416
417 if (err < 0)
418 return err;
419
420 memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
421 return 0;
422 }
423
424 case SNDCTL_DSP_GETOSPACE:
425 if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
426 return -EBUSY;
427
428 {
429 audio_buf_info info;
430
431 int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
432
433 if (err < 0)
434 return err;
435
436 if (wr_buff_no[dev] != -1)
437 info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
438
439 memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
440 return 0;
441 }
442
443 case SNDCTL_DSP_NONBLOCK:
444 dev_nblock[dev] = 1;
445 return 0;
446 break;
447
448 case SNDCTL_DSP_GETCAPS:
449 {
450 int info = 1;
451
452 if (audio_devs[dev]->flags & DMA_DUPLEX)
453 info |= DSP_CAP_DUPLEX;
454
455 if (audio_devs[dev]->coproc)
456 info |= DSP_CAP_COPROC;
457
458 if (audio_devs[dev]->local_qlen)
459 info |= DSP_CAP_BATCH;
460
461 if (audio_devs[dev]->trigger)
462 info |= DSP_CAP_TRIGGER;
463
464 memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
465 return 0;
466 }
467 break;
468
469 default:
470 return DMAbuf_ioctl (dev, cmd, arg, 0);
471 }
472 }
473
474 long
475 audio_init (long mem_start)
476 {
477
478
479
480 return mem_start;
481 }
482
483 int
484 audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
485 {
486
487 dev = dev >> 4;
488
489 switch (sel_type)
490 {
491 case SEL_IN:
492 if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
493 return 0;
494
495
496 return DMAbuf_select (dev, file, sel_type, wait);
497 break;
498
499 case SEL_OUT:
500 if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
501 return 0;
502
503 if (wr_buff_no[dev] != -1)
504 return 1;
505
506 return DMAbuf_select (dev, file, sel_type, wait);
507 break;
508
509 case SEL_EX:
510 return 0;
511 }
512
513 return 0;
514 }
515
516
517 #else
518
519
520
521
522 int
523 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
524 {
525 return -EIO;
526 }
527
528 int
529 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
530 {
531 return -EIO;
532 }
533
534 int
535 audio_open (int dev, struct fileinfo *file)
536 {
537 return -ENXIO;
538 }
539
540 void
541 audio_release (int dev, struct fileinfo *file)
542 {
543 };
544 int
545 audio_ioctl (int dev, struct fileinfo *file,
546 unsigned int cmd, unsigned int arg)
547 {
548 return -EIO;
549 }
550
551 int
552 audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
553 {
554 return -EIO;
555 }
556
557 long
558 audio_init (long mem_start)
559 {
560 return mem_start;
561 }
562
563 #endif
564
565 #endif