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

📄 sb16_dsp.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
  int             i;

  for (i = 0; i < SB_TIMEOUT; i++)
  {
    if ((in_byte (DSP_STATUS) & 0x80) == 0)
    {
      out_byte (DSP_COMMAND, value);
      return OK;
    }
  }

  printf ("sb16: SoundBlaster: DSP Command(%x) timeout\n", value);
  return -1;
}


/*=========================================================================*
 *				dsp_reset				   *
 *=========================================================================*/
PRIVATE int dsp_reset(void)
{
  int i;

  out_byte (DSP_RESET, 1);
  for(i =0; i<1000; i++); /* wait a while */
  out_byte (DSP_RESET, 0);

  for (i = 0; i < 1000 && !(in_byte (DSP_DATA_AVL) & 0x80); i++);	

  if (in_byte (DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */			

  DmaBusy = 0;
  DmaDone = 1;

  return OK;
}


/*=========================================================================*
 *				dsp_set_speed				   *
 *=========================================================================*/
static int dsp_set_speed(speed)
unsigned int speed;
{
#if SB_DEBUG
  printf("sb16: setting speed to %u, stereo = %d\n", speed, DspStereo);
#endif

  if (speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED)
    return EPERM;

  /* Soundblaster 16 can be programmed with real sample rates
   * instead of time constants
   *
   * Since you cannot sample and play at the same time
   * we set in- and output rate to the same value 
   */

   lock();   		        		/* disable interrupts */
   dsp_command(DSP_INPUT_RATE);			/* set input rate */
   dsp_command(speed >> 8);			/* high byte of speed */
   dsp_command(speed);			 	/* low byte of speed */
   dsp_command(DSP_OUTPUT_RATE);		/* same for output rate */
   dsp_command(speed >> 8);	
   dsp_command(speed); 
   unlock();					/* enable interrupts */

   DspSpeed = speed;

   return OK;
}


/*=========================================================================*
 *				dsp_set_stereo				   *
 *=========================================================================*/
static int dsp_set_stereo(stereo)
unsigned int stereo;
{
  if (stereo) 
    DspStereo = 1;
  else 
    DspStereo = 0;

  return OK;
}


/*=========================================================================*
 *				dsp_set_bits				   *
 *=========================================================================*/
static int dsp_set_bits(bits)
unsigned int bits;
{
  /* Sanity checks */
  if (bits != 8 && bits != 16) return EINVAL;

  DspBits = bits; 

  return OK;
}


/*=========================================================================*
 *				dsp_set_size				   *
 *=========================================================================*/
static int dsp_set_size(size)
unsigned int size;
{

#if SB_DEBUG
  printf("sb16: set fragment size to %u\n", size);
#endif
 
  /* Sanity checks */
  if (size < DSP_MIN_FRAGMENT_SIZE || 
      size > DSP_MAX_FRAGMENT_SIZE || 
      size % 2 != 0)
    return EINVAL;

  DspFragmentSize = size; 

  return OK;
}


/*=========================================================================*
 *				dsp_set_sign				   *
 *=========================================================================*/
static int dsp_set_sign(sign)
unsigned int sign;
{

#if SB_DEBUG
  printf("sb16: set sign to %u\n", sign);
#endif
 
  DspSign = (sign > 0 ? 1 : 0); 

  return OK;
}


/*===========================================================================*
 *				dsp_dma_setup				     *
 *===========================================================================*/
PRIVATE void dsp_dma_setup(address, count)
phys_bytes address;
int count;

{
#if SB_DEBUG
  printf("Setting up %d bit DMA\n", DspBits);
#endif

  if (DspBits == 8)    /* 8 bit sound */
  {
    count--;     

    lock();
    out_byte(DMA8_MASK, SB_DMA_8 | 0x04);      /* Disable DMA channel */
    out_byte(DMA8_CLEAR, 0x00);		       /* Clear flip flop */

    /* set DMA mode */
    out_byte(DMA8_MODE, 
               (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC)); 

    out_byte(DMA8_ADDR, address >>  0);        /* Low_byte of address */
    out_byte(DMA8_ADDR, address >>  8);        /* High byte of address */
    out_byte(DMA8_PAGE, address >> 16);        /* 64K page number */
    out_byte(DMA8_COUNT, count >> 0);          /* Low byte of count */
    out_byte(DMA8_COUNT, count >> 8);          /* High byte of count */
    out_byte(DMA8_MASK, SB_DMA_8);	       /* Enable DMA channel */
    unlock();
  }
  else  /* 16 bit sound */
  {
    count-= 2;

    lock();
    out_byte(DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */
    out_byte(DMA16_CLEAR, 0x00);                  /* Clear flip flop */

    /* Set dma mode */
    out_byte(DMA16_MODE, 
               (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));        

    out_byte(DMA16_ADDR, (address >> 1) & 0xFF);  /* Low_byte of address */
    out_byte(DMA16_ADDR, (address >> 9) & 0xFF);  /* High byte of address */
    out_byte(DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
    out_byte(DMA16_COUNT, count >> 1);            /* Low byte of count */
    out_byte(DMA16_COUNT, count >> 9);            /* High byte of count */
    out_byte(DMA16_MASK, SB_DMA_16 & 3);          /* Enable DMA channel */
    unlock();
  }
}


/*===========================================================================*
 *				dsp_setup				     *
 *===========================================================================*/
PRIVATE void dsp_setup()
{ 
  /* Set current sample speed */
  dsp_set_speed(DspSpeed);

  /* Put the speaker on */
   if (DmaMode == DEV_WRITE)
   {
     dsp_command (DSP_CMD_SPKON); /* put speaker on */

      /* Program DSP with dma mode */
      dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT));     
   }
   else
   {
     dsp_command (DSP_CMD_SPKOFF); /* put speaker off */

     /* Program DSP with dma mode */
     dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN));     
   }

  /* Program DSP with transfer mode */
  if (!DspSign)
    dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US));
  else
    dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S));

  /* Give length of fragment to DSP */
  if (DspBits == 8) /* 8 bit transfer */
  {
    /* #bytes - 1 */
    dsp_command((DspFragmentSize - 1) >> 0); 
    dsp_command((DspFragmentSize - 1) >> 8);
  }
  else              /* 16 bit transfer */
  {
    /* #words - 1 */
    dsp_command((DspFragmentSize - 1) >> 1);
    dsp_command((DspFragmentSize - 1) >> 9);
  }
}
      

/*===========================================================================*
 *				dsp_write				     *
 *===========================================================================*/
PRIVATE int dsp_write(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  message mess;

  if (m_ptr->COUNT != DspFragmentSize) return EINVAL;

  /* From this user address */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, DspFragmentSize);
  if (user_phys == 0) return EINVAL;

  if (DmaBusy)    /* Dma already started */
  {
    if (DmaMode != m_ptr->m_type) return EBUSY;

    DmaDone = 0;  /* No, we're not done yet */

    /* Wait for next block to become free */
    receive(HARDWARE, &mess); 

    /* Copy first block to dma buffer */
    phys_copy(user_phys, DmaPhys, (phys_bytes) DspFragmentSize);

  }
  else /* A new dma transfer has started */    
  {
    DmaMode = DEV_WRITE;           /* Dma mode is writing */

    /* Copy fragment to dma buffer */    
    phys_copy(user_phys, DmaPhys, (phys_bytes) DspFragmentSize);

    /* Set up the dma chip */
    dsp_dma_setup(DmaPhys, DspFragmentSize);  

    /* Set up the DSP */
    dsp_setup();
      
    DmaBusy = 1;         /* Dma is busy */
  }

  DmaDone = 1;            /* dma done for now */

  return(DspFragmentSize);
}


/*===========================================================================*
 *				dsp_read				     *
 *===========================================================================*/
PRIVATE int dsp_read(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  message mess;
 
  if (m_ptr->COUNT != DspFragmentSize) return EINVAL;

  /* To this user address */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, DspFragmentSize);
  if (user_phys == 0) return EINVAL;

  if (DmaBusy)     /* Dma already started */
  {
    if (DmaMode != m_ptr->m_type) return EBUSY;

    DmaDone = 0;   /* No, we're not done yet */ 

    /* Wait for a full dma buffer */
    receive(HARDWARE, &mess); 

    /* Copy the buffer */
    phys_copy(DmaPhys, user_phys, (phys_bytes) DspFragmentSize);
  }
  else  /* A new dma transfer has started */
  {
    DmaMode = DEV_READ;                /* Dma mode is reading */

    /* Set up the dma chip */
    dsp_dma_setup(DmaPhys, DspFragmentSize);  
 
    /* Set up the DSP */
    dsp_setup();

    DmaBusy = 1;       /* Dma has started */
    DmaDone = 0;       /* Dma not done */

    /* Wait for dma to finish with first block */
    receive(HARDWARE, &mess);

    /* Copy dma buffer to user */
    phys_copy(DmaPhys, user_phys, (phys_bytes) DspFragmentSize);
  }

  DmaDone = 1;   /* dma done for now */

  return(DspFragmentSize);
}
#endif /* ENABLE_AUDIO */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -