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

📄 pspan_lib.c

📁 adlink master board 6760 pci driver for control powerspan slave pci driver
💻 C
📖 第 1 页 / 共 3 页
字号:
	d  |= (unsigned short) PSPAN_EepromByteRead(hPlx, addr);
	return d;
}


////////////////////////////////////////////////////////////////////////////////// 
// DMA begin


/******************************************************************************
* NAME: PSPdirectModeDMA
*
* DESCRIPTION: setup and launch direct mode DMA transfer with the specified channel
*
* INPUT PARAMETERS:
*    src_addr          source address 
*    dst_addr          destination address
*    src_port          source port (PB/PCI1)
*    dst_port          destination port (PB/PCI1)
*    byte_count        byte count (>0)
*    channel           DMA channel number 0-3
*
* RETURN VALUES:  OK/ERROR
*
*******************************************************************************/
int PSPAN_directModeDMA(PSPAN_HANDLE hPlx,
                        unsigned long src_addr,
                        unsigned long dst_addr,
                        unsigned long src_port,
                        unsigned long dst_port,
                        unsigned long byte_count,
                        unsigned long channel )
{
   int retval = OK;
   
   unsigned long read_val;
   unsigned long temp;
   int i;
   
   if (channel > 3)
   {
      return (ERROR);
   }

   /* make sure DMA channel x is not active */
   read_val = PSPAN_ReadReg ( hPlx, T_DMA0_GCSR + channel*0x30);
   temp = read_val & DMAx_GCR_DACT_MASK;

   if ( temp != 0 )
   {
      pspan_lib_printf("DMA channel %d is not active\n",channel);
      return (ERROR);
   }
   else
   {
      /* DMA is not active */
      
      /* program source/dest ports and byte count, endian */
      if (src_port != dst_port)
      {
         temp = 0x08000000;     /* big endian */
         //temp = 0x04000000;   /* PowerPC little endian */
      }
      else
      {
         temp = 0; /* little endian */
      }
      switch (src_port)
      {
         case PCI1 :
            temp = temp | DMAx_TCR_SRC_PORT_P1_VAL;
            break;
         case PB :
            temp = temp | DMAx_TCR_SRC_PORT_PB_VAL;
            break;
         default:
            /* other value not allowed */
            pspan_lib_printf("Incorrect Source port %d\n", src_port);
            break;
      }
      switch (dst_port)
      {
         case PCI1 :
            temp = temp | DMAx_TCR_DST_PORT_P1_VAL;
            break;
         case PB :
            temp = temp | DMAx_TCR_DST_PORT_PB_VAL;
            break;
         default :
            /* other value not allowed */
            pspan_lib_printf("Incorrect destination port %d\n", dst_port);
            break;
      }
      
      temp = temp | ( DMAx_TCR_BC_MASK & byte_count );
      
      /* source and destination addresses, tcr register and zero out DMAx_CPP */

      PSPAN_WriteReg(hPlx, T_DMA0_SRC_ADDR + channel*0x30, src_addr);
      PSPAN_WriteReg(hPlx, T_DMA0_DST_ADDR + channel*0x30, dst_addr);
      PSPAN_WriteReg(hPlx, T_DMA0_TCR + channel*0x30, temp);
      PSPAN_WriteReg(hPlx, T_DMA0_CPP + channel*0x30, 0);
      PSPAN_WriteReg(hPlx, T_DMA0_ATTR + channel*0x30, PSPAN_ReadReg(hPlx, T_DMA0_ATTR + channel*0x30) | DMAx_ATTR_CI_MASK);

      /* set GO bit and clear all status bits at the same time */

      temp = read_val & 0x00000007; /* don't clear interrupt enable bits if set */
      temp |= DMAx_GCR_GO_MASK | 
			    DMAx_GCR_P1_ERR_MASK | 
			    DMAx_GCR_P2_ERR_MASK | 
			    DMAx_GCR_PB_ERR_MASK | 
			    DMAx_GCR_STOP_MASK | 
			    DMAx_GCR_HALT_MASK | 
			    DMAx_GCR_DONE_MASK;

      PSPAN_WriteReg(hPlx, T_DMA0_GCSR + channel*0x30, temp);
      for ( i = 0; i < 1000; i++ );			/* 100 wait a bit */
      temp = PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30);
      
      temp &= DMAx_GCR_DACT_MASK;
      if ( !temp )
      {
	      pspan_lib_printf( "ERROR:  DMA%d_GCSR[DACT] NOT Set!!\n", channel );
	      retval = ERROR;
      }
      
   }

   return ( retval );
   
} /* PowerSpan_Direct_Mode_DMA */


/****************************************************************************
* NAME: PSPAN_isDMADone
*
* DESCRIPTION: Check to see if DMA in specified channel is done
*
* INPUT PARAMETERS:
*    channel           DMA channel number 0-3
*
* RETURN VALUES: OK/ERROR
*
*******************************************************************************/
int PSPAN_isDMADone(PSPAN_HANDLE hPlx,unsigned long channel )
{
   int           retval;
   
   unsigned long read_val;
   unsigned long temp;

   if (channel > 3)
   {
      return (ERROR);
   }

   read_val = PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30);
   
   // test DMA active bit in the DMA_GCSR register 
   temp = read_val & DMAx_GCR_DACT_MASK; 
   
   if ( temp == 0 )
      retval = OK;
   else
      retval = ERROR;
   
   return ( retval );
} /* Is_PowerSpan_DMA_Done */


/******************************************************************************
* NAME: PSPAN_checkDMAStatus
*
* DESCRIPTION: Check to see if the error status bits in the specified channel are set
*
* INPUT PARAMETERS:
*    channel           DMA channel number 0-3
* OUTPUT PARAMETERS:
*
* RETURN VALUES: OK/ERROR
*
*******************************************************************************/
int PSPAN_checkDMAStatus(PSPAN_HANDLE hPlx, unsigned long channel )
{
   int           retval = OK;
   unsigned long read_val;
   
   if (channel > 3)
   {
      return (ERROR);
   }
   
   read_val = PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30);

   if ( (read_val & DMAx_GCR_P1_ERR_MASK) == 0 &&
    (read_val & DMAx_GCR_P2_ERR_MASK) == 0 &&
    (read_val & DMAx_GCR_PB_ERR_MASK) == 0 &&
    (read_val & DMAx_GCR_DONE_MASK) == DMAx_GCR_DONE_MASK )
   {
      retval = OK;
   }
   else
   {
      pspan_lib_printf( "Error, DMA%d_GCSR = %08x\n", channel, read_val );
      retval = ERROR;  /* DMA ended with errors */
   }

   return ( retval );
   
} // Check_PowerSpan_DMA_Status 


/******************************************************************************
* NAME: PSPAN_createCommandPacket
*
* DESCRIPTION: Generates a command packet at the address p_PowerSpanCmdPktDef
*
* INPUT PARAMETERS:
*
*    p_PowerSpanCmdPktDef  pointer to a command packet structure
*    src_addr              source address 
*    dst_addr              destination address
*    src_port              source port (PB/PCI1)
*    dst_port              destination port (PB/PCI1)
*    byte_count            byte count (>0)
*    next_cmd_pkt_ptr      32 byte aligned address to next command packet
*    last                  last command packet (TRUE/FALSE)
* OUTPUT PARAMETERS:
*
* RETURN VALUES: OK/ERROR
*
*******************************************************************************/
int PSPAN_createCommandPacket( struct PowerSpanCmdPktDef *p_PowerSpanCmdPktDef,
                                      unsigned long src_addr,
                                      unsigned long dst_addr,
                                      unsigned long src_port,
                                      unsigned long dst_port,
                                      unsigned long byte_count,
                                      struct PowerSpanCmdPktDef*  next_cmd_pkt_ptr,
                                      unsigned long last )
{
  int retval;
  unsigned long temp;

  retval = OK;
  /* source and dest addresses */
  p_PowerSpanCmdPktDef->DMAx_SRC_ADDR = NET_SWAP32(src_addr);
  p_PowerSpanCmdPktDef->DMAx_DST_ADDR = NET_SWAP32(dst_addr);

  /* src/dest ports and byte count - endian */
  if (src_port != dst_port)
  {
     temp = 0x08000000; /* big endian */
  }
  else
  {
     temp = 0; /* little endian */
  }
  
  switch (src_port)
  {
      case PCI1 :
         temp = temp | DMAx_TCR_SRC_PORT_P1_VAL;
         break;
      case PB :
         temp = temp | DMAx_TCR_SRC_PORT_PB_VAL;
         break;
      default:
         /* other value not allowed */
         break;
   }
   
   switch (dst_port)
   {
      case PCI1 :
         temp = temp | DMAx_TCR_DST_PORT_P1_VAL;
         break;
      case PB :
         temp = temp | DMAx_TCR_DST_PORT_PB_VAL;
         break;
      default :
         /* other value not allowed */
         break;
   }
      
   temp = temp | ( DMAx_TCR_BC_MASK & byte_count );
   p_PowerSpanCmdPktDef->DMAx_TCR = NET_SWAP32(temp);
   
   temp = 0;
   /* pointer to next cmd packet */
   temp = (unsigned long) next_cmd_pkt_ptr & DMAx_CPP_NCP_MASK;
   
   if ( last == TRUE )
      temp = temp | DMAx_CPP_LAST_MASK;
   
   p_PowerSpanCmdPktDef->DMAx_CPP = NET_SWAP32(temp);

  return ( retval );
} /* PowerSpan_Create_Command_Packet */


/******************************************************************************
* NAME: PSPAN_linkedListDMA
*
* DESCRIPTION: linked list mode DMA that polls the DMAx_GCSR[DACT] bit until 
*              done.  DMA is performed with channel 0.
*
* INPUT PARAMETERS:
*    cmd_ppkt          pointer to a command packet structure
*    cmd_pkt_port      port from wich load the first command packet ()
*    channel           DMA channel number 0-3
* OUTPUT PARAMETERS:
*
* RETURN VALUES: OK/ERROR
*
*******************************************************************************/
int PSPAN_linkedListDMA( PSPAN_HANDLE hPlx,
                         struct PowerSpanCmdPktDef *cmd_ppkt,
                         unsigned long cmd_pkt_port,
                         unsigned long channel)
{
   unsigned long retval = OK, read_val;
   unsigned long temp, cp_port_val, i;
   
   if (channel > 3)
   {
      return (ERROR);
   }

	/* make sure DMA channel x is not active */
   read_val = PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30);
   temp = read_val & DMAx_GCR_DACT_MASK;

   if ( temp != 0 ) retval = ERROR;
   else
   {
      switch (cmd_pkt_port)
      {
        case PCI1 :
           cp_port_val = DMAx_ATTR_CPA_PORT_P1_VAL ;
           break;
        case PB :
           cp_port_val = DMAx_ATTR_CPA_PORT_PB_VAL ;
           break;
        default:
           /* other value not allowed */
           retval = ERROR;
           break;
      }
  
      /* Disable DMA Stop, Halt and Done Interrupts */
      PSPAN_WriteReg(hPlx, T_DMA0_GCSR + channel*0x30,
                PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30) & ~0x00000007);
      /* and ensure DMAx_TCR[BC]=0 */
      PSPAN_WriteReg(hPlx, T_DMA0_TCR + channel*0x30, 0);
      /* set address of command packet */
      PSPAN_WriteReg(hPlx, T_DMA0_CPP + channel*0x30, (unsigned long) cmd_ppkt & DMAx_CPP_NCP_MASK);
      /* set CPA_PORT in DMAx_ATTR to PB */
      temp = PSPAN_ReadReg(hPlx, T_DMA0_ATTR + channel*0x30);
      temp = temp & ~DMAx_ATTR_CPA_PORT_MASK;    /* zero out CPA_PORT */
      temp = temp | cp_port_val;   /* set CPA_PORT to cmd_pkt_port */ 
      PSPAN_WriteReg(hPlx, T_DMA0_ATTR + channel*0x30, temp);
      
      /* set GO and CHAIN bits and clear all status bits at the same time */
      temp = 0;
      temp = DMAx_GCR_GO_MASK | 
            DMAx_GCR_CHAIN_MASK | 
            DMAx_GCR_P1_ERR_MASK | 
            DMAx_GCR_P2_ERR_MASK | 
            DMAx_GCR_PB_ERR_MASK | 
            DMAx_GCR_STOP_MASK | 
            DMAx_GCR_HALT_MASK | 
            DMAx_GCR_DONE_MASK;
            
      /* if want to keep STOP_EN, HALT_EN, and DONE_EN set */
      /* temp = temp | 0x00000007;*/
      temp |= 0x00000001;       // enable DONE_EN set added by pgn
      PSPAN_WriteReg(hPlx, T_DMA0_GCSR + channel*0x30, temp);
      for ( i = 0; i < 100; i++ );			/* wait a bit */
      temp = PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30);
   
      temp &= DMAx_GCR_DACT_MASK;
      if ( !temp )
      {
        pspan_lib_printf( "ERROR:  DMA%d_GCSR[DACT] NOT Set!!\n", channel );
        retval = ERROR;
      }
      
   }

   return ( retval );
}


/******************************************************************************
* NAME: PSPAN_configureDMAInterrupts
*
* DESCRIPTION: initialize registers for DMA interrupt test
*
* INPUT PARAMETERS: DMA channel to test
*
* OUTPUT PARAMETERS: none
*
* RETURN VALUES: none
*
*******************************************************************************/
void PSPAN_configureDMAInterrupts(PSPAN_HANDLE hPlx,unsigned long  channel)
{
   int i;
	
   // No interrupt source enabled 
   // the following two line added by pgn for debug use   
   PSPAN_WriteReg(hPlx, T_IER0, 0x00000000);	
   PSPAN_WriteReg(hPlx, T_IER1, 0x00000000);	
       
   
   // DMAX0-3 to -INTA 
   PSPAN_WriteReg(hPlx, T_IMR_DMA, 0x00000000);	
    
   // interrupts direction : INTA as output 
   PSPAN_WriteReg(hPlx, T_IDR, PSPAN_ReadReg(hPlx, T_IDR) | 0x40000000);	

    // disable DMA interrupts STOP_EN, HALT_EN, and enable DONE_EN 
   PSPAN_WriteReg(hPlx, T_DMA0_GCSR + channel*0x30, PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30) | 0x00000001);
   for ( i = 0; i < 100; i++ );			                // wait a bit 
   PSPAN_ReadReg(hPlx, T_DMA0_GCSR + channel*0x30);     // read to flush 
   
    // clear DMA interrupts bit in ISR0 
   PSPAN_WriteReg(hPlx, T_ISR0, PSPAN_ReadReg(hPlx, T_ISR0) | (0x01000000 << channel));
   for ( i = 0; i < 100; i++ );			        // wait a bit 
   PSPAN_ReadReg(hPlx, T_ISR0);                 // read to flush 
   
   // enable DMAx_EN and disable all other interrupts in IER0 and IER1 registers 
   PSPAN_WriteReg(hPlx, T_IER0, (0x01000000 << channel));
   for ( i = 0; i < 100; i++ );			        // wait a bit 
   PSPAN_ReadReg(hPlx, T_IER0);                 // read to flush 

}

//  DMA process end
//////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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