//涉及到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); }
dm9000驱动理解四(dm9000操作函数集net_device_ops)
最新推荐文章于 2023-07-17 16:20:23 发布