前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DM9000驱动之接受

DM9000驱动之接受

作者头像
DragonKingZhu
发布2022-05-08 15:43:49
4970
发布2022-05-08 15:43:49
举报
代码语言:javascript
复制
/*分析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字节的校验*/
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-01-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档