Date: Thu, 10 Jan 2008 16:45:24 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 132971 for review Message-ID: <200801101645.m0AGjOKW033069@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=132971 Change 132971 by jhb@jhb_zion on 2008/01/10 16:45:02 IFC @132967 Affected files ... .. //depot/projects/power/sys/alpha/include/ioctl_meteor.h#3 delete .. //depot/projects/power/sys/boot/i386/loader/loader.rc#3 integrate .. //depot/projects/power/sys/dev/coretemp/coretemp.c#2 integrate .. //depot/projects/power/sys/dev/lmc/if_lmc.c#3 branch .. //depot/projects/power/sys/dev/sound/midi/midi.c#3 integrate .. //depot/projects/power/sys/dev/sound/midi/midi.h#3 integrate .. //depot/projects/power/sys/dev/sound/midi/sequencer.c#3 integrate .. //depot/projects/power/sys/dev/sound/midi/sequencer.h#2 integrate .. //depot/projects/power/sys/modules/pflog/Makefile#3 integrate Differences ... ==== //depot/projects/power/sys/boot/i386/loader/loader.rc#3 (text+ko) ==== ==== //depot/projects/power/sys/dev/coretemp/coretemp.c#2 (text+ko) ==== @@ -23,7 +23,7 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.4 2007/10/15 20:00:21 netchild Exp $ + * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.5 2008/01/10 16:09:22 rpaulo Exp $ * */ @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.4 2007/10/15 20:00:21 netchild Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.5 2008/01/10 16:09:22 rpaulo Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -143,6 +143,11 @@ cpu_model += ((cpu_id >> 16) & 0xf) << 4; cpu_mask = cpu_id & 15; +#if 0 /* + * XXXrpaulo: I have this CPU model and when it returns from C3 + * coretemp continues to function properly. + */ + /* * Check for errata AE18. * "Processor Digital Thermal Sensor (DTS) Readout stops @@ -159,6 +164,7 @@ return (ENXIO); } } +#endif /* * On some Core 2 CPUs, there's an undocumented MSR that * can tell us if Tj(max) is 100 or 85. ==== //depot/projects/power/sys/dev/sound/midi/midi.c#3 (text+ko) ==== @@ -1,1054 +1,1528 @@ -/* - * Main midi driver for FreeBSD. This file provides the main - * entry points for probe/attach and all i/o demultiplexing, including - * default routines for generic devices. - * - * (C) 1999 Seigo Tanimura - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: +/*- + * Copyright (c) 2003 Mathew Kanner + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (augustss@netbsd.org). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + /* + * Parts of this file started out as NetBSD: midi.c 1.31 + * They are mostly gone. Still the most obvious will be the state + * machine midi_in + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/sys/dev/sound/midi/midi.c,v 1.24 2007/04/02 06:03:47 ariff Exp $"); + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/conf.h> +#include <sys/selinfo.h> +#include <sys/sysctl.h> +#include <sys/types.h> +#include <sys/malloc.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/poll.h> +#include <sys/sbuf.h> +#include <sys/kobj.h> +#include <sys/module.h> + +#include <dev/sound/midi/midi.h> +#include "mpu_if.h" + +#include <dev/sound/midi/midiq.h> +#include "synth_if.h" +MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area"); + + +#define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) +#define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c) + +#define MIDI_DEV_RAW 2 +#define MIDI_DEV_MIDICTL 12 + +enum midi_states { + MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA +}; + +/* + * The MPU interface current has init() uninit() inqsize(( outqsize() + * callback() : fiddle with the tx|rx status. + */ + +#include "mpu_if.h" + +/* + * /dev/rmidi Structure definitions + */ + +#define MIDI_NAMELEN 16 +struct snd_midi { + KOBJ_FIELDS; + 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 busy; + int flags; /* File flags */ + char name[MIDI_NAMELEN]; + struct mtx qlock; /* Protects inq, outq and flags */ + MIDIQ_HEAD(, char) inq, outq; + int rchan, wchan; + struct selinfo rsel, wsel; + int hiwat; /* QLEN(outq)>High-water -> disable + * writes from userland */ + enum midi_states inq_state; + int inq_status, inq_left; /* Variables for the state machine in + * Midi_in, this is to provide that + * signals only get issued only + * complete command packets. */ + struct proc *async; + struct cdev *dev; + struct synth_midi *synth; + int synth_flags; + TAILQ_ENTRY(snd_midi) link; +}; + +struct synth_midi { + KOBJ_FIELDS; + struct snd_midi *m; +}; + +static synth_open_t midisynth_open; +static synth_close_t midisynth_close; +static synth_writeraw_t midisynth_writeraw; +static synth_killnote_t midisynth_killnote; +static synth_startnote_t midisynth_startnote; +static synth_setinstr_t midisynth_setinstr; +static synth_alloc_t midisynth_alloc; +static synth_controller_t midisynth_controller; +static synth_bender_t midisynth_bender; + + +static kobj_method_t midisynth_methods[] = { + KOBJMETHOD(synth_open, midisynth_open), + KOBJMETHOD(synth_close, midisynth_close), + KOBJMETHOD(synth_writeraw, midisynth_writeraw), + KOBJMETHOD(synth_setinstr, midisynth_setinstr), + KOBJMETHOD(synth_startnote, midisynth_startnote), + KOBJMETHOD(synth_killnote, midisynth_killnote), + KOBJMETHOD(synth_alloc, midisynth_alloc), + KOBJMETHOD(synth_controller, midisynth_controller), + KOBJMETHOD(synth_bender, midisynth_bender), + {0, 0} +}; + +DEFINE_CLASS(midisynth, midisynth_methods, 0); + +/* + * Module Exports & Interface * + * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int + * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int + * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct + * midi_chan *, char *buf, int count) * - * For each card type a template "mididev_info" structure contains - * all the relevant parameters, both for configuration and runtime. + * midi_{in,out} return actual size transfered * - * In this file we build tables of pointers to the descriptors for - * the various supported cards. The generic probe routine scans - * the table(s) looking for a matching entry, then invokes the - * board-specific probe routine. If successful, a pointer to the - * correct mididev_info is stored in mididev_last_probed, for subsequent - * use in the attach routine. The generic attach routine copies - * the template to a permanent descriptor (midi_info and - * friends), initializes all generic parameters, and calls the - * board-specific attach routine. - * - * On device calls, the generic routines do the checks on unit and - * device parameters, then call the board-specific routines if - * available, or try to perform the task using the default code. - * - * $FreeBSD: src/sys/dev/sound/midi/midi.c,v 1.14 2004/02/21 21:10:47 phk Exp $ - * + */ + + +/* + * midi_devs tailq, holder of all rmidi instances protected by midistat_lock */ -#include <dev/sound/midi/midi.h> +TAILQ_HEAD(, snd_midi) midi_devs; + +/* + * /dev/midistat variables and declarations, protected by midistat_lock + */ -static devclass_t midi_devclass; +static struct mtx midistat_lock; +static int midistat_isopen = 0; +static struct sbuf midistat_sbuf; +static int midistat_bufptr; +static struct cdev *midistat_dev; -static d_open_t midiopen; -static d_close_t midiclose; -static d_ioctl_t midiioctl; -static d_read_t midiread; -static d_write_t midiwrite; -static d_poll_t midipoll; +/* + * /dev/midistat dev_t declarations + */ -/* These functions are local. */ static d_open_t midistat_open; static d_close_t midistat_close; static d_read_t midistat_read; -static int midi_initstatus(char *buf, int size); -static int midi_readstatus(char *buf, int *ptr, struct uio *uio); + +static struct cdevsw midistat_cdevsw = { + .d_version = D_VERSION, + .d_open = midistat_open, + .d_close = midistat_close, + .d_read = midistat_read, + .d_name = "midistat", +}; + + +/* + * /dev/rmidi dev_t declarations, struct variable access is protected by + * locks contained within the structure. + */ + +static d_open_t midi_open; +static d_close_t midi_close; +static d_ioctl_t midi_ioctl; +static d_read_t midi_read; +static d_write_t midi_write; +static d_poll_t midi_poll; -#define CDEV_MAJOR MIDI_CDEV_MAJOR static struct cdevsw midi_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = midiopen, - .d_close = midiclose, - .d_read = midiread, - .d_write = midiwrite, - .d_ioctl = midiioctl, - .d_poll = midipoll, - .d_name = "midi", - .d_maj = CDEV_MAJOR, + .d_version = D_VERSION, + .d_open = midi_open, + .d_close = midi_close, + .d_read = midi_read, + .d_write = midi_write, + .d_ioctl = midi_ioctl, + .d_poll = midi_poll, + .d_name = "rmidi", }; /* - * descriptors for active devices. also used as the public softc - * of a device. + * Prototypes of library functions */ -static TAILQ_HEAD(,_mididev_info) midi_info; -static int nmidi, nsynth; -/* Mutex to protect midi_info, nmidi and nsynth. */ -static struct mtx midiinfo_mtx; -static int midiinfo_mtx_init; -/* These make the buffer for /dev/midistat */ -static int midistatbusy; -static char midistatbuf[4096]; -static int midistatptr; +static int midi_destroy(struct snd_midi *, int); +static int midistat_prepare(struct sbuf * s); +static int midi_load(void); +static int midi_unload(void); +/* + * Misc declr. + */ SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver"); +SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD, 0, "Status device"); -int midi_debug; +int midi_debug; +/* XXX: should this be moved into debug.midi? */ SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, ""); -midi_cmdtab cmdtab_midiioctl[] = { - {SNDCTL_MIDI_PRETIME, "SNDCTL_MIDI_PRETIME"}, - {SNDCTL_MIDI_MPUMODE, "SNDCTL_MIDI_MPUMODE"}, - {SNDCTL_MIDI_MPUCMD, "SNDCTL_MIDI_MPUCMD"}, - {SNDCTL_SYNTH_INFO, "SNDCTL_SYNTH_INFO"}, - {SNDCTL_MIDI_INFO, "SNDCTL_MIDI_INFO"}, - {SNDCTL_SYNTH_MEMAVL, "SNDCTL_SYNTH_MEMAVL"}, - {SNDCTL_FM_LOAD_INSTR, "SNDCTL_FM_LOAD_INSTR"}, - {SNDCTL_FM_4OP_ENABLE, "SNDCTL_FM_4OP_ENABLE"}, - {MIOSPASSTHRU, "MIOSPASSTHRU"}, - {MIOGPASSTHRU, "MIOGPASSTHRU"}, - {AIONWRITE, "AIONWRITE"}, - {AIOGSIZE, "AIOGSIZE"}, - {AIOSSIZE, "AIOSSIZE"}, - {AIOGFMT, "AIOGFMT"}, - {AIOSFMT, "AIOSFMT"}, - {AIOGMIX, "AIOGMIX"}, - {AIOSMIX, "AIOSMIX"}, - {AIOSTOP, "AIOSTOP"}, - {AIOSYNC, "AIOSYNC"}, - {AIOGCAP, "AIOGCAP"}, - {-1, NULL}, -}; +int midi_dumpraw; +SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, ""); + +int midi_instroff; +SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, ""); + +int midistat_verbose; +SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW, + &midistat_verbose, 0, ""); + +#define MIDI_DEBUG(l,a) if(midi_debug>=l) a +/* + * CODE START + */ /* - * This is the generic init routine. - * Must be called after device-specific init. + * 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. + * + * It is an error to call midi_init with an already used unit/channel combo. + * + * Returns NULL on error + * */ -int -midiinit(mididev_info *d, device_t dev) +struct snd_midi * +midi_init(kobj_class_t cls, int unit, int channel, void *cookie) { - int unit; + struct snd_midi *m; + int i; + int inqsize, outqsize; + MIDI_TYPE *buf; + MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel)); + mtx_lock(&midistat_lock); /* - * initialize standard parameters for the device. This can be - * overridden by device-specific configurations but better do - * here the generic things. + * 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_NOWAIT | M_ZERO); + if (m == NULL) + goto err0; + + m->synth = malloc(sizeof(*m->synth), M_MIDI, M_NOWAIT | M_ZERO); + kobj_init((kobj_t)m->synth, &midisynth_class); + m->synth->m = m; + kobj_init((kobj_t)m, cls); + inqsize = MPU_INQSIZE(m, cookie); + outqsize = MPU_OUTQSIZE(m, cookie); + + MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize)); + if (!inqsize && !outqsize) + goto err1; + + mtx_init(&m->lock, "raw midi", NULL, 0); + mtx_init(&m->qlock, "q raw midi", NULL, 0); + + mtx_lock(&m->lock); + mtx_lock(&m->qlock); + + if (inqsize) + buf = malloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_NOWAIT); + else + buf = NULL; + + MIDIQ_INIT(m->inq, buf, inqsize); + + if (outqsize) + buf = malloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_NOWAIT); + else + buf = NULL; + m->hiwat = outqsize / 2; - MIDI_DEBUG(printf("midiinit: unit %d.\n", d->unit)); + MIDIQ_INIT(m->outq, buf, outqsize); + + if ((inqsize && !MIDIQ_BUF(m->inq)) || + (outqsize && !MIDIQ_BUF(m->outq))) + goto err2; + + + m->busy = 0; + m->flags = 0; + m->unit = unit; + m->channel = channel; + m->cookie = cookie; + + if (MPU_INIT(m, cookie)) + goto err2; + + mtx_unlock(&m->lock); + mtx_unlock(&m->qlock); + + TAILQ_INSERT_TAIL(&midi_devs, m, link); + + mtx_unlock(&midistat_lock); - unit = d->unit; - d->softc = device_get_softc(dev); - d->dev = dev; - d->magic = MAGIC(d->unit); /* debugging... */ - d->flags = 0; - d->fflags = 0; - d->midi_dbuf_in.unit_size = 1; - d->midi_dbuf_out.unit_size = 1; - d->midi_dbuf_passthru.unit_size = 1; + m->dev = make_dev(&midi_cdevsw, + MIDIMKMINOR(unit, MIDI_DEV_RAW, channel), + UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel); + m->dev->si_drv1 = m; - mtx_unlock(&d->flagqueue_mtx); + return m; - if (midi_devclass == NULL) { - midi_devclass = device_get_devclass(dev); - make_dev(&midi_cdevsw, MIDIMKMINOR(0, MIDI_DEV_STATUS), - UID_ROOT, GID_WHEEL, 0444, "midistat"); - } - make_dev(&midi_cdevsw, MIDIMKMINOR(unit, MIDI_DEV_MIDIN), - UID_ROOT, GID_WHEEL, 0666, "midi%d", unit); +err2: mtx_destroy(&m->qlock); + mtx_destroy(&m->lock); - return 0 ; + if (MIDIQ_BUF(m->inq)) + free(MIDIQ_BUF(m->inq), M_MIDI); + if (MIDIQ_BUF(m->outq)) + free(MIDIQ_BUF(m->outq), M_MIDI); +err1: free(m, M_MIDI); +err0: mtx_unlock(&midistat_lock); + MIDI_DEBUG(1, printf("midi_init ended in error\n")); + return NULL; } /* - * a small utility function which, given a device number, returns - * a pointer to the associated mididev_info struct, and sets the unit - * number. + * midi_uninit does not call MIDI_UNINIT, as since this is the implementors + * entry point. midi_unint if fact, does not send any methods. A call to + * midi_uninit is a defacto promise that you won't manipulate ch anymore + * */ -mididev_info * -get_mididev_info(dev_t i_dev, int *unit) + +int +midi_uninit(struct snd_midi *m) { - int u; + int err; + + err = ENXIO; + mtx_lock(&midistat_lock); + mtx_lock(&m->lock); + if (m->busy) { + if (!(m->rchan || m->wchan)) + goto err; - if (MIDIDEV(i_dev) != MIDI_DEV_MIDIN) - return NULL; - u = MIDIUNIT(i_dev); - if (unit) - *unit = u; + if (m->rchan) { + wakeup(&m->rchan); + m->rchan = 0; + } + if (m->wchan) { + wakeup(&m->wchan); + m->wchan = 0; + } + } + err = midi_destroy(m, 0); + if (!err) + goto exit; - return get_mididev_info_unit(u); +err: mtx_unlock(&m->lock); +exit: mtx_unlock(&midistat_lock); + return err; } /* - * a small utility function which, given a unit number, returns - * a pointer to the associated mididev_info struct. + * midi_in: process all data until the queue is full, then discards the rest. + * Since midi_in is a state machine, data discards can cause it to get out of + * whack. Process as much as possible. It calls, wakeup, selnotify and + * psignal at most once. */ -mididev_info * -get_mididev_info_unit(int unit) + +#ifdef notdef +static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0}; + +#endif /* notdef */ +/* Number of bytes in a MIDI command */ +#define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7]) +#define MIDI_ACK 0xfe +#define MIDI_IS_STATUS(d) ((d) >= 0x80) +#define MIDI_IS_COMMON(d) ((d) >= 0xf0) + +#define MIDI_SYSEX_START 0xF0 +#define MIDI_SYSEX_END 0xF7 + + +int +midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size) { - mididev_info *md; + /* int i, sig, enq; */ + int used; + + /* MIDI_TYPE data; */ + MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size)); + +/* + * XXX: locking flub + */ + if (!(m->flags & M_RX)) + return size; + + used = 0; + + mtx_lock(&m->qlock); +#if 0 + /* + * Don't bother queuing if not in read mode. Discard everything and + * return size so the caller doesn't freak out. + */ + + if (!(m->flags & M_RX)) + return size; + + for (i = sig = 0; i < size; i++) { + + data = buf[i]; + enq = 0; + if (data == MIDI_ACK) + continue; - /* XXX */ - if (!midiinfo_mtx_init) { - midiinfo_mtx_init = 1; - mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF); - TAILQ_INIT(&midi_info); - } + switch (m->inq_state) { + case MIDI_IN_START: + if (MIDI_IS_STATUS(data)) { + switch (data) { + case 0xf0: /* Sysex */ + m->inq_state = MIDI_IN_SYSEX; + break; + case 0xf1: /* MTC quarter frame */ + case 0xf3: /* Song select */ + m->inq_state = MIDI_IN_DATA; + enq = 1; + m->inq_left = 1; + break; + case 0xf2: /* Song position pointer */ + m->inq_state = MIDI_IN_DATA; + enq = 1; + m->inq_left = 2; + break; + default: + if (MIDI_IS_COMMON(data)) { + enq = 1; + sig = 1; + } else { + m->inq_state = MIDI_IN_DATA; + enq = 1; + m->inq_status = data; + m->inq_left = MIDI_LENGTH(data); + } + break; + } + } else if (MIDI_IS_STATUS(m->inq_status)) { + m->inq_state = MIDI_IN_DATA; + if (!MIDIQ_FULL(m->inq)) { + used++; + MIDIQ_ENQ(m->inq, &m->inq_status, 1); + } + enq = 1; + m->inq_left = MIDI_LENGTH(m->inq_status) - 1; + } + break; + /* + * End of case MIDI_IN_START: + */ - mtx_lock(&midiinfo_mtx); - TAILQ_FOREACH(md, &midi_info, md_link) { - if (md->unit == unit) + case MIDI_IN_DATA: + enq = 1; + if (--m->inq_left <= 0) + sig = 1;/* deliver data */ + break; + case MIDI_IN_SYSEX: + if (data == MIDI_SYSEX_END) + m->inq_state = MIDI_IN_START; break; + } + + if (enq) + if (!MIDIQ_FULL(m->inq)) { + MIDIQ_ENQ(m->inq, &data, 1); + used++; + } + /* + * End of the state machines main "for loop" + */ + } + if (sig) { +#endif + MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n", + (intmax_t)MIDIQ_LEN(m->inq), + (intmax_t)MIDIQ_AVAIL(m->inq))); + if (MIDIQ_AVAIL(m->inq) > size) { + used = size; + MIDIQ_ENQ(m->inq, buf, size); + } else { + MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n")); + mtx_unlock(&m->qlock); + return 0; + } + if (m->rchan) { + wakeup(&m->rchan); + m->rchan = 0; + } + selwakeup(&m->rsel); + if (m->async) { + PROC_LOCK(m->async); + psignal(m->async, SIGIO); + PROC_UNLOCK(m->async); + } +#if 0 } - mtx_unlock(&midiinfo_mtx); - - return md; +#endif + mtx_unlock(&m->qlock); + return used; } /* - * a small utility function which, given a unit number, returns - * a pointer to the associated mididev_info struct with MDT_MIDI. + * midi_out: The only clearer of the M_TXEN flag. */ -mididev_info * -get_mididev_midi_unit(int unit) +int +midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size) { - mididev_info *md; + int used; + +/* + * XXX: locking flub + */ + if (!(m->flags & M_TXEN)) + return 0; - /* XXX */ - if (!midiinfo_mtx_init) { - midiinfo_mtx_init = 1; - mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF); - TAILQ_INIT(&midi_info); + MIDI_DEBUG(2, printf("midi_out: %p\n", m)); + mtx_lock(&m->qlock); + used = MIN(size, MIDIQ_LEN(m->outq)); + MIDI_DEBUG(3, printf("midi_out: used %d\n", used)); + if (used) + MIDIQ_DEQ(m->outq, buf, used); + if (MIDIQ_EMPTY(m->outq)) { + m->flags &= ~M_TXEN; + MPU_CALLBACKP(m, m->cookie, m->flags); } - - mtx_lock(&midiinfo_mtx); - TAILQ_FOREACH(md, &midi_info, md_link) { - if (md->midiunit == unit) - break; + if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) { + if (m->wchan) { + wakeup(&m->wchan); + m->wchan = 0; + } + selwakeup(&m->wsel); + if (m->async) { + PROC_LOCK(m->async); + psignal(m->async, SIGIO); + PROC_UNLOCK(m->async); + } } - mtx_unlock(&midiinfo_mtx); + mtx_unlock(&m->qlock); + return used; +} - return md; -} /* - * a small utility function which, given a unit number, returns - * a pointer to the associated mididev_info struct with MDT_SYNTH. + * /dev/rmidi#.# device access functions */ -mididev_info * -get_mididev_synth_unit(int unit) +int +midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td) { - mididev_info *md; + struct snd_midi *m = i_dev->si_drv1; + int retval; + + MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td, + flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); + if (m == NULL) + return ENXIO; + + mtx_lock(&m->lock); + mtx_lock(&m->qlock); + + retval = 0; - /* XXX */ - if (!midiinfo_mtx_init) { - midiinfo_mtx_init = 1; - mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF); - TAILQ_INIT(&midi_info); + if (flags & FREAD) { + if (MIDIQ_SIZE(m->inq) == 0) + retval = ENXIO; + else if (m->flags & M_RX) + retval = EBUSY; + if (retval) + goto err; + } + if (flags & FWRITE) { + if (MIDIQ_SIZE(m->outq) == 0) + retval = ENXIO; + else if (m->flags & M_TX) + retval = EBUSY; + if (retval) + goto err; } + m->busy++; + + m->rchan = 0; + m->wchan = 0; + m->async = 0; - mtx_lock(&midiinfo_mtx); - TAILQ_FOREACH(md, &midi_info, md_link) { - if (md->synthunit == unit) - break; - } - mtx_unlock(&midiinfo_mtx); + if (flags & FREAD) { + m->flags |= M_RX | M_RXEN; + /* + * Only clear the inq, the outq might still have data to drain + * from a previous session + */ + MIDIQ_CLEAR(m->inq); + }; + + if (flags & FWRITE) + m->flags |= M_TX; + + MPU_CALLBACK(m, m->cookie, m->flags); + + MIDI_DEBUG(2, printf("midi_open: opened.\n")); - return md; +err: mtx_unlock(&m->qlock); + mtx_unlock(&m->lock); + return retval; } -/* Create a new midi device info structure. */ -/* TODO: lock md, then exit. */ -mididev_info * -create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf) +int +midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td) { - int unit; - mididev_info *md, *mdnew; + struct snd_midi *m = i_dev->si_drv1; + int retval; + int oldflags; - /* XXX */ - if (!midiinfo_mtx_init) { - midiinfo_mtx_init = 1; - mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF); - TAILQ_INIT(&midi_info); - } + MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td, + flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); - /* As malloc(9) might block, allocate mididev_info now. */ - mdnew = malloc(sizeof(mididev_info), M_DEVBUF, M_WAITOK | M_ZERO); - if (mdnew == NULL) - return NULL; - bcopy(mdinf, mdnew, sizeof(mididev_info)); - bcopy(syninf, &mdnew->synth, sizeof(synthdev_info)); - midibuf_init(&mdnew->midi_dbuf_in); - midibuf_init(&mdnew->midi_dbuf_out); - midibuf_init(&mdnew->midi_dbuf_passthru); - mtx_init(&mdnew->flagqueue_mtx, "midflq", NULL, MTX_DEF); - mtx_init(&mdnew->synth.vc_mtx, "synsvc", NULL, MTX_DEF); - mtx_init(&mdnew->synth.status_mtx, "synsst", NULL, MTX_DEF); + if (m == NULL) + return ENXIO; - mtx_lock(&midiinfo_mtx); + mtx_lock(&m->lock); + mtx_lock(&m->qlock); - switch (type) { - case MDT_MIDI: - mdnew->midiunit = nmidi; - mdnew->synthunit = nmidi; - nmidi++; - break; - case MDT_SYNTH: - mdnew->midiunit = -1; - mdnew->synthunit = nsynth; - nsynth++; - break; - default: - mtx_unlock(&midiinfo_mtx); - midibuf_destroy(&mdnew->midi_dbuf_in); - midibuf_destroy(&mdnew->midi_dbuf_out); - midibuf_destroy(&mdnew->midi_dbuf_passthru); - mtx_destroy(&mdnew->flagqueue_mtx); - mtx_destroy(&mdnew->synth.vc_mtx); - mtx_destroy(&mdnew->synth.status_mtx); - free(mdnew, M_DEVBUF); - panic("unsupported device type"); - return NULL; + if ((flags & FREAD && !(m->flags & M_RX)) || + (flags & FWRITE && !(m->flags & M_TX))) { + retval = ENXIO; >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801101645.m0AGjOKW033069>