DM9000驱动之接受
2015-01-21 18:30
295 查看
/*分析DM9000收到一个数据包后,应该做何处理?*/ /*当收到一个数据包后,DM9000就会触发一次发送中断,跳到中断处理函数处理*/ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) { /* Received the coming packet */ //当接受到一个数据包后 if (int_status & ISR_PRS) dm9000_rx(dev); } /*处理发送函数*/ /* * Received a packet and pass to upper layer */ static void dm9000_rx(struct net_device *dev) { board_info_t *db = netdev_priv(dev); struct dm9000_rxhdr rxhdr; struct sk_buff *skb; u8 rxbyte, *rdptr; bool GoodPacket; int RxLen; /* Check packet ready or not */ do { ior(db, DM9000_MRCMDX); /* Dummy read */ //空读一会,以使得数据完全接受 /* Get most updated data */ rxbyte = readb(db->io_data); // /* Status check: this byte must be 0 or 1 */ if (rxbyte & DM9000_PKT_ERR) { //判断接受数据是否有误 dev_warn(db->dev, "status check fail: %d\n", rxbyte); iow(db, DM9000_RCR, 0x00); /* Stop Device */ iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ return; } if (!(rxbyte & DM9000_PKT_RDY)) //是否接受完全 return; /* A packet ready now & Get status/length */ GoodPacket = true; writeb(DM9000_MRCMD, db->io_addr); (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); //获取长度和状态 RxLen = le16_to_cpu(rxhdr.RxLen); if (netif_msg_rx_status(db)) dev_dbg(db->dev, "RX: status %02x, length %04x\n", rxhdr.RxStatus, RxLen); //检测长度和状态是否合法 /* Packet Status check */ if (RxLen < 0x40) { GoodPacket = false; if (netif_msg_rx_err(db)) dev_dbg(db->dev, "RX: Bad Packet (runt)\n"); } if (RxLen > DM9000_PKT_MAX) { dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen); } /* rxhdr.RxStatus is identical to RSR register. */ if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE | RSR_PLE | RSR_RWTO | RSR_LCS | RSR_RF)) { GoodPacket = false; if (rxhdr.RxStatus & RSR_FOE) { if (netif_msg_rx_err(db)) dev_dbg(db->dev, "fifo error\n"); dev->stats.rx_fifo_errors++; } if (rxhdr.RxStatus & RSR_CE) { if (netif_msg_rx_err(db)) dev_dbg(db->dev, "crc error\n"); dev->stats.rx_crc_errors++; } if (rxhdr.RxStatus & RSR_RF) { if (netif_msg_rx_err(db)) dev_dbg(db->dev, "length error\n"); dev->stats.rx_length_errors++; } } /* Move data from DM9000 */ /*分配skb结构*/ if (GoodPacket && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { skb_reserve(skb, 2); rdptr = (u8 *) skb_put(skb, RxLen - 4); /* Read received packet from RX SRAM */ //从RX中读取数据 (db->inblk)(db->io_data, rdptr, RxLen); dev->stats.rx_bytes += RxLen; /* Pass to upper layer */ skb->protocol = eth_type_trans(skb, dev); //获取网络协议 if (dev->features & NETIF_F_RXCSUM) { if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); } netif_rx(skb); //发送数据到上层去 dev->stats.rx_packets++; } else { /* need to dump the packet's data */ (db->dumpblk)(db->io_data, RxLen); } } while (rxbyte & DM9000_PKT_RDY); } /*这里需要详细说明分配skb这块的细节问题*/ /*第一个问题: 为什么分配的RxLen+4? dev_alloc_skb(RxLen + 4)*/ /*答: 因为skb结构前面要带有MAC头, IP头, 网络包的头共4个字节。 所以要多分配4个字节*/ /*第二个问题: 为什么skb->data 和 tail指针要加2 ? skb_reserve(skb, 2); */ /*答:因为IP包要求4字节对齐的缘故 */ /*第三个问题: 为什么Rxelen-4 ? skb_put(skb, RxLen - 4);*/ /*答: 设置tail指针的位置,去掉后面4字节的校验*/
相关文章推荐
- 在linux-2.6.29.1内核中修改添加DM9000的驱动
- 嵌入式学习-驱动开发-lesson7.2-DM9000驱动流程分析
- Mini2440 DM9000 驱动分析(二)
- 写DM9000网卡芯片驱动的预备知识(转)
- Linux-2.6.32.2 中固然有 DM9000 网卡驱动,但并不是完全的适合mini2440,导致挂载不上nfs文件系统
- 【linux驱动分析】之dm9000驱动分析(五):另外几个重要的结构体
- struts2 接受参数的两种方式(属性驱动和模型驱动)
- 网卡(dm9000)驱动移植
- Linux设备驱动简析--dm9000网卡驱动
- ARM-Linux驱动--DM9000网卡驱动分析(一)
- ARM-Linux驱动--DM9000网卡驱动分析(二)
- 【学习笔记】DM9000裸机驱动(三)之简单ARP协议的实现
- linux设备驱动-DM9000移植
- uboot.2015.07移植之驱动DM9000(8)
- u-boot-2009.11移植(适用于TQ2440和MINI2440)第四篇:完善目标板外设驱动(Nand flash和Dm9000配置)
- DM9000驱动修改
- Mini2440 DM9000 驱动分析(一)
- Mini2440 DM9000 驱动分析(三)
- 【linux驱动分析】之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现
- Arm9+linux fl2440 dm9000网卡 驱动移植和分析