历史上的今天
返回首页

历史上的今天

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

正在发生

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

2021-11-10 来源:eefocus

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

推荐阅读

史海拾趣

启攀微(CHIPHOM)公司的发展小趣事

在快速发展的过程中,启攀微电子(CHIPHOM)始终注重与产业链上下游企业的合作。公司与多家知名芯片制造商、封装测试厂商和终端产品厂商建立了紧密的合作关系,共同推动产品的研发和市场推广。通过合作共赢的模式,启攀微电子(CHIPHOM)不仅提升了自身的技术水平和市场竞争力,还为整个电子行业的发展做出了积极贡献。

电连(ECT)公司的发展小趣事

随着汽车智能化的发展,ECT看到了车载连接器市场的巨大潜力。从2013年开始,公司开始布局车载连接器领域,并成功开发出多款适用于不同车型和场景的车载连接器产品。这一拓展不仅为ECT带来了新的增长点,也进一步巩固了公司在电子连接器行业的领先地位。

APX Technologies公司的发展小趣事

APX Technologies在成立初期就专注于研发高性能的半导体芯片。经过数年的努力,公司成功开发出一种具有革命性的低功耗芯片技术,这一技术极大地提高了电子设备的能效比。随着这一技术的广泛应用,APX Technologies迅速在电子行业中崭露头角,赢得了众多客户的青睐。

意华(CZT)公司的发展小趣事

自1995年成立以来,意华(CZT)始终秉持“诚信”的合作态度和“创新”的发展思路。在公司初创阶段,面对激烈的市场竞争,意华坚持高质量的产品和服务,赢得了客户的信赖。同时,公司不断投入研发,推出了一系列具有创新性的电子产品和连接器,迅速在市场上树立了良好的口碑。

FINDER公司的发展小趣事

为了实现公司的长远发展,意华于2010年开始筹备上市工作。经过多年的准备和努力,意华成功在资本市场上市,为公司的发展注入了新的活力。上市后,意华通过资本市场融资和资本运作,加速了公司的扩张和技术创新步伐。同时,公司也更加注重规范运作和透明度提升,赢得了投资者的信任和支持。

bb-smartworx公司的发展小趣事

为了提高产品质量,意华先后通过了ISO9001、ISO14001、IECQC080000等多项国际质量管理体系认证。这些认证不仅证明了公司的质量管理水平,也为客户提供了更可靠的产品保障。通过持续的质量改进和过程控制,意华的产品质量得到了显著提升,赢得了更多客户的认可。

问答坊 | AI 解惑

电信技术名词解释:EDGE技术详解

EDGE是英文Enhanced Data Rate for GSM Evolution 的缩写,即增强型数据速率GSM演进技术。EDGE是一种从GSM到3G的过渡技术,它主要是在GSM系统中采用了一种新的调制方法,即最先进的多时隙操作和8PSK调制技术。由于8PSK可将现有GSM网络采用的GMSK调 ...…

查看全部问答>

步进电机终于有点小收获了~~~~

步进电机终于转动起来了!!!!真是意想不到 只是转动的力度非常的小,带不动纸 ,需要调节motor的频率?还是调节什么呢?就是让它转动的力度大些 wow~~~~~~~~~·…

查看全部问答>

PLD EPM7128S里的内容 如何用MAX+plus II 通过JTAG把它倒出来?

求助 PLD EPM7128S里的内容 如何用MAX+plus II 通过JTAG把它倒出来?…

查看全部问答>

关于WDM和Directshow的结合开发,100分重谢!

    小弟目前已经开发完saa7130在windows下的驱动,现在准备将其写成硕士论文,前不久交了初稿,被导师痛批,道:没有丝豪创新点!郁闷之至,遂前往eeworld来寻求慰藉。请问各位大侠,能不能将directshow的部分小功能整合到WDM驱动中实现 ...…

查看全部问答>

TO USB驱动开发的例程问题

本人使用Cy7c68013A进行开发,其它例程都已经完成,控制传输找资料已经完成. 只是剩下   DriverObject->MajorFunction[IRP_MJ_WRITE] = Ezusb_Write;   //写入数据    DriverObject->MajorFunction[IRP_MJ_READ] = E ...…

查看全部问答>

Go Main

我使用的是2407 用汇编写程序时,调试 远行一切正常 当使用C时,发现load 后能进入_cint0,但点go main 程序就会跑飞(不能执行 call main那行 ) 请问这会是由什么原因引起的?…

查看全部问答>

高效率LED驅動電源設計

高效率LED驅動電源設計 作者: 德州儀器Robert Kollman   摘要   本文提供LED特性及驅動電源優缺點的概要說明。文中將介紹數種常見的電源供應應用電路,並且詳細說明其閉迴路設計。本文亦討論LED調光電路,同時介紹兩種調光電路設計 ...…

查看全部问答>

转售一些剩余芯片以及板子。

芯片的价格都是按照淘包成交价的一半左右来定的。有些没有明确交易,如果你想要,并且你有明确交易价格。就按照半价来出。 话不多说,上清单。 洞洞板   5x7CM 10块  7X12CM 8块    10元 MAX6033AA   & ...…

查看全部问答>

51单片机在外部中断0服务程序中,如何用串口中断??

51单片机在外部中断0服务程序中,如何用串口中断?? 我写的程序有问题吗?为什么我在外部中断0程序中不能用串口中断??? int main(void) { while(1); return 0; } //外部中断0 void INT0_Interrput(void) interrupt 0 {     & ...…

查看全部问答>

MQTT not IoT “god protocol,” but getting closer

有一种协议及其相关内容将万维网推向了成功,这就是 IP,或者叫做互联网协议。这个协议是每种浏览器与互联网连接的基础,也构成了 IT 数据中心的主干。有人认为物联网也会走同样的发展道路,他们相信拥有一个 IP 地址就足以让物联网连接在一起了 ...…

查看全部问答>