www.pudn.com > bcm1250-src.rar > dlicpa_dma.c


/*GENU#****************************************************************
* *
* ..GENERALITIES *
* *
*---------------------------------------------------------------------*
* *
* ..IDENTIFICATION: *
* ..MNAM: M.Thierauf *
* ..TITL: ldicpa_dma.c *
* ..READ: yy/mm/dd / <author> *
* ..REVW: 13/03/02 MTh *
* *
* ..DESCRIPTION: *
* ..APPL: ethernet driver for BCM1250 internal MAC *
* ..FUNC: DMA related functions *
* ..TYPE: *
* *
* ..CONTENTS: *
* *
****************************************************************UNEG#*/
/*DOCR#****************************************************************
* *
* ..Documentation *
* *
*--------------------------------------------------------------------*/

/*SPEC#********************************
* ..Specification *
**************************************/
/* TLD design specification SCM HdS
3CB 05111 AAAA DDZZA*/

/* VENUS HdS API specification
3FZ 70526 AAAA DSZZA */
/*TEST#********************************
* ..testing *
**************************************/
/*****************************************************************RCOD#*/

/*DPND#****************************************************************
* *
* ..Dependancies *
* *
*--------------------------------------------------------------------*/

/*EXTD#********************************
* ..inter-swbb *
**************************************/
/*INTD#********************************
* ..intra-swbb* *
**************************************/
/*****************************************************************PNPD#*/

/*HIST#****************************************************************
* *
* ..history *
* *
*--------------------------------------------------------------------*/
/*
13/03/02: create
*/
/*CHRQ#********************************
* ..change request *
**************************************/
/*PBRP#********************************
* ..problem report *
**************************************/
/*****************************************************************TSIH#*/

/*SDEV#****************************************************************
* *
* ..DEVELOPMENT SYMBOLS *
* *
*--------------------------------------------------------------------*/

/*LIBR#********************************
* ..LIBRARIES *
**************************************/
#include "dohmDI-up.h"
#include "dlicdd_dohm.h"

/*CSLT#********************************
* ..CONSTANTS *
**************************************/
/*****************************************************************VEDS#*/


/*SPRO#****************************************************************
* *
* ..PRODUCT SYMBOLS *
* *
*--------------------------------------------------------------------*/

/*LIBR#********************************
* ..LIBRARIES *
**************************************/
/*CSLT#********************************
* ..CONSTANTS *
**************************************/
/*DATS#********************************
* ..DATA STRUCTURES *
**************************************/
/*VARS#********************************
* ..VARIABLES *
**************************************/
/****************************************************************ORPS#*/

/*SEXT#****************************************************************
* *
* ..EXTERNAL SYMBOLS *
* *
*--------------------------------------------------------------------*/
/*LIBR#********************************
* ..LIBRARIES *
**************************************/
/*CSLT#********************************
* ..CONSTANTS *
**************************************/

/*VARS#********************************
* ..VARIABLES *
**************************************/

/*PROT#********************************
* ..PROTOTYPES *
**************************************/
/*SLOC#****************************************************************
* *
* ..LOCAL SYMBOLS *
* *
*--------------------------------------------------------------------*/
/*CSLT#********************************
* ..CONSTANTS *
**************************************/
/*DIAL#********************************
* ..DIALOG INTERFACES *
**************************************/

/*DATS#********************************
* ..DATA STRUCTURES *
**************************************/

/*VARS#********************************
* ..VARIABLES *
**************************************/

/*VARS#********************************
* ..MACRO *
**************************************/

/************************************************************************/
/* Receive Packet */
/************************************************************************/

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFsetup_RxRing *
* ..TITL: reset and initialize the DMA register *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFsetup_RxRing(dlicMdma_ctrl* pDma_ctrl, uint32_t macnum)
{
dlicMerror rc = 0;
uint32_t num;
uint64_t reg;

pDma_ctrl->channel = 0; /* always 0, not used, could provide QOS */
/* ToDo: get the address from Dohm descriptor */
pDma_ctrl->dmabase =
(uchar_t *)(PHYS_TO_K1(A_MAC_DMA_CHANNEL_BASE(macnum, DMA_RX, 0)));

pDma_ctrl->maxdescr = NUM_RDS_DEF;
pDma_ctrl->minRemAdd= NUM_RDS_DEF;
pDma_ctrl->txdir = DMA_RX;
pDma_ctrl->maxCount = 0;
pDma_ctrl->minCount = NUM_RDS_DEF;

/* allocate the ring structure + 32 byte to adjust the alignement*/
if( pDma_ctrl->dscrTable == 0 ){
dohmFmem_alloc(sizeof(dlicMdma_descr) * NUM_RDS_DEF + CACHELINESIZE,
(void**)&amt;pDma_ctrl->dscrTable );
}
/* align the start of the descriptors to cacheline boundaries */
pDma_ctrl->dscrTable_start
= (dlicMdma_descr*)(((uint32_t)(pDma_ctrl->dscrTable) + CACHELINESIZE)
&amt; ~(CACHELINESIZE - 1));

/* initialize the ring structure */
for( pDma_ctrl->dscrTable_end = pDma_ctrl->dscrTable_start, num = 0;
num < NUM_RDS_DEF;
pDma_ctrl->dscrTable_end++, num++ )
{
pDma_ctrl->dscrTable_end->dscr_a
= V_DMA_DSCRA_A_SIZE(MAC_BUFFER_SIZE / CACHELINESIZE);
pDma_ctrl->dscrTable_end->dscr_b = 0;
}
pDma_ctrl->dscrTable_end--;
pDma_ctrl->dscrTable_add = pDma_ctrl->dscrTable_start;
pDma_ctrl->dscrTable_rem = pDma_ctrl->dscrTable_start;

/* setup the registers: */
if( rc == 0 ){
reg = SB_DMA_REG_READ(pDma_ctrl, R_MAC_DMA_CONFIG0);
reg |= V_DMA_RINGSZ(NUM_RDS_DEF);
SB_DMA_REG_WRITE(pDma_ctrl, R_MAC_DMA_CONFIG0, reg );

SB_DMA_REG_WRITE(pDma_ctrl, R_MAC_DMA_CONFIG1, 0 );

SB_DMA_REG_WRITE(pDma_ctrl,
R_MAC_DMA_DSCR_BASE,
(uint32_t)dohmXvirtual2phys(pDma_ctrl->dscrTable_start) );
}

return(rc);
}



/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFcheck_RxReady *
* ..TITL: just look for buffers that were received *
* *
*---------------------------------------------------------------------*
* Packet received if SOP ==1 *
****************************************************************TNIP#*/
bool_t dlicFcheck_RxReady(dlicMdma_ctrl* pDma_ctrl)
{
return( (pDma_ctrl->dscrTable_rem->dscr_a &amt; M_DMA_ETHRX_SOP) ? 1 : 0 );
}


/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFget_RxFrame *
* ..TITL: read data from the Rx Ring and mark it as free *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFget_RxFrame(dlicMdma_ctrl *pDma_ctrl,
dohmMbuf_id *buf_id)
{
dlicMerror rc = 0;
uint64_t reg;
uint32_t length;
uint64_t status;

reg = SB_DMA_REG_READ(pDma_ctrl, R_MAC_DMA_DSCR_CNT);
if( reg < pDma_ctrl->minCount){
pDma_ctrl->minCount = reg;
}

/* read parameters from 'remove' descriptor */
*buf_id = (dohmMbuf_id)((uint32_t)((pDma_ctrl->dscrTable_rem->dscr_b
>> S_DMA_DSCRB_B_ADDR) &amt; 0xffffffff));
length = G_DMA_DSCRB_PKT_SIZE(pDma_ctrl->dscrTable_rem->dscr_b);
dohmFbuf_length_set( *buf_id, length );

/* read the status and handle errors */
status = pDma_ctrl->dscrTable_rem->dscr_a;
pDma_ctrl->lastStatus = G_DMA_DSCRA_STATUS(status);

/* check hw<->sw inconsistency */
if( !(status &amt; M_DMA_ETHRX_SOP) ){
rc = dlicCerrInternal;
}
/* descriptor error */
if( status &amt; M_DMA_ETHRX_DSCRERR ){
rc = dlicCerrRxDMA;
}
/*M_DMA_ETHRX_BCAST,M_DMA_ETHRX_MCAST*/
if( status &amt; M_DMA_ETHRX_BAD ){
rc = dlicCerrBadFrame;
}
/* clear part of the descriptor*/
pDma_ctrl->dscrTable_rem->dscr_a &amt;= ~M_DMA_DSCRA_A_ADDR;
pDma_ctrl->dscrTable_rem->dscr_a &amt;= ~M_DMA_DSCRA_STATUS;

dohmFmask();

/* adjust the pointer */
if( pDma_ctrl->dscrTable_rem == pDma_ctrl->dscrTable_end ){
pDma_ctrl->dscrTable_rem = pDma_ctrl->dscrTable_start;
}
else{
pDma_ctrl->dscrTable_rem++;
}
dohmFunmask();

reg = (pDma_ctrl->dscrTable_add - pDma_ctrl->dscrTable_start)
- (pDma_ctrl->dscrTable_rem - pDma_ctrl->dscrTable_start);
if( reg < pDma_ctrl->minRemAdd ){
pDma_ctrl->minRemAdd = reg;
}

return(rc);
}

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFadd_RxBuffer *
* ..TITL: give an allocated buffer to the DMA controller *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFadd_RxBuffer(dlicMdma_ctrl *pDma_ctrl,
dohmMbuf_id buf_id)
{
dlicMerror rc = 0;
uchar_t *pData;
uint32_t PhysData;
uint32_t offset = 0;
uint64_t reg;
uint64_t buf_addr;

reg = SB_DMA_REG_READ(pDma_ctrl, R_MAC_DMA_DSCR_CNT);
if( reg > pDma_ctrl->maxCount){
pDma_ctrl->maxCount = reg;
}
if( reg >= NUM_RDS_DEF ){
rc = dlicCerrRxOverflow;
}

if( rc == 0 ){
/* check the buffer and extract the parameter */
pData = (uchar_t*)dohmFbuf_data_add_get(buf_id);
#ifdef __VxWorks
/* align the buffer adress to cacheline boundaries */
pData = (uchar_t*)(((uint32_t)(pData + CACHELINESIZE)) &amt; ~(CACHELINESIZE - 1));
dohmFbuf_data_add_set(buf_id, pData);
#endif
PhysData = (uint32_t)dohmXvirtual2phys(pData);

/* calculate the offset */
offset = PhysData &amt; 0x1f;
PhysData &amt;= 0xffffffe0;

/* update the descriptor */
pDma_ctrl->dscrTable_add->dscr_a = offset &amt; M_DMA_DSCRA_OFFSET;
pDma_ctrl->dscrTable_add->dscr_a |= PhysData &amt; M_DMA_DSCRA_A_ADDR;
pDma_ctrl->dscrTable_add->dscr_a
|= V_DMA_DSCRA_A_SIZE(MAC_BUFFER_SIZE / CACHELINESIZE);
pDma_ctrl->dscrTable_add->dscr_a &amt;= ~M_DMA_ETHTX_SOP;

pDma_ctrl->dscrTable_add->dscr_b &amt;= ~(0xffffffff << S_DMA_DSCRB_B_ADDR);
pDma_ctrl->dscrTable_add->dscr_b &amt;= ~M_DMA_DSCRB_PKT_SIZE;
buf_addr = (uint64_t)((uint32_t)buf_id);
pDma_ctrl->dscrTable_add->dscr_b
|= ((buf_addr &amt; 0xffffffff) << S_DMA_DSCRB_B_ADDR);
pDma_ctrl->dscrTable_add->dscr_b |= V_DMA_DSCRB_PKT_SIZE(0);

dohmFmask();

/* increment the pointer */
if( pDma_ctrl->dscrTable_add == pDma_ctrl->dscrTable_end ){
pDma_ctrl->dscrTable_add = pDma_ctrl->dscrTable_start;
}
else{
pDma_ctrl->dscrTable_add++;
}
dohmFunmask();

/* give the descriptor to the hardware */
SB_DMA_REG_WRITE(pDma_ctrl, R_MAC_DMA_DSCR_CNT, 1 );
}
return(rc);
}

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFfree_RxBuffer *
* ..TITL: return the allocated buffer *
* *
*---------------------------------------------------------------------*
* NOTE: This function disturbs the receive process. *
* Reset the interface afterwards *
****************************************************************TNIP#*/
dohmMbuf_id dlicFfree_RxBuffer(dlicMdma_ctrl* pDma_ctrl,
uint32_t idx)
{
uint32_t buf_id = 0;

if((pDma_ctrl->dscrTable_start + idx)->dscr_a &amt; M_DMA_DSCRA_A_ADDR){
buf_id = (uint32_t)(((pDma_ctrl->dscrTable_start + idx)->dscr_b
>> S_DMA_DSCRB_B_ADDR) &amt; 0xffffffff);
}

(pDma_ctrl->dscrTable_start + idx)->dscr_a
= V_DMA_DSCRA_A_SIZE(MAC_BUFFER_SIZE / CACHELINESIZE);
(pDma_ctrl->dscrTable_start + idx)->dscr_b = 0;

return( (dohmMbuf_id)buf_id );
}
/************************************************************************/
/* */
/* Send Packet */
/* */
/************************************************************************/

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFsetup_TxRing *
* ..TITL: reset and initialize the DMA register *
* *
*---------------------------------------------------------------------*
* NOTE: DMA Descriptors MUST be aligned to cache line boundaries *
****************************************************************TNIP#*/
dlicMerror dlicFsetup_TxRing(dlicMdma_ctrl* pDma_ctrl, uint32_t macnum)
{
dlicMerror rc = 0;
uint32_t num;
uint64_t reg = 0;

pDma_ctrl->channel = 0; /* always 0, not used, can provide QOS */
pDma_ctrl->dmabase =
(uchar_t *)(PHYS_TO_K1(A_MAC_DMA_CHANNEL_BASE(macnum, DMA_TX, 0)));
/* ToDo: get the address from Dohm descriptor? */
pDma_ctrl->maxdescr = NUM_TDS_DEF;
pDma_ctrl->txdir = DMA_TX;
pDma_ctrl->maxCount = 0;
pDma_ctrl->minCount = 0;
pDma_ctrl->maxRemAdd = 0;
pDma_ctrl->minRemAdd = NUM_TDS_DEF;
pDma_ctrl->dscr_count = 0;

/* allocate the ring structure + 32 byte to adjust the alignement*/
if( pDma_ctrl->dscrTable == 0 ){
dohmFmem_alloc(sizeof(dlicMdma_descr) * NUM_TDS_DEF + CACHELINESIZE,
(void**)&amt;pDma_ctrl->dscrTable );
}
/* align the start of the descriptors to cacheline boundaries */
pDma_ctrl->dscrTable_start
= (dlicMdma_descr*)(((uint32_t)(pDma_ctrl->dscrTable) + CACHELINESIZE)
&amt; ~(CACHELINESIZE - 1));

/* initialize the ring structure */
for( pDma_ctrl->dscrTable_end = pDma_ctrl->dscrTable_start, num = 0;
num < NUM_TDS_DEF;
pDma_ctrl->dscrTable_end++, num++ )
{
pDma_ctrl->dscrTable_end->dscr_a
= V_DMA_DSCRA_A_SIZE(MAC_BUFFER_SIZE / CACHELINESIZE);
pDma_ctrl->dscrTable_end->dscr_b = 0;
}
pDma_ctrl->dscrTable_end--;
pDma_ctrl->dscrTable_add = pDma_ctrl->dscrTable_start;
pDma_ctrl->dscrTable_rem = pDma_ctrl->dscrTable_start;

/* setup the registers: */
if( rc == 0 ){
reg = SB_DMA_REG_READ(pDma_ctrl, R_MAC_DMA_CONFIG0);
reg |= V_DMA_RINGSZ(NUM_TDS_DEF); /* set ring size */
SB_DMA_REG_WRITE(pDma_ctrl, R_MAC_DMA_CONFIG0, reg );

SB_DMA_REG_WRITE(pDma_ctrl, R_MAC_DMA_CONFIG1, 0 );

SB_DMA_REG_WRITE(pDma_ctrl,
R_MAC_DMA_DSCR_BASE,
(uint32_t)dohmXvirtual2phys(pDma_ctrl->dscrTable_start) );

reg = SB_DMA_REG_READ(pDma_ctrl, R_MAC_DMA_DSCR_CNT);
}
if( reg != 0 ){
rc = dlicCerrInit; /* init error */
}
return(rc);
}

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFsend_TxFrame *
* ..TITL: send a frame on the selected link *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFsend_TxFrame(dlicMdma_ctrl* pDma_ctrl,
dohmMbuf_id buf_id)
{
dlicMerror rc = 0;
uchar_t *pData;
uint32_t PhysData;
uint32_t length;
uint32_t offset;
uint64_t reg;
uint64_t buf_addr;

/* extract parameters */
length = dohmFbuf_length_get(buf_id);
pData = (uchar_t*)dohmFbuf_data_add_get(buf_id);

/* padding to minsize frames */
if( length < 64 ){
memset( pData + length, 0, 64 - length );
length = 64;
}

PhysData = (uint32_t)dohmXvirtual2phys(pData);

/* calculate the offset */
offset = PhysData &amt; 0x1f;
PhysData &amt;= 0xffffffe0;

/* count multicast and broadcast frames */
if( *pData &amt; 0x1 )
{
pDma_ctrl->tx_bc_mcFrame++;
}

dohmFmask();
if( pDma_ctrl->dscr_count > pDma_ctrl->maxCount)
{
pDma_ctrl->maxCount = pDma_ctrl->dscr_count;
}
if( pDma_ctrl->dscr_count >= NUM_TDS_DEF - 3 )
{
rc = dlicCerrTxOverflow;
}
else
{
/* write parameters into next free descriptor */
pDma_ctrl->dscrTable_add->dscr_a = offset &amt; M_DMA_DSCRA_OFFSET;
pDma_ctrl->dscrTable_add->dscr_a |= PhysData &amt; M_DMA_DSCRA_A_ADDR;
pDma_ctrl->dscrTable_add->dscr_a
|= V_DMA_DSCRA_A_SIZE(MAC_BUFFER_SIZE / CACHELINESIZE);
pDma_ctrl->dscrTable_add->dscr_a |= M_DMA_ETHTX_SOP;

pDma_ctrl->dscrTable_add->dscr_b = K_DMA_ETHTX_APPENDCRC ;
pDma_ctrl->dscrTable_add->dscr_b &amt;= ~(0xffffffff << S_DMA_DSCRB_B_ADDR);
pDma_ctrl->dscrTable_add->dscr_b &amt;= ~M_DMA_DSCRB_PKT_SIZE;
buf_addr = (uint64_t)((uint32_t)buf_id);
pDma_ctrl->dscrTable_add->dscr_b
|= ((buf_addr &amt; 0xffffffff) << S_DMA_DSCRB_B_ADDR);
pDma_ctrl->dscrTable_add->dscr_b |= V_DMA_DSCRB_PKT_SIZE(length);


/* increment the descriptor counter to send the packet */
if( pDma_ctrl->dscrTable_add == pDma_ctrl->dscrTable_end ){
pDma_ctrl->dscrTable_add = pDma_ctrl->dscrTable_start;
}
else{
pDma_ctrl->dscrTable_add++;
}

pDma_ctrl->dscr_count++;


/* give the descriptor to the MAC */
SB_DMA_REG_WRITE(pDma_ctrl, R_MAC_DMA_DSCR_CNT, 1 );
}
dohmFunmask();

return(rc);
}


/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFcheck_TxReady *
* ..TITL: check if frames have been transmitted *
* *
*---------------------------------------------------------------------*
* packet sent if SOP = 0 *
****************************************************************TNIP#*/
bool_t dlicFcheck_TxReady(dlicMdma_ctrl* pDma_ctrl)
{

if( (pDma_ctrl->dscrTable_rem->dscr_a &amt; M_DMA_ETHTX_SOP) == 0
&amt;&amt; (pDma_ctrl->dscrTable_rem->dscr_a &amt; M_DMA_DSCRA_A_ADDR))
{
return( 1 );
}
else
{
return( 0 );
}

}

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFget_TxReady *
* ..TITL: returns the buffer of a transmitted frame *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMbuf_id dlicFget_TxReady(dlicMdma_ctrl* pDma_ctrl)
{
dohmMbuf_id buf_id;


dohmFmask();


if( ((pDma_ctrl->dscrTable_rem->dscr_a &amt; M_DMA_ETHTX_SOP) != 0)
|| ((pDma_ctrl->dscrTable_rem->dscr_a &amt; M_DMA_DSCRA_A_ADDR)==0))
{
dohmFunmask();
return( 0 );
}
buf_id = (dohmMbuf_id)((uint32_t)((pDma_ctrl->dscrTable_rem->dscr_b
>> S_DMA_DSCRB_B_ADDR) &amt; 0xffffffff));

pDma_ctrl->dscrTable_rem->dscr_a &amt;= ~M_DMA_DSCRA_A_ADDR;
pDma_ctrl->dscrTable_rem->dscr_a &amt;= ~M_DMA_DSCRA_STATUS;

if( pDma_ctrl->dscrTable_rem == pDma_ctrl->dscrTable_end ){
pDma_ctrl->dscrTable_rem = pDma_ctrl->dscrTable_start;
}
else{
pDma_ctrl->dscrTable_rem++;
}
pDma_ctrl->dscr_count--;
dohmFunmask();


return( buf_id );
}


/*FIUT#****************************************************************
* *
* ..UTS END *
* *
****************************************************************TUIF#*/