📄 lan91c111.c
字号:
#define TS_SUCCESS (0x0001)
#define TS_LOSTCAR (0x0400)
#define TS_LATCOL (0x0200)
#define TS_16COL (0x0010)
/* Receive status bits */
#define RS_ALGNERR (0x8000)
#define RS_BRODCAST (0x4000)
#define RS_BADCRC (0x2000)
#define RS_ODDFRAME (0x1000) // bug: the LAN91C111 never sets this on receive
#define RS_TOOLONG (0x0800)
#define RS_TOOSHORT (0x0400)
#define RS_MULTICAST (0x0001)
#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
/************************************************************************
* MII register numbering
*************************************************************************/
enum {
MII_CONTROL = 0,
MII_STATUS,
MII_PHYID1,
MII_PHYID2,
MII_ADVERTISEMENT,
MII_REMOTE_CAP,
MII_CONFIG1 = 16,
MII_CONFIG2,
MII_STATUS_OUTPUT,
MII_MASK,
MII_RESERVED
};
/*
* 0: control reg
*/
#define MII_CONTROL_RST (1 << 15)
#define MII_CONTROL_LPBK (1 << 14)
#define MII_CONTROL_SPEED (1 << 13)
#define MII_CONTROL_ANEG_EN (1 << 12)
#define MII_CONTROL_PDN (1 << 11)
#define MII_CONTROL_MII_DIS (1 << 10)
#define MII_CONTROL_ANEG_RST (1 << 9)
#define MII_CONTROL_DPLX (1 << 8)
#define MII_CONTROL_COLST (1 << 7)
/*
* 1: status reg
*/
#define MII_STATUS_CAP_T4 (1 << 15)
#define MII_STATUS_CAP_TXF (1 << 14)
#define MII_STATUS_CAP_TXH (1 << 13)
#define MII_STATUS_CAP_TF (1 << 12)
#define MII_STATUS_CAP_TH (1 << 11)
#define MII_STATUS_CAP_SUPR (1 << 6)
#define MII_STATUS_ANEG_ACK (1 << 5)
#define MII_STATUS_REM_FLT (1 << 4)
#define MII_STATUS_CAP_ANEG (1 << 3)
#define MII_STATUS_LINK (1 << 2)
#define MII_STATUS_JAB (1 << 1)
#define MII_STATUS_EXREG (1 << 0)
/*
* 2: phy id #1
*/
/*
* 3: phy id #2
*/
#define MII_PART_MASK (0x3f << 4)
#define MII_REV_MASK (0x0f)
/*
* 4: autonetotiation advertisement reg
*/
#define MII_ADVERTISEMENT_NP (1 << 15)
#define MII_ADVERTISEMENT_ACK (1 << 14)
#define MII_ADVERTISEMENT_RF (1 << 13)
#define MII_ADVERTISEMENT_T4 (1 << 9)
#define MII_ADVERTISEMENT_TX_FDX (1 << 8)
#define MII_ADVERTISEMENT_TX_HDX (1 << 7)
#define MII_ADVERTISEMENT_10_FDX (1 << 6)
#define MII_ADVERTISEMENT_10_HDX (1 << 5)
#define MII_ADVERTISEMENT_CSMA (1 << 0)
/*
* 5: autonetotiation remote capability reg
*/
#define MII_REMOTE_CAP_NP (1 << 15)
#define MII_REMOTE_CAP_ACK (1 << 14)
#define MII_REMOTE_CAP_RF (1 << 13)
#define MII_REMOTE_CAP_T4 (1 << 9)
#define MII_REMOTE_CAP_TX_FDX (1 << 8)
#define MII_REMOTE_CAP_TX_HDX (1 << 7)
#define MII_REMOTE_CAP_10_FDX (1 << 6)
#define MII_REMOTE_CAP_10_HDX (1 << 5)
#define MII_REMOTE_CAP_CSMA (1 << 0)
/*
* 16: configuration 1 reg
*/
#define MII_CONFIG1_LINKDIS (1 << 15)
#define MII_CONFIG1_XMITDIS (1 << 14)
#define MII_CONFIG1_XMITPDN (1 << 13)
#define MII_CONFIG1_BYPSCR (1 << 10)
#define MII_CONFIG1_UNSCDS (1 << 9)
#define MII_CONFIG1_EQLZR (1 << 8)
#define MII_CONFIG1_CABLE (1 << 7)
#define MII_CONFIG1_RLVL0 (1 << 6)
#define MII_CONFIG1_TLVL3 (1 << 5)
#define MII_CONFIG1_TLVL2 (1 << 4)
#define MII_CONFIG1_TLVL1 (1 << 3)
#define MII_CONFIG1_TLVL0 (1 << 2)
#define MII_CONFIG1_TRF1 (1 << 1)
#define MII_CONFIG1_TRF0 (1 << 0)
/*
* 17: configuration 2 reg
*/
#define MII_CONFIG2_APOLDIS (1 << 5)
#define MII_CONFIG2_JABDIS (1 << 4)
#define MII_CONFIG2_MREG (1 << 3)
#define MII_CONFIG2_INTMDIO (1 << 2)
/*
* 18: status output reg
*/
#define MII_STATUS_OUTPUT_INT (1 << 15)
#define MII_STATUS_OUTPUT_LNKFAIL (1 << 14)
#define MII_STATUS_OUTPUT_LOSSSYNC (1 << 13)
#define MII_STATUS_OUTPUT_CWRD (1 << 12)
#define MII_STATUS_OUTPUT_SSD (1 << 11)
#define MII_STATUS_OUTPUT_ESD (1 << 10)
#define MII_STATUS_OUTPUT_RPOL (1 << 9)
#define MII_STATUS_OUTPUT_JAB (1 << 8)
#define MII_STATUS_OUTPUT_SPDDET (1 << 7)
#define MII_STATUS_OUTPUT_DPLXDET (1 << 6)
/*
* 19: mask reg
*/
#define MII_MASK_MINT (1 << 15)
#define MII_MASK_MLNKFAIL (1 << 14)
#define MII_MASK_MLOSSSYN (1 << 13)
#define MII_MASK_MCWRD (1 << 12)
#define MII_MASK_MSSD (1 << 11)
#define MII_MASK_MESD (1 << 10)
#define MII_MASK_MRPOL (1 << 9)
#define MII_MASK_MJAB (1 << 8)
#define MII_MASK_MSPDDT (1 << 7)
#define MII_MASK_MDPLDT (1 << 6)
/*****************************
* special debug condition
*/
//#define DEBUG0
//#define DEBUG1
#if defined(DEBUG1)
#define DBG1 if (1) printf
#else
#define DBG1 if (0) printf
#endif
#if defined(DEBUG0)
#define DBG0 if (1) printf
#else
#define DBG0 if (0) printf
#endif
/*
* retry count
*/
#define MAX_MMU_CMD_RETRY (96)
/*********************************************************************
* board dependent definitions
*/
/*********************************************************************
* lan91c111 dependent definitions
*/
#ifndef LAN91C111_ADDR
#define LAN91C111_ADDR 0 /* will cause run-time exception */
#endif
static LAN91C111 *lan91c111 = (LAN91C111 *)LAN91C111_ADDR;
/************************************************************************
* Public variables
************************************************************************/
/************************************************************************
* Static variables
************************************************************************/
static char msg[160] ;
/* Global driver state */
static UINT32 LAN91C111_state = LAN91C111_DRIVER_IS_STOPPED ;
/* User registered receive handler */
static UINT32 (*usr_receive)( UINT32 length, UINT8 *data ) = NULL ;
/* Device context per minor device for this driver */
t_LAN91C111_device minor_device[LAN91C111_MINOR_DEVICE];
/************************************************************************
* Static function prototypes, local helper functions
************************************************************************/
/************************************************************************
* Implementation : Static functions
************************************************************************/
/************************************************************************
* Implementation : Local helper functions
************************************************************************/
/*********************************************************************
* lan91c111 dependent functions
*/
#define MDOE (1<<3)
#define MCLK (1<<2)
#define MDI (1<<1)
#define MDO (1<<0)
static void mdoSet (UINT16 org)
{
lan91c111->MGMT_3 = (org | MDOE | MDO);/* MDO = 1 */
lan91c111->MGMT_3 = (org | MDOE | MCLK | MDO);/* MCLK=1 */
sys_wait_ms(1);
lan91c111->MGMT_3 = (org ); /* MCLK=0 */
sys_wait_ms(1);
}
static void mdoClear (UINT16 org)
{
lan91c111->MGMT_3 = (org | MDOE); /* MDO = 0 */
lan91c111->MGMT_3 = (org | MDOE | MCLK ); /* MCLK=1 */
sys_wait_ms(1);
lan91c111->MGMT_3 = (org ); /* MCLK=0 */
sys_wait_ms(1);
}
static INT32 mdi (UINT16 org)
{
INT32 bit;
lan91c111->MGMT_3 = (org | MCLK ); /* MCLK=1 */
sys_wait_ms(1);
bit = (lan91c111->MGMT_3 & MDI) ? 1 : 0;
lan91c111->MGMT_3 = (org ); /* MCLK=0 */
sys_wait_ms(1);
return (bit);
}
static void miiWrite (UINT16 phy, UINT16 reg, UINT16 data)
{
INT32 i;
UINT16 org, bank;
/* preserve current bank */
bank = lan91c111->BANK;
select(BANK_3);
org = lan91c111->MGMT_3 & 0xFFF0;
/* 32 bits of IDLE */
for (i = 0; i <= 32; ++i)
mdoSet(org);
/* ST[1:0]=01 for start */
mdoClear(org);
mdoSet(org);
/* OP[1:0]=01 for write */
mdoClear(org);
mdoSet(org);
/* PHYAD[4:0] */
for (i = 4; i >= 0; --i)
if (phy & (1<<i)) mdoSet(org); else mdoClear(org);
/* REGAD[4:0] */
for (i = 4; i >= 0; --i)
if (reg & (1<<i)) mdoSet(org); else mdoClear(org);
/* TA[1:0] */
mdoSet(org);
mdoClear(org);
/* DATA[15:0] */
for (i = 15; i >= 0; --i)
if (data & (1<<i)) mdoSet(org); else mdoClear(org);
/* 32 bits of IDLE */
for (i = 0; i <= 32; ++i)
mdoSet(org);
/* restore bank */
lan91c111->BANK = bank;
}
static UINT16 miiRead (UINT16 phy, UINT16 reg)
{
INT32 i;
UINT16 org, bank;
UINT16 data = 0x0000;
/* preserve current bank */
bank = lan91c111->BANK;
select(BANK_3);
org = lan91c111->MGMT_3 & 0xFFF0;
/* 32 bits of IDLE */
for (i = 0; i <= 32; ++i)
mdoSet(org);
/* ST[1:0]=01 for start */
mdoClear(org);
mdoSet(org);
/* OP[1:0]=10 for read */
mdoSet(org);
mdoClear(org);
/* PHYAD[4:0] */
for (i = 4; i >= 0; --i)
if (phy & (1<<i)) mdoSet(org); else mdoClear(org);
/* REGAD[4:0] */
for (i = 4; i >= 0; --i)
if (reg & (1<<i)) mdoSet(org); else mdoClear(org);
/* TA[1:0] */
//mdoSet(org); HIGH Z turnaround time
mdoClear(org);
/* DATA[15:0] */
for (i = 15; i >= 0; --i)
data |= (mdi(org) << i);
/* 32 bits of IDLE */
for (i = 0; i <= 32; ++i)
mdoSet(org);
/* restore bank */
lan91c111->BANK = bank;
return (data);
}
/***********************************************************************
* MMU related functions
***********************************************************************/
static INT32 issue_mmu_command(INT32 mmu_command, INT32 wait)
{
select(BANK_2);
lan91c111->MMU_2 = mmu_command;
/* Wait for MMU command to complete */
if (wait == MMU_WAIT)
{
INT32 loop = MAX_MMU_CMD_RETRY;
while(loop--)
{
asm(" sync");
if(!(lan91c111->MMU_2 & MMU_BUSY)) return (OK);
}
return (ERROR_LAN_DEVICE_BUSY);
}
return (OK);
}
static UINT32 txStats(t_LAN91C111_device *pdevice, UINT16 status)
{
UINT32 ret_value = OK;
/* Check for frame abort */
if ((status /*= lan91c111->EPH_0*/) & (ESR_TXUNRN | ESR_LOST_CARR | ESR_LOTCAL |\
ESR_SQET | ESR_16COL | ESR_MULT_COL | ESR_SNGL_COL))
{
ret_value = ERROR_LAN_TXM_ERROR;
pdevice->status.tx_errors++;
if (status & ESR_TXUNRN)
pdevice->status.tx_under_run++;
if (status & ESR_LOST_CARR)
pdevice->status.tx_lost_carrier++;
if (status & ESR_LOTCAL)
pdevice->status.tx_late_collision++;
if (status & ESR_SQET)
pdevice->status.tx_signal_quality++;
if (status & ESR_16COL)
pdevice->status.tx_16_collisions++;
if (status & ESR_MULT_COL)
pdevice->status.tx_multiple_collisions++;
}
return (ret_value);
}
static int allocTx(t_LAN91C111_device *pdevice)
{
UINT8 alloc_result;
DBG0(">>ALLOC!\n");
issue_mmu_command(MMU_CMD_TX_ALLOC, MMU_WAIT);
//select(BANK_2);
alloc_result = lan91c111->PNRHI_2;
if (alloc_result & TX_ALLOCATION_FAILED)
{
//no packet alloced! issue_mmu_command(MMU_CMD_RELEASE_PACKET, MMU_NOWAIT);
//issue_mmu_command(MMU_CMD_TX_FIFO_RESET, MMU_NOWAIT);
DBG0("Failed#1\n");
return (ERROR_LAN_DEVICE_BUSY);
}
return (OK);
}
static INT32 setup_phy_pre(void)
{
int i;
/* disable all interrupts */
select(BANK_2);
lan91c111->INTMASKHI_2 = 0;
select(BANK_1);
/* set up configuration register(0) */
lan91c111->CONFIG_1 = (CFG_EPHPOWEREN | CFG_NOWAIT);
/* initialize Bank1 control register */
lan91c111->CONTROL_1 = (CTL_RX_BAD | CTL_AUTO | CTL_LE_EN | CTL_CR_EN | CTL_TE_EN);
/* zero clear the multi-cast table */
select(BANK_3);
lan91c111->MT01_3 = lan91c111->MT23_3 = lan91c111->MT45_3 = lan91c111->MT67_3 = 0;
select(BANK_0);
/* set up Rx control register */
lan91c111->RCR_0 = (RCR_RXEN | RCR_STRIP_CRC /*| RCR_PRMS*/);
/* set up Tx control register */
lan91c111->TCR_0 = (TCR_SWFDUP | TCR_PAD_EN | TCR_TXEN);
/* start auto neg. LED-A: Link, LED-B: rx or rx activity */
lan91c111->RPCR_0 = (RPCR_ANEG | LEDA_LINK | LEDB_ACTIVITY);
/* Reset PHY */
miiWrite(0, 0, 0x8000);
for (i = 0; i < 50; ++i)
{
if ((miiRead(0,0) & 0x8000) == 0x0000)
break;
}
/* Take PHY out of isolation; enable the PHY, ANEG */
miiWrite(0, 0, 0x1000);
return (OK);
}
/************************************************************************
*
* allocate_buffers
* Description :
* -------------
* This routine allocates memory for:
*
* - Receive buffers
* - Transmit buffer
*
*
* Parameters :
* ------------
*
* 'pdevice', IN, reference for this device context
*
*
* Return values :
* ---------------
*
* 'OK'(=0)
*
*
*
************************************************************************/
static
INT32 allocate_buffers( t_LAN91C111_device *pdevice )
{
INT32 i;
UINT8 *buf;
memset(pdevice, 0 , sizeof (t_LAN91C111_device));
buf = (UINT8 *)((UINT32)(pdevice->rx_buffer_pool + 31) & ~0x0000001f);
for (i = 0; i < RX_CIRCULAR_BUFFERS; ++i)
{
pdevice->rx_buffer_addr[i] = (UINT32)KSEG0(&buf[(i * RX_BUFF_SIZE)]);
}
pdevice->NextRxBuffer = 0;
return( OK );
}
static INT32 MII_status(t_LAN91C111_device *pdevice)
{
UINT32 ret_value = OK;
UINT16 data;
if ((data = miiRead(0,MII_ADVERTISEMENT)) & MII_ADVERTISEMENT_ACK)
{
DBG1("PHY is ready...%x\n", data);
if ((data = miiRead(0,MII_STATUS)) & MII_STATUS_LINK)
DBG1("Link is up...%x\n", data);
else
DBG1("No Link...%x\n", data);
}
else
{
DBG1("PHY auto-neg failed! %x \n", data);
ret_value = ERROR_LAN_DEVICE_NOTRDY;
}
return (ret_value);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -