⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb_dsp.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
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;  /* Allocate 8 bit dma   */  if (DMAbuf_open_dma (dev) < 0)    {      sb_free_irq ();      printk ("SB: DMA Busy\n");      return RET_ERROR (EBUSY);    }#ifdef JAZZ16  /* Allocate 16 bit dma   */  if (Jazz16_detected != 0)    if (dma16 != dma8)      {	if (ALLOC_DMA_CHN (dma16, "Jazz16 16 bit"))	  {	    sb_free_irq ();	    RELEASE_DMA_CHN (dma8);	    return RET_ERROR (EBUSY);	  }      }#endif  sb_irq_mode = IMODE_NONE;  sb_dsp_busy = 1;  open_mode = mode;  return 0;}static voidsb_dsp_close (int dev){#ifdef JAZZ16  /* Release 16 bit dma channel   */  if (Jazz16_detected)    RELEASE_DMA_CHN (dma16);#endif  DMAbuf_close_dma (dev);  sb_free_irq ();  dsp_cleanup ();  dsp_speaker (OFF);  sb_dsp_busy = 0;  sb_dsp_highspeed = 0;  open_mode = 0;}#ifdef JAZZ16/* Function dsp_set_bits() only required for 16 bit cards */static intdsp_set_bits (int arg){  if (arg)    if (Jazz16_detected == 0)      dsp_16bit = 0;    else      switch (arg)	{	case 8:	  dsp_16bit = 0;	  break;	case 16:	  dsp_16bit = 1;	  break;	default:	  dsp_16bit = 0;	}  return dsp_16bit ? 16 : 8;}#endif /* ifdef JAZZ16 */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;#ifdef JAZZ16      /* Word size specific cases here.         * SNDCTL_DSP_SETFMT=SOUND_PCM_WRITE_BITS       */    case SNDCTL_DSP_SETFMT:      if (local)	return dsp_set_bits (arg);      return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));      break;    case SOUND_PCM_READ_BITS:      if (local)	return dsp_16bit ? 16 : 8;      return IOCTL_OUT (arg, dsp_16bit ? 16 : 8);      break;#else    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;#endif /* ifdef JAZZ16  */    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_speed (dsp_current_speed);  dsp_cleanup ();  RESTORE_INTR (flags);}#endif#ifdef JAZZ16/* * Initialization of a Media Vision ProSonic 16 Soundcard. * The function initializes a ProSonic 16 like PROS.EXE does for DOS. It sets * the base address, the DMA-channels, interrupts and enables the joystickport. * * Also used by Jazz 16 (same card, different name) * * written 1994 by Rainer Vranken * E-Mail: rvranken@polaris.informatik.uni-essen.de */#ifndef MPU_BASE		/* take default values if not specified */#define MPU_BASE 0x330#endif#ifndef MPU_IRQ#define MPU_IRQ 9#endifunsigned intget_sb_byte (void){  int             i;  for (i = 1000; i; i--)    if (INB (DSP_DATA_AVAIL) & 0x80)      {	return INB (DSP_READ);      }  return 0xffff;}#ifdef SM_WAVE/* * Logitech Soundman Wave detection and initialization by Hannu Savolainen. * * There is a microcontroller (8031) in the SM Wave card for MIDI emulation. * it's located at address MPU_BASE+4.  MPU_BASE+7 is a SM Wave specific * control register for MC reset, SCSI, OPL4 and DSP (future expansion) * address decoding. Otherwise the SM Wave is just a ordinary MV Jazz16 * based soundcard. */static voidsmw_putmem (int base, int addr, unsigned char val){  unsigned long   flags;  DISABLE_INTR (flags);  OUTB (addr & 0xff, base + 1);	/* Low address bits */  OUTB (addr >> 8, base + 2);	/* High address bits */  OUTB (val, base);		/* Data */  RESTORE_INTR (flags);}static unsigned charsmw_getmem (int base, int addr){  unsigned long   flags;  unsigned char   val;  DISABLE_INTR (flags);  OUTB (addr & 0xff, base + 1);	/* Low address bits */  OUTB (addr >> 8, base + 2);	/* High address bits */  val = INB (base);		/* Data */  RESTORE_INTR (flags);  return val;}static intinitialize_smw (void){#ifdef SMW_MIDI0001_INCLUDED#include <i386/isa/sound/smw-midi0001.h>#else  unsigned char   smw_ucode[1];  int             smw_ucodeLen = 0;#endif  int             mp_base = MPU_BASE + 4;	/* Microcontroller base */  int             i;  unsigned char   control;  /*     *  Reset the microcontroller so that the RAM can be accessed   */  control = INB (MPU_BASE + 7);  OUTB (control | 3, MPU_BASE + 7);	/* Set last two bits to 1 (?) */  OUTB ((control & 0xfe) | 2, MPU_BASE + 7);	/* xxxxxxx0 resets the mc */  for (i = 0; i < 300; i++)	/* Wait at least 1ms */    tenmicrosec ();  OUTB (control & 0xfc, MPU_BASE + 7);	/* xxxxxx00 enables RAM */  /*     *  Detect microcontroller by probing the 8k RAM area   */  smw_putmem (mp_base, 0, 0x00);  smw_putmem (mp_base, 1, 0xff);  tenmicrosec ();  if (smw_getmem (mp_base, 0) != 0x00 || smw_getmem (mp_base, 1) != 0xff)    {      printk ("\nSM Wave: No microcontroller RAM detected (%02x, %02x)\n",	      smw_getmem (mp_base, 0), smw_getmem (mp_base, 1));      return 0;			/* No RAM */    }  /*     *  There is RAM so assume it's really a SM Wave   */#ifdef SMW_MIDI0001_INCLUDED  if (smw_ucodeLen != 8192)    {      printk ("\nSM Wave: Invalid microcode (MIDI0001.BIN) length\n");      return 1;    }#endif  /*     *  Download microcode   */  for (i = 0; i < 8192; i++)    smw_putmem (mp_base, i, smw_ucode[i]);  /*     *  Verify microcode   */  for (i = 0; i < 8192; i++)    if (smw_getmem (mp_base, i) != smw_ucode[i])      {	printk ("SM Wave: Microcode verification failed\n");	return 0;      }  control = 0;#ifdef SMW_SCSI_IRQ  /*     * Set the SCSI interrupt (IRQ2/9, IRQ3 or IRQ10). The SCSI interrupt     * is disabled by default.     *     * Btw the Zilog 5380 SCSI controller is located at MPU base + 0x10.   */  {    static unsigned char scsi_irq_bits[] =    {0, 0, 3, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0};    control |= scsi_irq_bits[SMW_SCSI_IRQ] << 6;  }#endif#ifdef SMW_OPL4_ENABLE  /*     *  Make the OPL4 chip visible on the PC bus at 0x380.     *     *  There is no need to enable this feature since VoxWare     *  doesn't support OPL4 yet. Also there is no RAM in SM Wave so     *  enabling OPL4 is pretty useless.   */  control |= 0x10;		/* Uses IRQ12 if bit 0x20 == 0 */  /* control |= 0x20;      Uncomment this if you want to use IRQ7 */#endif  OUTB (control | 0x03, MPU_BASE + 7);	/* xxxxxx11 restarts */  return 1;}#endifstatic intinitialize_ProSonic16 (void){  int             x;  static unsigned char int_translat[16] =  {0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6}, dma_translat[8] =  {0, 1, 0, 2, 0, 3, 0, 4};  OUTB (0xAF, 0x201);		/* ProSonic/Jazz16 wakeup */  for (x = 0; x < 1000; ++x)	/* wait 10 milliseconds */    tenmicrosec ();  OUTB (0x50, 0x201);  OUTB ((sbc_base & 0x70) | ((MPU_BASE & 0x30) >> 4), 0x201);  if (sb_reset_dsp ())    {				/* OK. We have at least a SB */      /* Check the version number of ProSonic (I guess) */      if (!sb_dsp_command (0xFA))	return 1;      if (get_sb_byte () != 0x12)	return 1;      if (sb_dsp_command (0xFB) &&	/* set DMA-channels and Interrupts */	  sb_dsp_command ((dma_translat[JAZZ_DMA16] << 4) | dma_translat[SBC_DMA]) &&      sb_dsp_command ((int_translat[MPU_IRQ] << 4) | int_translat[sbc_irq]))	{	  Jazz16_detected = 1;#ifdef SM_WAVE	  if (initialize_smw ())	    Jazz16_detected = 2;#endif	  sb_dsp_disable_midi ();	}      return 1;			/* There was at least a SB */    }  return 0;			/* No SB or ProSonic16 detected */}#endif /* ifdef JAZZ16  */intsb_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				 */#ifdef JAZZ16  dma8 = hw_config->dma;  dma16 = JAZZ_DMA16;  if (!initialize_ProSonic16 ())    return 0;#else  if (!sb_reset_dsp ())    return 0;#endif#ifdef PC98  switch (sbc_irq)    {    case 3:      sb_setmixer (IRQ_NR, 1);      break;    case 5:      sb_setmixer (IRQ_NR, 8);      break;    case 10:      sb_setmixer (IRQ_NR, 2);      break;    }  switch (hw_config->dma)    {    case 0:      sb_setmixer (DMA_NR, 1);      break;    case 3:      sb_setmixer (DMA_NR, 2);      break;    }#endif  return 1;			/*				 * Detected				 */}#ifndef EXCLUDE_AUDIOstatic struct audio_operations sb_dsp_operations ={  "SoundBlaster",  NOTHING_SPECIAL,  AFMT_U8,			/* Just 8 bits. Poor old SB */  NULL,  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,				/* local_qlen */  NULL				/* copy_from_user */};#endiflongsb_dsp_init (long mem_start, struct address_info *hw_config){  int             i;  int             mixer_type = 0;  sbc_major = sbc_minor = 0;  sb_dsp_command (0xe1);	/*				 * Get version				 */  for (i = 1000; i; i--)    {      if (INB (DSP_DATA_AVAIL) & 0x80)	{			/*				 * wait for Data Ready				 */	  if (sbc_major == 0)	    sbc_major = INB (DSP_READ);	  else	    {	      sbc_minor = INB (DSP_READ);	      break;	    }	}    }  if (sbc_major == 2 || sbc_major == 3)    sb_duplex_midi = 1;  if (sbc_major == 4)    sb16 = 1;#ifndef EXCLUDE_SBPRO  if (sbc_major >= 3)    mixer_type = sb_mixer_init (sbc_major);#else  if (sbc_major >= 3)    printk ("\n\n\n\nNOTE! SB Pro support is required with your soundcard!\n\n\n");#endif#ifndef EXCLUDE_YM3812#ifdef PC98  if (sbc_major > 3 ||      (sbc_major == 3 && INB (0x28d2) == 0x00))#else  if (sbc_major > 3 ||      (sbc_major == 3 && INB (0x388) == 0x00))	/* Should be 0x06 if not OPL-3 */#endif    enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH);#endif#ifndef EXCLUDE_AUDIO  if (sbc_major >= 3)    {      if (Jazz16_detected)	{	  if (Jazz16_detected == 2)	    sprintf (sb_dsp_operations.name, "SoundMan Wave %d.%d", sbc_major, sbc_minor);	  else	    sprintf (sb_dsp_operations.name, "MV Jazz16 %d.%d", sbc_major, sbc_minor);	  sb_dsp_operations.format_mask |= AFMT_S16_LE;		/* Hurrah, 16 bits          */	}      else#ifdef __SGNXPRO__      if (mixer_type == 2)	{	  sprintf (sb_dsp_operations.name, "Sound Galaxy NX Pro %d.%d", sbc_major, sbc_minor);	}      else#endif      if (sbc_major == 4)	{	  sprintf (sb_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);	}      else	{	  sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor);	}    }  else    {      sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor);    }#if defined(__FreeBSD__)  printk ("sb0: <%s>", sb_dsp_operations.name);#else  printk (" <%s>", sb_dsp_operations.name);#endif#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)  if (!sb16)			/*				 * There is a better driver for SB16				 */#endif    if (num_audiodevs < MAX_AUDIO_DEV)      {	audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;	audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT;	audio_devs[my_dev]->buffsize = (		(sbc_major > 2 || sbc_major == 2 && sbc_minor > 0) ?		16 : 8) * 1024;	audio_devs[my_dev]->dmachan = hw_config->dma;      }    else      printk ("SB: Too many DSP devices available\n");#else  printk (" <SoundBlaster (configured without audio support)>");#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 (sbc_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 + -