热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【linux驱动分析】之dm9000驱动分析(七):dm9000的卸载挂起和恢复以及打开和停止

分析dm9000的卸载,挂起和恢复,以及dm9000的打开和停止。涉及到的函数为:1staticint__devexit2dm9000_drv_remove(structplatfo
分析dm9000的卸载,挂起和恢复,以及dm9000的打开和停止。涉及到的函数为:
 1 static int __devexit
2 dm9000_drv_remove(struct platform_device *pdev)
3 static int
4 dm9000_drv_suspend(struct device *dev)
5 static int
6 dm9000_drv_resume(struct device *dev)
7 static int
8 dm9000_open(struct net_device *dev)
9 static int
10 dm9000_stop(struct net_device *ndev)
一、卸载驱动
驱动中可以看到,在模块卸载时执行
platform_driver_unregister(&dm9000_driver);
在卸载platform_driver时会执行remove函数,remove函数的功能是把设备从内核中移除,释放内存区域。下面给出dm9000_drv_remove函数的代码:
 1 static int __devexit
2 dm9000_drv_remove(struct platform_device *pdev)
3 {
4 struct net_device *ndev = platform_get_drvdata(pdev);
5
6 platform_set_drvdata(pdev, NULL);
7
8 unregister_netdev(ndev);
9 dm9000_release_board(pdev, netdev_priv(ndev));
10 free_netdev(ndev); /* free device structure */
11
12 dev_dbg(&pdev->dev, "released and freed device\n");
13 return 0;
14 }
15
16
17 /* dm9000_release_board
18 *
19 * release a board, and any mapped resources
20 */
21
22 static void
23 dm9000_release_board(struct platform_device *pdev, struct board_info *db)
24 {
25 /* unmap our resources */
26
27 iounmap(db->io_addr);
28 iounmap(db->io_data);
29
30 /* release the resources */
31
32 release_resource(db->data_req);
33 kfree(db->data_req);
34
35 release_resource(db->addr_req);
36 kfree(db->addr_req);
37 }
二、关于电源管理的设备的挂起和恢复函数

suspend函数并不真正把设备从内核中移除,而只是标志设备为removed状态,并设置挂起标志位为1,最后关闭设备。

resume函数将挂起的设备复位并初始化,软后将设备标志为attached状态,并设置挂起标志位为0。

 1 static int
2 dm9000_drv_suspend(struct device *dev)
3 {
4 struct platform_device *pdev = to_platform_device(dev);
5 struct net_device *ndev = platform_get_drvdata(pdev);
6 board_info_t *db;
7
8 if (ndev) {
9 db = netdev_priv(ndev);
10 db->in_suspend = 1;
11
12 if (!netif_running(ndev))
13 return 0;
14
15 netif_device_detach(ndev);
16
17 /* only shutdown if not using WoL */
18 if (!db->wake_state)
19 dm9000_shutdown(ndev);
20 }
21 return 0;
22 }
23
24 static int
25 dm9000_drv_resume(struct device *dev)
26 {
27 struct platform_device *pdev = to_platform_device(dev);
28 struct net_device *ndev = platform_get_drvdata(pdev);
29 board_info_t *db = netdev_priv(ndev);
30
31 if (ndev) {
32 if (netif_running(ndev)) {
33 /* reset if we were not in wake mode to ensure if
34 * the device was powered off it is in a known state */
35 if (!db->wake_state) {
36 dm9000_reset(db);
37 dm9000_init_dm9000(ndev);
38 }
39
40 netif_device_attach(ndev);
41 }
42
43 db->in_suspend = 0;
44 }
45 return 0;
46 }

三、dm9000的打开和停止

1、打开函数dm9000_open
 1 /* 2  * Open the interface. 3  * The interface is opened whenever "ifconfig" actives it. 4  */ 5 static int 6 dm9000_open(struct net_device *dev) 7 { 8     board_info_t *db = netdev_priv(dev); 9     unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;10 11     /* db结构体中的成员msg_enble,在probe函数中赋值为NETIF_MSG_LINK */12     if (netif_msg_ifup(db))13         dev_dbg(db->dev, "enabling %s\n", dev->name);14 15     /* If there is no IRQ type specified, default to something that16  * may work, and tell the user that this is a problem */17 18     if (irqflags == IRQF_TRIGGER_NONE)19         dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");20 21     irqflags |= IRQF_SHARED;22     /* 申请中断,中断函数dm9000_interrupt */23     if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))24         return -EAGAIN;25 26     /* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */27     iow(db, DM9000_GPR, 0);    /* REG_1F bit0 activate phyxcer */28     mdelay(1); /* delay needs by DM9000B */29 30     /* Initialize DM9000 board */31  dm9000_reset(db);32     /* dm9000初始化,下面会对这个函数做详细分析 */33  dm9000_init_dm9000(dev);34 35     /* Init driver variable */36     db->dbug_cnt = 0;37 38     /* 检查mii接口 39  * Returns 1 if the duplex mode changed, 0 if not.40  * If the media type is forced, always returns 0.41  * */42     mii_check_media(&db->mii, netif_msg_link(db), 1);43     /* 开启网络接口数据发送队列 */44  netif_start_queue(dev);45     /*延时一段时间执行dm9000_poll_work,原来在probe函数里把这个函数加入了工作队列,现在来调度执行*/46  dm9000_schedule_poll(db);47 48     return 0;49 }
2、dm9000_init_dm9000函数
 1 /* 2  * Initialize dm9000 board 3  */ 4 static void 5 dm9000_init_dm9000(struct net_device *dev) 6 { 7     board_info_t *db = netdev_priv(dev); 8     unsigned int imr; 9     unsigned int ncr;10 11     dm9000_dbg(db, 1, "entering %s\n", __func__);12 13     /* I/O mode */14     db->io_mode = ior(db, DM9000_ISR) >> 6;    /* ISR bit7:6 keeps I/O mode */15 16     /* Checksum mode */17     dm9000_set_rx_csum_unlocked(dev, db->rx_csum);18 19     iow(db, DM9000_GPCR, GPCR_GEP_CNTL);    /* Let GPIO0 output */20 21     ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;22 23     /* if wol is needed, then always set NCR_WAKEEN otherwise we end24  * up dumping the wake events if we disable this. There is already25  * a wake-mask in DM9000_WCR */26     if (db->wake_supported)27         ncr |= NCR_WAKEEN;28 29  iow(db, DM9000_NCR, ncr);30 31     /* Program operating register */32     iow(db, DM9000_TCR, 0);            /* TX Polling clear */33     iow(db, DM9000_BPTR, 0x3f);    /* Less 3Kb, 200us */34     iow(db, DM9000_FCR, 0xff);    /* Flow Control */35     iow(db, DM9000_SMCR, 0);        /* Special Mode */36     /* clear TX status */37     iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);38     iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */39 40     /* Set address filter table */41  dm9000_hash_table_unlocked(dev);42 43     imr = IMR_PAR | IMR_PTM | IMR_PRM;44     if (db->type != TYPE_DM9000E)45         imr |= IMR_LNKCHNG;46 47     db->imr_all = imr;48 49     /* Enable TX/RX interrupt mask */50  iow(db, DM9000_IMR, imr);51 52     /* Init Driver variable */53     db->tx_pkt_cnt = 0;54     db->queue_pkt_len = 0;55     dev->trans_start = jiffies;56 }
3、停止函数dm9000_stop
它会做与dm9000_stop相反的事情。
 1 /* 2  * Stop the interface. 3  * The interface is stopped when it is brought. 4  */ 5 static int 6 dm9000_stop(struct net_device *ndev) 7 { 8     board_info_t *db = netdev_priv(ndev); 9 10     if (netif_msg_ifdown(db))11         dev_dbg(db->dev, "shutting down %s\n", ndev->name);12 13     cancel_delayed_work_sync(&db->phy_poll);14 15  netif_stop_queue(ndev);16  netif_carrier_off(ndev);17 18     /* free interrupt */19     free_irq(ndev->irq, ndev);20 21  dm9000_shutdown(ndev);22 23     return 0;24 }

推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
author-avatar
日后再曰
这个家伙很懒,
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有