diff options
Diffstat (limited to 'sys/i386/isa/sound/midibuf.c')
-rw-r--r-- | sys/i386/isa/sound/midibuf.c | 618 |
1 files changed, 302 insertions, 316 deletions
diff --git a/sys/i386/isa/sound/midibuf.c b/sys/i386/isa/sound/midibuf.c index ae0ddc3ea54b..e452e0a35f21 100644 --- a/sys/i386/isa/sound/midibuf.c +++ b/sys/i386/isa/sound/midibuf.c @@ -1,10 +1,10 @@ /* * sound/midibuf.c - * + * * Device file manager for /dev/midi# - * + * * Copyright by Hannu Savolainen 1993 - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * * 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 @@ -24,420 +24,406 @@ * 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. - * + * */ -#include "sound_config.h" +#include <i386/isa/sound/sound_config.h> -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI) + +#if defined(CONFIG_MIDI) /* * Don't make MAX_QUEUE_SIZE larger than 4000 */ #define MAX_QUEUE_SIZE 4000 +int +MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait); + +void +drain_midi_queue(int dev); + +static int *midi_sleeper[MAX_MIDI_DEV] = {NULL}; +static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] = { {0}}; +static int *input_sleeper[MAX_MIDI_DEV] = {NULL}; +static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] = { {0}}; -DEFINE_WAIT_QUEUES (midi_sleeper[MAX_MIDI_DEV], midi_sleep_flag[MAX_MIDI_DEV]); -DEFINE_WAIT_QUEUES (input_sleeper[MAX_MIDI_DEV], input_sleep_flag[MAX_MIDI_DEV]); - -struct midi_buf - { - int len, head, tail; - unsigned char queue[MAX_QUEUE_SIZE]; - }; - -struct midi_parms - { - int prech_timeout; /* - * Timeout before the first ch - */ - }; - -static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = -{NULL}; -static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = -{NULL}; +struct midi_buf { + int len, head, tail; + u_char queue[MAX_QUEUE_SIZE]; +}; + +struct midi_parms { + int prech_timeout; /* Timeout before the first ch */ +}; + +static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL}; +static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL}; static struct midi_parms parms[MAX_MIDI_DEV]; -static void midi_poll (unsigned long dummy); +static void midi_poll(void *dummy); -DEFINE_TIMER (poll_timer, midi_poll); static volatile int open_devs = 0; #define DATA_AVAIL(q) (q->len) #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len) #define QUEUE_BYTE(q, data) \ - if (SPACE_AVAIL(q)) \ - { \ - unsigned long flags; \ - DISABLE_INTR(flags); \ + if (SPACE_AVAIL(q)) { \ + u_long flags; \ + flags = splhigh(); \ q->queue[q->tail] = (data); \ q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \ - RESTORE_INTR(flags); \ + splx(flags); \ } #define REMOVE_BYTE(q, data) \ - if (DATA_AVAIL(q)) \ - { \ - unsigned long flags; \ - DISABLE_INTR(flags); \ + if (DATA_AVAIL(q)) { \ + u_long flags; \ + flags = splhigh(); \ data = q->queue[q->head]; \ q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \ - RESTORE_INTR(flags); \ + splx(flags); \ } void -drain_midi_queue (int dev) +drain_midi_queue(int dev) { - /* - * Give the Midi driver time to drain its output queues - */ + /* + * Give the Midi driver time to drain its output queues + */ + + if (midi_devs[dev]->buffer_status != NULL) + while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) && + midi_devs[dev]->buffer_status(dev)) { + int chn; + + midi_sleeper[dev] = &chn; + DO_SLEEP(chn, midi_sleep_flag[dev], hz / 10); - if (midi_devs[dev]->buffer_status != NULL) - while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) && - midi_devs[dev]->buffer_status (dev)) - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], HZ / 10); + }; } static void -midi_input_intr (int dev, unsigned char data) +midi_input_intr(int dev, u_char data) { - if (midi_in_buf[dev] == NULL) - return; - - if (data == 0xfe) /* - * Active sensing - */ - return; /* - * Ignore - */ - - if (SPACE_AVAIL (midi_in_buf[dev])) - { - QUEUE_BYTE (midi_in_buf[dev], data); - if (SOMEONE_WAITING (input_sleeper[dev], input_sleep_flag[dev])) - WAKE_UP (input_sleeper[dev], input_sleep_flag[dev]); - } - + if (midi_in_buf[dev] == NULL) + return; + + if (data == 0xfe) /* Active sensing */ + return; /* Ignore */ + + if (SPACE_AVAIL(midi_in_buf[dev])) { + QUEUE_BYTE(midi_in_buf[dev], data); + if ((input_sleep_flag[dev].mode & WK_SLEEP)) { + input_sleep_flag[dev].mode = WK_WAKEUP; + wakeup(input_sleeper[dev]); + }; + } } static void -midi_output_intr (int dev) +midi_output_intr(int dev) { - /* - * Currently NOP - */ + /* + * Currently NOP + */ } static void -midi_poll (unsigned long dummy) +midi_poll(void *dummy) { - unsigned long flags; - int dev; - - DISABLE_INTR (flags); - if (open_devs) - { - for (dev = 0; dev < num_midis; dev++) - if (midi_out_buf[dev] != NULL) - { - while (DATA_AVAIL (midi_out_buf[dev]) && - midi_devs[dev]->putc (dev, - midi_out_buf[dev]->queue[midi_out_buf[dev]->head])) - { - midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE; - midi_out_buf[dev]->len--; - } - - if (DATA_AVAIL (midi_out_buf[dev]) < 100 && - SOMEONE_WAITING (midi_sleeper[dev], midi_sleep_flag[dev])) - WAKE_UP (midi_sleeper[dev], midi_sleep_flag[dev]); - } - ACTIVATE_TIMER (poll_timer, midi_poll, 1); /* - * Come back later - */ - } - RESTORE_INTR (flags); + u_long flags; + int dev; + + flags = splhigh(); + if (open_devs) { + for (dev = 0; dev < num_midis; dev++) + if (midi_out_buf[dev] != NULL) { + while (DATA_AVAIL(midi_out_buf[dev]) && + midi_devs[dev]->putc(dev, + midi_out_buf[dev]->queue[midi_out_buf[dev]->head])) { + midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE; + midi_out_buf[dev]->len--; + } + + if (DATA_AVAIL(midi_out_buf[dev]) < 100 && + (midi_sleep_flag[dev].mode & WK_SLEEP)) { + midi_sleep_flag[dev].mode = WK_WAKEUP; + wakeup(midi_sleeper[dev]); + }; + } + timeout( midi_poll, 0, 1);; /* Come back later */ + } + splx(flags); } int -MIDIbuf_open (int dev, struct fileinfo *file) +MIDIbuf_open(int dev, struct fileinfo * file) { - int mode, err; - unsigned long flags; + int mode, err; - dev = dev >> 4; - mode = file->mode & O_ACCMODE; - - if (num_midis > MAX_MIDI_DEV) - { - printk ("Sound: FATAL ERROR: Too many midi interfaces\n"); - num_midis = MAX_MIDI_DEV; - } - - if (dev < 0 || dev >= num_midis) - { - printk ("Sound: Nonexistent MIDI interface %d\n", dev); - return RET_ERROR (ENXIO); - } - - /* - * Interrupts disabled. Be careful - */ + dev = dev >> 4; + mode = file->mode & O_ACCMODE; + + if (num_midis > MAX_MIDI_DEV) { + printf("Sound: FATAL ERROR: Too many midi interfaces\n"); + num_midis = MAX_MIDI_DEV; + } + if (dev < 0 || dev >= num_midis) { + printf("Sound: Nonexistent MIDI interface %d\n", dev); + return -(ENXIO); + } + /* + * Interrupts disabled. Be careful + */ - DISABLE_INTR (flags); - if ((err = midi_devs[dev]->open (dev, mode, - midi_input_intr, midi_output_intr)) < 0) - { - RESTORE_INTR (flags); - return err; - } - - parms[dev].prech_timeout = 0; - - RESET_WAIT_QUEUE (midi_sleeper[dev], midi_sleep_flag[dev]); - RESET_WAIT_QUEUE (input_sleeper[dev], input_sleep_flag[dev]); - - midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf)); - - if (midi_in_buf[dev] == NULL) - { - printk ("midi: Can't allocate buffer\n"); - midi_devs[dev]->close (dev); - RESTORE_INTR (flags); - return RET_ERROR (EIO); - } - midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; - - midi_out_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf)); - - if (midi_out_buf[dev] == NULL) - { - printk ("midi: Can't allocate buffer\n"); - midi_devs[dev]->close (dev); - KERNEL_FREE (midi_in_buf[dev]); - midi_in_buf[dev] = NULL; - RESTORE_INTR (flags); - return RET_ERROR (EIO); - } - midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; - if (!open_devs) - ACTIVATE_TIMER (poll_timer, midi_poll, 1); /* - * Come back later - */ - open_devs++; - RESTORE_INTR (flags); - - return err; + if ((err = midi_devs[dev]->open(dev, mode, + midi_input_intr, midi_output_intr)) < 0) { + return err; + } + parms[dev].prech_timeout = 0; + + midi_in_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK); + + if (midi_in_buf[dev] == NULL) { + printf("midi: Can't allocate buffer\n"); + midi_devs[dev]->close(dev); + return -(EIO); + } + midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; + + midi_out_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK); + + if (midi_out_buf[dev] == NULL) { + printf("midi: Can't allocate buffer\n"); + midi_devs[dev]->close(dev); + free(midi_in_buf[dev], M_TEMP); + midi_in_buf[dev] = NULL; + return -(EIO); + } + midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; + open_devs++; + + { + midi_sleep_flag[dev].aborting = 0; + midi_sleep_flag[dev].mode = WK_NONE; + }; + { + input_sleep_flag[dev].aborting = 0; + input_sleep_flag[dev].mode = WK_NONE; + }; + + if (open_devs < 2) { /* This was first open */ + { + }; + + timeout( midi_poll, 0, 1);; /* Start polling */ + } + return err; } void -MIDIbuf_release (int dev, struct fileinfo *file) +MIDIbuf_release(int dev, struct fileinfo * file) { - int mode; - unsigned long flags; + int mode; + u_long flags; - dev = dev >> 4; - mode = file->mode & O_ACCMODE; + dev = dev >> 4; + mode = file->mode & O_ACCMODE; - DISABLE_INTR (flags); + if (dev < 0 || dev >= num_midis) + return; - /* - * Wait until the queue is empty - */ + flags = splhigh(); + + /* + * Wait until the queue is empty + */ - if (mode != OPEN_READ) - { - midi_devs[dev]->putc (dev, 0xfe); /* - * Active sensing to shut the - * devices - */ - - while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) && - DATA_AVAIL (midi_out_buf[dev])) - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); /* - * Sync - */ - - drain_midi_queue (dev); /* - * Ensure the output queues are empty - */ - } - - midi_devs[dev]->close (dev); - KERNEL_FREE (midi_in_buf[dev]); - KERNEL_FREE (midi_out_buf[dev]); - midi_in_buf[dev] = NULL; - midi_out_buf[dev] = NULL; - open_devs--; - RESTORE_INTR (flags); + if (mode != OPEN_READ) { + midi_devs[dev]->putc(dev, 0xfe); /* Active sensing to + * shut the devices */ + + while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) && + DATA_AVAIL(midi_out_buf[dev])) { + int chn; + midi_sleeper[dev] = &chn; + DO_SLEEP(chn, midi_sleep_flag[dev], 0); + + }; /* Sync */ + + drain_midi_queue(dev); /* Ensure the output queues are empty */ + } + splx(flags); + + midi_devs[dev]->close(dev); + + free(midi_in_buf[dev], M_TEMP); + free(midi_out_buf[dev], M_TEMP); + midi_in_buf[dev] = NULL; + midi_out_buf[dev] = NULL; + if (open_devs < 2) { + }; + open_devs--; } int -MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +MIDIbuf_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count) { - unsigned long flags; - int c, n, i; - unsigned char tmp_data; + u_long flags; + int c, n, i; + u_char tmp_data; - dev = dev >> 4; + dev = dev >> 4; - if (!count) - return 0; + if (!count) + return 0; - DISABLE_INTR (flags); + flags = splhigh(); - c = 0; + c = 0; - while (c < count) - { - n = SPACE_AVAIL (midi_out_buf[dev]); + while (c < count) { + n = SPACE_AVAIL(midi_out_buf[dev]); - if (n == 0) /* - * No space just now. We have to sleep - */ - { - DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0); - if (PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev])) - { - RESTORE_INTR (flags); - return RET_ERROR (EINTR); - } - - n = SPACE_AVAIL (midi_out_buf[dev]); - } + if (n == 0) { /* No space just now. We have to sleep */ - if (n > (count - c)) - n = count - c; + { + int chn; - for (i = 0; i < n; i++) - { - COPY_FROM_USER (&tmp_data, buf, c, 1); - QUEUE_BYTE (midi_out_buf[dev], tmp_data); - c++; + midi_sleeper[dev] = &chn; + DO_SLEEP(chn, midi_sleep_flag[dev], 0); + }; + + if (PROCESS_ABORTING(midi_sleep_flag[dev])) { + splx(flags); + return -(EINTR); + } + n = SPACE_AVAIL(midi_out_buf[dev]); + } + if (n > (count - c)) + n = count - c; + + for (i = 0; i < n; i++) { + + if (uiomove((char *) &tmp_data, 1, buf)) { + printf("sb: Bad copyin()!\n"); + }; + QUEUE_BYTE(midi_out_buf[dev], tmp_data); + c++; + } } - } - RESTORE_INTR (flags); + splx(flags); - return c; + return c; } int -MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +MIDIbuf_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count) { - int n, c = 0; - unsigned long flags; - unsigned char tmp_data; + int n, c = 0; + u_long flags; + u_char tmp_data; - dev = dev >> 4; + dev = dev >> 4; - DISABLE_INTR (flags); - - if (!DATA_AVAIL (midi_in_buf[dev])) /* - * No data yet, wait - */ - { - DO_SLEEP (input_sleeper[dev], input_sleep_flag[dev], - parms[dev].prech_timeout); - if (PROCESS_ABORTING (input_sleeper[dev], input_sleep_flag[dev])) - c = RET_ERROR (EINTR); /* - * The user is getting restless - */ - } - - if (c == 0 && DATA_AVAIL (midi_in_buf[dev])) /* - * Got some bytes - */ - { - n = DATA_AVAIL (midi_in_buf[dev]); - if (n > count) - n = count; - c = 0; - - while (c < n) - { - REMOVE_BYTE (midi_in_buf[dev], tmp_data); - COPY_TO_USER (buf, c, &tmp_data, 1); - c++; - } - } + flags = splhigh(); + + if (!DATA_AVAIL(midi_in_buf[dev])) { /* No data yet, wait */ - RESTORE_INTR (flags); + { + int chn; - return c; + + input_sleeper[dev] = &chn; + DO_SLEEP(chn, input_sleep_flag[dev], + parms[dev].prech_timeout); + + }; + if (PROCESS_ABORTING(input_sleep_flag[dev])) + c = -(EINTR); /* The user is getting restless */ + } + if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) { /* Got some bytes */ + n = DATA_AVAIL(midi_in_buf[dev]); + if (n > count) + n = count; + c = 0; + + while (c < n) { + REMOVE_BYTE(midi_in_buf[dev], tmp_data); + + if (uiomove((char *) &tmp_data, 1, buf)) { + printf("sb: Bad copyout()!\n"); + }; + c++; + } + } + splx(flags); + + return c; } int -MIDIbuf_ioctl (int dev, struct fileinfo *file, - unsigned int cmd, unsigned int arg) +MIDIbuf_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg) { - int val; + int val; - dev = dev >> 4; + dev = dev >> 4; - switch (cmd) - { + if (((cmd >> 8) & 0xff) == 'C') { + if (midi_devs[dev]->coproc) /* Coprocessor ioctl */ + return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0); + else + printf("/dev/midi%d: No coprocessor for this device\n", dev); - case SNDCTL_MIDI_PRETIME: - val = IOCTL_IN (arg); - if (val < 0) - val = 0; + return -(ENXIO); + } else + switch (cmd) { - val = (HZ * val) / 10; - parms[dev].prech_timeout = val; - return IOCTL_OUT (arg, val); - break; + case SNDCTL_MIDI_PRETIME: + val = (int) (*(int *) arg); + if (val < 0) + val = 0; - default: - return midi_devs[dev]->ioctl (dev, cmd, arg); - } + val = (hz * val) / 10; + parms[dev].prech_timeout = val; + return *(int *) arg = val; + break; + + default: + return midi_devs[dev]->ioctl(dev, cmd, arg); + } } -#ifdef ALLOW_SELECT +#ifdef ALLOW_POLL int -MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait) +MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait) { - dev = dev >> 4; + int revents = 0; - switch (sel_type) - { - case SEL_IN: - if (!DATA_AVAIL (midi_in_buf[dev])) - { - input_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&input_sleeper[dev], wait); - return 0; - } - return 1; - break; + dev = dev >> 4; - case SEL_OUT: - if (SPACE_AVAIL (midi_out_buf[dev])) - { - midi_sleep_flag[dev].mode = WK_SLEEP; - select_wait (&midi_sleeper[dev], wait); - return 0; - } - return 1; - break; + if (events & (POLLIN | POLLRDNORM)) + if (!DATA_AVAIL (midi_in_buf[dev])) + selrecord(wait, &selinfo[dev]); + else + revents |= events & (POLLIN | POLLRDNORM); - case SEL_EX: - return 0; - } + if (events & (POLLOUT | POLLWRNORM)) + if (SPACE_AVAIL (midi_out_buf[dev])) + selrecord(wait, &selinfo[dev]); + else + revents |= events & (POLLOUT | POLLWRNORM); - return 0; + return revents; } #endif /* ALLOW_SELECT */ -long -MIDIbuf_init (long mem_start) -{ - return mem_start; -} + #endif |