dhd_sdio.c 160 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825
  1. /*
  2. * DHD Bus Module for SDIO
  3. *
  4. * Copyright (C) 1999-2010, Broadcom Corporation
  5. *
  6. * Unless you and Broadcom execute a separate written software license
  7. * agreement governing use of this software, this software is licensed to you
  8. * under the terms of the GNU General Public License version 2 (the "GPL"),
  9. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  10. * following added to such license:
  11. *
  12. * As a special exception, the copyright holders of this software give you
  13. * permission to link this software with independent modules, and to copy and
  14. * distribute the resulting executable under terms of your choice, provided that
  15. * you also meet, for each linked independent module, the terms and conditions of
  16. * the license of that module. An independent module is a module which is not
  17. * derived from this software. The special exception does not apply to any
  18. * modifications of the software.
  19. *
  20. * Notwithstanding the above, under no circumstances may you combine this
  21. * software in any way with any other Broadcom software provided under a license
  22. * other than the GPL, without Broadcom's express prior written consent.
  23. *
  24. * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.129.4.1 2010/09/02 23:13:16 Exp $
  25. */
  26. #include <typedefs.h>
  27. #include <osl.h>
  28. #include <bcmsdh.h>
  29. #ifdef BCMEMBEDIMAGE
  30. #include BCMEMBEDIMAGE
  31. #endif /* BCMEMBEDIMAGE */
  32. #include <bcmdefs.h>
  33. #include <bcmutils.h>
  34. #include <bcmendian.h>
  35. #include <bcmdevs.h>
  36. #include <siutils.h>
  37. #include <hndpmu.h>
  38. #include <hndsoc.h>
  39. #include <sbchipc.h>
  40. #include <sbhnddma.h>
  41. #include <sdio.h>
  42. #include <sbsdio.h>
  43. #include <sbsdpcmdev.h>
  44. #include <bcmsdpcm.h>
  45. #include <proto/ethernet.h>
  46. #include <proto/802.1d.h>
  47. #include <proto/802.11.h>
  48. #include <dngl_stats.h>
  49. #include <dhd.h>
  50. #include <dhd_bus.h>
  51. #include <dhd_proto.h>
  52. #include <dhd_dbg.h>
  53. #include <dhdioctl.h>
  54. #include <sdiovar.h>
  55. #ifdef DHD_DEBUG
  56. #include <hndrte_cons.h>
  57. #endif /* DHD_DEBUG */
  58. #ifdef DHD_DEBUG_TRAP
  59. #include <hndrte_armtrap.h>
  60. #endif /* DHD_DEBUG_TRAP */
  61. #define QLEN 256 /* bulk rx and tx queue lengths */
  62. #define FCHI (QLEN - 10)
  63. #define FCLOW (FCHI / 2)
  64. #define PRIOMASK 7
  65. #define TXRETRIES 2 /* # of retries for tx frames */
  66. #if defined(CONFIG_MACH_SANDGATE2G)
  67. #define DHD_RXBOUND 250 /* Default for max rx frames in one scheduling */
  68. #else
  69. #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */
  70. #endif /* defined(CONFIG_MACH_SANDGATE2G) */
  71. #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
  72. #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
  73. #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
  74. #define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold biggest possible glom */
  75. /* Packet alignment for most efficient SDIO (can change based on platform) */
  76. #ifndef DHD_SDALIGN
  77. #define DHD_SDALIGN 32
  78. #endif
  79. #if !ISPOWEROF2(DHD_SDALIGN)
  80. #error DHD_SDALIGN is not a power of 2!
  81. #endif
  82. #ifndef DHD_FIRSTREAD
  83. #define DHD_FIRSTREAD 32
  84. #endif
  85. #if !ISPOWEROF2(DHD_FIRSTREAD)
  86. #error DHD_FIRSTREAD is not a power of 2!
  87. #endif
  88. /* Total length of frame header for dongle protocol */
  89. #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
  90. #ifdef SDTEST
  91. #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
  92. #else
  93. #define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN)
  94. #endif
  95. /* Space for header read, limit for data packets */
  96. #ifndef MAX_HDR_READ
  97. #define MAX_HDR_READ 32
  98. #endif
  99. #if !ISPOWEROF2(MAX_HDR_READ)
  100. #error MAX_HDR_READ is not a power of 2!
  101. #endif
  102. #define MAX_RX_DATASZ 2048
  103. /* Maximum milliseconds to wait for F2 to come up */
  104. #define DHD_WAIT_F2RDY 3000
  105. /* Bump up limit on waiting for HT to account for first startup;
  106. * if the image is doing a CRC calculation before programming the PMU
  107. * for HT availability, it could take a couple hundred ms more, so
  108. * max out at a 1 second (1000000us).
  109. */
  110. #if (PMU_MAX_TRANSITION_DLY < 1000000)
  111. #undef PMU_MAX_TRANSITION_DLY
  112. #define PMU_MAX_TRANSITION_DLY 1000000
  113. #endif
  114. /* Value for ChipClockCSR during initial setup */
  115. #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
  116. #define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
  117. /* Flags for SDH calls */
  118. #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
  119. /* Packet free applicable unconditionally for sdio and sdspi. Conditional if
  120. * bufpool was present for gspi bus.
  121. */
  122. #define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \
  123. PKTFREE(bus->dhd->osh, pkt, FALSE);
  124. DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
  125. extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
  126. extern void bcmsdh_set_irq(int flag);
  127. #ifdef DHD_DEBUG
  128. /* Device console log buffer state */
  129. typedef struct dhd_console {
  130. uint count; /* Poll interval msec counter */
  131. uint log_addr; /* Log struct address (fixed) */
  132. hndrte_log_t log; /* Log struct (host copy) */
  133. uint bufsize; /* Size of log buffer */
  134. uint8 *buf; /* Log buffer (host copy) */
  135. uint last; /* Last buffer read index */
  136. } dhd_console_t;
  137. #endif /* DHD_DEBUG */
  138. /* Private data for SDIO bus interaction */
  139. typedef struct dhd_bus {
  140. dhd_pub_t *dhd;
  141. bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */
  142. si_t *sih; /* Handle for SI calls */
  143. char *vars; /* Variables (from CIS and/or other) */
  144. uint varsz; /* Size of variables buffer */
  145. uint32 sbaddr; /* Current SB window pointer (-1, invalid) */
  146. sdpcmd_regs_t *regs; /* Registers for SDIO core */
  147. uint sdpcmrev; /* SDIO core revision */
  148. uint armrev; /* CPU core revision */
  149. uint ramrev; /* SOCRAM core revision */
  150. uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */
  151. uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
  152. uint32 bus; /* gSPI or SDIO bus */
  153. uint32 hostintmask; /* Copy of Host Interrupt Mask */
  154. uint32 intstatus; /* Intstatus bits (events) pending */
  155. bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
  156. bool fcstate; /* State of dongle flow-control */
  157. uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
  158. char *fw_path; /* module_param: path to firmware image */
  159. char *nv_path; /* module_param: path to nvram vars file */
  160. const char *nvram_params; /* user specified nvram params. */
  161. uint blocksize; /* Block size of SDIO transfers */
  162. uint roundup; /* Max roundup limit */
  163. struct pktq txq; /* Queue length used for flow-control */
  164. uint8 flowcontrol; /* per prio flow control bitmask */
  165. uint8 tx_seq; /* Transmit sequence number (next) */
  166. uint8 tx_max; /* Maximum transmit sequence allowed */
  167. uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
  168. uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
  169. uint16 nextlen; /* Next Read Len from last header */
  170. uint8 rx_seq; /* Receive sequence number (expected) */
  171. bool rxskip; /* Skip receive (awaiting NAK ACK) */
  172. void *glomd; /* Packet containing glomming descriptor */
  173. void *glom; /* Packet chain for glommed superframe */
  174. uint glomerr; /* Glom packet read errors */
  175. uint8 *rxbuf; /* Buffer for receiving control packets */
  176. uint rxblen; /* Allocated length of rxbuf */
  177. uint8 *rxctl; /* Aligned pointer into rxbuf */
  178. uint8 *databuf; /* Buffer for receiving big glom packet */
  179. uint8 *dataptr; /* Aligned pointer into databuf */
  180. uint rxlen; /* Length of valid data in buffer */
  181. uint8 sdpcm_ver; /* Bus protocol reported by dongle */
  182. bool intr; /* Use interrupts */
  183. bool poll; /* Use polling */
  184. bool ipend; /* Device interrupt is pending */
  185. bool intdis; /* Interrupts disabled by isr */
  186. uint intrcount; /* Count of device interrupt callbacks */
  187. uint lastintrs; /* Count as of last watchdog timer */
  188. uint spurious; /* Count of spurious interrupts */
  189. uint pollrate; /* Ticks between device polls */
  190. uint polltick; /* Tick counter */
  191. uint pollcnt; /* Count of active polls */
  192. #ifdef DHD_DEBUG
  193. dhd_console_t console; /* Console output polling support */
  194. uint console_addr; /* Console address from shared struct */
  195. #endif /* DHD_DEBUG */
  196. uint regfails; /* Count of R_REG/W_REG failures */
  197. uint clkstate; /* State of sd and backplane clock(s) */
  198. bool activity; /* Activity flag for clock down */
  199. int32 idletime; /* Control for activity timeout */
  200. int32 idlecount; /* Activity timeout counter */
  201. int32 idleclock; /* How to set bus driver when idle */
  202. int32 sd_divisor; /* Speed control to bus driver */
  203. int32 sd_mode; /* Mode control to bus driver */
  204. int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
  205. bool use_rxchain; /* If dhd should use PKT chains */
  206. bool sleeping; /* Is SDIO bus sleeping? */
  207. bool rxflow_mode; /* Rx flow control mode */
  208. bool rxflow; /* Is rx flow control on */
  209. uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */
  210. bool alp_only; /* Don't use HT clock (ALP only) */
  211. /* Field to decide if rx of control frames happen in rxbuf or lb-pool */
  212. bool usebufpool;
  213. #ifdef SDTEST
  214. /* external loopback */
  215. bool ext_loop;
  216. uint8 loopid;
  217. /* pktgen configuration */
  218. uint pktgen_freq; /* Ticks between bursts */
  219. uint pktgen_count; /* Packets to send each burst */
  220. uint pktgen_print; /* Bursts between count displays */
  221. uint pktgen_total; /* Stop after this many */
  222. uint pktgen_minlen; /* Minimum packet data len */
  223. uint pktgen_maxlen; /* Maximum packet data len */
  224. uint pktgen_mode; /* Configured mode: tx, rx, or echo */
  225. uint pktgen_stop; /* Number of tx failures causing stop */
  226. /* active pktgen fields */
  227. uint pktgen_tick; /* Tick counter for bursts */
  228. uint pktgen_ptick; /* Burst counter for printing */
  229. uint pktgen_sent; /* Number of test packets generated */
  230. uint pktgen_rcvd; /* Number of test packets received */
  231. uint pktgen_fail; /* Number of failed send attempts */
  232. uint16 pktgen_len; /* Length of next packet to send */
  233. #endif /* SDTEST */
  234. /* Some additional counters */
  235. uint tx_sderrs; /* Count of tx attempts with sd errors */
  236. uint fcqueued; /* Tx packets that got queued */
  237. uint rxrtx; /* Count of rtx requests (NAK to dongle) */
  238. uint rx_toolong; /* Receive frames too long to receive */
  239. uint rxc_errors; /* SDIO errors when reading control frames */
  240. uint rx_hdrfail; /* SDIO errors on header reads */
  241. uint rx_badhdr; /* Bad received headers (roosync?) */
  242. uint rx_badseq; /* Mismatched rx sequence number */
  243. uint fc_rcvd; /* Number of flow-control events received */
  244. uint fc_xoff; /* Number which turned on flow-control */
  245. uint fc_xon; /* Number which turned off flow-control */
  246. uint rxglomfail; /* Failed deglom attempts */
  247. uint rxglomframes; /* Number of glom frames (superframes) */
  248. uint rxglompkts; /* Number of packets from glom frames */
  249. uint f2rxhdrs; /* Number of header reads */
  250. uint f2rxdata; /* Number of frame data reads */
  251. uint f2txdata; /* Number of f2 frame writes */
  252. uint f1regdata; /* Number of f1 register accesses */
  253. uint8 *ctrl_frame_buf;
  254. uint32 ctrl_frame_len;
  255. bool ctrl_frame_stat;
  256. } dhd_bus_t;
  257. /* clkstate */
  258. #define CLK_NONE 0
  259. #define CLK_SDONLY 1
  260. #define CLK_PENDING 2 /* Not used yet */
  261. #define CLK_AVAIL 3
  262. #define DHD_NOPMU(dhd) (FALSE)
  263. #ifdef DHD_DEBUG
  264. static int qcount[NUMPRIO];
  265. static int tx_packets[NUMPRIO];
  266. #endif /* DHD_DEBUG */
  267. /* Deferred transmit */
  268. const uint dhd_deferred_tx = 1;
  269. extern uint dhd_watchdog_ms;
  270. extern void dhd_os_wd_timer(void *bus, uint wdtick);
  271. /* Tx/Rx bounds */
  272. uint dhd_txbound;
  273. uint dhd_rxbound;
  274. uint dhd_txminmax;
  275. /* override the RAM size if possible */
  276. #define DONGLE_MIN_MEMSIZE (128 *1024)
  277. int dhd_dongle_memsize;
  278. static bool dhd_doflow;
  279. static bool dhd_alignctl;
  280. static bool sd1idle;
  281. static bool retrydata;
  282. #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
  283. static const uint watermark = 8;
  284. static const uint firstread = DHD_FIRSTREAD;
  285. #define HDATLEN (firstread - (SDPCM_HDRLEN))
  286. /* Retry count for register access failures */
  287. static const uint retry_limit = 2;
  288. /* Force even SD lengths (some host controllers mess up on odd bytes) */
  289. static bool forcealign;
  290. #define ALIGNMENT 4
  291. #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
  292. extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
  293. #endif
  294. #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
  295. #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
  296. #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
  297. #define PKTALIGN(osh, p, len, align) \
  298. do { \
  299. uint datalign; \
  300. datalign = (uintptr)PKTDATA((osh), (p)); \
  301. datalign = ROUNDUP(datalign, (align)) - datalign; \
  302. ASSERT(datalign < (align)); \
  303. ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \
  304. if (datalign) \
  305. PKTPULL((osh), (p), datalign); \
  306. PKTSETLEN((osh), (p), (len)); \
  307. } while (0)
  308. /* Limit on rounding up frames */
  309. static const uint max_roundup = 512;
  310. /* Try doing readahead */
  311. static bool dhd_readahead;
  312. /* To check if there's window offered */
  313. #define DATAOK(bus) \
  314. (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
  315. (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
  316. /* Macros to get register read/write status */
  317. /* NOTE: these assume a local dhdsdio_bus_t *bus! */
  318. #define R_SDREG(regvar, regaddr, retryvar) \
  319. do { \
  320. retryvar = 0; \
  321. do { \
  322. regvar = R_REG(bus->dhd->osh, regaddr); \
  323. } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
  324. if (retryvar) { \
  325. bus->regfails += (retryvar-1); \
  326. if (retryvar > retry_limit) { \
  327. DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
  328. __FUNCTION__, __LINE__)); \
  329. regvar = 0; \
  330. } \
  331. } \
  332. } while (0)
  333. #define W_SDREG(regval, regaddr, retryvar) \
  334. do { \
  335. retryvar = 0; \
  336. do { \
  337. W_REG(bus->dhd->osh, regaddr, regval); \
  338. } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
  339. if (retryvar) { \
  340. bus->regfails += (retryvar-1); \
  341. if (retryvar > retry_limit) \
  342. DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
  343. __FUNCTION__, __LINE__)); \
  344. } \
  345. } while (0)
  346. #define DHD_BUS SDIO_BUS
  347. #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
  348. #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
  349. #define GSPI_PR55150_BAILOUT
  350. #ifdef SDTEST
  351. static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
  352. static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
  353. #endif
  354. #ifdef DHD_DEBUG_TRAP
  355. static int dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size);
  356. #endif /* DHD_DEBUG_TRAP */
  357. static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
  358. static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
  359. static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
  360. static void dhdsdio_disconnect(void *ptr);
  361. static bool dhdsdio_chipmatch(uint16 chipid);
  362. static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
  363. void * regsva, uint16 devid);
  364. static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
  365. static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
  366. static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, int reset_flag);
  367. static uint process_nvram_vars(char *varbuf, uint len);
  368. static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
  369. static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
  370. uint8 *buf, uint nbytes,
  371. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
  372. static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
  373. uint8 *buf, uint nbytes,
  374. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
  375. static bool dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh);
  376. static int _dhdsdio_download_firmware(struct dhd_bus *bus);
  377. static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
  378. static int dhdsdio_download_nvram(struct dhd_bus *bus);
  379. #ifdef BCMEMBEDIMAGE
  380. static int dhdsdio_download_code_array(struct dhd_bus *bus);
  381. #endif
  382. static void
  383. dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
  384. {
  385. int32 min_size = DONGLE_MIN_MEMSIZE;
  386. /* Restrict the memsize to user specified limit */
  387. DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
  388. dhd_dongle_memsize, min_size));
  389. if ((dhd_dongle_memsize > min_size) &&
  390. (dhd_dongle_memsize < (int32)bus->orig_ramsize))
  391. bus->ramsize = dhd_dongle_memsize;
  392. }
  393. static int
  394. dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
  395. {
  396. int err = 0;
  397. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
  398. (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
  399. if (!err)
  400. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
  401. (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
  402. if (!err)
  403. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
  404. (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
  405. return err;
  406. }
  407. /* Turn backplane clock on or off */
  408. static int
  409. dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
  410. {
  411. int err;
  412. uint8 clkctl, clkreq, devctl;
  413. bcmsdh_info_t *sdh;
  414. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  415. #if defined(OOB_INTR_ONLY)
  416. pendok = FALSE;
  417. #endif
  418. clkctl = 0;
  419. sdh = bus->sdh;
  420. if (on) {
  421. /* Request HT Avail */
  422. clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
  423. if ((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev == 0))
  424. clkreq |= SBSDIO_FORCE_ALP;
  425. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
  426. if (err) {
  427. DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
  428. return BCME_ERROR;
  429. }
  430. if (pendok &&
  431. ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) {
  432. uint32 dummy, retries;
  433. R_SDREG(dummy, &bus->regs->clockctlstatus, retries);
  434. }
  435. /* Check current status */
  436. clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  437. if (err) {
  438. DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
  439. return BCME_ERROR;
  440. }
  441. /* Go to pending and await interrupt if appropriate */
  442. if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
  443. /* Allow only clock-available interrupt */
  444. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  445. if (err) {
  446. DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
  447. __FUNCTION__, err));
  448. return BCME_ERROR;
  449. }
  450. devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
  451. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  452. DHD_INFO(("CLKCTL: set PENDING\n"));
  453. bus->clkstate = CLK_PENDING;
  454. return BCME_OK;
  455. } else if (bus->clkstate == CLK_PENDING) {
  456. /* Cancel CA-only interrupt filter */
  457. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  458. devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
  459. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  460. }
  461. /* Otherwise, wait here (polling) for HT Avail */
  462. if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
  463. SPINWAIT_SLEEP(sdioh_spinwait_sleep,
  464. ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  465. SBSDIO_FUNC1_CHIPCLKCSR, &err)),
  466. !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
  467. }
  468. if (err) {
  469. DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
  470. return BCME_ERROR;
  471. }
  472. if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
  473. DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
  474. __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
  475. return BCME_ERROR;
  476. }
  477. /* Mark clock available */
  478. bus->clkstate = CLK_AVAIL;
  479. DHD_INFO(("CLKCTL: turned ON\n"));
  480. #if defined(DHD_DEBUG)
  481. if (bus->alp_only == TRUE) {
  482. #if !defined(BCMLXSDMMC)
  483. if (!SBSDIO_ALPONLY(clkctl)) {
  484. DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
  485. }
  486. #endif /* !defined(BCMLXSDMMC) */
  487. } else {
  488. if (SBSDIO_ALPONLY(clkctl)) {
  489. DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
  490. }
  491. }
  492. #endif /* defined (DHD_DEBUG) */
  493. bus->activity = TRUE;
  494. } else {
  495. clkreq = 0;
  496. if (bus->clkstate == CLK_PENDING) {
  497. /* Cancel CA-only interrupt filter */
  498. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  499. devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
  500. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  501. }
  502. bus->clkstate = CLK_SDONLY;
  503. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
  504. DHD_INFO(("CLKCTL: turned OFF\n"));
  505. if (err) {
  506. DHD_ERROR(("%s: Failed access turning clock off: %d\n",
  507. __FUNCTION__, err));
  508. return BCME_ERROR;
  509. }
  510. }
  511. return BCME_OK;
  512. }
  513. /* Change idle/active SD state */
  514. static int
  515. dhdsdio_sdclk(dhd_bus_t *bus, bool on)
  516. {
  517. int err;
  518. int32 iovalue;
  519. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  520. if (on) {
  521. if (bus->idleclock == DHD_IDLE_STOP) {
  522. /* Turn on clock and restore mode */
  523. iovalue = 1;
  524. err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
  525. &iovalue, sizeof(iovalue), TRUE);
  526. if (err) {
  527. DHD_ERROR(("%s: error enabling sd_clock: %d\n",
  528. __FUNCTION__, err));
  529. return BCME_ERROR;
  530. }
  531. iovalue = bus->sd_mode;
  532. err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
  533. &iovalue, sizeof(iovalue), TRUE);
  534. if (err) {
  535. DHD_ERROR(("%s: error changing sd_mode: %d\n",
  536. __FUNCTION__, err));
  537. return BCME_ERROR;
  538. }
  539. } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
  540. /* Restore clock speed */
  541. iovalue = bus->sd_divisor;
  542. err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
  543. &iovalue, sizeof(iovalue), TRUE);
  544. if (err) {
  545. DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
  546. __FUNCTION__, err));
  547. return BCME_ERROR;
  548. }
  549. }
  550. bus->clkstate = CLK_SDONLY;
  551. } else {
  552. /* Stop or slow the SD clock itself */
  553. if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
  554. DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
  555. __FUNCTION__, bus->sd_divisor, bus->sd_mode));
  556. return BCME_ERROR;
  557. }
  558. if (bus->idleclock == DHD_IDLE_STOP) {
  559. if (sd1idle) {
  560. /* Change to SD1 mode and turn off clock */
  561. iovalue = 1;
  562. err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
  563. &iovalue, sizeof(iovalue), TRUE);
  564. if (err) {
  565. DHD_ERROR(("%s: error changing sd_clock: %d\n",
  566. __FUNCTION__, err));
  567. return BCME_ERROR;
  568. }
  569. }
  570. iovalue = 0;
  571. err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
  572. &iovalue, sizeof(iovalue), TRUE);
  573. if (err) {
  574. DHD_ERROR(("%s: error disabling sd_clock: %d\n",
  575. __FUNCTION__, err));
  576. return BCME_ERROR;
  577. }
  578. } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
  579. /* Set divisor to idle value */
  580. iovalue = bus->idleclock;
  581. err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
  582. &iovalue, sizeof(iovalue), TRUE);
  583. if (err) {
  584. DHD_ERROR(("%s: error changing sd_divisor: %d\n",
  585. __FUNCTION__, err));
  586. return BCME_ERROR;
  587. }
  588. }
  589. bus->clkstate = CLK_NONE;
  590. }
  591. return BCME_OK;
  592. }
  593. /* Transition SD and backplane clock readiness */
  594. static int
  595. dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
  596. {
  597. int ret = BCME_OK;
  598. #ifdef DHD_DEBUG
  599. uint oldstate = bus->clkstate;
  600. #endif /* DHD_DEBUG */
  601. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  602. /* Early exit if we're already there */
  603. if (bus->clkstate == target) {
  604. if (target == CLK_AVAIL) {
  605. dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
  606. bus->activity = TRUE;
  607. }
  608. return ret;
  609. }
  610. switch (target) {
  611. case CLK_AVAIL:
  612. /* Make sure SD clock is available */
  613. if (bus->clkstate == CLK_NONE)
  614. dhdsdio_sdclk(bus, TRUE);
  615. /* Now request HT Avail on the backplane */
  616. ret = dhdsdio_htclk(bus, TRUE, pendok);
  617. if (ret == BCME_OK) {
  618. dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
  619. bus->activity = TRUE;
  620. }
  621. break;
  622. case CLK_SDONLY:
  623. /* Remove HT request, or bring up SD clock */
  624. if (bus->clkstate == CLK_NONE)
  625. ret = dhdsdio_sdclk(bus, TRUE);
  626. else if (bus->clkstate == CLK_AVAIL)
  627. ret = dhdsdio_htclk(bus, FALSE, FALSE);
  628. else
  629. DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
  630. bus->clkstate, target));
  631. if (ret == BCME_OK)
  632. dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
  633. break;
  634. case CLK_NONE:
  635. /* Make sure to remove HT request */
  636. if (bus->clkstate == CLK_AVAIL)
  637. ret = dhdsdio_htclk(bus, FALSE, FALSE);
  638. /* Now remove the SD clock */
  639. ret = dhdsdio_sdclk(bus, FALSE);
  640. dhd_os_wd_timer(bus->dhd, 0);
  641. break;
  642. }
  643. #ifdef DHD_DEBUG
  644. DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
  645. #endif /* DHD_DEBUG */
  646. return ret;
  647. }
  648. int
  649. dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
  650. {
  651. bcmsdh_info_t *sdh = bus->sdh;
  652. sdpcmd_regs_t *regs = bus->regs;
  653. uint retries = 0;
  654. DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
  655. (sleep ? "SLEEP" : "WAKE"),
  656. (bus->sleeping ? "SLEEP" : "WAKE")));
  657. /* Done if we're already in the requested state */
  658. if (sleep == bus->sleeping)
  659. return BCME_OK;
  660. /* Going to sleep: set the alarm and turn off the lights... */
  661. if (sleep) {
  662. /* Don't sleep if something is pending */
  663. if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
  664. return BCME_BUSY;
  665. /* Disable SDIO interrupts (no longer interested) */
  666. bcmsdh_intr_disable(bus->sdh);
  667. /* Make sure the controller has the bus up */
  668. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  669. /* Tell device to start using OOB wakeup */
  670. W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
  671. if (retries > retry_limit)
  672. DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
  673. /* Turn off our contribution to the HT clock request */
  674. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  675. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  676. SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
  677. /* Isolate the bus */
  678. if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) {
  679. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
  680. SBSDIO_DEVCTL_PADS_ISO, NULL);
  681. }
  682. /* Change state */
  683. bus->sleeping = TRUE;
  684. } else {
  685. /* Waking up: bus power up is ok, set local state */
  686. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  687. 0, NULL);
  688. /* Force pad isolation off if possible (in case power never toggled) */
  689. if ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev >= 10))
  690. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
  691. /* Make sure the controller has the bus up */
  692. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  693. /* Send misc interrupt to indicate OOB not needed */
  694. W_SDREG(0, &regs->tosbmailboxdata, retries);
  695. if (retries <= retry_limit)
  696. W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
  697. if (retries > retry_limit)
  698. DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
  699. /* Make sure we have SD bus access */
  700. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  701. /* Change state */
  702. bus->sleeping = FALSE;
  703. /* Enable interrupts again */
  704. if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
  705. bus->intdis = FALSE;
  706. bcmsdh_intr_enable(bus->sdh);
  707. }
  708. }
  709. return BCME_OK;
  710. }
  711. #if defined(OOB_INTR_ONLY)
  712. void
  713. dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
  714. {
  715. #if defined(HW_OOB)
  716. bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
  717. #else
  718. sdpcmd_regs_t *regs = bus->regs;
  719. uint retries = 0;
  720. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  721. if (enable == TRUE) {
  722. /* Tell device to start using OOB wakeup */
  723. W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
  724. if (retries > retry_limit)
  725. DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
  726. } else {
  727. /* Send misc interrupt to indicate OOB not needed */
  728. W_SDREG(0, &regs->tosbmailboxdata, retries);
  729. if (retries <= retry_limit)
  730. W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
  731. }
  732. /* Turn off our contribution to the HT clock request */
  733. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  734. #endif /* !defined(HW_OOB) */
  735. }
  736. #endif /* defined(OOB_INTR_ONLY) */
  737. #define BUS_WAKE(bus) \
  738. do { \
  739. if ((bus)->sleeping) \
  740. dhdsdio_bussleep((bus), FALSE); \
  741. } while (0);
  742. /* Writes a HW/SW header into the packet and sends it. */
  743. /* Assumes: (a) header space already there, (b) caller holds lock */
  744. static int
  745. dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
  746. {
  747. int ret;
  748. osl_t *osh;
  749. uint8 *frame;
  750. uint16 len, pad = 0;
  751. uint32 swheader;
  752. uint retries = 0;
  753. bcmsdh_info_t *sdh;
  754. void *new;
  755. int i;
  756. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  757. sdh = bus->sdh;
  758. osh = bus->dhd->osh;
  759. if (bus->dhd->dongle_reset) {
  760. ret = BCME_NOTREADY;
  761. goto done;
  762. }
  763. frame = (uint8*)PKTDATA(osh, pkt);
  764. /* Add alignment padding, allocate new packet if needed */
  765. if ((pad = ((uintptr)frame % DHD_SDALIGN))) {
  766. if (PKTHEADROOM(osh, pkt) < pad) {
  767. DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
  768. __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad));
  769. bus->dhd->tx_realloc++;
  770. new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE);
  771. if (!new) {
  772. DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n",
  773. __FUNCTION__, PKTLEN(osh, pkt) + DHD_SDALIGN));
  774. ret = BCME_NOMEM;
  775. goto done;
  776. }
  777. PKTALIGN(osh, new, PKTLEN(osh, pkt), DHD_SDALIGN);
  778. bcopy(PKTDATA(osh, pkt), PKTDATA(osh, new), PKTLEN(osh, pkt));
  779. if (free_pkt)
  780. PKTFREE(osh, pkt, TRUE);
  781. /* free the pkt if canned one is not used */
  782. free_pkt = TRUE;
  783. pkt = new;
  784. frame = (uint8*)PKTDATA(osh, pkt);
  785. ASSERT(((uintptr)frame % DHD_SDALIGN) == 0);
  786. pad = 0;
  787. } else {
  788. PKTPUSH(osh, pkt, pad);
  789. frame = (uint8*)PKTDATA(osh, pkt);
  790. ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
  791. bzero(frame, pad + SDPCM_HDRLEN);
  792. }
  793. }
  794. ASSERT(pad < DHD_SDALIGN);
  795. /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
  796. len = (uint16)PKTLEN(osh, pkt);
  797. *(uint16*)frame = htol16(len);
  798. *(((uint16*)frame) + 1) = htol16(~len);
  799. /* Software tag: channel, sequence number, data offset */
  800. swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
  801. (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
  802. htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
  803. htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
  804. #ifdef DHD_DEBUG
  805. tx_packets[PKTPRIO(pkt)]++;
  806. if (DHD_BYTES_ON() &&
  807. (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
  808. (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
  809. prhex("Tx Frame", frame, len);
  810. } else if (DHD_HDRS_ON()) {
  811. prhex("TxHdr", frame, MIN(len, 16));
  812. }
  813. #endif
  814. /* Raise len to next SDIO block to eliminate tail command */
  815. if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
  816. uint16 pad = bus->blocksize - (len % bus->blocksize);
  817. if ((pad <= bus->roundup) && (pad < bus->blocksize))
  818. #ifdef NOTUSED
  819. if (pad <= PKTTAILROOM(osh, pkt))
  820. #endif /* NOTUSED */
  821. len += pad;
  822. } else if (len % DHD_SDALIGN) {
  823. len += DHD_SDALIGN - (len % DHD_SDALIGN);
  824. }
  825. /* Some controllers have trouble with odd bytes -- round to even */
  826. if (forcealign && (len & (ALIGNMENT - 1))) {
  827. #ifdef NOTUSED
  828. if (PKTTAILROOM(osh, pkt))
  829. #endif
  830. len = ROUNDUP(len, ALIGNMENT);
  831. #ifdef NOTUSED
  832. else
  833. DHD_ERROR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len));
  834. #endif
  835. }
  836. do {
  837. ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  838. frame, len, pkt, NULL, NULL);
  839. bus->f2txdata++;
  840. ASSERT(ret != BCME_PENDING);
  841. if (ret < 0) {
  842. /* On failure, abort the command and terminate the frame */
  843. DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
  844. __FUNCTION__, ret));
  845. bus->tx_sderrs++;
  846. bcmsdh_abort(sdh, SDIO_FUNC_2);
  847. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
  848. SFC_WF_TERM, NULL);
  849. bus->f1regdata++;
  850. for (i = 0; i < 3; i++) {
  851. uint8 hi, lo;
  852. hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  853. SBSDIO_FUNC1_WFRAMEBCHI, NULL);
  854. lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  855. SBSDIO_FUNC1_WFRAMEBCLO, NULL);
  856. bus->f1regdata += 2;
  857. if ((hi == 0) && (lo == 0))
  858. break;
  859. }
  860. }
  861. if (ret == 0) {
  862. bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
  863. }
  864. } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
  865. done:
  866. /* restore pkt buffer pointer before calling tx complete routine */
  867. PKTPULL(osh, pkt, SDPCM_HDRLEN + pad);
  868. dhd_os_sdunlock(bus->dhd);
  869. dhd_txcomplete(bus->dhd, pkt, ret != 0);
  870. dhd_os_sdlock(bus->dhd);
  871. if (free_pkt)
  872. PKTFREE(osh, pkt, TRUE);
  873. return ret;
  874. }
  875. int
  876. dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
  877. {
  878. int ret = BCME_ERROR;
  879. osl_t *osh;
  880. uint datalen, prec;
  881. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  882. osh = bus->dhd->osh;
  883. datalen = PKTLEN(osh, pkt);
  884. #ifdef SDTEST
  885. /* Push the test header if doing loopback */
  886. if (bus->ext_loop) {
  887. uint8* data;
  888. PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
  889. data = PKTDATA(osh, pkt);
  890. *data++ = SDPCM_TEST_ECHOREQ;
  891. *data++ = (uint8)bus->loopid++;
  892. *data++ = (datalen >> 0);
  893. *data++ = (datalen >> 8);
  894. datalen += SDPCM_TEST_HDRLEN;
  895. }
  896. #endif /* SDTEST */
  897. /* Add space for the header */
  898. PKTPUSH(osh, pkt, SDPCM_HDRLEN);
  899. ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
  900. prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
  901. /* Check for existing queue, current flow-control, pending event, or pending clock */
  902. if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
  903. (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
  904. (bus->clkstate != CLK_AVAIL)) {
  905. DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
  906. pktq_len(&bus->txq)));
  907. bus->fcqueued++;
  908. /* Priority based enq */
  909. dhd_os_sdlock_txq(bus->dhd);
  910. if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == FALSE) {
  911. PKTPULL(osh, pkt, SDPCM_HDRLEN);
  912. dhd_txcomplete(bus->dhd, pkt, FALSE);
  913. PKTFREE(osh, pkt, TRUE);
  914. DHD_ERROR(("%s: out of bus->txq !!!\n", __FUNCTION__));
  915. ret = BCME_NORESOURCE;
  916. } else {
  917. ret = BCME_OK;
  918. }
  919. dhd_os_sdunlock_txq(bus->dhd);
  920. if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow)
  921. dhd_txflowcontrol(bus->dhd, 0, ON);
  922. #ifdef DHD_DEBUG
  923. if (pktq_plen(&bus->txq, prec) > qcount[prec])
  924. qcount[prec] = pktq_plen(&bus->txq, prec);
  925. #endif
  926. /* Schedule DPC if needed to send queued packet(s) */
  927. if (dhd_deferred_tx && !bus->dpc_sched) {
  928. bus->dpc_sched = TRUE;
  929. dhd_sched_dpc(bus->dhd);
  930. }
  931. } else {
  932. /* Lock: we're about to use shared data/code (and SDIO) */
  933. dhd_os_sdlock(bus->dhd);
  934. /* Otherwise, send it now */
  935. BUS_WAKE(bus);
  936. /* Make sure back plane ht clk is on, no pending allowed */
  937. dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
  938. #ifndef SDTEST
  939. DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__));
  940. ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE);
  941. #else
  942. ret = dhdsdio_txpkt(bus, pkt,
  943. (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE);
  944. #endif
  945. if (ret)
  946. bus->dhd->tx_errors++;
  947. else
  948. bus->dhd->dstats.tx_bytes += datalen;
  949. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  950. bus->activity = FALSE;
  951. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  952. }
  953. dhd_os_sdunlock(bus->dhd);
  954. }
  955. return ret;
  956. }
  957. static uint
  958. dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
  959. {
  960. void *pkt;
  961. uint32 intstatus = 0;
  962. uint retries = 0;
  963. int ret = 0, prec_out;
  964. uint cnt = 0;
  965. uint datalen;
  966. uint8 tx_prec_map;
  967. dhd_pub_t *dhd = bus->dhd;
  968. sdpcmd_regs_t *regs = bus->regs;
  969. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  970. tx_prec_map = ~bus->flowcontrol;
  971. /* Send frames until the limit or some other event */
  972. for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
  973. dhd_os_sdlock_txq(bus->dhd);
  974. if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) {
  975. dhd_os_sdunlock_txq(bus->dhd);
  976. break;
  977. }
  978. dhd_os_sdunlock_txq(bus->dhd);
  979. datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN;
  980. #ifndef SDTEST
  981. ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE);
  982. #else
  983. ret = dhdsdio_txpkt(bus, pkt,
  984. (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE);
  985. #endif
  986. if (ret)
  987. bus->dhd->tx_errors++;
  988. else
  989. bus->dhd->dstats.tx_bytes += datalen;
  990. /* In poll mode, need to check for other events */
  991. if (!bus->intr && cnt)
  992. {
  993. /* Check device status, signal pending interrupt */
  994. R_SDREG(intstatus, &regs->intstatus, retries);
  995. bus->f2txdata++;
  996. if (bcmsdh_regfail(bus->sdh))
  997. break;
  998. if (intstatus & bus->hostintmask)
  999. bus->ipend = TRUE;
  1000. }
  1001. }
  1002. /* Deflow-control stack if needed */
  1003. if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
  1004. dhd->txoff && (pktq_len(&bus->txq) < FCLOW))
  1005. dhd_txflowcontrol(dhd, 0, OFF);
  1006. return cnt;
  1007. }
  1008. int
  1009. dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
  1010. {
  1011. uint8 *frame;
  1012. uint16 len;
  1013. uint32 swheader;
  1014. uint retries = 0;
  1015. bcmsdh_info_t *sdh = bus->sdh;
  1016. uint8 doff = 0;
  1017. int ret = -1;
  1018. int i;
  1019. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1020. if (bus->dhd->dongle_reset)
  1021. return -EIO;
  1022. /* Back the pointer to make a room for bus header */
  1023. frame = msg - SDPCM_HDRLEN;
  1024. len = (msglen += SDPCM_HDRLEN);
  1025. /* Add alignment padding (optional for ctl frames) */
  1026. if (dhd_alignctl) {
  1027. if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
  1028. frame -= doff;
  1029. len += doff;
  1030. msglen += doff;
  1031. bzero(frame, doff + SDPCM_HDRLEN);
  1032. }
  1033. ASSERT(doff < DHD_SDALIGN);
  1034. }
  1035. doff += SDPCM_HDRLEN;
  1036. /* Round send length to next SDIO block */
  1037. if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
  1038. uint16 pad = bus->blocksize - (len % bus->blocksize);
  1039. if ((pad <= bus->roundup) && (pad < bus->blocksize))
  1040. len += pad;
  1041. } else if (len % DHD_SDALIGN) {
  1042. len += DHD_SDALIGN - (len % DHD_SDALIGN);
  1043. }
  1044. /* Satisfy length-alignment requirements */
  1045. if (forcealign && (len & (ALIGNMENT - 1)))
  1046. len = ROUNDUP(len, ALIGNMENT);
  1047. ASSERT(ISALIGNED((uintptr)frame, 2));
  1048. /* Need to lock here to protect txseq and SDIO tx calls */
  1049. dhd_os_sdlock(bus->dhd);
  1050. BUS_WAKE(bus);
  1051. /* Make sure backplane clock is on */
  1052. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  1053. /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
  1054. *(uint16*)frame = htol16((uint16)msglen);
  1055. *(((uint16*)frame) + 1) = htol16(~msglen);
  1056. /* Software tag: channel, sequence number, data offset */
  1057. swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
  1058. | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
  1059. htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
  1060. htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
  1061. if (!DATAOK(bus)) {
  1062. DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
  1063. __FUNCTION__, bus->tx_max, bus->tx_seq));
  1064. bus->ctrl_frame_stat = TRUE;
  1065. /* Send from dpc */
  1066. bus->ctrl_frame_buf = frame;
  1067. bus->ctrl_frame_len = len;
  1068. dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
  1069. if (bus->ctrl_frame_stat == FALSE) {
  1070. DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
  1071. ret = 0;
  1072. } else {
  1073. if (!bus->dhd->hang_was_sent)
  1074. DHD_ERROR(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
  1075. ret = -1;
  1076. }
  1077. }
  1078. if (ret == -1) {
  1079. #ifdef DHD_DEBUG
  1080. if (DHD_BYTES_ON() && DHD_CTL_ON()) {
  1081. prhex("Tx Frame", frame, len);
  1082. } else if (DHD_HDRS_ON()) {
  1083. prhex("TxHdr", frame, MIN(len, 16));
  1084. }
  1085. #endif
  1086. do {
  1087. bus->ctrl_frame_stat = FALSE;
  1088. ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  1089. frame, len, NULL, NULL, NULL);
  1090. ASSERT(ret != BCME_PENDING);
  1091. if (ret < 0) {
  1092. /* On failure, abort the command and terminate the frame */
  1093. DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
  1094. __FUNCTION__, ret));
  1095. bus->tx_sderrs++;
  1096. bcmsdh_abort(sdh, SDIO_FUNC_2);
  1097. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
  1098. SFC_WF_TERM, NULL);
  1099. bus->f1regdata++;
  1100. for (i = 0; i < 3; i++) {
  1101. uint8 hi, lo;
  1102. hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  1103. SBSDIO_FUNC1_WFRAMEBCHI, NULL);
  1104. lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  1105. SBSDIO_FUNC1_WFRAMEBCLO, NULL);
  1106. bus->f1regdata += 2;
  1107. if ((hi == 0) && (lo == 0))
  1108. break;
  1109. }
  1110. }
  1111. if (ret == 0) {
  1112. bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
  1113. }
  1114. } while ((ret < 0) && retries++ < TXRETRIES);
  1115. }
  1116. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  1117. bus->activity = FALSE;
  1118. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  1119. }
  1120. dhd_os_sdunlock(bus->dhd);
  1121. if (ret)
  1122. bus->dhd->tx_ctlerrs++;
  1123. else
  1124. bus->dhd->tx_ctlpkts++;
  1125. return ret ? -EIO : 0;
  1126. }
  1127. int
  1128. dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
  1129. {
  1130. int timeleft;
  1131. uint rxlen = 0;
  1132. bool pending;
  1133. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1134. if (bus->dhd->dongle_reset)
  1135. return -EIO;
  1136. /* Wait until control frame is available */
  1137. timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
  1138. dhd_os_sdlock(bus->dhd);
  1139. rxlen = bus->rxlen;
  1140. bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
  1141. bus->rxlen = 0;
  1142. dhd_os_sdunlock(bus->dhd);
  1143. if (rxlen) {
  1144. DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
  1145. __FUNCTION__, rxlen, msglen));
  1146. } else if (timeleft == 0) {
  1147. DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
  1148. #ifdef DHD_DEBUG_TRAP
  1149. dhd_os_sdlock(bus->dhd);
  1150. dhdsdio_checkdied(bus, NULL, 0);
  1151. dhd_os_sdunlock(bus->dhd);
  1152. #endif /* DHD_DEBUG_TRAP */
  1153. } else if (pending == TRUE) {
  1154. DHD_CTL(("%s: cancelled\n", __FUNCTION__));
  1155. return -ERESTARTSYS;
  1156. } else {
  1157. DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
  1158. #ifdef DHD_DEBUG_TRAP
  1159. dhd_os_sdlock(bus->dhd);
  1160. dhdsdio_checkdied(bus, NULL, 0);
  1161. dhd_os_sdunlock(bus->dhd);
  1162. #endif /* DHD_DEBUG_TRAP */
  1163. }
  1164. if (rxlen)
  1165. bus->dhd->rx_ctlpkts++;
  1166. else
  1167. bus->dhd->rx_ctlerrs++;
  1168. return rxlen ? (int)rxlen : -ETIMEDOUT;
  1169. }
  1170. /* IOVar table */
  1171. enum {
  1172. IOV_INTR = 1,
  1173. IOV_POLLRATE,
  1174. IOV_SDREG,
  1175. IOV_SBREG,
  1176. IOV_SDCIS,
  1177. IOV_MEMBYTES,
  1178. IOV_MEMSIZE,
  1179. #ifdef DHD_DEBUG_TRAP
  1180. IOV_CHECKDIED,
  1181. #endif
  1182. IOV_DOWNLOAD,
  1183. IOV_FORCEEVEN,
  1184. IOV_SDIOD_DRIVE,
  1185. IOV_READAHEAD,
  1186. IOV_SDRXCHAIN,
  1187. IOV_ALIGNCTL,
  1188. IOV_SDALIGN,
  1189. IOV_DEVRESET,
  1190. IOV_CPU,
  1191. #ifdef SDTEST
  1192. IOV_PKTGEN,
  1193. IOV_EXTLOOP,
  1194. #endif /* SDTEST */
  1195. IOV_SPROM,
  1196. IOV_TXBOUND,
  1197. IOV_RXBOUND,
  1198. IOV_TXMINMAX,
  1199. IOV_IDLETIME,
  1200. IOV_IDLECLOCK,
  1201. IOV_SD1IDLE,
  1202. IOV_SLEEP,
  1203. IOV_VARS
  1204. };
  1205. const bcm_iovar_t dhdsdio_iovars[] = {
  1206. {"intr", IOV_INTR, 0, IOVT_BOOL, 0 },
  1207. {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 },
  1208. {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 },
  1209. {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 },
  1210. {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 },
  1211. {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 },
  1212. {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) },
  1213. {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0 },
  1214. {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0 },
  1215. {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 },
  1216. {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 },
  1217. {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 },
  1218. {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 },
  1219. {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 },
  1220. {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 },
  1221. {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 },
  1222. #ifdef DHD_DEBUG
  1223. {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
  1224. {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
  1225. {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN },
  1226. {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 },
  1227. {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 },
  1228. {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 },
  1229. {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 },
  1230. {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 },
  1231. #endif /* DHD_DEBUG */
  1232. #ifdef DHD_DEBUG_TRAP
  1233. {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0 },
  1234. #endif /* DHD_DEBUG_TRAP */
  1235. #ifdef SDTEST
  1236. {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 },
  1237. {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) },
  1238. #endif /* SDTEST */
  1239. {NULL, 0, 0, 0, 0 }
  1240. };
  1241. static void
  1242. dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
  1243. {
  1244. uint q1, q2;
  1245. if (!div) {
  1246. bcm_bprintf(strbuf, "%s N/A", desc);
  1247. } else {
  1248. q1 = num / div;
  1249. q2 = (100 * (num - (q1 * div))) / div;
  1250. bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
  1251. }
  1252. }
  1253. void
  1254. dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
  1255. {
  1256. dhd_bus_t *bus = dhdp->bus;
  1257. bcm_bprintf(strbuf, "Bus SDIO structure:\n");
  1258. bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
  1259. bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
  1260. bcm_bprintf(strbuf, "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
  1261. bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
  1262. bus->rxlen, bus->rx_seq);
  1263. bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
  1264. bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
  1265. bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
  1266. bus->pollrate, bus->pollcnt, bus->regfails);
  1267. bcm_bprintf(strbuf, "\nAdditional counters:\n");
  1268. bcm_bprintf(strbuf, "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
  1269. bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
  1270. bus->rxc_errors);
  1271. bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
  1272. bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
  1273. bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n",
  1274. bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
  1275. bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
  1276. bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
  1277. bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n",
  1278. (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
  1279. bus->f2txdata, bus->f1regdata);
  1280. {
  1281. dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
  1282. (bus->f2rxhdrs + bus->f2rxdata));
  1283. dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
  1284. dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
  1285. (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
  1286. dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
  1287. bcm_bprintf(strbuf, "\n");
  1288. dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
  1289. bus->dhd->rx_packets);
  1290. dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
  1291. bcm_bprintf(strbuf, "\n");
  1292. dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
  1293. dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
  1294. dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
  1295. (bus->f2txdata + bus->f1regdata));
  1296. dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
  1297. bcm_bprintf(strbuf, "\n");
  1298. dhd_dump_pct(strbuf, "Total: pkts/f2rw",
  1299. (bus->dhd->tx_packets + bus->dhd->rx_packets),
  1300. (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
  1301. dhd_dump_pct(strbuf, ", pkts/f1sd",
  1302. (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
  1303. dhd_dump_pct(strbuf, ", pkts/sd",
  1304. (bus->dhd->tx_packets + bus->dhd->rx_packets),
  1305. (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
  1306. dhd_dump_pct(strbuf, ", pkts/int",
  1307. (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
  1308. bcm_bprintf(strbuf, "\n\n");
  1309. }
  1310. #ifdef SDTEST
  1311. if (bus->pktgen_count) {
  1312. bcm_bprintf(strbuf, "pktgen config and count:\n");
  1313. bcm_bprintf(strbuf, "freq %d count %d print %d total %d min %d len %d\n",
  1314. bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
  1315. bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
  1316. bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
  1317. bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
  1318. }
  1319. #endif /* SDTEST */
  1320. #ifdef DHD_DEBUG
  1321. bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
  1322. bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
  1323. bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize, bus->roundup);
  1324. #endif /* DHD_DEBUG */
  1325. bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
  1326. bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
  1327. }
  1328. void
  1329. dhd_bus_clearcounts(dhd_pub_t *dhdp)
  1330. {
  1331. dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
  1332. bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
  1333. bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
  1334. bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
  1335. bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
  1336. bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
  1337. bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
  1338. }
  1339. #ifdef SDTEST
  1340. static int
  1341. dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
  1342. {
  1343. dhd_pktgen_t pktgen;
  1344. pktgen.version = DHD_PKTGEN_VERSION;
  1345. pktgen.freq = bus->pktgen_freq;
  1346. pktgen.count = bus->pktgen_count;
  1347. pktgen.print = bus->pktgen_print;
  1348. pktgen.total = bus->pktgen_total;
  1349. pktgen.minlen = bus->pktgen_minlen;
  1350. pktgen.maxlen = bus->pktgen_maxlen;
  1351. pktgen.numsent = bus->pktgen_sent;
  1352. pktgen.numrcvd = bus->pktgen_rcvd;
  1353. pktgen.numfail = bus->pktgen_fail;
  1354. pktgen.mode = bus->pktgen_mode;
  1355. pktgen.stop = bus->pktgen_stop;
  1356. bcopy(&pktgen, arg, sizeof(pktgen));
  1357. return 0;
  1358. }
  1359. static int
  1360. dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
  1361. {
  1362. dhd_pktgen_t pktgen;
  1363. uint oldcnt, oldmode;
  1364. bcopy(arg, &pktgen, sizeof(pktgen));
  1365. if (pktgen.version != DHD_PKTGEN_VERSION)
  1366. return BCME_BADARG;
  1367. oldcnt = bus->pktgen_count;
  1368. oldmode = bus->pktgen_mode;
  1369. bus->pktgen_freq = pktgen.freq;
  1370. bus->pktgen_count = pktgen.count;
  1371. bus->pktgen_print = pktgen.print;
  1372. bus->pktgen_total = pktgen.total;
  1373. bus->pktgen_minlen = pktgen.minlen;
  1374. bus->pktgen_maxlen = pktgen.maxlen;
  1375. bus->pktgen_mode = pktgen.mode;
  1376. bus->pktgen_stop = pktgen.stop;
  1377. bus->pktgen_tick = bus->pktgen_ptick = 0;
  1378. bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
  1379. bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
  1380. /* Clear counts for a new pktgen (mode change, or was stopped) */
  1381. if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
  1382. bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
  1383. return 0;
  1384. }
  1385. #endif /* SDTEST */
  1386. static int
  1387. dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
  1388. {
  1389. int bcmerror = 0;
  1390. uint32 sdaddr;
  1391. uint dsize;
  1392. /* Determine initial transfer parameters */
  1393. sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
  1394. if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
  1395. dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
  1396. else
  1397. dsize = size;
  1398. /* Set the backplane window to include the start address */
  1399. if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
  1400. DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
  1401. goto xfer_done;
  1402. }
  1403. /* Do the transfer(s) */
  1404. while (size) {
  1405. DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
  1406. __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
  1407. (address & SBSDIO_SBWINDOW_MASK)));
  1408. if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) {
  1409. DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
  1410. break;
  1411. }
  1412. /* Adjust for next transfer (if any) */
  1413. if ((size -= dsize)) {
  1414. data += dsize;
  1415. address += dsize;
  1416. if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
  1417. DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
  1418. break;
  1419. }
  1420. sdaddr = 0;
  1421. dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
  1422. }
  1423. }
  1424. xfer_done:
  1425. /* Return the window to backplane enumeration space for core access */
  1426. if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
  1427. DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
  1428. bcmsdh_cur_sbwad(bus->sdh)));
  1429. }
  1430. return bcmerror;
  1431. }
  1432. #ifdef DHD_DEBUG_TRAP
  1433. static int
  1434. dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
  1435. {
  1436. uint32 addr;
  1437. int rv;
  1438. /* Read last word in memory to determine address of sdpcm_shared structure */
  1439. if ((rv = dhdsdio_membytes(bus, FALSE, bus->ramsize - 4, (uint8 *)&addr, 4)) < 0)
  1440. return rv;
  1441. addr = ltoh32(addr);
  1442. DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
  1443. /*
  1444. * Check if addr is valid.
  1445. * NVRAM length at the end of memory should have been overwritten.
  1446. */
  1447. if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
  1448. DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n", __FUNCTION__, addr));
  1449. return BCME_ERROR;
  1450. }
  1451. /* Read hndrte_shared structure */
  1452. if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
  1453. return rv;
  1454. /* Endianness */
  1455. sh->flags = ltoh32(sh->flags);
  1456. sh->trap_addr = ltoh32(sh->trap_addr);
  1457. sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
  1458. sh->assert_file_addr = ltoh32(sh->assert_file_addr);
  1459. sh->assert_line = ltoh32(sh->assert_line);
  1460. sh->console_addr = ltoh32(sh->console_addr);
  1461. sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
  1462. if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
  1463. DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
  1464. "is different than sdpcm_shared version %d in dongle\n",
  1465. __FUNCTION__, SDPCM_SHARED_VERSION,
  1466. sh->flags & SDPCM_SHARED_VERSION_MASK));
  1467. return BCME_ERROR;
  1468. }
  1469. return BCME_OK;
  1470. }
  1471. static int
  1472. dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
  1473. {
  1474. int bcmerror = 0;
  1475. uint msize = 512;
  1476. char *mbuffer = NULL;
  1477. uint maxstrlen = 256;
  1478. char *str = NULL;
  1479. trap_t tr;
  1480. sdpcm_shared_t sdpcm_shared;
  1481. struct bcmstrbuf strbuf;
  1482. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1483. if (data == NULL) {
  1484. /*
  1485. * Called after a rx ctrl timeout. "data" is NULL.
  1486. * allocate memory to trace the trap or assert.
  1487. */
  1488. size = msize;
  1489. mbuffer = data = MALLOC(bus->dhd->osh, msize);
  1490. if (mbuffer == NULL) {
  1491. DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
  1492. bcmerror = BCME_NOMEM;
  1493. goto done;
  1494. }
  1495. }
  1496. if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
  1497. DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
  1498. bcmerror = BCME_NOMEM;
  1499. goto done;
  1500. }
  1501. if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0)
  1502. goto done;
  1503. bcm_binit(&strbuf, data, size);
  1504. bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
  1505. sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
  1506. if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
  1507. /* NOTE: Misspelled assert is intentional - DO NOT FIX.
  1508. * (Avoids conflict with real asserts for programmatic parsing of output.)
  1509. */
  1510. bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
  1511. }
  1512. if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
  1513. /* NOTE: Misspelled assert is intentional - DO NOT FIX.
  1514. * (Avoids conflict with real asserts for programmatic parsing of output.)
  1515. */
  1516. bcm_bprintf(&strbuf, "No trap%s in dongle",
  1517. (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
  1518. ?"/assrt" :"");
  1519. } else {
  1520. if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
  1521. /* Download assert */
  1522. bcm_bprintf(&strbuf, "Dongle assert");
  1523. if (sdpcm_shared.assert_exp_addr != 0) {
  1524. str[0] = '\0';
  1525. if ((bcmerror = dhdsdio_membytes(bus, FALSE,
  1526. sdpcm_shared.assert_exp_addr,
  1527. (uint8 *)str, maxstrlen)) < 0)
  1528. goto done;
  1529. str[maxstrlen - 1] = '\0';
  1530. bcm_bprintf(&strbuf, " expr \"%s\"", str);
  1531. }
  1532. if (sdpcm_shared.assert_file_addr != 0) {
  1533. str[0] = '\0';
  1534. if ((bcmerror = dhdsdio_membytes(bus, FALSE,
  1535. sdpcm_shared.assert_file_addr,
  1536. (uint8 *)str, maxstrlen)) < 0)
  1537. goto done;
  1538. str[maxstrlen - 1] = '\0';
  1539. bcm_bprintf(&strbuf, " file \"%s\"", str);
  1540. }
  1541. bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line);
  1542. }
  1543. if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
  1544. if ((bcmerror = dhdsdio_membytes(bus, FALSE,
  1545. sdpcm_shared.trap_addr,
  1546. (uint8*)&tr, sizeof(trap_t))) < 0)
  1547. goto done;
  1548. bcm_bprintf(&strbuf,
  1549. "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
  1550. "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
  1551. "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
  1552. tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13, tr.r14, tr.pc,
  1553. sdpcm_shared.trap_addr,
  1554. tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5, tr.r6, tr.r7);
  1555. }
  1556. }
  1557. if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
  1558. DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
  1559. }
  1560. done:
  1561. if (mbuffer)
  1562. MFREE(bus->dhd->osh, mbuffer, msize);
  1563. if (str)
  1564. MFREE(bus->dhd->osh, str, maxstrlen);
  1565. return bcmerror;
  1566. }
  1567. #endif /* DHD_DEBUG_TRAP */
  1568. #ifdef DHD_DEBUG
  1569. #define CONSOLE_LINE_MAX 192
  1570. static int
  1571. dhdsdio_readconsole(dhd_bus_t *bus)
  1572. {
  1573. dhd_console_t *c = &bus->console;
  1574. uint8 line[CONSOLE_LINE_MAX], ch;
  1575. uint32 n, idx, addr;
  1576. int rv;
  1577. /* Don't do anything until FWREADY updates console address */
  1578. if (bus->console_addr == 0)
  1579. return 0;
  1580. /* Read console log struct */
  1581. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
  1582. if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
  1583. return rv;
  1584. /* Allocate console buffer (one time only) */
  1585. if (c->buf == NULL) {
  1586. c->bufsize = ltoh32(c->log.buf_size);
  1587. if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
  1588. return BCME_NOMEM;
  1589. }
  1590. idx = ltoh32(c->log.idx);
  1591. /* Protect against corrupt value */
  1592. if (idx > c->bufsize)
  1593. return BCME_ERROR;
  1594. /* Skip reading the console buffer if the index pointer has not moved */
  1595. if (idx == c->last)
  1596. return BCME_OK;
  1597. /* Read the console buffer */
  1598. addr = ltoh32(c->log.buf);
  1599. if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
  1600. return rv;
  1601. while (c->last != idx) {
  1602. for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
  1603. if (c->last == idx) {
  1604. /* This would output a partial line. Instead, back up
  1605. * the buffer pointer and output this line next time around.
  1606. */
  1607. if (c->last >= n)
  1608. c->last -= n;
  1609. else
  1610. c->last = c->bufsize - n;
  1611. goto break2;
  1612. }
  1613. ch = c->buf[c->last];
  1614. c->last = (c->last + 1) % c->bufsize;
  1615. if (ch == '\n')
  1616. break;
  1617. line[n] = ch;
  1618. }
  1619. if (n > 0) {
  1620. if (line[n - 1] == '\r')
  1621. n--;
  1622. line[n] = 0;
  1623. printf("CONSOLE: %s\n", line);
  1624. }
  1625. }
  1626. break2:
  1627. return BCME_OK;
  1628. }
  1629. #endif /* DHD_DEBUG */
  1630. int
  1631. dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
  1632. {
  1633. int bcmerror = BCME_OK;
  1634. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1635. /* Basic sanity checks */
  1636. if (bus->dhd->up) {
  1637. bcmerror = BCME_NOTDOWN;
  1638. goto err;
  1639. }
  1640. if (!len) {
  1641. bcmerror = BCME_BUFTOOSHORT;
  1642. goto err;
  1643. }
  1644. /* Free the old ones and replace with passed variables */
  1645. if (bus->vars)
  1646. MFREE(bus->dhd->osh, bus->vars, bus->varsz);
  1647. bus->vars = MALLOC(bus->dhd->osh, len);
  1648. bus->varsz = bus->vars ? len : 0;
  1649. if (bus->vars == NULL) {
  1650. bcmerror = BCME_NOMEM;
  1651. goto err;
  1652. }
  1653. /* Copy the passed variables, which should include the terminating double-null */
  1654. bcopy(arg, bus->vars, bus->varsz);
  1655. err:
  1656. return bcmerror;
  1657. }
  1658. static int
  1659. dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
  1660. void *params, int plen, void *arg, int len, int val_size)
  1661. {
  1662. int bcmerror = 0;
  1663. int32 int_val = 0;
  1664. bool bool_val = 0;
  1665. DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
  1666. __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
  1667. if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
  1668. goto exit;
  1669. if (plen >= (int)sizeof(int_val))
  1670. bcopy(params, &int_val, sizeof(int_val));
  1671. bool_val = (int_val != 0) ? TRUE : FALSE;
  1672. /* Some ioctls use the bus */
  1673. dhd_os_sdlock(bus->dhd);
  1674. /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
  1675. if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
  1676. actionid == IOV_GVAL(IOV_DEVRESET))) {
  1677. bcmerror = BCME_NOTREADY;
  1678. goto exit;
  1679. }
  1680. /* Handle sleep stuff before any clock mucking */
  1681. if (vi->varid == IOV_SLEEP) {
  1682. if (IOV_ISSET(actionid)) {
  1683. bcmerror = dhdsdio_bussleep(bus, bool_val);
  1684. } else {
  1685. int_val = (int32)bus->sleeping;
  1686. bcopy(&int_val, arg, val_size);
  1687. }
  1688. goto exit;
  1689. }
  1690. /* Request clock to allow SDIO accesses */
  1691. if (!bus->dhd->dongle_reset) {
  1692. BUS_WAKE(bus);
  1693. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  1694. }
  1695. switch (actionid) {
  1696. case IOV_GVAL(IOV_INTR):
  1697. int_val = (int32)bus->intr;
  1698. bcopy(&int_val, arg, val_size);
  1699. break;
  1700. case IOV_SVAL(IOV_INTR):
  1701. bus->intr = bool_val;
  1702. bus->intdis = FALSE;
  1703. if (bus->dhd->up) {
  1704. if (bus->intr) {
  1705. DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
  1706. bcmsdh_intr_enable(bus->sdh);
  1707. } else {
  1708. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  1709. bcmsdh_intr_disable(bus->sdh);
  1710. }
  1711. }
  1712. break;
  1713. case IOV_GVAL(IOV_POLLRATE):
  1714. int_val = (int32)bus->pollrate;
  1715. bcopy(&int_val, arg, val_size);
  1716. break;
  1717. case IOV_SVAL(IOV_POLLRATE):
  1718. bus->pollrate = (uint)int_val;
  1719. bus->poll = (bus->pollrate != 0);
  1720. break;
  1721. case IOV_GVAL(IOV_IDLETIME):
  1722. int_val = bus->idletime;
  1723. bcopy(&int_val, arg, val_size);
  1724. break;
  1725. case IOV_SVAL(IOV_IDLETIME):
  1726. if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
  1727. bcmerror = BCME_BADARG;
  1728. } else {
  1729. bus->idletime = int_val;
  1730. }
  1731. break;
  1732. case IOV_GVAL(IOV_IDLECLOCK):
  1733. int_val = (int32)bus->idleclock;
  1734. bcopy(&int_val, arg, val_size);
  1735. break;
  1736. case IOV_SVAL(IOV_IDLECLOCK):
  1737. bus->idleclock = int_val;
  1738. break;
  1739. case IOV_GVAL(IOV_SD1IDLE):
  1740. int_val = (int32)sd1idle;
  1741. bcopy(&int_val, arg, val_size);
  1742. break;
  1743. case IOV_SVAL(IOV_SD1IDLE):
  1744. sd1idle = bool_val;
  1745. break;
  1746. case IOV_SVAL(IOV_MEMBYTES):
  1747. case IOV_GVAL(IOV_MEMBYTES):
  1748. {
  1749. uint32 address;
  1750. uint size, dsize;
  1751. uint8 *data;
  1752. bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
  1753. ASSERT(plen >= 2*sizeof(int));
  1754. address = (uint32)int_val;
  1755. bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
  1756. size = (uint)int_val;
  1757. /* Do some validation */
  1758. dsize = set ? plen - (2 * sizeof(int)) : len;
  1759. if (dsize < size) {
  1760. DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
  1761. __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
  1762. bcmerror = BCME_BADARG;
  1763. break;
  1764. }
  1765. DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
  1766. (set ? "write" : "read"), size, address));
  1767. /* If we know about SOCRAM, check for a fit */
  1768. if ((bus->orig_ramsize) &&
  1769. ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) {
  1770. DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
  1771. __FUNCTION__, bus->orig_ramsize, size, address));
  1772. bcmerror = BCME_BADARG;
  1773. break;
  1774. }
  1775. /* Generate the actual data pointer */
  1776. data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
  1777. /* Call to do the transfer */
  1778. bcmerror = dhdsdio_membytes(bus, set, address, data, size);
  1779. break;
  1780. }
  1781. case IOV_GVAL(IOV_MEMSIZE):
  1782. int_val = (int32)bus->ramsize;
  1783. bcopy(&int_val, arg, val_size);
  1784. break;
  1785. case IOV_GVAL(IOV_SDIOD_DRIVE):
  1786. int_val = (int32)dhd_sdiod_drive_strength;
  1787. bcopy(&int_val, arg, val_size);
  1788. break;
  1789. case IOV_SVAL(IOV_SDIOD_DRIVE):
  1790. dhd_sdiod_drive_strength = int_val;
  1791. si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
  1792. break;
  1793. case IOV_SVAL(IOV_DOWNLOAD):
  1794. bcmerror = dhdsdio_download_state(bus, bool_val);
  1795. break;
  1796. case IOV_SVAL(IOV_VARS):
  1797. bcmerror = dhdsdio_downloadvars(bus, arg, len);
  1798. break;
  1799. case IOV_GVAL(IOV_READAHEAD):
  1800. int_val = (int32)dhd_readahead;
  1801. bcopy(&int_val, arg, val_size);
  1802. break;
  1803. case IOV_SVAL(IOV_READAHEAD):
  1804. if (bool_val && !dhd_readahead)
  1805. bus->nextlen = 0;
  1806. dhd_readahead = bool_val;
  1807. break;
  1808. case IOV_GVAL(IOV_SDRXCHAIN):
  1809. int_val = (int32)bus->use_rxchain;
  1810. bcopy(&int_val, arg, val_size);
  1811. break;
  1812. case IOV_SVAL(IOV_SDRXCHAIN):
  1813. if (bool_val && !bus->sd_rxchain)
  1814. bcmerror = BCME_UNSUPPORTED;
  1815. else
  1816. bus->use_rxchain = bool_val;
  1817. break;
  1818. case IOV_GVAL(IOV_ALIGNCTL):
  1819. int_val = (int32)dhd_alignctl;
  1820. bcopy(&int_val, arg, val_size);
  1821. break;
  1822. case IOV_SVAL(IOV_ALIGNCTL):
  1823. dhd_alignctl = bool_val;
  1824. break;
  1825. case IOV_GVAL(IOV_SDALIGN):
  1826. int_val = DHD_SDALIGN;
  1827. bcopy(&int_val, arg, val_size);
  1828. break;
  1829. #ifdef DHD_DEBUG
  1830. case IOV_GVAL(IOV_VARS):
  1831. if (bus->varsz < (uint)len)
  1832. bcopy(bus->vars, arg, bus->varsz);
  1833. else
  1834. bcmerror = BCME_BUFTOOSHORT;
  1835. break;
  1836. #endif /* DHD_DEBUG */
  1837. #ifdef DHD_DEBUG
  1838. case IOV_GVAL(IOV_SDREG):
  1839. {
  1840. sdreg_t *sd_ptr;
  1841. uint32 addr, size;
  1842. sd_ptr = (sdreg_t *)params;
  1843. addr = (uintptr)bus->regs + sd_ptr->offset;
  1844. size = sd_ptr->func;
  1845. int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
  1846. if (bcmsdh_regfail(bus->sdh))
  1847. bcmerror = BCME_SDIO_ERROR;
  1848. bcopy(&int_val, arg, sizeof(int32));
  1849. break;
  1850. }
  1851. case IOV_SVAL(IOV_SDREG):
  1852. {
  1853. sdreg_t *sd_ptr;
  1854. uint32 addr, size;
  1855. sd_ptr = (sdreg_t *)params;
  1856. addr = (uintptr)bus->regs + sd_ptr->offset;
  1857. size = sd_ptr->func;
  1858. bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
  1859. if (bcmsdh_regfail(bus->sdh))
  1860. bcmerror = BCME_SDIO_ERROR;
  1861. break;
  1862. }
  1863. /* Same as above, but offset is not backplane (not SDIO core) */
  1864. case IOV_GVAL(IOV_SBREG):
  1865. {
  1866. sdreg_t sdreg;
  1867. uint32 addr, size;
  1868. bcopy(params, &sdreg, sizeof(sdreg));
  1869. addr = SI_ENUM_BASE + sdreg.offset;
  1870. size = sdreg.func;
  1871. int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
  1872. if (bcmsdh_regfail(bus->sdh))
  1873. bcmerror = BCME_SDIO_ERROR;
  1874. bcopy(&int_val, arg, sizeof(int32));
  1875. break;
  1876. }
  1877. case IOV_SVAL(IOV_SBREG):
  1878. {
  1879. sdreg_t sdreg;
  1880. uint32 addr, size;
  1881. bcopy(params, &sdreg, sizeof(sdreg));
  1882. addr = SI_ENUM_BASE + sdreg.offset;
  1883. size = sdreg.func;
  1884. bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
  1885. if (bcmsdh_regfail(bus->sdh))
  1886. bcmerror = BCME_SDIO_ERROR;
  1887. break;
  1888. }
  1889. case IOV_GVAL(IOV_SDCIS):
  1890. {
  1891. *(char *)arg = 0;
  1892. bcmstrcat(arg, "\nFunc 0\n");
  1893. bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
  1894. bcmstrcat(arg, "\nFunc 1\n");
  1895. bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
  1896. bcmstrcat(arg, "\nFunc 2\n");
  1897. bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
  1898. break;
  1899. }
  1900. case IOV_GVAL(IOV_FORCEEVEN):
  1901. int_val = (int32)forcealign;
  1902. bcopy(&int_val, arg, val_size);
  1903. break;
  1904. case IOV_SVAL(IOV_FORCEEVEN):
  1905. forcealign = bool_val;
  1906. break;
  1907. case IOV_GVAL(IOV_TXBOUND):
  1908. int_val = (int32)dhd_txbound;
  1909. bcopy(&int_val, arg, val_size);
  1910. break;
  1911. case IOV_SVAL(IOV_TXBOUND):
  1912. dhd_txbound = (uint)int_val;
  1913. break;
  1914. case IOV_GVAL(IOV_RXBOUND):
  1915. int_val = (int32)dhd_rxbound;
  1916. bcopy(&int_val, arg, val_size);
  1917. break;
  1918. case IOV_SVAL(IOV_RXBOUND):
  1919. dhd_rxbound = (uint)int_val;
  1920. break;
  1921. case IOV_GVAL(IOV_TXMINMAX):
  1922. int_val = (int32)dhd_txminmax;
  1923. bcopy(&int_val, arg, val_size);
  1924. break;
  1925. case IOV_SVAL(IOV_TXMINMAX):
  1926. dhd_txminmax = (uint)int_val;
  1927. break;
  1928. #endif /* DHD_DEBUG */
  1929. #ifdef SDTEST
  1930. case IOV_GVAL(IOV_EXTLOOP):
  1931. int_val = (int32)bus->ext_loop;
  1932. bcopy(&int_val, arg, val_size);
  1933. break;
  1934. case IOV_SVAL(IOV_EXTLOOP):
  1935. bus->ext_loop = bool_val;
  1936. break;
  1937. case IOV_GVAL(IOV_PKTGEN):
  1938. bcmerror = dhdsdio_pktgen_get(bus, arg);
  1939. break;
  1940. case IOV_SVAL(IOV_PKTGEN):
  1941. bcmerror = dhdsdio_pktgen_set(bus, arg);
  1942. break;
  1943. #endif /* SDTEST */
  1944. case IOV_SVAL(IOV_DEVRESET):
  1945. DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
  1946. __FUNCTION__, bool_val, bus->dhd->dongle_reset,
  1947. bus->dhd->busstate));
  1948. ASSERT(bus->dhd->osh);
  1949. /* ASSERT(bus->cl_devid); */
  1950. dhd_bus_devreset(bus->dhd, (uint8)bool_val);
  1951. break;
  1952. case IOV_GVAL(IOV_DEVRESET):
  1953. DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
  1954. /* Get its status */
  1955. int_val = (bool) bus->dhd->dongle_reset;
  1956. bcopy(&int_val, arg, val_size);
  1957. break;
  1958. default:
  1959. bcmerror = BCME_UNSUPPORTED;
  1960. break;
  1961. }
  1962. exit:
  1963. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  1964. bus->activity = FALSE;
  1965. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  1966. }
  1967. dhd_os_sdunlock(bus->dhd);
  1968. if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == FALSE)
  1969. dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
  1970. return bcmerror;
  1971. }
  1972. static int
  1973. dhdsdio_write_vars(dhd_bus_t *bus)
  1974. {
  1975. int bcmerror = 0;
  1976. uint32 varsize;
  1977. uint32 varaddr;
  1978. uint8 *vbuffer;
  1979. uint32 varsizew;
  1980. #ifdef DHD_DEBUG
  1981. char *nvram_ularray;
  1982. #endif /* DHD_DEBUG */
  1983. /* Even if there are no vars are to be written, we still need to set the ramsize. */
  1984. varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
  1985. varaddr = (bus->ramsize - 4) - varsize;
  1986. if (bus->vars) {
  1987. vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
  1988. if (!vbuffer)
  1989. return BCME_NOMEM;
  1990. bzero(vbuffer, varsize);
  1991. bcopy(bus->vars, vbuffer, bus->varsz);
  1992. /* Write the vars list */
  1993. bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
  1994. #ifdef DHD_DEBUG
  1995. /* Verify NVRAM bytes */
  1996. DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
  1997. nvram_ularray = (char*)MALLOC(bus->dhd->osh, varsize);
  1998. if (!nvram_ularray)
  1999. return BCME_NOMEM;
  2000. /* Upload image to verify downloaded contents. */
  2001. memset(nvram_ularray, 0xaa, varsize);
  2002. /* Read the vars list to temp buffer for comparison */
  2003. bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
  2004. if (bcmerror) {
  2005. DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
  2006. __FUNCTION__, bcmerror, varsize, varaddr));
  2007. }
  2008. /* Compare the org NVRAM with the one read from RAM */
  2009. if (memcmp(vbuffer, nvram_ularray, varsize)) {
  2010. DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
  2011. } else
  2012. DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
  2013. __FUNCTION__));
  2014. MFREE(bus->dhd->osh, nvram_ularray, varsize);
  2015. #endif /* DHD_DEBUG */
  2016. MFREE(bus->dhd->osh, vbuffer, varsize);
  2017. }
  2018. /* adjust to the user specified RAM */
  2019. DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
  2020. bus->orig_ramsize, bus->ramsize));
  2021. DHD_INFO(("Vars are at %d, orig varsize is %d\n",
  2022. varaddr, varsize));
  2023. varsize = ((bus->orig_ramsize - 4) - varaddr);
  2024. /*
  2025. * Determine the length token:
  2026. * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
  2027. */
  2028. if (bcmerror) {
  2029. varsizew = 0;
  2030. } else {
  2031. varsizew = varsize / 4;
  2032. varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
  2033. varsizew = htol32(varsizew);
  2034. }
  2035. DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
  2036. /* Write the length token to the last word */
  2037. bcmerror = dhdsdio_membytes(bus, TRUE, (bus->orig_ramsize - 4),
  2038. (uint8*)&varsizew, 4);
  2039. return bcmerror;
  2040. }
  2041. static int
  2042. dhdsdio_download_state(dhd_bus_t *bus, bool enter)
  2043. {
  2044. uint retries;
  2045. int bcmerror = 0;
  2046. /* To enter download state, disable ARM and reset SOCRAM.
  2047. * To exit download state, simply reset ARM (default is RAM boot).
  2048. */
  2049. if (enter) {
  2050. bus->alp_only = TRUE;
  2051. if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
  2052. !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
  2053. DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
  2054. bcmerror = BCME_ERROR;
  2055. goto fail;
  2056. }
  2057. si_core_disable(bus->sih, 0);
  2058. if (bcmsdh_regfail(bus->sdh)) {
  2059. bcmerror = BCME_SDIO_ERROR;
  2060. goto fail;
  2061. }
  2062. if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
  2063. DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
  2064. bcmerror = BCME_ERROR;
  2065. goto fail;
  2066. }
  2067. si_core_reset(bus->sih, 0, 0);
  2068. if (bcmsdh_regfail(bus->sdh)) {
  2069. DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__));
  2070. bcmerror = BCME_SDIO_ERROR;
  2071. goto fail;
  2072. }
  2073. /* Clear the top bit of memory */
  2074. if (bus->ramsize) {
  2075. uint32 zeros = 0;
  2076. dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4);
  2077. }
  2078. } else {
  2079. if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
  2080. DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
  2081. bcmerror = BCME_ERROR;
  2082. goto fail;
  2083. }
  2084. if (!si_iscoreup(bus->sih)) {
  2085. DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
  2086. bcmerror = BCME_ERROR;
  2087. goto fail;
  2088. }
  2089. if ((bcmerror = dhdsdio_write_vars(bus))) {
  2090. DHD_ERROR(("%s: no vars written to RAM\n", __FUNCTION__));
  2091. bcmerror = 0;
  2092. }
  2093. if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
  2094. !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
  2095. DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
  2096. bcmerror = BCME_ERROR;
  2097. goto fail;
  2098. }
  2099. W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
  2100. if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
  2101. !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
  2102. DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
  2103. bcmerror = BCME_ERROR;
  2104. goto fail;
  2105. }
  2106. si_core_reset(bus->sih, 0, 0);
  2107. if (bcmsdh_regfail(bus->sdh)) {
  2108. DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
  2109. bcmerror = BCME_SDIO_ERROR;
  2110. goto fail;
  2111. }
  2112. /* Allow HT Clock now that the ARM is running. */
  2113. bus->alp_only = FALSE;
  2114. bus->dhd->busstate = DHD_BUS_LOAD;
  2115. }
  2116. fail:
  2117. /* Always return to SDIOD core */
  2118. if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
  2119. si_setcore(bus->sih, SDIOD_CORE_ID, 0);
  2120. return bcmerror;
  2121. }
  2122. int
  2123. dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
  2124. void *params, int plen, void *arg, int len, bool set)
  2125. {
  2126. dhd_bus_t *bus = dhdp->bus;
  2127. const bcm_iovar_t *vi = NULL;
  2128. int bcmerror = 0;
  2129. int val_size;
  2130. uint32 actionid;
  2131. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2132. ASSERT(name);
  2133. ASSERT(len >= 0);
  2134. /* Get MUST have return space */
  2135. ASSERT(set || (arg && len));
  2136. /* Set does NOT take qualifiers */
  2137. ASSERT(!set || (!params && !plen));
  2138. /* Look up var locally; if not found pass to host driver */
  2139. if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
  2140. dhd_os_sdlock(bus->dhd);
  2141. BUS_WAKE(bus);
  2142. /* Turn on clock in case SD command needs backplane */
  2143. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  2144. bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
  2145. /* Check for bus configuration changes of interest */
  2146. /* If it was divisor change, read the new one */
  2147. if (set && strcmp(name, "sd_divisor") == 0) {
  2148. if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
  2149. &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
  2150. bus->sd_divisor = -1;
  2151. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
  2152. } else {
  2153. DHD_INFO(("%s: noted %s update, value now %d\n",
  2154. __FUNCTION__, name, bus->sd_divisor));
  2155. }
  2156. }
  2157. /* If it was a mode change, read the new one */
  2158. if (set && strcmp(name, "sd_mode") == 0) {
  2159. if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
  2160. &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
  2161. bus->sd_mode = -1;
  2162. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
  2163. } else {
  2164. DHD_INFO(("%s: noted %s update, value now %d\n",
  2165. __FUNCTION__, name, bus->sd_mode));
  2166. }
  2167. }
  2168. /* Similar check for blocksize change */
  2169. if (set && strcmp(name, "sd_blocksize") == 0) {
  2170. int32 fnum = 2;
  2171. if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
  2172. &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
  2173. bus->blocksize = 0;
  2174. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
  2175. } else {
  2176. DHD_INFO(("%s: noted %s update, value now %d\n",
  2177. __FUNCTION__, "sd_blocksize", bus->blocksize));
  2178. }
  2179. }
  2180. bus->roundup = MIN(max_roundup, bus->blocksize);
  2181. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  2182. bus->activity = FALSE;
  2183. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  2184. }
  2185. dhd_os_sdunlock(bus->dhd);
  2186. goto exit;
  2187. }
  2188. DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
  2189. name, (set ? "set" : "get"), len, plen));
  2190. /* set up 'params' pointer in case this is a set command so that
  2191. * the convenience int and bool code can be common to set and get
  2192. */
  2193. if (params == NULL) {
  2194. params = arg;
  2195. plen = len;
  2196. }
  2197. if (vi->type == IOVT_VOID)
  2198. val_size = 0;
  2199. else if (vi->type == IOVT_BUFFER)
  2200. val_size = len;
  2201. else
  2202. /* all other types are integer sized */
  2203. val_size = sizeof(int);
  2204. actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
  2205. bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
  2206. exit:
  2207. return bcmerror;
  2208. }
  2209. void
  2210. dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
  2211. {
  2212. osl_t *osh = bus->dhd->osh;
  2213. uint32 local_hostintmask;
  2214. uint8 saveclk;
  2215. uint retries;
  2216. int err;
  2217. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2218. if (enforce_mutex)
  2219. dhd_os_sdlock(bus->dhd);
  2220. BUS_WAKE(bus);
  2221. /* Change our idea of bus state */
  2222. bus->dhd->busstate = DHD_BUS_DOWN;
  2223. /* Enable clock for device interrupts */
  2224. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  2225. /* Disable and clear interrupts at the chip level also */
  2226. W_SDREG(0, &bus->regs->hostintmask, retries);
  2227. local_hostintmask = bus->hostintmask;
  2228. bus->hostintmask = 0;
  2229. /* Force clocks on backplane to be sure F2 interrupt propagates */
  2230. saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  2231. if (!err) {
  2232. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  2233. (saveclk | SBSDIO_FORCE_HT), &err);
  2234. }
  2235. if (err) {
  2236. DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
  2237. }
  2238. /* Turn off the bus (F2), free any pending packets */
  2239. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  2240. bcmsdh_intr_disable(bus->sdh);
  2241. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
  2242. /* Clear any pending interrupts now that F2 is disabled */
  2243. W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
  2244. /* Turn off the backplane clock (only) */
  2245. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  2246. /* Clear the data packet queues */
  2247. pktq_flush(osh, &bus->txq, TRUE);
  2248. /* Clear any held glomming stuff */
  2249. if (bus->glomd)
  2250. PKTFREE(osh, bus->glomd, FALSE);
  2251. if (bus->glom)
  2252. PKTFREE(osh, bus->glom, FALSE);
  2253. bus->glom = bus->glomd = NULL;
  2254. /* Clear rx control and wake any waiters */
  2255. bus->rxlen = 0;
  2256. dhd_os_ioctl_resp_wake(bus->dhd);
  2257. /* Reset some F2 state stuff */
  2258. bus->rxskip = FALSE;
  2259. bus->tx_seq = bus->rx_seq = 0;
  2260. if (enforce_mutex)
  2261. dhd_os_sdunlock(bus->dhd);
  2262. }
  2263. int
  2264. dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
  2265. {
  2266. dhd_bus_t *bus = dhdp->bus;
  2267. dhd_timeout_t tmo;
  2268. uint retries = 0;
  2269. uint8 ready, enable;
  2270. int err, ret = BCME_ERROR;
  2271. uint8 saveclk;
  2272. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2273. ASSERT(bus->dhd);
  2274. if (!bus->dhd)
  2275. return BCME_OK;
  2276. if (enforce_mutex)
  2277. dhd_os_sdlock(bus->dhd);
  2278. /* Make sure backplane clock is on, needed to generate F2 interrupt */
  2279. err = dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  2280. if ((err != BCME_OK) || (bus->clkstate != CLK_AVAIL)) {
  2281. DHD_ERROR(("%s: Failed to set backplane clock: err %d\n", __FUNCTION__, err));
  2282. goto exit;
  2283. }
  2284. /* Force clocks on backplane to be sure F2 interrupt propagates */
  2285. saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  2286. if (!err) {
  2287. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  2288. (saveclk | SBSDIO_FORCE_HT), &err);
  2289. }
  2290. if (err) {
  2291. DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
  2292. goto exit;
  2293. }
  2294. /* Enable function 2 (frame transfers) */
  2295. W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
  2296. &bus->regs->tosbmailboxdata, retries);
  2297. enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
  2298. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
  2299. /* Give the dongle some time to do its thing and set IOR2 */
  2300. dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
  2301. ready = 0;
  2302. while (ready != enable && !dhd_timeout_expired(&tmo))
  2303. ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
  2304. DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
  2305. __FUNCTION__, enable, ready, tmo.elapsed));
  2306. /* If F2 successfully enabled, set core and enable interrupts */
  2307. if (ready == enable) {
  2308. /* Make sure we're talking to the core. */
  2309. if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
  2310. bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
  2311. /* Set up the interrupt mask and enable interrupts */
  2312. bus->hostintmask = HOSTINTMASK;
  2313. W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
  2314. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err);
  2315. /* Set bus state according to enable result */
  2316. dhdp->busstate = DHD_BUS_DATA;
  2317. /* bcmsdh_intr_unmask(bus->sdh); */
  2318. bus->intdis = FALSE;
  2319. if (bus->intr) {
  2320. DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
  2321. bcmsdh_intr_enable(bus->sdh);
  2322. } else {
  2323. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  2324. bcmsdh_intr_disable(bus->sdh);
  2325. }
  2326. }
  2327. else {
  2328. /* Disable F2 again */
  2329. enable = SDIO_FUNC_ENABLE_1;
  2330. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
  2331. }
  2332. /* Restore previous clock setting */
  2333. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
  2334. /* If we didn't come up, turn off backplane clock */
  2335. if (dhdp->busstate != DHD_BUS_DATA)
  2336. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  2337. ret = BCME_OK;
  2338. exit:
  2339. if (enforce_mutex)
  2340. dhd_os_sdunlock(bus->dhd);
  2341. return ret;
  2342. }
  2343. static void
  2344. dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
  2345. {
  2346. bcmsdh_info_t *sdh = bus->sdh;
  2347. sdpcmd_regs_t *regs = bus->regs;
  2348. uint retries = 0;
  2349. uint16 lastrbc;
  2350. uint8 hi, lo;
  2351. int err;
  2352. DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
  2353. (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
  2354. if (abort) {
  2355. bcmsdh_abort(sdh, SDIO_FUNC_2);
  2356. }
  2357. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
  2358. bus->f1regdata++;
  2359. /* Wait until the packet has been flushed (device/FIFO stable) */
  2360. for (lastrbc = retries = 0xffff; retries > 0; retries--) {
  2361. hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
  2362. lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL);
  2363. bus->f1regdata += 2;
  2364. if ((hi == 0) && (lo == 0))
  2365. break;
  2366. if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
  2367. DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
  2368. __FUNCTION__, lastrbc, ((hi << 8) + lo)));
  2369. }
  2370. lastrbc = (hi << 8) + lo;
  2371. }
  2372. if (!retries) {
  2373. DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
  2374. } else {
  2375. DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
  2376. }
  2377. if (rtx) {
  2378. bus->rxrtx++;
  2379. W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
  2380. bus->f1regdata++;
  2381. if (retries <= retry_limit) {
  2382. bus->rxskip = TRUE;
  2383. }
  2384. }
  2385. /* Clear partial in any case */
  2386. bus->nextlen = 0;
  2387. /* If we can't reach the device, signal failure */
  2388. if (err || bcmsdh_regfail(sdh))
  2389. bus->dhd->busstate = DHD_BUS_DOWN;
  2390. }
  2391. static void
  2392. dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
  2393. {
  2394. bcmsdh_info_t *sdh = bus->sdh;
  2395. uint rdlen, pad;
  2396. int sdret;
  2397. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2398. /* Control data already received in aligned rxctl */
  2399. if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
  2400. goto gotpkt;
  2401. ASSERT(bus->rxbuf);
  2402. /* Set rxctl for frame (w/optional alignment) */
  2403. bus->rxctl = bus->rxbuf;
  2404. if (dhd_alignctl) {
  2405. bus->rxctl += firstread;
  2406. if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
  2407. bus->rxctl += (DHD_SDALIGN - pad);
  2408. bus->rxctl -= firstread;
  2409. }
  2410. ASSERT(bus->rxctl >= bus->rxbuf);
  2411. /* Copy the already-read portion over */
  2412. bcopy(hdr, bus->rxctl, firstread);
  2413. if (len <= firstread)
  2414. goto gotpkt;
  2415. /* Copy the full data pkt in gSPI case and process ioctl. */
  2416. if (bus->bus == SPI_BUS) {
  2417. bcopy(hdr, bus->rxctl, len);
  2418. goto gotpkt;
  2419. }
  2420. /* Raise rdlen to next SDIO block to avoid tail command */
  2421. rdlen = len - firstread;
  2422. if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
  2423. pad = bus->blocksize - (rdlen % bus->blocksize);
  2424. if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
  2425. ((len + pad) < bus->dhd->maxctl))
  2426. rdlen += pad;
  2427. } else if (rdlen % DHD_SDALIGN) {
  2428. rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
  2429. }
  2430. /* Satisfy length-alignment requirements */
  2431. if (forcealign && (rdlen & (ALIGNMENT - 1)))
  2432. rdlen = ROUNDUP(rdlen, ALIGNMENT);
  2433. /* Drop if the read is too big or it exceeds our maximum */
  2434. if ((rdlen + firstread) > bus->dhd->maxctl) {
  2435. DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
  2436. __FUNCTION__, rdlen, bus->dhd->maxctl));
  2437. bus->dhd->rx_errors++;
  2438. dhdsdio_rxfail(bus, FALSE, FALSE);
  2439. goto done;
  2440. }
  2441. if ((len - doff) > bus->dhd->maxctl) {
  2442. DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
  2443. __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
  2444. bus->dhd->rx_errors++; bus->rx_toolong++;
  2445. dhdsdio_rxfail(bus, FALSE, FALSE);
  2446. goto done;
  2447. }
  2448. /* Read remainder of frame body into the rxctl buffer */
  2449. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  2450. (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
  2451. bus->f2rxdata++;
  2452. ASSERT(sdret != BCME_PENDING);
  2453. /* Control frame failures need retransmission */
  2454. if (sdret < 0) {
  2455. DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
  2456. bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
  2457. dhdsdio_rxfail(bus, TRUE, TRUE);
  2458. goto done;
  2459. }
  2460. gotpkt:
  2461. #ifdef DHD_DEBUG
  2462. if (DHD_BYTES_ON() && DHD_CTL_ON()) {
  2463. prhex("RxCtrl", bus->rxctl, len);
  2464. }
  2465. #endif
  2466. /* Point to valid data and indicate its length */
  2467. bus->rxctl += doff;
  2468. bus->rxlen = len - doff;
  2469. done:
  2470. /* Awake any waiters */
  2471. dhd_os_ioctl_resp_wake(bus->dhd);
  2472. }
  2473. static uint8
  2474. dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
  2475. {
  2476. uint16 dlen, totlen;
  2477. uint8 *dptr, num = 0;
  2478. uint16 sublen, check;
  2479. void *pfirst, *plast, *pnext, *save_pfirst;
  2480. osl_t *osh = bus->dhd->osh;
  2481. int errcode;
  2482. uint8 chan, seq, doff, sfdoff;
  2483. uint8 txmax;
  2484. int ifidx = 0;
  2485. bool usechain = bus->use_rxchain;
  2486. /* If packets, issue read(s) and send up packet chain */
  2487. /* Return sequence numbers consumed? */
  2488. DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
  2489. /* If there's a descriptor, generate the packet chain */
  2490. if (bus->glomd) {
  2491. dhd_os_sdlock_rxq(bus->dhd);
  2492. pfirst = plast = pnext = NULL;
  2493. dlen = (uint16)PKTLEN(osh, bus->glomd);
  2494. dptr = PKTDATA(osh, bus->glomd);
  2495. if (!dlen || (dlen & 1)) {
  2496. DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
  2497. __FUNCTION__, dlen));
  2498. dlen = 0;
  2499. }
  2500. for (totlen = num = 0; dlen; num++) {
  2501. /* Get (and move past) next length */
  2502. sublen = ltoh16_ua(dptr);
  2503. dlen -= sizeof(uint16);
  2504. dptr += sizeof(uint16);
  2505. if ((sublen < SDPCM_HDRLEN) ||
  2506. ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
  2507. DHD_ERROR(("%s: descriptor len %d bad: %d\n",
  2508. __FUNCTION__, num, sublen));
  2509. pnext = NULL;
  2510. break;
  2511. }
  2512. if (sublen % DHD_SDALIGN) {
  2513. DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
  2514. __FUNCTION__, sublen, DHD_SDALIGN));
  2515. usechain = FALSE;
  2516. }
  2517. totlen += sublen;
  2518. /* For last frame, adjust read len so total is a block multiple */
  2519. if (!dlen) {
  2520. sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
  2521. totlen = ROUNDUP(totlen, bus->blocksize);
  2522. }
  2523. /* Allocate/chain packet for next subframe */
  2524. if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
  2525. DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
  2526. __FUNCTION__, num, sublen));
  2527. break;
  2528. }
  2529. ASSERT(!PKTLINK(pnext));
  2530. if (!pfirst) {
  2531. ASSERT(!plast);
  2532. pfirst = plast = pnext;
  2533. } else {
  2534. ASSERT(plast);
  2535. PKTSETNEXT(osh, plast, pnext);
  2536. plast = pnext;
  2537. }
  2538. /* Adhere to start alignment requirements */
  2539. PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
  2540. }
  2541. /* If all allocations succeeded, save packet chain in bus structure */
  2542. if (pnext) {
  2543. DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
  2544. __FUNCTION__, totlen, num));
  2545. if (DHD_GLOM_ON() && bus->nextlen) {
  2546. if (totlen != bus->nextlen) {
  2547. DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
  2548. "rxseq %d\n", __FUNCTION__, bus->nextlen,
  2549. totlen, rxseq));
  2550. }
  2551. }
  2552. bus->glom = pfirst;
  2553. pfirst = pnext = NULL;
  2554. } else {
  2555. if (pfirst)
  2556. PKTFREE(osh, pfirst, FALSE);
  2557. bus->glom = NULL;
  2558. num = 0;
  2559. }
  2560. /* Done with descriptor packet */
  2561. PKTFREE(osh, bus->glomd, FALSE);
  2562. bus->glomd = NULL;
  2563. bus->nextlen = 0;
  2564. dhd_os_sdunlock_rxq(bus->dhd);
  2565. }
  2566. /* Ok -- either we just generated a packet chain, or had one from before */
  2567. if (bus->glom) {
  2568. if (DHD_GLOM_ON()) {
  2569. DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
  2570. for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
  2571. DHD_GLOM((" %p: %p len 0x%04x (%d)\n",
  2572. pnext, (uint8*)PKTDATA(osh, pnext),
  2573. PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
  2574. }
  2575. }
  2576. pfirst = bus->glom;
  2577. dlen = (uint16)pkttotlen(osh, pfirst);
  2578. /* Do an SDIO read for the superframe. Configurable iovar to
  2579. * read directly into the chained packet, or allocate a large
  2580. * packet and and copy into the chain.
  2581. */
  2582. if (usechain) {
  2583. errcode = dhd_bcmsdh_recv_buf(bus,
  2584. bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
  2585. F2SYNC, (uint8*)PKTDATA(osh, pfirst),
  2586. dlen, pfirst, NULL, NULL);
  2587. } else if (bus->dataptr) {
  2588. errcode = dhd_bcmsdh_recv_buf(bus,
  2589. bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
  2590. F2SYNC, bus->dataptr,
  2591. dlen, NULL, NULL, NULL);
  2592. sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
  2593. if (sublen != dlen) {
  2594. DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
  2595. __FUNCTION__, dlen, sublen));
  2596. errcode = -1;
  2597. }
  2598. pnext = NULL;
  2599. } else {
  2600. DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
  2601. errcode = -1;
  2602. }
  2603. bus->f2rxdata++;
  2604. ASSERT(errcode != BCME_PENDING);
  2605. /* On failure, kill the superframe, allow a couple retries */
  2606. if (errcode < 0) {
  2607. DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
  2608. __FUNCTION__, dlen, errcode));
  2609. bus->dhd->rx_errors++;
  2610. if (bus->glomerr++ < 3) {
  2611. dhdsdio_rxfail(bus, TRUE, TRUE);
  2612. } else {
  2613. bus->glomerr = 0;
  2614. dhdsdio_rxfail(bus, TRUE, FALSE);
  2615. dhd_os_sdlock_rxq(bus->dhd);
  2616. PKTFREE(osh, bus->glom, FALSE);
  2617. dhd_os_sdunlock_rxq(bus->dhd);
  2618. bus->rxglomfail++;
  2619. bus->glom = NULL;
  2620. }
  2621. return 0;
  2622. }
  2623. #ifdef DHD_DEBUG
  2624. if (DHD_GLOM_ON()) {
  2625. prhex("SUPERFRAME", PKTDATA(osh, pfirst),
  2626. MIN(PKTLEN(osh, pfirst), 48));
  2627. }
  2628. #endif
  2629. /* Validate the superframe header */
  2630. dptr = (uint8 *)PKTDATA(osh, pfirst);
  2631. sublen = ltoh16_ua(dptr);
  2632. check = ltoh16_ua(dptr + sizeof(uint16));
  2633. chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
  2634. seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
  2635. bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
  2636. if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
  2637. DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
  2638. __FUNCTION__, bus->nextlen, seq));
  2639. bus->nextlen = 0;
  2640. }
  2641. doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  2642. txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  2643. errcode = 0;
  2644. if ((uint16)~(sublen^check)) {
  2645. DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
  2646. __FUNCTION__, sublen, check));
  2647. errcode = -1;
  2648. } else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
  2649. DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
  2650. __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
  2651. errcode = -1;
  2652. } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
  2653. DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
  2654. SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
  2655. errcode = -1;
  2656. } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
  2657. DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
  2658. errcode = -1;
  2659. } else if ((doff < SDPCM_HDRLEN) ||
  2660. (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
  2661. DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
  2662. __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst), SDPCM_HDRLEN));
  2663. errcode = -1;
  2664. }
  2665. /* Check sequence number of superframe SW header */
  2666. if (rxseq != seq) {
  2667. DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
  2668. __FUNCTION__, seq, rxseq));
  2669. bus->rx_badseq++;
  2670. rxseq = seq;
  2671. }
  2672. /* Check window for sanity */
  2673. if ((uint8)(txmax - bus->tx_seq) > 0x40) {
  2674. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  2675. __FUNCTION__, txmax, bus->tx_seq));
  2676. txmax = bus->tx_seq + 2;
  2677. }
  2678. bus->tx_max = txmax;
  2679. /* Remove superframe header, remember offset */
  2680. PKTPULL(osh, pfirst, doff);
  2681. sfdoff = doff;
  2682. /* Validate all the subframe headers */
  2683. for (num = 0, pnext = pfirst; pnext && !errcode;
  2684. num++, pnext = PKTNEXT(osh, pnext)) {
  2685. dptr = (uint8 *)PKTDATA(osh, pnext);
  2686. dlen = (uint16)PKTLEN(osh, pnext);
  2687. sublen = ltoh16_ua(dptr);
  2688. check = ltoh16_ua(dptr + sizeof(uint16));
  2689. chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
  2690. doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  2691. #ifdef DHD_DEBUG
  2692. if (DHD_GLOM_ON()) {
  2693. prhex("subframe", dptr, 32);
  2694. }
  2695. #endif
  2696. if ((uint16)~(sublen^check)) {
  2697. DHD_ERROR(("%s (subframe %d): HW hdr error: "
  2698. "len/check 0x%04x/0x%04x\n",
  2699. __FUNCTION__, num, sublen, check));
  2700. errcode = -1;
  2701. } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
  2702. DHD_ERROR(("%s (subframe %d): length mismatch: "
  2703. "len 0x%04x, expect 0x%04x\n",
  2704. __FUNCTION__, num, sublen, dlen));
  2705. errcode = -1;
  2706. } else if ((chan != SDPCM_DATA_CHANNEL) &&
  2707. (chan != SDPCM_EVENT_CHANNEL)) {
  2708. DHD_ERROR(("%s (subframe %d): bad channel %d\n",
  2709. __FUNCTION__, num, chan));
  2710. errcode = -1;
  2711. } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
  2712. DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
  2713. __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
  2714. errcode = -1;
  2715. }
  2716. }
  2717. if (errcode) {
  2718. /* Terminate frame on error, request a couple retries */
  2719. if (bus->glomerr++ < 3) {
  2720. /* Restore superframe header space */
  2721. PKTPUSH(osh, pfirst, sfdoff);
  2722. dhdsdio_rxfail(bus, TRUE, TRUE);
  2723. } else {
  2724. bus->glomerr = 0;
  2725. dhdsdio_rxfail(bus, TRUE, FALSE);
  2726. dhd_os_sdlock_rxq(bus->dhd);
  2727. PKTFREE(osh, bus->glom, FALSE);
  2728. dhd_os_sdunlock_rxq(bus->dhd);
  2729. bus->rxglomfail++;
  2730. bus->glom = NULL;
  2731. }
  2732. bus->nextlen = 0;
  2733. return 0;
  2734. }
  2735. /* Basic SD framing looks ok - process each packet (header) */
  2736. save_pfirst = pfirst;
  2737. bus->glom = NULL;
  2738. plast = NULL;
  2739. dhd_os_sdlock_rxq(bus->dhd);
  2740. for (num = 0; pfirst; rxseq++, pfirst = pnext) {
  2741. pnext = PKTNEXT(osh, pfirst);
  2742. PKTSETNEXT(osh, pfirst, NULL);
  2743. dptr = (uint8 *)PKTDATA(osh, pfirst);
  2744. sublen = ltoh16_ua(dptr);
  2745. chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
  2746. seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
  2747. doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  2748. DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
  2749. __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
  2750. PKTLEN(osh, pfirst), sublen, chan, seq));
  2751. ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
  2752. if (rxseq != seq) {
  2753. DHD_GLOM(("%s: rx_seq %d, expected %d\n",
  2754. __FUNCTION__, seq, rxseq));
  2755. bus->rx_badseq++;
  2756. rxseq = seq;
  2757. }
  2758. #ifdef DHD_DEBUG
  2759. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  2760. prhex("Rx Subframe Data", dptr, dlen);
  2761. }
  2762. #endif
  2763. PKTSETLEN(osh, pfirst, sublen);
  2764. PKTPULL(osh, pfirst, doff);
  2765. if (PKTLEN(osh, pfirst) == 0) {
  2766. PKTFREE(bus->dhd->osh, pfirst, FALSE);
  2767. if (plast) {
  2768. PKTSETNEXT(osh, plast, pnext);
  2769. } else {
  2770. ASSERT(save_pfirst == pfirst);
  2771. save_pfirst = pnext;
  2772. }
  2773. continue;
  2774. } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) != 0) {
  2775. DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
  2776. bus->dhd->rx_errors++;
  2777. PKTFREE(osh, pfirst, FALSE);
  2778. if (plast) {
  2779. PKTSETNEXT(osh, plast, pnext);
  2780. } else {
  2781. ASSERT(save_pfirst == pfirst);
  2782. save_pfirst = pnext;
  2783. }
  2784. continue;
  2785. }
  2786. /* this packet will go up, link back into chain and count it */
  2787. PKTSETNEXT(osh, pfirst, pnext);
  2788. plast = pfirst;
  2789. num++;
  2790. #ifdef DHD_DEBUG
  2791. if (DHD_GLOM_ON()) {
  2792. DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
  2793. __FUNCTION__, num, pfirst,
  2794. PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
  2795. PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
  2796. prhex("", (uint8 *)PKTDATA(osh, pfirst),
  2797. MIN(PKTLEN(osh, pfirst), 32));
  2798. }
  2799. #endif /* DHD_DEBUG */
  2800. }
  2801. dhd_os_sdunlock_rxq(bus->dhd);
  2802. if (num) {
  2803. dhd_os_sdunlock(bus->dhd);
  2804. dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num);
  2805. dhd_os_sdlock(bus->dhd);
  2806. }
  2807. bus->rxglomframes++;
  2808. bus->rxglompkts += num;
  2809. }
  2810. return num;
  2811. }
  2812. /* Return TRUE if there may be more frames to read */
  2813. static uint
  2814. dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
  2815. {
  2816. osl_t *osh = bus->dhd->osh;
  2817. bcmsdh_info_t *sdh = bus->sdh;
  2818. uint16 len, check; /* Extracted hardware header fields */
  2819. uint8 chan, seq, doff; /* Extracted software header fields */
  2820. uint8 fcbits; /* Extracted fcbits from software header */
  2821. uint8 delta;
  2822. void *pkt; /* Packet for event or data frames */
  2823. uint16 pad; /* Number of pad bytes to read */
  2824. uint16 rdlen; /* Total number of bytes to read */
  2825. uint8 rxseq; /* Next sequence number to expect */
  2826. uint rxleft = 0; /* Remaining number of frames allowed */
  2827. int sdret; /* Return code from bcmsdh calls */
  2828. uint8 txmax; /* Maximum tx sequence offered */
  2829. bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
  2830. uint8 *rxbuf;
  2831. int ifidx = 0;
  2832. uint rxcount = 0; /* Total frames read */
  2833. #if defined(DHD_DEBUG) || defined(SDTEST)
  2834. bool sdtest = FALSE; /* To limit message spew from test mode */
  2835. #endif
  2836. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2837. ASSERT(maxframes);
  2838. #ifdef SDTEST
  2839. /* Allow pktgen to override maxframes */
  2840. if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
  2841. maxframes = bus->pktgen_count;
  2842. sdtest = TRUE;
  2843. }
  2844. #endif
  2845. /* Not finished unless we encounter no more frames indication */
  2846. *finished = FALSE;
  2847. for (rxseq = bus->rx_seq, rxleft = maxframes;
  2848. !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
  2849. rxseq++, rxleft--) {
  2850. /* Handle glomming separately */
  2851. if (bus->glom || bus->glomd) {
  2852. uint8 cnt;
  2853. DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
  2854. __FUNCTION__, bus->glomd, bus->glom));
  2855. cnt = dhdsdio_rxglom(bus, rxseq);
  2856. DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
  2857. rxseq += cnt - 1;
  2858. rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
  2859. continue;
  2860. }
  2861. /* Try doing single read if we can */
  2862. if (dhd_readahead && bus->nextlen) {
  2863. uint16 nextlen = bus->nextlen;
  2864. bus->nextlen = 0;
  2865. if (bus->bus == SPI_BUS) {
  2866. rdlen = len = nextlen;
  2867. }
  2868. else {
  2869. rdlen = len = nextlen << 4;
  2870. /* Pad read to blocksize for efficiency */
  2871. if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
  2872. pad = bus->blocksize - (rdlen % bus->blocksize);
  2873. if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
  2874. ((rdlen + pad + firstread) < MAX_RX_DATASZ))
  2875. rdlen += pad;
  2876. } else if (rdlen % DHD_SDALIGN) {
  2877. rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
  2878. }
  2879. }
  2880. /* We use bus->rxctl buffer in WinXP for initial control pkt receives.
  2881. * Later we use buffer-poll for data as well as control packets.
  2882. * This is required becuase dhd receives full frame in gSPI unlike SDIO.
  2883. * After the frame is received we have to distinguish whether it is data
  2884. * or non-data frame.
  2885. */
  2886. /* Allocate a packet buffer */
  2887. dhd_os_sdlock_rxq(bus->dhd);
  2888. if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
  2889. if (bus->bus == SPI_BUS) {
  2890. bus->usebufpool = FALSE;
  2891. bus->rxctl = bus->rxbuf;
  2892. if (dhd_alignctl) {
  2893. bus->rxctl += firstread;
  2894. if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
  2895. bus->rxctl += (DHD_SDALIGN - pad);
  2896. bus->rxctl -= firstread;
  2897. }
  2898. ASSERT(bus->rxctl >= bus->rxbuf);
  2899. rxbuf = bus->rxctl;
  2900. /* Read the entire frame */
  2901. sdret = dhd_bcmsdh_recv_buf(bus,
  2902. bcmsdh_cur_sbwad(sdh),
  2903. SDIO_FUNC_2,
  2904. F2SYNC, rxbuf, rdlen,
  2905. NULL, NULL, NULL);
  2906. bus->f2rxdata++;
  2907. ASSERT(sdret != BCME_PENDING);
  2908. /* Control frame failures need retransmission */
  2909. if (sdret < 0) {
  2910. DHD_ERROR(("%s: read %d control bytes failed: %d\n",
  2911. __FUNCTION__, rdlen, sdret));
  2912. /* dhd.rx_ctlerrs is higher level */
  2913. bus->rxc_errors++;
  2914. dhd_os_sdunlock_rxq(bus->dhd);
  2915. dhdsdio_rxfail(bus, TRUE,
  2916. (bus->bus == SPI_BUS) ? FALSE : TRUE);
  2917. continue;
  2918. }
  2919. } else {
  2920. /* Give up on data, request rtx of events */
  2921. DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
  2922. "expected rxseq %d\n",
  2923. __FUNCTION__, len, rdlen, rxseq));
  2924. /* Just go try again w/normal header read */
  2925. dhd_os_sdunlock_rxq(bus->dhd);
  2926. continue;
  2927. }
  2928. } else {
  2929. if (bus->bus == SPI_BUS)
  2930. bus->usebufpool = TRUE;
  2931. ASSERT(!PKTLINK(pkt));
  2932. PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
  2933. rxbuf = (uint8 *)PKTDATA(osh, pkt);
  2934. /* Read the entire frame */
  2935. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
  2936. SDIO_FUNC_2,
  2937. F2SYNC, rxbuf, rdlen,
  2938. pkt, NULL, NULL);
  2939. bus->f2rxdata++;
  2940. ASSERT(sdret != BCME_PENDING);
  2941. if (sdret < 0) {
  2942. DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
  2943. __FUNCTION__, rdlen, sdret));
  2944. PKTFREE(bus->dhd->osh, pkt, FALSE);
  2945. bus->dhd->rx_errors++;
  2946. dhd_os_sdunlock_rxq(bus->dhd);
  2947. /* Force retry w/normal header read. Don't attemp NAK for
  2948. * gSPI
  2949. */
  2950. dhdsdio_rxfail(bus, TRUE,
  2951. (bus->bus == SPI_BUS) ? FALSE : TRUE);
  2952. continue;
  2953. }
  2954. }
  2955. dhd_os_sdunlock_rxq(bus->dhd);
  2956. /* Now check the header */
  2957. bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
  2958. /* Extract hardware header fields */
  2959. len = ltoh16_ua(bus->rxhdr);
  2960. check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
  2961. /* All zeros means readahead info was bad */
  2962. if (!(len|check)) {
  2963. DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
  2964. __FUNCTION__));
  2965. dhd_os_sdlock_rxq(bus->dhd);
  2966. PKTFREE2();
  2967. dhd_os_sdunlock_rxq(bus->dhd);
  2968. GSPI_PR55150_BAILOUT;
  2969. continue;
  2970. }
  2971. /* Validate check bytes */
  2972. if ((uint16)~(len^check)) {
  2973. DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
  2974. " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
  2975. len, check));
  2976. dhd_os_sdlock_rxq(bus->dhd);
  2977. PKTFREE2();
  2978. dhd_os_sdunlock_rxq(bus->dhd);
  2979. bus->rx_badhdr++;
  2980. dhdsdio_rxfail(bus, FALSE, FALSE);
  2981. GSPI_PR55150_BAILOUT;
  2982. continue;
  2983. }
  2984. /* Validate frame length */
  2985. if (len < SDPCM_HDRLEN) {
  2986. DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
  2987. __FUNCTION__, len));
  2988. dhd_os_sdlock_rxq(bus->dhd);
  2989. PKTFREE2();
  2990. dhd_os_sdunlock_rxq(bus->dhd);
  2991. GSPI_PR55150_BAILOUT;
  2992. continue;
  2993. }
  2994. /* Check for consistency with readahead info */
  2995. len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
  2996. if (len_consistent) {
  2997. /* Mismatch, force retry w/normal header (may be >4K) */
  2998. DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
  2999. "expected rxseq %d\n",
  3000. __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
  3001. dhd_os_sdlock_rxq(bus->dhd);
  3002. PKTFREE2();
  3003. dhd_os_sdunlock_rxq(bus->dhd);
  3004. dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
  3005. GSPI_PR55150_BAILOUT;
  3006. continue;
  3007. }
  3008. /* Extract software header fields */
  3009. chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3010. seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3011. doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3012. txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3013. bus->nextlen =
  3014. bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
  3015. if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
  3016. DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
  3017. " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
  3018. seq));
  3019. bus->nextlen = 0;
  3020. }
  3021. bus->dhd->rx_readahead_cnt ++;
  3022. /* Handle Flow Control */
  3023. fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3024. delta = 0;
  3025. if (~bus->flowcontrol & fcbits) {
  3026. bus->fc_xoff++;
  3027. delta = 1;
  3028. }
  3029. if (bus->flowcontrol & ~fcbits) {
  3030. bus->fc_xon++;
  3031. delta = 1;
  3032. }
  3033. if (delta) {
  3034. bus->fc_rcvd++;
  3035. bus->flowcontrol = fcbits;
  3036. }
  3037. /* Check and update sequence number */
  3038. if (rxseq != seq) {
  3039. DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
  3040. __FUNCTION__, seq, rxseq));
  3041. bus->rx_badseq++;
  3042. rxseq = seq;
  3043. }
  3044. /* Check window for sanity */
  3045. if ((uint8)(txmax - bus->tx_seq) > 0x40) {
  3046. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  3047. __FUNCTION__, txmax, bus->tx_seq));
  3048. txmax = bus->tx_seq + 2;
  3049. }
  3050. bus->tx_max = txmax;
  3051. #ifdef DHD_DEBUG
  3052. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  3053. prhex("Rx Data", rxbuf, len);
  3054. } else if (DHD_HDRS_ON()) {
  3055. prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
  3056. }
  3057. #endif
  3058. if (chan == SDPCM_CONTROL_CHANNEL) {
  3059. if (bus->bus == SPI_BUS) {
  3060. dhdsdio_read_control(bus, rxbuf, len, doff);
  3061. if (bus->usebufpool) {
  3062. dhd_os_sdlock_rxq(bus->dhd);
  3063. PKTFREE(bus->dhd->osh, pkt, FALSE);
  3064. dhd_os_sdunlock_rxq(bus->dhd);
  3065. }
  3066. continue;
  3067. } else {
  3068. DHD_ERROR(("%s (nextlen): readahead on control"
  3069. " packet %d?\n", __FUNCTION__, seq));
  3070. /* Force retry w/normal header read */
  3071. bus->nextlen = 0;
  3072. dhdsdio_rxfail(bus, FALSE, TRUE);
  3073. dhd_os_sdlock_rxq(bus->dhd);
  3074. PKTFREE2();
  3075. dhd_os_sdunlock_rxq(bus->dhd);
  3076. continue;
  3077. }
  3078. }
  3079. if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
  3080. DHD_ERROR(("Received %d bytes on %d channel. Running out of "
  3081. "rx pktbuf's or not yet malloced.\n", len, chan));
  3082. continue;
  3083. }
  3084. /* Validate data offset */
  3085. if ((doff < SDPCM_HDRLEN) || (doff > len)) {
  3086. DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
  3087. __FUNCTION__, doff, len, SDPCM_HDRLEN));
  3088. dhd_os_sdlock_rxq(bus->dhd);
  3089. PKTFREE2();
  3090. dhd_os_sdunlock_rxq(bus->dhd);
  3091. ASSERT(0);
  3092. dhdsdio_rxfail(bus, FALSE, FALSE);
  3093. continue;
  3094. }
  3095. /* All done with this one -- now deliver the packet */
  3096. goto deliver;
  3097. }
  3098. /* gSPI frames should not be handled in fractions */
  3099. if (bus->bus == SPI_BUS) {
  3100. break;
  3101. }
  3102. /* Read frame header (hardware and software) */
  3103. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  3104. bus->rxhdr, firstread, NULL, NULL, NULL);
  3105. bus->f2rxhdrs++;
  3106. ASSERT(sdret != BCME_PENDING);
  3107. if (sdret < 0) {
  3108. DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
  3109. bus->rx_hdrfail++;
  3110. dhdsdio_rxfail(bus, TRUE, TRUE);
  3111. continue;
  3112. }
  3113. #ifdef DHD_DEBUG
  3114. if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
  3115. prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
  3116. }
  3117. #endif
  3118. /* Extract hardware header fields */
  3119. len = ltoh16_ua(bus->rxhdr);
  3120. check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
  3121. /* All zeros means no more frames */
  3122. if (!(len|check)) {
  3123. *finished = TRUE;
  3124. break;
  3125. }
  3126. /* Validate check bytes */
  3127. if ((uint16)~(len^check)) {
  3128. DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
  3129. __FUNCTION__, len, check));
  3130. bus->rx_badhdr++;
  3131. dhdsdio_rxfail(bus, FALSE, FALSE);
  3132. continue;
  3133. }
  3134. /* Validate frame length */
  3135. if (len < SDPCM_HDRLEN) {
  3136. DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
  3137. continue;
  3138. }
  3139. /* Extract software header fields */
  3140. chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3141. seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3142. doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3143. txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3144. /* Validate data offset */
  3145. if ((doff < SDPCM_HDRLEN) || (doff > len)) {
  3146. DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
  3147. __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
  3148. bus->rx_badhdr++;
  3149. ASSERT(0);
  3150. dhdsdio_rxfail(bus, FALSE, FALSE);
  3151. continue;
  3152. }
  3153. /* Save the readahead length if there is one */
  3154. bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
  3155. if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
  3156. DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
  3157. __FUNCTION__, bus->nextlen, seq));
  3158. bus->nextlen = 0;
  3159. }
  3160. /* Handle Flow Control */
  3161. fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  3162. delta = 0;
  3163. if (~bus->flowcontrol & fcbits) {
  3164. bus->fc_xoff++;
  3165. delta = 1;
  3166. }
  3167. if (bus->flowcontrol & ~fcbits) {
  3168. bus->fc_xon++;
  3169. delta = 1;
  3170. }
  3171. if (delta) {
  3172. bus->fc_rcvd++;
  3173. bus->flowcontrol = fcbits;
  3174. }
  3175. /* Check and update sequence number */
  3176. if (rxseq != seq) {
  3177. DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
  3178. bus->rx_badseq++;
  3179. rxseq = seq;
  3180. }
  3181. /* Check window for sanity */
  3182. if ((uint8)(txmax - bus->tx_seq) > 0x40) {
  3183. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  3184. __FUNCTION__, txmax, bus->tx_seq));
  3185. txmax = bus->tx_seq + 2;
  3186. }
  3187. bus->tx_max = txmax;
  3188. /* Call a separate function for control frames */
  3189. if (chan == SDPCM_CONTROL_CHANNEL) {
  3190. dhdsdio_read_control(bus, bus->rxhdr, len, doff);
  3191. continue;
  3192. }
  3193. ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
  3194. (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
  3195. /* Length to read */
  3196. rdlen = (len > firstread) ? (len - firstread) : 0;
  3197. /* May pad read to blocksize for efficiency */
  3198. if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
  3199. pad = bus->blocksize - (rdlen % bus->blocksize);
  3200. if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
  3201. ((rdlen + pad + firstread) < MAX_RX_DATASZ))
  3202. rdlen += pad;
  3203. } else if (rdlen % DHD_SDALIGN) {
  3204. rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
  3205. }
  3206. /* Satisfy length-alignment requirements */
  3207. if (forcealign && (rdlen & (ALIGNMENT - 1)))
  3208. rdlen = ROUNDUP(rdlen, ALIGNMENT);
  3209. if ((rdlen + firstread) > MAX_RX_DATASZ) {
  3210. /* Too long -- skip this frame */
  3211. DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
  3212. bus->dhd->rx_errors++; bus->rx_toolong++;
  3213. dhdsdio_rxfail(bus, FALSE, FALSE);
  3214. continue;
  3215. }
  3216. dhd_os_sdlock_rxq(bus->dhd);
  3217. if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
  3218. /* Give up on data, request rtx of events */
  3219. DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
  3220. __FUNCTION__, rdlen, chan));
  3221. bus->dhd->rx_dropped++;
  3222. dhd_os_sdunlock_rxq(bus->dhd);
  3223. dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
  3224. continue;
  3225. }
  3226. dhd_os_sdunlock_rxq(bus->dhd);
  3227. ASSERT(!PKTLINK(pkt));
  3228. /* Leave room for what we already read, and align remainder */
  3229. ASSERT(firstread < (PKTLEN(osh, pkt)));
  3230. PKTPULL(osh, pkt, firstread);
  3231. PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
  3232. /* Read the remaining frame data */
  3233. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  3234. ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
  3235. bus->f2rxdata++;
  3236. ASSERT(sdret != BCME_PENDING);
  3237. if (sdret < 0) {
  3238. DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
  3239. ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
  3240. ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
  3241. dhd_os_sdlock_rxq(bus->dhd);
  3242. PKTFREE(bus->dhd->osh, pkt, FALSE);
  3243. dhd_os_sdunlock_rxq(bus->dhd);
  3244. bus->dhd->rx_errors++;
  3245. dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
  3246. continue;
  3247. }
  3248. /* Copy the already-read portion */
  3249. PKTPUSH(osh, pkt, firstread);
  3250. bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
  3251. #ifdef DHD_DEBUG
  3252. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  3253. prhex("Rx Data", PKTDATA(osh, pkt), len);
  3254. }
  3255. #endif
  3256. deliver:
  3257. /* Save superframe descriptor and allocate packet frame */
  3258. if (chan == SDPCM_GLOM_CHANNEL) {
  3259. if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
  3260. DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
  3261. __FUNCTION__, len));
  3262. #ifdef DHD_DEBUG
  3263. if (DHD_GLOM_ON()) {
  3264. prhex("Glom Data", PKTDATA(osh, pkt), len);
  3265. }
  3266. #endif
  3267. PKTSETLEN(osh, pkt, len);
  3268. ASSERT(doff == SDPCM_HDRLEN);
  3269. PKTPULL(osh, pkt, SDPCM_HDRLEN);
  3270. bus->glomd = pkt;
  3271. } else {
  3272. DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
  3273. dhdsdio_rxfail(bus, FALSE, FALSE);
  3274. }
  3275. continue;
  3276. }
  3277. /* Fill in packet len and prio, deliver upward */
  3278. PKTSETLEN(osh, pkt, len);
  3279. PKTPULL(osh, pkt, doff);
  3280. #ifdef SDTEST
  3281. /* Test channel packets are processed separately */
  3282. if (chan == SDPCM_TEST_CHANNEL) {
  3283. dhdsdio_testrcv(bus, pkt, seq);
  3284. continue;
  3285. }
  3286. #endif /* SDTEST */
  3287. if (PKTLEN(osh, pkt) == 0) {
  3288. dhd_os_sdlock_rxq(bus->dhd);
  3289. PKTFREE(bus->dhd->osh, pkt, FALSE);
  3290. dhd_os_sdunlock_rxq(bus->dhd);
  3291. continue;
  3292. } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
  3293. DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
  3294. dhd_os_sdlock_rxq(bus->dhd);
  3295. PKTFREE(bus->dhd->osh, pkt, FALSE);
  3296. dhd_os_sdunlock_rxq(bus->dhd);
  3297. bus->dhd->rx_errors++;
  3298. continue;
  3299. }
  3300. /* Unlock during rx call */
  3301. dhd_os_sdunlock(bus->dhd);
  3302. dhd_rx_frame(bus->dhd, ifidx, pkt, 1);
  3303. dhd_os_sdlock(bus->dhd);
  3304. }
  3305. rxcount = maxframes - rxleft;
  3306. #ifdef DHD_DEBUG
  3307. /* Message if we hit the limit */
  3308. if (!rxleft && !sdtest)
  3309. DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
  3310. else
  3311. #endif /* DHD_DEBUG */
  3312. DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
  3313. /* Back off rxseq if awaiting rtx, update rx_seq */
  3314. if (bus->rxskip)
  3315. rxseq--;
  3316. bus->rx_seq = rxseq;
  3317. return rxcount;
  3318. }
  3319. static uint32
  3320. dhdsdio_hostmail(dhd_bus_t *bus)
  3321. {
  3322. sdpcmd_regs_t *regs = bus->regs;
  3323. uint32 intstatus = 0;
  3324. uint32 hmb_data;
  3325. uint8 fcbits;
  3326. uint retries = 0;
  3327. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3328. /* Read mailbox data and ack that we did so */
  3329. R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
  3330. if (retries <= retry_limit)
  3331. W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
  3332. bus->f1regdata += 2;
  3333. /* Dongle recomposed rx frames, accept them again */
  3334. if (hmb_data & HMB_DATA_NAKHANDLED) {
  3335. DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
  3336. if (!bus->rxskip) {
  3337. DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
  3338. }
  3339. bus->rxskip = FALSE;
  3340. intstatus |= I_HMB_FRAME_IND;
  3341. }
  3342. /*
  3343. * DEVREADY does not occur with gSPI.
  3344. */
  3345. if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
  3346. bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
  3347. if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
  3348. DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
  3349. bus->sdpcm_ver, SDPCM_PROT_VERSION));
  3350. else
  3351. DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
  3352. }
  3353. /*
  3354. * Flow Control has been moved into the RX headers and this out of band
  3355. * method isn't used any more. Leae this here for possibly remaining backward
  3356. * compatible with older dongles
  3357. */
  3358. if (hmb_data & HMB_DATA_FC) {
  3359. fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
  3360. if (fcbits & ~bus->flowcontrol)
  3361. bus->fc_xoff++;
  3362. if (bus->flowcontrol & ~fcbits)
  3363. bus->fc_xon++;
  3364. bus->fc_rcvd++;
  3365. bus->flowcontrol = fcbits;
  3366. }
  3367. /* Shouldn't be any others */
  3368. if (hmb_data & ~(HMB_DATA_DEVREADY |
  3369. HMB_DATA_NAKHANDLED |
  3370. HMB_DATA_FC |
  3371. HMB_DATA_FWREADY |
  3372. HMB_DATA_FCDATA_MASK |
  3373. HMB_DATA_VERSION_MASK)) {
  3374. DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
  3375. }
  3376. return intstatus;
  3377. }
  3378. bool
  3379. dhdsdio_dpc(dhd_bus_t *bus)
  3380. {
  3381. bcmsdh_info_t *sdh = bus->sdh;
  3382. sdpcmd_regs_t *regs = bus->regs;
  3383. uint32 intstatus, newstatus = 0;
  3384. uint retries = 0;
  3385. uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
  3386. uint txlimit = dhd_txbound; /* Tx frames to send before resched */
  3387. uint framecnt = 0; /* Temporary counter of tx/rx frames */
  3388. bool rxdone = TRUE; /* Flag for no more read data */
  3389. bool resched = FALSE; /* Flag indicating resched wanted */
  3390. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3391. /* Start with leftover status bits */
  3392. intstatus = bus->intstatus;
  3393. dhd_os_sdlock(bus->dhd);
  3394. /* If waiting for HTAVAIL, check status */
  3395. if (bus->clkstate == CLK_PENDING) {
  3396. int err;
  3397. uint8 clkctl, devctl = 0;
  3398. #ifdef DHD_DEBUG
  3399. /* Check for inconsistent device control */
  3400. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  3401. if (err) {
  3402. DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
  3403. bus->dhd->busstate = DHD_BUS_DOWN;
  3404. } else {
  3405. ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
  3406. }
  3407. #endif /* DHD_DEBUG */
  3408. /* Read CSR, if clock on switch to AVAIL, else ignore */
  3409. clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  3410. if (err) {
  3411. DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
  3412. bus->dhd->busstate = DHD_BUS_DOWN;
  3413. }
  3414. DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
  3415. if (SBSDIO_HTAV(clkctl)) {
  3416. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  3417. if (err) {
  3418. DHD_ERROR(("%s: error reading DEVCTL: %d\n",
  3419. __FUNCTION__, err));
  3420. bus->dhd->busstate = DHD_BUS_DOWN;
  3421. }
  3422. devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
  3423. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  3424. if (err) {
  3425. DHD_ERROR(("%s: error writing DEVCTL: %d\n",
  3426. __FUNCTION__, err));
  3427. bus->dhd->busstate = DHD_BUS_DOWN;
  3428. }
  3429. bus->clkstate = CLK_AVAIL;
  3430. } else {
  3431. goto clkwait;
  3432. }
  3433. }
  3434. BUS_WAKE(bus);
  3435. /* Make sure backplane clock is on */
  3436. dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
  3437. if (bus->clkstate == CLK_PENDING)
  3438. goto clkwait;
  3439. /* Pending interrupt indicates new device status */
  3440. if (bus->ipend) {
  3441. bus->ipend = FALSE;
  3442. R_SDREG(newstatus, &regs->intstatus, retries);
  3443. bus->f1regdata++;
  3444. if (bcmsdh_regfail(bus->sdh))
  3445. newstatus = 0;
  3446. newstatus &= bus->hostintmask;
  3447. bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
  3448. if (newstatus) {
  3449. W_SDREG(newstatus, &regs->intstatus, retries);
  3450. bus->f1regdata++;
  3451. }
  3452. }
  3453. /* Merge new bits with previous */
  3454. intstatus |= newstatus;
  3455. bus->intstatus = 0;
  3456. /* Handle flow-control change: read new state in case our ack
  3457. * crossed another change interrupt. If change still set, assume
  3458. * FC ON for safety, let next loop through do the debounce.
  3459. */
  3460. if (intstatus & I_HMB_FC_CHANGE) {
  3461. intstatus &= ~I_HMB_FC_CHANGE;
  3462. W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
  3463. R_SDREG(newstatus, &regs->intstatus, retries);
  3464. bus->f1regdata += 2;
  3465. bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
  3466. intstatus |= (newstatus & bus->hostintmask);
  3467. }
  3468. /* Handle host mailbox indication */
  3469. if (intstatus & I_HMB_HOST_INT) {
  3470. intstatus &= ~I_HMB_HOST_INT;
  3471. intstatus |= dhdsdio_hostmail(bus);
  3472. }
  3473. /* Generally don't ask for these, can get CRC errors... */
  3474. if (intstatus & I_WR_OOSYNC) {
  3475. DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
  3476. intstatus &= ~I_WR_OOSYNC;
  3477. }
  3478. if (intstatus & I_RD_OOSYNC) {
  3479. DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
  3480. intstatus &= ~I_RD_OOSYNC;
  3481. }
  3482. if (intstatus & I_SBINT) {
  3483. DHD_ERROR(("Dongle reports SBINT\n"));
  3484. intstatus &= ~I_SBINT;
  3485. }
  3486. /* Would be active due to wake-wlan in gSPI */
  3487. if (intstatus & I_CHIPACTIVE) {
  3488. DHD_INFO(("Dongle reports CHIPACTIVE\n"));
  3489. intstatus &= ~I_CHIPACTIVE;
  3490. }
  3491. /* Ignore frame indications if rxskip is set */
  3492. if (bus->rxskip)
  3493. intstatus &= ~I_HMB_FRAME_IND;
  3494. /* On frame indication, read available frames */
  3495. if (PKT_AVAILABLE()) {
  3496. framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
  3497. if (rxdone || bus->rxskip)
  3498. intstatus &= ~I_HMB_FRAME_IND;
  3499. rxlimit -= MIN(framecnt, rxlimit);
  3500. }
  3501. /* Keep still-pending events for next scheduling */
  3502. bus->intstatus = intstatus;
  3503. clkwait:
  3504. /* Re-enable interrupts to detect new device events (mailbox, rx frame)
  3505. * or clock availability. (Allows tx loop to check ipend if desired.)
  3506. * (Unless register access seems hosed, as we may not be able to ACK...)
  3507. */
  3508. if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
  3509. DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
  3510. __FUNCTION__, rxdone, framecnt));
  3511. bus->intdis = FALSE;
  3512. #if defined(OOB_INTR_ONLY)
  3513. bcmsdh_oob_intr_set(1);
  3514. #endif /* (OOB_INTR_ONLY) */
  3515. bcmsdh_intr_enable(sdh);
  3516. }
  3517. if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
  3518. int ret, i;
  3519. ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  3520. (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
  3521. NULL, NULL, NULL);
  3522. ASSERT(ret != BCME_PENDING);
  3523. if (ret < 0) {
  3524. /* On failure, abort the command and terminate the frame */
  3525. DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
  3526. __FUNCTION__, ret));
  3527. bus->tx_sderrs++;
  3528. bcmsdh_abort(sdh, SDIO_FUNC_2);
  3529. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
  3530. SFC_WF_TERM, NULL);
  3531. bus->f1regdata++;
  3532. for (i = 0; i < 3; i++) {
  3533. uint8 hi, lo;
  3534. hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  3535. SBSDIO_FUNC1_WFRAMEBCHI, NULL);
  3536. lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  3537. SBSDIO_FUNC1_WFRAMEBCLO, NULL);
  3538. bus->f1regdata += 2;
  3539. if ((hi == 0) && (lo == 0))
  3540. break;
  3541. }
  3542. }
  3543. if (ret == 0) {
  3544. bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
  3545. }
  3546. printf("Return_dpc value is : %d\n", ret);
  3547. bus->ctrl_frame_stat = FALSE;
  3548. dhd_wait_event_wakeup(bus->dhd);
  3549. }
  3550. /* Send queued frames (limit 1 if rx may still be pending) */
  3551. else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
  3552. pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
  3553. framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
  3554. framecnt = dhdsdio_sendfromq(bus, framecnt);
  3555. txlimit -= framecnt;
  3556. }
  3557. /* Resched if events or tx frames are pending, else await next interrupt */
  3558. /* On failed register access, all bets are off: no resched or interrupts */
  3559. if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
  3560. DHD_ERROR(("%s: failed backplane access over SDIO, halting operation %d \n",
  3561. __FUNCTION__, bcmsdh_regfail(sdh)));
  3562. bus->dhd->busstate = DHD_BUS_DOWN;
  3563. bus->intstatus = 0;
  3564. } else if (bus->clkstate == CLK_PENDING) {
  3565. DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \
  3566. I_CHIPACTIVE interrupt", __FUNCTION__));
  3567. resched = TRUE;
  3568. } else if (bus->intstatus || bus->ipend ||
  3569. (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
  3570. PKT_AVAILABLE()) { /* Read multiple frames */
  3571. resched = TRUE;
  3572. }
  3573. bus->dpc_sched = resched;
  3574. /* If we're done for now, turn off clock request. */
  3575. if ((bus->clkstate != CLK_PENDING) && bus->idletime == DHD_IDLE_IMMEDIATE) {
  3576. bus->activity = FALSE;
  3577. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  3578. }
  3579. dhd_os_sdunlock(bus->dhd);
  3580. return resched;
  3581. }
  3582. bool
  3583. dhd_bus_dpc(struct dhd_bus *bus)
  3584. {
  3585. bool resched;
  3586. /* Call the DPC directly. */
  3587. DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
  3588. resched = dhdsdio_dpc(bus);
  3589. return resched;
  3590. }
  3591. void
  3592. dhdsdio_isr(void *arg)
  3593. {
  3594. dhd_bus_t *bus = (dhd_bus_t*)arg;
  3595. bcmsdh_info_t *sdh;
  3596. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3597. if (!bus) {
  3598. DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
  3599. return;
  3600. }
  3601. sdh = bus->sdh;
  3602. if (bus->dhd->busstate == DHD_BUS_DOWN) {
  3603. DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
  3604. return;
  3605. }
  3606. /* Count the interrupt call */
  3607. bus->intrcount++;
  3608. bus->ipend = TRUE;
  3609. /* Shouldn't get this interrupt if we're sleeping? */
  3610. if (bus->sleeping) {
  3611. DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
  3612. return;
  3613. }
  3614. /* Disable additional interrupts (is this needed now)? */
  3615. if (bus->intr) {
  3616. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  3617. } else {
  3618. DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
  3619. }
  3620. bcmsdh_intr_disable(sdh);
  3621. bus->intdis = TRUE;
  3622. #if defined(SDIO_ISR_THREAD)
  3623. DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
  3624. dhd_os_wake_lock(bus->dhd);
  3625. while (dhdsdio_dpc(bus));
  3626. dhd_os_wake_unlock(bus->dhd);
  3627. #else
  3628. bus->dpc_sched = TRUE;
  3629. dhd_sched_dpc(bus->dhd);
  3630. #endif
  3631. }
  3632. #ifdef SDTEST
  3633. static void
  3634. dhdsdio_pktgen_init(dhd_bus_t *bus)
  3635. {
  3636. /* Default to specified length, or full range */
  3637. if (dhd_pktgen_len) {
  3638. bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
  3639. bus->pktgen_minlen = bus->pktgen_maxlen;
  3640. } else {
  3641. bus->pktgen_maxlen = MAX_PKTGEN_LEN;
  3642. bus->pktgen_minlen = 0;
  3643. }
  3644. bus->pktgen_len = (uint16)bus->pktgen_minlen;
  3645. /* Default to per-watchdog burst with 10s print time */
  3646. bus->pktgen_freq = 1;
  3647. bus->pktgen_print = 10000 / dhd_watchdog_ms;
  3648. bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
  3649. /* Default to echo mode */
  3650. bus->pktgen_mode = DHD_PKTGEN_ECHO;
  3651. bus->pktgen_stop = 1;
  3652. }
  3653. static void
  3654. dhdsdio_pktgen(dhd_bus_t *bus)
  3655. {
  3656. void *pkt;
  3657. uint8 *data;
  3658. uint pktcount;
  3659. uint fillbyte;
  3660. osl_t *osh = bus->dhd->osh;
  3661. uint16 len;
  3662. /* Display current count if appropriate */
  3663. if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
  3664. bus->pktgen_ptick = 0;
  3665. printf("%s: send attempts %d rcvd %d\n",
  3666. __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd);
  3667. }
  3668. /* For recv mode, just make sure dongle has started sending */
  3669. if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
  3670. if (!bus->pktgen_rcvd)
  3671. dhdsdio_sdtest_set(bus, TRUE);
  3672. return;
  3673. }
  3674. /* Otherwise, generate or request the specified number of packets */
  3675. for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
  3676. /* Stop if total has been reached */
  3677. if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
  3678. bus->pktgen_count = 0;
  3679. break;
  3680. }
  3681. /* Allocate an appropriate-sized packet */
  3682. len = bus->pktgen_len;
  3683. if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
  3684. TRUE))) {;
  3685. DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
  3686. break;
  3687. }
  3688. PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
  3689. data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
  3690. /* Write test header cmd and extra based on mode */
  3691. switch (bus->pktgen_mode) {
  3692. case DHD_PKTGEN_ECHO:
  3693. *data++ = SDPCM_TEST_ECHOREQ;
  3694. *data++ = (uint8)bus->pktgen_sent;
  3695. break;
  3696. case DHD_PKTGEN_SEND:
  3697. *data++ = SDPCM_TEST_DISCARD;
  3698. *data++ = (uint8)bus->pktgen_sent;
  3699. break;
  3700. case DHD_PKTGEN_RXBURST:
  3701. *data++ = SDPCM_TEST_BURST;
  3702. *data++ = (uint8)bus->pktgen_count;
  3703. break;
  3704. default:
  3705. DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
  3706. PKTFREE(osh, pkt, TRUE);
  3707. bus->pktgen_count = 0;
  3708. return;
  3709. }
  3710. /* Write test header length field */
  3711. *data++ = (len >> 0);
  3712. *data++ = (len >> 8);
  3713. /* Then fill in the remainder -- N/A for burst, but who cares... */
  3714. for (fillbyte = 0; fillbyte < len; fillbyte++)
  3715. *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
  3716. #ifdef DHD_DEBUG
  3717. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  3718. data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
  3719. prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
  3720. }
  3721. #endif
  3722. /* Send it */
  3723. if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE)) {
  3724. bus->pktgen_fail++;
  3725. if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
  3726. bus->pktgen_count = 0;
  3727. }
  3728. bus->pktgen_sent++;
  3729. /* Bump length if not fixed, wrap at max */
  3730. if (++bus->pktgen_len > bus->pktgen_maxlen)
  3731. bus->pktgen_len = (uint16)bus->pktgen_minlen;
  3732. /* Special case for burst mode: just send one request! */
  3733. if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
  3734. break;
  3735. }
  3736. }
  3737. static void
  3738. dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
  3739. {
  3740. void *pkt;
  3741. uint8 *data;
  3742. osl_t *osh = bus->dhd->osh;
  3743. /* Allocate the packet */
  3744. if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN, TRUE))) {
  3745. DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
  3746. return;
  3747. }
  3748. PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
  3749. data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
  3750. /* Fill in the test header */
  3751. *data++ = SDPCM_TEST_SEND;
  3752. *data++ = start;
  3753. *data++ = (bus->pktgen_maxlen >> 0);
  3754. *data++ = (bus->pktgen_maxlen >> 8);
  3755. /* Send it */
  3756. if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE))
  3757. bus->pktgen_fail++;
  3758. }
  3759. static void
  3760. dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
  3761. {
  3762. osl_t *osh = bus->dhd->osh;
  3763. uint8 *data;
  3764. uint pktlen;
  3765. uint8 cmd;
  3766. uint8 extra;
  3767. uint16 len;
  3768. uint16 offset;
  3769. /* Check for min length */
  3770. if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
  3771. DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
  3772. PKTFREE(osh, pkt, FALSE);
  3773. return;
  3774. }
  3775. /* Extract header fields */
  3776. data = PKTDATA(osh, pkt);
  3777. cmd = *data++;
  3778. extra = *data++;
  3779. len = *data++; len += *data++ << 8;
  3780. /* Check length for relevant commands */
  3781. if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
  3782. if (pktlen != len + SDPCM_TEST_HDRLEN) {
  3783. DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
  3784. " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
  3785. PKTFREE(osh, pkt, FALSE);
  3786. return;
  3787. }
  3788. }
  3789. /* Process as per command */
  3790. switch (cmd) {
  3791. case SDPCM_TEST_ECHOREQ:
  3792. /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
  3793. *(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
  3794. if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE) == 0) {
  3795. bus->pktgen_sent++;
  3796. } else {
  3797. bus->pktgen_fail++;
  3798. PKTFREE(osh, pkt, FALSE);
  3799. }
  3800. bus->pktgen_rcvd++;
  3801. break;
  3802. case SDPCM_TEST_ECHORSP:
  3803. if (bus->ext_loop) {
  3804. PKTFREE(osh, pkt, FALSE);
  3805. bus->pktgen_rcvd++;
  3806. break;
  3807. }
  3808. for (offset = 0; offset < len; offset++, data++) {
  3809. if (*data != SDPCM_TEST_FILL(offset, extra)) {
  3810. DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
  3811. "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
  3812. offset, len, SDPCM_TEST_FILL(offset, extra), *data));
  3813. break;
  3814. }
  3815. }
  3816. PKTFREE(osh, pkt, FALSE);
  3817. bus->pktgen_rcvd++;
  3818. break;
  3819. case SDPCM_TEST_DISCARD:
  3820. PKTFREE(osh, pkt, FALSE);
  3821. bus->pktgen_rcvd++;
  3822. break;
  3823. case SDPCM_TEST_BURST:
  3824. case SDPCM_TEST_SEND:
  3825. default:
  3826. DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
  3827. " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
  3828. PKTFREE(osh, pkt, FALSE);
  3829. break;
  3830. }
  3831. /* For recv mode, stop at limie (and tell dongle to stop sending) */
  3832. if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
  3833. if (bus->pktgen_total && (bus->pktgen_rcvd >= bus->pktgen_total)) {
  3834. bus->pktgen_count = 0;
  3835. dhdsdio_sdtest_set(bus, FALSE);
  3836. }
  3837. }
  3838. }
  3839. #endif /* SDTEST */
  3840. extern bool
  3841. dhd_bus_watchdog(dhd_pub_t *dhdp)
  3842. {
  3843. dhd_bus_t *bus;
  3844. DHD_TIMER(("%s: Enter\n", __FUNCTION__));
  3845. bus = dhdp->bus;
  3846. if (bus->dhd->dongle_reset)
  3847. return FALSE;
  3848. /* Ignore the timer if simulating bus down */
  3849. if (bus->sleeping)
  3850. return FALSE;
  3851. /* Poll period: check device if appropriate. */
  3852. if (bus->poll && (++bus->polltick >= bus->pollrate)) {
  3853. uint32 intstatus = 0;
  3854. /* Reset poll tick */
  3855. bus->polltick = 0;
  3856. /* Check device if no interrupts */
  3857. if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
  3858. if (!bus->dpc_sched) {
  3859. uint8 devpend;
  3860. devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
  3861. SDIOD_CCCR_INTPEND, NULL);
  3862. intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
  3863. }
  3864. /* If there is something, make like the ISR and schedule the DPC */
  3865. if (intstatus) {
  3866. bus->pollcnt++;
  3867. bus->ipend = TRUE;
  3868. if (bus->intr) {
  3869. bcmsdh_intr_disable(bus->sdh);
  3870. }
  3871. bus->dpc_sched = TRUE;
  3872. dhd_sched_dpc(bus->dhd);
  3873. }
  3874. }
  3875. /* Update interrupt tracking */
  3876. bus->lastintrs = bus->intrcount;
  3877. }
  3878. #ifdef DHD_DEBUG
  3879. /* Poll for console output periodically */
  3880. if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
  3881. bus->console.count += dhd_watchdog_ms;
  3882. if (bus->console.count >= dhd_console_ms) {
  3883. bus->console.count -= dhd_console_ms;
  3884. /* Make sure backplane clock is on */
  3885. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  3886. if (dhdsdio_readconsole(bus) < 0)
  3887. dhd_console_ms = 0; /* On error, stop trying */
  3888. }
  3889. }
  3890. #endif /* DHD_DEBUG */
  3891. #ifdef SDTEST
  3892. /* Generate packets if configured */
  3893. if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
  3894. /* Make sure backplane clock is on */
  3895. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  3896. bus->pktgen_tick = 0;
  3897. dhdsdio_pktgen(bus);
  3898. }
  3899. #endif
  3900. /* On idle timeout clear activity flag and/or turn off clock */
  3901. if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
  3902. if (++bus->idlecount >= bus->idletime) {
  3903. bus->idlecount = 0;
  3904. if (bus->activity) {
  3905. bus->activity = FALSE;
  3906. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  3907. }
  3908. }
  3909. }
  3910. return bus->ipend;
  3911. }
  3912. #ifdef DHD_DEBUG
  3913. extern int
  3914. dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
  3915. {
  3916. dhd_bus_t *bus = dhdp->bus;
  3917. uint32 addr, val;
  3918. int rv;
  3919. void *pkt;
  3920. /* Address could be zero if CONSOLE := 0 in dongle Makefile */
  3921. if (bus->console_addr == 0)
  3922. return BCME_UNSUPPORTED;
  3923. /* Exclusive bus access */
  3924. dhd_os_sdlock(bus->dhd);
  3925. /* Don't allow input if dongle is in reset */
  3926. if (bus->dhd->dongle_reset) {
  3927. dhd_os_sdunlock(bus->dhd);
  3928. return BCME_NOTREADY;
  3929. }
  3930. /* Request clock to allow SDIO accesses */
  3931. BUS_WAKE(bus);
  3932. /* No pend allowed since txpkt is called later, ht clk has to be on */
  3933. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  3934. /* Zero cbuf_index */
  3935. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
  3936. val = htol32(0);
  3937. if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
  3938. goto done;
  3939. /* Write message into cbuf */
  3940. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
  3941. if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
  3942. goto done;
  3943. /* Write length into vcons_in */
  3944. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
  3945. val = htol32(msglen);
  3946. if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
  3947. goto done;
  3948. /* Bump dongle by sending an empty event pkt.
  3949. * sdpcm_sendup (RX) checks for virtual console input.
  3950. */
  3951. if (((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL) &&
  3952. bus->clkstate == CLK_AVAIL)
  3953. dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, TRUE);
  3954. done:
  3955. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  3956. bus->activity = FALSE;
  3957. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  3958. }
  3959. dhd_os_sdunlock(bus->dhd);
  3960. return rv;
  3961. }
  3962. #endif /* DHD_DEBUG */
  3963. #ifdef DHD_DEBUG
  3964. static void
  3965. dhd_dump_cis(uint fn, uint8 *cis)
  3966. {
  3967. uint byte, tag, tdata;
  3968. DHD_INFO(("Function %d CIS:\n", fn));
  3969. for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
  3970. if ((byte % 16) == 0)
  3971. DHD_INFO((" "));
  3972. DHD_INFO(("%02x ", cis[byte]));
  3973. if ((byte % 16) == 15)
  3974. DHD_INFO(("\n"));
  3975. if (!tdata--) {
  3976. tag = cis[byte];
  3977. if (tag == 0xff)
  3978. break;
  3979. else if (!tag)
  3980. tdata = 0;
  3981. else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
  3982. tdata = cis[byte + 1] + 1;
  3983. else
  3984. DHD_INFO(("]"));
  3985. }
  3986. }
  3987. if ((byte % 16) != 15)
  3988. DHD_INFO(("\n"));
  3989. }
  3990. #endif /* DHD_DEBUG */
  3991. static bool
  3992. dhdsdio_chipmatch(uint16 chipid)
  3993. {
  3994. if (chipid == BCM4325_CHIP_ID)
  3995. return TRUE;
  3996. if (chipid == BCM4329_CHIP_ID)
  3997. return TRUE;
  3998. if (chipid == BCM4315_CHIP_ID)
  3999. return TRUE;
  4000. if (chipid == BCM4319_CHIP_ID)
  4001. return TRUE;
  4002. return FALSE;
  4003. }
  4004. static void *
  4005. dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
  4006. uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
  4007. {
  4008. int ret;
  4009. dhd_bus_t *bus;
  4010. /* Init global variables at run-time, not as part of the declaration.
  4011. * This is required to support init/de-init of the driver. Initialization
  4012. * of globals as part of the declaration results in non-deterministic
  4013. * behavior since the value of the globals may be different on the
  4014. * first time that the driver is initialized vs subsequent initializations.
  4015. */
  4016. dhd_txbound = DHD_TXBOUND;
  4017. dhd_rxbound = DHD_RXBOUND;
  4018. dhd_alignctl = TRUE;
  4019. sd1idle = TRUE;
  4020. dhd_readahead = TRUE;
  4021. retrydata = FALSE;
  4022. dhd_doflow = FALSE;
  4023. dhd_dongle_memsize = 0;
  4024. dhd_txminmax = DHD_TXMINMAX;
  4025. forcealign = TRUE;
  4026. dhd_common_init();
  4027. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4028. DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
  4029. /* We make assumptions about address window mappings */
  4030. ASSERT((uintptr)regsva == SI_ENUM_BASE);
  4031. /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
  4032. * means early parse could fail, so here we should get either an ID
  4033. * we recognize OR (-1) indicating we must request power first.
  4034. */
  4035. /* Check the Vendor ID */
  4036. switch (venid) {
  4037. case 0x0000:
  4038. case VENDOR_BROADCOM:
  4039. break;
  4040. default:
  4041. DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
  4042. __FUNCTION__, venid));
  4043. return NULL;
  4044. }
  4045. /* Check the Device ID and make sure it's one that we support */
  4046. switch (devid) {
  4047. case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
  4048. case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
  4049. case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
  4050. DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__));
  4051. break;
  4052. case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */
  4053. case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
  4054. case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
  4055. case 0x4329:
  4056. DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__));
  4057. break;
  4058. case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */
  4059. case BCM4315_D11G_ID: /* 4315 802.11g id */
  4060. case BCM4315_D11A_ID: /* 4315 802.11a id */
  4061. DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__));
  4062. break;
  4063. case BCM4319_D11N_ID: /* 4319 802.11n id */
  4064. case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
  4065. case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
  4066. DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__));
  4067. break;
  4068. case 0:
  4069. DHD_INFO(("%s: allow device id 0, will check chip internals\n",
  4070. __FUNCTION__));
  4071. break;
  4072. default:
  4073. DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
  4074. __FUNCTION__, venid, devid));
  4075. return NULL;
  4076. }
  4077. if (osh == NULL) {
  4078. /* Ask the OS interface part for an OSL handle */
  4079. if (!(osh = dhd_osl_attach(sdh, DHD_BUS))) {
  4080. DHD_ERROR(("%s: osl_attach failed!\n", __FUNCTION__));
  4081. return NULL;
  4082. }
  4083. }
  4084. /* Allocate private bus interface state */
  4085. if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
  4086. DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
  4087. goto fail;
  4088. }
  4089. bzero(bus, sizeof(dhd_bus_t));
  4090. bus->sdh = sdh;
  4091. bus->cl_devid = (uint16)devid;
  4092. bus->bus = DHD_BUS;
  4093. bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
  4094. bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
  4095. /* attempt to attach to the dongle */
  4096. if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
  4097. DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
  4098. goto fail;
  4099. }
  4100. /* Attach to the dhd/OS/network interface */
  4101. if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
  4102. DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
  4103. goto fail;
  4104. }
  4105. /* Allocate buffers */
  4106. if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
  4107. DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
  4108. goto fail;
  4109. }
  4110. if (!(dhdsdio_probe_init(bus, osh, sdh))) {
  4111. DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
  4112. goto fail;
  4113. }
  4114. /* Register interrupt callback, but mask it (not operational yet). */
  4115. DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
  4116. bcmsdh_intr_disable(sdh);
  4117. if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
  4118. DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
  4119. __FUNCTION__, ret));
  4120. goto fail;
  4121. }
  4122. DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
  4123. DHD_INFO(("%s: completed!!\n", __FUNCTION__));
  4124. /* if firmware path present try to download and bring up bus */
  4125. if ((ret = dhd_bus_start(bus->dhd)) != 0) {
  4126. #if 1
  4127. DHD_ERROR(("%s: failed\n", __FUNCTION__));
  4128. goto fail;
  4129. #else
  4130. if (ret == BCME_NOTUP) {
  4131. DHD_ERROR(("%s: dongle is not responding\n", __FUNCTION__));
  4132. goto fail;
  4133. }
  4134. #endif
  4135. }
  4136. /* Ok, have the per-port tell the stack we're open for business */
  4137. if (dhd_net_attach(bus->dhd, 0) != 0) {
  4138. DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
  4139. goto fail;
  4140. }
  4141. return bus;
  4142. fail:
  4143. dhdsdio_release(bus, osh);
  4144. return NULL;
  4145. }
  4146. static bool
  4147. dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
  4148. uint16 devid)
  4149. {
  4150. uint8 clkctl = 0;
  4151. int err = 0;
  4152. bus->alp_only = TRUE;
  4153. /* Return the window to backplane enumeration space for core access */
  4154. if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) {
  4155. DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
  4156. }
  4157. #ifdef DHD_DEBUG
  4158. printf("F1 signature read @0x18000000=0x%4x\n",
  4159. bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
  4160. #endif /* DHD_DEBUG */
  4161. /* Force PLL off until si_attach() programs PLL control regs */
  4162. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
  4163. if (!err)
  4164. clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  4165. if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
  4166. DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
  4167. err, DHD_INIT_CLKCTL1, clkctl));
  4168. goto fail;
  4169. }
  4170. #ifdef DHD_DEBUG
  4171. if (DHD_INFO_ON()) {
  4172. uint fn, numfn;
  4173. uint8 *cis[SDIOD_MAX_IOFUNCS];
  4174. int err = 0;
  4175. numfn = bcmsdh_query_iofnum(sdh);
  4176. ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
  4177. /* Make sure ALP is available before trying to read CIS */
  4178. SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  4179. SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
  4180. !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
  4181. /* Now request ALP be put on the bus */
  4182. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  4183. DHD_INIT_CLKCTL2, &err);
  4184. OSL_DELAY(65);
  4185. for (fn = 0; fn <= numfn; fn++) {
  4186. if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
  4187. DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn));
  4188. break;
  4189. }
  4190. bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
  4191. if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) {
  4192. DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err));
  4193. MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
  4194. break;
  4195. }
  4196. dhd_dump_cis(fn, cis[fn]);
  4197. }
  4198. while (fn-- > 0) {
  4199. ASSERT(cis[fn]);
  4200. MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
  4201. }
  4202. if (err) {
  4203. DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
  4204. goto fail;
  4205. }
  4206. }
  4207. #endif /* DHD_DEBUG */
  4208. /* si_attach() will provide an SI handle and scan the backplane */
  4209. if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
  4210. &bus->vars, &bus->varsz))) {
  4211. DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
  4212. goto fail;
  4213. }
  4214. bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
  4215. if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
  4216. DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
  4217. __FUNCTION__, bus->sih->chip));
  4218. goto fail;
  4219. }
  4220. si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
  4221. /* Get info on the ARM and SOCRAM cores... */
  4222. if (!DHD_NOPMU(bus)) {
  4223. if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
  4224. (si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
  4225. bus->armrev = si_corerev(bus->sih);
  4226. } else {
  4227. DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
  4228. goto fail;
  4229. }
  4230. if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
  4231. DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
  4232. goto fail;
  4233. }
  4234. bus->ramsize = bus->orig_ramsize;
  4235. if (dhd_dongle_memsize)
  4236. dhd_dongle_setmemsize(bus, dhd_dongle_memsize);
  4237. DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
  4238. bus->ramsize, bus->orig_ramsize));
  4239. }
  4240. /* ...but normally deal with the SDPCMDEV core */
  4241. if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
  4242. !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
  4243. DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
  4244. goto fail;
  4245. }
  4246. bus->sdpcmrev = si_corerev(bus->sih);
  4247. /* Set core control so an SDIO reset does a backplane reset */
  4248. OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
  4249. pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
  4250. /* Locate an appropriately-aligned portion of hdrbuf */
  4251. bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
  4252. /* Set the poll and/or interrupt flags */
  4253. bus->intr = (bool)dhd_intr;
  4254. if ((bus->poll = (bool)dhd_poll))
  4255. bus->pollrate = 1;
  4256. return TRUE;
  4257. fail:
  4258. return FALSE;
  4259. }
  4260. static bool
  4261. dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
  4262. {
  4263. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4264. #ifndef DHD_USE_STATIC_BUF
  4265. if (bus->dhd->maxctl) {
  4266. bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
  4267. if (!(bus->rxbuf = MALLOC(osh, bus->rxblen))) {
  4268. DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
  4269. __FUNCTION__, bus->rxblen));
  4270. goto fail;
  4271. }
  4272. }
  4273. /* Allocate buffer to receive glomed packet */
  4274. if (!(bus->databuf = MALLOC(osh, MAX_DATA_BUF))) {
  4275. DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
  4276. __FUNCTION__, MAX_DATA_BUF));
  4277. /* release rxbuf which was already located as above */
  4278. if (!bus->rxblen) MFREE(osh, bus->rxbuf, bus->rxblen);
  4279. goto fail;
  4280. }
  4281. #else
  4282. if (bus->dhd->maxctl) {
  4283. bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
  4284. if (!(bus->rxbuf = dhd_os_prealloc(DHD_PREALLOC_RXBUF, bus->rxblen))) {
  4285. DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
  4286. __FUNCTION__, bus->rxblen));
  4287. goto fail;
  4288. }
  4289. }
  4290. /* Allocate buffer to receive glomed packet */
  4291. if (!(bus->databuf = dhd_os_prealloc(DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
  4292. DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
  4293. __FUNCTION__, MAX_DATA_BUF));
  4294. goto fail;
  4295. }
  4296. #endif /* DHD_USE_STATIC_BUF */
  4297. /* Align the buffer */
  4298. if ((uintptr)bus->databuf % DHD_SDALIGN)
  4299. bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
  4300. else
  4301. bus->dataptr = bus->databuf;
  4302. return TRUE;
  4303. fail:
  4304. return FALSE;
  4305. }
  4306. static bool
  4307. dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
  4308. {
  4309. int32 fnum;
  4310. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4311. #ifdef SDTEST
  4312. dhdsdio_pktgen_init(bus);
  4313. #endif /* SDTEST */
  4314. /* Disable F2 to clear any intermediate frame state on the dongle */
  4315. bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
  4316. bus->dhd->busstate = DHD_BUS_DOWN;
  4317. bus->sleeping = FALSE;
  4318. bus->rxflow = FALSE;
  4319. bus->prev_rxlim_hit = 0;
  4320. /* Done with backplane-dependent accesses, can drop clock... */
  4321. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
  4322. /* ...and initialize clock/power states */
  4323. bus->clkstate = CLK_SDONLY;
  4324. bus->idletime = (int32)dhd_idletime;
  4325. bus->idleclock = DHD_IDLE_ACTIVE;
  4326. /* Query the SD clock speed */
  4327. if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
  4328. &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
  4329. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
  4330. bus->sd_divisor = -1;
  4331. } else {
  4332. DHD_INFO(("%s: Initial value for %s is %d\n",
  4333. __FUNCTION__, "sd_divisor", bus->sd_divisor));
  4334. }
  4335. /* Query the SD bus mode */
  4336. if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
  4337. &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
  4338. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
  4339. bus->sd_mode = -1;
  4340. } else {
  4341. DHD_INFO(("%s: Initial value for %s is %d\n",
  4342. __FUNCTION__, "sd_mode", bus->sd_mode));
  4343. }
  4344. /* Query the F2 block size, set roundup accordingly */
  4345. fnum = 2;
  4346. if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
  4347. &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
  4348. bus->blocksize = 0;
  4349. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
  4350. } else {
  4351. DHD_INFO(("%s: Initial value for %s is %d\n",
  4352. __FUNCTION__, "sd_blocksize", bus->blocksize));
  4353. }
  4354. bus->roundup = MIN(max_roundup, bus->blocksize);
  4355. /* Query if bus module supports packet chaining, default to use if supported */
  4356. if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
  4357. &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
  4358. bus->sd_rxchain = FALSE;
  4359. } else {
  4360. DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
  4361. __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
  4362. }
  4363. bus->use_rxchain = (bool)bus->sd_rxchain;
  4364. return TRUE;
  4365. }
  4366. bool
  4367. dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
  4368. char *fw_path, char *nv_path)
  4369. {
  4370. bool ret;
  4371. bus->fw_path = fw_path;
  4372. bus->nv_path = nv_path;
  4373. ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
  4374. return ret;
  4375. }
  4376. static bool
  4377. dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
  4378. {
  4379. bool ret;
  4380. /* Download the firmware */
  4381. dhd_os_wake_lock(bus->dhd);
  4382. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  4383. ret = _dhdsdio_download_firmware(bus) == 0;
  4384. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  4385. dhd_os_wake_unlock(bus->dhd);
  4386. return ret;
  4387. }
  4388. /* Detach and free everything */
  4389. static void
  4390. dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
  4391. {
  4392. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4393. if (bus) {
  4394. ASSERT(osh);
  4395. /* De-register interrupt handler */
  4396. bcmsdh_intr_disable(bus->sdh);
  4397. bcmsdh_intr_dereg(bus->sdh);
  4398. if (bus->dhd) {
  4399. dhdsdio_release_dongle(bus, osh, TRUE);
  4400. dhd_detach(bus->dhd);
  4401. bus->dhd = NULL;
  4402. }
  4403. dhdsdio_release_malloc(bus, osh);
  4404. MFREE(osh, bus, sizeof(dhd_bus_t));
  4405. }
  4406. if (osh)
  4407. dhd_osl_detach(osh);
  4408. DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
  4409. }
  4410. static void
  4411. dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
  4412. {
  4413. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4414. if (bus->dhd && bus->dhd->dongle_reset)
  4415. return;
  4416. if (bus->rxbuf) {
  4417. #ifndef DHD_USE_STATIC_BUF
  4418. MFREE(osh, bus->rxbuf, bus->rxblen);
  4419. #endif
  4420. bus->rxctl = bus->rxbuf = NULL;
  4421. bus->rxlen = 0;
  4422. }
  4423. if (bus->databuf) {
  4424. #ifndef DHD_USE_STATIC_BUF
  4425. MFREE(osh, bus->databuf, MAX_DATA_BUF);
  4426. #endif
  4427. bus->databuf = NULL;
  4428. }
  4429. }
  4430. static void
  4431. dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, int reset_flag)
  4432. {
  4433. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4434. if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
  4435. return;
  4436. if (bus->sih) {
  4437. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  4438. #if !defined(BCMLXSDMMC)
  4439. si_watchdog(bus->sih, 4);
  4440. #endif /* !defined(BCMLXSDMMC) */
  4441. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  4442. si_detach(bus->sih);
  4443. if (bus->vars && bus->varsz)
  4444. MFREE(osh, bus->vars, bus->varsz);
  4445. bus->vars = NULL;
  4446. }
  4447. DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
  4448. }
  4449. static void
  4450. dhdsdio_disconnect(void *ptr)
  4451. {
  4452. dhd_bus_t *bus = (dhd_bus_t *)ptr;
  4453. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4454. if (bus) {
  4455. ASSERT(bus->dhd);
  4456. dhdsdio_release(bus, bus->dhd->osh);
  4457. }
  4458. DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
  4459. }
  4460. /* Register/Unregister functions are called by the main DHD entry
  4461. * point (e.g. module insertion) to link with the bus driver, in
  4462. * order to look for or await the device.
  4463. */
  4464. static bcmsdh_driver_t dhd_sdio = {
  4465. dhdsdio_probe,
  4466. dhdsdio_disconnect
  4467. };
  4468. int
  4469. dhd_bus_register(void)
  4470. {
  4471. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4472. return bcmsdh_register(&dhd_sdio);
  4473. }
  4474. void
  4475. dhd_bus_unregister(void)
  4476. {
  4477. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4478. bcmsdh_unregister();
  4479. }
  4480. #ifdef BCMEMBEDIMAGE
  4481. static int
  4482. dhdsdio_download_code_array(struct dhd_bus *bus)
  4483. {
  4484. int bcmerror = -1;
  4485. int offset = 0;
  4486. DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__));
  4487. /* Download image */
  4488. while ((offset + MEMBLOCK) < sizeof(dlarray)) {
  4489. bcmerror = dhdsdio_membytes(bus, TRUE, offset, dlarray + offset, MEMBLOCK);
  4490. if (bcmerror) {
  4491. DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
  4492. __FUNCTION__, bcmerror, MEMBLOCK, offset));
  4493. goto err;
  4494. }
  4495. offset += MEMBLOCK;
  4496. }
  4497. if (offset < sizeof(dlarray)) {
  4498. bcmerror = dhdsdio_membytes(bus, TRUE, offset,
  4499. dlarray + offset, sizeof(dlarray) - offset);
  4500. if (bcmerror) {
  4501. DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
  4502. __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
  4503. goto err;
  4504. }
  4505. }
  4506. #ifdef DHD_DEBUG
  4507. /* Upload and compare the downloaded code */
  4508. {
  4509. unsigned char *ularray;
  4510. ularray = MALLOC(bus->dhd->osh, bus->ramsize);
  4511. /* Upload image to verify downloaded contents. */
  4512. offset = 0;
  4513. memset(ularray, 0xaa, bus->ramsize);
  4514. while ((offset + MEMBLOCK) < sizeof(dlarray)) {
  4515. bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK);
  4516. if (bcmerror) {
  4517. DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
  4518. __FUNCTION__, bcmerror, MEMBLOCK, offset));
  4519. goto err;
  4520. }
  4521. offset += MEMBLOCK;
  4522. }
  4523. if (offset < sizeof(dlarray)) {
  4524. bcmerror = dhdsdio_membytes(bus, FALSE, offset,
  4525. ularray + offset, sizeof(dlarray) - offset);
  4526. if (bcmerror) {
  4527. DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
  4528. __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
  4529. goto err;
  4530. }
  4531. }
  4532. if (memcmp(dlarray, ularray, sizeof(dlarray))) {
  4533. DHD_ERROR(("%s: Downloaded image is corrupted.\n", __FUNCTION__));
  4534. ASSERT(0);
  4535. goto err;
  4536. } else
  4537. DHD_ERROR(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
  4538. MFREE(bus->dhd->osh, ularray, bus->ramsize);
  4539. }
  4540. #endif /* DHD_DEBUG */
  4541. err:
  4542. return bcmerror;
  4543. }
  4544. #endif /* BCMEMBEDIMAGE */
  4545. static int
  4546. dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
  4547. {
  4548. int bcmerror = -1;
  4549. int offset = 0;
  4550. uint len;
  4551. void *image = NULL;
  4552. uint8 *memblock = NULL, *memptr;
  4553. DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, fw_path));
  4554. image = dhd_os_open_image(fw_path);
  4555. if (image == NULL)
  4556. goto err;
  4557. memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
  4558. if (memblock == NULL) {
  4559. DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
  4560. goto err;
  4561. }
  4562. if ((uint32)(uintptr)memblock % DHD_SDALIGN)
  4563. memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
  4564. /* Download image */
  4565. while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) {
  4566. bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
  4567. if (bcmerror) {
  4568. DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
  4569. __FUNCTION__, bcmerror, MEMBLOCK, offset));
  4570. goto err;
  4571. }
  4572. offset += MEMBLOCK;
  4573. }
  4574. err:
  4575. if (memblock)
  4576. MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
  4577. if (image)
  4578. dhd_os_close_image(image);
  4579. return bcmerror;
  4580. }
  4581. /*
  4582. * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
  4583. * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
  4584. * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs.
  4585. */
  4586. static uint
  4587. process_nvram_vars(char *varbuf, uint len)
  4588. {
  4589. char *dp;
  4590. bool findNewline;
  4591. int column;
  4592. uint buf_len, n;
  4593. dp = varbuf;
  4594. findNewline = FALSE;
  4595. column = 0;
  4596. for (n = 0; n < len; n++) {
  4597. if (varbuf[n] == 0)
  4598. break;
  4599. if (varbuf[n] == '\r')
  4600. continue;
  4601. if (findNewline && varbuf[n] != '\n')
  4602. continue;
  4603. findNewline = FALSE;
  4604. if (varbuf[n] == '#') {
  4605. findNewline = TRUE;
  4606. continue;
  4607. }
  4608. if (varbuf[n] == '\n') {
  4609. if (column == 0)
  4610. continue;
  4611. *dp++ = 0;
  4612. column = 0;
  4613. continue;
  4614. }
  4615. *dp++ = varbuf[n];
  4616. column++;
  4617. }
  4618. buf_len = dp - varbuf;
  4619. while (dp < varbuf + n)
  4620. *dp++ = 0;
  4621. return buf_len;
  4622. }
  4623. /*
  4624. EXAMPLE: nvram_array
  4625. nvram_arry format:
  4626. name=value
  4627. Use carriage return at the end of each assignment, and an empty string with
  4628. carriage return at the end of array.
  4629. For example:
  4630. unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"};
  4631. Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
  4632. Search "EXAMPLE: nvram_array" to see how the array is activated.
  4633. */
  4634. void
  4635. dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params)
  4636. {
  4637. bus->nvram_params = nvram_params;
  4638. }
  4639. static int
  4640. dhdsdio_download_nvram(struct dhd_bus *bus)
  4641. {
  4642. int bcmerror = -1;
  4643. uint len;
  4644. void * image = NULL;
  4645. char * memblock = NULL;
  4646. char *bufp;
  4647. char *nv_path;
  4648. bool nvram_file_exists;
  4649. nv_path = bus->nv_path;
  4650. nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0'));
  4651. if (!nvram_file_exists && (bus->nvram_params == NULL))
  4652. return (0);
  4653. if (nvram_file_exists) {
  4654. image = dhd_os_open_image(nv_path);
  4655. if (image == NULL)
  4656. goto err;
  4657. }
  4658. memblock = MALLOC(bus->dhd->osh, MEMBLOCK);
  4659. if (memblock == NULL) {
  4660. DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
  4661. __FUNCTION__, MEMBLOCK));
  4662. goto err;
  4663. }
  4664. /* Download variables */
  4665. if (nvram_file_exists) {
  4666. len = dhd_os_get_image_block(memblock, MEMBLOCK, image);
  4667. }
  4668. else {
  4669. len = strlen(bus->nvram_params);
  4670. ASSERT(len <= MEMBLOCK);
  4671. if (len > MEMBLOCK)
  4672. len = MEMBLOCK;
  4673. memcpy(memblock, bus->nvram_params, len);
  4674. }
  4675. if (len > 0 && len < MEMBLOCK) {
  4676. bufp = (char *)memblock;
  4677. bufp[len] = 0;
  4678. len = process_nvram_vars(bufp, len);
  4679. bufp += len;
  4680. *bufp++ = 0;
  4681. if (len)
  4682. bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
  4683. if (bcmerror) {
  4684. DHD_ERROR(("%s: error downloading vars: %d\n",
  4685. __FUNCTION__, bcmerror));
  4686. }
  4687. }
  4688. else {
  4689. DHD_ERROR(("%s: error reading nvram file: %d\n",
  4690. __FUNCTION__, len));
  4691. bcmerror = BCME_SDIO_ERROR;
  4692. }
  4693. err:
  4694. if (memblock)
  4695. MFREE(bus->dhd->osh, memblock, MEMBLOCK);
  4696. if (image)
  4697. dhd_os_close_image(image);
  4698. return bcmerror;
  4699. }
  4700. static int
  4701. _dhdsdio_download_firmware(struct dhd_bus *bus)
  4702. {
  4703. int bcmerror = -1;
  4704. bool embed = FALSE; /* download embedded firmware */
  4705. bool dlok = FALSE; /* download firmware succeeded */
  4706. /* Out immediately if no image to download */
  4707. if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
  4708. #ifdef BCMEMBEDIMAGE
  4709. embed = TRUE;
  4710. #else
  4711. return bcmerror;
  4712. #endif
  4713. }
  4714. /* Keep arm in reset */
  4715. if (dhdsdio_download_state(bus, TRUE)) {
  4716. DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
  4717. goto err;
  4718. }
  4719. /* External image takes precedence if specified */
  4720. if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
  4721. if (dhdsdio_download_code_file(bus, bus->fw_path)) {
  4722. DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
  4723. #ifdef BCMEMBEDIMAGE
  4724. embed = TRUE;
  4725. #else
  4726. goto err;
  4727. #endif
  4728. }
  4729. else {
  4730. embed = FALSE;
  4731. dlok = TRUE;
  4732. }
  4733. }
  4734. #ifdef BCMEMBEDIMAGE
  4735. if (embed) {
  4736. if (dhdsdio_download_code_array(bus)) {
  4737. DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
  4738. goto err;
  4739. }
  4740. else {
  4741. dlok = TRUE;
  4742. }
  4743. }
  4744. #endif
  4745. if (!dlok) {
  4746. DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
  4747. goto err;
  4748. }
  4749. /* EXAMPLE: nvram_array */
  4750. /* If a valid nvram_arry is specified as above, it can be passed down to dongle */
  4751. /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
  4752. /* External nvram takes precedence if specified */
  4753. if (dhdsdio_download_nvram(bus)) {
  4754. DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
  4755. }
  4756. /* Take arm out of reset */
  4757. if (dhdsdio_download_state(bus, FALSE)) {
  4758. DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
  4759. goto err;
  4760. }
  4761. bcmerror = 0;
  4762. err:
  4763. return bcmerror;
  4764. }
  4765. static int
  4766. dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
  4767. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle)
  4768. {
  4769. int status;
  4770. /* 4329: GSPI check */
  4771. status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle);
  4772. return status;
  4773. }
  4774. static int
  4775. dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
  4776. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle)
  4777. {
  4778. return (bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle));
  4779. }
  4780. uint
  4781. dhd_bus_chip(struct dhd_bus *bus)
  4782. {
  4783. ASSERT(bus->sih != NULL);
  4784. return bus->sih->chip;
  4785. }
  4786. void *
  4787. dhd_bus_pub(struct dhd_bus *bus)
  4788. {
  4789. return bus->dhd;
  4790. }
  4791. void *
  4792. dhd_bus_txq(struct dhd_bus *bus)
  4793. {
  4794. return &bus->txq;
  4795. }
  4796. uint
  4797. dhd_bus_hdrlen(struct dhd_bus *bus)
  4798. {
  4799. return SDPCM_HDRLEN;
  4800. }
  4801. int
  4802. dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
  4803. {
  4804. int bcmerror = 0;
  4805. dhd_bus_t *bus;
  4806. bus = dhdp->bus;
  4807. if (flag == TRUE) {
  4808. if (!bus->dhd->dongle_reset) {
  4809. dhd_os_sdlock(dhdp);
  4810. /* Turning off watchdog */
  4811. dhd_os_wd_timer(dhdp, 0);
  4812. #if !defined(IGNORE_ETH0_DOWN)
  4813. /* Force flow control as protection when stop come before ifconfig_down */
  4814. dhd_txflowcontrol(bus->dhd, 0, ON);
  4815. #endif /* !defined(IGNORE_ETH0_DOWN) */
  4816. /* Expect app to have torn down any connection before calling */
  4817. /* Stop the bus, disable F2 */
  4818. dhd_bus_stop(bus, FALSE);
  4819. #if defined(OOB_INTR_ONLY)
  4820. bcmsdh_set_irq(FALSE);
  4821. #endif /* defined(OOB_INTR_ONLY) */
  4822. /* Clean tx/rx buffer pointers, detach from the dongle */
  4823. dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE);
  4824. bus->dhd->dongle_reset = TRUE;
  4825. bus->dhd->up = FALSE;
  4826. dhd_os_sdunlock(dhdp);
  4827. DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__));
  4828. /* App can now remove power from device */
  4829. } else
  4830. bcmerror = BCME_SDIO_ERROR;
  4831. } else {
  4832. /* App must have restored power to device before calling */
  4833. DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__));
  4834. if (bus->dhd->dongle_reset) {
  4835. /* Turn on WLAN */
  4836. dhd_os_sdlock(dhdp);
  4837. /* Reset SD client */
  4838. bcmsdh_reset(bus->sdh);
  4839. /* Attempt to re-attach & download */
  4840. if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
  4841. (uint32 *)SI_ENUM_BASE,
  4842. bus->cl_devid)) {
  4843. /* Attempt to download binary to the dongle */
  4844. if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
  4845. dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) {
  4846. /* Re-init bus, enable F2 transfer */
  4847. bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
  4848. if (bcmerror == BCME_OK) {
  4849. #if defined(OOB_INTR_ONLY)
  4850. bcmsdh_set_irq(TRUE);
  4851. dhd_enable_oob_intr(bus, TRUE);
  4852. #endif /* defined(OOB_INTR_ONLY) */
  4853. bus->dhd->dongle_reset = FALSE;
  4854. bus->dhd->up = TRUE;
  4855. #if !defined(IGNORE_ETH0_DOWN)
  4856. /* Restore flow control */
  4857. dhd_txflowcontrol(bus->dhd, 0, OFF);
  4858. #endif
  4859. /* Turning on watchdog back */
  4860. dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
  4861. DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
  4862. } else {
  4863. dhd_bus_stop(bus, FALSE);
  4864. dhdsdio_release_dongle(bus, bus->dhd->osh, FALSE);
  4865. }
  4866. } else
  4867. bcmerror = BCME_SDIO_ERROR;
  4868. } else
  4869. bcmerror = BCME_SDIO_ERROR;
  4870. dhd_os_sdunlock(dhdp);
  4871. } else {
  4872. bcmerror = BCME_NOTDOWN;
  4873. DHD_ERROR(("%s: Set DEVRESET=FALSE invoked when device is on\n",
  4874. __FUNCTION__));
  4875. bcmerror = BCME_SDIO_ERROR;
  4876. }
  4877. }
  4878. return bcmerror;
  4879. }