midi.c revision 1.43.2.5 1 /* $NetBSD: midi.c,v 1.43.2.5 2006/05/20 03:15:32 chap Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss (at) NetBSD.org).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: midi.c,v 1.43.2.5 2006/05/20 03:15:32 chap Exp $");
41
42 #include "midi.h"
43 #include "sequencer.h"
44
45 #include <sys/param.h>
46 #include <sys/ioctl.h>
47 #include <sys/fcntl.h>
48 #include <sys/vnode.h>
49 #include <sys/select.h>
50 #include <sys/poll.h>
51 #include <sys/malloc.h>
52 #include <sys/proc.h>
53 #include <sys/systm.h>
54 #include <sys/callout.h>
55 #include <sys/syslog.h>
56 #include <sys/kernel.h>
57 #include <sys/signalvar.h>
58 #include <sys/conf.h>
59 #include <sys/audioio.h>
60 #include <sys/midiio.h>
61
62 #include <dev/audio_if.h>
63 #include <dev/midi_if.h>
64 #include <dev/midivar.h>
65
66 #if NMIDI > 0
67
68
69 #ifdef AUDIO_DEBUG
70 #define DPRINTF(x) if (mididebug) printf x
71 #define DPRINTFN(n,x) if (mididebug >= (n)) printf x
72 int mididebug = 0;
73 /*
74 * 1: detected protocol errors and buffer overflows
75 * 2: probe, attach, detach
76 * 3: open, close
77 * 4: data received except realtime
78 * 5: ioctl
79 * 6: read, write, poll
80 * 7: data transmitted
81 * 8: uiomoves, synchronization
82 * 9: realtime data received
83 */
84 #else
85 #define DPRINTF(x)
86 #define DPRINTFN(n,x)
87 #endif
88
89 int midi_wait;
90
91 void midi_in(void *, int);
92 void midi_out(void *);
93 int midi_start_output(struct midi_softc *, int, int);
94 int midi_sleep_timo(int *, char *, int);
95 int midi_sleep(int *, char *);
96 void midi_wakeup(int *);
97 void midi_initbuf(struct midi_buffer *);
98 void midi_timeout(void *);
99
100 int midiprobe(struct device *, struct cfdata *, void *);
101 void midiattach(struct device *, struct device *, void *);
102 int mididetach(struct device *, int);
103 int midiactivate(struct device *, enum devact);
104
105 dev_type_open(midiopen);
106 dev_type_close(midiclose);
107 dev_type_read(midiread);
108 dev_type_write(midiwrite);
109 dev_type_ioctl(midiioctl);
110 dev_type_poll(midipoll);
111 dev_type_kqfilter(midikqfilter);
112
113 const struct cdevsw midi_cdevsw = {
114 midiopen, midiclose, midiread, midiwrite, midiioctl,
115 nostop, notty, midipoll, nommap, midikqfilter,
116 };
117
118 CFATTACH_DECL(midi, sizeof(struct midi_softc),
119 midiprobe, midiattach, mididetach, midiactivate);
120
121 #ifdef MIDI_SAVE
122 #define MIDI_SAVE_SIZE 100000
123 int midicnt;
124 struct {
125 int cnt;
126 u_char buf[MIDI_SAVE_SIZE];
127 } midisave;
128 #define MIDI_GETSAVE _IOWR('m', 100, int)
129
130 #endif
131
132 extern struct cfdriver midi_cd;
133
134 int
135 midiprobe(struct device *parent, struct cfdata *match, void *aux)
136 {
137 struct audio_attach_args *sa = aux;
138
139 DPRINTFN(2,("midiprobe: type=%d sa=%p hw=%p\n",
140 sa->type, sa, sa->hwif));
141 return (sa->type == AUDIODEV_TYPE_MIDI);
142 }
143
144 void
145 midiattach(struct device *parent, struct device *self, void *aux)
146 {
147 struct midi_softc *sc = (void *)self;
148 struct audio_attach_args *sa = aux;
149 struct midi_hw_if *hwp = sa->hwif;
150 void *hdlp = sa->hdl;
151
152 DPRINTFN(2, ("MIDI attach\n"));
153
154 #ifdef DIAGNOSTIC
155 if (hwp == 0 ||
156 hwp->open == 0 ||
157 hwp->close == 0 ||
158 hwp->output == 0 ||
159 hwp->getinfo == 0) {
160 printf("midi: missing method\n");
161 return;
162 }
163 #endif
164
165 sc->hw_if = hwp;
166 sc->hw_hdl = hdlp;
167 midi_attach(sc, parent);
168 }
169
170 int
171 midiactivate(struct device *self, enum devact act)
172 {
173 struct midi_softc *sc = (struct midi_softc *)self;
174
175 switch (act) {
176 case DVACT_ACTIVATE:
177 return (EOPNOTSUPP);
178
179 case DVACT_DEACTIVATE:
180 sc->dying = 1;
181 break;
182 }
183 return (0);
184 }
185
186 int
187 mididetach(struct device *self, int flags)
188 {
189 struct midi_softc *sc = (struct midi_softc *)self;
190 int maj, mn;
191
192 DPRINTFN(2,("midi_detach: sc=%p flags=%d\n", sc, flags));
193
194 sc->dying = 1;
195
196 wakeup(&sc->wchan);
197 wakeup(&sc->rchan);
198
199 /* locate the major number */
200 maj = cdevsw_lookup_major(&midi_cdevsw);
201
202 /* Nuke the vnodes for any open instances (calls close). */
203 mn = self->dv_unit;
204 vdevgone(maj, mn, mn, VCHR);
205
206 if ( sc->props & MIDI_PROP_CAN_INPUT ) {
207 evcnt_detach(&sc->rcvBytesDiscarded);
208 evcnt_detach(&sc->rcvIncompleteMessages);
209 }
210
211 return (0);
212 }
213
214 void
215 midi_attach(struct midi_softc *sc, struct device *parent)
216 {
217 struct midi_info mi;
218
219
220 callout_init(&sc->sc_callout);
221 callout_setfunc(&sc->sc_callout, midi_timeout, sc);
222 simple_lock_init(&sc->out_lock);
223 sc->dying = 0;
224 sc->isopen = 0;
225
226 midi_wait = MIDI_WAIT * hz / 1000000;
227 if (midi_wait == 0)
228 midi_wait = 1;
229
230 sc->sc_dev = parent;
231 sc->hw_if->getinfo(sc->hw_hdl, &mi);
232 sc->props = mi.props;
233
234 if ( sc->props & MIDI_PROP_CAN_INPUT ) {
235 evcnt_attach_dynamic(&sc->rcvBytesDiscarded,
236 EVCNT_TYPE_MISC, NULL,
237 sc->dev.dv_xname, "rcv bytes discarded");
238 evcnt_attach_dynamic(&sc->rcvIncompleteMessages,
239 EVCNT_TYPE_MISC, NULL,
240 sc->dev.dv_xname, "rcv incomplete msgs");
241 }
242
243 printf(": %s\n", mi.name);
244 }
245
246 int
247 midi_unit_count(void)
248 {
249 int i;
250 for ( i = 0; i < midi_cd.cd_ndevs; ++i )
251 if ( NULL == midi_cd.cd_devs[i] )
252 break;
253 return i;
254 }
255
256 void
257 midi_initbuf(struct midi_buffer *mb)
258 {
259 mb->used = 0;
260 mb->usedhigh = MIDI_BUFSIZE;
261 mb->end = mb->start + mb->usedhigh;
262 mb->inp = mb->outp = mb->start;
263 }
264
265 int
266 midi_sleep_timo(int *chan, char *label, int timo)
267 {
268 int st;
269
270 if (!label)
271 label = "midi";
272
273 DPRINTFN(8, ("midi_sleep_timo: %p %s %d\n", chan, label, timo));
274 *chan = 1;
275 st = tsleep(chan, PWAIT | PCATCH, label, timo);
276 *chan = 0;
277 #ifdef MIDI_DEBUG
278 if (st != 0)
279 printf("midi_sleep: %d\n", st);
280 #endif
281 return st;
282 }
283
284 int
285 midi_sleep(int *chan, char *label)
286 {
287 return midi_sleep_timo(chan, label, 0);
288 }
289
290 void
291 midi_wakeup(int *chan)
292 {
293 if (*chan) {
294 DPRINTFN(8, ("midi_wakeup: %p\n", chan));
295 wakeup(chan);
296 *chan = 0;
297 }
298 }
299
300 /* in midivar.h:
301 #define MIDI_CAT_DATA 0
302 #define MIDI_CAT_STATUS1 1
303 #define MIDI_CAT_STATUS2 2
304 #define MIDI_CAT_COMMON 3
305 */
306 static char const midi_cats[] = "\0\0\0\0\0\0\0\0\2\2\2\2\1\1\2\3";
307 #define MIDI_CAT(d) (midi_cats[((d)>>4)&15])
308
309 void
310 midi_in(void *addr, int data)
311 {
312 struct midi_softc *sc = addr;
313 struct midi_buffer *mb = &sc->inbuf;
314 int i;
315 u_char *what = sc->in_msg;
316 u_char rtbuf;
317 int count;
318
319 if (!sc->isopen)
320 return;
321
322 if (!(sc->flags & FREAD))
323 return; /* discard data if not reading */
324
325 if ( data >= 0xf8 ) { /* All realtime messages bypass state machine */
326 if ( data == 0xf9 || data == 0xfd ) {
327 DPRINTF( ("midi_in: sc=%p data=0x%02x undefined\n",
328 sc, data));
329 sc->rcvBytesDiscarded.ev_count++;
330 return;
331 }
332 DPRINTFN(9, ("midi_in: sc=%p System Real-Time data=0x%02x\n",
333 sc, data));
334 rtbuf = data;
335 count = sizeof rtbuf;
336 what = &rtbuf;
337 goto deliver;
338 }
339
340 DPRINTFN(4, ("midi_in: sc=%p data=0x%02x state=%d\n",
341 sc, data, sc->in_state));
342
343 retry:
344 switch ( sc->in_state | MIDI_CAT(data) ) {
345
346 case MIDI_IN_START | MIDI_CAT_COMMON:
347 case MIDI_IN_RUN1_1 | MIDI_CAT_COMMON:
348 case MIDI_IN_RUN2_2 | MIDI_CAT_COMMON:
349 sc->in_msg[0] = data;
350 count = 1;
351 switch ( data ) {
352 case 0xf0: sc->in_state = MIDI_IN_SYSEX; goto deliver_raw;
353 case 0xf1: sc->in_state = MIDI_IN_COM0_1; return;
354 case 0xf2: sc->in_state = MIDI_IN_COM0_2; return;
355 case 0xf3: sc->in_state = MIDI_IN_COM0_1; return;
356 case 0xf6: sc->in_state = MIDI_IN_START; break;
357 default: goto protocol_violation;
358 }
359 break;
360
361 case MIDI_IN_START | MIDI_CAT_STATUS1:
362 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS1:
363 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS1:
364 sc->in_state = MIDI_IN_RUN0_1;
365 sc->in_msg[0] = data;
366 return;
367
368 case MIDI_IN_START | MIDI_CAT_STATUS2:
369 case MIDI_IN_RUN1_1 | MIDI_CAT_STATUS2:
370 case MIDI_IN_RUN2_2 | MIDI_CAT_STATUS2:
371 sc->in_state = MIDI_IN_RUN0_2;
372 sc->in_msg[0] = data;
373 return;
374
375 case MIDI_IN_COM0_1 | MIDI_CAT_DATA:
376 sc->in_state = MIDI_IN_START;
377 sc->in_msg[1] = data;
378 count = 2;
379 break;
380
381 case MIDI_IN_COM0_2 | MIDI_CAT_DATA:
382 sc->in_state = MIDI_IN_COM1_2;
383 sc->in_msg[1] = data;
384 return;
385
386 case MIDI_IN_COM1_2 | MIDI_CAT_DATA:
387 sc->in_state = MIDI_IN_START;
388 sc->in_msg[2] = data;
389 count = 3;
390 break;
391
392 case MIDI_IN_RUN0_1 | MIDI_CAT_DATA:
393 case MIDI_IN_RUN1_1 | MIDI_CAT_DATA:
394 sc->in_state = MIDI_IN_RUN1_1;
395 sc->in_msg[1] = data;
396 count = 2;
397 break;
398
399 case MIDI_IN_RUN0_2 | MIDI_CAT_DATA:
400 case MIDI_IN_RUN2_2 | MIDI_CAT_DATA:
401 sc->in_state = MIDI_IN_RUN1_2;
402 sc->in_msg[1] = data;
403 return;
404
405 case MIDI_IN_RUN1_2 | MIDI_CAT_DATA:
406 sc->in_state = MIDI_IN_RUN2_2;
407 sc->in_msg[2] = data;
408 count = 3;
409 break;
410
411 case MIDI_IN_SYSEX | MIDI_CAT_DATA:
412 sc->in_msg[0] = data;
413 count = 1;
414 goto deliver_raw;
415
416 case MIDI_IN_SYSEX | MIDI_CAT_COMMON:
417 if ( data == 0xf7 ) {
418 sc->in_state = MIDI_IN_START;
419 sc->in_msg[0] = data;
420 count = 1;
421 goto deliver_raw;
422 }
423 /* FALLTHROUGH */
424
425 default:
426 protocol_violation:
427 DPRINTF(("midi_in: unexpected %#02x in state %u\n",
428 data, sc->in_state));
429 switch ( sc->in_state ) {
430 case MIDI_IN_RUN1_1: /* can only get here by seeing an */
431 case MIDI_IN_RUN2_2: /* INVALID System Common message */
432 sc->in_state = MIDI_IN_START;
433 /* FALLTHROUGH */
434 case MIDI_IN_START:
435 sc->rcvBytesDiscarded.ev_count++;
436 return;
437 case MIDI_IN_COM1_2:
438 case MIDI_IN_RUN1_2:
439 sc->rcvBytesDiscarded.ev_count++;
440 /* FALLTHROUGH */
441 case MIDI_IN_COM0_1:
442 case MIDI_IN_RUN0_1:
443 case MIDI_IN_COM0_2:
444 case MIDI_IN_RUN0_2:
445 sc->rcvBytesDiscarded.ev_count++;
446 /* FALLTHROUGH */
447 case MIDI_IN_SYSEX:
448 sc->rcvIncompleteMessages.ev_count++;
449 break;
450 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
451 default:
452 printf("midi_in: mishandled %#02x(%u) in state %u?!\n",
453 data, MIDI_CAT(data), sc->in_state);
454 #endif
455 }
456 sc->in_state = MIDI_IN_START;
457 goto retry;
458 }
459
460 deliver:
461 #if NSEQUENCER > 0
462 if (sc->seqopen) {
463 extern void midiseq_in(struct midi_dev *,u_char *,int);
464 midiseq_in(sc->seq_md, what, count);
465 return;
466 }
467 #endif
468 if ( data == MIDI_ACK ) /* sequencer should see these to support API */
469 return; /* otherwise discard (could track time last seen) */
470 deliver_raw:
471 if (mb->used + count > mb->usedhigh) {
472 DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
473 what[0]));
474 sc->rcvBytesDiscarded.ev_count += count;
475 return;
476 }
477 for (i = 0; i < count; i++) {
478 *mb->inp++ = what[i];
479 if (mb->inp >= mb->end)
480 mb->inp = mb->start;
481 mb->used++;
482 }
483 midi_wakeup(&sc->rchan);
484 selnotify(&sc->rsel, 0);
485 if (sc->async)
486 psignal(sc->async, SIGIO);
487 }
488
489 void
490 midi_out(void *addr)
491 {
492 struct midi_softc *sc = addr;
493
494 if (!sc->isopen)
495 return;
496 DPRINTFN(8, ("midi_out: %p\n", sc));
497 midi_start_output(sc, 0, 1);
498 }
499
500 int
501 midiopen(dev_t dev, int flags, int ifmt, struct proc *p)
502 {
503 struct midi_softc *sc;
504 struct midi_hw_if *hw;
505 int error;
506
507 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
508 if (sc == NULL)
509 return (ENXIO);
510 if (sc->dying)
511 return (EIO);
512
513 DPRINTFN(3,("midiopen %p\n", sc));
514
515 hw = sc->hw_if;
516 if (!hw)
517 return ENXIO;
518 if (sc->isopen)
519 return EBUSY;
520 sc->in_state = MIDI_IN_START;
521 error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc);
522 if (error)
523 return error;
524 sc->isopen++;
525 midi_initbuf(&sc->outbuf);
526 midi_initbuf(&sc->inbuf);
527 sc->flags = flags;
528 sc->rchan = 0;
529 sc->wchan = 0;
530 sc->pbus = 0;
531 sc->async = 0;
532
533 #ifdef MIDI_SAVE
534 if (midicnt != 0) {
535 midisave.cnt = midicnt;
536 midicnt = 0;
537 }
538 #endif
539
540 return 0;
541 }
542
543 int
544 midiclose(dev_t dev, int flags, int ifmt, struct proc *p)
545 {
546 int unit = MIDIUNIT(dev);
547 struct midi_softc *sc = midi_cd.cd_devs[unit];
548 struct midi_hw_if *hw = sc->hw_if;
549 int s, error;
550
551 DPRINTFN(3,("midiclose %p\n", sc));
552
553 midi_start_output(sc, 1, 0);
554 error = 0;
555 s = splaudio();
556 while (sc->outbuf.used > 0 && !error) {
557 DPRINTFN(8,("midiclose sleep used=%d\n", sc->outbuf.used));
558 error = midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz);
559 }
560 splx(s);
561 callout_stop(&sc->sc_callout);
562 sc->isopen = 0;
563 hw->close(sc->hw_hdl);
564 #if NSEQUENCER > 0
565 sc->seqopen = 0;
566 sc->seq_md = 0;
567 #endif
568 return 0;
569 }
570
571 int
572 midiread(dev_t dev, struct uio *uio, int ioflag)
573 {
574 int unit = MIDIUNIT(dev);
575 struct midi_softc *sc = midi_cd.cd_devs[unit];
576 struct midi_buffer *mb = &sc->inbuf;
577 int error;
578 u_char *outp;
579 int used, cc, n, resid;
580 int s;
581
582 DPRINTFN(6,("midiread: %p, count=%lu\n", sc,
583 (unsigned long)uio->uio_resid));
584
585 if (sc->dying)
586 return EIO;
587 if ( !(sc->flags & FREAD) )
588 return EBADF;
589 if ( !(sc->props & MIDI_PROP_CAN_INPUT) )
590 return ENXIO;
591
592 error = 0;
593 resid = uio->uio_resid;
594 while (uio->uio_resid == resid && !error) {
595 s = splaudio();
596 while (mb->used <= 0) {
597 if (ioflag & IO_NDELAY) {
598 splx(s);
599 return EWOULDBLOCK;
600 }
601 error = midi_sleep(&sc->rchan, "mid rd");
602 if (error) {
603 splx(s);
604 return error;
605 }
606 }
607 used = mb->used;
608 outp = mb->outp;
609 splx(s);
610 if (sc->dying)
611 return EIO;
612 cc = used; /* maximum to read */
613 n = mb->end - outp;
614 if (n < cc)
615 cc = n; /* don't read beyond end of buffer */
616 if (uio->uio_resid < cc)
617 cc = uio->uio_resid; /* and no more than we want */
618 DPRINTFN(8, ("midiread: uiomove cc=%d\n", cc));
619 error = uiomove(outp, cc, uio);
620 if (error)
621 break;
622 used -= cc;
623 outp += cc;
624 if (outp >= mb->end)
625 outp = mb->start;
626 s = splaudio();
627 mb->outp = outp;
628 mb->used = used;
629 splx(s);
630 }
631 return error;
632 }
633
634 void
635 midi_timeout(void *arg)
636 {
637 struct midi_softc *sc = arg;
638
639 DPRINTFN(8,("midi_timeout: %p\n", sc));
640 midi_start_output(sc, 0, 0);
641 }
642
643 /*
644 * Control can reach midi_start_output three ways:
645 * 1. as a result of user writing (user == 1)
646 * 2. by a ready interrupt from output hw (hw == 1)
647 * 3. by a callout scheduled at the end of midi_start_output.
648 *
649 * The callout is not scheduled unless we are sure the hw will not
650 * interrupt again (either because it just did and we supplied it
651 * no data, or because it lacks interrupt capability). So we do not
652 * expect a hw interrupt to occur with a callout pending.
653 *
654 * A user write may occur while the callout is pending, however, or before
655 * an interrupt-capable device has interrupted. There are two cases:
656 *
657 * 1. A device interrupt is expected, or the pending callout is a MIDI_WAIT
658 * (the brief delay we put in if MIDI_MAX_WRITE characters have been
659 * written without yielding; interrupt-capable hardware can avoid this
660 * penalty by making sure not to use EINPROGRESS to consume MIDI_MAX_WRITE
661 * or more characters at once). In these cases, the user invocation of
662 * start_output returns without action, leaving the output to be resumed
663 * by the device interrupt or by the callout after the proper delay. This
664 * case is identified by sc->pbus == 1.
665 *
666 * 2. The pending callout was scheduled to ensure an Active Sense gets
667 * written if there is no user write in time. In this case the user
668 * invocation (if there is something to write) cancels the pending
669 * callout. However, it may be possible the callout timer expired before
670 * we could cancel it, but the callout hasn't run yet. In this case
671 * (INVOKING status on the callout) the user invocation returns without
672 * further action so the callout can do the work. XXX handle the chance
673 * the callout got scheduled, saw our lock, and gave up.
674 *
675 * Is it possible that fast interrupt-driven hardware could interrupt while
676 * the start_output that triggered it still holds the lock? In this case we'll
677 * see on unlock that sc->hw_interrupted == 1 and loop around again if there
678 * is more to write.
679 */
680 int
681 midi_start_output(struct midi_softc *sc, int user, int hw)
682 {
683 struct midi_buffer *mb = &sc->outbuf;
684 u_char out;
685 int error;
686 int s;
687 int written;
688 int to_write;
689 u_char *from;
690 u_char *to;
691
692 again:
693 if ( mididebug > 9 ) return EIO;
694 error = 0;
695
696 if (sc->dying)
697 return EIO;
698
699 s = splaudio();
700
701 if ( ! simple_lock_try(&sc->out_lock) ) {
702 if ( hw )
703 sc->hw_interrupted = 1;
704 splx(s);
705 DPRINTFN(8,("midi_start_output: locked out user=%d hw=%d\n",
706 user, hw));
707 return 0;
708 }
709
710 to_write = mb->used;
711
712 if ( user ) {
713 if ( sc->pbus ) {
714 simple_unlock(&sc->out_lock);
715 splx(s);
716 DPRINTFN(8, ("midi_start_output: delaying\n"));
717 return 0;
718 }
719 if ( to_write > 0 ) {
720 callout_stop(&sc->sc_callout);
721 if (callout_invoking(&sc->sc_callout)) {
722 simple_unlock(&sc->out_lock);
723 splx(s);
724 DPRINTFN(8,("midi_start_output: "
725 "callout got away\n"));
726 return 0;
727 }
728 }
729 } else if ( hw )
730 sc->hw_interrupted = 0;
731 else
732 callout_ack(&sc->sc_callout);
733
734 splx(s);
735 /*
736 * As long as we hold the lock, we can rely on mb->outp not changing
737 * and mb->used not decreasing. We only need splaudio to update them.
738 */
739
740 from = mb->outp;
741
742 DPRINTFN(8,("midi_start_output: user=%d hw=%d to_write %u from %p\n",
743 user, hw, to_write, from));
744 sc->pbus = 0;
745
746 written = 0;
747 if ( to_write == 0 && ! user && ! hw ) {
748 error = sc->hw_if->output(sc->hw_hdl, MIDI_ACK);
749 written = 1;
750 }
751
752 do {
753 if ( to_write > MIDI_MAX_WRITE - written )
754 to_write = MIDI_MAX_WRITE - written;
755 if ( to_write == 0 )
756 break;
757 to = from + to_write;
758 if ( to > mb->end )
759 to = mb->end;
760 while ( from < to ) {
761 out = *from++;
762 #ifdef MIDI_SAVE
763 midisave.buf[midicnt] = out;
764 midicnt = (midicnt + 1) % MIDI_SAVE_SIZE;
765 #endif
766 DPRINTFN(8, ("midi_start_output: %p data=0x%02x\n",
767 sc, out));
768 error = sc->hw_if->output(sc->hw_hdl, out);
769 if ( error == 0 ) {
770 if ( sc->props & MIDI_PROP_OUT_INTR )
771 break;
772 } else if ( ( sc->props & MIDI_PROP_OUT_INTR )
773 && error == EINPROGRESS )
774 continue;
775 else { /* really an error */
776 -- from;
777 break;
778 }
779 }
780 written += from - mb->outp;
781 s = splaudio();
782 mb->used -= from - mb->outp;
783 if ( from == mb->end )
784 from = mb->start;
785 mb->outp = from;
786 splx(s);
787 to_write = mb->used;
788 } while ( error == ( sc->props&MIDI_PROP_OUT_INTR ) ? EINPROGRESS : 0 );
789
790 if ( written > 0 ) {
791 midi_wakeup(&sc->wchan);
792 selnotify(&sc->wsel, 0);
793 if (sc->async)
794 psignal(sc->async, SIGIO);
795 }
796
797 if ( sc->props & MIDI_PROP_OUT_INTR ) {
798 if ( written > 0 && error == 0 ) {
799 sc->pbus = 1;
800 goto unlock_exit;
801 }
802 if ( error == EINPROGRESS )
803 error = 0;
804 }
805
806 if ( error != 0 )
807 goto handle_error;
808
809 if ( to_write == 0 )
810 callout_schedule(&sc->sc_callout, mstohz(285));
811 else {
812 sc->pbus = 1;
813 callout_schedule(&sc->sc_callout, midi_wait);
814 }
815 goto unlock_exit;
816
817 handle_error:
818 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
819 printf("%s: midi_start_output error %d\n",
820 sc->dev.dv_xname, error);
821 #endif
822
823 unlock_exit:
824 simple_unlock(&sc->out_lock);
825 if ( sc->hw_interrupted ) {
826 user = 0;
827 hw = 1;
828 goto again;
829 }
830
831 return error;
832 }
833
834 int
835 midiwrite(dev_t dev, struct uio *uio, int ioflag)
836 {
837 int unit = MIDIUNIT(dev);
838 struct midi_softc *sc = midi_cd.cd_devs[unit];
839 struct midi_buffer *mb = &sc->outbuf;
840 int error;
841 u_char *inp;
842 int used, cc, n;
843 int s;
844
845 DPRINTFN(6, ("midiwrite: %p, unit=%d, count=%lu\n", sc, unit,
846 (unsigned long)uio->uio_resid));
847
848 if (sc->dying)
849 return EIO;
850 if ( !(sc->flags & FWRITE) )
851 return EBADF;
852
853 error = 0;
854 while (uio->uio_resid > 0 && !error) {
855 s = splaudio();
856 if (mb->used >= mb->usedhigh) {
857 DPRINTFN(8,("midi_write: sleep used=%d hiwat=%d\n",
858 mb->used, mb->usedhigh));
859 if (ioflag & IO_NDELAY) {
860 splx(s);
861 return EWOULDBLOCK;
862 }
863 error = midi_sleep(&sc->wchan, "mid wr");
864 if (error) {
865 splx(s);
866 return error;
867 }
868 }
869 used = mb->used;
870 inp = mb->inp;
871 splx(s);
872 if (sc->dying)
873 return EIO;
874 cc = mb->usedhigh - used; /* maximum to write */
875 n = mb->end - inp;
876 if (n < cc)
877 cc = n; /* don't write beyond end of buffer */
878 if (uio->uio_resid < cc)
879 cc = uio->uio_resid; /* and no more than we have */
880 error = uiomove(inp, cc, uio);
881 #ifdef MIDI_DEBUG
882 if (error)
883 printf("midi_write:(1) uiomove failed %d; "
884 "cc=%d inp=%p\n",
885 error, cc, inp);
886 #endif
887 if (error)
888 break;
889 inp = mb->inp + cc;
890 if (inp >= mb->end)
891 inp = mb->start;
892 s = splaudio();
893 mb->inp = inp;
894 mb->used += cc;
895 splx(s);
896 error = midi_start_output(sc, 1, 0);
897 }
898 return error;
899 }
900
901 /*
902 * This write routine is only called from sequencer code and expects
903 * a write that is smaller than the MIDI buffer.
904 */
905 int
906 midi_writebytes(int unit, u_char *buf, int cc)
907 {
908 struct midi_softc *sc = midi_cd.cd_devs[unit];
909 struct midi_buffer *mb = &sc->outbuf;
910 int n, s;
911
912 DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n",
913 sc, unit, cc, buf[0], buf[1], buf[2]));
914
915 if (sc->dying)
916 return EIO;
917
918 s = splaudio();
919 if (mb->used + cc >= mb->usedhigh) {
920 splx(s);
921 return (EWOULDBLOCK);
922 }
923 n = mb->end - mb->inp;
924 if (cc < n)
925 n = cc;
926 mb->used += cc;
927 memcpy(mb->inp, buf, n);
928 mb->inp += n;
929 if (mb->inp >= mb->end) {
930 mb->inp = mb->start;
931 cc -= n;
932 if (cc > 0) {
933 memcpy(mb->inp, buf + n, cc);
934 mb->inp += cc;
935 }
936 }
937 splx(s);
938 return (midi_start_output(sc, 1, 0));
939 }
940
941 int
942 midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
943 {
944 int unit = MIDIUNIT(dev);
945 struct midi_softc *sc = midi_cd.cd_devs[unit];
946 struct midi_hw_if *hw = sc->hw_if;
947 int error;
948
949 DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
950
951 if (sc->dying)
952 return EIO;
953
954 error = 0;
955 switch (cmd) {
956 case FIONBIO:
957 /* All handled in the upper FS layer. */
958 break;
959
960 case FIOASYNC:
961 if (*(int *)addr) {
962 if (sc->async)
963 return EBUSY;
964 sc->async = p;
965 DPRINTFN(5,("midi_ioctl: FIOASYNC %p\n", p));
966 } else
967 sc->async = 0;
968 break;
969
970 #if 0
971 case MIDI_PRETIME:
972 /* XXX OSS
973 * This should set up a read timeout, but that's
974 * why we have poll(), so there's nothing yet. */
975 error = EINVAL;
976 break;
977 #endif
978
979 #ifdef MIDI_SAVE
980 case MIDI_GETSAVE:
981 error = copyout(&midisave, *(void **)addr, sizeof midisave);
982 break;
983 #endif
984
985 default:
986 if (hw->ioctl)
987 error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p);
988 else
989 error = EINVAL;
990 break;
991 }
992 return error;
993 }
994
995 int
996 midipoll(dev_t dev, int events, struct proc *p)
997 {
998 int unit = MIDIUNIT(dev);
999 struct midi_softc *sc = midi_cd.cd_devs[unit];
1000 int revents = 0;
1001 int s;
1002
1003 DPRINTFN(6,("midipoll: %p events=0x%x\n", sc, events));
1004
1005 if (sc->dying)
1006 return EIO;
1007
1008 s = splaudio();
1009
1010 if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM)))
1011 if (sc->inbuf.used > 0)
1012 revents |= events & (POLLIN | POLLRDNORM);
1013
1014 if ((sc->flags&FWRITE) && (events & (POLLOUT | POLLWRNORM)))
1015 if (sc->outbuf.used < sc->outbuf.usedhigh)
1016 revents |= events & (POLLOUT | POLLWRNORM);
1017
1018 if (revents == 0) {
1019 if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM)))
1020 selrecord(p, &sc->rsel);
1021
1022 if ((sc->flags&FWRITE) && (events & (POLLOUT | POLLWRNORM)))
1023 selrecord(p, &sc->wsel);
1024 }
1025
1026 splx(s);
1027 return revents;
1028 }
1029
1030 static void
1031 filt_midirdetach(struct knote *kn)
1032 {
1033 struct midi_softc *sc = kn->kn_hook;
1034 int s;
1035
1036 s = splaudio();
1037 SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext);
1038 splx(s);
1039 }
1040
1041 static int
1042 filt_midiread(struct knote *kn, long hint)
1043 {
1044 struct midi_softc *sc = kn->kn_hook;
1045
1046 /* XXXLUKEM (thorpej): please make sure this is correct. */
1047
1048 kn->kn_data = sc->inbuf.used;
1049 return (kn->kn_data > 0);
1050 }
1051
1052 static const struct filterops midiread_filtops =
1053 { 1, NULL, filt_midirdetach, filt_midiread };
1054
1055 static void
1056 filt_midiwdetach(struct knote *kn)
1057 {
1058 struct midi_softc *sc = kn->kn_hook;
1059 int s;
1060
1061 s = splaudio();
1062 SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext);
1063 splx(s);
1064 }
1065
1066 static int
1067 filt_midiwrite(struct knote *kn, long hint)
1068 {
1069 struct midi_softc *sc = kn->kn_hook;
1070
1071 /* XXXLUKEM (thorpej): please make sure this is correct. */
1072
1073 kn->kn_data = sc->outbuf.usedhigh - sc->outbuf.used;
1074 return (kn->kn_data > 0);
1075 }
1076
1077 static const struct filterops midiwrite_filtops =
1078 { 1, NULL, filt_midiwdetach, filt_midiwrite };
1079
1080 int
1081 midikqfilter(dev_t dev, struct knote *kn)
1082 {
1083 int unit = MIDIUNIT(dev);
1084 struct midi_softc *sc = midi_cd.cd_devs[unit];
1085 struct klist *klist;
1086 int s;
1087
1088 switch (kn->kn_filter) {
1089 case EVFILT_READ:
1090 klist = &sc->rsel.sel_klist;
1091 kn->kn_fop = &midiread_filtops;
1092 break;
1093
1094 case EVFILT_WRITE:
1095 klist = &sc->wsel.sel_klist;
1096 kn->kn_fop = &midiwrite_filtops;
1097 break;
1098
1099 default:
1100 return (1);
1101 }
1102
1103 kn->kn_hook = sc;
1104
1105 s = splaudio();
1106 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1107 splx(s);
1108
1109 return (0);
1110 }
1111
1112 void
1113 midi_getinfo(dev_t dev, struct midi_info *mi)
1114 {
1115 struct midi_softc *sc;
1116
1117 sc = device_lookup(&midi_cd, MIDIUNIT(dev));
1118 if (sc == NULL)
1119 return;
1120 if (sc->dying)
1121 return;
1122
1123 sc->hw_if->getinfo(sc->hw_hdl, mi);
1124 }
1125
1126 #endif /* NMIDI > 0 */
1127
1128 #if NMIDI > 0 || NMIDIBUS > 0
1129
1130 int audioprint(void *, const char *);
1131
1132 struct device *
1133 midi_attach_mi(struct midi_hw_if *mhwp, void *hdlp, struct device *dev)
1134 {
1135 struct audio_attach_args arg;
1136
1137 #ifdef DIAGNOSTIC
1138 if (mhwp == NULL) {
1139 aprint_error("midi_attach_mi: NULL\n");
1140 return (0);
1141 }
1142 #endif
1143 arg.type = AUDIODEV_TYPE_MIDI;
1144 arg.hwif = mhwp;
1145 arg.hdl = hdlp;
1146 return (config_found(dev, &arg, audioprint));
1147 }
1148
1149 #endif /* NMIDI > 0 || NMIDIBUS > 0 */
1150