atheros无线驱动初始化流程

本文主要是描述pci接口的atheros无线驱动的初始化流程

先贴一张网上找来的图片,atheros的驱动是分层的


从下到上的每一层为:

HAL:Hardware  Abstraction Layer

LMAC: Lower MAC

UMAC: Upper  MAC

OSIF: OS Interface Layer。


1. atheros的主要数据结构:

struct ath_softc_net80211 {	//只列出几个重要的成员
    struct ieee80211com     sc_ic;      /* NB: base class, must be first */
    ath_dev_t               sc_dev;     /* Atheros device handle */
    struct ath_ops          *sc_ops;    /* Atheros device callback table */

    void                    (*sc_node_cleanup)(struct ieee80211_node *);
    void                    (*sc_node_free)(struct ieee80211_node *);

    osdev_t                 sc_osdev;   /* handle to use OS-independent services */
}

ath_softc_net80211是UMAC层的核心数据结构,是net_device的private数据

ath_ops是设备回调函数表,定义了好多的回调函数

struct ath_softc {	//只列出重要的几个成员

    struct ath_ops          sc_ath_ops;

    ieee80211_handle_t      sc_ieee;
    struct ieee80211_ops    *sc_ieee_ops;

    osdev_t                 sc_osdev;   /* Opaque handle to OS-specific device */
    struct ath_hal          *sc_ah;     /* Atheros HAL */
}
ath_softc是LMAC层的核心数据结构

atheros的几个数据结构都比较大,好多是函数指针,充分体现了分层设计的思想


2. atheros无线驱动初始化流程

pci接口的无线网卡的初始化从ath_pci_probe(if_ath_pci.c)开始讲,不清楚的可以参考我的linux设备驱动的文章。

static int
ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
    unsigned long mem;
    struct ath_pci_softc *sc;
    struct net_device *dev;
    ......

    dev = alloc_netdev(sizeof(struct ath_pci_softc), "wifi%d", ether_setup);
    if (dev == NULL) {
        printk(KERN_ERR "ath_pci: no memory for device state\n");
        goto bad2;
    }
    sc = ath_netdev_priv(dev);
    sc->aps_osdev.netdev = dev;
    sc->aps_osdev.bdev = (void *) pdev;
#ifdef ATH_SUPPORT_HTC
    sc->aps_osdev.wmi_dev = (void *)sc;
#endif

    dev->irq = pdev->irq;
    dev->mem_start = mem;
    dev->mem_end = mem + pci_resource_len(pdev, 0);

    /*
     * Don't leave arp type as ARPHRD_ETHER as this is no eth device
     */
    dev->type = ARPHRD_IEEE80211;	

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    SET_MODULE_OWNER(dev);
#endif
    SET_NETDEV_DEV(dev, &pdev->dev);

    pci_set_drvdata(pdev, dev);


    if (__ath_attach(id->device, dev, &bus_context, &sc->aps_osdev) != 0)
        goto bad3;

    athname = ath_hal_probe(id->vendor, id->device);

	..........

    return 0;
bad3:
    free_netdev(dev);
bad2:
    iounmap((void *) mem);
bad1:
    release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
bad:
    pci_disable_device(pdev);
    return (-ENODEV);
}
分配一个net_device和ath_pci_softc,其中ath_pci_softc内嵌了一个UMAC核心数据结构ath_softc_net80211
struct ath_pci_softc {
    struct ath_softc_net80211   aps_sc;
    struct _NIC_DEV             aps_osdev;
#ifdef ATH_BUS_PM
    u32                         aps_pmstate[16];
#endif
};
其中__ath_attach(ath_linux.c)是一个非常重要,也是一个非常复杂的函数。

int
__ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_CONTEXT *bus_context, osdev_t osdev)
{
    struct ath_softc_net80211 *scn = ath_netdev_priv(dev);
    struct ieee80211com *ic = &scn->sc_ic;
    
    /*
     * Set bus context to osdev
     */
    osdev->bc = *bus_context;
	//LMAC层数据结构的初始化
    error = ath_attach(devid, bus_context, scn, osdev, &ath_params, &hal_conf_parm, &wlan_reg_params);

    if (error != 0)
        goto bad;

 

    ald_init_netlink();



    osif_attach(dev);
    
    
    /*
     * initialize tx/rx engine
     */
    error = scn->sc_ops->tx_init(scn->sc_dev, ATH_TXBUF);	//对应ath_tx_init
    if (error != 0)
        goto bad1;

    error = scn->sc_ops->rx_init(scn->sc_dev, ATH_RXBUF);	//对应ath_rx_init
    if (error != 0)
        goto bad2;

    /*
     * setup net device
     */

    dev->netdev_ops = &athdev_net_ops;
      

    /*
    ** Attach the iwpriv handlers
    */
    
    ath_iw_attach(dev);

    /*
     * setup interrupt serivce routine
     */
     
    ATH_INIT_TQUEUE(&osdev->intr_tq, (adf_os_defer_fn_t)ath_tasklet, (void*)dev);	//定义tasklet





    /*
     * Resolving name to avoid a crash in request_irq() on new kernels
     */ 
    
    dev_alloc_name(dev, dev->name);
 


	//申请中断
    if (request_irq(dev->irq, ath_isr, IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev)) {
    
        printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
        error = -EIO;
        goto bad3;
    }


    /*
     * finally register netdev and ready to go
     */
    if ((error = register_netdev(dev)) != 0) {	//注册net_device
        printk(KERN_ERR "%s: unable to register device\n", dev->name);
        goto bad4;
    }
}
上述函数省略了一些函数,只列出几个重要的函数。ath_attach函数太长了,定义了太多的函数接口,主要调用了ath_dev_attach。

ath_dev_attach位于lmac/ath_dev/ath_main.c文件

ath_dev_attach主要是分配ath_softc结构并且初始化,调用_ath_hal_attach,完成hal层接口的初始化


初始化流程先分析到这里,atheros无线网卡驱动非常复杂,有好多#ifdef。初始化时主要是分配几个重要的数据结构,并且把一些静态定义的函数表赋值到这几个重要数据结构的成员变量中,好多回调函数,等后面用到时再分析。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值