From 230e5ab6a084ed50470f101934782dbf54b0d06b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 6 Dec 1997 23:51:34 +0000 Subject: Merge with Linux 2.1.67. --- drivers/sound/gus_wave.c | 5672 +++++++++++++++++++++++----------------------- 1 file changed, 2806 insertions(+), 2866 deletions(-) (limited to 'drivers/sound/gus_wave.c') diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c index 8c1523750..2814ffe12 100644 --- a/drivers/sound/gus_wave.c +++ b/drivers/sound/gus_wave.c @@ -19,7 +19,7 @@ #include #include "gus_hw.h" -#if defined(CONFIG_GUSHW) +#if defined(CONFIG_GUSHW) || defined(MODULE) #define GUS_BANK_SIZE (((iw_mode) ? 256*1024*1024 : 256*1024)) @@ -30,38 +30,39 @@ struct voice_info { - unsigned long orig_freq; - unsigned long current_freq; - unsigned long mode; - int fixed_pitch; - int bender; - int bender_range; - int panning; - int midi_volume; - unsigned int initial_volume; - unsigned int current_volume; - int loop_irq_mode, loop_irq_parm; + unsigned long orig_freq; + unsigned long current_freq; + unsigned long mode; + int fixed_pitch; + int bender; + int bender_range; + int panning; + int midi_volume; + unsigned int initial_volume; + unsigned int current_volume; + int loop_irq_mode, loop_irq_parm; #define LMODE_FINISH 1 #define LMODE_PCM 2 #define LMODE_PCM_STOP 3 - int volume_irq_mode, volume_irq_parm; + int volume_irq_mode, volume_irq_parm; #define VMODE_HALT 1 #define VMODE_ENVELOPE 2 #define VMODE_START_NOTE 3 - int env_phase; - unsigned char env_rate[6]; - unsigned char env_offset[6]; + int env_phase; + unsigned char env_rate[6]; + unsigned char env_offset[6]; - /* - * Volume computation parameters for gus_adagio_vol() - */ - int main_vol, expression_vol, patch_vol; + /* + * Volume computation parameters for gus_adagio_vol() + */ + int main_vol, expression_vol, patch_vol; - /* Variables for "Ultraclick" removal */ - int dev_pending, note_pending, volume_pending, sample_pending; - char kill_pending; - long offset_pending; + /* Variables for "Ultraclick" removal */ + int dev_pending, note_pending, volume_pending, + sample_pending; + char kill_pending; + long offset_pending; }; @@ -73,7 +74,6 @@ extern int gus_pnp_flag; static int gus_dma2 = -1; static int dual_dma_mode = 0; static long gus_mem_size = 0; -static long gus_rom_size = 0; static long free_mem_ptr = 0; static int gus_busy = 0; static int gus_no_dma = 0; @@ -137,26 +137,26 @@ static struct voice_info voices[32]; static int freq_div_table[] = { - 44100, - 44100, /* 14 */ - 41160, /* 15 */ - 38587, /* 16 */ - 36317, /* 17 */ - 34300, /* 18 */ - 32494, /* 19 */ - 30870, /* 20 */ - 29400, /* 21 */ - 28063, /* 22 */ - 26843, /* 23 */ - 25725, /* 24 */ - 24696, /* 25 */ - 23746, /* 26 */ - 22866, /* 27 */ - 22050, /* 28 */ - 21289, /* 29 */ - 20580, /* 30 */ - 19916, /* 31 */ - 19293 /* 32 */ + 44100, + 44100, /* 14 */ + 41160, /* 15 */ + 38587, /* 16 */ + 36317, /* 17 */ + 34300, /* 18 */ + 32494, /* 19 */ + 30870, /* 20 */ + 29400, /* 21 */ + 28063, /* 22 */ + 26843, /* 23 */ + 25725, /* 24 */ + 24696, /* 25 */ + 23746, /* 26 */ + 22866, /* 27 */ + 22050, /* 28 */ + 21289, /* 29 */ + 20580, /* 30 */ + 19916, /* 31 */ + 19293 /* 32 */ }; static struct patch_info *samples; @@ -172,720 +172,711 @@ static int patch_map[32]; static struct synth_info gus_info = {"Gravis UltraSound", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH}; -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); -static void gus_tmr_install (int io_base); +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); +static void gus_tmr_install(int io_base); #define INSTANT_RAMP -1 /* Instant change. No ramping */ #define FAST_RAMP 0 /* Fastest possible ramp */ static void -reset_sample_memory (void) +reset_sample_memory(void) { - int i; + int i; - for (i = 0; i <= MAX_SAMPLE; i++) - sample_ptrs[i] = -1; - for (i = 0; i < 32; i++) - sample_map[i] = -1; - for (i = 0; i < 32; i++) - patch_map[i] = -1; + for (i = 0; i <= MAX_SAMPLE; i++) + sample_ptrs[i] = -1; + for (i = 0; i < 32; i++) + sample_map[i] = -1; + for (i = 0; i < 32; i++) + patch_map[i] = -1; - gus_poke (0, 0); /* Put a silent sample to the beginning */ - gus_poke (1, 0); - free_mem_ptr = 2; + gus_poke(0, 0); /* Put a silent sample to the beginning */ + gus_poke(1, 0); + free_mem_ptr = 2; - free_sample = 0; + free_sample = 0; - for (i = 0; i < MAX_PATCH; i++) - patch_table[i] = NOT_SAMPLE; + for (i = 0; i < MAX_PATCH; i++) + patch_table[i] = NOT_SAMPLE; } void -gus_delay (void) +gus_delay(void) { - int i; + int i; - for (i = 0; i < 7; i++) - inb (u_DRAMIO); + for (i = 0; i < 7; i++) + inb(u_DRAMIO); } static void -gus_poke (long addr, unsigned char data) +gus_poke(long addr, unsigned char data) { /* Writes a byte to the DRAM */ - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli (); - outb ((0x43), u_Command); - outb ((addr & 0xff), u_DataLo); - outb (((addr >> 8) & 0xff), u_DataHi); + save_flags(flags); + cli(); + outb((0x43), u_Command); + outb((addr & 0xff), u_DataLo); + outb(((addr >> 8) & 0xff), u_DataHi); - outb ((0x44), u_Command); - outb (((addr >> 16) & 0xff), u_DataHi); - outb ((data), u_DRAMIO); - restore_flags (flags); + outb((0x44), u_Command); + outb(((addr >> 16) & 0xff), u_DataHi); + outb((data), u_DRAMIO); + restore_flags(flags); } static unsigned char -gus_peek (long addr) +gus_peek(long addr) { /* Reads a byte from the DRAM */ - unsigned long flags; - unsigned char tmp; + unsigned long flags; + unsigned char tmp; - save_flags (flags); - cli (); - outb ((0x43), u_Command); - outb ((addr & 0xff), u_DataLo); - outb (((addr >> 8) & 0xff), u_DataHi); + save_flags(flags); + cli(); + outb((0x43), u_Command); + outb((addr & 0xff), u_DataLo); + outb(((addr >> 8) & 0xff), u_DataHi); - outb ((0x44), u_Command); - outb (((addr >> 16) & 0xff), u_DataHi); - tmp = inb (u_DRAMIO); - restore_flags (flags); + outb((0x44), u_Command); + outb(((addr >> 16) & 0xff), u_DataHi); + tmp = inb(u_DRAMIO); + restore_flags(flags); - return tmp; + return tmp; } void -gus_write8 (int reg, unsigned int data) +gus_write8(int reg, unsigned int data) { /* Writes to an indirect register (8 bit) */ - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli (); + save_flags(flags); + cli(); - outb ((reg), u_Command); - outb (((unsigned char) (data & 0xff)), u_DataHi); + outb((reg), u_Command); + outb(((unsigned char) (data & 0xff)), u_DataHi); - restore_flags (flags); + restore_flags(flags); } static unsigned char -gus_read8 (int reg) +gus_read8(int reg) { /* Reads from an indirect register (8 bit). Offset 0x80. */ - unsigned long flags; - unsigned char val; + unsigned long flags; + unsigned char val; - save_flags (flags); - cli (); - outb ((reg | 0x80), u_Command); - val = inb (u_DataHi); - restore_flags (flags); + save_flags(flags); + cli(); + outb((reg | 0x80), u_Command); + val = inb(u_DataHi); + restore_flags(flags); - return val; + return val; } static unsigned char -gus_look8 (int reg) +gus_look8(int reg) { /* Reads from an indirect register (8 bit). No additional offset. */ - unsigned long flags; - unsigned char val; + unsigned long flags; + unsigned char val; - save_flags (flags); - cli (); - outb ((reg), u_Command); - val = inb (u_DataHi); - restore_flags (flags); + save_flags(flags); + cli(); + outb((reg), u_Command); + val = inb(u_DataHi); + restore_flags(flags); - return val; + return val; } static void -gus_write16 (int reg, unsigned int data) +gus_write16(int reg, unsigned int data) { /* Writes to an indirect register (16 bit) */ - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli (); + save_flags(flags); + cli(); - outb ((reg), u_Command); + outb((reg), u_Command); - outb (((unsigned char) (data & 0xff)), u_DataLo); - outb (((unsigned char) ((data >> 8) & 0xff)), u_DataHi); + outb(((unsigned char) (data & 0xff)), u_DataLo); + outb(((unsigned char) ((data >> 8) & 0xff)), u_DataHi); - restore_flags (flags); + restore_flags(flags); } static unsigned short -gus_read16 (int reg) +gus_read16(int reg) { /* Reads from an indirect register (16 bit). Offset 0x80. */ - unsigned long flags; - unsigned char hi, lo; + unsigned long flags; + unsigned char hi, lo; - save_flags (flags); - cli (); + save_flags(flags); + cli(); - outb ((reg | 0x80), u_Command); + outb((reg | 0x80), u_Command); - lo = inb (u_DataLo); - hi = inb (u_DataHi); + lo = inb(u_DataLo); + hi = inb(u_DataHi); - restore_flags (flags); + restore_flags(flags); - return ((hi << 8) & 0xff00) | lo; + return ((hi << 8) & 0xff00) | lo; } static unsigned short -gus_look16 (int reg) +gus_look16(int reg) { /* Reads from an indirect register (16 bit). No additional offset. */ - unsigned long flags; - unsigned char hi, lo; + unsigned long flags; + unsigned char hi, lo; - save_flags (flags); - cli (); + save_flags(flags); + cli(); - outb ((reg), u_Command); + outb((reg), u_Command); - lo = inb (u_DataLo); - hi = inb (u_DataHi); + lo = inb(u_DataLo); + hi = inb(u_DataHi); - restore_flags (flags); + restore_flags(flags); - return ((hi << 8) & 0xff00) | lo; + return ((hi << 8) & 0xff00) | lo; } static void -gus_write_addr (int reg, unsigned long address, int frac, int is16bit) +gus_write_addr(int reg, unsigned long address, int frac, int is16bit) { /* Writes an 24 bit memory address */ - unsigned long hold_address; - unsigned long flags; - - save_flags (flags); - cli (); - if (is16bit) - { - if (iw_mode) - { - /* Interwave spesific address translations */ - address >>= 1; - } - else - { - /* - * Special processing required for 16 bit patches - */ + unsigned long hold_address; + unsigned long flags; - hold_address = address; - address = address >> 1; - address &= 0x0001ffffL; - address |= (hold_address & 0x000c0000L); - } - } - - gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff)); - gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff) - + (frac << 5)); - /* 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) - + (frac << 5)); - restore_flags (flags); + save_flags(flags); + cli(); + if (is16bit) + { + if (iw_mode) + { + /* Interwave spesific address translations */ + address >>= 1; + } else + { + /* + * Special processing required for 16 bit patches + */ + + hold_address = address; + address = address >> 1; + address &= 0x0001ffffL; + address |= (hold_address & 0x000c0000L); + } + } + gus_write16(reg, (unsigned short) ((address >> 7) & 0xffff)); + gus_write16(reg + 1, (unsigned short) ((address << 9) & 0xffff) + + (frac << 5)); + /* 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) + + (frac << 5)); + restore_flags(flags); } static void -gus_select_voice (int voice) +gus_select_voice(int voice) { - if (voice < 0 || voice > 31) - return; + if (voice < 0 || voice > 31) + return; - outb ((voice), u_Voice); + outb((voice), u_Voice); } static void -gus_select_max_voices (int nvoices) +gus_select_max_voices(int nvoices) { - if (iw_mode) - nvoices = 32; - if (nvoices < 14) - nvoices = 14; - if (nvoices > 32) - nvoices = 32; + if (iw_mode) + nvoices = 32; + if (nvoices < 14) + nvoices = 14; + if (nvoices > 32) + nvoices = 32; - voice_alloc->max_voice = nr_voices = nvoices; + voice_alloc->max_voice = nr_voices = nvoices; - gus_write8 (0x0e, (nvoices - 1) | 0xc0); + gus_write8(0x0e, (nvoices - 1) | 0xc0); } static void -gus_voice_on (unsigned int mode) +gus_voice_on(unsigned int mode) { - gus_write8 (0x00, (unsigned char) (mode & 0xfc)); - gus_delay (); - gus_write8 (0x00, (unsigned char) (mode & 0xfc)); + gus_write8(0x00, (unsigned char) (mode & 0xfc)); + gus_delay(); + gus_write8(0x00, (unsigned char) (mode & 0xfc)); } static void -gus_voice_off (void) +gus_voice_off(void) { - gus_write8 (0x00, gus_read8 (0x00) | 0x03); + gus_write8(0x00, gus_read8(0x00) | 0x03); } static void -gus_voice_mode (unsigned int m) +gus_voice_mode(unsigned int m) { - unsigned char mode = (unsigned char) (m & 0xff); + unsigned char mode = (unsigned char) (m & 0xff); - gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | - (mode & 0xfc)); /* Don't touch last two bits */ - gus_delay (); - gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); + gus_write8(0x00, (gus_read8(0x00) & 0x03) | + (mode & 0xfc)); /* Don't touch last two bits */ + gus_delay(); + gus_write8(0x00, (gus_read8(0x00) & 0x03) | (mode & 0xfc)); } static void -gus_voice_freq (unsigned long freq) +gus_voice_freq(unsigned long freq) { - unsigned long divisor = freq_div_table[nr_voices - 14]; - unsigned short fc; + unsigned long divisor = freq_div_table[nr_voices - 14]; + unsigned short fc; - /* Interwave plays at 44100 Hz with any number of voices */ - if (iw_mode) - fc = (unsigned short) (((freq << 9) + (44100 >> 1)) / 44100); - else - fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor); - fc = fc << 1; + /* Interwave plays at 44100 Hz with any number of voices */ + if (iw_mode) + fc = (unsigned short) (((freq << 9) + (44100 >> 1)) / 44100); + else + fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor); + fc = fc << 1; - gus_write16 (0x01, fc); + gus_write16(0x01, fc); } static void -gus_voice_volume (unsigned int vol) +gus_voice_volume(unsigned int vol) { - gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */ - gus_write16 (0x09, (unsigned short) (vol << 4)); + gus_write8(0x0d, 0x03); /* Stop ramp before setting volume */ + gus_write16(0x09, (unsigned short) (vol << 4)); } static void -gus_voice_balance (unsigned int balance) +gus_voice_balance(unsigned int balance) { - gus_write8 (0x0c, (unsigned char) (balance & 0xff)); + gus_write8(0x0c, (unsigned char) (balance & 0xff)); } static void -gus_ramp_range (unsigned int low, unsigned int high) +gus_ramp_range(unsigned int low, unsigned int high) { - gus_write8 (0x07, (unsigned char) ((low >> 4) & 0xff)); - gus_write8 (0x08, (unsigned char) ((high >> 4) & 0xff)); + gus_write8(0x07, (unsigned char) ((low >> 4) & 0xff)); + gus_write8(0x08, (unsigned char) ((high >> 4) & 0xff)); } static void -gus_ramp_rate (unsigned int scale, unsigned int rate) +gus_ramp_rate(unsigned int scale, unsigned int rate) { - gus_write8 (0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f))); + gus_write8(0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f))); } static void -gus_rampon (unsigned int m) +gus_rampon(unsigned int m) { - unsigned char mode = (unsigned char) (m & 0xff); + unsigned char mode = (unsigned char) (m & 0xff); - gus_write8 (0x0d, mode & 0xfc); - gus_delay (); - gus_write8 (0x0d, mode & 0xfc); + gus_write8(0x0d, mode & 0xfc); + gus_delay(); + gus_write8(0x0d, mode & 0xfc); } static void -gus_ramp_mode (unsigned int m) +gus_ramp_mode(unsigned int m) { - unsigned char mode = (unsigned char) (m & 0xff); + unsigned char mode = (unsigned char) (m & 0xff); - gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | - (mode & 0xfc)); /* Leave the last 2 bits alone */ - gus_delay (); - gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); + gus_write8(0x0d, (gus_read8(0x0d) & 0x03) | + (mode & 0xfc)); /* Leave the last 2 bits alone */ + gus_delay(); + gus_write8(0x0d, (gus_read8(0x0d) & 0x03) | (mode & 0xfc)); } static void -gus_rampoff (void) +gus_rampoff(void) { - gus_write8 (0x0d, 0x03); + gus_write8(0x0d, 0x03); } static void -gus_set_voice_pos (int voice, long position) +gus_set_voice_pos(int voice, long position) { - int sample_no; + int sample_no; - if ((sample_no = sample_map[voice]) != -1) - if (position < samples[sample_no].len) - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - voices[voice].offset_pending = position; - else - gus_write_addr (0x0a, sample_ptrs[sample_no] + position, 0, - samples[sample_no].mode & WAVE_16_BITS); + if ((sample_no = sample_map[voice]) != -1) + if (position < samples[sample_no].len) + if (voices[voice].volume_irq_mode == VMODE_START_NOTE) + voices[voice].offset_pending = position; + else + gus_write_addr(0x0a, sample_ptrs[sample_no] + position, 0, + samples[sample_no].mode & WAVE_16_BITS); } static void -gus_voice_init (int voice) +gus_voice_init(int voice) { - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_volume (0); - gus_voice_off (); - gus_write_addr (0x0a, 0, 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_flags (flags); + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_volume(0); + gus_voice_off(); + gus_write_addr(0x0a, 0, 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_flags(flags); } static void -gus_voice_init2 (int voice) -{ - voices[voice].panning = 0; - voices[voice].mode = 0; - voices[voice].orig_freq = 20000; - voices[voice].current_freq = 20000; - voices[voice].bender = 0; - voices[voice].bender_range = 200; - voices[voice].initial_volume = 0; - voices[voice].current_volume = 0; - voices[voice].loop_irq_mode = 0; - voices[voice].loop_irq_parm = 0; - voices[voice].volume_irq_mode = 0; - voices[voice].volume_irq_parm = 0; - voices[voice].env_phase = 0; - voices[voice].main_vol = 127; - voices[voice].patch_vol = 127; - voices[voice].expression_vol = 127; - voices[voice].sample_pending = -1; - voices[voice].fixed_pitch = 0; +gus_voice_init2(int voice) +{ + voices[voice].panning = 0; + voices[voice].mode = 0; + voices[voice].orig_freq = 20000; + voices[voice].current_freq = 20000; + voices[voice].bender = 0; + voices[voice].bender_range = 200; + voices[voice].initial_volume = 0; + voices[voice].current_volume = 0; + voices[voice].loop_irq_mode = 0; + voices[voice].loop_irq_parm = 0; + voices[voice].volume_irq_mode = 0; + voices[voice].volume_irq_parm = 0; + voices[voice].env_phase = 0; + voices[voice].main_vol = 127; + voices[voice].patch_vol = 127; + voices[voice].expression_vol = 127; + voices[voice].sample_pending = -1; + voices[voice].fixed_pitch = 0; } static void -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) - { - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_rampoff (); - restore_flags (flags); - return; - /* - * Sustain phase begins. Continue envelope after receiving note off. - */ - } - - if (voices[voice].env_phase >= 5) - { /* Envelope finished. Shoot the voice down */ - gus_voice_init (voice); - return; - } - - prev_vol = voices[voice].current_volume; - 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]; - - save_flags (flags); - cli (); - 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 */ - { - restore_flags (flags); - step_envelope (voice); /* Continue the envelope on the next step */ - return; - } - - if (vol > prev_vol) - { - if (vol >= (4096 - 64)) - vol = 4096 - 65; - gus_ramp_range (0, vol); - gus_rampon (0x20); /* Increasing volume, with IRQ */ - } - else - { - if (vol <= 64) - vol = 65; - gus_ramp_range (vol, 4030); - gus_rampon (0x60); /* Decreasing volume, with IRQ */ - } - voices[voice].current_volume = vol; - restore_flags (flags); +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) + { + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_rampoff(); + restore_flags(flags); + return; + /* + * Sustain phase begins. Continue envelope after receiving note off. + */ + } + if (voices[voice].env_phase >= 5) + { /* Envelope finished. Shoot the voice down */ + gus_voice_init(voice); + return; + } + prev_vol = voices[voice].current_volume; + 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]; + + save_flags(flags); + cli(); + 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 */ + { + restore_flags(flags); + step_envelope(voice); /* Continue the envelope on the next step */ + return; + } + if (vol > prev_vol) + { + if (vol >= (4096 - 64)) + vol = 4096 - 65; + gus_ramp_range(0, vol); + gus_rampon(0x20); /* Increasing volume, with IRQ */ + } else + { + if (vol <= 64) + vol = 65; + gus_ramp_range(vol, 4030); + gus_rampon(0x60); /* Decreasing volume, with IRQ */ + } + voices[voice].current_volume = vol; + restore_flags(flags); } static void -init_envelope (int voice) +init_envelope(int voice) { - voices[voice].env_phase = -1; - voices[voice].current_volume = 64; + voices[voice].env_phase = -1; + voices[voice].current_volume = 64; - step_envelope (voice); + step_envelope(voice); } static void -start_release (int voice, long int flags) +start_release(int voice, long int flags) { - if (gus_read8 (0x00) & 0x03) - return; /* Voice already stopped */ + if (gus_read8(0x00) & 0x03) + 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 */ + voices[voice].current_volume = + voices[voice].initial_volume = + gus_read16(0x09) >> 4; /* Get current volume */ - voices[voice].mode &= ~WAVE_SUSTAIN_ON; - gus_rampoff (); - restore_flags (flags); - step_envelope (voice); + voices[voice].mode &= ~WAVE_SUSTAIN_ON; + gus_rampoff(); + restore_flags(flags); + step_envelope(voice); } static void -gus_voice_fade (int voice) -{ - int instr_no = sample_map[voice], is16bits; - long int flags; - - save_flags (flags); - cli (); - gus_select_voice (voice); - - if (instr_no < 0 || instr_no > MAX_SAMPLE) - { - gus_write8 (0x00, 0x03); /* Hard stop */ - voice_alloc->map[voice] = 0; - restore_flags (flags); - return; - } - - is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */ - - if (voices[voice].mode & WAVE_ENVELOPES) - { - start_release (voice, flags); - return; - } - - /* - * Ramp the volume down but not too quickly. - */ - if ((int) (gus_read16 (0x09) >> 4) < 100) /* Get current volume */ - { - gus_voice_off (); - gus_rampoff (); - gus_voice_init (voice); - return; - } - - gus_ramp_range (65, 4030); - gus_ramp_rate (2, 4); - gus_rampon (0x40 | 0x20); /* Down, once, with IRQ */ - voices[voice].volume_irq_mode = VMODE_HALT; - restore_flags (flags); +gus_voice_fade(int voice) +{ + int instr_no = sample_map[voice], is16bits; + long int flags; + + save_flags(flags); + cli(); + gus_select_voice(voice); + + if (instr_no < 0 || instr_no > MAX_SAMPLE) + { + gus_write8(0x00, 0x03); /* Hard stop */ + voice_alloc->map[voice] = 0; + restore_flags(flags); + return; + } + is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */ + + if (voices[voice].mode & WAVE_ENVELOPES) + { + start_release(voice, flags); + restore_flags(flags); + return; + } + /* + * Ramp the volume down but not too quickly. + */ + if ((int) (gus_read16(0x09) >> 4) < 100) /* Get current volume */ + { + gus_voice_off(); + gus_rampoff(); + gus_voice_init(voice); + restore_flags(flags); + return; + } + gus_ramp_range(65, 4030); + gus_ramp_rate(2, 4); + gus_rampon(0x40 | 0x20); /* Down, once, with IRQ */ + voices[voice].volume_irq_mode = VMODE_HALT; + restore_flags(flags); } static void -gus_reset (void) +gus_reset(void) { - int i; + int i; - gus_select_max_voices (24); - volume_base = 3071; - volume_scale = 4; - volume_method = VOL_METHOD_ADAGIO; + gus_select_max_voices(24); + volume_base = 3071; + volume_scale = 4; + volume_method = VOL_METHOD_ADAGIO; - for (i = 0; i < 32; i++) - { - gus_voice_init (i); /* Turn voice off */ - gus_voice_init2 (i); - } + for (i = 0; i < 32; i++) + { + gus_voice_init(i); /* Turn voice off */ + gus_voice_init2(i); + } } static void -gus_initialize (void) +gus_initialize(void) { - unsigned long flags; - unsigned char dma_image, irq_image, tmp; + unsigned long flags; + unsigned char dma_image, irq_image, tmp; + + static unsigned char gus_irq_map[16] = + {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7}; - static unsigned char gus_irq_map[16] = - {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}; + static unsigned char gus_dma_map[8] = + {0, 1, 0, 2, 0, 3, 4, 5}; - save_flags (flags); - cli (); - gus_write8 (0x4c, 0); /* Reset GF1 */ - gus_delay (); - gus_delay (); + save_flags(flags); + cli(); + gus_write8(0x4c, 0); /* Reset GF1 */ + gus_delay(); + gus_delay(); - gus_write8 (0x4c, 1); /* Release Reset */ - gus_delay (); - gus_delay (); + gus_write8(0x4c, 1); /* Release Reset */ + gus_delay(); + gus_delay(); - /* - * Clear all interrupts - */ + /* + * Clear all interrupts + */ - gus_write8 (0x41, 0); /* DMA control */ - gus_write8 (0x45, 0); /* Timer control */ - gus_write8 (0x49, 0); /* Sample control */ + gus_write8(0x41, 0); /* DMA control */ + gus_write8(0x45, 0); /* Timer control */ + gus_write8(0x49, 0); /* Sample control */ - gus_select_max_voices (24); + gus_select_max_voices(24); - inb (u_Status); /* Touch the status register */ + inb(u_Status); /* Touch the status register */ - gus_look8 (0x41); /* Clear any pending DMA IRQs */ - gus_look8 (0x49); /* Clear any pending sample IRQs */ - gus_read8 (0x0f); /* Clear pending IRQs */ + gus_look8(0x41); /* Clear any pending DMA IRQs */ + gus_look8(0x49); /* Clear any pending sample IRQs */ + gus_read8(0x0f); /* Clear pending IRQs */ - gus_reset (); /* Resets all voices */ + gus_reset(); /* Resets all voices */ - gus_look8 (0x41); /* Clear any pending DMA IRQs */ - gus_look8 (0x49); /* Clear any pending sample IRQs */ - gus_read8 (0x0f); /* Clear pending IRQs */ + gus_look8(0x41); /* Clear any pending DMA IRQs */ + gus_look8(0x49); /* Clear any pending sample IRQs */ + gus_read8(0x0f); /* Clear pending IRQs */ - gus_write8 (0x4c, 7); /* Master reset | DAC enable | IRQ enable */ + gus_write8(0x4c, 7); /* Master reset | DAC enable | IRQ enable */ - /* - * Set up for Digital ASIC - */ + /* + * Set up for Digital ASIC + */ - outb ((0x05), gus_base + 0x0f); + outb((0x05), gus_base + 0x0f); - mix_image |= 0x02; /* Disable line out (for a moment) */ - outb ((mix_image), u_Mixer); + mix_image |= 0x02; /* Disable line out (for a moment) */ + outb((mix_image), u_Mixer); - outb ((0x00), u_IRQDMAControl); + outb((0x00), u_IRQDMAControl); - outb ((0x00), gus_base + 0x0f); + 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. - */ + /* + * 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. + */ - irq_image = 0; - tmp = gus_irq_map[gus_irq]; - if (!gus_pnp_flag && !tmp) - printk ("Warning! GUS IRQ not selected\n"); - irq_image |= tmp; - irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */ + irq_image = 0; + tmp = gus_irq_map[gus_irq]; + if (!gus_pnp_flag && !tmp) + printk("Warning! GUS IRQ not selected\n"); + irq_image |= tmp; + irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */ - dual_dma_mode = 1; - if (gus_dma2 == gus_dma || gus_dma2 == -1) - { - dual_dma_mode = 0; - dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */ + dual_dma_mode = 1; + if (gus_dma2 == gus_dma || gus_dma2 == -1) + { + dual_dma_mode = 0; + dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */ - tmp = gus_dma_map[gus_dma]; - if (!tmp) - printk ("Warning! GUS DMA not selected\n"); + tmp = gus_dma_map[gus_dma]; + if (!tmp) + printk("Warning! GUS DMA not selected\n"); - dma_image |= tmp; - } - else - /* Setup dual DMA channel mode for GUS MAX */ - { - dma_image = gus_dma_map[gus_dma]; - if (!dma_image) - printk ("Warning! GUS DMA not selected\n"); + dma_image |= tmp; + } else + /* Setup dual DMA channel mode for GUS MAX */ + { + dma_image = gus_dma_map[gus_dma]; + if (!dma_image) + printk("Warning! GUS DMA not selected\n"); + + tmp = gus_dma_map[gus_dma2] << 3; + if (!tmp) + { + printk("Warning! Invalid GUS MAX DMA\n"); + tmp = 0x40; /* Combine DMA channels */ + dual_dma_mode = 0; + } + dma_image |= tmp; + } - tmp = gus_dma_map[gus_dma2] << 3; - if (!tmp) - { - printk ("Warning! Invalid GUS MAX DMA\n"); - tmp = 0x40; /* Combine DMA channels */ - dual_dma_mode = 0; - } + /* + * For some reason the IRQ and DMA addresses must be written twice + */ - dma_image |= tmp; - } + /* + * Doing it first time + */ - /* - * For some reason the IRQ and DMA addresses must be written twice - */ - - /* - * Doing it first time - */ - - outb ((mix_image), u_Mixer); /* Select DMA control */ - outb ((dma_image | 0x80), u_IRQDMAControl); /* Set DMA address */ + outb((mix_image), u_Mixer); /* Select DMA control */ + outb((dma_image | 0x80), u_IRQDMAControl); /* Set DMA address */ - outb ((mix_image | 0x40), u_Mixer); /* Select IRQ control */ - outb ((irq_image), u_IRQDMAControl); /* Set IRQ address */ + outb((mix_image | 0x40), u_Mixer); /* Select IRQ control */ + outb((irq_image), u_IRQDMAControl); /* Set IRQ address */ - /* - * Doing it second time - */ + /* + * Doing it second time + */ - outb ((mix_image), u_Mixer); /* Select DMA control */ - outb ((dma_image), u_IRQDMAControl); /* Set DMA address */ + outb((mix_image), u_Mixer); /* Select DMA control */ + outb((dma_image), u_IRQDMAControl); /* Set DMA address */ - outb ((mix_image | 0x40), u_Mixer); /* Select IRQ control */ - outb ((irq_image), u_IRQDMAControl); /* Set IRQ address */ + outb((mix_image | 0x40), u_Mixer); /* Select IRQ control */ + outb((irq_image), u_IRQDMAControl); /* Set IRQ address */ - gus_select_voice (0); /* This disables writes to IRQ/DMA reg */ + gus_select_voice(0); /* This disables writes to IRQ/DMA reg */ - mix_image &= ~0x02; /* Enable line out */ - mix_image |= 0x08; /* Enable IRQ */ - outb ((mix_image), u_Mixer); /* - * Turn mixer channels on - * Note! Mic in is left off. - */ + mix_image &= ~0x02; /* Enable line out */ + mix_image |= 0x08; /* Enable IRQ */ + outb((mix_image), u_Mixer); /* + * Turn mixer channels on + * Note! Mic in is left off. + */ - gus_select_voice (0); /* This disables writes to IRQ/DMA reg */ + gus_select_voice(0); /* This disables writes to IRQ/DMA reg */ - gusintr (gus_irq, NULL, NULL); /* Serve pending interrupts */ + gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */ - inb (u_Status); /* Touch the status register */ + inb(u_Status); /* Touch the status register */ - gus_look8 (0x41); /* Clear any pending DMA IRQs */ - gus_look8 (0x49); /* Clear any pending sample IRQs */ + gus_look8(0x41); /* Clear any pending DMA IRQs */ + gus_look8(0x49); /* Clear any pending sample IRQs */ - gus_read8 (0x0f); /* Clear pending IRQs */ + gus_read8(0x0f); /* Clear pending IRQs */ - if (iw_mode) - gus_write8 (0x19, gus_read8 (0x19) | 0x01); - restore_flags (flags); + if (iw_mode) + gus_write8(0x19, gus_read8(0x19) | 0x01); + restore_flags(flags); } static void -pnp_mem_init (void) +pnp_mem_init(void) { #include "iwmem.h" #define CHUNK_SIZE (256*1024) #define BANK_SIZE (4*1024*1024) #define CHUNKS_PER_BANK (BANK_SIZE/CHUNK_SIZE) - int bank, chunk, addr, total = 0; - int bank_sizes[4]; - int i, j, bits = -1, nbanks = 0; + int bank, chunk, addr, total = 0; + int bank_sizes[4]; + int i, j, bits = -1, nbanks = 0; /* * This routine determines what kind of RAM is installed in each of the four @@ -895,68 +886,68 @@ pnp_mem_init (void) /* * Place the chip into enhanced mode */ - gus_write8 (0x19, gus_read8 (0x19) | 0x01); - gus_write8 (0x53, gus_look8 (0x53) & ~0x02); /* Select DRAM I/O access */ + gus_write8(0x19, gus_read8(0x19) | 0x01); + gus_write8(0x53, gus_look8(0x53) & ~0x02); /* Select DRAM I/O access */ /* * Set memory configuration to 4 DRAM banks of 4M in each (16M total). */ - gus_write16 (0x52, (gus_look16 (0x52) & 0xfff0) | 0x000c); + gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | 0x000c); /* * Perform the DRAM size detection for each bank individually. */ - for (bank = 0; bank < 4; bank++) - { - int size = 0; - - addr = bank * BANK_SIZE; - - /* Clean check points of each chunk */ - for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++) - { - gus_poke (addr + chunk * CHUNK_SIZE + 0L, 0x00); - gus_poke (addr + chunk * CHUNK_SIZE + 1L, 0x00); - } - - /* Write a value to each chunk point and verify the result */ - for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++) - { - gus_poke (addr + chunk * CHUNK_SIZE + 0L, 0x55); - gus_poke (addr + chunk * CHUNK_SIZE + 1L, 0xAA); - - if (gus_peek (addr + chunk * CHUNK_SIZE + 0L) == 0x55 && - gus_peek (addr + chunk * CHUNK_SIZE + 1L) == 0xAA) - { /* OK. There is RAM. Now check for possible shadows */ - int ok = 1, chunk2; - - for (chunk2 = 0; ok && chunk2 < chunk; chunk2++) - if (gus_peek (addr + chunk2 * CHUNK_SIZE + 0L) || - gus_peek (addr + chunk2 * CHUNK_SIZE + 1L)) - ok = 0; /* Addressing wraps */ - - if (ok) - size = (chunk + 1) * CHUNK_SIZE; - } - gus_poke (addr + chunk * CHUNK_SIZE + 0L, 0x00); - gus_poke (addr + chunk * CHUNK_SIZE + 1L, 0x00); - } - - bank_sizes[bank] = size; - if (size) - nbanks = bank + 1; - DDB (printk ("Interwave: Bank %d, size=%dk\n", bank, size / 1024)); - } - - if (nbanks == 0) /* No RAM - Give up */ - { - printk ("Sound: An Interwave audio chip detected but no DRAM\n"); - printk ("Sound: Unable to work with this card.\n"); - gus_write8 (0x19, gus_read8 (0x19) & ~0x01); - gus_mem_size = 0; - return; - } + for (bank = 0; bank < 4; bank++) + { + int size = 0; + + addr = bank * BANK_SIZE; + + /* Clean check points of each chunk */ + for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++) + { + gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00); + gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00); + } + + /* Write a value to each chunk point and verify the result */ + for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++) + { + gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x55); + gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0xAA); + + if (gus_peek(addr + chunk * CHUNK_SIZE + 0L) == 0x55 && + gus_peek(addr + chunk * CHUNK_SIZE + 1L) == 0xAA) + { /* OK. There is RAM. Now check for possible shadows */ + int ok = 1, chunk2; + + for (chunk2 = 0; ok && chunk2 < chunk; chunk2++) + if (gus_peek(addr + chunk2 * CHUNK_SIZE + 0L) || + gus_peek(addr + chunk2 * CHUNK_SIZE + 1L)) + ok = 0; /* Addressing wraps */ + + if (ok) + size = (chunk + 1) * CHUNK_SIZE; + } + gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00); + gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00); + } + + bank_sizes[bank] = size; + if (size) + nbanks = bank + 1; + DDB(printk("Interwave: Bank %d, size=%dk\n", bank, size / 1024)); + } + + if (nbanks == 0) /* No RAM - Give up */ + { + printk("Sound: An Interwave audio chip detected but no DRAM\n"); + printk("Sound: Unable to work with this card.\n"); + gus_write8(0x19, gus_read8(0x19) & ~0x01); + gus_mem_size = 0; + return; + } /* * Now we know how much DRAM there is in each bank. The next step is * to find a DRAM size encoding (0 to 12) which is best for the combination @@ -966,668 +957,640 @@ pnp_mem_init (void) * of memory we have. */ - for (i = 0; bits == -1 && i < 13; i++) - { - bits = i; + for (i = 0; bits == -1 && i < 13; i++) + { + bits = i; - for (j = 0; bits != -1 && j < 4; j++) - if (mem_decode[i][j] != bank_sizes[j]) - bits = -1; /* No hit */ - } + for (j = 0; bits != -1 && j < 4; j++) + if (mem_decode[i][j] != bank_sizes[j]) + bits = -1; /* No hit */ + } /* * If necessary, try to find a combination where other than the last * bank matches our configuration and the last bank is left oversized. * In this way we don't leave holes in the middle of memory. */ - if (bits == -1) /* No luck yet */ - for (i = 0; bits == -1 && i < 13; i++) - { - bits = i; - - for (j = 0; bits != -1 && j < nbanks - 1; j++) - if (mem_decode[i][j] != bank_sizes[j]) - bits = -1; /* No hit */ - if (mem_decode[i][nbanks - 1] < bank_sizes[nbanks - 1]) - bits = -1; /* The last bank is too small */ - } - + if (bits == -1) /* No luck yet */ + for (i = 0; bits == -1 && i < 13; i++) + { + bits = i; + + for (j = 0; bits != -1 && j < nbanks - 1; j++) + if (mem_decode[i][j] != bank_sizes[j]) + bits = -1; /* No hit */ + if (mem_decode[i][nbanks - 1] < bank_sizes[nbanks - 1]) + bits = -1; /* The last bank is too small */ + } /* * The last resort is to search for a combination where the last bank is * smaller than the actual SIMM. This leaves some memory in the last bank * unused but doesn't leave holes in the DRAM address space. */ - if (bits == -1) /* No luck yet */ - { - for (i = 0; bits == -1 && i < 13; i++) - { - bits = i; - - for (j = 0; bits != -1 && j < nbanks - 1; j++) - if (mem_decode[i][j] != bank_sizes[j]) - bits = -1; /* No hit */ - } - - if (bits != -1) - { - printk ("Interwave: Can't use all installed RAM.\n"); - printk ("Interwave: Try reordering SIMMS.\n"); - } - } - - if (bits == -1) - { - printk ("Interwave: Can't find working DRAM encoding.\n"); - printk ("Interwave: Defaulting to 256k. Try reordering SIMMS.\n"); - bits = 0; - } - - DDB (printk ("Interwave: Selecting DRAM addressing mode %d\n", bits)); - - for (bank = 0; bank < 4; bank++) - { - DDB (printk (" Bank %d, mem=%dk (limit %dk)\n", - bank, bank_sizes[bank] / 1024, - mem_decode[bits][bank] / 1024)); - - if (bank_sizes[bank] > mem_decode[bits][bank]) - total += mem_decode[bits][bank]; - else - total += bank_sizes[bank]; - } - - DDB (printk ("Total %dk of DRAM (enhanced mode)\n", total / 1024)); + if (bits == -1) /* No luck yet */ + { + for (i = 0; bits == -1 && i < 13; i++) + { + bits = i; + + for (j = 0; bits != -1 && j < nbanks - 1; j++) + if (mem_decode[i][j] != bank_sizes[j]) + bits = -1; /* No hit */ + } + + if (bits != -1) + { + printk("Interwave: Can't use all installed RAM.\n"); + printk("Interwave: Try reordering SIMMS.\n"); + } + } + if (bits == -1) + { + printk("Interwave: Can't find working DRAM encoding.\n"); + printk("Interwave: Defaulting to 256k. Try reordering SIMMS.\n"); + bits = 0; + } + DDB(printk("Interwave: Selecting DRAM addressing mode %d\n", bits)); + + for (bank = 0; bank < 4; bank++) + { + DDB(printk(" Bank %d, mem=%dk (limit %dk)\n", bank, bank_sizes[bank] / 1024, mem_decode[bits][bank] / 1024)); + + if (bank_sizes[bank] > mem_decode[bits][bank]) + total += mem_decode[bits][bank]; + else + total += bank_sizes[bank]; + } + + DDB(printk("Total %dk of DRAM (enhanced mode)\n", total / 1024)); /* * Set the memory addressing mode. */ - gus_write16 (0x52, (gus_look16 (0x52) & 0xfff0) | bits); + gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | bits); /* Leave the chip into enhanced mode. Disable LFO */ - gus_mem_size = total; - iw_mode = 1; - gus_write8 (0x19, (gus_read8 (0x19) | 0x01) & ~0x02); + gus_mem_size = total; + iw_mode = 1; + gus_write8(0x19, (gus_read8(0x19) | 0x01) & ~0x02); } int -gus_wave_detect (int baseaddr) +gus_wave_detect(int baseaddr) { - unsigned long i, max_mem = 1024L; - unsigned long loc; - unsigned char val; + unsigned long i, max_mem = 1024L; + unsigned long loc; + unsigned char val; - gus_base = baseaddr; + gus_base = baseaddr; - gus_write8 (0x4c, 0); /* Reset GF1 */ - gus_delay (); - gus_delay (); + gus_write8(0x4c, 0); /* Reset GF1 */ + gus_delay(); + gus_delay(); - gus_write8 (0x4c, 1); /* Release Reset */ - gus_delay (); - gus_delay (); + gus_write8(0x4c, 1); /* Release Reset */ + gus_delay(); + gus_delay(); #ifdef GUSPNP_AUTODETECT - val = gus_look8 (0x5b); /* Version number register */ - gus_write8 (0x5b, ~val); /* Invert all bits */ - - if ((gus_look8 (0x5b) & 0xf0) == (val & 0xf0)) /* No change */ - if ((gus_look8 (0x5b) & 0x0f) == ((~val) & 0x0f)) /* Change */ - { - DDB (printk ("Interwave chip version %d detected\n", (val & 0xf0) >> 4)); - gus_pnp_flag = 1; - } - else - { - DDB (printk ("Not an Interwave chip (%x)\n", gus_look8 (0x5b))); - gus_pnp_flag = 0; - } - gus_write8 (0x5b, val); /* Restore all bits */ + val = gus_look8(0x5b); /* Version number register */ + gus_write8(0x5b, ~val); /* Invert all bits */ + + if ((gus_look8(0x5b) & 0xf0) == (val & 0xf0)) /* No change */ + if ((gus_look8(0x5b) & 0x0f) == ((~val) & 0x0f)) /* Change */ + { + DDB(printk("Interwave chip version %d detected\n", (val & 0xf0) >> 4)); + gus_pnp_flag = 1; + } else + { + DDB(printk("Not an Interwave chip (%x)\n", gus_look8(0x5b))); + gus_pnp_flag = 0; + } + gus_write8(0x5b, val); /* Restore all bits */ #endif - if (gus_pnp_flag) - pnp_mem_init (); - if (iw_mode) - return 1; - - /* See if there is first block there.... */ - gus_poke (0L, 0xaa); - if (gus_peek (0L) != 0xaa) - return (0); - - /* Now zero it out so that I can check for mirroring .. */ - gus_poke (0L, 0x00); - for (i = 1L; i < max_mem; i++) - { - int n, failed; - - /* check for mirroring ... */ - if (gus_peek (0L) != 0) - break; - loc = i << 10; - - for (n = loc - 1, failed = 0; n <= loc; n++) - { - gus_poke (loc, 0xaa); - if (gus_peek (loc) != 0xaa) - failed = 1; - - gus_poke (loc, 0x55); - if (gus_peek (loc) != 0x55) - failed = 1; - } - - if (failed) - break; - } - gus_mem_size = i << 10; - return 1; + if (gus_pnp_flag) + pnp_mem_init(); + if (iw_mode) + return 1; + + /* See if there is first block there.... */ + gus_poke(0L, 0xaa); + if (gus_peek(0L) != 0xaa) + return (0); + + /* Now zero it out so that I can check for mirroring .. */ + gus_poke(0L, 0x00); + for (i = 1L; i < max_mem; i++) + { + int n, failed; + + /* check for mirroring ... */ + if (gus_peek(0L) != 0) + break; + loc = i << 10; + + for (n = loc - 1, failed = 0; n <= loc; n++) + { + gus_poke(loc, 0xaa); + if (gus_peek(loc) != 0xaa) + failed = 1; + + gus_poke(loc, 0x55); + if (gus_peek(loc) != 0x55) + failed = 1; + } + + if (failed) + break; + } + gus_mem_size = i << 10; + return 1; } static int -guswave_ioctl (int dev, - unsigned int cmd, caddr_t arg) +guswave_ioctl(int dev, + unsigned int cmd, caddr_t arg) { - switch (cmd) - { - case SNDCTL_SYNTH_INFO: - gus_info.nr_voices = nr_voices; - memcpy ((&((char *) arg)[0]), (char *) &gus_info, sizeof (gus_info)); - return 0; - break; + switch (cmd) + { + case SNDCTL_SYNTH_INFO: + gus_info.nr_voices = nr_voices; + memcpy((&((char *) arg)[0]), (char *) &gus_info, sizeof(gus_info)); + return 0; + break; - case SNDCTL_SEQ_RESETSAMPLES: - reset_sample_memory (); - return 0; - break; + case SNDCTL_SEQ_RESETSAMPLES: + reset_sample_memory(); + return 0; + break; - case SNDCTL_SEQ_PERCMODE: - return 0; - break; + case SNDCTL_SEQ_PERCMODE: + return 0; + break; - case SNDCTL_SYNTH_MEMAVL: - return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32; + case SNDCTL_SYNTH_MEMAVL: + return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32; - default: - return -EINVAL; - } + default: + return -EINVAL; + } } static int -guswave_set_instr (int dev, int voice, int instr_no) +guswave_set_instr(int dev, int voice, int instr_no) { - int sample_no; + int sample_no; - if (instr_no < 0 || instr_no > MAX_PATCH) - instr_no = 0; /* Default to acoustic piano */ + if (instr_no < 0 || instr_no > MAX_PATCH) + instr_no = 0; /* Default to acoustic piano */ - if (voice < 0 || voice > 31) - return -EINVAL; + if (voice < 0 || voice > 31) + return -EINVAL; - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - { - voices[voice].sample_pending = instr_no; - return 0; - } - - sample_no = patch_table[instr_no]; - patch_map[voice] = -1; - - if (sample_no == NOT_SAMPLE) - { - printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice); - return -EINVAL; /* Patch not defined */ - } - - 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); - return -EINVAL; - } + if (voices[voice].volume_irq_mode == VMODE_START_NOTE) + { + voices[voice].sample_pending = instr_no; + return 0; + } + sample_no = patch_table[instr_no]; + patch_map[voice] = -1; - sample_map[voice] = sample_no; - patch_map[voice] = instr_no; - return 0; + if (sample_no == NOT_SAMPLE) + { + printk("GUS: Undefined patch %d for voice %d\n", instr_no, voice); + return -EINVAL; /* Patch not defined */ + } + 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); + return -EINVAL; + } + sample_map[voice] = sample_no; + patch_map[voice] = instr_no; + return 0; } static int -guswave_kill_note (int dev, int voice, int note, int velocity) +guswave_kill_note(int dev, int voice, int note, int velocity) { - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli (); - /* voice_alloc->map[voice] = 0xffff; */ - if (voices[voice].volume_irq_mode == VMODE_START_NOTE) - { - voices[voice].kill_pending = 1; - restore_flags (flags); - } - else - { - restore_flags (flags); - gus_voice_fade (voice); - } + save_flags(flags); + cli(); + /* voice_alloc->map[voice] = 0xffff; */ + if (voices[voice].volume_irq_mode == VMODE_START_NOTE) + { + voices[voice].kill_pending = 1; + restore_flags(flags); + } else + { + restore_flags(flags); + gus_voice_fade(voice); + } - restore_flags (flags); - return 0; + restore_flags(flags); + return 0; } static void -guswave_aftertouch (int dev, int voice, int pressure) +guswave_aftertouch(int dev, int voice, int pressure) { } static void -guswave_panning (int dev, int voice, int value) +guswave_panning(int dev, int voice, int value) { - if (voice >= 0 || voice < 32) - voices[voice].panning = value; + if (voice >= 0 || voice < 32) + voices[voice].panning = value; } static void -guswave_volume_method (int dev, int mode) +guswave_volume_method(int dev, int mode) { - if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO) - volume_method = mode; + if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO) + volume_method = mode; } static void -compute_volume (int voice, int volume) +compute_volume(int voice, int volume) { - if (volume < 128) - voices[voice].midi_volume = volume; - - switch (volume_method) - { - case VOL_METHOD_ADAGIO: - voices[voice].initial_volume = - gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol, - voices[voice].expression_vol, - voices[voice].patch_vol); - break; + if (volume < 128) + voices[voice].midi_volume = volume; - case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */ - voices[voice].initial_volume = - gus_linear_vol (volume, voices[voice].main_vol); - break; + switch (volume_method) + { + case VOL_METHOD_ADAGIO: + voices[voice].initial_volume = + gus_adagio_vol(voices[voice].midi_volume, voices[voice].main_vol, + voices[voice].expression_vol, + 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); - } + default: + voices[voice].initial_volume = volume_base + + (voices[voice].midi_volume * volume_scale); + } - if (voices[voice].initial_volume > 4030) - voices[voice].initial_volume = 4030; + if (voices[voice].initial_volume > 4030) + voices[voice].initial_volume = 4030; } static void -compute_and_set_volume (int voice, int volume, int ramp_time) -{ - int curr, target, rate; - unsigned long flags; - - compute_volume (voice, volume); - voices[voice].current_volume = voices[voice].initial_volume; - - save_flags (flags); - cli (); - /* - * CAUTION! Interrupts disabled. Enable them before returning - */ - - gus_select_voice (voice); - - curr = gus_read16 (0x09) >> 4; - target = voices[voice].initial_volume; - - if (ramp_time == INSTANT_RAMP) - { - gus_rampoff (); - gus_voice_volume (target); - restore_flags (flags); - return; - } - - if (ramp_time == FAST_RAMP) - rate = 63; - else - rate = 16; - gus_ramp_rate (0, rate); - - if ((target - curr) / 64 == 0) /* Close enough to target. */ - { - gus_rampoff (); - gus_voice_volume (target); - restore_flags (flags); - return; - } - - if (target > curr) - { - if (target > (4095 - 65)) - target = 4095 - 65; - gus_ramp_range (curr, target); - gus_rampon (0x00); /* Ramp up, once, no IRQ */ - } - else - { - if (target < 65) - target = 65; - - gus_ramp_range (target, curr); - gus_rampon (0x40); /* Ramp down, once, no irq */ - } - restore_flags (flags); +compute_and_set_volume(int voice, int volume, int ramp_time) +{ + int curr, target, rate; + unsigned long flags; + + compute_volume(voice, volume); + voices[voice].current_volume = voices[voice].initial_volume; + + save_flags(flags); + cli(); + /* + * CAUTION! Interrupts disabled. Enable them before returning + */ + + gus_select_voice(voice); + + curr = gus_read16(0x09) >> 4; + target = voices[voice].initial_volume; + + if (ramp_time == INSTANT_RAMP) + { + gus_rampoff(); + gus_voice_volume(target); + restore_flags(flags); + return; + } + if (ramp_time == FAST_RAMP) + rate = 63; + else + rate = 16; + gus_ramp_rate(0, rate); + + if ((target - curr) / 64 == 0) /* Close enough to target. */ + { + gus_rampoff(); + gus_voice_volume(target); + restore_flags(flags); + return; + } + if (target > curr) + { + if (target > (4095 - 65)) + target = 4095 - 65; + gus_ramp_range(curr, target); + gus_rampon(0x00); /* Ramp up, once, no IRQ */ + } else + { + if (target < 65) + target = 65; + + gus_ramp_range(target, curr); + gus_rampon(0x40); /* Ramp down, once, no irq */ + } + restore_flags(flags); } static void -dynamic_volume_change (int voice) +dynamic_volume_change(int voice) { - unsigned char status; - unsigned long flags; - - save_flags (flags); - cli (); - gus_select_voice (voice); - status = gus_read8 (0x00); /* Get voice status */ - restore_flags (flags); + unsigned char status; + unsigned long flags; - if (status & 0x03) - return; /* Voice was not running */ + save_flags(flags); + cli(); + gus_select_voice(voice); + status = gus_read8(0x00); /* Get voice status */ + restore_flags(flags); - if (!(voices[voice].mode & WAVE_ENVELOPES)) - { - compute_and_set_volume (voice, voices[voice].midi_volume, 1); - return; - } + if (status & 0x03) + return; /* Voice was not running */ - /* - * Voice is running and has envelopes. - */ - - save_flags (flags); - cli (); - gus_select_voice (voice); - status = gus_read8 (0x0d); /* Ramping status */ - restore_flags (flags); + if (!(voices[voice].mode & WAVE_ENVELOPES)) + { + compute_and_set_volume(voice, voices[voice].midi_volume, 1); + return; + } + /* + * Voice is running and has envelopes. + */ - if (status & 0x03) /* Sustain phase? */ - { - compute_and_set_volume (voice, voices[voice].midi_volume, 1); - return; - } + save_flags(flags); + cli(); + gus_select_voice(voice); + status = gus_read8(0x0d); /* Ramping status */ + restore_flags(flags); - if (voices[voice].env_phase < 0) - return; + if (status & 0x03) /* Sustain phase? */ + { + compute_and_set_volume(voice, voices[voice].midi_volume, 1); + return; + } + if (voices[voice].env_phase < 0) + return; - compute_volume (voice, voices[voice].midi_volume); + compute_volume(voice, voices[voice].midi_volume); } static void -guswave_controller (int dev, int voice, int ctrl_num, int value) -{ - unsigned long flags; - unsigned long freq; - - if (voice < 0 || voice > 31) - return; - - switch (ctrl_num) - { - case CTRL_PITCH_BENDER: - voices[voice].bender = value; - - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - { - freq = compute_finetune (voices[voice].orig_freq, value, - voices[voice].bender_range, 0); - voices[voice].current_freq = freq; - - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_freq (freq); - restore_flags (flags); - } - break; - - case CTRL_PITCH_BENDER_RANGE: - voices[voice].bender_range = value; - break; - case CTL_EXPRESSION: - value /= 128; - case CTRL_EXPRESSION: - 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; - - case CTL_PAN: - voices[voice].panning = (value * 2) - 128; - break; - - case CTL_MAIN_VOLUME: - value = (value * 100) / 16383; - - case CTRL_MAIN_VOLUME: - voices[voice].main_vol = value; - if (voices[voice].volume_irq_mode != VMODE_START_NOTE) - dynamic_volume_change (voice); - break; - - default: - break; - } +guswave_controller(int dev, int voice, int ctrl_num, int value) +{ + unsigned long flags; + unsigned long freq; + + if (voice < 0 || voice > 31) + return; + + switch (ctrl_num) + { + case CTRL_PITCH_BENDER: + voices[voice].bender = value; + + if (voices[voice].volume_irq_mode != VMODE_START_NOTE) + { + freq = compute_finetune(voices[voice].orig_freq, value, + voices[voice].bender_range, 0); + voices[voice].current_freq = freq; + + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_freq(freq); + restore_flags(flags); + } + break; + + case CTRL_PITCH_BENDER_RANGE: + voices[voice].bender_range = value; + break; + case CTL_EXPRESSION: + value /= 128; + case CTRL_EXPRESSION: + 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; + + case CTL_PAN: + voices[voice].panning = (value * 2) - 128; + break; + + case CTL_MAIN_VOLUME: + value = (value * 100) / 16383; + + case CTRL_MAIN_VOLUME: + voices[voice].main_vol = value; + if (voices[voice].volume_irq_mode != VMODE_START_NOTE) + dynamic_volume_change(voice); + break; + + default: + break; + } } static int -guswave_start_note2 (int dev, int voice, int note_num, int volume) -{ - int sample, best_sample, best_delta, delta_freq; - int is16bits, samplep, patch, pan; - unsigned long note_freq, base_note, freq, flags; - unsigned char mode = 0; - - if (voice < 0 || voice > 31) - { - printk ("GUS: Invalid voice\n"); - return -EINVAL; - } - - if (note_num == 255) - { - if (voices[voice].mode & WAVE_ENVELOPES) - { - voices[voice].midi_volume = volume; - dynamic_volume_change (voice); - return 0; - } - - compute_and_set_volume (voice, volume, 1); - return 0; - } - - if ((patch = patch_map[voice]) == -1) - { - return -EINVAL; - } - - if ((samplep = patch_table[patch]) == NOT_SAMPLE) - { - return -EINVAL; - } - - 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. - */ - sample = -1; - - best_sample = samplep; - best_delta = 1000000; - while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1) - { - delta_freq = note_freq - samples[samplep].base_note; - if (delta_freq < 0) - delta_freq = -delta_freq; - if (delta_freq < best_delta) - { - best_sample = samplep; - best_delta = delta_freq; - } - if (samples[samplep].low_note <= note_freq && - note_freq <= samples[samplep].high_note) - sample = samplep; - else - samplep = samples[samplep].key; /* Link to next sample */ - } - if (sample == -1) - sample = best_sample; - - if (sample == -1) - { - printk ("GUS: Patch %d not defined for note %d\n", patch, note_num); - return 0; /* Should play default patch ??? */ - } - - is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; - voices[voice].mode = samples[sample].mode; - voices[voice].patch_vol = samples[sample].volume; - - if (iw_mode) - gus_write8 (0x15, 0x00); /* RAM, Reset voice deactivate bit of SMSI */ - - if (voices[voice].mode & WAVE_ENVELOPES) - { - int i; - - for (i = 0; i < 6; i++) - { - voices[voice].env_rate[i] = samples[sample].env_rate[i]; - voices[voice].env_offset[i] = samples[sample].env_offset[i]; - } - } - - sample_map[voice] = sample; - - if (voices[voice].fixed_pitch) /* Fixed pitch */ - { - freq = samples[sample].base_freq; - } - else - { - base_note = samples[sample].base_note / 100; - note_freq /= 100; - - freq = samples[sample].base_freq * note_freq / base_note; - } - - voices[voice].orig_freq = freq; - - /* - * Since the pitch bender may have been set before playing the note, we - * have to calculate the bending now. - */ - - freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender, - voices[voice].bender_range, 0); - voices[voice].current_freq = freq; - - pan = (samples[sample].panning + voices[voice].panning) / 32; - pan += 7; - if (pan < 0) - pan = 0; - if (pan > 15) - pan = 15; - - if (samples[sample].mode & WAVE_16_BITS) - { - mode |= 0x04; /* 16 bits */ - if ((sample_ptrs[sample] / GUS_BANK_SIZE) != - ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE)) - printk ("GUS: Sample address error\n"); - } +guswave_start_note2(int dev, int voice, int note_num, int volume) +{ + int sample, best_sample, best_delta, delta_freq; + int is16bits, samplep, patch, pan; + unsigned long note_freq, base_note, freq, flags; + unsigned char mode = 0; + + if (voice < 0 || voice > 31) + { + printk("GUS: Invalid voice\n"); + return -EINVAL; + } + if (note_num == 255) + { + if (voices[voice].mode & WAVE_ENVELOPES) + { + voices[voice].midi_volume = volume; + dynamic_volume_change(voice); + return 0; + } + compute_and_set_volume(voice, volume, 1); + return 0; + } + if ((patch = patch_map[voice]) == -1) + { + return -EINVAL; + } + if ((samplep = patch_table[patch]) == NOT_SAMPLE) + { + return -EINVAL; + } + 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. + */ + sample = -1; + + best_sample = samplep; + best_delta = 1000000; + while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1) + { + delta_freq = note_freq - samples[samplep].base_note; + if (delta_freq < 0) + delta_freq = -delta_freq; + if (delta_freq < best_delta) + { + best_sample = samplep; + best_delta = delta_freq; + } + if (samples[samplep].low_note <= note_freq && + note_freq <= samples[samplep].high_note) + sample = samplep; + else + samplep = samples[samplep].key; /* Link to next sample */ + } + if (sample == -1) + sample = best_sample; + + if (sample == -1) + { + printk("GUS: Patch %d not defined for note %d\n", patch, note_num); + return 0; /* Should play default patch ??? */ + } + is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; + voices[voice].mode = samples[sample].mode; + voices[voice].patch_vol = samples[sample].volume; + + if (iw_mode) + gus_write8(0x15, 0x00); /* RAM, Reset voice deactivate bit of SMSI */ + + if (voices[voice].mode & WAVE_ENVELOPES) + { + int i; + + for (i = 0; i < 6; i++) + { + voices[voice].env_rate[i] = samples[sample].env_rate[i]; + voices[voice].env_offset[i] = samples[sample].env_offset[i]; + } + } + sample_map[voice] = sample; + + if (voices[voice].fixed_pitch) /* Fixed pitch */ + { + freq = samples[sample].base_freq; + } else + { + base_note = samples[sample].base_note / 100; + note_freq /= 100; + + freq = samples[sample].base_freq * note_freq / base_note; + } + + voices[voice].orig_freq = freq; + /* + * Since the pitch bender may have been set before playing the note, we + * have to calculate the bending now. + */ + + freq = compute_finetune(voices[voice].orig_freq, voices[voice].bender, + voices[voice].bender_range, 0); + voices[voice].current_freq = freq; + + pan = (samples[sample].panning + voices[voice].panning) / 32; + pan += 7; + if (pan < 0) + pan = 0; + if (pan > 15) + pan = 15; + + if (samples[sample].mode & WAVE_16_BITS) + { + mode |= 0x04; /* 16 bits */ + if ((sample_ptrs[sample] / GUS_BANK_SIZE) != + ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE)) + printk("GUS: Sample address error\n"); + } /************************************************************************* * CAUTION! Interrupts disabled. Don't return before enabling *************************************************************************/ - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_off (); - gus_rampoff (); - - restore_flags (flags); - - if (voices[voice].mode & WAVE_ENVELOPES) - { - compute_volume (voice, volume); - init_envelope (voice); - } - else - { - compute_and_set_volume (voice, volume, 0); - } - - save_flags (flags); - cli (); - 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, 0, is16bits); /* start=end */ - else - gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending, - 0, is16bits); /* Sample start=begin */ - - if (samples[sample].mode & WAVE_LOOPING) - { - mode |= 0x08; - - if (samples[sample].mode & WAVE_BIDIR_LOOP) - mode |= 0x10; - - if (samples[sample].mode & WAVE_LOOP_BACK) - { - gus_write_addr (0x0a, - sample_ptrs[sample] + samples[sample].loop_end - - voices[voice].offset_pending, - (samples[sample].fractions >> 4) & 0x0f, is16bits); - mode |= 0x40; - } - - gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, - samples[sample].fractions & 0x0f, - is16bits); /* Loop start location */ - gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, - (samples[sample].fractions >> 4) & 0x0f, - is16bits); /* Loop end location */ - } - else - { - mode |= 0x20; /* Loop IRQ at the end */ - voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */ - voices[voice].loop_irq_parm = 1; - gus_write_addr (0x02, sample_ptrs[sample], - 0, is16bits); /* Loop start location */ - gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1, - (samples[sample].fractions >> 4) & 0x0f, - is16bits); /* Loop end location */ - } - gus_voice_freq (freq); - gus_voice_balance (pan); - gus_voice_on (mode); - restore_flags (flags); - - return 0; + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_off(); + gus_rampoff(); + + restore_flags(flags); + + if (voices[voice].mode & WAVE_ENVELOPES) + { + compute_volume(voice, volume); + init_envelope(voice); + } else + { + compute_and_set_volume(voice, volume, 0); + } + + save_flags(flags); + cli(); + 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, 0, is16bits); /* start=end */ + else + gus_write_addr(0x0a, sample_ptrs[sample] + voices[voice].offset_pending, + 0, is16bits); /* Sample start=begin */ + + if (samples[sample].mode & WAVE_LOOPING) + { + mode |= 0x08; + + if (samples[sample].mode & WAVE_BIDIR_LOOP) + mode |= 0x10; + + if (samples[sample].mode & WAVE_LOOP_BACK) + { + gus_write_addr(0x0a, + sample_ptrs[sample] + samples[sample].loop_end - + voices[voice].offset_pending, + (samples[sample].fractions >> 4) & 0x0f, is16bits); + mode |= 0x40; + } + gus_write_addr(0x02, sample_ptrs[sample] + samples[sample].loop_start, + samples[sample].fractions & 0x0f, + is16bits); /* Loop start location */ + gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].loop_end, + (samples[sample].fractions >> 4) & 0x0f, + is16bits); /* Loop end location */ + } else + { + mode |= 0x20; /* Loop IRQ at the end */ + voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */ + voices[voice].loop_irq_parm = 1; + gus_write_addr(0x02, sample_ptrs[sample], + 0, is16bits); /* Loop start location */ + gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].len - 1, + (samples[sample].fractions >> 4) & 0x0f, + is16bits); /* Loop end location */ + } + gus_voice_freq(freq); + gus_voice_balance(pan); + gus_voice_on(mode); + restore_flags(flags); + + return 0; } /* @@ -1637,1946 +1600,1925 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume) */ static int -guswave_start_note (int dev, int voice, int note_num, int volume) -{ - long int flags; - int mode; - int ret_val = 0; - - save_flags (flags); - cli (); - if (note_num == 255) - { - 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); - } - } - else - { - gus_select_voice (voice); - mode = gus_read8 (0x00); - if (mode & 0x20) - gus_write8 (0x00, mode & 0xdf); /* No interrupt! */ - - voices[voice].offset_pending = 0; - voices[voice].kill_pending = 0; - voices[voice].volume_irq_mode = 0; - voices[voice].loop_irq_mode = 0; - - if (voices[voice].sample_pending >= 0) - { - restore_flags (flags); /* Run temporarily with interrupts enabled */ - guswave_set_instr (voices[voice].dev_pending, voice, - voices[voice].sample_pending); - voices[voice].sample_pending = -1; - save_flags (flags); - cli (); - gus_select_voice (voice); /* Reselect the voice (just to be sure) */ - } - - if ((mode & 0x01) || (int) ((gus_read16 (0x09) >> 4) < (unsigned) 2065)) - { - ret_val = guswave_start_note2 (dev, voice, note_num, volume); - } - else - { - voices[voice].dev_pending = dev; - 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_rampon (0x20 | 0x40); /* Ramp down, once, irq */ - } - } - restore_flags (flags); - return ret_val; +guswave_start_note(int dev, int voice, int note_num, int volume) +{ + long int flags; + int mode; + int ret_val = 0; + + save_flags(flags); + cli(); + if (note_num == 255) + { + 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); + } + } else + { + gus_select_voice(voice); + mode = gus_read8(0x00); + if (mode & 0x20) + gus_write8(0x00, mode & 0xdf); /* No interrupt! */ + + voices[voice].offset_pending = 0; + voices[voice].kill_pending = 0; + voices[voice].volume_irq_mode = 0; + voices[voice].loop_irq_mode = 0; + + if (voices[voice].sample_pending >= 0) + { + restore_flags(flags); /* Run temporarily with interrupts enabled */ + guswave_set_instr(voices[voice].dev_pending, voice, + voices[voice].sample_pending); + voices[voice].sample_pending = -1; + save_flags(flags); + cli(); + gus_select_voice(voice); /* Reselect the voice (just to be sure) */ + } + if ((mode & 0x01) || (int) ((gus_read16(0x09) >> 4) < (unsigned) 2065)) + { + ret_val = guswave_start_note2(dev, voice, note_num, volume); + } else + { + voices[voice].dev_pending = dev; + 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_rampon(0x20 | 0x40); /* Ramp down, once, irq */ + } + } + restore_flags(flags); + return ret_val; } static void -guswave_reset (int dev) +guswave_reset(int dev) { - int i; + int i; - for (i = 0; i < 32; i++) - { - gus_voice_init (i); - gus_voice_init2 (i); - } + for (i = 0; i < 32; i++) + { + gus_voice_init(i); + gus_voice_init2(i); + } } static int -guswave_open (int dev, int mode) +guswave_open(int dev, int mode) { - int err; + int err; - if (gus_busy) - return -EBUSY; + if (gus_busy) + return -EBUSY; - voice_alloc->timestamp = 0; + voice_alloc->timestamp = 0; - if ((err = DMAbuf_open_dma (gus_devnum)) < 0) - { - /* printk ("GUS: Loading samples without DMA\n"); */ - gus_no_dma = 1; /* Upload samples using PIO */ - } - else - gus_no_dma = 0; + if ((err = DMAbuf_open_dma(gus_devnum)) < 0) + { + /* printk( "GUS: Loading samples without DMA\n"); */ + gus_no_dma = 1; /* Upload samples using PIO */ + } else + gus_no_dma = 0; - dram_sleep_flag.opts = WK_NONE; - gus_busy = 1; - active_device = GUS_DEV_WAVE; + dram_sleep_flag.opts = WK_NONE; + gus_busy = 1; + active_device = GUS_DEV_WAVE; - gusintr (gus_irq, NULL, NULL); /* Serve pending interrupts */ - gus_initialize (); - gus_reset (); - gusintr (gus_irq, NULL, NULL); /* Serve pending interrupts */ + gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */ + gus_initialize(); + gus_reset(); + gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */ - return 0; + return 0; } static void -guswave_close (int dev) +guswave_close(int dev) { - gus_busy = 0; - active_device = 0; - gus_reset (); + gus_busy = 0; + active_device = 0; + gus_reset(); - if (!gus_no_dma) - DMAbuf_close_dma (gus_devnum); + if (!gus_no_dma) + DMAbuf_close_dma(gus_devnum); } static int -guswave_load_patch (int dev, int format, const char *addr, - int offs, int count, int pmgr_flag) -{ - struct patch_info patch; - int instr; - long sizeof_patch; - - unsigned long blk_sz, blk_end, left, src_offs, target; - - sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */ - - if (format != GUS_PATCH) - { - printk ("GUS Error: Invalid patch format (key) 0x%x\n", format); - return -EINVAL; - } - - if (count < sizeof_patch) - { - printk ("GUS Error: Patch header too short\n"); - return -EINVAL; - } - - count -= sizeof_patch; - - if (free_sample >= MAX_SAMPLE) - { - printk ("GUS: Sample table full\n"); - return -ENOSPC; - } - - /* - * Copy the header from user space but ignore the first bytes which have - * been transferred already. - */ - - copy_from_user (&((char *) &patch)[offs], &(addr)[offs], sizeof_patch - offs); - - if (patch.mode & WAVE_ROM) - return -EINVAL; - if (gus_mem_size == 0) - - return -ENOSPC; - - instr = patch.instr_no; - - if (instr < 0 || instr > MAX_PATCH) - { - printk ("GUS: Invalid patch number %d\n", instr); - return -EINVAL; - } - - if (count < patch.len) - { - printk ("GUS Warning: Patch record too short (%d<%d)\n", - count, (int) patch.len); - patch.len = count; - } - - if (patch.len <= 0 || patch.len > gus_mem_size) - { - printk ("GUS: Invalid sample length %d\n", (int) patch.len); - return -EINVAL; - } - - if (patch.mode & WAVE_LOOPING) - { - if (patch.loop_start < 0 || patch.loop_start >= patch.len) - { - printk ("GUS: Invalid loop start\n"); - return -EINVAL; - } - - if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len) - { - printk ("GUS: Invalid loop end\n"); - return -EINVAL; - } - } - - free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */ - - if (patch.mode & WAVE_16_BITS) - { - /* - * 16 bit samples must fit one 256k bank. - */ - if (patch.len >= GUS_BANK_SIZE) - { - printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len); - return -ENOSPC; - } - - if ((free_mem_ptr / GUS_BANK_SIZE) != - ((free_mem_ptr + patch.len) / GUS_BANK_SIZE)) - { - unsigned long tmp_mem = /* Align to 256K */ - ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE; - - if ((tmp_mem + patch.len) > gus_mem_size) - return -ENOSPC; - - free_mem_ptr = tmp_mem; /* This leaves unusable memory */ - } - } - - if ((free_mem_ptr + patch.len) > gus_mem_size) - return -ENOSPC; - - sample_ptrs[free_sample] = free_mem_ptr; - - /* - * Tremolo is not possible with envelopes - */ - - if (patch.mode & WAVE_ENVELOPES) - patch.mode &= ~WAVE_TREMOLO; - - if (!(patch.mode & WAVE_FRACTIONS)) - { - patch.fractions = 0; - } - - 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 - */ - - left = patch.len; - src_offs = 0; - target = free_mem_ptr; - - while (left) /* Not completely transferred yet */ - { - blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use; - if (blk_sz > left) - blk_sz = left; - - /* - * DMA cannot cross bank (256k) boundaries. Check for that. - */ - blk_end = target + blk_sz; - - if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE)) - { /* Split the block */ - - blk_end &= ~(GUS_BANK_SIZE - 1); - blk_sz = blk_end - target; - } - - if (gus_no_dma) - { - /* - * For some reason the DMA is not possible. We have to use PIO. - */ - long i; - unsigned char data; - - for (i = 0; i < blk_sz; i++) - { - get_user (*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i])); - if (patch.mode & WAVE_UNSIGNED) - if (!(patch.mode & WAVE_16_BITS) || (i & 0x01)) - data ^= 0x80; /* Convert to signed */ - gus_poke (target + i, data); - } - } - else - { - unsigned long address, hold_address; - unsigned char dma_command; - unsigned long flags; - - if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL) - { - printk ("GUS: DMA buffer == NULL\n"); - return -ENOSPC; - } +guswave_load_patch(int dev, int format, const char *addr, + int offs, int count, int pmgr_flag) +{ + struct patch_info patch; + int instr; + long sizeof_patch; - /* - * OK, move now. First in and then out. - */ + unsigned long blk_sz, blk_end, left, src_offs, target; - copy_from_user (audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz); + sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */ - save_flags (flags); - cli (); -/******** INTERRUPTS DISABLED NOW ********/ - gus_write8 (0x41, 0); /* Disable GF1 DMA */ - DMAbuf_start_dma (gus_devnum, - audio_devs[gus_devnum]->dmap_out->raw_buf_phys, - blk_sz, DMA_MODE_WRITE); + if (format != GUS_PATCH) + { + printk("GUS Error: Invalid patch format (key) 0x%x\n", format); + return -EINVAL; + } + if (count < sizeof_patch) + { + printk("GUS Error: Patch header too short\n"); + return -EINVAL; + } + count -= sizeof_patch; - /* - * Set the DRAM address for the wave data - */ + if (free_sample >= MAX_SAMPLE) + { + printk("GUS: Sample table full\n"); + return -ENOSPC; + } + /* + * Copy the header from user space but ignore the first bytes which have + * been transferred already. + */ - if (iw_mode) - { - /* Different address translation in enhanced mode */ + copy_from_user(&((char *) &patch)[offs], &(addr)[offs], sizeof_patch - offs); - unsigned char hi; + if (patch.mode & WAVE_ROM) + return -EINVAL; + if (gus_mem_size == 0) - if (gus_dma > 4) - address = target >> 1; /* Convert to 16 bit word address */ - else - address = target; + return -ENOSPC; - hi = (unsigned char) ((address >> 16) & 0xf0); - hi += (unsigned char) (address & 0x0f); + instr = patch.instr_no; - gus_write16 (0x42, (address >> 4) & 0xffff); /* DMA address (low) */ - gus_write8 (0x50, hi); - } - else - { - address = target; + if (instr < 0 || instr > MAX_PATCH) + { + printk("GUS: Invalid patch number %d\n", instr); + return -EINVAL; + } + if (count < patch.len) + { + printk("GUS Warning: Patch record too short (%d<%d)\n", count, (int) patch.len); + patch.len = count; + } + if (patch.len <= 0 || patch.len > gus_mem_size) + { + printk("GUS: Invalid sample length %d\n", (int) patch.len); + return -EINVAL; + } + if (patch.mode & WAVE_LOOPING) + { + if (patch.loop_start < 0 || patch.loop_start >= patch.len) + { + printk("GUS: Invalid loop start\n"); + return -EINVAL; + } + if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len) + { + printk("GUS: Invalid loop end\n"); + return -EINVAL; + } + } + free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */ - if (audio_devs[gus_devnum]->dmap_out->dma > 3) - { - hold_address = address; - address = address >> 1; - address &= 0x0001ffffL; - address |= (hold_address & 0x000c0000L); - } + if (patch.mode & WAVE_16_BITS) + { + /* + * 16 bit samples must fit one 256k bank. + */ + if (patch.len >= GUS_BANK_SIZE) + { + printk("GUS: Sample (16 bit) too long %d\n", (int) patch.len); + return -ENOSPC; + } + if ((free_mem_ptr / GUS_BANK_SIZE) != + ((free_mem_ptr + patch.len) / GUS_BANK_SIZE)) + { + unsigned long tmp_mem = /* Align to 256K */ + ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE; + + if ((tmp_mem + patch.len) > gus_mem_size) + return -ENOSPC; + + free_mem_ptr = tmp_mem; /* This leaves unusable memory */ + } + } + if ((free_mem_ptr + patch.len) > gus_mem_size) + return -ENOSPC; - gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */ - } + sample_ptrs[free_sample] = free_mem_ptr; - /* - * Start the DMA transfer - */ + /* + * Tremolo is not possible with envelopes + */ - dma_command = 0x21; /* IRQ enable, DMA start */ - if (patch.mode & WAVE_UNSIGNED) - dma_command |= 0x80; /* Invert MSB */ - if (patch.mode & WAVE_16_BITS) - dma_command |= 0x40; /* 16 bit _DATA_ */ - if (audio_devs[gus_devnum]->dmap_out->dma > 3) - dma_command |= 0x04; /* 16 bit DMA _channel_ */ + if (patch.mode & WAVE_ENVELOPES) + patch.mode &= ~WAVE_TREMOLO; - gus_write8 (0x41, dma_command); /* Lets go luteet (=bugs) */ + if (!(patch.mode & WAVE_FRACTIONS)) + { + patch.fractions = 0; + } + memcpy((char *) &samples[free_sample], &patch, sizeof_patch); - /* - * Sleep here until the DRAM DMA done interrupt is served - */ - active_device = GUS_DEV_WAVE; + /* + * 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 + */ + left = patch.len; + src_offs = 0; + target = free_mem_ptr; + + while (left) /* Not completely transferred yet */ { - unsigned long tlimit; + blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use; + if (blk_sz > left) + blk_sz = left; + + /* + * DMA cannot cross bank (256k) boundaries. Check for that. + */ + blk_end = target + blk_sz; + + if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE)) + { /* Split the block */ + + blk_end &= ~(GUS_BANK_SIZE - 1); + blk_sz = blk_end - target; + } + if (gus_no_dma) + { + /* + * For some reason the DMA is not possible. We have to use PIO. + */ + long i; + unsigned char data; + + for (i = 0; i < blk_sz; i++) + { + get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i])); + if (patch.mode & WAVE_UNSIGNED) + if (!(patch.mode & WAVE_16_BITS) || (i & 0x01)) + data ^= 0x80; /* Convert to signed */ + gus_poke(target + i, data); + } + } else + { + unsigned long address, hold_address; + unsigned char dma_command; + unsigned long flags; + + if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL) + { + printk("GUS: DMA buffer == NULL\n"); + return -ENOSPC; + } + /* + * OK, move now. First in and then out. + */ + + copy_from_user(audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz); + + save_flags(flags); + cli(); +/******** INTERRUPTS DISABLED NOW ********/ + gus_write8(0x41, 0); /* Disable GF1 DMA */ + DMAbuf_start_dma(gus_devnum, + audio_devs[gus_devnum]->dmap_out->raw_buf_phys, + blk_sz, DMA_MODE_WRITE); + + /* + * Set the DRAM address for the wave data + */ + + if (iw_mode) + { + /* Different address translation in enhanced mode */ + + unsigned char hi; + + if (gus_dma > 4) + address = target >> 1; /* Convert to 16 bit word address */ + else + address = target; + + hi = (unsigned char) ((address >> 16) & 0xf0); + hi += (unsigned char) (address & 0x0f); + + gus_write16(0x42, (address >> 4) & 0xffff); /* DMA address (low) */ + gus_write8(0x50, hi); + } else + { + address = target; + + if (audio_devs[gus_devnum]->dmap_out->dma > 3) + { + hold_address = address; + address = address >> 1; + address &= 0x0001ffffL; + address |= (hold_address & 0x000c0000L); + } + gus_write16(0x42, (address >> 4) & 0xffff); /* DRAM DMA address */ + } + + /* + * Start the DMA transfer + */ + + dma_command = 0x21; /* IRQ enable, DMA start */ + if (patch.mode & WAVE_UNSIGNED) + dma_command |= 0x80; /* Invert MSB */ + if (patch.mode & WAVE_16_BITS) + dma_command |= 0x40; /* 16 bit _DATA_ */ + if (audio_devs[gus_devnum]->dmap_out->dma > 3) + dma_command |= 0x04; /* 16 bit DMA _channel_ */ + + gus_write8(0x41, dma_command); /* Lets go luteet (=bugs) */ + + /* + * Sleep here until the DRAM DMA done interrupt is served + */ + active_device = GUS_DEV_WAVE; + + + { + unsigned long tlimit; + + if (HZ) + current->timeout = tlimit = jiffies + (HZ); + else + tlimit = (unsigned long) -1; + dram_sleep_flag.opts = WK_SLEEP; + interruptible_sleep_on(&dram_sleeper); + if (!(dram_sleep_flag.opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + dram_sleep_flag.opts |= WK_TIMEOUT; + } + dram_sleep_flag.opts &= ~WK_SLEEP; + }; + if ((dram_sleep_flag.opts & WK_TIMEOUT)) + printk("GUS: DMA Transfer timed out\n"); + restore_flags(flags); + } + + /* + * Now the next part + */ + + left -= blk_sz; + src_offs += blk_sz; + target += blk_sz; + + gus_write8(0x41, 0); /* Stop DMA */ + } - if (HZ) - current->timeout = tlimit = jiffies + (HZ); - else - tlimit = (unsigned long) -1; - dram_sleep_flag.opts = WK_SLEEP; - interruptible_sleep_on (&dram_sleeper); - if (!(dram_sleep_flag.opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - dram_sleep_flag.opts |= WK_TIMEOUT; - } - dram_sleep_flag.opts &= ~WK_SLEEP; - }; - if ((dram_sleep_flag.opts & WK_TIMEOUT)) - printk ("GUS: DMA Transfer timed out\n"); - restore_flags (flags); - } + free_mem_ptr += patch.len; - /* - * Now the next part - */ + free_sample++; + return 0; +} - left -= blk_sz; - src_offs += blk_sz; - target += blk_sz; +static void +guswave_hw_control(int dev, unsigned char *event_rec) +{ + int voice, cmd; + unsigned short p1, p2; + unsigned int plong; + unsigned flags; - gus_write8 (0x41, 0); /* Stop DMA */ - } + cmd = event_rec[2]; + voice = event_rec[3]; + p1 = *(unsigned short *) &event_rec[4]; + p2 = *(unsigned short *) &event_rec[6]; + plong = *(unsigned int *) &event_rec[4]; - free_mem_ptr += patch.len; + if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) && + (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS)) + do_volume_irq(voice); - free_sample++; - return 0; -} + switch (cmd) + { -static void -guswave_hw_control (int dev, unsigned char *event_rec) -{ - int voice, cmd; - unsigned short p1, p2; - unsigned int plong; - unsigned flags; - - cmd = event_rec[2]; - voice = event_rec[3]; - p1 = *(unsigned short *) &event_rec[4]; - p2 = *(unsigned short *) &event_rec[6]; - plong = *(unsigned int *) &event_rec[4]; - - if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) && - (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS)) - do_volume_irq (voice); - - switch (cmd) - { - - case _GUS_NUMVOICES: - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_select_max_voices (p1); - restore_flags (flags); - break; - - case _GUS_VOICESAMPLE: - guswave_set_instr (dev, voice, p1); - break; - - case _GUS_VOICEON: - save_flags (flags); - cli (); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_voice_on (p1); - restore_flags (flags); - break; - - case _GUS_VOICEOFF: - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_off (); - restore_flags (flags); - break; - - case _GUS_VOICEFADE: - gus_voice_fade (voice); - break; - - case _GUS_VOICEMODE: - save_flags (flags); - cli (); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_voice_mode (p1); - restore_flags (flags); - break; - - case _GUS_VOICEBALA: - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_balance (p1); - restore_flags (flags); - break; - - case _GUS_VOICEFREQ: - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_freq (plong); - restore_flags (flags); - break; - - case _GUS_VOICEVOL: - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_volume (p1); - restore_flags (flags); - break; - - case _GUS_VOICEVOL2: /* Just update the software voice level */ - voices[voice].initial_volume = - voices[voice].current_volume = p1; - break; - - case _GUS_RAMPRANGE: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NO-NO */ - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_ramp_range (p1, p2); - restore_flags (flags); - break; - - case _GUS_RAMPRATE: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NJET-NJET */ - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_ramp_rate (p1, p2); - restore_flags (flags); - break; - - case _GUS_RAMPMODE: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NO-NO */ - save_flags (flags); - cli (); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_ramp_mode (p1); - restore_flags (flags); - break; - - case _GUS_RAMPON: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* EI-EI */ - save_flags (flags); - cli (); - gus_select_voice (voice); - p1 &= ~0x20; /* Don't allow interrupts */ - gus_rampon (p1); - restore_flags (flags); - break; - - case _GUS_RAMPOFF: - if (voices[voice].mode & WAVE_ENVELOPES) - break; /* NEJ-NEJ */ - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_rampoff (); - restore_flags (flags); - break; - - case _GUS_VOLUME_SCALE: - volume_base = p1; - volume_scale = p2; - break; - - case _GUS_VOICE_POS: - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_set_voice_pos (voice, plong); - restore_flags (flags); - break; - - default:; - } + case _GUS_NUMVOICES: + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_select_max_voices(p1); + restore_flags(flags); + break; + + case _GUS_VOICESAMPLE: + guswave_set_instr(dev, voice, p1); + break; + + case _GUS_VOICEON: + save_flags(flags); + cli(); + gus_select_voice(voice); + p1 &= ~0x20; /* Don't allow interrupts */ + gus_voice_on(p1); + restore_flags(flags); + break; + + case _GUS_VOICEOFF: + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_off(); + restore_flags(flags); + break; + + case _GUS_VOICEFADE: + gus_voice_fade(voice); + break; + + case _GUS_VOICEMODE: + save_flags(flags); + cli(); + gus_select_voice(voice); + p1 &= ~0x20; /* Don't allow interrupts */ + gus_voice_mode(p1); + restore_flags(flags); + break; + + case _GUS_VOICEBALA: + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_balance(p1); + restore_flags(flags); + break; + + case _GUS_VOICEFREQ: + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_freq(plong); + restore_flags(flags); + break; + + case _GUS_VOICEVOL: + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_volume(p1); + restore_flags(flags); + break; + + case _GUS_VOICEVOL2: /* Just update the software voice level */ + voices[voice].initial_volume = + voices[voice].current_volume = p1; + break; + + case _GUS_RAMPRANGE: + if (voices[voice].mode & WAVE_ENVELOPES) + break; /* NO-NO */ + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_ramp_range(p1, p2); + restore_flags(flags); + break; + + case _GUS_RAMPRATE: + if (voices[voice].mode & WAVE_ENVELOPES) + break; /* NJET-NJET */ + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_ramp_rate(p1, p2); + restore_flags(flags); + break; + + case _GUS_RAMPMODE: + if (voices[voice].mode & WAVE_ENVELOPES) + break; /* NO-NO */ + save_flags(flags); + cli(); + gus_select_voice(voice); + p1 &= ~0x20; /* Don't allow interrupts */ + gus_ramp_mode(p1); + restore_flags(flags); + break; + + case _GUS_RAMPON: + if (voices[voice].mode & WAVE_ENVELOPES) + break; /* EI-EI */ + save_flags(flags); + cli(); + gus_select_voice(voice); + p1 &= ~0x20; /* Don't allow interrupts */ + gus_rampon(p1); + restore_flags(flags); + break; + + case _GUS_RAMPOFF: + if (voices[voice].mode & WAVE_ENVELOPES) + break; /* NEJ-NEJ */ + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_rampoff(); + restore_flags(flags); + break; + + case _GUS_VOLUME_SCALE: + volume_base = p1; + volume_scale = p2; + break; + + case _GUS_VOICE_POS: + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_set_voice_pos(voice, plong); + restore_flags(flags); + break; + + default:; + } } static int -gus_audio_set_speed (int speed) +gus_audio_set_speed(int speed) { - if (speed <= 0) - speed = gus_audio_speed; + if (speed <= 0) + speed = gus_audio_speed; - if (speed < 4000) - speed = 4000; + if (speed < 4000) + speed = 4000; - if (speed > 44100) - speed = 44100; + if (speed > 44100) + speed = 44100; - gus_audio_speed = speed; + gus_audio_speed = speed; - if (only_read_access) - { - /* Compute nearest valid recording speed and return it */ + if (only_read_access) + { + /* Compute nearest valid recording speed and return it */ - /* speed = (9878400 / (gus_audio_speed + 2)) / 16; */ - speed = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16; - speed = (9878400 / (speed * 16)) - 2; - } - return speed; + /* speed = (9878400 / (gus_audio_speed + 2)) / 16; */ + speed = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16; + speed = (9878400 / (speed * 16)) - 2; + } + return speed; } static int -gus_audio_set_channels (int channels) +gus_audio_set_channels(int channels) { - if (!channels) - return gus_audio_channels; - if (channels > 2) - channels = 2; - if (channels < 1) - channels = 1; - gus_audio_channels = channels; - return channels; + if (!channels) + return gus_audio_channels; + if (channels > 2) + channels = 2; + if (channels < 1) + channels = 1; + gus_audio_channels = channels; + return channels; } static int -gus_audio_set_bits (int bits) +gus_audio_set_bits(int bits) { - if (!bits) - return gus_audio_bits; + if (!bits) + return gus_audio_bits; - if (bits != 8 && bits != 16) - bits = 8; + if (bits != 8 && bits != 16) + bits = 8; - if (only_8_bits) - bits = 8; + if (only_8_bits) + bits = 8; - gus_audio_bits = bits; - return bits; + gus_audio_bits = bits; + return bits; } static int -gus_audio_ioctl (int dev, unsigned int cmd, caddr_t arg) +gus_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) { - int val; + int val; - switch (cmd) - { - case SOUND_PCM_WRITE_RATE: - val = *(int *) arg; - return (*(int *) arg = gus_audio_set_speed (val)); - break; + switch (cmd) + { + case SOUND_PCM_WRITE_RATE: + val = *(int *) arg; + return (*(int *) arg = gus_audio_set_speed(val)); + break; - case SOUND_PCM_READ_RATE: - return (*(int *) arg = gus_audio_speed); - break; + case SOUND_PCM_READ_RATE: + return (*(int *) arg = gus_audio_speed); + break; - case SNDCTL_DSP_STEREO: - val = *(int *) arg; - return (*(int *) arg = gus_audio_set_channels (val + 1) - 1); - break; + case SNDCTL_DSP_STEREO: + val = *(int *) arg; + return (*(int *) arg = gus_audio_set_channels(val + 1) - 1); + break; - case SOUND_PCM_WRITE_CHANNELS: - val = *(int *) arg; - return (*(int *) arg = gus_audio_set_channels (val)); - break; + case SOUND_PCM_WRITE_CHANNELS: + val = *(int *) arg; + return (*(int *) arg = gus_audio_set_channels(val)); + break; - case SOUND_PCM_READ_CHANNELS: - return (*(int *) arg = gus_audio_channels); - break; + case SOUND_PCM_READ_CHANNELS: + return (*(int *) arg = gus_audio_channels); + break; - case SNDCTL_DSP_SETFMT: - val = *(int *) arg; - return (*(int *) arg = gus_audio_set_bits (val)); - break; + case SNDCTL_DSP_SETFMT: + val = *(int *) arg; + return (*(int *) arg = gus_audio_set_bits(val)); + break; - case SOUND_PCM_READ_BITS: - return (*(int *) arg = gus_audio_bits); + case SOUND_PCM_READ_BITS: + return (*(int *) arg = gus_audio_bits); - case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */ - return (*(int *) arg = -EINVAL); - break; + case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */ + return (*(int *) arg = -EINVAL); + break; - case SOUND_PCM_READ_FILTER: - return (*(int *) arg = -EINVAL); - break; + case SOUND_PCM_READ_FILTER: + return (*(int *) arg = -EINVAL); + break; - } - return -EINVAL; + } + return -EINVAL; } static void -gus_audio_reset (int dev) +gus_audio_reset(int dev) { - if (recording_active) - { - gus_write8 (0x49, 0x00); /* Halt recording */ - set_input_volumes (); - } + if (recording_active) + { + gus_write8(0x49, 0x00); /* Halt recording */ + set_input_volumes(); + } } static int saved_iw_mode; /* A hack hack hack */ static int -gus_audio_open (int dev, int mode) -{ - if (gus_busy) - return -EBUSY; - - if (gus_pnp_flag && mode & OPEN_READ) - { - printk ("Sound: This audio device doesn't have recording capability\n"); - return -EIO; - } - gus_initialize (); - - gus_busy = 1; - active_device = 0; - - gus_reset (); - reset_sample_memory (); - gus_select_max_voices (14); - saved_iw_mode = iw_mode; - if (iw_mode) - { - /* There are some problems with audio in enhanced mode so disable it */ - gus_write8 (0x19, gus_read8 (0x19) & ~0x01); /* Disable enhanced mode */ - iw_mode = 0; - } - - pcm_active = 0; - dma_active = 0; - pcm_opened = 1; - if (mode & OPEN_READ) - { - recording_active = 1; - set_input_volumes (); - } - only_read_access = !(mode & OPEN_WRITE); - only_8_bits = mode & OPEN_READ; - if (only_8_bits) - audio_devs[dev]->format_mask = AFMT_U8; - else - audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE; - - return 0; +gus_audio_open(int dev, int mode) +{ + if (gus_busy) + return -EBUSY; + + if (gus_pnp_flag && mode & OPEN_READ) + { + printk("GUS: Audio device #%d is playback only.\n", dev); + return -EIO; + } + gus_initialize(); + + gus_busy = 1; + active_device = 0; + + gus_reset(); + reset_sample_memory(); + gus_select_max_voices(14); + saved_iw_mode = iw_mode; + if (iw_mode) + { + /* There are some problems with audio in enhanced mode so disable it */ + gus_write8(0x19, gus_read8(0x19) & ~0x01); /* Disable enhanced mode */ + iw_mode = 0; + } + pcm_active = 0; + dma_active = 0; + pcm_opened = 1; + if (mode & OPEN_READ) + { + recording_active = 1; + set_input_volumes(); + } + only_read_access = !(mode & OPEN_WRITE); + only_8_bits = mode & OPEN_READ; + if (only_8_bits) + audio_devs[dev]->format_mask = AFMT_U8; + else + audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE; + + return 0; } static void -gus_audio_close (int dev) +gus_audio_close(int dev) { - iw_mode = saved_iw_mode; - gus_reset (); - gus_busy = 0; - pcm_opened = 0; - active_device = 0; + iw_mode = saved_iw_mode; + gus_reset(); + gus_busy = 0; + pcm_opened = 0; + active_device = 0; - if (recording_active) - { - gus_write8 (0x49, 0x00); /* Halt recording */ - set_input_volumes (); - } + if (recording_active) + { + gus_write8(0x49, 0x00); /* Halt recording */ + set_input_volumes(); + } + recording_active = 0; +} + +static void +gus_audio_update_volume(void) +{ + unsigned long flags; + int voice; - recording_active = 0; + if (pcm_active && pcm_opened) + for (voice = 0; voice < gus_audio_channels; voice++) + { + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_rampoff(); + gus_voice_volume(1530 + (25 * gus_pcm_volume)); + gus_ramp_range(65, 1530 + (25 * gus_pcm_volume)); + restore_flags(flags); + } } static void -gus_audio_update_volume (void) +play_next_pcm_block(void) { - unsigned long flags; - int voice; + unsigned long flags; + int speed = gus_audio_speed; + int this_one, is16bits, chn; + unsigned long dram_loc; + unsigned char mode[2], ramp_mode[2]; + + if (!pcm_qlen) + return; - if (pcm_active && pcm_opened) - for (voice = 0; voice < gus_audio_channels; voice++) - { - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_rampoff (); - gus_voice_volume (1530 + (25 * gus_pcm_volume)); - gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); - restore_flags (flags); - } + this_one = pcm_head; + + for (chn = 0; chn < gus_audio_channels; chn++) + { + mode[chn] = 0x00; + ramp_mode[chn] = 0x03; /* Ramping and rollover off */ + + if (chn == 0) + { + mode[chn] |= 0x20; /* Loop IRQ */ + voices[chn].loop_irq_mode = LMODE_PCM; + } + if (gus_audio_bits != 8) + { + is16bits = 1; + mode[chn] |= 0x04; /* 16 bit data */ + } else + is16bits = 0; + + dram_loc = this_one * pcm_bsize; + dram_loc += chn * pcm_banksize; + + if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */ + { + mode[chn] |= 0x08; /* Enable loop */ + ramp_mode[chn] = 0x03; /* Disable rollover bit */ + } else + { + if (chn == 0) + ramp_mode[chn] = 0x04; /* Enable rollover bit */ + } + + save_flags(flags); + cli(); + gus_select_voice(chn); + gus_voice_freq(speed); + + if (gus_audio_channels == 1) + gus_voice_balance(7); /* mono */ + else if (chn == 0) + gus_voice_balance(0); /* left */ + else + gus_voice_balance(15); /* right */ + + if (!pcm_active) /* Playback not already active */ + { + /* + * 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(); + gus_rampoff(); + gus_voice_volume(1530 + (25 * gus_pcm_volume)); + gus_ramp_range(65, 1530 + (25 * gus_pcm_volume)); + + gus_write_addr(0x0a, chn * pcm_banksize, 0, is16bits); /* Starting position */ + gus_write_addr(0x02, chn * pcm_banksize, 0, is16bits); /* Loop start */ + + if (chn != 0) + gus_write_addr(0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1, + 0, is16bits); /* Loop end location */ + } + if (chn == 0) + gus_write_addr(0x04, dram_loc + pcm_bsize - 1, + 0, is16bits); /* Loop end location */ + else + mode[chn] |= 0x08; /* Enable looping */ + + + restore_flags(flags); + } + + for (chn = 0; chn < gus_audio_channels; chn++) + { + save_flags(flags); + cli(); + gus_select_voice(chn); + gus_write8(0x0d, ramp_mode[chn]); + if (iw_mode) + gus_write8(0x15, 0x00); /* Reset voice deactivate bit of SMSI */ + gus_voice_on(mode[chn]); + restore_flags(flags); + } + + pcm_active = 1; } static void -play_next_pcm_block (void) -{ - unsigned long flags; - int speed = gus_audio_speed; - int this_one, is16bits, chn; - unsigned long dram_loc; - unsigned char mode[2], ramp_mode[2]; - - if (!pcm_qlen) - return; - - this_one = pcm_head; - - for (chn = 0; chn < gus_audio_channels; chn++) - { - mode[chn] = 0x00; - ramp_mode[chn] = 0x03; /* Ramping and rollover off */ - - if (chn == 0) - { - mode[chn] |= 0x20; /* Loop IRQ */ - voices[chn].loop_irq_mode = LMODE_PCM; - } - - if (gus_audio_bits != 8) - { - is16bits = 1; - mode[chn] |= 0x04; /* 16 bit data */ - } - else - is16bits = 0; - - dram_loc = this_one * pcm_bsize; - dram_loc += chn * pcm_banksize; - - if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */ - { - mode[chn] |= 0x08; /* Enable loop */ - ramp_mode[chn] = 0x03; /* Disable rollover bit */ - } - else - { - if (chn == 0) - ramp_mode[chn] = 0x04; /* Enable rollover bit */ - } - - save_flags (flags); - cli (); - gus_select_voice (chn); - gus_voice_freq (speed); - - if (gus_audio_channels == 1) - gus_voice_balance (7); /* mono */ - else if (chn == 0) - gus_voice_balance (0); /* left */ - else - gus_voice_balance (15); /* right */ - - if (!pcm_active) /* Playback not already active */ - { - /* - * 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_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. + */ - gus_voice_off (); - gus_rampoff (); - gus_voice_volume (1530 + (25 * gus_pcm_volume)); - gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); + int this_one, count; + unsigned long flags; + unsigned char dma_command; + unsigned long address, hold_address; - gus_write_addr (0x0a, chn * pcm_banksize, 0, is16bits); /* Starting position */ - gus_write_addr (0x02, chn * pcm_banksize, 0, is16bits); /* Loop start */ + save_flags(flags); + cli(); - if (chn != 0) - gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1, - 0, is16bits); /* Loop end location */ - } + count = total_count / gus_audio_channels; - if (chn == 0) - gus_write_addr (0x04, dram_loc + pcm_bsize - 1, - 0, is16bits); /* Loop end location */ - else - mode[chn] |= 0x08; /* Enable looping */ + if (chn == 0) + { + if (pcm_qlen >= pcm_nblk) + printk("GUS Warning: PCM buffers out of sync\n"); + this_one = pcm_current_block = pcm_tail; + pcm_qlen++; + pcm_tail = (pcm_tail + 1) % pcm_nblk; + pcm_datasize[this_one] = count; + } else + this_one = pcm_current_block; - restore_flags (flags); - } + gus_write8(0x41, 0); /* Disable GF1 DMA */ + DMAbuf_start_dma(dev, buf + (chn * count), count, DMA_MODE_WRITE); - for (chn = 0; chn < gus_audio_channels; chn++) - { - save_flags (flags); - cli (); - gus_select_voice (chn); - gus_write8 (0x0d, ramp_mode[chn]); - if (iw_mode) - gus_write8 (0x15, 0x00); /* Reset voice deactivate bit of SMSI */ - gus_voice_on (mode[chn]); - restore_flags (flags); - } + address = this_one * pcm_bsize; + address += chn * pcm_banksize; - pcm_active = 1; -} + if (audio_devs[dev]->dmap_out->dma > 3) + { + hold_address = address; + address = address >> 1; + address &= 0x0001ffffL; + address |= (hold_address & 0x000c0000L); + } + gus_write16(0x42, (address >> 4) & 0xffff); /* DRAM DMA address */ -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. - */ - - int this_one, count; - unsigned long flags; - unsigned char dma_command; - unsigned long address, hold_address; - - save_flags (flags); - cli (); - - count = total_count / gus_audio_channels; - - if (chn == 0) - { - if (pcm_qlen >= pcm_nblk) - printk ("GUS Warning: PCM buffers out of sync\n"); - - this_one = pcm_current_block = pcm_tail; - pcm_qlen++; - pcm_tail = (pcm_tail + 1) % pcm_nblk; - pcm_datasize[this_one] = count; - } - else - this_one = pcm_current_block; - - gus_write8 (0x41, 0); /* Disable GF1 DMA */ - DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE); - - address = this_one * pcm_bsize; - address += chn * pcm_banksize; - - if (audio_devs[dev]->dmap_out->dma > 3) - { - hold_address = address; - address = address >> 1; - address &= 0x0001ffffL; - address |= (hold_address & 0x000c0000L); - } - - gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */ - - dma_command = 0x21; /* IRQ enable, DMA start */ - - if (gus_audio_bits != 8) - dma_command |= 0x40; /* 16 bit _DATA_ */ - else - dma_command |= 0x80; /* Invert MSB */ - - if (audio_devs[dev]->dmap_out->dma > 3) - dma_command |= 0x04; /* 16 bit DMA channel */ - - gus_write8 (0x41, dma_command); /* Kick start */ - - if (chn == (gus_audio_channels - 1)) /* Last channel */ - { - /* - * Last (right or mono) channel data - */ - dma_active = 1; /* DMA started. There is a unacknowledged buffer */ - active_device = GUS_DEV_PCM_DONE; - if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize)) - { - play_next_pcm_block (); - } - } - else - { - /* - * Left channel data. The right channel - * is transferred after DMA interrupt - */ - active_device = GUS_DEV_PCM_CONTINUE; - } - - restore_flags (flags); + dma_command = 0x21; /* IRQ enable, DMA start */ + + if (gus_audio_bits != 8) + dma_command |= 0x40; /* 16 bit _DATA_ */ + else + dma_command |= 0x80; /* Invert MSB */ + + if (audio_devs[dev]->dmap_out->dma > 3) + dma_command |= 0x04; /* 16 bit DMA channel */ + + gus_write8(0x41, dma_command); /* Kick start */ + + if (chn == (gus_audio_channels - 1)) /* Last channel */ + { + /* + * Last (right or mono) channel data + */ + dma_active = 1; /* DMA started. There is a unacknowledged buffer */ + active_device = GUS_DEV_PCM_DONE; + if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize)) + { + play_next_pcm_block(); + } + } else + { + /* + * Left channel data. The right channel + * is transferred after DMA interrupt + */ + active_device = GUS_DEV_PCM_CONTINUE; + } + + restore_flags(flags); } static void -gus_uninterleave8 (char *buf, int l) +gus_uninterleave8(char *buf, int l) { /* This routine uninterleaves 8 bit stereo output (LRLRLR->LLLRRR) */ - int i, p = 0, halfsize = l / 2; - char *buf2 = buf + halfsize, *src = bounce_buf; + int i, p = 0, halfsize = l / 2; + char *buf2 = buf + halfsize, *src = bounce_buf; - memcpy (bounce_buf, buf, l); + memcpy(bounce_buf, buf, l); - for (i = 0; i < halfsize; i++) - { - buf[i] = src[p++]; /* Left channel */ - buf2[i] = src[p++]; /* Right channel */ - } + for (i = 0; i < halfsize; i++) + { + buf[i] = src[p++]; /* Left channel */ + buf2[i] = src[p++]; /* Right channel */ + } } static void -gus_uninterleave16 (short *buf, int l) +gus_uninterleave16(short *buf, int l) { /* This routine uninterleaves 16 bit stereo output (LRLRLR->LLLRRR) */ - int i, p = 0, halfsize = l / 2; - short *buf2 = buf + halfsize, *src = (short *) bounce_buf; + int i, p = 0, halfsize = l / 2; + short *buf2 = buf + halfsize, *src = (short *) bounce_buf; - memcpy (bounce_buf, (char *) buf, l * 2); + memcpy(bounce_buf, (char *) buf, l * 2); - for (i = 0; i < halfsize; i++) - { - buf[i] = src[p++]; /* Left channel */ - buf2[i] = src[p++]; /* Right channel */ - } + for (i = 0; i < halfsize; i++) + { + buf[i] = src[p++]; /* Left channel */ + buf2[i] = src[p++]; /* Right channel */ + } } static void -gus_audio_output_block (int dev, unsigned long buf, int total_count, - int intrflag) +gus_audio_output_block(int dev, unsigned long buf, int total_count, + int intrflag) { - struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - dmap->flags |= DMA_NODMA | DMA_NOTIMEOUT; + dmap->flags |= DMA_NODMA | DMA_NOTIMEOUT; - pcm_current_buf = buf; - pcm_current_count = total_count; - pcm_current_intrflag = intrflag; - pcm_current_dev = dev; - if (gus_audio_channels == 2) - { - char *b = dmap->raw_buf + (buf - dmap->raw_buf_phys); + pcm_current_buf = buf; + pcm_current_count = total_count; + pcm_current_intrflag = intrflag; + pcm_current_dev = dev; + if (gus_audio_channels == 2) + { + char *b = dmap->raw_buf + (buf - dmap->raw_buf_phys); - if (gus_audio_bits == 8) - gus_uninterleave8 (b, total_count); - else - gus_uninterleave16 ((short *) b, total_count / 2); - } - gus_transfer_output_block (dev, buf, total_count, intrflag, 0); + if (gus_audio_bits == 8) + gus_uninterleave8(b, total_count); + else + gus_uninterleave16((short *) b, total_count / 2); + } + gus_transfer_output_block(dev, buf, total_count, intrflag, 0); } static void -gus_audio_start_input (int dev, unsigned long buf, int count, - int intrflag) +gus_audio_start_input(int dev, unsigned long buf, int count, + int intrflag) { - unsigned long flags; - unsigned char mode; + unsigned long flags; + unsigned char mode; - save_flags (flags); - cli (); + save_flags(flags); + cli(); - DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); + DMAbuf_start_dma(dev, buf, count, DMA_MODE_READ); - mode = 0xa0; /* DMA IRQ enabled, invert MSB */ + mode = 0xa0; /* DMA IRQ enabled, invert MSB */ - if (audio_devs[dev]->dmap_in->dma > 3) - mode |= 0x04; /* 16 bit DMA channel */ - if (gus_audio_channels > 1) - mode |= 0x02; /* Stereo */ - mode |= 0x01; /* DMA enable */ + if (audio_devs[dev]->dmap_in->dma > 3) + mode |= 0x04; /* 16 bit DMA channel */ + if (gus_audio_channels > 1) + mode |= 0x02; /* Stereo */ + mode |= 0x01; /* DMA enable */ - gus_write8 (0x49, mode); + gus_write8(0x49, mode); - restore_flags (flags); + restore_flags(flags); } static int -gus_audio_prepare_for_input (int dev, int bsize, int bcount) +gus_audio_prepare_for_input(int dev, int bsize, int bcount) { - unsigned int rate; - - gus_audio_bsize = bsize; - audio_devs[dev]->dmap_in->flags |= DMA_NODMA; - rate = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16; + unsigned int rate; - gus_write8 (0x48, rate & 0xff); /* Set sampling rate */ + gus_audio_bsize = bsize; + audio_devs[dev]->dmap_in->flags |= DMA_NODMA; + rate = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16; - if (gus_audio_bits != 8) - { - printk ("GUS Error: 16 bit recording not supported\n"); - return -EINVAL; - } + gus_write8(0x48, rate & 0xff); /* Set sampling rate */ - return 0; + if (gus_audio_bits != 8) + { + printk("GUS Error: 16 bit recording not supported\n"); + return -EINVAL; + } + return 0; } static int -gus_audio_prepare_for_output (int dev, int bsize, int bcount) +gus_audio_prepare_for_output(int dev, int bsize, int bcount) { - int i; + int i; - long mem_ptr, mem_size; + long mem_ptr, mem_size; - audio_devs[dev]->dmap_out->flags |= DMA_NODMA | DMA_NOTIMEOUT; - mem_ptr = 0; - mem_size = gus_mem_size / gus_audio_channels; + audio_devs[dev]->dmap_out->flags |= DMA_NODMA | DMA_NOTIMEOUT; + mem_ptr = 0; + mem_size = gus_mem_size / gus_audio_channels; - if (mem_size > (256 * 1024)) - mem_size = 256 * 1024; + if (mem_size > (256 * 1024)) + mem_size = 256 * 1024; - pcm_bsize = bsize / gus_audio_channels; - pcm_head = pcm_tail = pcm_qlen = 0; + pcm_bsize = bsize / gus_audio_channels; + pcm_head = pcm_tail = pcm_qlen = 0; - pcm_nblk = 2; /* MAX_PCM_BUFFERS; */ - if ((pcm_bsize * pcm_nblk) > mem_size) - pcm_nblk = mem_size / pcm_bsize; + pcm_nblk = 2; /* MAX_PCM_BUFFERS; */ + if ((pcm_bsize * pcm_nblk) > mem_size) + pcm_nblk = mem_size / pcm_bsize; - for (i = 0; i < pcm_nblk; i++) - pcm_datasize[i] = 0; + for (i = 0; i < pcm_nblk; i++) + pcm_datasize[i] = 0; - pcm_banksize = pcm_nblk * pcm_bsize; + pcm_banksize = pcm_nblk * pcm_bsize; - if (gus_audio_bits != 8 && pcm_banksize == (256 * 1024)) - pcm_nblk--; - gus_write8 (0x41, 0); /* Disable GF1 DMA */ + if (gus_audio_bits != 8 && pcm_banksize == (256 * 1024)) + pcm_nblk--; + gus_write8(0x41, 0); /* Disable GF1 DMA */ - return 0; + return 0; } static int -gus_local_qlen (int dev) +gus_local_qlen(int dev) { - return pcm_qlen; + return pcm_qlen; } static struct audio_driver gus_audio_driver = { - gus_audio_open, - gus_audio_close, - gus_audio_output_block, - gus_audio_start_input, - gus_audio_ioctl, - gus_audio_prepare_for_input, - gus_audio_prepare_for_output, - gus_audio_reset, - gus_local_qlen, - NULL + gus_audio_open, + gus_audio_close, + gus_audio_output_block, + gus_audio_start_input, + gus_audio_ioctl, + gus_audio_prepare_for_input, + gus_audio_prepare_for_output, + gus_audio_reset, + gus_local_qlen, + NULL }; static void -guswave_setup_voice (int dev, int voice, int chn) +guswave_setup_voice(int dev, int voice, int chn) { - struct channel_info *info = - &synth_devs[dev]->chn_info[chn]; + struct channel_info *info = + &synth_devs[dev]->chn_info[chn]; - guswave_set_instr (dev, voice, info->pgm_num); + guswave_set_instr(dev, voice, info->pgm_num); - voices[voice].expression_vol = - info->controllers[CTL_EXPRESSION]; /* Just MSB */ - voices[voice].main_vol = - (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128; - voices[voice].panning = - (info->controllers[CTL_PAN] * 2) - 128; - voices[voice].bender = 0; - voices[voice].bender_range = info->bender_range; + voices[voice].expression_vol = + info->controllers[CTL_EXPRESSION]; /* Just MSB */ + voices[voice].main_vol = + (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128; + voices[voice].panning = + (info->controllers[CTL_PAN] * 2) - 128; + voices[voice].bender = 0; + voices[voice].bender_range = info->bender_range; - if (chn == 9) - voices[voice].fixed_pitch = 1; + if (chn == 9) + voices[voice].fixed_pitch = 1; } static void -guswave_bender (int dev, int voice, int value) +guswave_bender(int dev, int voice, int value) { - int freq; - unsigned long flags; + int freq; + unsigned long flags; - voices[voice].bender = value - 8192; - freq = compute_finetune (voices[voice].orig_freq, value - 8192, - voices[voice].bender_range, 0); - voices[voice].current_freq = freq; + voices[voice].bender = value - 8192; + freq = compute_finetune(voices[voice].orig_freq, value - 8192, + voices[voice].bender_range, 0); + voices[voice].current_freq = freq; - save_flags (flags); - cli (); - gus_select_voice (voice); - gus_voice_freq (freq); - restore_flags (flags); + save_flags(flags); + cli(); + gus_select_voice(voice); + gus_voice_freq(freq); + restore_flags(flags); } static int -guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc) -{ - int i, p, best = -1, best_time = 0x7fffffff; - - p = alloc->ptr; - /* - * First look for a completely stopped voice - */ - - for (i = 0; i < alloc->max_voice; i++) - { - if (alloc->map[p] == 0) - { - alloc->ptr = p; - return p; - } - 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 - */ - - for (i = 0; i < alloc->max_voice; i++) - { - if (alloc->map[p] == 0xffff) - { - alloc->ptr = p; - return p; - } - p = (p + 1) % alloc->max_voice; - } - - if (best >= 0) - p = best; - - alloc->ptr = p; - return p; +guswave_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc) +{ + int i, p, best = -1, best_time = 0x7fffffff; + + p = alloc->ptr; + /* + * First look for a completely stopped voice + */ + + for (i = 0; i < alloc->max_voice; i++) + { + if (alloc->map[p] == 0) + { + alloc->ptr = p; + return p; + } + 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 + */ + + for (i = 0; i < alloc->max_voice; i++) + { + if (alloc->map[p] == 0xffff) + { + alloc->ptr = p; + return p; + } + p = (p + 1) % alloc->max_voice; + } + + if (best >= 0) + p = best; + + alloc->ptr = p; + return p; } static struct synth_operations guswave_operations = { - "GUS", - &gus_info, - 0, - SYNTH_TYPE_SAMPLE, - SAMPLE_TYPE_GUS, - guswave_open, - guswave_close, - guswave_ioctl, - guswave_kill_note, - guswave_start_note, - guswave_set_instr, - guswave_reset, - guswave_hw_control, - guswave_load_patch, - guswave_aftertouch, - guswave_controller, - guswave_panning, - guswave_volume_method, - guswave_bender, - guswave_alloc, - guswave_setup_voice + "GUS", + &gus_info, + 0, + SYNTH_TYPE_SAMPLE, + SAMPLE_TYPE_GUS, + guswave_open, + guswave_close, + guswave_ioctl, + guswave_kill_note, + guswave_start_note, + guswave_set_instr, + guswave_reset, + guswave_hw_control, + guswave_load_patch, + guswave_aftertouch, + guswave_controller, + guswave_panning, + guswave_volume_method, + guswave_bender, + guswave_alloc, + guswave_setup_voice }; static void -set_input_volumes (void) +set_input_volumes(void) { - unsigned long flags; - unsigned char mask = 0xff & ~0x06; /* Just line out enabled */ - - if (have_gus_max) /* Don't disturb GUS MAX */ - return; + unsigned long flags; + unsigned char mask = 0xff & ~0x06; /* Just line out enabled */ - save_flags (flags); - cli (); + if (have_gus_max) /* Don't disturb GUS MAX */ + return; - /* - * Enable channels having vol > 10% - * Note! bit 0x01 means the line in DISABLED while 0x04 means - * the mic in ENABLED. - */ - if (gus_line_vol > 10) - mask &= ~0x01; - if (gus_mic_vol > 10) - mask |= 0x04; + save_flags(flags); + cli(); - if (recording_active) - { - /* - * Disable channel, if not selected for recording - */ - if (!(gus_recmask & SOUND_MASK_LINE)) - mask |= 0x01; - if (!(gus_recmask & SOUND_MASK_MIC)) - mask &= ~0x04; - } + /* + * Enable channels having vol > 10% + * Note! bit 0x01 means the line in DISABLED while 0x04 means + * the mic in ENABLED. + */ + if (gus_line_vol > 10) + mask &= ~0x01; + if (gus_mic_vol > 10) + mask |= 0x04; - mix_image &= ~0x07; - mix_image |= mask & 0x07; - outb ((mix_image), u_Mixer); + if (recording_active) + { + /* + * Disable channel, if not selected for recording + */ + if (!(gus_recmask & SOUND_MASK_LINE)) + mask |= 0x01; + if (!(gus_recmask & SOUND_MASK_MIC)) + mask &= ~0x04; + } + mix_image &= ~0x07; + mix_image |= mask & 0x07; + outb((mix_image), u_Mixer); - restore_flags (flags); + restore_flags(flags); } int -gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) +gus_default_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) { #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ SOUND_MASK_SYNTH|SOUND_MASK_PCM) - if (((cmd >> 8) & 0xff) == 'M') - { - if (_SIOC_DIR (cmd) & _SIOC_WRITE) - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - gus_recmask = *(int *) arg; - gus_recmask &= MIX_DEVS; - if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE))) - gus_recmask = SOUND_MASK_MIC; - /* Note! Input volumes are updated during next open for recording */ - return (*(int *) arg = gus_recmask); - break; - - case SOUND_MIXER_MIC: - { - int vol; - - vol = *(int *) arg; - vol &= 0xff; - - if (vol < 0) - vol = 0; - if (vol > 100) - vol = 100; - gus_mic_vol = vol; - set_input_volumes (); - return (*(int *) arg = vol | (vol << 8)); - } - break; - - case SOUND_MIXER_LINE: - { - int vol; - - vol = *(int *) arg; - vol &= 0xff; - - if (vol < 0) - vol = 0; - if (vol > 100) - vol = 100; - gus_line_vol = vol; - set_input_volumes (); - return (*(int *) arg = vol | (vol << 8)); - } - break; - - case SOUND_MIXER_PCM: - gus_pcm_volume = *(int *) arg; - gus_pcm_volume &= 0xff; - if (gus_pcm_volume < 0) - gus_pcm_volume = 0; - if (gus_pcm_volume > 100) - gus_pcm_volume = 100; - gus_audio_update_volume (); - return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8)); - break; - - case SOUND_MIXER_SYNTH: - { - int voice; - - gus_wave_volume = *(int *) arg; - gus_wave_volume &= 0xff; - - if (gus_wave_volume < 0) - gus_wave_volume = 0; - if (gus_wave_volume > 100) - gus_wave_volume = 100; - - if (active_device == GUS_DEV_WAVE) - for (voice = 0; voice < nr_voices; voice++) - dynamic_volume_change (voice); /* Apply the new vol */ - - return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8)); - } - break; - - default: - return -EINVAL; - } - else - switch (cmd & 0xff) /* - * Return parameters - */ + if (((cmd >> 8) & 0xff) == 'M') { - - case SOUND_MIXER_RECSRC: - return (*(int *) arg = gus_recmask); - break; - - case SOUND_MIXER_DEVMASK: - return (*(int *) arg = MIX_DEVS); - break; - - case SOUND_MIXER_STEREODEVS: - return (*(int *) arg = 0); - break; - - case SOUND_MIXER_RECMASK: - return (*(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE); - break; - - case SOUND_MIXER_CAPS: - return (*(int *) arg = 0); - break; - - case SOUND_MIXER_MIC: - return (*(int *) arg = gus_mic_vol | (gus_mic_vol << 8)); - break; - - case SOUND_MIXER_LINE: - return (*(int *) arg = gus_line_vol | (gus_line_vol << 8)); - break; - - case SOUND_MIXER_PCM: - return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8)); - break; - - case SOUND_MIXER_SYNTH: - return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8)); - break; - - default: - return -EINVAL; - } - } - else - return -EINVAL; + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + gus_recmask = *(int *) arg; + gus_recmask &= MIX_DEVS; + if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE))) + gus_recmask = SOUND_MASK_MIC; + /* Note! Input volumes are updated during next open for recording */ + return (*(int *) arg = gus_recmask); + break; + + case SOUND_MIXER_MIC: + { + int vol; + + vol = *(int *) arg; + vol &= 0xff; + + if (vol < 0) + vol = 0; + if (vol > 100) + vol = 100; + gus_mic_vol = vol; + set_input_volumes(); + return (*(int *) arg = vol | (vol << 8)); + } + break; + + case SOUND_MIXER_LINE: + { + int vol; + + vol = *(int *) arg; + vol &= 0xff; + + if (vol < 0) + vol = 0; + if (vol > 100) + vol = 100; + gus_line_vol = vol; + set_input_volumes(); + return (*(int *) arg = vol | (vol << 8)); + } + break; + + case SOUND_MIXER_PCM: + gus_pcm_volume = *(int *) arg; + gus_pcm_volume &= 0xff; + if (gus_pcm_volume < 0) + gus_pcm_volume = 0; + if (gus_pcm_volume > 100) + gus_pcm_volume = 100; + gus_audio_update_volume(); + return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8)); + break; + + case SOUND_MIXER_SYNTH: + { + int voice; + + gus_wave_volume = *(int *) arg; + gus_wave_volume &= 0xff; + + if (gus_wave_volume < 0) + gus_wave_volume = 0; + if (gus_wave_volume > 100) + gus_wave_volume = 100; + + if (active_device == GUS_DEV_WAVE) + for (voice = 0; voice < nr_voices; voice++) + dynamic_volume_change(voice); /* Apply the new vol */ + + return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8)); + } + break; + + default: + return -EINVAL; + } else + switch (cmd & 0xff) /* + * Return parameters + */ + { + + case SOUND_MIXER_RECSRC: + return (*(int *) arg = gus_recmask); + break; + + case SOUND_MIXER_DEVMASK: + return (*(int *) arg = MIX_DEVS); + break; + + case SOUND_MIXER_STEREODEVS: + return (*(int *) arg = 0); + break; + + case SOUND_MIXER_RECMASK: + return (*(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE); + break; + + case SOUND_MIXER_CAPS: + return (*(int *) arg = 0); + break; + + case SOUND_MIXER_MIC: + return (*(int *) arg = gus_mic_vol | (gus_mic_vol << 8)); + break; + + case SOUND_MIXER_LINE: + return (*(int *) arg = gus_line_vol | (gus_line_vol << 8)); + break; + + case SOUND_MIXER_PCM: + return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8)); + break; + + case SOUND_MIXER_SYNTH: + return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8)); + break; + + default: + return -EINVAL; + } + } else + return -EINVAL; } static struct mixer_operations gus_mixer_operations = { - "GUS", - "Gravis Ultrasound", - gus_default_mixer_ioctl + "GUS", + "Gravis Ultrasound", + gus_default_mixer_ioctl }; -static void -gus_default_mixer_init (void) +static int +gus_default_mixer_init(void) { - if (num_mixers < MAX_MIXER_DEV) /* - * Don't install if there is another - * mixer - */ - mixer_devs[num_mixers++] = &gus_mixer_operations; + int n; - if (have_gus_max) - { + if ((n = sound_alloc_mixerdev()) != -1) + { /* + * Don't install if there is another + * mixer + */ + mixer_devs[n] = &gus_mixer_operations; + } + if (have_gus_max) + { /* * Enable all mixer channels on the GF1 side. Otherwise recording will * not be possible using GUS MAX. */ - mix_image &= ~0x07; - mix_image |= 0x04; /* All channels enabled */ - outb ((mix_image), u_Mixer); - } + mix_image &= ~0x07; + mix_image |= 0x04; /* All channels enabled */ + outb((mix_image), u_Mixer); + } + return n; } void -gus_wave_init (struct address_info *hw_config) -{ - unsigned long flags; - unsigned char val; - char *model_num = "2.4"; - char tmp[64], tmp2[64]; - int gus_type = 0x24; /* 2.4 */ - - int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2; - - if (!gus_pnp_flag) - if (irq < 0 || irq > 15) - { - printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq); - return; - } - - if (dma < 0 || dma > 7 || dma == 4) - { - printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma); - return; - } - - gus_irq = irq; - gus_dma = dma; - gus_dma2 = dma2; - - if (gus_dma2 == -1) - gus_dma2 = dma; - - /* - * Try to identify the GUS model. - * - * Versions < 3.6 don't have the digital ASIC. Try to probe it first. - */ - - save_flags (flags); - cli (); - outb ((0x20), gus_base + 0x0f); - val = inb (gus_base + 0x0f); - restore_flags (flags); - - if (gus_pnp_flag || (val != 0xff && (val & 0x06))) /* Should be 0x02?? */ - { - int ad_flags = 0; - - if (gus_pnp_flag) - ad_flags = 0x12345678; /* Interwave "magic" */ - /* - * It has the digital ASIC so the card is at least v3.4. - * Next try to detect the true model. - */ - - if (gus_pnp_flag) /* Hack hack hack */ - val = 10; - else - 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. - * - */ - - 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; - request_region (u_MixSelect, 1, "GUS mixer"); - } - else - { - model_num = "MAX"; - gus_type = 0x40; - mixer_type = CS4231; -#ifdef CONFIG_GUSMAX +gus_wave_init(struct address_info *hw_config) +{ + unsigned long flags; + unsigned char val; + char *model_num = "2.4"; + char tmp[64], tmp2[64]; + int gus_type = 0x24; /* 2.4 */ + + int irq = hw_config->irq, dma = hw_config->dma, + dma2 = hw_config->dma2; + int dev; + int sdev; + + hw_config->slots[0] = -1; /* No wave */ + hw_config->slots[1] = -1; /* No ad1848 */ + hw_config->slots[4] = -1; /* No audio */ + hw_config->slots[5] = -1; /* No mixer */ + + if (!gus_pnp_flag) + if (irq < 0 || irq > 15) + { + printk("ERROR! Invalid IRQ#%d. GUS Disabled", irq); + return; + } + if (dma < 0 || dma > 7 || dma == 4) { - unsigned char max_config = 0x40; /* Codec enable */ - - if (gus_dma2 == -1) - gus_dma2 = gus_dma; + printk("ERROR! Invalid DMA#%d. GUS Disabled", dma); + return; + } + gus_irq = irq; + gus_dma = dma; + gus_dma2 = dma2; - if (gus_dma > 3) - max_config |= 0x10; /* 16 bit capture DMA */ + if (gus_dma2 == -1) + gus_dma2 = dma; - if (gus_dma2 > 3) - max_config |= 0x20; /* 16 bit playback DMA */ + /* + * Try to identify the GUS model. + * + * Versions < 3.6 don't have the digital ASIC. Try to probe it first. + */ - max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */ + save_flags(flags); + cli(); + outb((0x20), gus_base + 0x0f); + val = inb(gus_base + 0x0f); + restore_flags(flags); - outb ((max_config), gus_base + 0x106); /* UltraMax control */ + if (gus_pnp_flag || (val != 0xff && (val & 0x06))) /* Should be 0x02?? */ + { + int ad_flags = 0; + + if (gus_pnp_flag) + ad_flags = 0x12345678; /* Interwave "magic" */ + /* + * It has the digital ASIC so the card is at least v3.4. + * Next try to detect the true model. + */ + + if (gus_pnp_flag) /* Hack hack hack */ + val = 10; + else + 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. + * + */ + + 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; + request_region(u_MixSelect, 1, "GUS mixer"); + } else + { + model_num = "MAX"; + gus_type = 0x40; + mixer_type = CS4231; +#ifdef CONFIG_GUSMAX + { + unsigned char max_config = 0x40; /* Codec enable */ + + if (gus_dma2 == -1) + gus_dma2 = gus_dma; + + if (gus_dma > 3) + max_config |= 0x10; /* 16 bit capture DMA */ + + if (gus_dma2 > 3) + max_config |= 0x20; /* 16 bit playback DMA */ + + 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, &ad_flags, hw_config->osp)) + { + char *name = "GUS MAX"; + int old_num_mixers = num_mixers; + + if (gus_pnp_flag) + name = "GUS PnP"; + + gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; + gus_wave_volume = 90; + have_gus_max = 1; + if (hw_config->name) + name = hw_config->name; + + hw_config->slots[1] = ad1848_init(name, gus_base + 0x10c, + -irq, + gus_dma2, /* Playback DMA */ + gus_dma, /* Capture DMA */ + 1, /* Share DMA channels with GF1 */ + hw_config->osp); + + if (num_mixers > old_num_mixers) + { /* GUS has it's own mixer map */ + AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_SYNTH); + AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD); + AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); + } + } else + printk("[Where's the CS4231?]"); +#else + printk("\n\n\nGUS MAX support was not compiled in!!!\n\n\n\n"); +#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. + */ } - if (ad1848_detect (gus_base + 0x10c, &ad_flags, hw_config->osp)) - { - char *name = "GUS MAX"; - int old_num_mixers = num_mixers; + if (hw_config->name) + { - if (gus_pnp_flag) - name = "GUS PnP"; + strncpy(tmp, hw_config->name, 45); + tmp[45] = 0; + sprintf(tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024); + tmp2[sizeof(tmp2) - 1] = 0; + } else if (gus_pnp_flag) + { + sprintf(tmp2, "Gravis UltraSound PnP (%dk)", + (int) gus_mem_size / 1024); + } else + sprintf(tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); - gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; - gus_wave_volume = 90; - have_gus_max = 1; - if (hw_config->name) - name = hw_config->name; - ad1848_init (name, gus_base + 0x10c, - -irq, - gus_dma2, /* Playback DMA */ - gus_dma, /* Capture DMA */ - 1, /* Share DMA channels with GF1 */ - hw_config->osp); + samples = (struct patch_info *) (sound_mem_blocks[sound_nblocks] = vmalloc((MAX_SAMPLE + 1) * sizeof(*samples))); + sound_mem_sizes[sound_nblocks] = (MAX_SAMPLE + 1) * sizeof(*samples); + if (sound_nblocks < 1024) + sound_nblocks++;; + if (samples == NULL) + { + printk(KERN_WARNING "gus_init: Cant allocate memory for instrument tables\n"); + return; + } + conf_printf(tmp2, hw_config); + tmp2[sizeof(gus_info.name) - 1] = 0; + strcpy(gus_info.name, tmp2); - if (num_mixers > old_num_mixers) - { /* GUS has it's own mixer map */ - AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_SYNTH); - AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD); - AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_LINE); - } - } - else - printk ("[Where's the CS4231?]"); -#else - printk ("\n\n\nGUS MAX support was not compiled in!!!\n\n\n\n"); -#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. - */ - } - - if (hw_config->name) - { - - strncpy (tmp, hw_config->name, 45); - tmp[45] = 0; - sprintf (tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024); - tmp2[sizeof (tmp2) - 1] = 0; - } - else if (gus_pnp_flag) - { - sprintf (tmp2, "Gravis UltraSound PnP (%dk)", - (int) gus_mem_size / 1024); - } - else - sprintf (tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); - - - samples = (struct patch_info *) (sound_mem_blocks[sound_nblocks] = vmalloc ((MAX_SAMPLE + 1) * sizeof (*samples))); - sound_mem_sizes[sound_nblocks] = (MAX_SAMPLE + 1) * sizeof (*samples); - if (sound_nblocks < 1024) - sound_nblocks++;; - if (samples == NULL) - { - printk ("GUS Error: Cant allocate memory for instrument tables\n"); - return; - } - - conf_printf (tmp2, hw_config); - tmp2[sizeof (gus_info.name) - 1] = 0; - strcpy (gus_info.name, tmp2); - - if (num_synths >= MAX_SYNTH_DEV) - printk ("GUS Error: Too many synthesizers\n"); - else - { - voice_alloc = &guswave_operations.alloc; - if (iw_mode) - guswave_operations.id = "IWAVE"; - synth_devs[num_synths++] = &guswave_operations; - sequencer_init (); -#ifdef CONFIG_SEQUENCER - gus_tmr_install (gus_base + 8); + if ((sdev = sound_alloc_synthdev()) == -1) + printk(KERN_WARNING "gus_init: Too many synthesizers\n"); + else + { + voice_alloc = &guswave_operations.alloc; + if (iw_mode) + guswave_operations.id = "IWAVE"; + hw_config->slots[0] = sdev; + synth_devs[sdev] = &guswave_operations; + sequencer_init(); +#if defined(CONFIG_SEQUENCER) || defined(MODULE) + gus_tmr_install(gus_base + 8); #endif - } - - reset_sample_memory (); - - gus_initialize (); - - if (gus_mem_size > 0) - if (num_audiodevs < MAX_AUDIO_DEV) - { - - if ((gus_devnum = sound_install_audiodrv (AUDIO_DRIVER_VERSION, - "Ultrasound", - &gus_audio_driver, - sizeof (struct audio_driver), - NEEDS_RESTART | - ((!iw_mode && dma2 != dma && dma2 != -1) ? - DMA_DUPLEX : 0), - AFMT_U8 | AFMT_S16_LE, - NULL, - dma, - dma2)) < 0) - return; - - audio_devs[gus_devnum]->min_fragment = 9; /* 512k */ - audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */ - audio_devs[gus_devnum]->mixer_dev = num_mixers; /* Next mixer# */ - audio_devs[gus_devnum]->flags |= DMA_HARDSTOP; - } - else - printk ("GUS: Too many audio devices available\n"); - - /* - * Mixer dependent initialization. - */ - - switch (mixer_type) - { - case ICS2101: - gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; - gus_wave_volume = 90; - request_region (u_MixSelect, 1, "GUS mixer"); - ics2101_mixer_init (); - return; - - case CS4231: - /* Initialized elsewhere (ad1848.c) */ - default: - gus_default_mixer_init (); - return; - } + } + + reset_sample_memory(); + + gus_initialize(); + + if (gus_mem_size > 0) + if ((dev = sound_alloc_audiodev()) != -1) + { + hw_config->slots[4] = dev; + if ((gus_devnum = sound_install_audiodrv(AUDIO_DRIVER_VERSION, + "Ultrasound", + &gus_audio_driver, + sizeof(struct audio_driver), + NEEDS_RESTART | + ((!iw_mode && dma2 != dma && dma2 != -1) ? + DMA_DUPLEX : 0), + AFMT_U8 | AFMT_S16_LE, + NULL, + dma, + dma2)) < 0) + return; + + audio_devs[gus_devnum]->min_fragment = 9; /* 512k */ + audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */ + audio_devs[gus_devnum]->mixer_dev = -1; /* Next mixer# */ + audio_devs[gus_devnum]->flags |= DMA_HARDSTOP; + } else + printk("GUS: Too many audio devices available\n"); + + /* + * Mixer dependent initialization. + */ + + switch (mixer_type) + { + case ICS2101: + gus_mic_vol = gus_line_vol = gus_pcm_volume = 100; + gus_wave_volume = 90; + request_region(u_MixSelect, 1, "GUS mixer"); + hw_config->slots[5] = ics2101_mixer_init(); + audio_devs[gus_devnum]->mixer_dev = hw_config->slots[5]; /* Next mixer# */ + return; + + case CS4231: + /* Initialized elsewhere (ad1848.c) */ + default: + hw_config->slots[5] = gus_default_mixer_init(); + audio_devs[gus_devnum]->mixer_dev = hw_config->slots[5]; /* Next mixer# */ + return; + } } void -gus_wave_unload (void) +gus_wave_unload(struct address_info *hw_config) { #ifdef CONFIG_GUSMAX - if (have_gus_max) - { - ad1848_unload (gus_base + 0x10c, - -gus_irq, - gus_dma2, /* Playback DMA */ - gus_dma, /* Capture DMA */ - 1); /* Share DMA channels with GF1 */ - } + if (have_gus_max) + { + ad1848_unload(gus_base + 0x10c, + -gus_irq, + gus_dma2, /* Playback DMA */ + gus_dma, /* Capture DMA */ + 1); /* Share DMA channels with GF1 */ + } #endif - if (mixer_type == ICS2101) - { - release_region (u_MixSelect, 1); - } + if (mixer_type == ICS2101) + { + release_region(u_MixSelect, 1); + } + if (hw_config->slots[0] != -1) + sound_unload_synthdev(hw_config->slots[0]); + if (hw_config->slots[1] != -1) + sound_unload_audiodev(hw_config->slots[1]); + if (hw_config->slots[2] != -1) + sound_unload_mididev(hw_config->slots[2]); + if (hw_config->slots[4] != -1) + sound_unload_audiodev(hw_config->slots[4]); + if (hw_config->slots[5] != -1) + sound_unload_mixerdev(hw_config->slots[4]); } static void -do_loop_irq (int voice) +do_loop_irq(int voice) { - unsigned char tmp; - int mode, parm; - unsigned long flags; + unsigned char tmp; + int mode, parm; + unsigned long flags; - save_flags (flags); - cli (); - gus_select_voice (voice); + save_flags(flags); + cli(); + gus_select_voice(voice); - tmp = gus_read8 (0x00); - tmp &= ~0x20; /* + tmp = gus_read8(0x00); + tmp &= ~0x20; /* * Disable wave IRQ for this_one voice */ - gus_write8 (0x00, tmp); + gus_write8(0x00, tmp); - if (tmp & 0x03) /* Voice stopped */ - voice_alloc->map[voice] = 0; + 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; + mode = voices[voice].loop_irq_mode; + voices[voice].loop_irq_mode = 0; + parm = voices[voice].loop_irq_parm; - switch (mode) - { + switch (mode) + { - case LMODE_FINISH: /* + case LMODE_FINISH: /* * Final loop finished, shoot volume down */ - if ((int) (gus_read16 (0x09) >> 4) < 100) /* - * Get current volume - */ - { - gus_voice_off (); - gus_rampoff (); - gus_voice_init (voice); - break; - } - gus_ramp_range (65, 4065); - gus_ramp_rate (0, 63); /* - * Fastest possible rate - */ - gus_rampon (0x20 | 0x40); /* - * Ramp down, once, irq - */ - voices[voice].volume_irq_mode = VMODE_HALT; - break; - - case LMODE_PCM_STOP: - pcm_active = 0; /* Signal to the play_next_pcm_block routine */ - case LMODE_PCM: - { - - pcm_qlen--; - pcm_head = (pcm_head + 1) % pcm_nblk; - 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 ((int) (gus_read16(0x09) >> 4) < 100) /* + * Get current volume + */ + { + gus_voice_off(); + gus_rampoff(); + gus_voice_init(voice); + break; + } + gus_ramp_range(65, 4065); + gus_ramp_rate(0, 63); /* + * Fastest possible rate + */ + gus_rampon(0x20 | 0x40); /* + * Ramp down, once, irq + */ + voices[voice].volume_irq_mode = VMODE_HALT; + break; + + case LMODE_PCM_STOP: + pcm_active = 0; /* Signal to the play_next_pcm_block routine */ + case LMODE_PCM: + { + + pcm_qlen--; + pcm_head = (pcm_head + 1) % pcm_nblk; + 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 (audio_devs[gus_devnum]->dmap_out->qlen > 0) + DMAbuf_outputintr(gus_devnum, 0); + } + break; + + default:; } - - /* - * If the queue was full before this interrupt, the DMA transfer was - * suspended. Let it continue now. - */ - if (audio_devs[gus_devnum]->dmap_out->qlen > 0) - DMAbuf_outputintr (gus_devnum, 0); - } - break; - - default:; - } - restore_flags (flags); + restore_flags(flags); } static void -do_volume_irq (int voice) +do_volume_irq(int voice) { - unsigned char tmp; - int mode, parm; - unsigned long flags; + unsigned char tmp; + int mode, parm; + unsigned long flags; - save_flags (flags); - cli (); + save_flags(flags); + cli(); - gus_select_voice (voice); + gus_select_voice(voice); - tmp = gus_read8 (0x0d); - tmp &= ~0x20; /* + tmp = gus_read8(0x0d); + tmp &= ~0x20; /* * Disable volume ramp IRQ */ - gus_write8 (0x0d, tmp); - - mode = voices[voice].volume_irq_mode; - voices[voice].volume_irq_mode = 0; - parm = voices[voice].volume_irq_parm; - - switch (mode) - { - case VMODE_HALT: /* Decay phase finished */ - if (iw_mode) - gus_write8 (0x15, 0x02); /* Set voice deactivate bit of SMSI */ - restore_flags (flags); - gus_voice_init (voice); - break; - - case VMODE_ENVELOPE: - gus_rampoff (); - restore_flags (flags); - step_envelope (voice); - break; - - case VMODE_START_NOTE: - restore_flags (flags); - guswave_start_note2 (voices[voice].dev_pending, voice, - voices[voice].note_pending, voices[voice].volume_pending); - if (voices[voice].kill_pending) - guswave_kill_note (voices[voice].dev_pending, voice, - voices[voice].note_pending, 0); - - if (voices[voice].sample_pending >= 0) - { - guswave_set_instr (voices[voice].dev_pending, voice, - voices[voice].sample_pending); - voices[voice].sample_pending = -1; - } - break; - - default:; - } -} + gus_write8(0x0d, tmp); -void -gus_voice_irq (void) -{ - unsigned long wave_ignore = 0, volume_ignore = 0; - unsigned long voice_bit; + mode = voices[voice].volume_irq_mode; + voices[voice].volume_irq_mode = 0; + parm = voices[voice].volume_irq_parm; - unsigned char src, voice; + switch (mode) + { + case VMODE_HALT: /* Decay phase finished */ + if (iw_mode) + gus_write8(0x15, 0x02); /* Set voice deactivate bit of SMSI */ + restore_flags(flags); + gus_voice_init(voice); + break; + + case VMODE_ENVELOPE: + gus_rampoff(); + restore_flags(flags); + step_envelope(voice); + break; + + case VMODE_START_NOTE: + restore_flags(flags); + guswave_start_note2(voices[voice].dev_pending, voice, + voices[voice].note_pending, voices[voice].volume_pending); + if (voices[voice].kill_pending) + guswave_kill_note(voices[voice].dev_pending, voice, + voices[voice].note_pending, 0); + + if (voices[voice].sample_pending >= 0) + { + guswave_set_instr(voices[voice].dev_pending, voice, + voices[voice].sample_pending); + voices[voice].sample_pending = -1; + } + break; - while (1) - { - src = gus_read8 (0x0f); /* - * Get source info - */ - voice = src & 0x1f; - src &= 0xc0; + default: + restore_flags(flags); + } + restore_flags(flags); +} - if (src == (0x80 | 0x40)) - return; /* - * No interrupt - */ +void +gus_voice_irq(void) +{ + unsigned long wave_ignore = 0, volume_ignore = 0; + unsigned long voice_bit; - voice_bit = 1 << voice; + unsigned char src, voice; - if (!(src & 0x80)) /* - * Wave IRQ pending - */ - if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /* - * Not done - * yet - */ + while (1) { - wave_ignore |= voice_bit; - do_loop_irq (voice); - } + src = gus_read8(0x0f); /* + * Get source info + */ + voice = src & 0x1f; + src &= 0xc0; + + if (src == (0x80 | 0x40)) + return; /* + * No interrupt + */ - if (!(src & 0x40)) /* - * Volume IRQ pending - */ - if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /* - * Not done - * yet - */ - { - volume_ignore |= voice_bit; - do_volume_irq (voice); + voice_bit = 1 << voice; + + if (!(src & 0x80)) /* + * Wave IRQ pending + */ + if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /* + * Not done + * yet + */ + { + wave_ignore |= voice_bit; + do_loop_irq(voice); + } + if (!(src & 0x40)) /* + * Volume IRQ pending + */ + if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /* + * Not done + * yet + */ + { + volume_ignore |= voice_bit; + do_volume_irq(voice); + } } - } } void -guswave_dma_irq (void) -{ - unsigned char status; - - status = gus_look8 (0x41); /* Get DMA IRQ Status */ - if (status & 0x40) /* DMA interrupt pending */ - switch (active_device) - { - case GUS_DEV_WAVE: - if ((dram_sleep_flag.opts & WK_SLEEP)) - { - dram_sleep_flag.opts = WK_WAKEUP; - wake_up (&dram_sleeper); - }; - break; - - case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */ - gus_write8 (0x41, 0); /* Disable GF1 DMA */ - gus_transfer_output_block (pcm_current_dev, pcm_current_buf, - pcm_current_count, - pcm_current_intrflag, 1); - break; - - case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */ - gus_write8 (0x41, 0); /* Disable GF1 DMA */ - if (pcm_qlen < pcm_nblk) - { - dma_active = 0; - if (gus_busy) - { - if (audio_devs[gus_devnum]->dmap_out->qlen > 0) - DMAbuf_outputintr (gus_devnum, 0); - } - } - break; - - default:; - } - - status = gus_look8 (0x49); /* - * Get Sampling IRQ Status - */ - if (status & 0x40) /* +guswave_dma_irq(void) +{ + unsigned char status; + + status = gus_look8(0x41); /* Get DMA IRQ Status */ + if (status & 0x40) /* DMA interrupt pending */ + switch (active_device) + { + case GUS_DEV_WAVE: + if ((dram_sleep_flag.opts & WK_SLEEP)) + { + dram_sleep_flag.opts = WK_WAKEUP; + wake_up(&dram_sleeper); + }; + break; + + case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */ + gus_write8(0x41, 0); /* Disable GF1 DMA */ + gus_transfer_output_block(pcm_current_dev, pcm_current_buf, + pcm_current_count, + pcm_current_intrflag, 1); + break; + + case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */ + gus_write8(0x41, 0); /* Disable GF1 DMA */ + if (pcm_qlen < pcm_nblk) + { + dma_active = 0; + if (gus_busy) + { + if (audio_devs[gus_devnum]->dmap_out->qlen > 0) + DMAbuf_outputintr(gus_devnum, 0); + } + } + break; + + default:; + } + status = gus_look8(0x49); /* + * Get Sampling IRQ Status + */ + if (status & 0x40) /* * Sampling Irq pending */ - { - DMAbuf_inputintr (gus_devnum); - } - + { + DMAbuf_inputintr(gus_devnum); + } } -#ifdef CONFIG_SEQUENCER +#if defined(CONFIG_SEQUENCER) || defined(MODULE) + /* * Timer stuff */ @@ -3585,105 +3527,103 @@ static volatile int select_addr, data_addr; static volatile int curr_timer = 0; void -gus_timer_command (unsigned int addr, unsigned int val) +gus_timer_command(unsigned int addr, unsigned int val) { - int i; + int i; - outb (((unsigned char) (addr & 0xff)), select_addr); + outb(((unsigned char) (addr & 0xff)), select_addr); - for (i = 0; i < 2; i++) - inb (select_addr); + for (i = 0; i < 2; i++) + inb(select_addr); - outb (((unsigned char) (val & 0xff)), data_addr); + outb(((unsigned char) (val & 0xff)), data_addr); - for (i = 0; i < 2; i++) - inb (select_addr); + for (i = 0; i < 2; i++) + inb(select_addr); } static void -arm_timer (int timer, unsigned int interval) +arm_timer(int timer, unsigned int interval) { - curr_timer = timer; + curr_timer = timer; - if (timer == 1) - { - gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */ - gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */ - gus_timer_command (0x04, 0x01); /* Start timer 1 */ - } - else - { - gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */ - gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */ - gus_timer_command (0x04, 0x02); /* Start timer 2 */ - } + if (timer == 1) + { + gus_write8(0x46, 256 - interval); /* Set counter for timer 1 */ + gus_write8(0x45, 0x04); /* Enable timer 1 IRQ */ + gus_timer_command(0x04, 0x01); /* Start timer 1 */ + } else + { + gus_write8(0x47, 256 - interval); /* Set counter for timer 2 */ + gus_write8(0x45, 0x08); /* Enable timer 2 IRQ */ + gus_timer_command(0x04, 0x02); /* Start timer 2 */ + } - gus_timer_enabled = 1; + gus_timer_enabled = 1; } static unsigned int -gus_tmr_start (int dev, unsigned int usecs_per_tick) +gus_tmr_start(int dev, unsigned int usecs_per_tick) { - int timer_no, resolution; - int divisor; + int timer_no, resolution; + int divisor; - if (usecs_per_tick > (256 * 80)) - { - timer_no = 2; - resolution = 320; /* usec */ - } - else - { - timer_no = 1; - resolution = 80; /* usec */ - } + if (usecs_per_tick > (256 * 80)) + { + timer_no = 2; + resolution = 320; /* usec */ + } else + { + timer_no = 1; + resolution = 80; /* usec */ + } - divisor = (usecs_per_tick + (resolution / 2)) / resolution; + divisor = (usecs_per_tick + (resolution / 2)) / resolution; - arm_timer (timer_no, divisor); + arm_timer(timer_no, divisor); - return divisor * resolution; + return divisor * resolution; } static void -gus_tmr_disable (int dev) +gus_tmr_disable(int dev) { - gus_write8 (0x45, 0); /* Disable both timers */ - gus_timer_enabled = 0; + gus_write8(0x45, 0); /* Disable both timers */ + gus_timer_enabled = 0; } static void -gus_tmr_restart (int dev) +gus_tmr_restart(int dev) { - if (curr_timer == 1) - gus_write8 (0x45, 0x04); /* Start timer 1 again */ - else - gus_write8 (0x45, 0x08); /* Start timer 2 again */ - gus_timer_enabled = 1; + if (curr_timer == 1) + gus_write8(0x45, 0x04); /* Start timer 1 again */ + else + gus_write8(0x45, 0x08); /* Start timer 2 again */ + gus_timer_enabled = 1; } static struct sound_lowlev_timer gus_tmr = { - 0, - 1, - gus_tmr_start, - gus_tmr_disable, - gus_tmr_restart + 0, + 1, + gus_tmr_start, + gus_tmr_disable, + gus_tmr_restart }; static void -gus_tmr_install (int io_base) +gus_tmr_install(int io_base) { - struct sound_lowlev_timer *tmr; + struct sound_lowlev_timer *tmr; - select_addr = io_base; - data_addr = io_base + 1; + select_addr = io_base; + data_addr = io_base + 1; - tmr = &gus_tmr; + tmr = &gus_tmr; #ifdef THIS_GETS_FIXED - sound_timer_init (&gus_tmr, "GUS"); + sound_timer_init(&gus_tmr, "GUS"); #endif } #endif -- cgit v1.2.3