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
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, long 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 long 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(NO_INLINE_ASM) || !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
186 #endif
187
188 int
189 audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
190 {
191 int c, p, l;
192 int err;
193
194 dev = dev >> 4;
195
196 p = 0;
197 c = count;
198
199 if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
200 {
201 wr_buff_no[dev] = -1;
202 }
203
204 if (audio_devs[dev]->flags & DMA_DUPLEX)
205 audio_mode[dev] |= AM_WRITE;
206 else
207 audio_mode[dev] = AM_WRITE;
208
209 if (!count)
210
211
212 {
213 if (wr_buff_no[dev] >= 0)
214 {
215 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
216
217 wr_buff_no[dev] = -1;
218 }
219 return 0;
220 }
221
222 while (c)
223 {
224
225
226 if (wr_buff_no[dev] < 0)
227
228
229 {
230 if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev],
231 &wr_buff_size[dev],
232 dev_nblock[dev])) < 0)
233 {
234
235 if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN)
236 return p;
237 return wr_buff_no[dev];
238 }
239 wr_buff_ptr[dev] = 0;
240 }
241
242 l = c;
243 if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
244 l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
245
246 if (!audio_devs[dev]->copy_from_user)
247 {
248
249
250 memcpy_fromfs (&wr_dma_buf[dev][wr_buff_ptr[dev]], &((buf)[p]), l);
251 }
252 else
253 audio_devs[dev]->copy_from_user (dev,
254 wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
255
256
257
258
259
260
261 if (local_conversion[dev] == AFMT_MU_LAW)
262 {
263
264
265
266 sti ();
267 translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
268 }
269
270 c -= l;
271 p += l;
272 wr_buff_ptr[dev] += l;
273
274 if (wr_buff_ptr[dev] >= wr_buff_size[dev])
275 {
276 if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
277 {
278 return err;
279 }
280
281 wr_buff_no[dev] = -1;
282 }
283
284 }
285
286 return count;
287 }
288
289 int
290 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
291 {
292 int c, p, l;
293 char *dmabuf;
294 int buff_no;
295
296 dev = dev >> 4;
297 p = 0;
298 c = count;
299
300 if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
301 {
302 if (wr_buff_no[dev] >= 0)
303 {
304 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
305
306 if (!(audio_devs[dev]->flags & DMA_DUPLEX))
307 wr_buff_no[dev] = -1;
308 }
309 }
310
311 if (audio_devs[dev]->flags & DMA_DUPLEX)
312 audio_mode[dev] |= AM_READ;
313 else
314 audio_mode[dev] = AM_READ;
315
316 while (c)
317 {
318 if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
319 dev_nblock[dev])) < 0)
320 {
321
322
323 if (dev_nblock[dev] && buff_no == -EAGAIN)
324 return p;
325
326 return buff_no;
327 }
328
329 if (l > c)
330 l = c;
331
332
333
334
335
336 if (local_conversion[dev] == AFMT_MU_LAW)
337 {
338
339
340
341 sti ();
342
343 translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
344 }
345
346 memcpy_tofs (&((buf)[p]), dmabuf, l);
347
348 DMAbuf_rmchars (dev, buff_no, l);
349
350 p += l;
351 c -= l;
352 }
353
354 return count - c;
355 }
356
357 int
358 audio_ioctl (int dev, struct fileinfo *file,
359 unsigned int cmd, ioctl_arg arg)
360 {
361
362 dev = dev >> 4;
363
364 if (((cmd >> 8) & 0xff) == 'C')
365 {
366 if (audio_devs[dev]->coproc)
367 return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
368 else
369 printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
370
371 return -ENXIO;
372 }
373 else
374 switch (cmd)
375 {
376 case SNDCTL_DSP_SYNC:
377 if (wr_buff_no[dev] >= 0)
378 {
379 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
380
381 wr_buff_no[dev] = -1;
382 }
383 return DMAbuf_ioctl (dev, cmd, arg, 0);
384 break;
385
386 case SNDCTL_DSP_POST:
387 if (wr_buff_no[dev] >= 0)
388 {
389 DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
390
391 wr_buff_no[dev] = -1;
392 }
393 return 0;
394 break;
395
396 case SNDCTL_DSP_RESET:
397 wr_buff_no[dev] = -1;
398 audio_mode[dev] = AM_NONE;
399 return DMAbuf_ioctl (dev, cmd, arg, 0);
400 break;
401
402 case SNDCTL_DSP_GETFMTS:
403 return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask);
404 break;
405
406 case SNDCTL_DSP_SETFMT:
407 return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
408
409 case SNDCTL_DSP_GETISPACE:
410 if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
411 return -EBUSY;
412
413 {
414 audio_buf_info info;
415
416 int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
417
418 if (err < 0)
419 return err;
420
421 memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
422 return 0;
423 }
424
425 case SNDCTL_DSP_GETOSPACE:
426 if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
427 return -EBUSY;
428
429 {
430 audio_buf_info info;
431
432 int err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
433
434 if (err < 0)
435 return err;
436
437 if (wr_buff_no[dev] != -1)
438 info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
439
440 memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
441 return 0;
442 }
443
444 case SNDCTL_DSP_NONBLOCK:
445 dev_nblock[dev] = 1;
446 return 0;
447 break;
448
449 case SNDCTL_DSP_GETCAPS:
450 {
451 int info = 1;
452
453 if (audio_devs[dev]->flags & DMA_DUPLEX)
454 info |= DSP_CAP_DUPLEX;
455
456 if (audio_devs[dev]->coproc)
457 info |= DSP_CAP_COPROC;
458
459 if (audio_devs[dev]->local_qlen)
460 info |= DSP_CAP_BATCH;
461
462 if (audio_devs[dev]->trigger)
463 info |= DSP_CAP_TRIGGER;
464
465 memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
466 return 0;
467 }
468 break;
469
470 default:
471 return DMAbuf_ioctl (dev, cmd, arg, 0);
472 }
473 }
474
475 long
476 audio_init (long mem_start)
477 {
478
479
480
481 return mem_start;
482 }
483
484 int
485 audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
486 {
487
488 dev = dev >> 4;
489
490 switch (sel_type)
491 {
492 case SEL_IN:
493 if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
494 return 0;
495
496
497 return DMAbuf_select (dev, file, sel_type, wait);
498 break;
499
500 case SEL_OUT:
501 if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
502 return 0;
503
504 if (wr_buff_no[dev] != -1)
505 {
506 return 1;
507 }
508
509 return DMAbuf_select (dev, file, sel_type, wait);
510 break;
511
512 case SEL_EX:
513 return 0;
514 }
515
516 return 0;
517 }
518
519
520 #endif
521 #endif