历史上的今天

今天是:2024年11月10日(星期日)

2021年11月10日 | mini2440 dm9000 网卡驱动详解 (二)

发布者:落霞与孤鹜 来源: eefocus关键字:mini2440  dm9000  网卡驱动 手机看文章 扫描二维码
随时随地手机看文章

3. platform_driver的remove, suspend和resume的实现


remove函数的功能是把设备从内核中移除,释放内存区域。该函数在卸载模块时被调用。代码清单如下:


static int __devexit      

dm9000_drv_remove(struct platform_device *pdev)      

{      

    struct net_device *ndev = platform_get_drvdata(pdev);      

     

    platform_set_drvdata(pdev, NULL);      

     

    unregister_netdev(ndev);      

    dm9000_release_board(pdev, (board_info_t *) netdev_priv(ndev));      

    free_netdev(ndev);      /* free device structure */     

     

    dev_dbg(&pdev->dev, "released and freed devicen");      

    return 0;      

}    


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


static int dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)      

{      

    struct net_device *ndev = platform_get_drvdata(dev);      

    board_info_t *db;      

     

    if (ndev) {      

        db = netdev_priv(ndev);      

        db->in_suspend = 1;      

     

        if (netif_running(ndev)) {      

            netif_device_detach(ndev);      

            dm9000_shutdown(ndev);      

        }      

    }      

    return 0;      

}    


resume函数将挂起的设备复位并初始化,软后将设备标志为attached状态,并设置挂起标志位。代码清单如下:


static int dm9000_drv_resume(structplatform_device *dev)     

  

{     

  

   struct net_device *ndev = platform_get_drvdata(dev);     

  

   board_info_t *db = netdev_priv(ndev);     

  

    

  

   if (ndev) {     

  

    

  

       if (netif_running(ndev)) {     

  

           dm9000_reset(db);     

  

           dm9000_init_dm9000(ndev);     

  

    

  

           netif_device_attach(ndev);     

  

       }     

  

    

  

       db->in_suspend = 0;     

  

   }     

  

   return 0;     

  

}   


4. 下面看一下用于填充net_device中netdev_ops和ethtool_ops的一些函数。


代码在上面已经写出来了,为了看着方便在下面再写一遍,可以看出虽然mini2440的板子上没有为DM9000挂EEPROM,但这里还是定义了操作EEPROM的函数。就是说写驱动的时候是不考虑具体的板子的,你板子用不用是你的事,但是我们的驱动应该所有的功能都考虑进去。这也体现了驱动和平台分离的设计思想。


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,      

    .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 const struct ethtool_ops dm9000_ethtool_ops = {      

    .get_drvinfo        = dm9000_get_drvinfo,      

    .get_settings       = dm9000_get_settings,      

    .set_settings       = dm9000_set_settings,      

    .get_msglevel       = dm9000_get_msglevel,      

    .set_msglevel       = dm9000_set_msglevel,      

    .nway_reset     = dm9000_nway_reset,      

    .get_link       = dm9000_get_link,      

    .get_eeprom_len     = dm9000_get_eeprom_len,      

    .get_eeprom     = dm9000_get_eeprom,      

    .set_eeprom     = dm9000_set_eeprom,      

};    


*dm9000_open()


进行的工作有 向内核注册中断,复位并初始化dm9000,检查MII接口,使能传输等。代码清单如下:


/*    

 *  Open the interface.    

 *  The interface is opened whenever "ifconfig" actives it.    

 */     

static int     

dm9000_open(struct net_device *dev)      

{      

    board_info_t *db = netdev_priv(dev);      

    unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;      

     

    if (netif_msg_ifup(db))      

        dev_dbg(db->dev, "enabling %sn", 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))/*注册一个中断,中断处理函数为dm9000_interrupt()*/     

        return -EAGAIN;      

     

    /* Initialize DM9000 board */     

    dm9000_reset(db);      

    dm9000_init_dm9000(dev);      

     

    /* Init driver variable */     

    db->dbug_cnt = 0;      

     

    mii_check_media(&db->mii, netif_msg_link(db), 1);      

    netif_start_queue(dev);      

          

    dm9000_schedule_poll(db);/*之前在probe函数中已经使用INIT_DELAYED_WORK来初始化一个延迟工作队列并关联了一个操作函数dm9000_poll_work(), 此时运行schedule来调用这个函数*/     

     

    return 0;      

}    


*dm9000_stop()


做的工作基本上和open相反。代码清单如下:


/*    

 * Stop the interface.    

 * The interface is stopped when it is brought.    

 */     

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 %sn", ndev->name);      

     

    cancel_delayed_work_sync(&db->phy_poll); /*杀死延迟工作队列phy_poll*/     

     

        /*停止传输并清空carrier*/     

    netif_stop_queue(ndev);      

    netif_carrier_off(ndev);      

     

    /* free interrupt */     

    free_irq(ndev->irq, ndev);      

     

    dm9000_shutdown(ndev);      

     

    return 0;      

}    


*dm9000_start_xmit()


重要的发送数据包函数。从上层发送sk_buff包。在看代码之前先来看一下DM9000是如何发送数据包的。

如上图所示,在DM9000内部SRAM中,地址0x0000~0x0BFF是TX Buffer,地址0x0C00~0x3FFF是RX Buffer。在发送一个包之前,包中的有效数据必须先被存储到TX Buffer中并且使用输出端口命令来选择MWCMD寄存器。包的长度定义在TXPLL和TXPLH中。最后设置TXCR寄存器的bit[0] TXREQ来自动发送包。如果设置了IMR寄存器的PTM位,则DM9000会产生一个中断触发在ISR寄存器的bit[1]=PTS=1, 同时设置一个完成标志在NSR寄存器的bit[2]=TX1END或者 bit[3]=TX2END,表示包已经发送完了。发送一个包的具体步骤如下:


Step 1: 检查存储数据宽度。通过读取中断状态寄存器(ISR)的bit[7:6]来确定是8bit,16bit还是32bit。


Step 2: 写数据到TX SRAM中。


Step 3: 写传输长度到TXPLL和TXPLH寄存器中。


Step 4: 设置TXCR寄存器的bit[0]TXREQ来开始发送一个包。


代码清单如下,让我们看看在获得自旋锁这段期间都干了些什么:


/*    

 *  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;      

    board_info_t *db = netdev_priv(dev);      

[1] [2]
关键字:mini2440  dm9000  网卡驱动 引用地址:mini2440 dm9000 网卡驱动详解 (二)

上一篇:Mini2440 DM9000 驱动分析(一)
下一篇:mini2440 dm9000 网卡驱动详解 (一)

推荐阅读

集微网消息(文/小如)11月8日,重庆西永综合保税区管委会与山西宇皓新型光学材料有限公司举行了西永导光板项目的签约,项目建成投产后,将实现年产导光板5千万台件,主要为重庆京东方和重庆惠科供货。        山西宇皓将在西永微电园投资2.3亿元,建成一家液晶显示器、激光导光板、光学级挤压板等新型光学材料研发、生产、销售于一体的企业。  ...
(文章来源:中科罗伯特机器人学院) 我国早前由于充足的劳动力以及较低的劳动成本,吸引了许多外商投资,使得我国的制造业发展迅速。在之后十多年,我国制造业逐渐转型升级,密集型的手工劳动已经不能适应时代发展的需求。特别是最近今年人力成本的成倍增长。迫使我国制造业从沿海到内陆掀起了一股机器换人、工业自动化的浪潮。 我国的大部分工业在全...
如今,传统照明系统已被技术先进的智能照明解决方案所取代,这些解决方案正在逐步改变我们对建筑控制规范的思考方式。 近年来,照明行业发生了一些变化,尽管某些变化已经悄然发生,并不一定会在建筑环境之外引起很多轰动,但诸如自动照明控制和自动照明的出现等发展已成为现实。 LED 技术已成为主流,极大地改变了照明市场。 完全集成到建筑操作系统中...
据外媒报道,半导体专家Nexperia宣布推出650 V、10 A碳化硅(SiC)肖特基二极管,进入高功率碳化硅二极管市场。Nexperia是高效功率氮化镓(GaN)FET值得信赖的供应商,此次新品推出是该公司的一项战略举措, 以扩展其高压宽带隙半导体器件产品。(图片来源:Nexperia)Nexperia的首款SiC肖特基二极管具有650 V重复峰值反向电压(VRRM)和10 A连续正向...

史海拾趣

问答坊 | AI 解惑

制梁厂水泥养护室温度集中监测系统

随着国民经济的快速发展,近年来高等级公路、铁路大量修建。水泥混凝土构件在桥梁建设中占有重要位置。影响水泥构件强度性能的因素有1.水泥的矿物成分2.外添加剂3.矿物掺料4.用水量5.水泥混凝土的养护 混凝土浇捣后,之所以能逐渐凝结硬化,主要是 ...…

查看全部问答∨

求个键盘 以及LED显示的流程图 和程序

求个键盘 以及LED显示的流程图 和程序求个键盘 以及LED显示的流程图 和程序   键盘是4个独立键盘  LED是通过TLC1549转换的…

查看全部问答∨

mobile c++ 如何控制手机按音量键时不让其响应

mobile c++ 如何控制手机按音量键时不让其响应 也就是说当我正在运行一个程序时,当按音量键时,一般会把当前程序退到后台,过一会后再置到前台,但现在我想让当前程序一直处于前台,也就是说当我的这个程序运行时,就不响应音量键。请问该怎么 ...…

查看全部问答∨

有关简繁字体的显示

最近用PlatForm Builder订制了一个系统.是一个中英台语的系统.同时加了SimSum&SimSum2_60 MingLis&MingLis2_80两种字体.默认开机语言是台语.在机器上只能显示繁体,简体只能显示与繁体有交集地字符.我要怎么让它同时都能显示简体和繁体两种字体. ...…

查看全部问答∨

怎么用zigbee给邻居节点发送信息啊

zigbee好像哪里有邻居节点信息,怎么和所有邻居节点通信,取得他们的信息呢…

查看全部问答∨

咨询问题

论坛里有没有搞OMAP_L138的,我最近在研究这个板子,遇到了一些问题,就是我程序也下进板子了,也可以编译,运行,最后下到板子里也可以把程序跑完了,可是当我用View观察图形时,就出不来了,谁人知道是什么原因吗?麻烦知道的给解决一下,不胜感 ...…

查看全部问答∨

关于I2C的问

这两天做个I2C方面的东西,可以Master读取数据的时候总是卡住,用示波器看了下,发现少个CLOCK,有谁知道啥原因吗?…

查看全部问答∨

易电源心得体会

易电源 TI为我们这些开发项目的提供了很多不错的电源解决方案和电源管理芯片,易电源更是简单我们的电源电路和需用开发流程中的时间减少了很多 论坛活动真多,要多多学习啊   游戏也。。是难玩我的60分。。。。图案会乱跑。。方左它 ...…

查看全部问答∨

利用AD5754 DAC提供软件可配置的16位、四通道单极性/双极性电压输出

利用AD5754 DAC提供软件可配置的16位、四通道单极性/双极性电压输出 …

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved