DM9000C U-BOOT驱动分析(三)

DM9000C发送数据部分

static int dm9000_send(struct eth_device *netdev, volatile void *packet,

    int length)

{

int tmo;

struct board_info *db = &dm9000_info;


DM9000_DMP_PACKET(__func__ , packet, length);


DM9000_iow(DM9000_ISR, IMR_PTM); 清除中断寄存器位设置


准备移动发送数据到DM9000C SRAM

DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */


移动发送数据到DM9000C SRAM

(db->outblk)(packet, length);


设置发送数据长度

DM9000_iow(DM9000_TXPLL, length & 0xff);

DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);


设置发送命令。

DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */


查询发送是否结束

tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;

while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||

!(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {

if (get_timer(0) >= tmo) {

printf("transmission timeout\n");

break;

}

}

发送结束,重新设置发送寄存器

DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */

传送完成

DM9000_DBG("transmit done\n\n");

return 0;

}


接收数据处理流程

static int dm9000_rx(struct eth_device *netdev)

{

u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];

u16 RxStatus, RxLen = 0;

struct board_info *db = &dm9000_info;


检查中断寄存器接收位标志,如果没有收到数据包就返回。

if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */

return 0;


有收到数据包,清除接收中断标志位

DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */


/* There is _at least_ 1 package in the fifo, read them all */

for (;;) {

预先设置读pointer寄存器

DM9000_ior(DM9000_MRCMDX);/* Dummy read */


读接收数据包的第一个byte,标志位,0x01表示数据包的开始。

rxbyte = DM9000_inb(DM9000_DATA) & 0x03;

if (rxbyte > DM9000_PKT_RDY) {

DM9000_iow(DM9000_RCR, 0x00);/* Stop Device */

DM9000_iow(DM9000_ISR, 0x80);/* Stop INT request */

printf("DM9000 error: status check fail: 0x%x\n",

rxbyte);

return 0;

}


接收数据包有误,返回

if (rxbyte != DM9000_PKT_RDY)

return 0; /* No packet received, ignore */


DM9000_DBG("receiving packet\n");

整个数据包状态及有效性检查

(db->rx_status)(&RxStatus, &RxLen);


DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);


从DM9000C SRAM把接收到数据包移动到处理器上层协议

(db->inblk)(rdptr, RxLen);


if ((RxStatus & 0xbf00) || (RxLen < 0x40)

|| (RxLen > DM9000_PKT_MAX)) {

if (RxStatus & 0x100) {

printf("rx fifo error\n");

}

if (RxStatus & 0x200) {

printf("rx crc error\n");

}

if (RxStatus & 0x8000) {

printf("rx length error\n");

}

if (RxLen > DM9000_PKT_MAX) {

printf("rx length too big\n");

dm9000_reset();

}

} else {

DM9000_DMP_PACKET(__func__ , rdptr, RxLen);


DM9000_DBG("passing packet to upper layer\n");

通知上层协议,处理接收到的数据

NetReceive(NetRxPackets[0], RxLen);

}

}

return 0;

}


你可能感兴趣的:(DM9000C U-BOOT驱动分析(三))