From: Miod Vallat Subject: modernize spkr(4) To: tech@openbsd.org Date: Wed, 4 Nov 2026 10:55:58 +0000 spkr(4), being a single-instance driver, uses a bunch of global variables to store its state. The following diff moves these variables to the device softc, so that they don't need to be globals anymore. Before: text data bss dec hex 3916 96 53 4065 fe1 After: text data bss dec hex 3836 96 1 3933 f5d Index: sys/dev/isa/spkr.c =================================================================== RCS file: /OpenBSD/src/sys/dev/isa/spkr.c,v diff -u -p -r1.27 spkr.c --- sys/dev/isa/spkr.c 6 Apr 2022 18:59:29 -0000 1.27 +++ sys/dev/isa/spkr.c 4 Nov 2026 10:52:56 -0000 @@ -63,29 +63,41 @@ cdev_decl(spkr); int spkrprobe(struct device *, void *, void *); void spkrattach(struct device *, struct device *, void *); +struct spkr_softc { + struct device sc_dev; + pcppi_tag_t sc_ppicookie; + int sc_open; /* exclusion flag */ + char *sc_inbuf; + + int octave; /* currently selected octave */ + int whole; /* whole-note time at current tempo, in milliseconds */ + int value; /* whole divisor for note time, quarter note = 1 */ + int fill; /* controls spacing of notes */ + int octtrack; /* octave-tracking on? */ + int octprefix; /* override current octave-tracking state? */ +}; + const struct cfattach spkr_ca = { - sizeof(struct device), spkrprobe, spkrattach + sizeof(struct spkr_softc), spkrprobe, spkrattach }; struct cfdriver spkr_cd = { NULL, "spkr", DV_DULL }; -static pcppi_tag_t ppicookie; - #define SPKRPRI (PZERO - 1) -static void tone(u_int, u_int); +static void tone(struct spkr_softc*, u_int, u_int); static void rest(int); -static void playinit(void); -static void playtone(int, int, int); -static void playstring(char *, size_t); +static void playinit(struct spkr_softc *); +static void playtone(struct spkr_softc *, int, int, int); +static void playstring(struct spkr_softc *, char *, size_t); /* emit tone of frequency freq for given number of milliseconds */ static void -tone(u_int freq, u_int ms) +tone(struct spkr_softc* sc, u_int freq, u_int ms) { - pcppi_bell(ppicookie, freq, ms, PCPPI_BELL_SLEEP); + pcppi_bell(sc->sc_ppicookie, freq, ms, PCPPI_BELL_SLEEP); } /* rest for given number of milliseconds */ @@ -114,14 +126,6 @@ rest(int ms) #define toupper(c) ((c) - ' ' * (((c) >= 'a') && ((c) <= 'z'))) #define isdigit(c) (((c) >= '0') && ((c) <= '9')) -#define dtoi(c) ((c) - '0') - -static int octave; /* currently selected octave */ -static int whole; /* whole-note time at current tempo, in milliseconds */ -static int value; /* whole divisor for note time, quarter note = 1 */ -static int fill; /* controls spacing of notes */ -static int octtrack; /* octave-tracking on? */ -static int octprefix; /* override current octave-tracking state? */ /* * Magic number avoidance... @@ -142,7 +146,7 @@ static int octprefix; /* override curren #define DENOM_MULT 2 /* denominator of dot multiplier */ /* letter to half-tone: A B C D E F G */ -static int notetab[8] = { 9, 11, 0, 2, 4, 5, 7 }; +static const int notetab[8] = { 9, 11, 0, 2, 4, 5, 7 }; /* * This is the American Standard A440 Equal-Tempered scale with frequencies @@ -150,7 +154,7 @@ static int notetab[8] = { 9, 11, 0, 2, 4 * our octave 0 is standard octave 2. */ #define OCTAVE_NOTES 12 /* semitones per octave */ -static int pitchtab[] = +static const int pitchtab[] = { /* C C# D D# E F F# G G# A A# B*/ /* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123, @@ -164,19 +168,19 @@ static int pitchtab[] = #define NOCTAVES (sizeof(pitchtab) / sizeof(pitchtab[0]) / OCTAVE_NOTES) static void -playinit(void) +playinit(struct spkr_softc *sc) { - octave = DFLT_OCTAVE; - whole = (1000 * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO; - fill = NORMAL; - value = DFLT_VALUE; - octtrack = 0; - octprefix = 1; /* act as though there was an initial O(n) */ + sc->octave = DFLT_OCTAVE; + sc->whole = (1000 * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO; + sc->fill = NORMAL; + sc->value = DFLT_VALUE; + sc->octtrack = 0; + sc->octprefix = 1; /* act as though there was an initial O(n) */ } /* play tone of proper duration for current rhythm signature */ static void -playtone(int pitch, int value, int sustain) +playtone(struct spkr_softc *sc, int pitch, int value, int sustain) { int sound, silence, snum = 1, sdenom = 1; @@ -187,12 +191,12 @@ playtone(int pitch, int value, int susta } if (pitch == -1) - rest(whole * snum / (value * sdenom)); + rest(sc->whole * snum / (value * sdenom)); else if (pitch >= 0 && pitch < (sizeof(pitchtab) / sizeof(pitchtab[0]))) { - sound = (whole * snum) / (value * sdenom) - - (whole * (FILLTIME - fill)) / (value * FILLTIME); - silence = whole * (FILLTIME-fill) * snum / + sound = (sc->whole * snum) / (value * sdenom) - + (sc->whole * (FILLTIME - sc->fill)) / (value * FILLTIME); + silence = sc->whole * (FILLTIME-sc->fill) * snum / (FILLTIME * value * sdenom); #ifdef SPKRDEBUG @@ -200,15 +204,15 @@ playtone(int pitch, int value, int susta pitch, sound, silence); #endif /* SPKRDEBUG */ - tone(pitchtab[pitch], sound); - if (fill != LEGATO) + tone(sc, pitchtab[pitch], sound); + if (sc->fill != LEGATO) rest(silence); } } /* interpret and play an item from a notation string */ static void -playstring(char *cp, size_t slen) +playstring(struct spkr_softc *sc, char *cp, size_t slen) { int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; @@ -237,7 +241,7 @@ do { \ case 'F': case 'G': /* compute pitch */ - pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES; + pitch = notetab[c - 'A'] + sc->octave * OCTAVE_NOTES; /* this may be followed by an accidental sign */ if (slen > 0 && (cp[1] == '#' || cp[1] == '+')) { @@ -256,20 +260,20 @@ do { \ * current letter note closest to the last regardless * of octave. */ - if (octtrack && !octprefix) { + if (sc->octtrack != 0 && sc->octprefix == 0) { if (abs(pitch - lastpitch) > abs(pitch + OCTAVE_NOTES - lastpitch)) { - ++octave; + ++(sc->octave); pitch += OCTAVE_NOTES; } if (abs(pitch - lastpitch) > abs(pitch - OCTAVE_NOTES - lastpitch)) { - --octave; + --(sc->octave); pitch -= OCTAVE_NOTES; } } - octprefix = 0; + sc->octprefix = 0; lastpitch = pitch; /* @@ -278,7 +282,7 @@ do { \ */ GETNUM(cp, timeval); if (timeval <= 0 || timeval > MIN_VALUE) - timeval = value; + timeval = sc->value; /* ...and/or sustain dots */ for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { @@ -287,36 +291,36 @@ do { \ } /* time to emit the actual tone */ - playtone(pitch, timeval, sustain); + playtone(sc, pitch, timeval, sustain); break; case 'O': if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { - octprefix = octtrack = 0; + sc->octprefix = sc->octtrack = 0; ++cp; slen--; } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { - octtrack = 1; + sc->octtrack = 1; ++cp; slen--; } else { - GETNUM(cp, octave); - if (octave >= NOCTAVES) - octave = DFLT_OCTAVE; - octprefix = 1; + GETNUM(cp, sc->octave); + if (sc->octave >= NOCTAVES) + sc->octave = DFLT_OCTAVE; + sc->octprefix = 1; } break; case '>': - if (octave < NOCTAVES - 1) - octave++; - octprefix = 1; + if (sc->octave < NOCTAVES - 1) + sc->octave++; + sc->octprefix = 1; break; case '<': - if (octave > 0) - octave--; - octprefix = 1; + if (sc->octave > 0) + sc->octave--; + sc->octprefix = 1; break; case 'N': @@ -325,13 +329,13 @@ do { \ slen--; sustain++; } - playtone(pitch - 1, value, sustain); + playtone(sc, pitch - 1, sc->value, sustain); break; case 'L': - GETNUM(cp, value); - if (value <= 0 || value > MIN_VALUE) - value = DFLT_VALUE; + GETNUM(cp, sc->value); + if (sc->value <= 0 || sc->value > MIN_VALUE) + sc->value = DFLT_VALUE; break; case 'P': @@ -339,32 +343,32 @@ do { \ /* this may be followed by an override time value */ GETNUM(cp, timeval); if (timeval <= 0 || timeval > MIN_VALUE) - timeval = value; + timeval = sc->value; for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) { slen--; sustain++; } - playtone(-1, timeval, sustain); + playtone(sc, -1, timeval, sustain); break; case 'T': GETNUM(cp, tempo); if (tempo < MIN_TEMPO || tempo > MAX_TEMPO) tempo = DFLT_TEMPO; - whole = (1000 * SECS_PER_MIN * WHOLE_NOTE) / tempo; + sc->whole = (1000 * SECS_PER_MIN * WHOLE_NOTE) / tempo; break; case 'M': if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) { - fill = NORMAL; + sc->fill = NORMAL; ++cp; slen--; } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) { - fill = LEGATO; + sc->fill = LEGATO; ++cp; slen--; } else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's')) { - fill = STACCATO; + sc->fill = STACCATO; ++cp; slen--; } @@ -379,9 +383,6 @@ do { \ * endtone(), and rest() functions defined above. */ -static int spkr_active; /* exclusion flag */ -static void *spkr_inbuf; - static int spkr_attached = 0; int @@ -393,26 +394,36 @@ spkrprobe(struct device *parent, void *m void spkrattach(struct device *parent, struct device *self, void *aux) { + struct spkr_softc *sc = (struct spkr_softc *)self; + struct pcppi_attach_args *paa = (struct pcppi_attach_args *)aux; + printf("\n"); - ppicookie = ((struct pcppi_attach_args *)aux)->pa_cookie; + sc->sc_ppicookie = paa->pa_cookie; spkr_attached = 1; } int spkropen(dev_t dev, int flags, int mode, struct proc *p) { + struct spkr_softc *sc; + int unit = minor(dev); + + if (unit >= spkr_cd.cd_ndevs) + return (ENXIO); + sc = (struct spkr_softc *)spkr_cd.cd_devs[unit]; + if (sc == NULL) + return (ENXIO); + #ifdef SPKRDEBUG printf("spkropen: entering with dev = %x\n", dev); #endif /* SPKRDEBUG */ - if (minor(dev) != 0 || !spkr_attached) - return (ENXIO); - else if (spkr_active) + if (sc->sc_open != 0) return (EBUSY); else { - playinit(); - spkr_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK); - spkr_active = 1; + playinit(sc); + sc->sc_inbuf = (char *)malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK); + sc->sc_open = 1; } return (0); } @@ -420,44 +431,43 @@ spkropen(dev_t dev, int flags, int mode, int spkrwrite(dev_t dev, struct uio *uio, int flags) { + struct spkr_softc *sc; size_t n; int error; + #ifdef SPKRDEBUG printf("spkrwrite: entering with dev = %x, count = %zu\n", dev, uio->uio_resid); #endif /* SPKRDEBUG */ - if (minor(dev) != 0) - return (ENXIO); - else { - n = ulmin(DEV_BSIZE, uio->uio_resid); - error = uiomove(spkr_inbuf, n, uio); - if (!error) - playstring((char *)spkr_inbuf, n); - return (error); - } + sc = (struct spkr_softc *)spkr_cd.cd_devs[minor(dev)]; + n = ulmin(DEV_BSIZE, uio->uio_resid); + error = uiomove(sc->sc_inbuf, n, uio); + if (!error) + playstring(sc, sc->sc_inbuf, n); + return (error); } int spkrclose(dev_t dev, int flags, int mode, struct proc *p) { + struct spkr_softc *sc; + #ifdef SPKRDEBUG printf("spkrclose: entering with dev = %x\n", dev); #endif /* SPKRDEBUG */ - if (minor(dev) != 0) - return (ENXIO); - else { - tone(0, 0); - free(spkr_inbuf, M_DEVBUF, DEV_BSIZE); - spkr_active = 0; - } + sc = (struct spkr_softc *)spkr_cd.cd_devs[minor(dev)]; + tone(sc, 0, 0); + free(sc->sc_inbuf, M_DEVBUF, DEV_BSIZE); + sc->sc_open = 0; return (0); } int spkrioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { + struct spkr_softc *sc; tone_t *tp, ttp; int error; @@ -465,8 +475,7 @@ spkrioctl(dev_t dev, u_long cmd, caddr_t printf("spkrioctl: entering with dev = %x, cmd = %lx\n", dev, cmd); #endif /* SPKRDEBUG */ - if (minor(dev) != 0) - return (ENXIO); + sc = (struct spkr_softc *)spkr_cd.cd_devs[minor(dev)]; switch (cmd) { case SPKRTONE: @@ -486,7 +495,7 @@ spkrioctl(dev_t dev, u_long cmd, caddr_t if (tp->frequency == 0) rest(tp->duration); else - tone(tp->frequency, tp->duration); + tone(sc, tp->frequency, tp->duration); break; case SPKRTUNE: tp = (tone_t *)(*(caddr_t *)data); @@ -502,7 +511,7 @@ spkrioctl(dev_t dev, u_long cmd, caddr_t if (ttp.frequency == 0) rest(ttp.duration); else - tone(ttp.frequency, ttp.duration); + tone(sc, ttp.frequency, ttp.duration); } break; default: