linux gmac驱动分析,Broadcom mac80211 驱动解析

1. 驱动的主进口如下:

/**

* This is the main entry point for the brcmsmac driver.

*

* This function is scheduled upon module initialization and

* does the driver registration, which result in brcms_bcma_probe()

* call resulting in the driver bringup.

*/

staticvoid brcms_driver_init(struct work_struct *work)

{

int error;

error = bcma_driver_register(&brcms_bcma_driver);

if (error)

pr_err("%s: register returned %d\n", __func__, error);

}

可以看到brcms_bcma_driver作为参数传递给了bcma_driver_register(). brcms_bcma_driver的定义如下:

staticstruct bcma_driver brcms_bcma_driver = {

.name     = KBUILD_MODNAME,

.probe    = brcms_bcma_probe,

.suspend  = brcms_suspend,

.resume   = brcms_resume,

.remove   = brcms_remove,

.id_table = brcms_coreid_table,

};

重视此中的probe函数。

2. 按照上方的解析,紧接着brcms_bcma_probe将会被调用。

staticint brcms_bcma_probe(struct bcma_device *pdev)

{

struct brcms_info *wl;

struct ieee80211_hw *hw;

dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",

pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,

pdev->irq);

if ((pdev->id.manuf != BCMA_MANUF_BCM) ||

(pdev->id.id != BCMA_CORE_80211))

return -ENODEV;

hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);

if (!hw) {

pr_err("%s: ieee80211_alloc_hw failed\n", __func__);

return -ENOMEM;

}

SET_IEEE80211_DEV(hw, &pdev->dev);

bcma_set_drvdata(pdev, hw);

memset(hw->priv, 0, sizeof(*wl));

wl = brcms_attach(pdev);

if (!wl) {

pr_err("%s: brcms_attach failed!\n", __func__);

return -ENODEV;

}

brcms_led_register(wl);

return0;

}

重视brcms_bcma_probe()函数体中的这行代码:

hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);

这里的参数是brcms_ops, 它的定义如下:

staticconststruct ieee80211_ops brcms_ops = {

.tx = brcms_ops_tx,

.start = brcms_ops_start,

.stop = brcms_ops_stop,

.add_interface = brcms_ops_add_interface,

.remove_interface = brcms_ops_remove_interface,

.config = brcms_ops_config,

.bss_info_changed = brcms_ops_bss_info_changed,

.configure_filter = brcms_ops_configure_filter,

.sw_scan_start = brcms_ops_sw_scan_start,

.sw_scan_complete = brcms_ops_sw_scan_complete,

.conf_tx = brcms_ops_conf_tx,

.sta_add = brcms_ops_sta_add,

.ampdu_action = brcms_ops_ampdu_action,

.rfkill_poll = brcms_ops_rfkill_poll,

.flush = brcms_ops_flush,

};

以tx为例,在tx.c中将会用到该函数指针。

这里有须要跟一下ieee80211_alloc_hw(), 关于该函数,Johannes Berg在他的《The mac80211 subsystem for kernel developers》中的申明是:

ieee80211_alloc_hw— Allocate a new hardware device

This must be called once for each hardware device. The returned pointer must be used to refer to this

device when calling other functions. mac80211 allocates a private data area for the driver pointed to by

priv in struct ieee80211_hw, the size of this area is given as priv_data_len.

我们重视到brcms_ops作为参数被传递给了ieee80211_alloc_hw(). 并且在该函数体中有如许的代码:

local->ops = ops;

这很首要,我们在后面会说起到。之后就是要new一个struct wiphy - wireless hardware description出来

/* Ensure 32-byte alignment of our private data and hw private data.

* We use the wiphy priv data for both our ieee80211_local and for

* the driver""s private data

*

* In memory it""ll be like this:

*

* +-------------------------+

* | struct wiphy        |

* +-------------------------+

* | struct ieee80211_local  |

* +-------------------------+

* | driver""s private data   |

* +-------------------------+

*

*/

priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;

wiphy = wiphy_new(&mac80211_config_ops, priv_size);

别的还有tasklet初始化的代码,是跟接管数据慎密相干的:

tasklet_init(&local->tasklet,

ieee80211_tasklet_handler,

(unsigned long) local);

在后面一节谈数据接管的时辰会胪陈。

在brcms_bcma_probe()的函数体中,完成了ieee80211_alloc_hw()之后的另一行首要代码就是:

wl = brcms_attach(pdev);

3. 接着解析brcms_attach()

3.1 起首初始化Tasklet

/* setup the bottom half handler */

tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);

这里可以看到中断处理惩罚函数是brcms_dpc().

3.2 Download firmware

/* prepare ucode */

if (brcms_request_fw(wl, pdev) 

wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "

"%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");

brcms_release_fw(wl);

brcms_remove(pdev);

return NULL;

}

3.3 初始化硬件

/*

* low level attach steps(all hw accesses go

* inside, no more in rest of the attach)

*/

err = brcms_b_attach(wlc, core, unit, piomode);

3.4 申请中断

/* register our interrupt handler */

if (request_irq(pdev->irq, brcms_isr,

IRQF_SHARED, KBUILD_MODNAME, wl)) {

wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);

goto fail;

}那么傍边断产生时比如稀有据过来须要接管时,brcms_isr()就会被触发。

3.5 注册设备

err = ieee80211_register_hw(hw);

if (err)

wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"

"%d\n", __func__, err);

ieee80211_register_hw()将会调用到ieee80211_if_add()来注册网卡设备

经由过程ieee80211_if_add()的代码可以看到这里终于调用了熟悉的register_netdevice()

int ieee8

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值