博通wifi驱动

很早之前自己的笔记,想想还是记录到网上吧

注册

7611 static int __init
 7612 dhd_module_init(void)
 7613 {
 7614     int err;
 7615     int retry = POWERUP_MAX_RETRY;
 7616 
 7617     printk("%s: in\n", __FUNCTION__);
 7618 
 7619     DHD_PERIM_RADIO_INIT();
 7620 
 7621     if (firmware_path[0] != '\0') {
 7622         strncpy(fw_bak_path, firmware_path, MOD_PARAM_PATHLEN);
 7623         fw_bak_path[MOD_PARAM_PATHLEN-1] = '\0';
 7624     }
 7625 
 7626     if (nvram_path[0] != '\0') {
 7627         strncpy(nv_bak_path, nvram_path, MOD_PARAM_PATHLEN);
 7628         nv_bak_path[MOD_PARAM_PATHLEN-1] = '\0';
 7629     }
 7630 
 7631     do {
 7632         err = dhd_wifi_platform_register_drv();
 7633         if (!err) {
 7634             register_reboot_notifier(&dhd_reboot_notifier);
 7635             break;
 7636         }
 7637         else {
 7638             DHD_ERROR(("%s: Failed to load the driver, try cnt %d\n",
 7639                 __FUNCTION__, retry));
 7640             strncpy(firmware_path, fw_bak_path, MOD_PARAM_PATHLEN);
 7641             firmware_path[MOD_PARAM_PATHLEN-1] = '\0';
  7642             strncpy(nvram_path, nv_bak_path, MOD_PARAM_PATHLEN);
 7643             nvram_path[MOD_PARAM_PATHLEN-1] = '\0';
 7644         }
 7645     } while (retry--);
 7646 
 7647     if (err)
 7648         DHD_ERROR(("%s: Failed to load driver max retry reached**\n", __FUNCTION__));
 7649 
 7650     printk("%s: Exit err=%d\n", __FUNCTION__, err);
 7651     return err;
 7652 }                                                                             

该数是博通wifi驱动注册的起始函数,7621~7629获得固件的路径,固件路径在makemenuconfig可以指定。

7632行注册wifi的平台驱动。如果注册成功,则7634行注册一个wifi重启的通知链。

543 int dhd_wifi_platform_register_drv(void) 
544 { 
545     int err = 0; 
...
565     { 
566         err = wifi_ctrlfunc_register_drv(); 
567 
568         /* no wifi ctrl func either, load bus directly and ignore this error */ 
569         if (err) { 
570             if (err == -ENXIO) { 
571                 /* wifi ctrl function does not exist */ 
572                 err = dhd_wifi_platform_load(); 
573             } else { 
574                 /* unregister driver due to initialization failure */ 
575                 wifi_ctrlfunc_unregister_drv(); 
576             } 
577         } 
578     } 
579 
580     return err; 
581 } 

566行注册wifi的相关控制函数。

381 static int wifi_ctrlfunc_register_drv(void) 
382 { 
383     wifi_adapter_info_t *adapter; 
384 
385 #ifndef CUSTOMER_HW 
386     int err = 0; 
387     struct device *dev1, *dev2; 
388     dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match); 
389     dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match); 
390 #endif 
391 
392 #if !defined(CONFIG_DTS) && !defined(CUSTOMER_HW) 
393     if (!dts_enabled) { 
394         if (dev1 == NULL && dev2 == NULL) { 
395             DHD_ERROR(("no wifi platform data, skip\n")); 
396             return -ENXIO; 
397         } 
398     } 
399 #endif /* !defined(CONFIG_DTS) */ 
400 
401     /* multi-chip support not enabled, build one adapter information for 
402      * DHD (either SDIO, USB or PCIe) 
403      */ 
404     adapter = kzalloc(sizeof(wifi_adapter_info_t), GFP_KERNEL); 
405     adapter->name = "DHD generic adapter"; 
406     adapter->bus_type = -1; 
407     adapter->bus_num = -1; 
408     adapter->slot_num = -1; 
409     adapter->irq_num = -1; 
410     is_power_on = FALSE; 
411     wifi_plat_dev_probe_ret = 0; 
412     dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL); 
413     dhd_wifi_platdata->num_adapters = 1; 
414     dhd_wifi_platdata->adapters = adapter; 
...
435 #if !defined(CONFIG_DTS) 
436     if (dts_enabled) { 
437 #ifdef CUSTOMER_HW 
438         adapter->wifi_plat_data = (void *)&dhd_wlan_control; 
439         bcm_wlan_set_plat_data(); 
440 #ifdef CUSTOMER_OOB 
441         adapter->irq_num = bcm_wlan_get_oob_irq(); 
442         adapter->intr_flags = bcm_wlan_get_oob_irq_flags(); 
443 #endif 
444 #else 
445         struct resource *resource; 
446         resource = &dhd_wlan_resources; 
447         adapter->irq_num = resource->start; 
448         adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK; 
449 #endif 
450         wifi_plat_dev_probe_ret = dhd_wifi_platform_load(); 
451     } 
452 #endif /* !defined(CONFIG_DTS) */ 
453 
454 
455 #if defined(CONFIG_DTS) && !defined(CUSTOMER_HW) 
456     wifi_plat_dev_probe_ret = platform_driver_register(&wifi_platform_dev_driver); 
457 #endif /* CONFIG_DTS */ 
458 
459     /* return probe function's return value if registeration succeeded */ 
460     return wifi_plat_dev_probe_ret; 
461 } 

385~390行,CUSTOMER_HWmakefile中定义了,该宏的意义是使用的用户定制的硬件情况下的驱动注册。392~399行同样略过。

我们使用的wifi模组是sdio接口方式,401415初始化一个wifiadapter的相关数据结构,在i2c设备驱动中也有adapter的概念。

435~437行,这三行的条件都满足。

438行为adapterwifi_plat_data成员先占坑。

439行的函数在dmesg出来的启动信息的2.685895秒有显示。其是为438行占坑的指针赋值成员初始化。赋值的这三个成员是平台相关的,如下:

dhd_wlan_control.set_power = bcm_wlan_set_power;
	dhd_wlan_control.set_carddetect = bcm_wlan_set_carddetect;
	dhd_wlan_control.get_mac_addr = bcm_wlan_get_mac_address;

441行获得wifi的中断号,对应于2.686263秒打印出的信息,该中断号是ap633513脚(WL_HOST_WAKE)输出信号,该脚的作用是WLAN唤醒AP(应用处理器)。

442行设置该中断的标志为中断,高电平触发,中断资源可以共享。

444~449行是else分支,并没有得到执行。

450行加载wifisdio驱动,2.687878打印的信息即进入该函数。其sdio加载函数是

dhd_wifi_platform_load_sdio()

685 #ifdef BCMSDIO 
686 static int dhd_wifi_platform_load_sdio(void) 
687 { 
688     int i; 
689     int err = 0; 
690     wifi_adapter_info_t *adapter; 

//去除没用使用的变量带来的警告,处理编译上的,和功能上没有什么关系。

692     BCM_REFERENCE(i); 
693     BCM_REFERENCE(adapter); 

//参数安全性检查

694     /* Sanity check on the module parameters 
695      * - Both watchdog and DPC as tasklets are ok 
696      * - If both watchdog and DPC are threads, TX must be deferred 
697      */ 
698     if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) && 
699         !(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx)) 
700         return -EINVAL; 

//702行同样在makefile中定义,dhd_wifi_platdata在上面红色那行已经被赋值。

702 #if defined(BCMLXSDMMC) 
703     if (dhd_wifi_platdata == NULL) { 
704         DHD_ERROR(("DHD wifi platform data is required for Android build\n")); 
705         return -EINVAL; 
706     } 

//dhd_registration_sem这个信号量初始化为0.

708     sema_init(&dhd_registration_sem, 0); 

//adapter的个数实际上就是1,所以该循环只执行一次/* power up all adapters */

710     for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) { 
711         bool chip_up = FALSE; 
712         int retry = POWERUP_MAX_RETRY; 
713         struct semaphore dhd_chipup_sem; 
714 
715         adapter = &dhd_wifi_platdata->adapters[i]; 

//对应于2.688490时刻打印的信息。

717         DHD_ERROR(("Power-up adapter '%s'\n", adapter->name)); 
718         DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n", 
719             adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path)); 
720         DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n", 
721             adapter->bus_type, adapter->bus_num, adapter->slot_num)); 
722 
723         do { 

//同样是信号量初始化

724             sema_init(&dhd_chipup_sem, 0); 
//Register a dummy SDIO client driver in order to be notified of new SDIO device
725             err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem); 
726             if (err) { 
727                 DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n", 
728                     __FUNCTION__, err)); 
729                 return err; 
730             } 

//调用bcm_wlan_set_power,将ap633512脚拉低,让其内部电源稳压器工作。上电完成返回TRUE。上电正常返回值err=0

731             err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY); 
732             if (err) { 
733                 /* WL_REG_ON state unknown, Power off forcely */ 
734                 wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); 
735                 continue; 
736             } else { 

//上电成功,则需要枚举设备,3.099935时刻打印的信息。bcm_wlan_set_carddetect

737                 wifi_platform_bus_enumerate(adapter, TRUE); 
738                 err = 0; 
739             } 

//如果成功获取到dhd_chipup_sem,则表示wifi芯片成功powerup,这时表sdionotify注销掉并跳出这个循环。

741             if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) { 
742                 dhd_bus_unreg_sdio_notify(); 
743                 chip_up = TRUE; 
744                 break; 
745             }

//出错处理,省略

...
751         } while (retry--); 
...
753         if (!chip_up) { 
754             DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name)); 
755             return -ENODEV; 
756         } 
757 
758     } 

//dhd总线注册

760     err = dhd_bus_register(); 
761 
762     if (err) { 
763         DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__)); 
764         goto fail; 
765     } 
766 
767 
768     /* 
769      * Wait till MMC sdio_register_driver callback called and made driver attach. 
770      * It's needed to make sync up exit from dhd insmod  and 
771      * Kernel MMC sdio device callback registration 
772      */ 
773     err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)); 
774     if (err) { 
775         DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__)); 
776         dhd_bus_unregister(); 
777         goto fail; 
778     } 
779 
780     return err; 
781 
782 fail: 
783     /* power down all adapters */ 
784     for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) { 
785         adapter = &dhd_wifi_platdata->adapters[i]; 
786         wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); 
787         wifi_platform_bus_enumerate(adapter, FALSE); 
788     } 
789 #else 
790 
791     /* x86 bring-up PC needs no power-up operations */ 
792     err = dhd_bus_register(); 
793 
794 #endif 
795 
796     return err; 
797 } 

sdio设备探测函数如下,对应3.100247时刻的输出信息就是下面88行的输出。

 82 extern void exynos_dwmci1_notify_change(int state); 
 83 int bcm_wlan_set_carddetect(bool present) 
 84 { 
 85     int err = 0; 
 86 
 87     if (present) { 
 88         printk("======== Card detection to detect SDIO card! ========\n"); 
 89 #ifdef CONFIG_MACH_ODROID_4210 
 90         exynos_dwmci1_notify_change(1); 
 91 #endif 
 92     } else { 
 93         printk("======== Card detection to remove SDIO card! ========\n"); 
 94 #ifdef CONFIG_MACH_ODROID_4210 
 95         exynos_dwmci1_notify_change(0); 
 96 #endif 
 97     } 
 98 
 99     return err; 
100 } 

由于exynos_dwmci1_notify_change属于mmc的范畴,

157 static void (*_exynos_dwmci1_notify_func)(struct platform_device *, int); 
158 void exynos_dwmci1_notify_change(int state) 
159 { 
160     if (_exynos_dwmci1_notify_func) 
161         _exynos_dwmci1_notify_func(&exynos5_device_dwmci1, state); 
162 } 
163 EXPORT_SYMBOL(exynos_dwmci1_notify_change); 
164 

_exynos_dwmci1_notify_func是一个函数指针,实际上就是函数dw_mci_notify_change

307 void __init exynos5_tf4_mmc_init(void) 
308 { 
309 #ifdef CONFIG_MMC_DW 
310     if (samsung_rev() < EXYNOS5410_REV_1_0) 
311         smdk5410_dwmci0_pdata.caps &= 
312             ~(MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR); 
313 #ifndef CONFIG_EXYNOS_EMMC_HS200 
314     smdk5410_dwmci0_pdata.caps2 &= 
315         ~MMC_CAP2_HS200_1_8V_SDR; 
316 #endif 
317     exynos_dwmci_set_platdata(&smdk5410_dwmci0_pdata, 0); 
318     exynos_dwmci_set_platdata(&smdk5410_dwmci1_pdata, 1); 
319     exynos_dwmci_set_platdata(&smdk5410_dwmci2_pdata, 2); 
320 #endif 
321     platform_add_devices(smdk5410_mmc_devices, 
322             ARRAY_SIZE(smdk5410_mmc_devices)); 
323 } 

数据接收

drivers/net/wireless/bcmdhd/dhd_linux.c

drivers/net/wireless/bcmdhd/dhd_sdio.c


 关键函数流程

	dhdsdio_probe
	dhd_attach
6054  dhd_bus_dpc
5788  dhdsdio_dpc  ---
5053  dhdsdio_readframes
接收处理函数,经过该函数后,见基于以太网的接收流程
drivers/net/wireless/bcmdhd/dhd_linux.c
2855 void
 2856 dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
 2857 {
 2858     dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
 2859     struct sk_buff *skb;
 2860     uchar *eth;
 2861     uint len;
 2862     void *data, *pnext = NULL;
….
3123         if (in_interrupt()) {
 3124             netif_rx(skb);
 3125         } else {
 3126             if (dhd->rxthread_enabled) {
 3127                 if (!skbhead)
 3128                     skbhead = skb;
 3129                 else
 3130                     PKTSETNEXT(dhdp->osh, skbprev, skb);
 3131                 skbprev = skb;
 3132             } else {
 3133 
 3134                 /* If the receive is not processed inside an ISR,
 3135                  * the softirqd must be woken explicitly to service
 3136                  * the NET_RX_SOFTIRQ.  In 2.6 kernels, this is handled
 3137                  * by netif_rx_ni(), but in earlier kernels, we need
 3138                  * to do it manually.
 3139                  */
 3140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
 3141                 netif_rx_ni(skb);
 3142 #else
 3143                 ulong flags;
 3144                 netif_rx(skb);

你可能感兴趣的:(网络)