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