Commit | Line | Data |
---|---|---|
1b261ae5 JH |
1 | /* |
2 | * linux/kernel/chr_drv/sound/dmabuf.c | |
3 | * | |
4 | * The DMA buffer manager for digitized voice applications | |
5 | * | |
6 | * (C) 1992 Hannu Savolainen (hsavolai@cs.helsinki.fi) See COPYING for further | |
7 | * details. Should be distributed with this file. | |
8 | */ | |
9 | ||
10 | #include "sound_config.h" | |
11 | ||
12 | #ifdef CONFIGURE_SOUNDCARD | |
13 | ||
14 | #include "sound_calls.h" | |
15 | ||
16 | #if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS) | |
17 | ||
18 | #define MAX_SUB_BUFFERS 16 | |
19 | ||
20 | /* | |
21 | * The DSP channel can be used either for input or output. Variable | |
22 | * 'dma_mode' will be set when the program calls read or write first time | |
23 | * after open. Current version doesn't support mode changes without closing | |
24 | * and reopening the device. Support for this feature may be implemented in a | |
25 | * future version of this driver. | |
26 | */ | |
27 | ||
28 | #define DMODE_NONE 0 | |
29 | #define DMODE_OUTPUT 1 | |
30 | #define DMODE_INPUT 2 | |
31 | #define DMODE_INIT 3 | |
32 | ||
33 | DEFINE_WAIT_QUEUES (dev_sleeper[MAX_DSP_DEV], dev_sleep_flag[MAX_DSP_DEV]); | |
34 | ||
35 | static int dma_mode[MAX_DSP_DEV] = | |
36 | {0}; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */ | |
37 | ||
38 | static volatile int dmabuf_interrupted[MAX_DSP_DEV] = | |
39 | {0}; | |
40 | ||
41 | #ifdef ISC | |
42 | /* I don't like this. */ | |
43 | #undef INTERRUPTIBLE_SLEEP_ON | |
44 | #define INTERRUPTIBLE_SLEEP_ON(A,F) { \ | |
45 | A = F = 1; \ | |
46 | if (sleep(&(A), (PZERO + 5) | PCATCH)) { \ | |
47 | A = F = 0; \ | |
48 | dmabuf_interrupted[dev] = 1; \ | |
49 | dev_busy[dev] = 0; \ | |
50 | dma_reset(dev); \ | |
51 | dmabuf_interrupted[dev] = 0; \ | |
52 | /* longjmp(u.u_qsav, 1); Where it goes??? */ \ | |
53 | } \ | |
54 | } | |
55 | #endif | |
56 | ||
57 | /* | |
58 | * Pointers to raw buffers | |
59 | */ | |
60 | ||
61 | char *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT]; | |
62 | unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT]; | |
63 | int snd_raw_count[MAX_DSP_DEV]; | |
64 | ||
65 | /* | |
66 | * Device state tables | |
67 | */ | |
68 | ||
69 | static int dev_busy[MAX_DSP_DEV]; | |
70 | static int dev_active[MAX_DSP_DEV]; | |
71 | static int dev_qlen[MAX_DSP_DEV]; | |
72 | static int dev_qhead[MAX_DSP_DEV]; | |
73 | static int dev_qtail[MAX_DSP_DEV]; | |
74 | static int dev_underrun[MAX_DSP_DEV]; | |
75 | static int bufferalloc_done[MAX_DSP_DEV] = | |
76 | {0}; | |
77 | ||
78 | /* | |
79 | * Logical buffers for each devices | |
80 | */ | |
81 | ||
82 | static int dev_nbufs[MAX_DSP_DEV]; /* # of logical buffers ( >= | |
83 | * sound_buffcounts[dev] */ | |
84 | static int dev_counts[MAX_DSP_DEV][MAX_SUB_BUFFERS]; | |
85 | static unsigned long dev_buf_phys[MAX_DSP_DEV][MAX_SUB_BUFFERS]; | |
86 | static char *dev_buf[MAX_DSP_DEV][MAX_SUB_BUFFERS]; | |
87 | static int dev_buffsize[MAX_DSP_DEV]; | |
88 | ||
89 | static void | |
90 | reorganize_buffers (int dev) | |
91 | { | |
92 | /* | |
93 | * This routine breaks the physical device buffers to logical ones. | |
94 | */ | |
95 | ||
96 | unsigned long i, p, n; | |
97 | unsigned long sr, nc, sz, bsz; | |
98 | ||
99 | sr = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1); | |
100 | nc = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1); | |
101 | sz = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1); | |
102 | ||
103 | if (sr < 1 || nc < 1 || sz < 1) | |
104 | { | |
105 | printk ("SOUND: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz); | |
106 | sr = DSP_DEFAULT_SPEED; | |
107 | nc = 1; | |
108 | sz = 8; | |
109 | } | |
110 | ||
111 | sz /= 8; /* Convert # of bits -> # of bytes */ | |
112 | ||
113 | sz = sr * nc * sz; | |
114 | ||
115 | /* | |
116 | * Compute a buffer size not exeeding 1 second. | |
117 | */ | |
118 | ||
119 | bsz = sound_buffsizes[dev]; | |
120 | ||
121 | while (bsz > sz) | |
122 | bsz >>= 1; /* Divide by 2 */ | |
123 | ||
124 | if (sound_buffcounts[dev] == 1 && bsz == sound_buffsizes[dev]) | |
125 | bsz >>= 1; /* Need at least 2 buffers */ | |
126 | ||
127 | dev_buffsize[dev] = bsz; | |
128 | n = 0; | |
129 | ||
130 | /* | |
131 | * Now computing addresses for the logical buffers | |
132 | */ | |
133 | ||
134 | for (i = 0; i < snd_raw_count[dev]; i++) | |
135 | { | |
136 | p = 0; | |
137 | ||
138 | while ((p + bsz) <= sound_buffsizes[dev]) | |
139 | { | |
140 | dev_buf[dev][n] = snd_raw_buf[dev][i] + p; | |
141 | dev_buf_phys[dev][n] = snd_raw_buf_phys[dev][i] + p; | |
142 | p += bsz; | |
143 | n++; | |
144 | } | |
145 | } | |
146 | ||
147 | dev_nbufs[dev] = n; | |
148 | ||
149 | for (i = 0; i < dev_nbufs[dev]; i++) | |
150 | { | |
151 | dev_counts[dev][i] = 0; | |
152 | } | |
153 | ||
154 | bufferalloc_done[dev] = 1; | |
155 | } | |
156 | ||
157 | int | |
158 | DMAbuf_open (int dev, int mode) | |
159 | { | |
160 | int retval; | |
161 | ||
162 | if (dev >= num_dspdevs) | |
163 | { | |
164 | printk ("PCM device %d not installed.\n", dev); | |
165 | return RET_ERROR (ENXIO); | |
166 | } | |
167 | ||
168 | if (dev_busy[dev]) | |
169 | return RET_ERROR (EBUSY); | |
170 | ||
171 | if (!dsp_devs[dev]) | |
172 | { | |
173 | printk ("DSP device %d not initialized\n", dev); | |
174 | return RET_ERROR (ENXIO); | |
175 | } | |
176 | ||
177 | if (sound_buffcounts[dev] <= 0) | |
178 | return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */ | |
179 | ||
180 | if ((retval = dsp_devs[dev]->open (dev, mode)) < 0) | |
181 | return retval; | |
182 | ||
183 | dev_underrun[dev] = 0; | |
184 | ||
185 | dev_busy[dev] = 1; | |
186 | ||
187 | reorganize_buffers (dev); | |
188 | bufferalloc_done[dev] = 0; | |
189 | ||
190 | dev_qlen[dev] = dev_qtail[dev] = dev_qhead[dev] = 0; | |
191 | ||
192 | return 0; | |
193 | } | |
194 | ||
195 | static void | |
196 | dma_reset (int dev) | |
197 | { | |
198 | dsp_devs[dev]->reset (dev); | |
199 | ||
200 | dev_qlen[dev] = 0; | |
201 | dev_qhead[dev] = 0; | |
202 | dev_qtail[dev] = 0; | |
203 | dev_active[dev] = 0; | |
204 | } | |
205 | ||
206 | static int | |
207 | dma_sync (int dev) | |
208 | { | |
209 | unsigned long flags; | |
210 | unsigned long time; | |
211 | int timed_out; | |
212 | ||
213 | if (dma_mode[dev] == DMODE_OUTPUT) | |
214 | { | |
215 | DISABLE_INTR (flags); | |
216 | ||
217 | timed_out = 0; | |
218 | time = GET_TIME (); | |
219 | ||
220 | while ((!(PROCESS_ABORTING || dmabuf_interrupted[dev]) && !timed_out) | |
221 | && dev_qlen[dev]) | |
222 | { | |
223 | REQUEST_TIMEOUT (10 * HZ, dev_sleeper[dev]); | |
224 | INTERRUPTIBLE_SLEEP_ON (dev_sleeper[dev], dev_sleep_flag[dev]); | |
225 | if ((GET_TIME () - time) > (10 * HZ)) | |
226 | timed_out = 1; | |
227 | } | |
228 | RESTORE_INTR (flags); | |
229 | ||
230 | /* | |
231 | * Some devices such as GUS have huge amount of on board RAM for the | |
232 | * audio data. We have to wait util the device has finished playing. | |
233 | */ | |
234 | ||
235 | DISABLE_INTR (flags); | |
236 | if (dsp_devs[dev]->has_output_drained) /* Device has hidden buffers */ | |
237 | { | |
238 | while (!(PROCESS_ABORTING || dmabuf_interrupted[dev]) | |
239 | && !dsp_devs[dev]->has_output_drained (dev)) | |
240 | { | |
241 | REQUEST_TIMEOUT (HZ / 4, dev_sleeper[dev]); | |
242 | INTERRUPTIBLE_SLEEP_ON (dev_sleeper[dev], dev_sleep_flag[dev]); | |
243 | } | |
244 | } | |
245 | RESTORE_INTR (flags); | |
246 | } | |
247 | return dev_qlen[dev]; | |
248 | } | |
249 | ||
250 | int | |
251 | DMAbuf_release (int dev, int mode) | |
252 | { | |
253 | ||
254 | if (!(PROCESS_ABORTING || dmabuf_interrupted[dev]) | |
255 | && (dma_mode[dev] == DMODE_OUTPUT)) | |
256 | { | |
257 | dma_sync (dev); | |
258 | } | |
259 | ||
260 | dma_reset (dev); | |
261 | ||
262 | if (!dev_active[dev]) | |
263 | dsp_devs[dev]->close (dev); | |
264 | ||
265 | dma_mode[dev] = DMODE_NONE; | |
266 | dev_busy[dev] = 0; | |
267 | ||
268 | return 0; | |
269 | } | |
270 | ||
271 | int | |
272 | DMAbuf_getrdbuffer (int dev, char **buf, int *len) | |
273 | { | |
274 | unsigned long flags; | |
275 | ||
276 | if (!bufferalloc_done[dev]) | |
277 | reorganize_buffers (dev); | |
278 | ||
279 | if (!dma_mode[dev]) | |
280 | { | |
281 | int err; | |
282 | ||
283 | if ((err = dsp_devs[dev]->prepare_for_input (dev, | |
284 | dev_buffsize[dev], dev_nbufs[dev])) < 0) | |
285 | return err; | |
286 | dma_mode[dev] = DMODE_INPUT; | |
287 | } | |
288 | ||
289 | if (dma_mode[dev] != DMODE_INPUT) | |
290 | return RET_ERROR (EBUSY); /* Can't change mode on fly */ | |
291 | ||
292 | DISABLE_INTR (flags); | |
293 | if (!dev_qlen[dev]) | |
294 | { | |
295 | if (!dev_active[dev]) | |
296 | { | |
297 | dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], dev_buffsize[dev], 0); | |
298 | dev_active[dev] = 1; | |
299 | } | |
300 | ||
301 | /* Wait for the next block */ | |
302 | #ifdef CRYPTO | |
303 | REQUEST_TIMEOUT (60 * HZ, dev_sleeper[dev]); | |
304 | #else | |
305 | REQUEST_TIMEOUT (10 * HZ, dev_sleeper[dev]); | |
306 | #endif | |
307 | INTERRUPTIBLE_SLEEP_ON (dev_sleeper[dev], dev_sleep_flag[dev]); | |
308 | } | |
309 | RESTORE_INTR (flags); | |
310 | ||
311 | if (!dev_qlen[dev]) | |
312 | return RET_ERROR (EINTR); | |
313 | ||
314 | *buf = &dev_buf[dev][dev_qhead[dev]][dev_counts[dev][dev_qhead[dev]]]; | |
315 | *len = dev_buffsize[dev] - dev_counts[dev][dev_qhead[dev]]; | |
316 | ||
317 | return dev_qhead[dev]; | |
318 | } | |
319 | ||
320 | int | |
321 | DMAbuf_rmchars (int dev, int buff_no, int c) | |
322 | { | |
323 | int p = dev_counts[dev][dev_qhead[dev]] + c; | |
324 | ||
325 | if (p >= dev_buffsize[dev]) | |
326 | { /* This buffer is now empty */ | |
327 | dev_counts[dev][dev_qhead[dev]] = 0; | |
328 | dev_qlen[dev]--; | |
329 | dev_qhead[dev] = (dev_qhead[dev] + 1) % dev_nbufs[dev]; | |
330 | } | |
331 | else | |
332 | dev_counts[dev][dev_qhead[dev]] = p; | |
333 | ||
334 | return 0; | |
335 | } | |
336 | ||
337 | int | |
338 | DMAbuf_read (int dev, snd_rw_buf * user_buf, int count) | |
339 | { | |
340 | char *dmabuf; | |
341 | int buff_no, c, err; | |
342 | ||
343 | /* | |
344 | * This routine returns at most 'count' bytes from the dsp input buffers. | |
345 | * Returns negative value if there is an error. | |
346 | */ | |
347 | ||
348 | if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &c)) < 0) | |
349 | return buff_no; | |
350 | ||
351 | if (c > count) | |
352 | c = count; | |
353 | ||
354 | COPY_TO_USER (user_buf, 0, dmabuf, c); | |
355 | ||
356 | if ((err = DMAbuf_rmchars (dev, buff_no, c)) < 0) | |
357 | return err; | |
358 | return c; | |
359 | ||
360 | } | |
361 | ||
362 | int | |
363 | DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) | |
364 | { | |
365 | switch (cmd) | |
366 | { | |
367 | case SNDCTL_DSP_RESET: | |
368 | dma_reset (dev); | |
369 | return 0; | |
370 | break; | |
371 | ||
372 | case SNDCTL_DSP_SYNC: | |
373 | dma_sync (dev); | |
374 | return 0; | |
375 | break; | |
376 | ||
377 | case SNDCTL_DSP_GETBLKSIZE: | |
378 | if (!bufferalloc_done[dev]) | |
379 | reorganize_buffers (dev); | |
380 | ||
381 | return IOCTL_OUT (arg, dev_buffsize[dev]); | |
382 | break; | |
383 | ||
384 | default: | |
385 | return dsp_devs[dev]->ioctl (dev, cmd, arg, local); | |
386 | } | |
387 | ||
388 | return RET_ERROR (EIO); | |
389 | } | |
390 | ||
391 | int | |
392 | DMAbuf_getwrbuffer (int dev, char **buf, int *size) | |
393 | { | |
394 | unsigned long flags; | |
395 | ||
396 | if (!bufferalloc_done[dev]) | |
397 | reorganize_buffers (dev); | |
398 | ||
399 | if (!dma_mode[dev]) | |
400 | { | |
401 | int err; | |
402 | ||
403 | dma_mode[dev] = DMODE_OUTPUT; | |
404 | if ((err = dsp_devs[dev]->prepare_for_output (dev, | |
405 | dev_buffsize[dev], dev_nbufs[dev])) < 0) | |
406 | return err; | |
407 | } | |
408 | ||
409 | if (dma_mode[dev] != DMODE_OUTPUT) | |
410 | return RET_ERROR (EBUSY); /* Can't change mode on fly */ | |
411 | ||
412 | DISABLE_INTR (flags); | |
413 | if (dev_qlen[dev] == dev_nbufs[dev]) | |
414 | { | |
415 | if (!dev_active[dev]) | |
416 | { | |
417 | printk ("Soundcard warning: DMA not activated %d/%d\n", | |
418 | dev_qlen[dev], dev_nbufs[dev]); | |
419 | return RET_ERROR (EIO); | |
420 | } | |
421 | ||
422 | /* Wait for free space */ | |
423 | REQUEST_TIMEOUT (60 * HZ, dev_sleeper[dev]); /* Overestimated timeout */ | |
424 | INTERRUPTIBLE_SLEEP_ON (dev_sleeper[dev], dev_sleep_flag[dev]); | |
425 | } | |
426 | RESTORE_INTR (flags); | |
427 | ||
428 | if (dev_qlen[dev] == dev_nbufs[dev]) | |
429 | return RET_ERROR (EIO); /* We have got signal (?) */ | |
430 | ||
431 | *buf = dev_buf[dev][dev_qtail[dev]]; | |
432 | *size = dev_buffsize[dev]; | |
433 | dev_counts[dev][dev_qtail[dev]] = 0; | |
434 | ||
435 | return dev_qtail[dev]; | |
436 | } | |
437 | ||
438 | int | |
439 | DMAbuf_start_output (int dev, int buff_no, int l) | |
440 | { | |
441 | if (buff_no != dev_qtail[dev]) | |
442 | printk ("Soundcard warning: DMA buffers out of sync %d != %d\n", buff_no, dev_qtail[dev]); | |
443 | ||
444 | dev_qlen[dev]++; | |
445 | ||
446 | dev_counts[dev][dev_qtail[dev]] = l; | |
447 | ||
448 | dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev]; | |
449 | ||
450 | if (!dev_active[dev]) | |
451 | { | |
452 | dev_active[dev] = 1; | |
453 | dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]], dev_counts[dev][dev_qhead[dev]], 0); | |
454 | } | |
455 | ||
456 | return 0; | |
457 | } | |
458 | ||
459 | int | |
460 | DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) | |
461 | { | |
462 | int chan = sound_dsp_dmachan[dev]; | |
463 | unsigned long flags; | |
464 | ||
465 | /* | |
466 | * This function is not as portable as it should be. | |
467 | */ | |
468 | ||
469 | /* | |
470 | * The count must be one less than the actual size. This is handled by | |
471 | * set_dma_addr() | |
472 | */ | |
473 | ||
474 | if (sound_dma_automode[dev]) | |
475 | { /* Auto restart mode. Transfer the whole | |
476 | * buffer */ | |
477 | #ifdef linux | |
478 | DISABLE_INTR (flags); | |
479 | disable_dma (chan); | |
480 | clear_dma_ff (chan); | |
481 | set_dma_mode (chan, dma_mode | DMA_AUTOINIT); | |
482 | set_dma_addr (chan, snd_raw_buf_phys[dev][0]); | |
483 | set_dma_count (chan, sound_buffsizes[dev]); | |
484 | enable_dma (chan); | |
485 | RESTORE_INTR (flags); | |
486 | #else | |
487 | ||
488 | #ifdef __386BSD__ | |
489 | printk ("sound: Invalid DMA mode for device %d\n", dev); | |
490 | ||
491 | isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, | |
492 | snd_raw_buf_phys[dev][0], | |
493 | sound_buffsizes[dev], | |
494 | chan); | |
495 | #else | |
496 | #ifdef ISC | |
497 | printk ("sound: Invalid DMA mode for device %d\n", dev); | |
498 | dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode) | DMAMODE_AUTO, | |
499 | snd_raw_buf_phys[dev][0], count - 1); | |
500 | dma_enable (chan); | |
501 | #else | |
502 | # error This routine is not valid for this OS. | |
503 | #endif | |
504 | #endif | |
505 | ||
506 | #endif | |
507 | } | |
508 | else | |
509 | { | |
510 | #ifdef linux | |
511 | DISABLE_INTR (flags); | |
512 | disable_dma (chan); | |
513 | clear_dma_ff (chan); | |
514 | set_dma_mode (chan, dma_mode); | |
515 | set_dma_addr (chan, physaddr); | |
516 | set_dma_count (chan, count); | |
517 | enable_dma (chan); | |
518 | RESTORE_INTR (flags); | |
519 | #else | |
520 | #ifdef __386BSD__ | |
521 | isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, | |
522 | physaddr, | |
523 | count, | |
524 | chan); | |
525 | #else | |
526 | ||
527 | #ifdef ISC | |
528 | dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode), | |
529 | physaddr, count - 1); | |
530 | dma_enable (chan); | |
531 | #else | |
532 | # error This routine is not valid for this OS. | |
533 | #endif /* !ISC */ | |
534 | #endif | |
535 | ||
536 | #endif | |
537 | } | |
538 | ||
539 | return count; | |
540 | } | |
541 | ||
542 | long | |
543 | DMAbuf_init (long mem_start) | |
544 | { | |
545 | int i; | |
546 | ||
547 | /* | |
548 | * In this version the DMA buffer allocation is done by sound_mem_init() | |
549 | * which is called by init/main.c | |
550 | */ | |
551 | ||
552 | for (i = 0; i < MAX_DSP_DEV; i++) | |
553 | { | |
554 | dev_qlen[i] = 0; | |
555 | dev_qhead[i] = 0; | |
556 | dev_qtail[i] = 0; | |
557 | dev_active[i] = 0; | |
558 | dev_busy[i] = 0; | |
559 | bufferalloc_done[i] = 0; | |
560 | } | |
561 | ||
562 | return mem_start; | |
563 | } | |
564 | ||
565 | void | |
566 | DMAbuf_outputintr (int dev) | |
567 | { | |
568 | unsigned long flags; | |
569 | ||
570 | dev_active[dev] = 0; | |
571 | dev_qlen[dev]--; | |
572 | dev_qhead[dev] = (dev_qhead[dev] + 1) % dev_nbufs[dev]; | |
573 | ||
574 | if (dev_qlen[dev]) | |
575 | { | |
576 | dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]], dev_counts[dev][dev_qhead[dev]], 1); | |
577 | dev_active[dev] = 1; | |
578 | } | |
579 | else | |
580 | { | |
581 | if (dev_busy[dev]) | |
582 | { | |
583 | dev_underrun[dev]++; | |
584 | dsp_devs[dev]->halt_xfer (dev); | |
585 | } | |
586 | else | |
587 | { /* Device has been closed */ | |
588 | dsp_devs[dev]->close (dev); | |
589 | } | |
590 | } | |
591 | ||
592 | DISABLE_INTR (flags); | |
593 | if (dev_sleep_flag[dev]) | |
594 | { | |
595 | dev_sleep_flag[dev] = 0; | |
596 | WAKE_UP (dev_sleeper[dev]); | |
597 | } | |
598 | RESTORE_INTR (flags); | |
599 | } | |
600 | ||
601 | void | |
602 | DMAbuf_inputintr (int dev) | |
603 | { | |
604 | unsigned long flags; | |
605 | ||
606 | dev_active[dev] = 0; | |
607 | if (!dev_busy[dev]) | |
608 | { | |
609 | dsp_devs[dev]->close (dev); | |
610 | } | |
611 | else if (dev_qlen[dev] == (dev_nbufs[dev] - 1)) | |
612 | { | |
613 | dev_underrun[dev]++; | |
614 | dsp_devs[dev]->halt_xfer (dev); | |
615 | } | |
616 | else | |
617 | { | |
618 | dev_qlen[dev]++; | |
619 | dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev]; | |
620 | ||
621 | dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]], dev_buffsize[dev], 1); | |
622 | dev_active[dev] = 1; | |
623 | } | |
624 | ||
625 | DISABLE_INTR (flags); | |
626 | if (dev_sleep_flag[dev]) | |
627 | { | |
628 | dev_sleep_flag[dev] = 0; | |
629 | WAKE_UP (dev_sleeper[dev]); | |
630 | } | |
631 | RESTORE_INTR (flags); | |
632 | } | |
633 | ||
634 | int | |
635 | DMAbuf_open_dma (int dev) | |
636 | { | |
637 | unsigned long flags; | |
638 | int chan = sound_dsp_dmachan[dev]; | |
639 | ||
640 | if (ALLOC_DMA_CHN (chan)) | |
641 | { | |
642 | printk ("Unable to grab DMA%d for the audio driver\n", chan); | |
643 | return 0; | |
644 | } | |
645 | ||
646 | DISABLE_INTR (flags); | |
647 | #ifdef linux | |
648 | disable_dma (chan); | |
649 | clear_dma_ff (chan); | |
650 | #endif | |
651 | RESTORE_INTR (flags); | |
652 | ||
653 | return 1; | |
654 | } | |
655 | ||
656 | void | |
657 | DMAbuf_close_dma (int dev) | |
658 | { | |
659 | int chan = sound_dsp_dmachan[dev]; | |
660 | ||
661 | DMAbuf_reset_dma (chan); | |
662 | RELEASE_DMA_CHN (chan); | |
663 | } | |
664 | ||
665 | void | |
666 | DMAbuf_reset_dma (int chan) | |
667 | { | |
668 | } | |
669 | ||
670 | /* | |
671 | * The sound_mem_init() is called by mem_init() immediately after mem_map is | |
672 | * initialized and before free_page_list is created. | |
673 | * | |
674 | * This routine allocates DMA buffers at the end of available physical memory ( | |
675 | * <16M) and marks pages reserved at mem_map. | |
676 | */ | |
677 | ||
678 | #else | |
679 | /* Stub versions if audio services not included */ | |
680 | ||
681 | int | |
682 | DMAbuf_open (int dev, int mode) | |
683 | { | |
684 | return RET_ERROR (ENXIO); | |
685 | } | |
686 | ||
687 | int | |
688 | DMAbuf_release (int dev, int mode) | |
689 | { | |
690 | return 0; | |
691 | } | |
692 | ||
693 | int | |
694 | DMAbuf_read (int dev, snd_rw_buf * user_buf, int count) | |
695 | { | |
696 | return RET_ERROR (EIO); | |
697 | } | |
698 | ||
699 | int | |
700 | DMAbuf_getwrbuffer (int dev, char **buf, int *size) | |
701 | { | |
702 | return RET_ERROR (EIO); | |
703 | } | |
704 | ||
705 | int | |
706 | DMAbuf_getrdbuffer (int dev, char **buf, int *len) | |
707 | { | |
708 | return RET_ERROR (EIO); | |
709 | } | |
710 | ||
711 | int | |
712 | DMAbuf_rmchars (int dev, int buff_no, int c) | |
713 | { | |
714 | return RET_ERROR (EIO); | |
715 | } | |
716 | ||
717 | int | |
718 | DMAbuf_start_output (int dev, int buff_no, int l) | |
719 | { | |
720 | return RET_ERROR (EIO); | |
721 | } | |
722 | ||
723 | int | |
724 | DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) | |
725 | { | |
726 | return RET_ERROR (EIO); | |
727 | } | |
728 | ||
729 | long | |
730 | DMAbuf_init (long mem_start) | |
731 | { | |
732 | return mem_start; | |
733 | } | |
734 | ||
735 | int | |
736 | DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) | |
737 | { | |
738 | return RET_ERROR (EIO); | |
739 | } | |
740 | ||
741 | int | |
742 | DMAbuf_open_dma (int chan) | |
743 | { | |
744 | return RET_ERROR (ENXIO); | |
745 | } | |
746 | ||
747 | void | |
748 | DMAbuf_close_dma (int chan) | |
749 | { | |
750 | return; | |
751 | } | |
752 | ||
753 | void | |
754 | DMAbuf_reset_dma (int chan) | |
755 | { | |
756 | return; | |
757 | } | |
758 | ||
759 | void | |
760 | DMAbuf_inputintr (int dev) | |
761 | { | |
762 | return; | |
763 | } | |
764 | ||
765 | void | |
766 | DMAbuf_outputintr (int dev) | |
767 | { | |
768 | return; | |
769 | } | |
770 | ||
771 | #endif | |
772 | ||
773 | #endif |