diff options
author | ache <ache@FreeBSD.org> | 1994-04-23 01:50:14 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 1994-04-23 01:50:14 +0000 |
commit | 8c1b1c10fa5c063441fc84538cf506af4de8e39a (patch) | |
tree | eefc94a690c6ee2a3b9ead56cb983ce789332964 | |
parent | 17ab3af527a10374eb42d4a22109e18a16d8a96b (diff) | |
download | FreeBSD-src-8c1b1c10fa5c063441fc84538cf506af4de8e39a.zip FreeBSD-src-8c1b1c10fa5c063441fc84538cf506af4de8e39a.tar.gz |
Update sound driver to version 2.5
31 files changed, 1302 insertions, 965 deletions
diff --git a/sys/i386/isa/sound/CHANGELOG b/sys/i386/isa/sound/CHANGELOG index 78168dd..6a9bef1 100644 --- a/sys/i386/isa/sound/CHANGELOG +++ b/sys/i386/isa/sound/CHANGELOG @@ -1,6 +1,26 @@ -Changelog for version 2.4 +Changelog for version 2.5 ------------------------- +Since 2.5-beta2 +- Some fine tuning to the GUS v3.7 mixer code. +- Fixed speed limits for the plain SB (1.0 to 2.0). + +Since 2.5-beta +- Fixed OPL-3 detection with SB. Caused problems with PAS16. +- GUS v3.7 mixer support. + +Since 2.4 +- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h). +- Fixed truncated sound on /dev/dsp when the device is closed. +- Linear volume mode for GUS +- Pitch bends larger than +/- 2 octaves. +- MIDI recording for SB and SB Pro. (Untested). +- Some other fixes. +- SB16 MIDI and DSP drivers only initialized if SB16 actually installed. +- Implemented better detection for OPL-3. This should be usefull if you + have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3. +- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested). + Since 2.3b - Fixed bug which made it impossible to make long recordings to disk. Recording was not restarted after a buffer overflow situation. diff --git a/sys/i386/isa/sound/RELNOTES.Linux b/sys/i386/isa/sound/RELNOTES.Linux index bd47ede..ea57d0a 100644 --- a/sys/i386/isa/sound/RELNOTES.Linux +++ b/sys/i386/isa/sound/RELNOTES.Linux @@ -1,5 +1,15 @@ -Release notes for the Linux Sound Driver 2.4 +Release notes for the Linux Sound Driver 2.5 -------------------------------------------- +There is also a version called 2.5-beta floating around the net. This +version contains some fixes after it. Mainly to the SB and GUS code. + +CAUTION! The SVR4.2 port has not been tested much. Backup your system + carefully before trying it. + +This is mainly a bug fix release. There are couple of new things such as +linear volume mode for GUS and MIDI recording for SB 2.0 and SB Pro. +Also this version supports the mixer of GUS v3.7. (Support for GUS MAX and +the 16-bit daughtercard is coming sooner or later). NOTE! The sound driver is a part of the Linux kernel distribution also. Check that your kernel doesn't have more recent version than this @@ -17,17 +27,13 @@ time with the /dev/dsp. Also the WaveBlaster daughter board is supported. No support for the ASP chip yet (the ASP chip can be installed but it's not used by the driver). -You will need the snd-util-2.4.tar.gz and snd-data-0.1.tar.Z +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/*. -There is a new version of the tracker program available (tracker-3_19.lzh) but -I don't know where it is available. The tracker 3.10 has bugs and it don't work -without some fixes. Look at the README of the snd-util-2.3. - If you are looking for the installation instructions, please -look at linux/Readme. +look at $OS/Readme. This version supports the following soundcards: GUS, SoundBlaster, SB Pro, SB16, Pro Audio Spectrum 16 and AdLib. @@ -220,21 +226,28 @@ 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 + 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 Initial ISC port + Jim Lowe Initial FreeBSD port Anders Baekgaard Bughunting and valuable suggestions. - Joerg Schubert SB16 DSP support. - Andrew Robinson Improvements to the GUS driver + 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. + Ian Hartas SVR4.2 port + Markus Aroharju and + Risto Kankkunen Major contributions to the mixer support + of GUS v3.7. + Hunyue Yau Sound Galaxy NX Pro mixer support. Regards, Hannu Savolainen -hsavolai@cs.helsinki.fi +hannu@voxware.pp.fi, Hannu.Savolainen@Helsinki.fi Snail mail: Hannu Savolainen Pallaksentie 4 A 2 diff --git a/sys/i386/isa/sound/adlib_card.c b/sys/i386/isa/sound/adlib_card.c index 3b7df5e..6365069 100644 --- a/sys/i386/isa/sound/adlib_card.c +++ b/sys/i386/isa/sound/adlib_card.c @@ -1,10 +1,10 @@ /* * sound/adlib_card.c - * + * * Detection routine for the AdLib card. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff --git a/sys/i386/isa/sound/audio.c b/sys/i386/isa/sound/audio.c index 84c1f6c..f27f9d5 100644 --- a/sys/i386/isa/sound/audio.c +++ b/sys/i386/isa/sound/audio.c @@ -1,10 +1,10 @@ /* * sound/audio.c - * + * * Device file manager for /dev/audio - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -116,9 +116,9 @@ translate_bytes (const void *table, void *buff, unsigned long n) "1:\tlodsb\n\t" "xlatb\n\t" "stosb\n\t" -"loop 1b\n\t": -: "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff) -: "bx", "cx", "di", "si", "ax"); + "loop 1b\n\t": + :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff) + :"bx", "cx", "di", "si", "ax"); } #endif @@ -183,7 +183,7 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) /* This just allows interrupts while the conversion is running */ __asm__ ("sti"); #endif - translate_bytes (ulaw_dsp, &wr_dma_buf[dev][wr_buff_ptr[dev]], l); + translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l); } c -= l; @@ -244,7 +244,7 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) __asm__ ("sti"); #endif - translate_bytes (dsp_ulaw, dmabuf, l); + translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l); } COPY_TO_USER (buf, p, dmabuf, l); diff --git a/sys/i386/isa/sound/dev_table.c b/sys/i386/isa/sound/dev_table.c index 5f6fc7b..7f7cae1 100644 --- a/sys/i386/isa/sound/dev_table.c +++ b/sys/i386/isa/sound/dev_table.c @@ -1,10 +1,10 @@ /* * sound/dev_table.c - * + * * Device call tables. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define _DEV_TABLE_C_ @@ -116,12 +116,12 @@ sndtable_get_cardcount (void) } #ifdef linux -void +void sound_setup (char *str, int *ints) { int i, n = sizeof (supported_drivers) / sizeof (struct card_info); -/* + /* * First disable all drivers */ @@ -130,7 +130,7 @@ sound_setup (char *str, int *ints) if (ints[0] == 0 || ints[1] == 0) return; -/* + /* * Then enable them one by time */ @@ -169,8 +169,9 @@ sound_setup (char *str, int *ints) } } } + #else -void +void sound_chconf (int card_type, int ioaddr, int irq, int dma) { int i, n = sizeof (supported_drivers) / sizeof (struct card_info); @@ -193,6 +194,7 @@ sound_chconf (int card_type, int ioaddr, int irq, int dma) supported_drivers[ptr].config.dma = dma; } } + #endif struct address_info * @@ -211,4 +213,5 @@ sound_getconf (int card_type) return &supported_drivers[ptr].config; } + #endif diff --git a/sys/i386/isa/sound/dev_table.h b/sys/i386/isa/sound/dev_table.h index 63e4776..4b656ba 100644 --- a/sys/i386/isa/sound/dev_table.h +++ b/sys/i386/isa/sound/dev_table.h @@ -58,6 +58,9 @@ struct generic_midi_info{ struct audio_operations { char name[32]; + int flags; +#define NOTHING_SPECIAL 0 +#define NEEDS_RESTART 1 int (*open) (int dev, int mode); void (*close) (int dev); void (*output_block) (int dev, unsigned long buf, @@ -96,6 +99,7 @@ struct synth_operations { void (*aftertouch) (int dev, int voice, int pressure); void (*controller) (int dev, int voice, int ctrl_num, int value); void (*panning) (int dev, int voice, int value); + void (*volume_method) (int dev, int mode); int (*pmgr_interface) (int dev, struct patmgr_info *info); }; diff --git a/sys/i386/isa/sound/dmabuf.c b/sys/i386/isa/sound/dmabuf.c index 4b75e40..851a70a1 100644 --- a/sys/i386/isa/sound/dmabuf.c +++ b/sys/i386/isa/sound/dmabuf.c @@ -1,10 +1,10 @@ /* * sound/dmabuf.c - * + * * The DMA buffer manager for digitized voice applications - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -49,10 +49,6 @@ #define DMODE_OUTPUT 1 #define DMODE_INPUT 2 -extern int sb_dsp_ok; -extern struct audio_operations sb_dsp_operations; -static int force_reset = 0; - DEFINE_WAIT_QUEUES (dev_sleeper[MAX_DSP_DEV], dev_sleep_flag[MAX_DSP_DEV]); static int dma_mode[MAX_DSP_DEV] = @@ -91,7 +87,7 @@ static int bufferalloc_done[MAX_DSP_DEV] = * Logical buffers for each devices */ -static int dev_nbufs[MAX_DSP_DEV]; /* # of logical buffers ( >= +static int dev_nbufs[MAX_DSP_DEV]; /* # of logical buffers ( >= * sound_buffcounts[dev] */ static int dev_counts[MAX_DSP_DEV][MAX_SUB_BUFFERS]; @@ -243,9 +239,6 @@ dma_reset (int dev) int retval; unsigned long flags; - if (!force_reset && sb_dsp_ok && dsp_devs[dev] == &sb_dsp_operations) - return; /* We don't need this code for SB */ - DISABLE_INTR (flags); dsp_devs[dev]->reset (dev); dsp_devs[dev]->close (dev); @@ -262,23 +255,18 @@ static int dma_sync (int dev) { unsigned long flags; - unsigned long time; - int timed_out; if (dma_mode[dev] == DMODE_OUTPUT) { DISABLE_INTR (flags); - timed_out = 0; - time = GET_TIME (); - while ((!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) || - dmabuf_interrupted[dev]) && !timed_out) + dmabuf_interrupted[dev])) && dev_qlen[dev]) { DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ); - if ((GET_TIME () - time) > (10 * HZ)) - timed_out = 1; + if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev])) + return dev_qlen[dev]; } RESTORE_INTR (flags); @@ -445,9 +433,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) switch (cmd) { case SNDCTL_DSP_RESET: - force_reset = 1; dma_reset (dev); - force_reset = 0; return 0; break; @@ -494,6 +480,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local) return dsp_devs[dev]->ioctl (dev, cmd, arg, local); } + /* NOTREACHED */ return RET_ERROR (EIO); } @@ -576,7 +563,8 @@ DMAbuf_start_output (int dev, int buff_no, int l) dev_counts[dev][dev_qtail[dev]] = l; - dev_needs_restart[dev] = (l != dev_buffsize[dev]); + dev_needs_restart[dev] = (l != dev_buffsize[dev]) && + (sound_dma_automode[dev] || dsp_devs[dev]->flags & NEEDS_RESTART); dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev]; @@ -615,11 +603,11 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) disable_dma (chan); clear_dma_ff (chan); set_dma_mode (chan, dma_mode | DMA_AUTOINIT); - set_dma_addr (chan, (caddr_t)snd_raw_buf_phys[dev][0]); - set_dma_count (chan, (unsigned)sound_buffsizes[dev]); - enable_dma ((unsigned)chan); + set_dma_addr (chan, snd_raw_buf_phys[dev][0]); + set_dma_count (chan, sound_buffsizes[dev]); + enable_dma (chan); RESTORE_INTR (flags); -#else +#else /* linux */ #ifdef __386BSD__ printk ("sound: Invalid DMA mode for device %d\n", dev); @@ -628,24 +616,24 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) (caddr_t)snd_raw_buf_phys[dev][0], sound_buffsizes[dev], chan); -#else -#if defined(ISC) || defined(SCO) +#else /* __386BSD__ */ +#if defined(ISC) || defined(SCO) || defined(SVR42) #ifndef DMAMODE_AUTO printk ("sound: Invalid DMA mode for device %d\n", dev); -#endif +#endif /* DMAMODE_AUTO */ dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode) #ifdef DMAMODE_AUTO | DMAMODE_AUTO -#endif +#endif /* DMAMODE_AUTO */ , snd_raw_buf_phys[dev][0], count); dma_enable (chan); -#else +#else /* SYSV */ #error This routine is not valid for this OS. -#endif -#endif +#endif /* SYSV */ +#endif /* __386BSD__ */ -#endif +#endif /* linux */ } else { @@ -658,24 +646,24 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode) set_dma_count (chan, count); enable_dma (chan); RESTORE_INTR (flags); -#else +#else /* linux */ #ifdef __386BSD__ isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE, (caddr_t)physaddr, count, chan); -#else +#else /* __386BSD__ */ -#if defined(ISC) || defined(SCO) +#if defined(ISC) || defined(SCO) || defined(SVR42) dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode), physaddr, count); dma_enable (chan); -#else +#else /* SYSV */ #error This routine is not valid for this OS. -#endif /* !ISC */ -#endif +#endif /* SYSV */ +#endif /* __386BSD__ */ -#endif +#endif /* linux */ } return count; @@ -724,7 +712,8 @@ DMAbuf_outputintr (int dev, int underrun_flag) { dev_underrun[dev]++; dsp_devs[dev]->halt_xfer (dev); - dev_needs_restart[dev] = 1; + dev_needs_restart[dev] = (sound_dma_automode[dev] || + dsp_devs[dev]->flags & NEEDS_RESTART); } DISABLE_INTR (flags); @@ -750,7 +739,7 @@ DMAbuf_inputintr (int dev) dev_underrun[dev]++; dsp_devs[dev]->halt_xfer (dev); dev_active[dev] = 0; - dev_needs_restart[dev] = 1; + dev_needs_restart[dev] = sound_dma_automode[dev]; } else { @@ -810,7 +799,7 @@ DMAbuf_reset_dma (int chan) /* * The sound_mem_init() is called by mem_init() immediately after mem_map is * initialized and before free_page_list is created. - * + * * This routine allocates DMA buffers at the end of available physical memory ( * <16M) and marks pages reserved at mem_map. */ diff --git a/sys/i386/isa/sound/gus_card.c b/sys/i386/isa/sound/gus_card.c index 29cc3d5..c7cfc0a 100644 --- a/sys/i386/isa/sound/gus_card.c +++ b/sys/i386/isa/sound/gus_card.c @@ -1,10 +1,10 @@ /* * sound/gus_card.c - * + * * Detection routine for the Gravis Ultrasound. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff --git a/sys/i386/isa/sound/gus_hw.h b/sys/i386/isa/sound/gus_hw.h index 48233e7..f97a0b8 100644 --- a/sys/i386/isa/sound/gus_hw.h +++ b/sys/i386/isa/sound/gus_hw.h @@ -24,6 +24,8 @@ #define u_Command (gus_base + 0x103) #define u_DataLo (gus_base + 0x104) #define u_DataHi (gus_base + 0x105) +#define u_MixData (gus_base + 0x106) /* Rev. 3.7+ mixing */ +#define u_MixSelect (gus_base + 0x506) /* registers. */ #define u_IrqStatus u_Status # define MIDI_TX_IRQ 0x01 /* pending MIDI xmit IRQ */ # define MIDI_RX_IRQ 0x02 /* pending MIDI recv IRQ */ @@ -32,4 +34,17 @@ # define WAVETABLE_IRQ 0x20 /* pending wavetable IRQ */ # define ENVELOPE_IRQ 0x40 /* pending volume envelope IRQ */ # define DMA_TC_IRQ 0x80 /* pending dma tc IRQ */ + +#define ICS2101 1 +# define ICS_MIXDEVS 6 +# define DEV_MIC 0 +# define DEV_LINE 1 +# define DEV_CD 2 +# define DEV_GF1 3 +# define DEV_UNUSED 4 +# define DEV_VOL 5 + +# define CHN_LEFT 0 +# define CHN_RIGHT 1 +#define CS4231 2 #define u_DRAMIO (gus_base + 0x107) diff --git a/sys/i386/isa/sound/gus_midi.c b/sys/i386/isa/sound/gus_midi.c index 5e06f7f..935c5c9 100644 --- a/sys/i386/isa/sound/gus_midi.c +++ b/sys/i386/isa/sound/gus_midi.c @@ -1,10 +1,10 @@ /* * sound/gus2_midi.c - * + * * The low level driver for the GUS Midi Interface. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff --git a/sys/i386/isa/sound/gus_vol.c b/sys/i386/isa/sound/gus_vol.c index 6e56d54..055a117 100644 --- a/sys/i386/isa/sound/gus_vol.c +++ b/sys/i386/isa/sound/gus_vol.c @@ -1,17 +1,18 @@ -/* +/* * gus_vol.c - Compute volume for GUS. - * + * * Greg Lee 1993. */ #include "sound_config.h" #ifndef EXCLUDE_GUS +#include "gus_linearvol.h" #define GUS_VOLUME gus_wave_volume extern int gus_wave_volume; -/* +/* * Calculate gus volume from note velocity, main volume, expression, and * intrinsic patch volume given in patch library. Expression is multiplied * in, so it emphasizes differences in note velocity, while main volume is @@ -20,7 +21,7 @@ extern int gus_wave_volume; * to expression controller messages, if they were found to be used for * dynamic volume adjustments, so here, main volume can be assumed to be * constant throughout a song.) - * + * * Intrinsic patch volume is added in, but if over 64 is also multiplied in, so * we can give a big boost to very weak voices like nylon guitar and the * basses. The normal value is 64. Strings are assigned lower values. @@ -31,27 +32,27 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) int i, m, n, x; - /* + /* * A voice volume of 64 is considered neutral, so adjust the main volume if * something other than this neutral value was assigned in the patch * library. */ x = 256 + 6 * (voicev - 64); - /* - * Boost expression by voice volume above neutral. + /* + * Boost expression by voice volume above neutral. */ if (voicev > 65) xpn += voicev - 64; xpn += (voicev - 64) / 2; - /* - * Combine multiplicative and level components. + /* + * Combine multiplicative and level components. */ x = vel * xpn * 6 + (voicev / 4) * x; #ifdef GUS_VOLUME - /* + /* * Further adjustment by installation-specific master volume control * (default 60). */ @@ -72,7 +73,7 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) else if (x >= 65535) return ((15 << 8) | 255); - /* + /* * Convert to gus's logarithmic form with 4 bit exponent i and 8 bit * mantissa m. */ @@ -89,14 +90,14 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) n >>= 1; i++; } - /* + /* * Mantissa is part of linear volume not expressed in exponent. (This is * not quite like real logs -- I wonder if it's right.) */ m = x - (1 << i); - /* - * Adjust mantissa to 8 bits. + /* + * Adjust mantissa to 8 bits. */ if (m > 0) { @@ -109,4 +110,38 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev) return ((i << 8) + m); } +/* + * Volume-values are interpreted as linear values. Volume is based on the + * value supplied with SEQ_START_NOTE(), channel main volume (if compiled in) + * and the volume set by the mixer-device (default 60%). + */ + +unsigned short +gus_linear_vol (int vol, int mainvol) +{ + int mixer_mainvol; + + if (vol <= 0) + vol = 0; + else if (vol >= 127) + vol = 127; + +#ifdef GUS_VOLUME + mixer_mainvol = GUS_VOLUME; +#else + mixer_mainvol = 100; +#endif + +#ifdef GUS_USE_CHN_MAIN_VOLUME + if (mainvol <= 0) + mainvol = 0; + else if (mainvol >= 127) + mainvol = 127; +#else + mainvol = 128; +#endif + + return gus_linearvol[(((vol * mainvol) / 128) * mixer_mainvol) / 100]; +} + #endif diff --git a/sys/i386/isa/sound/gus_wave.c b/sys/i386/isa/sound/gus_wave.c index db5ad81..948dd407 100644 --- a/sys/i386/isa/sound/gus_wave.c +++ b/sys/i386/isa/sound/gus_wave.c @@ -1,11 +1,10 @@ - -/* +/* * sound/gus_wave.c - * + * * Driver for the Gravis UltraSound wave table synth. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,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 @@ -25,13 +24,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" -#ifdef linux -#include <linux/ultrasound.h> -#elif __FreeBSD__ +#ifdef __FreeBSD__ #include <machine/ultrasound.h> #else #include "ultrasound.h" @@ -67,7 +64,7 @@ struct voice_info unsigned char env_rate[6]; unsigned char env_offset[6]; - /* + /* * Volume computation parameters for gus_adagio_vol() */ int main_vol, expression_vol, patch_vol; @@ -94,22 +91,21 @@ static int gus_line_vol = 100, gus_mic_vol = 0; static int gus_recmask = SOUND_MASK_MIC; static int recording_active = 0; -#define VOL_METHOD_ADAGIO 1 int gus_wave_volume = 60; int gus_pcm_volume = 80; static unsigned char mix_image = 0x00; -/* +/* * Current version of this driver doesn't allow synth and PCM functions * at the same time. The active_device specifies the active driver */ static int active_device = 0; -#define GUS_DEV_WAVE 1 /* +#define GUS_DEV_WAVE 1 /* * * * Wave table synth */ -#define GUS_DEV_PCM_DONE 2 /* +#define GUS_DEV_PCM_DONE 2 /* * * * PCM device, transfer done */ -#define GUS_DEV_PCM_CONTINUE 3 /* +#define GUS_DEV_PCM_CONTINUE 3 /* * * * PCM device, transfer the * second * * * chn */ @@ -119,31 +115,31 @@ static int gus_sampling_bits; DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag); -/* +/* * Variables and buffers for PCM output */ -#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* +#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* * * * Don't - * * * change - * + * * * change + * */ -static int pcm_bsize, /* - * Current blocksize +static int pcm_bsize, /* + * Current blocksize */ - pcm_nblk, /* - * Current # of blocks + pcm_nblk, /* + * Current # of blocks */ - pcm_banksize; /* + pcm_banksize; /* * * * * # bytes allocated for channels */ -static int pcm_datasize[MAX_PCM_BUFFERS]; /* +static int pcm_datasize[MAX_PCM_BUFFERS]; /* * * * * Actual # of bytes * in blk * */ -static volatile int pcm_head, pcm_tail, pcm_qlen; /* +static volatile int pcm_head, pcm_tail, pcm_qlen; /* * * * * DRAM queue @@ -160,62 +156,62 @@ struct voice_info voices[32]; static int freq_div_table[] = { - 44100, /* - * 14 + 44100, /* + * 14 */ - 41160, /* - * 15 + 41160, /* + * 15 */ - 38587, /* - * 16 + 38587, /* + * 16 */ - 36317, /* - * 17 + 36317, /* + * 17 */ - 34300, /* - * 18 + 34300, /* + * 18 */ - 32494, /* - * 19 + 32494, /* + * 19 */ - 30870, /* - * 20 + 30870, /* + * 20 */ - 29400, /* - * 21 + 29400, /* + * 21 */ - 28063, /* - * 22 + 28063, /* + * 22 */ - 26843, /* - * 23 + 26843, /* + * 23 */ - 25725, /* - * 24 + 25725, /* + * 24 */ - 24696, /* - * 25 + 24696, /* + * 25 */ - 23746, /* - * 26 + 23746, /* + * 26 */ - 22866, /* - * 27 + 22866, /* + * 27 */ - 22050, /* - * 28 + 22050, /* + * 28 */ - 21289, /* - * 29 + 21289, /* + * 29 */ - 20580, /* - * 30 + 20580, /* + * 30 */ - 19916, /* - * 31 + 19916, /* + * 31 */ - 19293 /* - * 32 + 19293 /* + * 32 */ }; @@ -234,13 +230,14 @@ static struct synth_info gus_info = static void gus_poke (long addr, unsigned char data); static void compute_and_set_volume (int voice, int volume, int ramp_time); extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev); +extern unsigned short gus_linear_vol (int vol, int mainvol); 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 /* +#define INSTANT_RAMP -1 /* * * * Dont use ramping */ -#define FAST_RAMP 0 /* +#define FAST_RAMP 0 /* * * * Fastest possible ramp */ static void @@ -255,8 +252,8 @@ 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 silence here */ gus_poke (1, 0); @@ -392,7 +389,7 @@ gus_write_addr (int reg, unsigned long address, int is16bit) if (is16bit) { - /* + /* * Special processing required for 16 bit patches */ @@ -404,6 +401,10 @@ gus_write_addr (int reg, unsigned long address, int is16bit) gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); + /* Could writing twice fix problems with GUS_VOICE_POS() ? Lets try... */ + gus_delay (); + gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); + gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)); } static void @@ -447,13 +448,13 @@ 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 + gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /* + * Don't + * start + * or * stop * * - * voice + * voice */ gus_delay (); gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); @@ -474,8 +475,8 @@ 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)); } @@ -514,13 +515,13 @@ 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 + gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); /* + * Don't + * start + * or * stop * * - * ramping + * ramping */ gus_delay (); gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); @@ -554,14 +555,14 @@ 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_write_addr (0x0a, 0, 0); /* + * Set current position to 0 */ - gus_write8 (0x00, 0x03); /* - * Voice off + gus_write8 (0x00, 0x03); /* + * Voice off */ - gus_write8 (0x0d, 0x03); /* - * Ramping off + gus_write8 (0x0d, 0x03); /* + * Ramping off */ RESTORE_INTR (flags); @@ -594,18 +595,22 @@ step_envelope (int voice) { unsigned vol, prev_vol, phase; unsigned char rate; + long int flags; if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2) { + DISABLE_INTR (flags); + gus_select_voice (voice); gus_rampoff (); - return; /* - * Sustain + RESTORE_INTR (flags); + return; /* + * Sustain */ } if (voices[voice].env_phase >= 5) { - /* + /* * Shoot the voice off */ @@ -614,25 +619,30 @@ step_envelope (int voice) } prev_vol = voices[voice].current_volume; - gus_voice_volume (prev_vol); phase = ++voices[voice].env_phase; - compute_volume (voice, voices[voice].midi_volume); - vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255; rate = voices[voice].env_rate[phase]; - gus_write8 (0x06, rate); /* - * Ramping rate + + DISABLE_INTR (flags); + gus_select_voice (voice); + + gus_voice_volume (prev_vol); + + + 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 */ { - step_envelope (voice); /* - * Continue with the next phase + RESTORE_INTR (flags); + step_envelope (voice); /* + * Continue with the next phase */ return; } @@ -642,8 +652,8 @@ 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, irq */ } else @@ -651,11 +661,12 @@ step_envelope (int voice) if (vol <= 64) vol = 65; gus_ramp_range (vol, 4030); - gus_rampon (0x60); /* - * Decreasing, irq + gus_rampon (0x60); /* + * Decreasing, irq */ } voices[voice].current_volume = vol; + RESTORE_INTR (flags); } static void @@ -668,25 +679,26 @@ init_envelope (int voice) } static void -start_release (int voice) +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 (); + RESTORE_INTR (flags); step_envelope (voice); } @@ -694,32 +706,37 @@ static void gus_voice_fade (int voice) { int instr_no = sample_map[voice], is16bits; + long int flags; + + DISABLE_INTR (flags); + gus_select_voice (voice); if (instr_no < 0 || instr_no > MAX_SAMPLE) { - gus_write8 (0x00, 0x03); /* - * Hard stop + gus_write8 (0x00, 0x03); /* + * Hard stop */ + RESTORE_INTR (flags); return; } - is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* + is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* * 8 or 16 * bit - * samples + * samples */ if (voices[voice].mode & WAVE_ENVELOPES) { - start_release (voice); + start_release (voice, flags); return; } - /* + /* * Ramp the volume down but not too quickly. */ - if ((gus_read16 (0x09) >> 4) < 100) /* - * Get current volume + if ((gus_read16 (0x09) >> 4) < 100) /* + * Get current volume */ { gus_voice_off (); @@ -730,10 +747,11 @@ 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, irq */ voices[voice].volume_irq_mode = VMODE_HALT; + RESTORE_INTR (flags); } static void @@ -748,24 +766,24 @@ 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 (0x41); /* + * Clear any pending DMA IRQs */ - gus_look8 (0x49); /* - * Clear any pending sample IRQs + gus_look8 (0x49); /* + * Clear any pending sample IRQs */ - gus_read8 (0x0f); /* - * Clear pending IRQs + gus_read8 (0x0f); /* + * Clear pending IRQs */ } @@ -774,7 +792,7 @@ static void gus_initialize (void) { unsigned long flags; - unsigned char dma_image, irq_image, tmp; + register 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}; @@ -784,74 +802,74 @@ gus_initialize (void) 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 (); - /* + /* * Clear all interrupts */ - gus_write8 (0x41, 0); /* - * DMA control + gus_write8 (0x41, 0); /* + * DMA control */ - gus_write8 (0x45, 0); /* - * Timer control + gus_write8 (0x45, 0); /* + * Timer control */ - gus_write8 (0x49, 0); /* - * Sample 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 (0x41); /* + * Clear any pending DMA IRQs */ - gus_look8 (0x49); /* - * Clear any pending sample IRQs + gus_look8 (0x49); /* + * Clear any pending sample IRQs */ - gus_read8 (0x0f); /* - * Clear pending 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 (0x41); /* + * Clear any pending DMA IRQs */ - gus_look8 (0x49); /* - * Clear any pending sample IRQs + gus_look8 (0x49); /* + * Clear any pending sample IRQs */ - gus_read8 (0x0f); /* - * Clear pending 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 */ OUTB (0x05, gus_base + 0x0f); - mix_image |= 0x02; /* - * Disable line out + mix_image |= 0x02; /* + * Disable line out */ OUTB (mix_image, u_Mixer); @@ -859,11 +877,11 @@ gus_initialize (void) OUTB (0x00, gus_base + 0x0f); - /* + /* * Now set up the DMA and IRQ interface - * + * * The GUS supports two IRQs and two DMAs. - * + * * Just one DMA channel is used. This prevents simultaneous ADC and DAC. * Adding this support requires significant changes to the dmabuf.c, dsp.c * and audio.c also. @@ -874,79 +892,79 @@ 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"); dma_image |= tmp; - /* + /* * For some reason the IRQ and DMA addresses must be written twice */ - /* - * Doing it first time + /* + * Doing it first time */ - OUTB (mix_image, u_Mixer); /* - * Select DMA control + OUTB (mix_image, u_Mixer); /* + * Select DMA control */ - OUTB (dma_image | 0x80, u_IRQDMAControl); /* - * Set DMA address + OUTB (dma_image | 0x80, u_IRQDMAControl); /* + * Set DMA address */ - OUTB (mix_image | 0x40, u_Mixer); /* - * Select IRQ control + OUTB (mix_image | 0x40, u_Mixer); /* + * Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* - * Set IRQ address + OUTB (irq_image, u_IRQDMAControl); /* + * Set IRQ address */ - /* - * Doing it second time + /* + * Doing it second time */ - OUTB (mix_image, u_Mixer); /* - * Select DMA control + OUTB (mix_image, u_Mixer); /* + * Select DMA control */ - OUTB (dma_image, u_IRQDMAControl); /* - * Set DMA address + OUTB (dma_image, u_IRQDMAControl); /* + * Set DMA address */ - OUTB (mix_image | 0x40, u_Mixer); /* - * Select IRQ control + OUTB (mix_image | 0x40, u_Mixer); /* + * Select IRQ control */ - OUTB (irq_image, u_IRQDMAControl); /* - * Set IRQ address + 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 &= ~0x02; /* + * Enable line out */ - mix_image |= 0x08; /* - * Enable IRQ + mix_image |= 0x08; /* + * Enable IRQ */ - OUTB (mix_image, u_Mixer); /* - * Turn mixer channels on + 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); } @@ -1054,13 +1072,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); @@ -1083,13 +1101,15 @@ guswave_kill_note (int dev, int voice, int velocity) DISABLE_INTR (flags); if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - voices[voice].kill_pending = 1; + { + voices[voice].kill_pending = 1; + RESTORE_INTR (flags); + } else { - gus_select_voice (voice); + RESTORE_INTR (flags); gus_voice_fade (voice); } - RESTORE_INTR (flags); return 0; } @@ -1100,16 +1120,16 @@ guswave_aftertouch (int dev, int voice, int pressure) short lo_limit, hi_limit; unsigned long flags; - return; /* - * Currently disabled + return; /* + * 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) @@ -1117,8 +1137,8 @@ guswave_aftertouch (int dev, int voice, int pressure) 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; @@ -1138,8 +1158,8 @@ 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, Down, Loop */ RESTORE_INTR (flags); } @@ -1152,6 +1172,13 @@ guswave_panning (int dev, int voice, int value) } static void +guswave_volume_method (int dev, int mode) +{ + if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO) + volume_method = mode; +} + +static void compute_volume (int voice, int volume) { if (volume < 128) @@ -1166,6 +1193,11 @@ compute_volume (int voice, int volume) voices[voice].patch_vol); break; + case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */ + voices[voice].initial_volume = + gus_linear_vol (volume, voices[voice].main_vol); + break; + default: voices[voice].initial_volume = volume_base + (voices[voice].midi_volume * volume_scale); @@ -1181,16 +1213,16 @@ compute_and_set_volume (int voice, int volume, int ramp_time) int current, target, rate; unsigned long flags; + compute_volume (voice, volume); + voices[voice].current_volume = voices[voice].initial_volume; + DISABLE_INTR (flags); -/* + /* * CAUTION! Interrupts disabled. Enable them before returning */ gus_select_voice (voice); - compute_volume (voice, volume); - voices[voice].current_volume = voices[voice].initial_volume; - current = gus_read16 (0x09) >> 4; target = voices[voice].initial_volume; @@ -1208,8 +1240,8 @@ 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) /* + * Too close */ { gus_rampoff (); @@ -1223,8 +1255,8 @@ 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 @@ -1233,8 +1265,8 @@ 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); @@ -1248,14 +1280,14 @@ dynamic_volume_change (int voice) DISABLE_INTR (flags); gus_select_voice (voice); - status = gus_read8 (0x00); /* - * Voice status + status = gus_read8 (0x00); /* + * Voice status */ RESTORE_INTR (flags); if (status & 0x03) - return; /* - * Voice not started + return; /* + * Voice not started */ if (!(voices[voice].mode & WAVE_ENVELOPES)) @@ -1264,19 +1296,19 @@ dynamic_volume_change (int voice) return; } - /* + /* * Voice is running and has envelopes. */ 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); @@ -1288,11 +1320,11 @@ dynamic_volume_change (int voice) compute_volume (voice, voices[voice].midi_volume); -#if 0 /* +#if 0 /* * * * Is this really required */ voices[voice].current_volume = - gus_read16 (0x09) >> 4; /* - * Get current volume + gus_read16 (0x09) >> 4; /* + * Get current volume */ voices[voice].env_phase--; @@ -1334,10 +1366,12 @@ guswave_controller (int dev, int voice, int ctrl_num, int value) value /= 128; #endif case CTRL_EXPRESSION: - volume_method = VOL_METHOD_ADAGIO; - voices[voice].expression_vol = value; - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - dynamic_volume_change (voice); + if (volume_method == VOL_METHOD_ADAGIO) + { + voices[voice].expression_vol = value; + if (voices[voice].volume_irq_mode != VMODE_START_NOTE) + dynamic_volume_change (voice); + } break; #ifdef FUTURE_VERSION @@ -1350,14 +1384,13 @@ guswave_controller (int dev, int voice, int ctrl_num, int value) #endif case CTRL_MAIN_VOLUME: - volume_method = VOL_METHOD_ADAGIO; voices[voice].main_vol = value; if (voices[voice].volume_irq_mode != VMODE_START_NOTE) dynamic_volume_change (voice); break; - default: /* - * Ignore + default: /* + * Ignore */ break; } @@ -1402,7 +1435,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) note_freq = note_to_freq (note_num); - /* + /* * Find a sample within a patch so that the note_freq is between low_note * and high_note. */ @@ -1423,8 +1456,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) if (samples[samplep].low_note <= note_freq && note_freq <= samples[samplep].high_note) sample = samplep; else - samplep = samples[samplep].key; /* - * Follow link + samplep = samples[samplep].key; /* + * Follow link */ } if (sample == -1) @@ -1433,15 +1466,15 @@ 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; /* + is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; /* * 8 or 16 * bit - * samples + * samples */ voices[voice].mode = samples[sample].mode; voices[voice].patch_vol = samples[sample].volume; @@ -1459,8 +1492,8 @@ 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; /* + * To avoid overflows */ note_freq /= 100; @@ -1468,7 +1501,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) voices[voice].orig_freq = freq; - /* + /* * Since the pitch bender may have been set before playing the note, we * have to calculate the bending now. */ @@ -1485,8 +1518,8 @@ 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)) @@ -1499,10 +1532,13 @@ 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 (); /* + * It may still be running */ gus_rampoff (); + + RESTORE_INTR (flags); + if (voices[voice].mode & WAVE_ENVELOPES) { compute_volume (voice, volume); @@ -1511,6 +1547,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) else compute_and_set_volume (voice, volume, 0); + DISABLE_INTR (flags); + gus_select_voice (voice); + if (samples[sample].mode & WAVE_LOOP_BACK) gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len - voices[voice].offset_pending, is16bits); /* Sample @@ -1521,13 +1560,13 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) if (samples[sample].mode & WAVE_LOOPING) { - mode |= 0x08; /* - * Looping on + mode |= 0x08; /* + * Looping on */ if (samples[sample].mode & WAVE_BIDIR_LOOP) - mode |= 0x10; /* - * Bidirectional looping on + mode |= 0x10; /* + * Bidirectional looping on */ if (samples[sample].mode & WAVE_LOOP_BACK) @@ -1538,35 +1577,35 @@ 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 (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 (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /* + * Loop + * end + * location */ } else { - mode |= 0x20; /* - * Loop irq at the end + mode |= 0x20; /* + * Loop irq at the end */ - voices[voice].loop_irq_mode = LMODE_FINISH; /* + voices[voice].loop_irq_mode = LMODE_FINISH; /* * Ramp it down at - * the * end + * the * end */ voices[voice].loop_irq_parm = 1; - gus_write_addr (0x02, sample_ptrs[sample], is16bits); /* - * Loop start - * 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_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1, is16bits); /* + * Loop + * end + * location */ } gus_voice_freq (freq); @@ -1577,9 +1616,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) return 0; } -/* +/* * * New guswave_start_note by Andrew J. Robinson attempts to minimize - * clicking * when the note playing on the voice is changed. It uses volume + * clicking * when the note playing on the voice is changed. It uses volume * ramping. */ static int @@ -1595,14 +1634,17 @@ guswave_start_note (int dev, int voice, int note_num, int volume) if (voices[voice].volume_irq_mode == VMODE_START_NOTE) voices[voice].volume_pending = volume; else - ret_val = guswave_start_note2 (dev, voice, note_num, volume); + { + RESTORE_INTR (flags); + ret_val = guswave_start_note2 (dev, voice, note_num, volume); + } } else { gus_select_voice (voice); mode = gus_read8 (0x00); if (mode & 0x20) - gus_write8 (0x00, mode & 0xdf); /* No interrupt! */ + gus_write8 (0x00, mode & 0xdf); /* No interrupt! */ voices[voice].offset_pending = 0; voices[voice].kill_pending = 0; @@ -1611,9 +1653,11 @@ guswave_start_note (int dev, int voice, int note_num, int volume) if (voices[voice].sample_pending >= 0) { + RESTORE_INTR (flags); guswave_set_instr (voices[voice].dev_pending, voice, voices[voice].sample_pending); voices[voice].sample_pending = -1; + DISABLE_INTR (flags); } if ((mode & 0x01) || ((gus_read16 (0x09) >> 4) < 2065)) @@ -1629,11 +1673,11 @@ guswave_start_note (int dev, int voice, int note_num, int volume) gus_rampoff (); gus_ramp_range (2000, 4065); - gus_ramp_rate (0, 63); /* Fastest possible rate */ + gus_ramp_rate (0, 63);/* Fastest possible rate */ gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */ + RESTORE_INTR (flags); } } - RESTORE_INTR (flags); return ret_val; } @@ -1691,10 +1735,10 @@ 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; /* + sizeof_patch = (long) &patch.data[0] - (long) &patch; /* * Size of * the header - * * info + * * info */ if (format != GUS_PATCH) @@ -1717,7 +1761,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, return RET_ERROR (ENOSPC); } - /* + /* * Copy the header from user space but ignore the first bytes which have * been transferred already. */ @@ -1760,15 +1804,15 @@ 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; /* + * Alignment 32 bytes */ #define GUS_BANK_SIZE (256*1024) if (patch.mode & WAVE_16_BITS) { - /* + /* * 16 bit samples must fit one 256k bank. */ if (patch.len >= GUS_BANK_SIZE) @@ -1780,16 +1824,16 @@ 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 = /* + * Align to 256K*N */ ((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 */ } } @@ -1799,8 +1843,8 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, sample_ptrs[free_sample] = free_mem_ptr; - /* - * Tremolo is not possible with envelopes + /* + * Tremolo is not possible with envelopes */ if (patch.mode & WAVE_ENVELOPES) @@ -1808,14 +1852,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, memcpy ((char *) &samples[free_sample], &patch, sizeof_patch); - /* + /* * Link this_one sample to the list of samples for patch 'instr'. */ samples[free_sample].key = patch_table[instr]; patch_table[instr] = free_sample; - /* + /* * Use DMA to transfer the wave data to the DRAM */ @@ -1823,22 +1867,22 @@ 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 all moved */ { blk_size = sound_buffsizes[gus_devnum]; if (blk_size > left) blk_size = left; - /* + /* * DMA cannot cross 256k bank boundaries. Check for that. */ blk_end = target + blk_size; if ((target >> 18) != (blk_end >> 18)) - { /* - * Have to split the block + { /* + * Have to split the block */ blk_end &= ~(256 * 1024 - 1); @@ -1846,7 +1890,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, } #if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA) - /* + /* * For some reason the DMA is not possible. We have to use PIO. */ { @@ -1859,20 +1903,20 @@ 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 /* +#else /* * * * GUS_NO_DMA */ { unsigned long address, hold_address; unsigned char dma_command; unsigned long flags; - /* + /* * OK, move now. First in and then out. */ @@ -1881,13 +1925,13 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, blk_size); DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/ - gus_write8 (0x41, 0); /* - * Disable GF1 DMA + gus_write8 (0x41, 0); /* + * Disable GF1 DMA */ DMAbuf_start_dma (gus_devnum, snd_raw_buf_phys[gus_devnum][0], blk_size, DMA_MODE_WRITE); - /* + /* * Set the DRAM address for the wave data */ @@ -1901,35 +1945,35 @@ 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_ + dma_command |= 0x40; /* + * 16 bit _DATA_ */ if (sound_dsp_dmachan[gus_devnum] > 3) - dma_command |= 0x04; /* - * 16 bit DMA channel + dma_command |= 0x04; /* + * 16 bit DMA channel */ - gus_write8 (0x41, dma_command); /* - * Let's go luteet (=bugs) + gus_write8 (0x41, dma_command); /* + * Let's go luteet (=bugs) */ - /* + /* * Sleep here until the DRAM DMA done interrupt is served */ active_device = GUS_DEV_WAVE; @@ -1939,10 +1983,10 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr, printk ("GUS: DMA Transfer timed out\n"); RESTORE_INTR (flags); } -#endif /* +#endif /* * * * GUS_NO_DMA */ - /* + /* * Now the next part */ @@ -1950,8 +1994,8 @@ 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 */ } @@ -1997,8 +2041,8 @@ guswave_hw_control (int dev, unsigned char *event) case _GUS_VOICEON: DISABLE_INTR (flags); gus_select_voice (voice); - p1 &= ~0x20; /* - * Disable intr + p1 &= ~0x20; /* + * Disable intr */ gus_voice_on (p1); RESTORE_INTR (flags); @@ -2012,17 +2056,14 @@ guswave_hw_control (int dev, unsigned char *event) break; case _GUS_VOICEFADE: - DISABLE_INTR (flags); - gus_select_voice (voice); gus_voice_fade (voice); - RESTORE_INTR (flags); break; case _GUS_VOICEMODE: DISABLE_INTR (flags); gus_select_voice (voice); - p1 &= ~0x20; /* - * Disable intr + p1 &= ~0x20; /* + * Disable intr */ gus_voice_mode (p1); RESTORE_INTR (flags); @@ -2049,8 +2090,8 @@ 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 voice value */ voices[voice].initial_volume = voices[voice].current_volume = p1; @@ -2058,8 +2099,8 @@ guswave_hw_control (int dev, unsigned char *event) case _GUS_RAMPRANGE: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); @@ -2069,8 +2110,8 @@ guswave_hw_control (int dev, unsigned char *event) case _GUS_RAMPRATE: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); @@ -2080,13 +2121,13 @@ 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; /* + * Disable intr */ gus_ramp_mode (p1); RESTORE_INTR (flags); @@ -2094,13 +2135,13 @@ guswave_hw_control (int dev, unsigned char *event) case _GUS_RAMPON: 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; /* + * Disable intr */ gus_rampon (p1); RESTORE_INTR (flags); @@ -2108,8 +2149,8 @@ guswave_hw_control (int dev, unsigned char *event) case _GUS_RAMPOFF: if (voices[voice].mode & WAVE_ENVELOPES) - break; /* - * NO-NO + break; /* + * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); @@ -2218,8 +2259,8 @@ 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 YET IMPLEMENTED */ return IOCTL_OUT (arg, RET_ERROR (EINVAL)); break; @@ -2319,14 +2360,14 @@ 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; } @@ -2334,8 +2375,8 @@ play_next_pcm_block (void) if (gus_sampling_bits != 8) { is16bits = 1; - mode[chn] |= 0x04; /* - * 16 bit data + mode[chn] |= 0x04; /* + * 16 bit data */ } else @@ -2344,22 +2385,22 @@ 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 of the DRAM buffers */ { - mode[chn] |= 0x08; /* - * Enable loop + mode[chn] |= 0x08; /* + * Enable loop */ - ramp_mode[chn] = 0x03; /* - * Disable rollover + ramp_mode[chn] = 0x03;/* + * Disable rollover */ } else { if (chn == 0) - ramp_mode[chn] = 0x04; /* - * Enable rollover bit + ramp_mode[chn] = 0x04; /* + * Enable rollover bit */ } @@ -2368,89 +2409,89 @@ 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) /* + * Voice not started yet */ { - /* + /* * The playback was not started yet (or there has been a pause). * Start the voice (again) and ask for a rollover irq at the end of * this_one block. If this_one one is last of the buffers, use just * the normal loop with irq. */ - gus_voice_off (); /* - * It could already be running + gus_voice_off (); /* + * It could already be running */ 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 (0x0a, dram_loc, is16bits); /* + * Starting position */ - gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* - * Loop start - * location + gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* + * Loop start + * location */ 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 loop */ if (pcm_datasize[this_one] != pcm_bsize) { - /* - * Incomplete block. Possibly the last one. + /* + * Incomplete block. Possibly the last one. */ if (chn == 0) { - mode[chn] &= ~0x08; /* - * Disable loop + mode[chn] &= ~0x08; /* + * Disable loop */ - mode[chn] |= 0x20; /* - * Enable loop IRQ + mode[chn] |= 0x20;/* + * Enable loop IRQ */ 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 + gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* + * Loop + * end + * location */ - mode[chn] &= ~0x08; /* - * Disable loop + mode[chn] &= ~0x08; /* + * Disable loop */ } } @@ -2474,11 +2515,11 @@ static void gus_transfer_output_block (int dev, unsigned long buf, int total_count, int intrflag, int chn) { - /* + /* * This routine transfers one block of audio data to the DRAM. In mono mode * it's called just once. When in stereo mode, this_one routine is called * once for both channels. - * + * * The left/mono channel data is transferred to the beginning of dram and the * right data to the area pointed by gus_page_size. */ @@ -2505,8 +2546,8 @@ 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); @@ -2521,38 +2562,38 @@ 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 + dma_command |= 0x04; /* + * 16 bit DMA channel */ - gus_write8 (0x41, dma_command); /* - * Kick on + gus_write8 (0x41, dma_command); /* + * Kick on */ - if (chn == (gus_sampling_channels - 1)) /* - * Last channel + if (chn == (gus_sampling_channels - 1)) /* + * Last channel */ { - /* - * Last (right or mono) channel data + /* + * Last (right or mono) channel data */ active_device = GUS_DEV_PCM_DONE; if (!pcm_active && (pcm_qlen > 2 || count < pcm_bsize)) @@ -2560,7 +2601,7 @@ gus_transfer_output_block (int dev, unsigned long buf, play_next_pcm_block (); } } - else /* + else /* * * * Left channel data. The right channel * is * * * transferred after DMA interrupt */ active_device = GUS_DEV_PCM_CONTINUE; @@ -2590,20 +2631,20 @@ 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 enable, invert MSB */ if (sound_dsp_dmachan[dev] > 3) - mode |= 0x04; /* - * 16 bit DMA channel + mode |= 0x04; /* + * 16 bit DMA channel */ if (gus_sampling_channels > 1) - mode |= 0x02; /* - * Stereo + mode |= 0x02; /* + * Stereo */ - mode |= 0x01; /* - * DMA enable + mode |= 0x01; /* + * DMA enable */ gus_write8 (0x49, mode); @@ -2618,8 +2659,8 @@ 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 frequency */ if (gus_sampling_bits != 8) @@ -2722,6 +2763,7 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs, static struct audio_operations gus_sampling_operations = { "Gravis UltraSound", + NEEDS_RESTART, gus_sampling_open, gus_sampling_close, gus_sampling_output_block, @@ -2751,6 +2793,7 @@ guswave_bender (int dev, int voice, int value) gus_voice_freq (freq); RESTORE_INTR (flags); } + #endif static int @@ -2782,8 +2825,8 @@ 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 */ } } @@ -2799,8 +2842,8 @@ 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 */ } } @@ -2821,11 +2864,11 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) pat = (struct patch_info *) rec->data.data8; - pat->key = GUS_PATCH; /* - * Restore patch type + pat->key = GUS_PATCH; /* + * Restore patch type */ - rec->parm1 = sample_ptrs[ptr]; /* - * DRAM address + rec->parm1 = sample_ptrs[ptr]; /* + * DRAM address */ rec->parm2 = sizeof (struct patch_info); } @@ -2842,13 +2885,13 @@ 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, @@ -2859,8 +2902,8 @@ 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; @@ -2872,12 +2915,12 @@ 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; /* + * Nr of bytes left */ if (l > n) @@ -2887,25 +2930,25 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) l = sizeof (rec->data.data8); if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? + return RET_ERROR (EINVAL); /* + * Was there a bug? */ - offs += sample_ptrs[sample]; /* - * Begin offsess + offset to DRAM + offs += sample_ptrs[sample]; /* + * Begin offsess + offset to DRAM */ for (n = 0; n < l; n++) rec->data.data8[n] = gus_peek (offs++); - rec->parm1 = n; /* - * Nr of bytes copied + rec->parm1 = n; /* + * Nr of bytes copied */ } return 0; break; - case PM_WRITE_PATCH: /* - * Writes a block of wave data to the DRAM + case PM_WRITE_PATCH: /* + * Writes a block of wave data to the DRAM */ { int sample = rec->parm1; @@ -2917,12 +2960,12 @@ 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; /* + * Nr of bytes left */ if (l > n) @@ -2932,18 +2975,18 @@ guswave_patchmgr (int dev, struct patmgr_info *rec) l = sizeof (rec->data.data8); if (l <= 0) - return RET_ERROR (EINVAL); /* - * Was there a bug? + return RET_ERROR (EINVAL); /* + * Was there a bug? */ - offs += sample_ptrs[sample]; /* - * Begin offsess + offset to DRAM + offs += sample_ptrs[sample]; /* + * Begin offsess + offset to DRAM */ for (n = 0; n < l; n++) gus_poke (offs++, rec->data.data8[n]); - rec->parm1 = n; /* - * Nr of bytes copied + rec->parm1 = n; /* + * Nr of bytes copied */ } return 0; @@ -2974,6 +3017,7 @@ static struct synth_operations guswave_operations = guswave_aftertouch, guswave_controller, guswave_panning, + guswave_volume_method, guswave_patchmgr, #ifdef FUTURE_VERSION guswave_bender @@ -2988,7 +3032,7 @@ set_input_volumes (void) DISABLE_INTR (flags); -/* + /* * Enable channels having vol > 10% * Note! bit 0x01 means line in DISABLED while 0x04 means * mic in ENABLED. @@ -3000,7 +3044,7 @@ set_input_volumes (void) if (recording_active) { -/* + /* * Disable channel, if not selected for recording */ if (!(gus_recmask & SOUND_MASK_LINE)) @@ -3016,8 +3060,8 @@ set_input_volumes (void) RESTORE_INTR (flags); } -static int -gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) +int +gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) { #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ SOUND_MASK_SYNTH|SOUND_MASK_PCM) @@ -3085,9 +3129,9 @@ gus_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); /* + dynamic_volume_change (voice); /* * Apply the new - * volume + * volume */ return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8)); @@ -3098,8 +3142,8 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) return RET_ERROR (EINVAL); } else - switch (cmd & 0xff) /* - * Return parameters + switch (cmd & 0xff) /* + * Return parameters */ { @@ -3149,13 +3193,97 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg) static struct mixer_operations gus_mixer_operations = { - gus_mixer_ioctl + gus_default_mixer_ioctl }; +static long +gus_default_mixer_init (long mem_start) +{ + if (num_mixers < MAX_MIXER_DEV) /* + * Don't install if there is another + * mixer + */ + mixer_devs[num_mixers++] = &gus_mixer_operations; + + return mem_start; +} + long gus_wave_init (long mem_start, int irq, int dma) { - printk ("snd4: <Gravis UltraSound %dk>", (int) gus_mem_size / 1024); + unsigned long flags; + unsigned char val; + char *model_num = "2.4"; + int gus_type = 0x24; /* 2.4 */ + int mixer_type = 0; + + /* + * Try to identify the GUS model. + * + * Versions < 3.6 don't have the digital ASIC. Try to probe it first. + */ + + DISABLE_INTR (flags); + OUTB (0x20, gus_base + 0x0f); + val = INB (gus_base + 0x0f); + RESTORE_INTR (flags); + + if (val != 0xff && (val & 0x06)) /* Should be 0x02? */ + { + /* + * It has the digital ASIC so the card is at least v3.4. + * Next try to detect the true model. + */ + + val = INB (u_MixSelect); + + /* + * Value 255 means pre-3.7 which don't have mixer. + * Values 5 thru 9 mean v3.7 which has a ICS2101 mixer. + * 10 and above is GUS MAX which has the CS4231 codec/mixer. + * + * Sorry. No GUS max support yet but it should be available + * soon after the SDK for GUS MAX is available. + */ + + if (val == 255 || val < 5) + { + model_num = "3.4"; + gus_type = 0x34; + } + else if (val < 10) + { + model_num = "3.7"; + gus_type = 0x37; + mixer_type = ICS2101; + } + else + { + model_num = "MAX"; + gus_type = 0x40; + mixer_type = CS4231; + } + } + else + { + /* + * ASIC not detected so the card must be 2.2 or 2.4. + * There could still be the 16-bit/mixer daughter card. + * It has the same codec/mixer than MAX. + * At this time there is no support for it but it will appear soon. + */ + } + + +#ifdef __FreeBSD__ + printk ("snd4: <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024); +#else + printk (" <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024); +#endif + +#ifndef SCO + sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); +#endif if (irq < 0 || irq > 15) { @@ -3188,18 +3316,28 @@ gus_wave_init (long mem_start, int irq, int dma) { dsp_devs[gus_devnum = num_dspdevs++] = &gus_sampling_operations; sound_dsp_dmachan[gus_devnum] = dma; - sound_buffcounts[gus_devnum] = DSP_BUFFCOUNT; + sound_buffcounts[gus_devnum] = 1; sound_buffsizes[gus_devnum] = DSP_BUFFSIZE; sound_dma_automode[gus_devnum] = 0; } else printk ("GUS: Too many PCM devices available\n"); - if (num_mixers < MAX_MIXER_DEV) /* - * Don't install if there is another - * mixer - */ - mixer_devs[num_mixers++] = &gus_mixer_operations; + /* + * Mixer dependent initialization. + */ + + switch (mixer_type) + { + case ICS2101: + gus_line_vol=gus_mic_vol=gus_wave_volume = gus_pcm_volume = 100; + return ics2101_mixer_init (mem_start); + + case CS4231: + /* Available soon */ + default: + return gus_default_mixer_init (mem_start); + } return mem_start; } @@ -3215,8 +3353,8 @@ do_loop_irq (int voice) gus_select_voice (voice); tmp = gus_read8 (0x00); - tmp &= ~0x20; /* - * Disable wave IRQ for this_one voice + tmp &= ~0x20; /* + * Disable wave IRQ for this_one voice */ gus_write8 (0x00, tmp); @@ -3227,12 +3365,12 @@ do_loop_irq (int voice) switch (mode) { - case LMODE_FINISH: /* - * Final loop finished, shoot volume down + case LMODE_FINISH: /* + * Final loop finished, shoot volume down */ - if ((gus_read16 (0x09) >> 4) < 100) /* - * Get current volume + if ((gus_read16 (0x09) >> 4) < 100) /* + * Get current volume */ { gus_voice_off (); @@ -3241,18 +3379,18 @@ do_loop_irq (int voice) break; } gus_ramp_range (65, 4065); - gus_ramp_rate (0, 63); /* - * Fastest possible rate + gus_ramp_rate (0, 63); /* + * Fastest possible rate */ - gus_rampon (0x20 | 0x40); /* - * Ramp down, once, irq + gus_rampon (0x20 | 0x40); /* + * Ramp down, once, irq */ voices[voice].volume_irq_mode = VMODE_HALT; break; case LMODE_PCM_STOP: - pcm_active = 0; /* - * Requires extensive processing + pcm_active = 0; /* + * Requires extensive processing */ case LMODE_PCM: { @@ -3265,8 +3403,8 @@ do_loop_irq (int voice) play_next_pcm_block (); } else - { /* - * Out of data. Just stop the voice + { /* + * Out of data. Just stop the voice */ gus_voice_off (); gus_rampoff (); @@ -3297,8 +3435,8 @@ do_volume_irq (int voice) gus_select_voice (voice); tmp = gus_read8 (0x0d); - tmp &= ~0x20; /* - * Disable volume ramp IRQ + tmp &= ~0x20; /* + * Disable volume ramp IRQ */ gus_write8 (0x0d, tmp); @@ -3308,18 +3446,21 @@ do_volume_irq (int voice) switch (mode) { - case VMODE_HALT: /* - * Decay phase finished + case VMODE_HALT: /* + * Decay phase finished */ + RESTORE_INTR (flags); gus_voice_init (voice); break; case VMODE_ENVELOPE: gus_rampoff (); + RESTORE_INTR (flags); step_envelope (voice); break; case VMODE_START_NOTE: + RESTORE_INTR (flags); guswave_start_note2 (voices[voice].dev_pending, voice, voices[voice].note_pending, voices[voice].volume_pending); if (voices[voice].kill_pending) @@ -3334,8 +3475,6 @@ do_volume_irq (int voice) default:; } - - RESTORE_INTR (flags); } void @@ -3348,37 +3487,37 @@ gus_voice_irq (void) while (1) { - src = gus_read8 (0x0f); /* - * Get source info + src = gus_read8 (0x0f); /* + * Get source info */ voice = src & 0x1f; src &= 0xc0; if (src == (0x80 | 0x40)) - return; /* - * No interrupt + return; /* + * No interrupt */ voice_bit = 1 << voice; - if (!(src & 0x80)) /* - * Wave IRQ pending + if (!(src & 0x80)) /* + * Wave IRQ pending */ - if (!(wave_ignore & voice_bit) && voice < nr_voices) /* + if (!(wave_ignore & voice_bit) && voice < nr_voices) /* * Not done - * yet + * yet */ { wave_ignore |= voice_bit; do_loop_irq (voice); } - if (!(src & 0x40)) /* - * Volume IRQ pending + if (!(src & 0x40)) /* + * Volume IRQ pending */ - if (!(volume_ignore & voice_bit) && voice < nr_voices) /* + if (!(volume_ignore & voice_bit) && voice < nr_voices) /* * Not done - * yet + * yet */ { volume_ignore |= voice_bit; @@ -3392,11 +3531,11 @@ guswave_dma_irq (void) { unsigned char status; - status = gus_look8 (0x41); /* - * Get DMA IRQ Status + status = gus_look8 (0x41); /* + * Get DMA IRQ Status */ - if (status & 0x40) /* - * DMA Irq pending + if (status & 0x40) /* + * DMA Irq pending */ switch (active_device) { @@ -3421,11 +3560,11 @@ guswave_dma_irq (void) default:; } - status = gus_look8 (0x49); /* - * Get Sampling IRQ Status + status = gus_look8 (0x49); /* + * Get Sampling IRQ Status */ - if (status & 0x40) /* - * Sampling Irq pending + if (status & 0x40) /* + * Sampling Irq pending */ { DMAbuf_inputintr (gus_devnum); diff --git a/sys/i386/isa/sound/midibuf.c b/sys/i386/isa/sound/midibuf.c index 54b7266..7dadb3f 100644 --- a/sys/i386/isa/sound/midibuf.c +++ b/sys/i386/isa/sound/midibuf.c @@ -1,12 +1,12 @@ /* * sound/midibuf.c - * + * * Device file manager for /dev/midi - * + * * NOTE! This part of the driver is currently just a stub. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,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 @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff --git a/sys/i386/isa/sound/mpu401.c b/sys/i386/isa/sound/mpu401.c index 449b6be..38ba486 100644 --- a/sys/i386/isa/sound/mpu401.c +++ b/sys/i386/isa/sound/mpu401.c @@ -1,12 +1,12 @@ /* * sound/mpu401.c - * + * * 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 * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,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 @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -35,7 +35,7 @@ #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI) -#define DATAPORT (mpu401_base) /* MPU-401 Data I/O Port on IBM */ +#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 */ @@ -61,58 +61,16 @@ static int my_dev; static int reset_mpu401 (void); static void (*midi_input_intr) (int dev, unsigned char data); -static void -mpu401_input_loop (void) -{ - int count; - - count = 10; - - while (count) /* Not timed out */ - if (input_avail ()) - { - unsigned char c = mpu401_read (); - - count = 100; - - if (mpu401_opened & OPEN_READ) - midi_input_intr (my_dev, c); - } - else - while (!input_avail () && count) - count--; -} - void mpuintr (int unit) { - if (input_avail ()) - mpu401_input_loop (); -} - -/* - * It looks like there is no input interrupts in the UART mode. Let's try - * polling. - */ - -static void -poll_mpu401 (unsigned long dummy) -{ - unsigned long flags; - - DEFINE_TIMER (mpu401_timer, poll_mpu401); - - if (!(mpu401_opened & OPEN_READ)) - return; /* No longer required */ - - DISABLE_INTR (flags); - - if (input_avail ()) - mpu401_input_loop (); - - ACTIVATE_TIMER (mpu401_timer, poll_mpu401, 1); /* Come back later */ + while (input_avail ()) + { + unsigned char c = mpu401_read (); - RESTORE_INTR (flags); + if (mpu401_opened & OPEN_READ) + midi_input_intr (my_dev, c); + } } static int @@ -127,11 +85,10 @@ mpu401_open (int dev, int mode, return RET_ERROR (EBUSY); } - mpu401_input_loop (); + mpuintr (0); midi_input_intr = input; mpu401_opened = mode; - poll_mpu401 (0); /* Enable input polling */ return 0; } @@ -155,7 +112,7 @@ mpu401_out (int dev, unsigned char midi_byte) DISABLE_INTR (flags); if (input_avail ()) - mpu401_input_loop (); + mpuintr (0); RESTORE_INTR (flags); @@ -250,7 +207,11 @@ attach_mpu401 (long mem_start, struct address_info *hw_config) RESTORE_INTR (flags); +#ifdef __FreeBSD__ printk ("snd5: <Roland MPU-401>"); +#else + printk (" <Roland MPU-401>"); +#endif my_dev = num_midis; mpu401_dev = num_midis; @@ -291,7 +252,7 @@ reset_mpu401 (void) mpu401_opened = 0; if (ok) - mpu401_input_loop (); /* Flush input before enabling interrupts */ + mpuintr (0); /* Flush input before enabling interrupts */ RESTORE_INTR (flags); diff --git a/sys/i386/isa/sound/opl3.c b/sys/i386/isa/sound/opl3.c index 58327a3..6e3dcca 100644 --- a/sys/i386/isa/sound/opl3.c +++ b/sys/i386/isa/sound/opl3.c @@ -1,10 +1,10 @@ /* * sound/opl3.c - * + * * A low level driver for Yamaha YM3812 and OPL-3 -chips - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ /* Major improvements to the FM handling 30AUG92 by Rob Hooft, */ @@ -81,6 +81,9 @@ static unsigned char connection_mask = 0x00; void enable_opl3_mode (int left, int right, int both) { + if (opl3_enabled) + return; + opl3_enabled = 1; left_address = left; right_address = right; @@ -168,10 +171,10 @@ opl3_detect (int ioaddr) * This function returns 1 if the FM chicp is present at the given I/O port * The detection algorithm plays with the timer built in the FM chip and * looks for a change in the status register. - * + * * Note! The timers of the FM chip are not connected to AdLib (and compatible) * boards. - * + * * Note2! The chip is initialized if detected. */ @@ -197,7 +200,7 @@ opl3_detect (int ioaddr) 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 */ @@ -305,9 +308,9 @@ char fm_volume_table[128] = -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 */ + -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 */ @@ -373,8 +376,8 @@ set_voice_volume (int voice, int volume) 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 */ @@ -414,7 +417,7 @@ 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); @@ -747,6 +750,11 @@ opl3_panning (int dev, int voice, int pressure) { } +static void +opl3_volume_method (int dev, int mode) +{ +} + #define SET_VIBRATO(cell) { \ tmp = instr->operators[(cell-1)+(((cell-1)/2)*OFFS_4OP)]; \ if (pressure > 110) \ @@ -851,9 +859,8 @@ opl3_controller (int dev, int voice, int ctrl_num, int value) 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 */ - + 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); break; @@ -887,6 +894,7 @@ static struct synth_operations opl3_operations = opl3_aftertouch, opl3_controller, opl3_panning, + opl3_volume_method, opl3_patchmgr }; @@ -895,7 +903,7 @@ opl3_init (long mem_start) { int i; - PERMANENT_MALLOC(struct sbi_instrument *, instrmap, + PERMANENT_MALLOC (struct sbi_instrument *, instrmap, SBFM_MAXINSTR * sizeof (*instrmap), mem_start); synth_devs[num_synths++] = &opl3_operations; @@ -903,7 +911,11 @@ opl3_init (long mem_start) opl3_ok = 1; if (opl3_enabled) { +#ifdef __FreeBSD__ printk ("snd1: <Yamaha OPL-3 FM>"); +#else + printk (" <Yamaha OPL-3 FM>"); +#endif fm_model = 2; nr_voices = 18; fm_info.nr_drums = 0; @@ -925,7 +937,11 @@ opl3_init (long mem_start) } else { +#ifdef __FreeBSD__ printk ("snd1: <Yamaha 2-OP FM>"); +#else + printk (" <Yamaha 2-OP FM>"); +#endif fm_model = 1; nr_voices = 9; fm_info.nr_drums = 0; diff --git a/sys/i386/isa/sound/pas.h b/sys/i386/isa/sound/pas.h index 797c8fd..9902e03 100644 --- a/sys/i386/isa/sound/pas.h +++ b/sys/i386/isa/sound/pas.h @@ -138,11 +138,11 @@ 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 */ - { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; + { 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 */ - { 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x05, 0x06, 0x07 }; + { 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 */ - { 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x28, 0x30, 0x38, 0, 0 }; + { 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 */ { 0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0 }; char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */ diff --git a/sys/i386/isa/sound/pas2_card.c b/sys/i386/isa/sound/pas2_card.c index c89dd33..a4791e8 100644 --- a/sys/i386/isa/sound/pas2_card.c +++ b/sys/i386/isa/sound/pas2_card.c @@ -2,11 +2,11 @@ #define SND_SA_INTERRUPT /* * sound/pas2_card.c - * + * * Detection routine for the Pro Audio Spectrum cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,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 @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -79,7 +79,7 @@ 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) { @@ -197,7 +197,7 @@ config_pas_hw (struct address_info *hw_config) } } -/* + /* * This fixes the timing problems of the PAS due to the Symphony chipset * as per Media Vision. Only define this if your PAS doesn't work correctly. */ @@ -317,7 +317,11 @@ attach_pas_card (long mem_start, struct address_info *hw_config) 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], pas_read (BOARD_REV_ID)); +#else + printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID)); +#endif } if (config_pas_hw (hw_config)) diff --git a/sys/i386/isa/sound/pas2_midi.c b/sys/i386/isa/sound/pas2_midi.c index 5620d72..4a07b0b 100644 --- a/sys/i386/isa/sound/pas2_midi.c +++ b/sys/i386/isa/sound/pas2_midi.c @@ -1,10 +1,10 @@ /* * sound/pas2_midi.c - * + * * The low level driver for the PAS Midi Interface. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -79,7 +79,7 @@ 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; } @@ -122,7 +122,7 @@ 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 */ } @@ -287,7 +287,7 @@ 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 0ec6753..fd3e106 100644 --- a/sys/i386/isa/sound/pas2_mixer.c +++ b/sys/i386/isa/sound/pas2_mixer.c @@ -2,11 +2,11 @@ /* * sound/pas2_mixer.c - * + * * Mixer routines for the Pro Audio Spectrum cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -14,7 +14,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 @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -39,7 +39,7 @@ 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 | \ @@ -331,7 +331,7 @@ 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.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; diff --git a/sys/i386/isa/sound/pas2_pcm.c b/sys/i386/isa/sound/pas2_pcm.c index f8b2238..06742d5 100644 --- a/sys/i386/isa/sound/pas2_pcm.c +++ b/sys/i386/isa/sound/pas2_pcm.c @@ -1,11 +1,11 @@ #define _PAS2_PCM_C_ /* * sound/pas2_pcm.c - * + * * The low level driver for the Pro Audio Spectrum ADC/DAC. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +13,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 @@ -25,7 +25,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -100,7 +100,7 @@ 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; @@ -337,14 +337,15 @@ pas_pcm_prepare_for_output (int dev, int bsize, int bcount) static struct audio_operations pas_pcm_operations = { "Pro Audio Spectrum", - pas_pcm_open, /* */ - pas_pcm_close, /* */ - pas_pcm_output_block, /* */ - pas_pcm_start_input, /* */ - pas_pcm_ioctl, /* */ - pas_pcm_prepare_for_input, /* */ - pas_pcm_prepare_for_output, /* */ - pas_pcm_reset, /* */ + NOTHING_SPECIAL, + pas_pcm_open, + pas_pcm_close, + pas_pcm_output_block, + pas_pcm_start_input, + pas_pcm_ioctl, + 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 */ diff --git a/sys/i386/isa/sound/patmgr.c b/sys/i386/isa/sound/patmgr.c index f5697ae..042d42d 100644 --- a/sys/i386/isa/sound/patmgr.c +++ b/sys/i386/isa/sound/patmgr.c @@ -1,10 +1,10 @@ /* * sound/patmgr.c - * + * * The patch maneger interface for the /dev/sequencer - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define PATMGR_C diff --git a/sys/i386/isa/sound/sb16_dsp.c b/sys/i386/isa/sound/sb16_dsp.c index d85359b..a755712 100644 --- a/sys/i386/isa/sound/sb16_dsp.c +++ b/sys/i386/isa/sound/sb16_dsp.c @@ -1,12 +1,12 @@ /* * sound/sb16_dsp.c - * + * * The low level driver for the SoundBlaster DSP chip. - * + * * (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de) * * based on SB-driver by (C) Hannu Savolainen - * + * * 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 @@ -14,7 +14,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 @@ -26,7 +26,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define DEB(x) @@ -40,9 +40,9 @@ #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO) -extern int sbc_base; +extern int sbc_base, sbc_minor, sbc_major; -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; */ @@ -74,6 +74,7 @@ int sb_reset_dsp (void); static struct audio_operations sb16_dsp_operations = { "SoundBlaster 16", + NOTHING_SPECIAL, sb16_dsp_open, sb16_dsp_close, sb16_dsp_output_block, @@ -87,7 +88,7 @@ static struct audio_operations sb16_dsp_operations = NULL }; -static int +static int sb_dsp_command01 (unsigned char val) { int i = 1 << 16; @@ -98,33 +99,32 @@ sb_dsp_command01 (unsigned char val) return sb_dsp_command (val); } -static int -wait_data_avail (int t) +static int +wait_data_avail (unsigned long t) { int loopc = 5000000; - unsigned long tt; - tt = t + GET_TIME (); + t += GET_TIME (); do { if (INB (DSP_DATA_AVAIL) & 0x80) return 1; } - while (--loopc && GET_TIME () < tt); + while (--loopc && GET_TIME () < t); printk ("!data_avail l=%d\n", loopc); return 0; } -static int +static int read_dsp (int t) { - if (!wait_data_avail (t)) + if (!wait_data_avail ((unsigned long) t)) return -1; else return INB (DSP_READ); } -static int +static int dsp_ini2 (void) { #if 0 @@ -141,6 +141,7 @@ dsp_ini2 (void) #endif return 0; } + /* static char *dsp_getmessage(unsigned char command,int maxn) { @@ -148,7 +149,7 @@ dsp_ini2 (void) int n=0; sb_dsp_command(command); - while(n<maxn && wait_data_avail(2)) { + while(n<maxn && wait_data_avail(2L)) { buff[++n]=INB(DSP_READ); if(!buff[n]) break; @@ -171,7 +172,7 @@ dsp_ini2 (void) printk("\n"); } */ -static int +static int dsp_set_speed (int mode) { DEB (printk ("dsp_set_speed(%d)\n", mode)); @@ -186,7 +187,7 @@ dsp_set_speed (int mode) return mode; } -static int +static int dsp_set_stereo (int mode) { DEB (printk ("dsp_set_stereo(%d)\n", mode)); @@ -196,7 +197,7 @@ dsp_set_stereo (int mode) return mode; } -static int +static int dsp_set_bits (int arg) { DEB (printk ("dsp_set_bits(%d)\n", arg)); @@ -523,36 +524,24 @@ set_irq_hw (int level) long sb16_dsp_init (long mem_start, struct address_info *hw_config) { - int i, major, minor; - - major = minor = 0; - sb_dsp_command (0xe1); /* Get version */ - - for (i = 1000; i; i--) - { - if (INB (DSP_DATA_AVAIL) & 0x80) - { /* wait for Data Ready */ - if (major == 0) - major = INB (DSP_READ); - else - { - minor = INB (DSP_READ); - break; - } - } - } + if (sbc_major < 4) + return mem_start; #ifndef SCO - sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", major, minor); + sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor); #endif +#ifdef __FreeBSD__ printk ("snd6: <%s>", sb16_dsp_operations.name); +#else + printk (" <%s>", sb16_dsp_operations.name); +#endif if (num_dspdevs < MAX_DSP_DEV) { dsp_devs[my_dev = num_dspdevs++] = &sb16_dsp_operations; sound_dsp_dmachan[my_dev] = hw_config->dma; - sound_buffcounts[my_dev] = DSP_BUFFCOUNT; + sound_buffcounts[my_dev] = 1; sound_buffsizes[my_dev] = DSP_BUFFSIZE; sound_dma_automode[my_dev] = 1; } @@ -576,9 +565,6 @@ sb16_dsp_detect (struct address_info *hw_config) return 0; } - if (sbc_base != hw_config->io_base) - printk ("Warning! SB16 I/O != SB I/O\n"); - /* sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0; */ @@ -586,13 +572,6 @@ sb16_dsp_detect (struct address_info *hw_config) if (!sb_reset_dsp ()) return 0; - if (hw_config->irq != sb_config->irq) - { - printk ("SB16 Error: Invalid IRQ number %d/%d\n", - sb_config->irq, hw_config->irq); - return 0; - } - if (hw_config->dma < 4) if (hw_config->dma != sb_config->dma) { @@ -603,12 +582,12 @@ sb16_dsp_detect (struct address_info *hw_config) dma16 = hw_config->dma; dma8 = sb_config->dma; - set_irq_hw (hw_config->irq); + set_irq_hw (sb_config->irq); sb_setmixer (DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma)); - DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", hw_config->irq, hw_config->dma)); + DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, hw_config->dma)); -/* + /* dsp_showmessage(0xe3,99); */ sb16_dsp_ok = 1; @@ -639,4 +618,5 @@ sb16_dsp_interrupt (int unused) printk ("SoundBlaster: Unexpected interrupt\n"); } } + #endif diff --git a/sys/i386/isa/sound/sb16_midi.c b/sys/i386/isa/sound/sb16_midi.c index f7a61a6..39808c8 100644 --- a/sys/i386/isa/sound/sb16_midi.c +++ b/sys/i386/isa/sound/sb16_midi.c @@ -1,10 +1,10 @@ /* * sound/sb16_midi.c - * + * * The low level driver for the MPU-401 UART emulation of the SB16. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -58,26 +58,19 @@ static int my_dev; 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) { - int count; - - count = 10; - - while (count) /* Not timed out */ - if (input_avail ()) - { - unsigned char c = sb16midi_read (); - count = 100; + while (input_avail ()) + { + unsigned char c = sb16midi_read (); - if (sb16midi_opened & OPEN_READ) - midi_input_intr (my_dev, c); - } - else - while (!input_avail () && count) - count--; + if (sb16midi_opened & OPEN_READ) + midi_input_intr (my_dev, c); + } } void @@ -87,31 +80,6 @@ sb16midiintr (int unit) sb16midi_input_loop (); } -/* - * It looks like there is no input interrupts in the UART mode. Let's try - * polling. - */ - -static void -poll_sb16midi (unsigned long dummy) -{ - unsigned long flags; - - DEFINE_TIMER (sb16midi_timer, poll_sb16midi); - - if (!(sb16midi_opened & OPEN_READ)) - return; /* No longer required */ - - DISABLE_INTR (flags); - - if (input_avail ()) - sb16midi_input_loop (); - - ACTIVATE_TIMER (sb16midi_timer, poll_sb16midi, 1); /* Come back later */ - - RESTORE_INTR (flags); -} - static int sb16midi_open (int dev, int mode, void (*input) (int dev, unsigned char data), @@ -127,7 +95,6 @@ sb16midi_open (int dev, int mode, midi_input_intr = input; sb16midi_opened = mode; - poll_sb16midi (0); /* Enable input polling */ return 0; } @@ -245,7 +212,11 @@ attach_sb16midi (long mem_start, struct address_info *hw_config) RESTORE_INTR (flags); +#ifdef __FreeBSD__ printk ("snd7: <SoundBlaster MPU-401>"); +#else + printk (" <SoundBlaster MPU-401>"); +#endif my_dev = num_midis; midi_devs[num_midis++] = &sb16midi_operations; @@ -299,6 +270,8 @@ probe_sb16midi (struct address_info *hw_config) int ok = 0; sb16midi_base = hw_config->io_base; + if (sbc_major < 4) + return 0; /* SB16 not detected */ if (sb_get_irq () < 0) return 0; diff --git a/sys/i386/isa/sound/sb_card.c b/sys/i386/isa/sound/sb_card.c index ef90b4b..f7588e1 100644 --- a/sys/i386/isa/sound/sb_card.c +++ b/sys/i386/isa/sound/sb_card.c @@ -1,10 +1,10 @@ /* * sound/sb_card.c - * + * * Detection routine for the SoundBlaster cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" diff --git a/sys/i386/isa/sound/sb_dsp.c b/sys/i386/isa/sound/sb_dsp.c index 9f0bfb2..17fb4b7 100644 --- a/sys/i386/isa/sound/sb_dsp.c +++ b/sys/i386/isa/sound/sb_dsp.c @@ -25,6 +25,10 @@ * 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 + * */ #include "sound_config.h" @@ -37,6 +41,7 @@ int sbc_base = 0; static int sbc_irq = 0; +static int open_mode=0; /* * The DSP channel can be used either for input or output. Variable @@ -49,7 +54,8 @@ static int sbc_irq = 0; int sb_dsp_ok = 0; /* Set to 1 after successful initialization */ static int midi_disabled = 0; int sb_dsp_highspeed = 0; -static int major = 1, minor = 0; /* DSP version */ +int sbc_major = 1; +int sbc_minor = 0; /* DSP version */ static int dsp_stereo = 0; static int dsp_current_speed = DSP_DEFAULT_SPEED; static int sb16 = 0; @@ -64,7 +70,6 @@ volatile int sb_irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT * or IMODE_NONE */ static volatile int irq_ok = 0; -int sb_dsp_model = 1; /* 1=SB, 2=SB Pro */ int sb_duplex_midi = 0; static int my_dev = 0; @@ -84,7 +89,7 @@ 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 @@ -111,7 +116,7 @@ sb_dsp_command (unsigned char val) void sbintr (int unit) { - int status, data; + int status; #ifndef EXCLUDE_SBPRO if (sb16) @@ -134,7 +139,7 @@ sbintr (int unit) } #endif - status = INB (DSP_DATA_AVAIL); /* Clear interrupt */ + status = INB (DSP_DATA_AVAIL);/* Clear interrupt */ if (sb_intr_active) switch (sb_irq_mode) @@ -156,10 +161,7 @@ sbintr (int unit) break; case IMODE_MIDI: - printk ("+"); - data = INB (DSP_READ); - printk ("%x", data); - + sb_midi_interrupt (unit); break; default: @@ -234,17 +236,31 @@ dsp_speed (int speed) { unsigned char tconst; unsigned long flags; + int max_speed = 44100; if (speed < 4000) speed = 4000; - if (speed > 44100) - speed = 44100; /* Invalid speed */ + /* + * Older SB models don't support higher speeds than 22050. + */ - if (sb_dsp_model == 1 && speed > 22050) - speed = 22050; - /* SB Classic doesn't support higher speed */ + if (sbc_major < 2 || + (sbc_major == 2 && sbc_minor == 0)) + max_speed = 22050; + /* + * SB models earlier than SB Pro have low limit for the input speed. + */ + if (open_mode != OPEN_WRITE) /* Recording is possible */ + if (sbc_major < 3) /* Limited input speed with these cards */ + if (sbc_major == 2 && sbc_minor > 0) + max_speed = 15000; + else + max_speed = 13000; + + if (speed > max_speed) + speed = max_speed; /* Invalid speed */ if (dsp_stereo && speed > 22050) speed = 22050; @@ -285,7 +301,7 @@ 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); @@ -308,7 +324,7 @@ dsp_set_stereo (int mode) #ifdef EXCLUDE_SBPRO return 0; #else - if (sb_dsp_model < 3 || sb16) + if (sbc_major < 3 || sb16) return 0; /* Sorry no stereo */ if (mode && sb_midi_busy) @@ -341,11 +357,11 @@ sb_dsp_output_block (int dev, unsigned long buf, int 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"); @@ -354,7 +370,7 @@ 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)); @@ -387,11 +403,11 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, 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"); @@ -400,7 +416,7 @@ 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)); @@ -425,7 +441,7 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount) dsp_cleanup (); dsp_speaker (OFF); - if (major == 3) /* SB Pro */ + if (sbc_major == 3) /* SB Pro */ { if (dsp_stereo) sb_dsp_command (0xa8); @@ -445,7 +461,7 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount) dsp_speaker (ON); #ifndef EXCLUDE_SBPRO - if (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 @@ -534,6 +550,7 @@ sb_dsp_open (int dev, int mode) sb_irq_mode = IMODE_NONE; sb_dsp_busy = 1; + open_mode = mode; return 0; } @@ -547,6 +564,7 @@ sb_dsp_close (int dev) dsp_speaker (OFF); sb_dsp_busy = 0; sb_dsp_highspeed = 0; + open_mode = 0; } static int @@ -588,7 +606,7 @@ 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: @@ -611,6 +629,7 @@ sb_dsp_reset (int dev) DISABLE_INTR (flags); sb_reset_dsp (); + dsp_speed (dsp_current_speed); dsp_cleanup (); RESTORE_INTR (flags); @@ -636,9 +655,10 @@ sb_dsp_detect (struct address_info *hw_config) static char card_name[32] = "SoundBlaster"; #ifndef EXCLUDE_AUDIO -struct audio_operations sb_dsp_operations = +static struct audio_operations sb_dsp_operations = { "SoundBlaster", + NOTHING_SPECIAL, sb_dsp_open, sb_dsp_close, sb_dsp_output_block, @@ -658,62 +678,77 @@ long sb_dsp_init (long mem_start, struct address_info *hw_config) { int i; + int prostat = 0; - major = minor = 0; + sbc_major = sbc_minor = 0; sb_dsp_command (0xe1); /* Get version */ for (i = 1000; i; i--) { if (INB (DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */ - if (major == 0) - major = INB (DSP_READ); + if (sbc_major == 0) + sbc_major = INB (DSP_READ); else { - minor = INB (DSP_READ); + sbc_minor = INB (DSP_READ); break; } } } - if (major == 2 || major == 3) + if (sbc_major == 2 || sbc_major == 3) /* SB 2.0 or SB Pro */ sb_duplex_midi = 1; - if (major == 4) + if (sbc_major == 4) sb16 = 1; - sb_dsp_model = major; - #ifndef EXCLUDE_SBPRO - if (major >= 3) - sb_mixer_init (major); + if (sbc_major >= 3 || + (sbc_major == 2 && sbc_minor == 1)) /* Sound Galaxy ??? */ + prostat = sb_mixer_init (sbc_major); #endif #ifndef EXCLUDE_YM3812 - if (major > 3 || (major == 3 && minor > 0)) /* SB Pro2 or later */ - { - enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); - } + if (sbc_major > 3 || + (sbc_major == 3 && INB (0x388) == 0x00)) /* Non OPL-3 should return 0x06 */ + enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); #endif -#ifndef SCO - if (major >= 3) + if (sbc_major >= 3) { +#ifndef SCO + if (prostat) + { #ifndef EXCLUDE_AUDIO - sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", major, minor); + 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 + { +#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 - sprintf (card_name, "SoundBlaster Pro %d.%d", major, minor); } else { +#ifndef SCO #ifndef EXCLUDE_AUDIO - sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", major, minor); + sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor); #endif - sprintf (card_name, "SoundBlaster %d.%d", major, minor); - } + sprintf (card_name, "SoundBlaster %d.%d", sbc_major, sbc_minor); #endif + } +#ifdef __FreeBSD__ printk ("snd2: <%s>", card_name); +#else + printk (" <%s>", card_name); +#endif #ifndef EXCLUDE_AUDIO #if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO) @@ -734,7 +769,7 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) #ifndef EXCLUDE_MIDI if (!midi_disabled && !sb16) /* Midi don't work in the SB emulation mode * of PAS, SB16 has better midi interface */ - sb_midi_init (major); + sb_midi_init (sbc_major); #endif sb_dsp_ok = 1; diff --git a/sys/i386/isa/sound/sb_midi.c b/sys/i386/isa/sound/sb_midi.c index 2b0ab52..fed19ab 100644 --- a/sys/i386/isa/sound/sb_midi.c +++ b/sys/i386/isa/sound/sb_midi.c @@ -1,10 +1,10 @@ /* * sound/sb_dsp.c - * + * * The low level driver for the SoundBlaster DS chips. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -49,12 +49,16 @@ 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 +extern volatile int sb_irq_mode;/* IMODE_INPUT, IMODE_OUTPUT * or IMODE_NONE */ -extern int sb_dsp_model; /* 1=SB, 2=SB Pro */ extern int sb_duplex_midi; extern int sb_intr_active; +extern int sbc_base; + +static int input_opened = 0; +static void (*midi_input_intr) (int dev, unsigned char data); +static int my_dev = 0; static int sb_midi_open (int dev, int mode, @@ -73,7 +77,7 @@ sb_midi_open (int dev, int mode, if (mode != OPEN_WRITE && !sb_duplex_midi) { if (num_midis == 1) - printk ("SoundBlaster: Midi input not currently supported\n"); + printk ("SoundBlaster: MIDI input not supported with plain SB\n"); return RET_ERROR (EPERM); } @@ -97,6 +101,9 @@ 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 */ sb_intr_active = 1; @@ -106,6 +113,9 @@ sb_midi_open (int dev, int mode, sb_reset_dsp (); return 0; /* IRQ not free */ } + input_opened = 1; + my_dev = dev; + midi_input_intr = input; } sb_midi_busy = 1; @@ -123,6 +133,7 @@ sb_midi_close (int dev) } sb_intr_active = 0; sb_midi_busy = 0; + input_opened = 0; } static int @@ -175,6 +186,21 @@ sb_midi_ioctl (int dev, unsigned cmd, unsigned arg) return RET_ERROR (EPERM); } +void +sb_midi_interrupt (int dummy) +{ + unsigned long flags; + unsigned char data; + + DISABLE_INTR (flags); + + data = INB (DSP_READ); + if (input_opened) + midi_input_intr (my_dev, data); + + RESTORE_INTR (flags); +} + static struct midi_operations sb_midi_operations = { {"SoundBlaster", 0, 0, SNDCARD_SB}, diff --git a/sys/i386/isa/sound/sb_mixer.c b/sys/i386/isa/sound/sb_mixer.c index 089a2af..39b97ca 100644 --- a/sys/i386/isa/sound/sb_mixer.c +++ b/sys/i386/isa/sound/sb_mixer.c @@ -1,11 +1,11 @@ /* * sound/sb_mixer.c - * + * * The low level mixer driver for the SoundBlaster Pro and SB16 cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +13,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 @@ -25,7 +25,11 @@ * 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 the Sound Galaxy NX Pro mixer. + * */ #include "sound_config.h" @@ -87,9 +91,21 @@ sb_mixer_set_stereo (int mode) | (mode ? STEREO_DAC : MONO_DAC))); } +/* + * Returns: + * 0 No mixer detected. + * 1 Only a plain Sound Blaster Pro style mixer detected. + * 2 The Sound Galaxy NX Pro mixer detected. + */ static int detect_mixer (void) { +#ifdef __SGNXPRO__ + int oldbass, oldtreble; + +#endif + int retcode = 1; + /* * Detect the mixer by changing parameters of two volume channels. If the * values read back match with the values written, the mixer is there (is @@ -103,7 +119,30 @@ detect_mixer (void) if (sb_getmixer (VOC_VOL) != 0x33) return 0; - return 1; +#ifdef __SGNXPRO__ + /* Attempt to detect the SG NX Pro by check for valid bass/treble + * registers. + */ + oldbass = sb_getmixer (BASS_LVL); + oldtreble = sb_getmixer (TREBLE_LVL); + + sb_setmixer (BASS_LVL, 0xaa); + sb_setmixer (TREBLE_LVL, 0x55); + + if ((sb_getmixer (BASS_LVL) != 0xaa) || + (sb_getmixer (TREBLE_LVL) != 0x55)) + { + retcode = 1; /* 1 == Only SB Pro detected */ + } + else + retcode = 2; /* 2 == SG NX Pro detected */ + /* Restore register in either case since SG NX Pro has EEPROM with + * 'preferred' values stored. + */ + sb_setmixer (BASS_LVL, oldbass); + sb_setmixer (TREBLE_LVL, oldtreble); +#endif + return retcode; } static void @@ -320,13 +359,24 @@ sb_mixer_reset (void) set_recmask (SOUND_MASK_MIC); } -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. + * + * Used to update message. + */ +int sb_mixer_init (int major_model) { + int mixerstat; + sb_setmixer (0x00, 0); /* Reset mixer */ - if (!detect_mixer ()) - return; /* No mixer. Why? */ + mixerstat = detect_mixer (); + + if (!mixerstat) + return 0; /* No mixer. Why? */ mixer_initialized = 1; mixer_model = major_model; @@ -335,9 +385,21 @@ sb_mixer_init (int major_model) { case 3: mixer_caps = SOUND_CAP_EXCL_INPUT; - supported_devices = SBPRO_MIXER_DEVICES; - supported_rec_devices = SBPRO_RECORDING_DEVICES; - iomap = &sbpro_mix; +#ifdef __SGNXPRO__ + if (mixerstat == 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; + } + break; case 4: @@ -349,11 +411,12 @@ sb_mixer_init (int major_model) default: printk ("SB Warning: Unsupported mixer type\n"); - return; + return 0; } mixer_devs[num_mixers++] = &sb_mixer_operations; sb_mixer_reset (); + return (mixerstat == 2); } #endif diff --git a/sys/i386/isa/sound/sb_mixer.h b/sys/i386/isa/sound/sb_mixer.h index 304af642..4caf773 100644 --- a/sys/i386/isa/sound/sb_mixer.h +++ b/sys/i386/isa/sound/sb_mixer.h @@ -24,13 +24,29 @@ * 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 defines for the Sound Galaxy NX Pro mixer. * */ + #define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) +/* Same as SB Pro, unless I find otherwise */ +#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES + #define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \ SOUND_MASK_CD | SOUND_MASK_VOLUME) +/* SG NX Pro has treble and bass settings on the mixer. The 'speaker' + * channel is the COVOX/DisneySoundSource emulation volume control + * on the mixer. It does NOT control speaker volume. Should have own + * mask eventually? + */ +#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \ + SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER ) + #define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \ SOUND_MASK_CD) @@ -62,6 +78,13 @@ #define IRQ_STAT 0x82 #define OPSW 0x3c +/* + * Additional registers on the SG NX Pro + */ +#define COVOX_VOL 0x42 +#define TREBLE_LVL 0x44 +#define BASS_LVL 0x46 + #define FREQ_HI (1 << 3)/* Use High-frequency ANFI filters */ #define FREQ_LOW 0 /* Use Low-frequency ANFI filters */ #define FILT_ON 0 /* Yes, 0 to turn it on, 1 for off */ @@ -108,6 +131,23 @@ MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) }; +#ifdef __SGNXPRO__ +mixer_tab sgnxpro_mix = { +MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), +MIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), +MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), +MIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), +MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), +MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) +}; +#endif + mixer_tab sb16_mix = { MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5), MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4), diff --git a/sys/i386/isa/sound/sequencer.c b/sys/i386/isa/sound/sequencer.c index e61e445..9885473 100644 --- a/sys/i386/isa/sound/sequencer.c +++ b/sys/i386/isa/sound/sequencer.c @@ -1,10 +1,10 @@ /* * sound/sequencer.c - * + * * The sequencer personality manager. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #define SEQUENCER_C @@ -46,7 +46,7 @@ static int midi_opened[MAX_MIDI_DEV] = static int midi_written[MAX_MIDI_DEV] = {0}; -unsigned long seq_time = 0; /* Reference point for the timer */ +unsigned long seq_time = 0; /* Reference point for the timer */ #include "tuning.h" @@ -87,6 +87,9 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) { 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) @@ -327,6 +330,10 @@ extended_event (unsigned char *q) synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]); break; + case SEQ_VOLMODE: + synth_devs[dev]->volume_method (dev, q[3]); + break; + default: return RET_ERROR (EINVAL); } @@ -688,7 +695,7 @@ seq_reset (void) { midi_outc (i, (unsigned char) (0xb0 + (chn & 0xff))); /* Channel msg */ - midi_outc (i, 0x7b); /* All notes off */ + midi_outc (i, 0x7b);/* All notes off */ midi_outc (i, 0); /* Dummy parameter */ } @@ -1049,7 +1056,7 @@ unsigned long compute_finetune (unsigned long base_freq, int bend, int range) { unsigned long amount; - int negative, semitones, cents; + int negative, semitones, cents, multiplier = 1; if (!bend) return base_freq; @@ -1073,13 +1080,20 @@ compute_finetune (unsigned long base_freq, int bend, int range) if (bend > range) bend = range; - if (bend > 2399) - bend = 2399; + /* + if (bend > 2399) + bend = 2399; + */ + while (bend > 2399) + { + multiplier *= 4; + bend -= 2400; + } semitones = bend / 100; cents = bend % 100; - amount = semitone_tuning[semitones] * cent_tuning[cents] / 10000; + amount = semitone_tuning[semitones] * multiplier * cent_tuning[cents] / 10000; if (negative) return (base_freq * 10000) / amount; /* Bend down */ diff --git a/sys/i386/isa/sound/sound_calls.h b/sys/i386/isa/sound/sound_calls.h index 97fb769..abc8200 100644 --- a/sys/i386/isa/sound/sound_calls.h +++ b/sys/i386/isa/sound/sound_calls.h @@ -129,12 +129,13 @@ int probe_sb16midi(struct address_info *hw_config); /* 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); int sb_getmixer (unsigned int port); void sb_mixer_set_stereo(int mode); -void sb_mixer_init(int major_model); +int sb_mixer_init(int major_model); /* From opl3.c */ int opl3_detect (int ioaddr); @@ -181,6 +182,7 @@ unsigned char gus_read8 (int reg); void gus_write8(int reg, unsigned int data); void guswave_dma_irq(void); void gus_delay(void); +int gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg); /* From gus_midi.c */ long gus_midi_init(long mem_start); @@ -201,3 +203,6 @@ int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count); int pmgr_access(int dev, struct patmgr_info *rec); int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2, unsigned long parm3, unsigned long parm4); + +/* From ics2101.c */ +long ics2101_mixer_init(long mem_start); diff --git a/sys/i386/isa/sound/sound_switch.c b/sys/i386/isa/sound/sound_switch.c index 52120d5..68c7575 100644 --- a/sys/i386/isa/sound/sound_switch.c +++ b/sys/i386/isa/sound/sound_switch.c @@ -1,10 +1,10 @@ /* * sound/sound_switch.c - * + * * The system call switch - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -441,4 +441,5 @@ sound_ioctl_sw (int dev, struct fileinfo *file, return RET_ERROR (EPERM); } + #endif |