zoukankan      html  css  js  c++  java
  • 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
    ", __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(("
    failed to power up wifi chip, retry again (%d left) **
    
    ",
    			retry+1));
    		dhd_bus_unreg_sdio_notify();
    		dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
    	} while (retry-- > 0);
    
    	if (!chip_up) {
    		DHD_ERROR(("
    failed to power up wifi chip, max retry reached, exits **
    
    "));
    		return -ENODEV;
    	}
    
    	sema_init(&dhd_registration_sem, 0);
    
    	error = dhd_bus_register();//具体分析看<三>,注冊dhd_sdio驱动,终于会调用到dhd_net_attach();
    
    	if (!error)
    		printf("
    %s
    ", dhd_version);
    	else {
    		DHD_ERROR(("%s: sdio_register_driver failed
    ", __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 
    ", __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
    ", __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
    ", __FUNCTION__));
    		goto fail;
    	}
    
    	/* Allocate buffers */
    	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
    		DHD_ERROR(("%s: dhdsdio_probe_malloc failed
    ", __FUNCTION__));
    		goto fail;
    	}
    
    	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
    		DHD_ERROR(("%s: dhdsdio_probe_init failed
    ", __FUNCTION__));
    		goto fail;
    	}
    
    	if (bus->intr) {
    		/* Register interrupt callback, but mask it (not operational yet). */
    		DHD_INTR(("%s: disable SDIO interrupts (not interested yet)
    ", __FUNCTION__));
    		bcmsdh_intr_disable(sdh);
    		if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
    			DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d
    ",
    			           __FUNCTION__, ret));
    			goto fail;
    		}
    		DHD_INTR(("%s: registered SDIO interrupt function ok
    ", __FUNCTION__));
    	} else {
    		DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode
    ",
    		           __FUNCTION__));
    	}
    
    	DHD_INFO(("%s: completed!!
    ", __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
    ", __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!!
    ", __FUNCTION__));
    		goto fail;
    	}
    
    
    	return bus;
    
    fail:
    	dhdsdio_release(bus, osh);
    
    	return NULL;
    }





    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    vue封装axios请求
    搭建vue开发环境
    webpack搭建vue环境报错
    JS的执行顺序 setTimeout与Promise async/await
    position属性脱离文档流覆盖其他内容
    MVC和MVT
    HTTP常见请求方式(get,post,put,delete)
    三次握手四次挥手
    web工作流程,中间件,请求顺序
    Vue整理
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4647841.html
Copyright © 2011-2022 走看看