rt2860v2源码分析一

本文深入探讨rt2860v2的源码,重点解析驱动模块的PCI设备初始化和网络设备模块初始化过程。通过分析`pci_register_device`、`rt2860_probe`等关键函数,揭示了驱动如何挂载在PCI总线上,并使用cfg80211接口注册无线网络设备。驱动程序包括设备检测、注册、卸载、挂起和唤醒功能,以及网络设备和无线设备的初始化步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

git出源码:
https://github.com/wuqiong/rt2860v2-for-openwrt-mt7620

再rt2860v2中搜索字符串__init, 找到驱动模块的入口函数:

os/linux/rbus_main_dev.c:37:int __init rt2880_module_init(VOID);
os/linux/pci_main_dev.c:46:static int __init rt2860_init_module(void);
os/linux/pci_main_dev.c:276:static INT __init rt2860_init_module(VOID)

查看rbus_main_dev.cpci_main_dev.c文件,可以发现rt2860v2驱动在pci_main_dev.c中进行了pci设备模块初始化,在rbus_main_dev.c 中是网络设备模块初始化。

pci_main_dev.c 中分析rt2860v2驱动程序的pci设备模块初始化:

static INT __init rt2860_init_module(VOID)
{
    DBGPRINT(RT_DEBUG_ERROR, ("register %s\n", RTMP_DRV_NAME));

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    return pci_register_driver(&rt2860_driver);
#else
    return pci_module_init(&rt2860_driver);
#endif
}


/* */
/* Driver module unload function */
/* */
static VOID __exit rt2860_cleanup_module(VOID)
{
    pci_unregister_driver(&rt2860_driver);
}

module_init(rt2860_init_module);
module_exit(rt2860_cleanup_module);

__init 中,pci_register_driver 进行了pci设备注册,rt2860v2驱动模块挂载在pci总线上。

/* */
/* Our PCI driver structure */
/* */
static struct pci_driver rt2860_driver =
{
    name:       RTMP_DRV_NAME,
    id_table:   rt2860_pci_tbl,
    probe:      rt2860_probe,
#if LINUX_VERSION_CODE >= 0x20412
    remove:     __devexit_p(rt2860_remove_one),
#else
    remove:     __devexit(rt2860_remove_one),
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#ifdef CONFIG_PM
    suspend:    rt2860_suspend,
    resume:     rt2860_resume,
#endif
#endif
};

PCI设备驱动结构,填充结构体

  • name : RTMP_DRV_NAME 就是rt2860
  • id_talbe :pci设备表,指明该驱动适合那些设备
  • probe :检测驱动设备
  • remove:卸载驱动设备
  • suspend:挂起设备使之处于节能状态
  • resume:唤醒处于挂起态的设备

id_table 中,驱动将选择对应的硬件设备,用此id来识别硬件信息:

/* */
/* Ralink PCI device table, include all supported chipsets */
/* */
static struct pci_device_id rt2860_pci_tbl[] __devinitdata =
{
#ifdef RT2860
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)},     /*RT28602.4G */
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)},
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)},
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)},
    {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)},
#endif /* RT2860 */
    {0,}        /* terminate list */
};

分析pci设备的probe函数,即rt2860v2_probe,该函数内容如下:


/* */
/* PCI device probe & initialization function */
/* */
static INT __devinit   rt2860_probe(
    IN  struct pci_dev              *pci_dev, 
    IN  const struct pci_device_id  *pci_id)
{
    VOID                *pAd = NULL;
    struct  net_device  *net_dev;
    PVOID               handle;
    PSTRING             print_name;
    ULONG               csr_addr;
    INT rv = 0;
    RTMP_OS_NETDEV_OP_HOOK  netDevHook;
    ULONG                   OpMode;

    DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n"));

/*PCIDevInit============================================== */
    /* wake up and enable device */
    if ((rv = pci_enable_device(pci_dev))!= 0)//使能pci设备
    {
        DBGPRINT(RT_DEBUG_ERROR, ("Enable PCI device failed, errno=%d!\n", rv));
        return rv;
    }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    print_name = pci_name(pci_dev);
#else
    print_name = pci_dev->slot_name;
#endif /* LINUX_VERSION_CODE */

    if ((rv = pci_request_regions(pci_dev, print_name)) != 0)//申请PCI的resource
    {
        DBGPRINT(RT_DEBUG_ERROR, ("Request PCI resource failed, errno=%d!\n", rv));
        goto err_out;
    }

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值