標籤:
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 }phy_read
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 }phy_write
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 }DM9000_ior
1 static void2 DM9000_iow(int reg, u8 value)3 {4 VALIDATE_ADDR_PORT(reg)5 6 *(u16*)(DM9000_DATA) = (u16)value;7 }DM9000_iow
1 #define VALIDATE_ADDR_PORT(p) 2 if( m_uLastAddressPort != (p) ) 3 { 4 *(u16*)(DM9000_IO) =(u16)(p);5 m_uLastAddressPort = (p);6 }VALIDATE_ADDR_PORT
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 byte17 desc = DeviceReadDataWithoutIncrement(); 18 DM9000_DBG("1:\tdesc is 0x%x\n",desc);19 20 // check if packet available, 01h means available, 00h means no data21 if(pdesc->bState != 0x01)22 {23 RxLen = 0;24 break;25 }26 27 // get the data descriptor again28 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 error37 // <3> PLE38 // <2> AE39 // <1> CE40 // <0> FOE41 if(pdesc->bStatus & MAKE_MASK4(3,2,1,0))42 {43 errors++;44 continue;45 } // of error happens46 47 RxLen =pdesc->nLength;48 49 break;50 } // of forever read loop51 52 /* Pass to upper layer */53 DM9000_DBG("passing packet to upper layer\n");54 NetReceive(NetRxPackets[0], RxLen);55 return RxLen;56 }eth_rx
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 #endif12 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 request18 DM9000_iow(DM9000_TCR, MAKE_MASK(0));19 20 21 DM9000_DBG("transmit done\n\n");22 return 0;23 }eth_send
資料接收時首先比對包頭4個位元組,第一個位元組必須是0x01,第3,4位元組是資料長度(減去開頭的4個位元組)。
接收完資料後再比對第二位元組(DM9000 RSR),確認是否又錯誤發生。
用到的編程技巧是讀取的包頭4個位元組直接賦值給一個u32,最低位元組即為01,高兩位為包長度。
u-boot中網口處理--軟體部分