diff options
author | swallace <swallace@FreeBSD.org> | 1994-10-01 02:17:17 +0000 |
---|---|---|
committer | swallace <swallace@FreeBSD.org> | 1994-10-01 02:17:17 +0000 |
commit | 3b7740a11ff2432cc8bbcfa2524ebc859cc4b643 (patch) | |
tree | 09d7913c895c85fdedc9a099ad0b7ac3ee4b3ef1 | |
parent | c2da26491490b8f15ad302a5fdf2a9532a07df5d (diff) | |
download | FreeBSD-src-3b7740a11ff2432cc8bbcfa2524ebc859cc4b643.zip FreeBSD-src-3b7740a11ff2432cc8bbcfa2524ebc859cc4b643.tar.gz |
Merged in changes to Hannu Savolainen's VoxWare sound drivers, version 2.9.
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 *) ¶ms, 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, |