bcm code save 不良和哪部分有关,matlab求解方程组

2244人阅读
BCMwifi驱动学习
一、wifi详解1
1、代码路径:Z:\home\stonechen\svn\3rdparty\wifi\BCM43362\special\bcmdhd\dhd\sys\dhd_linux.c
#if LINUX_VERSION_CODE &=KERNEL_VERSION(2, 6, 0)
late_initcall();
module_init(dhd_module_init);
module_exit(dhd_module_cleanup);
以上代码是wifi驱动的入口函数!!!!
static int __initdhd_module_init(void)
int error = 0;
DHD_TRACE((&%s: Enter\n&,__FUNCTION__));
dhd_msg_level=0
wl_android_init();//设置wlan的名字
。。。。。。。。
/* Call customer gpio to turn onpower with WL_REG_ON signal */
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);//开启wlan的电源
注:此函数调用如下!!!
caseWLAN_POWER_ON:
WL_TRACE((&%s:call customer specific GPIO to turn on WL_REG_ON\n&,
__FUNCTION__));
#ifdefCUSTOMER_HW
bcm_wlan_power_on(1);//这里将调用customize下的board_cfg.c
/*Lets customer power to get stable */
OSL_DELAY(200);
#endif/* CUSTOMER_HW */
voidbcm_wlan_power_on(int mode)
gpio_request(90,&gpio90&);
gpio_direction_output(90,0);
mdelay(10);
gpio_direction_output(90,1);
printk(&bcm_wlan_power_on1\n&);
mdelay(200);
if(mode==1)
printk(&bcm_wlan_power_on2\n&);
SP_force_scan_sdio(1);
//bcm_detect_card(0);
printk(&bcm_wlan_power_on3, start mmc_detect_change\n&);
//setOOB_Wake up Source for WIFI. /*GPIO142*/
//__raw_bits_or(BIT_14,SPRD_GPIO_BASE+0xX18); /*Michael*/
EXPORT_SYMBOL(bcm_wlan_power_on);
#ifdefined(CONFIG_WIFI_CONTROL_FUNC)
goto fail_1;
#if (LINUX_VERSION_CODE &=KERNEL_VERSION(2, 6, 27))
sema_init(&dhd_registration_sem,0);
#endif /* (LINUX_VERSION_CODE &=KERNEL_VERSION(2, 6, 27)) */
error = dhd_bus_register();
if (!error)
printf(&\n%s\n&,dhd_version);
DHD_ERROR((&%s:sdio_register_driver failed\n&, __FUNCTION__));
goto fail_1;
#if (LINUX_VERSION_CODE &=KERNEL_VERSION(2, 6, 27))
* Wait till MMCsdio_register_driver callback called and made driver attach.
* It's needed to make sync up exitfrom dhd insmod and
* Kernel MMC sdio device callbackregistration
if(down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) {
error = -ENODEV;
DHD_ERROR((&%s:sdio_register_driver timeout\n&, __FUNCTION__));
goto fail_2;
#if defined(WL_CFG80211)
wl_android_post_init();
#if 1 && (LINUX_VERSION_CODE&= KERNEL_VERSION(2, 6, 27))
dhd_bus_unregister();
#endif /* (LINUX_VERSION_CODE &=KERNEL_VERSION(2, 6, 27)) */
#ifdefined(CONFIG_WIFI_CONTROL_FUNC)
wl_android_wifictrl_func_del();
/* Call customer gpio to turn offpower with WL_REG_ON signal */
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
2、intwl_android_wifictrl_func_add(void)函数Z:\home\stonechen\svn\\3rdparty\wifi\BCM43362\special\bcmdhd\wl\sys\wl_android.c
intwl_android_wifictrl_func_add(void)
int ret = 0;
sema_init(&wifi_control_sem,0);
if (ret) {
DHD_ERROR((&%s:platform_driver_register failed\n&, __FUNCTION__));
g_wifidev_registered = 1;
/* Waiting callback afterplatform_driver_register is done or exit with error */
if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
ret = -EINVAL;
DHD_ERROR((&%s:platform_driver_register timeout\n&, __FUNCTION__));
static int wifi_add_dev(void)
DHD_TRACE((&## Callingplatform_driver_register\n&));
platform_driver_register(&wifi_device);
platform_driver_register(&wifi_device_legacy);
static struct platform_driverwifi_device= {
.probe = wifi_probe,
.remove = wifi_remove,
.suspend = wifi_suspend,
.resume = wifi_resume,
.driver = {
.name = &bcmdhd_wlan&,
static struct platform_driverwifi_device_legacy = {
.probe = wifi_probe,
.remove = wifi_remove,
.suspend = wifi_suspend,
.resume = wifi_resume,
.driver = {
.name = &bcm4329_wlan&,
3、这里我们看到wifi注册平台驱动,那么我们不禁要问wifi平台设备是在哪里注册的??
我们通过find |grep发现该路径是在:/home/stonechen/svn//customize/customer_cfg/sp8810g-brcm/kernel/wifi/dhd_adapter.c
设备注册函数如下:
static int __initwlan_device_init(void)
init_wifi_mem();
//wlan_ldo_enable();
gpio_request(sprd_3rdparty_gpio_wifi_irq,&oob_irq&);//irq是在gpio_cfg.c
gpio_direction_input(sprd_3rdparty_gpio_wifi_irq);
wlan_resources[1].start =sprd_alloc_gpio_irq(sprd_3rdparty_gpio_wifi_irq);
//wlan_resources[1].end =gpio_to_irq(sprd_3rdparty_gpio_wifi_irq);
gpio_request(sprd_3rdparty_gpio_wifi_power,&wifi_pwd&);
gpio_direction_output(sprd_3rdparty_gpio_wifi_power,0);
ret= platform_device_register(&sprd_wlan_device); //这里注册了平台设备
late_initcall(wlan_device_init);//这里是首先进入的函数哦
MODULE_DESCRIPTION(&Broadcommwlan driver&);
MODULE_LICENSE(&GPL&);
static struct platform_devicesprd_wlan_device = {
.name = &bcmdhd_wlan&,//和wifi平台驱动一样的名字,因此匹配执行probe函数
.platform_data =&wlan_device_control,
.resource = wlan_resources,
.num_resources =ARRAY_SIZE(wlan_resources),
4、wifi的平台驱动和平台设备都注册之后,将执行platform_probe函数!!
static int wifi_probe(structplatform_device *pdev)
struct wifi_platform_data*wifi_ctrl =
(struct wifi_platform_data*)(pdev-&dev.platform_data);
此处很重要,获取了device中的很多ops函数!!
DHD_ERROR((&## %s\n&,__FUNCTION__));
wifi_irqres =platform_get_resource_byname(pdev, IORESOURCE_IRQ,&bcmdhd_wlan_irq&);//此处是获取irq资源,成功!
if (wifi_irqres == NULL)
wifi_irqres =platform_get_resource_byname(pdev,
IORESOURCE_IRQ,&bcm4329_wlan_irq&);
wifi_control_data = wifi_
wifi_set_power(1, 0); /* Power On*/此处将调用wifi_control_data-&set_power(on),也就是获取data中的注册的函数{dhd_adapter.c}intwlan_device_power(int
wifi_set_carddetect(1); /*CardDetect (0-&1) */同理,也是调用函数dhd_adapter.c中的intwlan_device_set_carddetect(int
up(&wifi_control_sem);
int wlan_device_set_carddetect(intval)
pr_info(&%s: %d\n&,__func__, val);
mdelay(100);
#ifdef CONFIG_WLAN_SDIO
sdhci_bus_scan();//此处将调用\3rdparty\wifi\BCM43362\special\android\kernel\drivers\mmc\host\sprdmci.c中的函数void
sdhci_bus_scan(void)
总结一下:不难看出probe函数就是执行了2个功能开启wifi电源和扫描sd卡。扫描sd卡的前提需要注册sd驱动,而且sdhci_bus_scan函数调用的一个全局变量也需要赋值!!!
#ifdef SDHCI_BUS_SCAN
void sdhci_bus_scan(void){
if(sdhci_host_g&& (sdhci_host_g-&mmc)){ //此处该全局变量是在sdhci_add_host函数中赋值的:sdhci_host_g
printk(&%s, entry\n&,__func__);
if(sdhci_host_g-&ops-&set_clock) {
sdhci_host_g-&ops-&set_clock(sdhci_host_g, 1);
sdhci_reset(sdhci_host_g,SDHCI_RESET_ALL);
sdhci_reinit(sdhci_host_g);
mmc_detect_change(sdhci_host_g-&mmc,0);
EXPORT_SYMBOL_GPL(sdhci_bus_scan);
二、wifi详解2
这里我们就跟踪到了函数sdhci_add_host!!!通过阅读博客文章
具体sd卡驱动就不分析了!截取staticint __devinit sdhci_s3c_probe(struct platform_device *pdev)部分代码
host =sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
。。。。。。。
ret =sdhci_add_host(host);//就是这里调用该函数
if (ret) {
dev_err(dev,&sdhci_add_host() failed\n&);
gotoerr_add_
当然sd卡驱动注册的最后就是调用sdhci_add_host函数。
下面来看sdhci_add_host这个函数。
intsdhci_add_host(structsdhci_host
structmmc_host *
mmc= host-&
&&&&&&&&tasklet_init(&host-&card_tasklet,sdhci_tasklet_card,(unsigned
long)host);
&&&&&&&&tasklet_init(&host-&finish_tasklet,sdhci_tasklet_finish,(unsigned
long)host);
&&&&&&&&setup_timer(&host-&timer,sdhci_timeout_timer, (unsigned long)host);
&&&&&&&&request_irq(host-&irq,sdhci_irq,
IRQF_SHARED,mmc_hostname(mmc), host);//此处注册了中断函数sdhci_irq,很重要
mmc_add_host(mmc);
也许大家很困惑,为什么只关注这几行code,在该函数中主要是集中在mmc_host成员的初始化赋值。由于中断中需要处理的内容较多故采用底半部的办法来处理部分内容。
card_tasklet用于处理MMC插槽上的状态变化。finish_tasklet用于命令传输完成后的处理。Timer用于等待硬件中断。Irq则是SDHCI的中断处理。
将host添加入mmc管理,其本质即是添加host的class_dev
intmmc_add_host(struct mmc_host *host)
device_add(&host-&class_dev);
&&&&&&&&mmc_start_host(host);
&&&&&&&& return0;
voidmmc_start_host(struct mmc_host *host) –启动host
&&&&&&&&mmc_power_off(host);&&--关闭MMC
&&&&&&&& if(host-&caps & MMC_CAP_BOOT_ONTHEFLY)
&&&&&&&&&&&&&&&&&&mmc_rescan(&host-&detect.work);&--重新扫描
&&&&&&&& else
&&&&&&&&&&&&&&&&&&mmc_detect_change(host,0); &--处理状态改变
voidmmc_detect_change(struct mmc_host *host, unsigned long delay)
&&&&&&&&mmc_schedule_delayed_work(&host-&detect,delay);
在mmc_alloc_host时,存在下面一行code
INIT_DELAYED_WORK(&host-&detect,mmc_rescan);
到此就会发现mmc_start_host一定会执行mmc_rescan只不过一个是延时后执行,一个是没有延时执行。
voidmmc_rescan(struct work_struct *work)
&&&&&&&& structmmc_host *host =container_of(work, struct mmc_host, detect.work);
&&&&&&&& u32
&&&&&&&& mmc_bus_get(host);
&&&&&&&& if(host-&bus_ops == NULL) { --如果为第一次扫描总线上设备。
&&&&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&&&&* Only wecan add a new handler, so it's safe torelease the lock here.
&&&&&&&&&&&&&&&&&&&*/
&&&&&&&&&&&&&&&&&&mmc_bus_put(host);
&&&&&&&&&&&&&&&&&&if(host-&ops-&get_cd && host-&ops-&get_cd(host) ==0)
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&mmc_claim_host(host);&--申请一个host
&&&&&&&&&&&&&&&&&&mmc_power_up(host);&&--开启host电源
&&&&&&&&&&&&&&&&&&mmc_go_idle(host);&&&&--设置host为idle模式
&&&&&&&&&&&&&&&&&&mmc_send_if_cond(host,host-&ocr_avail);--是用于验证SD卡接口操作状态的有效性命令(CMD8)。如果SD_SEND_IF_COND指示为符合SD2.0标准的卡,则设置操作状态寄存器ocrbit30指示能够处理块地址SDHC卡
&&&&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&&&&* First wesearch for SDIO...
&&&&&&&&&&&&&&&&&&&*/
&&&&&&&&&&&&&&&&&&err =mmc_send_io_op_cond(host, 0, &ocr);
&&&&&&&&&&&&&&&&&&if (!err) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&if(mmc_attach_sdio(host, ocr))
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mmc_power_off(host);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&&&&* ...thennormal SD...
&&&&&&&&&&&&&&&&&&&*/
&&&&&&&&&&&&&&&&&&err =mmc_send_app_op_cond(host, 0, &ocr);
&&&&&&&&&&&&&&&&&&if (!err) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&if(mmc_attach_sd(host, ocr))
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mmc_power_off(host);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&&&&* ...andfinally MMC.
&&&&&&&&&&&&&&&&&&&*/
&&&&&&&&&&&&&&&&&&err =mmc_send_op_cond(host, 0, &ocr);
&&&&&&&&&&&&&&&&&&if (!err) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&if(mmc_attach_mmc(host, ocr))
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mmc_power_off(host);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&mmc_release_host(host);
&&&&&&&&&&&&&&&&&&mmc_power_off(host);
&&&&&&&& }else {
&&&&&&&&&&&&&&&&&&if(host-&bus_ops-&detect && !host-&bus_dead)
host-&bus_ops-&detect(host);
&&&&&&&&&&&&&&&&&&mmc_bus_put(host);
&&&&&&&& }
&&&&&&&& if(host-&caps & MMC_CAP_NEEDS_POLL)
&&&&&&&&&&&&&&&&&&mmc_schedule_delayed_work(&host-&detect,HZ);
那先来看mmc_send_if_cond实现,从字面意思上看该函数就是发送一个SD标准命令,亦如usb的标准命令一样。
在这里不得不先说明一点就是在SD子系统中,所有的数据传输均是由host发起。Host发送完一命令则会等待中断的产生,在这里采用完成量来实现进程的阻塞。
voidmmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
&&&&&&&&DECLARE_COMPLETION_ONSTACK(complete);
&&&&&&&& mrq-&done_data= &
&&&&&&&&mrq-&done= mmc_wait_
&&&&&&&&mmc_start_request(host,mrq);& --开始request
&&&&&&&&wait_for_completion(&complete);
mmc_start_request-&host-&ops-&request(即sdhci_request)
static voidsdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
&&&&&&&& structsdhci_host *
&&&&&&&& host= mmc_priv(mmc);
&&&&&&&&spin_lock_irqsave(&host-&lock,flags);
&&&&&&&& host-&mrq=
&&&&&&&& if((mmc-&caps & MMC_CAP_ON_BOARD) || (host-&flags &SDHCI_DEVICE_ALIVE))
&&&&&&&&&&&&&&&&&&sdhci_send_command(host,mrq-&cmd);
&&&&&&&& else{
&&&&&&&&&&&&&&&&&&if(!(readl(host-&ioaddr + SDHCI_PRESENT_STATE) &SDHCI_CARD_PRESENT)
|| (host-&flags& SDHCI_DEVICE_DEAD)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&host-&mrq-&cmd-&error= -ENOMEDIUM;
&&&&&&&&&&&&&&&&&&&&&&&&&&&tasklet_schedule(&host-&finish_tasklet);
&&&&&&&&&&&&&&&&&&} else
&&&&&&&&&&&&&&&&&&&&&&&&&&&sdhci_send_command(host,mrq-&cmd);
&&&&&&&& }
&&&&&&&& mmiowb();
&&&&&&&&spin_unlock_irqrestore(&host-&lock,flags);
sdhci_request-&sdhci_send_command发送命令。
当命令传输完成系统调用中断处理函数sdhci_irq。在其中进行中断完成后的处理。
再看注册的中断函数staticirqreturn_t sdhci_irq(int irq, void *dev_id)
irqreturn_
structsdhci_host* host = dev_
int cardint = 0;
spin_lock(&host-&lock);
intmask =sdhci_readl(host, SDHCI_INT_STATUS);
if (!intmask ||intmask == 0xffffffff) {
result =IRQ_NONE;
DBG(&*** %sgot interrupt: 0x%08x\n&,
mmc_hostname(host-&mmc),intmask);
if (intmask &(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
sdhci_writel(host,intmask & (SDHCI_INT_CARD_INSERT |
SDHCI_INT_CARD_REMOVE),SDHCI_INT_STATUS);
tasklet_schedule(&host-&card_tasklet);
intmask &=~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
if (intmask &SDHCI_INT_CMD_MASK) {
sdhci_writel(host,intmask & SDHCI_INT_CMD_MASK,
SDHCI_INT_STATUS);
sdhci_cmd_irq(host,intmask & SDHCI_INT_CMD_MASK);
if (intmask &SDHCI_INT_DATA_MASK) {
sdhci_writel(host,intmask & SDHCI_INT_DATA_MASK,
SDHCI_INT_STATUS);
sdhci_data_irq(host,intmask & SDHCI_INT_DATA_MASK);
intmask &=~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
intmask &=~SDHCI_INT_ERROR;
if (intmask &SDHCI_INT_BUS_POWER) {
printk(KERN_ERR&%s: Card is consuming too much power!\n&,
mmc_hostname(host-&mmc));
sdhci_writel(host,SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
intmask &=~SDHCI_INT_BUS_POWER;
if (intmask &SDHCI_INT_CARD_INT)
cardint = 1;
intmask &=~SDHCI_INT_CARD_INT;
if (intmask) {
printk(KERN_ERR&%s: Unexpected interrupt 0x%08x.\n&,
mmc_hostname(host-&mmc),intmask);
sdhci_dumpregs(host);
sdhci_writel(host,intmask, SDHCI_INT_STATUS);
result =IRQ_HANDLED;
spin_unlock(&host-&lock);
* We have todelay this as it calls back into the driver.
if (cardint)
mmc_signal_sdio_irq(host-&mmc);
三、wifi详解3
重新回到函数Z:\home\stonechen\svn\\3rdparty\wifi\BCM43362\special\bcmdhd\dhd\sys\dhd_linux.c
error= dhd_bus_register();
此调用流程由dhd_bus_register发起,通过sdio_register_driver注册一个sdio设备驱动,然后通过dhdsdio_probe初始化并注册一个网络设备,网络设备的注册标志着wifi驱动已经成功加载,关于网络设备的创建,初始化和注册后面会有详细介绍,先来理一下上面的调用流程,:
dhd_bus_register(void)
DHD_TRACE((&%s:Enter\n&, __FUNCTION__));
returnbcmsdh_register(&dhd_sdio);
bcmsdh_register(bcmsdh_driver_t*driver)
int error = 0;
drvinfo =*
#ifdefined(BCMPLATFORM_BUS)
SDLX_MSG((&LinuxKernel SDIO/MMC Driver\n&));
error =sdio_function_init();
#endif /*defined(BCMPLATFORM_BUS) */
#if!defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
#if(LINUX_VERSION_CODE & KERNEL_VERSION(2, 6, 0))
if (!(error =pci_module_init(&bcmsdh_pci_driver)))
if (!(error =pci_register_driver(&bcmsdh_pci_driver)))
SDLX_MSG((&%s:pci_module_init failed 0x%x\n&, __FUNCTION__, error));
#endif /*BCMPLATFORM_BUS */
intsdio_function_init(void)
int error = 0;
sd_trace((&bcmsdh_sdmmc:%s Enter\n&, __FUNCTION__));
gInstance =kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL);
if (!gInstance)
return -ENOMEM;
error =sdio_register_driver(&bcmsdh_sdmmc_driver);
分析到这里可以看到就是注册了一个sdmmc的driver。然后将执行probe函数
static structsdio_driver bcmsdh_sdmmc_driver = {
.probe =bcmsdh_sdmmc_probe,
.remove =bcmsdh_sdmmc_remove,
.name =&bcmsdh_sdmmc&,
.id_table =bcmsdh_sdmmc_ids,
/****Marked byMichael , to solve WIFI sleep issue caused by SPRD SDIO
#if(LINUX_VERSION_CODE & KERNEL_VERSION(2, 6, 39)) &&defined(CONFIG_PM)
.pm =&bcmsdh_sdmmc_pm_ops,
/****Marked byMichael , to solve WIFI sleep issue caused by SPRD SDIO
#endif****Michael*/ /* (LINUX_VERSION_CODE & KERNEL_VERSION(2, 6, 39))&& defined(CONFIG_PM) */
static intbcmsdh_sdmmc_probe(struct sdio_func *func,
conststruct sdio_device_id *id)
int ret = 0;
static structsdio_func sdio_func_0;
sd_trace((&bcmsdh_sdmmc:%s Enter\n&, __FUNCTION__));
sd_trace((&sdio_bcmsdh:func-&class=%x\n&, func-&class));
sd_trace((&sdio_vendor:0x%04x\n&, func-&vendor));
sd_trace((&sdio_device:0x%04x\n&, func-&device));
sd_trace((&Function#:0x%04x\n&, func-&num));
if (func-&num== 1) {
sdio_func_0.num= 0;
sdio_func_0.card= func-&
gInstance-&func[0]= &sdio_func_0;
if(func-&device== 0x4) { /* 4318 */
gInstance-&func[2]= NULL;
sd_trace((&NICfound, calling bcmsdh_probe...\n&));
ret= bcmsdh_probe(&func-&dev);
gInstance-&func[func-&num]=
if (func-&num== 2) {
#ifdefWL_CFG80211
wl_cfg80211_set_parent_dev(&func-&dev);
sd_trace((&F2found, calling bcmsdh_probe...\n&));
ret =bcmsdh_probe(&func-&dev);
bcmsdh_probe函数中:
if(!(sdhc-&ch = drvinfo.attach((vendevid && 16),
(vendevid & 0xFFFF), 0, 0, 0, 0,
(void *)regs, NULL, sdh))) {
SDLX_MSG((&%s:device attach failed\n&, __FUNCTION__));
此处将执行staticbcmsdh_driver_t dhd_sdio = {
&&&&&&&dhdsdio_probe,//执行此函数
&&&&&&&dhdsdio_disconnect
这是由于之前传递的实参为&&returnbcmsdh_register(&dhd_sdio);
四、wifi详解4
上面是网络设备注册流程,在dhdsdio_probe函数中先后对dhd_attach和dhd_net_attach两个函数调用,dhd_attach主要用于创建和初始化dhd_info_t和net_device两个结构变量,然后调用dhd_add_if将创建的net_device变量添加到dhd_info_t变量的iflist列表中(支持多接口)。
Dhd_attach的流程如下:
dhd_pub_t*
dhd_attach(osl_t*osh, structdhd_bus *bus, uint bus_hdrlen)
&&&&&&&dhd_info_t *dhd = NULL;
&&&&&&&struct net_device *net = NULL;
&&&&&&&/* Allocate etherdev, includingspacefor private structure */
&&&&&&&if(!(net = alloc_etherdev(sizeof(dhd)))) {&&//网络设备的创建
&&&&&&&&&&&&&&&DHD_ERROR((&%s: OOM-alloc_etherdev\n&, __FUNCTION__));
&&&&&&&&&&&&&&&
&&&&&&&dhd_state|=DHD_ATTACH_STATE_NET_ALLOC;
&&&&&&&/* Allocate primary dhd_info */
&&&&&&&if(!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { //dhd的创建
&&&&&&&&&&&&&&&DHD_ERROR((&%s: OOM -allocdhd_info\n&, __FUNCTION__));
&&&&&&&&&&&&&&&
/*Set network interface name if it was provided as moduleparameter */
&&&&&&&if (iface_name[0]) {
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&strncpy(net-&name,iface_name,IFNAMSIZ);
&&&&&&&&&&&&&&&net-&name[IFNAMSIZ - 1] = 0;
&&&&&&&&&&&&&&&len = strlen(net-&name);
&&&&&&&&&&&&&&&ch = net-&name[len - 1];
&&&&&&&&&&&&&&&if ((ch & '9' || ch &'0') &&(len & IFNAMSIZ - 2))
&&&&&&&&&&&&&&&&&&&&&&&strcat(net-&name,&%d&);
&&&&&&&if(dhd_add_if(dhd, 0, (void *)net, net-&name, NULL, 0, 0)==DHD_BAD_IF)&&//将前面创建的net添加到iflist列表中
&&&&&&&&&&&&&&&
&&&&&&&dhd_state |=DHD_ATTACH_STATE_ADD_IF;
Memcpy(netdev_priv(net),&dhd, sizeof(dhd));//关联dhd和net
//dhd的初始化工作
Dhd_add_if的添加网络接口流程:
dhd_add_if(dhd_info_t*dhd, int ifidx, void *handle, char *name,
&&&&&&&uint8*mac_addr,uint32 flags, uint8 bssidx)
&&&&&&&dhd_if_t *
&&&&&&&DHD_TRACE((&%s: idx%d,handle-&%p\n&, __FUNCTION__, ifidx, handle));
&&&&&&&ASSERT(dhd && (ifidx&DHD_MAX_IFS));
&&&&&&&ifp=dhd-&iflist[ifidx];
&&&&&&&if (ifp != NULL) {
&&&&&&&&&&&&&&&if (ifp-&net != NULL) {
&&&&&&&&&&&&&&&&&&&&&&&netif_stop_queue(ifp-&net);
&&&&&&&&&&&&&&&&&&&&&&&unregister_netdev(ifp-&net);
&&&&&&&&&&&&&&&&&&&&&&&free_netdev(ifp-&net);&&//如果已经存在,释放net成员
&&&&&&&&&&&&&&&}
&&&&&&&} else
&&&&&&&&&&&&&&&if((ifp = MALLOC(dhd-&pub.osh,sizeof(dhd_if_t))) == NULL) {
&&&&&&&&&&&&&&&&&&&&&&&DHD_ERROR((&%s:OOM - dhd_if_t\n&, __FUNCTION__)); &&&&//否则,创建一个dhd_if_t结构变量
&&&&&&&&&&&&&&&&&&&&&&&return -ENOMEM;
&&&&&&&&&&&&&&&}
&&&&&&&memset(ifp, 0, sizeof(dhd_if_t));
&&&&&&&ifp-&info=&&&&&//进行系列初始化,添加工作
&&&&&&&dhd-&iflist[ifidx]=
&&&&&&&strncpy(ifp-&name,name, IFNAMSIZ);
&&&&&&&ifp-&name[IFNAMSIZ] = '\0';
&&&&&&&if (mac_addr != NULL)
&&&&&&&&&&&&&&&memcpy(&ifp-&mac_addr,mac_addr,ETHER_ADDR_LEN);
&&&&&&&if (handle == NULL) {
&&&&&&&&&&&&&&&ifp-&state = DHD_IF_ADD;
&&&&&&&&&&&&&&&ifp-&idx =
&&&&&&&&&&&&&&&ifp-&bssidx =
&&&&&&&&&&&&&&&ASSERT(&dhd-&thr_sysioc_ctl.thr_pid&= 0);
&&&&&&&&&&&&&&&up(&dhd-&thr_sysioc_ctl.sema);
&&&&&&&} else
&&&&&&&&&&&&&&&ifp-&net= (struct net_device *)&&&&&&&&&&&&//handle即一个net_device变量
&&&&&&&return 0;
这样,一个net_device网路设备就被添加到了接口管理列表中了,但是这是网路设备还没有完成初始化和注册工作,bcmsdio_probe函数随后对dhd_net_attach的调用完成了这个操作:
dhd_net_attach(dhd_pub_t*dhdp,int ifidx)
&&&&&&&dhd_info_t *dhd =(dhd_info_t*)dhdp-&
&&&&&&&struct net_device *net = NULL;
&&&&&&&int err = 0;
&&&&&&&uint8 temp_addr[ETHER_ADDR_LEN] ={0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 };
&&&&&&&DHD_TRACE((&%s: ifidx%d\n&,__FUNCTION__, ifidx));
&&&&&&&ASSERT(dhd &&dhd-&iflist[ifidx]);
&&&&&&&net =dhd-&iflist[ifidx]-&&&&&&&&&&&&&&//首先从刚才添加的接口列表中取出net,然后进行下面的系列初始化工作
&&&&&&&ASSERT(net);
//根据内核版本信息,选择对net成员函数的初始化方式,假设是2.6.30的版本
#if(LINUX_VERSION_CODE &KERNEL_VERSION(2, 6, 31))
&&&&&&&ASSERT(!net-&open);
&&&&&&&net-&get_stats= dhd_get_
&&&&&&&net-&do_ioctl=dhd_ioctl_
&&&&&&&net-&hard_start_xmit= dhd_start_
&&&&&&&net-&set_mac_address= dhd_set_mac_
&&&&&&&net-&set_multicast_list= dhd_set_multicast_
&&&&&&&net-&open=net-&stop = NULL;
&&&&&&&ASSERT(!net-&netdev_ops);
&&&&&&&net-&netdev_ops = &dhd_ops_
&&&&&&&/* Ok, link into the networklayer...*/
&&&&&&&if (ifidx == 0) {
&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&* device functions for theprimaryinterface only
&&&&&&&&&&&&&&&&*/
#if(LINUX_VERSION_CODE &KERNEL_VERSION(2, 6, 31))
&&&&&&&&&&&&&&&net-&open= dhd_
&&&&&&&&&&&&&&&net-&stop= dhd_
&&&&&&&&&&&&&&&net-&netdev_ops= &dhd_ops_
&&&&&&&} else {
&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&* We have to use the primaryMAC forvirtual interfaces
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&66%
&&&&&&&&&&&&&&&&*/
&&&&&&&&&&&&&&&memcpy(temp_addr,dhd-&iflist[ifidx]-&mac_addr,ETHER_ADDR_LEN);
&&&&&&&&&&&&&&&/*
&&&&&&&&&&&&&&&&* Android sets thelocallyadministered bit to indicate that this is a
&&&&&&&&&&&&&&&&*portable hotspot.& This will not work in simultaneousAP/STAmode,
&&&&&&&&&&&&&&&&* nor with P2P.& Need to setthe Donlge's MAC address, andthen use that.
&&&&&&&&&&&&&&&&*/
&&&&&&&&&&&&&&&if(!memcmp(temp_addr,dhd-&iflist[0]-&mac_addr,
&&&&&&&&&&&&&&&&&&&&&&&ETHER_ADDR_LEN)){
&&&&&&&&&&&&&&&&&&&&&&&DHD_ERROR((&%sinterface [%s]:set locally administered bit in MAC\n&,
&&&&&&&&&&&&&&&&&&&&&&&__func__,net-&name));
&&&&&&&&&&&&&&&&&&&&&&&temp_addr[0] |= 0x02;
&&&&&&&&&&&&&&&}
&&&&&&&net-&hard_header_len= ETH_HLEN + dhd-&pub.
#ifLINUX_VERSION_CODE &=KERNEL_VERSION(2, 6, 24)
&&&&&&&net-&ethtool_ops= &dhd_ethtool_
#endif/* LINUX_VERSION_CODE&= KERNEL_VERSION(2, 6, 24) */
#ifdefined(CONFIG_WIRELESS_EXT)
#ifWIRELESS_EXT & 19
&&&&&&&net-&get_wireless_stats= dhd_get_wireless_
#endif/* WIRELESS_EXT & 19*/
#ifWIRELESS_EXT & 12
&&&&&&&net-&wireless_handlers= (struct iw_handler_def*)&wl_iw_handler_&&//这里的初始化工作很重要,之后的ioctl流程会涉及到对它的使用
#endif/* WIRELESS_EXT & 12*/
#endif/*defined(CONFIG_WIRELESS_EXT) */
&&&&&&&dhd-&pub.rxsz=DBUS_RX_BUFFER_SIZE_DHD(net);
&&&&&&&&&&&&&&&//设置设备地址
&&&&&&&memcpy(net-&dev_addr,temp_addr, ETHER_ADDR_LEN);
&&&&&&&if((err =register_netdev(net)) != 0) {&&&&&&//注册net
&&&&&&&&&&&&&&&DHD_ERROR((&couldn'tregisterthe net device, err %d\n&, err));
&&&&&&&&&&&&&&&
到这里net网络设备就被注册到系统中了,设备准备好了就好对设备进行访问了
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场}

我要回帖

更多关于 方程求解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信