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;
}