很早之前自己的笔记,想想还是记录到网上吧
注册
-
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_HW在makefile中定义了,该宏的意义是使用的用户定制的硬件情况下的驱动注册。392~399行同样略过。
我们使用的wifi模组是sdio接口方式,401~415初始化一个wifiadapter的相关数据结构,在i2c设备驱动中也有adapter的概念。
435~437行,这三行的条件都满足。
438行为adapter的wifi_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秒打印出的信息,该中断号是ap6335的13脚(WL_HOST_WAKE)输出信号,该脚的作用是WLAN唤醒AP(应用处理器)。
442行设置该中断的标志为中断,高电平触发,中断资源可以共享。
444~449行是else分支,并没有得到执行。
450行加载wifi的sdio驱动,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,将ap6335的12脚拉低,让其内部电源稳压器工作。上电完成返回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,这时表sdio的notify注销掉并跳出这个循环。
-
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);