summaryrefslogtreecommitdiff
path: root/sys/i386/isa/sound/sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/isa/sound/sequencer.c')
-rw-r--r--sys/i386/isa/sound/sequencer.c311
1 files changed, 166 insertions, 145 deletions
diff --git a/sys/i386/isa/sound/sequencer.c b/sys/i386/isa/sound/sequencer.c
index 7df08120ebcc5..1a39432899588 100644
--- a/sys/i386/isa/sound/sequencer.c
+++ b/sys/i386/isa/sound/sequencer.c
@@ -1,10 +1,10 @@
/*
- * linux/kernel/chr_drv/sound/sequencer.c
- *
+ * sound/sequencer.c
+ *
* The sequencer personality manager.
- *
+ *
* 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,7 +24,7 @@
* 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.
- *
+ *
*/
#define SEQUENCER_C
@@ -37,20 +37,24 @@
static int sequencer_ok = 0;
DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);
-DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);
+/* DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); */
+#define midi_sleeper seq_sleeper
+#define midi_sleep_flag seq_sleep_flag
static int midi_opened[MAX_MIDI_DEV] =
{0}; /* 1 if the process has opened MIDI */
static int midi_written[MAX_MIDI_DEV] =
{0};
-long seq_time = 0; /* Reference point for the timer */
+unsigned long seq_time = 0; /* Reference point for the timer */
#include "tuning.h"
#define EV_SZ 8
-static unsigned char queue[SEQ_MAX_QUEUE][EV_SZ];
-static unsigned char iqueue[SEQ_MAX_QUEUE][4];
+#define IEV_SZ 4
+static unsigned char *queue = NULL; /* SEQ_MAX_QUEUE * EV_SZ bytes */
+static unsigned char *iqueue = NULL; /* SEQ_MAX_QUEUE * IEV_SZ bytes */
+
static volatile int qhead = 0, qtail = 0, qlen = 0;
static volatile int iqhead = 0, iqtail = 0, iqlen = 0;
static volatile int seq_playing = 0;
@@ -83,13 +87,16 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
if (!iqlen)
{
- INTERRUPTIBLE_SLEEP_ON (midi_sleeper, midi_sleep_flag);
+ if (c != count) /* Some data has been received */
+ return count - c; /* Return what we have */
+
+ DO_SLEEP (midi_sleeper, midi_sleep_flag, 0);
if (!iqlen)
return count - c;
}
- COPY_TO_USER (buf, p, &iqueue[iqhead][0], 4);
+ COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], IEV_SZ);
p += 4;
c -= 4;
@@ -114,14 +121,14 @@ copy_to_input (unsigned char *event)
if (iqlen >= (SEQ_MAX_QUEUE - 1))
return; /* Overflow */
- memcpy (iqueue[iqtail], event, 4);
+ memcpy (&iqueue[iqtail * IEV_SZ], event, IEV_SZ);
iqlen++;
iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
DISABLE_INTR (flags);
- if (midi_sleep_flag)
+ if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))
{
- WAKE_UP (midi_sleeper);
+ WAKE_UP (midi_sleeper, midi_sleep_flag);
}
RESTORE_INTR (flags);
}
@@ -266,16 +273,16 @@ seq_queue (unsigned char *note)
if (!seq_playing)
seq_startplay (); /* Give chance to drain the queue */
- if (qlen >= SEQ_MAX_QUEUE && !seq_sleep_flag)
+ if (qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
/* Sleep until there is enough space on the queue */
- INTERRUPTIBLE_SLEEP_ON (seq_sleeper, seq_sleep_flag);
+ DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
if (qlen >= SEQ_MAX_QUEUE)
return 0; /* To be sure */
- memcpy (&queue[qtail][0], note, EV_SZ);
+ memcpy (&queue[qtail * EV_SZ], note, EV_SZ);
qtail = (qtail + 1) % SEQ_MAX_QUEUE;
qlen++;
@@ -323,6 +330,10 @@ extended_event (unsigned char *q)
synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]);
break;
+ case SEQ_VOLMODE:
+ synth_devs[dev]->volume_method (dev, q[3]);
+ break;
+
default:
return RET_ERROR (EINVAL);
}
@@ -342,7 +353,7 @@ seq_startplay (void)
qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;
qlen--;
- q = &queue[this_one][0];
+ q = &queue[this_one * EV_SZ];
switch (q[0])
{
@@ -378,10 +389,9 @@ seq_startplay (void)
unsigned long flags;
DISABLE_INTR (flags);
- if (seq_sleep_flag)
+ if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
- seq_sleep_flag = 0;
- WAKE_UP (seq_sleeper);
+ WAKE_UP (seq_sleeper, seq_sleep_flag);
}
RESTORE_INTR (flags);
}
@@ -449,10 +459,9 @@ seq_startplay (void)
unsigned long flags;
DISABLE_INTR (flags);
- if (seq_sleep_flag)
+ if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
- seq_sleep_flag = 0;
- WAKE_UP (seq_sleeper);
+ WAKE_UP (seq_sleeper, seq_sleep_flag);
}
RESTORE_INTR (flags);
}
@@ -461,86 +470,87 @@ seq_startplay (void)
int
sequencer_open (int dev, struct fileinfo *file)
- {
- int retval, mode, i;
+{
+ int retval, mode, i;
- dev = dev >> 4;
- mode = file->mode & O_ACCMODE;
+ dev = dev >> 4;
+ mode = file->mode & O_ACCMODE;
- DEB (printk ("sequencer_open(dev=%d)\n", dev));
+ DEB (printk ("sequencer_open(dev=%d)\n", dev));
- if (!sequencer_ok)
- {
- printk ("Soundcard: Sequencer not initialized\n");
- return RET_ERROR (ENXIO);
- }
+ if (!sequencer_ok)
+ {
+ printk ("Soundcard: Sequencer not initialized\n");
+ return RET_ERROR (ENXIO);
+ }
- if (dev) /* Patch manager device */
- {
- int err;
+ if (dev) /* Patch manager device */
+ {
+ int err;
- dev--;
- if (pmgr_present[dev])
- return RET_ERROR (EBUSY);
- if ((err = pmgr_open (dev)) < 0)
- return err; /* Failed */
+ dev--;
+ if (pmgr_present[dev])
+ return RET_ERROR (EBUSY);
+ if ((err = pmgr_open (dev)) < 0)
+ return err; /* Failed */
- pmgr_present[dev] = 1;
- return err;
- }
+ pmgr_present[dev] = 1;
+ return err;
+ }
- if (sequencer_busy)
- {
- printk ("Sequencer busy\n");
- return RET_ERROR (EBUSY);
- }
+ if (sequencer_busy)
+ {
+ printk ("Sequencer busy\n");
+ return RET_ERROR (EBUSY);
+ }
- if (!(num_synths + num_midis))
- return RET_ERROR (ENXIO);
+ if (!(num_synths + num_midis))
+ return RET_ERROR (ENXIO);
- synth_open_mask = 0;
+ synth_open_mask = 0;
- if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
- for (i = 0; i < num_synths; i++) /* Open synth devices */
- if (synth_devs[i]->open (i, mode) < 0)
- printk ("Sequencer: Warning! Cannot open synth device #%d\n", i);
- else
- synth_open_mask |= (1 << i);
+ if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
+ for (i = 0; i < num_synths; i++) /* Open synth devices */
+ if (synth_devs[i]->open (i, mode) < 0)
+ printk ("Sequencer: Warning! Cannot open synth device #%d\n", i);
+ else
+ synth_open_mask |= (1 << i);
- seq_time = GET_TIME ();
+ seq_time = GET_TIME ();
- for (i = 0; i < num_midis; i++)
- {
- midi_opened[i] = 0;
- midi_written[i] = 0;
- }
+ for (i = 0; i < num_midis; i++)
+ {
+ midi_opened[i] = 0;
+ midi_written[i] = 0;
+ }
- if (mode == OPEN_READ || mode == OPEN_READWRITE)
- { /* Initialize midi input devices */
- if (!num_midis)
- {
- printk ("Sequencer: No Midi devices. Input not possible\n");
- return RET_ERROR (ENXIO);
- }
+ if (mode == OPEN_READ || mode == OPEN_READWRITE)
+ { /* Initialize midi input devices */
+ if (!num_midis)
+ {
+ printk ("Sequencer: No Midi devices. Input not possible\n");
+ return RET_ERROR (ENXIO);
+ }
- for (i = 0; i < num_midis; i++)
- {
- if ((retval = midi_devs[i]->open (i, mode,
+ for (i = 0; i < num_midis; i++)
+ {
+ if ((retval = midi_devs[i]->open (i, mode,
sequencer_midi_input, sequencer_midi_output)) >= 0)
- midi_opened[i] = 1;
- }
- }
+ midi_opened[i] = 1;
+ }
+ }
- sequencer_busy = 1;
- seq_sleep_flag = midi_sleep_flag = 0;
- output_treshold = SEQ_MAX_QUEUE / 2;
+ sequencer_busy = 1;
+ RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);
+ RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);
+ output_treshold = SEQ_MAX_QUEUE / 2;
- for (i = 0; i < num_synths; i++)
- if (pmgr_present[i])
- pmgr_inform (i, PM_E_OPENED, 0, 0, 0, 0);
+ for (i = 0; i < num_synths; i++)
+ if (pmgr_present[i])
+ pmgr_inform (i, PM_E_OPENED, 0, 0, 0, 0);
- return 0;
- }
+ return 0;
+}
void
seq_drain_midi_queues (void)
@@ -553,7 +563,7 @@ seq_drain_midi_queues (void)
n = 1;
- while (!PROCESS_ABORTING && n)
+ while (!PROCESS_ABORTING (midi_sleeper, midi_sleep_flag) && n)
{
n = 0;
@@ -568,70 +578,70 @@ seq_drain_midi_queues (void)
*/
if (n)
{
- REQUEST_TIMEOUT (HZ / 10, seq_sleeper);
- INTERRUPTIBLE_SLEEP_ON (seq_sleeper, seq_sleep_flag);
+ DO_SLEEP (seq_sleeper, seq_sleep_flag, HZ / 10);
}
}
}
void
sequencer_release (int dev, struct fileinfo *file)
- {
- int i;
- int mode = file->mode & O_ACCMODE;
+{
+ int i;
+ int mode = file->mode & O_ACCMODE;
- dev = dev >> 4;
+ dev = dev >> 4;
- DEB (printk ("sequencer_release(dev=%d)\n", dev));
+ DEB (printk ("sequencer_release(dev=%d)\n", dev));
- if (dev) /* Patch manager device */
- {
- dev--;
- pmgr_release (dev);
- pmgr_present[dev] = 0;
- return;
- }
+ if (dev) /* Patch manager device */
+ {
+ dev--;
+ pmgr_release (dev);
+ pmgr_present[dev] = 0;
+ return;
+ }
- /*
+ /*
* Wait until the queue is empty
- */
- while (!PROCESS_ABORTING && qlen)
- {
- seq_sync ();
- }
+ */
- if (mode != OPEN_READ)
- seq_drain_midi_queues (); /* Ensure the output queues are empty */
- seq_reset ();
- if (mode != OPEN_READ)
- seq_drain_midi_queues (); /* Flush the all notes off messages */
+ while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen)
+ {
+ seq_sync ();
+ }
- for (i = 0; i < num_midis; i++)
- if (midi_opened[i])
- midi_devs[i]->close (i);
+ if (mode != OPEN_READ)
+ seq_drain_midi_queues (); /* Ensure the output queues are empty */
+ seq_reset ();
+ if (mode != OPEN_READ)
+ seq_drain_midi_queues (); /* Flush the all notes off messages */
- if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
- for (i = 0; i < num_synths; i++)
- if (synth_open_mask & (1 << i)) /* Actually opened */
- if (synth_devs[i])
- synth_devs[i]->close (i);
+ for (i = 0; i < num_midis; i++)
+ if (midi_opened[i])
+ midi_devs[i]->close (i);
+ if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
for (i = 0; i < num_synths; i++)
- if (pmgr_present[i])
- pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
+ if (synth_open_mask & (1 << i)) /* Actually opened */
+ if (synth_devs[i])
+ synth_devs[i]->close (i);
- sequencer_busy = 0;
- }
+ for (i = 0; i < num_synths; i++)
+ if (pmgr_present[i])
+ pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
+
+ sequencer_busy = 0;
+}
static int
seq_sync (void)
{
- if (qlen && !seq_playing && !PROCESS_ABORTING)
+ if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_startplay ();
- if (qlen && !seq_sleep_flag) /* Queue not empty */
+ if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) /* Queue not empty */
{
- INTERRUPTIBLE_SLEEP_ON (seq_sleeper, seq_sleep_flag);
+ DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
return qlen;
@@ -654,8 +664,7 @@ midi_outc (int dev, unsigned char data)
while (n && !midi_devs[dev]->putc (dev, data))
{
- REQUEST_TIMEOUT (1, seq_sleeper);
- INTERRUPTIBLE_SLEEP_ON (seq_sleeper, seq_sleep_flag);
+ DO_SLEEP (seq_sleeper, seq_sleep_flag, 4);
n--;
}
}
@@ -684,7 +693,8 @@ seq_reset (void)
{
for (chn = 0; chn < 16; chn++)
{
- midi_outc (i, 0xb0 + chn); /* Channel message */
+ midi_outc (i,
+ (unsigned char) (0xb0 + (chn & 0xff))); /* Channel msg */
midi_outc (i, 0x7b);/* All notes off */
midi_outc (i, 0); /* Dummy parameter */
}
@@ -697,7 +707,7 @@ seq_reset (void)
seq_playing = 0;
- if (seq_sleep_flag)
+ if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
printk ("Sequencer Warning: Unexpected sleeping process\n");
}
@@ -720,7 +730,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
if (mode == OPEN_READ)
return 0;
- while (qlen && !PROCESS_ABORTING)
+ while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_sync ();
return 0;
break;
@@ -979,7 +989,6 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
case SEL_IN:
if (!iqlen)
{
- midi_sleep_flag = 1;
select_wait (&midi_sleeper, wait);
return 0;
}
@@ -990,7 +999,6 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
case SEL_OUT:
if (qlen >= SEQ_MAX_QUEUE)
{
- seq_sleep_flag = 1;
select_wait (&seq_sleeper, wait);
return 0;
}
@@ -1039,7 +1047,7 @@ note_to_freq (int note_num)
else if (octave > BASE_OCTAVE)
note_freq <<= (octave - BASE_OCTAVE);
- /* note_freq >>= 1; */
+ /* note_freq >>= 1; */
return note_freq;
}
@@ -1048,7 +1056,7 @@ unsigned long
compute_finetune (unsigned long base_freq, int bend, int range)
{
unsigned long amount;
- int negative, semitones, cents;
+ int negative, semitones, cents, multiplier = 1;
if (!bend)
return base_freq;
@@ -1072,13 +1080,20 @@ compute_finetune (unsigned long base_freq, int bend, int range)
if (bend > range)
bend = range;
- if (bend > 2399)
- bend = 2399;
+ /*
+ if (bend > 2399)
+ bend = 2399;
+ */
+ while (bend > 2399)
+ {
+ multiplier *= 4;
+ bend -= 2400;
+ }
semitones = bend / 100;
cents = bend % 100;
- amount = semitone_tuning[semitones] * cent_tuning[cents] / 10000;
+ amount = semitone_tuning[semitones] * multiplier * cent_tuning[cents] / 10000;
if (negative)
return (base_freq * 10000) / amount; /* Bend down */
@@ -1092,6 +1107,9 @@ sequencer_init (long mem_start)
{
sequencer_ok = 1;
+ PERMANENT_MALLOC (unsigned char *, queue, SEQ_MAX_QUEUE * EV_SZ, mem_start);
+ PERMANENT_MALLOC (unsigned char *, iqueue, SEQ_MAX_QUEUE * IEV_SZ, mem_start);
+
return mem_start;
}
@@ -1111,14 +1129,14 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int
sequencer_open (int dev, struct fileinfo *file)
- {
- return RET_ERROR (ENXIO);
- }
+{
+ return RET_ERROR (ENXIO);
+}
void
sequencer_release (int dev, struct fileinfo *file)
- {
- }
+{
+}
int
sequencer_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg)
@@ -1138,11 +1156,14 @@ sequencer_init (long mem_start)
return mem_start;
}
+#ifdef ALLOW_SELECT
+
int
sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
{
return RET_ERROR (EIO);
}
+#endif /* ALLOW_SELECT */
#endif