📄 sb_dsp.c
字号:
dsp_speaker (OFF); sb_irq_mode = IMODE_INPUT; DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); if (sound_dsp_dmachan[dev] > 3) count >>= 1; count--; if (sb_dsp_highspeed) { DISABLE_INTR (flags); if (sb_dsp_command (0x48)) /* High speed size */ { sb_dsp_command ((unsigned char)(count & 0xff)); sb_dsp_command ((unsigned char)((count >> 8) & 0xff)); sb_dsp_command (0x99); /* High speed 8 bit ADC */ } else printk ("SB Error: Unable to start (high speed) ADC\n"); RESTORE_INTR (flags); } else { DISABLE_INTR (flags); if (sb_dsp_command (0x24)) /* 8-bit ADC (DMA) */ { sb_dsp_command ((unsigned char)(count & 0xff)); sb_dsp_command ((unsigned char)((count >> 8) & 0xff)); } else printk ("SB Error: Unable to start ADC\n"); RESTORE_INTR (flags); } sb_intr_active = 1;}static voiddsp_cleanup (void){ sb_intr_active = 0;}static intsb_dsp_prepare_for_input (int dev, int bsize, int bcount){ dsp_cleanup (); dsp_speaker (OFF); if (major == 3) /* SB Pro */ { if (dsp_stereo) sb_dsp_command(0xa8); else sb_dsp_command(0xa0); dsp_speed (dsp_current_speed);/* Speed must be recalculated if #channels * changes */ } return 0;}static intsb_dsp_prepare_for_output (int dev, int bsize, int bcount){ dsp_cleanup (); dsp_speaker (ON);#ifndef EXCLUDE_SBPRO if (major == 3) /* SB Pro */ { sb_mixer_set_stereo(dsp_stereo); dsp_speed (dsp_current_speed);/* Speed must be recalculated if #channels * changes */ }#endif return 0;}static voidsb_dsp_halt_xfer (int dev){}static intverify_irq (void){#if 0 DEFINE_WAIT_QUEUE(testq, testf); irq_ok = 0; if (sb_get_irq () == -1) { printk ("*** SB Error: Irq %d already in use\n", sbc_irq); return 0; } sb_irq_mode = IMODE_INIT; sb_dsp_command (0xf2); /* This should cause immediate interrupt */ DO_SLEEP(testq, testf, HZ / 5); sb_free_irq(); if (!irq_ok) { printk ("SB Warning: IRQ%d test not passed!", sbc_irq); irq_ok = 1; }#else irq_ok = 1;#endif return irq_ok;}static intsb_dsp_open (int dev, int mode){ int retval; if (!sb_dsp_ok) { printk ("SB Error: SoundBlaster board not installed\n"); return RET_ERROR (ENXIO); } if (sb_intr_active || (sb_midi_busy && sb_midi_mode == UART_MIDI)) { printk ("SB: PCM not possible during MIDI input\n"); return RET_ERROR (EBUSY); } if (!irq_verified) { verify_irq(); irq_verified = 1; } else if (!irq_ok) printk("SB Warning: Incorrect IRQ setting %d\n", sbc_irq); retval = sb_get_irq (); if (retval) return retval; if (!DMAbuf_open_dma (dev)) { sb_free_irq (); printk ("SB: DMA Busy\n"); return RET_ERROR (EBUSY); } sb_irq_mode = IMODE_NONE; sb_dsp_busy = 1; return 0;}static voidsb_dsp_close (int dev){ DMAbuf_close_dma (dev); sb_free_irq (); dsp_cleanup (); dsp_speaker (OFF); sb_dsp_busy = 0; sb_dsp_highspeed = 0;}static intsb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local){ switch (cmd) { case SOUND_PCM_WRITE_RATE: if (local) return dsp_speed (arg); return IOCTL_OUT (arg, dsp_speed (IOCTL_IN (arg))); break; case SOUND_PCM_READ_RATE: if (local) return dsp_current_speed; return IOCTL_OUT (arg, dsp_current_speed); break; case SOUND_PCM_WRITE_CHANNELS: if (local) return dsp_set_stereo (arg - 1) + 1; return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1); break; case SOUND_PCM_READ_CHANNELS: if (local) return dsp_stereo + 1; return IOCTL_OUT (arg, dsp_stereo + 1); break; case SNDCTL_DSP_STEREO: if (local) return dsp_set_stereo (arg); return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg))); break; case SOUND_PCM_WRITE_BITS: case SOUND_PCM_READ_BITS: if (local) return 8; return IOCTL_OUT (arg, 8);/* Only 8 bits/sample supported */ break; case SOUND_PCM_WRITE_FILTER: case SOUND_PCM_READ_FILTER: return RET_ERROR (EINVAL); break; default: return RET_ERROR (EINVAL); } return RET_ERROR (EINVAL);}static voidsb_dsp_reset (int dev){ unsigned long flags; DISABLE_INTR (flags); sb_reset_dsp (); dsp_cleanup (); RESTORE_INTR (flags);}#endifintsb_dsp_detect (struct address_info *hw_config){ sbc_base = hw_config->io_base; sbc_irq = hw_config->irq; if (sb_dsp_ok) return 0; /* Already initialized */ if (!sb_reset_dsp ()) return 0; return 1; /* Detected */}#ifndef EXCLUDE_AUDIOstatic struct audio_operations sb_dsp_operations ={ "SoundBlaster", sb_dsp_open, sb_dsp_close, sb_dsp_output_block, sb_dsp_start_input, sb_dsp_ioctl, sb_dsp_prepare_for_input, sb_dsp_prepare_for_output, sb_dsp_reset, sb_dsp_halt_xfer, NULL, /* has_output_drained */ NULL /* copy_from_user */};#endiflongsb_dsp_init (long mem_start, struct address_info *hw_config){ int i; major = minor = 0; sb_dsp_command (0xe1); /* Get version */ for (i = 1000; i; i--) { if (INB (DSP_DATA_AVAIL) & 0x80) { /* wait for Data Ready */ if (major == 0) major = INB (DSP_READ); else { minor = INB (DSP_READ); break; } } } if (major == 2 || major == 3) sb_duplex_midi = 1; if (major == 4) sb16 = 1; if (major >= 3) sb_dsp_model = 2;#ifndef EXCLUDE_SBPRO if (major >= 3) sb_mixer_init(major);#endif#ifndef EXCLUDE_YM3812 if (major > 3 || (major == 3 && minor > 0)) /* SB Pro2 or later */ { enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); }#endif if (major >= 3) {#ifndef SCO sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", major, minor);#endif } else {#ifndef SCO sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", major, minor);#endif } printk (" <%s>", sb_dsp_operations.name);#ifndef EXCLUDE_AUDIO# if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO) if (!sb16) /* There is a better driver for SB16 */# endif if (num_dspdevs < MAX_DSP_DEV) { dsp_devs[my_dev = num_dspdevs++] = &sb_dsp_operations; sound_buffcounts[my_dev] = DSP_BUFFCOUNT; sound_buffsizes[my_dev] = DSP_BUFFSIZE; sound_dsp_dmachan[my_dev] = hw_config->dma; sound_dma_automode[my_dev] = 0; } else printk ("SB: Too many DSP devices available\n");#endif#ifndef EXCLUDE_MIDI if (!midi_disabled && !sb16) /* Midi don't work in the SB emulation mode * of PAS, SB16 has better midi interface */ sb_midi_init(major);#endif sb_dsp_ok = 1; return mem_start;}voidsb_dsp_disable_midi (void){ midi_disabled = 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -