1166322Sjoel/*- 2166322Sjoel * Copyright (c) 2003 Mathew Kanner 3166322Sjoel * Copyright (c) 1993 Hannu Savolainen 4166322Sjoel * All rights reserved. 5166322Sjoel * 6158979Snetchild * Redistribution and use in source and binary forms, with or without 7166322Sjoel * modification, are permitted provided that the following conditions 8166322Sjoel * are met: 9166322Sjoel * 1. Redistributions of source code must retain the above copyright 10166322Sjoel * notice, this list of conditions and the following disclaimer. 11166322Sjoel * 2. Redistributions in binary form must reproduce the above copyright 12166322Sjoel * notice, this list of conditions and the following disclaimer in the 13166322Sjoel * documentation and/or other materials provided with the distribution. 14166322Sjoel * 15166322Sjoel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16166322Sjoel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17166322Sjoel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18166322Sjoel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19166322Sjoel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20166322Sjoel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21166322Sjoel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22166322Sjoel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23158979Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24158979Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25158979Snetchild * SUCH DAMAGE. 26158979Snetchild */ 27158979Snetchild 28166322Sjoel/* 29166322Sjoel * The sequencer personality manager. 30166322Sjoel */ 31166322Sjoel 32158979Snetchild#include <sys/cdefs.h> 33158979Snetchild__FBSDID("$FreeBSD: releng/11.0/sys/dev/sound/midi/sequencer.c 284865 2015-06-26 04:12:06Z adrian $"); 34158979Snetchild 35158979Snetchild#include <sys/param.h> 36158979Snetchild#include <sys/systm.h> 37158979Snetchild#include <sys/ioccom.h> 38158979Snetchild 39158979Snetchild#include <sys/filio.h> 40158979Snetchild#include <sys/lock.h> 41158979Snetchild#include <sys/sockio.h> 42158979Snetchild#include <sys/fcntl.h> 43158979Snetchild#include <sys/proc.h> 44158979Snetchild#include <sys/sysctl.h> 45158979Snetchild 46166971Snetchild#include <sys/kernel.h> /* for DATA_SET */ 47158979Snetchild 48158979Snetchild#include <sys/module.h> 49158979Snetchild#include <sys/conf.h> 50158979Snetchild#include <sys/file.h> 51158979Snetchild#include <sys/uio.h> 52158979Snetchild#include <sys/syslog.h> 53158979Snetchild#include <sys/errno.h> 54158979Snetchild#include <sys/malloc.h> 55158979Snetchild#include <sys/bus.h> 56158979Snetchild#include <machine/resource.h> 57158979Snetchild#include <machine/bus.h> 58166971Snetchild#include <machine/clock.h> /* for DELAY */ 59158979Snetchild#include <sys/soundcard.h> 60158979Snetchild#include <sys/rman.h> 61158979Snetchild#include <sys/mman.h> 62158979Snetchild#include <sys/poll.h> 63158979Snetchild#include <sys/mutex.h> 64158979Snetchild#include <sys/condvar.h> 65158979Snetchild#include <sys/kthread.h> 66158979Snetchild#include <sys/unistd.h> 67158979Snetchild#include <sys/selinfo.h> 68158979Snetchild 69193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 70193640Sariff#include "opt_snd.h" 71193640Sariff#endif 72158979Snetchild 73158979Snetchild#include <dev/sound/midi/midi.h> 74158979Snetchild#include <dev/sound/midi/midiq.h> 75158979Snetchild#include "synth_if.h" 76158979Snetchild 77158979Snetchild#include <dev/sound/midi/sequencer.h> 78158979Snetchild 79158979Snetchild#define TMR_TIMERBASE 13 80158979Snetchild 81166971Snetchild#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM 82166971Snetchild * synthesizer and MIDI output) */ 83166971Snetchild#define SND_DEV_MUSIC 8 /* /dev/music, level 2 interface */ 84158979Snetchild 85158979Snetchild/* Length of a sequencer event. */ 86158979Snetchild#define EV_SZ 8 87158979Snetchild#define IEV_SZ 8 88158979Snetchild 89158979Snetchild/* Lookup modes */ 90158979Snetchild#define LOOKUP_EXIST (0) 91158979Snetchild#define LOOKUP_OPEN (1) 92158979Snetchild#define LOOKUP_CLOSE (2) 93158979Snetchild 94158979Snetchild#define PCMMKMINOR(u, d, c) \ 95158979Snetchild ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) 96158979Snetchild#define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c) 97183397Sed#define MIDIUNIT(y) ((dev2unit(y) >> 4) & 0x0f) 98183397Sed#define MIDIDEV(y) (dev2unit(y) & 0x0f) 99158979Snetchild 100158979Snetchild/* These are the entries to the sequencer driver. */ 101284865Sadrianstatic d_open_t mseq_open; 102284865Sadrianstatic d_close_t mseq_close; 103284865Sadrianstatic d_ioctl_t mseq_ioctl; 104284865Sadrianstatic d_read_t mseq_read; 105284865Sadrianstatic d_write_t mseq_write; 106284865Sadrianstatic d_poll_t mseq_poll; 107158979Snetchild 108158979Snetchildstatic struct cdevsw seq_cdevsw = { 109158979Snetchild .d_version = D_VERSION, 110284865Sadrian .d_open = mseq_open, 111284865Sadrian .d_close = mseq_close, 112284865Sadrian .d_read = mseq_read, 113284865Sadrian .d_write = mseq_write, 114284865Sadrian .d_ioctl = mseq_ioctl, 115284865Sadrian .d_poll = mseq_poll, 116166971Snetchild .d_name = "sequencer", 117158979Snetchild}; 118158979Snetchild 119158979Snetchildstruct seq_softc { 120158979Snetchild KOBJ_FIELDS; 121158979Snetchild 122158979Snetchild struct mtx seq_lock, q_lock; 123158979Snetchild struct cv empty_cv, reset_cv, in_cv, out_cv, state_cv, th_cv; 124158979Snetchild 125158979Snetchild MIDIQ_HEAD(, u_char) in_q, out_q; 126158979Snetchild 127166971Snetchild u_long flags; 128158979Snetchild /* Flags (protected by flag_mtx of mididev_info) */ 129166971Snetchild int fflags; /* Access mode */ 130166971Snetchild int music; 131158979Snetchild 132166971Snetchild int out_water; /* Sequence output threshould */ 133166971Snetchild snd_sync_parm sync_parm; /* AIOSYNC parameter set */ 134166971Snetchild struct thread *sync_thread; /* AIOSYNCing thread */ 135158979Snetchild struct selinfo in_sel, out_sel; 136166971Snetchild int midi_number; 137158979Snetchild struct cdev *seqdev, *musicdev; 138166971Snetchild int unit; 139166971Snetchild int maxunits; 140158979Snetchild kobj_t *midis; 141166971Snetchild int *midi_flags; 142166971Snetchild kobj_t mapper; 143166971Snetchild void *mapper_cookie; 144158979Snetchild struct timeval timerstop, timersub; 145166971Snetchild int timerbase, tempo; 146166971Snetchild int timerrun; 147166971Snetchild int done; 148166971Snetchild int playing; 149166971Snetchild int recording; 150166971Snetchild int busy; 151166971Snetchild int pre_event_timeout; 152166971Snetchild int waiting; 153158979Snetchild}; 154158979Snetchild 155158979Snetchild/* 156158979Snetchild * Module specific stuff, including how many sequecers 157158979Snetchild * we currently own. 158158979Snetchild */ 159158979Snetchild 160158979SnetchildSYSCTL_NODE(_hw_midi, OID_AUTO, seq, CTLFLAG_RD, 0, "Midi sequencer"); 161158979Snetchild 162158979Snetchildint seq_debug; 163159732Snetchild/* XXX: should this be moved into debug.midi? */ 164158979SnetchildSYSCTL_INT(_hw_midi_seq, OID_AUTO, debug, CTLFLAG_RW, &seq_debug, 0, ""); 165158979Snetchild 166158979Snetchildmidi_cmdtab cmdtab_seqevent[] = { 167158979Snetchild {SEQ_NOTEOFF, "SEQ_NOTEOFF"}, 168158979Snetchild {SEQ_NOTEON, "SEQ_NOTEON"}, 169158979Snetchild {SEQ_WAIT, "SEQ_WAIT"}, 170158979Snetchild {SEQ_PGMCHANGE, "SEQ_PGMCHANGE"}, 171158979Snetchild {SEQ_SYNCTIMER, "SEQ_SYNCTIMER"}, 172158979Snetchild {SEQ_MIDIPUTC, "SEQ_MIDIPUTC"}, 173158979Snetchild {SEQ_DRUMON, "SEQ_DRUMON"}, 174158979Snetchild {SEQ_DRUMOFF, "SEQ_DRUMOFF"}, 175158979Snetchild {SEQ_ECHO, "SEQ_ECHO"}, 176158979Snetchild {SEQ_AFTERTOUCH, "SEQ_AFTERTOUCH"}, 177158979Snetchild {SEQ_CONTROLLER, "SEQ_CONTROLLER"}, 178158979Snetchild {SEQ_BALANCE, "SEQ_BALANCE"}, 179158979Snetchild {SEQ_VOLMODE, "SEQ_VOLMODE"}, 180158979Snetchild {SEQ_FULLSIZE, "SEQ_FULLSIZE"}, 181158979Snetchild {SEQ_PRIVATE, "SEQ_PRIVATE"}, 182158979Snetchild {SEQ_EXTENDED, "SEQ_EXTENDED"}, 183158979Snetchild {EV_SEQ_LOCAL, "EV_SEQ_LOCAL"}, 184158979Snetchild {EV_TIMING, "EV_TIMING"}, 185158979Snetchild {EV_CHN_COMMON, "EV_CHN_COMMON"}, 186158979Snetchild {EV_CHN_VOICE, "EV_CHN_VOICE"}, 187158979Snetchild {EV_SYSEX, "EV_SYSEX"}, 188158979Snetchild {-1, NULL}, 189158979Snetchild}; 190158979Snetchild 191158979Snetchildmidi_cmdtab cmdtab_seqioctl[] = { 192158979Snetchild {SNDCTL_SEQ_RESET, "SNDCTL_SEQ_RESET"}, 193158979Snetchild {SNDCTL_SEQ_SYNC, "SNDCTL_SEQ_SYNC"}, 194158979Snetchild {SNDCTL_SYNTH_INFO, "SNDCTL_SYNTH_INFO"}, 195158979Snetchild {SNDCTL_SEQ_CTRLRATE, "SNDCTL_SEQ_CTRLRATE"}, 196158979Snetchild {SNDCTL_SEQ_GETOUTCOUNT, "SNDCTL_SEQ_GETOUTCOUNT"}, 197158979Snetchild {SNDCTL_SEQ_GETINCOUNT, "SNDCTL_SEQ_GETINCOUNT"}, 198158979Snetchild {SNDCTL_SEQ_PERCMODE, "SNDCTL_SEQ_PERCMODE"}, 199158979Snetchild {SNDCTL_FM_LOAD_INSTR, "SNDCTL_FM_LOAD_INSTR"}, 200158979Snetchild {SNDCTL_SEQ_TESTMIDI, "SNDCTL_SEQ_TESTMIDI"}, 201158979Snetchild {SNDCTL_SEQ_RESETSAMPLES, "SNDCTL_SEQ_RESETSAMPLES"}, 202158979Snetchild {SNDCTL_SEQ_NRSYNTHS, "SNDCTL_SEQ_NRSYNTHS"}, 203158979Snetchild {SNDCTL_SEQ_NRMIDIS, "SNDCTL_SEQ_NRMIDIS"}, 204158979Snetchild {SNDCTL_SEQ_GETTIME, "SNDCTL_SEQ_GETTIME"}, 205158979Snetchild {SNDCTL_MIDI_INFO, "SNDCTL_MIDI_INFO"}, 206158979Snetchild {SNDCTL_SEQ_THRESHOLD, "SNDCTL_SEQ_THRESHOLD"}, 207158979Snetchild {SNDCTL_SYNTH_MEMAVL, "SNDCTL_SYNTH_MEMAVL"}, 208158979Snetchild {SNDCTL_FM_4OP_ENABLE, "SNDCTL_FM_4OP_ENABLE"}, 209158979Snetchild {SNDCTL_PMGR_ACCESS, "SNDCTL_PMGR_ACCESS"}, 210158979Snetchild {SNDCTL_SEQ_PANIC, "SNDCTL_SEQ_PANIC"}, 211158979Snetchild {SNDCTL_SEQ_OUTOFBAND, "SNDCTL_SEQ_OUTOFBAND"}, 212158979Snetchild {SNDCTL_TMR_TIMEBASE, "SNDCTL_TMR_TIMEBASE"}, 213158979Snetchild {SNDCTL_TMR_START, "SNDCTL_TMR_START"}, 214158979Snetchild {SNDCTL_TMR_STOP, "SNDCTL_TMR_STOP"}, 215158979Snetchild {SNDCTL_TMR_CONTINUE, "SNDCTL_TMR_CONTINUE"}, 216158979Snetchild {SNDCTL_TMR_TEMPO, "SNDCTL_TMR_TEMPO"}, 217158979Snetchild {SNDCTL_TMR_SOURCE, "SNDCTL_TMR_SOURCE"}, 218158979Snetchild {SNDCTL_TMR_METRONOME, "SNDCTL_TMR_METRONOME"}, 219158979Snetchild {SNDCTL_TMR_SELECT, "SNDCTL_TMR_SELECT"}, 220158979Snetchild {SNDCTL_MIDI_PRETIME, "SNDCTL_MIDI_PRETIME"}, 221158979Snetchild {AIONWRITE, "AIONWRITE"}, 222158979Snetchild {AIOGSIZE, "AIOGSIZE"}, 223158979Snetchild {AIOSSIZE, "AIOSSIZE"}, 224158979Snetchild {AIOGFMT, "AIOGFMT"}, 225158979Snetchild {AIOSFMT, "AIOSFMT"}, 226158979Snetchild {AIOGMIX, "AIOGMIX"}, 227158979Snetchild {AIOSMIX, "AIOSMIX"}, 228158979Snetchild {AIOSTOP, "AIOSTOP"}, 229158979Snetchild {AIOSYNC, "AIOSYNC"}, 230158979Snetchild {AIOGCAP, "AIOGCAP"}, 231158979Snetchild {-1, NULL}, 232158979Snetchild}; 233158979Snetchild 234158979Snetchildmidi_cmdtab cmdtab_timer[] = { 235158979Snetchild {TMR_WAIT_REL, "TMR_WAIT_REL"}, 236158979Snetchild {TMR_WAIT_ABS, "TMR_WAIT_ABS"}, 237158979Snetchild {TMR_STOP, "TMR_STOP"}, 238158979Snetchild {TMR_START, "TMR_START"}, 239158979Snetchild {TMR_CONTINUE, "TMR_CONTINUE"}, 240158979Snetchild {TMR_TEMPO, "TMR_TEMPO"}, 241158979Snetchild {TMR_ECHO, "TMR_ECHO"}, 242158979Snetchild {TMR_CLOCK, "TMR_CLOCK"}, 243158979Snetchild {TMR_SPP, "TMR_SPP"}, 244158979Snetchild {TMR_TIMESIG, "TMR_TIMESIG"}, 245158979Snetchild {-1, NULL}, 246158979Snetchild}; 247158979Snetchild 248158979Snetchildmidi_cmdtab cmdtab_seqcv[] = { 249158979Snetchild {MIDI_NOTEOFF, "MIDI_NOTEOFF"}, 250158979Snetchild {MIDI_NOTEON, "MIDI_NOTEON"}, 251158979Snetchild {MIDI_KEY_PRESSURE, "MIDI_KEY_PRESSURE"}, 252158979Snetchild {-1, NULL}, 253158979Snetchild}; 254158979Snetchild 255158979Snetchildmidi_cmdtab cmdtab_seqccmn[] = { 256158979Snetchild {MIDI_CTL_CHANGE, "MIDI_CTL_CHANGE"}, 257158979Snetchild {MIDI_PGM_CHANGE, "MIDI_PGM_CHANGE"}, 258158979Snetchild {MIDI_CHN_PRESSURE, "MIDI_CHN_PRESSURE"}, 259158979Snetchild {MIDI_PITCH_BEND, "MIDI_PITCH_BEND"}, 260158979Snetchild {MIDI_SYSTEM_PREFIX, "MIDI_SYSTEM_PREFIX"}, 261158979Snetchild {-1, NULL}, 262158979Snetchild}; 263158979Snetchild 264193640Sariff#ifndef KOBJMETHOD_END 265193640Sariff#define KOBJMETHOD_END { NULL, NULL } 266193640Sariff#endif 267193640Sariff 268158979Snetchild/* 269158979Snetchild * static const char *mpu401_mprovider(kobj_t obj, struct mpu401 *m); 270158979Snetchild */ 271158979Snetchild 272158979Snetchildstatic kobj_method_t seq_methods[] = { 273158979Snetchild /* KOBJMETHOD(mpu_provider,mpu401_mprovider), */ 274193640Sariff KOBJMETHOD_END 275158979Snetchild}; 276166971Snetchild 277158979SnetchildDEFINE_CLASS(sequencer, seq_methods, 0); 278158979Snetchild 279158979Snetchild/* The followings are the local function. */ 280158979Snetchildstatic int seq_convertold(u_char *event, u_char *out); 281166971Snetchild 282158979Snetchild/* 283158979Snetchild * static void seq_midiinput(struct seq_softc * scp, void *md); 284158979Snetchild */ 285166971Snetchildstatic void seq_reset(struct seq_softc *scp); 286166971Snetchildstatic int seq_sync(struct seq_softc *scp); 287158979Snetchild 288166971Snetchildstatic int seq_processevent(struct seq_softc *scp, u_char *event); 289158979Snetchild 290166971Snetchildstatic int seq_timing(struct seq_softc *scp, u_char *event); 291166971Snetchildstatic int seq_local(struct seq_softc *scp, u_char *event); 292158979Snetchild 293166971Snetchildstatic int seq_chnvoice(struct seq_softc *scp, kobj_t md, u_char *event); 294166971Snetchildstatic int seq_chncommon(struct seq_softc *scp, kobj_t md, u_char *event); 295166971Snetchildstatic int seq_sysex(struct seq_softc *scp, kobj_t md, u_char *event); 296158979Snetchild 297158979Snetchildstatic int seq_fetch_mid(struct seq_softc *scp, int unit, kobj_t *md); 298166971Snetchildvoid seq_copytoinput(struct seq_softc *scp, u_char *event, int len); 299166971Snetchildint seq_modevent(module_t mod, int type, void *data); 300158979Snetchildstruct seq_softc *seqs[10]; 301166971Snetchildstatic struct mtx seqinfo_mtx; 302166971Snetchildstatic u_long nseq = 0; 303158979Snetchild 304158979Snetchildstatic void timer_start(struct seq_softc *t); 305158979Snetchildstatic void timer_stop(struct seq_softc *t); 306158979Snetchildstatic void timer_setvals(struct seq_softc *t, int tempo, int timerbase); 307158979Snetchildstatic void timer_wait(struct seq_softc *t, int ticks, int wait_abs); 308158979Snetchildstatic int timer_now(struct seq_softc *t); 309158979Snetchild 310158979Snetchild 311158979Snetchildstatic void 312158979Snetchildtimer_start(struct seq_softc *t) 313158979Snetchild{ 314158979Snetchild t->timerrun = 1; 315158979Snetchild getmicrotime(&t->timersub); 316158979Snetchild} 317158979Snetchild 318158979Snetchildstatic void 319158979Snetchildtimer_continue(struct seq_softc *t) 320158979Snetchild{ 321158979Snetchild struct timeval now; 322158979Snetchild 323158979Snetchild if (t->timerrun == 1) 324166971Snetchild return; 325158979Snetchild t->timerrun = 1; 326158979Snetchild getmicrotime(&now); 327158979Snetchild timevalsub(&now, &t->timerstop); 328158979Snetchild timevaladd(&t->timersub, &now); 329158979Snetchild} 330158979Snetchild 331158979Snetchildstatic void 332158979Snetchildtimer_stop(struct seq_softc *t) 333158979Snetchild{ 334158979Snetchild t->timerrun = 0; 335158979Snetchild getmicrotime(&t->timerstop); 336158979Snetchild} 337158979Snetchild 338158979Snetchildstatic void 339158979Snetchildtimer_setvals(struct seq_softc *t, int tempo, int timerbase) 340158979Snetchild{ 341158979Snetchild t->tempo = tempo; 342158979Snetchild t->timerbase = timerbase; 343158979Snetchild} 344158979Snetchild 345158979Snetchildstatic void 346158979Snetchildtimer_wait(struct seq_softc *t, int ticks, int wait_abs) 347158979Snetchild{ 348158979Snetchild struct timeval now, when; 349158979Snetchild int ret; 350158979Snetchild unsigned long long i; 351158979Snetchild 352158979Snetchild while (t->timerrun == 0) { 353166971Snetchild SEQ_DEBUG(2, printf("Timer wait when timer isn't running\n")); 354166971Snetchild /* 355166971Snetchild * The old sequencer used timeouts that only increased 356166971Snetchild * the timer when the timer was running. 357166971Snetchild * Hence the sequencer would stick (?) if the 358166971Snetchild * timer was disabled. 359166971Snetchild */ 360166971Snetchild cv_wait(&t->reset_cv, &t->seq_lock); 361166971Snetchild if (t->playing == 0) 362166971Snetchild return; 363158979Snetchild } 364158979Snetchild 365158979Snetchild i = ticks * 60ull * 1000000ull / (t->tempo * t->timerbase); 366158979Snetchild 367158979Snetchild when.tv_sec = i / 1000000; 368158979Snetchild when.tv_usec = i % 1000000; 369158979Snetchild 370158979Snetchild#if 0 371166971Snetchild printf("timer_wait tempo %d timerbase %d ticks %d abs %d u_sec %llu\n", 372166971Snetchild t->tempo, t->timerbase, ticks, wait_abs, i); 373158979Snetchild#endif 374158979Snetchild 375158979Snetchild if (wait_abs != 0) { 376166971Snetchild getmicrotime(&now); 377166971Snetchild timevalsub(&now, &t->timersub); 378166971Snetchild timevalsub(&when, &now); 379158979Snetchild } 380158979Snetchild if (when.tv_sec < 0 || when.tv_usec < 0) { 381166971Snetchild SEQ_DEBUG(3, 382166971Snetchild printf("seq_timer error negative time %lds.%06lds\n", 383166971Snetchild (long)when.tv_sec, (long)when.tv_usec)); 384166971Snetchild return; 385158979Snetchild } 386158979Snetchild i = when.tv_sec * 1000000ull; 387158979Snetchild i += when.tv_usec; 388158979Snetchild i *= hz; 389158979Snetchild i /= 1000000ull; 390158979Snetchild#if 0 391166971Snetchild printf("seq_timer usec %llu ticks %llu\n", 392166971Snetchild when.tv_sec * 1000000ull + when.tv_usec, i); 393158979Snetchild#endif 394158979Snetchild t->waiting = 1; 395158979Snetchild ret = cv_timedwait(&t->reset_cv, &t->seq_lock, i + 1); 396158979Snetchild t->waiting = 0; 397158979Snetchild 398158979Snetchild if (ret != EWOULDBLOCK) 399166971Snetchild SEQ_DEBUG(3, printf("seq_timer didn't timeout\n")); 400158979Snetchild 401158979Snetchild} 402158979Snetchild 403158979Snetchildstatic int 404158979Snetchildtimer_now(struct seq_softc *t) 405158979Snetchild{ 406158979Snetchild struct timeval now; 407158979Snetchild unsigned long long i; 408158979Snetchild int ret; 409158979Snetchild 410158979Snetchild if (t->timerrun == 0) 411166971Snetchild now = t->timerstop; 412158979Snetchild else 413166971Snetchild getmicrotime(&now); 414158979Snetchild 415158979Snetchild timevalsub(&now, &t->timersub); 416158979Snetchild 417158979Snetchild i = now.tv_sec * 1000000ull; 418158979Snetchild i += now.tv_usec; 419158979Snetchild i *= t->timerbase; 420158979Snetchild/* i /= t->tempo; */ 421158979Snetchild i /= 1000000ull; 422158979Snetchild 423158979Snetchild ret = i; 424158979Snetchild /* 425158979Snetchild * printf("timer_now: %llu %d\n", i, ret); 426158979Snetchild */ 427158979Snetchild 428158979Snetchild return ret; 429158979Snetchild} 430158979Snetchild 431158979Snetchildstatic void 432158979Snetchildseq_eventthread(void *arg) 433158979Snetchild{ 434158979Snetchild struct seq_softc *scp = arg; 435158979Snetchild char event[EV_SZ]; 436158979Snetchild 437158979Snetchild mtx_lock(&scp->seq_lock); 438166971Snetchild SEQ_DEBUG(2, printf("seq_eventthread started\n")); 439166971Snetchild while (scp->done == 0) { 440158979Snetchildrestart: 441166971Snetchild while (scp->playing == 0) { 442166971Snetchild cv_wait(&scp->state_cv, &scp->seq_lock); 443166971Snetchild if (scp->done) 444166971Snetchild goto done; 445166971Snetchild } 446158979Snetchild 447166971Snetchild while (MIDIQ_EMPTY(scp->out_q)) { 448166971Snetchild cv_broadcast(&scp->empty_cv); 449166971Snetchild cv_wait(&scp->out_cv, &scp->seq_lock); 450166971Snetchild if (scp->playing == 0) 451166971Snetchild goto restart; 452166971Snetchild if (scp->done) 453166971Snetchild goto done; 454166971Snetchild } 455158979Snetchild 456166971Snetchild MIDIQ_DEQ(scp->out_q, event, EV_SZ); 457158979Snetchild 458166971Snetchild if (MIDIQ_AVAIL(scp->out_q) < scp->out_water) { 459166971Snetchild cv_broadcast(&scp->out_cv); 460166971Snetchild selwakeup(&scp->out_sel); 461166971Snetchild } 462166971Snetchild seq_processevent(scp, event); 463158979Snetchild } 464158979Snetchild 465158979Snetchilddone: 466158979Snetchild cv_broadcast(&scp->th_cv); 467158979Snetchild mtx_unlock(&scp->seq_lock); 468166971Snetchild SEQ_DEBUG(2, printf("seq_eventthread finished\n")); 469172836Sjulian kproc_exit(0); 470158979Snetchild} 471158979Snetchild 472158979Snetchild/* 473158979Snetchild * seq_processevent: This maybe called by the event thread or the IOCTL 474158979Snetchild * handler for queued and out of band events respectively. 475158979Snetchild */ 476158979Snetchildstatic int 477158979Snetchildseq_processevent(struct seq_softc *scp, u_char *event) 478158979Snetchild{ 479158979Snetchild int ret; 480158979Snetchild kobj_t m; 481158979Snetchild 482158979Snetchild ret = 0; 483158979Snetchild 484158979Snetchild if (event[0] == EV_SEQ_LOCAL) 485158979Snetchild ret = seq_local(scp, event); 486158979Snetchild else if (event[0] == EV_TIMING) 487158979Snetchild ret = seq_timing(scp, event); 488158979Snetchild else if (event[0] != EV_CHN_VOICE && 489166971Snetchild event[0] != EV_CHN_COMMON && 490166971Snetchild event[0] != EV_SYSEX && 491166971Snetchild event[0] != SEQ_MIDIPUTC) { 492158979Snetchild ret = 1; 493166971Snetchild SEQ_DEBUG(2, printf("seq_processevent not known %d\n", 494166971Snetchild event[0])); 495158979Snetchild } else if (seq_fetch_mid(scp, event[1], &m) != 0) { 496158979Snetchild ret = 1; 497166971Snetchild SEQ_DEBUG(2, printf("seq_processevent midi unit not found %d\n", 498166971Snetchild event[1])); 499166971Snetchild } else 500166971Snetchild switch (event[0]) { 501166971Snetchild case EV_CHN_VOICE: 502158979Snetchild ret = seq_chnvoice(scp, m, event); 503158979Snetchild break; 504158979Snetchild case EV_CHN_COMMON: 505158979Snetchild ret = seq_chncommon(scp, m, event); 506158979Snetchild break; 507158979Snetchild case EV_SYSEX: 508158979Snetchild ret = seq_sysex(scp, m, event); 509158979Snetchild break; 510158979Snetchild case SEQ_MIDIPUTC: 511158979Snetchild mtx_unlock(&scp->seq_lock); 512158979Snetchild ret = SYNTH_WRITERAW(m, &event[2], 1); 513158979Snetchild mtx_lock(&scp->seq_lock); 514158979Snetchild break; 515166971Snetchild } 516158979Snetchild return ret; 517158979Snetchild} 518158979Snetchild 519158979Snetchildstatic int 520158979Snetchildseq_addunit(void) 521158979Snetchild{ 522158979Snetchild struct seq_softc *scp; 523158979Snetchild int ret; 524158979Snetchild u_char *buf; 525158979Snetchild 526158979Snetchild /* Allocate the softc. */ 527158979Snetchild ret = ENOMEM; 528158979Snetchild scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO); 529158979Snetchild if (scp == NULL) { 530166971Snetchild SEQ_DEBUG(1, printf("seq_addunit: softc allocation failed.\n")); 531158979Snetchild goto err; 532158979Snetchild } 533166971Snetchild kobj_init((kobj_t)scp, &sequencer_class); 534158979Snetchild 535158979Snetchild buf = malloc(sizeof(*buf) * EV_SZ * 1024, M_TEMP, M_NOWAIT | M_ZERO); 536158979Snetchild if (buf == NULL) 537166971Snetchild goto err; 538158979Snetchild MIDIQ_INIT(scp->in_q, buf, EV_SZ * 1024); 539158979Snetchild buf = malloc(sizeof(*buf) * EV_SZ * 1024, M_TEMP, M_NOWAIT | M_ZERO); 540158979Snetchild if (buf == NULL) 541166971Snetchild goto err; 542158979Snetchild MIDIQ_INIT(scp->out_q, buf, EV_SZ * 1024); 543158979Snetchild ret = EINVAL; 544158979Snetchild 545158979Snetchild scp->midis = malloc(sizeof(kobj_t) * 32, M_TEMP, M_NOWAIT | M_ZERO); 546158979Snetchild scp->midi_flags = malloc(sizeof(*scp->midi_flags) * 32, M_TEMP, 547166971Snetchild M_NOWAIT | M_ZERO); 548158979Snetchild 549166971Snetchild if (scp->midis == NULL || scp->midi_flags == NULL) 550166971Snetchild goto err; 551158979Snetchild 552158979Snetchild scp->flags = 0; 553158979Snetchild 554167604Sariff mtx_init(&scp->seq_lock, "seqflq", NULL, 0); 555158979Snetchild cv_init(&scp->state_cv, "seqstate"); 556158979Snetchild cv_init(&scp->empty_cv, "seqempty"); 557158979Snetchild cv_init(&scp->reset_cv, "seqtimer"); 558158979Snetchild cv_init(&scp->out_cv, "seqqout"); 559158979Snetchild cv_init(&scp->in_cv, "seqqin"); 560158979Snetchild cv_init(&scp->th_cv, "seqstart"); 561158979Snetchild 562158979Snetchild /* 563158979Snetchild * Init the damn timer 564158979Snetchild */ 565158979Snetchild 566158979Snetchild scp->mapper = midimapper_addseq(scp, &scp->unit, &scp->mapper_cookie); 567158979Snetchild if (scp->mapper == NULL) 568166971Snetchild goto err; 569158979Snetchild 570158979Snetchild scp->seqdev = make_dev(&seq_cdevsw, 571166971Snetchild MIDIMKMINOR(scp->unit, SND_DEV_SEQ, 0), UID_ROOT, 572166971Snetchild GID_WHEEL, 0666, "sequencer%d", scp->unit); 573158979Snetchild 574158979Snetchild scp->musicdev = make_dev(&seq_cdevsw, 575166971Snetchild MIDIMKMINOR(scp->unit, SND_DEV_MUSIC, 0), UID_ROOT, 576166971Snetchild GID_WHEEL, 0666, "music%d", scp->unit); 577158979Snetchild 578158979Snetchild if (scp->seqdev == NULL || scp->musicdev == NULL) 579166971Snetchild goto err; 580158979Snetchild /* 581158979Snetchild * TODO: Add to list of sequencers this module provides 582158979Snetchild */ 583158979Snetchild 584193640Sariff ret = 585193640Sariff kproc_create 586193640Sariff (seq_eventthread, scp, NULL, RFHIGHPID, 0, 587166971Snetchild "sequencer %02d", scp->unit); 588158979Snetchild 589158979Snetchild if (ret) 590166971Snetchild goto err; 591158979Snetchild 592158979Snetchild scp->seqdev->si_drv1 = scp->musicdev->si_drv1 = scp; 593158979Snetchild 594166971Snetchild SEQ_DEBUG(2, printf("sequencer %d created scp %p\n", scp->unit, scp)); 595158979Snetchild 596158979Snetchild ret = 0; 597158979Snetchild 598158979Snetchild mtx_lock(&seqinfo_mtx); 599166971Snetchild seqs[nseq++] = scp; 600158979Snetchild mtx_unlock(&seqinfo_mtx); 601158979Snetchild 602158979Snetchild goto ok; 603158979Snetchild 604158979Snetchilderr: 605158979Snetchild if (scp != NULL) { 606166971Snetchild if (scp->seqdev != NULL) 607166971Snetchild destroy_dev(scp->seqdev); 608166971Snetchild if (scp->musicdev != NULL) 609166971Snetchild destroy_dev(scp->musicdev); 610166971Snetchild /* 611166971Snetchild * TODO: Destroy mutex and cv 612166971Snetchild */ 613166971Snetchild if (scp->midis != NULL) 614166971Snetchild free(scp->midis, M_TEMP); 615166971Snetchild if (scp->midi_flags != NULL) 616166971Snetchild free(scp->midi_flags, M_TEMP); 617166971Snetchild if (scp->out_q.b) 618166971Snetchild free(scp->out_q.b, M_TEMP); 619166971Snetchild if (scp->in_q.b) 620166971Snetchild free(scp->in_q.b, M_TEMP); 621166971Snetchild free(scp, M_DEVBUF); 622158979Snetchild } 623158979Snetchildok: 624158979Snetchild return ret; 625158979Snetchild} 626158979Snetchild 627158979Snetchildstatic int 628158979Snetchildseq_delunit(int unit) 629158979Snetchild{ 630158979Snetchild struct seq_softc *scp = seqs[unit]; 631158979Snetchild int i; 632158979Snetchild 633166971Snetchild //SEQ_DEBUG(4, printf("seq_delunit: %d\n", unit)); 634163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 1 \n")); 635158979Snetchild mtx_lock(&scp->seq_lock); 636158979Snetchild 637158979Snetchild scp->playing = 0; 638158979Snetchild scp->done = 1; 639158979Snetchild cv_broadcast(&scp->out_cv); 640158979Snetchild cv_broadcast(&scp->state_cv); 641158979Snetchild cv_broadcast(&scp->reset_cv); 642163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 2 \n")); 643158979Snetchild cv_wait(&scp->th_cv, &scp->seq_lock); 644163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 3.0 \n")); 645158979Snetchild mtx_unlock(&scp->seq_lock); 646163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 3.1 \n")); 647158979Snetchild 648158979Snetchild cv_destroy(&scp->state_cv); 649163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 4 \n")); 650158979Snetchild cv_destroy(&scp->empty_cv); 651163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 5 \n")); 652158979Snetchild cv_destroy(&scp->reset_cv); 653163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 6 \n")); 654158979Snetchild cv_destroy(&scp->out_cv); 655163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 7 \n")); 656158979Snetchild cv_destroy(&scp->in_cv); 657163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 8 \n")); 658158979Snetchild cv_destroy(&scp->th_cv); 659158979Snetchild 660163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 10 \n")); 661158979Snetchild if (scp->seqdev) 662166971Snetchild destroy_dev(scp->seqdev); 663163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 11 \n")); 664158979Snetchild if (scp->musicdev) 665166971Snetchild destroy_dev(scp->musicdev); 666163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 12 \n")); 667158979Snetchild scp->seqdev = scp->musicdev = NULL; 668158979Snetchild if (scp->midis != NULL) 669166971Snetchild free(scp->midis, M_TEMP); 670163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 13 \n")); 671158979Snetchild if (scp->midi_flags != NULL) 672166971Snetchild free(scp->midi_flags, M_TEMP); 673163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 14 \n")); 674158979Snetchild free(scp->out_q.b, M_TEMP); 675163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 15 \n")); 676158979Snetchild free(scp->in_q.b, M_TEMP); 677158979Snetchild 678163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 16 \n")); 679158979Snetchild 680158979Snetchild mtx_destroy(&scp->seq_lock); 681163364Sariff SEQ_DEBUG(1, printf("seq_delunit: 17 \n")); 682158979Snetchild free(scp, M_DEVBUF); 683158979Snetchild 684158979Snetchild mtx_lock(&seqinfo_mtx); 685166971Snetchild for (i = unit; i < (nseq - 1); i++) 686166971Snetchild seqs[i] = seqs[i + 1]; 687158979Snetchild nseq--; 688158979Snetchild mtx_unlock(&seqinfo_mtx); 689158979Snetchild 690158979Snetchild return 0; 691158979Snetchild} 692158979Snetchild 693158979Snetchildint 694158979Snetchildseq_modevent(module_t mod, int type, void *data) 695158979Snetchild{ 696158979Snetchild int retval, r; 697158979Snetchild 698158979Snetchild retval = 0; 699158979Snetchild 700158979Snetchild switch (type) { 701166971Snetchild case MOD_LOAD: 702167604Sariff mtx_init(&seqinfo_mtx, "seqmod", NULL, 0); 703158979Snetchild retval = seq_addunit(); 704158979Snetchild break; 705158979Snetchild 706166971Snetchild case MOD_UNLOAD: 707158979Snetchild while (nseq) { 708166971Snetchild r = seq_delunit(nseq - 1); 709158979Snetchild if (r) { 710158979Snetchild retval = r; 711158979Snetchild break; 712158979Snetchild } 713158979Snetchild } 714166971Snetchild if (nseq == 0) { 715158979Snetchild retval = 0; 716158979Snetchild mtx_destroy(&seqinfo_mtx); 717158979Snetchild } 718158979Snetchild break; 719158979Snetchild 720166971Snetchild default: 721158979Snetchild break; 722158979Snetchild } 723158979Snetchild 724158979Snetchild return retval; 725158979Snetchild} 726158979Snetchild 727158979Snetchildstatic int 728158979Snetchildseq_fetch_mid(struct seq_softc *scp, int unit, kobj_t *md) 729158979Snetchild{ 730158979Snetchild 731158979Snetchild if (unit > scp->midi_number || unit < 0) 732166971Snetchild return EINVAL; 733158979Snetchild 734158979Snetchild *md = scp->midis[unit]; 735158979Snetchild 736158979Snetchild return 0; 737158979Snetchild} 738158979Snetchild 739158979Snetchildint 740284865Sadrianmseq_open(struct cdev *i_dev, int flags, int mode, struct thread *td) 741158979Snetchild{ 742158979Snetchild struct seq_softc *scp = i_dev->si_drv1; 743158979Snetchild int i; 744158979Snetchild 745158979Snetchild if (scp == NULL) 746166971Snetchild return ENXIO; 747158979Snetchild 748166971Snetchild SEQ_DEBUG(3, printf("seq_open: scp %p unit %d, flags 0x%x.\n", 749166971Snetchild scp, scp->unit, flags)); 750158979Snetchild 751158979Snetchild /* 752166971Snetchild * Mark this device busy. 753158979Snetchild */ 754158979Snetchild 755158979Snetchild mtx_lock(&scp->seq_lock); 756158979Snetchild if (scp->busy) { 757158979Snetchild mtx_unlock(&scp->seq_lock); 758166971Snetchild SEQ_DEBUG(2, printf("seq_open: unit %d is busy.\n", scp->unit)); 759158979Snetchild return EBUSY; 760158979Snetchild } 761158979Snetchild scp->fflags = flags; 762158979Snetchild /* 763158979Snetchild if ((scp->fflags & O_NONBLOCK) != 0) 764158979Snetchild scp->flags |= SEQ_F_NBIO; 765158979Snetchild */ 766158979Snetchild scp->music = MIDIDEV(i_dev) == SND_DEV_MUSIC; 767158979Snetchild 768158979Snetchild /* 769158979Snetchild * Enumerate the available midi devices 770158979Snetchild */ 771158979Snetchild scp->midi_number = 0; 772158979Snetchild scp->maxunits = midimapper_open(scp->mapper, &scp->mapper_cookie); 773158979Snetchild 774158979Snetchild if (scp->maxunits == 0) 775166971Snetchild SEQ_DEBUG(2, printf("seq_open: no midi devices\n")); 776158979Snetchild 777166971Snetchild for (i = 0; i < scp->maxunits; i++) { 778166971Snetchild scp->midis[scp->midi_number] = 779166971Snetchild midimapper_fetch_synth(scp->mapper, scp->mapper_cookie, i); 780166971Snetchild if (scp->midis[scp->midi_number]) { 781166971Snetchild if (SYNTH_OPEN(scp->midis[scp->midi_number], scp, 782166971Snetchild scp->fflags) != 0) 783166971Snetchild scp->midis[scp->midi_number] = NULL; 784166971Snetchild else { 785166971Snetchild scp->midi_flags[scp->midi_number] = 786166971Snetchild SYNTH_QUERY(scp->midis[scp->midi_number]); 787166971Snetchild scp->midi_number++; 788166971Snetchild } 789158979Snetchild } 790158979Snetchild } 791158979Snetchild 792158979Snetchild timer_setvals(scp, 60, 100); 793158979Snetchild 794158979Snetchild timer_start(scp); 795158979Snetchild timer_stop(scp); 796158979Snetchild /* 797158979Snetchild * actually, if we're in rdonly mode, we should start the timer 798158979Snetchild */ 799158979Snetchild /* 800158979Snetchild * TODO: Handle recording now 801158979Snetchild */ 802158979Snetchild 803158979Snetchild scp->out_water = MIDIQ_SIZE(scp->out_q) / 2; 804158979Snetchild 805158979Snetchild scp->busy = 1; 806158979Snetchild mtx_unlock(&scp->seq_lock); 807158979Snetchild 808166971Snetchild SEQ_DEBUG(2, printf("seq_open: opened, mode %s.\n", 809166971Snetchild scp->music ? "music" : "sequencer")); 810166971Snetchild SEQ_DEBUG(2, 811166971Snetchild printf("Sequencer %d %p opened maxunits %d midi_number %d:\n", 812166971Snetchild scp->unit, scp, scp->maxunits, scp->midi_number)); 813166971Snetchild for (i = 0; i < scp->midi_number; i++) 814166971Snetchild SEQ_DEBUG(3, printf(" midi %d %p\n", i, scp->midis[i])); 815158979Snetchild 816158979Snetchild return 0; 817158979Snetchild} 818158979Snetchild 819158979Snetchild/* 820284865Sadrian * mseq_close 821158979Snetchild */ 822158979Snetchildint 823284865Sadrianmseq_close(struct cdev *i_dev, int flags, int mode, struct thread *td) 824158979Snetchild{ 825158979Snetchild int i; 826158979Snetchild struct seq_softc *scp = i_dev->si_drv1; 827158979Snetchild int ret; 828158979Snetchild 829158979Snetchild if (scp == NULL) 830166971Snetchild return ENXIO; 831158979Snetchild 832166971Snetchild SEQ_DEBUG(2, printf("seq_close: unit %d.\n", scp->unit)); 833158979Snetchild 834158979Snetchild mtx_lock(&scp->seq_lock); 835158979Snetchild 836158979Snetchild ret = ENXIO; 837158979Snetchild if (scp->busy == 0) 838166971Snetchild goto err; 839158979Snetchild 840158979Snetchild seq_reset(scp); 841158979Snetchild seq_sync(scp); 842158979Snetchild 843166971Snetchild for (i = 0; i < scp->midi_number; i++) 844166971Snetchild if (scp->midis[i]) 845166971Snetchild SYNTH_CLOSE(scp->midis[i]); 846158979Snetchild 847158979Snetchild midimapper_close(scp->mapper, scp->mapper_cookie); 848158979Snetchild 849158979Snetchild timer_stop(scp); 850158979Snetchild 851158979Snetchild scp->busy = 0; 852158979Snetchild ret = 0; 853158979Snetchild 854158979Snetchilderr: 855166971Snetchild SEQ_DEBUG(3, printf("seq_close: closed ret = %d.\n", ret)); 856158979Snetchild mtx_unlock(&scp->seq_lock); 857158979Snetchild return ret; 858158979Snetchild} 859158979Snetchild 860158979Snetchildint 861284865Sadrianmseq_read(struct cdev *i_dev, struct uio *uio, int ioflag) 862158979Snetchild{ 863158979Snetchild int retval, used; 864158979Snetchild struct seq_softc *scp = i_dev->si_drv1; 865166971Snetchild 866158979Snetchild#define SEQ_RSIZE 32 867158979Snetchild u_char buf[SEQ_RSIZE]; 868158979Snetchild 869158979Snetchild if (scp == NULL) 870166971Snetchild return ENXIO; 871158979Snetchild 872284865Sadrian SEQ_DEBUG(7, printf("mseq_read: unit %d, resid %zd.\n", 873166971Snetchild scp->unit, uio->uio_resid)); 874158979Snetchild 875158979Snetchild mtx_lock(&scp->seq_lock); 876158979Snetchild if ((scp->fflags & FREAD) == 0) { 877284865Sadrian SEQ_DEBUG(2, printf("mseq_read: unit %d is not for reading.\n", 878166971Snetchild scp->unit)); 879166971Snetchild retval = EIO; 880166971Snetchild goto err1; 881158979Snetchild } 882158979Snetchild /* 883158979Snetchild * Begin recording. 884158979Snetchild */ 885158979Snetchild /* 886158979Snetchild * if ((scp->flags & SEQ_F_READING) == 0) 887158979Snetchild */ 888158979Snetchild /* 889158979Snetchild * TODO, start recording if not alread 890158979Snetchild */ 891158979Snetchild 892158979Snetchild /* 893158979Snetchild * I think the semantics are to return as soon 894158979Snetchild * as possible. 895158979Snetchild * Second thought, it doens't seem like midimoutain 896158979Snetchild * expects that at all. 897158979Snetchild * TODO: Look up in some sort of spec 898158979Snetchild */ 899158979Snetchild 900158979Snetchild while (uio->uio_resid > 0) { 901166971Snetchild while (MIDIQ_EMPTY(scp->in_q)) { 902166971Snetchild retval = EWOULDBLOCK; 903166971Snetchild /* 904166971Snetchild * I wish I knew which one to care about 905166971Snetchild */ 906158979Snetchild 907166971Snetchild if (scp->fflags & O_NONBLOCK) 908166971Snetchild goto err1; 909166971Snetchild if (ioflag & O_NONBLOCK) 910166971Snetchild goto err1; 911158979Snetchild 912166971Snetchild retval = cv_wait_sig(&scp->in_cv, &scp->seq_lock); 913166971Snetchild if (retval == EINTR) 914166971Snetchild goto err1; 915166971Snetchild } 916158979Snetchild 917166971Snetchild used = MIN(MIDIQ_LEN(scp->in_q), uio->uio_resid); 918166971Snetchild used = MIN(used, SEQ_RSIZE); 919158979Snetchild 920166971Snetchild SEQ_DEBUG(8, printf("midiread: uiomove cc=%d\n", used)); 921166971Snetchild MIDIQ_DEQ(scp->in_q, buf, used); 922166971Snetchild retval = uiomove(buf, used, uio); 923166971Snetchild if (retval) 924166971Snetchild goto err1; 925158979Snetchild } 926158979Snetchild 927158979Snetchild retval = 0; 928158979Snetchilderr1: 929158979Snetchild mtx_unlock(&scp->seq_lock); 930284865Sadrian SEQ_DEBUG(6, printf("mseq_read: ret %d, resid %zd.\n", 931166971Snetchild retval, uio->uio_resid)); 932158979Snetchild 933158979Snetchild return retval; 934158979Snetchild} 935158979Snetchild 936158979Snetchildint 937284865Sadrianmseq_write(struct cdev *i_dev, struct uio *uio, int ioflag) 938158979Snetchild{ 939158979Snetchild u_char event[EV_SZ], newevent[EV_SZ], ev_code; 940158979Snetchild struct seq_softc *scp = i_dev->si_drv1; 941158979Snetchild int retval; 942158979Snetchild int used; 943158979Snetchild 944194990Skib SEQ_DEBUG(7, printf("seq_write: unit %d, resid %zd.\n", 945166971Snetchild scp->unit, uio->uio_resid)); 946158979Snetchild 947158979Snetchild if (scp == NULL) 948166971Snetchild return ENXIO; 949158979Snetchild 950158979Snetchild mtx_lock(&scp->seq_lock); 951158979Snetchild 952158979Snetchild if ((scp->fflags & FWRITE) == 0) { 953166971Snetchild SEQ_DEBUG(2, printf("seq_write: unit %d is not for writing.\n", 954166971Snetchild scp->unit)); 955166971Snetchild retval = EIO; 956166971Snetchild goto err0; 957158979Snetchild } 958158979Snetchild while (uio->uio_resid > 0) { 959166971Snetchild while (MIDIQ_AVAIL(scp->out_q) == 0) { 960166971Snetchild retval = EWOULDBLOCK; 961166971Snetchild if (scp->fflags & O_NONBLOCK) 962166971Snetchild goto err0; 963166971Snetchild if (ioflag & O_NONBLOCK) 964166971Snetchild goto err0; 965166971Snetchild SEQ_DEBUG(8, printf("seq_write cvwait\n")); 966158979Snetchild 967166971Snetchild scp->playing = 1; 968166971Snetchild cv_broadcast(&scp->out_cv); 969166971Snetchild cv_broadcast(&scp->state_cv); 970158979Snetchild 971166971Snetchild retval = cv_wait_sig(&scp->out_cv, &scp->seq_lock); 972166971Snetchild /* 973166971Snetchild * We slept, maybe things have changed since last 974166971Snetchild * dying check 975166971Snetchild */ 976166971Snetchild if (retval == EINTR) 977166971Snetchild goto err0; 978158979Snetchild#if 0 979166971Snetchild /* 980166971Snetchild * Useless test 981166971Snetchild */ 982166971Snetchild if (scp != i_dev->si_drv1) 983166971Snetchild retval = ENXIO; 984158979Snetchild#endif 985166971Snetchild } 986158979Snetchild 987166971Snetchild used = MIN(uio->uio_resid, 4); 988158979Snetchild 989194990Skib SEQ_DEBUG(8, printf("seqout: resid %zd len %jd avail %jd\n", 990166971Snetchild uio->uio_resid, (intmax_t)MIDIQ_LEN(scp->out_q), 991166971Snetchild (intmax_t)MIDIQ_AVAIL(scp->out_q))); 992158979Snetchild 993166971Snetchild if (used != 4) { 994166971Snetchild retval = ENXIO; 995166971Snetchild goto err0; 996166971Snetchild } 997166971Snetchild retval = uiomove(event, used, uio); 998166971Snetchild if (retval) 999166971Snetchild goto err0; 1000158979Snetchild 1001166971Snetchild ev_code = event[0]; 1002166971Snetchild SEQ_DEBUG(8, printf("seq_write: unit %d, event %s.\n", 1003166971Snetchild scp->unit, midi_cmdname(ev_code, cmdtab_seqevent))); 1004158979Snetchild 1005166971Snetchild /* Have a look at the event code. */ 1006166971Snetchild if (ev_code == SEQ_FULLSIZE) { 1007158979Snetchild 1008166971Snetchild /* 1009166971Snetchild * TODO: restore code for SEQ_FULLSIZE 1010166971Snetchild */ 1011158979Snetchild#if 0 1012166971Snetchild /* 1013166971Snetchild * A long event, these are the patches/samples for a 1014166971Snetchild * synthesizer. 1015166971Snetchild */ 1016166971Snetchild midiunit = *(u_short *)&event[2]; 1017166971Snetchild mtx_lock(&sd->seq_lock); 1018166971Snetchild ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md); 1019166971Snetchild mtx_unlock(&sd->seq_lock); 1020166971Snetchild if (ret != 0) 1021166971Snetchild return (ret); 1022158979Snetchild 1023166971Snetchild SEQ_DEBUG(printf("seq_write: loading a patch to the unit %d.\n", midiunit)); 1024158979Snetchild 1025166971Snetchild ret = md->synth.loadpatch(md, *(short *)&event[0], buf, 1026166971Snetchild p + 4, count, 0); 1027166971Snetchild return (ret); 1028158979Snetchild#else 1029166971Snetchild /* 1030166971Snetchild * For now, just flush the darn buffer 1031166971Snetchild */ 1032166971Snetchild SEQ_DEBUG(2, 1033166971Snetchild printf("seq_write: SEQ_FULLSIZE flusing buffer.\n")); 1034166971Snetchild while (uio->uio_resid > 0) { 1035166971Snetchild retval = uiomove(event, EV_SZ, uio); 1036166971Snetchild if (retval) 1037166971Snetchild goto err0; 1038166971Snetchild 1039166971Snetchild } 1040166971Snetchild retval = 0; 1041158979Snetchild goto err0; 1042166971Snetchild#endif 1043158979Snetchild } 1044166971Snetchild retval = EINVAL; 1045166971Snetchild if (ev_code >= 128) { 1046158979Snetchild 1047166971Snetchild /* 1048166971Snetchild * Some sort of an extended event. The size is eight 1049166971Snetchild * bytes. scoop extra info. 1050166971Snetchild */ 1051166971Snetchild if (scp->music && ev_code == SEQ_EXTENDED) { 1052166971Snetchild SEQ_DEBUG(2, printf("seq_write: invalid level two event %x.\n", ev_code)); 1053166971Snetchild goto err0; 1054166971Snetchild } 1055166971Snetchild if (uiomove((caddr_t)&event[4], 4, uio)) { 1056166971Snetchild SEQ_DEBUG(2, 1057166971Snetchild printf("seq_write: user memory mangled?\n")); 1058166971Snetchild goto err0; 1059166971Snetchild } 1060166971Snetchild } else { 1061166971Snetchild /* 1062166971Snetchild * Size four event. 1063166971Snetchild */ 1064166971Snetchild if (scp->music) { 1065166971Snetchild SEQ_DEBUG(2, printf("seq_write: four byte event in music mode.\n")); 1066166971Snetchild goto err0; 1067166971Snetchild } 1068158979Snetchild } 1069166971Snetchild if (ev_code == SEQ_MIDIPUTC) { 1070166971Snetchild /* 1071166971Snetchild * TODO: event[2] is unit number to receive char. 1072166971Snetchild * Range check it. 1073166971Snetchild */ 1074158979Snetchild } 1075158979Snetchild if (scp->music) { 1076159042Sru#ifdef not_ever_ever 1077166971Snetchild if (event[0] == EV_TIMING && 1078166971Snetchild (event[1] == TMR_START || event[1] == TMR_STOP)) { 1079166971Snetchild /* 1080166971Snetchild * For now, try to make midimoutain work by 1081166971Snetchild * forcing these events to be processed 1082166971Snetchild * immediatly. 1083166971Snetchild */ 1084166971Snetchild seq_processevent(scp, event); 1085166971Snetchild } else 1086166971Snetchild MIDIQ_ENQ(scp->out_q, event, EV_SZ); 1087158979Snetchild#else 1088166971Snetchild MIDIQ_ENQ(scp->out_q, event, EV_SZ); 1089158979Snetchild#endif 1090166971Snetchild } else { 1091166971Snetchild if (seq_convertold(event, newevent) > 0) 1092166971Snetchild MIDIQ_ENQ(scp->out_q, newevent, EV_SZ); 1093158979Snetchild#if 0 1094166971Snetchild else 1095166971Snetchild goto err0; 1096158979Snetchild#endif 1097166971Snetchild } 1098158979Snetchild 1099158979Snetchild } 1100158979Snetchild 1101158979Snetchild scp->playing = 1; 1102158979Snetchild cv_broadcast(&scp->state_cv); 1103158979Snetchild cv_broadcast(&scp->out_cv); 1104158979Snetchild 1105158979Snetchild retval = 0; 1106158979Snetchild 1107158979Snetchilderr0: 1108166971Snetchild SEQ_DEBUG(6, 1109194990Skib printf("seq_write done: leftover buffer length %zd retval %d\n", 1110166971Snetchild uio->uio_resid, retval)); 1111158979Snetchild mtx_unlock(&scp->seq_lock); 1112158979Snetchild return retval; 1113158979Snetchild} 1114158979Snetchild 1115158979Snetchildint 1116284865Sadrianmseq_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 1117166971Snetchild struct thread *td) 1118158979Snetchild{ 1119158979Snetchild int midiunit, ret, tmp; 1120158979Snetchild struct seq_softc *scp = i_dev->si_drv1; 1121158979Snetchild struct synth_info *synthinfo; 1122158979Snetchild struct midi_info *midiinfo; 1123158979Snetchild u_char event[EV_SZ]; 1124158979Snetchild u_char newevent[EV_SZ]; 1125158979Snetchild 1126158979Snetchild kobj_t md; 1127166971Snetchild 1128158979Snetchild /* 1129158979Snetchild * struct snd_size *sndsize; 1130158979Snetchild */ 1131158979Snetchild 1132158979Snetchild if (scp == NULL) 1133166971Snetchild return ENXIO; 1134158979Snetchild 1135166971Snetchild SEQ_DEBUG(6, printf("seq_ioctl: unit %d, cmd %s.\n", 1136166971Snetchild scp->unit, midi_cmdname(cmd, cmdtab_seqioctl))); 1137158979Snetchild 1138158979Snetchild ret = 0; 1139158979Snetchild 1140158979Snetchild switch (cmd) { 1141166971Snetchild case SNDCTL_SEQ_GETTIME: 1142158979Snetchild /* 1143158979Snetchild * ioctl needed by libtse 1144158979Snetchild */ 1145158979Snetchild mtx_lock(&scp->seq_lock); 1146158979Snetchild *(int *)arg = timer_now(scp); 1147158979Snetchild mtx_unlock(&scp->seq_lock); 1148166971Snetchild SEQ_DEBUG(6, printf("seq_ioctl: gettime %d.\n", *(int *)arg)); 1149158979Snetchild ret = 0; 1150158979Snetchild break; 1151166971Snetchild case SNDCTL_TMR_METRONOME: 1152158979Snetchild /* fallthrough */ 1153166971Snetchild case SNDCTL_TMR_SOURCE: 1154158979Snetchild /* 1155158979Snetchild * Not implemented 1156158979Snetchild */ 1157158979Snetchild ret = 0; 1158158979Snetchild break; 1159166971Snetchild case SNDCTL_TMR_TEMPO: 1160158979Snetchild event[1] = TMR_TEMPO; 1161162776Sru event[4] = *(int *)arg & 0xFF; 1162162776Sru event[5] = (*(int *)arg >> 8) & 0xFF; 1163162776Sru event[6] = (*(int *)arg >> 16) & 0xFF; 1164162776Sru event[7] = (*(int *)arg >> 24) & 0xFF; 1165158979Snetchild goto timerevent; 1166166971Snetchild case SNDCTL_TMR_TIMEBASE: 1167158979Snetchild event[1] = TMR_TIMERBASE; 1168162776Sru event[4] = *(int *)arg & 0xFF; 1169162776Sru event[5] = (*(int *)arg >> 8) & 0xFF; 1170162776Sru event[6] = (*(int *)arg >> 16) & 0xFF; 1171162776Sru event[7] = (*(int *)arg >> 24) & 0xFF; 1172158979Snetchild goto timerevent; 1173166971Snetchild case SNDCTL_TMR_START: 1174158979Snetchild event[1] = TMR_START; 1175158979Snetchild goto timerevent; 1176166971Snetchild case SNDCTL_TMR_STOP: 1177158979Snetchild event[1] = TMR_STOP; 1178158979Snetchild goto timerevent; 1179166971Snetchild case SNDCTL_TMR_CONTINUE: 1180158979Snetchild event[1] = TMR_CONTINUE; 1181166971Snetchildtimerevent: 1182158979Snetchild event[0] = EV_TIMING; 1183158979Snetchild mtx_lock(&scp->seq_lock); 1184158979Snetchild if (!scp->music) { 1185166971Snetchild ret = EINVAL; 1186166971Snetchild mtx_unlock(&scp->seq_lock); 1187166971Snetchild break; 1188158979Snetchild } 1189158979Snetchild seq_processevent(scp, event); 1190158979Snetchild mtx_unlock(&scp->seq_lock); 1191158979Snetchild break; 1192166971Snetchild case SNDCTL_TMR_SELECT: 1193166971Snetchild SEQ_DEBUG(2, 1194166971Snetchild printf("seq_ioctl: SNDCTL_TMR_SELECT not supported\n")); 1195158979Snetchild ret = EINVAL; 1196158979Snetchild break; 1197166971Snetchild case SNDCTL_SEQ_SYNC: 1198158979Snetchild if (mode == O_RDONLY) { 1199166971Snetchild ret = 0; 1200166971Snetchild break; 1201158979Snetchild } 1202158979Snetchild mtx_lock(&scp->seq_lock); 1203158979Snetchild ret = seq_sync(scp); 1204158979Snetchild mtx_unlock(&scp->seq_lock); 1205158979Snetchild break; 1206166971Snetchild case SNDCTL_SEQ_PANIC: 1207158979Snetchild /* fallthrough */ 1208166971Snetchild case SNDCTL_SEQ_RESET: 1209158979Snetchild /* 1210158979Snetchild * SNDCTL_SEQ_PANIC == SNDCTL_SEQ_RESET 1211158979Snetchild */ 1212158979Snetchild mtx_lock(&scp->seq_lock); 1213158979Snetchild seq_reset(scp); 1214158979Snetchild mtx_unlock(&scp->seq_lock); 1215158979Snetchild ret = 0; 1216158979Snetchild break; 1217166971Snetchild case SNDCTL_SEQ_TESTMIDI: 1218158979Snetchild mtx_lock(&scp->seq_lock); 1219158979Snetchild /* 1220158979Snetchild * TODO: SNDCTL_SEQ_TESTMIDI now means "can I write to the 1221158979Snetchild * device?". 1222158979Snetchild */ 1223158979Snetchild mtx_unlock(&scp->seq_lock); 1224158979Snetchild break; 1225158979Snetchild#if 0 1226166971Snetchild case SNDCTL_SEQ_GETINCOUNT: 1227158979Snetchild if (mode == O_WRONLY) 1228166971Snetchild *(int *)arg = 0; 1229158979Snetchild else { 1230166971Snetchild mtx_lock(&scp->seq_lock); 1231166971Snetchild *(int *)arg = scp->in_q.rl; 1232166971Snetchild mtx_unlock(&scp->seq_lock); 1233166971Snetchild SEQ_DEBUG(printf("seq_ioctl: incount %d.\n", 1234166971Snetchild *(int *)arg)); 1235158979Snetchild } 1236158979Snetchild ret = 0; 1237158979Snetchild break; 1238166971Snetchild case SNDCTL_SEQ_GETOUTCOUNT: 1239158979Snetchild if (mode == O_RDONLY) 1240166971Snetchild *(int *)arg = 0; 1241158979Snetchild else { 1242166971Snetchild mtx_lock(&scp->seq_lock); 1243166971Snetchild *(int *)arg = scp->out_q.fl; 1244166971Snetchild mtx_unlock(&scp->seq_lock); 1245166971Snetchild SEQ_DEBUG(printf("seq_ioctl: outcount %d.\n", 1246166971Snetchild *(int *)arg)); 1247158979Snetchild } 1248158979Snetchild ret = 0; 1249158979Snetchild break; 1250158979Snetchild#endif 1251166971Snetchild case SNDCTL_SEQ_CTRLRATE: 1252158979Snetchild if (*(int *)arg != 0) { 1253166971Snetchild ret = EINVAL; 1254166971Snetchild break; 1255158979Snetchild } 1256158979Snetchild mtx_lock(&scp->seq_lock); 1257158979Snetchild *(int *)arg = scp->timerbase; 1258158979Snetchild mtx_unlock(&scp->seq_lock); 1259166971Snetchild SEQ_DEBUG(3, printf("seq_ioctl: ctrlrate %d.\n", *(int *)arg)); 1260158979Snetchild ret = 0; 1261158979Snetchild break; 1262158979Snetchild /* 1263158979Snetchild * TODO: ioctl SNDCTL_SEQ_RESETSAMPLES 1264158979Snetchild */ 1265158979Snetchild#if 0 1266166971Snetchild case SNDCTL_SEQ_RESETSAMPLES: 1267158979Snetchild mtx_lock(&scp->seq_lock); 1268158979Snetchild ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md); 1269158979Snetchild mtx_unlock(&scp->seq_lock); 1270158979Snetchild if (ret != 0) 1271166971Snetchild break; 1272166971Snetchild ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, 1273166971Snetchild SND_DEV_MIDIN), cmd, arg, mode, td); 1274158979Snetchild break; 1275158979Snetchild#endif 1276166971Snetchild case SNDCTL_SEQ_NRSYNTHS: 1277158979Snetchild mtx_lock(&scp->seq_lock); 1278166971Snetchild *(int *)arg = scp->midi_number; 1279158979Snetchild mtx_unlock(&scp->seq_lock); 1280166971Snetchild SEQ_DEBUG(3, printf("seq_ioctl: synths %d.\n", *(int *)arg)); 1281158979Snetchild ret = 0; 1282158979Snetchild break; 1283166971Snetchild case SNDCTL_SEQ_NRMIDIS: 1284158979Snetchild mtx_lock(&scp->seq_lock); 1285158979Snetchild if (scp->music) 1286166971Snetchild *(int *)arg = 0; 1287158979Snetchild else { 1288166971Snetchild /* 1289166971Snetchild * TODO: count the numbder of devices that can WRITERAW 1290166971Snetchild */ 1291166971Snetchild *(int *)arg = scp->midi_number; 1292158979Snetchild } 1293158979Snetchild mtx_unlock(&scp->seq_lock); 1294166971Snetchild SEQ_DEBUG(3, printf("seq_ioctl: midis %d.\n", *(int *)arg)); 1295158979Snetchild ret = 0; 1296158979Snetchild break; 1297158979Snetchild /* 1298158979Snetchild * TODO: ioctl SNDCTL_SYNTH_MEMAVL 1299158979Snetchild */ 1300158979Snetchild#if 0 1301166971Snetchild case SNDCTL_SYNTH_MEMAVL: 1302158979Snetchild mtx_lock(&scp->seq_lock); 1303158979Snetchild ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md); 1304158979Snetchild mtx_unlock(&scp->seq_lock); 1305158979Snetchild if (ret != 0) 1306166971Snetchild break; 1307166971Snetchild ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, 1308166971Snetchild SND_DEV_MIDIN), cmd, arg, mode, td); 1309158979Snetchild break; 1310158979Snetchild#endif 1311166971Snetchild case SNDCTL_SEQ_OUTOFBAND: 1312158979Snetchild for (ret = 0; ret < EV_SZ; ret++) 1313166971Snetchild event[ret] = (u_char)arg[0]; 1314158979Snetchild 1315158979Snetchild mtx_lock(&scp->seq_lock); 1316158979Snetchild if (scp->music) 1317166971Snetchild ret = seq_processevent(scp, event); 1318158979Snetchild else { 1319166971Snetchild if (seq_convertold(event, newevent) > 0) 1320166971Snetchild ret = seq_processevent(scp, newevent); 1321166971Snetchild else 1322166971Snetchild ret = EINVAL; 1323158979Snetchild } 1324158979Snetchild mtx_unlock(&scp->seq_lock); 1325158979Snetchild break; 1326166971Snetchild case SNDCTL_SYNTH_INFO: 1327158979Snetchild synthinfo = (struct synth_info *)arg; 1328158979Snetchild midiunit = synthinfo->device; 1329158979Snetchild mtx_lock(&scp->seq_lock); 1330158979Snetchild if (seq_fetch_mid(scp, midiunit, &md) == 0) { 1331166971Snetchild bzero(synthinfo, sizeof(*synthinfo)); 1332166971Snetchild synthinfo->name[0] = 'f'; 1333166971Snetchild synthinfo->name[1] = 'a'; 1334166971Snetchild synthinfo->name[2] = 'k'; 1335166971Snetchild synthinfo->name[3] = 'e'; 1336166971Snetchild synthinfo->name[4] = 's'; 1337166971Snetchild synthinfo->name[5] = 'y'; 1338166971Snetchild synthinfo->name[6] = 'n'; 1339166971Snetchild synthinfo->name[7] = 't'; 1340166971Snetchild synthinfo->name[8] = 'h'; 1341166971Snetchild synthinfo->device = midiunit; 1342166971Snetchild synthinfo->synth_type = SYNTH_TYPE_MIDI; 1343166971Snetchild synthinfo->capabilities = scp->midi_flags[midiunit]; 1344166971Snetchild ret = 0; 1345158979Snetchild } else 1346166971Snetchild ret = EINVAL; 1347158979Snetchild mtx_unlock(&scp->seq_lock); 1348158979Snetchild break; 1349166971Snetchild case SNDCTL_MIDI_INFO: 1350158979Snetchild midiinfo = (struct midi_info *)arg; 1351158979Snetchild midiunit = midiinfo->device; 1352158979Snetchild mtx_lock(&scp->seq_lock); 1353158979Snetchild if (seq_fetch_mid(scp, midiunit, &md) == 0) { 1354166971Snetchild bzero(midiinfo, sizeof(*midiinfo)); 1355166971Snetchild midiinfo->name[0] = 'f'; 1356166971Snetchild midiinfo->name[1] = 'a'; 1357166971Snetchild midiinfo->name[2] = 'k'; 1358166971Snetchild midiinfo->name[3] = 'e'; 1359166971Snetchild midiinfo->name[4] = 'm'; 1360166971Snetchild midiinfo->name[5] = 'i'; 1361166971Snetchild midiinfo->name[6] = 'd'; 1362166971Snetchild midiinfo->name[7] = 'i'; 1363166971Snetchild midiinfo->device = midiunit; 1364166971Snetchild midiinfo->capabilities = scp->midi_flags[midiunit]; 1365166971Snetchild /* 1366166971Snetchild * TODO: What devtype? 1367166971Snetchild */ 1368166971Snetchild midiinfo->dev_type = 0x01; 1369166971Snetchild ret = 0; 1370158979Snetchild } else 1371166971Snetchild ret = EINVAL; 1372158979Snetchild mtx_unlock(&scp->seq_lock); 1373158979Snetchild break; 1374166971Snetchild case SNDCTL_SEQ_THRESHOLD: 1375158979Snetchild mtx_lock(&scp->seq_lock); 1376158979Snetchild RANGE(*(int *)arg, 1, MIDIQ_SIZE(scp->out_q) - 1); 1377158979Snetchild scp->out_water = *(int *)arg; 1378158979Snetchild mtx_unlock(&scp->seq_lock); 1379166971Snetchild SEQ_DEBUG(3, printf("seq_ioctl: water %d.\n", *(int *)arg)); 1380158979Snetchild ret = 0; 1381158979Snetchild break; 1382166971Snetchild case SNDCTL_MIDI_PRETIME: 1383158979Snetchild tmp = *(int *)arg; 1384158979Snetchild if (tmp < 0) 1385166971Snetchild tmp = 0; 1386158979Snetchild mtx_lock(&scp->seq_lock); 1387158979Snetchild scp->pre_event_timeout = (hz * tmp) / 10; 1388158979Snetchild *(int *)arg = scp->pre_event_timeout; 1389158979Snetchild mtx_unlock(&scp->seq_lock); 1390166971Snetchild SEQ_DEBUG(3, printf("seq_ioctl: pretime %d.\n", *(int *)arg)); 1391158979Snetchild ret = 0; 1392158979Snetchild break; 1393166971Snetchild case SNDCTL_FM_4OP_ENABLE: 1394166971Snetchild case SNDCTL_PMGR_IFACE: 1395166971Snetchild case SNDCTL_PMGR_ACCESS: 1396158979Snetchild /* 1397158979Snetchild * Patch manager and fm are ded, ded, ded. 1398158979Snetchild */ 1399158979Snetchild /* fallthrough */ 1400166971Snetchild default: 1401158979Snetchild /* 1402158979Snetchild * TODO: Consider ioctl default case. 1403158979Snetchild * Old code used to 1404158979Snetchild * if ((scp->fflags & O_ACCMODE) == FREAD) { 1405158979Snetchild * ret = EIO; 1406158979Snetchild * break; 1407158979Snetchild * } 1408158979Snetchild * Then pass on the ioctl to device 0 1409158979Snetchild */ 1410166971Snetchild SEQ_DEBUG(2, 1411166971Snetchild printf("seq_ioctl: unsupported IOCTL %ld.\n", cmd)); 1412158979Snetchild ret = EINVAL; 1413158979Snetchild break; 1414158979Snetchild } 1415158979Snetchild 1416158979Snetchild return ret; 1417158979Snetchild} 1418158979Snetchild 1419158979Snetchildint 1420284865Sadrianmseq_poll(struct cdev *i_dev, int events, struct thread *td) 1421158979Snetchild{ 1422158979Snetchild int ret, lim; 1423158979Snetchild struct seq_softc *scp = i_dev->si_drv1; 1424158979Snetchild 1425158979Snetchild SEQ_DEBUG(3, printf("seq_poll: unit %d.\n", scp->unit)); 1426163364Sariff SEQ_DEBUG(1, printf("seq_poll: unit %d.\n", scp->unit)); 1427158979Snetchild 1428158979Snetchild mtx_lock(&scp->seq_lock); 1429158979Snetchild 1430158979Snetchild ret = 0; 1431158979Snetchild 1432158979Snetchild /* Look up the apropriate queue and select it. */ 1433158979Snetchild if ((events & (POLLOUT | POLLWRNORM)) != 0) { 1434166971Snetchild /* Start playing. */ 1435166971Snetchild scp->playing = 1; 1436166971Snetchild cv_broadcast(&scp->state_cv); 1437166971Snetchild cv_broadcast(&scp->out_cv); 1438158979Snetchild 1439166971Snetchild lim = scp->out_water; 1440158979Snetchild 1441166971Snetchild if (MIDIQ_AVAIL(scp->out_q) < lim) 1442166971Snetchild /* No enough space, record select. */ 1443166971Snetchild selrecord(td, &scp->out_sel); 1444166971Snetchild else 1445166971Snetchild /* We can write now. */ 1446166971Snetchild ret |= events & (POLLOUT | POLLWRNORM); 1447158979Snetchild } 1448158979Snetchild if ((events & (POLLIN | POLLRDNORM)) != 0) { 1449166971Snetchild /* TODO: Start recording. */ 1450158979Snetchild 1451166971Snetchild /* Find out the boundary. */ 1452166971Snetchild lim = 1; 1453166971Snetchild if (MIDIQ_LEN(scp->in_q) < lim) 1454166971Snetchild /* No data ready, record select. */ 1455166971Snetchild selrecord(td, &scp->in_sel); 1456166971Snetchild else 1457166971Snetchild /* We can read now. */ 1458166971Snetchild ret |= events & (POLLIN | POLLRDNORM); 1459158979Snetchild } 1460158979Snetchild mtx_unlock(&scp->seq_lock); 1461158979Snetchild 1462158979Snetchild return (ret); 1463158979Snetchild} 1464166971Snetchild 1465158979Snetchild#if 0 1466158979Snetchildstatic void 1467158979Snetchildsein_qtr(void *p, void /* mididev_info */ *md) 1468158979Snetchild{ 1469158979Snetchild struct seq_softc *scp; 1470158979Snetchild 1471158979Snetchild scp = (struct seq_softc *)p; 1472158979Snetchild 1473158979Snetchild mtx_lock(&scp->seq_lock); 1474158979Snetchild 1475158979Snetchild /* Restart playing if we have the data to output. */ 1476158979Snetchild if (scp->queueout_pending) 1477158979Snetchild seq_callback(scp, SEQ_CB_START | SEQ_CB_WR); 1478158979Snetchild /* Check the midi device if we are reading. */ 1479158979Snetchild if ((scp->flags & SEQ_F_READING) != 0) 1480158979Snetchild seq_midiinput(scp, md); 1481158979Snetchild 1482158979Snetchild mtx_unlock(&scp->seq_lock); 1483158979Snetchild} 1484166971Snetchild 1485158979Snetchild#endif 1486158979Snetchild/* 1487158979Snetchild * seq_convertold 1488158979Snetchild * Was the old playevent. Use this to convert and old 1489166971Snetchild * style /dev/sequencer event to a /dev/music event 1490158979Snetchild */ 1491158979Snetchildstatic int 1492158979Snetchildseq_convertold(u_char *event, u_char *out) 1493158979Snetchild{ 1494158979Snetchild int used; 1495158979Snetchild u_char dev, chn, note, vel; 1496158979Snetchild 1497166971Snetchild out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = 1498166971Snetchild out[7] = 0; 1499158979Snetchild 1500158979Snetchild dev = 0; 1501158979Snetchild chn = event[1]; 1502158979Snetchild note = event[2]; 1503158979Snetchild vel = event[3]; 1504158979Snetchild 1505158979Snetchild used = 0; 1506158979Snetchild 1507158979Snetchildrestart: 1508158979Snetchild /* 1509158979Snetchild * TODO: Debug statement 1510158979Snetchild */ 1511166971Snetchild switch (event[0]) { 1512166971Snetchild case EV_TIMING: 1513166971Snetchild case EV_CHN_VOICE: 1514166971Snetchild case EV_CHN_COMMON: 1515166971Snetchild case EV_SYSEX: 1516166971Snetchild case EV_SEQ_LOCAL: 1517158979Snetchild out[0] = event[0]; 1518158979Snetchild out[1] = event[1]; 1519158979Snetchild out[2] = event[2]; 1520158979Snetchild out[3] = event[3]; 1521158979Snetchild out[4] = event[4]; 1522158979Snetchild out[5] = event[5]; 1523158979Snetchild out[6] = event[6]; 1524158979Snetchild out[7] = event[7]; 1525158979Snetchild used += 8; 1526158979Snetchild break; 1527166971Snetchild case SEQ_NOTEOFF: 1528158979Snetchild out[0] = EV_CHN_VOICE; 1529158979Snetchild out[1] = dev; 1530158979Snetchild out[2] = MIDI_NOTEOFF; 1531158979Snetchild out[3] = chn; 1532158979Snetchild out[4] = note; 1533158979Snetchild out[5] = 255; 1534166971Snetchild used += 4; 1535158979Snetchild break; 1536158979Snetchild 1537166971Snetchild case SEQ_NOTEON: 1538158979Snetchild out[0] = EV_CHN_VOICE; 1539158979Snetchild out[1] = dev; 1540158979Snetchild out[2] = MIDI_NOTEON; 1541158979Snetchild out[3] = chn; 1542158979Snetchild out[4] = note; 1543158979Snetchild out[5] = vel; 1544166971Snetchild used += 4; 1545158979Snetchild break; 1546158979Snetchild 1547158979Snetchild /* 1548158979Snetchild * wait delay = (event[2] << 16) + (event[3] << 8) + event[4] 1549158979Snetchild */ 1550158979Snetchild 1551166971Snetchild case SEQ_PGMCHANGE: 1552158979Snetchild out[0] = EV_CHN_COMMON; 1553158979Snetchild out[1] = dev; 1554158979Snetchild out[2] = MIDI_PGM_CHANGE; 1555158979Snetchild out[3] = chn; 1556158979Snetchild out[4] = note; 1557158979Snetchild out[5] = vel; 1558166971Snetchild used += 4; 1559158979Snetchild break; 1560158979Snetchild/* 1561158979Snetchild out[0] = EV_TIMING; 1562158979Snetchild out[1] = dev; 1563158979Snetchild out[2] = MIDI_PGM_CHANGE; 1564158979Snetchild out[3] = chn; 1565158979Snetchild out[4] = note; 1566158979Snetchild out[5] = vel; 1567158979Snetchild SEQ_DEBUG(4,printf("seq_playevent: synctimer\n")); 1568158979Snetchild break; 1569158979Snetchild*/ 1570158979Snetchild 1571166971Snetchild case SEQ_MIDIPUTC: 1572166971Snetchild SEQ_DEBUG(4, 1573166971Snetchild printf("seq_playevent: put data 0x%02x, unit %d.\n", 1574166971Snetchild event[1], event[2])); 1575158979Snetchild /* 1576158979Snetchild * Pass through to the midi device. 1577158979Snetchild * device = event[2] 1578158979Snetchild * data = event[1] 1579158979Snetchild */ 1580158979Snetchild out[0] = SEQ_MIDIPUTC; 1581158979Snetchild out[1] = dev; 1582158979Snetchild out[2] = chn; 1583166971Snetchild used += 4; 1584158979Snetchild break; 1585159042Sru#ifdef notyet 1586166971Snetchild case SEQ_ECHO: 1587158979Snetchild /* 1588158979Snetchild * This isn't handled here yet because I don't know if I can 1589166971Snetchild * just use four bytes events. There might be consequences 1590158979Snetchild * in the _read routing 1591158979Snetchild */ 1592158979Snetchild if (seq_copytoinput(scp, event, 4) == EAGAIN) { 1593166971Snetchild ret = QUEUEFULL; 1594166971Snetchild break; 1595158979Snetchild } 1596158979Snetchild ret = MORE; 1597158979Snetchild break; 1598158979Snetchild#endif 1599166971Snetchild case SEQ_EXTENDED: 1600158979Snetchild switch (event[1]) { 1601166971Snetchild case SEQ_NOTEOFF: 1602166971Snetchild case SEQ_NOTEON: 1603166971Snetchild case SEQ_PGMCHANGE: 1604158979Snetchild event++; 1605158979Snetchild used = 4; 1606158979Snetchild goto restart; 1607158979Snetchild break; 1608166971Snetchild case SEQ_AFTERTOUCH: 1609158979Snetchild /* 1610158979Snetchild * SYNTH_AFTERTOUCH(md, event[3], event[4]) 1611158979Snetchild */ 1612166971Snetchild case SEQ_BALANCE: 1613158979Snetchild /* 1614158979Snetchild * SYNTH_PANNING(md, event[3], (char)event[4]) 1615158979Snetchild */ 1616166971Snetchild case SEQ_CONTROLLER: 1617158979Snetchild /* 1618158979Snetchild * SYNTH_CONTROLLER(md, event[3], event[4], *(short *)&event[5]) 1619158979Snetchild */ 1620166971Snetchild case SEQ_VOLMODE: 1621158979Snetchild /* 1622166971Snetchild * SYNTH_VOLUMEMETHOD(md, event[3]) 1623158979Snetchild */ 1624166971Snetchild default: 1625166971Snetchild SEQ_DEBUG(2, 1626166971Snetchild printf("seq_convertold: SEQ_EXTENDED type %d" 1627166971Snetchild "not handled\n", event[1])); 1628158979Snetchild break; 1629158979Snetchild } 1630158979Snetchild break; 1631166971Snetchild case SEQ_WAIT: 1632158979Snetchild out[0] = EV_TIMING; 1633158979Snetchild out[1] = TMR_WAIT_REL; 1634158979Snetchild out[4] = event[2]; 1635158979Snetchild out[5] = event[3]; 1636158979Snetchild out[6] = event[4]; 1637158979Snetchild 1638166971Snetchild SEQ_DEBUG(5, printf("SEQ_WAIT %d", 1639166971Snetchild event[2] + (event[3] << 8) + (event[4] << 24))); 1640158979Snetchild 1641166971Snetchild used += 4; 1642158979Snetchild break; 1643158979Snetchild 1644166971Snetchild case SEQ_ECHO: 1645166971Snetchild case SEQ_SYNCTIMER: 1646166971Snetchild case SEQ_PRIVATE: 1647166971Snetchild default: 1648166971Snetchild SEQ_DEBUG(2, 1649166971Snetchild printf("seq_convertold: event type %d not handled %d %d %d\n", 1650166971Snetchild event[0], event[1], event[2], event[3])); 1651158979Snetchild break; 1652158979Snetchild } 1653158979Snetchild return used; 1654158979Snetchild} 1655158979Snetchild 1656158979Snetchild/* 1657158979Snetchild * Writting to the sequencer buffer never blocks and drops 1658158979Snetchild * input which cannot be queued 1659158979Snetchild */ 1660158979Snetchildvoid 1661158979Snetchildseq_copytoinput(struct seq_softc *scp, u_char *event, int len) 1662158979Snetchild{ 1663158979Snetchild 1664158979Snetchild mtx_assert(&scp->seq_lock, MA_OWNED); 1665158979Snetchild 1666158979Snetchild if (MIDIQ_AVAIL(scp->in_q) < len) { 1667166971Snetchild /* 1668166971Snetchild * ENOROOM? EINPUTDROPPED? ETOUGHLUCK? 1669166971Snetchild */ 1670166971Snetchild SEQ_DEBUG(2, printf("seq_copytoinput: queue full\n")); 1671158979Snetchild } else { 1672166971Snetchild MIDIQ_ENQ(scp->in_q, event, len); 1673166971Snetchild selwakeup(&scp->in_sel); 1674166971Snetchild cv_broadcast(&scp->in_cv); 1675158979Snetchild } 1676158979Snetchild 1677158979Snetchild} 1678158979Snetchild 1679158979Snetchildstatic int 1680158979Snetchildseq_chnvoice(struct seq_softc *scp, kobj_t md, u_char *event) 1681158979Snetchild{ 1682158979Snetchild int ret, voice; 1683158979Snetchild u_char cmd, chn, note, parm; 1684158979Snetchild 1685158979Snetchild ret = 0; 1686158979Snetchild cmd = event[2]; 1687158979Snetchild chn = event[3]; 1688158979Snetchild note = event[4]; 1689158979Snetchild parm = event[5]; 1690158979Snetchild 1691158979Snetchild mtx_assert(&scp->seq_lock, MA_OWNED); 1692158979Snetchild 1693166971Snetchild SEQ_DEBUG(5, printf("seq_chnvoice: unit %d, dev %d, cmd %s," 1694166971Snetchild " chn %d, note %d, parm %d.\n", scp->unit, event[1], 1695166971Snetchild midi_cmdname(cmd, cmdtab_seqcv), chn, note, parm)); 1696158979Snetchild 1697158979Snetchild voice = SYNTH_ALLOC(md, chn, note); 1698158979Snetchild 1699158979Snetchild mtx_unlock(&scp->seq_lock); 1700158979Snetchild 1701158979Snetchild switch (cmd) { 1702166971Snetchild case MIDI_NOTEON: 1703158979Snetchild if (note < 128 || note == 255) { 1704158979Snetchild#if 0 1705166971Snetchild if (scp->music && chn == 9) { 1706166971Snetchild /* 1707166971Snetchild * This channel is a percussion. The note 1708166971Snetchild * number is the patch number. 1709166971Snetchild */ 1710166971Snetchild /* 1711166971Snetchild mtx_unlock(&scp->seq_lock); 1712166971Snetchild if (SYNTH_SETINSTR(md, voice, 128 + note) 1713166971Snetchild == EAGAIN) { 1714166971Snetchild mtx_lock(&scp->seq_lock); 1715166971Snetchild return (QUEUEFULL); 1716166971Snetchild } 1717166971Snetchild mtx_lock(&scp->seq_lock); 1718166971Snetchild */ 1719166971Snetchild note = 60; /* Middle C. */ 1720158979Snetchild } 1721158979Snetchild#endif 1722166971Snetchild if (scp->music) { 1723166971Snetchild /* 1724166971Snetchild mtx_unlock(&scp->seq_lock); 1725166971Snetchild if (SYNTH_SETUPVOICE(md, voice, chn) 1726166971Snetchild == EAGAIN) { 1727166971Snetchild mtx_lock(&scp->seq_lock); 1728166971Snetchild return (QUEUEFULL); 1729166971Snetchild } 1730166971Snetchild mtx_lock(&scp->seq_lock); 1731166971Snetchild */ 1732158979Snetchild } 1733166971Snetchild SYNTH_STARTNOTE(md, voice, note, parm); 1734158979Snetchild } 1735158979Snetchild break; 1736158979Snetchild case MIDI_NOTEOFF: 1737158979Snetchild SYNTH_KILLNOTE(md, voice, note, parm); 1738158979Snetchild break; 1739158979Snetchild case MIDI_KEY_PRESSURE: 1740158979Snetchild SYNTH_AFTERTOUCH(md, voice, parm); 1741158979Snetchild break; 1742158979Snetchild default: 1743158979Snetchild ret = 1; 1744166971Snetchild SEQ_DEBUG(2, printf("seq_chnvoice event type %d not handled\n", 1745166971Snetchild event[1])); 1746158979Snetchild break; 1747158979Snetchild } 1748158979Snetchild 1749158979Snetchild mtx_lock(&scp->seq_lock); 1750158979Snetchild return ret; 1751158979Snetchild} 1752158979Snetchild 1753158979Snetchildstatic int 1754158979Snetchildseq_chncommon(struct seq_softc *scp, kobj_t md, u_char *event) 1755158979Snetchild{ 1756158979Snetchild int ret; 1757158979Snetchild u_short w14; 1758158979Snetchild u_char cmd, chn, p1; 1759158979Snetchild 1760158979Snetchild ret = 0; 1761158979Snetchild cmd = event[2]; 1762158979Snetchild chn = event[3]; 1763158979Snetchild p1 = event[4]; 1764158979Snetchild w14 = *(u_short *)&event[6]; 1765158979Snetchild 1766166971Snetchild SEQ_DEBUG(5, printf("seq_chncommon: unit %d, dev %d, cmd %s, chn %d," 1767166971Snetchild " p1 %d, w14 %d.\n", scp->unit, event[1], 1768166971Snetchild midi_cmdname(cmd, cmdtab_seqccmn), chn, p1, w14)); 1769158979Snetchild mtx_unlock(&scp->seq_lock); 1770158979Snetchild switch (cmd) { 1771166971Snetchild case MIDI_PGM_CHANGE: 1772166971Snetchild SEQ_DEBUG(4, printf("seq_chncommon pgmchn chn %d pg %d\n", 1773166971Snetchild chn, p1)); 1774166971Snetchild SYNTH_SETINSTR(md, chn, p1); 1775158979Snetchild break; 1776166971Snetchild case MIDI_CTL_CHANGE: 1777166971Snetchild SEQ_DEBUG(4, printf("seq_chncommon ctlch chn %d pg %d %d\n", 1778166971Snetchild chn, p1, w14)); 1779158979Snetchild SYNTH_CONTROLLER(md, chn, p1, w14); 1780158979Snetchild break; 1781166971Snetchild case MIDI_PITCH_BEND: 1782158979Snetchild if (scp->music) { 1783166971Snetchild /* 1784166971Snetchild * TODO: MIDI_PITCH_BEND 1785166971Snetchild */ 1786158979Snetchild#if 0 1787166971Snetchild mtx_lock(&md->synth.vc_mtx); 1788166971Snetchild md->synth.chn_info[chn].bender_value = w14; 1789166971Snetchild if (md->midiunit >= 0) { 1790166971Snetchild /* 1791166971Snetchild * Handle all of the notes playing on this 1792166971Snetchild * channel. 1793166971Snetchild */ 1794166971Snetchild key = ((int)chn << 8); 1795166971Snetchild for (i = 0; i < md->synth.alloc.max_voice; i++) 1796166971Snetchild if ((md->synth.alloc.map[i] & 0xff00) == key) { 1797166971Snetchild mtx_unlock(&md->synth.vc_mtx); 1798166971Snetchild mtx_unlock(&scp->seq_lock); 1799166971Snetchild if (md->synth.bender(md, i, w14) == EAGAIN) { 1800166971Snetchild mtx_lock(&scp->seq_lock); 1801166971Snetchild return (QUEUEFULL); 1802166971Snetchild } 1803166971Snetchild mtx_lock(&scp->seq_lock); 1804166971Snetchild } 1805166971Snetchild } else { 1806158979Snetchild mtx_unlock(&md->synth.vc_mtx); 1807158979Snetchild mtx_unlock(&scp->seq_lock); 1808166971Snetchild if (md->synth.bender(md, chn, w14) == EAGAIN) { 1809166971Snetchild mtx_lock(&scp->seq_lock); 1810166971Snetchild return (QUEUEFULL); 1811158979Snetchild } 1812158979Snetchild mtx_lock(&scp->seq_lock); 1813158979Snetchild } 1814158979Snetchild#endif 1815158979Snetchild } else 1816166971Snetchild SYNTH_BENDER(md, chn, w14); 1817158979Snetchild break; 1818166971Snetchild default: 1819158979Snetchild ret = 1; 1820166971Snetchild SEQ_DEBUG(2, 1821166971Snetchild printf("seq_chncommon event type %d not handled.\n", 1822166971Snetchild event[1])); 1823158979Snetchild break; 1824158979Snetchild 1825158979Snetchild } 1826158979Snetchild mtx_lock(&scp->seq_lock); 1827158979Snetchild return ret; 1828158979Snetchild} 1829158979Snetchild 1830158979Snetchildstatic int 1831158979Snetchildseq_timing(struct seq_softc *scp, u_char *event) 1832158979Snetchild{ 1833158979Snetchild int param; 1834158979Snetchild int ret; 1835158979Snetchild 1836158979Snetchild ret = 0; 1837158979Snetchild param = event[4] + (event[5] << 8) + 1838158979Snetchild (event[6] << 16) + (event[7] << 24); 1839158979Snetchild 1840166971Snetchild SEQ_DEBUG(5, printf("seq_timing: unit %d, cmd %d, param %d.\n", 1841166971Snetchild scp->unit, event[1], param)); 1842158979Snetchild switch (event[1]) { 1843158979Snetchild case TMR_WAIT_REL: 1844166971Snetchild timer_wait(scp, param, 0); 1845158979Snetchild break; 1846158979Snetchild case TMR_WAIT_ABS: 1847166971Snetchild timer_wait(scp, param, 1); 1848158979Snetchild break; 1849158979Snetchild case TMR_START: 1850158979Snetchild timer_start(scp); 1851158979Snetchild cv_broadcast(&scp->reset_cv); 1852158979Snetchild break; 1853158979Snetchild case TMR_STOP: 1854158979Snetchild timer_stop(scp); 1855158979Snetchild /* 1856158979Snetchild * The following cv_broadcast isn't needed since we only 1857158979Snetchild * wait for 0->1 transitions. It probably won't hurt 1858158979Snetchild */ 1859158979Snetchild cv_broadcast(&scp->reset_cv); 1860158979Snetchild break; 1861158979Snetchild case TMR_CONTINUE: 1862158979Snetchild timer_continue(scp); 1863158979Snetchild cv_broadcast(&scp->reset_cv); 1864158979Snetchild break; 1865158979Snetchild case TMR_TEMPO: 1866158979Snetchild if (param < 8) 1867166971Snetchild param = 8; 1868158979Snetchild if (param > 360) 1869166971Snetchild param = 360; 1870166971Snetchild SEQ_DEBUG(4, printf("Timer set tempo %d\n", param)); 1871158979Snetchild timer_setvals(scp, param, scp->timerbase); 1872158979Snetchild break; 1873158979Snetchild case TMR_TIMERBASE: 1874158979Snetchild if (param < 1) 1875166971Snetchild param = 1; 1876158979Snetchild if (param > 1000) 1877166971Snetchild param = 1000; 1878166971Snetchild SEQ_DEBUG(4, printf("Timer set timerbase %d\n", param)); 1879158979Snetchild timer_setvals(scp, scp->tempo, param); 1880158979Snetchild break; 1881158979Snetchild case TMR_ECHO: 1882158979Snetchild /* 1883158979Snetchild * TODO: Consider making 4-byte events for /dev/sequencer 1884158979Snetchild * PRO: Maybe needed by legacy apps 1885158979Snetchild * CON: soundcard.h has been warning for a while many years 1886158979Snetchild * to expect 8 byte events. 1887158979Snetchild */ 1888158979Snetchild#if 0 1889158979Snetchild if (scp->music) 1890158979Snetchild seq_copytoinput(scp, event, 8); 1891158979Snetchild else { 1892158979Snetchild param = (param << 8 | SEQ_ECHO); 1893158979Snetchild seq_copytoinput(scp, (u_char *)¶m, 4); 1894158979Snetchild } 1895158979Snetchild#else 1896158979Snetchild seq_copytoinput(scp, event, 8); 1897158979Snetchild#endif 1898158979Snetchild break; 1899166971Snetchild default: 1900166971Snetchild SEQ_DEBUG(2, printf("seq_timing event type %d not handled.\n", 1901166971Snetchild event[1])); 1902158979Snetchild ret = 1; 1903158979Snetchild break; 1904158979Snetchild } 1905158979Snetchild return ret; 1906158979Snetchild} 1907158979Snetchild 1908158979Snetchildstatic int 1909158979Snetchildseq_local(struct seq_softc *scp, u_char *event) 1910158979Snetchild{ 1911158979Snetchild int ret; 1912158979Snetchild 1913158979Snetchild ret = 0; 1914158979Snetchild mtx_assert(&scp->seq_lock, MA_OWNED); 1915158979Snetchild 1916166971Snetchild SEQ_DEBUG(5, printf("seq_local: unit %d, cmd %d\n", scp->unit, 1917166971Snetchild event[1])); 1918158979Snetchild switch (event[1]) { 1919166971Snetchild default: 1920166971Snetchild SEQ_DEBUG(1, printf("seq_local event type %d not handled\n", 1921166971Snetchild event[1])); 1922158979Snetchild ret = 1; 1923158979Snetchild break; 1924158979Snetchild } 1925158979Snetchild return ret; 1926158979Snetchild} 1927158979Snetchild 1928158979Snetchildstatic int 1929158979Snetchildseq_sysex(struct seq_softc *scp, kobj_t md, u_char *event) 1930158979Snetchild{ 1931158979Snetchild int i, l; 1932158979Snetchild 1933158979Snetchild mtx_assert(&scp->seq_lock, MA_OWNED); 1934166971Snetchild SEQ_DEBUG(5, printf("seq_sysex: unit %d device %d\n", scp->unit, 1935166971Snetchild event[1])); 1936158979Snetchild l = 0; 1937166971Snetchild for (i = 0; i < 6 && event[i + 2] != 0xff; i++) 1938158979Snetchild l = i + 1; 1939158979Snetchild if (l > 0) { 1940158979Snetchild mtx_unlock(&scp->seq_lock); 1941158979Snetchild if (SYNTH_SENDSYSEX(md, &event[2], l) == EAGAIN) { 1942158979Snetchild mtx_lock(&scp->seq_lock); 1943158979Snetchild return 1; 1944158979Snetchild } 1945158979Snetchild mtx_lock(&scp->seq_lock); 1946158979Snetchild } 1947158979Snetchild return 0; 1948158979Snetchild} 1949158979Snetchild 1950158979Snetchild/* 1951158979Snetchild * Reset no longer closes the raw devices nor seq_sync's 1952158979Snetchild * Callers are IOCTL and seq_close 1953158979Snetchild */ 1954158979Snetchildstatic void 1955158979Snetchildseq_reset(struct seq_softc *scp) 1956158979Snetchild{ 1957166971Snetchild int chn, i; 1958158979Snetchild kobj_t m; 1959158979Snetchild 1960158979Snetchild mtx_assert(&scp->seq_lock, MA_OWNED); 1961158979Snetchild 1962166971Snetchild SEQ_DEBUG(5, printf("seq_reset: unit %d.\n", scp->unit)); 1963158979Snetchild 1964158979Snetchild /* 1965158979Snetchild * Stop reading and writing. 1966158979Snetchild */ 1967158979Snetchild 1968158979Snetchild /* scp->recording = 0; */ 1969158979Snetchild scp->playing = 0; 1970158979Snetchild cv_broadcast(&scp->state_cv); 1971158979Snetchild cv_broadcast(&scp->out_cv); 1972158979Snetchild cv_broadcast(&scp->reset_cv); 1973158979Snetchild 1974158979Snetchild /* 1975158979Snetchild * For now, don't reset the timers. 1976158979Snetchild */ 1977158979Snetchild MIDIQ_CLEAR(scp->in_q); 1978158979Snetchild MIDIQ_CLEAR(scp->out_q); 1979158979Snetchild 1980158979Snetchild for (i = 0; i < scp->midi_number; i++) { 1981166971Snetchild m = scp->midis[i]; 1982166971Snetchild mtx_unlock(&scp->seq_lock); 1983166971Snetchild SYNTH_RESET(m); 1984166971Snetchild for (chn = 0; chn < 16; chn++) { 1985166971Snetchild SYNTH_CONTROLLER(m, chn, 123, 0); 1986166971Snetchild SYNTH_CONTROLLER(m, chn, 121, 0); 1987166971Snetchild SYNTH_BENDER(m, chn, 1 << 13); 1988166971Snetchild } 1989166971Snetchild mtx_lock(&scp->seq_lock); 1990158979Snetchild } 1991158979Snetchild} 1992158979Snetchild 1993158979Snetchild/* 1994158979Snetchild * seq_sync 1995158979Snetchild * *really* flush the output queue 1996158979Snetchild * flush the event queue, then flush the synthsisers. 1997158979Snetchild * Callers are IOCTL and close 1998158979Snetchild */ 1999158979Snetchild 2000158979Snetchild#define SEQ_SYNC_TIMEOUT 8 2001158979Snetchildstatic int 2002158979Snetchildseq_sync(struct seq_softc *scp) 2003158979Snetchild{ 2004158979Snetchild int i, rl, sync[16], done; 2005158979Snetchild 2006158979Snetchild mtx_assert(&scp->seq_lock, MA_OWNED); 2007158979Snetchild 2008166971Snetchild SEQ_DEBUG(4, printf("seq_sync: unit %d.\n", scp->unit)); 2009158979Snetchild 2010158979Snetchild /* 2011158979Snetchild * Wait until output queue is empty. Check every so often to see if 2012158979Snetchild * the queue is moving along. If it isn't just abort. 2013158979Snetchild */ 2014158979Snetchild while (!MIDIQ_EMPTY(scp->out_q)) { 2015158979Snetchild 2016166971Snetchild if (!scp->playing) { 2017166971Snetchild scp->playing = 1; 2018166971Snetchild cv_broadcast(&scp->state_cv); 2019166971Snetchild cv_broadcast(&scp->out_cv); 2020166971Snetchild } 2021166971Snetchild rl = MIDIQ_LEN(scp->out_q); 2022158979Snetchild 2023166971Snetchild i = cv_timedwait_sig(&scp->out_cv, 2024158979Snetchild &scp->seq_lock, SEQ_SYNC_TIMEOUT * hz); 2025158979Snetchild 2026166971Snetchild if (i == EINTR || i == ERESTART) { 2027166971Snetchild if (i == EINTR) { 2028166971Snetchild /* 2029166971Snetchild * XXX: I don't know why we stop playing 2030166971Snetchild */ 2031166971Snetchild scp->playing = 0; 2032166971Snetchild cv_broadcast(&scp->out_cv); 2033166971Snetchild } 2034166971Snetchild return i; 2035158979Snetchild } 2036166971Snetchild if (i == EWOULDBLOCK && rl == MIDIQ_LEN(scp->out_q) && 2037158979Snetchild scp->waiting == 0) { 2038166971Snetchild /* 2039166971Snetchild * A queue seems to be stuck up. Give up and clear 2040166971Snetchild * queues. 2041166971Snetchild */ 2042166971Snetchild MIDIQ_CLEAR(scp->out_q); 2043166971Snetchild scp->playing = 0; 2044166971Snetchild cv_broadcast(&scp->state_cv); 2045166971Snetchild cv_broadcast(&scp->out_cv); 2046166971Snetchild cv_broadcast(&scp->reset_cv); 2047158979Snetchild 2048166971Snetchild /* 2049166971Snetchild * TODO: Consider if the raw devices need to be flushed 2050166971Snetchild */ 2051158979Snetchild 2052166971Snetchild SEQ_DEBUG(1, printf("seq_sync queue stuck, aborting\n")); 2053158979Snetchild 2054166971Snetchild return i; 2055166971Snetchild } 2056158979Snetchild } 2057158979Snetchild 2058158979Snetchild scp->playing = 0; 2059158979Snetchild /* 2060158979Snetchild * Since syncing a midi device might block, unlock scp->seq_lock. 2061158979Snetchild */ 2062158979Snetchild 2063158979Snetchild mtx_unlock(&scp->seq_lock); 2064166971Snetchild for (i = 0; i < scp->midi_number; i++) 2065166971Snetchild sync[i] = 1; 2066158979Snetchild 2067158979Snetchild do { 2068166971Snetchild done = 1; 2069166971Snetchild for (i = 0; i < scp->midi_number; i++) 2070166971Snetchild if (sync[i]) { 2071166971Snetchild if (SYNTH_INSYNC(scp->midis[i]) == 0) 2072166971Snetchild sync[i] = 0; 2073166971Snetchild else 2074166971Snetchild done = 0; 2075166971Snetchild } 2076166971Snetchild if (!done) 2077166971Snetchild DELAY(5000); 2078158979Snetchild 2079158979Snetchild } while (!done); 2080158979Snetchild 2081158979Snetchild mtx_lock(&scp->seq_lock); 2082158979Snetchild return 0; 2083158979Snetchild} 2084158979Snetchild 2085166971Snetchildchar * 2086158979Snetchildmidi_cmdname(int cmd, midi_cmdtab *tab) 2087158979Snetchild{ 2088158979Snetchild while (tab->name != NULL) { 2089158979Snetchild if (cmd == tab->cmd) 2090158979Snetchild return (tab->name); 2091158979Snetchild tab++; 2092158979Snetchild } 2093158979Snetchild 2094158979Snetchild return ("unknown"); 2095158979Snetchild} 2096