www.pudn.com > bcm1250-src.rar > dlicpa_dohm.c
/*GENU#****************************************************************
* *
* ..GENERALITIES *
* *
*---------------------------------------------------------------------*
* *
* ..IDENTIFICATION: *
* ..MNAM: M.Thierauf *
* ..TITL: ldicpa.c *
* ..READ: yy/mm/dd / <author> *
* ..REVW: 13/03/02 MTh *
* *
* ..DESCRIPTION: *
* ..APPL: ethernet driver for BCM1250 internal MAC *
* ..FUNC: *
* ..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 "dlicdd_dohm.h"
/*CSLT#********************************
* ..CONSTANTS *
**************************************/
/*****************************************************************VEDS#*/
/*SEXT#****************************************************************
* *
* ..EXTERNAL SYMBOLS *
* *
*--------------------------------------------------------------------*/
/*LIBR#********************************
* ..LIBRARIES *
**************************************/
/*CSLT#********************************
* ..CONSTANTS *
**************************************/
/*VARS#********************************
* ..VARIABLES *
**************************************/
uint dlicDrv_signature1;
dlicMdrv_ctrl dlicDrvCtrl[dlicCmax_dev];
uint dlicDrvX_signature2;
/*PROT#********************************
* ..PROTOTYPES *
**************************************/
/* Access Functions declared to the dohm layer
-------------------------------------------*/
dohmMreturn dlicFattach (docxMid *inc_connection,
docxMuser_fct_to_call function_to_call,
docxMuser_parameter parameter,
dohmMprot protocol,
dohmMbuf_id pool_id );
dohmMreturn dlicFbuffer_send (dohmMbuf_id buffer_to_send );
dohmMreturn dlicFenable (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFwrite_mode (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFread_mode (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFwrite_promiscuous (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFread_promiscuous (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFloop_line (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFloop_network (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
dohmMreturn dlicFset_address (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att );
/* Event Functions declared to the dohm layer
------------------------------------------*/
dohmMreturn dlicFevent_enable (doeaMid *event);
dohmMreturn dlicFevent_disable (doeaMid *event);
dohmMreturn dlicFerror_counter_read (doeaMid *event,
uint32_t *value);
dohmMreturn dlicFtraffic_read (doeaMid *event,
uint32_t *value);
/* Support Functions desclared to the dohm layer
---------------------------------------------*/
void dlicFpolltask(void);
/* internal functions
------------------*/
static dlicMerror dlicFcount_declare(void);
static dlicMerror dlicFpollFrame(void);
static dlicMerror dlicFpollSentFrame(void);
/****************************************************************TXES#*/
/*SLOC#****************************************************************
* *
* ..LOCAL SYMBOLS *
* *
*--------------------------------------------------------------------*/
/*CSLT#********************************
* ..CONSTANTS *
**************************************/
#define dlicCmax_error 21
#define dlicCmax_count 7
char dlicCerror_string[dlicCmax_error][24] =
{
"Tx err w/o buf overr",
"Tx buffer overun",
"Tx jabber timeout",
"loss of carrier",
"no carrier",
"late collision",
"excessive coll.",
"collision count",
"link failure",
"underflow error",
"nr errors",
"Rx buffer error",
"Rx descr error",
"unknown packet",
"too large intern.",
"descchip length err",
"runt frames",
"giant frames",
"collission seen",
"receive watchdog",
"dribbling bit"
};
char dlicCtraffic_string[dlicCmax_count][24] =
{
"free Tx descr.",
"succ. Tx frames",
"succ. bmcast Tx frames",
"succ. Tx byte",
"succ. Rx frames",
"succ. bmcast Rx frames",
"succ. Rx bytes",
};
const dohmMdeclare dlicCdeclare_cx[] =
{
{ dohmCconnection,
doamCtype_icl,
docxCattach,
dohmCprot_mac,
(dohmMlogical_fct)dlicFattach
},
{ dohmCconnection,
doamCtype_icl,
docxCbuffer_send,
dohmCprot_mac,
(dohmMlogical_fct)dlicFbuffer_send
},
{ dohmCaccess,
doamCtype_icl,
doamCope_write,
doamCatt_in_service,
(dohmMlogical_fct)dlicFenable
},
{ dohmCaccess,
doamCtype_icl,
doamCope_write,
doamCatt_mode,
(dohmMlogical_fct)dlicFwrite_mode
},
{ dohmCaccess,
doamCtype_icl,
doamCope_read,
doamCatt_mode,
(dohmMlogical_fct)dlicFread_mode
},
{ dohmCaccess,
doamCtype_icl,
doamCope_write,
doamCatt_promiscuous, /*doamCatt_promiscuous,*/
(dohmMlogical_fct)dlicFwrite_promiscuous
},
{ dohmCaccess,
doamCtype_icl,
doamCope_read,
doamCatt_promiscuous, /*doamCatt_promiscuous,*/
(dohmMlogical_fct)dlicFread_promiscuous
},
{ dohmCaccess,
doamCtype_icl,
doamCope_write,
doamCatt_loop_line,
(dohmMlogical_fct)dlicFloop_line
},
{ dohmCaccess,
doamCtype_icl,
doamCope_write,
doamCatt_loop_network,
(dohmMlogical_fct)dlicFloop_network
},
{ dohmCaccess,
doamCtype_icl,
doamCope_write,
doamCatt_add_dest_MAC_L2_ADDR ,
(dohmMlogical_fct)dlicFset_address
}
};
const uchar_t dlicVetheraddr[] = { 0, 0, 0, 0, 0, 0 };
/* ToDo: move to a different location */
int debugVprint = 0;
/*DIAL#********************************
* ..DIALOG INTERFACES *
**************************************/
/*DATS#********************************
* ..DATA STRUCTURES *
**************************************/
/*VARS#********************************
* ..VARIABLES *
**************************************/
/*VARS#********************************
* ..MACRO *
**************************************/
/**********************************************************************/
/* Init Functions */
/**********************************************************************/
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFinit *
* ..TITL: init function of the driver *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
void dlicFinit(void)
{
dlicMerror rc = dlicCok;
int32_t i = 0;
#if 0
dohwMcomponent comp_struct;
#endif
dohmMtask_id polltask;
dlicDrv_signature1 = 0x47114712;
dlicDrvX_signature2 = 0x47134714;
memset(dlicDrvCtrl, 0, sizeof(dlicMdrv_ctrl) * dlicCmax_dev);
dohmFenter();
/* get component description */
dlicDrvCtrl[0].macbase = 0;
#if 0 /* ToDo */
rc = dohwFget_component_description(dohwCpart_et ,
dohwCcomp_tmp,
0 ,
&amt;comp_struct ) ;
#endif
if( rc == dlicCok ){
strncpy( dlicDrvCtrl[0].name, "ethe", 4);
dlicDrvCtrl[0].state = dlicCstate_fault;
dlicDrvCtrl[0].devNo = i;
dlicDrvCtrl[0].macbase = /*comp_struct.component_add_io;*/
(uchar_t *)(PHYS_TO_K1(A_MAC_BASE_0)
+ MAC_SPACING*(i));
memcpy( dlicDrvCtrl[0].enetAddr, dlicVetheraddr, 6);
}
/* Get 2nd component base address if nb_component >=2
NOTE: this inializes also devices masked by dlicCdev_mask */
for ( i = 1; (i < dlicCmax_dev) &amt;&amt; (rc == dlicCok); i++ )
{
dlicDrvCtrl[i].macbase = 0;
#if 0 /* ToDo */
rc = dohwFget_component_description ( dohwCpart_et ,
dohwCcomp_sbs ,
i ,
&amt;comp_struct );
#endif
strncpy( dlicDrvCtrl[i].name, "ethe", 4);
dlicDrvCtrl[0].state = dlicCstate_fault;
dlicDrvCtrl[i].devNo = i;
dlicDrvCtrl[i].macbase = /*comp_struct.component_add_io;*/
(uchar_t *)(PHYS_TO_K1(A_MAC_BASE_0)
+ MAC_SPACING*(i));
memcpy( dlicDrvCtrl[i].enetAddr, dlicVetheraddr, 6);
}
/* declare event and connection functions */
if( rc == dlicCok ){
rc = dohmFdeclare_table(dlicCdeclare_cx, sizeof(dlicCdeclare_cx));
}
/* declare the event on access functions */
if( rc == dlicCok ){
rc = dlicFcount_declare();
}
for( i = 0; (i < dlicCmax_dev) &amt;&amt; (rc == dlicCok); i++ )
{
if( ((1 << i) &amt; dlicCdev_mask) &amt;&amt; (dlicDrvCtrl[i].macbase != 0) )
{
/* setup hardware access data structure + init hardware */
if( rc == dlicCok ){
rc = dlicFinit_hw(&amt;dlicDrvCtrl[i]);
}
/* reset the traffic counter */
if( rc == dlicCok ){
rc = dlicFinit_counter(&amt;dlicDrvCtrl[i]);
}
/* init Rx DMA */
if( rc == dlicCok ){
rc = dlicFsetup_RxRing(&amt;(dlicDrvCtrl[i].rxDma[0]), i);
}
/* buffer are allocated when the interface is enabled */
/* init Tx DMA */
if( rc == dlicCok ){
rc = dlicFsetup_TxRing(&amt;(dlicDrvCtrl[i].txDma[0]), i);
}
if( rc == dlicCok ){
dlicDrvCtrl[i].state = dlicCstate_init;
}
/* the DMA channels are still disabled till the IN_SERVICE
attribute is set */
dlicDrvCtrl[i].promiscious = doamCatt_ed_enable;
}
}
/* create a polling "task" for GFI polling */
if( rc == dlicCok ){
dohmFtask_create_and_start("dlicPoll",
&amt;polltask ,
1, /* priority
*
* UM 19-02-2003 priority changed to force
* high priority gfi polling
*/
(dohmMtask_fct)dlicFpolltask);
}
dohmFexit();
if (rc != dlicCok){
dohmFstop();
DL_DEBUG("Error: >i internal ethernet driver init failed", rc);
}
else{
DL_DEBUG("internal ethernet driver initialized", rc);
}
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFcount_declare *
* ..TITL: init function of the driver *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
static dlicMerror dlicFcount_declare(void)
{
uint32_t event_num;
dlicMerror rc = dlicCok;
for (event_num = 0;
(event_num < dlicCmax_error) &amt;&amt; (rc == dlicCok);
event_num++)
{
doeaFdeclare_error(doamCtype_icl,
event_num,
dlicCerror_string[event_num],
(doeaMtype) doeaCtype_error_counter,
(doeaMmask*) (dlicFevent_disable),
(doeaMunmask*) (dlicFevent_enable),
(doeaMcounter_read*) (dlicFerror_counter_read));
}
for (event_num = 0;
(event_num < dlicCmax_count) &amt;&amt; (rc == dlicCok);
event_num++)
{
doeaFdeclare_traffic(doamCtype_icl,
event_num,
dlicCtraffic_string[event_num],
0,
(doeaMcounter_traffic_read*)dlicFtraffic_read);
}
return(rc);
}
/**********************************************************************/
/* Send/Receive Functions */
/**********************************************************************/
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFsend *
* ..TITL: function to send an ethernet frame *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMreturn dlicFbuffer_send( dohmMbuf_id buff_id )
{
dlicMerror rc = dlicCok;
docxMid connex_id; /* CNX ID => used to recover the port */
doamMid *access_id;
doamMnumber access_num;
doamMtype access_type;
/* On which link should i send? */
dohmFbuf_cx1_get ( buff_id , connex_id );
access_id = docxFaccess ( &amt;connex_id );
access_num = doamFnumber ( access_id );
access_type = doamFtype ( access_id );
if( access_type != doamCtype_icl ){
rc = dlicCerrWrongType;
#ifndef __VxWorks
sysprintf(">>>>>>> dlic: type = >x, id = >x, buff_id = >x <<<<<<\n",
access_type,access_id, buff_id );
#endif
}
if( access_num >= dlicCmax_dev ){
rc = dlicCerrWrongNum;
}
if( dlicDrvCtrl[access_num].state != dlicCstate_enabled){
rc = dlicCerrState;
}
if( rc == dlicCok ){
rc = dlicFsend_TxFrame(&amt;(dlicDrvCtrl[access_num].txDma[0]), buff_id );
/* other parameters are retrieved in the send function */
dlicDrvCtrl[access_num].sentFrame++;
if( rc != dlicCok ){
dlicDrvCtrl[access_num].txOverflow++;
rc = dohmFbuf_release( buff_id );
}
}
return( (dohmMreturn) rc );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFattach *
* ..TITL: store a callback function pointer for received frames *
*---------------------------------------------------------------------*
* NOTE: buffers are allocated in the enable function *
****************************************************************TNIP#*/
dohmMreturn dlicFattach( docxMid *inc_connection,
docxMuser_fct_to_call function_to_call,
docxMuser_parameter parameter,
dohmMprot protocol,
dohmMpool_buf_id pool_id )
{
dlicMerror rc = dlicCok;
doamMid *access_id;
doamMnumber access_num = 0;
doamMtype access_type = 0;
/* Check the parameter and store them */
access_id = docxFaccess ( inc_connection );
access_num = doamFnumber ( access_id );
access_type = doamFtype ( access_id );
if( access_type != doamCtype_icl ){
rc = dlicCerrWrongType;
}
if( access_num >= dlicCmax_dev ){
rc = dlicCerrWrongNum;
}
if( rc == dlicCok ){
dlicDrvCtrl[access_num].function_to_call = function_to_call;
dlicDrvCtrl[access_num].parameter = parameter;
dlicDrvCtrl[access_num].pool_id = pool_id;
dlicDrvCtrl[access_num].protocol = protocol;
}
if( (rc == dlicCok) &amt;&amt; (dlicDrvCtrl[access_num].state == dlicCstate_init))
{
dlicDrvCtrl[access_num].state = dlicCstate_ready;
}
else
{
rc = dlicCerrState;
}
return( (dohmMreturn) rc);
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFtask *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* NOTE: are there any parameters? *
****************************************************************TNIP#*/
void dlicFpolltask(void)
{
dlicMerror rc = dlicCok;
#ifdef __VxWorks
dohmForever
{
dohmFsleep( 0 );
#endif
/* wait for the init to be finished ? */
if( rc == dlicCok ){
rc = dlicFpollFrame();
}
if( rc == dlicCok ){
rc = dlicFpollSentFrame();
}
/* do some error handling... */
if (rc != dlicCok){
DL_DEBUG("ERROR: internal ethernet polling failed: >d", rc);
dohmFstop();
}
#ifdef __VxWorks
}
#endif
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFpollFrame *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
static dlicMerror dlicFpollFrame(void)
{
dlicMerror rc = dlicCok;
int32_t result = 0;
uint32_t num;
uint32_t count;
dohmMbuf_id buffer_id;
dohmMbuf_id newbuff_id;
doamMtype access_type;
#ifdef __dohm_gfi_adapt_stgt__
vbpdDlicPollStatistics(); /* UM 19-02-2003 to get performance indication */
#endif
/* look for new frames */
for ( num = 0; (num < dlicCmax_dev) &amt;&amt; (rc == 0); num++ )
{
if ( ((1 << num) &amt; dlicCdev_mask) )
{
count = 0;
while( dlicFcheck_RxReady(&amt;(dlicDrvCtrl[num].rxDma[0]))
&amt;&amt; (rc == 0)
&amt;&amt; (dlicDrvCtrl[num].state == dlicCstate_enabled)
&amt;&amt; (count < NUM_RDS_DEF/2))
{
rc = dlicFget_RxFrame(&amt;(dlicDrvCtrl[num].rxDma[0]), &amt;buffer_id);
/* make the error handling: result indicates a damaged frame...*/
switch(rc)
{
case dlicCok:
dlicDrvCtrl[num].receivedFrame++;
break;
case dlicCerrRxDMA:
dlicDrvCtrl[num].DmaError++;
DL_DEBUG("WARNING: DMA error!", rc);
break;
case dlicCerrInternal:
dlicDrvCtrl[num].RxInternalError++;
DL_DEBUG("WARNING: Rx internal error!", rc);
break;
case dlicCerrBadFrame:
dlicDrvCtrl[num].damagedFrame++;
DL_DEBUG("WARNING: DAMGED FRAME!", rc);
break;
default:
DL_DEBUG("INTERNAL ERROR", rc );
result = dlicCerrInternal;
break;
}
switch(rc)
{
case dlicCok:
/* call the user callback function */
(dlicDrvCtrl[num].function_to_call)(buffer_id,
dlicDrvCtrl[num].parameter,
result);
newbuff_id = dohmFbuf_take(dlicDrvCtrl[num].pool_id);
rc = dlicFadd_RxBuffer(&amt;(dlicDrvCtrl[num].rxDma[0]), newbuff_id);
break;
case dlicCerrRxDMA: /* fall through */
case dlicCerrBadFrame:
rc = dohmFbuf_release( buffer_id );
newbuff_id = dohmFbuf_take(dlicDrvCtrl[num].pool_id);
if( newbuff_id != dohmCbuf_nil )
{
rc = dlicFadd_RxBuffer(&amt;(dlicDrvCtrl[num].rxDma[0]),
newbuff_id);
}
else
{
rc = dlicCerrNoBuffers;
}
break;
case dlicCerrInternal:
default:
/* non recoverable error */
break;
} /* endswitch */
count++;
} /* endwhile */
if (rc != dlicCok){
dlicDrvCtrl[num].state = dlicCstate_fault;
}
}
}
return(rc);
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFpollFrame *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
static dlicMerror dlicFpollSentFrame(void)
{
dlicMerror rc = dlicCok;
dohmMbuf_id release_buf;
uint32_t num;
uint32_t count;
/* get all transmitted buffers */
for( num = 0; (num < dlicCmax_dev) &amt;&amt; (rc == dlicCok); num++ )
{
if( ((1 << num) &amt; dlicCdev_mask) &amt;&amt; (dlicDrvCtrl[num].macbase != 0) )
{
count = 0;
while( dlicFcheck_TxReady(&amt;(dlicDrvCtrl[num].txDma[0]))
&amt;&amt; (rc == dlicCok)
&amt;&amt; (count < NUM_TDS_DEF))
{
if( rc == dlicCok ){
release_buf = dlicFget_TxReady(&amt;(dlicDrvCtrl[num].txDma[0]));
/* handle the status of the transmitted frame ...*/
if( !release_buf){
rc = dlicCerrTxDMA;
}
}
if( rc == dlicCok ){
rc = dohmFbuf_release( release_buf );
if (rc != dlicCok){
DL_DEBUG("ERROR: internal ethernet polling failed: >d", rc);
dohmFstop();
}
dlicDrvCtrl[num].releasedFrame++;
}
count++;
}
if (rc != dlicCok){
dlicDrvCtrl[num].state = dlicCstate_fault;
}
}
}
return(rc);
}
/**********************************************************************/
/* Access Functions */
/**********************************************************************/
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFenable *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* NOTE: Attributes can be changed while in state disabled *
****************************************************************TNIP#*/
dohmMreturn dlicFenable (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
dlicMerror rc = dlicCok;
uint32_t idx = doamFnumber(&amt;access_id);
uint32_t i;
dohmMbuf_id buf_id;
if( att != doamCatt_in_service ){
return(dlicCerrWrongAttr);
}
if( !((1 << doamFnumber(&amt;access_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
if( *value == doamCatt_ed_enable )
{
/* enable
------*/
if( (dlicDrvCtrl[idx].state != dlicCstate_ready)
&amt;&amt; (dlicDrvCtrl[idx].state != dlicCstate_enabled) )
{
rc = dlicCerrState;
}
/* stop receiving */
if( rc == dlicCok ){
rc = dlicFdisable_hw(&amt;dlicDrvCtrl[idx]);
}
/* release all buffers */
for( i = 0; i < NUM_RDS_DEF; i++){
buf_id = dlicFfree_RxBuffer(&amt;(dlicDrvCtrl[idx].rxDma[0]), i );
if( buf_id ){
rc = dohmFbuf_release( buf_id );
}
}
/* setup hardware access data structure + init hardware */
if( rc == dlicCok ){
rc = dlicFinit_hw(&amt;dlicDrvCtrl[idx]);
}
/* init Rx DMA */
if( rc == dlicCok ){
rc = dlicFsetup_RxRing(&amt;(dlicDrvCtrl[idx].rxDma[0]), idx);
}
/* init Tx DMA */
if( rc == dlicCok ){
rc = dlicFsetup_TxRing(&amt;(dlicDrvCtrl[idx].txDma[0]), idx);
}
/* alloc new buffers (fill half of the buffer, rest is debug trace)*/
for( i = 0; (i < (NUM_RDS_DEF / 2)) &amt;&amt; (rc == dlicCok); i++ )
{
buf_id = dohmFbuf_take( dlicDrvCtrl[idx].pool_id );
if( buf_id ) {
rc = dlicFadd_RxBuffer(&amt;(dlicDrvCtrl[idx].rxDma[0]),
buf_id);
}
else{
rc = dlicCerrAlloc;
}
}
if( rc == dlicCok ){
rc = dlicFenable_hw(&amt;dlicDrvCtrl[idx]);
}
if( rc == dlicCok ){
dlicDrvCtrl[idx].state = dlicCstate_enabled;
}
}
else if (*value == doamCatt_ed_disable)
{
/* disable
-------*/
if( (dlicDrvCtrl[idx].state != dlicCstate_enabled) )
{
rc = dlicCerrState;
}
if( rc == dlicCok ){
rc = dlicFdisable_hw(&amt;dlicDrvCtrl[idx]);
}
if( rc == dlicCok ){
dlicDrvCtrl[idx].state = dlicCstate_ready;
}
}
else
{
rc = dlicCerrOutOfRange;
}
return( (dohmMreturn) rc );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFwrite_mode *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* Note: the mode cannot be changed. It is fixed by the hardware *
****************************************************************TNIP#*/
dohmMreturn dlicFwrite_mode (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
dlicMerror rc = dlicCok;
/* setting of half/full duplex is not possible */
if( att != doamCatt_mode ){
return(dlicCerrWrongAttr);
}
if( !((1 << doamFnumber(&amt;access_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
if( *value != doamCatt_full_duplex ){
return(dlicCerrNotImplemented);
}
return( (dohmMreturn) rc );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFread_mode *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* NOTE: always return full duplex (fixed by hardware) *
****************************************************************TNIP#*/
dohmMreturn dlicFread_mode (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
dlicMerror rc = dlicCok;
/* always return full duplex */
if( att != doamCatt_mode ){
return(dlicCerrWrongAttr);
}
if( !((1 << doamFnumber(&amt;access_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
*value = doamCatt_full_duplex;
return( (dohmMreturn) rc );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFwrite_promiscuous *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMreturn dlicFwrite_promiscuous (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
dlicMerror rc = dlicCok;
uint32_t idx = doamFnumber(&amt;access_id);
uint64_t addr;
if( att != doamCatt_promiscuous){
return(dlicCerrWrongAttr);
}
if( !((1 << idx) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
dohmFenter();
switch ( *value )
{
case doamCatt_ed_enable:
/* clear the frame filter */
SB_MAC_REG_WRITE(&amt;(dlicDrvCtrl[idx]),
R_MAC_ADFILTER_CFG,
_SB_MAKEMASK1(7) | M_MAC_ALLPKT_EN );
break;
case doamCatt_ed_disable:
/* setup the faddress filter to the mac address */
addr = ((uint64_t)dlicDrvCtrl[idx].enetAddr[5] << 40) &amt; 0xff0000000000
| ((uint64_t)dlicDrvCtrl[idx].enetAddr[4] << 32) &amt; 0xff00000000
| ((uint64_t)dlicDrvCtrl[idx].enetAddr[3] << 24) &amt; 0xff000000
| ((uint64_t)dlicDrvCtrl[idx].enetAddr[2] << 16) &amt; 0xff0000
| ((uint64_t)dlicDrvCtrl[idx].enetAddr[1] << 8) &amt; 0xff00
| ((uint64_t)dlicDrvCtrl[idx].enetAddr[0]) &amt; 0xff;
SB_MAC_REG_WRITE(&amt;(dlicDrvCtrl[idx]),
R_MAC_ADDR_BASE,
addr );
SB_MAC_REG_WRITE(&amt;(dlicDrvCtrl[idx]),
R_MAC_ADFILTER_CFG,
M_MAC_BCAST_EN );
break;
default:
rc = dlicCerrInternal;
break;
}
dlicDrvCtrl[idx].promiscious = *value;
dohmFexit();
return( (dohmMreturn) rc );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFread_promiscuous *
* ..TITL: return the address filter status *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMreturn dlicFread_promiscuous (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
uint32_t idx = doamFnumber(&amt;access_id);
dohmFenter();
if( att != doamCatt_promiscuous ){
return(dlicCerrWrongAttr);
}
if( !((1 << idx) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
*value = dlicDrvCtrl[idx].promiscious;
return(dohmCreturn_ok);
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFloop_line *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* NOTE: not available for internal traffic *
****************************************************************TNIP#*/
dohmMreturn dlicFloop_line (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
if( att != doamCatt_loop_line ){
return(dlicCerrWrongAttr);
}
if( !((1 << doamFnumber(&amt;access_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
return( dlicCerrNotImplemented );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFloop_network *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* Note: autonegotiation must be switched off: Done by hardware setting*
****************************************************************TNIP#*/
dohmMreturn dlicFloop_network (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
uint32_t idx = doamFnumber(&amt;access_id);
uint32_t reg;
if( att != doamCatt_loop_network ){
return(dlicCerrWrongAttr);
}
if( !((1 << doamFnumber(&amt;access_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
dohmFenter();
reg = sbeth_mii_read(&amt;dlicDrvCtrl[idx], dlicDrvCtrl[idx].phyAddr, 0);
if (*value)
{
reg &amt;= ~(BMCR_ANENABLE | BMCR_SPEED0 | BMCR_SPEED1);
reg |= BMCR_LOOPBACK | BMCR_DUPLEX | BMCR_SPEED100;
}
else
{
reg &amt;= ~(BMCR_LOOPBACK | BMCR_DUPLEX);
}
sbeth_mii_write( &amt;dlicDrvCtrl[idx], dlicDrvCtrl[idx].phyAddr, 0, reg );
dohmFexit();
return(dohmCreturn_ok);
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFset_address *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMreturn dlicFset_address (doamMid *access_id,
doamMatt_ed *value,
doamMatt_ed att )
{
dlicMerror rc = dlicCok;
uint32_t num;
if( att != doamCatt_add_dest_MAC_L2_ADDR ){
return(dlicCerrWrongAttr);
}
num = doamFnumber(&amt;access_id);
if( !((1 << num) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
memcpy( dlicDrvCtrl[num].enetAddr, ((doamML2_mac_add*)value)->tab, 6);
return( rc );
}
/**********************************************************************/
/* Event/Counter Functions */
/**********************************************************************/
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFevent_enable *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* NOTE: no interrupt and event handling is implemented *
****************************************************************TNIP#*/
dohmMreturn dlicFevent_enable (doeaMid *event)
{
return(dohmCreturn_ok);
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFevent_disable *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* NOTE: no interrupt and event handling is implemented *
****************************************************************TNIP#*/
dohmMreturn dlicFevent_disable (doeaMid *event)
{
return(dohmCreturn_ok);
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFerror_counter_read *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMreturn dlicFerror_counter_read (doeaMid *event,
uint32_t *value)
{
dlicMerror rc = dlicCok;
doeaMnumb number;
doamMid *acc_id;
dlicMdrv_ctrl *pDrvCtrl;
number = doeaFnumber(event);
acc_id = doeaFaccess(event);
if( !((1 << doamFnumber(acc_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
if( doeaFtype(event) != doeaCtype_traffic_counter ){
return(dlicCerrWrongType);
}
dohmFenter();
pDrvCtrl = &amt;dlicDrvCtrl[doamFnumber(acc_id)];
switch(number)
{
case 0:
*value = 0; /* error minus buffer overrun */
break;
case 1:
*value = pDrvCtrl->txOverflow; /* buffer overrun */
break;
case 2:
*value = 0; /* jabber timeout, no counter */
break;
case 3:
*value = 0; /* loss of carrier */
break;
case 4:
*value = 0; /* no carrier */
break;
case 5:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_LATE_COL);
break;
case 6:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_EX_COL);
break;
case 7:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_COLLISIONS);
break;
case 8:
*value = 0; /* link failed */
break;
case 9:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_TX_ABORT);
break;
case 10:
*value = 0; /* nr error ????? */
break;
case 11:
*value = 0; /* rx buffer errors */
break;
case 12:
*value = pDrvCtrl->DmaError; /* rx descr errors */
break;
case 13:
*value = pDrvCtrl->RxInternalError; /* unknown to system */
break;
case 14:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_OVERSIZE);
break;
case 15:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_OVERSIZE);
break;
case 16:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_RUNT);
break;
case 17:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_OVERSIZE);
break;
case 18:
*value = 0; /* collisions seen */
break;
case 19:
*value = 0; /* receive watchdog, no counter */
break;
case 20:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_ALIGN_ERROR);
break;
default:
rc = dlicCerrWrongNum;
break;
}
dohmFexit();
return( (dohmMreturn) rc );
}
/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFtraffic_read *
* ..TITL: *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dohmMreturn dlicFtraffic_read (doeaMid *event,
uint32_t *value)
{
dlicMerror rc = dlicCok;
doeaMnumb number;
doamMid *acc_id;
dlicMdrv_ctrl *pDrvCtrl;
number = doeaFnumber(event);
acc_id = doeaFaccess(event);
if( !((1 << doamFnumber(acc_id)) &amt; dlicCdev_mask) ){
return(dlicCerrWrongNum);
}
if( doeaFtype(event) != doeaCtype_traffic_counter ){
return(dlicCerrWrongType);
}
dohmFenter();
pDrvCtrl = &amt;dlicDrvCtrl[doamFnumber(acc_id)];
switch(number)
{
case 0:
*value = pDrvCtrl->releasedFrame;
break;
case 1:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_TX_GOOD);
break;
case 2:
*value = pDrvCtrl->txDma[0].tx_bc_mcFrame;
break;
case 3:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_TX_BYTES);
break;
case 4:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_GOOD);
break;
case 5:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_BCAST)
+ SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_RX_MCAST);
break;
case 6:
*value = SB_MAC_REG_READ(pDrvCtrl, R_MAC_RMON_TX_BYTES);
break;
default:
rc = dlicCerrWrongNum;
break;
}
dohmFexit();
return( (dohmMreturn) rc );
}
/*FIUT#****************************************************************
* *
* ..UTS END *
* *
****************************************************************TUIF#*/