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