www.pudn.com > bcm1250-src.rar > dlicpa_hw.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 "dohmDI-up.h"
#include "dlicdd_dohm.h"


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

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

/*PROT#********************************
* ..PROTOTYPES *
**************************************/

/* PHY control functions
---------------------*/
static void sbeth_mii_sync(dlicMdrv_ctrl * drvctrl);

static void sbeth_mii_senddata(dlicMdrv_ctrl * drvctrl,
unsigned int data,
int bitcnt);

static void sbeth_mii_findphy(dlicMdrv_ctrl * drvctrl);

static void init_phy(dlicMdrv_ctrl * drvctrl, int phyaddr);

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

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

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

/*VARS#********************************
* ..MACRO *
**************************************/
/***************************************************************************/
/* Hardware access functions */
/***************************************************************************/

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFinit_hw *
* ..TITL: initialize the hardware and related structures *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFinit_hw(dlicMdrv_ctrl *pDrvCtrl)
{
dlicMerror rc = dlicCok;
uint64_t reg;
uint32_t port;
uint32_t idx;
uint64_t addr;

/* init memory structures */
/* ???????UDO???????? patched */
pDrvCtrl->speed = sbmac_speed_10;
pDrvCtrl->duplex = sbmac_duplex_full;
pDrvCtrl->fc = sbmac_fc_disabled; /* flow control */

/* reset the MAC */
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_ENABLE, M_MAC_PORT_RESET );
dohmFsleep(1);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_ENABLE, M_MAC_PORT_RESET );
dohmFsleep(1);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_ENABLE, 0);

#if 0 /* CPU == MIPS64 */

/* fill in phyaddr */
sbeth_mii_findphy(pDrvCtrl);
/* set the PHY to 100 FDX */
init_phy(pDrvCtrl, pDrvCtrl->phyAddr );

#else
pDrvCtrl->phyAddr = 1;
#endif

/* setup the main config reg */
SB_MAC_REG_WRITE(pDrvCtrl,
R_MAC_CFG,
M_MAC_RETRY_EN |
M_MAC_TX_HOLD_SOP_EN |
V_MAC_TX_PAUSE_CNT_16K |
V_MAC_SPEED_SEL_100MBPS |
M_MAC_AP_STAT_EN |
M_MAC_FAST_SYNC |
M_MAC_SS_EN |
V_MAC_IPHDR_OFFSET(14));


/* set its own hw addr (due to PASS 1 bug address is not set)*/
port = R_MAC_ETHERNET_ADDR;
/* SB_MAC_REG_WRITE(pDrvCtrl,port,0x0180c2000001); */
SB_MAC_REG_WRITE(pDrvCtrl,port,0x0);

/* clear hash table */
port = R_MAC_HASH_BASE;
for (idx = 0; idx < MAC_HASH_COUNT; idx++)
{
SB_MAC_REG_WRITE(pDrvCtrl,port,0);
port += sizeof(uint64_t);
}

/* clear exact match addr table */
port = R_MAC_ADDR_BASE;
for (idx = 0; idx < MAC_ADDR_COUNT; idx++)
{
SB_MAC_REG_WRITE(pDrvCtrl,port,0);
port += sizeof(uint64_t);
}

if( pDrvCtrl->promiscious == doamCatt_ed_enable ){
SB_MAC_REG_WRITE(pDrvCtrl,
R_MAC_ADFILTER_CFG,
M_MAC_ALLPKT_EN |
/* M_MAC_BCAST_EN | */
_SB_MAKEMASK1(7) ); /* accept all multicast packets */
}
else{
SB_MAC_REG_WRITE(pDrvCtrl,
R_MAC_ADFILTER_CFG,
M_MAC_BCAST_EN );
/* fill in the ethernet address */
addr = ((uint64_t)pDrvCtrl->enetAddr[5] << 40) &amt; 0xff0000000000
| ((uint64_t)pDrvCtrl->enetAddr[4] << 32) &amt; 0xff00000000
| ((uint64_t)pDrvCtrl->enetAddr[3] << 24) &amt; 0xff000000
| ((uint64_t)pDrvCtrl->enetAddr[2] << 16) &amt; 0xff0000
| ((uint64_t)pDrvCtrl->enetAddr[1] << 8) &amt; 0xff00
| ((uint64_t)pDrvCtrl->enetAddr[0]) &amt; 0xff;

SB_MAC_REG_WRITE(pDrvCtrl,
R_MAC_ADDR_BASE,
addr );
}

/* reset channel map register */
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++)
{
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_CHLO0_BASE + idx * sizeof(uint64_t), 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_CHUP0_BASE + idx * sizeof(uint64_t), 0);
}

/* no interrupt, 0 = int masked! */
SB_MAC_REG_WRITE (pDrvCtrl, R_MAC_INT_MASK, 0);

/* setup frame cfg */
SB_MAC_REG_WRITE (pDrvCtrl,
R_MAC_FRAMECFG,
V_MAC_MIN_FRAMESZ_DEFAULT |
V_MAC_MAX_FRAMESZ_DEFAULT |
V_MAC_BACKOFF_SEL(1) );

/* setup fifo cfg (just copied from broadcom)*/
SB_MAC_REG_WRITE(pDrvCtrl,
R_MAC_THRSH_CFG,
V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
V_MAC_TX_RD_THRSH(4) |
V_MAC_TX_RL_THRSH(4) |
V_MAC_RX_PL_THRSH(4) |
V_MAC_RX_RD_THRSH(4) | /* Must be '4' */
V_MAC_RX_PL_THRSH(4) |
V_MAC_RX_RL_THRSH(8));

if(rc == dlicCok){
rc = dlicFsetSpeed(pDrvCtrl, pDrvCtrl->speed);
}
if(rc == dlicCok){
rc = dlicFsetDuplex(pDrvCtrl, pDrvCtrl->duplex, pDrvCtrl->fc);
}

return(rc);
}

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFinit_counter *
* ..TITL: initisalize and start the counter *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFinit_counter(dlicMdrv_ctrl *pDrvCtrl)
{
dlicMerror rc = dlicCok;

SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_TX_BYTES , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_COLLISIONS, 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_LATE_COL , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_EX_COL , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_FCS_ERROR , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_TX_ABORT , 0);
/* Counter #6 (0x30) now reserved */
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_TX_BAD , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_TX_GOOD , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_TX_RUNT , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_TX_OVERSIZE, 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_BYTES , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_MCAST , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_BCAST , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_BAD , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_GOOD , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_RUNT , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_OVERSIZE, 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_FCS_ERROR, 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_LENGTH_ERROR, 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_CODE_ERROR , 0);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_RMON_RX_ALIGN_ERROR , 0);

return(rc);
}



/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFdisable_hw *
* ..TITL: stop the hardware *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFdisable_hw(dlicMdrv_ctrl *pDrvCtrl)
{
dlicMerror rc = dlicCok;

SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_ENABLE, 0);

return(rc);
}

/*PINT#****************************************************************
* *
* ..FUNCTIONAL DESCRIPTION *
* *
*---------------------------------------------------------------------*
* *
* ..INAM: dlicFenable_hw *
* ..TITL: enable the hardware *
* *
*---------------------------------------------------------------------*
* *
****************************************************************TNIP#*/
dlicMerror dlicFenable_hw(dlicMdrv_ctrl *pDrvCtrl)
{
dlicMerror rc = dlicCok;

SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_ENABLE, M_MAC_RXDMA_EN0
| M_MAC_TXDMA_EN0
| M_MAC_RX_ENABLE
| M_MAC_TX_ENABLE );

return(rc);
}


/**********************************************************************
* sb1250MacSetSpeed(pDrvCtrl,speed)
*
* Configure LAN speed for the specified MAC
*
* Input parameters:
* speed - speed to set MAC to (see sbeth_speed_t enum)
*
* Return value:
* 1 if successful
* 0 indicates invalid parameters
**********************************************************************/
dlicMerror dlicFsetSpeed( dlicMdrv_ctrl *pDrvCtrl,
sbmac_speed_t speed )
{
uint64_t cfg;
uint64_t framecfg;

/* Read current register values */
cfg = SB_MAC_REG_READ(pDrvCtrl, R_MAC_CFG);
framecfg = SB_MAC_REG_READ(pDrvCtrl, R_MAC_FRAMECFG);

/* Mask out the stuff we want to change */
cfg &amt;= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
framecfg &amt;= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
M_MAC_SLOT_SIZE);

/* Now add in the new bits */
switch(speed)
{
case sbmac_speed_10:
framecfg |= V_MAC_IFG_RX_10 |
V_MAC_IFG_TX_10 |
K_MAC_IFG_THRSH_10 |
V_MAC_SLOT_SIZE_10;
cfg |= V_MAC_SPEED_SEL_10MBPS;
break;

case sbmac_speed_100:
framecfg |= V_MAC_IFG_RX_100 |
V_MAC_IFG_TX_100 |
V_MAC_IFG_THRSH_100 |
V_MAC_SLOT_SIZE_100;
cfg |= V_MAC_SPEED_SEL_100MBPS ;
break;

case sbmac_speed_1000:
framecfg |= V_MAC_IFG_RX_1000 |
V_MAC_IFG_TX_1000 |
V_MAC_IFG_THRSH_1000 |
V_MAC_SLOT_SIZE_1000;
cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
break;

default:
return(dlicCerrInternal);
}

/* Send the bits back to the hardware */
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_FRAMECFG, framecfg);
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_CFG, cfg);

return(dlicCok);
}

/**********************************************************************
* sb1250MacSetDuplex(pDrvCtrl,duplex,fc)
*
* Set Ethernet duplex and flow control options for this MAC
*
* Input parameters:
* duplex - duplex setting (see sbeth_duplex_t)
* fc - flow control setting (see sbeth_fc_t)
*
* Return value:
* 1 if ok
* 0 if an invalid parameter combination was specified
**********************************************************************/
dlicMerror dlicFsetDuplex(dlicMdrv_ctrl *pDrvCtrl,
sbmac_duplex_t duplex,
sbmac_fc_t fc)
{
uint64_t cfg;

/* Read current register values */
cfg = SB_MAC_REG_READ(pDrvCtrl, R_MAC_CFG);

/* Mask off the stuff we're about to change */
cfg &amt;= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);


switch(duplex)
{
case sbmac_duplex_half:
switch(fc)
{
case sbmac_fc_disabled:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
break;

case sbmac_fc_collision:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
break;

case sbmac_fc_carrier:
cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
break;

case sbmac_fc_frame: /* not valid in half duplex */
default: /* invalid selection */
return(dlicCerrInternal);
}
cfg &amt;= ~(M_MAC_BURST_EN);
break;

case sbmac_duplex_full:
switch(fc)
{
case sbmac_fc_disabled:
cfg |= V_MAC_FC_CMD_DISABLED;
break;

case sbmac_fc_frame:
cfg |= V_MAC_FC_CMD_ENABLED;
break;

case sbmac_fc_collision: /* not valid in full duplex */
case sbmac_fc_carrier: /* not valid in full duplex */
/* fall through */
default:
return(dlicCerrInternal);
}
break;
}

/* Send the bits back to the hardware */
SB_MAC_REG_WRITE(pDrvCtrl, R_MAC_CFG, cfg);

return(dlicCok);
}


/******************************
PHY/MII
(from CFE)
******************************/

/* *********************************************************************
* SBETH_MII_SYNC(s)
********************************************************************* */
static void sbeth_mii_sync(dlicMdrv_ctrl * drvctrl)
{
int cnt;
uint64_t bits;

bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;

SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits);

for(cnt = 0; cnt < 32; cnt++)
{
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits | M_MAC_MDC);
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits);
}
}

/* *********************************************************************
* SBETH_MII_SENDDATA(s,data,bitcnt)
********************************************************************* */
static void sbeth_mii_senddata(dlicMdrv_ctrl * drvctrl,
unsigned int data,
int bitcnt)
{
int i;
uint64_t bits;
unsigned int curmask;

bits = M_MAC_MDIO_DIR_OUTPUT;
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits);

curmask = 1 << (bitcnt - 1);

for(i = 0; i < bitcnt; i++)
{
if(data &amt; curmask)
{
bits |= M_MAC_MDIO_OUT;
}
else
{
bits &amt;= ~M_MAC_MDIO_OUT;
}
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits);
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits | M_MAC_MDC);
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, bits);
curmask >>= 1;
}
}

/* *********************************************************************
* SBETH_MII_READ(s,phyaddr,regidx)
********************************************************************* */

unsigned int sbeth_mii_read(dlicMdrv_ctrl * drvctrl,
int phyaddr,
int regidx)
{
int idx;
int error;
int regval;

/*
* Synchronize ourselves so that the PHY knows the next
* thing coming down is a command
*/
sbeth_mii_sync(drvctrl);
/*
* Send the data to the PHY. The sequence is
* a "start" command (2 bits)
* a "read" command (2 bits)
* the PHY addr (5 bits)
* the register index (5 bits)
*/
sbeth_mii_senddata(drvctrl, MII_COMMAND_START, 2);
sbeth_mii_senddata(drvctrl, MII_COMMAND_READ, 2);
sbeth_mii_senddata(drvctrl, phyaddr, 5);
sbeth_mii_senddata(drvctrl, regidx, 5);
/*
* Switch the port around without a clock transition.
*/
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT);

/*
* Send out a clock pulse to signal we want the status
*/

SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT);

/*
* If an error occured, the PHY will signal '1' back
*/
error = SB_MAC_REG_READ(drvctrl, R_MAC_MDIO) &amt; M_MAC_MDIO_IN;

/*
* Issue an 'idle' clock pulse, but keep the direction
* the same.
*/
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT);

regval = 0;
for(idx = 0; idx < 16; idx++)
{
regval <<= 1;

if(error == 0)
{
if(SB_MAC_REG_READ(drvctrl, R_MAC_MDIO) &amt; M_MAC_MDIO_IN)
{
regval |= 1;
}
}

SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_INPUT);
}

/* Switch back to output */
SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_OUTPUT);

if(error == 0) {
return(regval);
}
else{
return(0);
}
}

/* *********************************************************************
* SBETH_MII_WRITE(s,phyaddr,regidx,regval)
********************************************************************* */

void sbeth_mii_write(dlicMdrv_ctrl * drvctrl,
int phyaddr,
int regidx,
unsigned int regval)
{

sbeth_mii_sync(drvctrl);

sbeth_mii_senddata(drvctrl, MII_COMMAND_START, 2);
sbeth_mii_senddata(drvctrl, MII_COMMAND_WRITE, 2);
sbeth_mii_senddata(drvctrl, phyaddr, 5);
sbeth_mii_senddata(drvctrl, regidx, 5);
sbeth_mii_senddata(drvctrl, MII_COMMAND_ACK, 2);
sbeth_mii_senddata(drvctrl, regval, 16);

SB_MAC_REG_WRITE(drvctrl, R_MAC_MDIO, M_MAC_MDIO_DIR_OUTPUT);
}

/* *********************************************************************
* SBETH_MII_FINDPHY(s)
********************************************************************* */
static void sbeth_mii_findphy(dlicMdrv_ctrl * drvctrl)
{
int phy;
uint16_t bmsr;

for(phy = 0; phy < 31; phy++)
{
bmsr = sbeth_mii_read(drvctrl,phy, MII_BMSR);
if(bmsr != 0)
{
drvctrl->phyAddr = phy;
DL_DEBUG("Found PHY at address",phy);
DL_DEBUG("Command Reg", sbeth_mii_read(drvctrl,phy,0));
DL_DEBUG("Status Reg", sbeth_mii_read(drvctrl,phy,1));
return;
}
}
DL_DEBUG("Found no PHY ", -1);

drvctrl->phyAddr = 1;
}

/* *********************************************************************
* SBETH_MII_POLL(s)
*
* Ask the PHY what is going on, and configure speed appropriately.
* For the moment, we only support automatic configuration.
*
* Input parameters:
* s - sbeth structure
*
* Return value:
* nothing
********************************************************************* */
static void sbeth_mii_poll(dlicMdrv_ctrl * drvctrl)
{
uint16_t bmsr;
uint16_t bmcr;
uint16_t k1stsr;
uint16_t anlpar;

/* Read the mode status and mode control registers. */
bmsr = sbeth_mii_read(drvctrl, drvctrl->phyAddr, MII_BMSR);
bmcr = sbeth_mii_read(drvctrl, drvctrl->phyAddr, MII_BMCR);

/* get the link partner status */
anlpar = sbeth_mii_read(drvctrl, drvctrl->phyAddr, MII_ANLPAR);

/* if supported, read the 1000baseT register */
if(bmsr &amt; BMSR_1000BT_XSR)
{
k1stsr = sbeth_mii_read(drvctrl,drvctrl->phyAddr, MII_K1STSR);
}
else
{
k1stsr = 0;
}

DL_DEBUG("Link speed: ", 0);

if(k1stsr &amt; K1STSR_LP1KFD)
{
drvctrl->speed = sbmac_speed_1000;
drvctrl->duplex = sbmac_duplex_full;
drvctrl->fc = sbmac_fc_frame;
DL_DEBUG("1000BaseT FDX", 0);
}
else if(k1stsr &amt; K1STSR_LP1KHD)
{
drvctrl->speed = sbmac_speed_1000;
drvctrl->duplex = sbmac_duplex_half;
drvctrl->fc = sbmac_fc_disabled;
DL_DEBUG("1000BaseT HDX\n", 0);
}
else if(anlpar &amt; ANLPAR_TXFD)
{
drvctrl->speed = sbmac_speed_100;
drvctrl->duplex = sbmac_duplex_full;
drvctrl->fc = (anlpar &amt; ANLPAR_PAUSE) ? sbmac_fc_frame : sbmac_fc_disabled;
DL_DEBUG("100BaseT FDX\n", 0);
}
else if(anlpar &amt; ANLPAR_TXHD)
{
drvctrl->speed = sbmac_speed_100;
drvctrl->duplex = sbmac_duplex_half;
drvctrl->fc = sbmac_fc_disabled;
DL_DEBUG("100BaseT HDX\n", 0);
}
else if(anlpar &amt; ANLPAR_10FD)
{
drvctrl->speed = sbmac_speed_10;
drvctrl->duplex = sbmac_duplex_full;
drvctrl->fc = sbmac_fc_frame;
DL_DEBUG("10BaseT FDX\n", 0);
}
else if(anlpar &amt; ANLPAR_10HD)
{
drvctrl->speed = sbmac_speed_10;
drvctrl->duplex = sbmac_duplex_half;
drvctrl->fc = sbmac_fc_collision;
DL_DEBUG("10BaseT HDX\n", 0);
}
else
{
DL_DEBUG("Unknown\n", 0);
}

printf("BMSR=>04X, BMCR=>04X, 1KSTSR=>04X, ANLPAR=>04X\n", bmsr, bmcr,
k1stsr, anlpar);
}


/* *********************************************************************
* init_phy basic initialisation of the external PHY device
********************************************************************* */

static void init_phy(dlicMdrv_ctrl * drvctrl,
int phyaddr)
{
uint32_t reg;

/* reset the PHY */
sbeth_mii_write( drvctrl, drvctrl->phyAddr, 0, BMCR_RESET);
do{
reg = sbeth_mii_read(drvctrl, drvctrl->phyAddr, 0);
}
while(reg &amt; BMCR_RESET);
/* switch off auto-neg. and force to 100 Mbit FDX */
#if 0 /* does not work on swarm board, but i have no idea why.. */
reg = BMCR_DUPLEX | BMCR_SPEED100;
sbeth_mii_write( drvctrl, drvctrl->phyAddr, 0, reg);
#endif
reg = sbeth_mii_read(drvctrl, drvctrl->phyAddr, 0);

reg = sbeth_mii_read(drvctrl, drvctrl->phyAddr, 0);

}

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