This source file includes following definitions.
- tone
- rest
- playinit
- playtone
- playstring
- spkrprobe
- spkrattach
- spkropen
- spkrwrite
- spkrclose
- spkrioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/errno.h>
50 #include <sys/device.h>
51 #include <sys/malloc.h>
52 #include <sys/uio.h>
53 #include <sys/proc.h>
54 #include <sys/ioctl.h>
55 #include <sys/conf.h>
56
57 #include <dev/isa/pcppivar.h>
58
59 #include <dev/isa/spkrio.h>
60
61 cdev_decl(spkr);
62
63 int spkrprobe(struct device *, void *, void *);
64 void spkrattach(struct device *, struct device *, void *);
65
66 struct cfattach spkr_ca = {
67 sizeof(struct device), spkrprobe, spkrattach
68 };
69
70 struct cfdriver spkr_cd = {
71 NULL, "spkr", DV_DULL
72 };
73
74 static pcppi_tag_t ppicookie;
75
76 #define SPKRPRI (PZERO - 1)
77
78 static void tone(u_int, u_int);
79 static void rest(int);
80 static void playinit(void);
81 static void playtone(int, int, int);
82 static void playstring(char *, int);
83
84
85 static void
86 tone(hz, ticks)
87 u_int hz, ticks;
88 {
89 pcppi_bell(ppicookie, hz, ticks, PCPPI_BELL_SLEEP);
90 }
91
92
93 static void
94 rest(ticks)
95 int ticks;
96 {
97
98
99
100
101
102 #ifdef SPKRDEBUG
103 printf("rest: %d\n", ticks);
104 #endif
105 if (ticks > 0)
106 tsleep(rest, SPKRPRI | PCATCH, "rest", ticks);
107 }
108
109
110
111
112
113
114
115
116
117 typedef int bool;
118 #define TRUE 1
119 #define FALSE 0
120
121 #define toupper(c) ((c) - ' ' * (((c) >= 'a') && ((c) <= 'z')))
122 #define isdigit(c) (((c) >= '0') && ((c) <= '9'))
123 #define dtoi(c) ((c) - '0')
124
125 static int octave;
126 static int whole;
127 static int value;
128 static int fill;
129 static bool octtrack;
130 static bool octprefix;
131
132
133
134
135 #define SECS_PER_MIN 60
136 #define WHOLE_NOTE 4
137 #define MIN_VALUE 64
138 #define DFLT_VALUE 4
139 #define FILLTIME 8
140 #define STACCATO 6
141 #define NORMAL 7
142 #define LEGATO 8
143 #define DFLT_OCTAVE 4
144 #define MIN_TEMPO 32
145 #define DFLT_TEMPO 120
146 #define MAX_TEMPO 255
147 #define NUM_MULT 3
148 #define DENOM_MULT 2
149
150
151 static int notetab[8] = { 9, 11, 0, 2, 4, 5, 7 };
152
153
154
155
156
157
158 #define OCTAVE_NOTES 12
159 static int pitchtab[] =
160 {
161
162 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123,
163 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
164 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
165 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
166 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975,
167 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
168 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902,
169 };
170 #define NOCTAVES (sizeof(pitchtab) / sizeof(pitchtab[0]) / OCTAVE_NOTES)
171
172 static void
173 playinit()
174 {
175 octave = DFLT_OCTAVE;
176 whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
177 fill = NORMAL;
178 value = DFLT_VALUE;
179 octtrack = FALSE;
180 octprefix = TRUE;
181 }
182
183
184 static void
185 playtone(pitch, value, sustain)
186 int pitch, value, sustain;
187 {
188 int sound, silence, snum = 1, sdenom = 1;
189
190
191 for (; sustain; sustain--) {
192 snum *= NUM_MULT;
193 sdenom *= DENOM_MULT;
194 }
195
196 if (pitch == -1)
197 rest(whole * snum / (value * sdenom));
198 else if (pitch >= 0 &&
199 pitch < (sizeof(pitchtab) / sizeof(pitchtab[0]))) {
200 sound = (whole * snum) / (value * sdenom) -
201 (whole * (FILLTIME - fill)) / (value * FILLTIME);
202 silence = whole * (FILLTIME-fill) * snum /
203 (FILLTIME * value * sdenom);
204
205 #ifdef SPKRDEBUG
206 printf("playtone: pitch %d for %d ticks, rest for %d ticks\n",
207 pitch, sound, silence);
208 #endif
209
210 tone(pitchtab[pitch], sound);
211 if (fill != LEGATO)
212 rest(silence);
213 }
214 }
215
216
217 static void
218 playstring(cp, slen)
219 char *cp;
220 int slen;
221 {
222 int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
223
224 #define GETNUM(cp, v) \
225 do { \
226 for (v = 0; slen > 0 && isdigit(cp[1]); ) { \
227 v = v * 10 + (*++cp - '0'); \
228 slen--; \
229 } \
230 } while (0)
231
232 for (; slen--; cp++) {
233 int sustain, timeval, tempo;
234 char c = toupper(*cp);
235
236 #ifdef SPKRDEBUG
237 printf("playstring: %c (%x)\n", c, c);
238 #endif
239
240 switch (c) {
241 case 'A':
242 case 'B':
243 case 'C':
244 case 'D':
245 case 'E':
246 case 'F':
247 case 'G':
248
249 pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES;
250
251
252 if (slen > 0 && (cp[1] == '#' || cp[1] == '+')) {
253 ++pitch;
254 ++cp;
255 slen--;
256 } else if (slen > 0 && cp[1] == '-') {
257 --pitch;
258 ++cp;
259 slen--;
260 }
261
262
263
264
265
266
267
268 if (octtrack && !octprefix) {
269 if (abs(pitch - lastpitch) >
270 abs(pitch + OCTAVE_NOTES - lastpitch)) {
271 ++octave;
272 pitch += OCTAVE_NOTES;
273 }
274
275 if (abs(pitch - lastpitch) >
276 abs(pitch - OCTAVE_NOTES - lastpitch)) {
277 --octave;
278 pitch -= OCTAVE_NOTES;
279 }
280 }
281 octprefix = FALSE;
282 lastpitch = pitch;
283
284
285
286
287
288 GETNUM(cp, timeval);
289 if (timeval <= 0 || timeval > MIN_VALUE)
290 timeval = value;
291
292
293 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
294 slen--;
295 sustain++;
296 }
297
298
299 playtone(pitch, timeval, sustain);
300 break;
301
302 case 'O':
303 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
304 octprefix = octtrack = FALSE;
305 ++cp;
306 slen--;
307 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
308 octtrack = TRUE;
309 ++cp;
310 slen--;
311 } else {
312 GETNUM(cp, octave);
313 if (octave >= NOCTAVES)
314 octave = DFLT_OCTAVE;
315 octprefix = TRUE;
316 }
317 break;
318
319 case '>':
320 if (octave < NOCTAVES - 1)
321 octave++;
322 octprefix = TRUE;
323 break;
324
325 case '<':
326 if (octave > 0)
327 octave--;
328 octprefix = TRUE;
329 break;
330
331 case 'N':
332 GETNUM(cp, pitch);
333 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
334 slen--;
335 sustain++;
336 }
337 playtone(pitch - 1, value, sustain);
338 break;
339
340 case 'L':
341 GETNUM(cp, value);
342 if (value <= 0 || value > MIN_VALUE)
343 value = DFLT_VALUE;
344 break;
345
346 case 'P':
347 case '~':
348
349 GETNUM(cp, timeval);
350 if (timeval <= 0 || timeval > MIN_VALUE)
351 timeval = value;
352 for (sustain = 0; slen > 0 && cp[1] == '.'; cp++) {
353 slen--;
354 sustain++;
355 }
356 playtone(-1, timeval, sustain);
357 break;
358
359 case 'T':
360 GETNUM(cp, tempo);
361 if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
362 tempo = DFLT_TEMPO;
363 whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
364 break;
365
366 case 'M':
367 if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n')) {
368 fill = NORMAL;
369 ++cp;
370 slen--;
371 } else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l')) {
372 fill = LEGATO;
373 ++cp;
374 slen--;
375 } else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's')) {
376 fill = STACCATO;
377 ++cp;
378 slen--;
379 }
380 break;
381 }
382 }
383 }
384
385
386
387
388
389
390
391 static int spkr_active;
392 static void *spkr_inbuf;
393
394 static int spkr_attached = 0;
395
396 int
397 spkrprobe(parent, match, aux)
398 struct device *parent;
399 void *match;
400 void *aux;
401 {
402 return (!spkr_attached);
403 }
404
405 void
406 spkrattach(parent, self, aux)
407 struct device *parent;
408 struct device *self;
409 void *aux;
410 {
411 printf("\n");
412 ppicookie = ((struct pcppi_attach_args *)aux)->pa_cookie;
413 spkr_attached = 1;
414 }
415
416 int
417 spkropen(dev, flags, mode, p)
418 dev_t dev;
419 int flags;
420 int mode;
421 struct proc *p;
422 {
423 #ifdef SPKRDEBUG
424 printf("spkropen: entering with dev = %x\n", dev);
425 #endif
426
427 if (minor(dev) != 0 || !spkr_attached)
428 return (ENXIO);
429 else if (spkr_active)
430 return (EBUSY);
431 else {
432 playinit();
433 spkr_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK);
434 spkr_active = 1;
435 }
436 return (0);
437 }
438
439 int
440 spkrwrite(dev, uio, flags)
441 dev_t dev;
442 struct uio *uio;
443 int flags;
444 {
445 int n;
446 int error;
447 #ifdef SPKRDEBUG
448 printf("spkrwrite: entering with dev = %x, count = %d\n",
449 dev, uio->uio_resid);
450 #endif
451
452 if (minor(dev) != 0)
453 return (ENXIO);
454 else {
455 n = min(DEV_BSIZE, uio->uio_resid);
456 error = uiomove(spkr_inbuf, n, uio);
457 if (!error)
458 playstring((char *)spkr_inbuf, n);
459 return (error);
460 }
461 }
462
463 int
464 spkrclose(dev, flags, mode, p)
465 dev_t dev;
466 int flags;
467 int mode;
468 struct proc *p;
469 {
470 #ifdef SPKRDEBUG
471 printf("spkrclose: entering with dev = %x\n", dev);
472 #endif
473
474 if (minor(dev) != 0)
475 return (ENXIO);
476 else {
477 tone(0, 0);
478 free(spkr_inbuf, M_DEVBUF);
479 spkr_active = 0;
480 }
481 return (0);
482 }
483
484 int
485 spkrioctl(dev, cmd, data, flag, p)
486 dev_t dev;
487 u_long cmd;
488 caddr_t data;
489 int flag;
490 struct proc *p;
491 {
492 tone_t *tp, ttp;
493 int error;
494
495 #ifdef SPKRDEBUG
496 printf("spkrioctl: entering with dev = %x, cmd = %lx\n", dev, cmd);
497 #endif
498
499 if (minor(dev) != 0)
500 return (ENXIO);
501
502 switch (cmd) {
503 case SPKRTONE:
504 tp = (tone_t *)data;
505
506 if (tp->frequency == 0)
507 rest(tp->duration);
508 else
509 tone(tp->frequency, tp->duration);
510 break;
511 case SPKRTUNE:
512 tp = (tone_t *)(*(caddr_t *)data);
513
514 for (; ; tp++) {
515 error = copyin(tp, &ttp, sizeof(tone_t));
516 if (error)
517 return (error);
518 if (ttp.duration == 0)
519 break;
520 if (ttp.frequency == 0)
521 rest(ttp.duration);
522 else
523 tone(ttp.frequency, ttp.duration);
524 }
525 break;
526 default:
527 return (ENOTTY);
528 }
529
530 return (0);
531 }