📄 pspan_lib.c
字号:
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 + -