dm9000驱动理解四(dm9000操作函数集net_device_ops)

//涉及到dm9000底层的操作函数集
static const struct net_device_ops dm9000_netdev_ops = {
	.ndo_open		= dm9000_open,
	.ndo_stop		= dm9000_stop,
	.ndo_start_xmit		= dm9000_start_xmit,
	.ndo_tx_timeout		= dm9000_timeout,
	.ndo_set_multicast_list	= dm9000_hash_table, //设置组播地址 
	.ndo_do_ioctl		= dm9000_ioctl,
	.ndo_change_mtu		= eth_change_mtu, //修改mtu值,mtu就是最大数据包大小
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= dm9000_poll_controller,
#endif
};


static int dm9000_open(struct net_device *dev)
{
	board_info_t *db = netdev_priv(dev);
	//这个db->irq_res->flags就是在板级配置文件中设置的IRQ_flag
	//以前一直不理解为什么要配置两个IRQ,现在明白了,因为驱动里有两个中断。
	
	unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;

	if (netif_msg_ifup(db))
		dev_dbg(db->dev, "enabling %s\n", dev->name);

	/* If there is no IRQ type specified, default to something that
	 * may work, and tell the user that this is a problem */

	if (irqflags == IRQF_TRIGGER_NONE)
		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");

	irqflags |= IRQF_SHARED;

	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
		return -EAGAIN;

	/* Initialize DM9000 board */
	//复位DM9000,就是往NCR寄存器写0x01
	dm9000_reset(db);
	//dm9000初始化
	dm9000_init_dm9000(dev);

	/* Init driver variable */
	db->dbug_cnt = 0;
	//mii是什么,mii是介质无关接口,这个函数是检测mii接口状态
	//在我imx536项目中,移植dm9000后,执行ifconfig up命令后。老是提示link down
	//最后追踪到这个函数里。
	mii_check_media(&db->mii, netif_msg_link(db), 1);
	//告诉上层网络驱动层,可以发送数据到驱动层
	netif_start_queue(dev);
	//如果是DM9000E类芯片,延迟等待队列
	dm9000_schedule_poll(db);

	return 0;
}

static int dm9000_stop(struct net_device *ndev)
{
	//定义一个指针结构体指向网络结构体的末尾,即网络设备私有数据地址
	board_info_t *db = netdev_priv(ndev);

	if (netif_msg_ifdown(db))
		dev_dbg(db->dev, "shutting down %s\n", ndev->name);

	//调用 cancel_work_sync 将会终止队列中的任务或者阻塞任务直到回调结束(如果处理程序已经在处理该任务)。 
	//如果任务被延迟,可以调用 cancel_delayed_work_sync
	cancel_delayed_work_sync(&db->phy_poll);
	//停止接收数据
	netif_stop_queue(ndev);
	//对立的函数是netif_carrier_on,告诉内核设备载波丢失。网上搜查得知
	//大部分涉及实际的物理连接的网络技术提供有一个载波状态; 载波存在说明硬件存在并准备好
	netif_carrier_off(ndev);

	/* free interrupt */
	free_irq(ndev->irq, ndev);
	//关闭dm9000,主要是关phy,关中断,关接收。
	dm9000_shutdown(ndev);

	return 0;
}

//看门狗超时时调用该函数
static void dm9000_timeout(struct net_device *dev)
{
	board_info_t *db = netdev_priv(dev);
	u8 reg_save;
	unsigned long flags;

	/* Save previous register address */
	reg_save = readb(db->io_addr);
	//获得自旋锁,关中断
	spin_lock_irqsave(&db->lock, flags);
	//停止发送队列
	netif_stop_queue(dev);
	//软件复位dm9000
	dm9000_reset(db);
	//初始化dm9000
	dm9000_init_dm9000(dev);
	/* We can accept TX packets again */
	//jiffies,记录系统启动以来的节拍总数
	dev->trans_start = jiffies; /* prevent tx timeout */
	//开启发送队列
	netif_wake_queue(dev);

	/* Restore previous register address */
	writeb(reg_save, db->io_addr);
	//释放自旋锁,开中断
	spin_unlock_irqrestore(&db->lock, flags);
}



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值