Sun Mar 28 19:50:05 2021 UTC ()
"" is not a valid interface attribute, so don't pass it to spkr_rescan()
(luckily it wasn't used anyway).


(thorpej)
diff -r1.17.14.1 -r1.17.14.2 src/sys/dev/spkr.c

cvs diff -r1.17.14.1 -r1.17.14.2 src/sys/dev/spkr.c (switch to unified diff)

--- src/sys/dev/spkr.c 2021/03/21 21:09:09 1.17.14.1
+++ src/sys/dev/spkr.c 2021/03/28 19:50:05 1.17.14.2
@@ -1,594 +1,594 @@ @@ -1,594 +1,594 @@
1/* $NetBSD: spkr.c,v 1.17.14.1 2021/03/21 21:09:09 thorpej Exp $ */ 1/* $NetBSD: spkr.c,v 1.17.14.2 2021/03/28 19:50:05 thorpej Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com) 4 * Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com)
5 * Copyright (c) 1990 Andrew A. Chernov (ache@astral.msk.su) 5 * Copyright (c) 1990 Andrew A. Chernov (ache@astral.msk.su)
6 * Copyright (c) 1990 Lennart Augustsson (lennart@augustsson.net) 6 * Copyright (c) 1990 Lennart Augustsson (lennart@augustsson.net)
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed by Eric S. Raymond 19 * This product includes software developed by Eric S. Raymond
20 * 4. The name of the author may not be used to endorse or promote products 20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission. 21 * derived from this software without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE. 33 * POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36/* 36/*
37 * spkr.c -- device driver for console speaker on 80386 37 * spkr.c -- device driver for console speaker on 80386
38 * 38 *
39 * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990 39 * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
40 * modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su> 40 * modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
41 * 386bsd only clean version, all SYSV stuff removed 41 * 386bsd only clean version, all SYSV stuff removed
42 * use hz value from param.c 42 * use hz value from param.c
43 */ 43 */
44 44
45#include <sys/cdefs.h> 45#include <sys/cdefs.h>
46__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.17.14.1 2021/03/21 21:09:09 thorpej Exp $"); 46__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.17.14.2 2021/03/28 19:50:05 thorpej Exp $");
47 47
48#if defined(_KERNEL_OPT) 48#if defined(_KERNEL_OPT)
49#include "wsmux.h" 49#include "wsmux.h"
50#endif 50#endif
51 51
52#include <sys/param.h> 52#include <sys/param.h>
53#include <sys/systm.h> 53#include <sys/systm.h>
54#include <sys/kernel.h> 54#include <sys/kernel.h>
55#include <sys/errno.h> 55#include <sys/errno.h>
56#include <sys/device.h> 56#include <sys/device.h>
57#include <sys/malloc.h> 57#include <sys/malloc.h>
58#include <sys/module.h> 58#include <sys/module.h>
59#include <sys/uio.h> 59#include <sys/uio.h>
60#include <sys/proc.h> 60#include <sys/proc.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/conf.h> 62#include <sys/conf.h>
63 63
64#include <sys/bus.h> 64#include <sys/bus.h>
65 65
66#include <dev/spkrio.h> 66#include <dev/spkrio.h>
67#include <dev/spkrvar.h> 67#include <dev/spkrvar.h>
68#include <dev/wscons/wsconsio.h> 68#include <dev/wscons/wsconsio.h>
69#include <dev/wscons/wsbellvar.h> 69#include <dev/wscons/wsbellvar.h>
70#include <dev/wscons/wsbellmuxvar.h> 70#include <dev/wscons/wsbellmuxvar.h>
71 71
72#include "ioconf.h" 72#include "ioconf.h"
73 73
74dev_type_open(spkropen); 74dev_type_open(spkropen);
75dev_type_close(spkrclose); 75dev_type_close(spkrclose);
76dev_type_write(spkrwrite); 76dev_type_write(spkrwrite);
77dev_type_ioctl(spkrioctl); 77dev_type_ioctl(spkrioctl);
78 78
79const struct cdevsw spkr_cdevsw = { 79const struct cdevsw spkr_cdevsw = {
80 .d_open = spkropen, 80 .d_open = spkropen,
81 .d_close = spkrclose, 81 .d_close = spkrclose,
82 .d_read = noread, 82 .d_read = noread,
83 .d_write = spkrwrite, 83 .d_write = spkrwrite,
84 .d_ioctl = spkrioctl, 84 .d_ioctl = spkrioctl,
85 .d_stop = nostop, 85 .d_stop = nostop,
86 .d_tty = notty, 86 .d_tty = notty,
87 .d_poll = nopoll, 87 .d_poll = nopoll,
88 .d_mmap = nommap, 88 .d_mmap = nommap,
89 .d_kqfilter = nokqfilter, 89 .d_kqfilter = nokqfilter,
90 .d_discard = nodiscard, 90 .d_discard = nodiscard,
91 .d_flag = D_OTHER 91 .d_flag = D_OTHER
92}; 92};
93 93
94static void playinit(struct spkr_softc *); 94static void playinit(struct spkr_softc *);
95static void playtone(struct spkr_softc *, int, int, int); 95static void playtone(struct spkr_softc *, int, int, int);
96static void playstring(struct spkr_softc *, const char *, size_t); 96static void playstring(struct spkr_softc *, const char *, size_t);
97 97
98/**************** PLAY STRING INTERPRETER BEGINS HERE ********************** 98/**************** PLAY STRING INTERPRETER BEGINS HERE **********************
99 * 99 *
100 * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement; 100 * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement;
101 * M[LNS] are missing and the ~ synonym and octave-tracking facility is added. 101 * M[LNS] are missing and the ~ synonym and octave-tracking facility is added.
102 * Requires spkr_tone(), spkr_rest(). String play is not interruptible 102 * Requires spkr_tone(), spkr_rest(). String play is not interruptible
103 * except possibly at physical block boundaries. 103 * except possibly at physical block boundaries.
104 */ 104 */
105 105
106#define dtoi(c) ((c) - '0') 106#define dtoi(c) ((c) - '0')
107 107
108/* 108/*
109 * Magic number avoidance... 109 * Magic number avoidance...
110 */ 110 */
111#define SECS_PER_MIN 60 /* seconds per minute */ 111#define SECS_PER_MIN 60 /* seconds per minute */
112#define WHOLE_NOTE 4 /* quarter notes per whole note */ 112#define WHOLE_NOTE 4 /* quarter notes per whole note */
113#define MIN_VALUE 64 /* the most we can divide a note by */ 113#define MIN_VALUE 64 /* the most we can divide a note by */
114#define DFLT_VALUE 4 /* default value (quarter-note) */ 114#define DFLT_VALUE 4 /* default value (quarter-note) */
115#define FILLTIME 8 /* for articulation, break note in parts */ 115#define FILLTIME 8 /* for articulation, break note in parts */
116#define STACCATO 6 /* 6/8 = 3/4 of note is filled */ 116#define STACCATO 6 /* 6/8 = 3/4 of note is filled */
117#define NORMAL 7 /* 7/8ths of note interval is filled */ 117#define NORMAL 7 /* 7/8ths of note interval is filled */
118#define LEGATO 8 /* all of note interval is filled */ 118#define LEGATO 8 /* all of note interval is filled */
119#define DFLT_OCTAVE 4 /* default octave */ 119#define DFLT_OCTAVE 4 /* default octave */
120#define MIN_TEMPO 32 /* minimum tempo */ 120#define MIN_TEMPO 32 /* minimum tempo */
121#define DFLT_TEMPO 120 /* default tempo */ 121#define DFLT_TEMPO 120 /* default tempo */
122#define MAX_TEMPO 255 /* max tempo */ 122#define MAX_TEMPO 255 /* max tempo */
123#define NUM_MULT 3 /* numerator of dot multiplier */ 123#define NUM_MULT 3 /* numerator of dot multiplier */
124#define DENOM_MULT 2 /* denominator of dot multiplier */ 124#define DENOM_MULT 2 /* denominator of dot multiplier */
125 125
126/* letter to half-tone: A B C D E F G */ 126/* letter to half-tone: A B C D E F G */
127static const int notetab[8] = { 9, 11, 0, 2, 4, 5, 7 }; 127static const int notetab[8] = { 9, 11, 0, 2, 4, 5, 7 };
128 128
129/* 129/*
130 * This is the American Standard A440 Equal-Tempered scale with frequencies 130 * This is the American Standard A440 Equal-Tempered scale with frequencies
131 * rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook... 131 * rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook...
132 * our octave 0 is standard octave 2. 132 * our octave 0 is standard octave 2.
133 */ 133 */
134#define OCTAVE_NOTES 12 /* semitones per octave */ 134#define OCTAVE_NOTES 12 /* semitones per octave */
135static const int pitchtab[] = 135static const int pitchtab[] =
136{ 136{
137/* C C# D D# E F F# G G# A A# B*/ 137/* C C# D D# E F F# G G# A A# B*/
138/* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123, 138/* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123,
139/* 1 */ 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247, 139/* 1 */ 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
140/* 2 */ 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, 140/* 2 */ 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
141/* 3 */ 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 141/* 3 */ 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
142/* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975, 142/* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975,
143/* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, 143/* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
144/* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902, 144/* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902,
145}; 145};
146#define NOCTAVES (int)(__arraycount(pitchtab) / OCTAVE_NOTES) 146#define NOCTAVES (int)(__arraycount(pitchtab) / OCTAVE_NOTES)
147 147
148static void 148static void
149playinit(struct spkr_softc *sc) 149playinit(struct spkr_softc *sc)
150{ 150{
151 sc->sc_octave = DFLT_OCTAVE; 151 sc->sc_octave = DFLT_OCTAVE;
152 sc->sc_whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO; 152 sc->sc_whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
153 sc->sc_fill = NORMAL; 153 sc->sc_fill = NORMAL;
154 sc->sc_value = DFLT_VALUE; 154 sc->sc_value = DFLT_VALUE;
155 sc->sc_octtrack = false; 155 sc->sc_octtrack = false;
156 sc->sc_octprefix = true;/* act as though there was an initial O(n) */ 156 sc->sc_octprefix = true;/* act as though there was an initial O(n) */
157} 157}
158 158
159/* play tone of proper duration for current rhythm signature */ 159/* play tone of proper duration for current rhythm signature */
160static void 160static void
161playtone(struct spkr_softc *sc, int pitch, int val, int sustain) 161playtone(struct spkr_softc *sc, int pitch, int val, int sustain)
162{ 162{
163 int sound, silence, snum = 1, sdenom = 1; 163 int sound, silence, snum = 1, sdenom = 1;
164 164
165 /* this weirdness avoids floating-point arithmetic */ 165 /* this weirdness avoids floating-point arithmetic */
166 for (; sustain; sustain--) { 166 for (; sustain; sustain--) {
167 snum *= NUM_MULT; 167 snum *= NUM_MULT;
168 sdenom *= DENOM_MULT; 168 sdenom *= DENOM_MULT;
169 } 169 }
170 170
171 if (pitch == -1) { 171 if (pitch == -1) {
172 (*sc->sc_rest)(sc->sc_dev, sc->sc_whole 172 (*sc->sc_rest)(sc->sc_dev, sc->sc_whole
173 * snum / (val * sdenom)); 173 * snum / (val * sdenom));
174 return; 174 return;
175 } 175 }
176 176
177 int fac = sc->sc_whole * (FILLTIME - sc->sc_fill); 177 int fac = sc->sc_whole * (FILLTIME - sc->sc_fill);
178 int fval = FILLTIME * val; 178 int fval = FILLTIME * val;
179 sound = (sc->sc_whole * snum) / (val * sdenom) - fac / fval; 179 sound = (sc->sc_whole * snum) / (val * sdenom) - fac / fval;
180 silence = fac * snum / (fval * sdenom); 180 silence = fac * snum / (fval * sdenom);
181 181
182#ifdef SPKRDEBUG 182#ifdef SPKRDEBUG
183 aprint_debug_dev(sc->sc_dev, 183 aprint_debug_dev(sc->sc_dev,
184 "%s: pitch %d for %d ticks, rest for %d ticks\n", __func__, 184 "%s: pitch %d for %d ticks, rest for %d ticks\n", __func__,
185 pitch, sound, silence); 185 pitch, sound, silence);
186#endif /* SPKRDEBUG */ 186#endif /* SPKRDEBUG */
187 187
188 (*sc->sc_tone)(sc->sc_dev, pitchtab[pitch], sound); 188 (*sc->sc_tone)(sc->sc_dev, pitchtab[pitch], sound);
189 if (sc->sc_fill != LEGATO) 189 if (sc->sc_fill != LEGATO)
190 (*sc->sc_rest)(sc->sc_dev, silence); 190 (*sc->sc_rest)(sc->sc_dev, silence);
191} 191}
192 192
193/* interpret and play an item from a notation string */ 193/* interpret and play an item from a notation string */
194static void 194static void
195playstring(struct spkr_softc *sc, const char *cp, size_t slen) 195playstring(struct spkr_softc *sc, const char *cp, size_t slen)
196{ 196{
197 int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; 197 int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
198 198
199#define GETNUM(cp, v) \ 199#define GETNUM(cp, v) \
200 for (v = 0; slen > 0 && isdigit((unsigned char)cp[1]); ) { \ 200 for (v = 0; slen > 0 && isdigit((unsigned char)cp[1]); ) { \
201 v = v * 10 + (*++cp - '0'); \ 201 v = v * 10 + (*++cp - '0'); \
202 slen--; \ 202 slen--; \
203 } 203 }
204 204
205 for (; slen--; cp++) { 205 for (; slen--; cp++) {
206 int sustain, timeval, tempo; 206 int sustain, timeval, tempo;
207 char c = toupper((unsigned char)*cp); 207 char c = toupper((unsigned char)*cp);
208 208
209#ifdef SPKRDEBUG 209#ifdef SPKRDEBUG
210 aprint_debug_dev(sc->sc_dev, "%s: %c (%x)\n", __func__, c, c); 210 aprint_debug_dev(sc->sc_dev, "%s: %c (%x)\n", __func__, c, c);
211#endif /* SPKRDEBUG */ 211#endif /* SPKRDEBUG */
212 212
213 switch (c) { 213 switch (c) {
214 case 'A': case 'B': case 'C': case 'D': 214 case 'A': case 'B': case 'C': case 'D':
215 case 'E': case 'F': case 'G': 215 case 'E': case 'F': case 'G':
216 /* compute pitch */ 216 /* compute pitch */
217 pitch = notetab[c - 'A'] + sc->sc_octave * OCTAVE_NOTES; 217 pitch = notetab[c - 'A'] + sc->sc_octave * OCTAVE_NOTES;
218 218
219 /* this may be followed by an accidental sign */ 219 /* this may be followed by an accidental sign */
220 if (slen > 0 && (cp[1] == '#' || cp[1] == '+')) { 220 if (slen > 0 && (cp[1] == '#' || cp[1] == '+')) {
221 ++pitch; 221 ++pitch;
222 ++cp; 222 ++cp;
223 slen--; 223 slen--;
224 } else if (slen > 0 && cp[1] == '-') { 224 } else if (slen > 0 && cp[1] == '-') {
225 --pitch; 225 --pitch;
226 ++cp; 226 ++cp;
227 slen--; 227 slen--;
228 } 228 }
229 229
230 /* 230 /*
231 * If octave-tracking mode is on, and there has been no 231 * If octave-tracking mode is on, and there has been no
232 * octave- setting prefix, find the version of the 232 * octave- setting prefix, find the version of the
233 * current letter note * closest to the last 233 * current letter note * closest to the last
234 * regardless of octave. 234 * regardless of octave.
235 */ 235 */
236 if (sc->sc_octtrack && !sc->sc_octprefix) { 236 if (sc->sc_octtrack && !sc->sc_octprefix) {
237 int d = abs(pitch - lastpitch); 237 int d = abs(pitch - lastpitch);
238 if (d > abs(pitch + OCTAVE_NOTES - lastpitch)) { 238 if (d > abs(pitch + OCTAVE_NOTES - lastpitch)) {
239 if (sc->sc_octave < NOCTAVES - 1) { 239 if (sc->sc_octave < NOCTAVES - 1) {
240 ++sc->sc_octave; 240 ++sc->sc_octave;
241 pitch += OCTAVE_NOTES; 241 pitch += OCTAVE_NOTES;
242 } 242 }
243 } 243 }
244 244
245 if (d > abs(pitch - OCTAVE_NOTES - lastpitch)) { 245 if (d > abs(pitch - OCTAVE_NOTES - lastpitch)) {
246 if (sc->sc_octave > 0) { 246 if (sc->sc_octave > 0) {
247 --sc->sc_octave; 247 --sc->sc_octave;
248 pitch -= OCTAVE_NOTES; 248 pitch -= OCTAVE_NOTES;
249 } 249 }
250 } 250 }
251 } 251 }
252 sc->sc_octprefix = false; 252 sc->sc_octprefix = false;
253 lastpitch = pitch; 253 lastpitch = pitch;
254 254
255 /* 255 /*
256 * ...which may in turn be followed by an override 256 * ...which may in turn be followed by an override
257 * time value 257 * time value
258 */ 258 */
259 GETNUM(cp, timeval); 259 GETNUM(cp, timeval);
260 if (timeval <= 0 || timeval > MIN_VALUE) 260 if (timeval <= 0 || timeval > MIN_VALUE)
261 timeval = sc->sc_value; 261 timeval = sc->sc_value;
262 262
263 /* ...and/or sustain dots */ 263 /* ...and/or sustain dots */
264 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { 264 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
265 slen--; 265 slen--;
266 sustain++; 266 sustain++;
267 } 267 }
268 268
269 /* time to emit the actual tone */ 269 /* time to emit the actual tone */
270 playtone(sc, pitch, timeval, sustain); 270 playtone(sc, pitch, timeval, sustain);
271 break; 271 break;
272 272
273 case 'O': 273 case 'O':
274 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { 274 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
275 sc->sc_octprefix = sc->sc_octtrack = false; 275 sc->sc_octprefix = sc->sc_octtrack = false;
276 ++cp; 276 ++cp;
277 slen--; 277 slen--;
278 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { 278 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
279 sc->sc_octtrack = true; 279 sc->sc_octtrack = true;
280 ++cp; 280 ++cp;
281 slen--; 281 slen--;
282 } else { 282 } else {
283 GETNUM(cp, sc->sc_octave); 283 GETNUM(cp, sc->sc_octave);
284 if (sc->sc_octave >= NOCTAVES) 284 if (sc->sc_octave >= NOCTAVES)
285 sc->sc_octave = DFLT_OCTAVE; 285 sc->sc_octave = DFLT_OCTAVE;
286 sc->sc_octprefix = true; 286 sc->sc_octprefix = true;
287 } 287 }
288 break; 288 break;
289 289
290 case '>': 290 case '>':
291 if (sc->sc_octave < NOCTAVES - 1) 291 if (sc->sc_octave < NOCTAVES - 1)
292 sc->sc_octave++; 292 sc->sc_octave++;
293 sc->sc_octprefix = true; 293 sc->sc_octprefix = true;
294 break; 294 break;
295 295
296 case '<': 296 case '<':
297 if (sc->sc_octave > 0) 297 if (sc->sc_octave > 0)
298 sc->sc_octave--; 298 sc->sc_octave--;
299 sc->sc_octprefix = true; 299 sc->sc_octprefix = true;
300 break; 300 break;
301 301
302 case 'N': 302 case 'N':
303 GETNUM(cp, pitch); 303 GETNUM(cp, pitch);
304 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { 304 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
305 slen--; 305 slen--;
306 sustain++; 306 sustain++;
307 } 307 }
308 playtone(sc, pitch - 1, sc->sc_value, sustain); 308 playtone(sc, pitch - 1, sc->sc_value, sustain);
309 break; 309 break;
310 310
311 case 'L': 311 case 'L':
312 GETNUM(cp, sc->sc_value); 312 GETNUM(cp, sc->sc_value);
313 if (sc->sc_value <= 0 || sc->sc_value > MIN_VALUE) 313 if (sc->sc_value <= 0 || sc->sc_value > MIN_VALUE)
314 sc->sc_value = DFLT_VALUE; 314 sc->sc_value = DFLT_VALUE;
315 break; 315 break;
316 316
317 case 'P': 317 case 'P':
318 case '~': 318 case '~':
319 /* this may be followed by an override time value */ 319 /* this may be followed by an override time value */
320 GETNUM(cp, timeval); 320 GETNUM(cp, timeval);
321 if (timeval <= 0 || timeval > MIN_VALUE) 321 if (timeval <= 0 || timeval > MIN_VALUE)
322 timeval = sc->sc_value; 322 timeval = sc->sc_value;
323 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { 323 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
324 slen--; 324 slen--;
325 sustain++; 325 sustain++;
326 } 326 }
327 playtone(sc, -1, timeval, sustain); 327 playtone(sc, -1, timeval, sustain);
328 break; 328 break;
329 329
330 case 'T': 330 case 'T':
331 GETNUM(cp, tempo); 331 GETNUM(cp, tempo);
332 if (tempo < MIN_TEMPO || tempo > MAX_TEMPO) 332 if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
333 tempo = DFLT_TEMPO; 333 tempo = DFLT_TEMPO;
334 sc->sc_whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo; 334 sc->sc_whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
335 break; 335 break;
336 336
337 case 'M': 337 case 'M':
338 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { 338 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
339 sc->sc_fill = NORMAL; 339 sc->sc_fill = NORMAL;
340 ++cp; 340 ++cp;
341 slen--; 341 slen--;
342 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { 342 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
343 sc->sc_fill = LEGATO; 343 sc->sc_fill = LEGATO;
344 ++cp; 344 ++cp;
345 slen--; 345 slen--;
346 } else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's')) { 346 } else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's')) {
347 sc->sc_fill = STACCATO; 347 sc->sc_fill = STACCATO;
348 ++cp; 348 ++cp;
349 slen--; 349 slen--;
350 } 350 }
351 break; 351 break;
352 } 352 }
353 } 353 }
354} 354}
355 355
356/******************* UNIX DRIVER HOOKS BEGIN HERE ************************** 356/******************* UNIX DRIVER HOOKS BEGIN HERE **************************
357 * 357 *
358 * This section implements driver hooks to run playstring() and the spkr_tone() 358 * This section implements driver hooks to run playstring() and the spkr_tone()
359 * and spkr_rest() functions defined above. 359 * and spkr_rest() functions defined above.
360 */ 360 */
361#define spkrenter(d) device_lookup_private(&spkr_cd, d) 361#define spkrenter(d) device_lookup_private(&spkr_cd, d)
362 362
363void 363void
364spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int), 364spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int),
365 void (*rest)(device_t, int)) 365 void (*rest)(device_t, int))
366{ 366{
367 struct spkr_softc *sc = device_private(self); 367 struct spkr_softc *sc = device_private(self);
368 368
369#ifdef SPKRDEBUG 369#ifdef SPKRDEBUG
370 aprint_debug("%s: entering for unit %d\n", __func__, self->dv_unit); 370 aprint_debug("%s: entering for unit %d\n", __func__, self->dv_unit);
371#endif /* SPKRDEBUG */ 371#endif /* SPKRDEBUG */
372 sc->sc_dev = self; 372 sc->sc_dev = self;
373 sc->sc_tone = tone; 373 sc->sc_tone = tone;
374 sc->sc_rest = rest; 374 sc->sc_rest = rest;
375 sc->sc_inbuf = NULL; 375 sc->sc_inbuf = NULL;
376 sc->sc_wsbelldev = NULL; 376 sc->sc_wsbelldev = NULL;
377 377
378 spkr_rescan(self, "", NULL); 378 spkr_rescan(self, NULL, NULL);
379} 379}
380 380
381int 381int
382spkr_detach(device_t self, int flags) 382spkr_detach(device_t self, int flags)
383{ 383{
384 struct spkr_softc *sc = device_private(self); 384 struct spkr_softc *sc = device_private(self);
385 int rc; 385 int rc;
386 386
387#ifdef SPKRDEBUG 387#ifdef SPKRDEBUG
388 aprint_debug("%s: entering for unit %d\n", __func__, self->dv_unit); 388 aprint_debug("%s: entering for unit %d\n", __func__, self->dv_unit);
389#endif /* SPKRDEBUG */ 389#endif /* SPKRDEBUG */
390 if (sc == NULL) 390 if (sc == NULL)
391 return ENXIO; 391 return ENXIO;
392 392
393 /* XXXNS If speaker never closes, we cannot complete the detach. */ 393 /* XXXNS If speaker never closes, we cannot complete the detach. */
394 while ((flags & DETACH_FORCE) != 0 && sc->sc_inbuf != NULL) 394 while ((flags & DETACH_FORCE) != 0 && sc->sc_inbuf != NULL)
395 kpause("spkrwait", TRUE, 1, NULL); 395 kpause("spkrwait", TRUE, 1, NULL);
396 if (sc->sc_inbuf != NULL) 396 if (sc->sc_inbuf != NULL)
397 return EBUSY; 397 return EBUSY;
398 398
399 rc = config_detach_children(self, flags); 399 rc = config_detach_children(self, flags);
400 400
401 return rc; 401 return rc;
402} 402}
403 403
404/* ARGSUSED */ 404/* ARGSUSED */
405int 405int
406spkr_rescan(device_t self, const char *iattr, const int *locators) 406spkr_rescan(device_t self, const char *iattr, const int *locators)
407{ 407{
408#if NWSMUX > 0 408#if NWSMUX > 0
409 struct spkr_softc *sc = device_private(self); 409 struct spkr_softc *sc = device_private(self);
410 struct wsbelldev_attach_args a; 410 struct wsbelldev_attach_args a;
411 411
412 if (sc->sc_wsbelldev == NULL) { 412 if (sc->sc_wsbelldev == NULL) {
413 a.accesscookie = sc; 413 a.accesscookie = sc;
414 sc->sc_wsbelldev = config_found(self, &a, wsbelldevprint, 414 sc->sc_wsbelldev = config_found(self, &a, wsbelldevprint,
415 CFARG_EOL); 415 CFARG_EOL);
416 } 416 }
417#endif 417#endif
418 return 0; 418 return 0;
419} 419}
420 420
421int 421int
422spkr_childdet(device_t self, device_t child) 422spkr_childdet(device_t self, device_t child)
423{ 423{
424 struct spkr_softc *sc = device_private(self); 424 struct spkr_softc *sc = device_private(self);
425 425
426 if (sc->sc_wsbelldev == child) 426 if (sc->sc_wsbelldev == child)
427 sc->sc_wsbelldev = NULL; 427 sc->sc_wsbelldev = NULL;
428 428
429 return 0; 429 return 0;
430} 430}
431 431
432int 432int
433spkropen(dev_t dev, int flags, int mode, struct lwp *l) 433spkropen(dev_t dev, int flags, int mode, struct lwp *l)
434{ 434{
435#ifdef SPKRDEBUG 435#ifdef SPKRDEBUG
436 aprint_debug("%s: entering with dev = %"PRIx64"\n", __func__, dev); 436 aprint_debug("%s: entering with dev = %"PRIx64"\n", __func__, dev);
437#endif /* SPKRDEBUG */ 437#endif /* SPKRDEBUG */
438 struct spkr_softc *sc = spkrenter(minor(dev)); 438 struct spkr_softc *sc = spkrenter(minor(dev));
439 439
440 if (sc == NULL) 440 if (sc == NULL)
441 return ENXIO; 441 return ENXIO;
442 if (sc->sc_inbuf != NULL) 442 if (sc->sc_inbuf != NULL)
443 return EBUSY; 443 return EBUSY;
444 444
445 sc->sc_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK); 445 sc->sc_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK);
446 playinit(sc); 446 playinit(sc);
447 return 0; 447 return 0;
448} 448}
449 449
450int 450int
451spkrwrite(dev_t dev, struct uio *uio, int flags) 451spkrwrite(dev_t dev, struct uio *uio, int flags)
452{ 452{
453#ifdef SPKRDEBUG 453#ifdef SPKRDEBUG
454 aprint_debug("%s: entering with dev = %"PRIx64", count = %zu\n", 454 aprint_debug("%s: entering with dev = %"PRIx64", count = %zu\n",
455 __func__, dev, uio->uio_resid); 455 __func__, dev, uio->uio_resid);
456#endif /* SPKRDEBUG */ 456#endif /* SPKRDEBUG */
457 struct spkr_softc *sc = spkrenter(minor(dev)); 457 struct spkr_softc *sc = spkrenter(minor(dev));
458 458
459 if (sc == NULL) 459 if (sc == NULL)
460 return ENXIO; 460 return ENXIO;
461 if (sc->sc_inbuf == NULL) 461 if (sc->sc_inbuf == NULL)
462 return EINVAL; 462 return EINVAL;
463 463
464 size_t n = uimin(DEV_BSIZE, uio->uio_resid); 464 size_t n = uimin(DEV_BSIZE, uio->uio_resid);
465 int error = uiomove(sc->sc_inbuf, n, uio); 465 int error = uiomove(sc->sc_inbuf, n, uio);
466 if (error) 466 if (error)
467 return error; 467 return error;
468 playstring(sc, sc->sc_inbuf, n); 468 playstring(sc, sc->sc_inbuf, n);
469 return 0; 469 return 0;
470} 470}
471 471
472int 472int
473spkrclose(dev_t dev, int flags, int mode, struct lwp *l) 473spkrclose(dev_t dev, int flags, int mode, struct lwp *l)
474{ 474{
475#ifdef SPKRDEBUG 475#ifdef SPKRDEBUG
476 aprint_debug("%s: entering with dev = %"PRIx64"\n", __func__, dev); 476 aprint_debug("%s: entering with dev = %"PRIx64"\n", __func__, dev);
477#endif /* SPKRDEBUG */ 477#endif /* SPKRDEBUG */
478 struct spkr_softc *sc = spkrenter(minor(dev)); 478 struct spkr_softc *sc = spkrenter(minor(dev));
479 479
480 if (sc == NULL) 480 if (sc == NULL)
481 return ENXIO; 481 return ENXIO;
482 if (sc->sc_inbuf == NULL) 482 if (sc->sc_inbuf == NULL)
483 return EINVAL; 483 return EINVAL;
484 484
485 sc->sc_tone(sc->sc_dev, 0, 0); 485 sc->sc_tone(sc->sc_dev, 0, 0);
486 free(sc->sc_inbuf, M_DEVBUF); 486 free(sc->sc_inbuf, M_DEVBUF);
487 sc->sc_inbuf = NULL; 487 sc->sc_inbuf = NULL;
488 488
489 return 0; 489 return 0;
490} 490}
491 491
492static void 492static void
493playonetone(struct spkr_softc *sc, tone_t *tp) 493playonetone(struct spkr_softc *sc, tone_t *tp)
494{ 494{
495 if (tp->frequency == 0) 495 if (tp->frequency == 0)
496 (*sc->sc_rest)(sc->sc_dev, tp->duration); 496 (*sc->sc_rest)(sc->sc_dev, tp->duration);
497 else 497 else
498 (*sc->sc_tone)(sc->sc_dev, tp->frequency, tp->duration); 498 (*sc->sc_tone)(sc->sc_dev, tp->frequency, tp->duration);
499} 499}
500 500
501int 501int
502spkrioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 502spkrioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
503{ 503{
504 tone_t *tp; 504 tone_t *tp;
505 tone_t ttp; 505 tone_t ttp;
506 int error; 506 int error;
507#ifdef SPKRDEBUG 507#ifdef SPKRDEBUG
508 aprint_debug("%s: entering with dev = %"PRIx64", cmd = %lx\n", 508 aprint_debug("%s: entering with dev = %"PRIx64", cmd = %lx\n",
509 __func__, dev, cmd); 509 __func__, dev, cmd);
510#endif /* SPKRDEBUG */ 510#endif /* SPKRDEBUG */
511 511
512 struct spkr_softc *sc = spkrenter(minor(dev)); 512 struct spkr_softc *sc = spkrenter(minor(dev));
513 513
514 if (sc == NULL) 514 if (sc == NULL)
515 return ENXIO; 515 return ENXIO;
516 if (sc->sc_inbuf == NULL) 516 if (sc->sc_inbuf == NULL)
517 return EINVAL; 517 return EINVAL;
518 518
519 switch (cmd) { 519 switch (cmd) {
520 case SPKRTONE: 520 case SPKRTONE:
521 playonetone(sc, data); 521 playonetone(sc, data);
522 return 0; 522 return 0;
523 case SPKRTUNE: 523 case SPKRTUNE:
524 for (tp = *(void **)data;; tp++) { 524 for (tp = *(void **)data;; tp++) {
525 error = copyin(tp, &ttp, sizeof(tone_t)); 525 error = copyin(tp, &ttp, sizeof(tone_t));
526 if (error) 526 if (error)
527 return(error); 527 return(error);
528 if (ttp.duration == 0) 528 if (ttp.duration == 0)
529 break; 529 break;
530 playonetone(sc, &ttp); 530 playonetone(sc, &ttp);
531 } 531 }
532 return 0; 532 return 0;
533 case SPKRGETVOL: 533 case SPKRGETVOL:
534 if (data != NULL) 534 if (data != NULL)
535 *(u_int *)data = sc->sc_vol; 535 *(u_int *)data = sc->sc_vol;
536 return 0; 536 return 0;
537 case SPKRSETVOL: 537 case SPKRSETVOL:
538 if (data != NULL && *(u_int *)data <= 100) 538 if (data != NULL && *(u_int *)data <= 100)
539 sc->sc_vol = *(u_int *)data; 539 sc->sc_vol = *(u_int *)data;
540 return 0; 540 return 0;
541 default: 541 default:
542 return ENOTTY; 542 return ENOTTY;
543 } 543 }
544} 544}
545 545
546#ifdef _MODULE 546#ifdef _MODULE
547#include "ioconf.c" 547#include "ioconf.c"
548#endif 548#endif
549 549
550MODULE(MODULE_CLASS_DRIVER, spkr, "audio" /* and/or pcppi */ ); 550MODULE(MODULE_CLASS_DRIVER, spkr, "audio" /* and/or pcppi */ );
551 551
552int 552int
553spkr_modcmd(modcmd_t cmd, void *arg) 553spkr_modcmd(modcmd_t cmd, void *arg)
554{ 554{
555 int error = 0; 555 int error = 0;
556#ifdef _MODULE 556#ifdef _MODULE
557 devmajor_t bmajor, cmajor; 557 devmajor_t bmajor, cmajor;
558#endif 558#endif
559 559
560 switch(cmd) { 560 switch(cmd) {
561 case MODULE_CMD_INIT: 561 case MODULE_CMD_INIT:
562#ifdef _MODULE 562#ifdef _MODULE
563 bmajor = cmajor = -1; 563 bmajor = cmajor = -1;
564 error = devsw_attach(spkr_cd.cd_name, NULL, &bmajor, 564 error = devsw_attach(spkr_cd.cd_name, NULL, &bmajor,
565 &spkr_cdevsw, &cmajor); 565 &spkr_cdevsw, &cmajor);
566 if (error) 566 if (error)
567 break; 567 break;
568 568
569 error = config_init_component(cfdriver_ioconf_spkr, 569 error = config_init_component(cfdriver_ioconf_spkr,
570 cfattach_ioconf_spkr, cfdata_ioconf_spkr); 570 cfattach_ioconf_spkr, cfdata_ioconf_spkr);
571 if (error) { 571 if (error) {
572 devsw_detach(NULL, &spkr_cdevsw); 572 devsw_detach(NULL, &spkr_cdevsw);
573 } 573 }
574#endif 574#endif
575 break; 575 break;
576 576
577 case MODULE_CMD_FINI: 577 case MODULE_CMD_FINI:
578#ifdef _MODULE 578#ifdef _MODULE
579 devsw_detach(NULL, &spkr_cdevsw); 579 devsw_detach(NULL, &spkr_cdevsw);
580 error = config_fini_component(cfdriver_ioconf_spkr, 580 error = config_fini_component(cfdriver_ioconf_spkr,
581 cfattach_ioconf_spkr, cfdata_ioconf_spkr); 581 cfattach_ioconf_spkr, cfdata_ioconf_spkr);
582 if (error) 582 if (error)
583 devsw_attach(spkr_cd.cd_name, NULL, &bmajor, 583 devsw_attach(spkr_cd.cd_name, NULL, &bmajor,
584 &spkr_cdevsw, &cmajor); 584 &spkr_cdevsw, &cmajor);
585#endif 585#endif
586 break; 586 break;
587 587
588 default: 588 default:
589 error = ENOTTY; 589 error = ENOTTY;
590 break; 590 break;
591 } 591 }
592 592
593 return error; 593 return error;
594} 594}