1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2007-2009 Ariff Abdullah <ariff@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31#ifndef _SND_SNDSTAT_H_
32#define _SND_SNDSTAT_H_
33
34#define SNDSTAT_PREPARE_PCM_ARGS					\
35	struct sbuf *s, device_t dev, int verbose
36
37#define SNDSTAT_PREPARE_PCM_BEGIN()	do {				\
38	struct snddev_info *d;						\
39	struct pcm_channel *c;						\
40	struct pcm_feeder *f;						\
41									\
42	d = device_get_softc(dev);					\
43	PCM_BUSYASSERT(d);						\
44									\
45	if (CHN_EMPTY(d, channels.pcm)) {				\
46		sbuf_printf(s, " (mixer only)");			\
47		return (0);						\
48	}								\
49									\
50	if (verbose < 1) {						\
51		sbuf_printf(s, " (%s%s%s",				\
52		    d->playcount ? "play" : "",				\
53		    (d->playcount && d->reccount) ? "/" : "",		\
54		    d->reccount ? "rec" : "");				\
55	} else {							\
56		sbuf_printf(s, " (%dp:%dv/%dr:%dv",			\
57		    d->playcount, d->pvchancount,			\
58		    d->reccount, d->rvchancount);			\
59	}								\
60	sbuf_printf(s, "%s)%s",						\
61	    ((d->playcount != 0 && d->reccount != 0) &&			\
62	    (d->flags & SD_F_SIMPLEX)) ? " simplex" : "",		\
63	    (device_get_unit(dev) == snd_unit) ? " default" : "")
64
65#define SNDSTAT_PREPARE_PCM_END()					\
66	if (verbose <= 1)						\
67		return (0);						\
68									\
69	sbuf_printf(s, "\n\t");						\
70	sbuf_printf(s, "snddev flags=0x%b", d->flags, SD_F_BITS);	\
71									\
72	CHN_FOREACH(c, d, channels.pcm) {				\
73									\
74		KASSERT(c->bufhard != NULL && c->bufsoft != NULL,	\
75		    ("hosed pcm channel setup"));			\
76									\
77		sbuf_printf(s, "\n\t");					\
78									\
79		sbuf_printf(s, "%s[%s]: ",				\
80		    (c->parentchannel != NULL) ?			\
81		    c->parentchannel->name : "", c->name);		\
82		sbuf_printf(s, "spd %d", c->speed);			\
83		if (c->speed != sndbuf_getspd(c->bufhard))		\
84			sbuf_printf(s, "/%d",				\
85			    sndbuf_getspd(c->bufhard));			\
86		sbuf_printf(s, ", fmt 0x%08x", c->format);		\
87		if (c->format != sndbuf_getfmt(c->bufhard))		\
88			sbuf_printf(s, "/0x%08x",			\
89			    sndbuf_getfmt(c->bufhard));			\
90		sbuf_printf(s, ", flags 0x%08x, 0x%08x",		\
91		    c->flags, c->feederflags);				\
92		if (c->pid != -1)					\
93			sbuf_printf(s, ", pid %d (%s)",			\
94			    c->pid, c->comm);				\
95		sbuf_printf(s, "\n\t");					\
96									\
97		sbuf_printf(s, "interrupts %d, ", c->interrupts);	\
98									\
99		if (c->direction == PCMDIR_REC)				\
100			sbuf_printf(s,					\
101			    "overruns %d, feed %u, hfree %d, "		\
102			    "sfree %d [b:%d/%d/%d|bs:%d/%d/%d]",	\
103				c->xruns, c->feedcount,			\
104				sndbuf_getfree(c->bufhard),		\
105				sndbuf_getfree(c->bufsoft),		\
106				sndbuf_getsize(c->bufhard),		\
107				sndbuf_getblksz(c->bufhard),		\
108				sndbuf_getblkcnt(c->bufhard),		\
109				sndbuf_getsize(c->bufsoft),		\
110				sndbuf_getblksz(c->bufsoft),		\
111				sndbuf_getblkcnt(c->bufsoft));		\
112		else							\
113			sbuf_printf(s,					\
114			    "underruns %d, feed %u, ready %d "		\
115			    "[b:%d/%d/%d|bs:%d/%d/%d]",			\
116				c->xruns, c->feedcount,			\
117				sndbuf_getready(c->bufsoft),		\
118				sndbuf_getsize(c->bufhard),		\
119				sndbuf_getblksz(c->bufhard),		\
120				sndbuf_getblkcnt(c->bufhard),		\
121				sndbuf_getsize(c->bufsoft),		\
122				sndbuf_getblksz(c->bufsoft),		\
123				sndbuf_getblkcnt(c->bufsoft));		\
124		sbuf_printf(s, "\n\t");					\
125									\
126		sbuf_printf(s, "channel flags=0x%b", c->flags,		\
127		    CHN_F_BITS);					\
128		sbuf_printf(s, "\n\t");					\
129									\
130		sbuf_printf(s, "{%s}",					\
131		    (c->direction == PCMDIR_REC) ? "hardware" :		\
132		    "userland");					\
133		sbuf_printf(s, " -> ");					\
134		f = c->feeder;						\
135		while (f->source != NULL)				\
136			f = f->source;					\
137		while (f != NULL) {					\
138			sbuf_printf(s, "%s", f->class->name);		\
139			if (f->desc->type == FEEDER_FORMAT)		\
140				sbuf_printf(s, "(0x%08x -> 0x%08x)",	\
141				    f->desc->in, f->desc->out);		\
142			else if (f->desc->type == FEEDER_MATRIX)	\
143				sbuf_printf(s, "(%d.%d -> %d.%d)",	\
144				    AFMT_CHANNEL(f->desc->in) -		\
145				    AFMT_EXTCHANNEL(f->desc->in),	\
146				    AFMT_EXTCHANNEL(f->desc->in),	\
147				    AFMT_CHANNEL(f->desc->out) -	\
148				    AFMT_EXTCHANNEL(f->desc->out),	\
149				    AFMT_EXTCHANNEL(f->desc->out));	\
150			else if (f->desc->type == FEEDER_RATE)		\
151				sbuf_printf(s,				\
152				    "(0x%08x q:%d %d -> %d)",		\
153				    f->desc->out,			\
154				    FEEDER_GET(f, FEEDRATE_QUALITY),	\
155				    FEEDER_GET(f, FEEDRATE_SRC),	\
156				    FEEDER_GET(f, FEEDRATE_DST));	\
157			else						\
158				sbuf_printf(s, "(0x%08x)",		\
159				    f->desc->out);			\
160			sbuf_printf(s, " -> ");				\
161			f = f->parent;					\
162		}							\
163		sbuf_printf(s, "{%s}",					\
164		    (c->direction == PCMDIR_REC) ? "userland" :		\
165		    "hardware");					\
166	}								\
167									\
168	return (0);							\
169} while (0)
170
171#endif	/* !_SND_SNDSTAT_H_ */
172