Linux 下wifi 驱动开发—— SDIO接口WiFi驱动浅析.doc

上传人:豆**** 文档编号:33498081 上传时间:2022-08-11 格式:DOC 页数:15 大小:389KB
返回 下载 相关 举报
Linux 下wifi 驱动开发—— SDIO接口WiFi驱动浅析.doc_第1页
第1页 / 共15页
Linux 下wifi 驱动开发—— SDIO接口WiFi驱动浅析.doc_第2页
第2页 / 共15页
点击查看更多>>
资源描述

《Linux 下wifi 驱动开发—— SDIO接口WiFi驱动浅析.doc》由会员分享,可在线阅读,更多相关《Linux 下wifi 驱动开发—— SDIO接口WiFi驱动浅析.doc(15页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、-作者xxxx-日期xxxxLinux 下wifi 驱动开发 SDIO接口WiFi驱动浅析【精品文档】Linux 下wifi 驱动开发(三) SDIO接口WiFi驱动浅析 SDIO-Wifi模块是基于SDIO接口的符合wifi无线网络标准的嵌入式模块,内置无线网络协议协议栈以及TCP/IP协议栈,能够实现用户主平台数据通过SDIO口到无线网络之间的转换。SDIO具有传输数据快,兼容SD、MMC接口等特点。 对于SDIO接口的wifi,首先,它是一个sdio的卡的设备,然后具备了wifi的功能,所以,注册的时候还是先以sdio的卡的设备去注册的。然后检测到卡之后就要驱动他的wifi功能了,显然,

2、他是用sdio的协议,通过发命令和数据来控制的。下面先简单回顾一下SDIO的相关知识:一、SDIO相关基础知识解析1、SDIO接口 SDIO故名思义,就是SD 的 I/O 接口(interface)的意思,不过这样解释可能还有点抽像。更具体的说明,SD 本来是记忆卡的标准,但是现在也可以把 SD 拿来插上一些外围接口使用,这样的技术便是 SDIO。 所以 SDIO 本身是一种相当单纯的技术,透过 SD 的 I/O 接脚来连接外部外围,并且透过 SD 上的 I/O 数据接位与这些外围传输数据,而且 SD 协会会员也推出很完整的 SDIO stack 驱动程序,使得 SDIO 外围(我们称为SDI

3、O 卡)的开发与应用变得相当热门。 现在已经有非常多的手机或是手持装置都支持 SDIO 的功能(SD 标准原本就是针对 mobile device 而制定),而且许多 SDIO 外围也都被开发出来,让手机外接外围更加容易,并且开发上更有弹性(不需要内建外围)。目前常见的 SDIO 外围(SDIO 卡)有: Wi-Fi card(无线网络卡) CMOS sensor card(照相模块) GPS card GSM/GPRS modem card Bluetooth card SDIO 的应用将是未来嵌入式系统最重要的接口技术之一,并且也会取代目前 GPIO 式的 SPI 接口。2、SDIO总线

4、SDIO总线 和 USB总线 类似,SDIO也有两端,其中一端是HOST端,另一端是device端。所有的通信都是由HOST端 发送 命令 开始的,Device端只要能解析命令,就可以相互通信。CLK信号:HOST给DEVICE的 时钟信号,每个时钟周期传输一个命令。CMD信号:双向 的信号,用于传送 命令 和 反应。DAT0-DAT3 信号:四条用于传送的数据线。VDD信号:电源信号。VSS1,VSS2:电源地信号。3、SDIO热插拔原理方法:设置一个定时器检查或插拔中断检测硬件:假如GPG10(EINT18)用于SD卡检测GPG10 为高电平 即没有插入SD卡GPG10为低电平 即插入了S

5、D卡4、SDIO命令 SDIO总线上都是HOST端发起请求,然后DEVICE端回应请求。sdio命令由6个字节组成。a - Command:用于开始传输的命令,是由HOST端发往DEVICE端的。其中命令是通过CMD信号线传送的。b - Response:回应是DEVICE返回的HOST的命令,作为Command的回应。也是通过CMD线传送的。c - Data:数据是双向的传送的。可以设置为1线模式,也可以设置为4线模式。数据是通过DAT0-DAT3信号线传输的。 SDIO的每次操作都是由HOST在CMD线上发起一个CMD,对于有的CMD,DEVICE需要返回Response,有的则不需要。

6、对于读命令,首先HOST会向DEVICE发送命令,紧接着DEVICE会返回一个握手信号,此时,当HOST收到回应的握手信号后,会将数据放在4位的数据线上,在传送数据的同时会跟随着CRC校验码。当整个读传送完毕后,HOST会再次发送一个命令,通知DEVICE操作完毕,DEVICE同时会返回一个响应。 对于写命令,首先HOST会向DEVICE发送命令,紧接着DEVICE会返回一个握手信号,此时,当HOST收到回应的握手信号后,会将数据放在4位的数据线上,在传送数据的同时会跟随着CRC校验码。当整个写传送完毕后,HOST会再次发送一个命令,通知DEVICE操作完毕,DEVICE同时会返回一个响应。二

7、、SDIO接口驱动 前面讲到,SDIO接口的wifi,首先,它是一个sdio的卡的设备,然后具备了wifi的功能,所以SDIO接口的WiFi驱动就是在wifi驱动外面套上了一个SDIO驱动的外壳,SDIO驱动仍然符合设备驱动的分层与分离思想: 设备驱动层(wifi 设备) |核心层(向上向下提供接口) |主机驱动层 (实现SDIO驱动) 下面先分析SDIO接口驱动的实现,看几个重要的数据结构(用于核心层与主机驱动层 的数据交换处理)。 /include/linux/mmc/ struct mmc_host 用来描述卡控制器struct mmc_card 用来描述卡struct mmc_driv

8、er 用来描述 mmc 卡驱动struct sdio_func 用来描述 功能设备struct mmc_host_ops 用来描述卡控制器操作接口函数功能,用于从 主机控制器层向 core 层注册操作函数,从而将core 层与具体的主机控制器隔离。也就是说 core 要操作主机控制器,就用这个 ops 当中给的函数指针操作,不能直接调用具体主控制器的函数。 HOST层驱动分析在 前面的系列文章中Linux SD卡驱动开发(二) SD 卡驱动分析HOST篇有详细阐述,下面只简单回顾一下一些重要函数处理1、编写Host层驱动 这里参考的是S3C24XX的HOST驱动程序 /drivers/mmc/

9、host/s3cmci.ccppview plaincopy1. staticstructplatform_drivers3cmci_driver=2. .driver=3. .name=s3c-sdi,/名称和平台设备定义中的对应4. .owner=THIS_MODULE,5. .pm=s3cmci_pm_ops,6. ,7. .id_table=s3cmci_driver_ids,8. .probe=s3cmci_probe,/平台设备探测接口函数9. .remove=_devexit_p(s3cmci_remove),10. .shutdown=s3cmci_shutdown,11. ;

10、12. 13. s3cmci_probe(structplatform_device*pdev)14. 15. /.16. structmmc_host*mmc;17. mmc=mmc_alloc_host(sizeof(structs3cmci_host),&pdev-dev);/分配mmc_host结构体18. 19. /.20. 21. 22. /*注册中断处理函数s3cmci_irq,来处理数据收发过程引起的各种中断*/23. request_irq(host-irq,s3cmci_irq,0,DRIVER_NAME,host)/注册中断处理函数s3cmci_irq24. 25. /*

11、注册中断处理s3cmci_irq_cd函数,来处理热拨插引起的中断,中断触发的形式为上升沿、下降沿触发*/26. request_irq(host-irq_cd,s3cmci_irq_cd,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,DRIVER_NAME,host)27. 28. mmc_add_host(mmc);/initialisehosthardware/向MMCcore注册host驱动29. -device_add(&host-class_dev);/添加设备到mmc_bus_type总线上的设备链表中30. -mmc_start_host(h

12、ost);/启动mmchost31. 32. /*MMCdriversshouldcallthiswhentheydetectacardhasbeeninsertedorremoved.检测sd卡是否插上或移除*/33. -mmc_detect_change(host,0);34. 35. /*ScheduledelayedworkintheMMCworkqueue.调度延时工作队列*/36. mmc_schedule_delayed_work(&host-detect,delay);搜索host-detected得到以下信息:/drivers/mmc/core/cppview plainco

13、py1. NIT_DELAYED_WORK(&host-detect,mmc_rescan);2. 3. mmc_rescan(structwork_struct*work)4. -mmc_bus_put(host);/card从bus上移除时,释放它占有的总线空间5. 6. /*判断当前mmchost控制器是否被占用,当前mmc控制器如果被占用,那么host-claimed=1;否则为07. *如果为1,那么会在while(1)循环中调用schedule切换出自己,当占用mmc控制器的操作完成之后,执行*mmc_release_host()的时候,会激活登记到等待队列&host-wq中的其他

14、程序获得mmc主控制器的使用权8. */9. mmc_claim_host(host);10. mmc_rescan_try_freq(host,max(freqsi,host-f_min);11. 12. staticintmmc_rescan_try_freq(structmmc_host*host,unsignedfreq)13. 14. 15. /*Ordersimportant:probeSDIO,thenSD,thenMMC*/16. if(!mmc_attach_sdio(host)17. return0;18. if(!mmc_attach_sd(host)19. return

15、0;20. if(!mmc_attach_mmc(host)21. return0;22. .23. 24. 25. mmc_attach_sdio(structmmc_host*host)/匹配sdio接口卡26. -mmc_attach_bus(host,&mmc_sdio_ops);27. 28. /*当card与总线上的驱动匹配,就初始化card*/29. mmc_sdio_init_card(host,host-ocr,NULL,0);30. -card=mmc_alloc_card(host,NULL);/分配一个card结构体31. mmc_set_bus_mode(host,M

16、MC_BUSMODE_PUSHPULL);/设置mmc_bus的工作模式32. 33. structsdio_func*sdio_funcSDIO_MAX_FUNCS;/SDIOfunctions(devices)34. 35. sdio_init_func(host-card,i+1);36. -func=sdio_alloc_func(card);/分配structsdio_fun(sdio功能设备)结构体37. mmc_io_rw_direct();38. card-sdio_funcfn-1=func;39. 40. mmc_add_card(host-card);/将具体的sdio设

17、备挂载到mmc_bus_types总线41. sdio_add_func(host-card-sdio_funci);/将sdio功能设备挂载到sdio_bus_types总线这里一系列函数调用在前面的SD驱动蚊帐中已经阐述过了,不再详细阐述2、SDIO设备的热插拔 当插拔SDIO设备,会触发中断通知到CPU,然后执行卡检测中断处理函数在这个中断服务函数中,mmc_detect_change-mmc_schedule_delayed_work(&host-detect,delay), INIT_DELAYED_WORK(&host-detect, mmc_rescan)会调度mmc_resca

18、n函数延时调度工作队列,这样也会触发SDIO设备的初始化流程,检测到有效的SDIO设备后,会将它注册到系统中去。cppview plaincopy1. staticirqreturn_ts3cmci_irq_cd(intirq,void*dev_id)2. 3. structs3cmci_host*host=(structs3cmci_host*)dev_id;4. .5. mmc_detect_change(host-mmc,msecs_to_jiffies(500);6. 7. returnIRQ_HANDLED;8. 三、wifi 驱动部分解析wifi驱动的通用的软件架构1. 分为两部分

19、,上面为主机端驱动,下面是我们之前所说的firmware2. 其中固件部分的主要工作是:因为天线接受和发送回来的都是帧的帧,而主机接受和传送出来的数据都必须是的帧,所以必须由firmware来负责的帧和帧之间的转换3. 当天线收到数据,并被firmware处理好后会放在一个buffer里,并产生一个中断,主机在收到中断后就去读这个buffer。 SDIO设备的驱动由sdio_driver结构体定义,sdio_driver其实是driver的封装。通过sdio_register_driver函数将SDIO设备驱动加载进内核,其实就是挂载到sdio_bus_type总线上去。1、设备驱动的注册与匹

20、配Drivers/net/wireless/libertas/cppview plaincopy1. /*SDIOfunctiondevicedriver*/2. 3. structsdio_driver4. char*name;/设备名5. conststructsdio_device_id*id_table;/设备驱动ID6. int(*probe)(structsdio_func*,conststructsdio_device_id*);/匹配函数7. void(*remove)(structsdio_func*);8. structdevice_driverdrv;9. ;下面是具体函

21、数的填充:cppview plaincopy1. /*/2. 3. staticstructsdio_driverif_sdio_driver=4. .name=libertas_sdio,5. .id_table=if_sdio_ids,/用于设备与驱动的匹配6. .probe=if_sdio_probe,7. .remove=if_sdio_remove,8. .drv=9. .pm=&if_sdio_pm_ops,10. 11. ;设备注册函数cppview plaincopy1. /*2. *sdio_register_driver-registerafunctiondriver3.

22、*drv:SDIOfunctiondriver4. */5. 6. intsdio_register_driver(structsdio_driver*drv)7. 8. drv-drv.name=drv-name;9. drv-drv.bus=&sdio_bus_type;/设置driver的bus为sdio_bus_type10. returndriver_register(&drv-drv);11. 总线函数cppview plaincopy1. staticstructbus_typesdio_bus_type=2. .name=sdio,3. .dev_attrs=sdio_dev_

23、attrs,4. .match=sdio_bus_match,5. .uevent=sdio_bus_uevent,6. .probe=sdio_bus_probe,7. .remove=sdio_bus_remove,8. .pm=SDIO_PM_OPS_PTR,9. ;注意:设备或者驱动注册到系统中的过程中,都会调用相应bus上的匹配函数来进行匹配合适的驱动或者设备,对于sdio设备的匹配是由sdio_bus_match和sdio_bus_probe函数来完成。cppview plaincopy1. staticintsdio_bus_match(structdevice*dev,stru

24、ctdevice_driver*drv)2. 3. structsdio_func*func=dev_to_sdio_func(dev);4. structsdio_driver*sdrv=to_sdio_driver(drv);5. if(sdio_match_device(func,sdrv)6. return1;7. 8. return0;9. 10. 11. staticconststructsdio_device_id*sdio_match_device(structsdio_func*func,12. structsdio_driver*sdrv)13. 14. conststru

25、ctsdio_device_id*ids;15. ids=sdrv-id_table;16. 17. if(sdio_match_one(func,ids)18. returnids;19. 由以上匹配过程来看,通过匹配id_table 和 sdio_driver设备驱动中id,来匹配合适的驱动或设备。最终会调用.probe函数,来完成相关操作。2、If_sdio_probe函数 当检测到sdio卡插入了之后就会调用If_sdio_probe,而当卡被移除后就会调用If_sdio_remove。下面先看下If_sdio_probet函数,if_sdio_prob 函数 主要做了两件事 cppv

26、iew plaincopy1. staticstructsdio_driverif_sdio_driver=2. .name=libertas_sdio,3. .id_table=if_sdio_ids,/用于设备和驱动的匹配4. .probe=if_sdio_probe,5. .remove=if_sdio_remove,6. .drv=7. .pm=&if_sdio_pm_ops,8. ,9. ;10. 11. 12. 1/定义一个if_sdiocard的结构体13. structif_sdio_card*card;14. structif_sdio_packet*packet;/sdio

27、包的结构体15. structmmc_host*host=func-card-host;16. 17. /查询是否有指定的功能寄存器在mmc18. /_sdio_card中19. for(i=0;icard-num_info;i+)20. if(sscanf(func-card-infoi,21. 802.11SDIOID:%x,&model)=1)22. 23. /在这里进行片选选择到我们使用的marvell8686的设备24. caseMODEL_8686:25. card-scratch_reg=IF_SDIO_SCRATCH;26. 27. 28. /创建sdio的工作队列29. ca

28、rd-workqueue=create_workqueue(libertas_sdio);30. /调用下面的函数31. INIT_WORK(&card-packet_worker,if_sdio_host_to_card_worker);32. 33. 34. /主机到卡的工作队列35. staticvoidif_sdio_host_to_card_worker(structwork_struct*work)36. 37. /*Checkifwesupportthiscard选择我们所支持的卡的类型*/38. /赋值为39. /*fw_table中的MODEL_8686,sd8686_hel

29、per.bin,sd8686.bin,?/40. for(i=0;imodel=fw_tablei.model)42. break;43. 44. MODEL_8688,libertas/sd8688_helper.bin,libertas/sd8688.bin,45. 46. 47. /申请一个host48. sdio_claim_host(func);49. /使能sdio的功能寄存器50. ret=sdio_enable_func(func);51. if(ret)52. gotorelease;53. 54. 2/申请sdio的中断当有数据,命令或者是事件的时间执行中断55. ret=

30、sdio_claim_irq(func,if_sdio_interrupt);56. ret=if_sdio_card_to_host(card);/从无线网卡接收到数据或者说是上报数据57. ret=if_sdio_handle_data(card,card-buffer+4,chunk-4);/接收数据的处理58. ret=if_sdio_handle_cmd(card,card-buffer+4,chunk-4);/处理申请的命令中断59. ret=if_sdio_handle_event(card,card-buffer+4,chunk-4);/处理申请的事件中断60. 61. 62.

31、 /添加网络结构体分配设备并注册63. priv=lbs_add_card(card,&func-dev);64. 65. /分配Ethernet设备并注册66. wdev=lbs_cfg_alloc(dmdev);67. /802无线网的具体的操作函数68. wdev-wiphy=wiphy_new(&lbs_cfg80211_ops,sizeof(structlbs_private);69. 70. 71. /分配网络设备是整个网络部分操作的72. /的核心结构体73. dev=alloc_netdev(0,wlan%d,ether_setup);/实例化wlan0的属性74. dev-i

32、eee80211_ptr=wdev;75. dev-ml_priv=priv;76. /设置设备的物理地址77. SET_NETDEV_DEV(dev,dmdev);78. wdev-netdev=dev;79. priv-dev=dev;80. /初始化网络设备ops.看门狗81. dev-netdev_ops=&lbs_netdev_ops;/网络设备的具体的操作函数82. dev-watchdog_timeo=5*HZ;83. dev-ethtool_ops=&lbs_ethtool_ops;84. dev-flags|=IFF_BROADCAST|IFF_MULTICAST;/广播或者

33、多播85. 86. 87. 88. /启动一个内核线程来管理这个网络设备的数据发送,事件的处理(卡的拔出)和一些命令的处理89. priv-main_thread=kthread_run(lbs_thread,dev,lbs_main);90. /初始化相关的工作队列91. priv-work_thread=create_singlethread_workqueue(lbs_worker);92. INIT_WORK(&priv-mcast_work,lbs_set_mcast_worker);93. priv-wol_criteria=EHS_REMOVE_WAKEUP;94. priv-w

34、ol_gpio=0xff;95. priv-wol_gap=20;96. priv-ehs_remove_supported=true;97. 98. 99. /设置私有变量100. /设置主机发送数据到卡101. priv-hw_host_to_card=if_sdio_host_to_card;102. priv-enter_deep_sleep=if_sdio_enter_deep_sleep;103. priv-exit_deep_sleep=if_sdio_exit_deep_sleep;104. priv-reset_deep_sleep_wakeup=if_sdio_reset_

35、deep_sleep_wakeup;105. sdio_claim_host(func);106. 107. /启动卡设备108. ret=lbs_start_card(priv);109. if(lbs_cfg_register(priv)110. 111. ret=register_netdev(priv-dev);112. err=register_netdevice(dev);113. 114. 115. /具体的wifi设备驱动功能116. /网络设备操作的具体函数117. staticconststructnet_device_opslbs_netdev_ops=118. .ndo

36、_open=lbs_dev_open,/打开119. .ndo_stop=lbs_eth_stop,/停止120. .ndo_start_xmit=lbs_hard_start_xmit,/开始发送数据121. .ndo_set_mac_address=lbs_set_mac_address,/设置mac地址122. .ndo_tx_timeout=lbs_tx_timeout,/发送超时123. .ndo_set_multicast_list=lbs_set_multicast_list,/多播地址124. .ndo_change_mtu=eth_change_mtu,/最大传输单元125.

37、 .ndo_validate_addr=eth_validate_addr,/判断地址的有效性3、数据的接收,通过中断的方式来解决 网络设备接收数据的主要方法是由中断引发设备的中断处理函数,中断处理函数判断中断的类型,如果为接收中断,则读取接收到的数据,分配sk_buff数据结构和数据缓冲区,并将接收的数据复制到数据缓存区,并调用netif_rx()函数将sk_buff传递给上层协议。 搜索if_sdio_interrupt,可知道它是在文件中if_sdio_probe()函数中sdio_claim_irq(func, if_sdio_interrupt) ,func-irq_handler

38、= if_sdio_interrupt。当s3cmci_irq中断处理函数的S3C2410_SDIIMSK_SDIOIRQ 中断被触发时将调用if_sdio_interrupt()函数,进行接收数据。cppview plaincopy1. staticvoidif_sdio_interrupt(structsdio_func*func)2. 3. ret=if_sdio_card_to_host(card);/从无线网卡接收到数据或者说是上报数据4. /读取端口上的数据,放到card的buffer中5. ret=sdio_readsb(card-func,card-buffer,card-io

39、port,chunk);6. 1.在这里一方面处理中断还有27. switch(type)/处理cmddataevent的请求8. caseMVMS_CMD:9. ret=if_sdio_handle_cmd(card,card-buffer+4,chunk-4);/处理申请的命令中断10. if(ret)11. gotoout;12. break;13. caseMVMS_DAT:14. ret=if_sdio_handle_data(card,card-buffer+4,chunk-4);/处理申请的数据中断15. if(ret)16. gotoout;17. break;18. caseMVMS_EVENT:19. ret=if_sdio_handle_event(card,card-b

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com