u-boot中DM9000驱动分析
1. CSRs和PHY reg读写。
static u16
phy_read(int reg)
{
u16 val; /* Fill the phyxcer register into REG_0C */
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
udelay(); /* Wait read complete */
DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
val = (DM9000_ior(DM9000_EPDRH) << ) | DM9000_ior(DM9000_EPDRL); /* The read data keeps on REG_0D & REG_0E */
DM9000_DBG("phy_read(%d): %d\n", reg, val);
return val;
}
phy_read
static void
phy_write(int reg, u16 value)
{ /* Fill the phyxcer register into REG_0C */
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */
DM9000_iow(DM9000_EPDRL, (value & 0xff));
DM9000_iow(DM9000_EPDRH, ((value >> ) & 0xff));
DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
udelay(); /* Wait write complete */
DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value);
}
phy_write
static u8
DM9000_ior(int reg)
{
u32 val; VALIDATE_ADDR_PORT(reg) val = *(u16*)DM9000_DATA; val &= 0xffff; return (u8)val;
}
DM9000_ior
static void
DM9000_iow(int reg, u8 value)
{
VALIDATE_ADDR_PORT(reg) *(u16*)(DM9000_DATA) = (u16)value;
}
DM9000_iow
#define VALIDATE_ADDR_PORT(p) \
if( m_uLastAddressPort != (p) ) \
{ \
*(u16*)(DM9000_IO) =(u16)(p);\
m_uLastAddressPort = (p);\
}
VALIDATE_ADDR_PORT
2. 网口收发
int
eth_rx(void)
{
u8 rxbyte, *rdptr = (u8 *) NetRxPackets[];
int errors=;
u16 RxLen; u32 desc;
PDM9000_RX_DESCRIPTOR pdesc; DM9000_ior(DM9000_RSR);
DM9000_ior(DM9000_ROCR); for(pdesc=(PDM9000_RX_DESCRIPTOR)&desc;;)
{
// probe first byte
desc = DeviceReadDataWithoutIncrement();
DM9000_DBG("1:\tdesc is 0x%x\n",desc); // check if packet available, 01h means available, 00h means no data
if(pdesc->bState != 0x01)
{
RxLen = ;
break;
} // get the data descriptor again
desc = DeviceReadData();
DM9000_DBG("2:\tdesc is 0x%x\n",desc); DM9000_DBG("len is 0x%x\n",pdesc->nLength); DeviceReadString(rdptr,pdesc->nLength); // check status, as specified in DM9000_RXSR,
// the following bits are error
// <3> PLE
// <2> AE
// <1> CE
// <0> FOE
if(pdesc->bStatus & MAKE_MASK4(,,,))
{
errors++;
continue;
} // of error happens RxLen =pdesc->nLength; break;
} // of forever read loop /* Pass to upper layer */
DM9000_DBG("passing packet to upper layer\n");
NetReceive(NetRxPackets[], RxLen);
return RxLen;
}
eth_rx
int
eth_send(volatile void *packet, int length)
{
unsigned int loop;
#if 0
for(loop = ; loop<length;loop++)
{
printf("%02x ",*((char *)packet+loop));
}
printf("\n");
#endif
DeviceWriteString((u8*)packet,length); DM9000_iow(DM9000_TXPLH,HIGH_BYTE(length));
DM9000_iow(DM9000_TXPLL,LOW_BYTE(length)); // TXCR<0>, issue TX request
DM9000_iow(DM9000_TCR, MAKE_MASK()); DM9000_DBG("transmit done\n\n");
return ;
}
eth_send
数据接收时首先比对包头4个字节,第一个字节必须是0x01,第3,4字节是数据长度(减去开头的4个字节)。
接收完数据后再比对第二字节(DM9000 RSR),确认是否又错误发生。
用到的编程技巧是读取的包头4个字节直接赋值给一个u32,最低字节即为01,高两位为包长度。