dm9000a驱动源码分析(三)

dm9000a数据发送函数:

/*
 *  Hardware start transmission.
 *  Send a packet to media from the upper layer.
 */
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	unsigned long flags;
	
	/*获得ndev的私有数据,也就是芯片相关的信息*/
	board_info_t *db = dev->priv;

	dm9000_dbg(db, 3, "%s:\n", __func__);
	
	?*只能存放两个,如果已经有两个就退出*/ 
	if (db->tx_pkt_cnt > 1)
		return 1;

	spin_lock_irqsave(&db->lock, flags);

	/* 
     *MWCMD是Memory data write command with address increment Register(F8H) 
     *写数据到TX SRAM 
     *写这个命令后,根据IO操作模式(8-bit or 16-bit)来增加写指针1或2 
     */ 
	/* Move data to DM9000 TX RAM */
	writeb(DM9000_MWCMD, db->io_addr);
	
	/*把数据从sk_buff中拷贝到TX SRAM中*/ 
	(db->outblk)(db->io_data, skb->data, skb->len);
	
	/*为了统计发送了多少个字节,这个在使用ifconfig中显示出的
	那个发送了多少个字节就是这里计算的*/
	dev->stats.tx_bytes += skb->len;
	
	/*待发送的计数加一*/
	db->tx_pkt_cnt++;
	
	/* TX control: First packet immediately send, second packet queue */
	/*如果只有一个要发送就立即发送,如果这是第二个就应该进行排队了*/ 
	if (db->tx_pkt_cnt == 1) {
		
		/* Set TX length to DM9000 */
		/*把数据的长度填到TXPLL(发送包长度低字节)和TXPLH(发送包长度高字节)中*/
		iow(db, DM9000_TXPLL, skb->len);
		iow(db, DM9000_TXPLH, skb->len >> 8);

		/* Issue TX polling command */
		/*置发送控制寄存器(TX Control Register)的发送请
		求位TXREQ(Auto clears after sending completely),这样就可以发送出去了*/
		iow(db, DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */

		/* 
         *记下此时的时间,这里起一个时间戳的作用,之后的超时会用到。
         *如果当前的系统时间超过设备的trans_start时间 
         *至少一个超时周期,网络层将最终调用驱动程序的tx_timeout。
         *那个这个"一个超时周期"又是什么呢?这个是我们在 
         *probe函数中设置的,ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 
         */
		dev->trans_start = jiffies;	/* save the time stamp */
	} else {

		/* Second packet */
		/*如果是第二个包则把skb->len复制给队列的queue_pkt_len,然后告诉上层停止发送队列,因为发送队列已经满了*/
		db->queue_pkt_len = skb->len;
		
		/*停止接收*/
		netif_stop_queue(dev);
	}

	spin_unlock_irqrestore(&db->lock, flags);

	/* free this SKB */
	/*每个数据包写入网卡SRAM后都要释放skb*/
	dev_kfree_skb(skb);

	return 0;
}

dm9000a中断处理函数:

static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	board_info_t *db = dev->priv;
	int int_status;
	u8 reg_save;

	dm9000_dbg(db, 3, "entering %s\n", __func__);

	/* A real interrupt coming */
	spin_lock(&db->lock);

	/*保存寄存器地址*/
	reg_save = readb(db->io_addr);

	/*禁止DM9000的所有中断*/ 
	iow(db, DM9000_IMR, IMR_PAR);
	
	/*获得DM9000的中断状态*/
	int_status = ior(db, DM9000_ISR);	/* Got ISR */
	iow(db, DM9000_ISR, int_status);	/* Clear ISR status */

	if (netif_msg_intr(db))
		dev_dbg(db->dev, "interrupt status %02x\n", int_status);

	/*检查Interrupt Status Register的第0位,看有没有接收数据*/ 
	if (int_status & ISR_PRS)
		dm9000_rx(dev);

	/*检查Interrupt Status Register的第1位,看有没有发送完数据*/
	if (int_status & ISR_PTS)
		dm9000_tx_done(dev, db);

	if (db->type != TYPE_DM9000E) {
		/*检查Interrupt Status Register的第5位,看链路状态有没有变化*/ 
		if (int_status & ISR_LNKCHNG) {
			/* fire a link-change request */
			schedule_delayed_work(&db->phy_poll, 1);
		}
	}

	/*重新使能相应中断*/ 
	iow(db, DM9000_IMR, db->imr_all);

	/*还原原先的io地址*/ 
	writeb(reg_save, db->io_addr);
	/*还原中断状态*/ 
	spin_unlock(&db->lock);

	return IRQ_HANDLED;
}

dm9000a数据接收函数:

/*
 *  Received a packet and pass to upper layer
 */
static void
dm9000_rx(struct net_device *dev)
{
	board_info_t *db = (board_info_t *) dev->priv;
	struct dm9000_rxhdr rxhdr;
	struct sk_buff *skb;
	u8 rxbyte, *rdptr;
	bool GoodPacket;
	int RxLen;

	/* Check packet ready or not */
	do {
		/*MRCMDX为内存数据预取读命令,并且没有地址增加,
		读数据的第一个字节,直到读到0x01(数据有效)为止。*/
		ior(db, DM9000_MRCMDX);	/* Dummy read */

		/* Get most updated data */
		/*获得数据*/
		rxbyte = readb(db->io_data);

		/* Status check: this byte must be 0 or 1 */
		/*因为只能为0x00或0x01,所以如果大于0x01,则返回*/
		if (rxbyte > DM9000_PKT_RDY) {
			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;
		}
		/*如果为0x00,则返回*/
		if (rxbyte != DM9000_PKT_RDY)
			return;

		/* A packet ready now  & Get status/length */
		/*如果有有效数据包,设置标志标量*/
		GoodPacket = true;

		/*MRCMD是地址增加的内存数据读命令*/
		writeb(DM9000_MRCMD, db->io_addr);

		/*读取RX SRAM中的数据放入struct dm9000_rxhdr中*/
		(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));

		/*将一个无符号的26位小头数值转换成CPU使用的值*/
		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 */
		/*一个数据包的长度应大于64字节*/
		if (RxLen < 0x40) {
			GoodPacket = false;
			if (netif_msg_rx_err(db))
				dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
		}

		/*一个数据包的长度应小于1536字节*/
		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 */
		/*分配一个套接字缓冲区*/
		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 */

			(db->inblk)(db->io_data, rdptr, RxLen);
			dev->stats.rx_bytes += RxLen;

			/* Pass to upper layer */
			/*以太网支持代码导出了辅助函数eth_type_trans,用来查找填入protocol中的正确值*/
			skb->protocol = eth_type_trans(skb, dev);

			/*将套接字缓冲区发向上层*/
			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);
}

/*
 * DM9000 interrupt handler
 * receive the packet to upper layer, free the transmitted packet
 */

static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
{	/*从网络状态寄存器(Network Status Register)中获得发送状态*/

	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */
	/*如果发送状态为NSR_TX2END(第二个包发送完毕)或NSR_TX1END(第一个包发送完毕)*/
	if (tx_status & (NSR_TX2END | NSR_TX1END)) {
		
		/* One packet sent complete */
		/*如果一个数据包发送完,待发送数据包个数减1*/
		db->tx_pkt_cnt--;

		/*如果一个数据包发送完,已发送数据包个数加1*/
		dev->stats.tx_packets++;

		if (netif_msg_tx_done(db))
			dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);

		/* Queue packet check & send */
		/*如果还有数据包要发送*/ 
		if (db->tx_pkt_cnt > 0) {

			/*将发送的长度放到TXPLL,TXPLH寄存器中*/
			iow(db, DM9000_TXPLL, db->queue_pkt_len);
			iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8);

			/*置发送请求位*/ 
			iow(db, DM9000_TCR, TCR_TXREQ);
			/*保存时间戳*/ 
			dev->trans_start = jiffies;
		}
		/*通知内核将待发送数据包放入发送队列*/ 
		netif_wake_queue(dev);
	}
}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值