补:
//调用bcm_wlan_set_power,将ap6335的12脚拉低,让其内部电源稳压器工作。上电完成返回TRUE。上电正常返回值err=0。
[cpp] view plain copy
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
[cpp] view plain copy
737 wifi_platform_bus_enumerate(adapter, TRUE);
738 err = 0;
739 }
//如果成功获取到dhd_chipup_sem,则表示wifi芯片成功powerup,这时表sdio的notify注销掉并跳出这个循环。
[cpp] view plain copy
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 }
//出错处理,省略
[cpp] view plain copy
...
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总线注册
[cpp] view plain copy
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行的输出。
[cpp] view plain copy
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的范畴,
[cpp] view plain copy
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。
[cpp] view plain copy
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
关键函数流程
[cpp] view plain copy
dhdsdio_probe
dhd_attach
6054 dhd_bus_dpc
5788 dhdsdio_dpc ---
5053 dhdsdio_readframes
接收处理函数,经过该函数后,见基于以太网的接收流程
[cpp] view plain copy
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);