博通wifi驱动

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

注册

 

 
  1. 7611 static int __init

  2. 7612 dhd_module_init(void)

  3. 7613 {

  4. 7614 int err;

  5. 7615 int retry = POWERUP_MAX_RETRY;

  6. 7616

  7. 7617 printk("%s: in\n", __FUNCTION__);

  8. 7618

  9. 7619 DHD_PERIM_RADIO_INIT();

  10. 7620

  11. 7621 if (firmware_path[0] != '\0') {

  12. 7622 strncpy(fw_bak_path, firmware_path, MOD_PARAM_PATHLEN);

  13. 7623 fw_bak_path[MOD_PARAM_PATHLEN-1] = '\0';

  14. 7624 }

  15. 7625

  16. 7626 if (nvram_path[0] != '\0') {

  17. 7627 strncpy(nv_bak_path, nvram_path, MOD_PARAM_PATHLEN);

  18. 7628 nv_bak_path[MOD_PARAM_PATHLEN-1] = '\0';

  19. 7629 }

  20. 7630

  21. 7631 do {

  22. 7632 err = dhd_wifi_platform_register_drv();

  23. 7633 if (!err) {

  24. 7634 register_reboot_notifier(&dhd_reboot_notifier);

  25. 7635 break;

  26. 7636 }

  27. 7637 else {

  28. 7638 DHD_ERROR(("%s: Failed to load the driver, try cnt %d\n",

  29. 7639 __FUNCTION__, retry));

  30. 7640 strncpy(firmware_path, fw_bak_path, MOD_PARAM_PATHLEN);

  31. 7641 firmware_path[MOD_PARAM_PATHLEN-1] = '\0';

  32. 7642 strncpy(nvram_path, nv_bak_path, MOD_PARAM_PATHLEN);

  33. 7643 nvram_path[MOD_PARAM_PATHLEN-1] = '\0';

  34. 7644 }

  35. 7645 } while (retry--);

  36. 7646

  37. 7647 if (err)

  38. 7648 DHD_ERROR(("%s: Failed to load driver max retry reached**\n", __FUNCTION__));

  39. 7649

  40. 7650 printk("%s: Exit err=%d\n", __FUNCTION__, err);

  41. 7651 return err;

  42. 7652 }

 

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

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

 
  1. 543 int dhd_wifi_platform_register_drv(void)

  2. 544 {

  3. 545 int err = 0;

  4. ...

  5. 565 {

  6. 566 err = wifi_ctrlfunc_register_drv();

  7. 567

  8. 568 /* no wifi ctrl func either, load bus directly and ignore this error */

  9. 569 if (err) {

  10. 570 if (err == -ENXIO) {

  11. 571 /* wifi ctrl function does not exist */

  12. 572 err = dhd_wifi_platform_load();

  13. 573 } else {

  14. 574 /* unregister driver due to initialization failure */

  15. 575 wifi_ctrlfunc_unregister_drv();

  16. 576 }

  17. 577 }

  18. 578 }

  19. 579

  20. 580 return err;

  21. 581 }

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

 
  1. 381 static int wifi_ctrlfunc_register_drv(void)

  2. 382 {

  3. 383 wifi_adapter_info_t *adapter;

  4. 384

  5. 385 #ifndef CUSTOMER_HW

  6. 386 int err = 0;

  7. 387 struct device *dev1, *dev2;

  8. 388 dev1 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME, wifi_platdev_match);

  9. 389 dev2 = bus_find_device(&platform_bus_type, NULL, WIFI_PLAT_NAME2, wifi_platdev_match);

  10. 390 #endif

  11. 391

  12. 392 #if !defined(CONFIG_DTS) && !defined(CUSTOMER_HW)

  13. 393 if (!dts_enabled) {

  14. 394 if (dev1 == NULL && dev2 == NULL) {

  15. 395 DHD_ERROR(("no wifi platform data, skip\n"));

  16. 396 return -ENXIO;

  17. 397 }

  18. 398 }

  19. 399 #endif /* !defined(CONFIG_DTS) */

  20. 400

  21. 401 /* multi-chip support not enabled, build one adapter information for

  22. 402 * DHD (either SDIO, USB or PCIe)

  23. 403 */

  24. 404 adapter = kzalloc(sizeof(wifi_adapter_info_t), GFP_KERNEL);

  25. 405 adapter->name = "DHD generic adapter";

  26. 406 adapter->bus_type = -1;

  27. 407 adapter->bus_num = -1;

  28. 408 adapter->slot_num = -1;

  29. 409 adapter->irq_num = -1;

  30. 410 is_power_on = FALSE;

  31. 411 wifi_plat_dev_probe_ret = 0;

  32. 412 dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL);

  33. 413 dhd_wifi_platdata->num_adapters = 1;

  34. 414 dhd_wifi_platdata->adapters = adapter;

  35. ...

  36. 435 #if !defined(CONFIG_DTS)

  37. 436 if (dts_enabled) {

  38. 437 #ifdef CUSTOMER_HW

  39. 438 adapter->wifi_plat_data = (void *)&dhd_wlan_control;

  40. 439 bcm_wlan_set_plat_data();

  41. 440 #ifdef CUSTOMER_OOB

  42. 441 adapter->irq_num = bcm_wlan_get_oob_irq();

  43. 442 adapter->intr_flags = bcm_wlan_get_oob_irq_flags();

  44. 443 #endif

  45. 444 #else

  46. 445 struct resource *resource;

  47. 446 resource = &dhd_wlan_resources;

  48. 447 adapter->irq_num = resource->start;

  49. 448 adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK;

  50. 449 #endif

  51. 450 wifi_plat_dev_probe_ret = dhd_wifi_platform_load();

  52. 451 }

  53. 452 #endif /* !defined(CONFIG_DTS) */

  54. 453

  55. 454

  56. 455 #if defined(CONFIG_DTS) && !defined(CUSTOMER_HW)

  57. 456 wifi_plat_dev_probe_ret = platform_driver_register(&wifi_platform_dev_driver);

  58. 457 #endif /* CONFIG_DTS */

  59. 458

  60. 459 /* return probe function's return value if registeration succeeded */

  61. 460 return wifi_plat_dev_probe_ret;

  62. 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行占坑的指针赋值成员初始化。赋值的这三个成员是平台相关的,如下:

 
  1. dhd_wlan_control.set_power = bcm_wlan_set_power;

  2. dhd_wlan_control.set_carddetect = bcm_wlan_set_carddetect;

  3. 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()。

 
  1. 685 #ifdef BCMSDIO

  2. 686 static int dhd_wifi_platform_load_sdio(void)

  3. 687 {

  4. 688 int i;

  5. 689 int err = 0;

  6. 690 wifi_adapter_info_t *adapter;

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

 
  1. 692 BCM_REFERENCE(i);

  2. 693 BCM_REFERENCE(adapter);

//参数安全性检查

 
  1. 694 /* Sanity check on the module parameters

  2. 695 * - Both watchdog and DPC as tasklets are ok

  3. 696 * - If both watchdog and DPC are threads, TX must be deferred

  4. 697 */

  5. 698 if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) &&

  6. 699 !(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx))

  7. 700 return -EINVAL;

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

 
  1. 702 #if defined(BCMLXSDMMC)

  2. 703 if (dhd_wifi_platdata == NULL) {

  3. 704 DHD_ERROR(("DHD wifi platform data is required for Android build\n"));

  4. 705 return -EINVAL;

  5. 706 }

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

708     sema_init(&dhd_registration_sem, 0); 

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

 
  1. 710 for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {

  2. 711 bool chip_up = FALSE;

  3. 712 int retry = POWERUP_MAX_RETRY;

  4. 713 struct semaphore dhd_chipup_sem;

  5. 714

  6. 715 adapter = &dhd_wifi_platdata->adapters[i];

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

 
  1. 717 DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));

  2. 718 DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",

  3. 719 adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path));

  4. 720 DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",

  5. 721 adapter->bus_type, adapter->bus_num, adapter->slot_num));

  6. 722

  7. 723 do {

//同样是信号量初始化

 
  1. 724 sema_init(&dhd_chipup_sem, 0);

  2. //Register a dummy SDIO client driver in order to be notified of new SDIO device

  3. 725 err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem);

  4. 726 if (err) {

  5. 727 DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",

  6. 728 __FUNCTION__, err));

  7. 729 return err;

  8. 730 }

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

 
  1. 731 err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);

  2. 732 if (err) {

  3. 733 /* WL_REG_ON state unknown, Power off forcely */

  4. 734 wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);

  5. 735 continue;

  6. 736 } else {

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

 
  1. 737 wifi_platform_bus_enumerate(adapter, TRUE);

  2. 738 err = 0;

  3. 739 }

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

 
  1. 741 if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) {

  2. 742 dhd_bus_unreg_sdio_notify();

  3. 743 chip_up = TRUE;

  4. 744 break;

  5. 745 }

//出错处理,省略

 
  1. ...

  2. 751 } while (retry--);

  3. ...

  4. 753 if (!chip_up) {

  5. 754 DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name));

  6. 755 return -ENODEV;

  7. 756 }

  8. 757

  9. 758 }

//dhd总线注册

 
  1. 760 err = dhd_bus_register();

  2. 761

  3. 762 if (err) {

  4. 763 DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));

  5. 764 goto fail;

  6. 765 }

  7. 766

  8. 767

  9. 768 /*

  10. 769 * Wait till MMC sdio_register_driver callback called and made driver attach.

  11. 770 * It's needed to make sync up exit from dhd insmod and

  12. 771 * Kernel MMC sdio device callback registration

  13. 772 */

  14. 773 err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));

  15. 774 if (err) {

  16. 775 DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__));

  17. 776 dhd_bus_unregister();

  18. 777 goto fail;

  19. 778 }

  20. 779

  21. 780 return err;

  22. 781

  23. 782 fail:

  24. 783 /* power down all adapters */

  25. 784 for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {

  26. 785 adapter = &dhd_wifi_platdata->adapters[i];

  27. 786 wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);

  28. 787 wifi_platform_bus_enumerate(adapter, FALSE);

  29. 788 }

  30. 789 #else

  31. 790

  32. 791 /* x86 bring-up PC needs no power-up operations */

  33. 792 err = dhd_bus_register();

  34. 793

  35. 794 #endif

  36. 795

  37. 796 return err;

  38. 797 }

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

 
  1. 82 extern void exynos_dwmci1_notify_change(int state);

  2. 83 int bcm_wlan_set_carddetect(bool present)

  3. 84 {

  4. 85 int err = 0;

  5. 86

  6. 87 if (present) {

  7. 88 printk("======== Card detection to detect SDIO card! ========\n");

  8. 89 #ifdef CONFIG_MACH_ODROID_4210

  9. 90 exynos_dwmci1_notify_change(1);

  10. 91 #endif

  11. 92 } else {

  12. 93 printk("======== Card detection to remove SDIO card! ========\n");

  13. 94 #ifdef CONFIG_MACH_ODROID_4210

  14. 95 exynos_dwmci1_notify_change(0);

  15. 96 #endif

  16. 97 }

  17. 98

  18. 99 return err;

  19. 100 }

由于exynos_dwmci1_notify_change属于mmc的范畴,

 
  1. 157 static void (*_exynos_dwmci1_notify_func)(struct platform_device *, int);

  2. 158 void exynos_dwmci1_notify_change(int state)

  3. 159 {

  4. 160 if (_exynos_dwmci1_notify_func)

  5. 161 _exynos_dwmci1_notify_func(&exynos5_device_dwmci1, state);

  6. 162 }

  7. 163 EXPORT_SYMBOL(exynos_dwmci1_notify_change);

  8. 164

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

 
  1. 307 void __init exynos5_tf4_mmc_init(void)

  2. 308 {

  3. 309 #ifdef CONFIG_MMC_DW

  4. 310 if (samsung_rev() < EXYNOS5410_REV_1_0)

  5. 311 smdk5410_dwmci0_pdata.caps &=

  6. 312 ~(MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR);

  7. 313 #ifndef CONFIG_EXYNOS_EMMC_HS200

  8. 314 smdk5410_dwmci0_pdata.caps2 &=

  9. 315 ~MMC_CAP2_HS200_1_8V_SDR;

  10. 316 #endif

  11. 317 exynos_dwmci_set_platdata(&smdk5410_dwmci0_pdata, 0);

  12. 318 exynos_dwmci_set_platdata(&smdk5410_dwmci1_pdata, 1);

  13. 319 exynos_dwmci_set_platdata(&smdk5410_dwmci2_pdata, 2);

  14. 320 #endif

  15. 321 platform_add_devices(smdk5410_mmc_devices,

  16. 322 ARRAY_SIZE(smdk5410_mmc_devices));

  17. 323 }

数据接收

 

drivers/net/wireless/bcmdhd/dhd_linux.c

 

drivers/net/wireless/bcmdhd/dhd_sdio.c

 

 关键函数流程

 

 
  1. dhdsdio_probe

  2. dhd_attach

  3. 6054 dhd_bus_dpc

  4. 5788 dhdsdio_dpc ---

  5. 5053 dhdsdio_readframes

接收处理函数,经过该函数后,见基于以太网的接收流程

 
  1. drivers/net/wireless/bcmdhd/dhd_linux.c

  2. 2855 void

  3. 2856 dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)

  4. 2857 {

  5. 2858 dhd_info_t *dhd = (dhd_info_t *)dhdp->info;

  6. 2859 struct sk_buff *skb;

  7. 2860 uchar *eth;

  8. 2861 uint len;

  9. 2862 void *data, *pnext = NULL;

  10. ….

  11. 3123 if (in_interrupt()) {

  12. 3124 netif_rx(skb);

  13. 3125 } else {

  14. 3126 if (dhd->rxthread_enabled) {

  15. 3127 if (!skbhead)

  16. 3128 skbhead = skb;

  17. 3129 else

  18. 3130 PKTSETNEXT(dhdp->osh, skbprev, skb);

  19. 3131 skbprev = skb;

  20. 3132 } else {

  21. 3133

  22. 3134 /* If the receive is not processed inside an ISR,

  23. 3135 * the softirqd must be woken explicitly to service

  24. 3136 * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled

  25. 3137 * by netif_rx_ni(), but in earlier kernels, we need

  26. 3138 * to do it manually.

  27. 3139 */

  28. 3140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)

  29. 3141 netif_rx_ni(skb);

  30. 3142 #else

  31. 3143 ulong flags;

  32. 3144 netif_rx(skb);

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值