kernel - Rejigger midistat functions to close a race
[dragonfly.git] / sys / dev / sound / midi / midi.c
1 /*-
2  * Copyright (c) 2003 Mathew Kanner
3  * Copyright (c) 1998 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Lennart Augustsson (augustss@netbsd.org).
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31  /*
32   * Parts of this file started out as NetBSD: midi.c 1.31
33   * They are mostly gone.  Still the most obvious will be the state
34   * machine midi_in
35   */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 227309 2011-11-07 15:43:11Z ed $");
39
40 #include <sys/param.h>
41 #include <sys/queue.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/mutex.h>
45 #include <sys/proc.h>
46 #include <sys/signalvar.h>
47 #include <sys/conf.h>
48 #include <sys/sysctl.h>
49 #include <sys/types.h>
50 #include <sys/malloc.h>
51 #include <sys/systm.h>
52 #include <sys/fcntl.h>
53 #include <sys/uio.h>
54 #include <sys/poll.h>
55 #include <sys/sbuf.h>
56 #include <sys/kobj.h>
57 #include <sys/module.h>
58 #include <sys/device.h>
59
60 #ifdef HAVE_KERNEL_OPTION_HEADERS
61 #include "opt_snd.h"
62 #endif
63
64 #include <dev/sound/midi/midi.h>
65 #include "mpu_if.h"
66
67 #include <dev/sound/midi/midiq.h>
68 #include "synth_if.h"
69 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area");
70
71 #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f))
72 #define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c)
73
74 #define MIDI_DEV_RAW    2
75 #define MIDI_DEV_MIDICTL 12
76
77 enum midi_states {
78         MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA
79 };
80
81 /*
82  * The MPU interface current has init() uninit() inqsize(( outqsize()
83  * callback() : fiddle with the tx|rx status.
84  */
85
86 #include "mpu_if.h"
87
88 /*
89  * /dev/rmidi   Structure definitions
90  */
91
92 #define MIDI_NAMELEN   16
93 struct snd_midi {
94         KOBJ_FIELDS;
95         struct lock lock;               /* Protects all but queues */
96         void   *cookie;
97
98         int     unit;                   /* Should only be used in midistat */
99         int     channel;                /* Should only be used in midistat */
100
101         int     busy;
102         int     flags;                  /* File flags */
103         char    name[MIDI_NAMELEN];
104         struct lock qlock;              /* Protects inq, outq and flags */
105         MIDIQ_HEAD(, char) inq, outq;
106         int     rchan, wchan;
107         struct kqinfo rkq, wkq;
108         int     hiwat;                  /* QLEN(outq)>High-water -> disable
109                                          * writes from userland */
110         enum midi_states inq_state;
111         int     inq_status, inq_left;   /* Variables for the state machine in
112                                          * Midi_in, this is to provide that
113                                          * signals only get issued only
114                                          * complete command packets. */
115         struct proc *async;
116         struct cdev *dev;
117         struct synth_midi *synth;
118         int     synth_flags;
119         TAILQ_ENTRY(snd_midi) link;
120 };
121
122 struct synth_midi {
123         KOBJ_FIELDS;
124         struct snd_midi *m;
125 };
126
127 static synth_open_t midisynth_open;
128 static synth_close_t midisynth_close;
129 static synth_writeraw_t midisynth_writeraw;
130 static synth_killnote_t midisynth_killnote;
131 static synth_startnote_t midisynth_startnote;
132 static synth_setinstr_t midisynth_setinstr;
133 static synth_alloc_t midisynth_alloc;
134 static synth_controller_t midisynth_controller;
135 static synth_bender_t midisynth_bender;
136
137
138 static kobj_method_t midisynth_methods[] = {
139         KOBJMETHOD(synth_open, midisynth_open),
140         KOBJMETHOD(synth_close, midisynth_close),
141         KOBJMETHOD(synth_writeraw, midisynth_writeraw),
142         KOBJMETHOD(synth_setinstr, midisynth_setinstr),
143         KOBJMETHOD(synth_startnote, midisynth_startnote),
144         KOBJMETHOD(synth_killnote, midisynth_killnote),
145         KOBJMETHOD(synth_alloc, midisynth_alloc),
146         KOBJMETHOD(synth_controller, midisynth_controller),
147         KOBJMETHOD(synth_bender, midisynth_bender),
148         KOBJMETHOD_END
149 };
150
151 DEFINE_CLASS(midisynth, midisynth_methods, 0);
152
153 /*
154  * Module Exports & Interface
155  *
156  * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int
157  * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int
158  * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct
159  * midi_chan *, char *buf, int count)
160  *
161  * midi_{in,out} return actual size transfered
162  *
163  */
164
165
166 /*
167  * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
168  */
169
170 TAILQ_HEAD(, snd_midi) midi_devs;
171
172 /*
173  * /dev/midistat variables and declarations, protected by midistat_lock
174  */
175
176 static struct lock midistat_lock;
177 static int      midistat_isopen = 0;
178 static struct sbuf midistat_sbuf;
179 static struct cdev *midistat_dev;
180
181 /*
182  * /dev/midistat        dev_t declarations
183  */
184
185 static d_open_t midistat_open;
186 static d_close_t midistat_close;
187 static d_read_t midistat_read;
188
189 static void     midi_filter_detach(struct knote *);
190 static int      midi_filter_read(struct knote *, long);
191 static int      midi_filter_write(struct knote *, long);
192
193 static struct dev_ops midistat_ops = {
194         { "midistat", 0, D_MPSAFE },
195         .d_open = midistat_open,
196         .d_close = midistat_close,
197         .d_read = midistat_read,
198 };
199
200 static struct filterops midi_read_filterops =
201         { FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_read };
202 static struct filterops midi_write_filterops =
203         { FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_write };
204
205 /*
206  * /dev/rmidi dev_t declarations, struct variable access is protected by
207  * locks contained within the structure.
208  */
209
210 static d_open_t midi_open;
211 static d_close_t midi_close;
212 static d_ioctl_t midi_ioctl;
213 static d_read_t midi_read;
214 static d_write_t midi_write;
215 static d_kqfilter_t midi_kqfilter;
216
217 static struct dev_ops midi_ops = {
218         { "rmidi", 0, D_MPSAFE },
219         .d_open = midi_open,
220         .d_close = midi_close,
221         .d_read = midi_read,
222         .d_write = midi_write,
223         .d_ioctl = midi_ioctl,
224         .d_kqfilter = midi_kqfilter,
225 };
226
227 /*
228  * Prototypes of library functions
229  */
230
231 static int      midi_destroy(struct snd_midi *, int);
232 static int      midistat_prepare(struct sbuf * s);
233 static int      midi_load(void);
234 static int      midi_unload(void);
235
236 /*
237  * Misc declr.
238  */
239 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver");
240 static SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD, 0, "Status device");
241
242 int             midi_debug;
243 /* XXX: should this be moved into debug.midi? */
244 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
245
246 int             midi_dumpraw;
247 SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, "");
248
249 int             midi_instroff;
250 SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, "");
251
252 int             midistat_verbose;
253 SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW, 
254         &midistat_verbose, 0, "");
255
256 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a
257 /*
258  * CODE START
259  */
260
261 /*
262  * Register a new rmidi device. cls midi_if interface unit == 0 means
263  * auto-assign new unit number unit != 0 already assigned a unit number, eg.
264  * not the first channel provided by this device. channel,      sub-unit
265  * cookie is passed back on MPU calls Typical device drivers will call with
266  * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
267  * what unit number is used.
268  *
269  * It is an error to call midi_init with an already used unit/channel combo.
270  *
271  * Returns NULL on error
272  *
273  */
274 struct snd_midi *
275 midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
276 {
277         struct snd_midi *m;
278         int i;
279         int inqsize, outqsize;
280         MIDI_TYPE *buf;
281
282         MIDI_DEBUG(1, kprintf("midiinit: unit %d/%d.\n", unit, channel));
283         lockmgr(&midistat_lock, LK_EXCLUSIVE);
284         /*
285          * Protect against call with existing unit/channel or auto-allocate a
286          * new unit number.
287          */
288         i = -1;
289         TAILQ_FOREACH(m, &midi_devs, link) {
290                 lockmgr(&m->lock, LK_EXCLUSIVE);
291                 if (unit != 0) {
292                         if (m->unit == unit && m->channel == channel) {
293                                 lockmgr(&m->lock, LK_RELEASE);
294                                 goto err0;
295                         }
296                 } else {
297                         /*
298                          * Find a better unit number
299                          */
300                         if (m->unit > i)
301                                 i = m->unit;
302                 }
303                 lockmgr(&m->lock, LK_RELEASE);
304         }
305
306         if (unit == 0)
307                 unit = i + 1;
308
309         MIDI_DEBUG(1, kprintf("midiinit #2: unit %d/%d.\n", unit, channel));
310         m = kmalloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO);
311
312         m->synth = kmalloc(sizeof(*m->synth), M_MIDI, M_WAITOK | M_ZERO);
313         kobj_init((kobj_t)m->synth, &midisynth_class);
314         m->synth->m = m;
315         kobj_init((kobj_t)m, cls);
316         inqsize = MPU_INQSIZE(m, cookie);
317         outqsize = MPU_OUTQSIZE(m, cookie);
318
319         MIDI_DEBUG(1, kprintf("midiinit queues %d/%d.\n", inqsize, outqsize));
320         if (!inqsize && !outqsize)
321                 goto err1;
322
323         lockinit(&m->lock, "raw midi", 0, LK_CANRECURSE);
324         lockinit(&m->qlock, "q raw midi", 0, LK_CANRECURSE);
325
326         lockmgr(&m->lock, LK_EXCLUSIVE);
327         lockmgr(&m->qlock, LK_EXCLUSIVE);
328
329         if (inqsize)
330                 buf = kmalloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_WAITOK);
331         else
332                 buf = NULL;
333
334         MIDIQ_INIT(m->inq, buf, inqsize);
335
336         if (outqsize)
337                 buf = kmalloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_WAITOK);
338         else
339                 buf = NULL;
340         m->hiwat = outqsize / 2;
341
342         MIDIQ_INIT(m->outq, buf, outqsize);
343
344         if ((inqsize && !MIDIQ_BUF(m->inq)) ||
345             (outqsize && !MIDIQ_BUF(m->outq)))
346                 goto err2;
347
348
349         m->busy = 0;
350         m->flags = 0;
351         m->unit = unit;
352         m->channel = channel;
353         m->cookie = cookie;
354
355         if (MPU_INIT(m, cookie))
356                 goto err2;
357
358         lockmgr(&m->lock, LK_RELEASE);
359         lockmgr(&m->qlock, LK_RELEASE);
360
361         TAILQ_INSERT_TAIL(&midi_devs, m, link);
362
363         lockmgr(&midistat_lock, LK_RELEASE);
364
365         m->dev = make_dev(&midi_ops,
366             MIDIMKMINOR(unit, MIDI_DEV_RAW, channel),
367             UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel);
368         m->dev->si_drv1 = m;
369
370         return m;
371
372 err2:
373         lockuninit(&m->qlock);
374         lockuninit(&m->lock);
375
376         if (MIDIQ_BUF(m->inq))
377                 kfree(MIDIQ_BUF(m->inq), M_MIDI);
378         if (MIDIQ_BUF(m->outq))
379                 kfree(MIDIQ_BUF(m->outq), M_MIDI);
380 err1:
381         kfree(m, M_MIDI);
382 err0:
383         lockmgr(&midistat_lock, LK_RELEASE);
384         MIDI_DEBUG(1, kprintf("midi_init ended in error\n"));
385         return NULL;
386 }
387
388 /*
389  * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
390  * entry point. midi_unint if fact, does not send any methods. A call to
391  * midi_uninit is a defacto promise that you won't manipulate ch anymore
392  *
393  */
394
395 int
396 midi_uninit(struct snd_midi *m)
397 {
398         int err;
399
400         err = ENXIO;
401         lockmgr(&midistat_lock, LK_EXCLUSIVE);
402         lockmgr(&m->lock, LK_EXCLUSIVE);
403         if (m->busy) {
404                 if (!(m->rchan || m->wchan))
405                         goto err;
406
407                 if (m->rchan) {
408                         wakeup(&m->rchan);
409                         m->rchan = 0;
410                 }
411                 if (m->wchan) {
412                         wakeup(&m->wchan);
413                         m->wchan = 0;
414                 }
415         }
416         err = midi_destroy(m, 0);
417         if (!err)
418                 goto exit;
419
420 err:    lockmgr(&m->lock, LK_RELEASE);
421 exit:   lockmgr(&midistat_lock, LK_RELEASE);
422         return err;
423 }
424
425 /*
426  * midi_in: process all data until the queue is full, then discards the rest.
427  * Since midi_in is a state machine, data discards can cause it to get out of
428  * whack.  Process as much as possible.  It calls, wakeup, selnotify and
429  * psignal at most once.
430  */
431
432 #ifdef notdef
433 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
434
435 #endif                                  /* notdef */
436 /* Number of bytes in a MIDI command */
437 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
438 #define MIDI_ACK        0xfe
439 #define MIDI_IS_STATUS(d) ((d) >= 0x80)
440 #define MIDI_IS_COMMON(d) ((d) >= 0xf0)
441
442 #define MIDI_SYSEX_START        0xF0
443 #define MIDI_SYSEX_END      0xF7
444
445
446 int
447 midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size)
448 {
449         /* int             i, sig, enq; */
450         int used;
451
452         /* MIDI_TYPE       data; */
453         MIDI_DEBUG(5, kprintf("midi_in: m=%p size=%d\n", m, size));
454
455 /*
456  * XXX: locking flub
457  */
458         if (!(m->flags & M_RX))
459                 return size;
460
461         used = 0;
462
463         lockmgr(&m->qlock, LK_EXCLUSIVE);
464 #if 0
465         /*
466          * Don't bother queuing if not in read mode.  Discard everything and
467          * return size so the caller doesn't freak out.
468          */
469
470         if (!(m->flags & M_RX))
471                 return size;
472
473         for (i = sig = 0; i < size; i++) {
474
475                 data = buf[i];
476                 enq = 0;
477                 if (data == MIDI_ACK)
478                         continue;
479
480                 switch (m->inq_state) {
481                 case MIDI_IN_START:
482                         if (MIDI_IS_STATUS(data)) {
483                                 switch (data) {
484                                 case 0xf0:      /* Sysex */
485                                         m->inq_state = MIDI_IN_SYSEX;
486                                         break;
487                                 case 0xf1:      /* MTC quarter frame */
488                                 case 0xf3:      /* Song select */
489                                         m->inq_state = MIDI_IN_DATA;
490                                         enq = 1;
491                                         m->inq_left = 1;
492                                         break;
493                                 case 0xf2:      /* Song position pointer */
494                                         m->inq_state = MIDI_IN_DATA;
495                                         enq = 1;
496                                         m->inq_left = 2;
497                                         break;
498                                 default:
499                                         if (MIDI_IS_COMMON(data)) {
500                                                 enq = 1;
501                                                 sig = 1;
502                                         } else {
503                                                 m->inq_state = MIDI_IN_DATA;
504                                                 enq = 1;
505                                                 m->inq_status = data;
506                                                 m->inq_left = MIDI_LENGTH(data);
507                                         }
508                                         break;
509                                 }
510                         } else if (MIDI_IS_STATUS(m->inq_status)) {
511                                 m->inq_state = MIDI_IN_DATA;
512                                 if (!MIDIQ_FULL(m->inq)) {
513                                         used++;
514                                         MIDIQ_ENQ(m->inq, &m->inq_status, 1);
515                                 }
516                                 enq = 1;
517                                 m->inq_left = MIDI_LENGTH(m->inq_status) - 1;
518                         }
519                         break;
520                         /*
521                          * End of case MIDI_IN_START:
522                          */
523
524                 case MIDI_IN_DATA:
525                         enq = 1;
526                         if (--m->inq_left <= 0)
527                                 sig = 1;/* deliver data */
528                         break;
529                 case MIDI_IN_SYSEX:
530                         if (data == MIDI_SYSEX_END)
531                                 m->inq_state = MIDI_IN_START;
532                         break;
533                 }
534
535                 if (enq)
536                         if (!MIDIQ_FULL(m->inq)) {
537                                 MIDIQ_ENQ(m->inq, &data, 1);
538                                 used++;
539                         }
540                 /*
541                  * End of the state machines main "for loop"
542                  */
543         }
544         if (sig) {
545 #endif
546                 MIDI_DEBUG(6, kprintf("midi_in: len %jd avail %jd\n",
547                     (intmax_t)MIDIQ_LEN(m->inq),
548                     (intmax_t)MIDIQ_AVAIL(m->inq)));
549                 if (MIDIQ_AVAIL(m->inq) > size) {
550                         used = size;
551                         MIDIQ_ENQ(m->inq, buf, size);
552                 } else {
553                         MIDI_DEBUG(4, kprintf("midi_in: Discarding data qu\n"));
554                         lockmgr(&m->qlock, LK_RELEASE);
555                         return 0;
556                 }
557                 if (m->rchan) {
558                         wakeup(&m->rchan);
559                         m->rchan = 0;
560                 }
561                 KNOTE(&m->rkq.ki_note, 0);
562                 if (m->async) {
563                         PHOLD(m->async);
564                         ksignal(m->async, SIGIO);
565                         PRELE(m->async);
566                 }
567 #if 0
568         }
569 #endif
570         lockmgr(&m->qlock, LK_RELEASE);
571         return used;
572 }
573
574 /*
575  * midi_out: The only clearer of the M_TXEN flag.
576  */
577 int
578 midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size)
579 {
580         int used;
581
582 /*
583  * XXX: locking flub
584  */
585         if (!(m->flags & M_TXEN))
586                 return 0;
587
588         MIDI_DEBUG(2, kprintf("midi_out: %p\n", m));
589         lockmgr(&m->qlock, LK_EXCLUSIVE);
590         used = MIN(size, MIDIQ_LEN(m->outq));
591         MIDI_DEBUG(3, kprintf("midi_out: used %d\n", used));
592         if (used)
593                 MIDIQ_DEQ(m->outq, buf, used);
594         if (MIDIQ_EMPTY(m->outq)) {
595                 m->flags &= ~M_TXEN;
596                 MPU_CALLBACKP(m, m->cookie, m->flags);
597         }
598         if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) {
599                 if (m->wchan) {
600                         wakeup(&m->wchan);
601                         m->wchan = 0;
602                 }
603                 KNOTE(&m->wkq.ki_note, 0);
604                 if (m->async) {
605                         PHOLD(m->async);
606                         ksignal(m->async, SIGIO);
607                         PRELE(m->async);
608                 }
609         }
610         lockmgr(&m->qlock, LK_RELEASE);
611         return used;
612 }
613
614
615 /*
616  * /dev/rmidi#.#        device access functions
617  */
618 int
619 midi_open(struct dev_open_args *ap)
620 {
621         cdev_t i_dev = ap->a_head.a_dev;
622         int flags = ap->a_oflags;
623         struct snd_midi *m = i_dev->si_drv1;
624         int retval;
625
626 #if 0 /* XXX */
627         MIDI_DEBUG(1, kprintf("midiopen %p %s %s\n", td,
628             flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
629 #endif
630         if (m == NULL)
631                 return ENXIO;
632
633         lockmgr(&m->lock, LK_EXCLUSIVE);
634         lockmgr(&m->qlock, LK_EXCLUSIVE);
635
636         retval = 0;
637
638         if (flags & FREAD) {
639                 if (MIDIQ_SIZE(m->inq) == 0)
640                         retval = ENXIO;
641                 else if (m->flags & M_RX)
642                         retval = EBUSY;
643                 if (retval)
644                         goto err;
645         }
646         if (flags & FWRITE) {
647                 if (MIDIQ_SIZE(m->outq) == 0)
648                         retval = ENXIO;
649                 else if (m->flags & M_TX)
650                         retval = EBUSY;
651                 if (retval)
652                         goto err;
653         }
654         m->busy++;
655
656         m->rchan = 0;
657         m->wchan = 0;
658         m->async = 0;
659
660         if (flags & FREAD) {
661                 m->flags |= M_RX | M_RXEN;
662                 /*
663                  * Only clear the inq, the outq might still have data to drain
664                  * from a previous session
665                  */
666                 MIDIQ_CLEAR(m->inq);
667         };
668
669         if (flags & FWRITE)
670                 m->flags |= M_TX;
671
672         MPU_CALLBACK(m, m->cookie, m->flags);
673
674         MIDI_DEBUG(2, kprintf("midi_open: opened.\n"));
675
676 err:    lockmgr(&m->qlock, LK_RELEASE);
677         lockmgr(&m->lock, LK_RELEASE);
678         return retval;
679 }
680
681 int
682 midi_close(struct dev_close_args *ap)
683 {
684         cdev_t i_dev = ap->a_head.a_dev;
685         int flags = ap->a_fflag;
686         struct snd_midi *m = i_dev->si_drv1;
687         int retval;
688         int oldflags;
689
690 #if 0 /* XXX */
691         MIDI_DEBUG(1, kprintf("midi_close %p %s %s\n", td,
692             flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
693 #endif
694
695         if (m == NULL)
696                 return ENXIO;
697
698         lockmgr(&m->lock, LK_EXCLUSIVE);
699         lockmgr(&m->qlock, LK_EXCLUSIVE);
700
701         if ((flags & FREAD && !(m->flags & M_RX)) ||
702             (flags & FWRITE && !(m->flags & M_TX))) {
703                 retval = ENXIO;
704                 goto err;
705         }
706         m->busy--;
707
708         oldflags = m->flags;
709
710         if (flags & FREAD)
711                 m->flags &= ~(M_RX | M_RXEN);
712         if (flags & FWRITE)
713                 m->flags &= ~M_TX;
714
715         if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
716                 MPU_CALLBACK(m, m->cookie, m->flags);
717
718         MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy));
719
720         lockmgr(&m->qlock, LK_RELEASE);
721         lockmgr(&m->lock, LK_RELEASE);
722         retval = 0;
723 err:    return retval;
724 }
725
726 /*
727  * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
728  * as data is available.
729  */
730 int
731 midi_read(struct dev_read_args *ap)
732 {
733         cdev_t i_dev = ap->a_head.a_dev;
734         struct uio *uio = ap->a_uio;
735         int ioflag = ap->a_ioflag;
736 #define MIDI_RSIZE 32
737         struct snd_midi *m = i_dev->si_drv1;
738         int retval;
739         int used;
740         char buf[MIDI_RSIZE];
741
742         MIDI_DEBUG(5, kprintf("midiread: count=%lu\n",
743             (unsigned long)uio->uio_resid));
744
745         retval = EIO;
746
747         if (m == NULL)
748                 goto err0;
749
750         lockmgr(&m->lock, LK_EXCLUSIVE);
751         lockmgr(&m->qlock, LK_EXCLUSIVE);
752
753         if (!(m->flags & M_RX))
754                 goto err1;
755
756         while (uio->uio_resid > 0) {
757                 while (MIDIQ_EMPTY(m->inq)) {
758                         retval = EWOULDBLOCK;
759                         if (ioflag & O_NONBLOCK)
760                                 goto err1;
761                         lockmgr(&m->lock, LK_RELEASE);
762                         m->rchan = 1;
763                         retval = lksleep(&m->rchan, &m->qlock,
764                             PCATCH, "midi RX", 0);
765                         /*
766                          * We slept, maybe things have changed since last
767                          * dying check
768                          */
769                         if (retval == EINTR)
770                                 goto err0;
771                         if (m != i_dev->si_drv1)
772                                 retval = ENXIO;
773                         /* if (retval && retval != ERESTART) */
774                         if (retval)
775                                 goto err0;
776                         lockmgr(&m->lock, LK_EXCLUSIVE);
777                         lockmgr(&m->qlock, LK_EXCLUSIVE);
778                         m->rchan = 0;
779                         if (!m->busy)
780                                 goto err1;
781                 }
782                 MIDI_DEBUG(6, kprintf("midi_read start\n"));
783                 /*
784                  * At this point, it is certain that m->inq has data
785                  */
786
787                 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
788                 used = MIN(used, MIDI_RSIZE);
789
790                 MIDI_DEBUG(6, kprintf("midiread: uiomove cc=%d\n", used));
791                 MIDIQ_DEQ(m->inq, buf, used);
792                 retval = uiomove(buf, used, uio);
793                 if (retval)
794                         goto err1;
795         }
796
797         /*
798          * If we Made it here then transfer is good
799          */
800         retval = 0;
801 err1:   lockmgr(&m->qlock, LK_RELEASE);
802         lockmgr(&m->lock, LK_RELEASE);
803 err0:   MIDI_DEBUG(4, kprintf("midi_read: ret %d\n", retval));
804         return retval;
805 }
806
807 /*
808  * midi_write: The only setter of M_TXEN
809  */
810
811 int
812 midi_write(struct dev_write_args *ap)
813 {
814         cdev_t i_dev = ap->a_head.a_dev;
815         struct uio *uio = ap->a_uio;
816         int ioflag = ap->a_ioflag;
817 #define MIDI_WSIZE 32
818         struct snd_midi *m = i_dev->si_drv1;
819         int retval;
820         int used;
821         char buf[MIDI_WSIZE];
822
823
824         MIDI_DEBUG(4, kprintf("midi_write\n"));
825         retval = 0;
826         if (m == NULL)
827                 goto err0;
828
829         lockmgr(&m->lock, LK_EXCLUSIVE);
830         lockmgr(&m->qlock, LK_EXCLUSIVE);
831
832         if (!(m->flags & M_TX))
833                 goto err1;
834
835         while (uio->uio_resid > 0) {
836                 while (MIDIQ_AVAIL(m->outq) == 0) {
837                         retval = EWOULDBLOCK;
838                         if (ioflag & O_NONBLOCK)
839                                 goto err1;
840                         lockmgr(&m->lock, LK_RELEASE);
841                         m->wchan = 1;
842                         MIDI_DEBUG(3, kprintf("midi_write lksleep\n"));
843                         retval = lksleep(&m->wchan, &m->qlock,
844                             PCATCH, "midi TX", 0);
845                         /*
846                          * We slept, maybe things have changed since last
847                          * dying check
848                          */
849                         if (retval == EINTR)
850                                 goto err0;
851                         if (m != i_dev->si_drv1)
852                                 retval = ENXIO;
853                         if (retval)
854                                 goto err0;
855                         lockmgr(&m->lock, LK_EXCLUSIVE);
856                         lockmgr(&m->qlock, LK_EXCLUSIVE);
857                         m->wchan = 0;
858                         if (!m->busy)
859                                 goto err1;
860                 }
861
862                 /*
863                  * We are certain than data can be placed on the queue
864                  */
865
866                 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid);
867                 used = MIN(used, MIDI_WSIZE);
868                 MIDI_DEBUG(5, kprintf("midiout: resid %zd len %jd avail %jd\n",
869                     uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq),
870                     (intmax_t)MIDIQ_AVAIL(m->outq)));
871
872
873                 MIDI_DEBUG(5, kprintf("midi_write: uiomove cc=%d\n", used));
874                 retval = uiomove(buf, used, uio);
875                 if (retval)
876                         goto err1;
877                 MIDIQ_ENQ(m->outq, buf, used);
878                 /*
879                  * Inform the bottom half that data can be written
880                  */
881                 if (!(m->flags & M_TXEN)) {
882                         m->flags |= M_TXEN;
883                         MPU_CALLBACK(m, m->cookie, m->flags);
884                 }
885         }
886         /*
887          * If we Made it here then transfer is good
888          */
889         retval = 0;
890 err1:   lockmgr(&m->qlock, LK_RELEASE);
891         lockmgr(&m->lock, LK_RELEASE);
892 err0:   return retval;
893 }
894
895 int
896 midi_ioctl(struct dev_ioctl_args *ap)
897 {
898         return ENXIO;
899 }
900
901 int
902 midi_kqfilter(struct dev_kqfilter_args *ap)
903 {
904         cdev_t dev = ap->a_head.a_dev;
905         struct knote *kn = ap->a_kn;
906         struct snd_midi *m;
907         struct klist *klist;
908
909         ap->a_result = 0;
910         m = dev->si_drv1;
911
912         switch (kn->kn_filter) {
913         case EVFILT_READ:
914                 kn->kn_fop = &midi_read_filterops;
915                 kn->kn_hook = (caddr_t)m;
916                 klist = &m->rkq.ki_note;
917                 break;
918         case EVFILT_WRITE:
919                 kn->kn_fop = &midi_write_filterops;
920                 kn->kn_hook = (caddr_t)m;
921                 klist = &m->wkq.ki_note;
922                 break;
923         default:
924                 ap->a_result = EOPNOTSUPP;
925                 return (0);
926         }
927
928         knote_insert(klist, kn);
929
930         return(0);
931 }
932
933 static void
934 midi_filter_detach(struct knote *kn)
935 {
936         struct snd_midi *m = (struct snd_midi *)kn->kn_hook;
937         struct klist *rklist = &m->rkq.ki_note;
938         struct klist *wklist = &m->wkq.ki_note;
939
940         knote_remove(rklist, kn);
941         knote_remove(wklist, kn);
942 }
943
944 static int
945 midi_filter_read(struct knote *kn, long hint)
946 {
947         struct snd_midi *m = (struct snd_midi *)kn->kn_hook;
948         int ready = 0;
949
950         lockmgr(&m->lock, LK_EXCLUSIVE);
951         lockmgr(&m->qlock, LK_EXCLUSIVE);
952
953         if (!MIDIQ_EMPTY(m->inq))
954                 ready = 1;
955
956         lockmgr(&m->lock, LK_RELEASE);
957         lockmgr(&m->qlock, LK_RELEASE);
958
959         return (ready);
960 }
961
962 static int
963 midi_filter_write(struct knote *kn, long hint)
964 {
965         struct snd_midi *m = (struct snd_midi *)kn->kn_hook;
966         int ready = 0;
967
968         lockmgr(&m->lock, LK_EXCLUSIVE);
969         lockmgr(&m->qlock, LK_EXCLUSIVE);
970
971         if (MIDIQ_AVAIL(m->outq) < m->hiwat)
972                 ready = 1;
973
974         lockmgr(&m->lock, LK_RELEASE);
975         lockmgr(&m->qlock, LK_RELEASE);
976
977         return (ready);
978 }
979
980 /*
981  * /dev/midistat device functions
982  *
983  */
984 static int
985 midistat_open(struct dev_open_args *ap)
986 {
987         int error;
988
989         MIDI_DEBUG(1, kprintf("midistat_open\n"));
990         lockmgr(&midistat_lock, LK_EXCLUSIVE);
991
992         if (midistat_isopen) {
993                 lockmgr(&midistat_lock, LK_RELEASE);
994                 return EBUSY;
995         }
996         midistat_isopen = 1;
997
998         if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
999                 error = ENXIO;
1000                 goto out;
1001         }
1002         error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM;
1003
1004 out:
1005         if (error)
1006                 midistat_isopen = 0;
1007         lockmgr(&midistat_lock, LK_RELEASE);
1008         return error;
1009 }
1010
1011 static int
1012 midistat_close(struct dev_close_args *ap)
1013 {
1014         MIDI_DEBUG(1, kprintf("midistat_close\n"));
1015         lockmgr(&midistat_lock, LK_EXCLUSIVE);
1016         if (!midistat_isopen) {
1017                 lockmgr(&midistat_lock, LK_RELEASE);
1018                 return EBADF;
1019         }
1020         sbuf_delete(&midistat_sbuf);
1021         midistat_isopen = 0;
1022
1023         lockmgr(&midistat_lock, LK_RELEASE);
1024         return 0;
1025 }
1026
1027 static int
1028 midistat_read(struct dev_read_args *ap)
1029 {
1030         struct uio *uio = ap->a_uio;
1031         int l, err;
1032
1033         MIDI_DEBUG(4, kprintf("midistat_read\n"));
1034         lockmgr(&midistat_lock, LK_EXCLUSIVE);
1035         if (!midistat_isopen) {
1036                 lockmgr(&midistat_lock, LK_RELEASE);
1037                 return EBADF;
1038         }
1039         l = min(uio->uio_resid, sbuf_len(&midistat_sbuf) - uio->uio_offset);
1040         err = 0;
1041         if (l > 0) {
1042                 err = uiomove(sbuf_data(&midistat_sbuf) + uio->uio_offset,
1043                               l, uio);
1044         }
1045         lockmgr(&midistat_lock, LK_RELEASE);
1046
1047         return err;
1048 }
1049
1050 /*
1051  * Module library functions
1052  */
1053
1054 static int
1055 midistat_prepare(struct sbuf *s)
1056 {
1057         struct snd_midi *m;
1058
1059         KKASSERT(lockowned(&midistat_lock));
1060
1061         sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n");
1062         if (TAILQ_EMPTY(&midi_devs)) {
1063                 sbuf_printf(s, "No devices installed.\n");
1064                 sbuf_finish(s);
1065                 return sbuf_len(s);
1066         }
1067         sbuf_printf(s, "Installed devices:\n");
1068
1069         TAILQ_FOREACH(m, &midi_devs, link) {
1070                 lockmgr(&m->lock, LK_EXCLUSIVE);
1071                 sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel,
1072                     MPU_PROVIDER(m, m->cookie));
1073                 sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose));
1074                 sbuf_printf(s, "\n");
1075                 lockmgr(&m->lock, LK_RELEASE);
1076         }
1077
1078         sbuf_finish(s);
1079         return sbuf_len(s);
1080 }
1081
1082 #ifdef notdef
1083 /*
1084  * Convert IOCTL command to string for debugging
1085  */
1086
1087 static char *
1088 midi_cmdname(int cmd)
1089 {
1090         static struct {
1091                 int     cmd;
1092                 char   *name;
1093         }     *tab, cmdtab_midiioctl[] = {
1094 #define A(x)    {x, ## x}
1095                 /*
1096                  * Once we have some real IOCTLs define, the following will
1097                  * be relavant.
1098                  *
1099                  * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE),
1100                  * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO),
1101                  * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL),
1102                  * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE),
1103                  * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE),
1104                  * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT),
1105                  * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC),
1106                  * A(AIOGCAP),
1107                  */
1108 #undef A
1109                 {
1110                         -1, "unknown"
1111                 },
1112         };
1113
1114         for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++);
1115         return tab->name;
1116 }
1117
1118 #endif                                  /* notdef */
1119
1120 /*
1121  * midisynth
1122  */
1123
1124
1125 int
1126 midisynth_open(void *n, void *arg, int flags)
1127 {
1128         struct snd_midi *m = ((struct synth_midi *)n)->m;
1129         int retval;
1130
1131         MIDI_DEBUG(1, kprintf("midisynth_open %s %s\n",
1132             flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
1133
1134         if (m == NULL)
1135                 return ENXIO;
1136
1137         lockmgr(&m->lock, LK_EXCLUSIVE);
1138         lockmgr(&m->qlock, LK_EXCLUSIVE);
1139
1140         retval = 0;
1141
1142         if (flags & FREAD) {
1143                 if (MIDIQ_SIZE(m->inq) == 0)
1144                         retval = ENXIO;
1145                 else if (m->flags & M_RX)
1146                         retval = EBUSY;
1147                 if (retval)
1148                         goto err;
1149         }
1150         if (flags & FWRITE) {
1151                 if (MIDIQ_SIZE(m->outq) == 0)
1152                         retval = ENXIO;
1153                 else if (m->flags & M_TX)
1154                         retval = EBUSY;
1155                 if (retval)
1156                         goto err;
1157         }
1158         m->busy++;
1159
1160         /*
1161          * TODO: Consider m->async = 0;
1162          */
1163
1164         if (flags & FREAD) {
1165                 m->flags |= M_RX | M_RXEN;
1166                 /*
1167                  * Only clear the inq, the outq might still have data to drain
1168                  * from a previous session
1169                  */
1170                 MIDIQ_CLEAR(m->inq);
1171                 m->rchan = 0;
1172         };
1173
1174         if (flags & FWRITE) {
1175                 m->flags |= M_TX;
1176                 m->wchan = 0;
1177         }
1178         m->synth_flags = flags & (FREAD | FWRITE);
1179
1180         MPU_CALLBACK(m, m->cookie, m->flags);
1181
1182
1183 err:    lockmgr(&m->qlock, LK_RELEASE);
1184         lockmgr(&m->lock, LK_RELEASE);
1185         MIDI_DEBUG(2, kprintf("midisynth_open: return %d.\n", retval));
1186         return retval;
1187 }
1188
1189 int
1190 midisynth_close(void *n)
1191 {
1192         struct snd_midi *m = ((struct synth_midi *)n)->m;
1193         int retval;
1194         int oldflags;
1195
1196         MIDI_DEBUG(1, kprintf("midisynth_close %s %s\n",
1197             m->synth_flags & FREAD ? "M_RX" : "",
1198             m->synth_flags & FWRITE ? "M_TX" : ""));
1199
1200         if (m == NULL)
1201                 return ENXIO;
1202
1203         lockmgr(&m->lock, LK_EXCLUSIVE);
1204         lockmgr(&m->qlock, LK_EXCLUSIVE);
1205
1206         if ((m->synth_flags & FREAD && !(m->flags & M_RX)) ||
1207             (m->synth_flags & FWRITE && !(m->flags & M_TX))) {
1208                 retval = ENXIO;
1209                 goto err;
1210         }
1211         m->busy--;
1212
1213         oldflags = m->flags;
1214
1215         if (m->synth_flags & FREAD)
1216                 m->flags &= ~(M_RX | M_RXEN);
1217         if (m->synth_flags & FWRITE)
1218                 m->flags &= ~M_TX;
1219
1220         if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
1221                 MPU_CALLBACK(m, m->cookie, m->flags);
1222
1223         MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy));
1224
1225         lockmgr(&m->qlock, LK_RELEASE);
1226         lockmgr(&m->lock, LK_RELEASE);
1227         retval = 0;
1228 err:    return retval;
1229 }
1230
1231 /*
1232  * Always blocking.
1233  */
1234
1235 int
1236 midisynth_writeraw(void *n, uint8_t *buf, size_t len)
1237 {
1238         struct snd_midi *m = ((struct synth_midi *)n)->m;
1239         int retval;
1240         int used;
1241         int i;
1242
1243         MIDI_DEBUG(4, kprintf("midisynth_writeraw\n"));
1244
1245         retval = 0;
1246
1247         if (m == NULL)
1248                 return ENXIO;
1249
1250         lockmgr(&m->lock, LK_EXCLUSIVE);
1251         lockmgr(&m->qlock, LK_EXCLUSIVE);
1252
1253         if (!(m->flags & M_TX))
1254                 goto err1;
1255
1256         if (midi_dumpraw)
1257                 kprintf("midi dump: ");
1258
1259         while (len > 0) {
1260                 while (MIDIQ_AVAIL(m->outq) == 0) {
1261                         if (!(m->flags & M_TXEN)) {
1262                                 m->flags |= M_TXEN;
1263                                 MPU_CALLBACK(m, m->cookie, m->flags);
1264                         }
1265                         lockmgr(&m->lock, LK_RELEASE);
1266                         m->wchan = 1;
1267                         MIDI_DEBUG(3, kprintf("midisynth_writeraw lksleep\n"));
1268                         retval = lksleep(&m->wchan, &m->qlock,
1269                             PCATCH, "midi TX", 0);
1270                         /*
1271                          * We slept, maybe things have changed since last
1272                          * dying check
1273                          */
1274                         if (retval == EINTR)
1275                                 goto err0;
1276
1277                         if (retval)
1278                                 goto err0;
1279                         lockmgr(&m->lock, LK_EXCLUSIVE);
1280                         lockmgr(&m->qlock, LK_EXCLUSIVE);
1281                         m->wchan = 0;
1282                         if (!m->busy)
1283                                 goto err1;
1284                 }
1285
1286                 /*
1287                  * We are certain than data can be placed on the queue
1288                  */
1289
1290                 used = MIN(MIDIQ_AVAIL(m->outq), len);
1291                 used = MIN(used, MIDI_WSIZE);
1292                 MIDI_DEBUG(5,
1293                     kprintf("midi_synth: resid %zu len %jd avail %jd\n",
1294                     len, (intmax_t)MIDIQ_LEN(m->outq),
1295                     (intmax_t)MIDIQ_AVAIL(m->outq)));
1296
1297                 if (midi_dumpraw)
1298                         for (i = 0; i < used; i++)
1299                                 kprintf("%x ", buf[i]);
1300
1301                 MIDIQ_ENQ(m->outq, buf, used);
1302                 len -= used;
1303
1304                 /*
1305                  * Inform the bottom half that data can be written
1306                  */
1307                 if (!(m->flags & M_TXEN)) {
1308                         m->flags |= M_TXEN;
1309                         MPU_CALLBACK(m, m->cookie, m->flags);
1310                 }
1311         }
1312         /*
1313          * If we Made it here then transfer is good
1314          */
1315         if (midi_dumpraw)
1316                 kprintf("\n");
1317
1318         retval = 0;
1319 err1:   lockmgr(&m->qlock, LK_RELEASE);
1320         lockmgr(&m->lock, LK_RELEASE);
1321 err0:   return retval;
1322 }
1323
1324 static int
1325 midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1326 {
1327         u_char c[3];
1328
1329
1330         if (note > 127 || chn > 15)
1331                 return (EINVAL);
1332
1333         if (vel > 127)
1334                 vel = 127;
1335
1336         if (vel == 64) {
1337                 c[0] = 0x90 | (chn & 0x0f);     /* Note on. */
1338                 c[1] = (u_char)note;
1339                 c[2] = 0;
1340         } else {
1341                 c[0] = 0x80 | (chn & 0x0f);     /* Note off. */
1342                 c[1] = (u_char)note;
1343                 c[2] = (u_char)vel;
1344         }
1345
1346         return midisynth_writeraw(n, c, 3);
1347 }
1348
1349 static int
1350 midisynth_setinstr(void *n, uint8_t chn, uint16_t instr)
1351 {
1352         u_char c[2];
1353
1354         if (instr > 127 || chn > 15)
1355                 return EINVAL;
1356
1357         c[0] = 0xc0 | (chn & 0x0f);     /* Progamme change. */
1358         c[1] = instr + midi_instroff;
1359
1360         return midisynth_writeraw(n, c, 2);
1361 }
1362
1363 static int
1364 midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1365 {
1366         u_char c[3];
1367
1368         if (note > 127 || chn > 15)
1369                 return EINVAL;
1370
1371         if (vel > 127)
1372                 vel = 127;
1373
1374         c[0] = 0x90 | (chn & 0x0f);     /* Note on. */
1375         c[1] = (u_char)note;
1376         c[2] = (u_char)vel;
1377
1378         return midisynth_writeraw(n, c, 3);
1379 }
1380 static int
1381 midisynth_alloc(void *n, uint8_t chan, uint8_t note)
1382 {
1383         return chan;
1384 }
1385
1386 static int
1387 midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val)
1388 {
1389         u_char c[3];
1390
1391         if (ctrlnum > 127 || chn > 15)
1392                 return EINVAL;
1393
1394         c[0] = 0xb0 | (chn & 0x0f);     /* Control Message. */
1395         c[1] = ctrlnum;
1396         c[2] = val;
1397         return midisynth_writeraw(n, c, 3);
1398 }
1399
1400 static int
1401 midisynth_bender(void *n, uint8_t chn, uint16_t val)
1402 {
1403         u_char c[3];
1404
1405
1406         if (val > 16383 || chn > 15)
1407                 return EINVAL;
1408
1409         c[0] = 0xe0 | (chn & 0x0f);     /* Pitch bend. */
1410         c[1] = (u_char)val & 0x7f;
1411         c[2] = (u_char)(val >> 7) & 0x7f;
1412
1413         return midisynth_writeraw(n, c, 3);
1414 }
1415
1416 /*
1417  * Single point of midi destructions.
1418  */
1419 static int
1420 midi_destroy(struct snd_midi *m, int midiuninit)
1421 {
1422
1423         KKASSERT(lockowned(&midistat_lock));
1424         KKASSERT(lockowned(&m->lock));
1425
1426         MIDI_DEBUG(3, kprintf("midi_destroy\n"));
1427         m->dev->si_drv1 = NULL;
1428         lockmgr(&m->lock, LK_RELEASE);  /* XXX */
1429         destroy_dev(m->dev);
1430         TAILQ_REMOVE(&midi_devs, m, link);
1431         if (midiuninit)
1432                 MPU_UNINIT(m, m->cookie);
1433         kfree(MIDIQ_BUF(m->inq), M_MIDI);
1434         kfree(MIDIQ_BUF(m->outq), M_MIDI);
1435         lockuninit(&m->qlock);
1436         lockuninit(&m->lock);
1437         kfree(m, M_MIDI);
1438         return 0;
1439 }
1440
1441 /*
1442  * Load and unload functions, creates the /dev/midistat device
1443  */
1444
1445 static int
1446 midi_load(void)
1447 {
1448         lockinit(&midistat_lock, "midistat lock", 0, LK_CANRECURSE);
1449         TAILQ_INIT(&midi_devs);         /* Initialize the queue. */
1450
1451         midistat_dev = make_dev(&midistat_ops,
1452             MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0),
1453             UID_ROOT, GID_WHEEL, 0666, "midistat");
1454
1455         return 0;
1456 }
1457
1458 static int
1459 midi_unload(void)
1460 {
1461         struct snd_midi *m;
1462         int retval;
1463
1464         MIDI_DEBUG(1, kprintf("midi_unload()\n"));
1465         retval = EBUSY;
1466         lockmgr(&midistat_lock, LK_EXCLUSIVE);
1467         if (midistat_isopen)
1468                 goto exit0;
1469
1470         TAILQ_FOREACH(m, &midi_devs, link) {
1471                 lockmgr(&m->lock, LK_EXCLUSIVE);
1472                 if (m->busy)
1473                         retval = EBUSY;
1474                 else
1475                         retval = midi_destroy(m, 1);
1476                 if (retval)
1477                         goto exit1;
1478         }
1479
1480         lockmgr(&midistat_lock, LK_RELEASE);    /* XXX */
1481
1482         destroy_dev(midistat_dev);
1483         /*
1484          * Made it here then unload is complete
1485          */
1486         lockuninit(&midistat_lock);
1487         return 0;
1488
1489 exit1:
1490         lockmgr(&m->lock, LK_RELEASE);
1491 exit0:
1492         lockmgr(&midistat_lock, LK_RELEASE);
1493         if (retval)
1494                 MIDI_DEBUG(2, kprintf("midi_unload: failed\n"));
1495         return retval;
1496 }
1497
1498 extern int seq_modevent(module_t mod, int type, void *data);
1499
1500 static int
1501 midi_modevent(module_t mod, int type, void *data)
1502 {
1503         int retval;
1504
1505         retval = 0;
1506
1507         switch (type) {
1508         case MOD_LOAD:
1509                 retval = midi_load();
1510 #if 0
1511                 if (retval == 0)
1512                         retval = seq_modevent(mod, type, data);
1513 #endif
1514                 break;
1515
1516         case MOD_UNLOAD:
1517                 retval = midi_unload();
1518 #if 0
1519                 if (retval == 0)
1520                         retval = seq_modevent(mod, type, data);
1521 #endif
1522                 break;
1523
1524         default:
1525                 break;
1526         }
1527
1528         return retval;
1529 }
1530
1531 kobj_t
1532 midimapper_addseq(void *arg1, int *unit, void **cookie)
1533 {
1534         unit = 0;
1535
1536         return (kobj_t)arg1;
1537 }
1538
1539 int
1540 midimapper_open(void *arg1, void **cookie)
1541 {
1542         int retval = 0;
1543         struct snd_midi *m;
1544
1545         lockmgr(&midistat_lock, LK_EXCLUSIVE);
1546
1547         TAILQ_FOREACH(m, &midi_devs, link) {
1548                 retval++;
1549         }
1550
1551         lockmgr(&midistat_lock, LK_RELEASE);
1552         return retval;
1553 }
1554
1555 int
1556 midimapper_close(void *arg1, void *cookie)
1557 {
1558         return 0;
1559 }
1560
1561 kobj_t
1562 midimapper_fetch_synth(void *arg, void *cookie, int unit)
1563 {
1564         struct snd_midi *m;
1565         int retval = 0;
1566
1567         lockmgr(&midistat_lock, LK_EXCLUSIVE);
1568
1569         TAILQ_FOREACH(m, &midi_devs, link) {
1570                 if (unit == retval) {
1571                         lockmgr(&midistat_lock, LK_RELEASE);
1572                         return (kobj_t)m->synth;
1573                 }
1574                 retval++;
1575         }
1576
1577         lockmgr(&midistat_lock, LK_RELEASE);
1578         return NULL;
1579 }
1580
1581 DEV_MODULE(midi, midi_modevent, NULL);
1582 MODULE_VERSION(midi, 1);