?? gus_wave.c
字號:
*/ gus_poke (target + i, data); } }#else /* * * * GUS_NO_DMA */ { unsigned long address, hold_address; unsigned char dma_command; unsigned long flags; /* * OK, move now. First in and then out. */ COPY_FROM_USER (snd_raw_buf[gus_devnum][0], addr, sizeof_patch + src_offs, blk_size); DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/ gus_write8 (0x41, 0); /* * Disable GF1 DMA */ DMAbuf_start_dma (gus_devnum, snd_raw_buf_phys[gus_devnum][0], blk_size, DMA_MODE_WRITE); /* * Set the DRAM address for the wave data */ address = target; if (sound_dsp_dmachan[gus_devnum] > 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 (sound_dsp_dmachan[gus_devnum] > 3) dma_command |= 0x04; /* * 16 bit DMA channel */ gus_write8 (0x41, dma_command); /* * Let's go luteet (=bugs) */ /* * Sleep here until the DRAM DMA done interrupt is served */ active_device = GUS_DEV_WAVE; DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ); if (TIMED_OUT (dram_sleeper, dram_sleep_flag)) printk ("GUS: DMA Transfer timed out\n"); RESTORE_INTR (flags); }#endif /* * * * GUS_NO_DMA */ /* * Now the next part */ left -= blk_size; src_offs += blk_size; target += blk_size; gus_write8 (0x41, 0); /* * Stop DMA */ } free_mem_ptr += patch.len; if (!pmgr_flag) pmgr_inform (dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0); free_sample++; return 0;}static voidguswave_hw_control (int dev, unsigned char *event){ int voice, cmd; unsigned short p1, p2; unsigned long plong, flags; cmd = event[2]; voice = event[3]; p1 = *(unsigned short *) &event[4]; p2 = *(unsigned short *) &event[6]; plong = *(unsigned long *) &event[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: DISABLE_INTR (flags); gus_select_voice (voice); gus_select_max_voices (p1); RESTORE_INTR (flags); break; case _GUS_VOICESAMPLE: guswave_set_instr (dev, voice, p1); break; case _GUS_VOICEON: DISABLE_INTR (flags); gus_select_voice (voice); p1 &= ~0x20; /* * Disable intr */ gus_voice_on (p1); RESTORE_INTR (flags); break; case _GUS_VOICEOFF: DISABLE_INTR (flags); gus_select_voice (voice); gus_voice_off (); RESTORE_INTR (flags); break; case _GUS_VOICEFADE: DISABLE_INTR (flags); gus_select_voice (voice); gus_voice_fade (voice); RESTORE_INTR (flags); break; case _GUS_VOICEMODE: DISABLE_INTR (flags); gus_select_voice (voice); p1 &= ~0x20; /* * Disable intr */ gus_voice_mode (p1); RESTORE_INTR (flags); break; case _GUS_VOICEBALA: DISABLE_INTR (flags); gus_select_voice (voice); gus_voice_balance (p1); RESTORE_INTR (flags); break; case _GUS_VOICEFREQ: DISABLE_INTR (flags); gus_select_voice (voice); gus_voice_freq (plong); RESTORE_INTR (flags); break; case _GUS_VOICEVOL: DISABLE_INTR (flags); gus_select_voice (voice); gus_voice_volume (p1); RESTORE_INTR (flags); break; case _GUS_VOICEVOL2: /* * Just update the voice value */ voices[voice].initial_volume = voices[voice].current_volume = p1; break; case _GUS_RAMPRANGE: if (voices[voice].mode & WAVE_ENVELOPES) break; /* * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); gus_ramp_range (p1, p2); RESTORE_INTR (flags); break; case _GUS_RAMPRATE: if (voices[voice].mode & WAVE_ENVELOPES) break; /* * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); gus_ramp_rate (p1, p2); RESTORE_INTR (flags); break; case _GUS_RAMPMODE: if (voices[voice].mode & WAVE_ENVELOPES) break; /* * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); p1 &= ~0x20; /* * Disable intr */ gus_ramp_mode (p1); RESTORE_INTR (flags); break; case _GUS_RAMPON: if (voices[voice].mode & WAVE_ENVELOPES) break; /* * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); p1 &= ~0x20; /* * Disable intr */ gus_rampon (p1); RESTORE_INTR (flags); break; case _GUS_RAMPOFF: if (voices[voice].mode & WAVE_ENVELOPES) break; /* * NO-NO */ DISABLE_INTR (flags); gus_select_voice (voice); gus_rampoff (); RESTORE_INTR (flags); break; case _GUS_VOLUME_SCALE: volume_base = p1; volume_scale = p2; break; case _GUS_VOICE_POS: DISABLE_INTR (flags); gus_select_voice (voice); gus_set_voice_pos (voice, plong); RESTORE_INTR (flags); break; default:; }}gus_sampling_set_speed (int speed){ if (speed <= 0) return gus_sampling_speed; if (speed > 44100) speed = 44100; gus_sampling_speed = speed; return speed;}static intgus_sampling_set_channels (int channels){ if (!channels) return gus_sampling_channels; if (channels > 2) channels = 2; if (channels < 1) channels = 1; gus_sampling_channels = channels; return channels;}static intgus_sampling_set_bits (int bits){ if (!bits) return gus_sampling_bits; if (bits != 8 && bits != 16) bits = 8; gus_sampling_bits = bits; return bits;}static intgus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local){ switch (cmd) { case SOUND_PCM_WRITE_RATE: if (local) return gus_sampling_set_speed (arg); return IOCTL_OUT (arg, gus_sampling_set_speed (IOCTL_IN (arg))); break; if (local) return gus_sampling_speed; return IOCTL_OUT (arg, gus_sampling_speed); break; case SNDCTL_DSP_STEREO: if (local) return gus_sampling_set_channels (arg + 1) - 1; return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg) + 1) - 1); break; case SOUND_PCM_WRITE_CHANNELS: if (local) return gus_sampling_set_channels (arg); return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg))); break; case SOUND_PCM_READ_CHANNELS: if (local) return gus_sampling_channels; return IOCTL_OUT (arg, gus_sampling_channels); break; case SNDCTL_DSP_SAMPLESIZE: if (local) return gus_sampling_set_bits (arg); return IOCTL_OUT (arg, gus_sampling_set_bits (IOCTL_IN (arg))); break; case SOUND_PCM_READ_BITS: if (local) return gus_sampling_bits; return IOCTL_OUT (arg, gus_sampling_bits); case SOUND_PCM_WRITE_FILTER: /* * NOT YET IMPLEMENTED */ return IOCTL_OUT (arg, RET_ERROR (EINVAL)); break; case SOUND_PCM_READ_FILTER: return IOCTL_OUT (arg, RET_ERROR (EINVAL)); break; default: return RET_ERROR (EINVAL); } return RET_ERROR (EINVAL);}static voidgus_sampling_reset (int dev){}static intgus_sampling_open (int dev, int mode){#ifdef GUS_NO_DMA printk ("GUS: DMA mode not enabled. Device not supported\n"); return RET_ERROR (ENXIO);#endif if (gus_busy) return RET_ERROR (EBUSY); gus_initialize (); gus_busy = 1; active_device = 0; gus_reset (); reset_sample_memory (); gus_select_max_voices (14); pcm_active = 0; pcm_opened = 1; if (mode & OPEN_READ) { recording_active = 1; set_input_volumes(); } return 0;}static voidgus_sampling_close (int dev){ gus_reset (); gus_busy = 0; pcm_opened = 0; active_device = 0; if (recording_active) set_input_volumes(); recording_active = 0;}static voidgus_sampling_update_volume (void){ unsigned long flags; int voice; DISABLE_INTR (flags); if (pcm_active && pcm_opened) for (voice = 0; voice < gus_sampling_channels; voice++) { gus_select_voice (voice); gus_rampoff (); gus_voice_volume (1530 + (25 * gus_pcm_volume)); gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); } RESTORE_INTR (flags);}static voidplay_next_pcm_block (void){ unsigned long flags; int speed = gus_sampling_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_sampling_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_sampling_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 of the DRAM buffers */ { mode[chn] |= 0x08; /* * Enable loop */ ramp_mode[chn] = 0x03; /* * Disable rollover */ } else { if (chn == 0) ramp_mode[chn] = 0x04; /* * Enable rollover bit */ } DISABLE_INTR (flags); gus_select_voice (chn); gus_voice_freq (speed); if (gus_sampling_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) /* * Voice not started yet */ { /* * The playback was not started yet (or there has been a pause). * Start the voice (again) and ask for a rollover irq at the end of * this_one block. If this_one one is last of the buffers, use just * the normal loop with irq. */ gus_voice_off (); /* * It could already be running */ gus_rampoff (); gus_voice_volume (1530 + (25 * gus_pcm_volume)); gus_ramp_range (65, 1530 + (25 * gus_pcm_volume)); gus_write_addr (0x0a, dram_loc, is16bits); /* * Starting position */ gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* * Loop start * location */ if (chn != 0) gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk), is16bits); /* * Loop end location */ } if (chn == 0) gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* * Loop * end * location */ else mode[chn] |= 0x08; /* * Enable loop */ if (pcm_datasize[this_one] != pcm_bsize) { /* * Incomplete block. Possibly the last one. */ if (chn == 0) { mode[chn] &= ~0x08; /* * Disable loop */ mode[chn] |= 0x20; /* * Enable loop IRQ */ voices[0].loop_irq_mode = LMODE_PCM_STOP; ramp_mode[chn] = 0x03; /* * No rollover bit */ } else { gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* * Loop * end * location */ mode[chn] &= ~0x08; /* * Disable loop */ } } RESTORE_INTR (flags); } for (chn = 0; chn < gus_sampling_channels; chn++) { DISABLE_INTR (flags); gus_select_voice (chn); gus_write8 (0x0d, ramp_mode[chn]); gus_voice_on (mode[chn]); RESTORE_INTR (flags); } pcm_active = 1;}static voidgus_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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -