summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorswallace <swallace@FreeBSD.org>1994-10-01 02:17:17 +0000
committerswallace <swallace@FreeBSD.org>1994-10-01 02:17:17 +0000
commit3b7740a11ff2432cc8bbcfa2524ebc859cc4b643 (patch)
tree09d7913c895c85fdedc9a099ad0b7ac3ee4b3ef1 /sys
parentc2da26491490b8f15ad302a5fdf2a9532a07df5d (diff)
downloadFreeBSD-src-3b7740a11ff2432cc8bbcfa2524ebc859cc4b643.zip
FreeBSD-src-3b7740a11ff2432cc8bbcfa2524ebc859cc4b643.tar.gz
Merged in changes to Hannu Savolainen's VoxWare sound drivers, version 2.9.
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/sound/CHANGELOG39
-rw-r--r--sys/i386/isa/sound/README87
-rw-r--r--sys/i386/isa/sound/ad1848.c1
-rw-r--r--sys/i386/isa/sound/audio.c128
-rw-r--r--sys/i386/isa/sound/dev_table.c182
-rw-r--r--sys/i386/isa/sound/dev_table.h303
-rw-r--r--sys/i386/isa/sound/dmabuf.c708
-rw-r--r--sys/i386/isa/sound/gus_card.c67
-rw-r--r--sys/i386/isa/sound/gus_midi.c48
-rw-r--r--sys/i386/isa/sound/gus_vol.c3
-rw-r--r--sys/i386/isa/sound/gus_wave.c1080
-rw-r--r--sys/i386/isa/sound/ics2101.c50
-rw-r--r--sys/i386/isa/sound/local.h17
-rw-r--r--sys/i386/isa/sound/midi_ctrl.h3
-rw-r--r--sys/i386/isa/sound/midi_synth.c1
-rw-r--r--sys/i386/isa/sound/midi_synth.h3
-rw-r--r--sys/i386/isa/sound/midibuf.c370
-rw-r--r--sys/i386/isa/sound/mpu401.c1626
-rw-r--r--sys/i386/isa/sound/opl3.c505
-rw-r--r--sys/i386/isa/sound/opl3.h1
-rw-r--r--sys/i386/isa/sound/os.h5
-rw-r--r--sys/i386/isa/sound/pas.h26
-rw-r--r--sys/i386/isa/sound/pas2_card.c118
-rw-r--r--sys/i386/isa/sound/pas2_midi.c79
-rw-r--r--sys/i386/isa/sound/pas2_mixer.c316
-rw-r--r--sys/i386/isa/sound/pas2_pcm.c111
-rw-r--r--sys/i386/isa/sound/patmgr.c8
-rw-r--r--sys/i386/isa/sound/pss.c3
-rw-r--r--sys/i386/isa/sound/pss.h3
-rw-r--r--sys/i386/isa/sound/sb16_dsp.c182
-rw-r--r--sys/i386/isa/sound/sb16_midi.c81
-rw-r--r--sys/i386/isa/sound/sb_dsp.c252
-rw-r--r--sys/i386/isa/sound/sb_midi.c76
-rw-r--r--sys/i386/isa/sound/sb_mixer.c93
-rw-r--r--sys/i386/isa/sound/sb_mixer.h11
-rw-r--r--sys/i386/isa/sound/sequencer.c974
-rw-r--r--sys/i386/isa/sound/sound_calls.h47
-rw-r--r--sys/i386/isa/sound/sound_config.h129
-rw-r--r--sys/i386/isa/sound/sound_switch.c141
-rw-r--r--sys/i386/isa/sound/sound_timer.c1
-rw-r--r--sys/i386/isa/sound/soundcard.c72
-rw-r--r--sys/i386/isa/sound/sys_timer.c1
-rw-r--r--sys/i386/isa/sound/uart6850.c1
-rw-r--r--sys/i386/isa/sound/ulaw.h3
44 files changed, 5548 insertions, 2407 deletions
diff --git a/sys/i386/isa/sound/CHANGELOG b/sys/i386/isa/sound/CHANGELOG
index 6a9bef1..fcdbb8e 100644
--- a/sys/i386/isa/sound/CHANGELOG
+++ b/sys/i386/isa/sound/CHANGELOG
@@ -1,5 +1,40 @@
-Changelog for version 2.5
--------------------------
+Changelog for version 2.90
+------------------------------------
+
+This is an intermediate release (v3.0 prototype with some experimental
+features disabled). See experimental.txt for more info.
+
+Since pre-3.0-949712
+- GUS MAX support
+- Partially working MSS/WSS support (could work with some cards).
+- Hardware u-Law and A-Law support with AD1848/CS4248 and CS4231 codecs
+ (GUS MAX, GUS16, WSS etc). Hardware ADPCM is possible with GUS16 and
+ GUS MAX, but it doesn't work yet.
+Since pre-3.0-940426
+- AD1848/CS4248/CS4231 codec support (MSS, GUS MAX, Aztec, Orchid etc).
+This codec chip is used in various soundcards. This version is developed
+for the 16 bit daughtercard of GUS. It should work with other cards also
+if the following requirements are met:
+ - The I/O, IRQ and DMA settings are jumper selectable or
+ the card is initialized by booting DOS before booting Linux (etc.).
+ - You add the IO, IRQ and DMA settings manually to the local.h.
+ (Just define GUS16_BASE, GUS16_IRQ and GUS16_DMA). Note that
+ the base address bust be the base address of the codec chip not the
+ card itself. For the GUS16 these are the same but most MSS compatible
+ cards have the codec located at card_base+4.
+- Some minor changes
+
+Since 2.5 (******* MAJOR REWRITE ***********)
+
+This version is based on v2.3. I have tried to maintain two versions
+together so that this one should have the same features than v2.5.
+Something may still be missing. If you notice such things, please let me
+know.
+
+The Readme.v30 contains more details.
+
+- /dev/midi## devices.
+- /dev/sequencer2
Since 2.5-beta2
- Some fine tuning to the GUS v3.7 mixer code.
diff --git a/sys/i386/isa/sound/README b/sys/i386/isa/sound/README
index efb0b11..a4a0847 100644
--- a/sys/i386/isa/sound/README
+++ b/sys/i386/isa/sound/README
@@ -1,17 +1,80 @@
-CAUTION!
+VoxWare v2.90 release notes
+--------------------------
-This is a prototype version of the Linux Sound Driver for FreeBSD.
-The official and supported version is 1.0c.
+ This version includes some hidden features which
+ are described in the file experimental.txt
+ Some of these features are not enabled by default. Look at
+ experimental.txt for more info.
-This version 'should work' but there may be some bugs and the programmers
-API may change before the final version.
+ I just decided to release this version with some
+ incompletely implemented features disabled since
+ there are some new features required by a popular
+ application. In addition there is also support
+ for the GUS MAX and the 16 bit sampling option of GUS.
-There are some additional programs for GUS owners in the
-gustest subdirectory of this directory, namely a module
-(.MOD, .STM and .669) player and a patch file loader.
-Additionally, there is a midithru program which allows
-you to play the synth on the soundcard with a midi keyboard
-(also usable for OPL-3 owners).
+ The MSS/WSS support works now. At least with SG NX Pro 16.
-Hannu & FreeBSD team.
+********* IMPORTANT *****************************************
+Linux 1.0 or later is required to by this driver version.
+
+Don't distribute binaries which use /dev/sequencer and are
+compiled with the soundcard.h of this version. They will
+not work with version 2.x of the driver.
+*************************************************************
+
+
+You will need the snd-util-2.5.tar.gz and snd-data-0.1.tar.Z
+packages to use this driver. They should be in the same
+ftp site or BBS from where you got this driver. For
+example at nic.funet.fi:pub/OS/Linux/*.
+
+If you are looking for the installation instructions, please
+look at linux/Readme.
+
+Compatibility with the earlier versions
+---------------------------------------
+
+This version is backward compatible with the version 2.X. All programs
+compiled with sys/soundcard.h of v2.X should work without problems.
+PROGRAMS COMPILED WITH THE sys/soundcard.h OF THIS VERSION WILL NOT
+WORK WITH v2.X DRIVER. BE CAREFULL WHEN DISTRIBUTING BINARIES COMPILED
+FOR THIS VERSION.
+
+Contributors
+------------
+
+This driver contains code by several contributors. In addition several other
+persons have given usefull suggestions. The following is a list of major
+contributors. (I could have forgotten some names.)
+
+ Craig Metz 1/2 of the PAS16 Mixer and PCM support
+ Rob Hooft Volume computation algorithm for the FM synth.
+ Mika Liljeberg uLaw encoding and decoding routines
+ Greg Lee Volume computation algorithm for the GUS and
+ lot's of valuable suggestions.
+ Andy Warner ISC port
+ Jim Lowe FreeBSD port
+ Anders Baekgaard Bughunting and valuable suggestions.
+ Joerg Schubert SB16 DSP support.
+ Andrew Robinson Improvements to the GUS driver
+ Megens SA MIDI recording for SB and SB Pro.
+ Mikael Nordqvist Linear volume support for GUS.
+ Mikael Nordqvist Linear volume support for GUS.
+ Ian Hartas SVR4.2 port
+ Markus Aroharju and
+ Risto Kankkunen Major contributions to the mixer support
+ of GUS v3.7.
+ Hunyue Yau Mixer support for SG NX Pro.
+ Marc Hoffman PSS support.
+
+Regards,
+
+Hannu Savolainen
+hannu@voxware.pp.fi
+
+Snail mail: Hannu Savolainen
+ Pallaksentie 4 A 2
+ 00970 Helsinki
+ Finland
+FAX: +358 0 395 1968 (usually not connected)
diff --git a/sys/i386/isa/sound/ad1848.c b/sys/i386/isa/sound/ad1848.c
index b08f5f7..ed6498f 100644
--- a/sys/i386/isa/sound/ad1848.c
+++ b/sys/i386/isa/sound/ad1848.c
@@ -29,6 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $Id: sb16_dsp.c,v 1.7 1994/09/27 17:58:24 davidg Exp $
*/
#define DEB(x)
diff --git a/sys/i386/isa/sound/audio.c b/sys/i386/isa/sound/audio.c
index 092a5e5..0453bec 100644
--- a/sys/i386/isa/sound/audio.c
+++ b/sys/i386/isa/sound/audio.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: audio.c,v 1.5 1994/08/02 07:39:44 davidg Exp $
*/
#include "sound_config.h"
@@ -38,18 +38,48 @@
#define ON 1
#define OFF 0
-static int wr_buff_no[MAX_DSP_DEV]; /* != -1, if there is a
+static int wr_buff_no[MAX_AUDIO_DEV]; /*
+ * != -1, if there is
+ * a incomplete output
+ * block in the queue.
+ */
+static int wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
- * incomplete output block */
-static int wr_buff_size[MAX_DSP_DEV], wr_buff_ptr[MAX_DSP_DEV];
-
-static int audio_mode[MAX_DSP_DEV];
+static int audio_mode[MAX_AUDIO_DEV];
#define AM_NONE 0
#define AM_WRITE 1
#define AM_READ 2
-static char *wr_dma_buf[MAX_DSP_DEV];
+static char *wr_dma_buf[MAX_AUDIO_DEV];
+static int audio_format[MAX_AUDIO_DEV];
+static int local_conversion[MAX_AUDIO_DEV];
+
+static int
+set_format (int dev, int fmt)
+{
+ if (fmt != AFMT_QUERY)
+ {
+
+ local_conversion[dev] = 0;
+
+ if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */
+ if (fmt == AFMT_MU_LAW)
+ {
+ fmt = AFMT_U8;
+ local_conversion[dev] = AFMT_MU_LAW;
+ }
+ else
+ fmt = AFMT_U8; /* This is always supported */
+
+ audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1);
+ }
+
+ if (local_conversion[dev]) /* This shadows the HW format */
+ return local_conversion[dev];
+
+ return audio_format[dev];
+}
int
audio_open (int dev, struct fileinfo *file)
@@ -69,12 +99,21 @@ audio_open (int dev, struct fileinfo *file)
if ((ret = DMAbuf_open (dev, mode)) < 0)
return ret;
- if (DMAbuf_ioctl (dev, SNDCTL_DSP_SAMPLESIZE, bits, 1) != bits)
+ local_conversion[dev] = 0;
+
+ if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
{
audio_release (dev, file);
return RET_ERROR (ENXIO);
}
+ if (dev_type == SND_DEV_AUDIO)
+ {
+ set_format (dev, AFMT_MU_LAW);
+ }
+ else
+ set_format (dev, bits);
+
wr_buff_no[dev] = -1;
audio_mode[dev] = AM_NONE;
@@ -129,21 +168,24 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
int c, p, l;
int err;
- int dev_type = dev & 0x0f;
dev = dev >> 4;
p = 0;
c = count;
- if (audio_mode[dev] == AM_READ) /* Direction changed */
+ if (audio_mode[dev] == AM_READ) /*
+ * Direction changed
+ */
{
wr_buff_no[dev] = -1;
}
audio_mode[dev] = AM_WRITE;
- if (!count) /* Flush output */
+ if (!count) /*
+ * Flush output
+ */
{
if (wr_buff_no[dev] >= 0)
{
@@ -155,11 +197,17 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
}
while (c)
- { /* Perform output blocking */
- if (wr_buff_no[dev] < 0) /* There is no incomplete buffers */
+ { /*
+ * Perform output blocking
+ */
+ if (wr_buff_no[dev] < 0) /*
+ * There is no incomplete buffers
+ */
{
if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)
- return wr_buff_no[dev];
+ {
+ return wr_buff_no[dev];
+ }
wr_buff_ptr[dev] = 0;
}
@@ -167,21 +215,27 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
- if (!dsp_devs[dev]->copy_from_user)
- { /* No device specific copy routine */
+ if (!audio_devs[dev]->copy_from_user)
+ { /*
+ * No device specific copy routine
+ */
COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
}
else
- dsp_devs[dev]->copy_from_user (dev,
+ audio_devs[dev]->copy_from_user (dev,
wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
- /* Insert local processing here */
+ /*
+ * Insert local processing here
+ */
- if (dev_type == SND_DEV_AUDIO)
+ if (local_conversion[dev] == AFMT_MU_LAW)
{
#ifdef linux
- /* This just allows interrupts while the conversion is running */
+ /*
+ * This just allows interrupts while the conversion is running
+ */
__asm__ ("sti");
#endif
translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
@@ -194,7 +248,9 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
if (wr_buff_ptr[dev] >= wr_buff_size[dev])
{
if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
- return err;
+ {
+ return err;
+ }
wr_buff_no[dev] = -1;
}
@@ -210,7 +266,6 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int c, p, l;
char *dmabuf;
int buff_no;
- int dev_type = dev & 0x0f;
dev = dev >> 4;
p = 0;
@@ -236,12 +291,16 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
if (l > c)
l = c;
- /* Insert any local processing here. */
+ /*
+ * Insert any local processing here.
+ */
- if (dev_type == SND_DEV_AUDIO)
+ if (local_conversion[dev] == AFMT_MU_LAW)
{
#ifdef linux
- /* This just allows interrupts while the conversion is running */
+ /*
+ * This just allows interrupts while the conversion is running
+ */
__asm__ ("sti");
#endif
@@ -263,7 +322,6 @@ int
audio_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg)
{
- int dev_type = dev & 0x0f;
dev = dev >> 4;
@@ -294,22 +352,32 @@ audio_ioctl (int dev, struct fileinfo *file,
return DMAbuf_ioctl (dev, cmd, arg, 0);
break;
- default:
- if (dev_type == SND_DEV_AUDIO)
- return RET_ERROR (EIO);
+ case SNDCTL_DSP_GETFMTS:
+ return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
+ break;
+ case SNDCTL_DSP_SETFMT:
+ return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
+
+ default:
return DMAbuf_ioctl (dev, cmd, arg, 0);
+ break;
}
}
long
audio_init (long mem_start)
{
+ /*
+ * NOTE! This routine could be called several times during boot.
+ */
return mem_start;
}
#else
-/* Stub versions */
+/*
+ * Stub versions
+ */
int
audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
diff --git a/sys/i386/isa/sound/dev_table.c b/sys/i386/isa/sound/dev_table.c
index ccc32bc..f313b8c 100644
--- a/sys/i386/isa/sound/dev_table.c
+++ b/sys/i386/isa/sound/dev_table.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: dev_table.c,v 1.5 1994/08/02 07:39:46 davidg Exp $
*/
#define _DEV_TABLE_C_
@@ -33,101 +33,138 @@
#ifdef CONFIGURE_SOUNDCARD
+int
+snd_find_driver (int type)
+{
+ int i, n = sizeof (sound_drivers) / sizeof (struct driver_info);
+
+ for (i = 0; i < (n - 1); i++)
+ if (sound_drivers[i].card_type == type)
+ return i;
+
+ return -1; /*
+ * Not found
+ */
+}
+
long
sndtable_init (long mem_start)
{
- int i, n = sizeof (supported_drivers) / sizeof (struct card_info);
+ int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
+ int drv;
for (i = 0; i < (n - 1); i++)
- if (supported_drivers[i].enabled)
- if (supported_drivers[i].probe (&supported_drivers[i].config))
+ if (snd_installed_cards[i].enabled)
+ if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
+ snd_installed_cards[i].enabled = 0; /*
+ * Mark as not detected
+ */
+ else if (sound_drivers[drv].probe (&snd_installed_cards[i].config))
{
#ifndef SHORT_BANNERS
printk ("snd%d",
- supported_drivers[i].card_type);
+ snd_installed_cards[i].card_type);
#endif
- mem_start = supported_drivers[i].attach (mem_start, &supported_drivers[i].config);
+ mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config);
#ifndef SHORT_BANNERS
printk (" at 0x%x irq %d drq %d\n",
- supported_drivers[i].config.io_base,
- supported_drivers[i].config.irq,
- supported_drivers[i].config.dma);
+ snd_installed_cards[i].config.io_base,
+ snd_installed_cards[i].config.irq,
+ snd_installed_cards[i].config.dma);
#endif
}
else
- supported_drivers[i].enabled = 0; /* Mark as not detected */
+ snd_installed_cards[i].enabled = 0; /*
+ * Mark as not detected
+ */
return mem_start;
}
int
sndtable_probe (int unit, struct address_info *hw_config)
-{
- int i, n = sizeof (supported_drivers) / sizeof (struct card_info);
+ {
+ int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
- if (!unit)
- return TRUE;
-
- for (i = 0; i < (n - 1); i++)
- if (supported_drivers[i].card_type == unit)
- {
- supported_drivers[i].config.io_base = hw_config->io_base;
- supported_drivers[i].config.irq = hw_config->irq;
- supported_drivers[i].config.dma = hw_config->dma;
- if (supported_drivers[i].probe (hw_config))
- return 1;
- supported_drivers[i].enabled = 0; /* Mark as not detected */
- return 0;
- }
+ if (!unit)
+ return TRUE;
- return FALSE;
-}
+ for (i = 0; i < (n - 1); i++)
+ if (snd_installed_cards[i].enabled)
+ if (snd_installed_cards[i].card_type == unit)
+ {
+ int drv;
+
+ snd_installed_cards[i].config.io_base = hw_config->io_base;
+ snd_installed_cards[i].config.irq = hw_config->irq;
+ snd_installed_cards[i].config.dma = hw_config->dma;
+ if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
+ snd_installed_cards[i].enabled = 0; /*
+ * Mark as not
+ * detected
+ */
+ else if (sound_drivers[drv].probe (hw_config))
+ return 1;
+ snd_installed_cards[i].enabled = 0; /*
+ * Mark as not detected
+ */
+ return 0;
+ }
+
+ return FALSE;
+ }
int
sndtable_init_card (int unit, struct address_info *hw_config)
-{
- int i, n = sizeof (supported_drivers) / sizeof (struct card_info);
-
- if (!unit)
- {
- if (sndtable_init (0) != 0)
- panic ("snd: Invalid memory allocation\n");
- return TRUE;
- }
+ {
+ int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
- for (i = 0; i < (n - 1); i++)
- if (supported_drivers[i].card_type == unit)
+ if (!unit)
{
- supported_drivers[i].config.io_base = hw_config->io_base;
- supported_drivers[i].config.irq = hw_config->irq;
- supported_drivers[i].config.dma = hw_config->dma;
-
- if (supported_drivers[i].attach (0, hw_config) != 0)
- panic ("snd#: Invalid memory allocation\n");
+ if (sndtable_init (0) != 0)
+ panic ("snd: Invalid memory allocation\n");
return TRUE;
}
- return FALSE;
-}
+ for (i = 0; i < (n - 1); i++)
+ if (snd_installed_cards[i].card_type == unit)
+ {
+ int drv;
+
+ snd_installed_cards[i].config.io_base = hw_config->io_base;
+ snd_installed_cards[i].config.irq = hw_config->irq;
+ snd_installed_cards[i].config.dma = hw_config->dma;
+
+ if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
+ snd_installed_cards[i].enabled = 0; /*
+ * Mark as not detected
+ */
+ else if (sound_drivers[drv].attach (0, hw_config) != 0)
+ panic ("snd#: Invalid memory allocation\n");
+ return TRUE;
+ }
+
+ return FALSE;
+ }
int
sndtable_get_cardcount (void)
{
- return num_dspdevs + num_mixers + num_synths + num_midis;
+ return num_audiodevs + num_mixers + num_synths + num_midis;
}
#ifdef linux
void
sound_setup (char *str, int *ints)
{
- int i, n = sizeof (supported_drivers) / sizeof (struct card_info);
+ int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
/*
* First disable all drivers
*/
for (i = 0; i < n; i++)
- supported_drivers[i].enabled = 0;
+ snd_installed_cards[i].enabled = 0;
if (ints[0] == 0 || ints[1] == 0)
return;
@@ -146,7 +183,9 @@ sound_setup (char *str, int *ints)
if (card_type > 127)
{
- /* Add any future extensions here */
+ /*
+ * Add any future extensions here
+ */
return;
}
@@ -156,17 +195,20 @@ sound_setup (char *str, int *ints)
ptr = -1;
for (j = 0; j < n && ptr == -1; j++)
- if (supported_drivers[j].card_type == card_type)
+ if (snd_installed_cards[j].card_type == card_type &&
+ !snd_installed_cards[j].enabled) /*
+ * Not already found
+ */
ptr = j;
if (ptr == -1)
printk ("Sound: Invalid setup parameter 0x%08x\n", val);
else
{
- supported_drivers[ptr].enabled = 1;
- supported_drivers[ptr].config.io_base = ioaddr;
- supported_drivers[ptr].config.irq = irq;
- supported_drivers[ptr].config.dma = dma;
+ snd_installed_cards[ptr].enabled = 1;
+ snd_installed_cards[ptr].config.io_base = ioaddr;
+ snd_installed_cards[ptr].config.irq = irq;
+ snd_installed_cards[ptr].config.dma = dma;
}
}
}
@@ -175,24 +217,27 @@ sound_setup (char *str, int *ints)
void
sound_chconf (int card_type, int ioaddr, int irq, int dma)
{
- int i, n = sizeof (supported_drivers) / sizeof (struct card_info);
+ int i, n = sizeof (snd_installed_cards) / sizeof (struct card_info);
int ptr, j;
ptr = -1;
for (j = 0; j < n && ptr == -1; j++)
- if (supported_drivers[j].card_type == card_type)
+ if (snd_installed_cards[j].card_type == card_type &&
+ !snd_installed_cards[j].enabled) /*
+ * Not already found
+ */
ptr = j;
if (ptr != -1)
{
- supported_drivers[ptr].enabled = 1;
+ snd_installed_cards[ptr].enabled = 1;
if (ioaddr)
- supported_drivers[ptr].config.io_base = ioaddr;
+ snd_installed_cards[ptr].config.io_base = ioaddr;
if (irq)
- supported_drivers[ptr].config.irq = irq;
+ snd_installed_cards[ptr].config.irq = irq;
if (dma)
- supported_drivers[ptr].config.dma = dma;
+ snd_installed_cards[ptr].config.dma = dma;
}
}
@@ -202,17 +247,24 @@ struct address_info *
sound_getconf (int card_type)
{
int j, ptr;
- int n = sizeof (supported_drivers) / sizeof (struct card_info);
+ int n = sizeof (snd_installed_cards) / sizeof (struct card_info);
ptr = -1;
for (j = 0; j < n && ptr == -1; j++)
- if (supported_drivers[j].card_type == card_type)
+ if (snd_installed_cards[j].card_type == card_type)
ptr = j;
if (ptr == -1)
return (struct address_info *) NULL;
- return &supported_drivers[ptr].config;
+ return &snd_installed_cards[ptr].config;
+}
+
+#else
+
+void
+sound_setup (char *str, int *ints)
+{
}
#endif
diff --git a/sys/i386/isa/sound/dev_table.h b/sys/i386/isa/sound/dev_table.h
index 5c47285..c17aa85 100644
--- a/sys/i386/isa/sound/dev_table.h
+++ b/sys/i386/isa/sound/dev_table.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: dev_table.h,v 1.6 1994/08/02 07:39:47 davidg Exp $
+ * $Id: dev_table.h,v 1.7 1994/09/27 17:58:15 davidg Exp $
*/
#ifndef _DEV_TABLE_H_
@@ -40,20 +40,71 @@
* NOTE! NOTE! NOTE! NOTE!
*/
-struct card_info {
- int card_type; /* From soundcard.c */
+struct driver_info {
+ int card_type; /* From soundcard.h */
char *name;
long (*attach) (long mem_start, struct address_info *hw_config);
int (*probe) (struct address_info *hw_config);
+};
+
+struct card_info {
+ int card_type; /* Link (search key) to the driver list */
struct address_info config;
int enabled;
};
-/** UWM -- new MIDI structure here.. **/
+/*
+ * Device specific parameters (used only by dmabuf.c)
+ */
+#define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR)
+
+#define DMODE_NONE 0
+#define DMODE_OUTPUT 1
+#define DMODE_INPUT 2
+
+struct dma_buffparms {
+ int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
+
+ /*
+ * Pointers to raw buffers
+ */
+
+ char *raw_buf[DSP_BUFFCOUNT];
+ unsigned long raw_buf_phys[DSP_BUFFCOUNT];
+ int raw_count;
-struct generic_midi_info{
- char *name; /* Name of the MIDI device.. */
- long (*attach) (long mem_start);
+ /*
+ * Device state tables
+ */
+
+ unsigned long flags;
+#define DMA_BUSY 0x00000001
+#define DMA_RESTART 0x00000002
+#define DMA_ACTIVE 0x00000004
+#define DMA_STARTED 0x00000008
+#define DMA_ALLOC_DONE 0x00000020
+
+ int open_mode;
+
+ /*
+ * Queue parameters.
+ */
+ int qlen;
+ int qhead;
+ int qtail;
+
+ int nbufs;
+ int counts[MAX_SUB_BUFFERS];
+ int subdivision;
+ char *buf[MAX_SUB_BUFFERS];
+ unsigned long buf_phys[MAX_SUB_BUFFERS];
+
+ int fragment_size;
+ int max_fragments;
+
+ int bytes_in_use;
+
+ int underrun_count;
};
struct audio_operations {
@@ -61,6 +112,9 @@ struct audio_operations {
int flags;
#define NOTHING_SPECIAL 0
#define NEEDS_RESTART 1
+#define DMA_AUTOMODE 2
+ int format_mask; /* Bitmask for supported audio formats */
+ void *devc; /* Driver specific info */
int (*open) (int dev, int mode);
void (*close) (int dev);
void (*output_block) (int dev, unsigned long buf,
@@ -72,9 +126,13 @@ struct audio_operations {
int (*prepare_for_output) (int dev, int bufsize, int nbufs);
void (*reset) (int dev);
void (*halt_xfer) (int dev);
- int (*has_output_drained)(int dev);
+ int (*local_qlen)(int dev);
void (*copy_from_user)(int dev, char *localbuf, int localoffs,
snd_rw_buf *userbuf, int useroffs, int len);
+ int buffcount;
+ long buffsize;
+ int dmachan;
+ struct dma_buffparms *dmap;
};
struct mixer_operations {
@@ -83,13 +141,14 @@ struct mixer_operations {
struct synth_operations {
struct synth_info *info;
+ int midi_dev;
int synth_type;
int synth_subtype;
int (*open) (int dev, int mode);
void (*close) (int dev);
int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
- int (*kill_note) (int dev, int voice, int velocity);
+ int (*kill_note) (int dev, int voice, int note, int velocity);
int (*start_note) (int dev, int voice, int note, int velocity);
int (*set_instr) (int dev, int voice, int instr);
void (*reset) (int dev);
@@ -101,10 +160,16 @@ struct synth_operations {
void (*panning) (int dev, int voice, int value);
void (*volume_method) (int dev, int mode);
int (*pmgr_interface) (int dev, struct patmgr_info *info);
+ void (*bender) (int dev, int chn, int value);
+ int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc);
+
+ struct voice_alloc_info alloc;
+ struct channel_info chn_info[16];
};
struct midi_operations {
struct midi_info info;
+ struct synth_operations *converter;
int (*open) (int dev, int mode,
void (*inputintr)(int dev, unsigned char data),
void (*outputintr)(int dev)
@@ -115,158 +180,166 @@ struct midi_operations {
int (*start_read) (int dev);
int (*end_read) (int dev);
void (*kick)(int dev);
- int (*command) (int dev, unsigned char data);
+ int (*command) (int dev, unsigned char *data);
int (*buffer_status) (int dev);
+ int (*prefix_cmd) (int dev, unsigned char status);
};
-/** UWM -- new structure for MIDI **/
-
-struct generic_midi_operations {
- struct midi_info info;
- int (*open) (int dev, int mode);
- void (*close) (int dev);
- int (*write) (int dev, snd_rw_buf *data);
- int (*read) (int dev, snd_rw_buf *data);
-};
-
-#ifndef ALL_EXTERNAL_TO_ME
-
-#ifdef _MIDI_TABLE_C_
-
-/** UWM **/
- struct generic_midi_operations * generic_midi_devs[MAX_MIDI_DEV] = {NULL};
- int num_generic_midis = 0, pro_midi_dev = 0;
-
- struct generic_midi_info midi_supported[] = {
+struct sound_timer_operations {
+ struct sound_timer_info info;
+ int priority;
+ int devlink;
+ int (*open)(int dev, int mode);
+ void (*close)(int dev);
+ int (*event)(int dev, unsigned char *ev);
+ unsigned long (*get_time)(int dev);
+ int (*ioctl) (int dev, unsigned int cmd, unsigned int arg);
+ void (*arm_timer)(int dev, long time);
+};
-#ifndef EXCLUDE_PRO_MIDI
- {"ProAudioSpectrum MV101",pro_midi_attach}
+#ifdef _DEV_TABLE_C_
+ struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0;
+ struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
+ struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
+ struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
+
+#ifndef EXCLUDE_SEQUENCER
+ extern struct sound_timer_operations default_sound_timer;
+ struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
+ {&default_sound_timer, NULL};
+ int num_sound_timers = 1;
+#else
+ struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
+ {NULL};
+ int num_sound_timers = 0;
#endif
- };
- int num_midi_drivers =
- sizeof (midi_supported) / sizeof(struct generic_midi_info);
+/*
+ * List of low level drivers compiled into the kernel.
+ */
+ struct driver_info sound_drivers[] = {
+#ifndef EXCLUDE_PSS
+ {SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss},
#endif
-
-
-#ifdef _DEV_TABLE_C_
- struct audio_operations * dsp_devs[MAX_DSP_DEV] = {NULL}; int num_dspdevs = 0;
- struct mixer_operations * mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
- struct synth_operations * synth_devs[MAX_SYNTH_DEV] = {NULL}; int num_synths = 0;
- struct midi_operations * midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
-
-
-# ifndef EXCLUDE_MPU401
- int mpu401_dev = 0;
-# endif
+#ifndef EXCLUDE_YM3812
+ {SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib},
+#endif
+#ifndef EXCLUDE_PAS
+ {SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas},
+#endif
+#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
+ {SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401},
+#endif
+#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
+ {SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850},
+#endif
+#ifndef EXCLUDE_SB
+ {SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb},
+#endif
+#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
+#ifndef EXCLUDE_AUDIO
+ {SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect},
+#endif
+#ifndef EXCLUDE_MIDI
+ {SNDCARD_SB16MIDI,"SB16 MIDI", attach_sb16midi, probe_sb16midi},
+#endif
+#endif
+#ifndef EXCLUDE_GUS16
+ {SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16},
+#endif
+#ifndef EXCLUDE_MSS
+ {SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound},
+#endif
+#ifndef EXCLUDE_GUS
+ {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus},
+#endif
+ {0, "*?*", NULL, NULL}
+ };
/*
+ * List of devices actually configured in the system.
+ *
* Note! The detection order is significant. Don't change it.
*/
- struct card_info supported_drivers[] = {
+ struct card_info snd_installed_cards[] = {
+#ifndef EXCLUDE_PSS
+ {SNDCARD_PSS, {PSS_BASE, PSS_IRQ, PSS_DMA}, SND_DEFAULT_ENABLE},
+#endif
#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
- {SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401,
- {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
+ {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
+#ifdef MPU2_BASE
+ {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE},
+#endif
+#ifdef MPU3_BASE
+ {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0}, SND_DEFAULT_ENABLE},
+#endif
+#endif
+#ifndef EXCLUDE_MSS
+ {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA}, SND_DEFAULT_ENABLE},
+# ifdef MSS2_BASE
+ {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA}, SND_DEFAULT_ENABLE},
+# endif
+#endif
+
+#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
+ {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0}, SND_DEFAULT_ENABLE},
#endif
#ifndef EXCLUDE_PAS
- {SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas,
- {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE},
+ {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE},
#endif
#ifndef EXCLUDE_SB
- {SNDCARD_SB, "SoundBlaster", attach_sb_card, probe_sb,
- {SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE},
+ {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE},
#endif
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
+#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
#ifndef EXCLUDE_AUDIO
- {SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect,
- {SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE},
+ {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE},
#endif
#ifndef EXCLUDE_MIDI
- {SNDCARD_SB16MIDI,"SB16 MPU-401", attach_sb16midi, probe_sb16midi,
- {SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE},
+ {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE},
#endif
#endif
#ifndef EXCLUDE_GUS
- {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus,
- {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
+#ifndef EXCLUDE_GUS16
+ {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA}, SND_DEFAULT_ENABLE},
+#endif
+ {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
#endif
#ifndef EXCLUDE_YM3812
- {SNDCARD_ADLIB, "AdLib", attach_adlib_card, probe_adlib,
- {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE},
+ {SNDCARD_ADLIB, {FM_MONO, 0, 0}, SND_DEFAULT_ENABLE},
#endif
- {0, "*?*", NULL, 0}
+ {0, {0}, 0}
};
int num_sound_drivers =
- sizeof(supported_drivers) / sizeof (struct card_info);
+ sizeof(sound_drivers) / sizeof (struct driver_info);
+ int num_sound_cards =
+ sizeof(snd_installed_cards) / sizeof (struct card_info);
-# ifndef EXCLUDE_AUDIO
- int sound_buffcounts[MAX_DSP_DEV] = {0};
- long sound_buffsizes[MAX_DSP_DEV] = {0};
- int sound_dsp_dmachan[MAX_DSP_DEV] = {0};
- int sound_dma_automode[MAX_DSP_DEV] = {0};
-# endif
#else
- extern struct audio_operations * dsp_devs[MAX_DSP_DEV]; int num_dspdevs;
+ extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; int num_audiodevs;
extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
- extern struct synth_operations * synth_devs[MAX_SYNTH_DEV]; extern int num_synths;
+ extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths;
extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis;
-# ifndef EXCLUDE_MPU401
- extern int mpu401_dev;
-# endif
+ extern struct sound_timer_operations * sound_timer_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_sound_timers;
- extern struct card_info supported_drivers[];
+ extern struct driver_info sound_drivers[];
extern int num_sound_drivers;
-
-# ifndef EXCLUDE_AUDIO
- extern int sound_buffcounts[MAX_DSP_DEV];
- extern long sound_buffsizes[MAX_DSP_DEV];
- extern int sound_dsp_dmachan[MAX_DSP_DEV];
- extern int sound_dma_automode[MAX_DSP_DEV];
-# endif
-
-#endif
+ extern struct card_info snd_installed_cards[];
+ extern int num_sound_cards;
long sndtable_init(long mem_start);
int sndtable_get_cardcount (void);
struct address_info *sound_getconf(int card_type);
void sound_chconf(int card_type, int ioaddr, int irq, int dma);
-#endif
+int snd_find_driver(int type);
-#endif
-
-/* If external to me.... :) */
-
-#ifdef ALL_EXTERNAL_TO_ME
-
- extern struct audio_operations * dsp_devs[MAX_DSP_DEV]; int num_dspdevs;
- extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
- extern struct synth_operations * synth_devs[MAX_SYNTH_DEV]; extern int num_synths;
- extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis;
- extern struct generic_midi_operations *generic_midi_devs[];
- extern int num_generic_midis, pro_midi_dev;
-
-#ifndef EXCLUDE_MPU401
- extern int mpu401_dev;
-#endif
-
- extern struct generic_midi_info midi_supported[];
- extern struct card_info supported_drivers[];
- extern int num_sound_drivers;
- extern int num_midi_drivers;
-#ifndef EXCLUDE_AUDIO
- extern int sound_buffcounts[MAX_DSP_DEV];
- extern long sound_buffsizes[MAX_DSP_DEV];
- extern int sound_dsp_dmachan[MAX_DSP_DEV];
- extern int sound_dma_automode[MAX_DSP_DEV];
-#endif
-
-#endif
+#endif /* _DEV_TABLE_C_ */
+#endif /* _DEV_TABLE_H_ */
diff --git a/sys/i386/isa/sound/dmabuf.c b/sys/i386/isa/sound/dmabuf.c
index 7452717..1a736b5 100644
--- a/sys/i386/isa/sound/dmabuf.c
+++ b/sys/i386/isa/sound/dmabuf.c
@@ -3,7 +3,7 @@
*
* The DMA buffer manager for digitized voice applications
*
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1993, 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: dmabuf.c,v 1.8 1994/08/02 07:39:49 davidg Exp $
*/
#include "sound_config.h"
@@ -36,68 +36,14 @@
#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS)
-#define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR)
+DEFINE_WAIT_QUEUES (dev_sleeper[MAX_AUDIO_DEV], dev_sleep_flag[MAX_AUDIO_DEV]);
-/*
- * The DSP channel can be used either for input or output. Variable
- * 'dma_mode' will be set when the program calls read or write first time
- * after open. Current version doesn't support mode changes without closing
- * and reopening the device. Support for this feature may be implemented in a
- * future version of this driver.
- */
-
-#define DMODE_NONE 0
-#define DMODE_OUTPUT 1
-#define DMODE_INPUT 2
-
-DEFINE_WAIT_QUEUES (dev_sleeper[MAX_DSP_DEV], dev_sleep_flag[MAX_DSP_DEV]);
-
-static int dma_mode[MAX_DSP_DEV] =
-{0}; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
-
-static volatile int dmabuf_interrupted[MAX_DSP_DEV] =
-{0};
-
-/*
- * Pointers to raw buffers
- */
-
-char *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT] =
-{
- {NULL}};
-unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
-int snd_raw_count[MAX_DSP_DEV];
-
-/*
- * Device state tables
- */
-
-static int dev_busy[MAX_DSP_DEV];
-static int dev_needs_restart[MAX_DSP_DEV];
-static int dev_modes[MAX_DSP_DEV];
-static int dev_active[MAX_DSP_DEV];
-static int dev_started[MAX_DSP_DEV];
-static int dev_qlen[MAX_DSP_DEV];
-static int dev_qhead[MAX_DSP_DEV];
-static int dev_qtail[MAX_DSP_DEV];
-static int dev_underrun[MAX_DSP_DEV];
-static int bufferalloc_done[MAX_DSP_DEV] =
-{0};
-
-/*
- * Logical buffers for each devices
- */
-
-static int dev_nbufs[MAX_DSP_DEV]; /* # of logical buffers ( >=
-
- * sound_buffcounts[dev] */
-static int dev_counts[MAX_DSP_DEV][MAX_SUB_BUFFERS];
-static int dev_subdivision[MAX_DSP_DEV];
-static unsigned long dev_buf_phys[MAX_DSP_DEV][MAX_SUB_BUFFERS];
-static char *dev_buf[MAX_DSP_DEV][MAX_SUB_BUFFERS] =
-{
- {NULL}};
-static int dev_buffsize[MAX_DSP_DEV];
+static struct dma_buffparms dmaps[MAX_AUDIO_DEV] =
+{0}; /*
+ * Primitive way to allocate
+ * such a large array.
+ * Needs dynamic run-time alloction.
+ */
static void
reorganize_buffers (int dev)
@@ -106,130 +52,159 @@ reorganize_buffers (int dev)
* This routine breaks the physical device buffers to logical ones.
*/
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+ struct audio_operations *dsp_dev = audio_devs[dev];
+
unsigned i, p, n;
unsigned sr, nc, sz, bsz;
- sr = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1);
- nc = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1);
- sz = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1);
+ if (dmap->fragment_size == 0)
+ { /* Compute the fragment size using the default algorithm */
- if (sr < 1 || nc < 1 || sz < 1)
- {
- printk ("SOUND: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);
- sr = DSP_DEFAULT_SPEED;
- nc = 1;
- sz = 8;
- }
+ sr = dsp_dev->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1);
+ nc = dsp_dev->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1);
+ sz = dsp_dev->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1);
+
+ if (sr < 1 || nc < 1 || sz < 1)
+ {
+ printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
+ dev, sr, nc, sz);
+ sr = DSP_DEFAULT_SPEED;
+ nc = 1;
+ sz = 8;
+ }
- sz /= 8; /* Convert # of bits -> # of bytes */
+ sz /= 8; /* #bits -> #bytes */
- sz = sr * nc * sz;
+ sz = sr * nc * sz;
- /*
- * Compute a buffer size not exeeding 1 second.
+ /*
+ * Compute a buffer size for time not exeeding 1 second.
+ * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds
+ * of sound (using the current speed, sample size and #channels).
*/
- bsz = sound_buffsizes[dev];
-
- while (bsz > sz)
- bsz >>= 1; /* Divide by 2 */
+ bsz = dsp_dev->buffsize;
+ while (bsz > sz)
+ bsz /= 2;
- if (sound_buffcounts[dev] == 1 && bsz == sound_buffsizes[dev])
- bsz >>= 1; /* Need at least 2 buffers */
+ if (dsp_dev->buffcount == 1 && bsz == dsp_dev->buffsize)
+ bsz /= 2; /* Needs at least 2 buffers */
- if (dev_subdivision[dev] == 0)
- dev_subdivision[dev] = 1; /* Default value */
+ if (dmap->subdivision == 0) /* Not already set */
+ dmap->subdivision = 1; /* Init to default value */
- bsz /= dev_subdivision[dev]; /* Use smaller buffers */
+ bsz /= dmap->subdivision;
- if (bsz == 0)
- bsz = 4096; /* Just a sanity check */
+ if (bsz < 64)
+ bsz = 4096; /* Just a sanity check */
- while ((sound_buffsizes[dev] * sound_buffcounts[dev]) / bsz > MAX_SUB_BUFFERS)
- bsz <<= 1; /* Too much buffers */
+ while ((dsp_dev->buffsize * dsp_dev->buffcount) / bsz > MAX_SUB_BUFFERS)
+ bsz *= 2;
- dev_buffsize[dev] = bsz;
- n = 0;
+ dmap->fragment_size = bsz;
+ }
+ else
+ {
+ /*
+ * The process has specified the buffer sice with SNDCTL_DSP_SETFRAGMENT or
+ * the buffer sice computation has already been done.
+ */
+ if (dmap->fragment_size > audio_devs[dev]->buffsize)
+ dmap->fragment_size = audio_devs[dev]->buffsize;
+ bsz = dmap->fragment_size;
+ }
/*
* Now computing addresses for the logical buffers
*/
- for (i = 0; i < snd_raw_count[dev]; i++)
+ n = 0;
+ for (i = 0; i < dmap->raw_count &&
+ n < dmap->max_fragments &&
+ n < MAX_SUB_BUFFERS; i++)
{
p = 0;
- while ((p + bsz) <= sound_buffsizes[dev])
+ while ((p + bsz) <= dsp_dev->buffsize &&
+ n < dmap->max_fragments &&
+ n < MAX_SUB_BUFFERS)
{
- dev_buf[dev][n] = snd_raw_buf[dev][i] + p;
- dev_buf_phys[dev][n] = snd_raw_buf_phys[dev][i] + p;
+ dmap->buf[n] = dmap->raw_buf[i] + p;
+ dmap->buf_phys[n] = dmap->raw_buf_phys[i] + p;
p += bsz;
n++;
}
}
- dev_nbufs[dev] = n;
+ dmap->nbufs = n;
+ dmap->bytes_in_use = n * bsz;
- for (i = 0; i < dev_nbufs[dev]; i++)
+ for (i = 0; i < dmap->nbufs; i++)
{
- dev_counts[dev][i] = 0;
+ dmap->counts[i] = 0;
}
- bufferalloc_done[dev] = 1;
+ dmap->flags |= DMA_ALLOC_DONE;
}
static void
dma_init_buffers (int dev)
{
- RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
- dev_underrun[dev] = 0;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap = &dmaps[dev];
- dev_busy[dev] = 1;
+ RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
- bufferalloc_done[dev] = 0;
+ dmap->flags = DMA_BUSY; /* Other flags off */
+ dmap->qlen = dmap->qhead = dmap->qtail = 0;
- dev_active[dev] = dev_qlen[dev] = dev_qtail[dev] = dev_qhead[dev] = 0;
- dev_needs_restart[dev] = dev_started[dev] = 0;
- dma_mode[dev] = DMODE_NONE;
+ dmap->qlen = dmap->qtail = dmap->qhead = 0;
+ dmap->dma_mode = DMODE_NONE;
}
int
DMAbuf_open (int dev, int mode)
{
int retval;
+ struct dma_buffparms *dmap = NULL;
- if (dev >= num_dspdevs)
+ if (dev >= num_audiodevs)
{
printk ("PCM device %d not installed.\n", dev);
return RET_ERROR (ENXIO);
}
- if (dev_busy[dev])
- return RET_ERROR (EBUSY);
-
- if (!dsp_devs[dev])
+ if (!audio_devs[dev])
{
- printk ("DSP device %d not initialized\n", dev);
+ printk ("PCM device %d not initialized\n", dev);
return RET_ERROR (ENXIO);
}
+ dmap = audio_devs[dev]->dmap = &dmaps[dev];
+
+ if (dmap->flags & DMA_BUSY)
+ return RET_ERROR (EBUSY);
+
#ifdef USE_RUNTIME_DMAMEM
+ dmap->raw_buf[0] = NULL;
sound_dma_malloc (dev);
#endif
- if (snd_raw_buf[dev][0] == NULL)
+ if (dmap->raw_buf[0] == NULL)
return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */
- if ((retval = dsp_devs[dev]->open (dev, mode)) < 0)
+ if ((retval = audio_devs[dev]->open (dev, mode)) < 0)
return retval;
- dev_modes[dev] = mode;
- dev_subdivision[dev] = 0;
+ dmap->open_mode = mode;
+ dmap->subdivision = dmap->underrun_count = 0;
+ dmap->fragment_size = 0;
+ dmap->max_fragments = 65536; /* Just a large value */
dma_init_buffers (dev);
- dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1);
- dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1);
- dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1);
+ audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1);
+ audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1);
+ audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1);
return 0;
}
@@ -241,10 +216,11 @@ dma_reset (int dev)
unsigned long flags;
DISABLE_INTR (flags);
- dsp_devs[dev]->reset (dev);
- dsp_devs[dev]->close (dev);
- if ((retval = dsp_devs[dev]->open (dev, dev_modes[dev])) < 0)
+ audio_devs[dev]->reset (dev);
+ audio_devs[dev]->close (dev);
+
+ if ((retval = audio_devs[dev]->open (dev, audio_devs[dev]->dmap->open_mode)) < 0)
printk ("Sound: Reset failed - Can't reopen device\n");
RESTORE_INTR (flags);
@@ -257,17 +233,19 @@ dma_sync (int dev)
{
unsigned long flags;
- if (dma_mode[dev] == DMODE_OUTPUT)
+ if (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT)
{
DISABLE_INTR (flags);
- while ((!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) ||
- dmabuf_interrupted[dev]))
- && dev_qlen[dev])
+ while (!PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev])
+ && audio_devs[dev]->dmap->qlen)
{
DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ);
if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
- return dev_qlen[dev];
+ {
+ RESTORE_INTR (flags);
+ return audio_devs[dev]->dmap->qlen;
+ }
}
RESTORE_INTR (flags);
@@ -277,27 +255,26 @@ dma_sync (int dev)
*/
DISABLE_INTR (flags);
- if (dsp_devs[dev]->has_output_drained) /* Device has hidden buffers */
+ if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */
{
- while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) ||
- dmabuf_interrupted[dev])
- && !dsp_devs[dev]->has_output_drained (dev))
+ while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
+ && audio_devs[dev]->local_qlen (dev))
{
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ / 4);
+ DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ);
}
}
RESTORE_INTR (flags);
}
- return dev_qlen[dev];
+ return audio_devs[dev]->dmap->qlen;
}
int
DMAbuf_release (int dev, int mode)
{
+ unsigned long flags;
- if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) ||
- dmabuf_interrupted[dev])
- && (dma_mode[dev] == DMODE_OUTPUT))
+ if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
+ && (audio_devs[dev]->dmap->dma_mode == DMODE_OUTPUT))
{
dma_sync (dev);
}
@@ -306,12 +283,14 @@ DMAbuf_release (int dev, int mode)
sound_dma_free (dev);
#endif
- dsp_devs[dev]->reset (dev);
+ DISABLE_INTR (flags);
+ audio_devs[dev]->reset (dev);
- dsp_devs[dev]->close (dev);
+ audio_devs[dev]->close (dev);
- dma_mode[dev] = DMODE_NONE;
- dev_busy[dev] = 0;
+ audio_devs[dev]->dmap->dma_mode = DMODE_NONE;
+ audio_devs[dev]->dmap->flags &= ~DMA_BUSY;
+ RESTORE_INTR (flags);
return 0;
}
@@ -321,50 +300,51 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
{
unsigned long flags;
int err = EIO;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
DISABLE_INTR (flags);
- if (!dev_qlen[dev])
+ if (!dmap->qlen)
{
- if (dev_needs_restart[dev])
+ if (dmap->flags & DMA_RESTART)
{
dma_reset (dev);
- dev_needs_restart[dev] = 0;
+ dmap->flags &= ~DMA_RESTART;
}
- if (dma_mode[dev] == DMODE_OUTPUT) /* Was output -> direction change */
+ if (dmap->dma_mode == DMODE_OUTPUT) /* Direction change */
{
dma_sync (dev);
dma_reset (dev);
- dma_mode[dev] = DMODE_NONE;
+ dmap->dma_mode = DMODE_NONE;
}
- if (!bufferalloc_done[dev])
+ if (!(dmap->flags & DMA_ALLOC_DONE))
reorganize_buffers (dev);
- if (!dma_mode[dev])
+ if (dmap->dma_mode)
{
int err;
- if ((err = dsp_devs[dev]->prepare_for_input (dev,
- dev_buffsize[dev], dev_nbufs[dev])) < 0)
+ if ((err = audio_devs[dev]->prepare_for_input (dev,
+ dmap->fragment_size, dmap->nbufs)) < 0)
{
RESTORE_INTR (flags);
return err;
}
- dma_mode[dev] = DMODE_INPUT;
+ dmap->dma_mode = DMODE_INPUT;
}
- if (!dev_active[dev])
+ if (!(dmap->flags & DMA_ACTIVE))
{
- dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]],
- dev_buffsize[dev], 0,
- !sound_dma_automode[dev] ||
- !dev_started[dev]);
- dev_active[dev] = 1;
- dev_started[dev] = 1;
+ audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],
+ dmap->fragment_size, 0,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+ !(dmap->flags & DMA_STARTED));
+ dmap->flags |= DMA_ACTIVE | DMA_STARTED;
}
/* Wait for the next block */
+
DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
{
@@ -377,60 +357,42 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
}
RESTORE_INTR (flags);
- if (!dev_qlen[dev])
+ if (!dmap->qlen)
return RET_ERROR (err);
- *buf = &dev_buf[dev][dev_qhead[dev]][dev_counts[dev][dev_qhead[dev]]];
- *len = dev_buffsize[dev] - dev_counts[dev][dev_qhead[dev]];
+ *buf = &dmap->buf[dmap->qhead][dmap->counts[dmap->qhead]];
+ *len = dmap->fragment_size - dmap->counts[dmap->qhead];
- return dev_qhead[dev];
+ return dmap->qhead;
}
int
DMAbuf_rmchars (int dev, int buff_no, int c)
{
- int p = dev_counts[dev][dev_qhead[dev]] + c;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+
+ int p = dmap->counts[dmap->qhead] + c;
- if (p >= dev_buffsize[dev])
- { /* This buffer is now empty */
- dev_counts[dev][dev_qhead[dev]] = 0;
- dev_qlen[dev]--;
- dev_qhead[dev] = (dev_qhead[dev] + 1) % dev_nbufs[dev];
+ if (p >= dmap->fragment_size)
+ { /* This buffer is completely empty */
+ dmap->counts[dmap->qhead] = 0;
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ printk ("\nSound: Audio queue1 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
+ dmap->qlen--;
+ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
}
else
- dev_counts[dev][dev_qhead[dev]] = p;
+ dmap->counts[dmap->qhead] = p;
return 0;
}
int
-DMAbuf_read (int dev, snd_rw_buf * user_buf, int count)
-{
- char *dmabuf;
- int buff_no, c, err;
-
- /*
- * This routine returns at most 'count' bytes from the dsp input buffers.
- * Returns negative value if there is an error.
- */
-
- if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &c)) < 0)
- return buff_no;
-
- if (c > count)
- c = count;
-
- COPY_TO_USER (user_buf, 0, dmabuf, c);
-
- if ((err = DMAbuf_rmchars (dev, buff_no, c)) < 0)
- return err;
- return c;
-
-}
-
-int
DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
{
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+
switch (cmd)
{
case SNDCTL_DSP_RESET:
@@ -445,10 +407,10 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
break;
case SNDCTL_DSP_GETBLKSIZE:
- if (!bufferalloc_done[dev])
+ if (!(dmap->flags & DMA_ALLOC_DONE))
reorganize_buffers (dev);
- return IOCTL_OUT (arg, dev_buffsize[dev]);
+ return IOCTL_OUT (arg, dmap->fragment_size);
break;
case SNDCTL_DSP_SUBDIVIDE:
@@ -457,13 +419,14 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
if (fact == 0)
{
- fact = dev_subdivision[dev];
+ fact = dmap->subdivision;
if (fact == 0)
fact = 1;
return IOCTL_OUT (arg, fact);
}
- if (dev_subdivision[dev] != 0) /* Too late to change */
+ if (dmap->subdivision != 0 ||
+ dmap->fragment_size)/* Loo late to change */
return RET_ERROR (EINVAL);
if (fact > MAX_REALTIME_FACTOR)
@@ -472,110 +435,193 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
return RET_ERROR (EINVAL);
- dev_subdivision[dev] = fact;
+ dmap->subdivision = fact;
return IOCTL_OUT (arg, fact);
}
break;
+ case SNDCTL_DSP_SETFRAGMENT:
+ {
+ int fact = IOCTL_IN (arg);
+ int bytes, count;
+
+ if (fact == 0)
+ return RET_ERROR (EIO);
+
+ if (dmap->subdivision != 0 ||
+ dmap->fragment_size)/* Loo late to change */
+ return RET_ERROR (EINVAL);
+
+ bytes = fact & 0xffff;
+ count = (fact >> 16) & 0xffff;
+
+ if (count == 0)
+ count = MAX_SUB_BUFFERS;
+
+ if (bytes < 7 || bytes > 17) /* <64 || > 128k */
+ return RET_ERROR (EINVAL);
+
+ if (count < 2)
+ return RET_ERROR (EINVAL);
+
+ dmap->fragment_size = (1 << bytes);
+ dmap->max_fragments = count;
+
+ if (dmap->fragment_size > audio_devs[dev]->buffsize)
+ dmap->fragment_size = audio_devs[dev]->buffsize;
+
+ if (dmap->fragment_size == audio_devs[dev]->buffsize &&
+ audio_devs[dev]->flags & DMA_AUTOMODE)
+ dmap->fragment_size /= 2; /* Needs at least 2 buffers */
+
+ dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */
+ return IOCTL_OUT (arg, bytes | (count << 16));
+ }
+ break;
+
default:
- return dsp_devs[dev]->ioctl (dev, cmd, arg, local);
+ return audio_devs[dev]->ioctl (dev, cmd, arg, local);
}
/* NOTREACHED */
return RET_ERROR (EIO);
}
+static int
+space_in_queue (int dev)
+{
+ int len, max, tmp;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+
+ if (dmap->qlen == dmap->nbufs)/* No space at all */
+ return 0;
+
+ /*
+ * Verify that there are no more pending buffers than the limit
+ * defined by the process.
+ */
+
+ max = dmap->max_fragments;
+ len = dmap->qlen;
+
+ if (audio_devs[dev]->local_qlen)
+ {
+ tmp = audio_devs[dev]->local_qlen (dev);
+ if (tmp & len)
+ tmp--; /*
+ * This buffer has been counted twice
+ */
+ len += tmp;
+ }
+
+ if (len >= max)
+ return 0;
+ return 1;
+}
+
int
DMAbuf_getwrbuffer (int dev, char **buf, int *size)
{
unsigned long flags;
- int err = EIO;
+ int abort, err = EIO;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
- if (dma_mode[dev] == DMODE_INPUT) /* Was input -> Direction change */
+ if (dmap->dma_mode == DMODE_INPUT) /* Direction change */
{
dma_reset (dev);
- dma_mode[dev] = DMODE_NONE;
+ dmap->dma_mode = DMODE_NONE;
}
- else if (dev_needs_restart[dev]) /* Restart buffering */
+ else if (dmap->flags & DMA_RESTART) /* Restart buffering */
{
dma_sync (dev);
dma_reset (dev);
}
- dev_needs_restart[dev] = 0;
+ dmap->flags &= ~DMA_RESTART;
- if (!bufferalloc_done[dev])
+ if (!(dmap->flags & DMA_ALLOC_DONE))
reorganize_buffers (dev);
- if (!dma_mode[dev])
+ if (!dmap->dma_mode)
{
int err;
- dma_mode[dev] = DMODE_OUTPUT;
- if ((err = dsp_devs[dev]->prepare_for_output (dev,
- dev_buffsize[dev], dev_nbufs[dev])) < 0)
+ dmap->dma_mode = DMODE_OUTPUT;
+ if ((err = audio_devs[dev]->prepare_for_output (dev,
+ dmap->fragment_size, dmap->nbufs)) < 0)
return err;
}
DISABLE_INTR (flags);
- RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
-
- if (dev_qlen[dev] == dev_nbufs[dev])
+ abort = 0;
+ while (!space_in_queue (dev) &&
+ !abort)
{
- if (!dev_active[dev])
- {
- printk ("Soundcard warning: DMA not activated %d/%d\n",
- dev_qlen[dev], dev_nbufs[dev]);
- return RET_ERROR (EIO);
- }
-
- /* Wait for free space */
+ /*
+ * Wait for free space
+ */
DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
{
printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
err = EIO;
+ abort = 1;
SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
}
else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
- err = EINTR;
+ {
+ err = EINTR;
+ abort = 1;
+ }
}
RESTORE_INTR (flags);
- if (dev_qlen[dev] == dev_nbufs[dev])
- return RET_ERROR (err); /* We have got signal (?) */
+ if (!space_in_queue (dev))
+ {
+ return RET_ERROR (err); /* Caught a signal ? */
+ }
- *buf = dev_buf[dev][dev_qtail[dev]];
- *size = dev_buffsize[dev];
- dev_counts[dev][dev_qtail[dev]] = 0;
+ *buf = dmap->buf[dmap->qtail];
+ *size = dmap->fragment_size;
+ dmap->counts[dmap->qtail] = 0;
- return dev_qtail[dev];
+ return dmap->qtail;
}
int
DMAbuf_start_output (int dev, int buff_no, int l)
{
- if (buff_no != dev_qtail[dev])
- printk ("Soundcard warning: DMA buffers out of sync %d != %d\n", buff_no, dev_qtail[dev]);
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
+
+ if (buff_no != dmap->qtail)
+ printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
- dev_qlen[dev]++;
+ dmap->qlen++;
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
- dev_counts[dev][dev_qtail[dev]] = l;
+ dmap->counts[dmap->qtail] = l;
- dev_needs_restart[dev] = (l != dev_buffsize[dev]) &&
- (sound_dma_automode[dev] || dsp_devs[dev]->flags & NEEDS_RESTART);
+ if ((l != dmap->fragment_size) &&
+ ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
+ audio_devs[dev]->flags & NEEDS_RESTART))
+ dmap->flags |= DMA_RESTART;
+ else
+ dmap->flags &= ~DMA_RESTART;
- dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev];
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
- if (!dev_active[dev])
+ if (!(dmap->flags & DMA_ACTIVE))
{
- dev_active[dev] = 1;
- dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]],
- dev_counts[dev][dev_qhead[dev]], 0,
- !sound_dma_automode[dev] || !dev_started[dev]);
- dev_started[dev] = 1;
+ dmap->flags |= DMA_ACTIVE;
+ audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],
+ dmap->counts[dmap->qhead], 0,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+ !(dmap->flags & DMA_STARTED));
+ dmap->flags |= DMA_STARTED;
}
return 0;
@@ -584,7 +630,8 @@ DMAbuf_start_output (int dev, int buff_no, int l)
int
DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
{
- int chan = sound_dsp_dmachan[dev];
+ int chan = audio_devs[dev]->dmachan;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
unsigned long flags;
/*
@@ -596,29 +643,30 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
* set_dma_addr()
*/
- if (sound_dma_automode[dev])
- { /* Auto restart mode. Transfer the whole
- * buffer */
+ if (audio_devs[dev]->flags & DMA_AUTOMODE)
+ { /*
+ * Auto restart mode. Transfer the whole *
+ * buffer
+ */
#ifdef linux
DISABLE_INTR (flags);
disable_dma (chan);
clear_dma_ff (chan);
set_dma_mode (chan, dma_mode | DMA_AUTOINIT);
- set_dma_addr (chan, snd_raw_buf_phys[dev][0]);
- set_dma_count (chan, sound_buffsizes[dev]);
+ set_dma_addr (chan, dmap->raw_buf_phys[0]);
+ set_dma_count (chan, dmap->bytes_in_use);
enable_dma (chan);
RESTORE_INTR (flags);
#else /* linux */
-
-#ifdef __386BSD__
+#ifdef __FreeBSD__
printk ("sound: Invalid DMA mode for device %d\n", dev);
isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
- (caddr_t)snd_raw_buf_phys[dev][0],
- sound_buffsizes[dev],
+ (caddr_t)dmap->raw_buf_phys[0],
+ dmap->bytes_in_use,
chan);
-#else /* __386BSD__ */
-#if defined(ISC) || defined(SCO) || defined(SVR42)
+#else /* __FreeBSD__ */
+#if defined(GENERIC_SYSV)
#ifndef DMAMODE_AUTO
printk ("sound: Invalid DMA mode for device %d\n", dev);
#endif /* DMAMODE_AUTO */
@@ -627,14 +675,14 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
| DMAMODE_AUTO
#endif /* DMAMODE_AUTO */
,
- snd_raw_buf_phys[dev][0], count);
+ dmap->raw_buf_phys[0], dmap->bytes_in_use);
dma_enable (chan);
-#else /* SYSV */
+#else /* GENERIC_SYSV */
#error This routine is not valid for this OS.
-#endif /* SYSV */
-#endif /* __386BSD__ */
-
+#endif /* __FreeBSD__ */
#endif /* linux */
+
+#endif
}
else
{
@@ -648,21 +696,21 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
enable_dma (chan);
RESTORE_INTR (flags);
#else /* linux */
-#ifdef __386BSD__
+#ifdef __FreeBSD__
isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
(caddr_t)physaddr,
count,
chan);
-#else /* __386BSD__ */
+#else /* __FreeBSD__ */
-#if defined(ISC) || defined(SCO) || defined(SVR42)
+#if defined(GENERIC_SYSV)
dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode),
physaddr, count);
dma_enable (chan);
-#else /* SYSV */
+#else /* GENERIC_SYSV */
#error This routine is not valid for this OS.
-#endif /* SYSV */
-#endif /* __386BSD__ */
+#endif /* GENERIC_SYSV */
+#endif /* __FreeBSD */
#endif /* linux */
}
@@ -673,49 +721,64 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
long
DMAbuf_init (long mem_start)
{
- int i;
+ int dev;
/*
- * In this version the DMA buffer allocation is done by sound_mem_init()
- * which is called by init/main.c
- */
-
- for (i = 0; i < MAX_DSP_DEV; i++)
- {
- dev_qlen[i] = 0;
- dev_qhead[i] = 0;
- dev_qtail[i] = 0;
- dev_active[i] = 0;
- dev_busy[i] = 0;
- bufferalloc_done[i] = 0;
- }
+ * NOTE! This routine could be called several times.
+ */
+ for (dev = 0; dev < num_audiodevs; dev++)
+ audio_devs[dev]->dmap = &dmaps[dev];
return mem_start;
}
void
-DMAbuf_outputintr (int dev, int underrun_flag)
+DMAbuf_outputintr (int dev, int event_type)
{
- unsigned long flags;
+ /*
+ * Event types:
+ * 0 = DMA transfer done. Device still has more data in the local
+ * buffer.
+ * 1 = DMA transfer done. Device doesn't have local buffer or it's
+ * empty now.
+ * 2 = No DMA transfer but the device has now more space in it's local
+ * buffer.
+ */
- dev_qlen[dev]--;
- dev_qhead[dev] = (dev_qhead[dev] + 1) % dev_nbufs[dev];
- dev_active[dev] = 0;
+ unsigned long flags;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
- if (dev_qlen[dev])
- {
- dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]],
- dev_counts[dev][dev_qhead[dev]], 1,
- !sound_dma_automode[dev]);
- dev_active[dev] = 1;
- }
- else if (underrun_flag)
+ if (event_type != 2)
{
- dev_underrun[dev]++;
- dsp_devs[dev]->halt_xfer (dev);
- dev_needs_restart[dev] = (sound_dma_automode[dev] ||
- dsp_devs[dev]->flags & NEEDS_RESTART);
- }
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ {
+ printk ("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
+ return;
+ }
+
+ dmap->qlen--;
+ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ dmap->flags &= ~DMA_ACTIVE;
+
+ if (dmap->qlen)
+ {
+ audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],
+ dmap->counts[dmap->qhead], 1,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE));
+ dmap->flags |= DMA_ACTIVE;
+ }
+ else if (event_type == 1)
+ {
+ dmap->underrun_count++;
+ audio_devs[dev]->halt_xfer (dev);
+ if ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
+ audio_devs[dev]->flags & NEEDS_RESTART)
+ dmap->flags |= DMA_RESTART;
+ else
+ dmap->flags &= ~DMA_RESTART;
+ }
+ } /* event_type != 2 */
DISABLE_INTR (flags);
if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
@@ -729,28 +792,31 @@ void
DMAbuf_inputintr (int dev)
{
unsigned long flags;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap;
- if (!dev_busy[dev])
- {
- dsp_devs[dev]->close (dev);
- }
- else if (dev_qlen[dev] == (dev_nbufs[dev] - 1))
+ if (dmap->qlen == (dmap->nbufs - 1))
{
printk ("Sound: Recording overrun\n");
- dev_underrun[dev]++;
- dsp_devs[dev]->halt_xfer (dev);
- dev_active[dev] = 0;
- dev_needs_restart[dev] = sound_dma_automode[dev];
+ dmap->underrun_count++;
+ audio_devs[dev]->halt_xfer (dev);
+ dmap->flags &= ~DMA_ACTIVE;
+ if (audio_devs[dev]->flags & DMA_AUTOMODE)
+ dmap->flags |= DMA_RESTART;
+ else
+ dmap->flags &= ~DMA_RESTART;
}
else
{
- dev_qlen[dev]++;
- dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev];
-
- dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]],
- dev_buffsize[dev], 1,
- !sound_dma_automode[dev]);
- dev_active[dev] = 1;
+ dmap->qlen++;
+ if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
+ printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
+ dev, dmap->qlen, dmap->nbufs);
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+
+ audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],
+ dmap->fragment_size, 1,
+ !(audio_devs[dev]->flags & DMA_AUTOMODE));
+ dmap->flags |= DMA_ACTIVE;
}
DISABLE_INTR (flags);
@@ -765,12 +831,12 @@ int
DMAbuf_open_dma (int dev)
{
unsigned long flags;
- int chan = sound_dsp_dmachan[dev];
+ int chan = audio_devs[dev]->dmachan;
if (ALLOC_DMA_CHN (chan))
{
printk ("Unable to grab DMA%d for the audio driver\n", chan);
- return 0;
+ return RET_ERROR (EBUSY);
}
DISABLE_INTR (flags);
@@ -780,13 +846,13 @@ DMAbuf_open_dma (int dev)
#endif
RESTORE_INTR (flags);
- return 1;
+ return 0;
}
void
DMAbuf_close_dma (int dev)
{
- int chan = sound_dsp_dmachan[dev];
+ int chan = audio_devs[dev]->dmachan;
DMAbuf_reset_dma (chan);
RELEASE_DMA_CHN (chan);
@@ -806,7 +872,9 @@ DMAbuf_reset_dma (int chan)
*/
#else
-/* Stub versions if audio services not included */
+/*
+ * Stub versions if audio services not included
+ */
int
DMAbuf_open (int dev, int mode)
@@ -821,12 +889,6 @@ DMAbuf_release (int dev, int mode)
}
int
-DMAbuf_read (int dev, snd_rw_buf * user_buf, int count)
-{
- return RET_ERROR (EIO);
-}
-
-int
DMAbuf_getwrbuffer (int dev, char **buf, int *size)
{
return RET_ERROR (EIO);
diff --git a/sys/i386/isa/sound/gus_card.c b/sys/i386/isa/sound/gus_card.c
index e0121d7..7f3bc42 100644
--- a/sys/i386/isa/sound/gus_card.c
+++ b/sys/i386/isa/sound/gus_card.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: gus_card.c,v 1.7 1994/08/02 07:39:52 davidg Exp $
+ * $Id: gus_card.c,v 1.8 1994/09/27 17:58:17 davidg Exp $
*/
#include "sound_config.h"
@@ -35,6 +35,9 @@
#include "gus_hw.h"
int gus_base, gus_irq, gus_dma;
+extern int gus_wave_volume;
+extern int gus_pcm_volume;
+extern int have_gus_max;
long
attach_gus_card (long mem_start, struct address_info *hw_config)
@@ -43,12 +46,17 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
snd_set_irq_handler (hw_config->irq, gusintr);
- if (gus_wave_detect (hw_config->io_base)) /* Try first the default */
+ if (gus_wave_detect (hw_config->io_base)) /*
+ * Try first the default
+ */
{
mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma);
#ifndef EXCLUDE_MIDI
mem_start = gus_midi_init (mem_start);
#endif
+#ifndef EXCLUDE_SEQUENCER
+ sound_timer_init (hw_config->io_base + 8);
+#endif
return mem_start;
}
@@ -59,7 +67,9 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
*/
for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
- if (io_addr != hw_config->io_base) /* Already tested */
+ if (io_addr != hw_config->io_base) /*
+ * Already tested
+ */
if (gus_wave_detect (io_addr))
{
printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base);
@@ -67,12 +77,17 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
#ifndef EXCLUDE_MIDI
mem_start = gus_midi_init (mem_start);
#endif
+#ifndef EXCLUDE_SEQUENCER
+ sound_timer_init (io_addr + 8);
+#endif
return mem_start;
}
#endif
- return mem_start; /* Not detected */
+ return mem_start; /*
+ * Not detected
+ */
}
int
@@ -90,7 +105,9 @@ probe_gus (struct address_info *hw_config)
*/
for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
- if (io_addr != hw_config->io_base) /* Already tested */
+ if (io_addr != hw_config->io_base) /*
+ * Already tested
+ */
if (gus_wave_detect (io_addr))
return 1;
@@ -100,7 +117,7 @@ probe_gus (struct address_info *hw_config)
}
void
-gusintr (int unit)
+gusintr (int irq)
{
unsigned char src;
@@ -108,6 +125,11 @@ gusintr (int unit)
sti ();
#endif
+#ifndef EXCLUDE_GUSMAX
+ if (have_gus_max)
+ ad1848_interrupt (irq);
+#endif
+
while (1)
{
if (!(src = INB (u_IrqStatus)))
@@ -127,8 +149,11 @@ gusintr (int unit)
if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ))
{
- printk ("T");
- gus_write8 (0x45, 0); /* Timer control */
+#ifndef EXCLUDE_SEQUENCER
+ sound_timer_interrupt ();
+#else
+ gus_write8 (0x45, 0); /* Stop timers */
+#endif
}
if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
@@ -139,3 +164,29 @@ gusintr (int unit)
}
#endif
+
+/*
+ * Some extra code for the 16 bit sampling option
+ */
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS16)
+
+int
+probe_gus_db16 (struct address_info *hw_config)
+{
+ return ad1848_detect (hw_config->io_base);
+}
+
+long
+attach_gus_db16 (long mem_start, struct address_info *hw_config)
+{
+ gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+
+ ad1848_init ("GUS 16 bit sampling", hw_config->io_base,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma);
+ return mem_start;
+}
+
+#endif
diff --git a/sys/i386/isa/sound/gus_midi.c b/sys/i386/isa/sound/gus_midi.c
index 15931cc..94a856f 100644
--- a/sys/i386/isa/sound/gus_midi.c
+++ b/sys/i386/isa/sound/gus_midi.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: gus_midi.c,v 1.5 1994/08/02 07:39:58 davidg Exp $
*/
#include "sound_config.h"
@@ -80,7 +80,9 @@ gus_midi_open (int dev, int mode,
gus_midi_control |= MIDI_ENABLE_XMIT;
}
- OUTB (gus_midi_control, u_MidiControl); /* Enable */
+ OUTB (gus_midi_control, u_MidiControl); /*
+ * Enable
+ */
midi_busy = 1;
qlen = qhead = qtail = output_used = 0;
@@ -106,7 +108,9 @@ dump_to_midi (unsigned char midi_byte)
}
else
{
- /* Enable Midi xmit interrupts (again) */
+ /*
+ * Enable Midi xmit interrupts (again)
+ */
gus_midi_control |= MIDI_ENABLE_XMIT;
OUTB (gus_midi_control, u_MidiControl);
}
@@ -118,7 +122,9 @@ dump_to_midi (unsigned char midi_byte)
static void
gus_midi_close (int dev)
{
- /* Reset FIFO pointers, disable intrs */
+ /*
+ * Reset FIFO pointers, disable intrs
+ */
OUTB (MIDI_RESET, u_MidiControl);
midi_busy = 0;
@@ -150,14 +156,18 @@ gus_midi_out (int dev, unsigned char midi_byte)
if (!qlen)
if (dump_to_midi (midi_byte))
- return 1; /* OK */
+ return 1; /*
+ * OK
+ */
/*
* Put to the local queue
*/
if (qlen >= 256)
- return 0; /* Local queue full */
+ return 0; /*
+ * Local queue full
+ */
DISABLE_INTR (flags);
@@ -214,9 +224,14 @@ gus_midi_buffer_status (int dev)
return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY);
}
+#define MIDI_SYNTH_NAME "Gravis Ultrasound Midi"
+#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
+#include "midi_synth.h"
+
static struct midi_operations gus_midi_operations =
{
- {"Gravis UltraSound", 0, 0, SNDCARD_GUS},
+ {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
+ &std_midi_synth,
gus_midi_open,
gus_midi_close,
gus_midi_ioctl,
@@ -224,16 +239,25 @@ static struct midi_operations gus_midi_operations =
gus_midi_start_read,
gus_midi_end_read,
gus_midi_kick,
- NULL, /* command */
- gus_midi_buffer_status
+ NULL, /*
+ * command
+ */
+ gus_midi_buffer_status,
+ NULL
};
long
gus_midi_init (long mem_start)
{
+ if (num_midis >= MAX_MIDI_DEV)
+ {
+ printk ("Sound: Too many midi devices detected\n");
+ return mem_start;
+ }
+
OUTB (MIDI_RESET, u_MidiControl);
- my_dev = num_midis;
+ std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &gus_midi_operations;
return mem_start;
}
@@ -265,7 +289,9 @@ gus_midi_interrupt (int dummy)
if (!qlen)
{
- /* Disable Midi output interrupts, since no data in the buffer */
+ /*
+ * Disable Midi output interrupts, since no data in the buffer
+ */
gus_midi_control &= ~MIDI_ENABLE_XMIT;
OUTB (gus_midi_control, u_MidiControl);
}
diff --git a/sys/i386/isa/sound/gus_vol.c b/sys/i386/isa/sound/gus_vol.c
index 0ec1417..07c2c6e 100644
--- a/sys/i386/isa/sound/gus_vol.c
+++ b/sys/i386/isa/sound/gus_vol.c
@@ -2,7 +2,8 @@
* gus_vol.c - Compute volume for GUS.
*
* Greg Lee 1993.
- * $Id$
+ *
+ * $Id: gus_vol.c,v 1.4 1994/08/02 07:39:59 davidg Exp $
*/
#include "sound_config.h"
#ifndef EXCLUDE_GUS
diff --git a/sys/i386/isa/sound/gus_wave.c b/sys/i386/isa/sound/gus_wave.c
index 621286f..dddb527 100644
--- a/sys/i386/isa/sound/gus_wave.c
+++ b/sys/i386/isa/sound/gus_wave.c
@@ -3,7 +3,7 @@
*
* Driver for the Gravis UltraSound wave table synth.
*
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1993, 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: gus_wave.c,v 1.9 1994/08/02 07:40:02 davidg Exp $
*/
#include "sound_config.h"
@@ -77,23 +77,23 @@ struct voice_info
};
+static struct voice_alloc_info *voice_alloc;
+
extern int gus_base;
extern int gus_irq, gus_dma;
-extern char *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT];
-extern unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
-extern int snd_raw_count[MAX_DSP_DEV];
static long gus_mem_size = 0;
static long free_mem_ptr = 0;
static int gus_busy = 0;
static int nr_voices = 0;
static int gus_devnum = 0;
static int volume_base, volume_scale, volume_method;
-static int gus_line_vol = 100, gus_mic_vol = 0;
static int gus_recmask = SOUND_MASK_MIC;
static int recording_active = 0;
int gus_wave_volume = 60;
int gus_pcm_volume = 80;
+int have_gus_max = 0;
+static int gus_line_vol = 100, gus_mic_vol = 0;
static unsigned char mix_image = 0x00;
/*
@@ -102,13 +102,9 @@ static unsigned char mix_image = 0x00;
*/
static int active_device = 0;
-#define GUS_DEV_WAVE 1 /*
- * * * Wave table synth */
-#define GUS_DEV_PCM_DONE 2 /*
- * * * PCM device, transfer done */
-#define GUS_DEV_PCM_CONTINUE 3 /*
- * * * PCM device, transfer the
- * second * * * chn */
+#define GUS_DEV_WAVE 1 /* Wave table synth */
+#define GUS_DEV_PCM_DONE 2 /* PCM device, transfer done */
+#define GUS_DEV_PCM_CONTINUE 3 /* PCM device, transfer done ch. 1/2 */
static int gus_sampling_speed;
static int gus_sampling_channels;
@@ -119,33 +115,13 @@ DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
/*
* Variables and buffers for PCM output
*/
-#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /*
- * * * Don't
- * * * change
- *
- */
-
-static int pcm_bsize, /*
- * Current blocksize
- */
- pcm_nblk, /*
- * Current # of blocks
- */
- pcm_banksize; /*
-
-
- * * * * # bytes allocated for channels */
-static int pcm_datasize[MAX_PCM_BUFFERS]; /*
+#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* Don't change */
-
- * * * * Actual # of bytes
- * in blk * */
-static volatile int pcm_head, pcm_tail, pcm_qlen; /*
-
-
- * * * * DRAM queue
- * */
+static int pcm_bsize, pcm_nblk, pcm_banksize;
+static int pcm_datasize[MAX_PCM_BUFFERS];
+static volatile int pcm_head, pcm_tail, pcm_qlen;
static volatile int pcm_active;
+static volatile int dma_active;
static int pcm_opened = 0;
static int pcm_current_dev;
static int pcm_current_block;
@@ -157,63 +133,25 @@ struct voice_info voices[32];
static int freq_div_table[] =
{
- 44100, /*
- * 14
- */
- 41160, /*
- * 15
- */
- 38587, /*
- * 16
- */
- 36317, /*
- * 17
- */
- 34300, /*
- * 18
- */
- 32494, /*
- * 19
- */
- 30870, /*
- * 20
- */
- 29400, /*
- * 21
- */
- 28063, /*
- * 22
- */
- 26843, /*
- * 23
- */
- 25725, /*
- * 24
- */
- 24696, /*
- * 25
- */
- 23746, /*
- * 26
- */
- 22866, /*
- * 27
- */
- 22050, /*
- * 28
- */
- 21289, /*
- * 29
- */
- 20580, /*
- * 30
- */
- 19916, /*
- * 31
- */
- 19293 /*
- * 32
- */
+ 44100, /* 14 */
+ 41160, /* 15 */
+ 38587, /* 16 */
+ 36317, /* 17 */
+ 34300, /* 18 */
+ 32494, /* 19 */
+ 30870, /* 20 */
+ 29400, /* 21 */
+ 28063, /* 22 */
+ 26843, /* 23 */
+ 25725, /* 24 */
+ 24696, /* 25 */
+ 23746, /* 26 */
+ 22866, /* 27 */
+ 22050, /* 28 */
+ 21289, /* 29 */
+ 20580, /* 30 */
+ 19916, /* 31 */
+ 19293 /* 32 */
};
static struct patch_info *samples;
@@ -236,10 +174,8 @@ static void compute_volume (int voice, int volume);
static void do_volume_irq (int voice);
static void set_input_volumes (void);
-#define INSTANT_RAMP -1 /*
- * * * Dont use ramping */
-#define FAST_RAMP 0 /*
- * * * Fastest possible ramp */
+#define INSTANT_RAMP -1 /* Instant change. No ramping */
+#define FAST_RAMP 0 /* Fastest possible ramp */
static void
reset_sample_memory (void)
@@ -253,12 +189,10 @@ reset_sample_memory (void)
for (i = 0; i < 32; i++)
patch_map[i] = -1;
- gus_poke (0, 0); /*
- * Put silence here
- */
+ gus_poke (0, 0); /* Put a silent sample to the beginning */
gus_poke (1, 0);
-
free_mem_ptr = 2;
+
free_sample = 0;
for (i = 0; i < MAX_PATCH; i++)
@@ -276,7 +210,7 @@ gus_delay (void)
static void
gus_poke (long addr, unsigned char data)
-{
+{ /* Writes a byte to the DRAM */
unsigned long flags;
DISABLE_INTR (flags);
@@ -292,7 +226,7 @@ gus_poke (long addr, unsigned char data)
static unsigned char
gus_peek (long addr)
-{
+{ /* Reads a byte from the DRAM */
unsigned long flags;
unsigned char tmp;
@@ -311,7 +245,7 @@ gus_peek (long addr)
void
gus_write8 (int reg, unsigned int data)
-{
+{ /* Writes to an indirect register (8 bit) */
unsigned long flags;
DISABLE_INTR (flags);
@@ -324,7 +258,7 @@ gus_write8 (int reg, unsigned int data)
unsigned char
gus_read8 (int reg)
-{
+{ /* Reads from an indirect register (8 bit). Offset 0x80. */
unsigned long flags;
unsigned char val;
@@ -338,7 +272,7 @@ gus_read8 (int reg)
unsigned char
gus_look8 (int reg)
-{
+{ /* Reads from an indirect register (8 bit). No additional offset. */
unsigned long flags;
unsigned char val;
@@ -352,7 +286,7 @@ gus_look8 (int reg)
void
gus_write16 (int reg, unsigned int data)
-{
+{ /* Writes to an indirect register (16 bit) */
unsigned long flags;
DISABLE_INTR (flags);
@@ -367,7 +301,7 @@ gus_write16 (int reg, unsigned int data)
unsigned short
gus_read16 (int reg)
-{
+{ /* Reads from an indirect register (16 bit). Offset 0x80. */
unsigned long flags;
unsigned char hi, lo;
@@ -385,9 +319,11 @@ gus_read16 (int reg)
void
gus_write_addr (int reg, unsigned long address, int is16bit)
-{
+{ /* Writes an 24 bit memory address */
unsigned long hold_address;
+ unsigned long flags;
+ DISABLE_INTR (flags);
if (is16bit)
{
/*
@@ -406,6 +342,7 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
gus_delay ();
gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff));
gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff));
+ RESTORE_INTR (flags);
}
static void
@@ -425,7 +362,7 @@ gus_select_max_voices (int nvoices)
if (nvoices > 32)
nvoices = 32;
- nr_voices = nvoices;
+ voice_alloc->max_voice = nr_voices = nvoices;
gus_write8 (0x0e, (nvoices - 1) | 0xc0);
}
@@ -449,14 +386,8 @@ gus_voice_mode (unsigned int m)
{
unsigned char mode = (unsigned char) (m & 0xff);
- gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /*
- * Don't
- * start
- * or
- * stop
- * *
- * voice
- */
+ gus_write8 (0x00, (gus_read8 (0x00) & 0x03) |
+ (mode & 0xfc)); /* Don't touch last two bits */
gus_delay ();
gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));
}
@@ -476,9 +407,7 @@ gus_voice_freq (unsigned long freq)
static void
gus_voice_volume (unsigned int vol)
{
- gus_write8 (0x0d, 0x03); /*
- * Stop ramp before setting volume
- */
+ gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */
gus_write16 (0x09, (unsigned short) (vol << 4));
}
@@ -516,14 +445,8 @@ gus_ramp_mode (unsigned int m)
{
unsigned char mode = (unsigned char) (m & 0xff);
- gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); /*
- * Don't
- * start
- * or
- * stop
- * *
- * ramping
- */
+ gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) |
+ (mode & 0xfc)); /* Leave the last 2 bits alone */
gus_delay ();
gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));
}
@@ -556,15 +479,10 @@ gus_voice_init (int voice)
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_voice_volume (0);
- gus_write_addr (0x0a, 0, 0); /*
- * Set current position to 0
- */
- gus_write8 (0x00, 0x03); /*
- * Voice off
- */
- gus_write8 (0x0d, 0x03); /*
- * Ramping off
- */
+ gus_write_addr (0x0a, 0, 0); /* Set current position to 0 */
+ gus_write8 (0x00, 0x03); /* Voice off */
+ gus_write8 (0x0d, 0x03); /* Ramping off */
+ voice_alloc->map[voice] = 0;
RESTORE_INTR (flags);
}
@@ -604,17 +522,14 @@ step_envelope (int voice)
gus_select_voice (voice);
gus_rampoff ();
RESTORE_INTR (flags);
- return; /*
- * Sustain
- */
- }
-
- if (voices[voice].env_phase >= 5)
- {
+ return;
/*
- * Shoot the voice off
+ * Sustain phase begins. Continue envelope after receiving note off.
*/
+ }
+ if (voices[voice].env_phase >= 5)
+ { /* Envelope finished. Shoot the voice down */
gus_voice_init (voice);
return;
}
@@ -631,20 +546,14 @@ step_envelope (int voice)
gus_voice_volume (prev_vol);
- gus_write8 (0x06, rate); /*
- * Ramping rate
- */
+ gus_write8 (0x06, rate); /* Ramping rate */
voices[voice].volume_irq_mode = VMODE_ENVELOPE;
- if (((vol - prev_vol) / 64) == 0) /*
- * No significant volume change
- */
+ if (((vol - prev_vol) / 64) == 0) /* No significant volume change */
{
RESTORE_INTR (flags);
- step_envelope (voice); /*
- * Continue with the next phase
- */
+ step_envelope (voice); /* Continue the envelope on the next step */
return;
}
@@ -653,18 +562,14 @@ step_envelope (int voice)
if (vol >= (4096 - 64))
vol = 4096 - 65;
gus_ramp_range (0, vol);
- gus_rampon (0x20); /*
- * Increasing, irq
- */
+ gus_rampon (0x20); /* Increasing volume, with IRQ */
}
else
{
if (vol <= 64)
vol = 65;
gus_ramp_range (vol, 4030);
- gus_rampon (0x60); /*
- * Decreasing, irq
- */
+ gus_rampon (0x60); /* Decreasing volume, with IRQ */
}
voices[voice].current_volume = vol;
RESTORE_INTR (flags);
@@ -683,19 +588,13 @@ static void
start_release (int voice, long int flags)
{
if (gus_read8 (0x00) & 0x03)
- return; /*
- * Voice already stopped
- */
+ return; /* Voice already stopped */
- voices[voice].env_phase = 2; /*
- * Will be incremented by step_envelope
- */
+ voices[voice].env_phase = 2; /* Will be incremented by step_envelope */
voices[voice].current_volume =
voices[voice].initial_volume =
- gus_read16 (0x09) >> 4; /*
- * Get current volume
- */
+ gus_read16 (0x09) >> 4; /* Get current volume */
voices[voice].mode &= ~WAVE_SUSTAIN_ON;
gus_rampoff ();
@@ -714,18 +613,13 @@ gus_voice_fade (int voice)
if (instr_no < 0 || instr_no > MAX_SAMPLE)
{
- gus_write8 (0x00, 0x03); /*
- * Hard stop
- */
+ gus_write8 (0x00, 0x03); /* Hard stop */
+ voice_alloc->map[voice] = 0;
RESTORE_INTR (flags);
return;
}
- is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /*
- * 8 or 16
- * bit
- * samples
- */
+ is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */
if (voices[voice].mode & WAVE_ENVELOPES)
{
@@ -736,9 +630,7 @@ gus_voice_fade (int voice)
/*
* Ramp the volume down but not too quickly.
*/
- if ((gus_read16 (0x09) >> 4) < 100) /*
- * Get current volume
- */
+ if ((int) (gus_read16 (0x09) >> 4) < 100) /* Get current volume */
{
gus_voice_off ();
gus_rampoff ();
@@ -748,9 +640,7 @@ gus_voice_fade (int voice)
gus_ramp_range (65, 4030);
gus_ramp_rate (2, 4);
- gus_rampon (0x40 | 0x20); /*
- * Down, once, irq
- */
+ gus_rampon (0x40 | 0x20); /* Down, once, with IRQ */
voices[voice].volume_irq_mode = VMODE_HALT;
RESTORE_INTR (flags);
}
@@ -767,25 +657,16 @@ gus_reset (void)
for (i = 0; i < 32; i++)
{
- gus_voice_init (i); /*
- * Turn voice off
- */
+ gus_voice_init (i); /* Turn voice off */
gus_voice_init2 (i);
}
- INB (u_Status); /*
- * Touch the status register
- */
+ INB (u_Status); /* Touch the status register */
- gus_look8 (0x41); /*
- * Clear any pending DMA IRQs
- */
- gus_look8 (0x49); /*
- * Clear any pending sample IRQs
- */
- gus_read8 (0x0f); /*
- * Clear pending IRQs
- */
+ gus_look8 (0x41); /* Clear any pending DMA IRQs */
+ gus_look8 (0x49); /* Clear any pending sample IRQs */
+
+ gus_read8 (0x0f); /* Clear pending IRQs */
}
@@ -793,7 +674,7 @@ static void
gus_initialize (void)
{
unsigned long flags;
- register unsigned char dma_image, irq_image, tmp;
+ unsigned char dma_image, irq_image, tmp;
static unsigned char gus_irq_map[16] =
{0, 0, 1, 3, 0, 2, 0, 4, 0, 0, 0, 5, 6, 0, 0, 7};
@@ -802,16 +683,11 @@ gus_initialize (void)
{0, 1, 0, 2, 0, 3, 4, 5};
DISABLE_INTR (flags);
-
- gus_write8 (0x4c, 0); /*
- * Reset GF1
- */
+ gus_write8 (0x4c, 0); /* Reset GF1 */
gus_delay ();
gus_delay ();
- gus_write8 (0x4c, 1); /*
- * Release Reset
- */
+ gus_write8 (0x4c, 1); /* Release Reset */
gus_delay ();
gus_delay ();
@@ -819,49 +695,25 @@ gus_initialize (void)
* Clear all interrupts
*/
- gus_write8 (0x41, 0); /*
- * DMA control
- */
- gus_write8 (0x45, 0); /*
- * Timer control
- */
- gus_write8 (0x49, 0); /*
- * Sample control
- */
+ gus_write8 (0x41, 0); /* DMA control */
+ gus_write8 (0x45, 0); /* Timer control */
+ gus_write8 (0x49, 0); /* Sample control */
gus_select_max_voices (24);
- INB (u_Status); /*
- * Touch the status register
- */
+ INB (u_Status); /* Touch the status register */
- gus_look8 (0x41); /*
- * Clear any pending DMA IRQs
- */
- gus_look8 (0x49); /*
- * Clear any pending sample IRQs
- */
- gus_read8 (0x0f); /*
- * Clear pending IRQs
- */
+ gus_look8 (0x41); /* Clear any pending DMA IRQs */
+ gus_look8 (0x49); /* Clear any pending sample IRQs */
+ gus_read8 (0x0f); /* Clear pending IRQs */
- gus_reset (); /*
- * Resets all voices
- */
+ gus_reset (); /* Resets all voices */
- gus_look8 (0x41); /*
- * Clear any pending DMA IRQs
- */
- gus_look8 (0x49); /*
- * Clear any pending sample IRQs
- */
- gus_read8 (0x0f); /*
- * Clear pending IRQs
- */
+ gus_look8 (0x41); /* Clear any pending DMA IRQs */
+ gus_look8 (0x49); /* Clear any pending sample IRQs */
+ gus_read8 (0x0f); /* Clear pending IRQs */
- gus_write8 (0x4c, 7); /*
- * Master reset | DAC enable | IRQ enable
- */
+ gus_write8 (0x4c, 7); /* Master reset | DAC enable | IRQ enable */
/*
* Set up for Digital ASIC
@@ -869,9 +721,7 @@ gus_initialize (void)
OUTB (0x05, gus_base + 0x0f);
- mix_image |= 0x02; /*
- * Disable line out
- */
+ mix_image |= 0x02; /* Disable line out */
OUTB (mix_image, u_Mixer);
OUTB (0x00, u_IRQDMAControl);
@@ -893,13 +743,9 @@ gus_initialize (void)
if (!tmp)
printk ("Warning! GUS IRQ not selected\n");
irq_image |= tmp;
- irq_image |= 0x40; /*
- * Combine IRQ1 (GF1) and IRQ2 (Midi)
- */
+ irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
- dma_image = 0x40; /*
- * Combine DMA1 (DRAM) and IRQ2 (ADC)
- */
+ dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
tmp = gus_dma_map[gus_dma];
if (!tmp)
printk ("Warning! GUS DMA not selected\n");
@@ -913,60 +759,34 @@ gus_initialize (void)
* Doing it first time
*/
- OUTB (mix_image, u_Mixer); /*
- * Select DMA control
- */
- OUTB (dma_image | 0x80, u_IRQDMAControl); /*
- * Set DMA address
- */
+ OUTB (mix_image, u_Mixer); /* Select DMA control */
+ OUTB (dma_image | 0x80, u_IRQDMAControl); /* Set DMA address */
- OUTB (mix_image | 0x40, u_Mixer); /*
- * Select IRQ control
- */
- OUTB (irq_image, u_IRQDMAControl); /*
- * Set IRQ address
- */
+ OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */
+ OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */
/*
* Doing it second time
*/
- OUTB (mix_image, u_Mixer); /*
- * Select DMA control
- */
- OUTB (dma_image, u_IRQDMAControl); /*
- * Set DMA address
- */
+ OUTB (mix_image, u_Mixer); /* Select DMA control */
+ OUTB (dma_image, u_IRQDMAControl); /* Set DMA address */
- OUTB (mix_image | 0x40, u_Mixer); /*
- * Select IRQ control
- */
- OUTB (irq_image, u_IRQDMAControl); /*
- * Set IRQ address
- */
+ OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */
+ OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */
- gus_select_voice (0); /*
- * This disables writes to IRQ/DMA reg
- */
+ gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
- mix_image &= ~0x02; /*
- * Enable line out
- */
- mix_image |= 0x08; /*
- * Enable IRQ
- */
+ mix_image &= ~0x02; /* Enable line out */
+ mix_image |= 0x08; /* Enable IRQ */
OUTB (mix_image, u_Mixer); /*
* Turn mixer channels on
* Note! Mic in is left off.
*/
- gus_select_voice (0); /*
- * This disables writes to IRQ/DMA reg
- */
+ gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
- gusintr (0); /*
- * Serve pending interrupts
- */
+ gusintr (0); /* Serve pending interrupts */
RESTORE_INTR (flags);
}
@@ -1073,16 +893,13 @@ guswave_set_instr (int dev, int voice, int instr_no)
if (sample_no < 0)
{
printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
- return RET_ERROR (EINVAL);/*
- * Patch not defined
- */
+ return RET_ERROR (EINVAL);/* Patch not defined */
}
- if (sample_ptrs[sample_no] == -1) /*
- * Sample not loaded
- */
+ if (sample_ptrs[sample_no] == -1) /* Sample not loaded */
{
- printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice);
+ printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n",
+ sample_no, instr_no, voice);
return RET_ERROR (EINVAL);
}
@@ -1092,15 +909,12 @@ guswave_set_instr (int dev, int voice, int instr_no)
}
static int
-#ifdef FUTURE_VERSION
guswave_kill_note (int dev, int voice, int note, int velocity)
-#else
-guswave_kill_note (int dev, int voice, int velocity)
-#endif
{
unsigned long flags;
DISABLE_INTR (flags);
+ voice_alloc->map[voice] = 0xffff;
if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
{
voices[voice].kill_pending = 1;
@@ -1121,26 +935,20 @@ guswave_aftertouch (int dev, int voice, int pressure)
short lo_limit, hi_limit;
unsigned long flags;
- return; /*
- * Currently disabled
- */
+ return; /* Procedure currently disabled */
if (voice < 0 || voice > 31)
return;
if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2)
- return; /*
- * Don't mix with envelopes
- */
+ return; /* Don't mix with envelopes */
if (pressure < 32)
{
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_rampoff ();
- compute_and_set_volume (voice, 255, 0); /*
- * Back to original volume
- */
+ compute_and_set_volume (voice, 255, 0); /* Back to original volume */
RESTORE_INTR (flags);
return;
}
@@ -1159,9 +967,7 @@ guswave_aftertouch (int dev, int voice, int pressure)
}
gus_ramp_range (lo_limit, hi_limit);
gus_ramp_rate (3, 8);
- gus_rampon (0x58); /*
- * Bidirectional, Down, Loop
- */
+ gus_rampon (0x58); /* Bidirectional, dow, loop */
RESTORE_INTR (flags);
}
@@ -1241,9 +1047,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
rate = 16;
gus_ramp_rate (0, rate);
- if ((target - current) / 64 == 0) /*
- * Too close
- */
+ if ((target - current) / 64 == 0) /* Close enough to target. */
{
gus_rampoff ();
gus_voice_volume (target);
@@ -1256,9 +1060,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
if (target > (4095 - 65))
target = 4095 - 65;
gus_ramp_range (current, target);
- gus_rampon (0x00); /*
- * Ramp up, once, no irq
- */
+ gus_rampon (0x00); /* Ramp up, once, no IRQ */
}
else
{
@@ -1266,9 +1068,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
target = 65;
gus_ramp_range (target, current);
- gus_rampon (0x40); /*
- * Ramp down, once, no irq
- */
+ gus_rampon (0x40); /* Ramp down, once, no irq */
}
RESTORE_INTR (flags);
}
@@ -1281,15 +1081,11 @@ dynamic_volume_change (int voice)
DISABLE_INTR (flags);
gus_select_voice (voice);
- status = gus_read8 (0x00); /*
- * Voice status
- */
+ status = gus_read8 (0x00); /* Get voice status */
RESTORE_INTR (flags);
if (status & 0x03)
- return; /*
- * Voice not started
- */
+ return; /* Voice was not running */
if (!(voices[voice].mode & WAVE_ENVELOPES))
{
@@ -1303,14 +1099,10 @@ dynamic_volume_change (int voice)
DISABLE_INTR (flags);
gus_select_voice (voice);
- status = gus_read8 (0x0d); /*
- * Ramping status
- */
+ status = gus_read8 (0x0d); /* Ramping status */
RESTORE_INTR (flags);
- if (status & 0x03) /*
- * Sustain phase?
- */
+ if (status & 0x03) /* Sustain phase? */
{
compute_and_set_volume (voice, voices[voice].midi_volume, 1);
return;
@@ -1321,16 +1113,6 @@ dynamic_volume_change (int voice)
compute_volume (voice, voices[voice].midi_volume);
-#if 0 /*
- * * * Is this really required */
- voices[voice].current_volume =
- gus_read16 (0x09) >> 4; /*
- * Get current volume
- */
-
- voices[voice].env_phase--;
- step_envelope (voice);
-#endif
}
static void
@@ -1349,7 +1131,8 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
{
- freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
+ freq = compute_finetune (voices[voice].orig_freq, value,
+ voices[voice].bender_range);
voices[voice].current_freq = freq;
DISABLE_INTR (flags);
@@ -1362,10 +1145,8 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
case CTRL_PITCH_BENDER_RANGE:
voices[voice].bender_range = value;
break;
-#ifdef FUTURE_VERSION
case CTL_EXPRESSION:
value /= 128;
-#endif
case CTRL_EXPRESSION:
if (volume_method == VOL_METHOD_ADAGIO)
{
@@ -1375,14 +1156,12 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
}
break;
-#ifdef FUTURE_VERSION
case CTL_PAN:
voices[voice].panning = (value * 2) - 128;
break;
case CTL_MAIN_VOLUME:
value = (value * 100) / 16383;
-#endif
case CTRL_MAIN_VOLUME:
voices[voice].main_vol = value;
@@ -1390,9 +1169,7 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
dynamic_volume_change (voice);
break;
- default: /*
- * Ignore
- */
+ default:
break;
}
}
@@ -1454,7 +1231,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
best_sample = samplep;
best_delta = delta_freq;
}
- if (samples[samplep].low_note <= note_freq && note_freq <= samples[samplep].high_note)
+ if (samples[samplep].low_note <= note_freq &&
+ note_freq <= samples[samplep].high_note)
sample = samplep;
else
samplep = samples[samplep].key; /*
@@ -1467,16 +1245,10 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if (sample == -1)
{
printk ("GUS: Patch %d not defined for note %d\n", patch, note_num);
- return 0; /*
- * Should play default patch ???
- */
+ return 0; /* Should play default patch ??? */
}
- is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; /*
- * 8 or 16
- * bit
- * samples
- */
+ is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
voices[voice].mode = samples[sample].mode;
voices[voice].patch_vol = samples[sample].volume;
@@ -1493,9 +1265,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
sample_map[voice] = sample;
- base_note = samples[sample].base_note / 100; /*
- * To avoid overflows
- */
+ base_note = samples[sample].base_note / 100; /* Try to avoid overflows */
note_freq /= 100;
freq = samples[sample].base_freq * note_freq / base_note;
@@ -1507,7 +1277,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
* have to calculate the bending now.
*/
- freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
+ freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender,
+ voices[voice].bender_range);
voices[voice].current_freq = freq;
pan = (samples[sample].panning + voices[voice].panning) / 32;
@@ -1519,9 +1290,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if (samples[sample].mode & WAVE_16_BITS)
{
- mode |= 0x04; /*
- * 16 bits
- */
+ mode |= 0x04; /* 16 bits */
if ((sample_ptrs[sample] >> 18) !=
((sample_ptrs[sample] + samples[sample].len) >> 18))
printk ("GUS: Sample address error\n");
@@ -1533,9 +1302,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
DISABLE_INTR (flags);
gus_select_voice (voice);
- gus_voice_off (); /*
- * It may still be running
- */
+ gus_voice_off ();
gus_rampoff ();
RESTORE_INTR (flags);
@@ -1553,22 +1320,17 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if (samples[sample].mode & WAVE_LOOP_BACK)
gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len -
- voices[voice].offset_pending, is16bits); /* Sample
- * start=end */
+ voices[voice].offset_pending, is16bits); /* start=end */
else
gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
is16bits); /* Sample start=begin */
if (samples[sample].mode & WAVE_LOOPING)
{
- mode |= 0x08; /*
- * Looping on
- */
+ mode |= 0x08;
if (samples[sample].mode & WAVE_BIDIR_LOOP)
- mode |= 0x10; /*
- * Bidirectional looping on
- */
+ mode |= 0x10;
if (samples[sample].mode & WAVE_LOOP_BACK)
{
@@ -1578,36 +1340,20 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
mode |= 0x40;
}
- gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits); /*
- * Loop
- * start
- * location
- */
- gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /*
- * Loop
- * end
- * location
- */
+ gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start,
+ is16bits);/* Loop start location */
+ gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end,
+ is16bits);/* Loop end location */
}
else
{
- mode |= 0x20; /*
- * Loop irq at the end
- */
- voices[voice].loop_irq_mode = LMODE_FINISH; /*
- * Ramp it down at
- * the * end
- */
+ mode |= 0x20; /* Loop IRQ at the end */
+ voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */
voices[voice].loop_irq_parm = 1;
- gus_write_addr (0x02, sample_ptrs[sample], is16bits); /*
- * Loop start
- * location
- */
- gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1, is16bits); /*
- * Loop
- * end
- * location
- */
+ gus_write_addr (0x02, sample_ptrs[sample],
+ is16bits);/* Loop start location */
+ gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1,
+ is16bits);/* Loop end location */
}
gus_voice_freq (freq);
gus_voice_balance (pan);
@@ -1618,9 +1364,10 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
}
/*
- * * New guswave_start_note by Andrew J. Robinson attempts to minimize
- * clicking * when the note playing on the voice is changed. It uses volume
- * ramping. */
+ * New guswave_start_note by Andrew J. Robinson attempts to minimize clicking
+ * when the note playing on the voice is changed. It uses volume
+ * ramping.
+ */
static int
guswave_start_note (int dev, int voice, int note_num, int volume)
@@ -1661,7 +1408,7 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
DISABLE_INTR (flags);
}
- if ((mode & 0x01) || ((gus_read16 (0x09) >> 4) < 2065))
+ if ((mode & 0x01) || (int) ((gus_read16 (0x09) >> 4) < 2065))
{
ret_val = guswave_start_note2 (dev, voice, note_num, volume);
}
@@ -1704,7 +1451,7 @@ guswave_open (int dev, int mode)
gus_initialize ();
- if ((err = DMAbuf_open_dma (gus_devnum)))
+ if ((err = DMAbuf_open_dma (gus_devnum)) < 0)
return err;
RESET_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
@@ -1736,11 +1483,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
unsigned long blk_size, blk_end, left, src_offs, target;
- sizeof_patch = (long) &patch.data[0] - (long) &patch; /*
- * Size of
- * the header
- * * info
- */
+ sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
if (format != GUS_PATCH)
{
@@ -1805,9 +1548,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
}
}
- free_mem_ptr = (free_mem_ptr + 31) & ~31; /*
- * Alignment 32 bytes
- */
+ free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */
#define GUS_BANK_SIZE (256*1024)
@@ -1825,17 +1566,13 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if ((free_mem_ptr / GUS_BANK_SIZE) !=
((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
{
- unsigned long tmp_mem = /*
- * Align to 256K*N
- */
+ unsigned long tmp_mem = /* Aling to 256K */
((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
if ((tmp_mem + patch.len) > gus_mem_size)
return RET_ERROR (ENOSPC);
- free_mem_ptr = tmp_mem; /*
- * This leaves unusable memory
- */
+ free_mem_ptr = tmp_mem; /* This leaves unusable memory */
}
}
@@ -1868,11 +1605,9 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
src_offs = 0;
target = free_mem_ptr;
- while (left) /*
- * Not all moved
- */
+ while (left) /* Not completely transferred yet */
{
- blk_size = sound_buffsizes[gus_devnum];
+ blk_size = audio_devs[gus_devnum]->buffsize;
if (blk_size > left)
blk_size = left;
@@ -1882,9 +1617,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
blk_end = target + blk_size;
if ((target >> 18) != (blk_end >> 18))
- { /*
- * Have to split the block
- */
+ { /* Split the block */
blk_end &= ~(256 * 1024 - 1);
blk_size = blk_end - target;
@@ -1904,14 +1637,11 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if (patch.mode & WAVE_UNSIGNED)
if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
- data ^= 0x80; /*
- * Convert to signed
- */
+ data ^= 0x80; /* Convert to signed */
gus_poke (target + i, data);
}
}
-#else /*
- * * * GUS_NO_DMA */
+#else /* GUS_NO_DMA */
{
unsigned long address, hold_address;
unsigned char dma_command;
@@ -1921,15 +1651,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
* OK, move now. First in and then out.
*/
- COPY_FROM_USER (snd_raw_buf[gus_devnum][0],
+ COPY_FROM_USER (audio_devs[gus_devnum]->dmap->raw_buf[0],
addr, sizeof_patch + src_offs,
blk_size);
DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/
- gus_write8 (0x41, 0); /*
- * Disable GF1 DMA
- */
- DMAbuf_start_dma (gus_devnum, snd_raw_buf_phys[gus_devnum][0],
+ gus_write8 (0x41, 0); /* Disable GF1 DMA */
+ DMAbuf_start_dma (gus_devnum,
+ audio_devs[gus_devnum]->dmap->raw_buf_phys[0],
blk_size, DMA_MODE_WRITE);
/*
@@ -1938,7 +1667,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
address = target;
- if (sound_dsp_dmachan[gus_devnum] > 3)
+ if (audio_devs[gus_devnum]->dmachan > 3)
{
hold_address = address;
address = address >> 1;
@@ -1946,33 +1675,21 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
address |= (hold_address & 0x000c0000L);
}
- gus_write16 (0x42, (address >> 4) & 0xffff); /*
- * DRAM DMA address
- */
+ gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
/*
* Start the DMA transfer
*/
- dma_command = 0x21; /*
- * IRQ enable, DMA start
- */
+ dma_command = 0x21; /* IRQ enable, DMA start */
if (patch.mode & WAVE_UNSIGNED)
- dma_command |= 0x80; /*
- * Invert MSB
- */
+ dma_command |= 0x80; /* Invert MSB */
if (patch.mode & WAVE_16_BITS)
- dma_command |= 0x40; /*
- * 16 bit _DATA_
- */
- if (sound_dsp_dmachan[gus_devnum] > 3)
- dma_command |= 0x04; /*
- * 16 bit DMA channel
- */
+ dma_command |= 0x40; /* 16 bit _DATA_ */
+ if (audio_devs[gus_devnum]->dmachan > 3)
+ dma_command |= 0x04; /* 16 bit DMA _channel_ */
- gus_write8 (0x41, dma_command); /*
- * Let's go luteet (=bugs)
- */
+ gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */
/*
* Sleep here until the DRAM DMA done interrupt is served
@@ -1984,8 +1701,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
printk ("GUS: DMA Transfer timed out\n");
RESTORE_INTR (flags);
}
-#endif /*
- * * * GUS_NO_DMA */
+#endif /* GUS_NO_DMA */
/*
* Now the next part
@@ -1995,9 +1711,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
src_offs += blk_size;
target += blk_size;
- gus_write8 (0x41, 0); /*
- * Stop DMA
- */
+ gus_write8 (0x41, 0); /* Stop DMA */
}
free_mem_ptr += patch.len;
@@ -2042,9 +1756,7 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_VOICEON:
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /*
- * Disable intr
- */
+ p1 &= ~0x20; /* Don't allow interrupts */
gus_voice_on (p1);
RESTORE_INTR (flags);
break;
@@ -2063,9 +1775,7 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_VOICEMODE:
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /*
- * Disable intr
- */
+ p1 &= ~0x20; /* Don't allow interrupts */
gus_voice_mode (p1);
RESTORE_INTR (flags);
break;
@@ -2091,18 +1801,14 @@ guswave_hw_control (int dev, unsigned char *event)
RESTORE_INTR (flags);
break;
- case _GUS_VOICEVOL2: /*
- * Just update the voice value
- */
+ case _GUS_VOICEVOL2: /* Just update the software voice level */
voices[voice].initial_volume =
voices[voice].current_volume = p1;
break;
case _GUS_RAMPRANGE:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /*
- * NO-NO
- */
+ break; /* NO-NO */
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_ramp_range (p1, p2);
@@ -2111,9 +1817,7 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_RAMPRATE:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /*
- * NO-NO
- */
+ break; /* NJET-NJET */
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_ramp_rate (p1, p2);
@@ -2122,37 +1826,27 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_RAMPMODE:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /*
- * NO-NO
- */
+ break; /* NO-NO */
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /*
- * Disable intr
- */
+ p1 &= ~0x20; /* Don't allow interrupts */
gus_ramp_mode (p1);
RESTORE_INTR (flags);
break;
case _GUS_RAMPON:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /*
- * NO-NO
- */
+ break; /* EI-EI */
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /*
- * Disable intr
- */
+ p1 &= ~0x20; /* Don't allow interrupts */
gus_rampon (p1);
RESTORE_INTR (flags);
break;
case _GUS_RAMPOFF:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /*
- * NO-NO
- */
+ break; /* NEJ-NEJ */
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_rampoff ();
@@ -2249,7 +1943,7 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return IOCTL_OUT (arg, gus_sampling_channels);
break;
- case SNDCTL_DSP_SAMPLESIZE:
+ case SNDCTL_DSP_SETFMT:
if (local)
return gus_sampling_set_bits (arg);
return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg)));
@@ -2260,9 +1954,7 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return gus_sampling_bits;
return IOCTL_OUT (arg, gus_sampling_bits);
- case SOUND_PCM_WRITE_FILTER: /*
- * NOT YET IMPLEMENTED
- */
+ case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */
return IOCTL_OUT (arg, RET_ERROR (EINVAL));
break;
@@ -2302,6 +1994,7 @@ gus_sampling_open (int dev, int mode)
gus_select_max_voices (14);
pcm_active = 0;
+ dma_active = 0;
pcm_opened = 1;
if (mode & OPEN_READ)
{
@@ -2361,24 +2054,18 @@ play_next_pcm_block (void)
for (chn = 0; chn < gus_sampling_channels; chn++)
{
mode[chn] = 0x00;
- ramp_mode[chn] = 0x03; /*
- * Ramping and rollover off
- */
+ ramp_mode[chn] = 0x03; /* Ramping and rollover off */
if (chn == 0)
{
- mode[chn] |= 0x20; /*
- * Loop irq
- */
+ mode[chn] |= 0x20; /* Loop IRQ */
voices[chn].loop_irq_mode = LMODE_PCM;
}
if (gus_sampling_bits != 8)
{
is16bits = 1;
- mode[chn] |= 0x04; /*
- * 16 bit data
- */
+ mode[chn] |= 0x04; /* 16 bit data */
}
else
is16bits = 0;
@@ -2386,23 +2073,15 @@ play_next_pcm_block (void)
dram_loc = this_one * pcm_bsize;
dram_loc += chn * pcm_banksize;
- if (this_one == (pcm_nblk - 1)) /*
- * Last of the DRAM buffers
- */
+ if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */
{
- mode[chn] |= 0x08; /*
- * Enable loop
- */
- ramp_mode[chn] = 0x03;/*
- * Disable rollover
- */
+ mode[chn] |= 0x08; /* Enable loop */
+ ramp_mode[chn] = 0x03;/* Disable rollover bit */
}
else
{
if (chn == 0)
- ramp_mode[chn] = 0x04; /*
- * Enable rollover bit
- */
+ ramp_mode[chn] = 0x04; /* Enable rollover bit */
}
DISABLE_INTR (flags);
@@ -2410,21 +2089,13 @@ play_next_pcm_block (void)
gus_voice_freq (speed);
if (gus_sampling_channels == 1)
- gus_voice_balance (7); /*
- * mono
- */
+ gus_voice_balance (7); /* mono */
else if (chn == 0)
- gus_voice_balance (0); /*
- * left
- */
+ gus_voice_balance (0); /* left */
else
- gus_voice_balance (15); /*
- * right
- */
+ gus_voice_balance (15); /* right */
- if (!pcm_active) /*
- * Voice not started yet
- */
+ if (!pcm_active) /* Playback not already active */
{
/*
* The playback was not started yet (or there has been a pause).
@@ -2433,67 +2104,42 @@ play_next_pcm_block (void)
* the normal loop with irq.
*/
- gus_voice_off (); /*
- * It could already be running
- */
+ gus_voice_off ();
gus_rampoff ();
gus_voice_volume (1530 + (25 * gus_pcm_volume));
gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
- gus_write_addr (0x0a, dram_loc, is16bits); /*
- * Starting position
- */
- gus_write_addr (0x02, chn * pcm_banksize, is16bits); /*
- * Loop start
- * location
- */
+ gus_write_addr (0x0a, dram_loc, is16bits); /* Starting position */
+ gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* Loop start */
if (chn != 0)
gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk),
- is16bits); /*
- * Loop end location
- */
+ is16bits); /* Loop end location */
}
if (chn == 0)
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /*
- * Loop
- * end
- * location
- */
+ gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],
+ is16bits); /* Loop end location */
else
- mode[chn] |= 0x08; /*
- * Enable loop
- */
+ mode[chn] |= 0x08; /* Enable looping */
if (pcm_datasize[this_one] != pcm_bsize)
{
/*
- * Incomplete block. Possibly the last one.
+ * Incompletely filled block. Possibly the last one.
*/
if (chn == 0)
{
- mode[chn] &= ~0x08; /*
- * Disable loop
- */
- mode[chn] |= 0x20;/*
- * Enable loop IRQ
- */
+ mode[chn] &= ~0x08; /* Disable looping */
+ mode[chn] |= 0x20;/* Enable IRQ at the end */
voices[0].loop_irq_mode = LMODE_PCM_STOP;
- ramp_mode[chn] = 0x03; /*
- * No rollover bit
- */
+ ramp_mode[chn] = 0x03; /* No rollover bit */
}
else
{
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /*
- * Loop
- * end
- * location
- */
- mode[chn] &= ~0x08; /*
- * Disable loop
- */
+ gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],
+ is16bits); /* Loop end location */
+ mode[chn] &= ~0x08; /* Disable looping */
}
}
@@ -2547,15 +2193,13 @@ gus_transfer_output_block (int dev, unsigned long buf,
else
this_one = pcm_current_block;
- gus_write8 (0x41, 0); /*
- * Disable GF1 DMA
- */
+ gus_write8 (0x41, 0); /* Disable GF1 DMA */
DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE);
address = this_one * pcm_bsize;
address += chn * pcm_banksize;
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
{
hold_address = address;
address = address >> 1;
@@ -2563,49 +2207,40 @@ gus_transfer_output_block (int dev, unsigned long buf,
address |= (hold_address & 0x000c0000L);
}
- gus_write16 (0x42, (address >> 4) & 0xffff); /*
- * DRAM DMA address
- */
+ gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
- dma_command = 0x21; /*
- * IRQ enable, DMA start
- */
+ dma_command = 0x21; /* IRQ enable, DMA start */
if (gus_sampling_bits != 8)
- dma_command |= 0x40; /*
- * 16 bit _DATA_
- */
+ dma_command |= 0x40; /* 16 bit _DATA_ */
else
- dma_command |= 0x80; /*
- * Invert MSB
- */
+ dma_command |= 0x80; /* Invert MSB */
- if (sound_dsp_dmachan[dev] > 3)
- dma_command |= 0x04; /*
- * 16 bit DMA channel
- */
+ if (audio_devs[dev]->dmachan > 3)
+ dma_command |= 0x04; /* 16 bit DMA channel */
- gus_write8 (0x41, dma_command); /*
- * Kick on
- */
+ gus_write8 (0x41, dma_command); /* Kickstart */
- if (chn == (gus_sampling_channels - 1)) /*
- * Last channel
- */
+ if (chn == (gus_sampling_channels - 1)) /* Last channel */
{
/*
* Last (right or mono) channel data
*/
+ dma_active = 1; /* DMA started. There is a unacknowledged buffer */
active_device = GUS_DEV_PCM_DONE;
- if (!pcm_active && (pcm_qlen > 2 || count < pcm_bsize))
+ if (!pcm_active && (pcm_qlen > 0 || count < pcm_bsize))
{
play_next_pcm_block ();
}
}
- else /*
- * * * Left channel data. The right channel
- * is * * * transferred after DMA interrupt */
- active_device = GUS_DEV_PCM_CONTINUE;
+ else
+ {
+ /*
+ * Left channel data. The right channel
+ * is transferred after DMA interrupt
+ */
+ active_device = GUS_DEV_PCM_CONTINUE;
+ }
RESTORE_INTR (flags);
}
@@ -2632,21 +2267,13 @@ gus_sampling_start_input (int dev, unsigned long buf, int count,
DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
- mode = 0xa0; /*
- * DMA IRQ enable, invert MSB
- */
+ mode = 0xa0; /* DMA IRQ enabled, invert MSB */
- if (sound_dsp_dmachan[dev] > 3)
- mode |= 0x04; /*
- * 16 bit DMA channel
- */
+ if (audio_devs[dev]->dmachan > 3)
+ mode |= 0x04; /* 16 bit DMA channel */
if (gus_sampling_channels > 1)
- mode |= 0x02; /*
- * Stereo
- */
- mode |= 0x01; /*
- * DMA enable
- */
+ mode |= 0x02; /* Stereo */
+ mode |= 0x01; /* DMA enable */
gus_write8 (0x49, mode);
@@ -2660,9 +2287,7 @@ gus_sampling_prepare_for_input (int dev, int bsize, int bcount)
rate = (9878400 / (gus_sampling_speed + 2)) / 16;
- gus_write8 (0x48, rate & 0xff); /*
- * Set sampling frequency
- */
+ gus_write8 (0x48, rate & 0xff); /* Set sampling rate */
if (gus_sampling_bits != 8)
{
@@ -2705,9 +2330,9 @@ gus_sampling_prepare_for_output (int dev, int bsize, int bcount)
}
static int
-gus_has_output_drained (int dev)
+gus_local_qlen (int dev)
{
- return !pcm_qlen;
+ return pcm_qlen;
}
static void
@@ -2765,6 +2390,8 @@ static struct audio_operations gus_sampling_operations =
{
"Gravis UltraSound",
NEEDS_RESTART,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
gus_sampling_open,
gus_sampling_close,
gus_sampling_output_block,
@@ -2774,11 +2401,10 @@ static struct audio_operations gus_sampling_operations =
gus_sampling_prepare_for_output,
gus_sampling_reset,
gus_sampling_reset,
- gus_has_output_drained,
+ gus_local_qlen,
gus_copy_from_user
};
-#ifdef FUTURE_VERSION
static void
guswave_bender (int dev, int voice, int value)
{
@@ -2786,7 +2412,8 @@ guswave_bender (int dev, int voice, int value)
unsigned long flags;
voices[voice].bender = value - 8192;
- freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
+ freq = compute_finetune (voices[voice].orig_freq, value,
+ voices[voice].bender_range);
voices[voice].current_freq = freq;
DISABLE_INTR (flags);
@@ -2795,8 +2422,6 @@ guswave_bender (int dev, int voice, int value)
RESTORE_INTR (flags);
}
-#endif
-
static int
guswave_patchmgr (int dev, struct patmgr_info *rec)
{
@@ -2826,9 +2451,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
while (ptr >= 0 && ptr < free_sample)
{
rec->data.data8[i]++;
- ptr = samples[ptr].key; /*
- * Follow link
- */
+ ptr = samples[ptr].key; /* Follow link */
}
}
return 0;
@@ -2843,9 +2466,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
while (ptr >= 0 && ptr < free_sample)
{
rec->data.data32[n++] = ptr;
- ptr = samples[ptr].key; /*
- * Follow link
- */
+ ptr = samples[ptr].key; /* Follow link */
}
}
rec->parm1 = n;
@@ -2865,12 +2486,8 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
pat = (struct patch_info *) rec->data.data8;
- pat->key = GUS_PATCH; /*
- * Restore patch type
- */
- rec->parm1 = sample_ptrs[ptr]; /*
- * DRAM address
- */
+ pat->key = GUS_PATCH; /* Restore patch type */
+ rec->parm1 = sample_ptrs[ptr]; /* DRAM location */
rec->parm2 = sizeof (struct patch_info);
}
return 0;
@@ -2886,14 +2503,10 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
pat = (struct patch_info *) rec->data.data8;
- if (pat->len > samples[ptr].len) /*
- * Cannot expand sample
- */
+ if (pat->len > samples[ptr].len) /* Cannot expand sample */
return RET_ERROR (EINVAL);
- pat->key = samples[ptr].key; /*
- * Ensure the link is correct
- */
+ pat->key = samples[ptr].key; /* Ensure the link is correct */
memcpy ((char *) &samples[ptr], rec->data.data8,
sizeof (struct patch_info));
@@ -2903,9 +2516,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return 0;
break;
- case PM_READ_PATCH: /*
- * Returns a block of wave data from the DRAM
- */
+ case PM_READ_PATCH: /* Returns a block of wave data from the DRAM */
{
int sample = rec->parm1;
int n;
@@ -2916,13 +2527,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return RET_ERROR (EINVAL);
if (offs < 0 || offs >= samples[sample].len)
- return RET_ERROR (EINVAL); /*
- * Invalid offset
- */
+ return RET_ERROR (EINVAL); /* Invalid offset */
- n = samples[sample].len - offs; /*
- * Nr of bytes left
- */
+ n = samples[sample].len - offs; /* Num of bytes left */
if (l > n)
l = n;
@@ -2998,12 +2605,49 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
}
}
+static int
+guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc)
+{
+ int i, p;
+
+ p = alloc->ptr;
+ /*
+ * First look for a completely stopped voice
+ */
+
+ for (i = 0; i < alloc->max_voice; i++)
+ {
+ if (alloc->map[p] == 0)
+ {
+ alloc->ptr = p;
+ return p;
+ }
+ p = (p + 1) % alloc->max_voice;
+ }
+
+ /*
+ * Then look for a releasing voice
+ */
+
+ for (i = 0; i < alloc->max_voice; i++)
+ {
+ if (alloc->map[p] == 0xffff)
+ {
+ alloc->ptr = p;
+ return p;
+ }
+ p = (p + 1) % alloc->max_voice;
+ }
+ printk ("GUS: Out of free voices\n");
+
+ alloc->ptr = p;
+ return p;
+}
+
static struct synth_operations guswave_operations =
{
&gus_info,
-#ifdef FUTURE_VERSION
0,
-#endif
SYNTH_TYPE_SAMPLE,
SAMPLE_TYPE_GUS,
guswave_open,
@@ -3020,9 +2664,8 @@ static struct synth_operations guswave_operations =
guswave_panning,
guswave_volume_method,
guswave_patchmgr,
-#ifdef FUTURE_VERSION
- guswave_bender
-#endif
+ guswave_bender,
+ guswave_alloc
};
static void
@@ -3130,10 +2773,7 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
if (active_device == GUS_DEV_WAVE)
for (voice = 0; voice < nr_voices; voice++)
- dynamic_volume_change (voice); /*
- * Apply the new
- * volume
- */
+ dynamic_volume_change (voice); /* Apply the new vol */
return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
}
@@ -3229,7 +2869,7 @@ gus_wave_init (long mem_start, int irq, int dma)
val = INB (gus_base + 0x0f);
RESTORE_INTR (flags);
- if (val != 0xff && (val & 0x06)) /* Should be 0x02? */
+ if (val != 0xff && (val & 0x06)) /* Should be 0x02?? */
{
/*
* It has the digital ASIC so the card is at least v3.4.
@@ -3263,6 +2903,31 @@ gus_wave_init (long mem_start, int irq, int dma)
model_num = "MAX";
gus_type = 0x40;
mixer_type = CS4231;
+#ifndef EXCLUDE_GUSMAX
+ {
+ unsigned char max_config = 0x40; /* Codec enable */
+
+ if (dma > 3)
+ max_config |= 0x30; /* 16 bit playback and capture DMAs */
+
+ max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
+
+ OUTB (max_config, gus_base + 0x106); /* UltraMax control */
+ }
+
+ if (ad1848_detect (gus_base + 0x10c))
+ {
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+ have_gus_max = 1;
+ ad1848_init ("GUS MAX", gus_base + 0x10c,
+ -irq,
+ dma,
+ dma);
+ }
+ else
+ printk ("[Where's the CS4231?]");
+#endif
}
}
else
@@ -3278,9 +2943,9 @@ gus_wave_init (long mem_start, int irq, int dma)
#ifdef __FreeBSD__
printk ("snd4: <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024);
-#else
+#else /* __FreeBSD__ */
printk (" <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024);
-#endif
+#endif /* __FreeBSD__ */
#ifndef SCO
sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
@@ -3304,7 +2969,10 @@ gus_wave_init (long mem_start, int irq, int dma)
if (num_synths >= MAX_SYNTH_DEV)
printk ("GUS Error: Too many synthesizers\n");
else
- synth_devs[num_synths++] = &guswave_operations;
+ {
+ voice_alloc = &guswave_operations.alloc;
+ synth_devs[num_synths++] = &guswave_operations;
+ }
PERMANENT_MALLOC (struct patch_info *, samples,
(MAX_SAMPLE + 1) * sizeof (*samples), mem_start);
@@ -3313,13 +2981,17 @@ gus_wave_init (long mem_start, int irq, int dma)
gus_initialize ();
- if (num_dspdevs < MAX_DSP_DEV)
+ if (num_audiodevs < MAX_AUDIO_DEV)
{
- dsp_devs[gus_devnum = num_dspdevs++] = &gus_sampling_operations;
- sound_dsp_dmachan[gus_devnum] = dma;
- sound_buffcounts[gus_devnum] = DSP_BUFFCOUNT;
- sound_buffsizes[gus_devnum] = DSP_BUFFSIZE;
- sound_dma_automode[gus_devnum] = 0;
+ audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations;
+ audio_devs[gus_devnum]->dmachan = dma;
+#ifndef NO_AUTODMA
+ audio_devs[gus_devnum]->buffcount = 1;
+#else
+ audio_devs[gus_devnum]->flags &= ~DMA_AUTOMODE;
+ audio_devs[gus_devnum]->buffcount = DSP_BUFFCOUNT;
+#endif
+ audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
}
else
printk ("GUS: Too many PCM devices available\n");
@@ -3331,11 +3003,12 @@ gus_wave_init (long mem_start, int irq, int dma)
switch (mixer_type)
{
case ICS2101:
- gus_line_vol=gus_mic_vol=gus_wave_volume = gus_pcm_volume = 100;
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
return ics2101_mixer_init (mem_start);
case CS4231:
- /* Available soon */
+ /* Initialized elsewhere (ad1848.c) */
default:
return gus_default_mixer_init (mem_start);
}
@@ -3370,7 +3043,7 @@ do_loop_irq (int voice)
* Final loop finished, shoot volume down
*/
- if ((gus_read16 (0x09) >> 4) < 100) /*
+ if ((int) (gus_read16 (0x09) >> 4) < 100) /*
* Get current volume
*/
{
@@ -3390,12 +3063,11 @@ do_loop_irq (int voice)
break;
case LMODE_PCM_STOP:
- pcm_active = 0; /*
- * Requires extensive processing
- */
+ pcm_active = 0; /* Signal to the play_next_pcm_block routine */
case LMODE_PCM:
{
int orig_qlen = pcm_qlen;
+ int flag; /* 0 or 2 */
pcm_qlen--;
pcm_head = (pcm_head + 1) % pcm_nblk;
@@ -3404,18 +3076,27 @@ do_loop_irq (int voice)
play_next_pcm_block ();
}
else
- { /*
- * Out of data. Just stop the voice
- */
+ { /* Underrun. Just stop the voice */
gus_voice_off ();
gus_rampoff ();
pcm_active = 0;
}
- if (orig_qlen == pcm_nblk)
+ /*
+ * If the queue was full before this interrupt, the DMA transfer was
+ * suspended. Let it continue now.
+ */
+ if (dma_active)
{
- DMAbuf_outputintr (gus_devnum, 0);
+ if (pcm_qlen == 0)
+ flag = 1; /* Underflow */
+ else
+ flag = 0;
+ dma_active = 0;
}
+ else
+ flag = 2; /* Just notify the dmabuf.c */
+ DMAbuf_outputintr (gus_devnum, flag);
}
break;
@@ -3465,7 +3146,9 @@ do_volume_irq (int voice)
guswave_start_note2 (voices[voice].dev_pending, voice,
voices[voice].note_pending, voices[voice].volume_pending);
if (voices[voice].kill_pending)
- guswave_kill_note (voices[voice].dev_pending, voice, 0);
+ guswave_kill_note (voices[voice].dev_pending, voice,
+ voices[voice].note_pending, 0);
+
if (voices[voice].sample_pending >= 0)
{
guswave_set_instr (voices[voice].dev_pending, voice,
@@ -3504,7 +3187,7 @@ gus_voice_irq (void)
if (!(src & 0x80)) /*
* Wave IRQ pending
*/
- if (!(wave_ignore & voice_bit) && voice < nr_voices) /*
+ if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /*
* Not done
* yet
*/
@@ -3516,7 +3199,7 @@ gus_voice_irq (void)
if (!(src & 0x40)) /*
* Volume IRQ pending
*/
- if (!(volume_ignore & voice_bit) && voice < nr_voices) /*
+ if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /*
* Not done
* yet
*/
@@ -3532,12 +3215,8 @@ guswave_dma_irq (void)
{
unsigned char status;
- status = gus_look8 (0x41); /*
- * Get DMA IRQ Status
- */
- if (status & 0x40) /*
- * DMA Irq pending
- */
+ status = gus_look8 (0x41); /* Get DMA IRQ Status */
+ if (status & 0x40) /* DMA interrupt pending */
switch (active_device)
{
case GUS_DEV_WAVE:
@@ -3545,16 +3224,21 @@ guswave_dma_irq (void)
WAKE_UP (dram_sleeper, dram_sleep_flag);
break;
- case GUS_DEV_PCM_CONTINUE:
+ case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */
gus_transfer_output_block (pcm_current_dev, pcm_current_buf,
pcm_current_count,
pcm_current_intrflag, 1);
break;
- case GUS_DEV_PCM_DONE:
+ case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */
if (pcm_qlen < pcm_nblk)
{
- DMAbuf_outputintr (gus_devnum, pcm_qlen == 0);
+ int flag = (1 - dma_active) * 2; /* 0 or 2 */
+
+ if (pcm_qlen == 0)
+ flag = 1; /* Underrun */
+ dma_active = 0;
+ DMAbuf_outputintr (gus_devnum, flag);
}
break;
diff --git a/sys/i386/isa/sound/ics2101.c b/sys/i386/isa/sound/ics2101.c
index c06fec0..899c94e 100644
--- a/sys/i386/isa/sound/ics2101.c
+++ b/sys/i386/isa/sound/ics2101.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: ics2101.c,v 1.3 1994/08/02 07:40:05 davidg Exp $
*/
#include "sound_config.h"
@@ -49,34 +49,36 @@ static int left_fix[ICS_MIXDEVS] =
static int right_fix[ICS_MIXDEVS] =
{2, 2, 2, 1, 2, 1};
-static int
-scale_vol(int vol)
+static int
+scale_vol (int vol)
{
#if 1
-/*
+ /*
* Experimental volume scaling by Risto Kankkunen.
* This should give smoother volume response than just
* a plain multiplication.
*/
- int e;
-
- if (vol < 0)
- vol = 0;
- if (vol > 100)
- vol = 100;
- vol = (31 * vol + 50) / 100;
- e = 0;
- if (vol) {
- while (vol < 16) {
- vol <<= 1;
- e--;
- }
- vol -= 16;
- e += 7;
- }
- return ((e << 4) + vol);
+ int e;
+
+ if (vol < 0)
+ vol = 0;
+ if (vol > 100)
+ vol = 100;
+ vol = (31 * vol + 50) / 100;
+ e = 0;
+ if (vol)
+ {
+ while (vol < 16)
+ {
+ vol <<= 1;
+ e--;
+ }
+ vol -= 16;
+ e += 7;
+ }
+ return ((e << 4) + vol);
#else
- return ((vol*127)+50)/100;
+ return ((vol * 127) + 50) / 100;
#endif
}
@@ -88,7 +90,7 @@ write_mix (int dev, int chn, int vol)
int ctrl_addr = dev << 3;
int attn_addr = dev << 3;
- vol=scale_vol(vol);
+ vol = scale_vol (vol);
if (chn == CHN_LEFT)
{
@@ -185,7 +187,7 @@ ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
case SOUND_MIXER_STEREODEVS:
return IOCTL_OUT (arg, SOUND_MASK_LINE | SOUND_MASK_CD |
- SOUND_MASK_SYNTH | SOUND_MASK_VOLUME|
+ SOUND_MASK_SYNTH | SOUND_MASK_VOLUME |
SOUND_MASK_MIC);
break;
diff --git a/sys/i386/isa/sound/local.h b/sys/i386/isa/sound/local.h
index 3be3b58..72e0d6b 100644
--- a/sys/i386/isa/sound/local.h
+++ b/sys/i386/isa/sound/local.h
@@ -1,6 +1,6 @@
/* for FreeBSD */
/*
- * $Id: local.h,v 1.8 1994/08/02 07:40:06 davidg Exp $
+ * $Id: local.h,v 1.9 1994/09/27 17:58:19 davidg Exp $
*/
#include "snd.h"
@@ -13,11 +13,18 @@
#define KERNEL_SOUNDCARD
#endif
+#ifndef EXCLUDE_UART6850
+#define EXCLUDE_UART6850
+#endif
+#ifndef EXCLUDE_PSS
+#define EXCLUDE_PSS
+#endif
+
#define DSP_BUFFSIZE 65536
#define NO_AUTODMA /* still */
#define SELECTED_SOUND_OPTIONS 0xffffffff
-#define SOUND_VERSION_STRING "2.5"
-#define SOUND_CONFIG_DATE "Sat Apr 23 07:45:17 MSD 1994"
-#define SOUND_CONFIG_BY "ache"
-#define SOUND_CONFIG_HOST "dream.demos.su"
+#define SOUND_VERSION_STRING "2.90-2"
+#define SOUND_CONFIG_DATE "Thu Sep 29 15:33:39 PDT 1994"
+#define SOUND_CONFIG_BY "swallace"
+#define SOUND_CONFIG_HOST "pal-r32-a07b.slip.nts.uci.edu"
#define SOUND_CONFIG_DOMAIN ""
diff --git a/sys/i386/isa/sound/midi_ctrl.h b/sys/i386/isa/sound/midi_ctrl.h
index 616b591..c7fdd0b 100644
--- a/sys/i386/isa/sound/midi_ctrl.h
+++ b/sys/i386/isa/sound/midi_ctrl.h
@@ -1,3 +1,6 @@
+/*
+ * $Id: midi_ctrl.c,v 1.7 1994/09/27 17:58:24 davidg Exp $
+ */
static unsigned char ctrl_def_values[128] =
{
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 0 to 7 */
diff --git a/sys/i386/isa/sound/midi_synth.c b/sys/i386/isa/sound/midi_synth.c
index fd6d8bd..98f2672 100644
--- a/sys/i386/isa/sound/midi_synth.c
+++ b/sys/i386/isa/sound/midi_synth.c
@@ -25,6 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $Id: $
*/
#include "sound_config.h"
diff --git a/sys/i386/isa/sound/midi_synth.h b/sys/i386/isa/sound/midi_synth.h
index 04075e2..e22bd5e 100644
--- a/sys/i386/isa/sound/midi_synth.h
+++ b/sys/i386/isa/sound/midi_synth.h
@@ -1,3 +1,6 @@
+/*
+ * $Id: $
+ */
int midi_synth_ioctl (int dev,
unsigned int cmd, unsigned int arg);
int midi_synth_kill_note (int dev, int channel, int note, int velocity);
diff --git a/sys/i386/isa/sound/midibuf.c b/sys/i386/isa/sound/midibuf.c
index 399fdfd..74067b6 100644
--- a/sys/i386/isa/sound/midibuf.c
+++ b/sys/i386/isa/sound/midibuf.c
@@ -1,9 +1,7 @@
/*
* sound/midibuf.c
*
- * Device file manager for /dev/midi
- *
- * NOTE! This part of the driver is currently just a stub.
+ * Device file manager for /dev/midi#
*
* Copyright by Hannu Savolainen 1993
*
@@ -27,94 +25,416 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: midibuf.c,v 1.5 1994/08/02 07:40:10 davidg Exp $
*/
#include "sound_config.h"
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MPU401)
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
-#if 0
-#include "midiioctl.h"
-#include "midivar.h"
-#endif
+/*
+ * Don't make MAX_QUEUE_SIZE larger than 4000
+ */
+
+#define MAX_QUEUE_SIZE 4000
+
+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};
+static struct midi_parms parms[MAX_MIDI_DEV];
+
+static void midi_poll (unsigned long 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)
-static int midibuf_busy = 0;
+#define QUEUE_BYTE(q, data) \
+ if (SPACE_AVAIL(q)) \
+ { \
+ unsigned long flags; \
+ DISABLE_INTR(flags); \
+ q->queue[q->tail] = (data); \
+ q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
+ RESTORE_INTR(flags); \
+ }
+
+#define REMOVE_BYTE(q, data) \
+ if (DATA_AVAIL(q)) \
+ { \
+ unsigned long flags; \
+ DISABLE_INTR(flags); \
+ data = q->queue[q->head]; \
+ q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
+ RESTORE_INTR(flags); \
+ }
+
+void
+drain_midi_queue (int dev)
+{
+
+ /*
+ * Give the Midi driver time to drain its output queues
+ */
+
+ 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)
+{
+ 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]);
+ }
+
+}
+
+static void
+midi_output_intr (int dev)
+{
+ /*
+ * Currently NOP
+ */
+}
+
+static void
+midi_poll (unsigned long 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);
+}
int
MIDIbuf_open (int dev, struct fileinfo *file)
{
int mode, err;
+ unsigned long flags;
dev = dev >> 4;
mode = file->mode & O_ACCMODE;
- if (midibuf_busy)
- return RET_ERROR (EBUSY);
+ if (num_midis > MAX_MIDI_DEV)
+ {
+ printk ("Sound: FATAL ERROR: Too many midi interfaces\n");
+ num_midis = MAX_MIDI_DEV;
+ }
- if (!mpu401_dev)
+ if (dev < 0 || dev >= num_midis)
{
- printk ("Midi: MPU-401 compatible Midi interface not present\n");
+ printk ("Sound: Nonexistent MIDI interface %d\n", dev);
return RET_ERROR (ENXIO);
}
- if ((err = midi_devs[mpu401_dev]->open (mpu401_dev, mode, NULL, NULL)) < 0)
- return err;
+ /*
+ * 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));
- midibuf_busy = 1;
+ 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 RET_ERROR (ENXIO);
+ return err;
}
void
MIDIbuf_release (int dev, struct fileinfo *file)
{
int mode;
+ unsigned long flags;
dev = dev >> 4;
mode = file->mode & O_ACCMODE;
- midi_devs[mpu401_dev]->close (mpu401_dev);
- midibuf_busy = 0;
+ DISABLE_INTR (flags);
+
+ /*
+ * 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);
}
int
MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
+ unsigned long flags;
+ int c, n, i;
+ unsigned char tmp_data;
dev = dev >> 4;
- return count;
+ if (!count)
+ return 0;
+
+ DISABLE_INTR (flags);
+
+ c = 0;
+
+ 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 > (count - c))
+ n = count - c;
+
+ for (i = 0; i < n; i++)
+ {
+ COPY_FROM_USER (&tmp_data, buf, c, 1);
+ QUEUE_BYTE (midi_out_buf[dev], tmp_data);
+ c++;
+ }
+ }
+
+ RESTORE_INTR (flags);
+
+ return c;
}
int
MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
+ int n, c = 0;
+ unsigned long flags;
+ unsigned char tmp_data;
+
dev = dev >> 4;
- return RET_ERROR (EIO);
+ 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++;
+ }
+ }
+
+ RESTORE_INTR (flags);
+
+ return c;
}
int
MIDIbuf_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg)
{
+ int val;
+
dev = dev >> 4;
switch (cmd)
{
+ case SNDCTL_MIDI_PRETIME:
+ val = IOCTL_IN (arg);
+ if (val < 0)
+ val = 0;
+
+ val = (HZ * val) / 10;
+ parms[dev].prech_timeout = val;
+ return IOCTL_OUT (arg, val);
+ break;
+
default:
- return midi_devs[0]->ioctl (dev, cmd, arg);
+ return midi_devs[dev]->ioctl (dev, cmd, arg);
}
}
-void
-MIDIbuf_bytes_received (int dev, unsigned char *buf, int count)
+#ifdef ALLOW_SELECT
+int
+MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
{
+ dev = dev >> 4;
+
+ 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;
+
+ 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;
+
+ case SEL_EX:
+ return 0;
+ }
+
+ return 0;
}
+#endif /* ALLOW_SELECT */
+
long
MIDIbuf_init (long mem_start)
{
diff --git a/sys/i386/isa/sound/mpu401.c b/sys/i386/isa/sound/mpu401.c
index 0b1685d..3728de5 100644
--- a/sys/i386/isa/sound/mpu401.c
+++ b/sys/i386/isa/sound/mpu401.c
@@ -3,8 +3,6 @@
*
* The low level driver for Roland MPU-401 compatible Midi cards.
*
- * This version supports just the DUMB UART mode.
- *
* Copyright by Hannu Savolainen 1993
*
* Redistribution and use in source and binary forms, with or without
@@ -27,51 +25,489 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: mpu401.c,v 1.8 1994/08/02 07:40:12 davidg Exp $
*/
+#define USE_SEQ_MACROS
+#define USE_SIMPLE_MACROS
+
#include "sound_config.h"
#ifdef CONFIGURE_SOUNDCARD
#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
-#define DATAPORT (mpu401_base)/* MPU-401 Data I/O Port on IBM */
-#define COMDPORT (mpu401_base+1) /* MPU-401 Command Port on IBM */
-#define STATPORT (mpu401_base+1) /* MPU-401 Status Port on IBM */
+static int init_sequence[20]; /* NOTE! pos 0 = len, start pos 1. */
+static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL;
+
+struct mpu_config
+ {
+ int base; /*
+ * I/O base
+ */
+ int irq;
+ int opened; /*
+ * Open mode
+ */
+ int devno;
+ int synthno;
+ int uart_mode;
+ int initialized;
+ int mode;
+#define MODE_MIDI 1
+#define MODE_SYNTH 2
+ unsigned char version, revision;
+ unsigned int capabilities;
+#define MPU_CAP_INTLG 0x10000000
+#define MPU_CAP_SYNC 0x00000010
+#define MPU_CAP_FSK 0x00000020
+#define MPU_CAP_CLS 0x00000040
+#define MPU_CAP_SMPTE 0x00000080
+#define MPU_CAP_2PORT 0x00000001
+ int timer_flag;
+
+#define MBUF_MAX 10
+#define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \
+ {printk("MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;}
+ int m_busy;
+ unsigned char m_buf[MBUF_MAX];
+ int m_ptr;
+ int m_state;
+ int m_left;
+ unsigned char last_status;
+ void (*inputintr) (int dev, unsigned char data);
+ unsigned short controls[32];
+ };
+
+#define DATAPORT(base) (base)
+#define COMDPORT(base) (base+1)
+#define STATPORT(base) (base+1)
+
+#define mpu401_status(base) INB(STATPORT(base))
+#define input_avail(base) (!(mpu401_status(base)&INPUT_AVAIL))
+#define output_ready(base) (!(mpu401_status(base)&OUTPUT_READY))
+#define write_command(base, cmd) OUTB(cmd, COMDPORT(base))
+#define read_data(base) INB(DATAPORT(base))
+
+#define write_data(base, byte) OUTB(byte, DATAPORT(base))
+
+#define OUTPUT_READY 0x40
+#define INPUT_AVAIL 0x80
+#define MPU_ACK 0xF7
+#define MPU_RESET 0xFF
+#define UART_MODE_ON 0x3F
+
+static struct mpu_config dev_conf[MAX_MIDI_DEV] =
+{
+ {0}};
+
+static int n_mpu_devs = 0;
+static int irq2dev[16];
+
+static int reset_mpu401 (struct mpu_config *devc);
+static void set_uart_mode (int dev, struct mpu_config *devc, int arg);
+static void mpu_timer_init (int midi_dev);
+static void mpu_timer_interrupt (void);
+static void timer_ext_event (struct mpu_config *devc, int event, int parm);
+
+static struct synth_info mpu_synth_info_proto =
+{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, SYNTH_CAP_INPUT};
+
+static struct synth_info mpu_synth_info[MAX_MIDI_DEV];
+
+/*
+ * States for the input scanner
+ */
+
+#define ST_INIT 0 /* Ready for timing byte or msg */
+#define ST_TIMED 1 /* Leading timing byte rcvd */
+#define ST_DATABYTE 2 /* Waiting for (nr_left) data bytes */
+
+#define ST_SYSMSG 100 /* System message (sysx etc). */
+#define ST_SYSEX 101 /* System exclusive msg */
+#define ST_MTC 102 /* Midi Time Code (MTC) qframe msg */
+#define ST_SONGSEL 103 /* Song select */
+#define ST_SONGPOS 104 /* Song position pointer */
+
+static unsigned char len_tab[] =/* # of data bytes following a status
+ */
+{
+ 2, /* 8x */
+ 2, /* 9x */
+ 2, /* Ax */
+ 2, /* Bx */
+ 1, /* Cx */
+ 1, /* Dx */
+ 2, /* Ex */
+ 0 /* Fx */
+};
+
+#define STORE(cmd) \
+if (devc->opened & OPEN_READ) \
+{ \
+ int len; \
+ unsigned char obuf[8]; \
+ cmd; \
+ seq_input_event(obuf, len); \
+}
+#define _seqbuf obuf
+#define _seqbufptr 0
+#define _SEQ_ADVBUF(x) len=x
+
+static void
+do_midi_msg (struct mpu_config *devc, unsigned char *msg, int mlen)
+{
+ switch (msg[0] & 0xf0)
+ {
+ case 0x90:
+ if (msg[2] != 0)
+ {
+ STORE (SEQ_START_NOTE (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+ }
+ msg[2] = 64;
+
+ case 0x80:
+ STORE (SEQ_STOP_NOTE (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+
+ case 0xA0:
+ STORE (SEQ_KEY_PRESSURE (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+
+ case 0xB0:
+ /*
+ * Fix the controller value (combine MSB and LSB)
+ */
+ if (msg[1] < 64)
+ {
+ int ctrl = msg[1];
+
+ if (ctrl < 32)
+ {
+ devc->controls[ctrl] = (msg[2] & 0x7f) << 7;
+ }
+ else
+ {
+ ctrl -= 32;
+ devc->controls[ctrl] =
+ (devc->controls[ctrl] & ~0x7f) | (msg[2] & 0x7f);
+ }
+ STORE (SEQ_CONTROL (devc->synthno, msg[0] & 0x0f,
+ msg[1], devc->controls[ctrl]));
+ }
+ else
+ STORE (SEQ_CONTROL (devc->synthno, msg[0] & 0x0f, msg[1], msg[2]));
+ break;
+
+ case 0xC0:
+ STORE (SEQ_SET_PATCH (devc->synthno, msg[0] & 0x0f, msg[1]));
+ break;
+
+ case 0xD0:
+ STORE (SEQ_CHN_PRESSURE (devc->synthno, msg[0] & 0x0f, msg[1]));
+ break;
+
+ case 0xE0:
+ STORE (SEQ_BENDER (devc->synthno, msg[0] & 0x0f,
+ (msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7)));
+ break;
+
+ default:
+ printk ("MPU: Unknown midi channel message %02x\n", msg[0]);
+ }
+}
+
+static int
+mpu_input_scanner (struct mpu_config *devc, unsigned char midic)
+{
+ switch (devc->m_state)
+ {
+ case ST_INIT:
+ switch (midic)
+ {
+ case 0xf8:
+ /* Timer overflow */
+ break;
+
+ case 0xfc:
+ printk ("<all end>");
+ break;
+
+ case 0xfd:
+ if (devc->timer_flag)
+ mpu_timer_interrupt ();
+ break;
+
+ case 0xfe:
+ return MPU_ACK;
+ break;
+
+ case 0xf0:
+ case 0xf1:
+ case 0xf2:
+ case 0xf3:
+ case 0xf4:
+ case 0xf5:
+ case 0xf6:
+ case 0xf7:
+ printk ("<Trk data rq #%d>", midic & 0x0f);
+ break;
+
+ case 0xf9:
+ printk ("<conductor rq>");
+ break;
+
+ case 0xff:
+ devc->m_state = ST_SYSMSG;
+ break;
+
+ default:
+ if (midic <= 0xef)
+ {
+ /* printk("mpu time: %d ", midic); */
+ devc->m_state = ST_TIMED;
+ }
+ else
+ printk ("<MPU: Unknown event %02x> ", midic);
+ }
+ break;
+
+ case ST_TIMED:
+ {
+ int msg = (midic & 0xf0) >> 4;
+
+ devc->m_state = ST_DATABYTE;
+ if (msg < 8) /* Data byte */
+ {
+ /* printk("midi msg (running status) "); */
+ msg = (devc->last_status & 0xf0) >> 4;
+ msg -= 8;
+ devc->m_left = len_tab[msg] - 1;
+
+ devc->m_ptr = 2;
+ devc->m_buf[0] = devc->last_status;
+ devc->m_buf[1] = midic;
+
+ if (devc->m_left <= 0)
+ {
+ devc->m_state = ST_INIT;
+ do_midi_msg (devc, devc->m_buf, devc->m_ptr);
+ devc->m_ptr = 0;
+ }
+ }
+ else if (msg == 0xf) /* MPU MARK */
+ {
+ devc->m_state = ST_INIT;
+
+ switch (midic)
+ {
+ case 0xf8:
+ /* printk("NOP "); */
+ break;
+
+ case 0xf9:
+ /* printk("meas end "); */
+ break;
+
+ case 0xfc:
+ /* printk("data end "); */
+ break;
+
+ default:
+ printk ("Unknown MPU mark %02x\n", midic);
+ }
+ }
+ else
+ {
+ devc->last_status = midic;
+ /* printk("midi msg "); */
+ msg -= 8;
+ devc->m_left = len_tab[msg];
+
+ devc->m_ptr = 1;
+ devc->m_buf[0] = midic;
-#define mpu401_status() INB(STATPORT)
-#define input_avail() (!(mpu401_status()&INPUT_AVAIL))
-#define output_ready() (!(mpu401_status()&OUTPUT_READY))
-#define mpu401_cmd(cmd) OUTB(cmd, COMDPORT)
-#define mpu401_read() INB(DATAPORT)
-#define mpu401_write(byte) OUTB(byte, DATAPORT)
+ if (devc->m_left <= 0)
+ {
+ devc->m_state = ST_INIT;
+ do_midi_msg (devc, devc->m_buf, devc->m_ptr);
+ devc->m_ptr = 0;
+ }
+ }
+ }
+ break;
-#define OUTPUT_READY 0x40 /* Mask for Data Read Redy Bit */
-#define INPUT_AVAIL 0x80 /* Mask for Data Send Ready Bit */
-#define MPU_ACK 0xFE /* MPU-401 Acknowledge Response */
-#define MPU_RESET 0xFF /* MPU-401 Total Reset Command */
-#define UART_MODE_ON 0x3F /* MPU-401 "Dumb UART Mode" */
+ case ST_SYSMSG:
+ switch (midic)
+ {
+ case 0xf0:
+ printk ("<SYX>");
+ devc->m_state = ST_SYSEX;
+ break;
-static int mpu401_opened = 0;
-static int mpu401_base = 0x330;
-static int mpu401_irq;
-static int mpu401_detected = 0;
-static int my_dev;
+ case 0xf1:
+ devc->m_state = ST_MTC;
+ break;
-static int reset_mpu401 (void);
-static void (*midi_input_intr) (int dev, unsigned char data);
+ case 0xf2:
+ devc->m_state = ST_SONGPOS;
+ devc->m_ptr = 0;
+ break;
+
+ case 0xf3:
+ devc->m_state = ST_SONGSEL;
+ break;
+
+ case 0xf6:
+ /* printk("tune_request\n"); */
+ devc->m_state = ST_INIT;
+
+ /*
+ * Real time messages
+ */
+ case 0xf8:
+ /* midi clock */
+ devc->m_state = ST_INIT;
+ timer_ext_event (devc, TMR_CLOCK, 0);
+ break;
+
+ case 0xfA:
+ devc->m_state = ST_INIT;
+ timer_ext_event (devc, TMR_START, 0);
+ break;
+
+ case 0xFB:
+ devc->m_state = ST_INIT;
+ timer_ext_event (devc, TMR_CONTINUE, 0);
+ break;
+
+ case 0xFC:
+ devc->m_state = ST_INIT;
+ timer_ext_event (devc, TMR_STOP, 0);
+ break;
+
+ case 0xFE:
+ /* active sensing */
+ devc->m_state = ST_INIT;
+ break;
+
+ case 0xff:
+ /* printk("midi hard reset"); */
+ devc->m_state = ST_INIT;
+ break;
+
+ default:
+ printk ("unknown MIDI sysmsg %0x\n", midic);
+ devc->m_state = ST_INIT;
+ }
+ break;
+
+ case ST_MTC:
+ devc->m_state = ST_INIT;
+ printk ("MTC frame %x02\n", midic);
+ break;
+
+ case ST_SYSEX:
+ if (midic == 0xf7)
+ {
+ printk ("<EOX>");
+ devc->m_state = ST_INIT;
+ }
+ else
+ printk ("%02x ", midic);
+ break;
+
+ case ST_SONGPOS:
+ BUFTEST (devc);
+ devc->m_buf[devc->m_ptr++] = midic;
+ if (devc->m_ptr == 2)
+ {
+ devc->m_state = ST_INIT;
+ devc->m_ptr = 0;
+ timer_ext_event (devc, TMR_SPP,
+ ((devc->m_buf[1] & 0x7f) << 7) |
+ (devc->m_buf[0] & 0x7f));
+ }
+ break;
+
+ case ST_DATABYTE:
+ BUFTEST (devc);
+ devc->m_buf[devc->m_ptr++] = midic;
+ if ((--devc->m_left) <= 0)
+ {
+ devc->m_state = ST_INIT;
+ do_midi_msg (devc, devc->m_buf, devc->m_ptr);
+ devc->m_ptr = 0;
+ }
+ break;
+
+ default:
+ printk ("Bad state %d ", devc->m_state);
+ devc->m_state = ST_INIT;
+ }
+
+ return 1;
+}
+
+static void
+mpu401_input_loop (struct mpu_config *devc)
+{
+ unsigned long flags;
+ int busy;
+
+ DISABLE_INTR (flags);
+ busy = devc->m_busy;
+ devc->m_busy = 1;
+ RESTORE_INTR (flags);
+
+ if (busy)
+ return;
+
+ while (input_avail (devc->base))
+ {
+ unsigned char c = read_data (devc->base);
+
+ if (devc->mode == MODE_SYNTH)
+ {
+ mpu_input_scanner (devc, c);
+ }
+ else if (devc->opened & OPEN_READ && devc->inputintr != NULL)
+ devc->inputintr (devc->devno, c);
+ }
+
+ devc->m_busy = 0;
+}
void
-mpuintr (int unit)
+mpuintr (int irq)
{
- while (input_avail ())
+ struct mpu_config *devc;
+ int dev;
+
+#ifdef linux
+ sti ();
+#endif
+
+ if (irq < 1 || irq > 15)
{
- unsigned char c = mpu401_read ();
+ printk ("MPU-401: Interrupt #%d?\n", irq);
+ return;
+ }
- if (mpu401_opened & OPEN_READ)
- midi_input_intr (my_dev, c);
+ dev = irq2dev[irq];
+ if (dev == -1)
+ {
+ printk ("MPU-401: Interrupt #%d?\n", irq);
+ return;
}
+
+ devc = &dev_conf[dev];
+
+ if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH))
+ if (input_avail (devc->base))
+ mpu401_input_loop (devc);
+
}
static int
@@ -80,16 +516,32 @@ mpu401_open (int dev, int mode,
void (*output) (int dev)
)
{
- if (mpu401_opened)
+ int err;
+ struct mpu_config *devc;
+
+ if (dev < 0 || dev >= num_midis)
+ return RET_ERROR (ENXIO);
+
+ devc = &dev_conf[dev];
+
+ if (devc->opened)
{
printk ("MPU-401: Midi busy\n");
return RET_ERROR (EBUSY);
}
- mpuintr (0);
+ irq2dev[devc->irq] = dev;
+ if ((err = snd_set_irq_handler (devc->irq, mpuintr) < 0))
+ return err;
+
+ set_uart_mode (dev, devc, 1);
+ devc->mode = MODE_MIDI;
+ devc->synthno = 0;
- midi_input_intr = input;
- mpu401_opened = mode;
+ mpu401_input_loop (devc);
+
+ devc->inputintr = input;
+ devc->opened = mode;
return 0;
}
@@ -97,7 +549,20 @@ mpu401_open (int dev, int mode,
static void
mpu401_close (int dev)
{
- mpu401_opened = 0;
+ struct mpu_config *devc;
+
+ devc = &dev_conf[dev];
+
+ if (devc->uart_mode)
+ reset_mpu401 (devc); /*
+ * This disables the UART mode
+ */
+ devc->mode = 0;
+
+ snd_release_irq (devc->irq);
+ devc->inputintr = NULL;
+ irq2dev[devc->irq] = -1;
+ devc->opened = 0;
}
static int
@@ -106,38 +571,180 @@ mpu401_out (int dev, unsigned char midi_byte)
int timeout;
unsigned long flags;
+ struct mpu_config *devc;
+
+ devc = &dev_conf[dev];
+
+#if 0
/*
* Test for input since pending input seems to block the output.
*/
- DISABLE_INTR (flags);
+ if (input_avail (devc->base))
+ mpu401_input_loop (devc);
+#endif
+ /*
+ * Sometimes it takes about 13000 loops before the output becomes ready
+ * (After reset). Normally it takes just about 10 loops.
+ */
- if (input_avail ())
- mpuintr (0);
+ for (timeout = 30000; timeout > 0 && !output_ready (devc->base); timeout--); /*
+ * Wait
+ */
+ DISABLE_INTR (flags);
+ if (!output_ready (devc->base))
+ {
+ printk ("MPU-401: Send data timeout\n");
+ RESTORE_INTR (flags);
+ return 0;
+ }
+
+ write_data (devc->base, midi_byte);
RESTORE_INTR (flags);
+ return 1;
+}
+
+static int
+mpu401_command (int dev, mpu_command_rec * cmd)
+{
+ int i, timeout, ok;
+ int ret = 0;
+ unsigned long flags;
+ struct mpu_config *devc;
+
+ devc = &dev_conf[dev];
+
+ if (devc->uart_mode) /*
+ * Not possible in UART mode
+ */
+ {
+ printk ("MPU-401 commands not possible in the UART mode\n");
+ return RET_ERROR (EINVAL);
+ }
/*
- * Sometimes it takes about 13000 loops before the output becomes ready
+ * Test for input since pending input seems to block the output.
+ */
+ if (input_avail (devc->base))
+ mpu401_input_loop (devc);
+
+ /*
+ * Sometimes it takes about 30000 loops before the output becomes ready
* (After reset). Normally it takes just about 10 loops.
*/
- for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /* Wait */
+ for (timeout = 500000; timeout > 0 && !output_ready (devc->base); timeout--);
- if (!output_ready ())
+ DISABLE_INTR (flags);
+ if (!output_ready (devc->base))
{
- printk ("MPU-401: Timeout\n");
- return 0;
+ printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);
+ RESTORE_INTR (flags);
+ return RET_ERROR (EIO);
}
- mpu401_write (midi_byte);
- return 1;
+ write_command (devc->base, cmd->cmd);
+ ok = 0;
+ for (timeout = 500000; timeout > 0 && !ok; timeout--)
+ if (input_avail (devc->base))
+ if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK)
+ ok = 1;
+
+ if (!ok)
+ {
+ RESTORE_INTR (flags);
+ printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd);
+ return RET_ERROR (EIO);
+ }
+
+ if (cmd->nr_args)
+ for (i = 0; i < cmd->nr_args; i++)
+ {
+ for (timeout = 30000; timeout > 0 && !output_ready (devc->base); timeout--);
+
+ if (!mpu401_out (dev, cmd->data[i]))
+ {
+ RESTORE_INTR (flags);
+ printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);
+ return RET_ERROR (EIO);
+ }
+ }
+
+ ret = 0;
+ cmd->data[0] = 0;
+
+ if (cmd->nr_returns)
+ for (i = 0; i < cmd->nr_returns; i++)
+ {
+ ok = 0;
+ for (timeout = 5000; timeout > 0 && !ok; timeout--)
+ if (input_avail (devc->base))
+ {
+ cmd->data[i] = read_data (devc->base);
+ ok = 1;
+ }
+
+ if (!ok)
+ {
+ RESTORE_INTR (flags);
+ printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd);
+ return RET_ERROR (EIO);
+ }
+ }
+
+ RESTORE_INTR (flags);
+
+ return ret;
}
static int
-mpu401_command (int dev, unsigned char midi_byte)
+exec_cmd (int dev, int cmd, int data)
{
- return 1;
+ int ret;
+
+ static mpu_command_rec rec;
+
+ rec.cmd = cmd & 0xff;
+ rec.nr_args = ((cmd & 0xf0) == 0xE0);
+ rec.nr_returns = ((cmd & 0xf0) == 0xA0);
+ rec.data[0] = data & 0xff;
+
+ if ((ret = mpu401_command (dev, &rec)) < 0)
+ return ret;
+ return (unsigned char) rec.data[0];
+}
+
+static int
+mpu401_prefix_cmd (int dev, unsigned char status)
+{
+ struct mpu_config *devc = &dev_conf[dev];
+
+ if (devc->uart_mode)
+ return 1;
+
+ if (status < 0xf0)
+ {
+ if (exec_cmd (dev, 0xD0, 0) < 0)
+ return 0;
+
+ return 1;
+ }
+
+ switch (status)
+ {
+ case 0xF0:
+ if (exec_cmd (dev, 0xDF, 0) < 0)
+ return 0;
+
+ return 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
}
static int
@@ -155,7 +762,45 @@ mpu401_end_read (int dev)
static int
mpu401_ioctl (int dev, unsigned cmd, unsigned arg)
{
- return RET_ERROR (EINVAL);
+ struct mpu_config *devc;
+
+ devc = &dev_conf[dev];
+
+ switch (cmd)
+ {
+ case 1:
+ IOCTL_FROM_USER ((char *) &init_sequence, (char *) arg, 0, sizeof (init_sequence));
+ return 0;
+ break;
+
+ case SNDCTL_MIDI_MPUMODE:
+ if (devc->version == 0)
+ {
+ printk ("MPU-401: Intelligent mode not supported by the HW\n");
+ return RET_ERROR (EINVAL);
+ }
+ set_uart_mode (dev, devc, !IOCTL_IN (arg));
+ return 0;
+ break;
+
+ case SNDCTL_MIDI_MPUCMD:
+ {
+ int ret;
+ mpu_command_rec rec;
+
+ IOCTL_FROM_USER ((char *) &rec, (char *) arg, 0, sizeof (rec));
+
+ if ((ret = mpu401_command (dev, &rec)) < 0)
+ return ret;
+
+ IOCTL_TO_USER ((char *) arg, 0, (char *) &rec, sizeof (rec));
+ return 0;
+ }
+ break;
+
+ default:
+ return RET_ERROR (EINVAL);
+ }
}
static void
@@ -166,12 +811,135 @@ mpu401_kick (int dev)
static int
mpu401_buffer_status (int dev)
{
- return 0; /* No data in buffers */
+ return 0; /*
+ * No data in buffers
+ */
+}
+
+static int
+mpu_synth_ioctl (int dev,
+ unsigned int cmd, unsigned int arg)
+{
+ int midi_dev;
+ struct mpu_config *devc;
+
+ midi_dev = synth_devs[dev]->midi_dev;
+
+ if (midi_dev < 0 || midi_dev > num_midis)
+ return RET_ERROR (ENXIO);
+
+ devc = &dev_conf[midi_dev];
+
+ switch (cmd)
+ {
+
+ case SNDCTL_SYNTH_INFO:
+ IOCTL_TO_USER ((char *) arg, 0, &mpu_synth_info[midi_dev],
+ sizeof (struct synth_info));
+
+ return 0;
+ break;
+
+ case SNDCTL_SYNTH_MEMAVL:
+ return 0x7fffffff;
+ break;
+
+ default:
+ return RET_ERROR (EINVAL);
+ }
}
-static struct midi_operations mpu401_operations =
+static int
+mpu_synth_open (int dev, int mode)
{
- {"MPU-401", 0, 0, SNDCARD_MPU401},
+ int midi_dev, err;
+ struct mpu_config *devc;
+
+ midi_dev = synth_devs[dev]->midi_dev;
+
+ if (midi_dev < 0 || midi_dev > num_midis)
+ return RET_ERROR (ENXIO);
+
+ devc = &dev_conf[midi_dev];
+
+ if (devc->opened)
+ {
+ printk ("MPU-401: Midi busy\n");
+ return RET_ERROR (EBUSY);
+ }
+
+ devc->opened = mode;
+ devc->mode = MODE_SYNTH;
+ devc->synthno = dev;
+
+ devc->inputintr = NULL;
+ irq2dev[devc->irq] = midi_dev;
+ if ((err = snd_set_irq_handler (devc->irq, mpuintr) < 0))
+ return err;
+
+ reset_mpu401 (devc);
+
+ if (mode & OPEN_READ)
+ {
+ exec_cmd (midi_dev, 0x34, 0); /* Return timing bytes in stop mode */
+ exec_cmd (midi_dev, 0x8B, 0); /* Enable data in stop mode */
+ }
+
+ return 0;
+}
+
+static void
+mpu_synth_close (int dev)
+{
+ int midi_dev;
+ struct mpu_config *devc;
+
+ midi_dev = synth_devs[dev]->midi_dev;
+
+ devc = &dev_conf[midi_dev];
+ exec_cmd (midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */
+ exec_cmd (midi_dev, 0x8a, 0); /* Disable data in stopped mode */
+
+ devc->opened = 0;
+ devc->mode = 0;
+ snd_release_irq (devc->irq);
+ devc->inputintr = NULL;
+ irq2dev[devc->irq] = -1;
+}
+
+#define MIDI_SYNTH_NAME "MPU-401 UART Midi"
+#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
+#include "midi_synth.h"
+
+static struct synth_operations mpu401_synth_proto =
+{
+ NULL,
+ 0,
+ SYNTH_TYPE_MIDI,
+ 0,
+ mpu_synth_open,
+ mpu_synth_close,
+ mpu_synth_ioctl,
+ midi_synth_kill_note,
+ midi_synth_start_note,
+ midi_synth_set_instr,
+ midi_synth_reset,
+ midi_synth_hw_control,
+ midi_synth_load_patch,
+ midi_synth_aftertouch,
+ midi_synth_controller,
+ midi_synth_panning,
+ NULL,
+ midi_synth_patchmgr,
+ midi_synth_bender
+};
+
+static struct synth_operations mpu401_synth_operations[MAX_MIDI_DEV];
+
+static struct midi_operations mpu401_midi_proto =
+{
+ {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
+ NULL,
mpu401_open,
mpu401_close,
mpu401_ioctl,
@@ -179,105 +947,785 @@ static struct midi_operations mpu401_operations =
mpu401_start_read,
mpu401_end_read,
mpu401_kick,
- mpu401_command,
- mpu401_buffer_status
+ NULL,
+ mpu401_buffer_status,
+ mpu401_prefix_cmd
};
+static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV];
+
+static void
+mpu401_chk_version (struct mpu_config *devc)
+{
+ int tmp;
+
+ devc->version = devc->revision = 0;
+
+ if ((tmp = exec_cmd (num_midis, 0xAC, 0)) < 0)
+ return;
+ devc->version = tmp;
+
+ if ((tmp = exec_cmd (num_midis, 0xAD, 0)) < 0)
+ return;
+ devc->revision = tmp;
+}
long
attach_mpu401 (long mem_start, struct address_info *hw_config)
{
- int ok, timeout;
+ int i;
unsigned long flags;
+ char revision_char;
- mpu401_base = hw_config->io_base;
- mpu401_irq = hw_config->irq;
+ struct mpu_config *devc;
- if (!mpu401_detected)
- return RET_ERROR (EIO);
+ for (i = 0; i < 16; i++)
+ irq2dev[i] = -1;
- DISABLE_INTR (flags);
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* Wait */
- mpu401_cmd (UART_MODE_ON);
+ if (num_midis >= MAX_MIDI_DEV)
+ {
+ printk ("MPU-401: Too many midi devices detected\n");
+ return mem_start;
+ }
- ok = 0;
- for (timeout = 50000; timeout > 0 && !ok; timeout--)
- if (input_avail ())
- if (mpu401_read () == MPU_ACK)
- ok = 1;
+ devc = &dev_conf[num_midis];
+
+ devc->base = hw_config->io_base;
+ devc->irq = hw_config->irq;
+ devc->opened = 0;
+ devc->uart_mode = 0;
+ devc->initialized = 0;
+ devc->version = 0;
+ devc->revision = 0;
+ devc->capabilities = 0;
+ devc->timer_flag = 0;
+ devc->m_busy = 0;
+ devc->m_state = ST_INIT;
+
+ for (i = 0; i < 32; i++)
+ devc->controls[i] = 0x2000;
+
+ if (!reset_mpu401 (devc))
+ return mem_start;
+ DISABLE_INTR (flags);
+ mpu401_chk_version (devc);
+ if (devc->version == 0)
+ mpu401_chk_version (devc);
RESTORE_INTR (flags);
+ if (devc->version == 0)
+ {
+ memcpy ((char *) &mpu401_synth_operations[num_midis],
+ (char *) &std_midi_synth,
+ sizeof (struct synth_operations));
+ }
+ else
+ {
+ devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */
+ memcpy ((char *) &mpu401_synth_operations[num_midis],
+ (char *) &mpu401_synth_proto,
+ sizeof (struct synth_operations));
+ }
+
+ memcpy ((char *) &mpu401_midi_operations[num_midis],
+ (char *) &mpu401_midi_proto,
+ sizeof (struct midi_operations));
+
+ mpu401_midi_operations[num_midis].converter =
+ &mpu401_synth_operations[num_midis];
+
+ memcpy ((char *) &mpu_synth_info[num_midis],
+ (char *) &mpu_synth_info_proto,
+ sizeof (struct synth_info));
+
+ n_mpu_devs++;
+
+ if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */
+ {
+ int ports = (devc->revision & 0x08) ? 32 : 16;
+
+ devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE |
+ MPU_CAP_CLS | MPU_CAP_2PORT;
+
+ revision_char = (devc->revision == 0x7f) ? 'M' : ' ';
+#ifdef __FreeBSD__
+ printk ("snd5: <MQX-%d%c MIDI Interface>",
+#else
+ printk (" <MQX-%d%c MIDI Interface>",
+#endif
+ ports,
+ revision_char);
+#ifndef SCO
+ sprintf (mpu_synth_info[num_midis].name,
+ "MQX-%d%c MIDI Interface #%d",
+ ports,
+ revision_char,
+ n_mpu_devs);
+#endif
+ }
+ else
+ {
+
+ revision_char = devc->revision ? devc->revision + '@' : ' ';
+ if (devc->revision > ('Z' - '@'))
+ revision_char = '+';
+
+ devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK;
+
#ifdef __FreeBSD__
- printk ("snd5: <Roland MPU-401>");
+ printk ("snd5: <MPU-401 MIDI Interface %d.%d%c>",
#else
- printk (" <Roland MPU-401>");
+ printk (" <MPU-401 MIDI Interface %d.%d%c>",
+#endif
+ (devc->version & 0xf0) >> 4,
+ devc->version & 0x0f,
+ revision_char);
+#ifndef SCO
+ sprintf (mpu_synth_info[num_midis].name,
+ "MPU-401 %d.%d%c Midi interface #%d",
+ (devc->version & 0xf0) >> 4,
+ devc->version & 0x0f,
+ revision_char,
+ n_mpu_devs);
+#endif
+ }
+
+#ifndef SCO
+ strcpy (mpu401_midi_operations[num_midis].info.name,
+ mpu_synth_info[num_midis].name);
#endif
- my_dev = num_midis;
- mpu401_dev = num_midis;
- midi_devs[num_midis++] = &mpu401_operations;
+ mpu401_synth_operations[num_midis].midi_dev = devc->devno = num_midis;
+ mpu401_synth_operations[devc->devno].info =
+ &mpu_synth_info[devc->devno];
+
+ if (devc->capabilities & MPU_CAP_INTLG) /* Has timer */
+ mpu_timer_init (num_midis);
+
+ midi_devs[num_midis++] = &mpu401_midi_operations[devc->devno];
return mem_start;
}
static int
-reset_mpu401 (void)
+reset_mpu401 (struct mpu_config *devc)
{
unsigned long flags;
int ok, timeout, n;
+ int timeout_limit;
/*
* Send the RESET command. Try again if no success at the first time.
+ * (If the device is in the UART mode, it will not ack the reset cmd).
*/
ok = 0;
- DISABLE_INTR (flags);
+ timeout_limit = devc->initialized ? 30000 : 100000;
+ devc->initialized = 1;
for (n = 0; n < 2 && !ok; n++)
{
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* Wait */
- mpu401_cmd (MPU_RESET); /* Send MPU-401 RESET Command */
+ for (timeout = timeout_limit; timeout > 0 && !ok; timeout--)
+ ok = output_ready (devc->base);
+
+ write_command (devc->base, MPU_RESET); /*
+ * Send MPU-401 RESET Command
+ */
/*
* Wait at least 25 msec. This method is not accurate so let's make the
* loop bit longer. Cannot sleep since this is called during boot.
*/
- for (timeout = 50000; timeout > 0 && !ok; timeout--)
- if (input_avail ())
- if (mpu401_read () == MPU_ACK)
- ok = 1;
+ for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--)
+ {
+ DISABLE_INTR (flags);
+ if (input_avail (devc->base))
+ if (read_data (devc->base) == MPU_ACK)
+ ok = 1;
+ RESTORE_INTR (flags);
+ }
}
- mpu401_opened = 0;
- if (ok)
- mpuintr (0); /* Flush input before enabling interrupts */
-
- RESTORE_INTR (flags);
+ devc->m_state = ST_INIT;
+ devc->m_ptr = 0;
+ devc->m_left = 0;
+ devc->last_status = 0;
+ devc->uart_mode = 0;
return ok;
}
+static void
+set_uart_mode (int dev, struct mpu_config *devc, int arg)
+{
+
+ if (!arg && devc->version == 0)
+ return;
+
+ if ((devc->uart_mode == 0) == (arg == 0))
+ return; /* Already set */
+
+ reset_mpu401 (devc); /* This exits the uart mode */
+
+ if (arg)
+ {
+ if (exec_cmd (dev, UART_MODE_ON, 0) < 0)
+ {
+ printk ("MPU%d: Can't enter UART mode\n", devc->devno);
+ devc->uart_mode = 0;
+ return;
+ }
+ }
+ devc->uart_mode = arg;
+
+}
int
probe_mpu401 (struct address_info *hw_config)
{
int ok = 0;
+ struct mpu_config tmp_devc;
+
+ tmp_devc.base = hw_config->io_base;
+ tmp_devc.irq = hw_config->irq;
+ tmp_devc.initialized = 0;
+
+ ok = reset_mpu401 (&tmp_devc);
+
+ return ok;
+}
+
+/*****************************************************
+ * Timer stuff
+ ****************************************************/
- mpu401_base = hw_config->io_base;
- mpu401_irq = hw_config->irq;
+#if !defined(EXCLUDE_SEQUENCER)
- if (snd_set_irq_handler (mpu401_irq, mpuintr) < 0)
+static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0;
+static volatile int curr_tempo, curr_timebase, hw_timebase;
+static int max_timebase = 8; /* 8*24=192 ppqn */
+static volatile unsigned long next_event_time;
+static volatile unsigned long curr_ticks, curr_clocks;
+static unsigned long prev_event_time;
+static int metronome_mode;
+
+static unsigned long
+clocks2ticks (unsigned long clocks)
+{
+ /*
+ * The MPU-401 supports just a limited set of possible timebase values.
+ * Since the applications require more choices, the driver has to
+ * program the HW to do it's best and to convert between the HW and
+ * actual timebases.
+ */
+
+ return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase;
+}
+
+static void
+set_timebase (int midi_dev, int val)
+{
+ int hw_val;
+
+ if (val < 48)
+ val = 48;
+ if (val > 1000)
+ val = 1000;
+
+ hw_val = val;
+ hw_val = (hw_val + 23) / 24;
+ if (hw_val > max_timebase)
+ hw_val = max_timebase;
+
+ if (exec_cmd (midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0)
+ {
+ printk ("MPU: Can't set HW timebase to %d\n", hw_val * 24);
+ return;
+ }
+ hw_timebase = hw_val * 24;
+ curr_timebase = val;
+
+}
+
+static void
+tmr_reset (void)
+{
+ unsigned long flags;
+
+ DISABLE_INTR (flags);
+ next_event_time = 0xffffffff;
+ prev_event_time = 0;
+ curr_ticks = curr_clocks = 0;
+ RESTORE_INTR (flags);
+}
+
+static void
+set_timer_mode (int midi_dev)
+{
+ if (timer_mode & TMR_MODE_CLS)
+ exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */
+ else if (timer_mode & TMR_MODE_SMPTE)
+ exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */
+
+ if (timer_mode & TMR_INTERNAL)
+ {
+ exec_cmd (midi_dev, 0x80, 0); /* Use MIDI sync */
+ }
+ else
+ {
+ if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS))
+ {
+ exec_cmd (midi_dev, 0x82, 0); /* Use MIDI sync */
+ exec_cmd (midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */
+ }
+ else if (timer_mode & TMR_MODE_FSK)
+ exec_cmd (midi_dev, 0x81, 0); /* Use FSK sync */
+ }
+}
+
+static void
+stop_metronome (int midi_dev)
+{
+ exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */
+}
+
+static void
+setup_metronome (int midi_dev)
+{
+ int numerator, denominator;
+ int clks_per_click, num_32nds_per_beat;
+ int beats_per_measure;
+
+ numerator = ((unsigned) metronome_mode >> 24) & 0xff;
+ denominator = ((unsigned) metronome_mode >> 16) & 0xff;
+ clks_per_click = ((unsigned) metronome_mode >> 8) & 0xff;
+ num_32nds_per_beat = (unsigned) metronome_mode & 0xff;
+ beats_per_measure = (numerator * 4) >> denominator;
+
+ if (!metronome_mode)
+ exec_cmd (midi_dev, 0x84, 0); /* Disable metronome */
+ else
+ {
+ exec_cmd (midi_dev, 0xE4, clks_per_click);
+ exec_cmd (midi_dev, 0xE6, beats_per_measure);
+ exec_cmd (midi_dev, 0x83, 0); /* Enable metronome without accents */
+ }
+}
+
+static int
+start_timer (int midi_dev)
+{
+ tmr_reset ();
+ set_timer_mode (midi_dev);
+
+ if (tmr_running)
+ return TIMER_NOT_ARMED; /* Already running */
+
+ if (timer_mode & TMR_INTERNAL)
+ {
+ exec_cmd (midi_dev, 0x02, 0); /* Send MIDI start */
+ tmr_running = 1;
+ return TIMER_NOT_ARMED;
+ }
+ else
+ {
+ exec_cmd (midi_dev, 0x35, 0); /* Enable mode messages to PC */
+ exec_cmd (midi_dev, 0x38, 0); /* Enable sys common messages to PC */
+ exec_cmd (midi_dev, 0x39, 0); /* Enable real time messages to PC */
+ exec_cmd (midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */
+ }
+
+ return TIMER_ARMED;
+}
+
+static int
+mpu_timer_open (int dev, int mode)
+{
+ int midi_dev = sound_timer_devs[dev]->devlink;
+
+ if (timer_open)
+ return RET_ERROR (EBUSY);
+
+ tmr_reset ();
+ curr_tempo = 50;
+ exec_cmd (midi_dev, 0xE0, 50);
+ curr_timebase = hw_timebase = 120;
+ set_timebase (midi_dev, 120);
+ timer_open = 1;
+ metronome_mode = 0;
+ set_timer_mode (midi_dev);
+
+ exec_cmd (midi_dev, 0xe7, 0x04); /* Send all clocks to host */
+ exec_cmd (midi_dev, 0x95, 0); /* Enable clock to host */
+
+ return 0;
+}
+
+static void
+mpu_timer_close (int dev)
+{
+ int midi_dev = sound_timer_devs[dev]->devlink;
+
+ timer_open = tmr_running = 0;
+ exec_cmd (midi_dev, 0x15, 0); /* Stop all */
+ exec_cmd (midi_dev, 0x94, 0); /* Disable clock to host */
+ exec_cmd (midi_dev, 0x8c, 0); /* Disable measure end messages to host */
+ stop_metronome (midi_dev);
+}
+
+static int
+mpu_timer_event (int dev, unsigned char *event)
+{
+ unsigned char command = event[1];
+ unsigned long parm = *(unsigned int *) &event[4];
+ int midi_dev = sound_timer_devs[dev]->devlink;
+
+ switch (command)
+ {
+ case TMR_WAIT_REL:
+ parm += prev_event_time;
+ case TMR_WAIT_ABS:
+ if (parm > 0)
+ {
+ long time;
+
+ if (parm <= curr_ticks) /* It's the time */
+ return TIMER_NOT_ARMED;
+
+ time = parm;
+ next_event_time = prev_event_time = time;
+
+ return TIMER_ARMED;
+ }
+ break;
+
+ case TMR_START:
+ if (tmr_running)
+ break;
+ return start_timer (midi_dev);
+ break;
+
+ case TMR_STOP:
+ exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */
+ stop_metronome (midi_dev);
+ tmr_running = 0;
+ break;
+
+ case TMR_CONTINUE:
+ if (tmr_running)
+ break;
+ exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */
+ setup_metronome (midi_dev);
+ tmr_running = 1;
+ break;
+
+ case TMR_TEMPO:
+ if (parm)
+ {
+ if (parm < 8)
+ parm = 8;
+ if (parm > 250)
+ parm = 250;
+
+ if (exec_cmd (midi_dev, 0xE0, parm) < 0)
+ printk ("MPU: Can't set tempo to %d\n", (int) parm);
+ curr_tempo = parm;
+ }
+ break;
+
+ case TMR_ECHO:
+ seq_copy_to_input (event, 8);
+ break;
+
+ case TMR_TIMESIG:
+ if (metronome_mode) /* Metronome enabled */
+ {
+ metronome_mode = parm;
+ setup_metronome (midi_dev);
+ }
+ break;
+
+ default:;
+ }
+
+ return TIMER_NOT_ARMED;
+}
+
+static unsigned long
+mpu_timer_get_time (int dev)
+{
+ if (!timer_open)
return 0;
- ok = reset_mpu401 ();
+ return curr_ticks;
+}
- mpu401_detected = ok;
- return ok;
+static int
+mpu_timer_ioctl (int dev,
+ unsigned int command, unsigned int arg)
+{
+ int midi_dev = sound_timer_devs[dev]->devlink;
+
+ switch (command)
+ {
+ case SNDCTL_TMR_SOURCE:
+ {
+ int parm = IOCTL_IN (arg) & timer_caps;
+
+ if (parm != 0)
+ {
+ timer_mode = parm;
+
+ if (timer_mode & TMR_MODE_CLS)
+ exec_cmd (midi_dev, 0x3c, 0); /* Use CLS sync */
+ else if (timer_mode & TMR_MODE_SMPTE)
+ exec_cmd (midi_dev, 0x3d, 0); /* Use SMPTE sync */
+ }
+
+ return IOCTL_OUT (arg, timer_mode);
+ }
+ break;
+
+ case SNDCTL_TMR_START:
+ if (tmr_running)
+ return 0;
+ start_timer (midi_dev);
+ return 0;
+ break;
+
+ case SNDCTL_TMR_STOP:
+ tmr_running = 0;
+ exec_cmd (midi_dev, 0x01, 0); /* Send MIDI stop */
+ stop_metronome (midi_dev);
+ return 0;
+ break;
+
+ case SNDCTL_TMR_CONTINUE:
+ if (tmr_running)
+ return 0;
+ tmr_running = 1;
+ exec_cmd (midi_dev, 0x03, 0); /* Send MIDI continue */
+ return 0;
+ break;
+
+ case SNDCTL_TMR_TIMEBASE:
+ {
+ int val = IOCTL_IN (arg);
+
+ if (val)
+ set_timebase (midi_dev, val);
+
+ return IOCTL_OUT (arg, curr_timebase);
+ }
+ break;
+
+ case SNDCTL_TMR_TEMPO:
+ {
+ int val = IOCTL_IN (arg);
+ int ret;
+
+ if (val)
+ {
+ if (val < 8)
+ val = 8;
+ if (val > 250)
+ val = 250;
+ if ((ret = exec_cmd (midi_dev, 0xE0, val)) < 0)
+ {
+ printk ("MPU: Can't set tempo to %d\n", (int) val);
+ return ret;
+ }
+
+ curr_tempo = val;
+ }
+
+ return IOCTL_OUT (arg, curr_tempo);
+ }
+ break;
+
+ case SNDCTL_SEQ_CTRLRATE:
+ if (IOCTL_IN (arg) != 0) /* Can't change */
+ return RET_ERROR (EINVAL);
+
+ return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+ break;
+
+ case SNDCTL_TMR_METRONOME:
+ metronome_mode = IOCTL_IN (arg);
+ setup_metronome (midi_dev);
+ return 0;
+ break;
+
+ default:
+ }
+
+ return RET_ERROR (EINVAL);
+}
+
+static void
+mpu_timer_arm (int dev, long time)
+{
+ if (time < 0)
+ time = curr_ticks + 1;
+ else if (time <= curr_ticks) /* It's the time */
+ return;
+
+ next_event_time = prev_event_time = time;
+
+ return;
+}
+
+static struct sound_timer_operations mpu_timer =
+{
+ {"MPU-401 Timer", 0},
+ 10, /* Priority */
+ 0, /* Local device link */
+ mpu_timer_open,
+ mpu_timer_close,
+ mpu_timer_event,
+ mpu_timer_get_time,
+ mpu_timer_ioctl,
+ mpu_timer_arm
+};
+
+static void
+mpu_timer_interrupt (void)
+{
+
+ if (!timer_open)
+ return;
+
+ if (!tmr_running)
+ return;
+
+ curr_clocks++;
+ curr_ticks = clocks2ticks (curr_clocks);
+
+ if (curr_ticks >= next_event_time)
+ {
+ next_event_time = 0xffffffff;
+ sequencer_timer ();
+ }
}
+static void
+timer_ext_event (struct mpu_config *devc, int event, int parm)
+{
+ int midi_dev = devc->devno;
+
+ if (!devc->timer_flag)
+ return;
+
+ switch (event)
+ {
+ case TMR_CLOCK:
+ printk ("<MIDI clk>");
+ break;
+
+ case TMR_START:
+ printk ("Ext MIDI start\n");
+ if (!tmr_running)
+ if (timer_mode & TMR_EXTERNAL)
+ {
+ tmr_running = 1;
+ setup_metronome (midi_dev);
+ next_event_time = 0;
+ STORE (SEQ_START_TIMER ());
+ }
+ break;
+
+ case TMR_STOP:
+ printk ("Ext MIDI stop\n");
+ if (timer_mode & TMR_EXTERNAL)
+ {
+ tmr_running = 0;
+ stop_metronome (midi_dev);
+ STORE (SEQ_STOP_TIMER ());
+ }
+ break;
+
+ case TMR_CONTINUE:
+ printk ("Ext MIDI continue\n");
+ if (timer_mode & TMR_EXTERNAL)
+ {
+ tmr_running = 1;
+ setup_metronome (midi_dev);
+ STORE (SEQ_CONTINUE_TIMER ());
+ }
+ break;
+
+ case TMR_SPP:
+ printk ("Songpos: %d\n", parm);
+ if (timer_mode & TMR_EXTERNAL)
+ {
+ STORE (SEQ_SONGPOS (parm));
+ }
+ break;
+ }
+}
+
+static void
+mpu_timer_init (int midi_dev)
+{
+ struct mpu_config *devc;
+ int n;
+
+ devc = &dev_conf[midi_dev];
+
+ if (timer_initialized)
+ return; /* There is already a similar timer */
+
+ timer_initialized = 1;
+
+ mpu_timer.devlink = midi_dev;
+ dev_conf[midi_dev].timer_flag = 1;
+
+#if 1
+ if (num_sound_timers >= MAX_TIMER_DEV)
+ n = 0; /* Overwrite the system timer */
+ else
+ n = num_sound_timers++;
+#else
+ n = 0;
+#endif
+ sound_timer_devs[n] = &mpu_timer;
+
+ if (devc->version < 0x20) /* Original MPU-401 */
+ timer_caps = TMR_INTERNAL | TMR_EXTERNAL | TMR_MODE_FSK | TMR_MODE_MIDI;
+ else
+ {
+ /*
+ * The version number 2.0 is used (at least) by the
+ * MusicQuest cards and the Roland Super-MPU.
+ *
+ * MusicQuest has given a special meaning to the bits of the
+ * revision number. The Super-MPU returns 0.
+ */
+
+ if (devc->revision)
+ timer_caps |= TMR_EXTERNAL | TMR_MODE_MIDI;
+
+ if (devc->revision & 0x02)
+ timer_caps |= TMR_MODE_CLS;
+
+#if 0
+ if (devc->revision & 0x04)
+ timer_caps |= TMR_MODE_SMPTE;
+#endif
+
+ if (devc->revision & 0x40)
+ max_timebase = 10; /* Has the 216 and 240 ppqn modes */
+ }
+
+ timer_mode = (TMR_INTERNAL | TMR_MODE_MIDI) & timer_caps;
+
+}
+
+#endif
+
#endif
#endif
diff --git a/sys/i386/isa/sound/opl3.c b/sys/i386/isa/sound/opl3.c
index 4278d19..00c27f2 100644
--- a/sys/i386/isa/sound/opl3.c
+++ b/sys/i386/isa/sound/opl3.c
@@ -25,11 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: opl3.c,v 1.6 1994/08/02 07:40:13 davidg Exp $
*/
-/* Major improvements to the FM handling 30AUG92 by Rob Hooft, */
-/* hooft@chem.ruu.nl */
+/*
+ * Major improvements to the FM handling 30AUG92 by Rob Hooft,
+ * hooft@chem.ruu.nl
+ */
#include "sound_config.h"
@@ -38,8 +40,9 @@
#include "opl3.h"
#define MAX_VOICE 18
-#define OFFS_4OP 11 /* Definitions for the operators OP3 and OP4
- * begin here */
+#define OFFS_4OP 11 /*
+ * * * Definitions for the operators OP3 and
+ * * OP4 * * begin here */
static int opl3_enabled = 0;
static int left_address = 0x388, right_address = 0x388, both_address = 0;
@@ -59,24 +62,30 @@ struct voice_info
};
static struct voice_info voices[MAX_VOICE];
+static struct voice_alloc_info *voice_alloc;
+static struct channel_info *chn_info;
static struct sbi_instrument *instrmap;
static struct sbi_instrument *active_instrument[MAX_VOICE] =
{NULL};
static struct synth_info fm_info =
-{"AdLib", 0, SYNTH_TYPE_FM, FM_TYPE_ADLIB, 0, 9, 0, SBFM_MAXINSTR, 0};
+{"OPL-2", 0, SYNTH_TYPE_FM, FM_TYPE_ADLIB, 0, 9, 0, SBFM_MAXINSTR, 0};
static int already_initialized = 0;
static int opl3_ok = 0;
static int opl3_busy = 0;
-static int fm_model = 0; /* 0=no fm, 1=mono, 2=SB Pro 1, 3=SB Pro 2 */
+static int fm_model = 0; /*
+
+
+ * * * * 0=no fm, 1=mono, 2=SB Pro 1, 3=SB
+ * Pro 2 * * */
static int store_instr (int instr_no, struct sbi_instrument *instr);
static void freq_to_fnum (int freq, int *block, int *fnum);
static void opl3_command (int io_addr, unsigned int addr, unsigned int val);
-static int opl3_kill_note (int dev, int voice, int velocity);
+static int opl3_kill_note (int dev, int voice, int note, int velocity);
static unsigned char connection_mask = 0x00;
void
@@ -100,9 +109,9 @@ enter_4op_mode (void)
static int voices_4op[MAX_VOICE] =
{0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17};
- connection_mask = 0x3f;
- opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x3f); /* Select all 4-OP
- * voices */
+ connection_mask = 0x3f; /* Connect all possible 4 OP voices */
+ opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x3f);
+
for (i = 0; i < 3; i++)
physical_voices[i].voice_mode = 4;
for (i = 3; i < 6; i++)
@@ -115,7 +124,7 @@ enter_4op_mode (void)
for (i = 0; i < 12; i++)
logical_voices[i] = voices_4op[i];
- nr_voices = 12;
+ voice_alloc->max_voice = nr_voices = 12;
}
static int
@@ -184,66 +193,111 @@ opl3_detect (int ioaddr)
if (already_initialized)
{
- return 0; /* Do avoid duplicate initializations */
+ return 0; /*
+ * Do avoid duplicate initializations
+ */
}
if (opl3_enabled)
ioaddr = left_address;
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); /* Reset timers 1 and 2 */
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); /* Reset the IRQ of FM
- * chicp */
-
- stat1 = INB (ioaddr); /* Read status register */
+ opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); /*
+ * Reset
+ * timers
+ * 1
+ * and
+ * 2
+ */
+ opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); /*
+ * Reset the
+ * IRQ of FM
+ * * chicp
+ */
+
+ stat1 = INB (ioaddr); /*
+ * Read status register
+ */
if ((stat1 & 0xE0) != 0x00)
{
- return 0; /* Should be 0x00 */
+ return 0; /*
+ * Should be 0x00
+ */
}
- opl3_command (ioaddr, TIMER1_REGISTER, 0xff); /* Set timer 1 to 0xff */
+ opl3_command (ioaddr, TIMER1_REGISTER, 0xff); /*
+ * Set timer 1 to
+ * 0xff
+ */
opl3_command (ioaddr, TIMER_CONTROL_REGISTER,
- TIMER2_MASK | TIMER1_START); /* Unmask and start timer 1 */
+ TIMER2_MASK | TIMER1_START); /*
+ * Unmask and start timer 1
+ */
/*
* Now we have to delay at least 80 msec
*/
for (i = 0; i < 50; i++)
- tenmicrosec (); /* To be sure */
+ tenmicrosec (); /*
+ * To be sure
+ */
- stat2 = INB (ioaddr); /* Read status after timers have expired */
+ stat2 = INB (ioaddr); /*
+ * Read status after timers have expired
+ */
- /* Stop the timers */
+ /*
+ * Stop the timers
+ */
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); /* Reset timers 1 and 2 */
- opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); /* Reset the IRQ of FM
- * chicp */
+ opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); /*
+ * Reset
+ * timers
+ * 1
+ * and
+ * 2
+ */
+ opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); /*
+ * Reset the
+ * IRQ of FM
+ * * chicp
+ */
if ((stat2 & 0xE0) != 0xc0)
{
- return 0; /* There is no YM3812 */
+ return 0; /*
+ * There is no YM3812
+ */
}
- /* There is a FM chicp in this address. Now set some default values. */
+ /*
+ * There is a FM chicp in this address. Now set some default values.
+ */
for (i = 0; i < 9; i++)
- opl3_command (ioaddr, KEYON_BLOCK + i, 0); /* Note off */
+ opl3_command (ioaddr, KEYON_BLOCK + i, 0); /*
+ * Note off
+ */
opl3_command (ioaddr, TEST_REGISTER, ENABLE_WAVE_SELECT);
- opl3_command (ioaddr, PERCUSSION_REGISTER, 0x00); /* Melodic mode. */
+ opl3_command (ioaddr, PERCUSSION_REGISTER, 0x00); /*
+ * Melodic mode.
+ */
return 1;
}
static int
-opl3_kill_note (int dev, int voice, int velocity)
+opl3_kill_note (int dev, int voice, int note, int velocity)
{
struct physical_voice_info *map;
if (voice < 0 || voice >= nr_voices)
return 0;
+ voice_alloc->map[voice] = 0;
+
map = &physical_voices[logical_voices[voice]];
DEB (printk ("Kill note %d\n", voice));
@@ -255,7 +309,9 @@ opl3_kill_note (int dev, int voice, int velocity)
voices[voice].keyon_byte = 0;
voices[voice].bender = 0;
- voices[voice].bender_range = 200; /* 200 cents = 2 semitones */
+ voices[voice].bender_range = 200; /*
+ * 200 cents = 2 semitones
+ */
voices[voice].orig_freq = 0;
voices[voice].current_freq = 0;
voices[voice].mode = 0;
@@ -305,22 +361,55 @@ opl3_set_instr (int dev, int voice, int instr_no)
* it saves a lot of log() calculations. (RH)
*/
char fm_volume_table[128] =
-{-64, -48, -40, -35, -32, -29, -27, -26, /* 0 - 7 */
- -24, -23, -21, -20, -19, -18, -18, -17, /* 8 - 15 */
- -16, -15, -15, -14, -13, -13, -12, -12, /* 16 - 23 */
- -11, -11, -10, -10, -10, -9, -9, -8, /* 24 - 31 */
- -8, -8, -7, -7, -7, -6, -6, -6,/* 32 - 39 */
- -5, -5, -5, -5, -4, -4, -4, -4,/* 40 - 47 */
- -3, -3, -3, -3, -2, -2, -2, -2,/* 48 - 55 */
- -2, -1, -1, -1, -1, 0, 0, 0, /* 56 - 63 */
- 0, 0, 0, 1, 1, 1, 1, 1, /* 64 - 71 */
- 1, 2, 2, 2, 2, 2, 2, 2, /* 72 - 79 */
- 3, 3, 3, 3, 3, 3, 3, 4, /* 80 - 87 */
- 4, 4, 4, 4, 4, 4, 4, 5, /* 88 - 95 */
- 5, 5, 5, 5, 5, 5, 5, 5, /* 96 - 103 */
- 6, 6, 6, 6, 6, 6, 6, 6, /* 104 - 111 */
- 6, 7, 7, 7, 7, 7, 7, 7, /* 112 - 119 */
- 7, 7, 7, 8, 8, 8, 8, 8}; /* 120 - 127 */
+{-64, -48, -40, -35, -32, -29, -27, -26, /*
+ * 0 - 7
+ */
+ -24, -23, -21, -20, -19, -18, -18, -17, /*
+ * 8 - 15
+ */
+ -16, -15, -15, -14, -13, -13, -12, -12, /*
+ * 16 - 23
+ */
+ -11, -11, -10, -10, -10, -9, -9, -8, /*
+ * 24 - 31
+ */
+ -8, -8, -7, -7, -7, -6, -6, -6,/*
+ * 32 - 39
+ */
+ -5, -5, -5, -5, -4, -4, -4, -4,/*
+ * 40 - 47
+ */
+ -3, -3, -3, -3, -2, -2, -2, -2,/*
+ * 48 - 55
+ */
+ -2, -1, -1, -1, -1, 0, 0, 0, /*
+ * 56 - 63
+ */
+ 0, 0, 0, 1, 1, 1, 1, 1, /*
+ * 64 - 71
+ */
+ 1, 2, 2, 2, 2, 2, 2, 2, /*
+ * 72 - 79
+ */
+ 3, 3, 3, 3, 3, 3, 3, 4, /*
+ * 80 - 87
+ */
+ 4, 4, 4, 4, 4, 4, 4, 5, /*
+ * 88 - 95
+ */
+ 5, 5, 5, 5, 5, 5, 5, 5, /*
+ * 96 - 103
+ */
+ 6, 6, 6, 6, 6, 6, 6, 6, /*
+ * 104 - 111
+ */
+ 6, 7, 7, 7, 7, 7, 7, 7, /*
+ * 112 - 119
+ */
+ 7, 7, 7, 8, 8, 8, 8, 8}; /*
+
+
+ * * * * 120 - 127 */
static void
calc_vol (unsigned char *regbyte, int volume)
@@ -362,26 +451,40 @@ set_voice_volume (int voice, int volume)
return;
if (voices[voice].mode == 2)
- { /* 2 OP voice */
+ { /*
+ * 2 OP voice
+ */
vol1 = instr->operators[2];
vol2 = instr->operators[3];
if ((instr->operators[10] & 0x01))
- { /* Additive synthesis */
+ { /*
+ * Additive synthesis
+ */
calc_vol (&vol1, volume);
calc_vol (&vol2, volume);
}
else
- { /* FM synthesis */
+ { /*
+ * FM synthesis
+ */
calc_vol (&vol2, volume);
}
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1); /* Modulator volume */
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2); /* Carrier volume */
+ opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1); /*
+ * Modulator
+ * volume
+ */
+ opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], vol2); /*
+ * Carrier
+ * volume
+ */
}
else
- { /* 4 OP voice */
+ { /*
+ * 4 OP voice
+ */
int connection;
vol1 = instr->operators[2];
@@ -399,7 +502,9 @@ set_voice_volume (int voice, int volume)
switch (connection)
{
case 0:
- calc_vol (&vol4, volume); /* Just the OP 4 is carrier */
+ calc_vol (&vol4, volume); /*
+ * Just the OP 4 is carrier
+ */
break;
case 1:
@@ -418,7 +523,9 @@ set_voice_volume (int voice, int volume)
calc_vol (&vol4, volume);
break;
- default:/* Why ?? */ ;
+ default: /*
+ * Why ??
+ */ ;
}
opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], vol1);
@@ -444,15 +551,26 @@ opl3_start_note (int dev, int voice, int note, int volume)
if (map->voice_mode == 0)
return 0;
- if (note == 255) /* Just change the volume */
+ if (note == 255) /*
+ * Just change the volume
+ */
{
set_voice_volume (voice, volume);
return 0;
}
- /* Kill previous note before playing */
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], 0xff); /* Carrier volume to min */
- opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], 0xff); /* Modulator volume to */
+ /*
+ * Kill previous note before playing
+ */
+ opl3_command (map->ioaddr, KSL_LEVEL + map->op[1], 0xff); /*
+ * Carrier
+ * volume to
+ * min
+ */
+ opl3_command (map->ioaddr, KSL_LEVEL + map->op[0], 0xff); /*
+ * Modulator
+ * volume to
+ */
if (map->voice_mode == 4)
{
@@ -460,7 +578,10 @@ opl3_start_note (int dev, int voice, int note, int volume)
opl3_command (map->ioaddr, KSL_LEVEL + map->op[3], 0xff);
}
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, 0x00); /* Note off */
+ opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, 0x00); /*
+ * Note
+ * off
+ */
instr = active_instrument[voice];
@@ -476,7 +597,9 @@ opl3_start_note (int dev, int voice, int note, int volume)
}
if (map->voice_mode == 2 && instr->key == OPL3_PATCH)
- return 0; /* Cannot play */
+ return 0; /*
+ * Cannot play
+ */
voice_mode = map->voice_mode;
@@ -487,7 +610,9 @@ opl3_start_note (int dev, int voice, int note, int volume)
voice_shift = (map->ioaddr == left_address) ? 0 : 3;
voice_shift += map->voice_num;
- if (instr->key != OPL3_PATCH) /* Just 2 OP patch */
+ if (instr->key != OPL3_PATCH) /*
+ * Just 2 OP patch
+ */
{
voice_mode = 2;
connection_mask &= ~(1 << voice_shift);
@@ -500,26 +625,38 @@ opl3_start_note (int dev, int voice, int note, int volume)
opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask);
}
- /* Set Sound Characteristics */
+ /*
+ * Set Sound Characteristics
+ */
opl3_command (map->ioaddr, AM_VIB + map->op[0], instr->operators[0]);
opl3_command (map->ioaddr, AM_VIB + map->op[1], instr->operators[1]);
- /* Set Attack/Decay */
+ /*
+ * Set Attack/Decay
+ */
opl3_command (map->ioaddr, ATTACK_DECAY + map->op[0], instr->operators[4]);
opl3_command (map->ioaddr, ATTACK_DECAY + map->op[1], instr->operators[5]);
- /* Set Sustain/Release */
+ /*
+ * Set Sustain/Release
+ */
opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[0], instr->operators[6]);
opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[1], instr->operators[7]);
- /* Set Wave Select */
+ /*
+ * Set Wave Select
+ */
opl3_command (map->ioaddr, WAVE_SELECT + map->op[0], instr->operators[8]);
opl3_command (map->ioaddr, WAVE_SELECT + map->op[1], instr->operators[9]);
- /* Set Feedback/Connection */
+ /*
+ * Set Feedback/Connection
+ */
fpc = instr->operators[10];
if (!(fpc & 0x30))
- fpc |= 0x30; /* Ensure that at least one chn is enabled */
+ fpc |= 0x30; /*
+ * Ensure that at least one chn is enabled
+ */
opl3_command (map->ioaddr, FEEDBACK_CONNECTION + map->voice_num,
fpc);
@@ -530,26 +667,38 @@ opl3_start_note (int dev, int voice, int note, int volume)
if (voice_mode == 4)
{
- /* Set Sound Characteristics */
+ /*
+ * Set Sound Characteristics
+ */
opl3_command (map->ioaddr, AM_VIB + map->op[2], instr->operators[OFFS_4OP + 0]);
opl3_command (map->ioaddr, AM_VIB + map->op[3], instr->operators[OFFS_4OP + 1]);
- /* Set Attack/Decay */
+ /*
+ * Set Attack/Decay
+ */
opl3_command (map->ioaddr, ATTACK_DECAY + map->op[2], instr->operators[OFFS_4OP + 4]);
opl3_command (map->ioaddr, ATTACK_DECAY + map->op[3], instr->operators[OFFS_4OP + 5]);
- /* Set Sustain/Release */
+ /*
+ * Set Sustain/Release
+ */
opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[2], instr->operators[OFFS_4OP + 6]);
opl3_command (map->ioaddr, SUSTAIN_RELEASE + map->op[3], instr->operators[OFFS_4OP + 7]);
- /* Set Wave Select */
+ /*
+ * Set Wave Select
+ */
opl3_command (map->ioaddr, WAVE_SELECT + map->op[2], instr->operators[OFFS_4OP + 8]);
opl3_command (map->ioaddr, WAVE_SELECT + map->op[3], instr->operators[OFFS_4OP + 9]);
- /* Set Feedback/Connection */
+ /*
+ * Set Feedback/Connection
+ */
fpc = instr->operators[OFFS_4OP + 10];
if (!(fpc & 0x30))
- fpc |= 0x30; /* Ensure that at least one chn is enabled */
+ fpc |= 0x30; /*
+ * Ensure that at least one chn is enabled
+ */
opl3_command (map->ioaddr, FEEDBACK_CONNECTION + map->voice_num + 3, fpc);
}
@@ -569,9 +718,13 @@ opl3_start_note (int dev, int voice, int note, int volume)
freq_to_fnum (freq, &block, &fnum);
- /* Play note */
+ /*
+ * Play note
+ */
- data = fnum & 0xff; /* Least significant bits of fnumber */
+ data = fnum & 0xff; /*
+ * Least significant bits of fnumber
+ */
opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);
@@ -588,8 +741,12 @@ freq_to_fnum (int freq, int *block, int *fnum)
{
int f, octave;
- /* Converts the note frequency to block and fnum values for the FM chip */
- /* First try to compute the block -value (octave) where the note belongs */
+ /*
+ * Converts the note frequency to block and fnum values for the FM chip
+ */
+ /*
+ * First try to compute the block -value (octave) where the note belongs
+ */
f = freq;
@@ -631,7 +788,10 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
* register. The OPL-3 survives with just two INBs
*/
- OUTB ((unsigned char) (addr & 0xff), io_addr); /* Select register */
+ OUTB ((unsigned char) (addr & 0xff), io_addr); /*
+ * Select register
+ *
+ */
if (!opl3_enabled)
tenmicrosec ();
@@ -639,7 +799,10 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
for (i = 0; i < 2; i++)
INB (io_addr);
- OUTB ((unsigned char) (val & 0xff), io_addr + 1); /* Write to register */
+ OUTB ((unsigned char) (val & 0xff), io_addr + 1); /*
+ * Write to register
+ *
+ */
if (!opl3_enabled)
{
@@ -660,26 +823,26 @@ opl3_reset (int dev)
for (i = 0; i < nr_voices; i++)
{
opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[0], 0xff); /* OP1 volume to min */
+ KSL_LEVEL + physical_voices[logical_voices[i]].op[0], 0xff);
opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[1], 0xff); /* OP2 volume to min */
+ KSL_LEVEL + physical_voices[logical_voices[i]].op[1], 0xff);
- if (physical_voices[logical_voices[i]].voice_mode == 4) /* 4 OP voice */
+ if (physical_voices[logical_voices[i]].voice_mode == 4)
{
opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[2], 0xff); /* OP3 volume to min */
+ KSL_LEVEL + physical_voices[logical_voices[i]].op[2], 0xff);
opl3_command (physical_voices[logical_voices[i]].ioaddr,
- KSL_LEVEL + physical_voices[logical_voices[i]].op[3], 0xff); /* OP4 volume to min */
+ KSL_LEVEL + physical_voices[logical_voices[i]].op[3], 0xff);
}
- opl3_kill_note (dev, i, 64);
+ opl3_kill_note (dev, i, 0, 64);
}
if (opl3_enabled)
{
- nr_voices = 18;
+ voice_alloc->max_voice = nr_voices = 18;
for (i = 0; i < 18; i++)
logical_voices[i] = i;
@@ -700,7 +863,9 @@ opl3_open (int dev, int mode)
return RET_ERROR (EBUSY);
opl3_busy = 1;
- connection_mask = 0x00; /* Just 2 OP voices */
+ connection_mask = 0x00; /*
+ * Just 2 OP voices
+ */
if (opl3_enabled)
opl3_command (right_address, CONNECTION_SELECT_REGISTER, connection_mask);
return 0;
@@ -710,7 +875,7 @@ static void
opl3_close (int dev)
{
opl3_busy = 0;
- nr_voices = opl3_enabled ? 18 : 9;
+ voice_alloc->max_voice = nr_voices = opl3_enabled ? 18 : 9;
fm_info.nr_drums = 0;
fm_info.perc_mode = 0;
@@ -815,13 +980,17 @@ opl3_aftertouch (int dev, int voice, int pressure)
break;
}
- /* Not implemented yet */
+ /*
+ * Not implemented yet
+ */
}
else
{
SET_VIBRATO (1);
- if ((instr->operators[10] & 0x01)) /* Additive synthesis */
+ if ((instr->operators[10] & 0x01)) /*
+ * Additive synthesis
+ */
SET_VIBRATO (2);
}
}
@@ -829,41 +998,57 @@ opl3_aftertouch (int dev, int voice, int pressure)
#undef SET_VIBRATO
static void
-opl3_controller (int dev, int voice, int ctrl_num, int value)
+bend_pitch (int dev, int voice, int value)
{
unsigned char data;
int block, fnum, freq;
struct physical_voice_info *map;
- if (voice < 0 || voice >= nr_voices)
- return;
-
map = &physical_voices[logical_voices[voice]];
if (map->voice_mode == 0)
return;
- switch (ctrl_num)
- {
- case CTRL_PITCH_BENDER:
- voices[voice].bender = value;
- if (!value)
- return;
- if (!(voices[voice].keyon_byte & 0x20))
- return; /* Not keyed on */
+ voices[voice].bender = value;
+ if (!value)
+ return;
+ if (!(voices[voice].keyon_byte & 0x20))
+ return; /*
+ * Not keyed on
+ */
+
+ freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
+ voices[voice].current_freq = freq;
- freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, voices[voice].bender_range);
- voices[voice].current_freq = freq;
+ freq_to_fnum (freq, &block, &fnum);
- freq_to_fnum (freq, &block, &fnum);
+ data = fnum & 0xff; /*
+ * Least significant bits of fnumber
+ */
+ opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
- data = fnum & 0xff; /* Least significant bits of fnumber */
- opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
+ data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3); /*
+ * *
+ * KEYON|OCTAVE|MS
+ *
+ * * bits * *
+ * of * f-num
+ *
+ */
+ voices[voice].keyon_byte = data;
+ opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
+}
- data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3); /* KEYON|OCTAVE|MS bits
- * of f-num */
- voices[voice].keyon_byte = data;
- opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
+static void
+opl3_controller (int dev, int voice, int ctrl_num, int value)
+{
+ if (voice < 0 || voice >= nr_voices)
+ return;
+
+ switch (ctrl_num)
+ {
+ case CTRL_PITCH_BENDER:
+ bend_pitch (dev, voice, value);
break;
case CTRL_PITCH_BENDER_RANGE:
@@ -878,9 +1063,76 @@ opl3_patchmgr (int dev, struct patmgr_info *rec)
return RET_ERROR (EINVAL);
}
+static void
+opl3_bender (int dev, int voice, int value)
+{
+ if (voice < 0 || voice >= nr_voices)
+ return;
+
+ bend_pitch (dev, voice, value);
+}
+
+static int
+opl3_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
+{
+ int i, p, avail_voices;
+ struct sbi_instrument *instr;
+ int is4op;
+ int instr_no;
+
+ if (chn < 0 || chn > 15)
+ instr_no = 0;
+ else
+ instr_no = chn_info[chn].pgm_num;
+
+ instr = &instrmap[instr_no];
+ if (instr->channel < 0 || /* Instrument not loaded */
+ nr_voices != 12) /* Not in 4 OP mode */
+ is4op = 0;
+ else if (nr_voices == 12) /* 4 OP mode */
+ is4op = (instr->key == OPL3_PATCH);
+ else
+ is4op = 0;
+
+ if (is4op)
+ {
+ p = 0;
+ avail_voices = 6;
+ }
+ else
+ {
+ if (nr_voices == 12) /* 4 OP mode. Use the '2 OP only' voices first */
+ p = 6;
+ else
+ p = 0;
+ avail_voices = nr_voices;
+ }
+
+ /*
+ * Now try to find a free voice
+ */
+
+ for (i = 0; i < avail_voices; i++)
+ {
+ if (alloc->map[p] == 0)
+ {
+ return p;
+ }
+ p = (p + 1) % nr_voices;
+ }
+
+ /*
+ * Insert some kind of priority mechanism here.
+ */
+
+ printk ("OPL3: Out of free voices\n");
+ return 0; /* All voices in use. Select the first one. */
+}
+
static struct synth_operations opl3_operations =
{
&fm_info,
+ 0,
SYNTH_TYPE_FM,
FM_TYPE_ADLIB,
opl3_open,
@@ -896,7 +1148,9 @@ static struct synth_operations opl3_operations =
opl3_controller,
opl3_panning,
opl3_volume_method,
- opl3_patchmgr
+ opl3_patchmgr,
+ opl3_bender,
+ opl3_alloc_voice
};
long
@@ -907,7 +1161,15 @@ opl3_init (long mem_start)
PERMANENT_MALLOC (struct sbi_instrument *, instrmap,
SBFM_MAXINSTR * sizeof (*instrmap), mem_start);
- synth_devs[num_synths++] = &opl3_operations;
+ if (num_synths >= MAX_SYNTH_DEV)
+ printk ("OPL3 Error: Too many synthesizers\n");
+ else
+ {
+ synth_devs[num_synths++] = &opl3_operations;
+ voice_alloc = &opl3_operations.alloc;
+ chn_info = &opl3_operations.chn_info[0];
+ }
+
fm_model = 0;
opl3_ok = 1;
if (opl3_enabled)
@@ -918,7 +1180,7 @@ opl3_init (long mem_start)
printk (" <Yamaha OPL-3 FM>");
#endif
fm_model = 2;
- nr_voices = 18;
+ voice_alloc->max_voice = nr_voices = 18;
fm_info.nr_drums = 0;
fm_info.capabilities |= SYNTH_CAP_OPL3;
#ifndef SCO
@@ -931,10 +1193,11 @@ opl3_init (long mem_start)
else
physical_voices[i].ioaddr = right_address;
+ /* Enable OPL-3 mode */
+ opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE);
- opl3_command (right_address, OPL3_MODE_REGISTER, OPL3_ENABLE); /* Enable OPL-3 mode */
- opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x00); /* Select all 2-OP
- * voices */
+ /* Select all 2-OP voices */
+ opl3_command (right_address, CONNECTION_SELECT_REGISTER, 0x00);
}
else
{
@@ -944,7 +1207,7 @@ opl3_init (long mem_start)
printk (" <Yamaha 2-OP FM>");
#endif
fm_model = 1;
- nr_voices = 9;
+ voice_alloc->max_voice = nr_voices = 9;
fm_info.nr_drums = 0;
for (i = 0; i < 18; i++)
diff --git a/sys/i386/isa/sound/opl3.h b/sys/i386/isa/sound/opl3.h
index eeb8fef..ea7901f 100644
--- a/sys/i386/isa/sound/opl3.h
+++ b/sys/i386/isa/sound/opl3.h
@@ -24,7 +24,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
*/
/*
diff --git a/sys/i386/isa/sound/os.h b/sys/i386/isa/sound/os.h
index ee187b6..005b3c2 100644
--- a/sys/i386/isa/sound/os.h
+++ b/sys/i386/isa/sound/os.h
@@ -37,7 +37,7 @@
* before making the changes. It's possible that I have already made the
* change.
*
- * $Id: os.h,v 1.11 1994/08/02 07:40:16 davidg Exp $
+ * $Id: os.h,v 1.12 1994/09/27 17:58:21 davidg Exp $
*/
/*
@@ -290,7 +290,8 @@ extern unsigned long get_time(void);
* memory area. The type is the type of the mem_ptr.
*/
#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \
- (mem_ptr) = (typecast)malloc((size), M_TEMP, M_WAITOK)
+ {(mem_ptr) = (typecast)malloc((size), M_DEVBUF, M_NOWAIT); \
+ if (!(mem_ptr))panic("SOUND: Cannot allocate memory\n");}
/*
* The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if
diff --git a/sys/i386/isa/sound/pas.h b/sys/i386/isa/sound/pas.h
index 29f9ff6..34fd322 100644
--- a/sys/i386/isa/sound/pas.h
+++ b/sys/i386/isa/sound/pas.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: pas.h,v 1.4 1994/08/02 07:40:19 davidg Exp $
*/
/* */
/* Port addresses and bit fields for the Media Vision Pro AudioSpectrum second generation sound cards. */
@@ -138,25 +138,25 @@
#define PAS_16D 4
#ifdef DEFINE_TRANSLATIONS
- char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */
+ unsigned char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */
{ 4, 1, 2, 3, 0, 5, 6, 7 };
- char I_C_3_PCM_IRQ_translate[] = /* R W PCM PCM IRQ level value translation */
+ unsigned char I_C_3_PCM_IRQ_translate[] = /* R W PCM PCM IRQ level value translation */
{ 0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11 };
- char E_C_MPU401_IRQ_translate[] = /* R W MIDI MPU401 emulation IRQ value translation */
+ unsigned char E_C_MPU401_IRQ_translate[] = /* R W MIDI MPU401 emulation IRQ value translation */
{ 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x05, 0x06, 0x07 };
- char E_C_SB_IRQ_translate[] = /* R W PCM SB emulation IRQ translate */
+ unsigned char E_C_SB_IRQ_translate[] = /* R W PCM SB emulation IRQ translate */
{ 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0 };
- char E_C_SB_DMA_translate[] = /* R W PCM SB emulation DMA translate */
+ unsigned char E_C_SB_DMA_translate[] = /* R W PCM SB emulation DMA translate */
{ 0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0 };
- char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */
+ unsigned char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 2, 3 };
#else
- extern char I_C_2_PCM_DMA_translate[]; /* R W PCM PCM DMA channel value translations */
- extern char I_C_3_PCM_IRQ_translate[]; /* R W PCM PCM IRQ level value translation */
- extern char E_C_MPU401_IRQ_translate[]; /* R W MIDI MPU401 emulation IRQ value translation */
- extern char E_C_SB_IRQ_translate[]; /* R W PCM SB emulation IRQ translate */
- extern char E_C_SB_DMA_translate[]; /* R W PCM SB emulation DMA translate */
- extern char O_M_1_to_card[]; /* R W Control Translate (OM1 & 0x0f) to card type */
+ extern unsigned char I_C_2_PCM_DMA_translate[]; /* R W PCM PCM DMA channel value translations */
+ extern unsigned char I_C_3_PCM_IRQ_translate[]; /* R W PCM PCM IRQ level value translation */
+ extern unsigned char E_C_MPU401_IRQ_translate[]; /* R W MIDI MPU401 emulation IRQ value translation */
+ extern unsigned char E_C_SB_IRQ_translate[]; /* R W PCM SB emulation IRQ translate */
+ extern unsigned char E_C_SB_DMA_translate[]; /* R W PCM SB emulation DMA translate */
+ extern unsigned char O_M_1_to_card[]; /* R W Control Translate (OM1 & 0x0f) to card type */
#endif
#define PARALLEL_MIXER 0x078B /* W Mixer Documented for MVD101 as FM Mono Right decode?? */
diff --git a/sys/i386/isa/sound/pas2_card.c b/sys/i386/isa/sound/pas2_card.c
index fc023a0..63f5235 100644
--- a/sys/i386/isa/sound/pas2_card.c
+++ b/sys/i386/isa/sound/pas2_card.c
@@ -1,5 +1,4 @@
#define _PAS2_CARD_C_
-#define SND_SA_INTERRUPT
/*
* sound/pas2_card.c
*
@@ -27,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: pas2_card.c,v 1.9 1994/08/02 07:40:20 davidg Exp $
*/
#include "sound_config.h"
@@ -52,9 +51,15 @@ static unsigned char board_rev_id;
static char *pas_model_names[] =
{"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
-/* pas_read() and pas_write() are equivalents of INB() and OUTB() */
-/* These routines perform the I/O address translation required */
-/* to support other than the default base address */
+/*
+ * pas_read() and pas_write() are equivalents of INB() and OUTB()
+ */
+/*
+ * These routines perform the I/O address translation required
+ */
+/*
+ * to support other than the default base address
+ */
unsigned char
pas_read (int ioaddr)
@@ -99,7 +104,9 @@ pasintr (int unused)
int status;
status = pas_read (INTERRUPT_STATUS);
- pas_write (status, INTERRUPT_STATUS); /* Clear interrupt */
+ pas_write (status, INTERRUPT_STATUS); /*
+ * Clear interrupt
+ */
if (status & I_S_PCM_SAMPLE_BUFFER_IRQ)
{
@@ -163,27 +170,39 @@ int
config_pas_hw (struct address_info *hw_config)
{
char ok = 1;
+ unsigned int_ptrs; /* scsi/sound interrupt pointers */
pas_irq = hw_config->irq;
pas_write (0x00, INTERRUPT_MASK);
- pas_write (0x36, SAMPLE_COUNTER_CONTROL); /* Local timer control
- * register */
+ pas_write (0x36, SAMPLE_COUNTER_CONTROL); /*
+ * Local timer control *
+ * register
+ */
- pas_write (0x36, SAMPLE_RATE_TIMER); /* Sample rate timer (16 bit) */
+ pas_write (0x36, SAMPLE_RATE_TIMER); /*
+ * Sample rate timer (16 bit)
+ */
pas_write (0, SAMPLE_RATE_TIMER);
- pas_write (0x74, SAMPLE_COUNTER_CONTROL); /* Local timer control
- * register */
+ pas_write (0x74, SAMPLE_COUNTER_CONTROL); /*
+ * Local timer control *
+ * register
+ */
- pas_write (0x74, SAMPLE_BUFFER_COUNTER); /* Sample count register (16
- * bit) */
+ pas_write (0x74, SAMPLE_BUFFER_COUNTER); /*
+ * Sample count register (16
+ * * bit)
+ */
pas_write (0, SAMPLE_BUFFER_COUNTER);
pas_write (F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY);
pas_write (P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL);
- pas_write (S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* | S_M_OPL3_DUAL_MONO */ , SERIAL_MIXER);
+ pas_write (S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /*
+ * |
+ * S_M_OPL3_DUAL_MONO
+ */ , SERIAL_MIXER);
pas_write (I_C_1_BOOT_RESET_ENABLE, IO_CONFIGURATION_1);
@@ -194,7 +213,9 @@ config_pas_hw (struct address_info *hw_config)
}
else
{
- pas_write (I_C_3_PCM_IRQ_translate[pas_irq], IO_CONFIGURATION_3);
+ int_ptrs = pas_read (IO_CONFIGURATION_3);
+ int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf;
+ pas_write (int_ptrs, IO_CONFIGURATION_3);
if (!I_C_3_PCM_IRQ_translate[pas_irq])
{
printk ("PAS2: Invalid IRQ %d", pas_irq);
@@ -229,14 +250,23 @@ config_pas_hw (struct address_info *hw_config)
#ifdef BROKEN_BUS_CLOCK
pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1);
#else
- /* pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1); */
+ /*
+ * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1);
+ */
pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1);
#endif
- pas_write (0x18, SYSTEM_CONFIGURATION_3); /* ??? */
-
- pas_write (F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* Sets mute off and
- * selects filter rate
- * of 17.897 kHz */
+ pas_write (0x18, SYSTEM_CONFIGURATION_3); /*
+ * ???
+ */
+
+ pas_write (F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /*
+ * Sets mute
+ * off and *
+ * selects
+ * filter
+ * rate * of
+ * 17.897 kHz
+ */
if (pas_model == PAS_16 || pas_model == PAS_16D)
pas_write (8, PRESCALE_DIVIDER);
@@ -255,12 +285,20 @@ config_pas_hw (struct address_info *hw_config)
{
unsigned char irq_dma;
- /* Turn on Sound Blaster compatibility */
- /* bit 1 = SB emulation */
- /* bit 0 = MPU401 emulation (CDPC only :-( ) */
+ /*
+ * Turn on Sound Blaster compatibility
+ */
+ /*
+ * bit 1 = SB emulation
+ */
+ /*
+ * bit 0 = MPU401 emulation (CDPC only :-( )
+ */
pas_write (0x02, COMPATIBILITY_ENABLE);
- /* "Emulation address" */
+ /*
+ * "Emulation address"
+ */
pas_write ((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS);
if (!E_C_SB_DMA_translate[sb_config->dma])
@@ -297,10 +335,16 @@ detect_pas_hw (struct address_info *hw_config)
* you have something on base port 0x388. SO be forewarned.
*/
- OUTB (0xBC, MASTER_DECODE); /* Talk to first board */
- OUTB (hw_config->io_base >> 2, MASTER_DECODE); /* Set base address */
+ OUTB (0xBC, MASTER_DECODE); /*
+ * Talk to first board
+ */
+ OUTB (hw_config->io_base >> 2, MASTER_DECODE); /*
+ * Set base address
+ */
translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base;
- pas_write (1, WAIT_STATE); /* One wait-state */
+ pas_write (1, WAIT_STATE); /*
+ * One wait-state
+ */
board_id = pas_read (INTERRUPT_MASK);
@@ -319,7 +363,9 @@ detect_pas_hw (struct address_info *hw_config)
foo = INB (INTERRUPT_MASK);
pas_write (board_id, INTERRUPT_MASK);
- if (board_id != foo) /* Not a PAS2 */
+ if (board_id != foo) /*
+ * Not a PAS2
+ */
return 0;
pas_model = O_M_1_to_card[pas_read (OPERATION_MODE_1) & 0x0f];
@@ -335,14 +381,14 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
if (detect_pas_hw (hw_config))
{
- board_rev_id = pas_read (BOARD_REV_ID);
+ board_rev_id = pas_read (BOARD_REV_ID);
if ((pas_model = O_M_1_to_card[pas_read (OPERATION_MODE_1) & 0x0f]))
{
#ifdef __FreeBSD__
printk ("snd3: <%s rev %d>", pas_model_names[(int) pas_model], board_rev_id);
-#else
- printk (" <%s rev %d>", pas_model_names[(int) pas_model], board_rev_id);
-#endif
+#else /* __FreeBSD__ */
+ printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID));
+#endif /* __FreeBSD__ */
}
if (config_pas_hw (hw_config))
@@ -354,8 +400,10 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
- sb_dsp_disable_midi (); /* The SB emulation don't support
- * midi */
+ sb_dsp_disable_midi (); /*
+ * The SB emulation don't support *
+ * midi
+ */
#endif
#ifndef EXCLUDE_YM3812
diff --git a/sys/i386/isa/sound/pas2_midi.c b/sys/i386/isa/sound/pas2_midi.c
index e502db9..817e7d1 100644
--- a/sys/i386/isa/sound/pas2_midi.c
+++ b/sys/i386/isa/sound/pas2_midi.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: pas2_midi.c,v 1.5 1994/08/02 07:40:22 davidg Exp $
*/
#include "sound_config.h"
@@ -63,7 +63,9 @@ pas_midi_open (int dev, int mode,
return RET_ERROR (EBUSY);
}
- /* Reset input and output FIFO pointers */
+ /*
+ * Reset input and output FIFO pointers
+ */
pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
MIDI_CONTROL);
@@ -72,7 +74,9 @@ pas_midi_open (int dev, int mode,
if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0)
return err;
- /* Enable input available and output FIFO empty interrupts */
+ /*
+ * Enable input available and output FIFO empty interrupts
+ */
ctrl = 0;
input_opened = 0;
@@ -80,20 +84,26 @@ pas_midi_open (int dev, int mode,
if (mode == OPEN_READ || mode == OPEN_READWRITE)
{
- ctrl |= M_C_ENA_INPUT_IRQ;/* Enable input */
+ ctrl |= M_C_ENA_INPUT_IRQ;/*
+ * Enable input
+ */
input_opened = 1;
}
if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
{
- ctrl |= M_C_ENA_OUTPUT_IRQ | /* Enable output */
+ ctrl |= M_C_ENA_OUTPUT_IRQ | /*
+ * Enable output
+ */
M_C_ENA_OUTPUT_HALF_IRQ;
}
pas_write (ctrl,
MIDI_CONTROL);
- /* Acknowledge any pending interrupts */
+ /*
+ * Acknowledge any pending interrupts
+ */
pas_write (0xff, MIDI_STATUS);
ofifo_bytes = 0;
@@ -109,7 +119,9 @@ static void
pas_midi_close (int dev)
{
- /* Reset FIFO pointers, disable intrs */
+ /*
+ * Reset FIFO pointers, disable intrs
+ */
pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL);
pas_remove_intr (I_M_MIDI_IRQ_ENABLE);
@@ -123,9 +135,14 @@ dump_to_midi (unsigned char midi_byte)
fifo_space = ((x = pas_read (MIDI_FIFO_STATUS)) >> 4) & 0x0f;
- if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) /* Fifo full */
+ if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) /*
+ * Fifo
+ * full
+ */
{
- return 0; /* Upper layer will call again */
+ return 0; /*
+ * Upper layer will call again
+ */
}
ofifo_bytes++;
@@ -161,14 +178,18 @@ pas_midi_out (int dev, unsigned char midi_byte)
if (!qlen)
if (dump_to_midi (midi_byte))
- return 1; /* OK */
+ return 1; /*
+ * OK
+ */
/*
* Put to the local queue
*/
if (qlen >= 256)
- return 0; /* Local queue full */
+ return 0; /*
+ * Local queue full
+ */
DISABLE_INTR (flags);
@@ -211,9 +232,14 @@ pas_buffer_status (int dev)
return !qlen;
}
+#define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi"
+#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
+#include "midi_synth.h"
+
static struct midi_operations pas_midi_operations =
{
{"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
+ &std_midi_synth,
pas_midi_open,
pas_midi_close,
pas_midi_ioctl,
@@ -221,14 +247,23 @@ static struct midi_operations pas_midi_operations =
pas_midi_start_read,
pas_midi_end_read,
pas_midi_kick,
- NULL, /* command */
- pas_buffer_status
+ NULL, /*
+ * command
+ */
+ pas_buffer_status,
+ NULL
};
long
pas_midi_init (long mem_start)
{
- my_dev = num_midis;
+ if (num_midis >= MAX_MIDI_DEV)
+ {
+ printk ("Sound: Too many midi devices detected\n");
+ return mem_start;
+ }
+
+ std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &pas_midi_operations;
return mem_start;
}
@@ -242,9 +277,13 @@ pas_midi_interrupt (void)
stat = pas_read (MIDI_STATUS);
- if (stat & M_S_INPUT_AVAIL) /* Input byte available */
+ if (stat & M_S_INPUT_AVAIL) /*
+ * Input byte available
+ */
{
- incount = pas_read (MIDI_FIFO_STATUS) & 0x0f; /* Input FIFO count */
+ incount = pas_read (MIDI_FIFO_STATUS) & 0x0f; /*
+ * Input FIFO count
+ */
if (!incount)
incount = 16;
@@ -254,7 +293,9 @@ pas_midi_interrupt (void)
midi_input_intr (my_dev, pas_read (MIDI_DATA));
}
else
- pas_read (MIDI_DATA); /* Flush */
+ pas_read (MIDI_DATA); /*
+ * Flush
+ */
}
if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY))
@@ -288,7 +329,9 @@ pas_midi_interrupt (void)
ofifo_bytes = 100;
}
- pas_write (stat, MIDI_STATUS);/* Acknowledge interrupts */
+ pas_write (stat, MIDI_STATUS);/*
+ * Acknowledge interrupts
+ */
}
#endif
diff --git a/sys/i386/isa/sound/pas2_mixer.c b/sys/i386/isa/sound/pas2_mixer.c
index 8d83df4..7a4ccbd 100644
--- a/sys/i386/isa/sound/pas2_mixer.c
+++ b/sys/i386/isa/sound/pas2_mixer.c
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: pas2_mixer.c,v 1.6 1994/08/02 07:40:24 davidg Exp $
*/
#include "sound_config.h"
@@ -36,11 +36,18 @@
#include "pas.h"
-#define TRACE(what) /* (what) */
+#define TRACE(what) /*
+ * * * (what) */
extern int translat_code;
-static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */
+static int rec_devices = (SOUND_MASK_MIC); /*
+
+
+ * * * * Default *
+ * recording * source
+ *
+ * * */
static int mode_control = 0;
#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
@@ -53,34 +60,65 @@ static int mode_control = 0;
static unsigned short levels[SOUND_MIXER_NRDEVICES] =
{
- 0x3232, /* Master Volume */
- 0x3232, /* Bass */
- 0x3232, /* Treble */
- 0x5050, /* FM */
- 0x4b4b, /* PCM */
- 0x3232, /* PC Speaker */
- 0x4b4b, /* Ext Line */
- 0x4b4b, /* Mic */
- 0x4b4b, /* CD */
- 0x6464, /* Recording monitor */
- 0x4b4b, /* SB PCM */
- 0x6464}; /* Recording level */
+ 0x3232, /*
+ * Master Volume
+ */
+ 0x3232, /*
+ * Bass
+ */
+ 0x3232, /*
+ * Treble
+ */
+ 0x5050, /*
+ * FM
+ */
+ 0x4b4b, /*
+ * PCM
+ */
+ 0x3232, /*
+ * PC Speaker
+ */
+ 0x4b4b, /*
+ * Ext Line
+ */
+ 0x4b4b, /*
+ * Mic
+ */
+ 0x4b4b, /*
+ * CD
+ */
+ 0x6464, /*
+ * Recording monitor
+ */
+ 0x4b4b, /*
+ * SB PCM
+ */
+ 0x6464}; /*
+
+
+ * * * * Recording level */
static int
mixer_output (int right_vol, int left_vol, int div, int bits,
- int mixer /* Input or output mixer */ )
+ int mixer /*
+ * Input or output mixer
+ */ )
{
int left = left_vol * div / 100;
int right = right_vol * div / 100;
if (bits & P_M_MV508_MIXER)
- { /* Select input or output mixer */
+ { /*
+ * Select input or output mixer
+ */
left |= mixer;
right |= mixer;
}
if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE)
- { /* Bass and trebble are mono devices */
+ { /*
+ * Bass and trebble are mono devices
+ */
mix_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER);
mix_write (left, PARALLEL_MIXER);
right_vol = left_vol;
@@ -123,7 +161,9 @@ pas_mixer_set (int whichDev, unsigned int level)
switch (whichDev)
{
- case SOUND_MIXER_VOLUME: /* Master volume (0-63) */
+ case SOUND_MIXER_VOLUME: /*
+ * Master volume (0-63)
+ */
levels[whichDev] = mixer_output (right, left, 63, P_M_MV508_MASTER_A, 0);
break;
@@ -131,40 +171,62 @@ pas_mixer_set (int whichDev, unsigned int level)
* Note! Bass and Treble are mono devices. Will use just the left
* channel.
*/
- case SOUND_MIXER_BASS: /* Bass (0-12) */
+ case SOUND_MIXER_BASS: /*
+ * Bass (0-12)
+ */
levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_BASS, 0);
break;
- case SOUND_MIXER_TREBLE: /* Treble (0-12) */
+ case SOUND_MIXER_TREBLE: /*
+ * Treble (0-12)
+ */
levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_TREBLE, 0);
break;
- case SOUND_MIXER_SYNTH: /* Internal synthesizer (0-31) */
+ case SOUND_MIXER_SYNTH: /*
+ * Internal synthesizer (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer);
break;
- case SOUND_MIXER_PCM: /* PAS PCM (0-31) */
+ case SOUND_MIXER_PCM: /*
+ * PAS PCM (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer);
break;
- case SOUND_MIXER_ALTPCM: /* SB PCM (0-31) */
+ case SOUND_MIXER_ALTPCM: /*
+ * SB PCM (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer);
break;
- case SOUND_MIXER_SPEAKER: /* PC speaker (0-31) */
+ case SOUND_MIXER_SPEAKER: /*
+ * PC speaker (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer);
break;
- case SOUND_MIXER_LINE: /* External line (0-31) */
+ case SOUND_MIXER_LINE: /*
+ * External line (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer);
break;
- case SOUND_MIXER_CD: /* CD (0-31) */
+ case SOUND_MIXER_CD: /*
+ * CD (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer);
break;
- case SOUND_MIXER_MIC: /* External microphone (0-31) */
+ case SOUND_MIXER_MIC: /*
+ * External microphone (0-31)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer);
break;
- case SOUND_MIXER_IMIX: /* Recording monitor (0-31) (Only available
- * on the Output Mixer) */
+ case SOUND_MIXER_IMIX: /*
+ * Recording monitor (0-31) (Only available *
+ * on the Output Mixer)
+ */
levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER,
P_M_MV508_OUTPUTMIX);
break;
- case SOUND_MIXER_RECLEV: /* Recording level (0-15) */
+ case SOUND_MIXER_RECLEV: /*
+ * Recording level (0-15)
+ */
levels[whichDev] = mixer_output (right, left, 15, P_M_MV508_MASTER_B, 0);
break;
@@ -192,7 +254,9 @@ pas_mixer_set (int whichDev, unsigned int level)
if (level)
mode_control |= P_M_MV508_LOUDNESS;
set_mode (mode_control);
- return !!level; /* 0 or 1 */
+ return !!level; /*
+ * 0 or 1
+ */
break;
case SOUND_MIXER_RECSRC:
@@ -219,91 +283,6 @@ pas_mixer_set (int whichDev, unsigned int level)
/*****/
static int
-mixer_set_levels (struct sb_mixer_levels *user_l)
-{
-#define cmix(v) ((((v.r*100+7)/15)<<8)| ((v.l*100+7)/15))
-
- struct sb_mixer_levels l;
-
- IOCTL_FROM_USER ((char *) &l, (char *) user_l, 0, sizeof (l));
-
- if (l.master.l & ~0xF || l.master.r & ~0xF
- || l.line.l & ~0xF || l.line.r & ~0xF
- || l.voc.l & ~0xF || l.voc.r & ~0xF
- || l.fm.l & ~0xF || l.fm.r & ~0xF
- || l.cd.l & ~0xF || l.cd.r & ~0xF
- || l.mic & ~0x7)
- return (RET_ERROR (EINVAL));
-
- pas_mixer_set (SOUND_MIXER_VOLUME, cmix (l.master));
- pas_mixer_set (SOUND_MIXER_LINE, cmix (l.line));
- pas_mixer_set (SOUND_MIXER_PCM, cmix (l.voc));
- pas_mixer_set (SOUND_MIXER_ALTPCM, cmix (l.voc));
- pas_mixer_set (SOUND_MIXER_SYNTH, cmix (l.fm));
- pas_mixer_set (SOUND_MIXER_CD, cmix (l.cd));
- pas_mixer_set (SOUND_MIXER_MIC, ((l.mic * 100 + 3) / 7) | (((l.mic * 100 + 3) / 7) << 8));
- return (0);
-}
-
-/*
- * This sets aspects of the Mixer that are not volume levels. (Recording
- * source, filter level, I/O filtering, and stereo.)
- */
-static int
-mixer_set_params (struct sb_mixer_params *user_p)
-{
- struct sb_mixer_params p;
- S_BYTE val;
- int src;
- unsigned long flags;
-
- IOCTL_FROM_USER ((char *) &p, (char *) user_p, 0, sizeof (p));
-
- if (p.record_source != SRC_MIC
- && p.record_source != SRC_CD
- && p.record_source != SRC_LINE)
- return (RET_ERROR (EINVAL));
-
- /*
- * I'm not sure if this is The Right Thing. Should stereo be entirely
- * under control of DSP? I like being able to toggle it while a sound is
- * playing, so I do this... because I can.
- */
-
- DISABLE_INTR (flags);
-
- val = (pas_read (PCM_CONTROL) & ~P_C_MIXER_CROSS_FIELD) | P_C_MIXER_CROSS_R_TO_R | P_C_MIXER_CROSS_L_TO_L;
- if (!p.dsp_stereo)
- val |= (P_C_MIXER_CROSS_R_TO_L | P_C_MIXER_CROSS_L_TO_R); /* Mono */
- pas_write (val, PCM_CONTROL);
-
- RESTORE_INTR (flags);
-
- switch (p.record_source)
- {
- case SRC_CD:
- src = SOUND_MASK_CD;
- break;
-
- case SRC_LINE:
- src = SOUND_MASK_LINE;
- break;
-
- default:
- src = SOUND_MASK_MIC;
- break;
- }
-
- pas_mixer_set (SOUND_MIXER_RECSRC, src);
-
- /*
- * setmixer (OUT_FILTER, ((dsp_stereo ? STEREO_DAC : MONO_DAC) |
- * (p.filter_output ? FILT_ON : FILT_OFF)));
- */
- return (0);
-}
-
-static int
getmixer (int dev, int chn)
{
if (chn == P_M_MV508_RIGHT)
@@ -316,73 +295,6 @@ getmixer (int dev, int chn)
}
}
-/* Read the current mixer level settings into the user's struct. */
-static int
-mixer_get_levels (struct sb_mixer_levels *user_l)
-{
-
- struct sb_mixer_levels l;
-
- l.master.r = ((((levels[SOUND_MIXER_VOLUME] >> 8) & 0x7f) * 15) + 50) / 100; /* Master */
- l.master.l = (((levels[SOUND_MIXER_VOLUME] & 0x7f) * 15) + 50) / 100; /* Master */
-
- l.line.r = ((getmixer (SOUND_MIXER_LINE, P_M_MV508_RIGHT) * 15) + 50) / 100; /* Line */
- l.line.l = ((getmixer (SOUND_MIXER_LINE, P_M_MV508_LEFT) * 15) + 50) / 100;
-
- l.voc.r = ((getmixer (SOUND_MIXER_PCM, P_M_MV508_RIGHT) * 15) + 50) / 100; /* DAC */
- l.voc.l = ((getmixer (SOUND_MIXER_PCM, P_M_MV508_LEFT) * 15) + 50) / 100;
-
- l.fm.r = ((getmixer (SOUND_MIXER_SYNTH, P_M_MV508_RIGHT) * 15) + 50) / 100; /* FM */
- l.fm.l = ((getmixer (SOUND_MIXER_SYNTH, P_M_MV508_LEFT) * 15) + 50) / 100;
-
- l.cd.r = ((getmixer (SOUND_MIXER_CD, P_M_MV508_RIGHT) * 15) + 50) / 100; /* CD */
- l.cd.l = ((getmixer (SOUND_MIXER_CD, P_M_MV508_LEFT) * 15) + 50) / 100;
-
- l.mic = ((getmixer (SOUND_MIXER_MIC, P_M_MV508_LEFT) * 7) + 50) / 100; /* Microphone */
-
- IOCTL_TO_USER ((char *) user_l, 0, (char *) &l, sizeof (l));
- return (0);
-}
-
-/* Read the current mixer parameters into the user's struct. */
-static int
-mixer_get_params (struct sb_mixer_params *user_params)
-{
- S_BYTE val;
- struct sb_mixer_params params;
-
- switch (rec_devices)
- {
- case SOUND_MASK_CD:
- params.record_source = SRC_CD;
- break;
-
- case SOUND_MASK_LINE:
- params.record_source = SRC_LINE;
- break;
-
- case SOUND_MASK_MIC:
- params.record_source = SRC_MIC;
- break;
-
- default:
- params.record_source = SRC_MIC;
- pas_mixer_set (SOUND_MIXER_RECSRC, SOUND_MASK_MIC); /* Adjust */
- }
-
- params.hifreq_filter = OFF;
- params.filter_input = OFF;
- params.filter_output = OFF;
-
- val = INB (PCM_CONTROL);
- params.dsp_stereo = ((val & P_C_MIXER_CROSS_FIELD) == (P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R));
-
- IOCTL_TO_USER ((char *) user_params, 0, (char *) &params, sizeof (params));
- return (0);
-}
-
-/*****/
-
static void
pas_mixer_reset (void)
{
@@ -406,7 +318,9 @@ pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
if (cmd & IOC_IN)
return IOCTL_OUT (arg, pas_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
else
- { /* Read parameters */
+ { /*
+ * Read parameters
+ */
switch (cmd & 0xff)
{
@@ -428,11 +342,15 @@ pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
break;
case SOUND_MIXER_CAPS:
- return IOCTL_OUT (arg, 0); /* No special capabilities */
+ return IOCTL_OUT (arg, 0); /*
+ * No special capabilities
+ */
break;
case SOUND_MIXER_MUTE:
- return IOCTL_OUT (arg, 0); /* No mute yet */
+ return IOCTL_OUT (arg, 0); /*
+ * No mute yet
+ */
break;
case SOUND_MIXER_ENHANCE:
@@ -452,27 +370,6 @@ pas_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
}
}
}
- else
- {
- switch (cmd)
- {
- case MIXER_IOCTL_SET_LEVELS:
- mixer_set_levels ((struct sb_mixer_levels *) arg);
- return mixer_get_levels ((struct sb_mixer_levels *) arg);
- case MIXER_IOCTL_SET_PARAMS:
- mixer_set_params ((struct sb_mixer_params *) arg);
- return mixer_get_params ((struct sb_mixer_params *) arg);
- case MIXER_IOCTL_READ_LEVELS:
- return mixer_get_levels ((struct sb_mixer_levels *) arg);
- case MIXER_IOCTL_READ_PARAMS:
- return mixer_get_params ((struct sb_mixer_params *) arg);
- case MIXER_IOCTL_RESET:
- pas_mixer_reset ();
- return (0);
- default:
- return RET_ERROR (EINVAL);
- }
- }
return RET_ERROR (EINVAL);
}
@@ -486,7 +383,8 @@ pas_init_mixer (void)
{
pas_mixer_reset ();
- mixer_devs[num_mixers++] = &pas_mixer_operations;
+ if (num_mixers < MAX_MIXER_DEV)
+ mixer_devs[num_mixers++] = &pas_mixer_operations;
return 1;
}
diff --git a/sys/i386/isa/sound/pas2_pcm.c b/sys/i386/isa/sound/pas2_pcm.c
index 1eef59b..e286215 100644
--- a/sys/i386/isa/sound/pas2_pcm.c
+++ b/sys/i386/isa/sound/pas2_pcm.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: pas2_pcm.c,v 1.6 1994/08/02 07:40:28 davidg Exp $
*/
#include "sound_config.h"
@@ -37,17 +37,20 @@
#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_AUDIO)
-#define TRACE(WHAT) /* (WHAT) */
+#define TRACE(WHAT) /*
+ * * * (WHAT) */
#define PAS_PCM_INTRBITS (0x08)
-/* Sample buffer timer interrupt enable */
+/*
+ * Sample buffer timer interrupt enable
+ */
#define PCM_NON 0
#define PCM_DAC 1
#define PCM_ADC 2
static unsigned long pcm_speed = 0; /* sampling rate */
-static unsigned char pcm_channels = 1; /* channels/sample (1 or 2) */
+static unsigned char pcm_channels = 1; /* channels (1 or 2) */
static unsigned char pcm_bits = 8; /* bits/sample (8 or 16) */
static unsigned char pcm_filter = 0; /* filter FLAG */
static unsigned char pcm_mode = PCM_NON;
@@ -66,7 +69,7 @@ pcm_set_speed (int arg)
if (arg < 5000)
arg = 5000;
- foo = 1193180 / arg;
+ foo = (1193180 + (arg / 2)) / arg;
arg = 1193180 / foo;
if (pcm_channels & 2)
@@ -76,6 +79,31 @@ pcm_set_speed (int arg)
tmp = pas_read (FILTER_FREQUENCY);
+ /*
+ * Set anti-aliasing filters according to sample rate. You reall *NEED*
+ * to enable this feature for all normal recording unless you want to
+ * experiment with aliasing effects.
+ * These filters apply to the selected "recording" source.
+ * I (pfw) don't know the encoding of these 5 bits. The values shown
+ * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
+*/
+#if !defined NO_AUTO_FILTER_SET
+ tmp &= 0xe0;
+ if (pcm_speed >= 2 * 17897)
+ tmp |= 0x21;
+ else if (pcm_speed >= 2 * 15909)
+ tmp |= 0x22;
+ else if (pcm_speed >= 2 * 11931)
+ tmp |= 0x29;
+ else if (pcm_speed >= 2 * 8948)
+ tmp |= 0x31;
+ else if (pcm_speed >= 2 * 5965)
+ tmp |= 0x39;
+ else if (pcm_speed >= 2 * 2982)
+ tmp |= 0x24;
+ pcm_filter = tmp;
+#endif
+
DISABLE_INTR (flags);
pas_write (tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
@@ -101,7 +129,9 @@ pcm_set_channels (int arg)
pas_write (pas_read (PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
pcm_channels = arg;
- pcm_set_speed (pcm_speed);/* The speed must be reinitialized */
+ pcm_set_speed (pcm_speed);/*
+ * The speed must be reinitialized
+ */
}
return pcm_channels;
@@ -160,7 +190,7 @@ pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return IOCTL_OUT (arg, pcm_channels);
break;
- case SNDCTL_DSP_SAMPLESIZE:
+ case SNDCTL_DSP_SETFMT:
if (local)
return pcm_set_bits (arg);
return IOCTL_OUT (arg, pcm_set_bits (IOCTL_IN (arg)));
@@ -171,7 +201,9 @@ pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return pcm_bits;
return IOCTL_OUT (arg, pcm_bits);
- case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
+ case SOUND_PCM_WRITE_FILTER: /*
+ * NOT YET IMPLEMENTED
+ */
if (IOCTL_IN (arg) > 1)
return IOCTL_OUT (arg, RET_ERROR (EINVAL));
break;
@@ -206,7 +238,7 @@ pas_pcm_open (int dev, int mode)
if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
return err;
- if (!DMAbuf_open_dma (dev))
+ if (DMAbuf_open_dma (dev) < 0)
{
pas_remove_intr (PAS_PCM_INTRBITS);
return RET_ERROR (EBUSY);
@@ -243,13 +275,15 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
cnt = count;
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
cnt >>= 1;
- if (sound_dma_automode[dev] &&
+ if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == pcm_count)
- return; /* Auto mode on. No need to react */
+ return; /*
+ * Auto mode on. No need to react
+ */
DISABLE_INTR (flags);
@@ -259,7 +293,7 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
if (restart_dma)
DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
count >>= 1;
if (count != pcm_count)
@@ -290,20 +324,22 @@ pas_pcm_start_input (int dev, unsigned long buf, int count,
TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
cnt = count;
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
cnt >>= 1;
- if (sound_dma_automode[my_devnum] &&
+ if (audio_devs[my_devnum]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == pcm_count)
- return; /* Auto mode on. No need to react */
+ return; /*
+ * Auto mode on. No need to react
+ */
DISABLE_INTR (flags);
if (restart_dma)
DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
count >>= 1;
if (count != pcm_count)
@@ -338,7 +374,9 @@ pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
static struct audio_operations pas_pcm_operations =
{
"Pro Audio Spectrum",
- NOTHING_SPECIAL,
+ DMA_AUTOMODE,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
pas_pcm_open,
pas_pcm_close,
pas_pcm_output_block,
@@ -347,9 +385,9 @@ static struct audio_operations pas_pcm_operations =
pas_pcm_prepare_for_input,
pas_pcm_prepare_for_output,
pas_pcm_reset,
- pas_pcm_reset, /* halt_xfer */
- NULL, /* has_output_drained */
- NULL /* copy_from_user */
+ pas_pcm_reset,
+ NULL,
+ NULL
};
long
@@ -363,28 +401,17 @@ pas_pcm_init (long mem_start, struct address_info *hw_config)
pcm_set_speed (DSP_DEFAULT_SPEED);
- if (num_dspdevs < MAX_DSP_DEV)
+ if (num_audiodevs < MAX_AUDIO_DEV)
{
- dsp_devs[my_devnum = num_dspdevs++] = &pas_pcm_operations;
- sound_dsp_dmachan[my_devnum] = hw_config->dma;
+ audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations;
+ audio_devs[my_devnum]->dmachan = hw_config->dma;
#ifndef NO_AUTODMA
- if (hw_config->dma > 3)
- {
- sound_buffcounts[my_devnum] = 1;
- sound_buffsizes[my_devnum] = 2 * 65536;
- sound_dma_automode[my_devnum] = 1;
- }
- else
- {
- sound_buffcounts[my_devnum] = 1;
- sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
- sound_dma_automode[my_devnum] = 1;
- }
+ audio_devs[my_devnum]->buffcount = 1;
#else
- sound_buffcounts[my_devnum] = DSP_BUFFCOUNT;
- sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
- sound_dma_automode[my_devnum] = 0;
+ audio_devs[my_devnum]->flags &= ~DMA_AUTOMODE;
+ audio_devs[my_devnum]->buffcount = DSP_BUFFCOUNT;
#endif
+ audio_devs[my_devnum]->buffsize = 2 * DSP_BUFFSIZE;
}
else
printk ("PAS2: Too many PCM devices available\n");
@@ -395,14 +422,16 @@ pas_pcm_init (long mem_start, struct address_info *hw_config)
void
pas_pcm_interrupt (unsigned char status, int cause)
{
- if (cause == 1) /* PCM buffer done */
+ if (cause == 1) /*
+ * PCM buffer done
+ */
{
/*
* Halt the PCM first. Otherwise we don't have time to start a new
* block before the PCM chip proceeds to the next sample
*/
- if (!sound_dma_automode[my_devnum])
+ if (!(audio_devs[my_devnum]->flags & DMA_AUTOMODE))
{
pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
PCM_CONTROL);
diff --git a/sys/i386/isa/sound/patmgr.c b/sys/i386/isa/sound/patmgr.c
index 1811ee9..43d0950 100644
--- a/sys/i386/isa/sound/patmgr.c
+++ b/sys/i386/isa/sound/patmgr.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: patmgr.c,v 1.5 1994/08/02 07:40:30 davidg Exp $
+ * $Id: patmgr.c,v 1.6 1994/09/27 17:58:22 davidg Exp $
*/
#define PATMGR_C
@@ -68,7 +68,9 @@ void
pmgr_release (int dev)
{
- if (mbox[dev]) /* Killed in action. Inform the client */
+ if (mbox[dev]) /*
+ * Killed in action. Inform the client
+ */
{
mbox[dev]->key = PM_ERROR;
@@ -130,7 +132,7 @@ pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
return RET_ERROR (EIO);
}
- COPY_FROM_USER ((caddr_t) mbox[dev], buf, 0, 4);
+ COPY_FROM_USER ((caddr_t)mbox[dev], buf, 0, 4);
if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE)
{
diff --git a/sys/i386/isa/sound/pss.c b/sys/i386/isa/sound/pss.c
index 6a0e7a8..3d7a620 100644
--- a/sys/i386/isa/sound/pss.c
+++ b/sys/i386/isa/sound/pss.c
@@ -44,7 +44,8 @@
marc.hoffman@analog.com
- */
+ * $Id: $
+ */
#include "sound_config.h"
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PSS)
diff --git a/sys/i386/isa/sound/pss.h b/sys/i386/isa/sound/pss.h
index e020af6..4676756 100644
--- a/sys/i386/isa/sound/pss.h
+++ b/sys/i386/isa/sound/pss.h
@@ -7,6 +7,9 @@
Copyright (c) 1993 Analog Devices Inc. All rights reserved
******************************************************************************/
+/*
+ * $Id: $
+ */
/* Port offsets from base port for Sound Blaster DSP */
#define DSP_PORT_CMSD0 0x00 /* C/MS music voice 1-6 data port, write only */
#define DSP_PORT_CMSR0 0x01 /* C/MS music voice 1-6 register port, write only */
diff --git a/sys/i386/isa/sound/sb16_dsp.c b/sys/i386/isa/sound/sb16_dsp.c
index cd9290d..a5586ef 100644
--- a/sys/i386/isa/sound/sb16_dsp.c
+++ b/sys/i386/isa/sound/sb16_dsp.c
@@ -27,13 +27,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: sb16_dsp.c,v 1.6 1994/08/02 07:40:36 davidg Exp $
+ * $Id: sb16_dsp.c,v 1.7 1994/09/27 17:58:24 davidg Exp $
*/
#define DEB(x)
#define DEB1(x)
/*
- #define DEB_DMARES
+ * #define DEB_DMARES
*/
#include "sound_config.h"
#include "sb.h"
@@ -41,19 +41,28 @@
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
-extern int sbc_base, sbc_minor, sbc_major;
+extern int sbc_base;
-static int sb16_dsp_ok = 0;/* Set to 1 after successful initialization */
+static int sb16_dsp_ok = 0;/*
+
+
+ * * * * Set to 1 after successful *
+ * * initialization */
static int dsp_16bit = 0;
static int dsp_stereo = 0;
-static int dsp_current_speed = 8000; /*DSP_DEFAULT_SPEED; */
+static int dsp_current_speed = 8000; /*
+
+
+ * * * * DSP_DEFAULT_SPEED; */
static int dsp_busy = 0;
static int dma16, dma8;
static unsigned long dsp_count = 0;
-static int irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT or
+static int irq_mode = IMODE_NONE; /*
+
- IMODE_NONE */
+ * * * * IMODE_INPUT, IMODE_OUTPUT
+ * or * * IMODE_NONE */
static int my_dev = 0;
static volatile int intr_active = 0;
@@ -74,7 +83,9 @@ static void dsp_cleanup (void);
static struct audio_operations sb16_dsp_operations =
{
"SoundBlaster 16",
- NOTHING_SPECIAL,
+ DMA_AUTOMODE,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
sb16_dsp_open,
sb16_dsp_close,
sb16_dsp_output_block,
@@ -100,79 +111,6 @@ sb_dsp_command01 (unsigned char val)
}
static int
-wait_data_avail (unsigned long t)
-{
- int loopc = 5000000;
-
- t += GET_TIME ();
- do
- {
- if (INB (DSP_DATA_AVAIL) & 0x80)
- return 1;
- }
- while (--loopc && GET_TIME () < t);
- printk ("!data_avail l=%d\n", loopc);
- return 0;
-}
-
-static int
-read_dsp (int t)
-{
- if (!wait_data_avail ((unsigned long) t))
- return -1;
- else
- return INB (DSP_READ);
-}
-
-static int
-dsp_ini2 (void)
-{
-#if 0
- /* sb_setmixer(0x83, sb_getmixer(0x83) | 0x03); */
- sb_dsp_command (0xe2);
- sb_dsp_command (0x76); /* E0 ??? */
- sb_dsp_command (0xe2);
- sb_dsp_command (0x30); /* A0 ??? */
- sb_dsp_command (0xe4);
- sb_dsp_command (0xaa);
- sb_dsp_command (0xe8);
- if (read_dsp (100) != 0xaa)
- printk ("Error dsp_ini2\n");
-#endif
- return 0;
-}
-
-/*
- static char *dsp_getmessage(unsigned char command,int maxn)
- {
- static char buff[100];
- int n=0;
-
- sb_dsp_command(command);
- while(n<maxn && wait_data_avail(2L)) {
- buff[++n]=INB(DSP_READ);
- if(!buff[n])
- break;
- }
- buff[0]=n;
- return buff;
- }
-
- static void dsp_showmessage(unsigned char command,int len)
- {
- int n;
- unsigned char *c;
- c=dsp_getmessage(command,len);
- printk("DSP C=%x l=%d,lr=%d b=",command,len,c[0]);
- for(n=1;n<=c[0];n++)
- if(c[n]>=' ' & c[n]<='z')
- printk("%c",c[n]);
- else
- printk("|%x|",c[n]);
- printk("\n");
- }
- */
-static int
dsp_set_speed (int mode)
{
DEB (printk ("dsp_set_speed(%d)\n", mode));
@@ -212,7 +150,7 @@ dsp_set_bits (int arg)
dsp_16bit = 1;
break;
default:
- return RET_ERROR (EINVAL);
+ dsp_16bit = 0;
}
return dsp_16bit ? 16 : 8;
}
@@ -247,7 +185,7 @@ sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return dsp_stereo + 1;
return IOCTL_OUT (arg, dsp_stereo + 1);
- case SNDCTL_DSP_SAMPLESIZE:
+ case SNDCTL_DSP_SETFMT:
if (local)
return dsp_set_bits (arg);
return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
@@ -257,7 +195,9 @@ sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return dsp_16bit ? 16 : 8;
return IOCTL_OUT (arg, dsp_16bit ? 16 : 8);
- case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
+ case SOUND_PCM_WRITE_FILTER: /*
+ * NOT YET IMPLEMENTED
+ */
if (IOCTL_IN (arg) > 1)
return IOCTL_OUT (arg, RET_ERROR (EINVAL));
default:
@@ -286,6 +226,8 @@ sb16_dsp_open (int dev, int mode)
if (retval < 0)
return retval;
+ sb_reset_dsp ();
+
if (ALLOC_DMA_CHN (dma8))
{
printk ("SB16: Unable to grab DMA%d\n", dma8);
@@ -302,8 +244,6 @@ sb16_dsp_open (int dev, int mode)
return RET_ERROR (EBUSY);
}
- dsp_ini2 ();
-
irq_mode = IMODE_NONE;
dsp_busy = 1;
@@ -344,7 +284,7 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
printk ("output_block: %x %d %d\n", buf, count, intrflag);
if (intrflag)
{
- int pos, chan = sound_dsp_dmachan[dev];
+ int pos, chan = audio_devs[dev]->dmachan;
DISABLE_INTR (flags);
clear_dma_ff (chan);
@@ -355,13 +295,15 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
printk ("dmapos=%d %x\n", pos, pos);
}
#endif
- if (sound_dma_automode[dev] &&
+ if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == dsp_count)
{
irq_mode = IMODE_OUTPUT;
intr_active = 1;
- return; /* Auto mode on. No need to react */
+ return; /*
+ * Auto mode on. No need to react
+ */
}
DISABLE_INTR (flags);
@@ -378,13 +320,11 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
(dsp_16bit ? 0x10 : 0)));
sb_dsp_command01 ((unsigned char) (cnt & 0xff));
sb_dsp_command ((unsigned char) (cnt >> 8));
- /* sb_dsp_command (0);
- sb_dsp_command (0); */
- RESTORE_INTR (flags);
dsp_count = cnt;
irq_mode = IMODE_OUTPUT;
intr_active = 1;
+ RESTORE_INTR (flags);
}
static void
@@ -401,7 +341,7 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int d
printk ("start_input: %x %d %d\n", buf, count, intrflag);
if (intrflag)
{
- int pos, chan = sound_dsp_dmachan[dev];
+ int pos, chan = audio_devs[dev]->dmachan;
DISABLE_INTR (flags);
clear_dma_ff (chan);
@@ -412,19 +352,21 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int d
printk ("dmapos=%d %x\n", pos, pos);
}
#endif
- if (sound_dma_automode[dev] &&
+ if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == dsp_count)
{
irq_mode = IMODE_INPUT;
intr_active = 1;
- return; /* Auto mode on. No need to react */
+ return; /*
+ * Auto mode on. No need to react
+ */
}
DISABLE_INTR (flags);
if (dma_restart)
{
- sb16_dsp_halt (dev);
+ sb_reset_dsp ();
DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
}
@@ -437,18 +379,16 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int d
sb_dsp_command01 ((unsigned char) (cnt & 0xff));
sb_dsp_command ((unsigned char) (cnt >> 8));
- /* sb_dsp_command (0);
- sb_dsp_command (0); */
- RESTORE_INTR (flags);
dsp_count = cnt;
irq_mode = IMODE_INPUT;
intr_active = 1;
+ RESTORE_INTR (flags);
}
static int
sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
{
- sound_dsp_dmachan[my_dev] = dsp_16bit ? dma16 : dma8;
+ audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
dsp_count = 0;
dsp_cleanup ();
return 0;
@@ -457,7 +397,7 @@ sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
static int
sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
{
- sound_dsp_dmachan[my_dev] = dsp_16bit ? dma16 : dma8;
+ audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
dsp_count = 0;
dsp_cleanup ();
return 0;
@@ -511,6 +451,9 @@ set_irq_hw (int level)
case 7:
ival = 4;
break;
+ case 9:
+ ival = 1;
+ break;
case 10:
ival = 8;
break;
@@ -524,8 +467,10 @@ set_irq_hw (int level)
long
sb16_dsp_init (long mem_start, struct address_info *hw_config)
{
+ extern int sbc_major, sbc_minor;
+
if (sbc_major < 4)
- return mem_start;
+ return mem_start; /* Not a SB16 */
#ifndef SCO
sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
@@ -537,18 +482,17 @@ sb16_dsp_init (long mem_start, struct address_info *hw_config)
printk (" <%s>", sb16_dsp_operations.name);
#endif
- if (num_dspdevs < MAX_DSP_DEV)
+ if (num_audiodevs < MAX_AUDIO_DEV)
{
- dsp_devs[my_dev = num_dspdevs++] = &sb16_dsp_operations;
- sound_dsp_dmachan[my_dev] = hw_config->dma;
+ audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
+ audio_devs[my_dev]->dmachan = hw_config->dma;
#ifndef NO_AUTODMA
- sound_buffcounts[my_dev] = 1;
- sound_dma_automode[my_dev] = 1;
+ audio_devs[my_dev]->buffcount = 1;
#else
- sound_buffcounts[my_dev] = DSP_BUFFCOUNT;
- sound_dma_automode[my_dev] = 0;
+ audio_devs[my_dev]->flags &= ~DMA_AUTOMODE;
+ audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT;
#endif
- sound_buffsizes[my_dev] = DSP_BUFFSIZE;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
}
else
printk ("SB: Too many DSP devices available\n");
@@ -560,9 +504,10 @@ int
sb16_dsp_detect (struct address_info *hw_config)
{
struct address_info *sb_config;
+ extern int sbc_major;
if (sb16_dsp_ok)
- return 1; /* Already initialized */
+ return 1; /* Can't drive two cards */
if (!(sb_config = sound_getconf (SNDCARD_SB)))
{
@@ -570,13 +515,16 @@ sb16_dsp_detect (struct address_info *hw_config)
return 0;
}
- /* sb_setmixer(OPSW,0xf);
- if(sb_getmixer(OPSW)!=0xf)
- return 0; */
+ /*
+ * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
+ */
if (!sb_reset_dsp ())
return 0;
+ if (sbc_major < 4) /* Set by the plain SB driver */
+ return 0; /* Not a SB16 */
+
if (hw_config->dma < 4)
if (hw_config->dma != sb_config->dma)
{
@@ -593,7 +541,7 @@ sb16_dsp_detect (struct address_info *hw_config)
DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, hw_config->dma));
/*
- dsp_showmessage(0xe3,99);
+ * dsp_showmessage(0xe3,99);
*/
sb16_dsp_ok = 1;
return 1;
@@ -604,7 +552,9 @@ sb16_dsp_interrupt (int unused)
{
int data;
- data = INB (DSP_DATA_AVL16); /* Interrupt acknowledge */
+ data = INB (DSP_DATA_AVL16); /*
+ * Interrupt acknowledge
+ */
if (intr_active)
switch (irq_mode)
diff --git a/sys/i386/isa/sound/sb16_midi.c b/sys/i386/isa/sound/sb16_midi.c
index d15fe17..7b23b4b 100644
--- a/sys/i386/isa/sound/sb16_midi.c
+++ b/sys/i386/isa/sound/sb16_midi.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sb16_midi.c,v 1.3 1994/08/02 07:40:38 davidg Exp $
*/
#include "sound_config.h"
@@ -34,9 +34,11 @@
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI)
-#define DATAPORT (sb16midi_base) /* MPU-401 Data I/O Port on IBM */
-#define COMDPORT (sb16midi_base+1) /* MPU-401 Command Port on IBM */
-#define STATPORT (sb16midi_base+1) /* MPU-401 Status Port on IBM */
+#include "sb.h"
+
+#define DATAPORT (sb16midi_base)
+#define COMDPORT (sb16midi_base+1)
+#define STATPORT (sb16midi_base+1)
#define sb16midi_status() INB(STATPORT)
#define input_avail() (!(sb16midi_status()&INPUT_AVAIL))
@@ -45,26 +47,24 @@
#define sb16midi_read() INB(DATAPORT)
#define sb16midi_write(byte) OUTB(byte, DATAPORT)
-#define OUTPUT_READY 0x40 /* Mask for Data Read Redy Bit */
-#define INPUT_AVAIL 0x80 /* Mask for Data Send Ready Bit */
-#define MPU_ACK 0xFE /* MPU-401 Acknowledge Response */
-#define MPU_RESET 0xFF /* MPU-401 Total Reset Command */
-#define UART_MODE_ON 0x3F /* MPU-401 "Dumb UART Mode" */
+#define OUTPUT_READY 0x40
+#define INPUT_AVAIL 0x80
+#define MPU_ACK 0xFE
+#define MPU_RESET 0xFF
+#define UART_MODE_ON 0x3F
static int sb16midi_opened = 0;
static int sb16midi_base = 0x330;
static int sb16midi_detected = 0;
static int my_dev;
+extern int sbc_base;
static int reset_sb16midi (void);
static void (*midi_input_intr) (int dev, unsigned char data);
-extern int sbc_major;
-
static void
sb16midi_input_loop (void)
{
-
while (input_avail ())
{
unsigned char c = sb16midi_read ();
@@ -128,7 +128,9 @@ sb16midi_out (int dev, unsigned char midi_byte)
* (After reset). Normally it takes just about 10 loops.
*/
- for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /* Wait */
+ for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /*
+ * Wait
+ */
if (!output_ready ())
{
@@ -141,12 +143,6 @@ sb16midi_out (int dev, unsigned char midi_byte)
}
static int
-sb16midi_command (int dev, unsigned char midi_byte)
-{
- return 1;
-}
-
-static int
sb16midi_start_read (int dev)
{
return 0;
@@ -172,12 +168,19 @@ sb16midi_kick (int dev)
static int
sb16midi_buffer_status (int dev)
{
- return 0; /* No data in buffers */
+ return 0; /*
+ * No data in buffers
+ */
}
+#define MIDI_SYNTH_NAME "SoundBlaster 16 Midi"
+#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
+#include "midi_synth.h"
+
static struct midi_operations sb16midi_operations =
{
- {"SoundBlaster MPU-401", 0, 0, SNDCARD_SB16MIDI},
+ {"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
+ &std_midi_synth,
sb16midi_open,
sb16midi_close,
sb16midi_ioctl,
@@ -185,8 +188,9 @@ static struct midi_operations sb16midi_operations =
sb16midi_start_read,
sb16midi_end_read,
sb16midi_kick,
- sb16midi_command,
- sb16midi_buffer_status
+ NULL,
+ sb16midi_buffer_status,
+ NULL
};
@@ -202,7 +206,9 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
return RET_ERROR (EIO);
DISABLE_INTR (flags);
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* Wait */
+ for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
+ * Wait
+ */
sb16midi_cmd (UART_MODE_ON);
ok = 0;
@@ -213,13 +219,19 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
RESTORE_INTR (flags);
+ if (num_midis >= MAX_MIDI_DEV)
+ {
+ printk ("Sound: Too many midi devices detected\n");
+ return mem_start;
+ }
+
#ifdef __FreeBSD__
printk ("snd7: <SoundBlaster MPU-401>");
#else
printk (" <SoundBlaster MPU-401>");
#endif
- my_dev = num_midis;
+ std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &sb16midi_operations;
return mem_start;
}
@@ -240,8 +252,12 @@ reset_sb16midi (void)
for (n = 0; n < 2 && !ok; n++)
{
- for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* Wait */
- sb16midi_cmd (MPU_RESET); /* Send MPU-401 RESET Command */
+ for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /*
+ * Wait
+ */
+ sb16midi_cmd (MPU_RESET); /*
+ * Send MPU-401 RESET Command
+ */
/*
* Wait at least 25 msec. This method is not accurate so let's make the
@@ -257,7 +273,9 @@ reset_sb16midi (void)
sb16midi_opened = 0;
if (ok)
- sb16midi_input_loop (); /* Flush input before enabling interrupts */
+ sb16midi_input_loop (); /*
+ * Flush input before enabling interrupts
+ */
RESTORE_INTR (flags);
@@ -269,10 +287,13 @@ int
probe_sb16midi (struct address_info *hw_config)
{
int ok = 0;
+ int i;
+ extern int sbc_major;
- sb16midi_base = hw_config->io_base;
if (sbc_major < 4)
- return 0; /* SB16 not detected */
+ return 0; /* Not a SB16 */
+
+ sb16midi_base = hw_config->io_base;
if (sb_get_irq () < 0)
return 0;
diff --git a/sys/i386/isa/sound/sb_dsp.c b/sys/i386/isa/sound/sb_dsp.c
index 992a00b..82087a0 100644
--- a/sys/i386/isa/sound/sb_dsp.c
+++ b/sys/i386/isa/sound/sb_dsp.c
@@ -1,10 +1,10 @@
/*
* sound/sb_dsp.c
- *
- * The low level driver for the SoundBlaster DSP chip.
- *
- * Copyright by Hannu Savolainen 1993
- *
+ *
+ * The low level driver for the SoundBlaster DSP chip (SB1.0 to 2.1, SB Pro).
+ *
+ * Copyright by Hannu Savolainen 1994
+ *
* 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,12 +24,12 @@
* 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.
- *
+ *
* Modified:
* Hunyue Yau Jan 6 1994
* Added code to support Sound Galaxy NX Pro
*
- * $Id: sb_dsp.c,v 1.19 1994/08/02 07:40:42 davidg Exp $
+ * $Id: sb_dsp.c,v 1.20 1994/09/27 17:58:26 davidg Exp $
*/
#include "sound_config.h"
@@ -42,7 +42,7 @@
int sbc_base = 0;
static int sbc_irq = 0;
-static int open_mode=0;
+static int open_mode = 0; /* Read, write or both */
/*
* The DSP channel can be used either for input or output. Variable
@@ -52,23 +52,36 @@ static int open_mode=0;
* future version of this driver.
*/
-int sb_dsp_ok = 0; /* Set to 1 after successful initialization */
+int sb_dsp_ok = 0; /*
+
+
+ * * * * Set to 1 after successful
+ * initialization * */
static int midi_disabled = 0;
int sb_dsp_highspeed = 0;
-int sbc_major = 1;
-int sbc_minor = 0; /* DSP version */
+int sbc_major = 1, sbc_minor = 0; /*
+
+
+ * * * * DSP version */
static int dsp_stereo = 0;
static int dsp_current_speed = DSP_DEFAULT_SPEED;
static int sb16 = 0;
static int irq_verified = 0;
int sb_midi_mode = NORMAL_MIDI;
-int sb_midi_busy = 0; /* 1 if the process has output to MIDI */
+int sb_midi_busy = 0; /*
+
+
+ * * * * 1 if the process has output
+ * to * * MIDI */
int sb_dsp_busy = 0;
-volatile int sb_irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT
+volatile int sb_irq_mode = IMODE_NONE; /*
- * or IMODE_NONE */
+
+ * * * * IMODE_INPUT, *
+ * IMODE_OUTPUT * * or *
+ * IMODE_NONE */
static volatile int irq_ok = 0;
int sb_duplex_midi = 0;
@@ -81,7 +94,9 @@ static int dsp_set_stereo (int mode);
#if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO)
-/* Common code for the midi and pcm functions */
+/*
+ * Common code for the midi and pcm functions
+ */
int
sb_dsp_command (unsigned char val)
@@ -89,7 +104,9 @@ sb_dsp_command (unsigned char val)
int i;
unsigned long limit;
- limit = GET_TIME () + HZ / 10;/* The timeout is 0.1 secods */
+ limit = GET_TIME () + HZ / 10;/*
+ * The timeout is 0.1 secods
+ */
/*
* Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
@@ -121,7 +138,12 @@ sbintr (int unit)
#ifndef EXCLUDE_SBPRO
if (sb16)
{
- unsigned char src = sb_getmixer (IRQ_STAT); /* Interrupt source register */
+ unsigned char src = sb_getmixer (IRQ_STAT); /*
+
+
+ * * * * Interrupt
+ * source * *
+ * register */
#ifndef EXCLUDE_SB16
if (src & 3)
@@ -129,17 +151,23 @@ sbintr (int unit)
#ifndef EXCLUDE_MIDI
if (src & 4)
- sb16midiintr (unit); /* MPU401 interrupt */
+ sb16midiintr (unit); /*
+ * SB MPU401 interrupt
+ */
#endif
#endif
if (!(src & 1))
- return; /* Not a DSP interupt */
+ return; /*
+ * Not a DSP interupt
+ */
}
#endif
- status = INB (DSP_DATA_AVAIL);/* Clear interrupt */
+ status = INB (DSP_DATA_AVAIL);/*
+ * Clear interrupt
+ */
if (sb_intr_active)
switch (sb_irq_mode)
@@ -152,7 +180,9 @@ sbintr (int unit)
case IMODE_INPUT:
sb_intr_active = 0;
DMAbuf_inputintr (my_dev);
- /* A complete buffer has been input. Let's start new one */
+ /*
+ * A complete buffer has been input. Let's start new one
+ */
break;
case IMODE_INIT:
@@ -161,7 +191,9 @@ sbintr (int unit)
break;
case IMODE_MIDI:
+#ifndef EXCLUDE_MIDI
sb_midi_interrupt (unit);
+#endif
break;
default:
@@ -209,11 +241,19 @@ sb_reset_dsp (void)
tenmicrosec ();
tenmicrosec ();
- for (loopc = 0; loopc < 1000 && !(INB (DSP_DATA_AVAIL) & 0x80); loopc++); /* Wait for data
- * available status */
+ for (loopc = 0; loopc < 1000 && !(INB (DSP_DATA_AVAIL) & 0x80); loopc++); /*
+ * Wait
+ * for
+ * data
+ * *
+ * available
+ * status
+ */
if (INB (DSP_READ) != 0xAA)
- return 0; /* Sorry */
+ return 0; /*
+ * Sorry
+ */
return 1;
}
@@ -260,11 +300,15 @@ dsp_speed (int speed)
max_speed = 13000;
if (speed > max_speed)
- speed = max_speed; /* Invalid speed */
+ speed = max_speed; /*
+ * Invalid speed
+ */
if (dsp_stereo && speed > 22050)
speed = 22050;
- /* Max. stereo speed is 22050 */
+ /*
+ * Max. stereo speed is 22050
+ */
if ((speed > 22050) && sb_midi_busy)
{
@@ -275,10 +319,14 @@ dsp_speed (int speed)
if (dsp_stereo)
speed *= 2;
- /* Now the speed should be valid */
+ /*
+ * Now the speed should be valid
+ */
if (speed > 22050)
- { /* High speed mode */
+ { /*
+ * High speed mode
+ */
int tmp;
tconst = (unsigned char) ((65536 -
@@ -301,7 +349,9 @@ dsp_speed (int speed)
tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
DISABLE_INTR (flags);
- if (sb_dsp_command (0x40))/* Set time constant */
+ if (sb_dsp_command (0x40))/*
+ * Set time constant
+ */
sb_dsp_command (tconst);
RESTORE_INTR (flags);
@@ -325,7 +375,9 @@ dsp_set_stereo (int mode)
return 0;
#else
if (sbc_major < 3 || sb16)
- return 0; /* Sorry no stereo */
+ return 0; /*
+ * Sorry no stereo
+ */
if (mode && sb_midi_busy)
{
@@ -350,18 +402,22 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
sb_irq_mode = IMODE_OUTPUT;
DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
count >>= 1;
count--;
if (sb_dsp_highspeed)
{
DISABLE_INTR (flags);
- if (sb_dsp_command (0x48))/* High speed size */
+ if (sb_dsp_command (0x48))/*
+ * High speed size
+ */
{
sb_dsp_command ((unsigned char) (count & 0xff));
sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
- sb_dsp_command (0x91);/* High speed 8 bit DAC */
+ sb_dsp_command (0x91);/*
+ * High speed 8 bit DAC
+ */
}
else
printk ("SB Error: Unable to start (high speed) DAC\n");
@@ -370,7 +426,9 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
else
{
DISABLE_INTR (flags);
- if (sb_dsp_command (0x14))/* 8-bit DAC (DMA) */
+ if (sb_dsp_command (0x14))/*
+ * 8-bit DAC (DMA)
+ */
{
sb_dsp_command ((unsigned char) (count & 0xff));
sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
@@ -386,7 +444,9 @@ static void
sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
int restart_dma)
{
- /* Start a DMA input to the buffer pointed by dmaqtail */
+ /*
+ * Start a DMA input to the buffer pointed by dmaqtail
+ */
unsigned long flags;
@@ -396,18 +456,22 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
sb_irq_mode = IMODE_INPUT;
DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
- if (sound_dsp_dmachan[dev] > 3)
+ if (audio_devs[dev]->dmachan > 3)
count >>= 1;
count--;
if (sb_dsp_highspeed)
{
DISABLE_INTR (flags);
- if (sb_dsp_command (0x48))/* High speed size */
+ if (sb_dsp_command (0x48))/*
+ * High speed size
+ */
{
sb_dsp_command ((unsigned char) (count & 0xff));
sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
- sb_dsp_command (0x99);/* High speed 8 bit ADC */
+ sb_dsp_command (0x99);/*
+ * High speed 8 bit ADC
+ */
}
else
printk ("SB Error: Unable to start (high speed) ADC\n");
@@ -416,7 +480,9 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
else
{
DISABLE_INTR (flags);
- if (sb_dsp_command (0x24))/* 8-bit ADC (DMA) */
+ if (sb_dsp_command (0x24))/*
+ * 8-bit ADC (DMA)
+ */
{
sb_dsp_command ((unsigned char) (count & 0xff));
sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
@@ -441,15 +507,19 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
dsp_cleanup ();
dsp_speaker (OFF);
- if (sbc_major == 3) /* SB Pro */
+ if (sbc_major == 3) /*
+ * SB Pro
+ */
{
if (dsp_stereo)
sb_dsp_command (0xa8);
else
sb_dsp_command (0xa0);
- dsp_speed (dsp_current_speed); /* Speed must be recalculated if #channels
- * changes */
+ dsp_speed (dsp_current_speed); /*
+ * Speed must be recalculated if
+ * #channels * changes
+ */
}
return 0;
}
@@ -461,11 +531,15 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
dsp_speaker (ON);
#ifndef EXCLUDE_SBPRO
- if (sbc_major == 3) /* SB Pro */
+ if (sbc_major == 3) /*
+ * SB Pro
+ */
{
sb_mixer_set_stereo (dsp_stereo);
- dsp_speed (dsp_current_speed); /* Speed must be recalculated if #channels
- * changes */
+ dsp_speed (dsp_current_speed); /*
+ * Speed must be recalculated if
+ * #channels * changes
+ */
}
#endif
return 0;
@@ -493,7 +567,9 @@ verify_irq (void)
sb_irq_mode = IMODE_INIT;
- sb_dsp_command (0xf2); /* This should cause immediate interrupt */
+ sb_dsp_command (0xf2); /*
+ * This should cause immediate interrupt
+ */
DO_SLEEP (testq, testf, HZ / 5);
@@ -540,7 +616,7 @@ sb_dsp_open (int dev, int mode)
if (retval)
return retval;
- if (!DMAbuf_open_dma (dev))
+ if (DMAbuf_open_dma (dev) < 0)
{
sb_free_irq ();
printk ("SB: DMA Busy\n");
@@ -606,7 +682,9 @@ sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
case SOUND_PCM_READ_BITS:
if (local)
return 8;
- return IOCTL_OUT (arg, 8);/* Only 8 bits/sample supported */
+ return IOCTL_OUT (arg, 8);/*
+ * Only 8 bits/sample supported
+ */
break;
case SOUND_PCM_WRITE_FILTER:
@@ -644,21 +722,25 @@ sb_dsp_detect (struct address_info *hw_config)
sbc_irq = hw_config->irq;
if (sb_dsp_ok)
- return 0; /* Already initialized */
+ return 0; /*
+ * Already initialized
+ */
if (!sb_reset_dsp ())
return 0;
- return 1; /* Detected */
+ return 1; /*
+ * Detected
+ */
}
-static char card_name[32] = "SoundBlaster";
-
#ifndef EXCLUDE_AUDIO
static struct audio_operations sb_dsp_operations =
{
- "SoundBlaster",
+ "SoundBlaster ",
NOTHING_SPECIAL,
+ AFMT_U8, /* Just 8 bits. Poor old SB */
+ NULL,
sb_dsp_open,
sb_dsp_close,
sb_dsp_output_block,
@@ -668,7 +750,7 @@ static struct audio_operations sb_dsp_operations =
sb_dsp_prepare_for_output,
sb_dsp_reset,
sb_dsp_halt_xfer,
- NULL, /* has_output_drained */
+ NULL, /* local_qlen */
NULL /* copy_from_user */
};
@@ -678,15 +760,19 @@ long
sb_dsp_init (long mem_start, struct address_info *hw_config)
{
int i;
- int prostat = 0;
+ int mixer_type = 0;
sbc_major = sbc_minor = 0;
- sb_dsp_command (0xe1); /* Get version */
+ sb_dsp_command (0xe1); /*
+ * Get version
+ */
for (i = 1000; i; i--)
{
if (INB (DSP_DATA_AVAIL) & 0x80)
- { /* wait for Data Ready */
+ { /*
+ * wait for Data Ready
+ */
if (sbc_major == 0)
sbc_major = INB (DSP_READ);
else
@@ -697,78 +783,74 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
}
}
- if (sbc_major == 2 || sbc_major == 3) /* SB 2.0 or SB Pro */
+ if (sbc_major == 2 || sbc_major == 3)
sb_duplex_midi = 1;
if (sbc_major == 4)
sb16 = 1;
#ifndef EXCLUDE_SBPRO
- if (sbc_major >= 3 ||
- (sbc_major == 2 && sbc_minor == 1)) /* Sound Galaxy ??? */
- prostat = sb_mixer_init (sbc_major);
+ if (sbc_major >= 3)
+ mixer_type = sb_mixer_init (sbc_major);
#endif
-#ifndef EXCLUDE_YM3812
+#ifndef EXCLUDE_YM8312
+
if (sbc_major > 3 ||
- (sbc_major == 3 && INB (0x388) == 0x00)) /* Non OPL-3 should return 0x06 */
+ (sbc_major == 3 && INB (0x388) == 0x00)) /* Should be 0x06 if not OPL-3 */
enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH);
#endif
if (sbc_major >= 3)
{
#ifndef SCO
- if (prostat)
+# ifdef __SGNXPRO__
+ if (mixer_type == 2)
{
-#ifndef EXCLUDE_AUDIO
sprintf (sb_dsp_operations.name, "Sound Galaxy NX Pro %d.%d", sbc_major, sbc_minor);
-#endif
- sprintf (card_name, "Sound Galaxy NX Pro %d.%d", sbc_major, sbc_minor);
}
else
+# endif
{
-#ifndef EXCLUDE_AUDIO
sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor);
-#endif
- sprintf (card_name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor);
}
#endif
}
else
{
#ifndef SCO
-#ifndef EXCLUDE_AUDIO
sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor);
#endif
- sprintf (card_name, "SoundBlaster %d.%d", sbc_major, sbc_minor);
-#endif
}
#ifdef __FreeBSD__
- printk ("snd2: <%s>", card_name);
+ printk ("snd2: <%s>", sb_dsp_operations.name);
#else
- printk (" <%s>", card_name);
+ printk (" <%s>", sb_dsp_operations.name);
#endif
#ifndef EXCLUDE_AUDIO
#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
- if (!sb16) /* There is a better driver for SB16 */
+ if (!sb16) /*
+ * There is a better driver for SB16
+ */
#endif
- if (num_dspdevs < MAX_DSP_DEV)
+ if (num_audiodevs < MAX_AUDIO_DEV)
{
- dsp_devs[my_dev = num_dspdevs++] = &sb_dsp_operations;
- sound_buffcounts[my_dev] = DSP_BUFFCOUNT;
- sound_buffsizes[my_dev] = DSP_BUFFSIZE;
- sound_dsp_dmachan[my_dev] = hw_config->dma;
- sound_dma_automode[my_dev] = 0;
+ audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;
+ audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
+ audio_devs[my_dev]->dmachan = hw_config->dma;
}
else
printk ("SB: Too many DSP devices available\n");
#endif
#ifndef EXCLUDE_MIDI
- if (!midi_disabled && !sb16) /* Midi don't work in the SB emulation mode
- * of PAS, SB16 has better midi interface */
+ if (!midi_disabled && !sb16) /*
+ * Midi don't work in the SB emulation mode *
+ * of PAS, SB16 has better midi interface
+ */
sb_midi_init (sbc_major);
#endif
diff --git a/sys/i386/isa/sound/sb_midi.c b/sys/i386/isa/sound/sb_midi.c
index dc6bba07..6431cd7 100644
--- a/sys/i386/isa/sound/sb_midi.c
+++ b/sys/i386/isa/sound/sb_midi.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sb_midi.c,v 1.3 1994/08/02 07:40:43 davidg Exp $
*/
#include "sound_config.h"
@@ -43,23 +43,26 @@
* future version of this driver.
*/
-extern int sb_dsp_ok; /* Set to 1 after successful initialization */
+extern int sb_dsp_ok; /* Set to 1 atfer successful initialization */
+extern int sbc_base;
extern int sb_midi_mode;
-extern int sb_midi_busy; /* 1 if the process has output to MIDI */
+extern int sb_midi_busy; /*
+
+
+ * * * * 1 if the process has output to MIDI
+ *
+ */
extern int sb_dsp_busy;
extern int sb_dsp_highspeed;
-extern volatile int sb_irq_mode;/* IMODE_INPUT, IMODE_OUTPUT
-
- * or IMODE_NONE */
+extern volatile int sb_irq_mode;
extern int sb_duplex_midi;
extern int sb_intr_active;
-extern int sbc_base;
+int input_opened = 0;
+static int my_dev;
-static int input_opened = 0;
-static void (*midi_input_intr) (int dev, unsigned char data);
-static int my_dev = 0;
+void (*midi_input_intr) (int dev, unsigned char data);
static int
sb_midi_open (int dev, int mode,
@@ -75,10 +78,13 @@ sb_midi_open (int dev, int mode,
return RET_ERROR (ENXIO);
}
+ if (sb_midi_busy)
+ return RET_ERROR (EBUSY);
+
if (mode != OPEN_WRITE && !sb_duplex_midi)
{
if (num_midis == 1)
- printk ("SoundBlaster: MIDI input not supported with plain SB\n");
+ printk ("SoundBlaster: Midi input not currently supported\n");
return RET_ERROR (EPERM);
}
@@ -102,20 +108,20 @@ sb_midi_open (int dev, int mode,
sb_reset_dsp ();
- if (!sb_dsp_command (0xf2)) /* This is undodumented, isn't it */
- return RET_ERROR (EIO); /* be nice to DSP */
-
if (!sb_dsp_command (0x35))
- return RET_ERROR (EIO); /* Enter the UART mode */
+ return RET_ERROR (EIO); /*
+ * Enter the UART mode
+ */
sb_intr_active = 1;
if ((ret = sb_get_irq ()) < 0)
{
sb_reset_dsp ();
- return 0; /* IRQ not free */
+ return 0; /*
+ * IRQ not free
+ */
}
input_opened = 1;
- my_dev = dev;
midi_input_intr = input;
}
@@ -129,7 +135,9 @@ sb_midi_close (int dev)
{
if (sb_midi_mode == UART_MIDI)
{
- sb_reset_dsp (); /* The only way to kill the UART mode */
+ sb_reset_dsp (); /*
+ * The only way to kill the UART mode
+ */
sb_free_irq ();
}
sb_intr_active = 0;
@@ -142,8 +150,6 @@ sb_midi_out (int dev, unsigned char midi_byte)
{
unsigned long flags;
- sb_midi_busy = 1; /* Kill all notes after close */
-
if (sb_midi_mode == NORMAL_MIDI)
{
DISABLE_INTR (flags);
@@ -154,7 +160,9 @@ sb_midi_out (int dev, unsigned char midi_byte)
RESTORE_INTR (flags);
}
else
- sb_dsp_command (midi_byte); /* UART write */
+ sb_dsp_command (midi_byte); /*
+ * UART write
+ */
return 1;
}
@@ -202,23 +210,43 @@ sb_midi_interrupt (int dummy)
RESTORE_INTR (flags);
}
+#define MIDI_SYNTH_NAME "SoundBlaster Midi"
+#define MIDI_SYNTH_CAPS 0
+#include "midi_synth.h"
+
static struct midi_operations sb_midi_operations =
{
{"SoundBlaster", 0, 0, SNDCARD_SB},
+ &std_midi_synth,
sb_midi_open,
sb_midi_close,
sb_midi_ioctl,
sb_midi_out,
sb_midi_start_read,
sb_midi_end_read,
- NULL, /* Kick */
- NULL, /* command */
- NULL /* buffer_status */
+ NULL, /*
+ * Kick
+ */
+ NULL, /*
+ * command
+ */
+ NULL, /*
+ * buffer_status
+ */
+ NULL
};
void
sb_midi_init (int model)
{
+ if (num_midis >= MAX_MIDI_DEV)
+ {
+ printk ("Sound: Too many midi devices detected\n");
+ return;
+ }
+
+ std_midi_synth.midi_dev = num_midis;
+ my_dev = num_midis;
midi_devs[num_midis++] = &sb_midi_operations;
}
diff --git a/sys/i386/isa/sound/sb_mixer.c b/sys/i386/isa/sound/sb_mixer.c
index 508dc67..d9bcb1e 100644
--- a/sys/i386/isa/sound/sb_mixer.c
+++ b/sys/i386/isa/sound/sb_mixer.c
@@ -4,7 +4,7 @@
*
* The low level mixer driver for the SoundBlaster Pro and SB16 cards.
*
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,7 +30,7 @@
* Hunyue Yau Jan 6 1994
* Added code to support the Sound Galaxy NX Pro mixer.
*
- * $Id$
+ * $Id: sb_mixer.c,v 1.3 1994/08/02 07:40:46 davidg Exp $
*/
#include "sound_config.h"
@@ -59,7 +59,9 @@ sb_setmixer (unsigned int port, unsigned int value)
unsigned long flags;
DISABLE_INTR (flags);
- OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* Select register */
+ OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /*
+ * Select register
+ */
tenmicrosec ();
OUTB ((unsigned char) (value & 0xff), MIXER_DATA);
tenmicrosec ();
@@ -73,7 +75,9 @@ sb_getmixer (unsigned int port)
unsigned long flags;
DISABLE_INTR (flags);
- OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /* Select register */
+ OUTB ((unsigned char) (port & 0xff), MIXER_ADDR); /*
+ * Select register
+ */
tenmicrosec ();
val = INB (MIXER_DATA);
tenmicrosec ();
@@ -116,7 +120,9 @@ detect_mixer (void)
sb_setmixer (VOC_VOL, 0x33);
if (sb_getmixer (FM_VOL) != 0xff)
- return 0; /* No match */
+ return 0; /*
+ * No match
+ */
if (sb_getmixer (VOC_VOL) != 0x33)
return 0;
@@ -153,12 +159,18 @@ change_bits (unsigned char *regval, int dev, int chn, int newval)
int shift;
mask = (1 << (*iomap)[dev][chn].nbits) - 1;
- newval = ((newval * mask) + 50) / 100; /* Scale it */
+ newval = (int) ((newval * mask) + 50) / 100; /*
+ * Scale it
+ */
shift = (*iomap)[dev][chn].bitoffs - (*iomap)[dev][LEFT_CHN].nbits + 1;
- *regval &= ~(mask << shift); /* Filter out the previous value */
- *regval |= (newval & mask) << shift; /* Set the new value */
+ *regval &= ~(mask << shift); /*
+ * Filter out the previous value
+ */
+ *regval |= (newval & mask) << shift; /*
+ * Set the new value
+ */
}
static int
@@ -187,7 +199,9 @@ sb_mixer_set (int dev, int value)
if (dev > 31)
return RET_ERROR (EINVAL);
- if (!(supported_devices & (1 << dev))) /* Not supported */
+ if (!(supported_devices & (1 << dev))) /*
+ * Not supported
+ */
return RET_ERROR (EINVAL);
regoffs = (*iomap)[dev][LEFT_CHN].regno;
@@ -200,15 +214,23 @@ sb_mixer_set (int dev, int value)
levels[dev] = left | (left << 8);
- if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) /* Change register */
+ if ((*iomap)[dev][RIGHT_CHN].regno != regoffs) /*
+ * Change register
+ */
{
- sb_setmixer (regoffs, val); /* Save the old one */
+ sb_setmixer (regoffs, val); /*
+ * Save the old one
+ */
regoffs = (*iomap)[dev][RIGHT_CHN].regno;
if (regoffs == 0)
- return left | (left << 8); /* Just left channel present */
+ return left | (left << 8); /*
+ * Just left channel present
+ */
- val = sb_getmixer (regoffs); /* Read the new one */
+ val = sb_getmixer (regoffs); /*
+ * Read the new one
+ */
}
change_bits (&val, dev, RIGHT_CHN, right);
@@ -239,21 +261,27 @@ set_recmask (int mask)
if (devmask != SOUND_MASK_MIC &&
devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD)
- { /* More than one devices selected. Drop the
- * previous selection */
+ { /*
+ * More than one devices selected. Drop the *
+ * previous selection
+ */
devmask &= ~recmask;
}
if (devmask != SOUND_MASK_MIC &&
devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD)
- { /* More than one devices selected. Default to
- * mic */
+ { /*
+ * More than one devices selected. Default to
+ * * mic
+ */
devmask = SOUND_MASK_MIC;
}
- if (devmask ^ recmask) /* Input source changed */
+ if (devmask ^ recmask) /*
+ * Input source changed
+ */
{
switch (devmask)
{
@@ -313,7 +341,9 @@ sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
return IOCTL_OUT (arg, sb_mixer_set (cmd & 0xff, IOCTL_IN (arg)));
}
else
- switch (cmd & 0xff) /* Return parameters */
+ switch (cmd & 0xff) /*
+ * Return parameters
+ */
{
case SOUND_MIXER_RECSRC:
@@ -362,21 +392,20 @@ sb_mixer_reset (void)
/*
* Returns a code depending on whether a SG NX Pro was detected.
- * 0 == Plain SB 16 or SB Pro
- * 1 == SG NX Pro detected.
+ * 1 == Plain SB Pro
+ * 2 == SG NX Pro detected.
+ * 3 == SB16
*
* Used to update message.
*/
int
sb_mixer_init (int major_model)
{
- int mixerstat;
+ int mixer_type = 0;
sb_setmixer (0x00, 0); /* Reset mixer */
- mixerstat = detect_mixer ();
-
- if (!mixerstat)
+ if (!(mixer_type = detect_mixer ()))
return 0; /* No mixer. Why? */
mixer_initialized = 1;
@@ -387,20 +416,20 @@ sb_mixer_init (int major_model)
case 3:
mixer_caps = SOUND_CAP_EXCL_INPUT;
#ifdef __SGNXPRO__
- if (mixerstat == 2)
- { /* A SGNXPRO was detected */
+ if (mixer_type == 2) /* A SGNXPRO was detected */
+ {
supported_devices = SGNXPRO_MIXER_DEVICES;
supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
iomap = &sgnxpro_mix;
}
else
#endif
- { /* Otherwise plain SB Pro */
+ {
supported_devices = SBPRO_MIXER_DEVICES;
supported_rec_devices = SBPRO_RECORDING_DEVICES;
iomap = &sbpro_mix;
+ mixer_type = 1;
}
-
break;
case 4:
@@ -408,6 +437,7 @@ sb_mixer_init (int major_model)
supported_devices = SB16_MIXER_DEVICES;
supported_rec_devices = SB16_RECORDING_DEVICES;
iomap = &sb16_mix;
+ mixer_type = 3;
break;
default:
@@ -415,9 +445,10 @@ sb_mixer_init (int major_model)
return 0;
}
- mixer_devs[num_mixers++] = &sb_mixer_operations;
+ if (num_mixers < MAX_MIXER_DEV)
+ mixer_devs[num_mixers++] = &sb_mixer_operations;
sb_mixer_reset ();
- return (mixerstat == 2);
+ return mixer_type;
}
#endif
diff --git a/sys/i386/isa/sound/sb_mixer.h b/sys/i386/isa/sound/sb_mixer.h
index 89b66d0..c7d5ca1 100644
--- a/sys/i386/isa/sound/sb_mixer.h
+++ b/sys/i386/isa/sound/sb_mixer.h
@@ -29,7 +29,7 @@
* Hunyue Yau Jan 6 1994
* Added defines for the Sound Galaxy NX Pro mixer.
*
- * $Id$
+ * $Id: sb_mixer.h,v 1.3 1994/08/02 07:40:48 davidg Exp $
*/
#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
@@ -210,4 +210,13 @@ static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
0x00, /* SOUND_MIXER_ALTPCM */
0x00 /* SOUND_MIXER_RECLEV */
};
+
+/*
+ * Recording sources (SB Pro)
+ */
+
+#define SRC_MIC 1 /* Select Microphone recording source */
+#define SRC_CD 3 /* Select CD recording source */
+#define SRC_LINE 7 /* Use Line-in for recording source */
+
#endif
diff --git a/sys/i386/isa/sound/sequencer.c b/sys/i386/isa/sound/sequencer.c
index 5748012..39ab789 100644
--- a/sys/i386/isa/sound/sequencer.c
+++ b/sys/i386/isa/sound/sequencer.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sequencer.c,v 1.6 1994/08/02 07:40:49 davidg Exp $
*/
#define SEQUENCER_C
@@ -36,31 +36,52 @@
#ifndef EXCLUDE_SEQUENCER
static int sequencer_ok = 0;
+static struct sound_timer_operations *tmr;
+static int tmr_no = -1; /* Currently selected timer */
+static int pending_timer = -1; /* For timer change operation */
+
+/*
+ * Local counts for number of synth and MIDI devices. These are initialized
+ * by the sequencer_open.
+ */
+static int max_mididev = 0;
+static int max_synthdev = 0;
+
+/*
+ * The seq_mode gives the operating mode of the sequencer:
+ * 1 = level1 (the default)
+ * 2 = level2 (extended capabilites)
+ */
+
+#define SEQ_1 1
+#define SEQ_2 2
+static int seq_mode = SEQ_1;
DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);
-/* DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); */
-#define midi_sleeper seq_sleeper
-#define midi_sleep_flag seq_sleep_flag
+DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);
static int midi_opened[MAX_MIDI_DEV] =
-{0}; /* 1 if the process has opened MIDI */
+{0};
static int midi_written[MAX_MIDI_DEV] =
{0};
-unsigned long seq_time = 0; /* Reference point for the timer */
+unsigned long prev_input_time = 0;
+int prev_event_time;
+unsigned long seq_time = 0;
#include "tuning.h"
#define EV_SZ 8
-#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 */
+#define IEV_SZ 8
+static unsigned char *queue = NULL;
+static unsigned char *iqueue = NULL;
static volatile int qhead = 0, qtail = 0, qlen = 0;
static volatile int iqhead = 0, iqtail = 0, iqlen = 0;
static volatile int seq_playing = 0;
static int sequencer_busy = 0;
static int output_treshold;
+static int pre_event_timeout;
static unsigned synth_open_mask;
static int seq_queue (unsigned char *note);
@@ -71,39 +92,48 @@ static int pmgr_present[MAX_SYNTH_DEV] =
{0};
#if MAX_SYNTH_DEV > 15
-#error Too many synthesizer devices
+#error Too many synthesizer devices enabled.
#endif
int
sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
int c = count, p = 0;
+ int ev_len;
+ unsigned long flags;
dev = dev >> 4;
- if (dev) /* Patch manager device */
+ ev_len = seq_mode == SEQ_1 ? 4 : 8;
+
+ if (dev) /*
+ * Patch manager device
+ */
return pmgr_read (dev - 1, file, buf, count);
- while (c > 3)
+ DISABLE_INTR (flags);
+ if (!iqlen)
{
+ DO_SLEEP (midi_sleeper, midi_sleep_flag, pre_event_timeout);
+
if (!iqlen)
{
- 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;
+ RESTORE_INTR (flags);
+ return 0;
}
+ }
+
+ while (iqlen && c >= ev_len)
+ {
- COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], IEV_SZ);
- p += 4;
- c -= 4;
+ COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], ev_len);
+ p += ev_len;
+ c -= ev_len;
iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;
iqlen--;
}
+ RESTORE_INTR (flags);
return count - c;
}
@@ -111,22 +141,33 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
static void
sequencer_midi_output (int dev)
{
- /* Currently NOP */
+ /*
+ * Currently NOP
+ */
}
-static void
-copy_to_input (unsigned char *event)
+void
+seq_copy_to_input (unsigned char *event, int len)
{
unsigned long flags;
+ /*
+ * Verify that the len is valid for the current mode.
+ */
+
+ if (len != 4 && len != 8)
+ return;
+ if ((seq_mode == SEQ_1) != (len == 4))
+ return;
+
if (iqlen >= (SEQ_MAX_QUEUE - 1))
return; /* Overflow */
- memcpy (&iqueue[iqtail * IEV_SZ], event, IEV_SZ);
+ DISABLE_INTR (flags);
+ memcpy (&iqueue[iqtail * IEV_SZ], event, len);
iqlen++;
iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
- DISABLE_INTR (flags);
if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))
{
WAKE_UP (midi_sleeper, midi_sleep_flag);
@@ -137,23 +178,54 @@ copy_to_input (unsigned char *event)
static void
sequencer_midi_input (int dev, unsigned char data)
{
- int tstamp;
+ unsigned int tstamp;
unsigned char event[4];
- if (data == 0xfe) /* Active sensing */
- return; /* Ignore */
+ if (data == 0xfe) /* Ignore active sensing */
+ return;
- tstamp = GET_TIME () - seq_time; /* Time since open() */
- tstamp = (tstamp << 8) | SEQ_WAIT;
+ tstamp = GET_TIME () - seq_time;
+ if (tstamp != prev_input_time)
+ {
+ tstamp = (tstamp << 8) | SEQ_WAIT;
- copy_to_input ((unsigned char *) &tstamp);
+ seq_copy_to_input ((unsigned char *) &tstamp, 4);
+ prev_input_time = tstamp;
+ }
event[0] = SEQ_MIDIPUTC;
event[1] = data;
event[2] = dev;
event[3] = 0;
- copy_to_input (event);
+ seq_copy_to_input (event, 4);
+}
+
+void
+seq_input_event (unsigned char *event, int len)
+{
+ unsigned long this_time;
+
+ if (seq_mode == SEQ_2)
+ this_time = tmr->get_time (tmr_no);
+ else
+ this_time = GET_TIME () - seq_time;
+
+ if (this_time != prev_input_time)
+ {
+ unsigned char tmp_event[8];
+
+ tmp_event[0] = EV_TIMING;
+ tmp_event[1] = TMR_WAIT_ABS;
+ tmp_event[2] = 0;
+ tmp_event[3] = 0;
+ *(unsigned long *) &tmp_event[4] = this_time;
+
+ seq_copy_to_input (tmp_event, 8);
+ prev_input_time = this_time;
+ }
+
+ seq_copy_to_input (event, len);
}
int
@@ -171,7 +243,9 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
if (mode == OPEN_READ)
return RET_ERROR (EIO);
- if (dev) /* Patch manager device */
+ if (dev) /*
+ * Patch manager device
+ */
return pmgr_write (dev - 1, file, buf, count);
c = count;
@@ -186,7 +260,7 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int err;
dev = *(unsigned short *) &event[2];
- if (dev < 0 || dev >= num_synths)
+ if (dev < 0 || dev >= max_synthdev)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)))
@@ -199,8 +273,13 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
return err;
}
- if (ev_code == SEQ_EXTENDED || ev_code == SEQ_PRIVATE)
+ if (ev_code >= 128)
{
+ if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)
+ {
+ printk ("Sequencer: Invalid level 2 event %x\n", ev_code);
+ return RET_ERROR (EINVAL);
+ }
ev_size = 8;
@@ -215,7 +294,14 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
}
else
- ev_size = 4;
+ {
+ if (seq_mode == SEQ_2)
+ {
+ printk ("Sequencer: 4 byte event in level 2 mode\n");
+ return RET_ERROR (EINVAL);
+ }
+ ev_size = 4;
+ }
if (event[0] == SEQ_MIDIPUTC)
{
@@ -225,7 +311,7 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int mode;
int dev = event[2];
- if (dev >= num_midis)
+ if (dev >= max_mididev)
{
printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);
return RET_ERROR (ENXIO);
@@ -268,20 +354,28 @@ static int
seq_queue (unsigned char *note)
{
- /* Test if there is space in the queue */
+ /*
+ * Test if there is space in the queue
+ */
if (qlen >= SEQ_MAX_QUEUE)
if (!seq_playing)
- seq_startplay (); /* Give chance to drain the queue */
+ seq_startplay (); /*
+ * Give chance to drain the queue
+ */
if (qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
- /* Sleep until there is enough space on the queue */
+ /*
+ * Sleep until there is enough space on the queue
+ */
DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
if (qlen >= SEQ_MAX_QUEUE)
- return 0; /* To be sure */
+ return 0; /*
+ * To be sure
+ */
memcpy (&queue[qtail * EV_SZ], note, EV_SZ);
@@ -296,7 +390,7 @@ extended_event (unsigned char *q)
{
int dev = q[2];
- if (dev < 0 || dev >= num_synths)
+ if (dev < 0 || dev >= max_synthdev)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)))
@@ -305,7 +399,7 @@ extended_event (unsigned char *q)
switch (q[1])
{
case SEQ_NOTEOFF:
- synth_devs[dev]->kill_note (dev, q[3], q[5]);
+ synth_devs[dev]->kill_note (dev, q[3], q[4], q[5]);
break;
case SEQ_NOTEON:
@@ -332,7 +426,8 @@ extended_event (unsigned char *q)
break;
case SEQ_VOLMODE:
- synth_devs[dev]->volume_method (dev, q[3]);
+ if (synth_devs[dev]->volume_method != NULL)
+ synth_devs[dev]->volume_method (dev, q[3]);
break;
default:
@@ -342,6 +437,282 @@ extended_event (unsigned char *q)
return 0;
}
+static int
+find_voice (int dev, int chn, int note)
+{
+ unsigned short key;
+ int i;
+
+ key = (chn << 8) | (note + 1);
+
+ for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)
+ if (synth_devs[dev]->alloc.map[i] == key)
+ return i;
+
+ return -1;
+}
+
+static int
+alloc_voice (int dev, int chn, int note)
+{
+ unsigned short key;
+ int voice;
+
+ key = (chn << 8) | (note + 1);
+
+ voice = synth_devs[dev]->alloc_voice (dev, chn, note,
+ &synth_devs[dev]->alloc);
+ synth_devs[dev]->alloc.map[voice] = key;
+ return voice;
+}
+
+static void
+seq_chn_voice_event (unsigned char *event)
+{
+ unsigned char dev = event[1];
+ unsigned char cmd = event[2];
+ unsigned char chn = event[3];
+ unsigned char note = event[4];
+ unsigned char parm = event[5];
+ int voice = -1;
+
+ if ((int) dev > max_synthdev)
+ return;
+ if (!(synth_open_mask & (1 << dev)))
+ return;
+ if (!synth_devs[dev])
+ return;
+
+ if (seq_mode == SEQ_2)
+ if (synth_devs[dev]->alloc_voice)
+ voice = find_voice (dev, chn, note);
+
+ if (cmd == MIDI_NOTEON && parm == 0)
+ {
+ cmd = MIDI_NOTEOFF;
+ parm = 64;
+ }
+
+ switch (cmd)
+ {
+ case MIDI_NOTEON:
+ if (note > 127)
+ return;
+
+ if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice)
+ {
+ voice = alloc_voice (dev, chn, note);
+ }
+
+ if (voice == -1)
+ voice = chn;
+
+ if (seq_mode == SEQ_2)
+ {
+ synth_devs[dev]->set_instr (dev, voice,
+ synth_devs[dev]->chn_info[chn].pgm_num);
+ }
+
+ synth_devs[dev]->start_note (dev, voice, note, parm);
+ break;
+
+ case MIDI_NOTEOFF:
+ if (voice == -1)
+ voice = chn;
+ synth_devs[dev]->kill_note (dev, voice, note, parm);
+ break;
+
+ case MIDI_KEY_PRESSURE:
+ /* To be implemented */
+ break;
+
+ default:;
+ }
+}
+
+static void
+seq_chn_common_event (unsigned char *event)
+{
+ unsigned char dev = event[1];
+ unsigned char cmd = event[2];
+ unsigned char chn = event[3];
+ unsigned char p1 = event[4];
+
+ /* unsigned char p2 = event[5]; */
+ unsigned short w14 = *(short *) &event[6];
+
+ if ((int) dev > max_synthdev)
+ return;
+ if (!(synth_open_mask & (1 << dev)))
+ return;
+ if (!synth_devs[dev])
+ return;
+
+ switch (cmd)
+ {
+ case MIDI_PGM_CHANGE:
+ if (seq_mode == SEQ_2)
+ {
+ synth_devs[dev]->chn_info[chn].pgm_num = p1;
+ }
+ else
+ synth_devs[dev]->set_instr (dev, chn, p1);
+ break;
+
+ case MIDI_CTL_CHANGE:
+ if (p1 == CTRL_MAIN_VOLUME)
+ {
+ w14 = (unsigned short) (((int) w14 * 16383) / 100);
+ p1 = CTL_MAIN_VOLUME;
+ }
+ if (p1 == CTRL_EXPRESSION)
+ {
+ w14 *= 128;
+ p1 = CTL_EXPRESSION;
+ }
+
+ if (seq_mode == SEQ_2)
+ {
+ if (chn > 15 || p1 > 127)
+ break;
+
+ synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0xff;
+
+ if (dev < num_synths)
+ {
+ int val = w14 & 0xff;
+
+ if (p1 < 64) /* Combine MSB and LSB */
+ {
+ val = ((synth_devs[dev]->
+ chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)
+ | (synth_devs[dev]->
+ chn_info[chn].controllers[p1 | 32] & 0x7f);
+ p1 &= ~32;
+ }
+ else
+ val = synth_devs[dev]->chn_info[chn].controllers[p1];
+
+ synth_devs[dev]->controller (dev, chn, p1, val);
+ }
+ else
+ synth_devs[dev]->controller (dev, chn, p1, w14);
+ }
+ else
+ synth_devs[dev]->controller (dev, chn, p1, w14);
+ break;
+
+ case MIDI_PITCH_BEND:
+ synth_devs[dev]->bender (dev, chn, w14);
+ break;
+
+ default:;
+ }
+}
+
+static int
+seq_timing_event (unsigned char *event)
+{
+ unsigned char cmd = event[1];
+ unsigned int parm = *(int *) &event[4];
+
+ if (seq_mode == SEQ_2)
+ {
+ int ret;
+
+ if ((ret = tmr->event (tmr_no, event)) == TIMER_ARMED)
+ {
+ if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
+ {
+ unsigned long flags;
+
+ DISABLE_INTR (flags);
+ if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+ {
+ WAKE_UP (seq_sleeper, seq_sleep_flag);
+ }
+ RESTORE_INTR (flags);
+ }
+ }
+ return ret;
+ }
+
+ switch (cmd)
+ {
+ case TMR_WAIT_REL:
+ parm += prev_event_time;
+
+ /*
+ * NOTE! No break here. Execution of TMR_WAIT_REL continues in the
+ * next case (TMR_WAIT_ABS)
+ */
+
+ case TMR_WAIT_ABS:
+ if (parm > 0)
+ {
+ long time;
+
+ seq_playing = 1;
+ time = parm;
+ prev_event_time = time;
+
+ request_sound_timer (time);
+
+ if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
+ {
+ unsigned long flags;
+
+ DISABLE_INTR (flags);
+ if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
+ {
+ WAKE_UP (seq_sleeper, seq_sleep_flag);
+ }
+ RESTORE_INTR (flags);
+ }
+
+ return TIMER_ARMED;
+ }
+ break;
+
+ case TMR_START:
+ seq_time = GET_TIME ();
+ prev_input_time = 0;
+ prev_event_time = 0;
+ break;
+
+ case TMR_STOP:
+ break;
+
+ case TMR_CONTINUE:
+ break;
+
+ case TMR_TEMPO:
+ break;
+
+ case TMR_ECHO:
+ if (seq_mode == SEQ_2)
+ seq_copy_to_input (event, 8);
+ else
+ {
+ parm = (parm << 8 | SEQ_ECHO);
+ seq_copy_to_input ((unsigned char *) &parm, 4);
+ }
+ break;
+
+ default:;
+ }
+
+ return TIMER_NOT_ARMED;
+}
+
+static void
+seq_local_event (unsigned char *event)
+{
+ /* unsigned char cmd = event[1]; */
+
+ printk ("seq_local_event() called. WHY????????\n");
+}
+
static void
seq_startplay (void)
{
@@ -351,6 +722,9 @@ seq_startplay (void)
while (qlen > 0)
{
+
+ seq_playing = 1;
+
qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;
qlen--;
@@ -361,7 +735,7 @@ seq_startplay (void)
case SEQ_NOTEOFF:
if (synth_open_mask & (1 << 0))
if (synth_devs[0])
- synth_devs[0]->kill_note (0, q[1], q[3]);
+ synth_devs[0]->kill_note (0, q[1], 255, q[3]);
break;
case SEQ_NOTEON:
@@ -372,8 +746,10 @@ seq_startplay (void)
break;
case SEQ_WAIT:
- delay = (unsigned long *) q; /* Bytes 1 to 3 are containing the
- * delay in GET_TIME() */
+ delay = (unsigned long *) q; /*
+ * Bytes 1 to 3 are containing the *
+ * delay in GET_TIME()
+ */
*delay = (*delay >> 8) & 0xffffff;
if (*delay > 0)
@@ -382,6 +758,7 @@ seq_startplay (void)
seq_playing = 1;
time = *delay;
+ prev_event_time = time;
request_sound_timer (time);
@@ -396,8 +773,11 @@ seq_startplay (void)
}
RESTORE_INTR (flags);
}
- return; /* Stop here. Timer routine will continue
- * playing after the delay */
+ /*
+ * The timer is now active and will reinvoke this function
+ * after the timer expires. Return to the caller now.
+ */
+ return;
}
break;
@@ -407,11 +787,17 @@ seq_startplay (void)
synth_devs[0]->set_instr (0, q[1], q[2]);
break;
- case SEQ_SYNCTIMER: /* Reset timer */
+ case SEQ_SYNCTIMER: /*
+ * Reset timer
+ */
seq_time = GET_TIME ();
+ prev_input_time = 0;
+ prev_event_time = 0;
break;
- case SEQ_MIDIPUTC: /* Put a midi character */
+ case SEQ_MIDIPUTC: /*
+ * Put a midi character
+ */
if (midi_opened[q[2]])
{
int dev;
@@ -425,7 +811,9 @@ seq_startplay (void)
*/
qlen++;
- qhead = this_one; /* Restore queue */
+ qhead = this_one; /*
+ * Restore queue
+ */
seq_playing = 1;
request_sound_timer (-1);
return;
@@ -436,11 +824,13 @@ seq_startplay (void)
break;
case SEQ_ECHO:
- copy_to_input (q); /* Echo back to the process */
+ seq_copy_to_input (q, 4); /*
+ * Echo back to the process
+ */
break;
case SEQ_PRIVATE:
- if (q[1] < num_synths)
+ if ((int) q[1] < max_synthdev)
synth_devs[q[1]]->hw_control (q[1], q);
break;
@@ -448,6 +838,25 @@ seq_startplay (void)
extended_event (q);
break;
+ case EV_CHN_VOICE:
+ seq_chn_voice_event (q);
+ break;
+
+ case EV_CHN_COMMON:
+ seq_chn_common_event (q);
+ break;
+
+ case EV_TIMING:
+ if (seq_timing_event (q) == TIMER_ARMED)
+ {
+ return;
+ }
+ break;
+
+ case EV_SEQ_LOCAL:
+ seq_local_event (q);
+ break;
+
default:;
}
@@ -469,10 +878,55 @@ seq_startplay (void)
}
+static void
+reset_controllers (int dev, unsigned char *controller, int update_dev)
+{
+#include "midi_ctrl.h"
+
+ int i;
+
+ for (i = 0; i < 128; i++)
+ controller[i] = ctrl_def_values[i];
+}
+
+static void
+setup_mode2 (void)
+{
+ int dev;
+
+ max_synthdev = num_synths;
+
+ for (dev = 0; dev < num_midis; dev++)
+ if (midi_devs[dev]->converter != NULL)
+ {
+ synth_devs[max_synthdev++] =
+ midi_devs[dev]->converter;
+ }
+
+ for (dev = 0; dev < max_synthdev; dev++)
+ {
+ int chn;
+
+ for (chn = 0; chn < 16; chn++)
+ {
+ synth_devs[dev]->chn_info[chn].pgm_num = 0;
+ reset_controllers (dev,
+ synth_devs[dev]->chn_info[chn].controllers,
+ 0);
+ }
+ }
+
+ max_mididev = 0;
+ seq_mode = SEQ_2;
+}
+
int
sequencer_open (int dev, struct fileinfo *file)
{
int retval, mode, i;
+ int level, tmp;
+
+ level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1;
dev = dev >> 4;
mode = file->mode & O_ACCMODE;
@@ -485,15 +939,22 @@ sequencer_open (int dev, struct fileinfo *file)
return RET_ERROR (ENXIO);
}
- if (dev) /* Patch manager device */
+ if (dev) /*
+ * Patch manager device
+ */
{
int err;
dev--;
+
+ if (dev >= MAX_SYNTH_DEV)
+ return RET_ERROR (ENXIO);
if (pmgr_present[dev])
return RET_ERROR (EBUSY);
if ((err = pmgr_open (dev)) < 0)
- return err; /* Failed */
+ return err; /*
+ * Failed
+ */
pmgr_present[dev] = 1;
return err;
@@ -505,40 +966,105 @@ sequencer_open (int dev, struct fileinfo *file)
return RET_ERROR (EBUSY);
}
- if (!(num_synths + num_midis))
- return RET_ERROR (ENXIO);
+ max_mididev = num_midis;
+ max_synthdev = num_synths;
+ pre_event_timeout = 0;
+ seq_mode = SEQ_1;
- synth_open_mask = 0;
+ if (pending_timer != -1)
+ {
+ tmr_no = pending_timer;
+ pending_timer = -1;
+ }
- 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 (tmr_no == -1) /* Not selected yet */
+ {
+ int i, best;
- seq_time = GET_TIME ();
+ best = -1;
+ for (i = 0; i < num_sound_timers; i++)
+ if (sound_timer_devs[i]->priority > best)
+ {
+ tmr_no = i;
+ best = sound_timer_devs[i]->priority;
+ }
- for (i = 0; i < num_midis; i++)
- {
- midi_opened[i] = 0;
- midi_written[i] = 0;
+ if (tmr_no == -1) /* Should not be */
+ tmr_no = 0;
}
- if (mode == OPEN_READ || mode == OPEN_READWRITE)
- { /* Initialize midi input devices */
- if (!num_midis)
+ tmr = sound_timer_devs[tmr_no];
+
+ if (level == 2)
+ {
+ printk ("Using timer #%d\n", tmr_no);
+ if (tmr == NULL)
{
- printk ("Sequencer: No Midi devices. Input not possible\n");
+ printk ("sequencer: No timer for level 2\n");
return RET_ERROR (ENXIO);
}
+ setup_mode2 ();
+ }
- for (i = 0; i < num_midis; i++)
- {
- if ((retval = midi_devs[i]->open (i, mode,
+ if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
+ if (!max_mididev)
+ {
+ printk ("Sequencer: No Midi devices. Input not possible\n");
+ return RET_ERROR (ENXIO);
+ }
+
+ if (!max_synthdev && !max_mididev)
+ return RET_ERROR (ENXIO);
+
+ synth_open_mask = 0;
+
+ for (i = 0; i < max_mididev; i++)
+ {
+ midi_opened[i] = 0;
+ midi_written[i] = 0;
+ }
+
+ /*
+ * if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
+ */
+ for (i = 0; i < max_synthdev; i++) /*
+ * Open synth devices
+ */
+ if ((tmp = synth_devs[i]->open (i, mode)) < 0)
+ {
+ printk ("Sequencer: Warning! Cannot open synth device #%d (%d)\n", i, tmp);
+ if (synth_devs[i]->midi_dev)
+ printk ("(Maps to midi dev #%d\n", synth_devs[i]->midi_dev);
+ }
+ else
+ {
+ synth_open_mask |= (1 << i);
+ if (synth_devs[i]->midi_dev) /*
+ * Is a midi interface
+ */
+ midi_opened[synth_devs[i]->midi_dev] = 1;
+ }
+
+ seq_time = GET_TIME ();
+ prev_input_time = 0;
+ prev_event_time = 0;
+
+ if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
+ { /*
+ * Initialize midi input devices
+ */
+ for (i = 0; i < max_mididev; i++)
+ if (!midi_opened[i])
+ {
+ if ((retval = midi_devs[i]->open (i, mode,
sequencer_midi_input, sequencer_midi_output)) >= 0)
- midi_opened[i] = 1;
- }
+ midi_opened[i] = 1;
+ }
+ }
+
+ if (seq_mode == SEQ_2)
+ {
+ tmr->open (tmr_no, seq_mode);
}
sequencer_busy = 1;
@@ -568,7 +1094,7 @@ seq_drain_midi_queues (void)
{
n = 0;
- for (i = 0; i < num_midis; i++)
+ for (i = 0; i < max_mididev; i++)
if (midi_opened[i] && midi_written[i])
if (midi_devs[i]->buffer_status != NULL)
if (midi_devs[i]->buffer_status (i))
@@ -594,7 +1120,9 @@ sequencer_release (int dev, struct fileinfo *file)
DEB (printk ("sequencer_release(dev=%d)\n", dev));
- if (dev) /* Patch manager device */
+ if (dev) /*
+ * Patch manager device
+ */
{
dev--;
pmgr_release (dev);
@@ -603,34 +1131,48 @@ sequencer_release (int dev, struct fileinfo *file)
}
/*
- * Wait until the queue is empty
+ * * Wait until the queue is empty
*/
- while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen)
- {
- seq_sync ();
- }
+ if (mode != OPEN_READ)
+ while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen)
+ {
+ seq_sync ();
+ }
if (mode != OPEN_READ)
- seq_drain_midi_queues (); /* Ensure the output queues are empty */
+ 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 */
-
- 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 (synth_open_mask & (1 << i)) /* Actually opened */
- if (synth_devs[i])
+ seq_drain_midi_queues (); /*
+ * Flush the all notes off messages
+ */
+
+ for (i = 0; i < max_synthdev; i++)
+ if (synth_open_mask & (1 << i)) /*
+ * Actually opened
+ */
+ if (synth_devs[i])
+ {
synth_devs[i]->close (i);
+ if (synth_devs[i]->midi_dev)
+ midi_opened[synth_devs[i]->midi_dev] = 0;
+ }
+
for (i = 0; i < num_synths; i++)
if (pmgr_present[i])
pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
+ for (i = 0; i < max_mididev; i++)
+ if (midi_opened[i])
+ midi_devs[i]->close (i);
+
+ if (seq_mode == SEQ_2)
+ tmr->close (tmr_no);
+
sequencer_busy = 0;
}
@@ -640,7 +1182,10 @@ seq_sync (void)
if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_startplay ();
- if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) /* Queue not empty */
+ if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) /*
+ * Queue not
+ * empty
+ */
{
DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
@@ -657,11 +1202,19 @@ midi_outc (int dev, unsigned char data)
int n;
- /* This routine sends one byte to the Midi channel. */
- /* If the output Fifo is full, it waits until there */
- /* is space in the queue */
+ /*
+ * This routine sends one byte to the Midi channel.
+ */
+ /*
+ * If the output Fifo is full, it waits until there
+ */
+ /*
+ * is space in the queue
+ */
- n = 300; /* Timeout in jiffies */
+ n = 300; /*
+ * Timeout in jiffies
+ */
while (n && !midi_devs[dev]->putc (dev, data))
{
@@ -677,34 +1230,66 @@ seq_reset (void)
* NOTE! Calls sleep(). Don't call this from interrupt.
*/
- int i, chn;
+ int i;
+
+ int chn;
sound_stop_timer ();
+ seq_time = GET_TIME ();
+ prev_input_time = 0;
+ prev_event_time = 0;
qlen = qhead = qtail = 0;
iqlen = iqhead = iqtail = 0;
- for (i = 0; i < num_synths; i++)
+ for (i = 0; i < max_synthdev; i++)
if (synth_open_mask & (1 << i))
if (synth_devs[i])
synth_devs[i]->reset (i);
- for (i = 0; i < num_midis; i++)
- if (midi_written[i]) /* Midi used. Some notes may still be playing */
- {
- for (chn = 0; chn < 16; chn++)
+ if (seq_mode == SEQ_2)
+ {
+ for (i = 0; i < max_synthdev; i++)
+ if (synth_open_mask & (1 << i))
+ if (synth_devs[i])
+ for (chn = 0; chn < 16; chn++)
+ synth_devs[i]->controller (i, chn, 0xfe, 0); /* All notes off */
+ }
+ else
+ {
+ for (i = 0; i < max_mididev; i++)
+ if (midi_written[i]) /*
+ * Midi used. Some notes may still be playing
+ */
{
- midi_outc (i,
- (unsigned char) (0xb0 + (chn & 0xff))); /* Channel msg */
- midi_outc (i, 0x7b);/* All notes off */
- midi_outc (i, 0); /* Dummy parameter */
+ /*
+ * Sending just a ACTIVE SENSING message should be enough to stop all
+ * playing notes. Since there are devices not recognizing the
+ * active sensing, we have to send some all notes off messages also.
+ */
+ midi_outc (i, 0xfe);
+
+ for (chn = 0; chn < 16; chn++)
+ {
+ midi_outc (i,
+ (unsigned char) (0xb0 + (chn & 0xff))); /*
+ * Channel
+ * msg
+ */
+ midi_outc (i, 0x7b); /*
+ * All notes off
+ */
+ midi_outc (i, 0); /*
+ * Dummy parameter
+ */
+ }
+
+ midi_devs[i]->close (i);
+
+ midi_written[i] = 0;
+ midi_opened[i] = 0;
}
-
- midi_devs[i]->close (i);
-
- midi_written[i] = 0;
- midi_opened[i] = 0;
- }
+ }
seq_playing = 0;
@@ -713,6 +1298,28 @@ seq_reset (void)
}
+static void
+seq_panic (void)
+{
+ /*
+ * This routine is called by the application in case the user
+ * wants to reset the system to the default state.
+ */
+
+ seq_reset ();
+
+ /*
+ * Since some of the devices don't recognize the active sensing and
+ * all notes off messages, we have to shut all notes manually.
+ *
+ * TO BE IMPLEMENTED LATER
+ */
+
+ /*
+ * Also return the controllers to their default states
+ */
+}
+
int
sequencer_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg)
@@ -724,20 +1331,62 @@ sequencer_ioctl (int dev, struct fileinfo *file,
switch (cmd)
{
+ case SNDCTL_TMR_TIMEBASE:
+ case SNDCTL_TMR_TEMPO:
+ case SNDCTL_TMR_START:
+ case SNDCTL_TMR_STOP:
+ case SNDCTL_TMR_CONTINUE:
+ case SNDCTL_TMR_METRONOME:
+ case SNDCTL_TMR_SOURCE:
+ if (dev) /* Patch manager */
+ return RET_ERROR (EIO);
- case SNDCTL_SEQ_SYNC:
+ if (seq_mode != SEQ_2)
+ return RET_ERROR (EINVAL);
+ return tmr->ioctl (tmr_no, cmd, arg);
+ break;
+
+ case SNDCTL_TMR_SELECT:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
+ if (seq_mode != SEQ_2)
+ return RET_ERROR (EINVAL);
+ pending_timer = IOCTL_IN (arg);
+
+ if (pending_timer < 0 || pending_timer >= num_sound_timers)
+ {
+ pending_timer = -1;
+ return RET_ERROR (EINVAL);
+ }
+
+ return IOCTL_OUT (arg, pending_timer);
+ break;
+
+ case SNDCTL_SEQ_PANIC:
+ seq_panic ();
+ break;
+
+ case SNDCTL_SEQ_SYNC:
+ if (dev) /*
+ * Patch manager
+ */
+ return RET_ERROR (EIO);
+
if (mode == OPEN_READ)
return 0;
while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_sync ();
- return 0;
+ if (qlen)
+ return RET_ERROR (EINTR);
+ else
+ return 0;
break;
case SNDCTL_SEQ_RESET:
- if (dev) /* Patch manager */
+ if (dev) /*
+ * Patch manager
+ */
return RET_ERROR (EIO);
seq_reset ();
@@ -745,11 +1394,13 @@ sequencer_ioctl (int dev, struct fileinfo *file,
break;
case SNDCTL_SEQ_TESTMIDI:
- if (dev) /* Patch manager */
+ if (dev) /*
+ * Patch manager
+ */
return RET_ERROR (EIO);
midi_dev = IOCTL_IN (arg);
- if (midi_dev >= num_midis)
+ if (midi_dev >= max_mididev)
return RET_ERROR (ENXIO);
if (!midi_opened[midi_dev])
@@ -769,7 +1420,9 @@ sequencer_ioctl (int dev, struct fileinfo *file,
break;
case SNDCTL_SEQ_GETINCOUNT:
- if (dev) /* Patch manager */
+ if (dev) /*
+ * Patch manager
+ */
return RET_ERROR (EIO);
if (mode == OPEN_WRITE)
@@ -788,7 +1441,15 @@ sequencer_ioctl (int dev, struct fileinfo *file,
if (dev) /* Patch manager */
return RET_ERROR (EIO);
- /* If *arg == 0, just return the current rate */
+ /*
+ * If *arg == 0, just return the current rate
+ */
+ if (seq_mode == SEQ_2)
+ return tmr->ioctl (tmr_no, cmd, arg);
+
+ if (IOCTL_IN (arg) != 0)
+ return RET_ERROR (EINVAL);
+
return IOCTL_OUT (arg, HZ);
break;
@@ -807,11 +1468,11 @@ sequencer_ioctl (int dev, struct fileinfo *file,
break;
case SNDCTL_SEQ_NRSYNTHS:
- return IOCTL_OUT (arg, num_synths);
+ return IOCTL_OUT (arg, max_synthdev);
break;
case SNDCTL_SEQ_NRMIDIS:
- return IOCTL_OUT (arg, num_midis);
+ return IOCTL_OUT (arg, max_mididev);
break;
case SNDCTL_SYNTH_MEMAVL:
@@ -851,7 +1512,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
dev = inf.device;
- if (dev < 0 || dev >= num_synths)
+ if (dev < 0 || dev >= max_synthdev)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)) && !orig_dev)
@@ -869,7 +1530,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
dev = inf.device;
- if (dev < 0 || dev >= num_midis)
+ if (dev < 0 || dev >= max_mididev)
return RET_ERROR (ENXIO);
IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf));
@@ -949,7 +1610,9 @@ sequencer_ioctl (int dev, struct fileinfo *file,
{
int tmp = IOCTL_IN (arg);
- if (dev) /* Patch manager */
+ if (dev) /*
+ * Patch manager
+ */
return RET_ERROR (EIO);
if (tmp < 1)
@@ -961,8 +1624,23 @@ sequencer_ioctl (int dev, struct fileinfo *file,
}
break;
+ case SNDCTL_MIDI_PRETIME:
+ {
+ int val = IOCTL_IN (arg);
+
+ if (val < 0)
+ val = 0;
+
+ val = (HZ * val) / 10;
+ pre_event_timeout = val;
+ return IOCTL_OUT (arg, val);
+ }
+ break;
+
default:
- if (dev) /* Patch manager */
+ if (dev) /*
+ * Patch manager
+ */
return RET_ERROR (EIO);
if (mode == OPEN_READ)
@@ -983,6 +1661,8 @@ sequencer_ioctl (int dev, struct fileinfo *file,
int
sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
{
+ unsigned long flags;
+
dev = dev >> 4;
switch (sel_type)
@@ -990,17 +1670,22 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
case SEL_IN:
if (!iqlen)
{
+ DISABLE_INTR (flags);
+ midi_sleep_flag.mode = WK_SLEEP;
select_wait (&midi_sleeper, wait);
+ RESTORE_INTR (flags);
return 0;
}
return 1;
-
break;
case SEL_OUT:
if (qlen >= SEQ_MAX_QUEUE)
{
+ DISABLE_INTR (flags);
+ seq_sleep_flag.mode = WK_SLEEP;
select_wait (&seq_sleeper, wait);
+ RESTORE_INTR (flags);
return 0;
}
return 1;
@@ -1034,7 +1719,7 @@ note_to_freq (int note_num)
{
261632, 277189, 293671, 311132, 329632, 349232,
369998, 391998, 415306, 440000, 466162, 493880
- }; /* Note freq*1000 for octave 5 */
+ };
#define BASE_OCTAVE 5
@@ -1048,7 +1733,9 @@ 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;
}
@@ -1094,12 +1781,17 @@ compute_finetune (unsigned long base_freq, int bend, int range)
semitones = bend / 100;
cents = bend % 100;
- amount = semitone_tuning[semitones] * multiplier * cent_tuning[cents] / 10000;
+ amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents])
+ / 10000;
if (negative)
- return (base_freq * 10000) / amount; /* Bend down */
+ return (base_freq * 10000) / amount; /*
+ * Bend down
+ */
else
- return (base_freq * amount) / 10000; /* Bend up */
+ return (base_freq * amount) / 10000; /*
+ * Bend up
+ */
}
@@ -1115,7 +1807,9 @@ sequencer_init (long mem_start)
}
#else
-/* Stub version */
+/*
+ * Stub version
+ */
int
sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
diff --git a/sys/i386/isa/sound/sound_calls.h b/sys/i386/isa/sound/sound_calls.h
index 161118a..f67ea05 100644
--- a/sys/i386/isa/sound/sound_calls.h
+++ b/sys/i386/isa/sound/sound_calls.h
@@ -1,15 +1,14 @@
/*
- * $Id: sound_calls.h,v 1.5 1994/08/02 07:40:51 davidg Exp $
- */
-/*
* DMA buffer calls
+ *
+ * $Id: sound_calls.h,v 1.6 1994/09/27 17:58:28 davidg Exp $
*/
+
#ifndef _MACHINE_ISA_SOUND_H_
#define _MACHINE_ISA_SOUND_H_
int DMAbuf_open(int dev, int mode);
int DMAbuf_release(int dev, int mode);
-int DMAbuf_read (int dev, snd_rw_buf *user_buf, int count);
int DMAbuf_getwrbuffer(int dev, char **buf, int *size);
int DMAbuf_getrdbuffer(int dev, char **buf, int *len);
int DMAbuf_rmchars(int dev, int buff_no, int c);
@@ -51,6 +50,8 @@ long sequencer_init (long mem_start);
void sequencer_timer(void);
int note_to_freq(int note_num);
unsigned long compute_finetune(unsigned long base_freq, int bend, int range);
+void seq_input_event(unsigned char *event, int len);
+void seq_copy_to_input (unsigned char *event, int len);
#ifdef ALLOW_SELECT
int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
@@ -70,6 +71,10 @@ int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
long MIDIbuf_init(long mem_start);
+#ifdef ALLOW_SELECT
+int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+#endif
+
/*
* System calls for the generic midi interface.
*
@@ -130,10 +135,10 @@ int sb16_dsp_detect(struct address_info *hw_config);
void sb16midiintr (int unit);
long attach_sb16midi(long mem_start, struct address_info * hw_config);
int probe_sb16midi(struct address_info *hw_config);
+void sb_midi_interrupt(int dummy);
/* From sb_midi.c */
void sb_midi_init(int model);
-void sb_midi_interrupt(int dummy);
/* From sb_mixer.c */
void sb_setmixer (unsigned int port, unsigned int value);
@@ -177,6 +182,8 @@ long attach_gus_card(long mem_start, struct address_info * hw_config);
int probe_gus(struct address_info *hw_config);
int gus_set_midi_irq(int num);
void gusintr(int);
+long attach_gus_db16(long mem_start, struct address_info * hw_config);
+int probe_gus_db16(struct address_info *hw_config);
/* From gus_wave.c */
int gus_wave_detect(int baseaddr);
@@ -196,6 +203,10 @@ void gus_midi_interrupt(int dummy);
long attach_mpu401(long mem_start, struct address_info * hw_config);
int probe_mpu401(struct address_info *hw_config);
+/* From uart6850.c */
+long attach_uart6850(long mem_start, struct address_info * hw_config);
+int probe_uart6850(struct address_info *hw_config);
+
/* From opl3.c */
void enable_opl3_mode(int left, int right, int both);
@@ -211,4 +222,28 @@ int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2,
/* From ics2101.c */
long ics2101_mixer_init(long mem_start);
-#endif
+/* From sound_timer.c */
+void sound_timer_init(int io_base);
+void sound_timer_interrupt(void);
+
+/* From ad1848.c */
+void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture);
+int ad1848_detect (int io_base);
+void ad1848_interrupt (int dev);
+long attach_ms_sound(long mem_start, struct address_info * hw_config);
+int probe_ms_sound(struct address_info *hw_config);
+
+/* From pss.c */
+int probe_pss (struct address_info *hw_config);
+long attach_pss (long mem_start, struct address_info *hw_config);
+
+int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+int pss_open (int dev, struct fileinfo *file);
+void pss_release (int dev, struct fileinfo *file);
+int pss_ioctl (int dev, struct fileinfo *file,
+ unsigned int cmd, unsigned int arg);
+int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
+long pss_init(long mem_start);
+
+#endif /* _MACHINE_ISA_SOUND_H_ */
diff --git a/sys/i386/isa/sound/sound_config.h b/sys/i386/isa/sound/sound_config.h
index e692eae..1938621 100644
--- a/sys/i386/isa/sound/sound_config.h
+++ b/sys/i386/isa/sound/sound_config.h
@@ -26,11 +26,22 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sound_config.h,v 1.5 1994/08/02 07:40:53 davidg Exp $
*/
#include "local.h"
+#if defined(ISC) || defined(SCO) || defined(SVR42)
+#define GENERIC_SYSV
+#endif
+
+/*
+ * Disable the AD1848 driver if there are no other drivers requiring it.
+ */
+
+#if defined(EXCLUDE_GUS16) && defined(EXCLUDE_MSS) && defined(EXCLUDE_PSS) && defined(EXCLUDE_GUSMAX)
+#define EXCLUDE_AD1848
+#endif
#undef CONFIGURE_SOUNDCARD
#undef DYNAMIC_BUFFER
@@ -57,20 +68,6 @@
#define SND_DEFAULT_ENABLE 1
#endif
-/** UWM - new MIDI stuff **/
-
-#ifdef EXCLUDE_CHIP_MIDI
-#ifndef EXCLUDE_PRO_MIDI
-#define EXCLUDE_PRO_MIDI
-#endif
-#endif
-
-/** UWM - stuff **/
-
-#if defined(EXCLUDE_SEQUENCER) && defined(EXCLUDE_AUDIO)
-#undef CONFIGURE_SOUNDCARD
-#endif
-
#ifdef CONFIGURE_SOUNDCARD
/* ****** IO-address, DMA and IRQ settings ****
@@ -126,6 +123,18 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define GUS_DMA 6
#endif
+#ifndef GUS16_BASE
+#define GUS16_BASE 0x530
+#endif
+
+#ifndef GUS16_IRQ
+#define GUS16_IRQ 7
+#endif
+
+#ifndef GUS16_DMA
+#define GUS16_DMA 3
+#endif
+
#ifndef MPU_BASE
#define MPU_BASE 0x330
#endif
@@ -134,6 +143,31 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define MPU_IRQ 6
#endif
+/* Echo Personal Sound System */
+#ifndef PSS_BASE
+#define PSS_BASE 0x220 /* 0x240 or */
+#endif
+
+#ifndef PSS_IRQ
+#define PSS_IRQ 7
+#endif
+
+#ifndef PSS_DMA
+#define PSS_DMA 1
+#endif
+
+#ifndef MSS_BASE
+#define MSS_BASE 0x530
+#endif
+
+#ifndef MSS_IRQ
+#define MSS_IRQ 10
+#endif
+
+#ifndef MSS_DMA
+#define MSS_DMA 3
+#endif
+
#ifndef MAX_REALTIME_FACTOR
#define MAX_REALTIME_FACTOR 4
#endif
@@ -165,48 +199,42 @@ If your card has nonstandard I/O address or IRQ number, change defines
driver. (There is no need to alter this) */
#define SEQ_MAX_QUEUE 1024
-#define SBFM_MAXINSTR (256) /* Size of the FM Instrument
- bank */
+#define SBFM_MAXINSTR (256) /* Size of the FM Instrument bank */
/* 128 instruments for general MIDI setup and 16 unassigned */
-#define SND_NDEVS 50 /* Number of supported devices */
+/*
+ * Minor numbers for the sound driver.
+ *
+ * Unfortunately Creative called the codec chip of SB as a DSP. For this
+ * reason the /dev/dsp is reserved for digitized audio use. There is a
+ * device for true DSP processors but it will be called something else.
+ * In v3.0 it's /dev/sndproc but this could be a temporary solution.
+ */
+
+#define SND_NDEVS 256 /* Number of supported devices */
#define SND_DEV_CTL 0 /* Control port /dev/mixer */
#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
synthesizer and MIDI output) */
-#define SND_DEV_MIDIN 2 /* MIDI input /dev/midin (not implemented
- yet) */
+#define SND_DEV_MIDIN 2 /* Raw midi access */
#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
-#define SND_DEV_STATUS 6 /* /dev/sndstatus */
-
-/* UWM ... note add new MIDI devices here..
- * Also do not forget to add table midi_supported[]
- * Minor numbers for on-chip midi devices start from 15.. and
- * should be contiguous.. viz. 15,16,17....
- * ERROR!!!!!!!!! NO NO. Minor numbers above 15 are reserved!!!!!! Hannu
- * Also note the max # of midi devices as MAX_MIDI_DEV
- */
-
-#define CMIDI_DEV_PRO 15 /* Chip midi device == /dev/pro_midi */
-
-/*
- * Add other midis here...
- .
- .
- .
- .
- */
+#define SND_DEV_STATUS 6 /* /dev/sndstat */
+/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
+#define SND_DEV_SEQ2 8 /* /dev/sequecer, level 2 interface */
+#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
+#define SND_DEV_PSS SND_DEV_SNDPROC
#define DSP_DEFAULT_SPEED 8000
#define ON 1
#define OFF 0
-#define MAX_DSP_DEV 4
+#define MAX_AUDIO_DEV 5
#define MAX_MIXER_DEV 2
#define MAX_SYNTH_DEV 3
-#define MAX_MIDI_DEV 4
+#define MAX_MIDI_DEV 6
+#define MAX_TIMER_DEV 3
struct fileinfo {
int mode; /* Open mode */
@@ -218,6 +246,20 @@ struct address_info {
int dma;
};
+#define SYNTH_MAX_VOICES 32
+
+struct voice_alloc_info {
+ int max_voice;
+ int used_voices;
+ int ptr; /* For device specific use */
+ unsigned short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */
+ };
+
+struct channel_info {
+ int pgm_num;
+ unsigned char controllers[128];
+ };
+
/*
* Process wakeup reasons
*/
@@ -237,6 +279,11 @@ struct address_info {
#ifndef DEB
#define DEB(x)
+
+#define TIMER_ARMED 121234
+#define TIMER_NOT_ARMED 1
+
+#define FUTURE_VERSION
#endif
#endif
diff --git a/sys/i386/isa/sound/sound_switch.c b/sys/i386/isa/sound/sound_switch.c
index a271a6a..de35b0d 100644
--- a/sys/i386/isa/sound/sound_switch.c
+++ b/sys/i386/isa/sound/sound_switch.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: sound_switch.c,v 1.3 1994/08/02 07:40:55 davidg Exp $
*/
#include "sound_config.h"
@@ -41,9 +41,11 @@ static struct sbc_device sbc_devices[SND_NDEVS] =
{
{0}};
-static int in_use = 0; /* Total # of open device files (excluding
+static int in_use = 0; /*
- * minor 0) */
+
+ * * * * Total # of open device files
+ * (excluding * * * minor 0) */
/*
* /dev/sndstatus -device
@@ -57,7 +59,9 @@ put_status (char *s)
{
int l;
- for (l = 0; l < 256, s[l]; l++); /* l=strlen(s); */
+ for (l = 0; l < 256, s[l]; l++); /*
+ * l=strlen(s);
+ */
if (status_len + l >= 4000)
return 0;
@@ -122,37 +126,58 @@ init_status (void)
if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
return;
- if (!put_status ("\n\nHW config: \n"))
+ if (!put_status ("\n\nInstalled drivers: \n"))
return;
for (i = 0; i < (num_sound_drivers - 1); i++)
{
- if (!supported_drivers[i].enabled)
- if (!put_status ("("))
- return;
-
if (!put_status ("Type "))
return;
- if (!put_status_int (supported_drivers[i].card_type, 10))
+ if (!put_status_int (sound_drivers[i].card_type, 10))
return;
if (!put_status (": "))
return;
- if (!put_status (supported_drivers[i].name))
+ if (!put_status (sound_drivers[i].name))
+ return;
+
+ if (!put_status ("\n"))
return;
+ }
+
+ if (!put_status ("\n\nCard config: \n"))
+ return;
+
+ for (i = 0; i < (num_sound_cards - 1); i++)
+ {
+ int drv;
+
+ if (!snd_installed_cards[i].enabled)
+ if (!put_status ("("))
+ return;
+
+ /*
+ * if (!put_status_int(snd_installed_cards[i].card_type, 10)) return;
+ * if (!put_status (": ")) return;
+ */
+
+ if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) != -1)
+ if (!put_status (sound_drivers[drv].name))
+ return;
+
if (!put_status (" at 0x"))
return;
- if (!put_status_int (supported_drivers[i].config.io_base, 16))
+ if (!put_status_int (snd_installed_cards[i].config.io_base, 16))
return;
if (!put_status (" irq "))
return;
- if (!put_status_int (supported_drivers[i].config.irq, 10))
+ if (!put_status_int (snd_installed_cards[i].config.irq, 10))
return;
if (!put_status (" drq "))
return;
- if (!put_status_int (supported_drivers[i].config.dma, 10))
+ if (!put_status_int (snd_installed_cards[i].config.dma, 10))
return;
- if (!supported_drivers[i].enabled)
+ if (!snd_installed_cards[i].enabled)
if (!put_status (")"))
return;
@@ -163,13 +188,13 @@ init_status (void)
if (!put_status ("\nPCM devices:\n"))
return;
- for (i = 0; i < num_dspdevs; i++)
+ for (i = 0; i < num_audiodevs; i++)
{
if (!put_status_int (i, 10))
return;
if (!put_status (": "))
return;
- if (!put_status (dsp_devs[i]->name))
+ if (!put_status (audio_devs[i]->name))
return;
if (!put_status ("\n"))
return;
@@ -205,16 +230,27 @@ init_status (void)
return;
}
- if (num_mixers)
+ if (!put_status ("\nMIDI Timers:\n"))
+ return;
+
+ for (i = 0; i < num_sound_timers; i++)
{
- if (!put_status ("\nMixer(s) installed\n"))
+ if (!put_status_int (i, 10))
return;
- }
- else
- {
- if (!put_status ("\nNo mixers installed\n"))
+ if (!put_status (": "))
+ return;
+ if (!put_status (sound_timer_devs[i]->info.name))
+ return;
+ if (!put_status ("\n"))
return;
}
+
+ if (!put_status ("\n"))
+ return;
+ if (!put_status_int (num_mixers, 10))
+ return;
+ if (!put_status (" mixer(s) installed\n"))
+ return;
}
static int
@@ -257,14 +293,20 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
break;
case SND_DEV_SEQ:
+ case SND_DEV_SEQ2:
return sequencer_read (dev, file, buf, count);
break;
-#ifndef EXCLUDE_MPU401
+#ifndef EXCLUDE_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_read (dev, file, buf, count);
#endif
+#ifndef EXCLUDE_PSS
+ case SND_DEV_PSS:
+ return pss_read (dev, file, buf, count);
+#endif
+
default:
printk ("Sound: Undefined minor device %d\n", dev);
}
@@ -282,6 +324,7 @@ sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
case SND_DEV_SEQ:
+ case SND_DEV_SEQ2:
return sequencer_write (dev, file, buf, count);
break;
@@ -291,6 +334,16 @@ sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
return audio_write (dev, file, buf, count);
break;
+#ifndef EXCLUDE_MIDI
+ case SND_DEV_MIDIN:
+ return MIDIbuf_write (dev, file, buf, count);
+#endif
+
+#ifndef EXCLUDE_PSS
+ case SND_DEV_PSS:
+ return pss_write (dev, file, buf, count);
+#endif
+
default:
return RET_ERROR (EPERM);
}
@@ -328,17 +381,25 @@ sound_open_sw (int dev, struct fileinfo *file)
break;
case SND_DEV_SEQ:
+ case SND_DEV_SEQ2:
if ((retval = sequencer_open (dev, file)) < 0)
return retval;
break;
-#ifndef EXCLUDE_MPU401
+#ifndef EXCLUDE_MIDI
case SND_DEV_MIDIN:
if ((retval = MIDIbuf_open (dev, file)) < 0)
return retval;
break;
#endif
+#ifndef EXCLUDE_PSS
+ case SND_DEV_PSS:
+ if ((retval = pss_open (dev, file)) < 0)
+ return retval;
+ break;
+#endif
+
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
@@ -376,15 +437,22 @@ sound_release_sw (int dev, struct fileinfo *file)
break;
case SND_DEV_SEQ:
+ case SND_DEV_SEQ2:
sequencer_release (dev, file);
break;
-#ifndef EXCLUDE_MPU401
+#ifndef EXCLUDE_MIDI
case SND_DEV_MIDIN:
MIDIbuf_release (dev, file);
break;
#endif
+#ifndef EXCLUDE_PSS
+ case SND_DEV_PSS:
+ pss_release (dev, file);
+ break;
+#endif
+
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
@@ -405,6 +473,12 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
{
DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
+ if ((dev & 0x0f) != SND_DEV_CTL && num_mixers > 0)
+ if ((cmd >> 8) & 0xff == 'M') /*
+ * Mixer ioctl
+ */
+ return mixer_devs[0]->ioctl (0, cmd, arg);
+
switch (dev & 0x0f)
{
@@ -413,13 +487,16 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
if (!num_mixers)
return RET_ERROR (ENXIO);
- if ((dev >> 4) >= num_mixers)
+ dev = dev >> 4;
+
+ if (dev >= num_mixers)
return RET_ERROR (ENXIO);
- return mixer_devs[dev >> 4]->ioctl (dev >> 4, cmd, arg);
+ return mixer_devs[dev]->ioctl (dev, cmd, arg);
break;
case SND_DEV_SEQ:
+ case SND_DEV_SEQ2:
return sequencer_ioctl (dev, file, cmd, arg);
break;
@@ -429,12 +506,18 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
return audio_ioctl (dev, file, cmd, arg);
break;
-#ifndef EXCLUDE_MPU401
+#ifndef EXCLUDE_MIDI
case SND_DEV_MIDIN:
return MIDIbuf_ioctl (dev, file, cmd, arg);
break;
#endif
+#ifndef EXCLUDE_PSS
+ case SND_DEV_PSS:
+ return pss_ioctl (dev, file, cmd, arg);
+ break;
+#endif
+
default:
return RET_ERROR (EPERM);
break;
diff --git a/sys/i386/isa/sound/sound_timer.c b/sys/i386/isa/sound/sound_timer.c
index c6544c8..79a3ff1 100644
--- a/sys/i386/isa/sound/sound_timer.c
+++ b/sys/i386/isa/sound/sound_timer.c
@@ -26,6 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $Id: sb16_dsp.c,v 1.7 1994/09/27 17:58:24 davidg Exp $
*/
#define SEQUENCER_C
diff --git a/sys/i386/isa/sound/soundcard.c b/sys/i386/isa/sound/soundcard.c
index f3acf7e..aab352d 100644
--- a/sys/i386/isa/sound/soundcard.c
+++ b/sys/i386/isa/sound/soundcard.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: soundcard.c,v 1.18 1994/08/02 07:40:58 davidg Exp $
+ * $Id: soundcard.c,v 1.19 1994/09/27 17:58:30 davidg Exp $
*/
#include "sound_config.h"
@@ -52,9 +52,6 @@ static int timer_running = 0;
static int soundcards_installed = 0; /* Number of installed
* soundcards */
static int soundcard_configured = 0;
-extern char *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT];
-extern unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
-extern int snd_raw_count[MAX_DSP_DEV];
static struct fileinfo files[SND_NDEVS];
@@ -187,7 +184,6 @@ int
sndattach (struct isa_device *dev)
{
int i;
- static int dsp_initialized = 0;
static int midi_initialized = 0;
static int seq_initialized = 0;
static int generic_midi_initialized = 0;
@@ -218,37 +214,21 @@ sndattach (struct isa_device *dev)
printf("\n");
#ifndef EXCLUDE_AUDIO
- soundcard_configured = 1;
- if (num_dspdevs)
- sound_mem_init ();
-#endif
-
- if (num_dspdevs && !dsp_initialized) /* Audio devices present */
+ if (num_audiodevs) /* Audio devices present */
{
- dsp_initialized = 1;
mem_start = DMAbuf_init (mem_start);
mem_start = audio_init (mem_start);
+ sound_mem_init ();
}
-/** UWM stuff **/
-
-#ifndef EXCLUDE_CHIP_MIDI
-
- if (!generic_midi_initialized)
- {
- generic_midi_initialized = 1;
- mem_start = CMIDI_init (mem_start);
- }
-
-#endif
+ soundcard_configured = 1;
+#endif
-#ifndef EXCLUDE_MPU401
if (num_midis && !midi_initialized)
{
midi_initialized = 1;
mem_start = MIDIbuf_init (mem_start);
}
-#endif
if ((num_midis + num_synths) && !seq_initialized)
{
@@ -268,14 +248,6 @@ tenmicrosec (void)
inb (0x80);
}
-#ifdef EXCLUDE_GUS
-void
-gusintr (int unit)
-{
- return;
-}
-#endif
-
void
request_sound_timer (int count)
{
@@ -316,50 +288,52 @@ sound_mem_init (void)
{
int i, dev;
unsigned long dma_pagesize;
+ struct dma_buffparms *dmap;
static unsigned long dsp_init_mask = 0;
- for (dev = 0; dev < num_dspdevs; dev++) /* Enumerate devices */
+ for (dev = 0; dev < num_audiodevs; dev++) /* Enumerate devices */
if (!(dsp_init_mask & (1 << dev))) /* Not already done */
- if (sound_buffcounts[dev] > 0 && sound_dsp_dmachan[dev] > 0)
+ if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan > 0)
{
dsp_init_mask |= (1 << dev);
+ dmap = audio_devs[dev]->dmap;
- if (sound_dma_automode[dev])
- sound_buffcounts[dev] = 1;
+ if (audio_devs[dev]->flags & DMA_AUTOMODE)
+ audio_devs[dev]->buffcount = 1;
- if (sound_dsp_dmachan[dev] > 3 && sound_buffsizes[dev] > 65536)
+ if (audio_devs[dev]->dmachan > 3 && audio_devs[dev]->buffsize > 65536)
dma_pagesize = 131072; /* 128k */
else
dma_pagesize = 65536;
/* More sanity checks */
- if (sound_buffsizes[dev] > dma_pagesize)
- sound_buffsizes[dev] = dma_pagesize;
- sound_buffsizes[dev] &= ~0xfff; /* Truncate to n*4k */
- if (sound_buffsizes[dev] < 4096)
- sound_buffsizes[dev] = 4096;
+ if (audio_devs[dev]->buffsize > dma_pagesize)
+ audio_devs[dev]->buffsize = dma_pagesize;
+ audio_devs[dev]->buffsize &= ~0xfff; /* Truncate to n*4k */
+ if (audio_devs[dev]->buffsize < 4096)
+ audio_devs[dev]->buffsize = 4096;
/* Now allocate the buffers */
- for (snd_raw_count[dev] = 0; snd_raw_count[dev] < sound_buffcounts[dev]; snd_raw_count[dev]++)
+ for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; dmap->raw_count++)
{
- char *tmpbuf = (char *)vm_page_alloc_contig(sound_buffsizes[dev], 0ul, 0xfffffful, dma_pagesize);
+ char *tmpbuf = (char *)vm_page_alloc_contig(audio_devs[dev]->buffsize, 0ul, 0xfffffful, dma_pagesize);
if (tmpbuf == NULL)
{
printk ("snd: Unable to allocate %d bytes of buffer\n",
- sound_buffsizes[dev]);
+ audio_devs[dev]->buffsize);
return;
}
- snd_raw_buf[dev][snd_raw_count[dev]] = tmpbuf;
+ dmap->raw_buf[dmap->raw_count] = tmpbuf;
/*
* Use virtual address as the physical address, since
* isa_dmastart performs the phys address computation.
*/
- snd_raw_buf_phys[dev][snd_raw_count[dev]] =
- (unsigned long) snd_raw_buf[dev][snd_raw_count[dev]];
+ dmap->raw_buf_phys[dmap->raw_count] =
+ (unsigned long) dmap->raw_buf[dmap->raw_count];
}
} /* for dev */
diff --git a/sys/i386/isa/sound/sys_timer.c b/sys/i386/isa/sound/sys_timer.c
index 1000045..383fe3c 100644
--- a/sys/i386/isa/sound/sys_timer.c
+++ b/sys/i386/isa/sound/sys_timer.c
@@ -26,6 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $Id: sys_timer.c,v 1.7 1994/09/27 17:58:24 davidg Exp $
*/
#define SEQUENCER_C
diff --git a/sys/i386/isa/sound/uart6850.c b/sys/i386/isa/sound/uart6850.c
index ca63135..f8e23a0 100644
--- a/sys/i386/isa/sound/uart6850.c
+++ b/sys/i386/isa/sound/uart6850.c
@@ -26,6 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $Id: uart6850.c,v 1.7 1994/09/27 17:58:24 davidg Exp $
*/
#include "sound_config.h"
diff --git a/sys/i386/isa/sound/ulaw.h b/sys/i386/isa/sound/ulaw.h
index 9984e36..be9f92d 100644
--- a/sys/i386/isa/sound/ulaw.h
+++ b/sys/i386/isa/sound/ulaw.h
@@ -1,6 +1,3 @@
-/*
- * $Id$
- */
static unsigned char ulaw_dsp[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
OpenPOWER on IntegriCloud