Linux 下wifi 驅(qū)動開發(fā)—— SDIO接口WiFi驅(qū)動淺析_第1頁
Linux 下wifi 驅(qū)動開發(fā)—— SDIO接口WiFi驅(qū)動淺析_第2頁
Linux 下wifi 驅(qū)動開發(fā)—— SDIO接口WiFi驅(qū)動淺析_第3頁
Linux 下wifi 驅(qū)動開發(fā)—— SDIO接口WiFi驅(qū)動淺析_第4頁
Linux 下wifi 驅(qū)動開發(fā)—— SDIO接口WiFi驅(qū)動淺析_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、-作者xxxx-日期xxxxLinux 下wifi 驅(qū)動開發(fā) SDIO接口WiFi驅(qū)動淺析【精品文檔】Linux 下wifi 驅(qū)動開發(fā)(三) SDIO接口WiFi驅(qū)動淺析 SDIO-Wifi模塊是基于SDIO接口的符合wifi無線網(wǎng)絡(luò)標準的嵌入式模塊,內(nèi)置無線網(wǎng)絡(luò)協(xié)議協(xié)議棧以及TCP/IP協(xié)議棧,能夠?qū)崿F(xiàn)用戶主平臺數(shù)據(jù)通過SDIO口到無線網(wǎng)絡(luò)之間的轉(zhuǎn)換。SDIO具有傳輸數(shù)據(jù)快,兼容SD、MMC接口等特點。 對于SDIO接口的wifi,首先,它是一個sdio的卡的設(shè)備,然后具備了wifi的功能,所以,注冊的時候還是先以sdio的卡的設(shè)備去注冊的。然后檢測到卡之后就要驅(qū)動他的wifi功能了,顯然,

2、他是用sdio的協(xié)議,通過發(fā)命令和數(shù)據(jù)來控制的。下面先簡單回顧一下SDIO的相關(guān)知識:一、SDIO相關(guān)基礎(chǔ)知識解析1、SDIO接口 SDIO故名思義,就是SD 的 I/O 接口(interface)的意思,不過這樣解釋可能還有點抽像。更具體的說明,SD 本來是記憶卡的標準,但是現(xiàn)在也可以把 SD 拿來插上一些外圍接口使用,這樣的技術(shù)便是 SDIO。 所以 SDIO 本身是一種相當單純的技術(shù),透過 SD 的 I/O 接腳來連接外部外圍,并且透過 SD 上的 I/O 數(shù)據(jù)接位與這些外圍傳輸數(shù)據(jù),而且 SD 協(xié)會會員也推出很完整的 SDIO stack 驅(qū)動程序,使得 SDIO 外圍(我們稱為SDI

3、O 卡)的開發(fā)與應(yīng)用變得相當熱門。 現(xiàn)在已經(jīng)有非常多的手機或是手持裝置都支持 SDIO 的功能(SD 標準原本就是針對 mobile device 而制定),而且許多 SDIO 外圍也都被開發(fā)出來,讓手機外接外圍更加容易,并且開發(fā)上更有彈性(不需要內(nèi)建外圍)。目前常見的 SDIO 外圍(SDIO 卡)有: Wi-Fi card(無線網(wǎng)絡(luò)卡) CMOS sensor card(照相模塊) GPS card GSM/GPRS modem card Bluetooth card SDIO 的應(yīng)用將是未來嵌入式系統(tǒng)最重要的接口技術(shù)之一,并且也會取代目前 GPIO 式的 SPI 接口。2、SDIO總線

4、SDIO總線 和 USB總線 類似,SDIO也有兩端,其中一端是HOST端,另一端是device端。所有的通信都是由HOST端 發(fā)送 命令 開始的,Device端只要能解析命令,就可以相互通信。CLK信號:HOST給DEVICE的 時鐘信號,每個時鐘周期傳輸一個命令。CMD信號:雙向 的信號,用于傳送 命令 和 反應(yīng)。DAT0-DAT3 信號:四條用于傳送的數(shù)據(jù)線。VDD信號:電源信號。VSS1,VSS2:電源地信號。3、SDIO熱插拔原理方法:設(shè)置一個定時器檢查或插拔中斷檢測硬件:假如GPG10(EINT18)用于SD卡檢測GPG10 為高電平 即沒有插入SD卡GPG10為低電平 即插入了S

5、D卡4、SDIO命令 SDIO總線上都是HOST端發(fā)起請求,然后DEVICE端回應(yīng)請求。sdio命令由6個字節(jié)組成。a - Command:用于開始傳輸?shù)拿睿怯蒆OST端發(fā)往DEVICE端的。其中命令是通過CMD信號線傳送的。b - Response:回應(yīng)是DEVICE返回的HOST的命令,作為Command的回應(yīng)。也是通過CMD線傳送的。c - Data:數(shù)據(jù)是雙向的傳送的??梢栽O(shè)置為1線模式,也可以設(shè)置為4線模式。數(shù)據(jù)是通過DAT0-DAT3信號線傳輸?shù)摹?SDIO的每次操作都是由HOST在CMD線上發(fā)起一個CMD,對于有的CMD,DEVICE需要返回Response,有的則不需要。

6、對于讀命令,首先HOST會向DEVICE發(fā)送命令,緊接著DEVICE會返回一個握手信號,此時,當HOST收到回應(yīng)的握手信號后,會將數(shù)據(jù)放在4位的數(shù)據(jù)線上,在傳送數(shù)據(jù)的同時會跟隨著CRC校驗碼。當整個讀傳送完畢后,HOST會再次發(fā)送一個命令,通知DEVICE操作完畢,DEVICE同時會返回一個響應(yīng)。 對于寫命令,首先HOST會向DEVICE發(fā)送命令,緊接著DEVICE會返回一個握手信號,此時,當HOST收到回應(yīng)的握手信號后,會將數(shù)據(jù)放在4位的數(shù)據(jù)線上,在傳送數(shù)據(jù)的同時會跟隨著CRC校驗碼。當整個寫傳送完畢后,HOST會再次發(fā)送一個命令,通知DEVICE操作完畢,DEVICE同時會返回一個響應(yīng)。二

7、、SDIO接口驅(qū)動 前面講到,SDIO接口的wifi,首先,它是一個sdio的卡的設(shè)備,然后具備了wifi的功能,所以SDIO接口的WiFi驅(qū)動就是在wifi驅(qū)動外面套上了一個SDIO驅(qū)動的外殼,SDIO驅(qū)動仍然符合設(shè)備驅(qū)動的分層與分離思想: 設(shè)備驅(qū)動層(wifi 設(shè)備) |核心層(向上向下提供接口) |主機驅(qū)動層 (實現(xiàn)SDIO驅(qū)動) 下面先分析SDIO接口驅(qū)動的實現(xiàn),看幾個重要的數(shù)據(jù)結(jié)構(gòu)(用于核心層與主機驅(qū)動層 的數(shù)據(jù)交換處理)。 /include/linux/mmc/ struct mmc_host 用來描述卡控制器struct mmc_card 用來描述卡struct mmc_driv

8、er 用來描述 mmc 卡驅(qū)動struct sdio_func 用來描述 功能設(shè)備struct mmc_host_ops 用來描述卡控制器操作接口函數(shù)功能,用于從 主機控制器層向 core 層注冊操作函數(shù),從而將core 層與具體的主機控制器隔離。也就是說 core 要操作主機控制器,就用這個 ops 當中給的函數(shù)指針操作,不能直接調(diào)用具體主控制器的函數(shù)。 HOST層驅(qū)動分析在 前面的系列文章中Linux SD卡驅(qū)動開發(fā)(二) SD 卡驅(qū)動分析HOST篇有詳細闡述,下面只簡單回顧一下一些重要函數(shù)處理1、編寫Host層驅(qū)動 這里參考的是S3C24XX的HOST驅(qū)動程序 /drivers/mmc/

9、host/s3cmci.ccppview plaincopy1. staticstructplatform_drivers3cmci_driver=2. .driver=3. .name=s3c-sdi,/名稱和平臺設(shè)備定義中的對應(yīng)4. .owner=THIS_MODULE,5. .pm=s3cmci_pm_ops,6. ,7. .id_table=s3cmci_driver_ids,8. .probe=s3cmci_probe,/平臺設(shè)備探測接口函數(shù)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結(jié)構(gòu)體18. 19. /.20. 21. 22. /*注冊中斷處理函數(shù)s3cmci_irq,來處理數(shù)據(jù)收發(fā)過程引起的各種中斷*/23. request_irq(host-irq,s3cmci_irq,0,DRIVER_NAME,host)/注冊中斷處理函數(shù)s3cmci_irq24. 25. /*

11、注冊中斷處理s3cmci_irq_cd函數(shù),來處理熱撥插引起的中斷,中斷觸發(fā)的形式為上升沿、下降沿觸發(fā)*/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驅(qū)動29. -device_add(&host-class_dev);/添加設(shè)備到mmc_bus_type總線上的設(shè)備鏈表中30. -mmc_start_host(h

12、ost);/啟動mmchost31. 32. /*MMCdriversshouldcallthiswhentheydetectacardhasbeeninsertedorremoved.檢測sd卡是否插上或移除*/33. -mmc_detect_change(host,0);34. 35. /*ScheduledelayedworkintheMMCworkqueue.調(diào)度延時工作隊列*/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)循環(huán)中調(diào)用schedule切換出自己,當占用mmc控制器的操作完成之后,執(zhí)行*mmc_release_host()的時候,會激活登記到等待隊列&host-wq中的其他

14、程序獲得mmc主控制器的使用權(quán)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與總線上的驅(qū)動匹配,就初始化card*/29. mmc_sdio_init_card(host,host-ocr,NULL,0);30. -card=mmc_alloc_card(host,NULL);/分配一個card結(jié)構(gòu)體31. mmc_set_bus_mode(host,M

16、MC_BUSMODE_PUSHPULL);/設(shè)置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功能設(shè)備)結(jié)構(gòu)體37. mmc_io_rw_direct();38. card-sdio_funcfn-1=func;39. 40. mmc_add_card(host-card);/將具體的sdio設(shè)

17、備掛載到mmc_bus_types總線41. sdio_add_func(host-card-sdio_funci);/將sdio功能設(shè)備掛載到sdio_bus_types總線這里一系列函數(shù)調(diào)用在前面的SD驅(qū)動蚊帳中已經(jīng)闡述過了,不再詳細闡述2、SDIO設(shè)備的熱插拔 當插拔SDIO設(shè)備,會觸發(fā)中斷通知到CPU,然后執(zhí)行卡檢測中斷處理函數(shù)在這個中斷服務(wù)函數(shù)中,mmc_detect_change-mmc_schedule_delayed_work(&host-detect,delay), INIT_DELAYED_WORK(&host-detect, mmc_rescan)會調(diào)度mmc_resca

18、n函數(shù)延時調(diào)度工作隊列,這樣也會觸發(fā)SDIO設(shè)備的初始化流程,檢測到有效的SDIO設(shè)備后,會將它注冊到系統(tǒng)中去。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 驅(qū)動部分解析wifi驅(qū)動的通用的軟件架構(gòu)1. 分為兩部分

19、,上面為主機端驅(qū)動,下面是我們之前所說的firmware2. 其中固件部分的主要工作是:因為天線接受和發(fā)送回來的都是幀的幀,而主機接受和傳送出來的數(shù)據(jù)都必須是的幀,所以必須由firmware來負責的幀和幀之間的轉(zhuǎn)換3. 當天線收到數(shù)據(jù),并被firmware處理好后會放在一個buffer里,并產(chǎn)生一個中斷,主機在收到中斷后就去讀這個buffer。 SDIO設(shè)備的驅(qū)動由sdio_driver結(jié)構(gòu)體定義,sdio_driver其實是driver的封裝。通過sdio_register_driver函數(shù)將SDIO設(shè)備驅(qū)動加載進內(nèi)核,其實就是掛載到sdio_bus_type總線上去。1、設(shè)備驅(qū)動的注冊與匹

20、配Drivers/net/wireless/libertas/cppview plaincopy1. /*SDIOfunctiondevicedriver*/2. 3. structsdio_driver4. char*name;/設(shè)備名5. conststructsdio_device_id*id_table;/設(shè)備驅(qū)動ID6. int(*probe)(structsdio_func*,conststructsdio_device_id*);/匹配函數(shù)7. void(*remove)(structsdio_func*);8. structdevice_driverdrv;9. ;下面是具體函

21、數(shù)的填充:cppview plaincopy1. /*/2. 3. staticstructsdio_driverif_sdio_driver=4. .name=libertas_sdio,5. .id_table=if_sdio_ids,/用于設(shè)備與驅(qū)動的匹配6. .probe=if_sdio_probe,7. .remove=if_sdio_remove,8. .drv=9. .pm=&if_sdio_pm_ops,10. 11. ;設(shè)備注冊函數(shù)cppview plaincopy1. /*2. *sdio_register_driver-registerafunctiondriver3.

22、*drv:SDIOfunctiondriver4. */5. 6. intsdio_register_driver(structsdio_driver*drv)7. 8. =drv-name;9. drv-drv.bus=&sdio_bus_type;/設(shè)置driver的bus為sdio_bus_type10. returndriver_register(&drv-drv);11. 總線函數(shù)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. ;注意:設(shè)備或者驅(qū)動注冊到系統(tǒng)中的過程中,都會調(diào)用相應(yīng)bus上的匹配函數(shù)來進行匹配合適的驅(qū)動或者設(shè)備,對于sdio設(shè)備的匹配是由sdio_bus_match和sdio_bus_probe函數(shù)來完成。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設(shè)備驅(qū)動中id,來匹配合適的驅(qū)動或設(shè)備。最終會調(diào)用.probe函數(shù),來完成相關(guān)操作。2、If_sdio_probe函數(shù) 當檢測到sdio卡插入了之后就會調(diào)用If_sdio_probe,而當卡被移除后就會調(diào)用If_sdio_remove。下面先看下If_sdio_probet函數(shù),if_sdio_prob 函數(shù) 主要做了兩件事 cppv

26、iew plaincopy1. staticstructsdio_driverif_sdio_driver=2. .name=libertas_sdio,3. .id_table=if_sdio_ids,/用于設(shè)備和驅(qū)動的匹配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的結(jié)構(gòu)體13. structif_sdio_card*card;14. structif_sdio_packet*packet;/sdio

27、包的結(jié)構(gòu)體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的設(shè)備24. caseMODEL_8686:25. card-scratch_reg=IF_SDIO_SCRATCH;26. 27. 28. /創(chuàng)建sdio的工作隊列29. ca

28、rd-workqueue=create_workqueue(libertas_sdio);30. /調(diào)用下面的函數(shù)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的中斷當有數(shù)據(jù),命令或者是事件的時間執(zhí)行中斷55. ret=

30、sdio_claim_irq(func,if_sdio_interrupt);56. ret=if_sdio_card_to_host(card);/從無線網(wǎng)卡接收到數(shù)據(jù)或者說是上報數(shù)據(jù)57. ret=if_sdio_handle_data(card,card-buffer+4,chunk-4);/接收數(shù)據(jù)的處理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、 /添加網(wǎng)絡(luò)結(jié)構(gòu)體分配設(shè)備并注冊63. priv=lbs_add_card(card,&func-dev);64. 65. /分配Ethernet設(shè)備并注冊66. wdev=lbs_cfg_alloc(dmdev);67. /802無線網(wǎng)的具體的操作函數(shù)68. wdev-wiphy=wiphy_new(&lbs_cfg80211_ops,sizeof(structlbs_private);69. 70. 71. /分配網(wǎng)絡(luò)設(shè)備是整個網(wǎng)絡(luò)部分操作的72. /的核心結(jié)構(gòu)體73. dev=alloc_netdev(0,wlan%d,ether_setup);/實例化wlan0的屬性74. dev-i

32、eee80211_ptr=wdev;75. dev-ml_priv=priv;76. /設(shè)置設(shè)備的物理地址77. SET_NETDEV_DEV(dev,dmdev);78. wdev-netdev=dev;79. priv-dev=dev;80. /初始化網(wǎng)絡(luò)設(shè)備ops.看門狗81. dev-netdev_ops=&lbs_netdev_ops;/網(wǎng)絡(luò)設(shè)備的具體的操作函數(shù)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. /啟動一個內(nèi)核線程來管理這個網(wǎng)絡(luò)設(shè)備的數(shù)據(jù)發(fā)送,事件的處理(卡的拔出)和一些命令的處理89. priv-main_thread=kthread_run(lbs_thread,dev,lbs_main);90. /初始化相關(guān)的工作隊列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. /設(shè)置私有變量100. /設(shè)置主機發(fā)送數(shù)據(jù)到卡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. /啟動卡設(shè)備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設(shè)備驅(qū)動功能116. /網(wǎng)絡(luò)設(shè)備操作的具體函數(shù)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,/開始發(fā)送數(shù)據(jù)121. .ndo_set_mac_address=lbs_set_mac_address,/設(shè)置mac地址122. .ndo_tx_timeout=lbs_tx_timeout,/發(fā)送超時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、數(shù)據(jù)的接收,通過中斷的方式來解決 網(wǎng)絡(luò)設(shè)備接收數(shù)據(jù)的主要方法是由中斷引發(fā)設(shè)備的中斷處理函數(shù),中斷處理函數(shù)判斷中斷的類型,如果為接收中斷,則讀取接收到的數(shù)據(jù),分配sk_buff數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)緩沖區(qū),并將接收的數(shù)據(jù)復(fù)制到數(shù)據(jù)緩存區(qū),并調(diào)用netif_rx()函數(shù)將sk_buff傳遞給上層協(xié)議。 搜索if_sdio_interrupt,可知道它是在文件中if_sdio_probe()函數(shù)中sdio_claim_irq(func, if_sdio_interrupt) ,func-irq_handler

38、= if_sdio_interrupt。當s3cmci_irq中斷處理函數(shù)的S3C2410_SDIIMSK_SDIOIRQ 中斷被觸發(fā)時將調(diào)用if_sdio_interrupt()函數(shù),進行接收數(shù)據(jù)。cppview plaincopy1. staticvoidif_sdio_interrupt(structsdio_func*func)2. 3. ret=if_sdio_card_to_host(card);/從無線網(wǎng)卡接收到數(shù)據(jù)或者說是上報數(shù)據(jù)4. /讀取端口上的數(shù)據(jù),放到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);/處理申請的數(shù)據(jù)中斷15. if(ret)16. gotoout;17. break;18. case

40、MVMS_EVENT:19. ret=if_sdio_handle_event(card,card-buffer+4,chunk-4);/處理申請的事件中斷20. 21. /讀取包的過程22. lbs_process_rxed_packet(card-priv,skb);23. 24. /如果是中斷,就把skb這個包提交給協(xié)議層,這個函數(shù)是25. /協(xié)議層提供的netif_rx(skb)26. if(in_interrupt()27. netif_rx(skb);/提交給協(xié)議層28. 29. 30. 2/讀取端口上的數(shù)據(jù),放到card的buffer中31. ret=sdio_readsb(ca

41、rd-func,card-buffer,card-ioport,chunk);32. /讀取地址,目的地址,數(shù)量等33. intsdio_readsb(structsdio_func*func,void*dst,unsignedintaddr,intcount)34. 35. returnsdio_io_rw_ext_helper(func,0,addr,0,dst,count);36. 37. ret=mmc_io_rw_extended(func-card,write,func-num,addr,incr_addr,buf,blocks,func-cur_blksize);38. cmd.

42、arg=write?0x80000000:0x00000000;39. 40. /waitforrequest41. mmc_wait_for_req(card-host,&mrq);42. 開始應(yīng)答43. mmc_start_request(host,mrq);44. wait_for_completion(&complete);45. 46. host-ops-request(host,mrq);4、數(shù)據(jù)發(fā)送cppview plaincopy1. /IP層通過dev_queue_xmit()將數(shù)據(jù)交給網(wǎng)絡(luò)設(shè)備協(xié)議接口層,網(wǎng)絡(luò)接口層通過netdevice中的注冊函數(shù)的數(shù)據(jù)發(fā)送函數(shù)2. int

43、dev_queue_xmit(structsk_buff*skb)3. 4. if(!netif_tx_queue_stopped(txq)5. _this_cpu_inc(xmit_recursion);6. /設(shè)備硬件開始發(fā)送7. rc=dev_hard_start_xmit(skb,dev,txq);8. /調(diào)用wifi網(wǎng)絡(luò)中的ops9. 10. rc=ops-ndo_start_xmit(skb,dev);11. 12. dev-netdev_ops=&lbs_netdev_ops;/設(shè)備的操作函數(shù)13. 14. /處理sdiofirware數(shù)據(jù)和內(nèi)核的數(shù)據(jù)main_thread主線程15. priv-main_thread=kthread_run(lbs_thread,dev,lbs_main);16. 17. /調(diào)用host

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論