BCM wifi分析
一个:载入中wifi驱动模块
在hardware/libhardware_legacy/wifi/wifi.c调用函数
insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG)
当中
DRIVER_MODULE_PATH = /system/lib/dhd.ko
DRIVER_MODULE_ARG = "firmware_path=/etc/wifi/40181/fw_bcm40181a2.bin nvram_path=/etc/wifi/40181/nvram.txt"
二:wifi驱动模块执行
wifi驱动入口dhd_module_init(void) ... dhd_linux.c
dhd_module_init(void) { int error = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); wl_android_init(); //初始化dhd_msg_level |= DHD_ERROR_VAL,给iface_name赋值为wlan do { sema_init(&dhd_chipup_sem, 0); dhd_bus_reg_sdio_notify(&dhd_chipup_sem);//注冊sdio driver,支持例如以下图wifi列表,sdio驱动获取wifi列表的设备后调用dummy_probe() --> up(dhd_chipup_sem) dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); if (down_timeout(&dhd_chipup_sem, //2000ms超时等待 msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) { dhd_bus_unreg_sdio_notify(); chip_up = 1; break; } DHD_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n", retry+1)); dhd_bus_unreg_sdio_notify(); dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); } while (retry-- > 0); if (!chip_up) { DHD_ERROR(("\nfailed to power up wifi chip, max retry reached, exits **\n\n")); return -ENODEV; } sema_init(&dhd_registration_sem, 0); error = dhd_bus_register();//具体分析看<三>,注冊dhd_sdio驱动,终于会调用到dhd_net_attach(); if (!error) printf("\n%s\n", dhd_version); else { DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__)); goto fail_1; } /* * Wait till MMC sdio_register_driver callback called and made driver attach. * It's needed to make sync up exit from dhd insmod and * Kernel MMC sdio device callback registration */ if ((down_timeout(&dhd_registration_sem,//函数dhd_net_attach() --> up(&dhd_registration_sem); msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) || (dhd_registration_check != TRUE)) { error = -ENODEV; DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__)); goto fail_2; } wl_android_post_init(); return error; fail_2: dhd_bus_unregister(); fail_1: /* Call customer gpio to turn off power with WL_REG_ON signal */ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); return error; }
三:dhd_bus_register(void) ... dhd_sdio.c分析
bcmsdh_register(&dhd_sdio)会调用pci_register_driver(&bcmsdh_pci_driver)注冊一个pci类型的驱动。假设匹配到bcmsdh_pci_devid就会调用到bcmsdh_pci_probe --> drvinfo.attach --> drvinfo.attach ,终于调用到dhd_sdio->dhdsdio_probe,接下来分析dhdsdio_probe函数
四:dhdsdio_probe() ... dhd_sdio.c分析
dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh) { int ret; dhd_bus_t *bus; /* attach the common module */ dhd_common_init(osh); /* attempt to attach to the dongle */ if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) { DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__)); goto fail; } /* Attach to the dhd/OS/network interface */ //创建3个线程,各自是dhd_watchdog_thread、dhd_dpc、dhd_sysioc if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) { DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__)); goto fail; } /* Allocate buffers */ if (!(dhdsdio_probe_malloc(bus, osh, sdh))) { DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__)); goto fail; } if (!(dhdsdio_probe_init(bus, osh, sdh))) { DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__)); goto fail; } if (bus->intr) { /* Register interrupt callback, but mask it (not operational yet). */ DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__)); bcmsdh_intr_disable(sdh); if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) { DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n", __FUNCTION__, ret)); goto fail; } DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__)); } else { DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n", __FUNCTION__)); } DHD_INFO(("%s: completed!!\n", __FUNCTION__)); //获取wifi MAC地址 ret = dhd_custom_get_mac_address(ea_addr.octet); /* if firmware path present try to download and bring up bus */ if (dhd_download_fw_on_driverload) { //更新模组firmware、nvram,当中使用了filp_open、kernel_read、filp_close进行文件系统的操作 if ((ret = dhd_bus_start(bus->dhd)) != 0) { DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); goto fail; } } /* Ok, have the per-port tell the stack we're open for business */ if (dhd_net_attach(bus->dhd, 0) != 0) { DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); goto fail; } return bus; fail: dhdsdio_release(bus, osh); return NULL; }
版权声明:本文博客原创文章,博客,未经同意,不得转载。