Module Name:    src
Committed By:   christos
Date:           Tue Dec 13 20:20:34 UTC 2016

Modified Files:
        src/sys/conf: files
        src/sys/dev: files.audio spkr.c spkr_synth.c spkrvar.h
        src/sys/dev/isa: spkr_pcppi.c

Log Message:
Restructure speaker devices so that there can be multiple of them, and have
proper softc's.


To generate a diff of this commit:
cvs rdiff -u -r1.1166 -r1.1167 src/sys/conf/files
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/files.audio
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/spkr.c src/sys/dev/spkrvar.h
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/spkr_synth.c
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/isa/spkr_pcppi.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1166 src/sys/conf/files:1.1167
--- src/sys/conf/files:1.1166	Tue Nov  1 20:11:59 2016
+++ src/sys/conf/files	Tue Dec 13 15:20:34 2016
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.1166 2016/11/02 00:11:59 pgoyette Exp $
+#	$NetBSD: files,v 1.1167 2016/12/13 20:20:34 christos Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20150846
@@ -331,6 +331,10 @@ define 	pckbport	{[slot = -1]}
 define	pckbport_machdep_cnattach
 define	firmload
 
+# speaker devices, attaches to audio or pcppi drivers
+device	spkr
+file	dev/spkr.c			spkr
+
 include "dev/files.audio"
 
 # High definition audio

Index: src/sys/dev/files.audio
diff -u src/sys/dev/files.audio:1.7 src/sys/dev/files.audio:1.8
--- src/sys/dev/files.audio:1.7	Sun Dec 11 01:30:11 2016
+++ src/sys/dev/files.audio	Tue Dec 13 15:20:34 2016
@@ -1,4 +1,4 @@
-#	$NetBSD: files.audio,v 1.7 2016/12/11 06:30:11 christos Exp $
+#	$NetBSD: files.audio,v 1.8 2016/12/13 20:20:34 christos Exp $
 
 define	audiobus	{ }
 define	midibus		{ }
@@ -17,8 +17,7 @@ device	audio {}: audiodev, auconv, aurat
 attach	audio at audiobus
 device	midi: audio
 attach	midi at midibus
-device	spkr: audiobell
-attach  spkr at audio with spkr_synth
+attach	spkr at audio with spkr_synth
 
 # console bell via audio device
 #
@@ -26,12 +25,11 @@ define	audiobell
 
 file	dev/auconv.c			auconv
 file	dev/audio.c			audio			needs-flag
-file	dev/audiobell.c			audiobell		needs-flag
+file	dev/audiobell.c			spkr_synth		needs-flag
 file	dev/aurateconv.c		aurateconv		needs-flag
 file	dev/auvolconv.c			auvolconv
 file	dev/midi.c			midi			needs-flag
 file	dev/midictl.c			midisyn
 file	dev/midisyn.c			midisyn
 file	dev/mulaw.c			mulaw			needs-flag
-file	dev/spkr.c			spkr			needs-flag
 file	dev/spkr_synth.c		spkr_synth		needs-flag

Index: src/sys/dev/spkr.c
diff -u src/sys/dev/spkr.c:1.3 src/sys/dev/spkr.c:1.4
--- src/sys/dev/spkr.c:1.3	Fri Dec  9 00:17:03 2016
+++ src/sys/dev/spkr.c	Tue Dec 13 15:20:34 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: spkr.c,v 1.3 2016/12/09 05:17:03 christos Exp $	*/
+/*	$NetBSD: spkr.c,v 1.4 2016/12/13 20:20:34 christos Exp $	*/
 
 /*
  * Copyright (c) 1990 Eric S. Raymond (e...@snark.thyrsus.com)
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.3 2016/12/09 05:17:03 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.4 2016/12/13 20:20:34 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -82,9 +82,9 @@ const struct cdevsw spkr_cdevsw = {
 	.d_flag = D_OTHER
 };
 
-static void playinit(void);
-static void playtone(int, int, int);
-static void playstring(char *, int);
+static void playinit(struct spkr_softc *);
+static void playtone(struct spkr_softc *, int, int, int);
+static void playstring(struct spkr_softc *, const char *, size_t);
 
 /**************** PLAY STRING INTERPRETER BEGINS HERE **********************
  *
@@ -96,13 +96,6 @@ static void playstring(char *, int);
 
 #define dtoi(c)		((c) - '0')
 
-static int octave;	/* currently selected octave */
-static int whole;	/* whole-note time at current tempo, in ticks */
-static int value;	/* whole divisor for note time, quarter note = 1 */
-static int fill;	/* controls spacing of notes */
-static bool octtrack;	/* octave-tracking on? */
-static bool octprefix;	/* override current octave-tracking state? */
-
 /*
  * Magic number avoidance...
  */
@@ -144,221 +137,211 @@ static const int pitchtab[] =
 #define NOCTAVES (int)(__arraycount(pitchtab) / OCTAVE_NOTES)
 
 static void
-playinit(void)
+playinit(struct spkr_softc *sc)
 {
-    octave = DFLT_OCTAVE;
-    whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
-    fill = NORMAL;
-    value = DFLT_VALUE;
-    octtrack = false;
-    octprefix = true;	/* act as though there was an initial O(n) */
+	sc->sc_octave = DFLT_OCTAVE;
+	sc->sc_whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
+	sc->sc_fill = NORMAL;
+	sc->sc_value = DFLT_VALUE;
+	sc->sc_octtrack = false;
+	sc->sc_octprefix = true;/* act as though there was an initial O(n) */
 }
 
-static void
-playtone(int pitch, int val, int sustain)
 /* play tone of proper duration for current rhythm signature */
+static void
+playtone(struct spkr_softc *sc, int pitch, int val, int sustain)
 {
-    int	sound, silence, snum = 1, sdenom = 1;
+	int sound, silence, snum = 1, sdenom = 1;
 
-    /* this weirdness avoids floating-point arithmetic */
-    for (; sustain; sustain--)
-    {
-	snum *= NUM_MULT;
-	sdenom *= DENOM_MULT;
-    }
+	/* this weirdness avoids floating-point arithmetic */
+	for (; sustain; sustain--) {
+		snum *= NUM_MULT;
+		sdenom *= DENOM_MULT;
+	}
 
-    if (pitch == -1)
-	spkr_rest(whole * snum / (val * sdenom));
-    else
-    {
-	sound = (whole * snum) / (val * sdenom)
-		- (whole * (FILLTIME - fill)) / (val * FILLTIME);
-	silence = whole * (FILLTIME-fill) * snum / (FILLTIME * val * sdenom);
+	if (pitch == -1) {
+		(*sc->sc_rest)(sc->sc_dev, sc->sc_whole
+		    * snum / (val * sdenom));
+		return;
+	}
+
+	int fac = sc->sc_whole * (FILLTIME - sc->sc_fill);
+	int fval = FILLTIME * val;
+	sound = (sc->sc_whole * snum) / (val * sdenom) -  fac / fval;
+	silence = fac * snum / (fval * sdenom);
 
 #ifdef SPKRDEBUG
-	printf("playtone: pitch %d for %d ticks, rest for %d ticks\n",
+	aprint_debug_dev(sc->sc_dev,
+	    "%s: pitch %d for %d ticks, rest for %d ticks\n", __func__,
 	    pitch, sound, silence);
 #endif /* SPKRDEBUG */
 
-	spkr_tone(pitchtab[pitch], sound);
-	if (fill != LEGATO)
-	    spkr_rest(silence);
-    }
+	(*sc->sc_tone)(sc->sc_dev, pitchtab[pitch], sound);
+	if (sc->sc_fill != LEGATO)
+		(*sc->sc_rest)(sc->sc_dev, silence);
 }
 
-static void
-playstring(char *cp, int slen)
 /* interpret and play an item from a notation string */
+static void
+playstring(struct spkr_softc *sc, const char *cp, size_t slen)
 {
-    int		pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
+	int		pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
+
+#define GETNUM(cp, v)	\
+	for (v = 0; slen > 0 && isdigit((unsigned char)cp[1]); ) { \
+		v = v * 10 + (*++cp - '0'); \
+		slen--; \
+	}
 
-#define GETNUM(cp, v)	for(v=0; slen > 0 && isdigit(cp[1]); ) \
-				{v = v * 10 + (*++cp - '0'); slen--;}
-    for (; slen--; cp++)
-    {
-	int		sustain, timeval, tempo;
-	char	c = toupper(*cp);
+	for (; slen--; cp++) {
+		int sustain, timeval, tempo;
+		char c = toupper((unsigned char)*cp);
 
 #ifdef SPKRDEBUG
-	printf("playstring: %c (%x)\n", c, c);
+		aprint_debug_dev(sc->sc_dev, "%s: %c (%x)\n", __func__, c, c);
 #endif /* SPKRDEBUG */
 
-	switch (c)
-	{
-	case 'A':  case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
-
-	    /* compute pitch */
-	    pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES;
-
-	    /* this may be followed by an accidental sign */
-	    if (slen > 0 && (cp[1] == '#' || cp[1] == '+'))
-	    {
-		++pitch;
-		++cp;
-		slen--;
-	    }
-	    else if (slen > 0 && cp[1] == '-')
-	    {
-		--pitch;
-		++cp;
-		slen--;
-	    }
-
-	    /*
-	     * If octave-tracking mode is on, and there has been no octave-
-	     * setting prefix, find the version of the current letter note
-	     * closest to the last regardless of octave.
-	     */
-	    if (octtrack && !octprefix)
-	    {
-		if (abs(pitch-lastpitch) > abs(pitch+OCTAVE_NOTES-lastpitch))
-		{
-		    if (octave < NOCTAVES - 1) {
-			++octave;
-			pitch += OCTAVE_NOTES;
-		    }
-		}
+		switch (c) {
+		case 'A':  case 'B': case 'C': case 'D':
+		case 'E': case 'F': case 'G':
+			/* compute pitch */
+			pitch = notetab[c - 'A'] + sc->sc_octave * OCTAVE_NOTES;
+
+			/* this may be followed by an accidental sign */
+			if (slen > 0 && (cp[1] == '#' || cp[1] == '+')) {
+				++pitch;
+				++cp;
+				slen--;
+			} else if (slen > 0 && cp[1] == '-') {
+				--pitch;
+				++cp;
+				slen--;
+			}
+
+			/*
+			 * If octave-tracking mode is on, and there has been no
+			 * octave- setting prefix, find the version of the
+			 * current letter note * closest to the last
+			 * regardless of octave.
+			 */
+			if (sc->sc_octtrack && !sc->sc_octprefix) {
+				int d = abs(pitch - lastpitch);
+				if (d > abs(pitch + OCTAVE_NOTES - lastpitch)) {
+					if (sc->sc_octave < NOCTAVES - 1) {
+						++sc->sc_octave;
+						pitch += OCTAVE_NOTES;
+					}
+				}
+
+				if (d > abs(pitch - OCTAVE_NOTES - lastpitch)) {
+					if (sc->sc_octave > 0) {
+						--sc->sc_octave;
+						pitch -= OCTAVE_NOTES;
+					}
+				}
+			}
+			sc->sc_octprefix = false;
+			lastpitch = pitch;
+
+			/*
+			 * ...which may in turn be followed by an override
+			 * time value
+			 */
+			GETNUM(cp, timeval);
+			if (timeval <= 0 || timeval > MIN_VALUE)
+				timeval = sc->sc_value;
+
+			/* ...and/or sustain dots */
+			for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
+				slen--;
+				sustain++;
+			}
+
+			/* time to emit the actual tone */
+			playtone(sc, pitch, timeval, sustain);
+			break;
+
+		case 'O':
+			if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
+				sc->sc_octprefix = sc->sc_octtrack = false;
+				++cp;
+				slen--;
+			} else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
+				sc->sc_octtrack = true;
+				++cp;
+				slen--;
+			} else {
+				GETNUM(cp, sc->sc_octave);
+				if (sc->sc_octave >= NOCTAVES)
+					sc->sc_octave = DFLT_OCTAVE;
+				sc->sc_octprefix = true;
+			}
+			break;
+
+		case '>':
+			if (sc->sc_octave < NOCTAVES - 1)
+				sc->sc_octave++;
+			sc->sc_octprefix = true;
+			break;
+
+		case '<':
+			if (sc->sc_octave > 0)
+				sc->sc_octave--;
+			sc->sc_octprefix = true;
+			break;
+
+		case 'N':
+			GETNUM(cp, pitch);
+			for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
+				slen--;
+				sustain++;
+			}
+			playtone(sc, pitch - 1, sc->sc_value, sustain);
+			break;
+
+		case 'L':
+			GETNUM(cp, sc->sc_value);
+			if (sc->sc_value <= 0 || sc->sc_value > MIN_VALUE)
+				sc->sc_value = DFLT_VALUE;
+			break;
+
+		case 'P':
+		case '~':
+			/* this may be followed by an override time value */
+			GETNUM(cp, timeval);
+			if (timeval <= 0 || timeval > MIN_VALUE)
+				timeval = sc->sc_value;
+			for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
+				slen--;
+				sustain++;
+			}
+			playtone(sc, -1, timeval, sustain);
+			break;
 
-		if (abs(pitch-lastpitch) > abs((pitch-OCTAVE_NOTES)-lastpitch))
-		{
-		    if (octave > 0) {
-			--octave;
-			pitch -= OCTAVE_NOTES;
-		    }
+		case 'T':
+			GETNUM(cp, tempo);
+			if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
+				tempo = DFLT_TEMPO;
+			sc->sc_whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
+			break;
+
+		case 'M':
+			if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
+				sc->sc_fill = NORMAL;
+				++cp;
+				slen--;
+			} else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
+				sc->sc_fill = LEGATO;
+				++cp;
+				slen--;
+			} else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's')) {
+				sc->sc_fill = STACCATO;
+				++cp;
+				slen--;
+			}
+			break;
 		}
-	    }
-	    octprefix = false;
-	    lastpitch = pitch;
-
-	    /* ...which may in turn be followed by an override time value */
-	    GETNUM(cp, timeval);
-	    if (timeval <= 0 || timeval > MIN_VALUE)
-		timeval = value;
-
-	    /* ...and/or sustain dots */
-	    for (sustain = 0; slen > 0 && cp[1] == '.'; cp++)
-	    {
-		slen--;
-		sustain++;
-	    }
-
-	    /* time to emit the actual tone */
-	    playtone(pitch, timeval, sustain);
-	    break;
-
-	case 'O':
-	    if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n'))
-	    {
-		octprefix = octtrack = false;
-		++cp;
-		slen--;
-	    }
-	    else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l'))
-	    {
-		octtrack = true;
-		++cp;
-		slen--;
-	    }
-	    else
-	    {
-		GETNUM(cp, octave);
-		if (octave >= NOCTAVES)
-		    octave = DFLT_OCTAVE;
-		octprefix = true;
-	    }
-	    break;
-
-	case '>':
-	    if (octave < NOCTAVES - 1)
-		octave++;
-	    octprefix = true;
-	    break;
-
-	case '<':
-	    if (octave > 0)
-		octave--;
-	    octprefix = true;
-	    break;
-
-	case 'N':
-	    GETNUM(cp, pitch);
-	    for (sustain = 0; slen > 0 && cp[1] == '.'; cp++)
-	    {
-		slen--;
-		sustain++;
-	    }
-	    playtone(pitch - 1, value, sustain);
-	    break;
-
-	case 'L':
-	    GETNUM(cp, value);
-	    if (value <= 0 || value > MIN_VALUE)
-		value = DFLT_VALUE;
-	    break;
-
-	case 'P':
-	case '~':
-	    /* this may be followed by an override time value */
-	    GETNUM(cp, timeval);
-	    if (timeval <= 0 || timeval > MIN_VALUE)
-		timeval = value;
-	    for (sustain = 0; slen > 0 && cp[1] == '.'; cp++)
-	    {
-		slen--;
-		sustain++;
-	    }
-	    playtone(-1, timeval, sustain);
-	    break;
-
-	case 'T':
-	    GETNUM(cp, tempo);
-	    if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
-		tempo = DFLT_TEMPO;
-	    whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
-	    break;
-
-	case 'M':
-	    if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n'))
-	    {
-		fill = NORMAL;
-		++cp;
-		slen--;
-	    }
-	    else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l'))
-	    {
-		fill = LEGATO;
-		++cp;
-		slen--;
-	    }
-	    else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's'))
-	    {
-		fill = STACCATO;
-		++cp;
-		slen--;
-	    }
-	    break;
 	}
-    }
 }
 
 /******************* UNIX DRIVER HOOKS BEGIN HERE **************************
@@ -366,116 +349,125 @@ playstring(char *cp, int slen)
  * This section implements driver hooks to run playstring() and the spkr_tone()
  * and spkr_rest() functions defined above.
  */
+extern struct cfdriver spkr_cd;
+#define spkrenter(d)	device_lookup_private(&spkr_cd, d)
 
-static int spkr_active;	/* exclusion flag */
-int spkr_attached;
-static void *spkr_inbuf;
-
-int
-spkr_probe(device_t parent, cfdata_t match, void *aux)
+void
+spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int),
+    void (*rest)(device_t, int))
 {
-	return (!spkr_attached);
+	struct spkr_softc *sc = device_private(self);
+
+	sc->sc_dev = self;
+	sc->sc_tone = tone;
+	sc->sc_rest = rest;
+	sc->sc_inbuf = NULL;
 }
 
 int
 spkropen(dev_t dev, int	flags, int mode, struct lwp *l)
 {
 #ifdef SPKRDEBUG
-    printf("spkropen: entering with dev = %"PRIx64"\n", dev);
+	aprint_debug("%s: entering with dev = %"PRIx64"\n", __func__, dev);
 #endif /* SPKRDEBUG */
+	struct spkr_softc *sc = spkrenter(minor(dev));
 
-    if (minor(dev) != 0 || !spkr_attached)
-	return(ENXIO);
-    else if (spkr_active)
-	return(EBUSY);
-    else
-    {
-	playinit();
-	spkr_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK);
-	spkr_active = 1;
-    }
-    return(0);
+	if (sc == NULL)
+		return ENXIO;
+	if (sc->sc_inbuf)
+		return EBUSY;
+
+	sc->sc_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK);
+	playinit(sc);
+	return 0;
 }
 
 int
 spkrwrite(dev_t dev, struct uio *uio, int flags)
 {
-    int n;
-    int error;
 #ifdef SPKRDEBUG
-    printf("spkrwrite: entering with dev = %"PRIx64", count = %zu\n",
-		dev, uio->uio_resid);
+	aprint_debug("%s: entering with dev = %"PRIx64", count = %zu\n",
+	    __func__, dev, uio->uio_resid);
 #endif /* SPKRDEBUG */
+	struct spkr_softc *sc = spkrenter(minor(dev));
 
-    if (minor(dev) != 0)
-	return(ENXIO);
-    else
-    {
-	n = min(DEV_BSIZE, uio->uio_resid);
-	error = uiomove(spkr_inbuf, n, uio);
-	if (!error)
-		playstring((char *)spkr_inbuf, n);
-	return(error);
-    }
+	if (sc == NULL)
+		return ENXIO;
+	if (!sc->sc_inbuf)
+		return EINVAL;
+
+	size_t n = min(DEV_BSIZE, uio->uio_resid);
+	int error = uiomove(sc->sc_inbuf, n, uio);
+	if (error)
+		return error;
+	playstring(sc, sc->sc_inbuf, n);
+	return 0;
 }
 
 int
 spkrclose(dev_t dev, int flags, int mode, struct lwp *l)
 {
 #ifdef SPKRDEBUG
-    printf("spkrclose: entering with dev = %"PRIx64"\n", dev);
+	aprint_debug("%s: entering with dev = %"PRIx64"\n", __func__, dev);
 #endif /* SPKRDEBUG */
+	struct spkr_softc *sc = spkrenter(minor(dev));
+
+	if (sc == NULL)
+		return ENXIO;
+	if (!sc->sc_inbuf)
+		return EINVAL;
+
+	sc->sc_tone(sc->sc_dev, 0, 0);
+	free(sc->sc_inbuf, M_DEVBUF);
+	sc->sc_inbuf = NULL;
 
-    if (minor(dev) != 0)
-	return(ENXIO);
+	return 0;
+}
+
+static void
+playonetone(struct spkr_softc *sc, tone_t *tp)
+{
+    if (tp->frequency == 0)
+	    (*sc->sc_rest)(sc->sc_dev, tp->duration);
     else
-    {
-	spkr_tone(0, 0);
-	free(spkr_inbuf, M_DEVBUF);
-	spkr_active = 0;
-    }
-    return(0);
+	    (*sc->sc_tone)(sc->sc_dev, tp->frequency, tp->duration);
 }
 
 int
 spkrioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
 {
+	tone_t *tp;
+	tone_t ttp;
+	int error;
 #ifdef SPKRDEBUG
-    printf("spkrioctl: entering with dev = %"PRIx64", cmd = %lx\n", dev, cmd);
+	aprint_debug("%s: entering with dev = %"PRIx64", cmd = %lx\n",
+	    __func__, dev, cmd);
 #endif /* SPKRDEBUG */
 
-    if (minor(dev) != 0)
-	return(ENXIO);
-    else if (cmd == SPKRTONE)
-    {
-	tone_t	*tp = (tone_t *)data;
-
-	if (tp->frequency == 0)
-	    spkr_rest(tp->duration);
-	else
-	    spkr_tone(tp->frequency, tp->duration);
-    }
-    else if (cmd == SPKRTUNE)
-    {
-	tone_t  *tp = (tone_t *)(*(void **)data);
-	tone_t ttp;
-	int error;
+	struct spkr_softc *sc = spkrenter(minor(dev));
 
-	for (; ; tp++) {
-	    error = copyin(tp, &ttp, sizeof(tone_t));
-	    if (error)
-		    return(error);
-	    if (ttp.duration == 0)
-		    break;
-	    if (ttp.frequency == 0)
-		spkr_rest(ttp.duration);
-	    else
-		spkr_tone(ttp.frequency, ttp.duration);
+	if (sc == NULL)
+		return ENXIO;
+	if (!sc->sc_inbuf)
+		return EINVAL;
+
+	switch (cmd) {
+    	case SPKRTONE:
+		playonetone(sc, data);
+		return 0;
+	case SPKRTUNE:
+		for (tp = *(void **)data;; tp++) {
+			error = copyin(tp, &ttp, sizeof(tone_t));
+			if (error)
+				return(error);
+			if (ttp.duration == 0)
+				break;
+			playonetone(sc, &ttp);
+		}
+		return 0;
+	default:
+		return ENOTTY;
 	}
-    }
-    else
-	return(EINVAL);
-    return(0);
 }
 
 #ifdef _MODULE
@@ -506,12 +498,13 @@ spkr__modcmd(modcmd_t cmd, void *arg)
 		break;
 
 	case MODULE_CMD_FINI:
-		if (spkr_active)
-			return EBUSY;
+		return EBUSY;
+#ifdef notyet
 		error = config_fini_component(cfdriver_ioconf_spkr,
 			cfattach_ioconf_spkr, cfdata_ioconf_spkr);
 		devsw_detach(NULL, &spkr_cdevsw);
 		break;
+#endif
 	default:
 		error = ENOTTY;
 		break;
Index: src/sys/dev/spkrvar.h
diff -u src/sys/dev/spkrvar.h:1.3 src/sys/dev/spkrvar.h:1.4
--- src/sys/dev/spkrvar.h:1.3	Fri Dec  9 00:45:20 2016
+++ src/sys/dev/spkrvar.h	Tue Dec 13 15:20:34 2016
@@ -1,18 +1,27 @@
-/* $NetBSD: spkrvar.h,v 1.3 2016/12/09 05:45:20 christos Exp $ */
+/* $NetBSD: spkrvar.h,v 1.4 2016/12/13 20:20:34 christos Exp $ */
 
 #ifndef _SYS_DEV_SPKRVAR_H
 #define _SYS_DEV_SPKRVAR_H
 
 #include <sys/module.h>
 
-device_t speakerattach_mi(device_t);
-void speaker_play(u_int, u_int, u_int);
+struct spkr_softc {
+	device_t sc_dev;
+	int sc_octave;	/* currently selected octave */
+	int sc_whole;	/* whole-note time at current tempo, in ticks */
+	int sc_value;	/* whole divisor for note time, quarter note = 1 */
+	int sc_fill;	/* controls spacing of notes */
+	bool sc_octtrack;	/* octave-tracking on? */
+	bool sc_octprefix;	/* override current octave-tracking state? */
+	char *sc_inbuf;
+
+	/* attachment-specific hooks */
+	void (*sc_tone)(device_t, u_int, u_int);
+	void (*sc_rest)(device_t, int);
+};
 
-// XXX:
-void spkr_tone(u_int, u_int);
-void spkr_rest(int);
 int spkr__modcmd(modcmd_t, void *);
-int spkr_probe(device_t, cfdata_t, void *);
-extern int spkr_attached;
+void spkr_attach(device_t,
+    void (*)(device_t, u_int, u_int), void (*)(device_t, int));
 
 #endif /* _SYS_DEV_SPKRVAR_H */

Index: src/sys/dev/spkr_synth.c
diff -u src/sys/dev/spkr_synth.c:1.6 src/sys/dev/spkr_synth.c:1.7
--- src/sys/dev/spkr_synth.c:1.6	Mon Dec 12 05:46:39 2016
+++ src/sys/dev/spkr_synth.c	Tue Dec 13 15:20:34 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: spkr_synth.c,v 1.6 2016/12/12 10:46:39 joerg Exp $	*/
+/*	$NetBSD: spkr_synth.c,v 1.7 2016/12/13 20:20:34 christos Exp $	*/
 
 /*-
  * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spkr_synth.c,v 1.6 2016/12/12 10:46:39 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spkr_synth.c,v 1.7 2016/12/13 20:20:34 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -48,7 +48,6 @@ __KERNEL_RCSID(0, "$NetBSD: spkr_synth.c
 #include <dev/audiovar.h>
 
 struct vbell_args {
-	device_t *cookie;
 	u_int pitch;
 	u_int period;
 	u_int volume;
@@ -56,18 +55,27 @@ struct vbell_args {
 };
 
 static void bell_thread(void *) __dead;
-static int beep_sysctl_device(SYSCTLFN_PROTO);
 
 #include <dev/audiobellvar.h>
 
 #include <dev/spkrvar.h>
 #include <dev/spkrio.h>
 
-static void spkrattach(device_t, device_t, void *);
-static int spkrdetach(device_t, int);
-device_t speakerattach_mi(device_t);
+static int spkr_synth_probe(device_t, cfdata_t, void *);
+static void spkr_synth_attach(device_t, device_t, void *);
+static int spkr_synth_detach(device_t, int);
+
+struct spkr_synth_softc {
+	struct spkr_softc sc_spkr;
+	lwp_t		*sc_bellthread;
+	kmutex_t	sc_bellock;
+	kcondvar_t	sc_bellcv;
+	device_t		sc_audiodev;
+	struct vbell_args sc_bell_args;
+};
 
-#include "ioconf.h"
+CFATTACH_DECL_NEW(spkr_synth, sizeof(struct spkr_synth_softc),
+    spkr_synth_probe, spkr_synth_attach, spkr_synth_detach, NULL);
 
 MODULE(MODULE_CLASS_DRIVER, spkr, NULL /* "audio" */);
 
@@ -77,173 +85,116 @@ spkr_modcmd(modcmd_t cmd, void *arg)
 	return spkr__modcmd(cmd, arg);
 }
 
-CFATTACH_DECL3_NEW(spkr_synth, 0,
-    spkr_probe, spkrattach, spkrdetach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
-
-extern struct cfdriver audio_cd;
-
-static struct sysctllog	*spkr_sc_log;	/* sysctl log */
-static int beep_unit = 0;
-
-struct vbell_args sc_bell_args;
-lwp_t		*sc_bellthread;
-kmutex_t	sc_bellock;
-kcondvar_t	sc_bellcv;
-
-struct spkr_attach_args {
-	device_t dev;
-};
-
-void
-spkr_tone(u_int xhz, u_int ticks)
+static void
+spkr_synth_tone(device_t self, u_int xhz, u_int ticks)
 {
-	audiobell(&beep_unit, xhz, ticks * (1000 / hz), 80, 0);
+	struct spkr_synth_softc *sc = device_private(self);
+
+#ifdef SPKRDEBUG
+	aprint_debug_dev(self, "%s: %u %d\n", __func__, xhz, ticks);
+#endif /* SPKRDEBUG */
+	audiobell(sc->sc_audiodev, xhz, ticks * (1000 / hz), 80, 0);
 }
 
-void
-spkr_rest(int ticks)
+static void
+spkr_synth_rest(device_t self, int ticks)
 {
+	struct spkr_synth_softc *sc = device_private(self);
+	
 #ifdef SPKRDEBUG
-    printf("%s: %d\n", __func__, ticks);
+	aprint_debug_dev(self, "%s: %d\n", __func__, ticks);
 #endif /* SPKRDEBUG */
-    if (ticks > 0)
-	audiobell(&beep_unit, 0, ticks * (1000 / hz), 80, 0);
+	if (ticks > 0)
+		audiobell(sc->sc_audiodev, 0, ticks * (1000 / hz), 80, 0);
+}
+
+#ifdef notyet
+static void
+spkr_synth_play(device_t self, u_int pitch, u_int period, u_int volume)
+{
+	struct spkr_synth_softc *sc = device_private(self);
+
+	mutex_enter(&sc->sc_bellock);
+	sc->sc_bell_args.dying = false;
+	sc->sc_bell_args.pitch = pitch;
+	sc->sc_bell_args.period = period;
+	sc->sc_bell_args.volume = volume;
+
+	cv_broadcast(&sc->sc_bellcv);
+	mutex_exit(&sc->sc_bellock);
 }
+#endif
 
-device_t
-speakerattach_mi(device_t dev)
+static int
+spkr_synth_probe(device_t parent, cfdata_t cf, void *aux)
 {
-	struct spkr_attach_args sa;
-	sa.dev = dev;
-	return config_found(dev, &sa, NULL);
+
+	return 1;
 }
 
 static void
-spkrattach(device_t parent, device_t self, void *aux)
+spkr_synth_attach(device_t parent, device_t self, void *aux)
 {
-	const struct sysctlnode *node;
+	struct spkr_synth_softc *sc = device_private(self);
+
+	aprint_normal("\n");
 
-	printf("\n");
-	beep_unit = 0;
-	spkr_attached = 1;
+	sc->sc_audiodev = parent;
 	
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n"); 
-	mutex_init(&sc_bellock, MUTEX_DEFAULT, IPL_SCHED);
-	cv_init(&sc_bellcv, "bellcv");
-
-	/* sysctl set-up for default audio device */
-	sysctl_createv(&spkr_sc_log, 0, NULL, &node,
-		0,
-		CTLTYPE_NODE, "beep",
-		SYSCTL_DESCR("synthesized beeper information"),
-		NULL, 0,
-		NULL, 0,
-		CTL_HW,
-		CTL_CREATE, CTL_EOL);
-
-	if (node != NULL) {
-		sysctl_createv(&spkr_sc_log, 0, NULL, NULL,
-			CTLFLAG_READWRITE,
-			CTLTYPE_INT, "device",
-			SYSCTL_DESCR("default device"),
-			beep_sysctl_device, 0,
-			NULL, 0,
-			CTL_HW, node->sysctl_num,
-			CTL_CREATE, CTL_EOL);
-	}
+	mutex_init(&sc->sc_bellock, MUTEX_DEFAULT, IPL_SCHED);
+	cv_init(&sc->sc_bellcv, "bellcv");
 
 	kthread_create(PRI_BIO, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
-	    bell_thread, &sc_bell_args, &sc_bellthread, "vbell");
+	    bell_thread, sc, &sc->sc_bellthread, device_xname(self));
+
+	spkr_attach(self, spkr_synth_tone, spkr_synth_rest);
 }
 
 static int
-spkrdetach(device_t self, int flags)
+spkr_synth_detach(device_t self, int flags)
 {
+	struct spkr_synth_softc *sc = device_private(self);
 
 	pmf_device_deregister(self);
 
-	mutex_enter(&sc_bellock);
-	sc_bell_args.dying = true;
+	mutex_enter(&sc->sc_bellock);
+	sc->sc_bell_args.dying = true;
 
-	cv_broadcast(&sc_bellcv);
-	mutex_exit(&sc_bellock);
+	cv_broadcast(&sc->sc_bellcv);
+	mutex_exit(&sc->sc_bellock);
 
-	kthread_join(sc_bellthread);
-	cv_destroy(&sc_bellcv);
-	mutex_destroy(&sc_bellock);
+	kthread_join(sc->sc_bellthread);
+	cv_destroy(&sc->sc_bellcv);
+	mutex_destroy(&sc->sc_bellock);
 
-	/* delete sysctl nodes */
-	sysctl_teardown(&spkr_sc_log);
-
-	spkr_attached = 0;
 
 	return 0;
 }
 
-void
+static void
 bell_thread(void *arg)
 {
-	struct vbell_args *vb = arg;
+	struct spkr_synth_softc *sc = arg;
+	struct vbell_args *vb = &sc->sc_bell_args;
 	u_int bpitch;
 	u_int bperiod;
 	u_int bvolume;
 	
 	for (;;) {
-		mutex_enter(&sc_bellock);
-		cv_wait_sig(&sc_bellcv, &sc_bellock);
+		mutex_enter(&sc->sc_bellock);
+		cv_wait_sig(&sc->sc_bellcv, &sc->sc_bellock);
 		
 		if (vb->dying == true) {
-			mutex_exit(&sc_bellock);
+			mutex_exit(&sc->sc_bellock);
 			kthread_exit(0);
 		}
 		
 		bpitch = vb->pitch;
 		bperiod = vb->period;
 		bvolume = vb->volume;
-		mutex_exit(&sc_bellock);
-		audiobell(&beep_unit, bpitch, bperiod, bvolume, 0);
+		mutex_exit(&sc->sc_bellock);
+		audiobell(sc->sc_audiodev, bpitch, bperiod, bvolume, 0);
 	}
 }
-
-void
-speaker_play(u_int pitch, u_int period, u_int volume)
-{
-	if (spkr_attached == 0 || beep_unit == -1)
-		return;
-
-	mutex_enter(&sc_bellock);
-	sc_bell_args.dying = false;
-	sc_bell_args.pitch = pitch;
-	sc_bell_args.period = period;
-	sc_bell_args.volume = volume;
-
-	cv_broadcast(&sc_bellcv);
-	mutex_exit(&sc_bellock);
-}
-
-/* sysctl helper to set common audio channels */
-static int
-beep_sysctl_device(SYSCTLFN_ARGS)
-{
-	struct sysctlnode node;
-	struct audio_softc *ac;
-	int t, error;
-
-	node = *rnode;
-
-	t = beep_unit;
-	node.sysctl_data = &t;
-	error = sysctl_lookup(SYSCTLFN_CALL(&node));
-	if (error || newp == NULL)
-		return error;
-
-	
-	if (t < -1 || (t != -1 && (ac = device_lookup_private(&audio_cd, t)) ==
-	    NULL))
-		return EINVAL;
-
-	beep_unit = t;
-
-	return error;
-}

Index: src/sys/dev/isa/spkr_pcppi.c
diff -u src/sys/dev/isa/spkr_pcppi.c:1.4 src/sys/dev/isa/spkr_pcppi.c:1.5
--- src/sys/dev/isa/spkr_pcppi.c:1.4	Fri Dec  9 00:17:03 2016
+++ src/sys/dev/isa/spkr_pcppi.c	Tue Dec 13 15:20:34 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: spkr_pcppi.c,v 1.4 2016/12/09 05:17:03 christos Exp $	*/
+/*	$NetBSD: spkr_pcppi.c,v 1.5 2016/12/13 20:20:34 christos Exp $	*/
 
 /*
  * Copyright (c) 1990 Eric S. Raymond (e...@snark.thyrsus.com)
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c,v 1.4 2016/12/09 05:17:03 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c,v 1.5 2016/12/13 20:20:34 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -64,11 +64,18 @@ __KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c
 #include <dev/spkrvar.h>
 #include <dev/spkrio.h>
 
-extern int spkr_attached;
-static void spkrattach(device_t, device_t, void *);
-static int spkrdetach(device_t, int);
+struct spkr_pcppi_softc {
+	device_t sc_dev;
+	device_t sc_spkr_dev;
+	pcppi_tag_t sc_pcppicookie;
+};
+
+static int spkr_pcppi_probe(device_t, cfdata_t, void *);
+static void spkr_pcppi_attach(device_t, device_t, void *);
+static int spkr_pcppi_detach(device_t, int);
 
-#include "ioconf.h"
+CFATTACH_DECL_NEW(spkr_pcppi, sizeof(struct spkr_pcppi_softc),
+    spkr_pcppi_probe, spkr_pcppi_attach, spkr_pcppi_detach, NULL);
 
 MODULE(MODULE_CLASS_DRIVER, spkr, NULL /* "pcppi" */);
 
@@ -78,53 +85,62 @@ spkr_modcmd(modcmd_t cmd, void *arg)
 	return spkr__modcmd(cmd, arg);
 }
 
-CFATTACH_DECL_NEW(spkr_pcppi, 0, spkr_probe, spkrattach, spkrdetach, NULL);
-
-static pcppi_tag_t ppicookie;
-
 #define SPKRPRI (PZERO - 1)
 
-void
-spkr_tone(u_int xhz, u_int ticks)
 /* emit tone of frequency hz for given number of ticks */
+static void
+spkr_pcppi_tone(device_t self, u_int xhz, u_int ticks)
 {
-	pcppi_bell(ppicookie, xhz, ticks, PCPPI_BELL_SLEEP);
+#ifdef SPKRDEBUG
+	aprint_debug_dev(self, "%s: %u %u\n", __func__, xhz, ticks);
+#endif /* SPKRDEBUG */
+	struct spkr_pcppi_softc *sc = device_private(self);
+	pcppi_bell(sc->sc_pcppicookie, xhz, ticks, PCPPI_BELL_SLEEP);
 }
 
-void
-spkr_rest(int ticks)
 /* rest for given number of ticks */
+static void
+spkr_pcppi_rest(device_t self, int ticks)
 {
-    /*
-     * Set timeout to endrest function, then give up the timeslice.
-     * This is so other processes can execute while the rest is being
-     * waited out.
-     */
+	/*
+	 * Set timeout to endrest function, then give up the timeslice.
+	 * This is so other processes can execute while the rest is being
+	 * waited out.
+	 */
 #ifdef SPKRDEBUG
-    printf("%s: %d\n", __func__, ticks);
+	aprint_debug_dev(self, "%s: %d\n", __func__, ticks);
 #endif /* SPKRDEBUG */
-    if (ticks > 0)
-	    tsleep(spkr_rest, SPKRPRI | PCATCH, "rest", ticks);
+	if (ticks > 0)
+		tsleep(self, SPKRPRI | PCATCH, device_xname(self), ticks);
+}
+
+static int
+spkr_pcppi_probe(device_t parent, cfdata_t cf, void *aux)
+{
+	return 1;
 }
 
 static void
-spkrattach(device_t parent, device_t self, void *aux)
+spkr_pcppi_attach(device_t parent, device_t self, void *aux)
 {
+	struct pcppi_attach_args *pa = aux;
+	struct spkr_pcppi_softc *sc = device_private(self);
+
 	aprint_naive("\n");
 	aprint_normal("\n");
-	ppicookie = ((struct pcppi_attach_args *)aux)->pa_cookie;
-	spkr_attached = 1;
+
+	sc->sc_pcppicookie = pa->pa_cookie;
+	spkr_attach(self, spkr_pcppi_tone, spkr_pcppi_rest);
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 }
 
 static int
-spkrdetach(device_t self, int flags)
+spkr_pcppi_detach(device_t self, int flags)
 {
+	struct spkr_pcppi_softc *sc = device_private(self);
 
+	sc->sc_pcppicookie = NULL;
 	pmf_device_deregister(self);
-	spkr_attached = 0;
-	ppicookie = NULL;
-
 	return 0;
 }

Reply via email to