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