xref: /freebsd/sys/dev/sound/pcm/channel.c (revision 7bd6fde3)
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 #define BUF_PARENT(c, b)	\
45 	(((c) != NULL && (c)->parentchannel != NULL && \
46 	(c)->parentchannel->bufhard != NULL) ? \
47 	(c)->parentchannel->bufhard : (b))
48 
49 /*
50 #define DEB(x) x
51 */
52 
53 int report_soft_formats = 1;
54 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
55 	&report_soft_formats, 1, "report software-emulated formats");
56 
57 int chn_latency = CHN_LATENCY_DEFAULT;
58 TUNABLE_INT("hw.snd.latency", &chn_latency);
59 
60 static int
61 sysctl_hw_snd_latency(SYSCTL_HANDLER_ARGS)
62 {
63 	int err, val;
64 
65 	val = chn_latency;
66 	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
67 	if (val < CHN_LATENCY_MIN || val > CHN_LATENCY_MAX)
68 		err = EINVAL;
69 	else
70 		chn_latency = val;
71 
72 	return err;
73 }
74 SYSCTL_PROC(_hw_snd, OID_AUTO, latency, CTLTYPE_INT | CTLFLAG_RW,
75 	0, sizeof(int), sysctl_hw_snd_latency, "I",
76 	"buffering latency (0=low ... 10=high)");
77 
78 int chn_latency_profile = CHN_LATENCY_PROFILE_DEFAULT;
79 TUNABLE_INT("hw.snd.latency_profile", &chn_latency_profile);
80 
81 static int
82 sysctl_hw_snd_latency_profile(SYSCTL_HANDLER_ARGS)
83 {
84 	int err, val;
85 
86 	val = chn_latency_profile;
87 	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
88 	if (val < CHN_LATENCY_PROFILE_MIN || val > CHN_LATENCY_PROFILE_MAX)
89 		err = EINVAL;
90 	else
91 		chn_latency_profile = val;
92 
93 	return err;
94 }
95 SYSCTL_PROC(_hw_snd, OID_AUTO, latency_profile, CTLTYPE_INT | CTLFLAG_RW,
96 	0, sizeof(int), sysctl_hw_snd_latency_profile, "I",
97 	"buffering latency profile (0=aggresive 1=safe)");
98 
99 /**
100  * @brief Channel sync group lock
101  *
102  * Clients should acquire this lock @b without holding any channel locks
103  * before touching syncgroups or the main syncgroup list.
104  */
105 struct mtx snd_pcm_syncgroups_mtx;
106 MTX_SYSINIT(pcm_syncgroup, &snd_pcm_syncgroups_mtx, "PCM channel sync group lock", MTX_DEF);
107 /**
108  * @brief syncgroups' master list
109  *
110  * Each time a channel syncgroup is created, it's added to this list.  This
111  * list should only be accessed with @sa snd_pcm_syncgroups_mtx held.
112  *
113  * See SNDCTL_DSP_SYNCGROUP for more information.
114  */
115 struct pcm_synclist snd_pcm_syncgroups = SLIST_HEAD_INITIALIZER(head);
116 
117 static int chn_buildfeeder(struct pcm_channel *c);
118 
119 static void
120 chn_lockinit(struct pcm_channel *c, int dir)
121 {
122 	switch(dir) {
123 	case PCMDIR_PLAY:
124 		c->lock = snd_mtxcreate(c->name, "pcm play channel");
125 		break;
126 	case PCMDIR_REC:
127 		c->lock = snd_mtxcreate(c->name, "pcm record channel");
128 		break;
129 	case PCMDIR_VIRTUAL:
130 		c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
131 		break;
132 	case 0:
133 		c->lock = snd_mtxcreate(c->name, "pcm fake channel");
134 		break;
135 	}
136 
137 	cv_init(&c->cv, c->name);
138 }
139 
140 static void
141 chn_lockdestroy(struct pcm_channel *c)
142 {
143 	snd_mtxfree(c->lock);
144 	cv_destroy(&c->cv);
145 }
146 
147 /**
148  * @brief Determine channel is ready for I/O
149  *
150  * @retval 1 = ready for I/O
151  * @retval 0 = not ready for I/O
152  */
153 static int
154 chn_polltrigger(struct pcm_channel *c)
155 {
156 	struct snd_dbuf *bs = c->bufsoft;
157 	unsigned amt, lim;
158 
159 	CHN_LOCKASSERT(c);
160 	if (c->flags & CHN_F_MAPPED) {
161 		if (sndbuf_getprevblocks(bs) == 0)
162 			return 1;
163 		else
164 			return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
165 	} else {
166 		amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
167 #if 0
168 		lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
169 #endif
170 		lim = c->lw;
171 		return (amt >= lim) ? 1 : 0;
172 	}
173 	return 0;
174 }
175 
176 static int
177 chn_pollreset(struct pcm_channel *c)
178 {
179 	struct snd_dbuf *bs = c->bufsoft;
180 
181 	CHN_LOCKASSERT(c);
182 	sndbuf_updateprevtotal(bs);
183 	return 1;
184 }
185 
186 static void
187 chn_wakeup(struct pcm_channel *c)
188 {
189 	struct snd_dbuf *bs = c->bufsoft;
190 	struct pcmchan_children *pce;
191 
192 	CHN_LOCKASSERT(c);
193 	if (SLIST_EMPTY(&c->children)) {
194 		if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
195 			selwakeuppri(sndbuf_getsel(bs), PRIBIO);
196 	} else {
197 		SLIST_FOREACH(pce, &c->children, link) {
198 			CHN_LOCK(pce->channel);
199 			chn_wakeup(pce->channel);
200 			CHN_UNLOCK(pce->channel);
201 		}
202 	}
203 
204 	wakeup_one(bs);
205 }
206 
207 static int
208 chn_sleep(struct pcm_channel *c, char *str, int timeout)
209 {
210     	struct snd_dbuf *bs = c->bufsoft;
211 	int ret;
212 
213 	CHN_LOCKASSERT(c);
214 #ifdef USING_MUTEX
215 	ret = msleep(bs, c->lock, PRIBIO | PCATCH, str, timeout);
216 #else
217 	ret = tsleep(bs, PRIBIO | PCATCH, str, timeout);
218 #endif
219 
220 	return ret;
221 }
222 
223 /*
224  * chn_dmaupdate() tracks the status of a dma transfer,
225  * updating pointers.
226  */
227 
228 static unsigned int
229 chn_dmaupdate(struct pcm_channel *c)
230 {
231 	struct snd_dbuf *b = c->bufhard;
232 	unsigned int delta, old, hwptr, amt;
233 
234 	KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
235 	CHN_LOCKASSERT(c);
236 
237 	old = sndbuf_gethwptr(b);
238 	hwptr = chn_getptr(c);
239 	delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
240 	sndbuf_sethwptr(b, hwptr);
241 
242 	DEB(
243 	if (delta >= ((sndbuf_getsize(b) * 15) / 16)) {
244 		if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING)))
245 			device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr);
246 	}
247 	);
248 
249 	if (c->direction == PCMDIR_PLAY) {
250 		amt = MIN(delta, sndbuf_getready(b));
251 		amt -= amt % sndbuf_getbps(b);
252 		if (amt > 0)
253 			sndbuf_dispose(b, NULL, amt);
254 	} else {
255 		amt = MIN(delta, sndbuf_getfree(b));
256 		amt -= amt % sndbuf_getbps(b);
257 		if (amt > 0)
258 		       sndbuf_acquire(b, NULL, amt);
259 	}
260 	if (snd_verbose > 2 && (c->flags & CHN_F_TRIGGERED) && delta == 0) {
261 		device_printf(c->dev, "WARNING: PCMDIR_%s DMA completion "
262 			"too fast/slow ! hwptr=%u, old=%u "
263 			"delta=%u amt=%u ready=%u free=%u\n",
264 			(c->direction == PCMDIR_PLAY) ? "PLAY" : "REC",
265 			hwptr, old, delta, amt,
266 			sndbuf_getready(b), sndbuf_getfree(b));
267 	}
268 
269 	return delta;
270 }
271 
272 void
273 chn_wrupdate(struct pcm_channel *c)
274 {
275 	int ret;
276 
277 	CHN_LOCKASSERT(c);
278 	KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
279 
280 	if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || !(c->flags & CHN_F_TRIGGERED))
281 		return;
282 	chn_dmaupdate(c);
283 	ret = chn_wrfeed(c);
284 	/* tell the driver we've updated the primary buffer */
285 	chn_trigger(c, PCMTRIG_EMLDMAWR);
286 	DEB(if (ret)
287 		printf("chn_wrupdate: chn_wrfeed returned %d\n", ret);)
288 
289 }
290 
291 int
292 chn_wrfeed(struct pcm_channel *c)
293 {
294     	struct snd_dbuf *b = c->bufhard;
295     	struct snd_dbuf *bs = c->bufsoft;
296 	unsigned int ret, amt;
297 
298 	CHN_LOCKASSERT(c);
299 #if 0
300     	DEB(
301 	if (c->flags & CHN_F_CLOSING) {
302 		sndbuf_dump(b, "b", 0x02);
303 		sndbuf_dump(bs, "bs", 0x02);
304 	})
305 #endif
306 
307 	if (c->flags & CHN_F_MAPPED)
308 		sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
309 
310 	amt = sndbuf_getfree(b);
311 	DEB(if (amt > sndbuf_getsize(bs) &&
312 		    sndbuf_getbps(bs) >= sndbuf_getbps(b)) {
313 		printf("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name,
314 		    amt, sndbuf_getsize(bs), c->flags);
315 	});
316 
317 	ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
318 	/*
319 	 * Possible xruns. There should be no empty space left in buffer.
320 	 */
321 	if (sndbuf_getfree(b) > 0)
322 		c->xruns++;
323 
324 	if (ret == 0 && sndbuf_getfree(b) < amt)
325 		chn_wakeup(c);
326 
327 	return ret;
328 }
329 
330 static void
331 chn_wrintr(struct pcm_channel *c)
332 {
333 	int ret;
334 
335 	CHN_LOCKASSERT(c);
336 	/* update pointers in primary buffer */
337 	chn_dmaupdate(c);
338 	/* ...and feed from secondary to primary */
339 	ret = chn_wrfeed(c);
340 	/* tell the driver we've updated the primary buffer */
341 	chn_trigger(c, PCMTRIG_EMLDMAWR);
342 	DEB(if (ret)
343 		printf("chn_wrintr: chn_wrfeed returned %d\n", ret);)
344 }
345 
346 /*
347  * user write routine - uiomove data into secondary buffer, trigger if necessary
348  * if blocking, sleep, rinse and repeat.
349  *
350  * called externally, so must handle locking
351  */
352 
353 int
354 chn_write(struct pcm_channel *c, struct uio *buf)
355 {
356 	int ret, count, sz;
357 	struct snd_dbuf *bs = c->bufsoft;
358 	void *off;
359 	int t, x, togo, p;
360 
361 	CHN_LOCKASSERT(c);
362 
363 	ret = 0;
364 	count = hz;
365 
366 	while (!ret && (buf->uio_resid > 0) && (count > 0)) {
367 		sz = sndbuf_getfree(bs);
368 		if (sz == 0) {
369 			if (c->flags & CHN_F_NBIO)
370 				ret = EWOULDBLOCK;
371 			else if (c->flags & CHN_F_NOTRIGGER) {
372 				/**
373 				 * @todo Evaluate whether EAGAIN is truly desirable.
374 				 * 	 4Front drivers behave like this, but I'm
375 				 * 	 not sure if it at all violates the "write
376 				 * 	 should be allowed to block" model.
377 				 *
378 				 * 	 The idea is that, while set with CHN_F_NOTRIGGER,
379 				 * 	 a channel isn't playing, *but* without this we
380 				 * 	 end up with "interrupt timeout / channel dead".
381 				 */
382 				ret = EAGAIN;
383 			} else {
384 	   			ret = chn_sleep(c, "pcmwr", c->timeout);
385 				if (ret == EWOULDBLOCK) {
386 					count -= c->timeout;
387 					ret = 0;
388 				} else if (ret == ERESTART || ret == EINTR) {
389 					c->flags |= CHN_F_ABORTING;
390 					return ret;
391 				} else if (ret == 0)
392 					count = hz;
393 			}
394 		} else {
395 			sz = MIN(sz, buf->uio_resid);
396 			KASSERT(sz > 0, ("confusion in chn_write"));
397 			/* printf("sz: %d\n", sz); */
398 
399 			/*
400 			 * The following assumes that the free space in
401 			 * the buffer can never be less around the
402 			 * unlock-uiomove-lock sequence.
403 			 */
404 			togo = sz;
405 			while (ret == 0 && togo > 0) {
406 				p = sndbuf_getfreeptr(bs);
407 				t = MIN(togo, sndbuf_getsize(bs) - p);
408 				off = sndbuf_getbufofs(bs, p);
409 				CHN_UNLOCK(c);
410 				ret = uiomove(off, t, buf);
411 				CHN_LOCK(c);
412 				togo -= t;
413 				x = sndbuf_acquire(bs, NULL, t);
414 			}
415 			ret = 0;
416 			if (!(c->flags & CHN_F_TRIGGERED))
417 				chn_start(c, 0);
418 		}
419 	}
420 	/* printf("ret: %d left: %d\n", ret, buf->uio_resid); */
421 
422 	if (count <= 0) {
423 		c->flags |= CHN_F_DEAD;
424 		printf("%s: play interrupt timeout, channel dead\n", c->name);
425 	}
426 
427 	return ret;
428 }
429 
430 #if 0
431 static int
432 chn_rddump(struct pcm_channel *c, unsigned int cnt)
433 {
434     	struct snd_dbuf *b = c->bufhard;
435 
436 	CHN_LOCKASSERT(c);
437 #if 0
438 	static u_int32_t kk = 0;
439 	printf("%u: dumping %d bytes\n", ++kk, cnt);
440 #endif
441 	c->xruns++;
442 	sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt);
443 	return sndbuf_dispose(b, NULL, cnt);
444 }
445 #endif
446 
447 /*
448  * Feed new data from the read buffer. Can be called in the bottom half.
449  */
450 int
451 chn_rdfeed(struct pcm_channel *c)
452 {
453     	struct snd_dbuf *b = c->bufhard;
454     	struct snd_dbuf *bs = c->bufsoft;
455 	unsigned int ret, amt;
456 
457 	CHN_LOCKASSERT(c);
458     	DEB(
459 	if (c->flags & CHN_F_CLOSING) {
460 		sndbuf_dump(b, "b", 0x02);
461 		sndbuf_dump(bs, "bs", 0x02);
462 	})
463 
464 #if 0
465 	amt = sndbuf_getready(b);
466 	if (sndbuf_getfree(bs) < amt) {
467 		c->xruns++;
468 		amt = sndbuf_getfree(bs);
469 	}
470 #endif
471 	amt = sndbuf_getfree(bs);
472 	ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
473 
474 	amt = sndbuf_getready(b);
475 	if (amt > 0) {
476 		c->xruns++;
477 		sndbuf_dispose(b, NULL, amt);
478 	}
479 
480 	chn_wakeup(c);
481 
482 	return ret;
483 }
484 
485 void
486 chn_rdupdate(struct pcm_channel *c)
487 {
488 	int ret;
489 
490 	CHN_LOCKASSERT(c);
491 	KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
492 
493 	if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED))
494 		return;
495 	chn_trigger(c, PCMTRIG_EMLDMARD);
496 	chn_dmaupdate(c);
497 	ret = chn_rdfeed(c);
498 	DEB(if (ret)
499 		printf("chn_rdfeed: %d\n", ret);)
500 
501 }
502 
503 /* read interrupt routine. Must be called with interrupts blocked. */
504 static void
505 chn_rdintr(struct pcm_channel *c)
506 {
507 	int ret;
508 
509 	CHN_LOCKASSERT(c);
510 	/* tell the driver to update the primary buffer if non-dma */
511 	chn_trigger(c, PCMTRIG_EMLDMARD);
512 	/* update pointers in primary buffer */
513 	chn_dmaupdate(c);
514 	/* ...and feed from primary to secondary */
515 	ret = chn_rdfeed(c);
516 }
517 
518 /*
519  * user read routine - trigger if necessary, uiomove data from secondary buffer
520  * if blocking, sleep, rinse and repeat.
521  *
522  * called externally, so must handle locking
523  */
524 
525 int
526 chn_read(struct pcm_channel *c, struct uio *buf)
527 {
528 	int ret, sz, count;
529 	struct snd_dbuf *bs = c->bufsoft;
530 	void *off;
531 	int t, x, togo, p;
532 
533 	CHN_LOCKASSERT(c);
534 	if (!(c->flags & CHN_F_TRIGGERED))
535 		chn_start(c, 0);
536 
537 	ret = 0;
538 	count = hz;
539 	while (!ret && (buf->uio_resid > 0) && (count > 0)) {
540 		sz = MIN(buf->uio_resid, sndbuf_getready(bs));
541 
542 		if (sz > 0) {
543 			/*
544 			 * The following assumes that the free space in
545 			 * the buffer can never be less around the
546 			 * unlock-uiomove-lock sequence.
547 			 */
548 			togo = sz;
549 			while (ret == 0 && togo > 0) {
550 				p = sndbuf_getreadyptr(bs);
551 				t = MIN(togo, sndbuf_getsize(bs) - p);
552 				off = sndbuf_getbufofs(bs, p);
553 				CHN_UNLOCK(c);
554 				ret = uiomove(off, t, buf);
555 				CHN_LOCK(c);
556 				togo -= t;
557 				x = sndbuf_dispose(bs, NULL, t);
558 			}
559 			ret = 0;
560 		} else {
561 			if (c->flags & CHN_F_NBIO)
562 				ret = EWOULDBLOCK;
563 			else {
564 	   			ret = chn_sleep(c, "pcmrd", c->timeout);
565 				if (ret == EWOULDBLOCK) {
566 					count -= c->timeout;
567 					ret = 0;
568 				} else if (ret == ERESTART || ret == EINTR) {
569 					c->flags |= CHN_F_ABORTING;
570 					return ret;
571 				} else
572 					count = hz;
573 			}
574 		}
575 	}
576 
577 	if (count <= 0) {
578 		c->flags |= CHN_F_DEAD;
579 		printf("%s: record interrupt timeout, channel dead\n", c->name);
580 	}
581 
582 	return ret;
583 }
584 
585 void
586 chn_intr(struct pcm_channel *c)
587 {
588 	CHN_LOCK(c);
589 	c->interrupts++;
590 	if (c->direction == PCMDIR_PLAY)
591 		chn_wrintr(c);
592 	else
593 		chn_rdintr(c);
594 	CHN_UNLOCK(c);
595 }
596 
597 u_int32_t
598 chn_start(struct pcm_channel *c, int force)
599 {
600 	u_int32_t i, j;
601 	struct snd_dbuf *b = c->bufhard;
602 	struct snd_dbuf *bs = c->bufsoft;
603 
604 	CHN_LOCKASSERT(c);
605 	/* if we're running, or if we're prevented from triggering, bail */
606 	if ((c->flags & CHN_F_TRIGGERED) || ((c->flags & CHN_F_NOTRIGGER) && !force))
607 		return EINVAL;
608 
609 	if (force) {
610 		i = 1;
611 		j = 0;
612 	} else {
613 		if (c->direction == PCMDIR_REC) {
614 			i = sndbuf_getfree(bs);
615 			j = sndbuf_getready(b);
616 		} else {
617 			struct snd_dbuf *pb;
618 
619 			i = sndbuf_getready(bs);
620 
621 			pb = BUF_PARENT(c, b);
622 			j = min(sndbuf_xbytes(sndbuf_getsize(pb), pb, bs),
623 			    sndbuf_getsize(bs));
624 		}
625 		if (snd_verbose > 3 && SLIST_EMPTY(&c->children))
626 			printf("%s: PCMDIR_%s (%s) threshold i=%d j=%d\n",
627 			    __func__,
628 			    (c->direction == PCMDIR_PLAY) ? "PLAY" : "REC",
629 			    (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
630 			    i, j);
631 	}
632 
633 	if (i >= j) {
634 		c->flags |= CHN_F_TRIGGERED;
635 		sndbuf_setrun(b, 1);
636 		c->feedcount = (c->flags & CHN_F_CLOSING) ? 2 : 0;
637 		c->interrupts = 0;
638 		c->xruns = 0;
639 		if (c->direction == PCMDIR_PLAY && c->parentchannel == NULL) {
640 			chn_wrfeed(c);
641 			if (snd_verbose > 3)
642 				printf("%s: %s starting! (%s) (ready=%d "
643 				    "force=%d i=%d j=%d intrtimeout=%u)\n",
644 				    __func__,
645 				    (c->flags & CHN_F_HAS_VCHAN) ?
646 				    "VCHAN" : "HW",
647 				    (c->flags & CHN_F_CLOSING) ? "closing" :
648 				    "running",
649 				    sndbuf_getready(b),
650 				    force, i, j, c->timeout);
651 		}
652 	    	chn_trigger(c, PCMTRIG_START);
653 		return 0;
654 	}
655 
656 	return 0;
657 }
658 
659 void
660 chn_resetbuf(struct pcm_channel *c)
661 {
662 	struct snd_dbuf *b = c->bufhard;
663 	struct snd_dbuf *bs = c->bufsoft;
664 
665 	c->blocks = 0;
666 	sndbuf_reset(b);
667 	sndbuf_reset(bs);
668 }
669 
670 /*
671  * chn_sync waits until the space in the given channel goes above
672  * a threshold. The threshold is checked against fl or rl respectively.
673  * Assume that the condition can become true, do not check here...
674  */
675 int
676 chn_sync(struct pcm_channel *c, int threshold)
677 {
678 	int ret, count, hcount, minflush, resid, residp;
679     	struct snd_dbuf *b, *bs;
680 
681 	CHN_LOCKASSERT(c);
682 
683 	if (c->flags & (CHN_F_DEAD | CHN_F_ABORTING))
684 		return 0;
685 
686 	if (c->direction != PCMDIR_PLAY)
687 		return EINVAL;
688 
689 	bs = c->bufsoft;
690 
691 	/* if we haven't yet started and nothing is buffered, else start*/
692 	if (!(c->flags & CHN_F_TRIGGERED)) {
693 		if (sndbuf_getready(bs) > 0) {
694 			ret = chn_start(c, 1);
695 			if (ret)
696 				return ret;
697 		} else
698 			return 0;
699 	}
700 
701 	b = BUF_PARENT(c, c->bufhard);
702 
703 	threshold += sndbuf_getready(b);
704 	minflush = sndbuf_xbytes(threshold, b, bs);
705 	minflush -= minflush % sndbuf_getbps(bs);
706 
707 	if (minflush > 0) {
708 		threshold = min(minflush, sndbuf_getfree(bs));
709 		sndbuf_clear(bs, threshold);
710 		sndbuf_acquire(bs, NULL, threshold);
711 		minflush -= threshold;
712 	}
713 
714 	resid = sndbuf_getready(bs);
715 	residp = resid;
716 	count = sndbuf_xbytes(minflush + resid, bs, b) / sndbuf_getblksz(b);
717 	hcount = count;
718 	ret = 0;
719 
720 	while (count > 0 && resid > 0) {
721 		ret = chn_sleep(c, "pcmsyn", c->timeout);
722     		if (ret == ERESTART || ret == EINTR) {
723 			c->flags |= CHN_F_ABORTING;
724 			break;
725 		}
726 		if (ret == 0 || ret == EWOULDBLOCK) {
727 			resid = sndbuf_getready(bs);
728 			if (resid == residp) {
729 				--count;
730 				if (snd_verbose > 3)
731 					printf("%s: [stalled] timeout=%d "
732 					    "count=%d hcount=%d "
733 					    "resid=%d minflush=%d\n",
734 					    __func__, c->timeout, count,
735 					    hcount, resid, minflush);
736 			} else if (resid < residp && count < hcount) {
737 				++count;
738 				if (snd_verbose > 3)
739 					printf("%s: [resume] timeout=%d "
740 					    "count=%d hcount=%d "
741 					    "resid=%d minflush=%d\n",
742 					    __func__, c->timeout, count,
743 					    hcount, resid, minflush);
744 			}
745 			if (minflush > 0 && sndbuf_getfree(bs) > 0) {
746 				threshold = min(minflush,
747 				    sndbuf_getfree(bs));
748 				sndbuf_clear(bs, threshold);
749 				sndbuf_acquire(bs, NULL, threshold);
750 				resid = sndbuf_getready(bs);
751 				minflush -= threshold;
752 			}
753 			residp = resid;
754 		}
755 	}
756 
757 	if (snd_verbose > 3)
758 		printf("%s: timeout=%d count=%d hcount=%d resid=%d residp=%d "
759 		    "minflush=%d ret=%d\n",
760 		    __func__, c->timeout, count, hcount, resid, residp,
761 		    minflush, ret);
762 
763     	return 0;
764 }
765 
766 /* called externally, handle locking */
767 int
768 chn_poll(struct pcm_channel *c, int ev, struct thread *td)
769 {
770 	struct snd_dbuf *bs = c->bufsoft;
771 	int ret;
772 
773 	CHN_LOCKASSERT(c);
774     	if (!(c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_TRIGGERED))
775 		chn_start(c, 1);
776 	ret = 0;
777 	if (chn_polltrigger(c) && chn_pollreset(c))
778 		ret = ev;
779 	else
780 		selrecord(td, sndbuf_getsel(bs));
781 	return ret;
782 }
783 
784 /*
785  * chn_abort terminates a running dma transfer.  it may sleep up to 200ms.
786  * it returns the number of bytes that have not been transferred.
787  *
788  * called from: dsp_close, dsp_ioctl, with channel locked
789  */
790 int
791 chn_abort(struct pcm_channel *c)
792 {
793     	int missing = 0;
794     	struct snd_dbuf *b = c->bufhard;
795     	struct snd_dbuf *bs = c->bufsoft;
796 
797 	CHN_LOCKASSERT(c);
798 	if (!(c->flags & CHN_F_TRIGGERED))
799 		return 0;
800 	c->flags |= CHN_F_ABORTING;
801 
802 	c->flags &= ~CHN_F_TRIGGERED;
803 	/* kill the channel */
804 	chn_trigger(c, PCMTRIG_ABORT);
805 	sndbuf_setrun(b, 0);
806 	if (!(c->flags & CHN_F_VIRTUAL))
807 		chn_dmaupdate(c);
808     	missing = sndbuf_getready(bs) + sndbuf_getready(b);
809 
810 	c->flags &= ~CHN_F_ABORTING;
811 	return missing;
812 }
813 
814 /*
815  * this routine tries to flush the dma transfer. It is called
816  * on a close of a playback channel.
817  * first, if there is data in the buffer, but the dma has not yet
818  * begun, we need to start it.
819  * next, we wait for the play buffer to drain
820  * finally, we stop the dma.
821  *
822  * called from: dsp_close, not valid for record channels.
823  */
824 
825 int
826 chn_flush(struct pcm_channel *c)
827 {
828     	struct snd_dbuf *b = c->bufhard;
829 
830 	CHN_LOCKASSERT(c);
831 	KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
832     	DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags));
833 
834 	c->flags |= CHN_F_CLOSING;
835 	chn_sync(c, 0);
836 	c->flags &= ~CHN_F_TRIGGERED;
837 	/* kill the channel */
838 	chn_trigger(c, PCMTRIG_ABORT);
839 	sndbuf_setrun(b, 0);
840 
841     	c->flags &= ~CHN_F_CLOSING;
842     	return 0;
843 }
844 
845 int
846 fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
847 {
848 	int i;
849 
850 	for (i = 0; fmtlist[i]; i++)
851 		if (fmt == fmtlist[i])
852 			return 1;
853 	return 0;
854 }
855 
856 static struct afmtstr_table default_afmtstr_table[] = {
857 	{  "alaw", AFMT_A_LAW  }, { "mulaw", AFMT_MU_LAW },
858 	{    "u8", AFMT_U8     }, {    "s8", AFMT_S8     },
859 	{ "s16le", AFMT_S16_LE }, { "s16be", AFMT_S16_BE },
860 	{ "u16le", AFMT_U16_LE }, { "u16be", AFMT_U16_BE },
861 	{ "s24le", AFMT_S24_LE }, { "s24be", AFMT_S24_BE },
862 	{ "u24le", AFMT_U24_LE }, { "u24be", AFMT_U24_BE },
863 	{ "s32le", AFMT_S32_LE }, { "s32be", AFMT_S32_BE },
864 	{ "u32le", AFMT_U32_LE }, { "u32be", AFMT_U32_BE },
865 	{    NULL, 0           },
866 };
867 
868 int
869 afmtstr_swap_sign(char *s)
870 {
871 	if (s == NULL || strlen(s) < 2) /* full length of "s8" */
872 		return 0;
873 	if (*s == 's')
874 		*s = 'u';
875 	else if (*s == 'u')
876 		*s = 's';
877 	else
878 		return 0;
879 	return 1;
880 }
881 
882 int
883 afmtstr_swap_endian(char *s)
884 {
885 	if (s == NULL || strlen(s) < 5) /* full length of "s16le" */
886 		return 0;
887 	if (s[3] == 'l')
888 		s[3] = 'b';
889 	else if (s[3] == 'b')
890 		s[3] = 'l';
891 	else
892 		return 0;
893 	return 1;
894 }
895 
896 u_int32_t
897 afmtstr2afmt(struct afmtstr_table *tbl, const char *s, int stereo)
898 {
899 	size_t fsz, sz;
900 
901 	sz = (s == NULL) ? 0 : strlen(s);
902 
903 	if (sz > 1) {
904 
905 		if (tbl == NULL)
906 			tbl = default_afmtstr_table;
907 
908 		for (; tbl->fmtstr != NULL; tbl++) {
909 			fsz = strlen(tbl->fmtstr);
910 			if (sz < fsz)
911 				continue;
912 			if (strncmp(s, tbl->fmtstr, fsz) != 0)
913 				continue;
914 			if (fsz == sz)
915 				return tbl->format |
916 					    ((stereo) ? AFMT_STEREO : 0);
917 			if ((sz - fsz) < 2 || s[fsz] != ':')
918 				break;
919 			/*
920 			 * For now, just handle mono/stereo.
921 			 */
922 			if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 'm' ||
923 				    s[fsz + 1] == '1')) ||
924 				    strcmp(s + fsz + 1, "mono") == 0)
925 				return tbl->format;
926 			if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 's' ||
927 				    s[fsz + 1] == '2')) ||
928 				    strcmp(s + fsz + 1, "stereo") == 0)
929 				return tbl->format | AFMT_STEREO;
930 			break;
931 		}
932 	}
933 
934 	return 0;
935 }
936 
937 u_int32_t
938 afmt2afmtstr(struct afmtstr_table *tbl, u_int32_t afmt, char *dst,
939 					size_t len, int type, int stereo)
940 {
941 	u_int32_t fmt = 0;
942 	char *fmtstr = NULL, *tag = "";
943 
944 	if (tbl == NULL)
945 		tbl = default_afmtstr_table;
946 
947 	for (; tbl->format != 0; tbl++) {
948 		if (tbl->format == 0)
949 			break;
950 		if ((afmt & ~AFMT_STEREO) != tbl->format)
951 			continue;
952 		fmt = afmt;
953 		fmtstr = tbl->fmtstr;
954 		break;
955 	}
956 
957 	if (fmt != 0 && fmtstr != NULL && dst != NULL && len > 0) {
958 		strlcpy(dst, fmtstr, len);
959 		switch (type) {
960 		case AFMTSTR_SIMPLE:
961 			tag = (fmt & AFMT_STEREO) ? ":s" : ":m";
962 			break;
963 		case AFMTSTR_NUM:
964 			tag = (fmt & AFMT_STEREO) ? ":2" : ":1";
965 			break;
966 		case AFMTSTR_FULL:
967 			tag = (fmt & AFMT_STEREO) ? ":stereo" : ":mono";
968 			break;
969 		case AFMTSTR_NONE:
970 		default:
971 			break;
972 		}
973 		if (strlen(tag) > 0 && ((stereo && !(fmt & AFMT_STEREO)) || \
974 			    (!stereo && (fmt & AFMT_STEREO))))
975 			strlcat(dst, tag, len);
976 	}
977 
978 	return fmt;
979 }
980 
981 int
982 chn_reset(struct pcm_channel *c, u_int32_t fmt)
983 {
984 	int hwspd, r;
985 
986 	CHN_LOCKASSERT(c);
987 	c->feedcount = 0;
988 	c->flags &= CHN_F_RESET;
989 	c->interrupts = 0;
990 	c->timeout = 1;
991 	c->xruns = 0;
992 
993 	r = CHANNEL_RESET(c->methods, c->devinfo);
994 	if (fmt != 0) {
995 #if 0
996 		hwspd = DSP_DEFAULT_SPEED;
997 		/* only do this on a record channel until feederbuilder works */
998 		if (c->direction == PCMDIR_REC)
999 			RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
1000 		c->speed = hwspd;
1001 #endif
1002 		hwspd = chn_getcaps(c)->minspeed;
1003 		c->speed = hwspd;
1004 
1005 		if (r == 0)
1006 			r = chn_setformat(c, fmt);
1007 		if (r == 0)
1008 			r = chn_setspeed(c, hwspd);
1009 #if 0
1010 		if (r == 0)
1011 			r = chn_setvolume(c, 100, 100);
1012 #endif
1013 	}
1014 	if (r == 0)
1015 		r = chn_setlatency(c, chn_latency);
1016 	if (r == 0) {
1017 		chn_resetbuf(c);
1018 		r = CHANNEL_RESETDONE(c->methods, c->devinfo);
1019 	}
1020 	return r;
1021 }
1022 
1023 int
1024 chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
1025 {
1026 	struct feeder_class *fc;
1027 	struct snd_dbuf *b, *bs;
1028 	int ret;
1029 
1030 	chn_lockinit(c, dir);
1031 
1032 	b = NULL;
1033 	bs = NULL;
1034 	c->devinfo = NULL;
1035 	c->feeder = NULL;
1036 	c->latency = -1;
1037 	c->timeout = 1;
1038 
1039 	ret = ENOMEM;
1040 	b = sndbuf_create(c->dev, c->name, "primary", c);
1041 	if (b == NULL)
1042 		goto out;
1043 	bs = sndbuf_create(c->dev, c->name, "secondary", c);
1044 	if (bs == NULL)
1045 		goto out;
1046 
1047 	CHN_LOCK(c);
1048 
1049 	ret = EINVAL;
1050 	fc = feeder_getclass(NULL);
1051 	if (fc == NULL)
1052 		goto out;
1053 	if (chn_addfeeder(c, fc, NULL))
1054 		goto out;
1055 
1056 	/*
1057 	 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
1058 	 *	 with the channel unlocked because they are also called
1059 	 *	 from driver methods that don't know about locking
1060 	 */
1061 	CHN_UNLOCK(c);
1062 	sndbuf_setup(bs, NULL, 0);
1063 	CHN_LOCK(c);
1064 	c->bufhard = b;
1065 	c->bufsoft = bs;
1066 	c->flags = 0;
1067 	c->feederflags = 0;
1068 	c->sm = NULL;
1069 
1070 	ret = ENODEV;
1071 	CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() malloc() call */
1072 	c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
1073 	CHN_LOCK(c);
1074 	if (c->devinfo == NULL)
1075 		goto out;
1076 
1077 	ret = ENOMEM;
1078 	if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
1079 		goto out;
1080 
1081 	ret = chn_setdir(c, direction);
1082 	if (ret)
1083 		goto out;
1084 
1085 	ret = sndbuf_setfmt(b, AFMT_U8);
1086 	if (ret)
1087 		goto out;
1088 
1089 	ret = sndbuf_setfmt(bs, AFMT_U8);
1090 	if (ret)
1091 		goto out;
1092 
1093 	/**
1094 	 * @todo Should this be moved somewhere else?  The primary buffer
1095 	 * 	 is allocated by the driver or via DMA map setup, and tmpbuf
1096 	 * 	 seems to only come into existence in sndbuf_resize().
1097 	 */
1098 	if (c->direction == PCMDIR_PLAY) {
1099 		bs->sl = sndbuf_getmaxsize(bs);
1100 		bs->shadbuf = malloc(bs->sl, M_DEVBUF, M_NOWAIT);
1101 		if (bs->shadbuf == NULL) {
1102 			ret = ENOMEM;
1103 			goto out;
1104 		}
1105 	}
1106 
1107 out:
1108 	CHN_UNLOCK(c);
1109 	if (ret) {
1110 		if (c->devinfo) {
1111 			if (CHANNEL_FREE(c->methods, c->devinfo))
1112 				sndbuf_free(b);
1113 		}
1114 		if (bs)
1115 			sndbuf_destroy(bs);
1116 		if (b)
1117 			sndbuf_destroy(b);
1118 		c->flags |= CHN_F_DEAD;
1119 		chn_lockdestroy(c);
1120 
1121 		return ret;
1122 	}
1123 
1124 	return 0;
1125 }
1126 
1127 int
1128 chn_kill(struct pcm_channel *c)
1129 {
1130     	struct snd_dbuf *b = c->bufhard;
1131     	struct snd_dbuf *bs = c->bufsoft;
1132 
1133 	if (c->flags & CHN_F_TRIGGERED)
1134 		chn_trigger(c, PCMTRIG_ABORT);
1135 	while (chn_removefeeder(c) == 0);
1136 	if (CHANNEL_FREE(c->methods, c->devinfo))
1137 		sndbuf_free(b);
1138 	c->flags |= CHN_F_DEAD;
1139 	sndbuf_destroy(bs);
1140 	sndbuf_destroy(b);
1141 	chn_lockdestroy(c);
1142 	return 0;
1143 }
1144 
1145 int
1146 chn_setdir(struct pcm_channel *c, int dir)
1147 {
1148 #ifdef DEV_ISA
1149     	struct snd_dbuf *b = c->bufhard;
1150 #endif
1151 	int r;
1152 
1153 	CHN_LOCKASSERT(c);
1154 	c->direction = dir;
1155 	r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
1156 #ifdef DEV_ISA
1157 	if (!r && SND_DMA(b))
1158 		sndbuf_dmasetdir(b, c->direction);
1159 #endif
1160 	return r;
1161 }
1162 
1163 int
1164 chn_setvolume(struct pcm_channel *c, int left, int right)
1165 {
1166 	CHN_LOCKASSERT(c);
1167 	/* should add a feeder for volume changing if channel returns -1 */
1168 	if (left > 100)
1169 		left = 100;
1170 	if (left < 0)
1171 		left = 0;
1172 	if (right > 100)
1173 		right = 100;
1174 	if (right < 0)
1175 		right = 0;
1176 	c->volume = left | (right << 8);
1177 	return 0;
1178 }
1179 
1180 static u_int32_t
1181 round_pow2(u_int32_t v)
1182 {
1183 	u_int32_t ret;
1184 
1185 	if (v < 2)
1186 		v = 2;
1187 	ret = 0;
1188 	while (v >> ret)
1189 		ret++;
1190 	ret = 1 << (ret - 1);
1191 	while (ret < v)
1192 		ret <<= 1;
1193 	return ret;
1194 }
1195 
1196 /*
1197  * 4Front call it DSP Policy, while we call it "Latency Profile". The idea
1198  * is to keep 2nd buffer short so that it doesn't cause long queue during
1199  * buffer transfer.
1200  *
1201  *    Latency reference table for 48khz stereo 16bit: (PLAY)
1202  *
1203  *      +---------+------------+-----------+------------+
1204  *      | Latency | Blockcount | Blocksize | Buffersize |
1205  *      +---------+------------+-----------+------------+
1206  *      |     0   |       2    |   64      |    128     |
1207  *      +---------+------------+-----------+------------+
1208  *      |     1   |       4    |   128     |    512     |
1209  *      +---------+------------+-----------+------------+
1210  *      |     2   |       8    |   512     |    4096    |
1211  *      +---------+------------+-----------+------------+
1212  *      |     3   |      16    |   512     |    8192    |
1213  *      +---------+------------+-----------+------------+
1214  *      |     4   |      32    |   512     |    16384   |
1215  *      +---------+------------+-----------+------------+
1216  *      |     5   |      32    |   1024    |    32768   |
1217  *      +---------+------------+-----------+------------+
1218  *      |     6   |      16    |   2048    |    32768   |
1219  *      +---------+------------+-----------+------------+
1220  *      |     7   |       8    |   4096    |    32768   |
1221  *      +---------+------------+-----------+------------+
1222  *      |     8   |       4    |   8192    |    32768   |
1223  *      +---------+------------+-----------+------------+
1224  *      |     9   |       2    |   16384   |    32768   |
1225  *      +---------+------------+-----------+------------+
1226  *      |    10   |       2    |   32768   |    65536   |
1227  *      +---------+------------+-----------+------------+
1228  *
1229  * Recording need a different reference table. All we care is
1230  * gobbling up everything within reasonable buffering threshold.
1231  *
1232  *    Latency reference table for 48khz stereo 16bit: (REC)
1233  *
1234  *      +---------+------------+-----------+------------+
1235  *      | Latency | Blockcount | Blocksize | Buffersize |
1236  *      +---------+------------+-----------+------------+
1237  *      |     0   |     512    |   32      |    16384   |
1238  *      +---------+------------+-----------+------------+
1239  *      |     1   |     256    |   64      |    16384   |
1240  *      +---------+------------+-----------+------------+
1241  *      |     2   |     128    |   128     |    16384   |
1242  *      +---------+------------+-----------+------------+
1243  *      |     3   |      64    |   256     |    16384   |
1244  *      +---------+------------+-----------+------------+
1245  *      |     4   |      32    |   512     |    16384   |
1246  *      +---------+------------+-----------+------------+
1247  *      |     5   |      32    |   1024    |    32768   |
1248  *      +---------+------------+-----------+------------+
1249  *      |     6   |      16    |   2048    |    32768   |
1250  *      +---------+------------+-----------+------------+
1251  *      |     7   |       8    |   4096    |    32768   |
1252  *      +---------+------------+-----------+------------+
1253  *      |     8   |       4    |   8192    |    32768   |
1254  *      +---------+------------+-----------+------------+
1255  *      |     9   |       2    |   16384   |    32768   |
1256  *      +---------+------------+-----------+------------+
1257  *      |    10   |       2    |   32768   |    65536   |
1258  *      +---------+------------+-----------+------------+
1259  *
1260  * Calculations for other data rate are entirely based on these reference
1261  * tables. For normal operation, Latency 5 seems give the best, well
1262  * balanced performance for typical workload. Anything below 5 will
1263  * eat up CPU to keep up with increasing context switches because of
1264  * shorter buffer space and usually require the application to handle it
1265  * aggresively through possibly real time programming technique.
1266  *
1267  */
1268 #define CHN_LATENCY_PBLKCNT_REF				\
1269 	{{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1},		\
1270 	{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}}
1271 #define CHN_LATENCY_PBUFSZ_REF				\
1272 	{{7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16},	\
1273 	{11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17}}
1274 
1275 #define CHN_LATENCY_RBLKCNT_REF				\
1276 	{{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1},		\
1277 	{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}}
1278 #define CHN_LATENCY_RBUFSZ_REF				\
1279 	{{14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16},	\
1280 	{15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17}}
1281 
1282 #define CHN_LATENCY_DATA_REF	192000 /* 48khz stereo 16bit ~ 48000 x 2 x 2 */
1283 
1284 static int
1285 chn_calclatency(int dir, int latency, int bps, u_int32_t datarate,
1286 				u_int32_t max, int *rblksz, int *rblkcnt)
1287 {
1288 	u_int32_t bufsz;
1289 	int blksz, blkcnt;
1290 	static int pblkcnts[CHN_LATENCY_PROFILE_MAX+1][CHN_LATENCY_MAX+1] =
1291 	    CHN_LATENCY_PBLKCNT_REF;
1292 	static int  pbufszs[CHN_LATENCY_PROFILE_MAX+1][CHN_LATENCY_MAX+1] =
1293 	    CHN_LATENCY_PBUFSZ_REF;
1294 	static int rblkcnts[CHN_LATENCY_PROFILE_MAX+1][CHN_LATENCY_MAX+1] =
1295 	    CHN_LATENCY_RBLKCNT_REF;
1296 	static int  rbufszs[CHN_LATENCY_PROFILE_MAX+1][CHN_LATENCY_MAX+1] =
1297 	    CHN_LATENCY_RBUFSZ_REF;
1298 
1299 	if (CHN_LATENCY_MIN != 0 || CHN_LATENCY_MAX != 10 ||
1300 	    latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX ||
1301 	    bps < 1 || datarate < 1 ||
1302 	    !(dir == PCMDIR_PLAY || dir == PCMDIR_REC)) {
1303 		if (rblksz != NULL)
1304 			*rblksz = CHN_2NDBUFMAXSIZE >> 1;
1305 		if (rblkcnt != NULL)
1306 			*rblkcnt = 2;
1307 		printf("%s: FAILED dir=%d latency=%d bps=%d "
1308 		    "datarate=%u max=%u\n",
1309 		    __func__, dir, latency, bps, datarate, max);
1310 		return CHN_2NDBUFMAXSIZE;
1311 	}
1312 
1313 	if (dir == PCMDIR_PLAY) {
1314 		blkcnt = pblkcnts[chn_latency_profile][latency];
1315 		bufsz = pbufszs[chn_latency_profile][latency];
1316 	} else {
1317 		blkcnt = rblkcnts[chn_latency_profile][latency];
1318 		bufsz = rbufszs[chn_latency_profile][latency];
1319 	}
1320 	bufsz = snd_xbytes(1 << bufsz, CHN_LATENCY_DATA_REF, datarate);
1321 	if (bufsz > max)
1322 		bufsz = max;
1323 	if (bufsz < 32)
1324 		bufsz = 32;
1325 	blksz = bufsz >> blkcnt;
1326 	blksz -= blksz % bps;
1327 	while (blksz < 16 || blksz < bps)
1328 		blksz += bps;
1329 	while ((blksz << blkcnt) > bufsz && blkcnt > 1)
1330 		blkcnt--;
1331 	if (rblksz != NULL)
1332 		*rblksz = blksz;
1333 	if (rblkcnt != NULL)
1334 		*rblkcnt = 1 << blkcnt;
1335 
1336 	return blksz << blkcnt;
1337 }
1338 
1339 /*
1340  * Note that there is no strict requirement to align blksz to the
1341  * nearest ^2, except for hardware CHANNEL_SETBLOCKSIZE. If the application
1342  * trying to act smarter and requesting for specific blksz/blkcnt, so be it.
1343  */
1344 static int
1345 chn_resizebuf(struct pcm_channel *c, int latency,
1346 					int blkcnt, int blksz)
1347 {
1348 	struct snd_dbuf *b, *bs, *pb;
1349 	int sblksz, sblkcnt, hblksz, limit = 1;
1350 	int ret;
1351 
1352 	CHN_LOCKASSERT(c);
1353 
1354 	if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED) ||
1355 	    !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC))
1356 		return EINVAL;
1357 
1358 	if (latency == -1) {
1359 		c->latency = -1;
1360 		latency = chn_latency;
1361 	} else if (latency == -2) {
1362 		latency = c->latency;
1363 		if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX)
1364 			latency = chn_latency;
1365 	} else if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX)
1366 		return EINVAL;
1367 	else {
1368 		c->latency = latency;
1369 		limit = 0;
1370 	}
1371 
1372 	bs = c->bufsoft;
1373 	b = c->bufhard;
1374 
1375 	if (!(blksz == 0 || blkcnt == -1) &&
1376 	    (blksz < 16 || blksz < sndbuf_getbps(bs) || blkcnt < 2 ||
1377 	    (blksz * blkcnt) > CHN_2NDBUFMAXSIZE))
1378 		return EINVAL;
1379 
1380 	chn_calclatency(c->direction, latency, sndbuf_getbps(bs),
1381 	    sndbuf_getbps(bs) * sndbuf_getspd(bs), CHN_2NDBUFMAXSIZE,
1382 	    &sblksz, &sblkcnt);
1383 
1384 	if (blksz == 0 || blkcnt == -1) {
1385 		if (blkcnt == -1)
1386 			c->flags &= ~CHN_F_HAS_SIZE;
1387 		if (c->flags & CHN_F_HAS_SIZE) {
1388 			blksz = sndbuf_getblksz(bs);
1389 			blkcnt = sndbuf_getblkcnt(bs);
1390 		}
1391 	} else
1392 		c->flags |= CHN_F_HAS_SIZE;
1393 
1394 	if (c->flags & CHN_F_HAS_SIZE) {
1395 		/*
1396 		 * The application has requested their own blksz/blkcnt.
1397 		 * Just obey with it, and let them toast alone. We can
1398 		 * clamp it to the nearest latency profile, but that would
1399 		 * defeat the purpose of having custom control. The least
1400 		 * we can do is round it to the nearest ^2 and align it.
1401 		 */
1402 		sblksz = round_pow2(blksz);
1403 		sblksz -= sblksz % sndbuf_getbps(bs);
1404 		sblkcnt = blkcnt;
1405 		while (sblksz < 16 || sblksz < sndbuf_getbps(bs))
1406 			sblksz += sndbuf_getbps(bs);
1407 		if (snd_verbose > 3 && !(blksz == 0 || blkcnt == -1))
1408 			printf("%s: requested blksz=%d blkcnt=%d -> %d/%d\n",
1409 			    __func__, blksz, blkcnt, sblksz, sblkcnt);
1410 		limit = 0;
1411 	}
1412 
1413 	if (c->parentchannel != NULL) {
1414 		pb = BUF_PARENT(c, NULL);
1415 		CHN_UNLOCK(c);
1416 		chn_notify(c->parentchannel, CHN_N_BLOCKSIZE);
1417 		CHN_LOCK(c);
1418 		limit = (limit != 0 && pb != NULL) ?
1419 		    sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0;
1420 		c->timeout = c->parentchannel->timeout;
1421 	} else {
1422 		if (c->flags & CHN_F_HAS_SIZE) {
1423 			hblksz = sndbuf_xbytes(sblksz, bs, b);
1424 			if (snd_verbose > 3)
1425 				printf("%s: sblksz=%d -> hblksz=%d\n",
1426 				    __func__, sblksz, hblksz);
1427 		} else
1428 			chn_calclatency(c->direction, latency,
1429 			    sndbuf_getbps(b),
1430 			    sndbuf_getbps(b) * sndbuf_getspd(b),
1431 			    CHN_2NDBUFMAXSIZE, &hblksz, NULL);
1432 
1433 		hblksz = round_pow2(hblksz);
1434 		if ((hblksz << 1) > sndbuf_getmaxsize(b))
1435 			hblksz = sndbuf_getmaxsize(b) >> 1;
1436 		hblksz -= hblksz % sndbuf_getbps(b);
1437 		while (hblksz < 16 || hblksz < sndbuf_getbps(b))
1438 			hblksz += sndbuf_getbps(b);
1439 
1440 #if 0
1441 		hblksz = sndbuf_getmaxsize(b) >> 1;
1442 #endif
1443 		CHN_UNLOCK(c);
1444 		sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods,
1445 		    c->devinfo, hblksz));
1446 		CHN_LOCK(c);
1447 
1448 		if (!SLIST_EMPTY(&c->children)) {
1449 			/*
1450 			 * Virtual channels underneath. Set the biggest
1451 			 * possible value for their mixing space.
1452 			 */
1453 			sblksz = CHN_2NDBUFMAXSIZE >> 1;
1454 			sblksz -= sblksz % sndbuf_getbps(bs);
1455 			sblkcnt = 2;
1456 			limit = 0;
1457 		} else if (limit != 0)
1458 			limit = sndbuf_xbytes(sndbuf_getsize(b), b, bs);
1459 
1460 		/*
1461 		 * Interrupt timeout
1462 		 */
1463 		c->timeout = ((u_int64_t)hz * sndbuf_getblksz(b)) /
1464 		    ((u_int64_t)sndbuf_getspd(b) * sndbuf_getbps(b));
1465 		if (c->timeout < 1)
1466 			c->timeout = 1;
1467 		c->timeout <<= 1;
1468 	}
1469 
1470 	if (limit > CHN_2NDBUFMAXSIZE)
1471 		limit = CHN_2NDBUFMAXSIZE;
1472 
1473 	hblksz = sblksz;
1474 	while ((sblksz * sblkcnt) < limit) {
1475 		sblksz += hblksz;
1476 		if ((sblksz * sblkcnt) > CHN_2NDBUFMAXSIZE) {
1477 			sblksz -= hblksz;
1478 			break;
1479 		}
1480 	}
1481 
1482 	if (sndbuf_getblkcnt(bs) != sblkcnt || sndbuf_getblksz(bs) != sblksz ||
1483 	    sndbuf_getsize(bs) != (sblkcnt * sblksz)) {
1484 		ret = sndbuf_remalloc(bs, sblkcnt, sblksz);
1485 		if (ret != 0) {
1486 			printf("%s: Failed: %d %d\n", __func__,
1487 			    sblkcnt, sblksz);
1488 			return ret;
1489 		}
1490 	}
1491 
1492 	/*
1493 	 * OSSv4 docs: "By default OSS will set the low water level equal
1494 	 * to the fragment size which is optimal in most cases."
1495 	 */
1496 	c->lw = sndbuf_getblksz(bs);
1497 	chn_resetbuf(c);
1498 
1499 	if (snd_verbose > 3)
1500 		printf("%s: PCMDIR_%s (%s) timeout=%u "
1501 		    "b[%d/%d/%d] bs[%d/%d/%d] limit=%d\n",
1502 		    __func__, (c->direction == PCMDIR_REC) ? "REC" : "PLAY",
1503 		    (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
1504 		    c->timeout,
1505 		    sndbuf_getsize(b), sndbuf_getblksz(b),
1506 		    sndbuf_getblkcnt(b),
1507 		    sndbuf_getsize(bs), sndbuf_getblksz(bs),
1508 		    sndbuf_getblkcnt(bs), limit);
1509 
1510 	return 0;
1511 }
1512 
1513 int
1514 chn_setlatency(struct pcm_channel *c, int latency)
1515 {
1516 	CHN_LOCKASSERT(c);
1517 	/* Destroy blksz/blkcnt, enforce latency profile. */
1518 	return chn_resizebuf(c, latency, -1, 0);
1519 }
1520 
1521 int
1522 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
1523 {
1524 	CHN_LOCKASSERT(c);
1525 	/* Destroy latency profile, enforce blksz/blkcnt */
1526 	return chn_resizebuf(c, -1, blkcnt, blksz);
1527 }
1528 
1529 static int
1530 chn_tryspeed(struct pcm_channel *c, int speed)
1531 {
1532 	struct pcm_feeder *f;
1533     	struct snd_dbuf *b = c->bufhard;
1534     	struct snd_dbuf *bs = c->bufsoft;
1535     	struct snd_dbuf *x;
1536 	int r, delta;
1537 
1538 	CHN_LOCKASSERT(c);
1539 	DEB(printf("setspeed, channel %s\n", c->name));
1540 	DEB(printf("want speed %d, ", speed));
1541 	if (speed <= 0)
1542 		return EINVAL;
1543 	if (CANCHANGE(c)) {
1544 		r = 0;
1545 		c->speed = speed;
1546 		sndbuf_setspd(bs, speed);
1547 		RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
1548 		DEB(printf("try speed %d, ", speed));
1549 		sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
1550 		DEB(printf("got speed %d\n", sndbuf_getspd(b)));
1551 
1552 		delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
1553 		if (delta < 0)
1554 			delta = -delta;
1555 
1556 		c->feederflags &= ~(1 << FEEDER_RATE);
1557 		/*
1558 		 * Used to be 500. It was too big!
1559 		 */
1560 		if (delta > feeder_rate_round)
1561 			c->feederflags |= 1 << FEEDER_RATE;
1562 		else
1563 			sndbuf_setspd(bs, sndbuf_getspd(b));
1564 
1565 		r = chn_buildfeeder(c);
1566 		DEB(printf("r = %d\n", r));
1567 		if (r)
1568 			goto out;
1569 
1570 		if (!(c->feederflags & (1 << FEEDER_RATE)))
1571 			goto out;
1572 
1573 		r = EINVAL;
1574 		f = chn_findfeeder(c, FEEDER_RATE);
1575 		DEB(printf("feedrate = %p\n", f));
1576 		if (f == NULL)
1577 			goto out;
1578 
1579 		x = (c->direction == PCMDIR_REC)? b : bs;
1580 		r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
1581 		DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r));
1582 		if (r)
1583 			goto out;
1584 
1585 		x = (c->direction == PCMDIR_REC)? bs : b;
1586 		r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
1587 		DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r));
1588 out:
1589 		if (!r)
1590 			r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
1591 							sndbuf_getfmt(b));
1592 		if (!r)
1593 			sndbuf_setfmt(bs, c->format);
1594 		if (!r)
1595 			r = chn_resizebuf(c, -2, 0, 0);
1596 		DEB(printf("setspeed done, r = %d\n", r));
1597 		return r;
1598 	} else
1599 		return EINVAL;
1600 }
1601 
1602 int
1603 chn_setspeed(struct pcm_channel *c, int speed)
1604 {
1605 	int r, oldspeed = c->speed;
1606 
1607 	r = chn_tryspeed(c, speed);
1608 	if (r) {
1609 		if (snd_verbose > 3)
1610 			printf("Failed to set speed %d falling back to %d\n",
1611 			    speed, oldspeed);
1612 		r = chn_tryspeed(c, oldspeed);
1613 	}
1614 	return r;
1615 }
1616 
1617 static int
1618 chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
1619 {
1620 	struct snd_dbuf *b = c->bufhard;
1621 	struct snd_dbuf *bs = c->bufsoft;
1622 	int r;
1623 
1624 	CHN_LOCKASSERT(c);
1625 	if (CANCHANGE(c)) {
1626 		DEB(printf("want format %d\n", fmt));
1627 		c->format = fmt;
1628 		r = chn_buildfeeder(c);
1629 		if (r == 0) {
1630 			sndbuf_setfmt(bs, c->format);
1631 			chn_resetbuf(c);
1632 			r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
1633 			if (r == 0)
1634 				r = chn_tryspeed(c, c->speed);
1635 		}
1636 		return r;
1637 	} else
1638 		return EINVAL;
1639 }
1640 
1641 int
1642 chn_setformat(struct pcm_channel *c, u_int32_t fmt)
1643 {
1644 	u_int32_t oldfmt = c->format;
1645 	int r;
1646 
1647 	r = chn_tryformat(c, fmt);
1648 	if (r) {
1649 		if (snd_verbose > 3)
1650 			printf("Format change 0x%08x failed, reverting to 0x%08x\n",
1651 			    fmt, oldfmt);
1652 		chn_tryformat(c, oldfmt);
1653 	}
1654 	return r;
1655 }
1656 
1657 int
1658 chn_trigger(struct pcm_channel *c, int go)
1659 {
1660 #ifdef DEV_ISA
1661     	struct snd_dbuf *b = c->bufhard;
1662 #endif
1663 	int ret;
1664 
1665 	CHN_LOCKASSERT(c);
1666 #ifdef DEV_ISA
1667 	if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
1668 		sndbuf_dmabounce(b);
1669 #endif
1670 	ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
1671 
1672 	return ret;
1673 }
1674 
1675 /**
1676  * @brief Queries sound driver for sample-aligned hardware buffer pointer index
1677  *
1678  * This function obtains the hardware pointer location, then aligns it to
1679  * the current bytes-per-sample value before returning.  (E.g., a channel
1680  * running in 16 bit stereo mode would require 4 bytes per sample, so a
1681  * hwptr value ranging from 32-35 would be returned as 32.)
1682  *
1683  * @param c	PCM channel context
1684  * @returns 	sample-aligned hardware buffer pointer index
1685  */
1686 int
1687 chn_getptr(struct pcm_channel *c)
1688 {
1689 #if 0
1690 	int hwptr;
1691 	int a = (1 << c->align) - 1;
1692 
1693 	CHN_LOCKASSERT(c);
1694 	hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1695 	/* don't allow unaligned values in the hwa ptr */
1696 #if 1
1697 	hwptr &= ~a ; /* Apply channel align mask */
1698 #endif
1699 	hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
1700 	return hwptr;
1701 #endif
1702 	int hwptr;
1703 
1704 	CHN_LOCKASSERT(c);
1705 	hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1706 	return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
1707 }
1708 
1709 struct pcmchan_caps *
1710 chn_getcaps(struct pcm_channel *c)
1711 {
1712 	CHN_LOCKASSERT(c);
1713 	return CHANNEL_GETCAPS(c->methods, c->devinfo);
1714 }
1715 
1716 u_int32_t
1717 chn_getformats(struct pcm_channel *c)
1718 {
1719 	u_int32_t *fmtlist, fmts;
1720 	int i;
1721 
1722 	fmtlist = chn_getcaps(c)->fmtlist;
1723 	fmts = 0;
1724 	for (i = 0; fmtlist[i]; i++)
1725 		fmts |= fmtlist[i];
1726 
1727 	/* report software-supported formats */
1728 	if (report_soft_formats)
1729 		fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
1730 		    AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
1731 		    AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
1732 		    AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
1733 
1734 	return fmts;
1735 }
1736 
1737 static int
1738 chn_buildfeeder(struct pcm_channel *c)
1739 {
1740 	struct feeder_class *fc;
1741 	struct pcm_feederdesc desc;
1742 	u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
1743 	int err;
1744 	char fmtstr[AFMTSTR_MAXSZ];
1745 
1746 	CHN_LOCKASSERT(c);
1747 	while (chn_removefeeder(c) == 0);
1748 	KASSERT((c->feeder == NULL), ("feeder chain not empty"));
1749 
1750 	c->align = sndbuf_getalign(c->bufsoft);
1751 
1752 	if (SLIST_EMPTY(&c->children)) {
1753 		fc = feeder_getclass(NULL);
1754 		KASSERT(fc != NULL, ("can't find root feeder"));
1755 
1756 		err = chn_addfeeder(c, fc, NULL);
1757 		if (err) {
1758 			DEB(printf("can't add root feeder, err %d\n", err));
1759 
1760 			return err;
1761 		}
1762 		c->feeder->desc->out = c->format;
1763 	} else {
1764 		if (c->flags & CHN_F_HAS_VCHAN) {
1765 			desc.type = FEEDER_MIXER;
1766 			desc.in = c->format;
1767 		} else {
1768 			DEB(printf("can't decide which feeder type to use!\n"));
1769 			return EOPNOTSUPP;
1770 		}
1771 		desc.out = c->format;
1772 		desc.flags = 0;
1773 		fc = feeder_getclass(&desc);
1774 		if (fc == NULL) {
1775 			DEB(printf("can't find vchan feeder\n"));
1776 
1777 			return EOPNOTSUPP;
1778 		}
1779 
1780 		err = chn_addfeeder(c, fc, &desc);
1781 		if (err) {
1782 			DEB(printf("can't add vchan feeder, err %d\n", err));
1783 
1784 			return err;
1785 		}
1786 	}
1787 	c->feederflags &= ~(1 << FEEDER_VOLUME);
1788 	if (c->direction == PCMDIR_PLAY &&
1789 			!(c->flags & CHN_F_VIRTUAL) &&
1790 			c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTPCMVOL) &&
1791 			c->parentsnddev->mixer_dev)
1792 		c->feederflags |= 1 << FEEDER_VOLUME;
1793 	flags = c->feederflags;
1794 	fmtlist = chn_getcaps(c)->fmtlist;
1795 
1796 	DEB(printf("feederflags %x\n", flags));
1797 
1798 	for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
1799 		if (flags & (1 << type)) {
1800 			desc.type = type;
1801 			desc.in = 0;
1802 			desc.out = 0;
1803 			desc.flags = 0;
1804 			DEB(printf("find feeder type %d, ", type));
1805 			if (type == FEEDER_VOLUME || type == FEEDER_RATE) {
1806 				if (c->feeder->desc->out & AFMT_32BIT)
1807 					strlcpy(fmtstr,"s32le", sizeof(fmtstr));
1808 				else if (c->feeder->desc->out & AFMT_24BIT)
1809 					strlcpy(fmtstr, "s24le", sizeof(fmtstr));
1810 				else {
1811 					/*
1812 					 * 8bit doesn't provide enough headroom
1813 					 * for proper processing without
1814 					 * creating too much noises. Force to
1815 					 * 16bit instead.
1816 					 */
1817 					strlcpy(fmtstr, "s16le", sizeof(fmtstr));
1818 				}
1819 				if (!(c->feeder->desc->out & AFMT_8BIT) &&
1820 					    c->feeder->desc->out & AFMT_BIGENDIAN)
1821 					afmtstr_swap_endian(fmtstr);
1822 				if (!(c->feeder->desc->out & (AFMT_A_LAW | AFMT_MU_LAW)) &&
1823 					    !(c->feeder->desc->out & AFMT_SIGNED))
1824 					afmtstr_swap_sign(fmtstr);
1825 				desc.in = afmtstr2afmt(NULL, fmtstr, AFMTSTR_MONO_RETURN);
1826 				if (desc.in == 0)
1827 					desc.in = AFMT_S16_LE;
1828 				/* feeder_volume need stereo processing */
1829 				if (type == FEEDER_VOLUME ||
1830 					    c->feeder->desc->out & AFMT_STEREO)
1831 					desc.in |= AFMT_STEREO;
1832 				desc.out = desc.in;
1833 				fc = feeder_getclass(&desc);
1834 				if (fc != NULL && fc->desc != NULL)
1835 					desc.flags = fc->desc->flags;
1836 			} else {
1837 				fc = feeder_getclass(&desc);
1838 				if (fc != NULL && fc->desc != NULL)
1839 					desc = *fc->desc;
1840 			}
1841 			DEB(printf("got %p\n", fc));
1842 			if (fc == NULL) {
1843 				DEB(printf("can't find required feeder type %d\n", type));
1844 
1845 				return EOPNOTSUPP;
1846 			}
1847 
1848  			DEB(printf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
1849 			tmp[0] = desc.in;
1850 			tmp[1] = 0;
1851 			if (chn_fmtchain(c, tmp) == 0) {
1852 				DEB(printf("failed\n"));
1853 
1854 				return ENODEV;
1855 			}
1856  			DEB(printf("ok\n"));
1857 
1858 			err = chn_addfeeder(c, fc, &desc);
1859 			if (err) {
1860 				DEB(printf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err));
1861 
1862 				return err;
1863 			}
1864 			DEB(printf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out));
1865 		}
1866 	}
1867 
1868  	if (c->direction == PCMDIR_REC) {
1869 	 	tmp[0] = c->format;
1870  		tmp[1] = 0;
1871  		hwfmt = chn_fmtchain(c, tmp);
1872  	} else
1873  		hwfmt = chn_fmtchain(c, fmtlist);
1874 
1875 	if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
1876 		DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt));
1877 		return ENODEV;
1878 	}
1879 
1880 	sndbuf_setfmt(c->bufhard, hwfmt);
1881 
1882 	if ((flags & (1 << FEEDER_VOLUME))) {
1883 		u_int32_t parent = SOUND_MIXER_NONE;
1884 		int vol, left, right;
1885 
1886 		vol = 100 | (100 << 8);
1887 
1888 		CHN_UNLOCK(c);
1889 		/*
1890 		 * XXX This is ugly! The way mixer subs being so secretive
1891 		 * about its own internals force us to use this silly
1892 		 * monkey trick.
1893 		 */
1894 		if (mixer_ioctl(c->parentsnddev->mixer_dev,
1895 				MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&vol, -1, NULL) != 0)
1896 			device_printf(c->dev, "Soft PCM Volume: Failed to read default value\n");
1897 		left = vol & 0x7f;
1898 		right = (vol >> 8) & 0x7f;
1899 		if (c->parentsnddev != NULL &&
1900 		    c->parentsnddev->mixer_dev != NULL &&
1901 		    c->parentsnddev->mixer_dev->si_drv1 != NULL)
1902 			parent = mix_getparent(
1903 			    c->parentsnddev->mixer_dev->si_drv1,
1904 			    SOUND_MIXER_PCM);
1905 		if (parent != SOUND_MIXER_NONE) {
1906 			vol = 100 | (100 << 8);
1907 			if (mixer_ioctl(c->parentsnddev->mixer_dev,
1908 					MIXER_READ(parent),
1909 					(caddr_t)&vol, -1, NULL) != 0)
1910 				device_printf(c->dev, "Soft Volume: Failed to read parent default value\n");
1911 			left = (left * (vol & 0x7f)) / 100;
1912 			right = (right * ((vol >> 8) & 0x7f)) / 100;
1913 		}
1914 		CHN_LOCK(c);
1915 		chn_setvolume(c, left, right);
1916 	}
1917 
1918 	return 0;
1919 }
1920 
1921 int
1922 chn_notify(struct pcm_channel *c, u_int32_t flags)
1923 {
1924 	struct pcmchan_children *pce;
1925 	struct pcm_channel *child;
1926 	int run;
1927 
1928 	CHN_LOCK(c);
1929 
1930 	if (SLIST_EMPTY(&c->children)) {
1931 		CHN_UNLOCK(c);
1932 		return ENODEV;
1933 	}
1934 
1935 	run = (c->flags & CHN_F_TRIGGERED)? 1 : 0;
1936 	/*
1937 	 * if the hwchan is running, we can't change its rate, format or
1938 	 * blocksize
1939 	 */
1940 	if (run)
1941 		flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
1942 
1943 	if (flags & CHN_N_RATE) {
1944 		/*
1945 		 * we could do something here, like scan children and decide on
1946 		 * the most appropriate rate to mix at, but we don't for now
1947 		 */
1948 	}
1949 	if (flags & CHN_N_FORMAT) {
1950 		/*
1951 		 * we could do something here, like scan children and decide on
1952 		 * the most appropriate mixer feeder to use, but we don't for now
1953 		 */
1954 	}
1955 	if (flags & CHN_N_VOLUME) {
1956 		/*
1957 		 * we could do something here but we don't for now
1958 		 */
1959 	}
1960 	if (flags & CHN_N_BLOCKSIZE) {
1961 		/*
1962 		 * Set to default latency profile
1963 		 */
1964 		chn_setlatency(c, chn_latency);
1965 	}
1966 	if (flags & CHN_N_TRIGGER) {
1967 		int nrun;
1968 		/*
1969 		 * scan the children, and figure out if any are running
1970 		 * if so, we need to be running, otherwise we need to be stopped
1971 		 * if we aren't in our target sstate, move to it
1972 		 */
1973 		nrun = 0;
1974 		SLIST_FOREACH(pce, &c->children, link) {
1975 			child = pce->channel;
1976 			CHN_LOCK(child);
1977 			if (child->flags & CHN_F_TRIGGERED)
1978 				nrun = 1;
1979 			CHN_UNLOCK(child);
1980 		}
1981 		if (nrun && !run)
1982 			chn_start(c, 1);
1983 		if (!nrun && run)
1984 			chn_abort(c);
1985 	}
1986 	CHN_UNLOCK(c);
1987 	return 0;
1988 }
1989 
1990 /**
1991  * @brief Fetch array of supported discrete sample rates
1992  *
1993  * Wrapper for CHANNEL_GETRATES.  Please see channel_if.m:getrates() for
1994  * detailed information.
1995  *
1996  * @note If the operation isn't supported, this function will just return 0
1997  *       (no rates in the array), and *rates will be set to NULL.  Callers
1998  *       should examine rates @b only if this function returns non-zero.
1999  *
2000  * @param c	pcm channel to examine
2001  * @param rates	pointer to array of integers; rate table will be recorded here
2002  *
2003  * @return number of rates in the array pointed to be @c rates
2004  */
2005 int
2006 chn_getrates(struct pcm_channel *c, int **rates)
2007 {
2008 	KASSERT(rates != NULL, ("rates is null"));
2009 	CHN_LOCKASSERT(c);
2010 	return CHANNEL_GETRATES(c->methods, c->devinfo, rates);
2011 }
2012 
2013 /**
2014  * @brief Remove channel from a sync group, if there is one.
2015  *
2016  * This function is initially intended for the following conditions:
2017  *   - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl)
2018  *   - Closing a device.  (A channel can't be destroyed if it's still in use.)
2019  *
2020  * @note Before calling this function, the syncgroup list mutex must be
2021  * held.  (Consider pcm_channel::sm protected by the SG list mutex
2022  * whether @c c is locked or not.)
2023  *
2024  * @param c	channel device to be started or closed
2025  * @returns	If this channel was the only member of a group, the group ID
2026  * 		is returned to the caller so that the caller can release it
2027  * 		via free_unr() after giving up the syncgroup lock.  Else it
2028  * 		returns 0.
2029  */
2030 int
2031 chn_syncdestroy(struct pcm_channel *c)
2032 {
2033 	struct pcmchan_syncmember *sm;
2034 	struct pcmchan_syncgroup *sg;
2035 	int sg_id;
2036 
2037 	sg_id = 0;
2038 
2039 	PCM_SG_LOCKASSERT(MA_OWNED);
2040 
2041 	if (c->sm != NULL) {
2042 		sm = c->sm;
2043 		sg = sm->parent;
2044 		c->sm = NULL;
2045 
2046 		KASSERT(sg != NULL, ("syncmember has null parent"));
2047 
2048 		SLIST_REMOVE(&sg->members, sm, pcmchan_syncmember, link);
2049 		free(sm, M_DEVBUF);
2050 
2051 		if (SLIST_EMPTY(&sg->members)) {
2052 			SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
2053 			sg_id = sg->id;
2054 			free(sg, M_DEVBUF);
2055 		}
2056 	}
2057 
2058 	return sg_id;
2059 }
2060 
2061 void
2062 chn_lock(struct pcm_channel *c)
2063 {
2064 	CHN_LOCK(c);
2065 }
2066 
2067 void
2068 chn_unlock(struct pcm_channel *c)
2069 {
2070 	CHN_UNLOCK(c);
2071 }
2072 
2073 #ifdef OSSV4_EXPERIMENT
2074 int
2075 chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak)
2076 {
2077 	CHN_LOCKASSERT(c);
2078 	return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak);
2079 }
2080 #endif
2081