summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/sound/gus_wave.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-07-28 21:40:49 +0000
committerjkh <jkh@FreeBSD.org>1995-07-28 21:40:49 +0000
commit19112b8b1d7c4013411f77a8ee48332903ec93ab (patch)
tree81647a2f70826c19344d26635282f97d889294b9 /sys/i386/isa/sound/gus_wave.c
parentccee31df86151913015fb2d5accc4c61a4a5f822 (diff)
downloadFreeBSD-src-19112b8b1d7c4013411f77a8ee48332903ec93ab.zip
FreeBSD-src-19112b8b1d7c4013411f77a8ee48332903ec93ab.tar.gz
Update the sound driver to VOXWARE 3.05 with one GUS patch from
Amancio. There is some SoundSource support here that is primitive and probably doesn't work, but I'll let the two submitters let me know how my integration of that was since I don't have this card to test. I've only tested this on my GUS MAX since it's all I have. This all probably needs to be re-done anyway since we're widely variant from the original VOXWARE source in the current layout. Submitted by: Amancio Hasty and Jim Lowe Obtained from: Hannu Savolainen
Diffstat (limited to 'sys/i386/isa/sound/gus_wave.c')
-rw-r--r--sys/i386/isa/sound/gus_wave.c464
1 files changed, 292 insertions, 172 deletions
diff --git a/sys/i386/isa/sound/gus_wave.c b/sys/i386/isa/sound/gus_wave.c
index 1008aa4..2def4909 100644
--- a/sys/i386/isa/sound/gus_wave.c
+++ b/sys/i386/isa/sound/gus_wave.c
@@ -25,19 +25,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: gus_wave.c,v 1.14 1995/03/12 23:33:52 swallace Exp $
*/
#include "sound_config.h"
-#include <machine/ultrasound.h>
+#include "ultrasound.h"
#include "gus_hw.h"
-#undef OUTB
-#define OUTB(val, port) outb(port, val)
-
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
-#define MAX_SAMPLE 128
+#define MAX_SAMPLE 150
#define MAX_PATCH 256
struct voice_info
@@ -82,12 +78,14 @@ extern int gus_base;
extern int gus_irq, gus_dma;
static long gus_mem_size = 0;
static long free_mem_ptr = 0;
-static int gus_busy = 0;
+ int gus_busy[MAX_AUDIO_DEV], gus_dspnum=0;
+static int gus_dma_read=0;
static int nr_voices = 0;
-static int gus_devnum = 0;
+ int gus_devnum = 0;
static int volume_base, volume_scale, volume_method;
static int gus_recmask = SOUND_MASK_MIC;
static int recording_active = 0;
+static int only_read_access = 0;
int gus_wave_volume = 60;
int gus_pcm_volume = 80;
@@ -478,10 +476,12 @@ gus_voice_init (int voice)
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_voice_volume (0);
+ gus_voice_off ();
gus_write_addr (0x0a, 0, 0); /* Set current position to 0 */
gus_write8 (0x00, 0x03); /* Voice off */
gus_write8 (0x0d, 0x03); /* Ramping off */
voice_alloc->map[voice] = 0;
+ voice_alloc->alloc_times[voice] = 0;
RESTORE_INTR (flags);
}
@@ -676,7 +676,7 @@ gus_initialize (void)
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};
+ {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
static unsigned char gus_dma_map[8] =
{0, 1, 0, 2, 0, 3, 4, 5};
@@ -744,7 +744,14 @@ gus_initialize (void)
irq_image |= tmp;
irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
- dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
+ dma_image = gus_dma_map[gus_dma_read] << 3;
+ if(!dma_image)
+ printk ("Warning! GUS DMA read channel not selected.\n");
+ if(gus_dma_read == gus_dma)
+ {
+ dma_image = 0x40; /* dual dma inhibited
+ Combine DMA1 (DRAM) and IRQ2 (ADC) */
+ }
tmp = gus_dma_map[gus_dma];
if (!tmp)
printk ("Warning! GUS DMA not selected\n");
@@ -785,7 +792,7 @@ gus_initialize (void)
gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
- gusintr (0); /* Serve pending interrupts */
+ gusintr (INT_HANDLER_CALL (0)); /* Serve pending interrupts */
RESTORE_INTR (flags);
}
@@ -892,7 +899,7 @@ 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 */
@@ -913,7 +920,7 @@ guswave_kill_note (int dev, int voice, int note, int velocity)
unsigned long flags;
DISABLE_INTR (flags);
- voice_alloc->map[voice] = 0xffff;
+ /* voice_alloc->map[voice] = 0xffff; */
if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
{
voices[voice].kill_pending = 1;
@@ -925,17 +932,17 @@ guswave_kill_note (int dev, int voice, int note, int velocity)
gus_voice_fade (voice);
}
+ RESTORE_INTR (flags);
return 0;
}
static void
guswave_aftertouch (int dev, int voice, int pressure)
{
+#if 0
short lo_limit, hi_limit;
unsigned long flags;
- return; /* Procedure currently disabled */
-
if (voice < 0 || voice > 31)
return;
@@ -968,6 +975,7 @@ guswave_aftertouch (int dev, int voice, int pressure)
gus_ramp_rate (3, 8);
gus_rampon (0x58); /* Bidirectional, dow, loop */
RESTORE_INTR (flags);
+#endif /* 0 */
}
static void
@@ -1024,8 +1032,8 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
DISABLE_INTR (flags);
/*
- * CAUTION! Interrupts disabled. Enable them before returning
- */
+ * CAUTION! Interrupts disabled. Enable them before returning
+ */
gus_select_voice (voice);
@@ -1234,8 +1242,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
note_freq <= samples[samplep].high_note)
sample = samplep;
else
- samplep = samples[samplep].key; /*
- * Follow link
+ samplep = samples[samplep].key; /*
+ * Follow link
*/
}
if (sample == -1)
@@ -1340,9 +1348,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
}
gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start,
- is16bits);/* Loop start location */
+ is16bits); /* Loop start location */
gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end,
- is16bits);/* Loop end location */
+ is16bits); /* Loop end location */
}
else
{
@@ -1350,9 +1358,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */
voices[voice].loop_irq_parm = 1;
gus_write_addr (0x02, sample_ptrs[sample],
- is16bits);/* Loop start location */
+ is16bits); /* Loop start location */
gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1,
- is16bits);/* Loop end location */
+ is16bits); /* Loop end location */
}
gus_voice_freq (freq);
gus_voice_balance (pan);
@@ -1382,8 +1390,7 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
voices[voice].volume_pending = volume;
else
{
- RESTORE_INTR (flags);
- ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+ ret_val = guswave_start_note2 (gus_devnum, voice, note_num, volume);
}
}
else
@@ -1391,7 +1398,7 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
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;
@@ -1400,31 +1407,32 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
if (voices[voice].sample_pending >= 0)
{
- RESTORE_INTR (flags);
+ RESTORE_INTR (flags); /* Run temporarily with interrupts enabled */
guswave_set_instr (voices[voice].dev_pending, voice,
voices[voice].sample_pending);
voices[voice].sample_pending = -1;
DISABLE_INTR (flags);
+ gus_select_voice (voice); /* Reselect the voice (just to be sure) */
}
if ((mode & 0x01) || (int) ((gus_read16 (0x09) >> 4) < 2065))
{
- ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+ ret_val = guswave_start_note2 (gus_devnum, voice, note_num, volume);
}
else
{
- voices[voice].dev_pending = dev;
+ voices[voice].dev_pending = gus_devnum;
voices[voice].note_pending = note_num;
voices[voice].volume_pending = volume;
voices[voice].volume_irq_mode = VMODE_START_NOTE;
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;
}
@@ -1445,16 +1453,19 @@ guswave_open (int dev, int mode)
{
int err;
- if (gus_busy)
+ if (mode & OPEN_WRITE && gus_busy[gus_devnum] ||
+ mode & OPEN_READ && gus_busy[gus_dspnum])
return RET_ERROR (EBUSY);
- gus_initialize ();
+ if(gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0)
+ gus_initialize ();
+ voice_alloc->timestamp = 0;
if ((err = DMAbuf_open_dma (gus_devnum)) < 0)
return err;
RESET_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
- gus_busy = 1;
+ gus_busy[gus_devnum] = 1;
active_device = GUS_DEV_WAVE;
gus_reset ();
@@ -1465,7 +1476,7 @@ guswave_open (int dev, int mode)
static void
guswave_close (int dev)
{
- gus_busy = 0;
+ gus_busy[gus_devnum] = 0;
active_device = 0;
gus_reset ();
@@ -1482,7 +1493,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
unsigned long blk_size, blk_end, left, src_offs, target;
- sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
+ sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
if (format != GUS_PATCH)
{
@@ -1654,7 +1665,8 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
addr, sizeof_patch + src_offs,
blk_size);
- DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/
+ DISABLE_INTR (flags);
+/******** INTERRUPTS DISABLED NOW ********/
gus_write8 (0x41, 0); /* Disable GF1 DMA */
DMAbuf_start_dma (gus_devnum,
audio_devs[gus_devnum]->dmap->raw_buf_phys[0],
@@ -1688,7 +1700,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if (audio_devs[gus_devnum]->dmachan > 3)
dma_command |= 0x04; /* 16 bit DMA _channel_ */
- gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */
+ gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */
/*
* Sleep here until the DRAM DMA done interrupt is served
@@ -1716,7 +1728,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
free_mem_ptr += patch.len;
if (!pmgr_flag)
- pmgr_inform (dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);
+ pmgr_inform (gus_devnum, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);
free_sample++;
return 0;
}
@@ -1871,13 +1883,25 @@ guswave_hw_control (int dev, unsigned char *event)
static int
gus_sampling_set_speed (int speed)
{
+
if (speed <= 0)
- return gus_sampling_speed;
+ speed = gus_sampling_speed;
+
+ if (speed < 4000)
+ speed = 4000;
if (speed > 44100)
speed = 44100;
gus_sampling_speed = speed;
+
+ if (only_read_access)
+ {
+ /* Compute nearest valid recording speed and return it */
+
+ speed = (9878400 / (gus_sampling_speed + 2)) / 16;
+ speed = (9878400 / (speed * 16)) - 2;
+ }
return speed;
}
@@ -1961,8 +1985,6 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return IOCTL_OUT (arg, RET_ERROR (EINVAL));
break;
- default:
- return RET_ERROR (EINVAL);
}
return RET_ERROR (EINVAL);
}
@@ -1975,17 +1997,36 @@ gus_sampling_reset (int dev)
static int
gus_sampling_open (int dev, int mode)
{
+ int dev_flag;
#ifdef GUS_NO_DMA
printk ("GUS: DMA mode not enabled. Device not supported\n");
return RET_ERROR (ENXIO);
#endif
+ dev_flag = 0;
+ if(mode & OPEN_WRITE)
+ {
+ if (gus_busy[gus_devnum])
+ return RET_ERROR(EBUSY);
+ if(dev != gus_devnum)
+ return RET_ERROR(ENXIO);
+ dev_flag = gus_busy[gus_devnum] = 1;
+ }
+ if(mode & OPEN_READ)
+ {
+ if(gus_busy[gus_dspnum]) {
+ if (dev_flag) gus_busy[gus_devnum] = 0;
+ return RET_ERROR(EBUSY);
+ }
+
+ if(dev != gus_dspnum) {
+ if (dev_flag) gus_busy[gus_devnum] = 0;
+ return RET_ERROR(ENXIO);
+ }
+ }
+
+ if(gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum] == 0)
+ gus_initialize ();
- if (gus_busy)
- return RET_ERROR (EBUSY);
-
- gus_initialize ();
-
- gus_busy = 1;
active_device = 0;
gus_reset ();
@@ -2000,6 +2041,7 @@ gus_sampling_open (int dev, int mode)
recording_active = 1;
set_input_volumes ();
}
+ only_read_access = !(mode & OPEN_WRITE);
return 0;
}
@@ -2007,10 +2049,12 @@ gus_sampling_open (int dev, int mode)
static void
gus_sampling_close (int dev)
{
- gus_reset ();
- gus_busy = 0;
- pcm_opened = 0;
- active_device = 0;
+ gus_busy[dev] = 0;
+ if (gus_busy[gus_devnum] == 0 && gus_busy[gus_dspnum]) {
+ active_device = 0;
+ gus_reset();
+ pcm_opened = 0;
+ }
if (recording_active)
set_input_volumes ();
@@ -2024,16 +2068,16 @@ gus_sampling_update_volume (void)
unsigned long flags;
int voice;
- DISABLE_INTR (flags);
if (pcm_active && pcm_opened)
for (voice = 0; voice < gus_sampling_channels; voice++)
{
+ DISABLE_INTR (flags);
gus_select_voice (voice);
gus_rampoff ();
gus_voice_volume (1530 + (25 * gus_pcm_volume));
gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
+ RESTORE_INTR (flags);
}
- RESTORE_INTR (flags);
}
static void
@@ -2075,7 +2119,7 @@ play_next_pcm_block (void)
if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */
{
mode[chn] |= 0x08; /* Enable loop */
- ramp_mode[chn] = 0x03;/* Disable rollover bit */
+ ramp_mode[chn] = 0x03; /* Disable rollover bit */
}
else
{
@@ -2112,12 +2156,12 @@ play_next_pcm_block (void)
gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* Loop start */
if (chn != 0)
- gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk),
+ gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,
is16bits); /* Loop end location */
}
if (chn == 0)
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],
+ gus_write_addr (0x04, dram_loc + pcm_datasize[this_one] - 1,
is16bits); /* Loop end location */
else
mode[chn] |= 0x08; /* Enable looping */
@@ -2130,7 +2174,7 @@ play_next_pcm_block (void)
if (chn == 0)
{
mode[chn] &= ~0x08; /* Disable looping */
- mode[chn] |= 0x20;/* Enable IRQ at the end */
+ mode[chn] |= 0x20; /* Enable IRQ at the end */
voices[0].loop_irq_mode = LMODE_PCM_STOP;
ramp_mode[chn] = 0x03; /* No rollover bit */
}
@@ -2193,12 +2237,12 @@ gus_transfer_output_block (int dev, unsigned long buf,
this_one = pcm_current_block;
gus_write8 (0x41, 0); /* Disable GF1 DMA */
- DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE);
+ DMAbuf_start_dma (gus_devnum, buf + (chn * count), count, DMA_MODE_WRITE);
address = this_one * pcm_bsize;
address += chn * pcm_banksize;
- if (audio_devs[dev]->dmachan > 3)
+ if (audio_devs[gus_devnum]->dmachan > 3)
{
hold_address = address;
address = address >> 1;
@@ -2215,7 +2259,7 @@ gus_transfer_output_block (int dev, unsigned long buf,
else
dma_command |= 0x80; /* Invert MSB */
- if (audio_devs[dev]->dmachan > 3)
+ if (audio_devs[gus_devnum]->dmachan > 3)
dma_command |= 0x04; /* 16 bit DMA channel */
gus_write8 (0x41, dma_command); /* Kickstart */
@@ -2235,9 +2279,9 @@ gus_transfer_output_block (int dev, unsigned long buf,
else
{
/*
- * Left channel data. The right channel
- * is transferred after DMA interrupt
- */
+ * Left channel data. The right channel
+ * is transferred after DMA interrupt
+ */
active_device = GUS_DEV_PCM_CONTINUE;
}
@@ -2251,8 +2295,8 @@ gus_sampling_output_block (int dev, unsigned long buf, int total_count,
pcm_current_buf = buf;
pcm_current_count = total_count;
pcm_current_intrflag = intrflag;
- pcm_current_dev = dev;
- gus_transfer_output_block (dev, buf, total_count, intrflag, 0);
+ pcm_current_dev = gus_devnum;
+ gus_transfer_output_block (gus_devnum, buf, total_count, intrflag, 0);
}
static void
@@ -2264,11 +2308,11 @@ gus_sampling_start_input (int dev, unsigned long buf, int count,
DISABLE_INTR (flags);
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+ DMAbuf_start_dma (gus_dspnum, buf, count, DMA_MODE_READ);
mode = 0xa0; /* DMA IRQ enabled, invert MSB */
- if (audio_devs[dev]->dmachan > 3)
+ if (audio_devs[gus_dspnum]->dmachan > 3)
mode |= 0x04; /* 16 bit DMA channel */
if (gus_sampling_channels > 1)
mode |= 0x02; /* Stereo */
@@ -2364,8 +2408,8 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
}
else
{
- int in_left = useroffs;
- int in_right = useroffs + 1;
+ int in_left = useroffs / 2;
+ int in_right = useroffs / 2 + 1;
short *out_left, *out_right;
int i;
@@ -2404,6 +2448,42 @@ static struct audio_operations gus_sampling_operations =
gus_copy_from_user
};
+static struct audio_operations gus_sampling_operations_read =
+{
+ "Gravis UltraSound - read only",
+ NEEDS_RESTART,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ gus_sampling_open,
+ gus_sampling_close,
+ gus_sampling_output_block,
+ gus_sampling_start_input,
+ gus_sampling_ioctl,
+ gus_sampling_prepare_for_input,
+ gus_sampling_prepare_for_output,
+ gus_sampling_reset,
+ gus_sampling_reset,
+ gus_local_qlen,
+ gus_copy_from_user
+};
+
+static void
+guswave_setup_voice (int dev, int voice, int chn)
+{
+ struct channel_info *info =
+ &synth_devs[gus_devnum]->chn_info[chn];
+
+ guswave_set_instr (gus_devnum, voice, info->pgm_num);
+
+ voices[voice].expression_vol =
+ info->controllers[CTL_EXPRESSION]; /* Just msb */
+ voices[voice].main_vol =
+ (info->controllers[CTL_MAIN_VOLUME] * 100) / 128;
+ voices[voice].panning =
+ (info->controllers[CTL_PAN] * 2) - 128;
+ voices[voice].bender = info->bender_value;
+}
+
static void
guswave_bender (int dev, int voice, int value)
{
@@ -2528,7 +2608,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
if (offs < 0 || offs >= samples[sample].len)
return RET_ERROR (EINVAL); /* Invalid offset */
- n = samples[sample].len - offs; /* Num of bytes left */
+ n = samples[sample].len - offs; /* Num of bytes left */
if (l > n)
l = n;
@@ -2542,7 +2622,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
*/
offs += sample_ptrs[sample]; /*
- * Begin offset + offset to DRAM
+ * Begin offsess + offset to DRAM
*/
for (n = 0; n < l; n++)
@@ -2571,8 +2651,8 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
* Invalid offset
*/
- n = samples[sample].len - offs; /*
- * Nr of bytes left
+ n = samples[sample].len - offs; /*
+ * Nr of bytes left
*/
if (l > n)
@@ -2587,7 +2667,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
*/
offs += sample_ptrs[sample]; /*
- * Begin offset + offset to DRAM
+ * Begin offsess + offset to DRAM
*/
for (n = 0; n < l; n++)
@@ -2607,12 +2687,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
static int
guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc)
{
- int i, p;
+ int i, p, best = -1, best_time = 0x7fffffff;
p = alloc->ptr;
/*
- * First look for a completely stopped voice
- */
+ * First look for a completely stopped voice
+ */
for (i = 0; i < alloc->max_voice; i++)
{
@@ -2621,12 +2701,17 @@ guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc)
alloc->ptr = p;
return p;
}
+ if (alloc->alloc_times[p] < best_time)
+ {
+ best = p;
+ best_time = alloc->alloc_times[p];
+ }
p = (p + 1) % alloc->max_voice;
}
/*
- * Then look for a releasing voice
- */
+ * Then look for a releasing voice
+ */
for (i = 0; i < alloc->max_voice; i++)
{
@@ -2637,7 +2722,9 @@ guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc)
}
p = (p + 1) % alloc->max_voice;
}
- printk ("GUS: Out of free voices\n");
+
+ if (best >= 0)
+ p = best;
alloc->ptr = p;
return p;
@@ -2664,7 +2751,8 @@ static struct synth_operations guswave_operations =
guswave_volume_method,
guswave_patchmgr,
guswave_bender,
- guswave_alloc
+ guswave_alloc,
+ guswave_setup_voice
};
static void
@@ -2676,10 +2764,10 @@ 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.
- */
+ * Enable channels having vol > 10%
+ * Note! bit 0x01 means line in DISABLED while 0x04 means
+ * mic in ENABLED.
+ */
if (gus_line_vol > 10)
mask &= ~0x01;
if (gus_mic_vol > 10)
@@ -2688,8 +2776,8 @@ set_input_volumes (void)
if (recording_active)
{
/*
- * Disable channel, if not selected for recording
- */
+ * Disable channel, if not selected for recording
+ */
if (!(gus_recmask & SOUND_MASK_LINE))
mask |= 0x01;
if (!(gus_recmask & SOUND_MASK_MIC))
@@ -2833,6 +2921,7 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
static struct mixer_operations gus_mixer_operations =
{
+ "Gravis Ultrasound",
gus_default_mixer_ioctl
};
@@ -2849,7 +2938,7 @@ gus_default_mixer_init (long mem_start)
}
long
-gus_wave_init (long mem_start, int irq, int dma)
+gus_wave_init (long mem_start, int irq, int dma, int dma_read)
{
unsigned long flags;
unsigned char val;
@@ -2857,11 +2946,29 @@ gus_wave_init (long mem_start, int irq, int dma)
int gus_type = 0x24; /* 2.4 */
int mixer_type = 0;
+ if (irq < 0 || irq > 15)
+ {
+ printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
+ return mem_start;
+ }
+
+ if (dma < 0 || dma > 7)
+ {
+ printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma);
+ return mem_start;
+ }
+
+ if (dma_read == 0) dma_read = dma;
+ if (dma_read < 0 || dma_read > 7)
+ {
+ printk ("ERROR! Invalid DMA#%d. GUS DMA-read disabled", dma_read);
+ dma_read = dma;
+ }
/*
- * Try to identify the GUS model.
- *
- * Versions < 3.6 don't have the digital ASIC. Try to probe it first.
- */
+ * 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);
@@ -2871,9 +2978,9 @@ gus_wave_init (long mem_start, int irq, int dma)
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.
- */
+ * It has the digital ASIC so the card is at least v3.4.
+ * Next try to detect the true model.
+ */
val = INB (u_MixSelect);
@@ -2883,8 +2990,8 @@ gus_wave_init (long mem_start, int irq, int dma)
* 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.
- */
+ * soon after the SDK for GUS MAX is available.
+ */
if (val == 255 || val < 5)
{
@@ -2902,68 +3009,31 @@ gus_wave_init (long mem_start, int irq, int dma)
model_num = "MAX";
gus_type = 0x40;
mixer_type = CS4231;
-#ifndef EXCLUDE_GUSMAX
- {
- unsigned char max_config = 0x40; /* Codec enable */
-
- if (dma > 3)
- max_config |= 0x30; /* 16 bit playback and capture DMAs */
-
- max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
-
- OUTB (max_config, gus_base + 0x106); /* UltraMax control */
- }
-
- if (ad1848_detect (gus_base + 0x10c))
- {
- gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
- gus_wave_volume = 90;
- have_gus_max = 1;
- ad1848_init ("gusmax0: <GUS MAX>", gus_base + 0x10c,
- -irq,
- dma,
- dma);
- }
- else
- printk ("[Where's the CS4231?]");
-#endif
}
}
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.
- */
+ * 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 ("gus0: <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024);
-#else /* __FreeBSD__ */
+#if defined(__FreeBSD__)
+ printk ("gus0: <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 /* __FreeBSD__ */
-
-#ifndef SCO
- sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
#endif
- if (irq < 0 || irq > 15)
- {
- printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
- return mem_start;
- }
-
- if (dma < 0 || dma > 7)
- {
- printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma);
- return mem_start;
- }
+ sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
gus_irq = irq;
gus_dma = dma;
+ gus_dma_read = dma_read;
if (num_synths >= MAX_SYNTH_DEV)
printk ("GUS Error: Too many synthesizers\n");
@@ -2984,21 +3054,36 @@ gus_wave_init (long mem_start, int irq, int dma)
{
audio_devs[gus_devnum = num_audiodevs++] = &gus_sampling_operations;
audio_devs[gus_devnum]->dmachan = dma;
-#ifndef NO_AUTODMA
audio_devs[gus_devnum]->buffcount = 1;
-#else
- audio_devs[gus_devnum]->flags &= ~DMA_AUTOMODE;
- audio_devs[gus_devnum]->buffcount = DSP_BUFFCOUNT;
-#endif
audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
+ gus_dspnum = gus_devnum;
+ gus_busy[gus_devnum] = 0;
+ gus_busy[gus_dspnum] = 0;
}
else
printk ("GUS: Too many PCM devices available\n");
- /*
- * Mixer dependent initialization.
- */
+ if (num_audiodevs < MAX_AUDIO_DEV)
+ {
+ if(dma_read && dma != dma_read)
+ {
+ audio_devs[gus_dspnum = num_audiodevs++]= &gus_sampling_operations_read;
+ audio_devs[gus_dspnum]->dmachan = gus_dma_read;
+ audio_devs[gus_dspnum]->buffcount = 1;
+ audio_devs[gus_dspnum]->buffsize = DSP_BUFFSIZE;
+ gus_busy[gus_dspnum] = 0;
+ }
+ else
+ {
+ gus_dspnum = gus_devnum;
+ }
+ }
+ else
+ printk ("GUS READ: Too many PCM devices available\n");
+ /*
+ * Mixer dependent initialization.
+ */
switch (mixer_type)
{
case ICS2101:
@@ -3008,11 +3093,37 @@ gus_wave_init (long mem_start, int irq, int dma)
case CS4231:
/* Initialized elsewhere (ad1848.c) */
+#ifndef EXCLUDE_GUSMAX
+ {
+ unsigned char max_config = 0x40; /* Codec enable */
+ long mixer_init_return;
+
+ if (dma > 3)
+ max_config |= 0x30; /* 16 bit playback and capture DMAs */
+
+ max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
+
+ OUTB (max_config, gus_base + 0x106); /* UltraMax control */
+ mixer_init_return = gus_default_mixer_init(mem_start);
+
+ if (ad1848_detect (gus_base + 0x10c))
+ {
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+ have_gus_max = 1;
+ ad1848_init ("GUS MAX", gus_base + 0x10c,
+ -irq,
+ dma_read, /* read write reversed */
+ dma);
+ }
+ else
+ printk ("[Where's the CS4231?]");
+ return mixer_init_return;
+ }
+#endif
default:
return gus_default_mixer_init (mem_start);
}
-
- return mem_start;
}
static void
@@ -3031,6 +3142,9 @@ do_loop_irq (int voice)
*/
gus_write8 (0x00, tmp);
+ if (tmp & 0x03) /* Voice stopped */
+ voice_alloc->map[voice] = 0;
+
mode = voices[voice].loop_irq_mode;
voices[voice].loop_irq_mode = 0;
parm = voices[voice].loop_irq_parm;
@@ -3042,9 +3156,9 @@ do_loop_irq (int voice)
* Final loop finished, shoot volume down
*/
- if ((int) (gus_read16 (0x09) >> 4) < 100) /*
- * Get current volume
- */
+ if ((int) (gus_read16 (0x09) >> 4) < 100) /*
+ * Get current volume
+ */
{
gus_voice_off ();
gus_rampoff ();
@@ -3065,26 +3179,29 @@ do_loop_irq (int voice)
pcm_active = 0; /* Signal to the play_next_pcm_block routine */
case LMODE_PCM:
{
- int orig_qlen = pcm_qlen;
int flag; /* 0 or 2 */
pcm_qlen--;
pcm_head = (pcm_head + 1) % pcm_nblk;
- if (pcm_qlen)
+ if (pcm_qlen && pcm_active)
{
play_next_pcm_block ();
}
else
{ /* Underrun. Just stop the voice */
+ gus_select_voice (0); /* Left channel */
+ gus_voice_off ();
+ gus_rampoff ();
+ gus_select_voice (1); /* Right channel */
gus_voice_off ();
gus_rampoff ();
pcm_active = 0;
}
-/*
- * If the queue was full before this interrupt, the DMA transfer was
- * suspended. Let it continue now.
- */
+ /*
+ * If the queue was full before this interrupt, the DMA transfer was
+ * suspended. Let it continue now.
+ */
if (dma_active)
{
if (pcm_qlen == 0)
@@ -3187,9 +3304,9 @@ gus_voice_irq (void)
* Wave IRQ pending
*/
if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /*
- * Not done
- * yet
- */
+ * Not done
+ * yet
+ */
{
wave_ignore |= voice_bit;
do_loop_irq (voice);
@@ -3199,9 +3316,9 @@ gus_voice_irq (void)
* Volume IRQ pending
*/
if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /*
- * Not done
- * yet
- */
+ * Not done
+ * yet
+ */
{
volume_ignore |= voice_bit;
do_volume_irq (voice);
@@ -3251,7 +3368,10 @@ guswave_dma_irq (void)
* Sampling Irq pending
*/
{
- DMAbuf_inputintr (gus_devnum);
+ if (gus_dma_read && gus_dma_read != gus_dma)
+ DMAbuf_inputintr (gus_dspnum);
+ else
+ DMAbuf_inputintr (gus_devnum);
}
}
OpenPOWER on IntegriCloud