Deleted Added
full compact
channel.c (53603) channel.c (54155)
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * Portions Copyright by Luigi Rizzo - 1997-99
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * Portions Copyright by Luigi Rizzo - 1997-99
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/sound/pcm/channel.c 53603 1999-11-22 21:16:01Z cg $
27 * $FreeBSD: head/sys/dev/sound/pcm/channel.c 54155 1999-12-05 19:09:13Z cg $
28 */
29
30#include <dev/sound/pcm/sound.h>
31
32#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
33#define DMA_ALIGN_THRESHOLD 4
34#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
35
36#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8))
37#define CANCHANGE(c) (!(c)->buffer.dl)
38
39static void chn_stintr(pcm_channel *c);
28 */
29
30#include <dev/sound/pcm/sound.h>
31
32#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
33#define DMA_ALIGN_THRESHOLD 4
34#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
35
36#define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8))
37#define CANCHANGE(c) (!(c)->buffer.dl)
38
39static void chn_stintr(pcm_channel *c);
40static void chn_clearbuf(pcm_channel *c, int length);
40/*
41 * SOUND OUTPUT
42
43We use a circular buffer to store samples directed to the DAC.
44The buffer is split into two variable-size regions, each identified
45by an offset in the buffer (rp,fp) and a length (rl,fl):
46
47 0 rp,rl fp,fl bufsize

--- 50 unchanged lines hidden (view full) ---

98 * gets copied in or out of the real buffer. fix requires mods to isa_dma.c
99 * and possibly fixes to other autodma mode clients
100 */
101static void
102chn_isadmabounce(pcm_channel *c)
103{
104 if (ISA_DMA(&c->buffer)) {
105 /* tell isa_dma to bounce data in/out */
41/*
42 * SOUND OUTPUT
43
44We use a circular buffer to store samples directed to the DAC.
45The buffer is split into two variable-size regions, each identified
46by an offset in the buffer (rp,fp) and a length (rl,fl):
47
48 0 rp,rl fp,fl bufsize

--- 50 unchanged lines hidden (view full) ---

99 * gets copied in or out of the real buffer. fix requires mods to isa_dma.c
100 * and possibly fixes to other autodma mode clients
101 */
102static void
103chn_isadmabounce(pcm_channel *c)
104{
105 if (ISA_DMA(&c->buffer)) {
106 /* tell isa_dma to bounce data in/out */
106 } else panic("chn_isadmabounce called on invalid channel");
107 } else KASSERT(1, ("chn_isadmabounce called on invalid channel"));
107}
108
109static int
110chn_polltrigger(pcm_channel *c)
111{
112 snd_dbuf *b = &c->buffer;
113 unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize : 1;
114 int trig = 0;

--- 33 unchanged lines hidden (view full) ---

148
149/*
150 * chn_dmaupdate() tracks the status of a dma transfer,
151 * updating pointers. It must be called at spltty().
152 *
153 * NOTE: when we are using auto dma in the device, rl might become
154 * negative.
155 */
108}
109
110static int
111chn_polltrigger(pcm_channel *c)
112{
113 snd_dbuf *b = &c->buffer;
114 unsigned lim = (c->flags & CHN_F_HAS_SIZE)? c->blocksize : 1;
115 int trig = 0;

--- 33 unchanged lines hidden (view full) ---

149
150/*
151 * chn_dmaupdate() tracks the status of a dma transfer,
152 * updating pointers. It must be called at spltty().
153 *
154 * NOTE: when we are using auto dma in the device, rl might become
155 * negative.
156 */
157DEB (static int chn_updatecount=0);
158
156void
157chn_dmaupdate(pcm_channel *c)
158{
159 snd_dbuf *b = &c->buffer;
159void
160chn_dmaupdate(pcm_channel *c)
161{
162 snd_dbuf *b = &c->buffer;
160 int delta, hwptr = chn_getptr(c);
163 int delta, hwptr;
164 DEB (int b_rl=b->rl; int b_fl=b->fl; int b_rp=b->rp; int b_fp=b->fp);
161
165
166 hwptr = chn_getptr(c);
162 if (c->direction == PCMDIR_PLAY) {
163 delta = (b->bufsize + hwptr - b->rp) % b->bufsize;
164 b->rp = hwptr;
165 b->rl -= delta;
166 b->fl += delta;
167 if (c->direction == PCMDIR_PLAY) {
168 delta = (b->bufsize + hwptr - b->rp) % b->bufsize;
169 b->rp = hwptr;
170 b->rl -= delta;
171 b->fl += delta;
172 DEB(if (b->rl<0) printf("OUCH!(%d) rl %d(%d) delta %d bufsize %d hwptr %d rp %d(%d)\n", chn_updatecount++, b->rl, b_rl, delta, b->bufsize, hwptr, b->rp, b_rp));
167 } else {
168 delta = (b->bufsize + hwptr - b->fp) % b->bufsize;
169 b->fp = hwptr;
170 b->rl += delta;
171 b->fl -= delta;
173 } else {
174 delta = (b->bufsize + hwptr - b->fp) % b->bufsize;
175 b->fp = hwptr;
176 b->rl += delta;
177 b->fl -= delta;
178 DEB(if (b->fl<0) printf("OUCH!(%d) fl %d(%d) delta %d bufsize %d hwptr %d fp %d(%d)\n", chn_updatecount++, b->fl, b_fl, delta, b->bufsize, hwptr, b->fp, b_fp));
172 }
173 b->total += delta;
174}
175
176/*
179 }
180 b->total += delta;
181}
182
183/*
184 * Check channel for underflow occured, reset DMA buffer in case of
185 * underflow. It must be called at spltty().
186 */
187static void
188chn_checkunderflow(pcm_channel *c)
189{
190 snd_dbuf *b = &c->buffer;
191
192 if (b->underflow) {
193 DEB(printf("Clear underflow condition\n"));
194 b->rp = b->fp = chn_getptr(c);
195 b->rl = 0;
196 b->fl = b->bufsize;
197 b->underflow=0;
198 } else {
199 chn_dmaupdate(c);
200 }
201}
202
203/*
177 * Write interrupt routine. Can be called from other places (e.g.
178 * to start a paused transfer), but with interrupts disabled.
179 */
180static void
181chn_wrintr(pcm_channel *c)
182{
183 snd_dbuf *b = &c->buffer;
184 int start;
185
204 * Write interrupt routine. Can be called from other places (e.g.
205 * to start a paused transfer), but with interrupts disabled.
206 */
207static void
208chn_wrintr(pcm_channel *c)
209{
210 snd_dbuf *b = &c->buffer;
211 int start;
212
186 if (b->dl) chn_dmadone(c);
213 if (b->underflow) return; /* nothing new happened */
214 if (b->dl) chn_dmadone(c);
187
188 /*
189 * start another dma operation only if have ready data in the buffer,
190 * there is no pending abort, have a full-duplex device, or have a
191 * half duplex device and there is no pending op on the other side.
192 *
193 * Force transfers to be aligned to a boundary of 4, which is
194 * needed when doing stereo and 16-bit.
195 */
196 if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED;
197 else start = (b->rl >= DMA_ALIGN_THRESHOLD && !(c->flags & CHN_F_ABORTING));
198 if (start) {
199 int l;
200 chn_dmaupdate(c);
215
216 /*
217 * start another dma operation only if have ready data in the buffer,
218 * there is no pending abort, have a full-duplex device, or have a
219 * half duplex device and there is no pending op on the other side.
220 *
221 * Force transfers to be aligned to a boundary of 4, which is
222 * needed when doing stereo and 16-bit.
223 */
224 if (c->flags & CHN_F_MAPPED) start = c->flags & CHN_F_TRIGGERED;
225 else start = (b->rl >= DMA_ALIGN_THRESHOLD && !(c->flags & CHN_F_ABORTING));
226 if (start) {
227 int l;
228 chn_dmaupdate(c);
201 l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK;
202 if (c->flags & CHN_F_MAPPED) l = c->blocksize;
229 if (c->flags & CHN_F_MAPPED) l = c->blocksize;
230 else l = min(b->rl, c->blocksize) & DMA_ALIGN_MASK;
203 /*
204 * check if we need to reprogram the DMA on the sound card.
231 /*
232 * check if we need to reprogram the DMA on the sound card.
205 * This happens if the size has changed _and_ the new size
206 * is smaller, or it matches the blocksize.
233 * This happens if the size has changed from zero
207 *
234 *
208 * 0 <= l <= blocksize
209 * 0 <= dl <= blocksize
210 * reprog if (dl == 0 || l != dl)
211 * was:
212 * l != b->dl && (b->dl == 0 || l < b->dl || l == c->blocksize)
213 */
235 */
214 if (b->dl == 0 || l != b->dl) {
215 /* size has changed. Stop and restart */
216 DEB(printf("wrintr: bsz %d -> %d, rp %d rl %d\n",
217 b->dl, l, b->rp, b->rl));
218 if (b->dl) chn_trigger(c, PCMTRIG_STOP);
219 b->dl = l; /* record new transfer size */
236 if (b->dl == 0) {
237 /* Start DMA operation */
238 b->dl = c->blocksize ; /* record new transfer size */
220 chn_trigger(c, PCMTRIG_START);
239 chn_trigger(c, PCMTRIG_START);
240 } else if (b->dl != l) {
241 /*
242 * we are near to underflow condition, so to prevent
243 * audio 'clicks' clear next 1.5*dl bytes
244 */
245 chn_clearbuf(c, (b->dl*3)/2);
221 }
222 } else {
223 /* cannot start a new dma transfer */
224 DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n",
225 c->flags, b->rp, b->rl));
246 }
247 } else {
248 /* cannot start a new dma transfer */
249 DEB(printf("cannot start wr-dma flags 0x%08x rp %d rl %d\n",
250 c->flags, b->rp, b->rl));
226 if (b->dl) { /* was active */
227 b->dl = 0;
228 chn_trigger(c, PCMTRIG_STOP);
229#if 0
230 if (c->flags & CHN_F_WRITING)
231 DEB(printf("got wrint while reloading\n"));
232 else if (b->rl <= 0) /* XXX added 980110 lr */
233 chn_resetbuf(c);
234#endif
251 if (b->dl) { /* DMA was active */
252 b->underflow = 1; /* set underflow flag */
253 chn_clearbuf(c, b->bufsize); /* and clear all DMA buffer */
235 }
236 }
237}
238
239/*
240 * user write routine
241 *
242 * advance the boundary between READY and FREE, fill the space with

--- 7 unchanged lines hidden (view full) ---

250 * data, we reduce the latency to something proportional to the length
251 * of the first piece, while keeping the overhead low and being able
252 * to feed the DMA with large blocks.
253 */
254
255int
256chn_write(pcm_channel *c, struct uio *buf)
257{
254 }
255 }
256}
257
258/*
259 * user write routine
260 *
261 * advance the boundary between READY and FREE, fill the space with

--- 7 unchanged lines hidden (view full) ---

269 * data, we reduce the latency to something proportional to the length
270 * of the first piece, while keeping the overhead low and being able
271 * to feed the DMA with large blocks.
272 */
273
274int
275chn_write(pcm_channel *c, struct uio *buf)
276{
258 int a, l, w, timeout, ret = 0;
277 int a, l, w, timeout, ret = 0, rc;
259 long s;
260 snd_dbuf *b = &c->buffer;
278 long s;
279 snd_dbuf *b = &c->buffer;
280 int threshold, maxthreshold, minthreshold;
261
262 if (c->flags & CHN_F_WRITING) {
263 /* This shouldn't happen and is actually silly
264 * - will never wake up, just timeout; why not sleep on b?
265 */
266 tsleep(&s, PZERO, "pcmwrW", hz);
267 return EBUSY;
268 }
269 a = (1 << c->align) - 1;
281
282 if (c->flags & CHN_F_WRITING) {
283 /* This shouldn't happen and is actually silly
284 * - will never wake up, just timeout; why not sleep on b?
285 */
286 tsleep(&s, PZERO, "pcmwrW", hz);
287 return EBUSY;
288 }
289 a = (1 << c->align) - 1;
290 maxthreshold = (b->dl / 4 + a) & ~a;
291 minthreshold = a;
270 c->flags |= CHN_F_WRITING;
292 c->flags |= CHN_F_WRITING;
271 while ((c->smegcnt + buf->uio_resid) > a) {
272 s = spltty();
273 chn_dmaupdate(c);
274 splx(s);
275 if (b->fl < DMA_ALIGN_THRESHOLD) {
293 s = spltty();
294 chn_checkunderflow(c);
295 splx(s);
296 while ((buf->uio_resid + c->smegcnt) > minthreshold ) { /* Don't allow write unaligned data */
297 threshold = min((buf->uio_resid + c->smegcnt), maxthreshold);
298 if (b->fl < threshold) {
276 if (c->flags & CHN_F_NBIO) {
277 ret = -1;
278 break;
279 }
280 timeout = (buf->uio_resid >= b->dl)? hz : 1;
299 if (c->flags & CHN_F_NBIO) {
300 ret = -1;
301 break;
302 }
303 timeout = (buf->uio_resid >= b->dl)? hz : 1;
281 ret = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout);
282 if (ret == EINTR) chn_abort(c);
283 if (ret == EINTR || ret == ERESTART) break;
284 ret = 0;
285 continue;
304 rc = tsleep(b, PRIBIO | PCATCH, "pcmwr", timeout);
305 if (rc == 0 || rc == EWOULDBLOCK) {
306 s = spltty();
307 chn_checkunderflow(c);
308 splx(s);
309 if (b->fl < minthreshold) continue; /* write only alligned chunk of data */
310 } else {
311#if 0
312 if (ret == EINTR) chn_abort(c);
313#endif
314 ret = rc;
315 break;
316 }
286 }
287 /* ensure we always have a whole number of samples */
288 l = min(b->fl, b->bufsize - b->fp) & ~a;
289 if (l == 0) continue;
290 w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf);
317 }
318 /* ensure we always have a whole number of samples */
319 l = min(b->fl, b->bufsize - b->fp) & ~a;
320 if (l == 0) continue;
321 w = c->feeder->feed(c->feeder, c, b->buf + b->fp, l, buf);
291 if (w == 0) panic("no feed");
322 KASSERT(w, ("chn_write: no feed"));
292 s = spltty();
293 b->rl += w;
294 b->fl -= w;
295 b->fp = (b->fp + w) % b->bufsize;
296 splx(s);
323 s = spltty();
324 b->rl += w;
325 b->fl -= w;
326 b->fp = (b->fp + w) % b->bufsize;
327 splx(s);
297 if (b->rl && !b->dl) chn_stintr(c);
328 DEB(if(1) printf("write %d bytes fp %d rl %d\n",w ,b->fp, b->rl));
329 if (!b->dl) chn_stintr(c);
298 }
299 if ((ret == 0) && (buf->uio_resid > 0)) {
330 }
331 if ((ret == 0) && (buf->uio_resid > 0)) {
332 s = spltty();
300 l = buf->uio_resid;
333 l = buf->uio_resid;
301 if ((c->smegcnt + l) >= SMEGBUFSZ) panic("resid overflow %d", l);
334 KASSERT( (c->smegcnt + l) < SMEGBUFSZ, ("resid overflow %d", l));
302 uiomove(c->smegbuf + c->smegcnt, l, buf);
303 c->smegcnt += l;
335 uiomove(c->smegbuf + c->smegcnt, l, buf);
336 c->smegcnt += l;
337 splx(s);
304 }
305 c->flags &= ~CHN_F_WRITING;
306 return (ret > 0)? ret : 0;
307}
308
309/*
310 * SOUND INPUT
311 *

--- 158 unchanged lines hidden (view full) ---

470{
471 if (bus_dmamem_alloc(parent_dmat, (void **)&b->buf,
472 BUS_DMA_NOWAIT, &b->dmamap)) return -1;
473 if (bus_dmamap_load(parent_dmat, b->dmamap, b->buf,
474 b->bufsize, chn_dma_setmap, b, 0)) return -1;
475 return 0;
476}
477
338 }
339 c->flags &= ~CHN_F_WRITING;
340 return (ret > 0)? ret : 0;
341}
342
343/*
344 * SOUND INPUT
345 *

--- 158 unchanged lines hidden (view full) ---

504{
505 if (bus_dmamem_alloc(parent_dmat, (void **)&b->buf,
506 BUS_DMA_NOWAIT, &b->dmamap)) return -1;
507 if (bus_dmamap_load(parent_dmat, b->dmamap, b->buf,
508 b->bufsize, chn_dma_setmap, b, 0)) return -1;
509 return 0;
510}
511
512static void
513chn_clearbuf(pcm_channel *c, int length)
514{
515int i;
516u_int16_t data, *p;
517
518 snd_dbuf *b = &c->buffer;
519 /* rely on length & DMA_ALIGN_MASK == 0 */
520 length&=DMA_ALIGN_MASK;
521 if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80;
522 if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8;
523 if (c->hwfmt & AFMT_BIGENDIAN)
524 data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00);
525 for (i = b->fp, p=(u_int16_t*)(b->buf+b->fp) ; i < b->bufsize && length; i += 2, length-=2)
526 *p++ = data;
527 for (i = 0, p=(u_int16_t*)b->buf; i < b->bufsize && length; i += 2, length-=2)
528 *p++ = data;
529
530 return;
531}
532
478void
479chn_resetbuf(pcm_channel *c)
480{
481 snd_dbuf *b = &c->buffer;
533void
534chn_resetbuf(pcm_channel *c)
535{
536 snd_dbuf *b = &c->buffer;
482 u_int16_t data, *p;
483 u_int32_t i;
484
485 c->smegcnt = 0;
486 c->buffer.sample_size = 1;
487 c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0;
488 c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0;
537
538 c->smegcnt = 0;
539 c->buffer.sample_size = 1;
540 c->buffer.sample_size <<= (c->hwfmt & AFMT_STEREO)? 1 : 0;
541 c->buffer.sample_size <<= (c->hwfmt & AFMT_16BIT)? 1 : 0;
489 /* rely on bufsize & 3 == 0 */
490 if (c->hwfmt & AFMT_SIGNED) data = 0x00; else data = 0x80;
491 if (c->hwfmt & AFMT_16BIT) data <<= 8; else data |= data << 8;
492 if (c->hwfmt & AFMT_BIGENDIAN)
493 data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00);
494 for (i = 0, p = (u_int16_t *)b->buf; i < b->bufsize; i += 2)
495 *p++ = data;
496 b->rp = b->fp = 0;
497 b->dl = b->rl = 0;
542 b->rp = b->fp = 0;
543 b->dl = b->rl = 0;
544 b->fl = b->bufsize;
545 chn_clearbuf(c, b->bufsize);
498 b->prev_total = b->total = 0;
499 b->prev_int_count = b->int_count = 0;
500 b->first_poll = 1;
546 b->prev_total = b->total = 0;
547 b->prev_int_count = b->int_count = 0;
548 b->first_poll = 1;
501 b->fl = b->bufsize;
549 b->underflow=0;
502}
503
504void
505buf_isadma(snd_dbuf *b, int go)
506{
507 if (ISA_DMA(b)) {
550}
551
552void
553buf_isadma(snd_dbuf *b, int go)
554{
555 if (ISA_DMA(b)) {
508 if (go == PCMTRIG_START) isa_dmastart(b->dir | B_RAW, b->buf,
509 b->bufsize, b->chan);
510 else {
556 if (go == PCMTRIG_START) {
557 DEB(printf("buf 0x%p ISA DMA started\n", b));
558 isa_dmastart(b->dir | B_RAW, b->buf,
559 b->bufsize, b->chan);
560 } else {
561 DEB(printf("buf 0x%p ISA DMA stopped\n", b));
511 isa_dmastop(b->chan);
512 isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize,
513 b->chan);
514 }
562 isa_dmastop(b->chan);
563 isa_dmadone(b->dir | B_RAW, b->buf, b->bufsize,
564 b->chan);
565 }
515 } else panic("buf_isadma called on invalid channel");
566 } else KASSERT(1, ("buf_isadma called on invalid channel"));
516}
517
518int
519buf_isadmaptr(snd_dbuf *b)
520{
521 if (ISA_DMA(b)) {
522 int i = b->dl? isa_dmastatus(b->chan) : b->bufsize;
523 if (i < 0) i = 0;
524 return b->bufsize - i;
567}
568
569int
570buf_isadmaptr(snd_dbuf *b)
571{
572 if (ISA_DMA(b)) {
573 int i = b->dl? isa_dmastatus(b->chan) : b->bufsize;
574 if (i < 0) i = 0;
575 return b->bufsize - i;
525 } else panic("buf_isadmaptr called on invalid channel");
576 } else KASSERT(1, ("buf_isadmaptr called on invalid channel"));
526 return -1;
527}
528
529/*
530 * snd_sync waits until the space in the given channel goes above
531 * a threshold. The threshold is checked against fl or rl respectively.
532 * Assume that the condition can become true, do not check here...
533 */

--- 7 unchanged lines hidden (view full) ---

541 for (;;) {
542 s = spltty();
543 chn_dmaupdate(c);
544 rdy = (c->direction == PCMDIR_PLAY)? b->fl : b->rl;
545 if (rdy <= threshold) {
546 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1);
547 splx(s);
548 if (ret == ERESTART || ret == EINTR) {
577 return -1;
578}
579
580/*
581 * snd_sync waits until the space in the given channel goes above
582 * a threshold. The threshold is checked against fl or rl respectively.
583 * Assume that the condition can become true, do not check here...
584 */

--- 7 unchanged lines hidden (view full) ---

592 for (;;) {
593 s = spltty();
594 chn_dmaupdate(c);
595 rdy = (c->direction == PCMDIR_PLAY)? b->fl : b->rl;
596 if (rdy <= threshold) {
597 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmsyn", 1);
598 splx(s);
599 if (ret == ERESTART || ret == EINTR) {
549 printf("tsleep returns %d\n", ret);
600 DEB(printf("chn_sync: tsleep returns %d\n", ret));
550 return -1;
551 }
552 } else break;
553 }
554 splx(s);
555 return 0;
556}
557

--- 45 unchanged lines hidden (view full) ---

603chn_flush(pcm_channel *c)
604{
605 int ret, count = 10;
606 snd_dbuf *b = &c->buffer;
607
608 DEB(printf("snd_flush c->flags 0x%08x\n", c->flags));
609 c->flags |= CHN_F_CLOSING;
610 if (c->direction != PCMDIR_PLAY) chn_abort(c);
601 return -1;
602 }
603 } else break;
604 }
605 splx(s);
606 return 0;
607}
608

--- 45 unchanged lines hidden (view full) ---

654chn_flush(pcm_channel *c)
655{
656 int ret, count = 10;
657 snd_dbuf *b = &c->buffer;
658
659 DEB(printf("snd_flush c->flags 0x%08x\n", c->flags));
660 c->flags |= CHN_F_CLOSING;
661 if (c->direction != PCMDIR_PLAY) chn_abort(c);
611 else while (b->dl) {
662 else if (b->dl) while (!b->underflow) {
612 /* still pending output data. */
613 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz);
663 /* still pending output data. */
664 ret = tsleep((caddr_t)b, PRIBIO | PCATCH, "pcmflu", hz);
614 chn_dmaupdate(c);
665 DEB(chn_dmaupdate(c));
615 DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl));
666 DEB(printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl));
616 if (ret == EINTR) {
617 printf("tsleep returns %d\n", ret);
667 if (ret == EINTR || ret == ERESTART) {
668 DEB(printf("chn_flush: tsleep returns %d\n", ret));
618 return -1;
619 }
620 if (ret && --count == 0) {
669 return -1;
670 }
671 if (ret && --count == 0) {
621 printf("timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n",
622 b->rl, c->flags);
672 DEB(printf("chn_flush: timeout flushing dbuf_out, cnt 0x%x flags 0x%x\n",\
673 b->rl, c->flags));
623 break;
624 }
625 }
626 c->flags &= ~CHN_F_CLOSING;
627 if (c->direction == PCMDIR_PLAY) chn_abort(c);
628 return 0;
629}
630

--- 8 unchanged lines hidden (view full) ---

639}
640
641int
642chn_reinit(pcm_channel *c)
643{
644 if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) {
645 chn_setformat(c, c->format);
646 chn_setspeed(c, c->speed);
674 break;
675 }
676 }
677 c->flags &= ~CHN_F_CLOSING;
678 if (c->direction == PCMDIR_PLAY) chn_abort(c);
679 return 0;
680}
681

--- 8 unchanged lines hidden (view full) ---

690}
691
692int
693chn_reinit(pcm_channel *c)
694{
695 if ((c->flags & CHN_F_INIT) && CANCHANGE(c)) {
696 chn_setformat(c, c->format);
697 chn_setspeed(c, c->speed);
647 chn_setblocksize(c, c->blocksize);
698 chn_setblocksize(c, (c->flags & CHN_F_HAS_SIZE) ? c->blocksize : 0);
648 chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff);
649 c->flags &= ~CHN_F_INIT;
650 return 1;
651 }
699 chn_setvolume(c, (c->volume >> 8) & 0xff, c->volume & 0xff);
700 c->flags &= ~CHN_F_INIT;
701 return 1;
702 }
703 if (CANCHANGE(c) && !(c->flags & CHN_F_HAS_SIZE) )
704 chn_setblocksize(c, 0); /* Apply new block size */
652 return 0;
653}
654
655int
656chn_init(pcm_channel *c, void *devinfo, int dir)
657{
658 c->flags = 0;
659 c->feeder = &feeder_root;

--- 54 unchanged lines hidden (view full) ---

714
715int
716chn_setblocksize(pcm_channel *c, int blksz)
717{
718 if (CANCHANGE(c)) {
719 c->flags &= ~CHN_F_HAS_SIZE;
720 if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE;
721 if (blksz < 0) blksz = -blksz;
705 return 0;
706}
707
708int
709chn_init(pcm_channel *c, void *devinfo, int dir)
710{
711 c->flags = 0;
712 c->feeder = &feeder_root;

--- 54 unchanged lines hidden (view full) ---

767
768int
769chn_setblocksize(pcm_channel *c, int blksz)
770{
771 if (CANCHANGE(c)) {
772 c->flags &= ~CHN_F_HAS_SIZE;
773 if (blksz >= 2) c->flags |= CHN_F_HAS_SIZE;
774 if (blksz < 0) blksz = -blksz;
722 if (blksz < 2) blksz = (c->buffer.sample_size * c->speed) >> 2;
775 if (blksz < 2) blksz = c->buffer.sample_size * (c->speed >> 2);
723 RANGE(blksz, 1024, c->buffer.bufsize / 4);
776 RANGE(blksz, 1024, c->buffer.bufsize / 4);
724 blksz &= ~3;
725 c->blocksize = c->setblocksize(c->devinfo, blksz);
777 blksz &= DMA_ALIGN_MASK;
778 c->blocksize = c->setblocksize(c->devinfo, blksz) & DMA_ALIGN_MASK;
726 return c->blocksize;
727 }
728 c->blocksize = blksz;
729 c->flags |= CHN_F_INIT;
730 return 0;
731}
732
733int
734chn_trigger(pcm_channel *c, int go)
735{
736 return c->trigger(c->devinfo, go);
737}
738
739int
740chn_getptr(pcm_channel *c)
741{
779 return c->blocksize;
780 }
781 c->blocksize = blksz;
782 c->flags |= CHN_F_INIT;
783 return 0;
784}
785
786int
787chn_trigger(pcm_channel *c, int go)
788{
789 return c->trigger(c->devinfo, go);
790}
791
792int
793chn_getptr(pcm_channel *c)
794{
742 return c->getptr(c->devinfo);
795 int hwptr;
796 int a = (1 << c->align) - 1;
797
798 hwptr=c->getptr(c->devinfo);
799 /* don't allow unaligned values in the hwa ptr */
800 hwptr &= ~a ; /* Apply channel align mask */
801 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
802 return hwptr;
743}
744
745pcmchan_caps *
746chn_getcaps(pcm_channel *c)
747{
748 return c->getcaps(c->devinfo);
749}
803}
804
805pcmchan_caps *
806chn_getcaps(pcm_channel *c)
807{
808 return c->getcaps(c->devinfo);
809}