diff --git a/sys/dev/sound/midi/midi.h b/sys/dev/sound/midi/midi.h --- a/sys/dev/sound/midi/midi.h +++ b/sys/dev/sound/midi/midi.h @@ -41,12 +41,7 @@ struct snd_midi; -void midistat_lock(void); -void midistat_unlock(void); -void midistat_lockassert(void); - -struct snd_midi * -midi_init(kobj_class_t _mpu_cls, int _unit, int _channel, void *cookie); +struct snd_midi *midi_init(kobj_class_t _mpu_cls, void *cookie); int midi_uninit(struct snd_midi *_m); int midi_out(struct snd_midi *_m, uint8_t *_buf, int _size); int midi_in(struct snd_midi *_m, uint8_t *_buf, int _size); diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c --- a/sys/dev/sound/midi/midi.c +++ b/sys/dev/sound/midi/midi.c @@ -36,12 +36,11 @@ #include #include #include +#include #include #include #include -#include #include -#include #include #include @@ -62,8 +61,8 @@ struct mtx lock; /* Protects all but queues */ void *cookie; - int unit; /* Should only be used in midistat */ - int channel; /* Should only be used in midistat */ + int unit; + int channel; int busy; int flags; /* File flags */ @@ -75,13 +74,8 @@ int hiwat; /* QLEN(outq)>High-water -> disable * writes from userland */ struct cdev *dev; - TAILQ_ENTRY(snd_midi) link; }; -TAILQ_HEAD(, snd_midi) midi_devs; - -struct sx mstat_lock; - static d_open_t midi_open; static d_close_t midi_close; static d_ioctl_t midi_ioctl; @@ -102,6 +96,9 @@ static int midi_destroy(struct snd_midi *, int); +struct unrhdr *dev_unr = NULL; +struct unrhdr *chn_unr = NULL; + SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Midi driver"); @@ -111,70 +108,19 @@ #define MIDI_DEBUG(l,a) if(midi_debug>=l) a -void -midistat_lock(void) -{ - sx_xlock(&mstat_lock); -} - -void -midistat_unlock(void) -{ - sx_xunlock(&mstat_lock); -} - -void -midistat_lockassert(void) -{ - sx_assert(&mstat_lock, SA_XLOCKED); -} - /* - * Register a new rmidi device. cls midi_if interface unit == 0 means - * auto-assign new unit number unit != 0 already assigned a unit number, eg. - * not the first channel provided by this device. channel, sub-unit - * cookie is passed back on MPU calls Typical device drivers will call with - * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care - * what unit number is used. + * Register a new rmidi device. * - * It is an error to call midi_init with an already used unit/channel combo. + * "cookie" is passed to the MPU calls, and is normally set to the driver's + * softc. */ struct snd_midi * -midi_init(kobj_class_t cls, int unit, int channel, void *cookie) +midi_init(kobj_class_t cls, void *cookie) { struct snd_midi *m; - int i; int inqsize, outqsize; uint8_t *buf; - MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel)); - midistat_lock(); - /* - * Protect against call with existing unit/channel or auto-allocate a - * new unit number. - */ - i = -1; - TAILQ_FOREACH(m, &midi_devs, link) { - mtx_lock(&m->lock); - if (unit != 0) { - if (m->unit == unit && m->channel == channel) { - mtx_unlock(&m->lock); - goto err0; - } - } else { - /* - * Find a better unit number - */ - if (m->unit > i) - i = m->unit; - } - mtx_unlock(&m->lock); - } - - if (unit == 0) - unit = i + 1; - - MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel)); m = malloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO); kobj_init((kobj_t)m, cls); inqsize = MPU_INQSIZE(m, cookie); @@ -211,8 +157,8 @@ m->busy = 0; m->flags = 0; - m->unit = unit; - m->channel = channel; + m->unit = alloc_unr(dev_unr); + m->channel = alloc_unr(chn_unr); m->cookie = cookie; if (MPU_INIT(m, cookie)) @@ -221,12 +167,8 @@ mtx_unlock(&m->lock); mtx_unlock(&m->qlock); - TAILQ_INSERT_TAIL(&midi_devs, m, link); - - midistat_unlock(); - - m->dev = make_dev(&midi_cdevsw, unit, UID_ROOT, GID_WHEEL, 0666, - "midi%d.%d", unit, channel); + m->dev = make_dev(&midi_cdevsw, m->unit, UID_ROOT, GID_WHEEL, 0666, + "midi%d.%d", m->unit, m->channel); m->dev->si_drv1 = m; return m; @@ -241,8 +183,6 @@ free(MIDIQ_BUF(m->outq), M_MIDI); err1: free(m, M_MIDI); -err0: - midistat_unlock(); MIDI_DEBUG(1, printf("midi_init ended in error\n")); return NULL; } @@ -258,7 +198,6 @@ int err; err = EBUSY; - midistat_lock(); mtx_lock(&m->lock); if (m->busy) { if (!(m->rchan || m->wchan)) @@ -280,7 +219,6 @@ err: mtx_unlock(&m->lock); exit: - midistat_unlock(); return err; } @@ -680,16 +618,17 @@ static int midi_destroy(struct snd_midi *m, int midiuninit) { - midistat_lockassert(); mtx_assert(&m->lock, MA_OWNED); MIDI_DEBUG(3, printf("midi_destroy\n")); m->dev->si_drv1 = NULL; mtx_unlock(&m->lock); /* XXX */ destroy_dev(m->dev); - TAILQ_REMOVE(&midi_devs, m, link); + /* XXX */ if (midiuninit) MPU_UNINIT(m, m->cookie); + free_unr(dev_unr, m->unit); + free_unr(chn_unr, m->channel); free(MIDIQ_BUF(m->inq), M_MIDI); free(MIDIQ_BUF(m->outq), M_MIDI); mtx_destroy(&m->qlock); @@ -701,38 +640,17 @@ static void midi_sysinit(void *data __unused) { - sx_init(&mstat_lock, "midistat lock"); - TAILQ_INIT(&midi_devs); + dev_unr = new_unrhdr(0, INT_MAX, NULL); + chn_unr = new_unrhdr(0, INT_MAX, NULL); } SYSINIT(midi_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, midi_sysinit, NULL); static void midi_sysuninit(void *data __unused) { - struct snd_midi *m, *tmp; - int retval; - - MIDI_DEBUG(1, printf("midi_unload()\n")); - retval = EBUSY; - midistat_lock(); - TAILQ_FOREACH_SAFE(m, &midi_devs, link, tmp) { - mtx_lock(&m->lock); - if (m->busy) - retval = EBUSY; - else - retval = midi_destroy(m, 1); - if (retval) - goto exit; - } - midistat_unlock(); - - sx_destroy(&mstat_lock); - return; - -exit: - mtx_unlock(&m->lock); - midistat_unlock(); - if (retval) - MIDI_DEBUG(2, printf("midi_unload: failed\n")); + if (dev_unr != NULL) + delete_unrhdr(dev_unr); + if (chn_unr != NULL) + delete_unrhdr(chn_unr); } -SYSUNINIT(midi_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, midi_sysuninit, NULL); +SYSUNINIT(midi_sysuninit, SI_SUB_DRIVERS, SI_ORDER_ANY, midi_sysuninit, NULL); diff --git a/sys/dev/sound/midi/mpu401.c b/sys/dev/sound/midi/mpu401.c --- a/sys/dev/sound/midi/mpu401.c +++ b/sys/dev/sound/midi/mpu401.c @@ -157,7 +157,7 @@ m->cookie = cookie; m->flags = 0; - m->mid = midi_init(&mpu401_class, 0, 0, m); + m->mid = midi_init(&mpu401_class, m); if (!m->mid) goto err; *cb = mpu401_intr;