File:
[DragonFly] /
src /
sys /
dev /
sound /
pcm /
sndstat.c
Revision
1.5:
download - view:
text,
annotated -
select for diffs
Thu May 13 23:49:21 2004 UTC (9 years ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).
d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device. It was never
used for that purpose.
d_clone will be more fully implemented as work continues. We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads. This is something we will be needing later
on.
1: /*
2: * Copyright (c) 2001 Cameron Grant <gandalf@vilnya.demon.co.uk>
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: * $FreeBSD: src/sys/dev/sound/pcm/sndstat.c,v 1.4.2.2 2002/04/22 15:49:36 cg Exp $
27: * $DragonFly: src/sys/dev/sound/pcm/sndstat.c,v 1.5 2004/05/13 23:49:21 dillon Exp $
28: */
29:
30: #include <dev/sound/pcm/sound.h>
31: #include <dev/sound/pcm/vchan.h>
32:
33: SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/sndstat.c,v 1.5 2004/05/13 23:49:21 dillon Exp $");
34:
35: #define SS_TYPE_MODULE 0
36: #define SS_TYPE_FIRST 1
37: #define SS_TYPE_PCM 1
38: #define SS_TYPE_MIDI 2
39: #define SS_TYPE_SEQUENCER 3
40: #define SS_TYPE_LAST 3
41:
42: static d_open_t sndstat_open;
43: static d_close_t sndstat_close;
44: static d_read_t sndstat_read;
45:
46: static struct cdevsw sndstat_cdevsw = {
47: /* name */ "sndstat",
48: /* maj */ SND_CDEV_MAJOR,
49: /* flags */ 0,
50: /* port */ NULL,
51: /* clone */ NULL,
52:
53: /* open */ sndstat_open,
54: /* close */ sndstat_close,
55: /* read */ sndstat_read,
56: /* write */ nowrite,
57: /* ioctl */ noioctl,
58: /* poll */ nopoll,
59: /* mmap */ nommap,
60: /* strategy */ nostrategy,
61: /* dump */ nodump,
62: /* psize */ nopsize
63: };
64:
65: struct sndstat_entry {
66: SLIST_ENTRY(sndstat_entry) link;
67: device_t dev;
68: char *str;
69: sndstat_handler handler;
70: int type, unit;
71: };
72:
73: static struct sbuf sndstat_sbuf;
74: static dev_t sndstat_dev = 0;
75: static int sndstat_isopen = 0;
76: static int sndstat_bufptr;
77: static int sndstat_maxunit = -1;
78: static int sndstat_files = 0;
79:
80: static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(none);
81:
82: static int sndstat_verbose = 1;
83: #ifdef USING_MUTEX
84: TUNABLE_INT("hw.snd.verbose", &sndstat_verbose);
85: #else
86: TUNABLE_INT_DECL("hw.snd.verbose", 1, sndstat_verbose);
87: #endif
88:
89: static int sndstat_prepare(struct sbuf *s);
90:
91: static int
92: sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
93: {
94: intrmask_t s;
95: int error, verbose;
96:
97: verbose = sndstat_verbose;
98: error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
99: if (error == 0 && req->newptr != NULL) {
100: s = spltty();
101: if (verbose < 0 || verbose > 3)
102: error = EINVAL;
103: else
104: sndstat_verbose = verbose;
105: splx(s);
106: }
107: return error;
108: }
109: SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RW,
110: 0, sizeof(int), sysctl_hw_sndverbose, "I", "");
111:
112: static int
113: sndstat_open(dev_t i_dev, int flags, int mode, struct thread *td)
114: {
115: intrmask_t s;
116: int err;
117:
118: s = spltty();
119: if (sndstat_isopen) {
120: splx(s);
121: return EBUSY;
122: }
123: if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
124: splx(s);
125: return ENXIO;
126: }
127: sndstat_bufptr = 0;
128: err = (sndstat_prepare(&sndstat_sbuf) > 0)? 0 : ENOMEM;
129: if (!err)
130: sndstat_isopen = 1;
131:
132: splx(s);
133: return err;
134: }
135:
136: static int
137: sndstat_close(dev_t i_dev, int flags, int mode, struct thread *td)
138: {
139: intrmask_t s;
140:
141: s = spltty();
142: if (!sndstat_isopen) {
143: splx(s);
144: return EBADF;
145: }
146: sbuf_delete(&sndstat_sbuf);
147: sndstat_isopen = 0;
148:
149: splx(s);
150: return 0;
151: }
152:
153: static int
154: sndstat_read(dev_t i_dev, struct uio *buf, int flag)
155: {
156: intrmask_t s;
157: int l, err;
158:
159: s = spltty();
160: if (!sndstat_isopen) {
161: splx(s);
162: return EBADF;
163: }
164: l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr);
165: err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
166: sndstat_bufptr += l;
167:
168: splx(s);
169: return err;
170: }
171:
172: /************************************************************************/
173:
174: static struct sndstat_entry *
175: sndstat_find(int type, int unit)
176: {
177: struct sndstat_entry *ent;
178:
179: SLIST_FOREACH(ent, &sndstat_devlist, link) {
180: if (ent->type == type && ent->unit == unit)
181: return ent;
182: }
183:
184: return NULL;
185: }
186:
187: int
188: sndstat_register(device_t dev, char *str, sndstat_handler handler)
189: {
190: intrmask_t s;
191: struct sndstat_entry *ent;
192: const char *devtype;
193: int type, unit;
194:
195: if (dev) {
196: unit = device_get_unit(dev);
197: devtype = device_get_name(dev);
198: if (!strcmp(devtype, "pcm"))
199: type = SS_TYPE_PCM;
200: else if (!strcmp(devtype, "midi"))
201: type = SS_TYPE_MIDI;
202: else if (!strcmp(devtype, "sequencer"))
203: type = SS_TYPE_SEQUENCER;
204: else
205: return EINVAL;
206: } else {
207: type = SS_TYPE_MODULE;
208: unit = -1;
209: }
210:
211: ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_WAITOK);
212: if (!ent)
213: return ENOSPC;
214:
215: ent->dev = dev;
216: ent->str = str;
217: ent->type = type;
218: ent->unit = unit;
219: ent->handler = handler;
220:
221: s = spltty();
222: SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
223: if (type == SS_TYPE_MODULE)
224: sndstat_files++;
225: sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
226: splx(s);
227:
228: return 0;
229: }
230:
231: int
232: sndstat_registerfile(char *str)
233: {
234: return sndstat_register(NULL, str, NULL);
235: }
236:
237: int
238: sndstat_unregister(device_t dev)
239: {
240: intrmask_t s;
241: struct sndstat_entry *ent;
242:
243: s = spltty();
244: SLIST_FOREACH(ent, &sndstat_devlist, link) {
245: if (ent->dev == dev) {
246: SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
247: free(ent, M_DEVBUF);
248: splx(s);
249:
250: return 0;
251: }
252: }
253: splx(s);
254:
255: return ENXIO;
256: }
257:
258: int
259: sndstat_unregisterfile(char *str)
260: {
261: intrmask_t s;
262: struct sndstat_entry *ent;
263:
264: s = spltty();
265: SLIST_FOREACH(ent, &sndstat_devlist, link) {
266: if (ent->dev == NULL && ent->str == str) {
267: SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
268: free(ent, M_DEVBUF);
269: sndstat_files--;
270: splx(s);
271:
272: return 0;
273: }
274: }
275: splx(s);
276:
277: return ENXIO;
278: }
279:
280: /************************************************************************/
281:
282: static int
283: sndstat_prepare(struct sbuf *s)
284: {
285: struct sndstat_entry *ent;
286: int i, j;
287:
288: sbuf_printf(s, "FreeBSD Audio Driver (newpcm)\n");
289: if (SLIST_EMPTY(&sndstat_devlist)) {
290: sbuf_printf(s, "No devices installed.\n");
291: sbuf_finish(s);
292: return sbuf_len(s);
293: }
294:
295: sbuf_printf(s, "Installed devices:\n");
296:
297: for (i = 0; i <= sndstat_maxunit; i++) {
298: for (j = SS_TYPE_FIRST; j <= SS_TYPE_LAST; j++) {
299: ent = sndstat_find(j, i);
300: if (!ent)
301: continue;
302: sbuf_printf(s, "%s:", device_get_nameunit(ent->dev));
303: sbuf_printf(s, " <%s>", device_get_desc(ent->dev));
304: sbuf_printf(s, " %s", ent->str);
305: if (ent->handler)
306: ent->handler(s, ent->dev, sndstat_verbose);
307: else
308: sbuf_printf(s, " [no handler]");
309: sbuf_printf(s, "\n");
310: }
311: }
312:
313: if (sndstat_verbose >= 3 && sndstat_files > 0) {
314: sbuf_printf(s, "\nFile Versions:\n");
315:
316: SLIST_FOREACH(ent, &sndstat_devlist, link) {
317: if (ent->dev == NULL && ent->str != NULL)
318: sbuf_printf(s, "%s\n", ent->str);
319: }
320: }
321:
322: sbuf_finish(s);
323: return sbuf_len(s);
324: }
325:
326: static int
327: sndstat_init(void)
328: {
329: sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
330:
331: return (sndstat_dev != 0)? 0 : ENXIO;
332: }
333:
334: static int
335: sndstat_uninit(void)
336: {
337: intrmask_t s;
338:
339: s = spltty();
340: if (sndstat_isopen) {
341: splx(s);
342: return EBUSY;
343: }
344:
345: if (sndstat_dev)
346: destroy_dev(sndstat_dev);
347: sndstat_dev = 0;
348:
349: splx(s);
350: return 0;
351: }
352:
353: int
354: sndstat_busy(void)
355: {
356: return (sndstat_isopen);
357: }
358:
359: static void
360: sndstat_sysinit(void *p)
361: {
362: sndstat_init();
363: }
364:
365: static void
366: sndstat_sysuninit(void *p)
367: {
368: sndstat_uninit();
369: }
370:
371: SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
372: SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysuninit, NULL);
373:
374: