This source file includes following definitions.
- midi_iintr
- midiread
- midi_ointr
- midi_out_start
- midi_out_stop
- midi_out_do
- midiwrite
- midipoll
- midiioctl
- midiopen
- midiclose
- midiprobe
- midi_attach
- midiattach
- mididetach
- midiprint
- midi_getinfo
- midi_attach_mi
- midi_unit_count
- midi_toevent
- midi_writebytes
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 #include "midi.h"
28 #include "sequencer.h"
29 #if NMIDI > 0
30
31 #include <sys/param.h>
32 #include <sys/fcntl.h>
33 #include <sys/systm.h>
34 #include <sys/ioctl.h>
35 #include <sys/exec.h>
36 #include <sys/conf.h>
37 #include <sys/lkm.h>
38 #include <sys/proc.h>
39 #include <sys/poll.h>
40 #include <sys/kernel.h>
41 #include <sys/timeout.h>
42 #include <sys/vnode.h>
43 #include <sys/signalvar.h>
44 #include <sys/malloc.h>
45 #include <sys/device.h>
46
47 #include <dev/midi_if.h>
48 #include <dev/audio_if.h>
49 #include <dev/midivar.h>
50
51
52 int midiopen(dev_t, int, int, struct proc *);
53 int midiclose(dev_t, int, int, struct proc *);
54 int midiread(dev_t, struct uio *, int);
55 int midiwrite(dev_t, struct uio *, int);
56 int midipoll(dev_t, int, struct proc *);
57 int midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
58 int midiprobe(struct device *, void *, void *);
59 void midiattach(struct device *, struct device *, void *);
60 int mididetach(struct device *, int);
61 int midiprint(void *, const char *);
62
63 void midi_iintr(void *, int);
64 void midi_ointr(void *);
65 void midi_out_start(struct midi_softc *);
66 void midi_out_stop(struct midi_softc *);
67 void midi_out_do(struct midi_softc *);
68 void midi_attach(struct midi_softc *, struct device *);
69
70
71 #if NSEQUENCER > 0
72 int midi_unit_count(void);
73 struct midi_hw_if *midi_get_hwif(int);
74 void midi_toevent(struct midi_softc *, int);
75 int midi_writebytes(int, u_char *, int);
76 void midiseq_in(struct midi_dev *, u_char *, int);
77 #endif
78
79 struct cfattach midi_ca = {
80 sizeof(struct midi_softc), midiprobe, midiattach, mididetach
81 };
82
83 struct cfdriver midi_cd = {
84 NULL, "midi", DV_DULL
85 };
86
87
88 void
89 midi_iintr(void *addr, int data)
90 {
91 struct midi_softc *sc = (struct midi_softc *)addr;
92 struct midi_buffer *mb = &sc->inbuf;
93
94 if (sc->isdying || !sc->isopen || !(sc->flags & FREAD)) return;
95
96 #if NSEQUENCER > 0
97 if (sc->seqopen) {
98 midi_toevent(sc, data);
99 return;
100 }
101 #endif
102 if (MIDIBUF_ISFULL(mb))
103 return;
104 if (MIDIBUF_ISEMPTY(mb)) {
105 if (sc->rchan) {
106 sc->rchan = 0;
107 wakeup(&sc->rchan);
108 }
109 selwakeup(&sc->rsel);
110 if (sc->async)
111 psignal(sc->async, SIGIO);
112 }
113 MIDIBUF_WRITE(mb, data);
114 }
115
116
117 int
118 midiread(dev_t dev, struct uio *uio, int ioflag)
119 {
120 struct midi_softc *sc = MIDI_DEV2SC(dev);
121 struct midi_buffer *mb = &sc->inbuf;
122 unsigned count;
123 int s, error;
124
125 if (!(sc->flags & FREAD))
126 return ENXIO;
127
128
129
130 s = splaudio();
131 while(MIDIBUF_ISEMPTY(mb)) {
132 if (sc->isdying) {
133 splx(s);
134 return EIO;
135 }
136 if (ioflag & IO_NDELAY) {
137 splx(s);
138 return EWOULDBLOCK;
139 }
140 sc->rchan = 1;
141 error = tsleep(&sc->rchan, PWAIT|PCATCH, "mid_rd", 0);
142 if (error) {
143 splx(s);
144 return error;
145 }
146 }
147
148
149
150 while (uio->uio_resid > 0 && mb->used > 0) {
151 count = MIDIBUF_SIZE - mb->start;
152 if (count > mb->used)
153 count = mb->used;
154 if (count > uio->uio_resid)
155 count = uio->uio_resid;
156 error = uiomove(mb->data + mb->start, count, uio);
157 if (error) {
158 splx(s);
159 return error;
160 }
161 MIDIBUF_REMOVE(mb, count);
162 }
163 splx(s);
164 return 0;
165 }
166
167
168 void
169 midi_ointr(void *addr)
170 {
171 struct midi_softc *sc = (struct midi_softc *)addr;
172 struct midi_buffer *mb;
173 int s;
174
175 if (sc->isopen && !sc->isdying) {
176 #ifdef MIDI_DEBUG
177 if (!sc->isbusy) {
178 printf("midi_ointr: output should be busy\n");
179 }
180 #endif
181 mb = &sc->outbuf;
182 s = splaudio();
183 if (mb->used == 0)
184 midi_out_stop(sc);
185 else
186 midi_out_do(sc);
187 splx(s);
188 }
189 }
190
191
192 void
193 midi_out_start(struct midi_softc *sc)
194 {
195 if (!sc->isbusy) {
196 sc->isbusy = 1;
197 midi_out_do(sc);
198 }
199 }
200
201 void
202 midi_out_stop(struct midi_softc *sc)
203 {
204 sc->isbusy = 0;
205 if (sc->wchan) {
206 sc->wchan = 0;
207 wakeup(&sc->wchan);
208 }
209 selwakeup(&sc->wsel);
210 if (sc->async)
211 psignal(sc->async, SIGIO);
212 }
213
214
215
216
217
218
219 void
220 midi_out_do(struct midi_softc *sc)
221 {
222 struct midi_buffer *mb = &sc->outbuf;
223 unsigned i, max;
224 int error;
225
226
227
228
229
230
231 max = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAXWRITE;
232 for (i = max; i != 0;) {
233 if (mb->used == 0)
234 break;
235 error = sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]);
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 if (error == EINPROGRESS) {
254 MIDIBUF_REMOVE(mb, 1);
255 if (MIDIBUF_ISEMPTY(mb)) {
256 if (sc->hw_if->flush != NULL)
257 sc->hw_if->flush(sc->hw_hdl);
258 midi_out_stop(sc);
259 return;
260 }
261 } else if (error == 0) {
262 MIDIBUF_REMOVE(mb, 1);
263 i--;
264 } else if (error == EAGAIN) {
265 break;
266 } else {
267 MIDIBUF_INIT(mb);
268 midi_out_stop(sc);
269 return;
270 }
271 }
272
273 if (!(sc->props & MIDI_PROP_OUT_INTR)) {
274 if (MIDIBUF_ISEMPTY(mb))
275 midi_out_stop(sc);
276 else
277 timeout_add(&sc->timeo, sc->wait);
278 }
279 }
280
281
282 int
283 midiwrite(dev_t dev, struct uio *uio, int ioflag)
284 {
285 struct midi_softc *sc = MIDI_DEV2SC(dev);
286 struct midi_buffer *mb = &sc->outbuf;
287 unsigned count;
288 int s, error;
289
290 if (!(sc->flags & FWRITE))
291 return ENXIO;
292 if (sc->isdying)
293 return EIO;
294
295
296
297
298
299
300
301 if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) &&
302 (uio->uio_resid > 0))
303 return EWOULDBLOCK;
304
305 while (uio->uio_resid > 0) {
306 s = splaudio();
307 while (MIDIBUF_ISFULL(mb)) {
308 if (ioflag & IO_NDELAY) {
309
310
311
312
313 splx(s);
314 return 0;
315 }
316 sc->wchan = 1;
317 error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_wr", 0);
318 if (error) {
319 splx(s);
320 return error;
321 }
322 if (sc->isdying) {
323 splx(s);
324 return EIO;
325 }
326 }
327
328 count = MIDIBUF_SIZE - MIDIBUF_END(mb);
329 if (count > MIDIBUF_AVAIL(mb))
330 count = MIDIBUF_AVAIL(mb);
331 if (count > uio->uio_resid)
332 count = uio->uio_resid;
333 error = uiomove(mb->data + MIDIBUF_END(mb), count, uio);
334 if (error) {
335 splx(s);
336 return error;
337 }
338 mb->used += count;
339 midi_out_start(sc);
340 splx(s);
341 }
342 return 0;
343 }
344
345
346 int
347 midipoll(dev_t dev, int events, struct proc *p)
348 {
349 struct midi_softc *sc = MIDI_DEV2SC(dev);
350 int s, revents;
351
352 if (sc->isdying)
353 return POLLERR;
354
355 revents = 0;
356 s = splaudio();
357 if (events & (POLLIN | POLLRDNORM)) {
358 if (!MIDIBUF_ISEMPTY(&sc->inbuf))
359 revents |= events & (POLLIN | POLLRDNORM);
360 }
361 if (events & (POLLOUT | POLLWRNORM)) {
362 if (!MIDIBUF_ISFULL(&sc->outbuf))
363 revents |= events & (POLLOUT | POLLWRNORM);
364 }
365 if (revents == 0) {
366 if (events & (POLLIN | POLLRDNORM))
367 selrecord(p, &sc->rsel);
368 if (events & (POLLOUT | POLLWRNORM))
369 selrecord(p, &sc->wsel);
370 }
371 splx(s);
372 return (revents);
373 }
374
375
376 int
377 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
378 {
379 struct midi_softc *sc = MIDI_DEV2SC(dev);
380
381 if (sc->isdying) return EIO;
382
383 switch(cmd) {
384 case FIONBIO:
385
386 break;
387 case FIOASYNC:
388 if (*(int *)addr) {
389 if (sc->async) return EBUSY;
390 sc->async = p;
391 } else
392 sc->async = 0;
393 break;
394 default:
395 return ENOTTY;
396 break;
397 }
398 return 0;
399 }
400
401
402 int
403 midiopen(dev_t dev, int flags, int mode, struct proc *p)
404 {
405 struct midi_softc *sc;
406 int err;
407
408 if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs)
409 return ENXIO;
410 sc = MIDI_DEV2SC(dev);
411 if (sc == NULL)
412 return ENXIO;
413 if (sc->isdying)
414 return EIO;
415 if (sc->isopen)
416 return EBUSY;
417
418 MIDIBUF_INIT(&sc->inbuf);
419 MIDIBUF_INIT(&sc->outbuf);
420 sc->isbusy = 0;
421 sc->rchan = sc->wchan = 0;
422 sc->async = 0;
423 sc->flags = flags;
424
425 err = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
426 if (err)
427 return err;
428 sc->isopen = 1;
429 #if NSEQUENCER > 0
430 sc->seq_md = 0;
431 sc->seqopen = 0;
432 sc->evstatus = 0xff;
433 #endif
434 return 0;
435 }
436
437
438 int
439 midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
440 {
441 struct midi_softc *sc = MIDI_DEV2SC(dev);
442 struct midi_buffer *mb;
443 int error;
444 int s;
445
446 mb = &sc->outbuf;
447 if (!sc->isdying) {
448
449 s = splaudio();
450 if (!MIDIBUF_ISEMPTY(mb))
451 midi_out_start(sc);
452 while (sc->isbusy) {
453 sc->wchan = 1;
454 error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_dr", 0);
455 if (error || sc->isdying)
456 break;
457 }
458 splx(s);
459 }
460
461
462
463
464
465
466
467
468
469
470 tsleep(&sc->wchan, PWAIT|PCATCH, "mid_cl", 2 * sc->wait);
471 sc->hw_if->close(sc->hw_hdl);
472 sc->isopen = 0;
473 return 0;
474 }
475
476
477 int
478 midiprobe(struct device *parent, void *match, void *aux)
479 {
480 struct audio_attach_args *sa = aux;
481 return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0);
482 }
483
484
485 void
486 midi_attach(struct midi_softc *sc, struct device *parent)
487 {
488 struct midi_info mi;
489
490 sc->isdying = 0;
491 sc->wait = (hz * MIDI_MAXWRITE) / MIDI_RATE;
492 if (sc->wait == 0)
493 sc->wait = 1;
494 sc->hw_if->getinfo(sc->hw_hdl, &mi);
495 sc->props = mi.props;
496 sc->isopen = 0;
497 timeout_set(&sc->timeo, midi_ointr, sc);
498 printf(": <%s>\n", mi.name);
499 }
500
501
502 void
503 midiattach(struct device *parent, struct device *self, void *aux)
504 {
505 struct midi_softc *sc = (struct midi_softc *)self;
506 struct audio_attach_args *sa = (struct audio_attach_args *)aux;
507 struct midi_hw_if *hwif = sa->hwif;
508 void *hdl = sa->hdl;
509
510 #ifdef DIAGNOSTIC
511 if (hwif == 0 ||
512 hwif->open == 0 ||
513 hwif->close == 0 ||
514 hwif->output == 0 ||
515 hwif->getinfo == 0) {
516 printf("midi: missing method\n");
517 return;
518 }
519 #endif
520 sc->hw_if = hwif;
521 sc->hw_hdl = hdl;
522 midi_attach(sc, parent);
523 }
524
525
526 int
527 mididetach(struct device *self, int flags)
528 {
529 struct midi_softc *sc = (struct midi_softc *)self;
530 int maj, mn;
531
532 sc->isdying = 1;
533 if (sc->wchan) {
534 sc->wchan = 0;
535 wakeup(&sc->wchan);
536 }
537 if (sc->rchan) {
538 sc->rchan = 0;
539 wakeup(&sc->rchan);
540 }
541
542
543 for (maj = 0; maj < nchrdev; maj++)
544 if (cdevsw[maj].d_open == midiopen)
545 break;
546
547
548 mn = self->dv_unit;
549 vdevgone(maj, mn, mn, VCHR);
550
551 return 0;
552 }
553
554
555 int
556 midiprint(void *aux, const char *pnp)
557 {
558 if (pnp)
559 printf("midi at %s", pnp);
560 return (UNCONF);
561 }
562
563
564 void
565 midi_getinfo(dev_t dev, struct midi_info *mi)
566 {
567 struct midi_softc *sc = MIDI_DEV2SC(dev);
568 if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs || sc == NULL || sc->isdying) {
569 mi->name = "unconfigured";
570 mi->props = 0;
571 return;
572 }
573 sc->hw_if->getinfo(sc->hw_hdl, mi);
574 }
575
576
577 struct device *
578 midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev)
579 {
580 struct audio_attach_args arg;
581
582 arg.type = AUDIODEV_TYPE_MIDI;
583 arg.hwif = hwif;
584 arg.hdl = hdl;
585 return config_found(dev, &arg, midiprint);
586 }
587
588
589 int
590 midi_unit_count(void)
591 {
592 return midi_cd.cd_ndevs;
593 }
594
595
596 #if NSEQUENCER > 0
597 #define MIDI_EVLEN(status) (midi_evlen[((status) >> 4) & 7])
598 unsigned midi_evlen[] = { 2, 2, 2, 2, 1, 1, 2 };
599
600 void
601 midi_toevent(struct midi_softc *sc, int data)
602 {
603 unsigned char mesg[3];
604
605 if (data >= 0xf8) {
606 switch(data) {
607 case 0xf8:
608 case 0xfa:
609 case 0xfb:
610 case 0xfc:
611 mesg[0] = data;
612 midiseq_in(sc->seq_md, mesg, 1);
613 break;
614 default:
615 break;
616 }
617 } else if (data >= 0x80) {
618 sc->evstatus = data;
619 sc->evindex = 0;
620 } else {
621
622 if (sc->evstatus >= 0xf0 || sc->evstatus < 0x80)
623 return;
624
625 sc->evdata[sc->evindex++] = data;
626 if (sc->evindex == MIDI_EVLEN(sc->evstatus)) {
627 sc->evindex = 0;
628 mesg[0] = sc->evstatus;
629 mesg[1] = sc->evdata[0];
630 mesg[2] = sc->evdata[1];
631 midiseq_in(sc->seq_md, mesg, 1 + MIDI_EVLEN(sc->evstatus));
632 }
633 }
634 }
635
636
637 int
638 midi_writebytes(int unit, unsigned char *mesg, int mesglen)
639 {
640 struct midi_softc *sc = midi_cd.cd_devs[unit];
641 struct midi_buffer *mb = &sc->outbuf;
642 unsigned count;
643 int s;
644
645 s = splaudio();
646 if (mesglen > MIDIBUF_AVAIL(mb)) {
647 splx(s);
648 return EWOULDBLOCK;
649 }
650
651 while (mesglen > 0) {
652 count = MIDIBUF_SIZE - MIDIBUF_END(mb);
653 if (count > MIDIBUF_AVAIL(mb)) count = MIDIBUF_AVAIL(mb);
654 if (count > mesglen) count = mesglen;
655 bcopy(mesg, mb->data + MIDIBUF_END(mb), count);
656 mb->used += count;
657 mesg += count;
658 mesglen -= count;
659 midi_out_start(sc);
660 }
661 splx(s);
662 return 0;
663 }
664
665 #endif
666 #endif