【linux驱动分析】之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 }
二、关于电源管理的设备的挂起和恢复函数
3、停止函数dm9000_stopsuspend函数并不真正把设备从内核中移除,而只是标志设备为removed状态,并设置挂起标志位为1,最后关闭设备。
resume函数将挂起的设备复位并初始化,软后将设备标志为attached状态,并设置挂起标志位为0。
三、dm9000的打开和停止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 }1、打开函数dm9000_open2、dm9000_init_dm9000函数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 that 16 * 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 }
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 end 24 * up dumping the wake events if we disable this. There is already 25 * 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 }它会做与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 }
【linux驱动分析】之dm9000驱动分析(七):dm9000的卸载挂起和恢复以及打开和停止,古老的榕树,5-wow.com
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。