xref: /dragonfly/sys/dev/sound/pcm/channel.c (revision 3f5e28f4)
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
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:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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: src/sys/dev/sound/pcm/channel.c,v 1.99.2.4 2006/04/04 17:37:51 ariff Exp $
28  * $DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.11 2007/01/04 21:47:03 corecode Exp $
29  */
30 
31 #include "use_isa.h"
32 
33 #include <dev/sound/pcm/sound.h>
34 #include <sys/vnode.h>		/* IO_NDELAY */
35 
36 #include "feeder_if.h"
37 
38 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.11 2007/01/04 21:47:03 corecode Exp $");
39 
40 #define MIN_CHUNK_SIZE 		256	/* for uiomove etc. */
41 #if 0
42 #define	DMA_ALIGN_THRESHOLD	4
43 #define	DMA_ALIGN_MASK		(~(DMA_ALIGN_THRESHOLD - 1))
44 #endif
45 
46 #define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
47 
48 /*
49 #define DEB(x) x
50 */
51 
52 static int chn_targetirqrate = 32;
53 TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate);
54 
55 static int
56 sysctl_hw_snd_targetirqrate(SYSCTL_HANDLER_ARGS)
57 {
58 	int err, val;
59 
60 	val = chn_targetirqrate;
61 	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
62 	if (val < 16 || val > 512)
63 		err = EINVAL;
64 	else
65 		chn_targetirqrate = val;
66 
67 	return err;
68 }
69 SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW,
70 	0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "");
71 static int report_soft_formats = 1;
72 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
73 	&report_soft_formats, 1, "report software-emulated formats");
74 
75 static int chn_buildfeeder(struct pcm_channel *c);
76 
77 static void
78 chn_lockinit(struct pcm_channel *c, int dir)
79 {
80 	switch(dir) {
81 	case PCMDIR_PLAY:
82 		c->lock = snd_mtxcreate(c->name, "pcm play channel");
83 		break;
84 	case PCMDIR_REC:
85 		c->lock = snd_mtxcreate(c->name, "pcm record channel");
86 		break;
87 	case PCMDIR_VIRTUAL:
88 		c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
89 		break;
90 	case 0:
91 		c->lock = snd_mtxcreate(c->name, "pcm fake channel");
92 		break;
93 	}
94 }
95 
96 static void
97 chn_lockdestroy(struct pcm_channel *c)
98 {
99 	snd_mtxfree(c->lock);
100 }
101 
102 static int
103 chn_polltrigger(struct pcm_channel *c)
104 {
105 	struct snd_dbuf *bs = c->bufsoft;
106 	unsigned amt, lim;
107 
108 	CHN_LOCKASSERT(c);
109 	if (c->flags & CHN_F_MAPPED) {
110 		if (sndbuf_getprevblocks(bs) == 0)
111 			return 1;
112 		else
113 			return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
114 	} else {
115 		amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
116 #if 0
117 		lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
118 #endif
119 		lim = 1;
120 		return (amt >= lim)? 1 : 0;
121 	}
122 	return 0;
123 }
124 
125 static int
126 chn_pollreset(struct pcm_channel *c)
127 {
128 	struct snd_dbuf *bs = c->bufsoft;
129 
130 	CHN_LOCKASSERT(c);
131 	sndbuf_updateprevtotal(bs);
132 	return 1;
133 }
134 
135 static void
136 chn_wakeup(struct pcm_channel *c)
137 {
138 	struct snd_dbuf *bs = c->bufsoft;
139 	struct pcmchan_children *pce;
140 
141 	CHN_LOCKASSERT(c);
142 	if (SLIST_EMPTY(&c->children)) {
143 		/*if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))*/
144 		if (sndbuf_getsel(bs)->si_pid && chn_polltrigger(c))
145 			selwakeup(sndbuf_getsel(bs));
146 	} else {
147 		SLIST_FOREACH(pce, &c->children, link) {
148 			CHN_LOCK(pce->channel);
149 			chn_wakeup(pce->channel);
150 			CHN_UNLOCK(pce->channel);
151 		}
152 	}
153 
154 	wakeup(bs);
155 }
156 
157 static int
158 chn_sleep(struct pcm_channel *c, char *str, int timeout)
159 {
160     	struct snd_dbuf *bs = c->bufsoft;
161 	int ret;
162 
163 	CHN_LOCKASSERT(c);
164 #ifdef USING_MUTEX
165 	ret = msleep(bs, c->lock, PCATCH, str, timeout);
166 #else
167 	ret = tsleep(bs, PRIBIO | PCATCH, str, timeout);
168 #endif
169 
170 	return ret;
171 }
172 
173 /*
174  * chn_dmaupdate() tracks the status of a dma transfer,
175  * updating pointers.
176  */
177 
178 static unsigned int
179 chn_dmaupdate(struct pcm_channel *c)
180 {
181 	struct snd_dbuf *b = c->bufhard;
182 	unsigned int delta, old, hwptr, amt;
183 
184 	KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
185 	CHN_LOCKASSERT(c);
186 
187 	old = sndbuf_gethwptr(b);
188 	hwptr = chn_getptr(c);
189 	delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
190 	sndbuf_sethwptr(b, hwptr);
191 
192 	DEB(
193 	if (delta >= ((sndbuf_getsize(b) * 15) / 16)) {
194 		if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING)))
195 			device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr);
196 	}
197 	);
198 
199 	if (c->direction == PCMDIR_PLAY) {
200 		amt = MIN(delta, sndbuf_getready(b));
201 		if (amt > 0)
202 			sndbuf_dispose(b, NULL, amt);
203 	} else {
204 		amt = MIN(delta, sndbuf_getfree(b));
205 		if (amt > 0)
206 		       sndbuf_acquire(b, NULL, amt);
207 	}
208 
209 	return delta;
210 }
211 
212 void
213 chn_wrupdate(struct pcm_channel *c)
214 {
215 	int ret;
216 
217 	CHN_LOCKASSERT(c);
218 	KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
219 
220 	if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || !(c->flags & CHN_F_TRIGGERED))
221 		return;
222 	chn_dmaupdate(c);
223 	ret = chn_wrfeed(c);
224 	/* tell the driver we've updated the primary buffer */
225 	chn_trigger(c, PCMTRIG_EMLDMAWR);
226 	DEB(if (ret)
227 		kprintf("chn_wrupdate: chn_wrfeed returned %d\n", ret);)
228 
229 }
230 
231 int
232 chn_wrfeed(struct pcm_channel *c)
233 {
234     	struct snd_dbuf *b = c->bufhard;
235     	struct snd_dbuf *bs = c->bufsoft;
236 	unsigned int ret, amt;
237 
238 	CHN_LOCKASSERT(c);
239 #if 0
240     	DEB(
241 	if (c->flags & CHN_F_CLOSING) {
242 		sndbuf_dump(b, "b", 0x02);
243 		sndbuf_dump(bs, "bs", 0x02);
244 	})
245 #endif
246 
247 	if (c->flags & CHN_F_MAPPED)
248 		sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
249 
250 	amt = sndbuf_getfree(b);
251 	KASSERT(amt <= sndbuf_getsize(bs),
252 	    ("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name,
253 	   amt, sndbuf_getsize(bs), c->flags));
254 
255 	ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
256 	/*
257 	 * Possible xruns. There should be no empty space left in buffer.
258 	 */
259 	if (sndbuf_getfree(b) > 0)
260 		c->xruns++;
261 
262 	if (ret == 0 && sndbuf_getfree(b) < amt)
263 		chn_wakeup(c);
264 
265 	return ret;
266 }
267 
268 static void
269 chn_wrintr(struct pcm_channel *c)
270 {
271 	int ret;
272 
273 	CHN_LOCKASSERT(c);
274 	/* update pointers in primary buffer */
275 	chn_dmaupdate(c);
276 	/* ...and feed from secondary to primary */
277 	ret = chn_wrfeed(c);
278 	/* tell the driver we've updated the primary buffer */
279 	chn_trigger(c, PCMTRIG_EMLDMAWR);
280 	DEB(if (ret)
281 		kprintf("chn_wrintr: chn_wrfeed returned %d\n", ret);)
282 }
283 
284 /*
285  * user write routine - uiomove data into secondary buffer, trigger if necessary
286  * if blocking, sleep, rinse and repeat.
287  *
288  * called externally, so must handle locking
289  */
290 
291 int
292 chn_write(struct pcm_channel *c, struct uio *buf, int ioflags)
293 {
294 	int ret, timeout, newsize, count, sz;
295 	int nbio;
296 	struct snd_dbuf *bs = c->bufsoft;
297 	void *off;
298 	int t, x,togo,p;
299 
300 	CHN_LOCKASSERT(c);
301 	/*
302 	 * XXX Certain applications attempt to write larger size
303 	 * of pcm data than c->blocksize2nd without blocking,
304 	 * resulting partial write. Expand the block size so that
305 	 * the write operation avoids blocking.
306 	 */
307 	nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY);
308 	if (nbio && buf->uio_resid > sndbuf_getblksz(bs)) {
309 		DEB(device_printf(c->dev, "broken app, nbio and tried to write %d bytes with fragsz %d\n",
310 			buf->uio_resid, sndbuf_getblksz(bs)));
311 		newsize = 16;
312 		while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2))
313 			newsize <<= 1;
314 		chn_setblocksize(c, sndbuf_getblkcnt(bs), newsize);
315 		DEB(device_printf(c->dev, "frags reset to %d x %d\n", sndbuf_getblkcnt(bs), sndbuf_getblksz(bs)));
316 	}
317 
318 	ret = 0;
319 	count = hz;
320 	while (!ret && (buf->uio_resid > 0) && (count > 0)) {
321 		sz = sndbuf_getfree(bs);
322 		if (sz == 0) {
323 			if (nbio)
324 				ret = EWOULDBLOCK;
325 			else {
326 				timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
327 				if (timeout < 1)
328 					timeout = 1;
329 				timeout = 1;
330 	   			ret = chn_sleep(c, "pcmwr", timeout);
331 				if (ret == EWOULDBLOCK) {
332 					count -= timeout;
333 					ret = 0;
334 				} else if (ret == 0)
335 					count = hz;
336 			}
337 		} else {
338 			sz = MIN(sz, buf->uio_resid);
339 			KASSERT(sz > 0, ("confusion in chn_write"));
340 			/* kprintf("sz: %d\n", sz); */
341 
342 			/*
343 			 * The following assumes that the free space in
344 			 * the buffer can never be less around the
345 			 * unlock-uiomove-lock sequence.
346 			 */
347 			togo = sz;
348 			while (ret == 0 && togo> 0) {
349 				p = sndbuf_getfreeptr(bs);
350 				t = MIN(togo, sndbuf_getsize(bs) - p);
351 				off = sndbuf_getbufofs(bs, p);
352 				CHN_UNLOCK(c);
353 				ret = uiomove(off, t, buf);
354 				CHN_LOCK(c);
355 				togo -= t;
356 				x = sndbuf_acquire(bs, NULL, t);
357 			}
358 			ret = 0;
359 			if (ret == 0 && !(c->flags & CHN_F_TRIGGERED))
360 				chn_start(c, 0);
361 		}
362 	}
363 	/* kprintf("ret: %d left: %d\n", ret, buf->uio_resid); */
364 
365 	if (count <= 0) {
366 		c->flags |= CHN_F_DEAD;
367 		kprintf("%s: play interrupt timeout, channel dead\n", c->name);
368 	}
369 
370 	return ret;
371 }
372 
373 #if 0
374 static int
375 chn_rddump(struct pcm_channel *c, unsigned int cnt)
376 {
377     	struct snd_dbuf *b = c->bufhard;
378 
379 	CHN_LOCKASSERT(c);
380 #if 0
381 	static uint32_t kk = 0;
382 	printf("%u: dumping %d bytes\n", ++kk, cnt);
383 #endif
384 	c->xruns++;
385 	sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt);
386 	return sndbuf_dispose(b, NULL, cnt);
387 }
388 #endif
389 
390 /*
391  * Feed new data from the read buffer. Can be called in the bottom half.
392  */
393 int
394 chn_rdfeed(struct pcm_channel *c)
395 {
396     	struct snd_dbuf *b = c->bufhard;
397     	struct snd_dbuf *bs = c->bufsoft;
398 	unsigned int ret, amt;
399 
400 	CHN_LOCKASSERT(c);
401     	DEB(
402 	if (c->flags & CHN_F_CLOSING) {
403 		sndbuf_dump(b, "b", 0x02);
404 		sndbuf_dump(bs, "bs", 0x02);
405 	})
406 
407 #if 0
408 	amt = sndbuf_getready(b);
409 	if (sndbuf_getfree(bs) < amt) {
410 		c->xruns++;
411 		amt = sndbuf_getfree(bs);
412 	}
413 #endif
414 	amt = sndbuf_getfree(bs);
415 	ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
416 
417 	amt = sndbuf_getready(b);
418 	if (amt > 0) {
419 		c->xruns++;
420 		sndbuf_dispose(b, NULL, amt);
421 	}
422 
423 	chn_wakeup(c);
424 
425 	return ret;
426 }
427 
428 void
429 chn_rdupdate(struct pcm_channel *c)
430 {
431 	int ret;
432 
433 	CHN_LOCKASSERT(c);
434 	KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
435 
436 	if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED))
437 		return;
438 	chn_trigger(c, PCMTRIG_EMLDMARD);
439 	chn_dmaupdate(c);
440 	ret = chn_rdfeed(c);
441 	DEB(if (ret)
442 		kprintf("chn_rdfeed: %d\n", ret);)
443 }
444 
445 /* read interrupt routine. Must be called with interrupts blocked. */
446 static void
447 chn_rdintr(struct pcm_channel *c)
448 {
449 	int ret;
450 
451 	CHN_LOCKASSERT(c);
452 	/* tell the driver to update the primary buffer if non-dma */
453 	chn_trigger(c, PCMTRIG_EMLDMARD);
454 	/* update pointers in primary buffer */
455 	chn_dmaupdate(c);
456 	/* ...and feed from primary to secondary */
457 	ret = chn_rdfeed(c);
458 }
459 
460 /*
461  * user read routine - trigger if necessary, uiomove data from secondary buffer
462  * if blocking, sleep, rinse and repeat.
463  *
464  * called externally, so must handle locking
465  */
466 
467 int
468 chn_read(struct pcm_channel *c, struct uio *buf, int ioflags)
469 {
470 	int		ret, timeout, sz, count;
471 	int nbio;
472 	struct snd_dbuf       *bs = c->bufsoft;
473 	void *off;
474 	int t, x,togo,p;
475 
476 	CHN_LOCKASSERT(c);
477 	nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY);
478 	if (!(c->flags & CHN_F_TRIGGERED))
479 		chn_start(c, 0);
480 
481 	ret = 0;
482 	count = hz;
483 	while (!ret && (buf->uio_resid > 0) && (count > 0)) {
484 		sz = MIN(buf->uio_resid, sndbuf_getready(bs));
485 
486 		if (sz > 0) {
487 			/*
488 			 * The following assumes that the free space in
489 			 * the buffer can never be less around the
490 			 * unlock-uiomove-lock sequence.
491 			 */
492 			togo = sz;
493 			while (ret == 0 && togo> 0) {
494 				p = sndbuf_getreadyptr(bs);
495 				t = MIN(togo, sndbuf_getsize(bs) - p);
496 				off = sndbuf_getbufofs(bs, p);
497 				CHN_UNLOCK(c);
498 				ret = uiomove(off, t, buf);
499 				CHN_LOCK(c);
500 				togo -= t;
501 				x = sndbuf_dispose(bs, NULL, t);
502 			}
503 			ret = 0;
504 		} else {
505 			if (nbio) {
506 				ret = EWOULDBLOCK;
507 			} else {
508 				timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
509 				if (timeout < 1)
510 					timeout = 1;
511 	   			ret = chn_sleep(c, "pcmrd", timeout);
512 				if (ret == EWOULDBLOCK) {
513 					count -= timeout;
514 					ret = 0;
515 				} else {
516 					count = hz;
517 				}
518 
519 			}
520 		}
521 	}
522 
523 	if (count <= 0) {
524 		c->flags |= CHN_F_DEAD;
525 		kprintf("%s: record interrupt timeout, channel dead\n", c->name);
526 	}
527 
528 	return ret;
529 }
530 
531 void
532 chn_intr(struct pcm_channel *c)
533 {
534 	CHN_LOCK(c);
535 	c->interrupts++;
536 	if (c->direction == PCMDIR_PLAY)
537 		chn_wrintr(c);
538 	else
539 		chn_rdintr(c);
540 	CHN_UNLOCK(c);
541 }
542 
543 u_int32_t
544 chn_start(struct pcm_channel *c, int force)
545 {
546 	u_int32_t i, j;
547 	struct snd_dbuf *b = c->bufhard;
548 	struct snd_dbuf *bs = c->bufsoft;
549 
550 	CHN_LOCKASSERT(c);
551 	/* if we're running, or if we're prevented from triggering, bail */
552 	if ((c->flags & CHN_F_TRIGGERED) || ((c->flags & CHN_F_NOTRIGGER) && !force))
553 		return EINVAL;
554 
555 	i = (c->direction == PCMDIR_PLAY)? sndbuf_getready(bs) : sndbuf_getfree(bs);
556 	j = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(b) : sndbuf_getready(b);
557 	if (force || (i >= j)) {
558 		c->flags |= CHN_F_TRIGGERED;
559 		/*
560 		 * if we're starting because a vchan started, don't feed any data
561 		 * or it becomes impossible to start vchans synchronised with the
562 		 * first one.  the hardbuf should be empty so we top it up with
563 		 * silence to give it something to chew.  the real data will be
564 		 * fed at the first irq.
565 		 */
566 		if (c->direction == PCMDIR_PLAY) {
567 			/*
568 			 * Reduce pops during playback startup.
569 			 */
570 			sndbuf_fillsilence(b);
571 			if (SLIST_EMPTY(&c->children))
572 				chn_wrfeed(c);
573 		}
574 		sndbuf_setrun(b, 1);
575 		c->xruns = 0;
576 	    	chn_trigger(c, PCMTRIG_START);
577 		return 0;
578 	}
579 
580 	return 0;
581 }
582 
583 void
584 chn_resetbuf(struct pcm_channel *c)
585 {
586 	struct snd_dbuf *b = c->bufhard;
587 	struct snd_dbuf *bs = c->bufsoft;
588 
589 	c->blocks = 0;
590 	sndbuf_reset(b);
591 	sndbuf_reset(bs);
592 }
593 
594 /*
595  * chn_sync waits until the space in the given channel goes above
596  * a threshold. The threshold is checked against fl or rl respectively.
597  * Assume that the condition can become true, do not check here...
598  */
599 int
600 chn_sync(struct pcm_channel *c, int threshold)
601 {
602     	u_long rdy;
603     	int ret;
604     	struct snd_dbuf *bs = c->bufsoft;
605 
606 	CHN_LOCKASSERT(c);
607 
608 	/* if we haven't yet started and nothing is buffered, else start*/
609 	if (!(c->flags & CHN_F_TRIGGERED)) {
610 		if (sndbuf_getready(bs) > 0) {
611 			ret = chn_start(c, 1);
612 			if (ret)
613 				return ret;
614 		} else {
615 			return 0;
616 		}
617 	}
618 
619 	for (;;) {
620 		rdy = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
621 		if (rdy <= threshold) {
622 	    		ret = chn_sleep(c, "pcmsyn", 1);
623 	    		if (ret == ERESTART || ret == EINTR) {
624 				DEB(kprintf("chn_sync: tsleep returns %d\n", ret));
625 				return -1;
626 	    		}
627 		} else
628 			break;
629     	}
630     	return 0;
631 }
632 
633 /* called externally, handle locking */
634 int
635 chn_poll(struct pcm_channel *c, int ev, struct thread *td)
636 {
637 	struct snd_dbuf *bs = c->bufsoft;
638 	int ret;
639 
640 	CHN_LOCKASSERT(c);
641     	if (!(c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_TRIGGERED))
642 		chn_start(c, 1);
643 	ret = 0;
644 	if (chn_polltrigger(c) && chn_pollreset(c))
645 		ret = ev;
646 	else
647 		selrecord(td, sndbuf_getsel(bs));
648 	return ret;
649 }
650 
651 /*
652  * chn_abort terminates a running dma transfer.  it may sleep up to 200ms.
653  * it returns the number of bytes that have not been transferred.
654  *
655  * called from: dsp_close, dsp_ioctl, with channel locked
656  */
657 int
658 chn_abort(struct pcm_channel *c)
659 {
660     	int missing = 0;
661     	struct snd_dbuf *b = c->bufhard;
662     	struct snd_dbuf *bs = c->bufsoft;
663 
664 	CHN_LOCKASSERT(c);
665 	if (!(c->flags & CHN_F_TRIGGERED))
666 		return 0;
667 	c->flags |= CHN_F_ABORTING;
668 
669 	c->flags &= ~CHN_F_TRIGGERED;
670 	/* kill the channel */
671 	chn_trigger(c, PCMTRIG_ABORT);
672 	sndbuf_setrun(b, 0);
673 	if (!(c->flags & CHN_F_VIRTUAL))
674 		chn_dmaupdate(c);
675     	missing = sndbuf_getready(bs) + sndbuf_getready(b);
676 
677 	c->flags &= ~CHN_F_ABORTING;
678 	return missing;
679 }
680 
681 /*
682  * this routine tries to flush the dma transfer. It is called
683  * on a close of a playback channel.
684  * first, if there is data in the buffer, but the dma has not yet
685  * begun, we need to start it.
686  * next, we wait for the play buffer to drain
687  * finally, we stop the dma.
688  *
689  * called from: dsp_close, not valid for record channels.
690  */
691 
692 int
693 chn_flush(struct pcm_channel *c)
694 {
695     	int ret, count, resid, resid_p;
696     	struct snd_dbuf *b = c->bufhard;
697     	struct snd_dbuf *bs = c->bufsoft;
698 
699 	CHN_LOCKASSERT(c);
700 	KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
701     	DEB(kprintf("chn_flush: c->flags 0x%08x\n", c->flags));
702 
703 	/* if we haven't yet started and nothing is buffered, else start*/
704 	if (!(c->flags & CHN_F_TRIGGERED)) {
705 		if (sndbuf_getready(bs) > 0) {
706 			ret = chn_start(c, 1);
707 			if (ret)
708 				return ret;
709 		} else {
710 			return 0;
711 		}
712 	}
713 
714 	c->flags |= CHN_F_CLOSING;
715 	resid = sndbuf_getready(bs) + sndbuf_getready(b);
716 	resid_p = resid;
717 	count = 10;
718 	ret = 0;
719 	while ((count > 0) && (resid > sndbuf_getsize(b)) && (ret == 0)) {
720 		/* still pending output data. */
721 		ret = chn_sleep(c, "pcmflu", hz / 10);
722 		if (ret == EWOULDBLOCK)
723 			ret = 0;
724 		if (ret == 0) {
725 			resid = sndbuf_getready(bs) + sndbuf_getready(b);
726 			if (resid == resid_p)
727 				count--;
728 			if (resid > resid_p)
729 				DEB(printf("chn_flush: buffer length increasind %d -> %d\n", resid_p, resid));
730 			resid_p = resid;
731 		}
732    	}
733 	if (count == 0)
734 		DEB(kprintf("chn_flush: timeout, hw %d, sw %d\n",
735 			sndbuf_getready(b), sndbuf_getready(bs)));
736 
737 	c->flags &= ~CHN_F_TRIGGERED;
738 	/* kill the channel */
739 	chn_trigger(c, PCMTRIG_ABORT);
740 	sndbuf_setrun(b, 0);
741 
742     	c->flags &= ~CHN_F_CLOSING;
743     	return 0;
744 }
745 
746 int
747 fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
748 {
749 	int i;
750 
751 	for (i = 0; fmtlist[i]; i++)
752 		if (fmt == fmtlist[i])
753 			return 1;
754 	return 0;
755 }
756 
757 int
758 chn_reset(struct pcm_channel *c, u_int32_t fmt)
759 {
760 	int hwspd, r;
761 
762 	CHN_LOCKASSERT(c);
763 	c->flags &= CHN_F_RESET;
764 	c->interrupts = 0;
765 	c->xruns = 0;
766 
767 	r = CHANNEL_RESET(c->methods, c->devinfo);
768 	if (fmt != 0) {
769 #if 0
770 		hwspd = DSP_DEFAULT_SPEED;
771 		/* only do this on a record channel until feederbuilder works */
772 		if (c->direction == PCMDIR_REC)
773 			RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
774 		c->speed = hwspd;
775 #endif
776 		hwspd = chn_getcaps(c)->minspeed;
777 		c->speed = hwspd;
778 
779 		if (r == 0)
780 			r = chn_setformat(c, fmt);
781 		if (r == 0)
782 			r = chn_setspeed(c, hwspd);
783 #if 0
784 		if (r == 0)
785 			r = chn_setvolume(c, 100, 100);
786 #endif
787 	}
788 	if (r == 0)
789 		r = chn_setblocksize(c, 0, 0);
790 	if (r == 0) {
791 		chn_resetbuf(c);
792 		r = CHANNEL_RESETDONE(c->methods, c->devinfo);
793 	}
794 	return r;
795 }
796 
797 int
798 chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
799 {
800 	struct feeder_class *fc;
801 	struct snd_dbuf *b, *bs;
802 	int ret;
803 
804 	chn_lockinit(c, dir);
805 
806 	b = NULL;
807 	bs = NULL;
808 	c->devinfo = NULL;
809 	c->feeder = NULL;
810 
811 	ret = ENOMEM;
812 	b = sndbuf_create(c->dev, c->name, "primary", c);
813 	if (b == NULL)
814 		goto out;
815 	bs = sndbuf_create(c->dev, c->name, "secondary", c);
816 	if (bs == NULL)
817 		goto out;
818 
819 	CHN_LOCK(c);
820 
821 	ret = EINVAL;
822 	fc = feeder_getclass(NULL);
823 	if (fc == NULL)
824 		goto out;
825 	if (chn_addfeeder(c, fc, NULL))
826 		goto out;
827 
828 	/*
829 	 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
830 	 *	 with the channel unlocked because they are also called
831 	 *	 from driver methods that don't know about locking
832 	 */
833 	CHN_UNLOCK(c);
834 	sndbuf_setup(bs, NULL, 0);
835 	CHN_LOCK(c);
836 	c->bufhard = b;
837 	c->bufsoft = bs;
838 	c->flags = 0;
839 	c->feederflags = 0;
840 
841 	ret = ENODEV;
842 	CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() kmalloc() call */
843 	c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
844 	CHN_LOCK(c);
845 	if (c->devinfo == NULL)
846 		goto out;
847 
848 	ret = ENOMEM;
849 	if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
850 		goto out;
851 
852 	ret = chn_setdir(c, direction);
853 	if (ret)
854 		goto out;
855 
856 	ret = sndbuf_setfmt(b, AFMT_U8);
857 	if (ret)
858 		goto out;
859 
860 	ret = sndbuf_setfmt(bs, AFMT_U8);
861 	if (ret)
862 		goto out;
863 
864 
865 out:
866 	CHN_UNLOCK(c);
867 	if (ret) {
868 		if (c->devinfo) {
869 			if (CHANNEL_FREE(c->methods, c->devinfo))
870 				sndbuf_free(b);
871 		}
872 		if (bs)
873 			sndbuf_destroy(bs);
874 		if (b)
875 			sndbuf_destroy(b);
876 		c->flags |= CHN_F_DEAD;
877 		chn_lockdestroy(c);
878 
879 		return ret;
880 	}
881 
882 	return 0;
883 }
884 
885 int
886 chn_kill(struct pcm_channel *c)
887 {
888     	struct snd_dbuf *b = c->bufhard;
889     	struct snd_dbuf *bs = c->bufsoft;
890 
891 	if (c->flags & CHN_F_TRIGGERED)
892 		chn_trigger(c, PCMTRIG_ABORT);
893 	while (chn_removefeeder(c) == 0);
894 	if (CHANNEL_FREE(c->methods, c->devinfo))
895 		sndbuf_free(b);
896 	c->flags |= CHN_F_DEAD;
897 	sndbuf_destroy(bs);
898 	sndbuf_destroy(b);
899 	chn_lockdestroy(c);
900 	return 0;
901 }
902 
903 int
904 chn_setdir(struct pcm_channel *c, int dir)
905 {
906 #if NISA > 0
907     	struct snd_dbuf *b = c->bufhard;
908 #endif
909 	int r;
910 
911 	CHN_LOCKASSERT(c);
912 	c->direction = dir;
913 	r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
914 #if NISA > 0
915 	if (!r && SND_DMA(b))
916 		sndbuf_dmasetdir(b, c->direction);
917 #endif
918 	return r;
919 }
920 
921 int
922 chn_setvolume(struct pcm_channel *c, int left, int right)
923 {
924 	CHN_LOCKASSERT(c);
925 	/* should add a feeder for volume changing if channel returns -1 */
926 	if (left > 100)
927 		left = 100;
928 	if (left < 0)
929 		left = 0;
930 	if (right > 100)
931 		right = 100;
932 	if (right < 0)
933 		right = 0;
934 	c->volume = left | (right << 8);
935 	return 0;
936 }
937 
938 static int
939 chn_tryspeed(struct pcm_channel *c, int speed)
940 {
941 	struct pcm_feeder *f;
942     	struct snd_dbuf *b = c->bufhard;
943     	struct snd_dbuf *bs = c->bufsoft;
944     	struct snd_dbuf *x;
945 	int r, delta;
946 
947 	CHN_LOCKASSERT(c);
948 	DEB(kprintf("setspeed, channel %s\n", c->name));
949 	DEB(kprintf("want speed %d, ", speed));
950 	if (speed <= 0)
951 		return EINVAL;
952 	if (CANCHANGE(c)) {
953 		r = 0;
954 		c->speed = speed;
955 		sndbuf_setspd(bs, speed);
956 		RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
957 		DEB(kprintf("try speed %d, ", speed));
958 		sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
959 		DEB(kprintf("got speed %d\n", sndbuf_getspd(b)));
960 
961 		delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
962 		if (delta < 0)
963 			delta = -delta;
964 
965 		c->feederflags &= ~(1 << FEEDER_RATE);
966 		/*
967 		 * Used to be 500. It was too big!
968 		 */
969 		if (delta > 25)
970 			c->feederflags |= 1 << FEEDER_RATE;
971 		else
972 			sndbuf_setspd(bs, sndbuf_getspd(b));
973 
974 		r = chn_buildfeeder(c);
975 		DEB(kprintf("r = %d\n", r));
976 		if (r)
977 			goto out;
978 
979 		r = chn_setblocksize(c, 0, 0);
980 		if (r)
981 			goto out;
982 
983 		if (!(c->feederflags & (1 << FEEDER_RATE)))
984 			goto out;
985 
986 		r = EINVAL;
987 		f = chn_findfeeder(c, FEEDER_RATE);
988 		DEB(kprintf("feedrate = %p\n", f));
989 		if (f == NULL)
990 			goto out;
991 
992 		x = (c->direction == PCMDIR_REC)? b : bs;
993 		r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
994 		DEB(kprintf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r));
995 		if (r)
996 			goto out;
997 
998 		x = (c->direction == PCMDIR_REC)? bs : b;
999 		r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
1000 		DEB(kprintf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r));
1001 out:
1002 		if (!r)
1003 			r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
1004 							sndbuf_getfmt(b));
1005 		if (!r)
1006 			sndbuf_setfmt(bs, c->format);
1007 		DEB(kprintf("setspeed done, r = %d\n", r));
1008 		return r;
1009 	} else
1010 		return EINVAL;
1011 }
1012 
1013 int
1014 chn_setspeed(struct pcm_channel *c, int speed)
1015 {
1016 	int r, oldspeed = c->speed;
1017 
1018 	r = chn_tryspeed(c, speed);
1019 	if (r) {
1020 		DEB(kprintf("Failed to set speed %d falling back to %d\n", speed, oldspeed));
1021 		r = chn_tryspeed(c, oldspeed);
1022 	}
1023 	return r;
1024 }
1025 
1026 static int
1027 chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
1028 {
1029 	struct snd_dbuf *b = c->bufhard;
1030 	struct snd_dbuf *bs = c->bufsoft;
1031 	int r;
1032 
1033 	CHN_LOCKASSERT(c);
1034 	if (CANCHANGE(c)) {
1035 		DEB(kprintf("want format %d\n", fmt));
1036 		c->format = fmt;
1037 		r = chn_buildfeeder(c);
1038 		if (r == 0) {
1039 			sndbuf_setfmt(bs, c->format);
1040 			chn_resetbuf(c);
1041 			r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
1042 			if (r == 0)
1043 				r = chn_tryspeed(c, c->speed);
1044 		}
1045 		return r;
1046 	} else
1047 		return EINVAL;
1048 }
1049 
1050 int
1051 chn_setformat(struct pcm_channel *c, u_int32_t fmt)
1052 {
1053 	u_int32_t oldfmt = c->format;
1054 	int r;
1055 
1056 	r = chn_tryformat(c, fmt);
1057 	if (r) {
1058 		DEB(kprintf("Format change %d failed, reverting to %d\n", fmt, oldfmt));
1059 		chn_tryformat(c, oldfmt);
1060 	}
1061 	return r;
1062 }
1063 
1064 /*
1065  * given a bufsz value, round it to a power of 2 in the min-max range
1066  * XXX only works if min and max are powers of 2
1067  */
1068 static int
1069 round_bufsz(int bufsz, int min, int max)
1070 {
1071 	int tmp = min * 2;
1072 
1073 	KASSERT((min & (min-1)) == 0, ("min %d must be power of 2\n", min));
1074 	KASSERT((max & (max-1)) == 0, ("max %d must be power of 2\n", max));
1075 	while (tmp <= bufsz)
1076 		tmp <<= 1;
1077 	tmp >>= 1;
1078 	if (tmp > max)
1079 		tmp = max;
1080 	return tmp;
1081 }
1082 
1083 /*
1084  * set the channel's blocksize both for soft and hard buffers.
1085  *
1086  * blksz should be a power of 2 between 2**4 and 2**16 -- it is useful
1087  * that it has the same value for both bufsoft and bufhard.
1088  * blksz == -1 computes values according to a target irq rate.
1089  * blksz == 0 reuses previous values if available, otherwise
1090  * behaves as for -1
1091  *
1092  * blkcnt is set by the user, between 2 and (2**17)/blksz for bufsoft,
1093  * but should be a power of 2 for bufhard to simplify life to low
1094  * level drivers.
1095  * Note, for the rec channel a large blkcnt is ok,
1096  * but for the play channel we want blksz as small as possible to keep
1097  * the delay small, because routines in the write path always try to
1098  * keep bufhard full.
1099  *
1100  * Unless we have good reason to, use the values suggested by the caller.
1101  */
1102 int
1103 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
1104 {
1105 	struct snd_dbuf *b = c->bufhard;
1106 	struct snd_dbuf *bs = c->bufsoft;
1107 	int irqhz, ret, maxsz, maxsize, reqblksz;
1108 
1109 	CHN_LOCKASSERT(c);
1110 	if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED)) {
1111 		KASSERT(sndbuf_getsize(bs) ==  0 ||
1112 		    sndbuf_getsize(bs) >= sndbuf_getsize(b),
1113 		    ("%s(%s): bufsoft size %d < bufhard size %d", __func__,
1114 		    c->name, sndbuf_getsize(bs), sndbuf_getsize(b)));
1115 		return EINVAL;
1116 	}
1117 	c->flags |= CHN_F_SETBLOCKSIZE;
1118 
1119 	ret = 0;
1120 	DEB(kprintf("%s(%d, %d)\n", __func__, blkcnt, blksz));
1121 	if (blksz == 0 || blksz == -1) { /* let the driver choose values */
1122 		if (blksz == -1)	/* delete previous values */
1123 			c->flags &= ~CHN_F_HAS_SIZE;
1124 		if (!(c->flags & CHN_F_HAS_SIZE)) { /* no previous value */
1125 			/*
1126 			 * compute a base blksz according to the target irq
1127 			 * rate, then round to a suitable power of 2
1128 			 * in the range 16.. 2^17/2.
1129 			 * Finally compute a suitable blkcnt.
1130 			 */
1131 			blksz = round_bufsz( (sndbuf_getbps(bs) *
1132 				sndbuf_getspd(bs)) / chn_targetirqrate,
1133 				16, CHN_2NDBUFMAXSIZE / 2);
1134 			blkcnt = CHN_2NDBUFMAXSIZE / blksz;
1135 		} else { /* use previously defined value */
1136 			blkcnt = sndbuf_getblkcnt(bs);
1137 			blksz = sndbuf_getblksz(bs);
1138 		}
1139 	} else {
1140 		/*
1141 		 * use supplied values if reasonable. Note that here we
1142 		 * might have blksz which is not a power of 2 if the
1143 		 * ioctl() to compute it allows such values.
1144 		 */
1145 		ret = EINVAL;
1146 		if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE))
1147 			goto out;
1148 		ret = 0;
1149 		c->flags |= CHN_F_HAS_SIZE;
1150 	}
1151 
1152 	reqblksz = blksz;
1153 	if (reqblksz < sndbuf_getbps(bs))
1154 		reqblksz = sndbuf_getbps(bs);
1155 	if (reqblksz % sndbuf_getbps(bs))
1156 		reqblksz -= reqblksz % sndbuf_getbps(bs);
1157 
1158 	/* adjust for different hw format/speed */
1159 	/*
1160 	 * Now compute the approx irq rate for the given (soft) blksz,
1161 	 * reduce to the acceptable range and compute a corresponding blksz
1162 	 * for the hard buffer. Then set the channel's blocksize and
1163 	 * corresponding hardbuf value. The number of blocks used should
1164 	 * be set by the device-specific routine. In fact, even the
1165 	 * call to sndbuf_setblksz() should not be here! XXX
1166 	 */
1167 
1168 	irqhz = (sndbuf_getbps(bs) * sndbuf_getspd(bs)) / blksz;
1169 	RANGE(irqhz, 16, 512);
1170 
1171 	maxsz = sndbuf_getmaxsize(b);
1172 	if (maxsz == 0) /* virtual channels don't appear to allocate bufhard */
1173 		maxsz = CHN_2NDBUFMAXSIZE;
1174 	blksz = round_bufsz( (sndbuf_getbps(b) * sndbuf_getspd(b)) / irqhz,
1175 			16, maxsz / 2);
1176 
1177 	/* Increase the size of bufsoft if before increasing bufhard. */
1178 	maxsize = sndbuf_getsize(b);
1179 	if (sndbuf_getsize(bs) > maxsize)
1180 		maxsize = sndbuf_getsize(bs);
1181 	if (reqblksz * blkcnt > maxsize)
1182 		maxsize = reqblksz * blkcnt;
1183 	if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
1184 		ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
1185 		if (ret)
1186 			goto out1;
1187 	}
1188 
1189 	CHN_UNLOCK(c);
1190 	sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz));
1191 	CHN_LOCK(c);
1192 
1193 	/* Decrease the size of bufsoft after decreasing bufhard. */
1194 	maxsize = sndbuf_getsize(b);
1195 	if (reqblksz * blkcnt > maxsize)
1196 		maxsize = reqblksz * blkcnt;
1197 	if (maxsize > sndbuf_getsize(bs))
1198 		kprintf("Danger! %s bufsoft size increasing from %d to %d after CHANNEL_SETBLOCKSIZE()\n",
1199 		    c->name, sndbuf_getsize(bs), maxsize);
1200 	if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
1201 		ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
1202 		if (ret)
1203 			goto out1;
1204 	}
1205 
1206 	chn_resetbuf(c);
1207 out1:
1208 	KASSERT(sndbuf_getsize(bs) ==  0 ||
1209 	    sndbuf_getsize(bs) >= sndbuf_getsize(b),
1210 	    ("%s(%s): bufsoft size %d < bufhard size %d, reqblksz=%d blksz=%d maxsize=%d blkcnt=%d",
1211 	    __func__, c->name, sndbuf_getsize(bs), sndbuf_getsize(b), reqblksz,
1212 	    blksz, maxsize, blkcnt));
1213 out:
1214 	c->flags &= ~CHN_F_SETBLOCKSIZE;
1215 #if 0
1216 	if (1) {
1217 		static uint32_t kk = 0;
1218 		printf("%u: b %d/%d/%d : (%d)%d/0x%0x | bs %d/%d/%d : (%d)%d/0x%0x\n", ++kk,
1219 			sndbuf_getsize(b), sndbuf_getblksz(b), sndbuf_getblkcnt(b),
1220 			sndbuf_getbps(b),
1221 			sndbuf_getspd(b), sndbuf_getfmt(b),
1222 			sndbuf_getsize(bs), sndbuf_getblksz(bs), sndbuf_getblkcnt(bs),
1223 			sndbuf_getbps(bs),
1224 			sndbuf_getspd(bs), sndbuf_getfmt(bs));
1225 		if (sndbuf_getsize(b) % sndbuf_getbps(b) ||
1226 				sndbuf_getblksz(b) % sndbuf_getbps(b) ||
1227 				sndbuf_getsize(bs) % sndbuf_getbps(bs) ||
1228 				sndbuf_getblksz(b) % sndbuf_getbps(b)) {
1229 			printf("%u: bps/blksz alignment screwed!\n", kk);
1230 		}
1231 	}
1232 #endif
1233 	return ret;
1234 }
1235 
1236 int
1237 chn_trigger(struct pcm_channel *c, int go)
1238 {
1239 #if NISA > 0
1240     	struct snd_dbuf *b = c->bufhard;
1241 #endif
1242 	int ret;
1243 
1244 	CHN_LOCKASSERT(c);
1245 #if NISA > 0
1246 	if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
1247 		sndbuf_dmabounce(b);
1248 #endif
1249 	ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
1250 
1251 	return ret;
1252 }
1253 
1254 int
1255 chn_getptr(struct pcm_channel *c)
1256 {
1257 #if 0
1258 	int hwptr;
1259 	int a = (1 << c->align) - 1;
1260 
1261 	CHN_LOCKASSERT(c);
1262 	hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1263 	/* don't allow unaligned values in the hwa ptr */
1264 #if 1
1265 	hwptr &= ~a ; /* Apply channel align mask */
1266 #endif
1267 	hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
1268 	return hwptr;
1269 #endif
1270 	int hwptr;
1271 
1272 	CHN_LOCKASSERT(c);
1273 	hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1274 	return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
1275 }
1276 
1277 struct pcmchan_caps *
1278 chn_getcaps(struct pcm_channel *c)
1279 {
1280 	CHN_LOCKASSERT(c);
1281 	return CHANNEL_GETCAPS(c->methods, c->devinfo);
1282 }
1283 
1284 u_int32_t
1285 chn_getformats(struct pcm_channel *c)
1286 {
1287 	u_int32_t *fmtlist, fmts;
1288 	int i;
1289 
1290 	fmtlist = chn_getcaps(c)->fmtlist;
1291 	fmts = 0;
1292 	for (i = 0; fmtlist[i]; i++)
1293 		fmts |= fmtlist[i];
1294 
1295 	/* report software-supported formats */
1296 	if (report_soft_formats)
1297 		fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
1298 		    AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
1299 		    AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
1300 		    AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
1301 
1302 	return fmts;
1303 }
1304 
1305 static int
1306 chn_buildfeeder(struct pcm_channel *c)
1307 {
1308 	struct feeder_class *fc;
1309 	struct pcm_feederdesc desc;
1310 	u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
1311 	int err;
1312 
1313 	CHN_LOCKASSERT(c);
1314 	while (chn_removefeeder(c) == 0);
1315 	KASSERT((c->feeder == NULL), ("feeder chain not empty"));
1316 
1317 	c->align = sndbuf_getalign(c->bufsoft);
1318 
1319 	if (SLIST_EMPTY(&c->children)) {
1320 		fc = feeder_getclass(NULL);
1321 		KASSERT(fc != NULL, ("can't find root feeder"));
1322 
1323 		err = chn_addfeeder(c, fc, NULL);
1324 		if (err) {
1325 			DEB(kprintf("can't add root feeder, err %d\n", err));
1326 
1327 			return err;
1328 		}
1329 		c->feeder->desc->out = c->format;
1330 	} else {
1331 		if (c->flags & CHN_F_HAS_VCHAN) {
1332 			desc.type = FEEDER_MIXER;
1333 			desc.in = 0;
1334 		} else {
1335 			DEB(printf("can't decide which feeder type to use!\n"));
1336 			return EOPNOTSUPP;
1337 		}
1338 		desc.out = c->format;
1339 		desc.flags = 0;
1340 		fc = feeder_getclass(&desc);
1341 		if (fc == NULL) {
1342 			DEB(kprintf("can't find vchan feeder\n"));
1343 
1344 			return EOPNOTSUPP;
1345 		}
1346 
1347 		err = chn_addfeeder(c, fc, &desc);
1348 		if (err) {
1349 			DEB(kprintf("can't add vchan feeder, err %d\n", err));
1350 
1351 			return err;
1352 		}
1353 	}
1354 	c->feederflags &= ~(1 << FEEDER_VOLUME);
1355 	if (c->direction == PCMDIR_PLAY &&
1356 			!(c->flags & CHN_F_VIRTUAL) &&
1357 			c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTVOL) &&
1358 			c->parentsnddev->mixer_dev)
1359 		c->feederflags |= 1 << FEEDER_VOLUME;
1360 	flags = c->feederflags;
1361 	fmtlist = chn_getcaps(c)->fmtlist;
1362 
1363 	DEB(kprintf("feederflags %x\n", flags));
1364 
1365 	for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
1366 		if (flags & (1 << type)) {
1367 			desc.type = type;
1368 			desc.in = 0;
1369 			desc.out = 0;
1370 			desc.flags = 0;
1371 			DEB(kprintf("find feeder type %d, ", type));
1372 			fc = feeder_getclass(&desc);
1373 			DEB(kprintf("got %p\n", fc));
1374 			if (fc == NULL) {
1375 				DEB(kprintf("can't find required feeder type %d\n", type));
1376 
1377 				return EOPNOTSUPP;
1378 			}
1379 
1380  			DEB(kprintf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
1381 			tmp[0] = fc->desc->in;
1382 			tmp[1] = 0;
1383 			if (chn_fmtchain(c, tmp) == 0) {
1384 				DEB(printf("failed\n"));
1385 
1386 				return ENODEV;
1387 			}
1388  			DEB(printf("ok\n"));
1389 
1390 			err = chn_addfeeder(c, fc, fc->desc);
1391 			if (err) {
1392 				DEB(kprintf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err));
1393 
1394 				return err;
1395 			}
1396 			DEB(kprintf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out));
1397 		}
1398 	}
1399 
1400  	if (c->direction == PCMDIR_REC) {
1401 	 	tmp[0] = c->format;
1402  		tmp[1] = 0;
1403  		hwfmt = chn_fmtchain(c, tmp);
1404  	} else
1405  		hwfmt = chn_fmtchain(c, fmtlist);
1406 
1407 	if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
1408 		DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt));
1409 		return ENODEV;
1410 	}
1411 
1412 	sndbuf_setfmt(c->bufhard, hwfmt);
1413 
1414 	if ((flags & (1 << FEEDER_VOLUME))) {
1415 		struct dev_ioctl_args map;
1416 		int vol = 100 | (100 << 8);
1417 
1418 		CHN_UNLOCK(c);
1419 		/*
1420 		 * XXX This is ugly! The way mixer subs being so secretive
1421 		 * about its own internals force us to use this silly
1422 		 * monkey trick.
1423 		 */
1424 		map.a_head.a_dev = c->parentsnddev->mixer_dev;
1425 		map.a_cmd = MIXER_READ(SOUND_MIXER_PCM);
1426 		map.a_data = (caddr_t)&vol;
1427 		map.a_fflag = -1;
1428 		map.a_cred = NULL;
1429 		if (mixer_ioctl(&map) != 0)
1430 			device_printf(c->dev, "Soft Volume: Failed to read default value\n");
1431 		CHN_LOCK(c);
1432 		chn_setvolume(c, vol & 0x7f, (vol >> 8) & 0x7f);
1433 	}
1434 
1435 	return 0;
1436 }
1437 
1438 int
1439 chn_notify(struct pcm_channel *c, u_int32_t flags)
1440 {
1441 	struct pcmchan_children *pce;
1442 	struct pcm_channel *child;
1443 	int run;
1444 
1445 	CHN_LOCK(c);
1446 
1447 	if (SLIST_EMPTY(&c->children)) {
1448 		CHN_UNLOCK(c);
1449 		return ENODEV;
1450 	}
1451 
1452 	run = (c->flags & CHN_F_TRIGGERED)? 1 : 0;
1453 	/*
1454 	 * if the hwchan is running, we can't change its rate, format or
1455 	 * blocksize
1456 	 */
1457 	if (run)
1458 		flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
1459 
1460 	if (flags & CHN_N_RATE) {
1461 		/*
1462 		 * we could do something here, like scan children and decide on
1463 		 * the most appropriate rate to mix at, but we don't for now
1464 		 */
1465 	}
1466 	if (flags & CHN_N_FORMAT) {
1467 		/*
1468 		 * we could do something here, like scan children and decide on
1469 		 * the most appropriate mixer feeder to use, but we don't for now
1470 		 */
1471 	}
1472 	if (flags & CHN_N_VOLUME) {
1473 		/*
1474 		 * we could do something here but we don't for now
1475 		 */
1476 	}
1477 	if (flags & CHN_N_BLOCKSIZE) {
1478 		int blksz;
1479 		/*
1480 		 * scan the children, find the lowest blocksize and use that
1481 		 * for the hard blocksize
1482 		 */
1483 		blksz = sndbuf_getmaxsize(c->bufhard) / 2;
1484 		SLIST_FOREACH(pce, &c->children, link) {
1485 			child = pce->channel;
1486 			CHN_LOCK(child);
1487 			if (sndbuf_getblksz(child->bufhard) < blksz)
1488 				blksz = sndbuf_getblksz(child->bufhard);
1489 			CHN_UNLOCK(child);
1490 		}
1491 		chn_setblocksize(c, 2, blksz);
1492 	}
1493 	if (flags & CHN_N_TRIGGER) {
1494 		int nrun;
1495 		/*
1496 		 * scan the children, and figure out if any are running
1497 		 * if so, we need to be running, otherwise we need to be stopped
1498 		 * if we aren't in our target sstate, move to it
1499 		 */
1500 		nrun = 0;
1501 		SLIST_FOREACH(pce, &c->children, link) {
1502 			child = pce->channel;
1503 			CHN_LOCK(child);
1504 			if (child->flags & CHN_F_TRIGGERED)
1505 				nrun = 1;
1506 			CHN_UNLOCK(child);
1507 		}
1508 		if (nrun && !run)
1509 			chn_start(c, 1);
1510 		if (!nrun && run)
1511 			chn_abort(c);
1512 	}
1513 	CHN_UNLOCK(c);
1514 	return 0;
1515 }
1516 
1517 void
1518 chn_lock(struct pcm_channel *c)
1519 {
1520 	CHN_LOCK(c);
1521 }
1522 
1523 void
1524 chn_unlock(struct pcm_channel *c)
1525 {
1526 	CHN_UNLOCK(c);
1527 }
1528