orinoco.patch 362 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933
  1. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/Kconfig linux-6.15.6/drivers/net/wireless/intersil/Kconfig
  2. --- linux-6.15.6.orig/drivers/net/wireless/intersil/Kconfig 2025-07-10 16:08:55.000000000 +0200
  3. +++ linux-6.15.6/drivers/net/wireless/intersil/Kconfig 2025-08-03 00:20:27.566744589 +0200
  4. @@ -12,6 +12,7 @@
  5. if WLAN_VENDOR_INTERSIL
  6. +source "drivers/net/wireless/intersil/orinoco/Kconfig"
  7. source "drivers/net/wireless/intersil/p54/Kconfig"
  8. endif # WLAN_VENDOR_INTERSIL
  9. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/Makefile linux-6.15.6/drivers/net/wireless/intersil/Makefile
  10. --- linux-6.15.6.orig/drivers/net/wireless/intersil/Makefile 2025-07-10 16:08:55.000000000 +0200
  11. +++ linux-6.15.6/drivers/net/wireless/intersil/Makefile 2025-08-03 00:20:54.161967083 +0200
  12. @@ -1,2 +1,3 @@
  13. # SPDX-License-Identifier: GPL-2.0-only
  14. +obj-$(CONFIG_HERMES) += orinoco/
  15. obj-$(CONFIG_P54_COMMON) += p54/
  16. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/airport.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/airport.c
  17. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/airport.c 1970-01-01 01:00:00.000000000 +0100
  18. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/airport.c 2025-08-03 15:01:59.313131673 +0200
  19. @@ -0,0 +1,268 @@
  20. +/* airport.c
  21. + *
  22. + * A driver for "Hermes" chipset based Apple Airport wireless
  23. + * card.
  24. + *
  25. + * Copyright notice & release notes in file main.c
  26. + *
  27. + * Note specific to airport stub:
  28. + *
  29. + * 0.05 : first version of the new split driver
  30. + * 0.06 : fix possible hang on powerup, add sleep support
  31. + */
  32. +
  33. +#define DRIVER_NAME "airport"
  34. +#define PFX DRIVER_NAME ": "
  35. +
  36. +#include <linux/module.h>
  37. +#include <linux/kernel.h>
  38. +#include <linux/init.h>
  39. +#include <linux/delay.h>
  40. +#include <linux/mod_devicetable.h>
  41. +#include <asm/pmac_feature.h>
  42. +
  43. +#include "orinoco.h"
  44. +
  45. +#define AIRPORT_IO_LEN (0x1000) /* one page */
  46. +
  47. +struct airport {
  48. + struct macio_dev *mdev;
  49. + void __iomem *vaddr;
  50. + unsigned int irq;
  51. + int irq_requested;
  52. + int ndev_registered;
  53. +};
  54. +
  55. +static int
  56. +airport_suspend(struct macio_dev *mdev, pm_message_t state)
  57. +{
  58. + struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
  59. + struct net_device *dev = priv->ndev;
  60. + struct airport *card = priv->card;
  61. + unsigned long flags;
  62. + int err;
  63. +
  64. + printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
  65. +
  66. + err = orinoco_lock(priv, &flags);
  67. + if (err) {
  68. + printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
  69. + dev->name);
  70. + return 0;
  71. + }
  72. +
  73. + orinoco_down(priv);
  74. + orinoco_unlock(priv, &flags);
  75. +
  76. + disable_irq(card->irq);
  77. + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  78. + macio_get_of_node(mdev), 0, 0);
  79. +
  80. + return 0;
  81. +}
  82. +
  83. +static int
  84. +airport_resume(struct macio_dev *mdev)
  85. +{
  86. + struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
  87. + struct net_device *dev = priv->ndev;
  88. + struct airport *card = priv->card;
  89. + unsigned long flags;
  90. + int err;
  91. +
  92. + printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
  93. +
  94. + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  95. + macio_get_of_node(mdev), 0, 1);
  96. + msleep(200);
  97. +
  98. + enable_irq(card->irq);
  99. +
  100. + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
  101. + err = orinoco_up(priv);
  102. + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  103. +
  104. + return err;
  105. +}
  106. +
  107. +static int
  108. +airport_detach(struct macio_dev *mdev)
  109. +{
  110. + struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
  111. + struct airport *card = priv->card;
  112. +
  113. + if (card->ndev_registered)
  114. + orinoco_if_del(priv);
  115. + card->ndev_registered = 0;
  116. +
  117. + if (card->irq_requested)
  118. + free_irq(card->irq, priv);
  119. + card->irq_requested = 0;
  120. +
  121. + if (card->vaddr)
  122. + iounmap(card->vaddr);
  123. + card->vaddr = NULL;
  124. +
  125. + macio_release_resource(mdev, 0);
  126. +
  127. + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  128. + macio_get_of_node(mdev), 0, 0);
  129. + ssleep(1);
  130. +
  131. + macio_set_drvdata(mdev, NULL);
  132. + free_orinocodev(priv);
  133. +
  134. + return 0;
  135. +}
  136. +
  137. +static int airport_hard_reset(struct orinoco_private *priv)
  138. +{
  139. + /* It would be nice to power cycle the Airport for a real hard
  140. + * reset, but for some reason although it appears to
  141. + * re-initialize properly, it falls in a screaming heap
  142. + * shortly afterwards. */
  143. +#if 0
  144. + struct airport *card = priv->card;
  145. +
  146. + /* Vitally important. If we don't do this it seems we get an
  147. + * interrupt somewhere during the power cycle, since
  148. + * hw_unavailable is already set it doesn't get ACKed, we get
  149. + * into an interrupt loop and the PMU decides to turn us
  150. + * off. */
  151. + disable_irq(card->irq);
  152. +
  153. + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  154. + macio_get_of_node(card->mdev), 0, 0);
  155. + ssleep(1);
  156. + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  157. + macio_get_of_node(card->mdev), 0, 1);
  158. + ssleep(1);
  159. +
  160. + enable_irq(card->irq);
  161. + ssleep(1);
  162. +#endif
  163. +
  164. + return 0;
  165. +}
  166. +
  167. +static int
  168. +airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
  169. +{
  170. + struct orinoco_private *priv;
  171. + struct airport *card;
  172. + unsigned long phys_addr;
  173. + struct hermes *hw;
  174. +
  175. + if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
  176. + printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
  177. + return -ENODEV;
  178. + }
  179. +
  180. + /* Allocate space for private device-specific data */
  181. + priv = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
  182. + airport_hard_reset, NULL);
  183. + if (!priv) {
  184. + printk(KERN_ERR PFX "Cannot allocate network device\n");
  185. + return -ENODEV;
  186. + }
  187. + card = priv->card;
  188. +
  189. + hw = &priv->hw;
  190. + card->mdev = mdev;
  191. +
  192. + if (macio_request_resource(mdev, 0, DRIVER_NAME)) {
  193. + printk(KERN_ERR PFX "can't request IO resource !\n");
  194. + free_orinocodev(priv);
  195. + return -EBUSY;
  196. + }
  197. +
  198. + macio_set_drvdata(mdev, priv);
  199. +
  200. + /* Setup interrupts & base address */
  201. + card->irq = macio_irq(mdev, 0);
  202. + phys_addr = macio_resource_start(mdev, 0); /* Physical address */
  203. + printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
  204. + card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
  205. + if (!card->vaddr) {
  206. + printk(KERN_ERR PFX "ioremap() failed\n");
  207. + goto failed;
  208. + }
  209. +
  210. + hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
  211. +
  212. + /* Power up card */
  213. + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  214. + macio_get_of_node(mdev), 0, 1);
  215. + ssleep(1);
  216. +
  217. + /* Reset it before we get the interrupt */
  218. + hw->ops->init(hw);
  219. +
  220. + if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
  221. + printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
  222. + goto failed;
  223. + }
  224. + card->irq_requested = 1;
  225. +
  226. + /* Initialise the main driver */
  227. + if (orinoco_init(priv) != 0) {
  228. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  229. + goto failed;
  230. + }
  231. +
  232. + /* Register an interface with the stack */
  233. + if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
  234. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  235. + goto failed;
  236. + }
  237. + card->ndev_registered = 1;
  238. + return 0;
  239. + failed:
  240. + airport_detach(mdev);
  241. + return -ENODEV;
  242. +} /* airport_attach */
  243. +
  244. +
  245. +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  246. + " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
  247. +MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
  248. +MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
  249. +MODULE_LICENSE("Dual MPL/GPL");
  250. +
  251. +static const struct of_device_id airport_match[] = {
  252. + {
  253. + .name = "radio",
  254. + },
  255. + {},
  256. +};
  257. +
  258. +MODULE_DEVICE_TABLE(of, airport_match);
  259. +
  260. +static struct macio_driver airport_driver = {
  261. + .driver = {
  262. + .name = DRIVER_NAME,
  263. + .owner = THIS_MODULE,
  264. + .of_match_table = airport_match,
  265. + },
  266. + .probe = airport_attach,
  267. + .remove = airport_detach,
  268. + .suspend = airport_suspend,
  269. + .resume = airport_resume,
  270. +};
  271. +
  272. +static int __init
  273. +init_airport(void)
  274. +{
  275. + printk(KERN_DEBUG "%s\n", version);
  276. +
  277. + return macio_register_driver(&airport_driver);
  278. +}
  279. +
  280. +static void __exit
  281. +exit_airport(void)
  282. +{
  283. + macio_unregister_driver(&airport_driver);
  284. +}
  285. +
  286. +module_init(init_airport);
  287. +module_exit(exit_airport);
  288. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/cfg.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/cfg.c
  289. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/cfg.c 1970-01-01 01:00:00.000000000 +0100
  290. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/cfg.c 2025-08-03 16:35:08.118093622 +0200
  291. @@ -0,0 +1,292 @@
  292. +/* cfg80211 support
  293. + *
  294. + * See copyright notice in main.c
  295. + */
  296. +#include <linux/ieee80211.h>
  297. +#include <net/cfg80211.h>
  298. +#include "hw.h"
  299. +#include "main.h"
  300. +#include "orinoco.h"
  301. +
  302. +#include "cfg.h"
  303. +
  304. +/* Supported bitrates. Must agree with hw.c */
  305. +static struct ieee80211_rate orinoco_rates[] = {
  306. + { .bitrate = 10 },
  307. + { .bitrate = 20 },
  308. + { .bitrate = 55 },
  309. + { .bitrate = 110 },
  310. +};
  311. +
  312. +static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
  313. +
  314. +/* Called after orinoco_private is allocated. */
  315. +void orinoco_wiphy_init(struct wiphy *wiphy)
  316. +{
  317. + struct orinoco_private *priv = wiphy_priv(wiphy);
  318. +
  319. + wiphy->privid = orinoco_wiphy_privid;
  320. +
  321. + set_wiphy_dev(wiphy, priv->dev);
  322. +}
  323. +
  324. +/* Called after firmware is initialised */
  325. +int orinoco_wiphy_register(struct wiphy *wiphy)
  326. +{
  327. + struct orinoco_private *priv = wiphy_priv(wiphy);
  328. + int i, channels = 0;
  329. +
  330. + if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
  331. + wiphy->max_scan_ssids = 1;
  332. + else
  333. + wiphy->max_scan_ssids = 0;
  334. +
  335. + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
  336. +
  337. + /* TODO: should we set if we only have demo ad-hoc?
  338. + * (priv->has_port3)
  339. + */
  340. + if (priv->has_ibss)
  341. + wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
  342. +
  343. + if (!priv->broken_monitor || force_monitor)
  344. + wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
  345. +
  346. + priv->band.bitrates = orinoco_rates;
  347. + priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
  348. +
  349. + /* Only support channels allowed by the card EEPROM */
  350. + for (i = 0; i < NUM_CHANNELS; i++) {
  351. + if (priv->channel_mask & (1 << i)) {
  352. + priv->channels[i].center_freq =
  353. + ieee80211_channel_to_frequency(i + 1,
  354. + NL80211_BAND_2GHZ);
  355. + channels++;
  356. + }
  357. + }
  358. + priv->band.channels = priv->channels;
  359. + priv->band.n_channels = channels;
  360. +
  361. + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
  362. + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
  363. +
  364. + i = 0;
  365. + if (priv->has_wep) {
  366. + priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
  367. + i++;
  368. +
  369. + if (priv->has_big_wep) {
  370. + priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
  371. + i++;
  372. + }
  373. + }
  374. + if (priv->has_wpa) {
  375. + priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
  376. + i++;
  377. + }
  378. + wiphy->cipher_suites = priv->cipher_suites;
  379. + wiphy->n_cipher_suites = i;
  380. +
  381. + wiphy->rts_threshold = priv->rts_thresh;
  382. + if (!priv->has_mwo)
  383. + wiphy->frag_threshold = priv->frag_thresh + 1;
  384. + wiphy->retry_short = priv->short_retry_limit;
  385. + wiphy->retry_long = priv->long_retry_limit;
  386. +
  387. + return wiphy_register(wiphy);
  388. +}
  389. +
  390. +static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
  391. + enum nl80211_iftype type,
  392. + struct vif_params *params)
  393. +{
  394. + struct orinoco_private *priv = wiphy_priv(wiphy);
  395. + int err = 0;
  396. + unsigned long lock;
  397. +
  398. + if (orinoco_lock(priv, &lock) != 0)
  399. + return -EBUSY;
  400. +
  401. + switch (type) {
  402. + case NL80211_IFTYPE_ADHOC:
  403. + if (!priv->has_ibss && !priv->has_port3)
  404. + err = -EINVAL;
  405. + break;
  406. +
  407. + case NL80211_IFTYPE_STATION:
  408. + break;
  409. +
  410. + case NL80211_IFTYPE_MONITOR:
  411. + if (priv->broken_monitor && !force_monitor) {
  412. + wiphy_warn(wiphy,
  413. + "Monitor mode support is buggy in this firmware, not enabling\n");
  414. + err = -EINVAL;
  415. + }
  416. + break;
  417. +
  418. + default:
  419. + err = -EINVAL;
  420. + }
  421. +
  422. + if (!err) {
  423. + priv->iw_mode = type;
  424. + set_port_type(priv);
  425. + err = orinoco_commit(priv);
  426. + }
  427. +
  428. + orinoco_unlock(priv, &lock);
  429. +
  430. + return err;
  431. +}
  432. +
  433. +static int orinoco_scan(struct wiphy *wiphy,
  434. + struct cfg80211_scan_request *request)
  435. +{
  436. + struct orinoco_private *priv = wiphy_priv(wiphy);
  437. + int err;
  438. +
  439. + if (!request)
  440. + return -EINVAL;
  441. +
  442. + if (priv->scan_request && priv->scan_request != request)
  443. + return -EBUSY;
  444. +
  445. + priv->scan_request = request;
  446. +
  447. + err = orinoco_hw_trigger_scan(priv, request->ssids);
  448. + /* On error the we aren't processing the request */
  449. + if (err)
  450. + priv->scan_request = NULL;
  451. +
  452. + return err;
  453. +}
  454. +
  455. +static int orinoco_set_monitor_channel(struct wiphy *wiphy,
  456. + struct net_device *dev,
  457. + struct cfg80211_chan_def *chandef)
  458. +{
  459. + struct orinoco_private *priv = wiphy_priv(wiphy);
  460. + int err = 0;
  461. + unsigned long flags;
  462. + int channel;
  463. +
  464. + if (!chandef->chan)
  465. + return -EINVAL;
  466. +
  467. + if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
  468. + return -EINVAL;
  469. +
  470. + if (chandef->chan->band != NL80211_BAND_2GHZ)
  471. + return -EINVAL;
  472. +
  473. + channel = ieee80211_frequency_to_channel(chandef->chan->center_freq);
  474. +
  475. + if ((channel < 1) || (channel > NUM_CHANNELS) ||
  476. + !(priv->channel_mask & (1 << (channel - 1))))
  477. + return -EINVAL;
  478. +
  479. + if (orinoco_lock(priv, &flags) != 0)
  480. + return -EBUSY;
  481. +
  482. + priv->channel = channel;
  483. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
  484. + /* Fast channel change - no commit if successful */
  485. + struct hermes *hw = &priv->hw;
  486. + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
  487. + HERMES_TEST_SET_CHANNEL,
  488. + channel, NULL);
  489. + }
  490. + orinoco_unlock(priv, &flags);
  491. +
  492. + return err;
  493. +}
  494. +
  495. +static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
  496. +{
  497. + struct orinoco_private *priv = wiphy_priv(wiphy);
  498. + int frag_value = -1;
  499. + int rts_value = -1;
  500. + int err = 0;
  501. +
  502. + if (changed & WIPHY_PARAM_RETRY_SHORT) {
  503. + /* Setting short retry not supported */
  504. + err = -EINVAL;
  505. + }
  506. +
  507. + if (changed & WIPHY_PARAM_RETRY_LONG) {
  508. + /* Setting long retry not supported */
  509. + err = -EINVAL;
  510. + }
  511. +
  512. + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
  513. + /* Set fragmentation */
  514. + if (priv->has_mwo) {
  515. + if (wiphy->frag_threshold == -1)
  516. + frag_value = 0;
  517. + else {
  518. + printk(KERN_WARNING "%s: Fixed fragmentation "
  519. + "is not supported on this firmware. "
  520. + "Using MWO robust instead.\n",
  521. + priv->ndev->name);
  522. + frag_value = 1;
  523. + }
  524. + } else {
  525. + if (wiphy->frag_threshold == -1)
  526. + frag_value = 2346;
  527. + else if ((wiphy->frag_threshold < 257) ||
  528. + (wiphy->frag_threshold > 2347))
  529. + err = -EINVAL;
  530. + else
  531. + /* cfg80211 value is 257-2347 (odd only)
  532. + * orinoco rid has range 256-2346 (even only) */
  533. + frag_value = wiphy->frag_threshold & ~0x1;
  534. + }
  535. + }
  536. +
  537. + if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
  538. + /* Set RTS.
  539. + *
  540. + * Prism documentation suggests default of 2432,
  541. + * and a range of 0-3000.
  542. + *
  543. + * Current implementation uses 2347 as the default and
  544. + * the upper limit.
  545. + */
  546. +
  547. + if (wiphy->rts_threshold == -1)
  548. + rts_value = 2347;
  549. + else if (wiphy->rts_threshold > 2347)
  550. + err = -EINVAL;
  551. + else
  552. + rts_value = wiphy->rts_threshold;
  553. + }
  554. +
  555. + if (!err) {
  556. + unsigned long flags;
  557. +
  558. + if (orinoco_lock(priv, &flags) != 0)
  559. + return -EBUSY;
  560. +
  561. + if (frag_value >= 0) {
  562. + if (priv->has_mwo)
  563. + priv->mwo_robust = frag_value;
  564. + else
  565. + priv->frag_thresh = frag_value;
  566. + }
  567. + if (rts_value >= 0)
  568. + priv->rts_thresh = rts_value;
  569. +
  570. + err = orinoco_commit(priv);
  571. +
  572. + orinoco_unlock(priv, &flags);
  573. + }
  574. +
  575. + return err;
  576. +}
  577. +
  578. +const struct cfg80211_ops orinoco_cfg_ops = {
  579. + .change_virtual_intf = orinoco_change_vif,
  580. + .set_monitor_channel = orinoco_set_monitor_channel,
  581. + .scan = orinoco_scan,
  582. + .set_wiphy_params = orinoco_set_wiphy_params,
  583. +};
  584. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/cfg.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/cfg.h
  585. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/cfg.h 1970-01-01 01:00:00.000000000 +0100
  586. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/cfg.h 2025-08-03 15:01:59.313131673 +0200
  587. @@ -0,0 +1,15 @@
  588. +/* cfg80211 support.
  589. + *
  590. + * See copyright notice in main.c
  591. + */
  592. +#ifndef ORINOCO_CFG_H
  593. +#define ORINOCO_CFG_H
  594. +
  595. +#include <net/cfg80211.h>
  596. +
  597. +extern const struct cfg80211_ops orinoco_cfg_ops;
  598. +
  599. +void orinoco_wiphy_init(struct wiphy *wiphy);
  600. +int orinoco_wiphy_register(struct wiphy *wiphy);
  601. +
  602. +#endif /* ORINOCO_CFG_H */
  603. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/fw.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/fw.c
  604. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/fw.c 1970-01-01 01:00:00.000000000 +0100
  605. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/fw.c 2025-08-03 15:01:59.313131673 +0200
  606. @@ -0,0 +1,387 @@
  607. +/* Firmware file reading and download helpers
  608. + *
  609. + * See copyright notice in main.c
  610. + */
  611. +#include <linux/kernel.h>
  612. +#include <linux/slab.h>
  613. +#include <linux/firmware.h>
  614. +#include <linux/device.h>
  615. +#include <linux/module.h>
  616. +
  617. +#include "hermes.h"
  618. +#include "hermes_dld.h"
  619. +#include "orinoco.h"
  620. +
  621. +#include "fw.h"
  622. +
  623. +/* End markers (for Symbol firmware only) */
  624. +#define TEXT_END 0x1A /* End of text header */
  625. +
  626. +struct fw_info {
  627. + char *pri_fw;
  628. + char *sta_fw;
  629. + char *ap_fw;
  630. + u32 pda_addr;
  631. + u16 pda_size;
  632. +};
  633. +
  634. +static const struct fw_info orinoco_fw[] = {
  635. + { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
  636. + { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
  637. + { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
  638. +};
  639. +MODULE_FIRMWARE("agere_sta_fw.bin");
  640. +MODULE_FIRMWARE("agere_ap_fw.bin");
  641. +MODULE_FIRMWARE("prism_sta_fw.bin");
  642. +MODULE_FIRMWARE("prism_ap_fw.bin");
  643. +MODULE_FIRMWARE("symbol_sp24t_prim_fw");
  644. +MODULE_FIRMWARE("symbol_sp24t_sec_fw");
  645. +
  646. +/* Structure used to access fields in FW
  647. + * Make sure LE decoding macros are used
  648. + */
  649. +struct orinoco_fw_header {
  650. + char hdr_vers[6]; /* ASCII string for header version */
  651. + __le16 headersize; /* Total length of header */
  652. + __le32 entry_point; /* NIC entry point */
  653. + __le32 blocks; /* Number of blocks to program */
  654. + __le32 block_offset; /* Offset of block data from eof header */
  655. + __le32 pdr_offset; /* Offset to PDR data from eof header */
  656. + __le32 pri_offset; /* Offset to primary plug data */
  657. + __le32 compat_offset; /* Offset to compatibility data*/
  658. + char signature[]; /* FW signature length headersize-20 */
  659. +} __packed;
  660. +
  661. +/* Check the range of various header entries. Return a pointer to a
  662. + * description of the problem, or NULL if everything checks out. */
  663. +static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len)
  664. +{
  665. + u16 hdrsize;
  666. +
  667. + if (len < sizeof(*hdr))
  668. + return "image too small";
  669. + if (memcmp(hdr->hdr_vers, "HFW", 3) != 0)
  670. + return "format not recognised";
  671. +
  672. + hdrsize = le16_to_cpu(hdr->headersize);
  673. + if (hdrsize > len)
  674. + return "bad headersize";
  675. + if ((hdrsize + le32_to_cpu(hdr->block_offset)) > len)
  676. + return "bad block offset";
  677. + if ((hdrsize + le32_to_cpu(hdr->pdr_offset)) > len)
  678. + return "bad PDR offset";
  679. + if ((hdrsize + le32_to_cpu(hdr->pri_offset)) > len)
  680. + return "bad PRI offset";
  681. + if ((hdrsize + le32_to_cpu(hdr->compat_offset)) > len)
  682. + return "bad compat offset";
  683. +
  684. + /* TODO: consider adding a checksum or CRC to the firmware format */
  685. + return NULL;
  686. +}
  687. +
  688. +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
  689. +static inline const struct firmware *
  690. +orinoco_cached_fw_get(struct orinoco_private *priv, bool primary)
  691. +{
  692. + if (primary)
  693. + return priv->cached_pri_fw;
  694. + else
  695. + return priv->cached_fw;
  696. +}
  697. +#else
  698. +#define orinoco_cached_fw_get(priv, primary) (NULL)
  699. +#endif
  700. +
  701. +/* Download either STA or AP firmware into the card. */
  702. +static int
  703. +orinoco_dl_firmware(struct orinoco_private *priv,
  704. + const struct fw_info *fw,
  705. + int ap)
  706. +{
  707. + /* Plug Data Area (PDA) */
  708. + __le16 *pda;
  709. +
  710. + struct hermes *hw = &priv->hw;
  711. + const struct firmware *fw_entry;
  712. + const struct orinoco_fw_header *hdr;
  713. + const unsigned char *first_block;
  714. + const void *end;
  715. + const char *firmware;
  716. + const char *fw_err;
  717. + struct device *dev = priv->dev;
  718. + int err = 0;
  719. +
  720. + pda = kzalloc(fw->pda_size, GFP_KERNEL);
  721. + if (!pda)
  722. + return -ENOMEM;
  723. +
  724. + if (ap)
  725. + firmware = fw->ap_fw;
  726. + else
  727. + firmware = fw->sta_fw;
  728. +
  729. + dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
  730. +
  731. + /* Read current plug data */
  732. + err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
  733. + dev_dbg(dev, "Read PDA returned %d\n", err);
  734. + if (err)
  735. + goto free;
  736. +
  737. + if (!orinoco_cached_fw_get(priv, false)) {
  738. + err = request_firmware(&fw_entry, firmware, priv->dev);
  739. +
  740. + if (err) {
  741. + dev_err(dev, "Cannot find firmware %s\n", firmware);
  742. + err = -ENOENT;
  743. + goto free;
  744. + }
  745. + } else
  746. + fw_entry = orinoco_cached_fw_get(priv, false);
  747. +
  748. + hdr = (const struct orinoco_fw_header *) fw_entry->data;
  749. +
  750. + fw_err = validate_fw(hdr, fw_entry->size);
  751. + if (fw_err) {
  752. + dev_warn(dev, "Invalid firmware image detected (%s). "
  753. + "Aborting download\n", fw_err);
  754. + err = -EINVAL;
  755. + goto abort;
  756. + }
  757. +
  758. + /* Enable aux port to allow programming */
  759. + err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));
  760. + dev_dbg(dev, "Program init returned %d\n", err);
  761. + if (err != 0)
  762. + goto abort;
  763. +
  764. + /* Program data */
  765. + first_block = (fw_entry->data +
  766. + le16_to_cpu(hdr->headersize) +
  767. + le32_to_cpu(hdr->block_offset));
  768. + end = fw_entry->data + fw_entry->size;
  769. +
  770. + err = hermes_program(hw, first_block, end);
  771. + dev_dbg(dev, "Program returned %d\n", err);
  772. + if (err != 0)
  773. + goto abort;
  774. +
  775. + /* Update production data */
  776. + first_block = (fw_entry->data +
  777. + le16_to_cpu(hdr->headersize) +
  778. + le32_to_cpu(hdr->pdr_offset));
  779. +
  780. + err = hermes_apply_pda_with_defaults(hw, first_block, end, pda,
  781. + &pda[fw->pda_size / sizeof(*pda)]);
  782. + dev_dbg(dev, "Apply PDA returned %d\n", err);
  783. + if (err)
  784. + goto abort;
  785. +
  786. + /* Tell card we've finished */
  787. + err = hw->ops->program_end(hw);
  788. + dev_dbg(dev, "Program end returned %d\n", err);
  789. + if (err != 0)
  790. + goto abort;
  791. +
  792. + /* Check if we're running */
  793. + dev_dbg(dev, "hermes_present returned %d\n", hermes_present(hw));
  794. +
  795. +abort:
  796. + /* If we requested the firmware, release it. */
  797. + if (!orinoco_cached_fw_get(priv, false))
  798. + release_firmware(fw_entry);
  799. +
  800. +free:
  801. + kfree(pda);
  802. + return err;
  803. +}
  804. +
  805. +/*
  806. + * Process a firmware image - stop the card, load the firmware, reset
  807. + * the card and make sure it responds. For the secondary firmware take
  808. + * care of the PDA - read it and then write it on top of the firmware.
  809. + */
  810. +static int
  811. +symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
  812. + const unsigned char *image, const void *end,
  813. + int secondary)
  814. +{
  815. + struct hermes *hw = &priv->hw;
  816. + int ret = 0;
  817. + const unsigned char *ptr;
  818. + const unsigned char *first_block;
  819. +
  820. + /* Plug Data Area (PDA) */
  821. + __le16 *pda = NULL;
  822. +
  823. + /* Binary block begins after the 0x1A marker */
  824. + ptr = image;
  825. + while (*ptr++ != TEXT_END);
  826. + first_block = ptr;
  827. +
  828. + /* Read the PDA from EEPROM */
  829. + if (secondary) {
  830. + pda = kzalloc(fw->pda_size, GFP_KERNEL);
  831. + if (!pda)
  832. + return -ENOMEM;
  833. +
  834. + ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
  835. + if (ret)
  836. + goto free;
  837. + }
  838. +
  839. + /* Stop the firmware, so that it can be safely rewritten */
  840. + if (priv->stop_fw) {
  841. + ret = priv->stop_fw(priv, 1);
  842. + if (ret)
  843. + goto free;
  844. + }
  845. +
  846. + /* Program the adapter with new firmware */
  847. + ret = hermes_program(hw, first_block, end);
  848. + if (ret)
  849. + goto free;
  850. +
  851. + /* Write the PDA to the adapter */
  852. + if (secondary) {
  853. + size_t len = hermes_blocks_length(first_block, end);
  854. + ptr = first_block + len;
  855. + ret = hermes_apply_pda(hw, ptr, end, pda,
  856. + &pda[fw->pda_size / sizeof(*pda)]);
  857. + kfree(pda);
  858. + if (ret)
  859. + return ret;
  860. + }
  861. +
  862. + /* Run the firmware */
  863. + if (priv->stop_fw) {
  864. + ret = priv->stop_fw(priv, 0);
  865. + if (ret)
  866. + return ret;
  867. + }
  868. +
  869. + /* Reset hermes chip and make sure it responds */
  870. + ret = hw->ops->init(hw);
  871. +
  872. + /* hermes_reset() should return 0 with the secondary firmware */
  873. + if (secondary && ret != 0)
  874. + return -ENODEV;
  875. +
  876. + /* And this should work with any firmware */
  877. + if (!hermes_present(hw))
  878. + return -ENODEV;
  879. +
  880. + return 0;
  881. +
  882. +free:
  883. + kfree(pda);
  884. + return ret;
  885. +}
  886. +
  887. +
  888. +/*
  889. + * Download the firmware into the card, this also does a PCMCIA soft
  890. + * reset on the card, to make sure it's in a sane state.
  891. + */
  892. +static int
  893. +symbol_dl_firmware(struct orinoco_private *priv,
  894. + const struct fw_info *fw)
  895. +{
  896. + struct device *dev = priv->dev;
  897. + int ret;
  898. + const struct firmware *fw_entry;
  899. +
  900. + if (!orinoco_cached_fw_get(priv, true)) {
  901. + if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) {
  902. + dev_err(dev, "Cannot find firmware: %s\n", fw->pri_fw);
  903. + return -ENOENT;
  904. + }
  905. + } else
  906. + fw_entry = orinoco_cached_fw_get(priv, true);
  907. +
  908. + /* Load primary firmware */
  909. + ret = symbol_dl_image(priv, fw, fw_entry->data,
  910. + fw_entry->data + fw_entry->size, 0);
  911. +
  912. + if (!orinoco_cached_fw_get(priv, true))
  913. + release_firmware(fw_entry);
  914. + if (ret) {
  915. + dev_err(dev, "Primary firmware download failed\n");
  916. + return ret;
  917. + }
  918. +
  919. + if (!orinoco_cached_fw_get(priv, false)) {
  920. + if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) {
  921. + dev_err(dev, "Cannot find firmware: %s\n", fw->sta_fw);
  922. + return -ENOENT;
  923. + }
  924. + } else
  925. + fw_entry = orinoco_cached_fw_get(priv, false);
  926. +
  927. + /* Load secondary firmware */
  928. + ret = symbol_dl_image(priv, fw, fw_entry->data,
  929. + fw_entry->data + fw_entry->size, 1);
  930. + if (!orinoco_cached_fw_get(priv, false))
  931. + release_firmware(fw_entry);
  932. + if (ret)
  933. + dev_err(dev, "Secondary firmware download failed\n");
  934. +
  935. + return ret;
  936. +}
  937. +
  938. +int orinoco_download(struct orinoco_private *priv)
  939. +{
  940. + int err = 0;
  941. + /* Reload firmware */
  942. + switch (priv->firmware_type) {
  943. + case FIRMWARE_TYPE_AGERE:
  944. + /* case FIRMWARE_TYPE_INTERSIL: */
  945. + err = orinoco_dl_firmware(priv,
  946. + &orinoco_fw[priv->firmware_type], 0);
  947. + break;
  948. +
  949. + case FIRMWARE_TYPE_SYMBOL:
  950. + err = symbol_dl_firmware(priv,
  951. + &orinoco_fw[priv->firmware_type]);
  952. + break;
  953. + case FIRMWARE_TYPE_INTERSIL:
  954. + break;
  955. + }
  956. + /* TODO: if we fail we probably need to reinitialise
  957. + * the driver */
  958. +
  959. + return err;
  960. +}
  961. +
  962. +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
  963. +void orinoco_cache_fw(struct orinoco_private *priv, int ap)
  964. +{
  965. + const struct firmware *fw_entry = NULL;
  966. + const char *pri_fw;
  967. + const char *fw;
  968. +
  969. + pri_fw = orinoco_fw[priv->firmware_type].pri_fw;
  970. + if (ap)
  971. + fw = orinoco_fw[priv->firmware_type].ap_fw;
  972. + else
  973. + fw = orinoco_fw[priv->firmware_type].sta_fw;
  974. +
  975. + if (pri_fw) {
  976. + if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0)
  977. + priv->cached_pri_fw = fw_entry;
  978. + }
  979. +
  980. + if (fw) {
  981. + if (request_firmware(&fw_entry, fw, priv->dev) == 0)
  982. + priv->cached_fw = fw_entry;
  983. + }
  984. +}
  985. +
  986. +void orinoco_uncache_fw(struct orinoco_private *priv)
  987. +{
  988. + release_firmware(priv->cached_pri_fw);
  989. + release_firmware(priv->cached_fw);
  990. + priv->cached_pri_fw = NULL;
  991. + priv->cached_fw = NULL;
  992. +}
  993. +#endif
  994. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/fw.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/fw.h
  995. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/fw.h 1970-01-01 01:00:00.000000000 +0100
  996. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/fw.h 2025-08-03 15:01:59.313131673 +0200
  997. @@ -0,0 +1,21 @@
  998. +/* Firmware file reading and download helpers
  999. + *
  1000. + * See copyright notice in main.c
  1001. + */
  1002. +#ifndef _ORINOCO_FW_H_
  1003. +#define _ORINOCO_FW_H_
  1004. +
  1005. +/* Forward declations */
  1006. +struct orinoco_private;
  1007. +
  1008. +int orinoco_download(struct orinoco_private *priv);
  1009. +
  1010. +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
  1011. +void orinoco_cache_fw(struct orinoco_private *priv, int ap);
  1012. +void orinoco_uncache_fw(struct orinoco_private *priv);
  1013. +#else
  1014. +#define orinoco_cache_fw(priv, ap) do { } while (0)
  1015. +#define orinoco_uncache_fw(priv) do { } while (0)
  1016. +#endif
  1017. +
  1018. +#endif /* _ORINOCO_FW_H_ */
  1019. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes.c
  1020. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes.c 1970-01-01 01:00:00.000000000 +0100
  1021. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes.c 2025-08-03 22:42:47.279513981 +0200
  1022. @@ -0,0 +1,778 @@
  1023. +/* hermes.c
  1024. + *
  1025. + * Driver core for the "Hermes" wireless MAC controller, as used in
  1026. + * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
  1027. + * work on the hfa3841 and hfa3842 MAC controller chips used in the
  1028. + * Prism II chipsets.
  1029. + *
  1030. + * This is not a complete driver, just low-level access routines for
  1031. + * the MAC controller itself.
  1032. + *
  1033. + * Based on the prism2 driver from Absolute Value Systems' linux-wlan
  1034. + * project, the Linux wvlan_cs driver, Lucent's HCF-Light
  1035. + * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
  1036. + * particular order).
  1037. + *
  1038. + * Copyright (C) 2000, David Gibson, Linuxcare Australia.
  1039. + * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  1040. + *
  1041. + * The contents of this file are subject to the Mozilla Public License
  1042. + * Version 1.1 (the "License"); you may not use this file except in
  1043. + * compliance with the License. You may obtain a copy of the License
  1044. + * at http://www.mozilla.org/MPL/
  1045. + *
  1046. + * Software distributed under the License is distributed on an "AS IS"
  1047. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  1048. + * the License for the specific language governing rights and
  1049. + * limitations under the License.
  1050. + *
  1051. + * Alternatively, the contents of this file may be used under the
  1052. + * terms of the GNU General Public License version 2 (the "GPL"), in
  1053. + * which case the provisions of the GPL are applicable instead of the
  1054. + * above. If you wish to allow the use of your version of this file
  1055. + * only under the terms of the GPL and not to allow others to use your
  1056. + * version of this file under the MPL, indicate your decision by
  1057. + * deleting the provisions above and replace them with the notice and
  1058. + * other provisions required by the GPL. If you do not delete the
  1059. + * provisions above, a recipient may use your version of this file
  1060. + * under either the MPL or the GPL.
  1061. + */
  1062. +
  1063. +#include <linux/net.h>
  1064. +#include <linux/module.h>
  1065. +#include <linux/kernel.h>
  1066. +#include <linux/delay.h>
  1067. +
  1068. +#include "hermes.h"
  1069. +
  1070. +/* These are maximum timeouts. Most often, card wil react much faster */
  1071. +#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
  1072. +#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
  1073. +#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
  1074. +#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
  1075. +
  1076. +/*
  1077. + * AUX port access. To unlock the AUX port write the access keys to the
  1078. + * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
  1079. + * register. Then read it and make sure it's HERMES_AUX_ENABLED.
  1080. + */
  1081. +#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
  1082. +#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
  1083. +#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
  1084. +#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
  1085. +
  1086. +#define HERMES_AUX_PW0 0xFE01
  1087. +#define HERMES_AUX_PW1 0xDC23
  1088. +#define HERMES_AUX_PW2 0xBA45
  1089. +
  1090. +/* HERMES_CMD_DOWNLD */
  1091. +#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
  1092. +#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
  1093. +#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
  1094. +#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
  1095. +
  1096. +/*
  1097. + * Debugging helpers
  1098. + */
  1099. +
  1100. +#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
  1101. + printk(stuff); } while (0)
  1102. +
  1103. +#undef HERMES_DEBUG
  1104. +#ifdef HERMES_DEBUG
  1105. +
  1106. +#define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff)
  1107. +
  1108. +#else /* ! HERMES_DEBUG */
  1109. +
  1110. +#define DEBUG(lvl, stuff...) do { } while (0)
  1111. +
  1112. +#endif /* ! HERMES_DEBUG */
  1113. +
  1114. +static const struct hermes_ops hermes_ops_local;
  1115. +
  1116. +/*
  1117. + * Internal functions
  1118. + */
  1119. +
  1120. +/* Issue a command to the chip. Waiting for it to complete is the caller's
  1121. + problem.
  1122. +
  1123. + Returns -EBUSY if the command register is busy, 0 on success.
  1124. +
  1125. + Callable from any context.
  1126. +*/
  1127. +static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0,
  1128. + u16 param1, u16 param2)
  1129. +{
  1130. + int k = CMD_BUSY_TIMEOUT;
  1131. + u16 reg;
  1132. +
  1133. + /* First wait for the command register to unbusy */
  1134. + reg = hermes_read_regn(hw, CMD);
  1135. + while ((reg & HERMES_CMD_BUSY) && k) {
  1136. + k--;
  1137. + udelay(1);
  1138. + reg = hermes_read_regn(hw, CMD);
  1139. + }
  1140. + if (reg & HERMES_CMD_BUSY)
  1141. + return -EBUSY;
  1142. +
  1143. + hermes_write_regn(hw, PARAM2, param2);
  1144. + hermes_write_regn(hw, PARAM1, param1);
  1145. + hermes_write_regn(hw, PARAM0, param0);
  1146. + hermes_write_regn(hw, CMD, cmd);
  1147. +
  1148. + return 0;
  1149. +}
  1150. +
  1151. +/*
  1152. + * Function definitions
  1153. + */
  1154. +
  1155. +/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
  1156. +static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
  1157. + u16 parm0, u16 parm1, u16 parm2,
  1158. + struct hermes_response *resp)
  1159. +{
  1160. + int err = 0;
  1161. + int k;
  1162. + u16 status, reg;
  1163. +
  1164. + err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
  1165. + if (err)
  1166. + return err;
  1167. +
  1168. + reg = hermes_read_regn(hw, EVSTAT);
  1169. + k = CMD_INIT_TIMEOUT;
  1170. + while ((!(reg & HERMES_EV_CMD)) && k) {
  1171. + k--;
  1172. + udelay(10);
  1173. + reg = hermes_read_regn(hw, EVSTAT);
  1174. + }
  1175. +
  1176. + hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
  1177. +
  1178. + if (!hermes_present(hw)) {
  1179. + DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
  1180. + hw->iobase);
  1181. + err = -ENODEV;
  1182. + goto out;
  1183. + }
  1184. +
  1185. + if (!(reg & HERMES_EV_CMD)) {
  1186. + printk(KERN_ERR "hermes @ %p: "
  1187. + "Timeout waiting for card to reset (reg=0x%04x)!\n",
  1188. + hw->iobase, reg);
  1189. + err = -ETIMEDOUT;
  1190. + goto out;
  1191. + }
  1192. +
  1193. + status = hermes_read_regn(hw, STATUS);
  1194. + if (resp) {
  1195. + resp->status = status;
  1196. + resp->resp0 = hermes_read_regn(hw, RESP0);
  1197. + resp->resp1 = hermes_read_regn(hw, RESP1);
  1198. + resp->resp2 = hermes_read_regn(hw, RESP2);
  1199. + }
  1200. +
  1201. + hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
  1202. +
  1203. + if (status & HERMES_STATUS_RESULT)
  1204. + err = -EIO;
  1205. +out:
  1206. + return err;
  1207. +}
  1208. +
  1209. +void hermes_struct_init(struct hermes *hw, void __iomem *address,
  1210. + int reg_spacing)
  1211. +{
  1212. + hw->iobase = address;
  1213. + hw->reg_spacing = reg_spacing;
  1214. + hw->inten = 0x0;
  1215. + hw->eeprom_pda = false;
  1216. + hw->ops = &hermes_ops_local;
  1217. +}
  1218. +EXPORT_SYMBOL(hermes_struct_init);
  1219. +
  1220. +static int hermes_init(struct hermes *hw)
  1221. +{
  1222. + u16 reg;
  1223. + int err = 0;
  1224. + int k;
  1225. +
  1226. + /* We don't want to be interrupted while resetting the chipset */
  1227. + hw->inten = 0x0;
  1228. + hermes_write_regn(hw, INTEN, 0);
  1229. + hermes_write_regn(hw, EVACK, 0xffff);
  1230. +
  1231. + /* Normally it's a "can't happen" for the command register to
  1232. + be busy when we go to issue a command because we are
  1233. + serializing all commands. However we want to have some
  1234. + chance of resetting the card even if it gets into a stupid
  1235. + state, so we actually wait to see if the command register
  1236. + will unbusy itself here. */
  1237. + k = CMD_BUSY_TIMEOUT;
  1238. + reg = hermes_read_regn(hw, CMD);
  1239. + while (k && (reg & HERMES_CMD_BUSY)) {
  1240. + if (reg == 0xffff) /* Special case - the card has probably been
  1241. + removed, so don't wait for the timeout */
  1242. + return -ENODEV;
  1243. +
  1244. + k--;
  1245. + udelay(1);
  1246. + reg = hermes_read_regn(hw, CMD);
  1247. + }
  1248. +
  1249. + /* No need to explicitly handle the timeout - if we've timed
  1250. + out hermes_issue_cmd() will probably return -EBUSY below */
  1251. +
  1252. + /* According to the documentation, EVSTAT may contain
  1253. + obsolete event occurrence information. We have to acknowledge
  1254. + it by writing EVACK. */
  1255. + reg = hermes_read_regn(hw, EVSTAT);
  1256. + hermes_write_regn(hw, EVACK, reg);
  1257. +
  1258. + /* We don't use hermes_docmd_wait here, because the reset wipes
  1259. + the magic constant in SWSUPPORT0 away, and it gets confused */
  1260. + err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL);
  1261. +
  1262. + return err;
  1263. +}
  1264. +
  1265. +/* Issue a command to the chip, and (busy!) wait for it to
  1266. + * complete.
  1267. + *
  1268. + * Returns:
  1269. + * < 0 on internal error
  1270. + * 0 on success
  1271. + * > 0 on error returned by the firmware
  1272. + *
  1273. + * Callable from any context, but locking is your problem. */
  1274. +static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
  1275. + struct hermes_response *resp)
  1276. +{
  1277. + int err;
  1278. + int k;
  1279. + u16 reg;
  1280. + u16 status;
  1281. +
  1282. + err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
  1283. + if (err) {
  1284. + if (!hermes_present(hw)) {
  1285. + if (net_ratelimit())
  1286. + printk(KERN_WARNING "hermes @ %p: "
  1287. + "Card removed while issuing command "
  1288. + "0x%04x.\n", hw->iobase, cmd);
  1289. + err = -ENODEV;
  1290. + } else
  1291. + if (net_ratelimit())
  1292. + printk(KERN_ERR "hermes @ %p: "
  1293. + "Error %d issuing command 0x%04x.\n",
  1294. + hw->iobase, err, cmd);
  1295. + goto out;
  1296. + }
  1297. +
  1298. + reg = hermes_read_regn(hw, EVSTAT);
  1299. + k = CMD_COMPL_TIMEOUT;
  1300. + while ((!(reg & HERMES_EV_CMD)) && k) {
  1301. + k--;
  1302. + udelay(10);
  1303. + reg = hermes_read_regn(hw, EVSTAT);
  1304. + }
  1305. +
  1306. + if (!hermes_present(hw)) {
  1307. + printk(KERN_WARNING "hermes @ %p: Card removed "
  1308. + "while waiting for command 0x%04x completion.\n",
  1309. + hw->iobase, cmd);
  1310. + err = -ENODEV;
  1311. + goto out;
  1312. + }
  1313. +
  1314. + if (!(reg & HERMES_EV_CMD)) {
  1315. + printk(KERN_ERR "hermes @ %p: Timeout waiting for "
  1316. + "command 0x%04x completion.\n", hw->iobase, cmd);
  1317. + err = -ETIMEDOUT;
  1318. + goto out;
  1319. + }
  1320. +
  1321. + status = hermes_read_regn(hw, STATUS);
  1322. + if (resp) {
  1323. + resp->status = status;
  1324. + resp->resp0 = hermes_read_regn(hw, RESP0);
  1325. + resp->resp1 = hermes_read_regn(hw, RESP1);
  1326. + resp->resp2 = hermes_read_regn(hw, RESP2);
  1327. + }
  1328. +
  1329. + hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
  1330. +
  1331. + if (status & HERMES_STATUS_RESULT)
  1332. + err = -EIO;
  1333. +
  1334. + out:
  1335. + return err;
  1336. +}
  1337. +
  1338. +static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid)
  1339. +{
  1340. + int err = 0;
  1341. + int k;
  1342. + u16 reg;
  1343. +
  1344. + if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX))
  1345. + return -EINVAL;
  1346. +
  1347. + err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL);
  1348. + if (err)
  1349. + return err;
  1350. +
  1351. + reg = hermes_read_regn(hw, EVSTAT);
  1352. + k = ALLOC_COMPL_TIMEOUT;
  1353. + while ((!(reg & HERMES_EV_ALLOC)) && k) {
  1354. + k--;
  1355. + udelay(10);
  1356. + reg = hermes_read_regn(hw, EVSTAT);
  1357. + }
  1358. +
  1359. + if (!hermes_present(hw)) {
  1360. + printk(KERN_WARNING "hermes @ %p: "
  1361. + "Card removed waiting for frame allocation.\n",
  1362. + hw->iobase);
  1363. + return -ENODEV;
  1364. + }
  1365. +
  1366. + if (!(reg & HERMES_EV_ALLOC)) {
  1367. + printk(KERN_ERR "hermes @ %p: "
  1368. + "Timeout waiting for frame allocation\n",
  1369. + hw->iobase);
  1370. + return -ETIMEDOUT;
  1371. + }
  1372. +
  1373. + *fid = hermes_read_regn(hw, ALLOCFID);
  1374. + hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
  1375. +
  1376. + return 0;
  1377. +}
  1378. +
  1379. +/* Set up a BAP to read a particular chunk of data from card's internal buffer.
  1380. + *
  1381. + * Returns:
  1382. + * < 0 on internal failure (errno)
  1383. + * 0 on success
  1384. + * > 0 on error
  1385. + * from firmware
  1386. + *
  1387. + * Callable from any context */
  1388. +static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
  1389. +{
  1390. + int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
  1391. + int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
  1392. + int k;
  1393. + u16 reg;
  1394. +
  1395. + /* Paranoia.. */
  1396. + if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2))
  1397. + return -EINVAL;
  1398. +
  1399. + k = HERMES_BAP_BUSY_TIMEOUT;
  1400. + reg = hermes_read_reg(hw, oreg);
  1401. + while ((reg & HERMES_OFFSET_BUSY) && k) {
  1402. + k--;
  1403. + udelay(1);
  1404. + reg = hermes_read_reg(hw, oreg);
  1405. + }
  1406. +
  1407. + if (reg & HERMES_OFFSET_BUSY)
  1408. + return -ETIMEDOUT;
  1409. +
  1410. + /* Now we actually set up the transfer */
  1411. + hermes_write_reg(hw, sreg, id);
  1412. + hermes_write_reg(hw, oreg, offset);
  1413. +
  1414. + /* Wait for the BAP to be ready */
  1415. + k = HERMES_BAP_BUSY_TIMEOUT;
  1416. + reg = hermes_read_reg(hw, oreg);
  1417. + while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
  1418. + k--;
  1419. + udelay(1);
  1420. + reg = hermes_read_reg(hw, oreg);
  1421. + }
  1422. +
  1423. + if (reg != offset) {
  1424. + printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
  1425. + "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
  1426. + (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
  1427. + reg, id, offset);
  1428. +
  1429. + if (reg & HERMES_OFFSET_BUSY)
  1430. + return -ETIMEDOUT;
  1431. +
  1432. + return -EIO; /* error or wrong offset */
  1433. + }
  1434. +
  1435. + return 0;
  1436. +}
  1437. +
  1438. +/* Read a block of data from the chip's buffer, via the
  1439. + * BAP. Synchronization/serialization is the caller's problem. len
  1440. + * must be even.
  1441. + *
  1442. + * Returns:
  1443. + * < 0 on internal failure (errno)
  1444. + * 0 on success
  1445. + * > 0 on error from firmware
  1446. + */
  1447. +static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len,
  1448. + u16 id, u16 offset)
  1449. +{
  1450. + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
  1451. + int err = 0;
  1452. +
  1453. + if ((len < 0) || (len % 2))
  1454. + return -EINVAL;
  1455. +
  1456. + err = hermes_bap_seek(hw, bap, id, offset);
  1457. + if (err)
  1458. + goto out;
  1459. +
  1460. + /* Actually do the transfer */
  1461. + hermes_read_words(hw, dreg, buf, len / 2);
  1462. +
  1463. + out:
  1464. + return err;
  1465. +}
  1466. +
  1467. +/* Write a block of data to the chip's buffer, via the
  1468. + * BAP. Synchronization/serialization is the caller's problem.
  1469. + *
  1470. + * Returns:
  1471. + * < 0 on internal failure (errno)
  1472. + * 0 on success
  1473. + * > 0 on error from firmware
  1474. + */
  1475. +static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf,
  1476. + int len, u16 id, u16 offset)
  1477. +{
  1478. + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
  1479. + int err = 0;
  1480. +
  1481. + if (len < 0)
  1482. + return -EINVAL;
  1483. +
  1484. + err = hermes_bap_seek(hw, bap, id, offset);
  1485. + if (err)
  1486. + goto out;
  1487. +
  1488. + /* Actually do the transfer */
  1489. + hermes_write_bytes(hw, dreg, buf, len);
  1490. +
  1491. + out:
  1492. + return err;
  1493. +}
  1494. +
  1495. +/* Read a Length-Type-Value record from the card.
  1496. + *
  1497. + * If length is NULL, we ignore the length read from the card, and
  1498. + * read the entire buffer regardless. This is useful because some of
  1499. + * the configuration records appear to have incorrect lengths in
  1500. + * practice.
  1501. + *
  1502. + * Callable from user or bh context. */
  1503. +static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid,
  1504. + unsigned bufsize, u16 *length, void *buf)
  1505. +{
  1506. + int err = 0;
  1507. + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
  1508. + u16 rlength, rtype;
  1509. + unsigned nwords;
  1510. +
  1511. + if (bufsize % 2)
  1512. + return -EINVAL;
  1513. +
  1514. + err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
  1515. + if (err)
  1516. + return err;
  1517. +
  1518. + err = hermes_bap_seek(hw, bap, rid, 0);
  1519. + if (err)
  1520. + return err;
  1521. +
  1522. + rlength = hermes_read_reg(hw, dreg);
  1523. +
  1524. + if (!rlength)
  1525. + return -ENODATA;
  1526. +
  1527. + rtype = hermes_read_reg(hw, dreg);
  1528. +
  1529. + if (length)
  1530. + *length = rlength;
  1531. +
  1532. + if (rtype != rid)
  1533. + printk(KERN_WARNING "hermes @ %p: %s(): "
  1534. + "rid (0x%04x) does not match type (0x%04x)\n",
  1535. + hw->iobase, __func__, rid, rtype);
  1536. + if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
  1537. + printk(KERN_WARNING "hermes @ %p: "
  1538. + "Truncating LTV record from %d to %d bytes. "
  1539. + "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
  1540. + HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
  1541. +
  1542. + nwords = min((unsigned)rlength - 1, bufsize / 2);
  1543. + hermes_read_words(hw, dreg, buf, nwords);
  1544. +
  1545. + return 0;
  1546. +}
  1547. +
  1548. +static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid,
  1549. + u16 length, const void *value)
  1550. +{
  1551. + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
  1552. + int err = 0;
  1553. + unsigned count;
  1554. +
  1555. + if (length == 0)
  1556. + return -EINVAL;
  1557. +
  1558. + err = hermes_bap_seek(hw, bap, rid, 0);
  1559. + if (err)
  1560. + return err;
  1561. +
  1562. + hermes_write_reg(hw, dreg, length);
  1563. + hermes_write_reg(hw, dreg, rid);
  1564. +
  1565. + count = length - 1;
  1566. +
  1567. + hermes_write_bytes(hw, dreg, value, count << 1);
  1568. +
  1569. + err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
  1570. + rid, NULL);
  1571. +
  1572. + return err;
  1573. +}
  1574. +
  1575. +/*** Hermes AUX control ***/
  1576. +
  1577. +static inline void
  1578. +hermes_aux_setaddr(struct hermes *hw, u32 addr)
  1579. +{
  1580. + hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
  1581. + hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
  1582. +}
  1583. +
  1584. +static inline int
  1585. +hermes_aux_control(struct hermes *hw, int enabled)
  1586. +{
  1587. + int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
  1588. + int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
  1589. + int i;
  1590. +
  1591. + /* Already open? */
  1592. + if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
  1593. + return 0;
  1594. +
  1595. + hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
  1596. + hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
  1597. + hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
  1598. + hermes_write_reg(hw, HERMES_CONTROL, action);
  1599. +
  1600. + for (i = 0; i < 20; i++) {
  1601. + udelay(10);
  1602. + if (hermes_read_reg(hw, HERMES_CONTROL) ==
  1603. + desired_state)
  1604. + return 0;
  1605. + }
  1606. +
  1607. + return -EBUSY;
  1608. +}
  1609. +
  1610. +/*** Hermes programming ***/
  1611. +
  1612. +/* About to start programming data (Hermes I)
  1613. + * offset is the entry point
  1614. + *
  1615. + * Spectrum_cs' Symbol fw does not require this
  1616. + * wl_lkm Agere fw does
  1617. + * Don't know about intersil
  1618. + */
  1619. +static int hermesi_program_init(struct hermes *hw, u32 offset)
  1620. +{
  1621. + int err;
  1622. +
  1623. + /* Disable interrupts?*/
  1624. + /*hw->inten = 0x0;*/
  1625. + /*hermes_write_regn(hw, INTEN, 0);*/
  1626. + /*hermes_set_irqmask(hw, 0);*/
  1627. +
  1628. + /* Acknowledge any outstanding command */
  1629. + hermes_write_regn(hw, EVACK, 0xFFFF);
  1630. +
  1631. + /* Using init_cmd_wait rather than cmd_wait */
  1632. + err = hw->ops->init_cmd_wait(hw,
  1633. + 0x0100 | HERMES_CMD_INIT,
  1634. + 0, 0, 0, NULL);
  1635. + if (err)
  1636. + return err;
  1637. +
  1638. + err = hw->ops->init_cmd_wait(hw,
  1639. + 0x0000 | HERMES_CMD_INIT,
  1640. + 0, 0, 0, NULL);
  1641. + if (err)
  1642. + return err;
  1643. +
  1644. + err = hermes_aux_control(hw, 1);
  1645. + pr_debug("AUX enable returned %d\n", err);
  1646. +
  1647. + if (err)
  1648. + return err;
  1649. +
  1650. + pr_debug("Enabling volatile, EP 0x%08x\n", offset);
  1651. + err = hw->ops->init_cmd_wait(hw,
  1652. + HERMES_PROGRAM_ENABLE_VOLATILE,
  1653. + offset & 0xFFFFu,
  1654. + offset >> 16,
  1655. + 0,
  1656. + NULL);
  1657. + pr_debug("PROGRAM_ENABLE returned %d\n", err);
  1658. +
  1659. + return err;
  1660. +}
  1661. +
  1662. +/* Done programming data (Hermes I)
  1663. + *
  1664. + * Spectrum_cs' Symbol fw does not require this
  1665. + * wl_lkm Agere fw does
  1666. + * Don't know about intersil
  1667. + */
  1668. +static int hermesi_program_end(struct hermes *hw)
  1669. +{
  1670. + struct hermes_response resp;
  1671. + int rc = 0;
  1672. + int err;
  1673. +
  1674. + rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
  1675. +
  1676. + pr_debug("PROGRAM_DISABLE returned %d, "
  1677. + "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
  1678. + rc, resp.resp0, resp.resp1, resp.resp2);
  1679. +
  1680. + if ((rc == 0) &&
  1681. + ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
  1682. + rc = -EIO;
  1683. +
  1684. + err = hermes_aux_control(hw, 0);
  1685. + pr_debug("AUX disable returned %d\n", err);
  1686. +
  1687. + /* Acknowledge any outstanding command */
  1688. + hermes_write_regn(hw, EVACK, 0xFFFF);
  1689. +
  1690. + /* Reinitialise, ignoring return */
  1691. + (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
  1692. + 0, 0, 0, NULL);
  1693. +
  1694. + return rc ? rc : err;
  1695. +}
  1696. +
  1697. +static int hermes_program_bytes(struct hermes *hw, const char *data,
  1698. + u32 addr, u32 len)
  1699. +{
  1700. + /* wl lkm splits the programming into chunks of 2000 bytes.
  1701. + * This restriction appears to come from USB. The PCMCIA
  1702. + * adapters can program the whole lot in one go */
  1703. + hermes_aux_setaddr(hw, addr);
  1704. + hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
  1705. + return 0;
  1706. +}
  1707. +
  1708. +/* Read PDA from the adapter */
  1709. +static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr,
  1710. + u16 pda_len)
  1711. +{
  1712. + int ret;
  1713. + u16 pda_size;
  1714. + u16 data_len = pda_len;
  1715. + __le16 *data = pda;
  1716. +
  1717. + if (hw->eeprom_pda) {
  1718. + /* PDA of spectrum symbol is in eeprom */
  1719. +
  1720. + /* Issue command to read EEPROM */
  1721. + ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
  1722. + if (ret)
  1723. + return ret;
  1724. + } else {
  1725. + /* wl_lkm does not include PDA size in the PDA area.
  1726. + * We will pad the information into pda, so other routines
  1727. + * don't have to be modified */
  1728. + pda[0] = cpu_to_le16(pda_len - 2);
  1729. + /* Includes CFG_PROD_DATA but not itself */
  1730. + pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
  1731. + data_len = pda_len - 4;
  1732. + data = pda + 2;
  1733. + }
  1734. +
  1735. + /* Open auxiliary port */
  1736. + ret = hermes_aux_control(hw, 1);
  1737. + pr_debug("AUX enable returned %d\n", ret);
  1738. + if (ret)
  1739. + return ret;
  1740. +
  1741. + /* Read PDA */
  1742. + hermes_aux_setaddr(hw, pda_addr);
  1743. + hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
  1744. +
  1745. + /* Close aux port */
  1746. + ret = hermes_aux_control(hw, 0);
  1747. + pr_debug("AUX disable returned %d\n", ret);
  1748. +
  1749. + /* Check PDA length */
  1750. + pda_size = le16_to_cpu(pda[0]);
  1751. + pr_debug("Actual PDA length %d, Max allowed %d\n",
  1752. + pda_size, pda_len);
  1753. + if (pda_size > pda_len)
  1754. + return -EINVAL;
  1755. +
  1756. + return 0;
  1757. +}
  1758. +
  1759. +static void hermes_lock_irqsave(spinlock_t *lock,
  1760. + unsigned long *flags) __acquires(lock)
  1761. +{
  1762. + spin_lock_irqsave(lock, *flags);
  1763. +}
  1764. +
  1765. +static void hermes_unlock_irqrestore(spinlock_t *lock,
  1766. + unsigned long *flags) __releases(lock)
  1767. +{
  1768. + spin_unlock_irqrestore(lock, *flags);
  1769. +}
  1770. +
  1771. +static void hermes_lock_irq(spinlock_t *lock) __acquires(lock)
  1772. +{
  1773. + spin_lock_irq(lock);
  1774. +}
  1775. +
  1776. +static void hermes_unlock_irq(spinlock_t *lock) __releases(lock)
  1777. +{
  1778. + spin_unlock_irq(lock);
  1779. +}
  1780. +
  1781. +/* Hermes operations for local buses */
  1782. +static const struct hermes_ops hermes_ops_local = {
  1783. + .init = hermes_init,
  1784. + .cmd_wait = hermes_docmd_wait,
  1785. + .init_cmd_wait = hermes_doicmd_wait,
  1786. + .allocate = hermes_allocate,
  1787. + .read_ltv = hermes_read_ltv,
  1788. + .read_ltv_pr = hermes_read_ltv,
  1789. + .write_ltv = hermes_write_ltv,
  1790. + .bap_pread = hermes_bap_pread,
  1791. + .bap_pwrite = hermes_bap_pwrite,
  1792. + .read_pda = hermes_read_pda,
  1793. + .program_init = hermesi_program_init,
  1794. + .program_end = hermesi_program_end,
  1795. + .program = hermes_program_bytes,
  1796. + .lock_irqsave = hermes_lock_irqsave,
  1797. + .unlock_irqrestore = hermes_unlock_irqrestore,
  1798. + .lock_irq = hermes_lock_irq,
  1799. + .unlock_irq = hermes_unlock_irq,
  1800. +};
  1801. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes_dld.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes_dld.c
  1802. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes_dld.c 1970-01-01 01:00:00.000000000 +0100
  1803. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes_dld.c 2025-08-03 15:01:59.325131328 +0200
  1804. @@ -0,0 +1,477 @@
  1805. +/*
  1806. + * Hermes download helper.
  1807. + *
  1808. + * This helper:
  1809. + * - is capable of writing to the volatile area of the hermes device
  1810. + * - is currently not capable of writing to non-volatile areas
  1811. + * - provide helpers to identify and update plugin data
  1812. + * - is not capable of interpreting a fw image directly. That is up to
  1813. + * the main card driver.
  1814. + * - deals with Hermes I devices. It can probably be modified to deal
  1815. + * with Hermes II devices
  1816. + *
  1817. + * Copyright (C) 2007, David Kilroy
  1818. + *
  1819. + * Plug data code slightly modified from spectrum_cs driver
  1820. + * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
  1821. + * Portions based on information in wl_lkm_718 Agere driver
  1822. + * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved
  1823. + *
  1824. + * The contents of this file are subject to the Mozilla Public License
  1825. + * Version 1.1 (the "License"); you may not use this file except in
  1826. + * compliance with the License. You may obtain a copy of the License
  1827. + * at http://www.mozilla.org/MPL/
  1828. + *
  1829. + * Software distributed under the License is distributed on an "AS IS"
  1830. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  1831. + * the License for the specific language governing rights and
  1832. + * limitations under the License.
  1833. + *
  1834. + * Alternatively, the contents of this file may be used under the
  1835. + * terms of the GNU General Public License version 2 (the "GPL"), in
  1836. + * which case the provisions of the GPL are applicable instead of the
  1837. + * above. If you wish to allow the use of your version of this file
  1838. + * only under the terms of the GPL and not to allow others to use your
  1839. + * version of this file under the MPL, indicate your decision by
  1840. + * deleting the provisions above and replace them with the notice and
  1841. + * other provisions required by the GPL. If you do not delete the
  1842. + * provisions above, a recipient may use your version of this file
  1843. + * under either the MPL or the GPL.
  1844. + */
  1845. +
  1846. +#include <linux/module.h>
  1847. +#include <linux/delay.h>
  1848. +#include "hermes.h"
  1849. +#include "hermes_dld.h"
  1850. +
  1851. +#define PFX "hermes_dld: "
  1852. +
  1853. +/* End markers used in dblocks */
  1854. +#define PDI_END 0x00000000 /* End of PDA */
  1855. +#define BLOCK_END 0xFFFFFFFF /* Last image block */
  1856. +#define TEXT_END 0x1A /* End of text header */
  1857. +
  1858. +/*
  1859. + * The following structures have little-endian fields denoted by
  1860. + * the leading underscore. Don't access them directly - use inline
  1861. + * functions defined below.
  1862. + */
  1863. +
  1864. +/*
  1865. + * The binary image to be downloaded consists of series of data blocks.
  1866. + * Each block has the following structure.
  1867. + */
  1868. +struct dblock {
  1869. + __le32 addr; /* adapter address where to write the block */
  1870. + __le16 len; /* length of the data only, in bytes */
  1871. + char data[]; /* data to be written */
  1872. +} __packed;
  1873. +
  1874. +/*
  1875. + * Plug Data References are located in the image after the last data
  1876. + * block. They refer to areas in the adapter memory where the plug data
  1877. + * items with matching ID should be written.
  1878. + */
  1879. +struct pdr {
  1880. + __le32 id; /* record ID */
  1881. + __le32 addr; /* adapter address where to write the data */
  1882. + __le32 len; /* expected length of the data, in bytes */
  1883. + char next[]; /* next PDR starts here */
  1884. +} __packed;
  1885. +
  1886. +/*
  1887. + * Plug Data Items are located in the EEPROM read from the adapter by
  1888. + * primary firmware. They refer to the device-specific data that should
  1889. + * be plugged into the secondary firmware.
  1890. + */
  1891. +struct pdi {
  1892. + __le16 len; /* length of ID and data, in words */
  1893. + __le16 id; /* record ID */
  1894. + char data[]; /* plug data */
  1895. +} __packed;
  1896. +
  1897. +/*** FW data block access functions ***/
  1898. +
  1899. +static inline u32
  1900. +dblock_addr(const struct dblock *blk)
  1901. +{
  1902. + return le32_to_cpu(blk->addr);
  1903. +}
  1904. +
  1905. +static inline u32
  1906. +dblock_len(const struct dblock *blk)
  1907. +{
  1908. + return le16_to_cpu(blk->len);
  1909. +}
  1910. +
  1911. +/*** PDR Access functions ***/
  1912. +
  1913. +static inline u32
  1914. +pdr_id(const struct pdr *pdr)
  1915. +{
  1916. + return le32_to_cpu(pdr->id);
  1917. +}
  1918. +
  1919. +static inline u32
  1920. +pdr_addr(const struct pdr *pdr)
  1921. +{
  1922. + return le32_to_cpu(pdr->addr);
  1923. +}
  1924. +
  1925. +static inline u32
  1926. +pdr_len(const struct pdr *pdr)
  1927. +{
  1928. + return le32_to_cpu(pdr->len);
  1929. +}
  1930. +
  1931. +/*** PDI Access functions ***/
  1932. +
  1933. +static inline u32
  1934. +pdi_id(const struct pdi *pdi)
  1935. +{
  1936. + return le16_to_cpu(pdi->id);
  1937. +}
  1938. +
  1939. +/* Return length of the data only, in bytes */
  1940. +static inline u32
  1941. +pdi_len(const struct pdi *pdi)
  1942. +{
  1943. + return 2 * (le16_to_cpu(pdi->len) - 1);
  1944. +}
  1945. +
  1946. +/*** Plug Data Functions ***/
  1947. +
  1948. +/*
  1949. + * Scan PDR for the record with the specified RECORD_ID.
  1950. + * If it's not found, return NULL.
  1951. + */
  1952. +static const struct pdr *
  1953. +hermes_find_pdr(const struct pdr *first_pdr, u32 record_id, const void *end)
  1954. +{
  1955. + const struct pdr *pdr = first_pdr;
  1956. +
  1957. + end -= sizeof(struct pdr);
  1958. +
  1959. + while (((void *) pdr <= end) &&
  1960. + (pdr_id(pdr) != PDI_END)) {
  1961. + /*
  1962. + * PDR area is currently not terminated by PDI_END.
  1963. + * It's followed by CRC records, which have the type
  1964. + * field where PDR has length. The type can be 0 or 1.
  1965. + */
  1966. + if (pdr_len(pdr) < 2)
  1967. + return NULL;
  1968. +
  1969. + /* If the record ID matches, we are done */
  1970. + if (pdr_id(pdr) == record_id)
  1971. + return pdr;
  1972. +
  1973. + pdr = (struct pdr *) pdr->next;
  1974. + }
  1975. + return NULL;
  1976. +}
  1977. +
  1978. +/* Scan production data items for a particular entry */
  1979. +static const struct pdi *
  1980. +hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end)
  1981. +{
  1982. + const struct pdi *pdi = first_pdi;
  1983. +
  1984. + end -= sizeof(struct pdi);
  1985. +
  1986. + while (((void *) pdi <= end) &&
  1987. + (pdi_id(pdi) != PDI_END)) {
  1988. +
  1989. + /* If the record ID matches, we are done */
  1990. + if (pdi_id(pdi) == record_id)
  1991. + return pdi;
  1992. +
  1993. + pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
  1994. + }
  1995. + return NULL;
  1996. +}
  1997. +
  1998. +/* Process one Plug Data Item - find corresponding PDR and plug it */
  1999. +static int
  2000. +hermes_plug_pdi(struct hermes *hw, const struct pdr *first_pdr,
  2001. + const struct pdi *pdi, const void *pdr_end)
  2002. +{
  2003. + const struct pdr *pdr;
  2004. +
  2005. + /* Find the PDR corresponding to this PDI */
  2006. + pdr = hermes_find_pdr(first_pdr, pdi_id(pdi), pdr_end);
  2007. +
  2008. + /* No match is found, safe to ignore */
  2009. + if (!pdr)
  2010. + return 0;
  2011. +
  2012. + /* Lengths of the data in PDI and PDR must match */
  2013. + if (pdi_len(pdi) != pdr_len(pdr))
  2014. + return -EINVAL;
  2015. +
  2016. + /* do the actual plugging */
  2017. + hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));
  2018. +
  2019. + return 0;
  2020. +}
  2021. +
  2022. +/* Parse PDA and write the records into the adapter
  2023. + *
  2024. + * Attempt to write every records that is in the specified pda
  2025. + * which also has a valid production data record for the firmware.
  2026. + */
  2027. +int hermes_apply_pda(struct hermes *hw,
  2028. + const char *first_pdr,
  2029. + const void *pdr_end,
  2030. + const __le16 *pda,
  2031. + const void *pda_end)
  2032. +{
  2033. + int ret;
  2034. + const struct pdi *pdi;
  2035. + const struct pdr *pdr;
  2036. +
  2037. + pdr = (const struct pdr *) first_pdr;
  2038. + pda_end -= sizeof(struct pdi);
  2039. +
  2040. + /* Go through every PDI and plug them into the adapter */
  2041. + pdi = (const struct pdi *) (pda + 2);
  2042. + while (((void *) pdi <= pda_end) &&
  2043. + (pdi_id(pdi) != PDI_END)) {
  2044. + ret = hermes_plug_pdi(hw, pdr, pdi, pdr_end);
  2045. + if (ret)
  2046. + return ret;
  2047. +
  2048. + /* Increment to the next PDI */
  2049. + pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)];
  2050. + }
  2051. + return 0;
  2052. +}
  2053. +
  2054. +/* Identify the total number of bytes in all blocks
  2055. + * including the header data.
  2056. + */
  2057. +size_t
  2058. +hermes_blocks_length(const char *first_block, const void *end)
  2059. +{
  2060. + const struct dblock *blk = (const struct dblock *) first_block;
  2061. + int total_len = 0;
  2062. + int len;
  2063. +
  2064. + end -= sizeof(*blk);
  2065. +
  2066. + /* Skip all blocks to locate Plug Data References
  2067. + * (Spectrum CS) */
  2068. + while (((void *) blk <= end) &&
  2069. + (dblock_addr(blk) != BLOCK_END)) {
  2070. + len = dblock_len(blk);
  2071. + total_len += sizeof(*blk) + len;
  2072. + blk = (struct dblock *) &blk->data[len];
  2073. + }
  2074. +
  2075. + return total_len;
  2076. +}
  2077. +
  2078. +/*** Hermes programming ***/
  2079. +
  2080. +/* Program the data blocks */
  2081. +int hermes_program(struct hermes *hw, const char *first_block, const void *end)
  2082. +{
  2083. + const struct dblock *blk;
  2084. + u32 blkaddr;
  2085. + u32 blklen;
  2086. + int err = 0;
  2087. +
  2088. + blk = (const struct dblock *) first_block;
  2089. +
  2090. + if ((void *) blk > (end - sizeof(*blk)))
  2091. + return -EIO;
  2092. +
  2093. + blkaddr = dblock_addr(blk);
  2094. + blklen = dblock_len(blk);
  2095. +
  2096. + while ((blkaddr != BLOCK_END) &&
  2097. + (((void *) blk + blklen) <= end)) {
  2098. + pr_debug(PFX "Programming block of length %d "
  2099. + "to address 0x%08x\n", blklen, blkaddr);
  2100. +
  2101. + err = hw->ops->program(hw, blk->data, blkaddr, blklen);
  2102. + if (err)
  2103. + break;
  2104. +
  2105. + blk = (const struct dblock *) &blk->data[blklen];
  2106. +
  2107. + if ((void *) blk > (end - sizeof(*blk)))
  2108. + return -EIO;
  2109. +
  2110. + blkaddr = dblock_addr(blk);
  2111. + blklen = dblock_len(blk);
  2112. + }
  2113. + return err;
  2114. +}
  2115. +
  2116. +/*** Default plugging data for Hermes I ***/
  2117. +/* Values from wl_lkm_718/hcf/dhf.c */
  2118. +
  2119. +#define DEFINE_DEFAULT_PDR(pid, length, data) \
  2120. +static const struct { \
  2121. + __le16 len; \
  2122. + __le16 id; \
  2123. + u8 val[length]; \
  2124. +} __packed default_pdr_data_##pid = { \
  2125. + cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
  2126. + sizeof(__le16)) - 1), \
  2127. + cpu_to_le16(pid), \
  2128. + data \
  2129. +}
  2130. +
  2131. +#define DEFAULT_PDR(pid) default_pdr_data_##pid
  2132. +
  2133. +/* HWIF Compatibility */
  2134. +DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00");
  2135. +
  2136. +/* PPPPSign */
  2137. +DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00");
  2138. +
  2139. +/* PPPPProf */
  2140. +DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00");
  2141. +
  2142. +/* Antenna diversity */
  2143. +DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F");
  2144. +
  2145. +/* Modem VCO band Set-up */
  2146. +DEFINE_DEFAULT_PDR(0x0160, 28,
  2147. + "\x00\x00\x00\x00\x00\x00\x00\x00"
  2148. + "\x00\x00\x00\x00\x00\x00\x00\x00"
  2149. + "\x00\x00\x00\x00\x00\x00\x00\x00"
  2150. + "\x00\x00\x00\x00");
  2151. +
  2152. +/* Modem Rx Gain Table Values */
  2153. +DEFINE_DEFAULT_PDR(0x0161, 256,
  2154. + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
  2155. + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
  2156. + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
  2157. + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
  2158. + "\x3F\x01\x3E\01\x3E\x01\x3D\x01"
  2159. + "\x3D\x01\x3C\01\x3C\x01\x3B\x01"
  2160. + "\x3B\x01\x3A\01\x3A\x01\x39\x01"
  2161. + "\x39\x01\x38\01\x38\x01\x37\x01"
  2162. + "\x37\x01\x36\01\x36\x01\x35\x01"
  2163. + "\x35\x01\x34\01\x34\x01\x33\x01"
  2164. + "\x33\x01\x32\x01\x32\x01\x31\x01"
  2165. + "\x31\x01\x30\x01\x30\x01\x7B\x01"
  2166. + "\x7B\x01\x7A\x01\x7A\x01\x79\x01"
  2167. + "\x79\x01\x78\x01\x78\x01\x77\x01"
  2168. + "\x77\x01\x76\x01\x76\x01\x75\x01"
  2169. + "\x75\x01\x74\x01\x74\x01\x73\x01"
  2170. + "\x73\x01\x72\x01\x72\x01\x71\x01"
  2171. + "\x71\x01\x70\x01\x70\x01\x68\x01"
  2172. + "\x68\x01\x67\x01\x67\x01\x66\x01"
  2173. + "\x66\x01\x65\x01\x65\x01\x57\x01"
  2174. + "\x57\x01\x56\x01\x56\x01\x55\x01"
  2175. + "\x55\x01\x54\x01\x54\x01\x53\x01"
  2176. + "\x53\x01\x52\x01\x52\x01\x51\x01"
  2177. + "\x51\x01\x50\x01\x50\x01\x48\x01"
  2178. + "\x48\x01\x47\x01\x47\x01\x46\x01"
  2179. + "\x46\x01\x45\x01\x45\x01\x44\x01"
  2180. + "\x44\x01\x43\x01\x43\x01\x42\x01"
  2181. + "\x42\x01\x41\x01\x41\x01\x40\x01"
  2182. + "\x40\x01\x40\x01\x40\x01\x40\x01"
  2183. + "\x40\x01\x40\x01\x40\x01\x40\x01"
  2184. + "\x40\x01\x40\x01\x40\x01\x40\x01"
  2185. + "\x40\x01\x40\x01\x40\x01\x40\x01");
  2186. +
  2187. +/* Write PDA according to certain rules.
  2188. + *
  2189. + * For every production data record, look for a previous setting in
  2190. + * the pda, and use that.
  2191. + *
  2192. + * For certain records, use defaults if they are not found in pda.
  2193. + */
  2194. +int hermes_apply_pda_with_defaults(struct hermes *hw,
  2195. + const char *first_pdr,
  2196. + const void *pdr_end,
  2197. + const __le16 *pda,
  2198. + const void *pda_end)
  2199. +{
  2200. + const struct pdr *pdr = (const struct pdr *) first_pdr;
  2201. + const struct pdi *first_pdi = (const struct pdi *) &pda[2];
  2202. + const struct pdi *pdi;
  2203. + const struct pdi *default_pdi = NULL;
  2204. + const struct pdi *outdoor_pdi;
  2205. + int record_id;
  2206. +
  2207. + pdr_end -= sizeof(struct pdr);
  2208. +
  2209. + while (((void *) pdr <= pdr_end) &&
  2210. + (pdr_id(pdr) != PDI_END)) {
  2211. + /*
  2212. + * For spectrum_cs firmwares,
  2213. + * PDR area is currently not terminated by PDI_END.
  2214. + * It's followed by CRC records, which have the type
  2215. + * field where PDR has length. The type can be 0 or 1.
  2216. + */
  2217. + if (pdr_len(pdr) < 2)
  2218. + break;
  2219. + record_id = pdr_id(pdr);
  2220. +
  2221. + pdi = hermes_find_pdi(first_pdi, record_id, pda_end);
  2222. + if (pdi)
  2223. + pr_debug(PFX "Found record 0x%04x at %p\n",
  2224. + record_id, pdi);
  2225. +
  2226. + switch (record_id) {
  2227. + case 0x110: /* Modem REFDAC values */
  2228. + case 0x120: /* Modem VGDAC values */
  2229. + outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1,
  2230. + pda_end);
  2231. + default_pdi = NULL;
  2232. + if (outdoor_pdi) {
  2233. + pdi = outdoor_pdi;
  2234. + pr_debug(PFX
  2235. + "Using outdoor record 0x%04x at %p\n",
  2236. + record_id + 1, pdi);
  2237. + }
  2238. + break;
  2239. + case 0x5: /* HWIF Compatibility */
  2240. + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005);
  2241. + break;
  2242. + case 0x108: /* PPPPSign */
  2243. + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108);
  2244. + break;
  2245. + case 0x109: /* PPPPProf */
  2246. + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109);
  2247. + break;
  2248. + case 0x150: /* Antenna diversity */
  2249. + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150);
  2250. + break;
  2251. + case 0x160: /* Modem VCO band Set-up */
  2252. + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160);
  2253. + break;
  2254. + case 0x161: /* Modem Rx Gain Table Values */
  2255. + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161);
  2256. + break;
  2257. + default:
  2258. + default_pdi = NULL;
  2259. + break;
  2260. + }
  2261. + if (!pdi && default_pdi) {
  2262. + /* Use default */
  2263. + pdi = default_pdi;
  2264. + pr_debug(PFX "Using default record 0x%04x at %p\n",
  2265. + record_id, pdi);
  2266. + }
  2267. +
  2268. + if (pdi) {
  2269. + /* Lengths of the data in PDI and PDR must match */
  2270. + if ((pdi_len(pdi) == pdr_len(pdr)) &&
  2271. + ((void *) pdi->data + pdi_len(pdi) < pda_end)) {
  2272. + /* do the actual plugging */
  2273. + hw->ops->program(hw, pdi->data, pdr_addr(pdr),
  2274. + pdi_len(pdi));
  2275. + }
  2276. + }
  2277. +
  2278. + pdr++;
  2279. + }
  2280. + return 0;
  2281. +}
  2282. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes_dld.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes_dld.h
  2283. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes_dld.h 1970-01-01 01:00:00.000000000 +0100
  2284. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes_dld.h 2025-08-03 15:01:59.325131328 +0200
  2285. @@ -0,0 +1,52 @@
  2286. +/*
  2287. + * Copyright (C) 2007, David Kilroy
  2288. + *
  2289. + * The contents of this file are subject to the Mozilla Public License
  2290. + * Version 1.1 (the "License"); you may not use this file except in
  2291. + * compliance with the License. You may obtain a copy of the License
  2292. + * at http://www.mozilla.org/MPL/
  2293. + *
  2294. + * Software distributed under the License is distributed on an "AS IS"
  2295. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  2296. + * the License for the specific language governing rights and
  2297. + * limitations under the License.
  2298. + *
  2299. + * Alternatively, the contents of this file may be used under the
  2300. + * terms of the GNU General Public License version 2 (the "GPL"), in
  2301. + * which case the provisions of the GPL are applicable instead of the
  2302. + * above. If you wish to allow the use of your version of this file
  2303. + * only under the terms of the GPL and not to allow others to use your
  2304. + * version of this file under the MPL, indicate your decision by
  2305. + * deleting the provisions above and replace them with the notice and
  2306. + * other provisions required by the GPL. If you do not delete the
  2307. + * provisions above, a recipient may use your version of this file
  2308. + * under either the MPL or the GPL.
  2309. + */
  2310. +#ifndef _HERMES_DLD_H
  2311. +#define _HERMES_DLD_H
  2312. +
  2313. +#include "hermes.h"
  2314. +
  2315. +int hermesi_program_init(struct hermes *hw, u32 offset);
  2316. +int hermesi_program_end(struct hermes *hw);
  2317. +int hermes_program(struct hermes *hw, const char *first_block, const void *end);
  2318. +
  2319. +int hermes_read_pda(struct hermes *hw,
  2320. + __le16 *pda,
  2321. + u32 pda_addr,
  2322. + u16 pda_len,
  2323. + int use_eeprom);
  2324. +int hermes_apply_pda(struct hermes *hw,
  2325. + const char *first_pdr,
  2326. + const void *pdr_end,
  2327. + const __le16 *pda,
  2328. + const void *pda_end);
  2329. +int hermes_apply_pda_with_defaults(struct hermes *hw,
  2330. + const char *first_pdr,
  2331. + const void *pdr_end,
  2332. + const __le16 *pda,
  2333. + const void *pda_end);
  2334. +
  2335. +size_t hermes_blocks_length(const char *first_block, const void *end);
  2336. +
  2337. +#endif /* _HERMES_DLD_H */
  2338. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes.h
  2339. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes.h 1970-01-01 01:00:00.000000000 +0100
  2340. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes.h 2025-08-03 15:01:59.329131213 +0200
  2341. @@ -0,0 +1,534 @@
  2342. +/* SPDX-License-Identifier: GPL-2.0-only */
  2343. +/* hermes.h
  2344. + *
  2345. + * Driver core for the "Hermes" wireless MAC controller, as used in
  2346. + * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
  2347. + * work on the hfa3841 and hfa3842 MAC controller chips used in the
  2348. + * Prism I & II chipsets.
  2349. + *
  2350. + * This is not a complete driver, just low-level access routines for
  2351. + * the MAC controller itself.
  2352. + *
  2353. + * Based on the prism2 driver from Absolute Value Systems' linux-wlan
  2354. + * project, the Linux wvlan_cs driver, Lucent's HCF-Light
  2355. + * (wvlan_hcf.c) library, and the NetBSD wireless driver.
  2356. + *
  2357. + * Copyright (C) 2000, David Gibson, Linuxcare Australia.
  2358. + * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  2359. + *
  2360. + * Portions taken from hfa384x.h.
  2361. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  2362. + */
  2363. +
  2364. +#ifndef _HERMES_H
  2365. +#define _HERMES_H
  2366. +
  2367. +/* Notes on locking:
  2368. + *
  2369. + * As a module of low level hardware access routines, there is no
  2370. + * locking. Users of this module should ensure that they serialize
  2371. + * access to the hermes structure, and to the hardware
  2372. +*/
  2373. +
  2374. +#include <linux/if_ether.h>
  2375. +#include <linux/io.h>
  2376. +
  2377. +/*
  2378. + * Limits and constants
  2379. + */
  2380. +#define HERMES_ALLOC_LEN_MIN (4)
  2381. +#define HERMES_ALLOC_LEN_MAX (2400)
  2382. +#define HERMES_LTV_LEN_MAX (34)
  2383. +#define HERMES_BAP_DATALEN_MAX (4096)
  2384. +#define HERMES_BAP_OFFSET_MAX (4096)
  2385. +#define HERMES_PORTID_MAX (7)
  2386. +#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX + 1)
  2387. +#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */
  2388. +#define HERMES_PDA_RECS_MAX (200) /* a guess */
  2389. +#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */
  2390. +#define HERMES_SCANRESULT_MAX (35)
  2391. +#define HERMES_CHINFORESULT_MAX (8)
  2392. +#define HERMES_MAX_MULTICAST (16)
  2393. +#define HERMES_MAGIC (0x7d1f)
  2394. +
  2395. +/*
  2396. + * Hermes register offsets
  2397. + */
  2398. +#define HERMES_CMD (0x00)
  2399. +#define HERMES_PARAM0 (0x02)
  2400. +#define HERMES_PARAM1 (0x04)
  2401. +#define HERMES_PARAM2 (0x06)
  2402. +#define HERMES_STATUS (0x08)
  2403. +#define HERMES_RESP0 (0x0A)
  2404. +#define HERMES_RESP1 (0x0C)
  2405. +#define HERMES_RESP2 (0x0E)
  2406. +#define HERMES_INFOFID (0x10)
  2407. +#define HERMES_RXFID (0x20)
  2408. +#define HERMES_ALLOCFID (0x22)
  2409. +#define HERMES_TXCOMPLFID (0x24)
  2410. +#define HERMES_SELECT0 (0x18)
  2411. +#define HERMES_OFFSET0 (0x1C)
  2412. +#define HERMES_DATA0 (0x36)
  2413. +#define HERMES_SELECT1 (0x1A)
  2414. +#define HERMES_OFFSET1 (0x1E)
  2415. +#define HERMES_DATA1 (0x38)
  2416. +#define HERMES_EVSTAT (0x30)
  2417. +#define HERMES_INTEN (0x32)
  2418. +#define HERMES_EVACK (0x34)
  2419. +#define HERMES_CONTROL (0x14)
  2420. +#define HERMES_SWSUPPORT0 (0x28)
  2421. +#define HERMES_SWSUPPORT1 (0x2A)
  2422. +#define HERMES_SWSUPPORT2 (0x2C)
  2423. +#define HERMES_AUXPAGE (0x3A)
  2424. +#define HERMES_AUXOFFSET (0x3C)
  2425. +#define HERMES_AUXDATA (0x3E)
  2426. +
  2427. +/*
  2428. + * CMD register bitmasks
  2429. + */
  2430. +#define HERMES_CMD_BUSY (0x8000)
  2431. +#define HERMES_CMD_AINFO (0x7f00)
  2432. +#define HERMES_CMD_MACPORT (0x0700)
  2433. +#define HERMES_CMD_RECL (0x0100)
  2434. +#define HERMES_CMD_WRITE (0x0100)
  2435. +#define HERMES_CMD_PROGMODE (0x0300)
  2436. +#define HERMES_CMD_CMDCODE (0x003f)
  2437. +
  2438. +/*
  2439. + * STATUS register bitmasks
  2440. + */
  2441. +#define HERMES_STATUS_RESULT (0x7f00)
  2442. +#define HERMES_STATUS_CMDCODE (0x003f)
  2443. +
  2444. +/*
  2445. + * OFFSET register bitmasks
  2446. + */
  2447. +#define HERMES_OFFSET_BUSY (0x8000)
  2448. +#define HERMES_OFFSET_ERR (0x4000)
  2449. +#define HERMES_OFFSET_DATAOFF (0x0ffe)
  2450. +
  2451. +/*
  2452. + * Event register bitmasks (INTEN, EVSTAT, EVACK)
  2453. + */
  2454. +#define HERMES_EV_TICK (0x8000)
  2455. +#define HERMES_EV_WTERR (0x4000)
  2456. +#define HERMES_EV_INFDROP (0x2000)
  2457. +#define HERMES_EV_INFO (0x0080)
  2458. +#define HERMES_EV_DTIM (0x0020)
  2459. +#define HERMES_EV_CMD (0x0010)
  2460. +#define HERMES_EV_ALLOC (0x0008)
  2461. +#define HERMES_EV_TXEXC (0x0004)
  2462. +#define HERMES_EV_TX (0x0002)
  2463. +#define HERMES_EV_RX (0x0001)
  2464. +
  2465. +/*
  2466. + * Command codes
  2467. + */
  2468. +/*--- Controller Commands ----------------------------*/
  2469. +#define HERMES_CMD_INIT (0x0000)
  2470. +#define HERMES_CMD_ENABLE (0x0001)
  2471. +#define HERMES_CMD_DISABLE (0x0002)
  2472. +#define HERMES_CMD_DIAG (0x0003)
  2473. +
  2474. +/*--- Buffer Mgmt Commands ---------------------------*/
  2475. +#define HERMES_CMD_ALLOC (0x000A)
  2476. +#define HERMES_CMD_TX (0x000B)
  2477. +
  2478. +/*--- Regulate Commands ------------------------------*/
  2479. +#define HERMES_CMD_NOTIFY (0x0010)
  2480. +#define HERMES_CMD_INQUIRE (0x0011)
  2481. +
  2482. +/*--- Configure Commands -----------------------------*/
  2483. +#define HERMES_CMD_ACCESS (0x0021)
  2484. +#define HERMES_CMD_DOWNLD (0x0022)
  2485. +
  2486. +/*--- Serial I/O Commands ----------------------------*/
  2487. +#define HERMES_CMD_READMIF (0x0030)
  2488. +#define HERMES_CMD_WRITEMIF (0x0031)
  2489. +
  2490. +/*--- Debugging Commands -----------------------------*/
  2491. +#define HERMES_CMD_TEST (0x0038)
  2492. +
  2493. +
  2494. +/* Test command arguments */
  2495. +#define HERMES_TEST_SET_CHANNEL 0x0800
  2496. +#define HERMES_TEST_MONITOR 0x0b00
  2497. +#define HERMES_TEST_STOP 0x0f00
  2498. +
  2499. +/* Authentication algorithms */
  2500. +#define HERMES_AUTH_OPEN 1
  2501. +#define HERMES_AUTH_SHARED_KEY 2
  2502. +
  2503. +/* WEP settings */
  2504. +#define HERMES_WEP_PRIVACY_INVOKED 0x0001
  2505. +#define HERMES_WEP_EXCL_UNENCRYPTED 0x0002
  2506. +#define HERMES_WEP_HOST_ENCRYPT 0x0010
  2507. +#define HERMES_WEP_HOST_DECRYPT 0x0080
  2508. +
  2509. +/* Symbol hostscan options */
  2510. +#define HERMES_HOSTSCAN_SYMBOL_5SEC 0x0001
  2511. +#define HERMES_HOSTSCAN_SYMBOL_ONCE 0x0002
  2512. +#define HERMES_HOSTSCAN_SYMBOL_PASSIVE 0x0040
  2513. +#define HERMES_HOSTSCAN_SYMBOL_BCAST 0x0080
  2514. +
  2515. +/*
  2516. + * Frame structures and constants
  2517. + */
  2518. +
  2519. +#define HERMES_DESCRIPTOR_OFFSET 0
  2520. +#define HERMES_802_11_OFFSET (14)
  2521. +#define HERMES_802_3_OFFSET (14 + 32)
  2522. +#define HERMES_802_2_OFFSET (14 + 32 + 14)
  2523. +#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
  2524. +
  2525. +#define HERMES_RXSTAT_ERR (0x0003)
  2526. +#define HERMES_RXSTAT_BADCRC (0x0001)
  2527. +#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
  2528. +#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */
  2529. +#define HERMES_RXSTAT_MACPORT (0x0700)
  2530. +#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */
  2531. +#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */
  2532. +#define HERMES_RXSTAT_MSGTYPE (0xE000)
  2533. +#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */
  2534. +#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */
  2535. +#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
  2536. +
  2537. +/* Shift amount for key ID in RXSTAT and TXCTRL */
  2538. +#define HERMES_MIC_KEY_ID_SHIFT 11
  2539. +
  2540. +struct hermes_tx_descriptor {
  2541. + __le16 status;
  2542. + __le16 reserved1;
  2543. + __le16 reserved2;
  2544. + __le32 sw_support;
  2545. + u8 retry_count;
  2546. + u8 tx_rate;
  2547. + __le16 tx_control;
  2548. +} __packed;
  2549. +
  2550. +#define HERMES_TXSTAT_RETRYERR (0x0001)
  2551. +#define HERMES_TXSTAT_AGEDERR (0x0002)
  2552. +#define HERMES_TXSTAT_DISCON (0x0004)
  2553. +#define HERMES_TXSTAT_FORMERR (0x0008)
  2554. +
  2555. +#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */
  2556. +#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */
  2557. +#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */
  2558. +#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */
  2559. +#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */
  2560. +#define HERMES_TXCTRL_ALT_RTRY (0x0020)
  2561. +
  2562. +/* Inquiry constants and data types */
  2563. +
  2564. +#define HERMES_INQ_TALLIES (0xF100)
  2565. +#define HERMES_INQ_SCAN (0xF101)
  2566. +#define HERMES_INQ_CHANNELINFO (0xF102)
  2567. +#define HERMES_INQ_HOSTSCAN (0xF103)
  2568. +#define HERMES_INQ_HOSTSCAN_SYMBOL (0xF104)
  2569. +#define HERMES_INQ_LINKSTATUS (0xF200)
  2570. +#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
  2571. +
  2572. +struct hermes_tallies_frame {
  2573. + __le16 TxUnicastFrames;
  2574. + __le16 TxMulticastFrames;
  2575. + __le16 TxFragments;
  2576. + __le16 TxUnicastOctets;
  2577. + __le16 TxMulticastOctets;
  2578. + __le16 TxDeferredTransmissions;
  2579. + __le16 TxSingleRetryFrames;
  2580. + __le16 TxMultipleRetryFrames;
  2581. + __le16 TxRetryLimitExceeded;
  2582. + __le16 TxDiscards;
  2583. + __le16 RxUnicastFrames;
  2584. + __le16 RxMulticastFrames;
  2585. + __le16 RxFragments;
  2586. + __le16 RxUnicastOctets;
  2587. + __le16 RxMulticastOctets;
  2588. + __le16 RxFCSErrors;
  2589. + __le16 RxDiscards_NoBuffer;
  2590. + __le16 TxDiscardsWrongSA;
  2591. + __le16 RxWEPUndecryptable;
  2592. + __le16 RxMsgInMsgFragments;
  2593. + __le16 RxMsgInBadMsgFragments;
  2594. + /* Those last are probably not available in very old firmwares */
  2595. + __le16 RxDiscards_WEPICVError;
  2596. + __le16 RxDiscards_WEPExcluded;
  2597. +} __packed;
  2598. +
  2599. +/* Grabbed from wlan-ng - Thanks Mark... - Jean II
  2600. + * This is the result of a scan inquiry command */
  2601. +/* Structure describing info about an Access Point */
  2602. +struct prism2_scan_apinfo {
  2603. + __le16 channel; /* Channel where the AP sits */
  2604. + __le16 noise; /* Noise level */
  2605. + __le16 level; /* Signal level */
  2606. + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
  2607. + __le16 beacon_interv; /* Beacon interval */
  2608. + __le16 capabilities; /* Capabilities */
  2609. + __le16 essid_len; /* ESSID length */
  2610. + u8 essid[32]; /* ESSID of the network */
  2611. + u8 rates[10]; /* Bit rate supported */
  2612. + __le16 proberesp_rate; /* Data rate of the response frame */
  2613. + __le16 atim; /* ATIM window time, Kus (hostscan only) */
  2614. +} __packed;
  2615. +
  2616. +/* Same stuff for the Lucent/Agere card.
  2617. + * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
  2618. +struct agere_scan_apinfo {
  2619. + __le16 channel; /* Channel where the AP sits */
  2620. + __le16 noise; /* Noise level */
  2621. + __le16 level; /* Signal level */
  2622. + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
  2623. + __le16 beacon_interv; /* Beacon interval */
  2624. + __le16 capabilities; /* Capabilities */
  2625. + /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
  2626. + __le16 essid_len; /* ESSID length */
  2627. + u8 essid[32]; /* ESSID of the network */
  2628. +} __packed;
  2629. +
  2630. +/* Moustafa: Scan structure for Symbol cards */
  2631. +struct symbol_scan_apinfo {
  2632. + u8 channel; /* Channel where the AP sits */
  2633. + u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
  2634. + __le16 noise; /* Noise level */
  2635. + __le16 level; /* Signal level */
  2636. + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
  2637. + __le16 beacon_interv; /* Beacon interval */
  2638. + __le16 capabilities; /* Capabilities */
  2639. + /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
  2640. + __le16 essid_len; /* ESSID length */
  2641. + u8 essid[32]; /* ESSID of the network */
  2642. + __le16 rates[5]; /* Bit rate supported */
  2643. + __le16 basic_rates; /* Basic rates bitmask */
  2644. + u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
  2645. + u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
  2646. +} __packed;
  2647. +
  2648. +union hermes_scan_info {
  2649. + struct agere_scan_apinfo a;
  2650. + struct prism2_scan_apinfo p;
  2651. + struct symbol_scan_apinfo s;
  2652. +};
  2653. +
  2654. +/* Extended scan struct for HERMES_INQ_CHANNELINFO.
  2655. + * wl_lkm calls this an ACS scan (Automatic Channel Select).
  2656. + * Keep out of union hermes_scan_info because it is much bigger than
  2657. + * the older scan structures. */
  2658. +struct agere_ext_scan_info {
  2659. + __le16 reserved0;
  2660. +
  2661. + u8 noise;
  2662. + u8 level;
  2663. + u8 rx_flow;
  2664. + u8 rate;
  2665. + __le16 reserved1[2];
  2666. +
  2667. + __le16 frame_control;
  2668. + __le16 dur_id;
  2669. + u8 addr1[ETH_ALEN];
  2670. + u8 addr2[ETH_ALEN];
  2671. + u8 bssid[ETH_ALEN];
  2672. + __le16 sequence;
  2673. + u8 addr4[ETH_ALEN];
  2674. +
  2675. + __le16 data_length;
  2676. +
  2677. + /* Next 3 fields do not get filled in. */
  2678. + u8 daddr[ETH_ALEN];
  2679. + u8 saddr[ETH_ALEN];
  2680. + __le16 len_type;
  2681. +
  2682. + __le64 timestamp;
  2683. + __le16 beacon_interval;
  2684. + __le16 capabilities;
  2685. + u8 data[];
  2686. +} __packed;
  2687. +
  2688. +#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000)
  2689. +#define HERMES_LINKSTATUS_CONNECTED (0x0001)
  2690. +#define HERMES_LINKSTATUS_DISCONNECTED (0x0002)
  2691. +#define HERMES_LINKSTATUS_AP_CHANGE (0x0003)
  2692. +#define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004)
  2693. +#define HERMES_LINKSTATUS_AP_IN_RANGE (0x0005)
  2694. +#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
  2695. +
  2696. +struct hermes_linkstatus {
  2697. + __le16 linkstatus; /* Link status */
  2698. +} __packed;
  2699. +
  2700. +struct hermes_response {
  2701. + u16 status, resp0, resp1, resp2;
  2702. +};
  2703. +
  2704. +/* "ID" structure - used for ESSID and station nickname */
  2705. +struct hermes_idstring {
  2706. + __le16 len;
  2707. + __le16 val[16];
  2708. +} __packed;
  2709. +
  2710. +struct hermes_multicast {
  2711. + u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
  2712. +} __packed;
  2713. +
  2714. +/* Timeouts */
  2715. +#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
  2716. +
  2717. +struct hermes;
  2718. +
  2719. +/* Functions to access hardware */
  2720. +struct hermes_ops {
  2721. + int (*init)(struct hermes *hw);
  2722. + int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0,
  2723. + struct hermes_response *resp);
  2724. + int (*init_cmd_wait)(struct hermes *hw, u16 cmd,
  2725. + u16 parm0, u16 parm1, u16 parm2,
  2726. + struct hermes_response *resp);
  2727. + int (*allocate)(struct hermes *hw, u16 size, u16 *fid);
  2728. + int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen,
  2729. + u16 *length, void *buf);
  2730. + int (*read_ltv_pr)(struct hermes *hw, int bap, u16 rid,
  2731. + unsigned buflen, u16 *length, void *buf);
  2732. + int (*write_ltv)(struct hermes *hw, int bap, u16 rid,
  2733. + u16 length, const void *value);
  2734. + int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len,
  2735. + u16 id, u16 offset);
  2736. + int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf,
  2737. + int len, u16 id, u16 offset);
  2738. + int (*read_pda)(struct hermes *hw, __le16 *pda,
  2739. + u32 pda_addr, u16 pda_len);
  2740. + int (*program_init)(struct hermes *hw, u32 entry_point);
  2741. + int (*program_end)(struct hermes *hw);
  2742. + int (*program)(struct hermes *hw, const char *buf,
  2743. + u32 addr, u32 len);
  2744. + void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags);
  2745. + void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags);
  2746. + void (*lock_irq)(spinlock_t *lock);
  2747. + void (*unlock_irq)(spinlock_t *lock);
  2748. +};
  2749. +
  2750. +/* Basic control structure */
  2751. +struct hermes {
  2752. + void __iomem *iobase;
  2753. + int reg_spacing;
  2754. +#define HERMES_16BIT_REGSPACING 0
  2755. +#define HERMES_32BIT_REGSPACING 1
  2756. + u16 inten; /* Which interrupts should be enabled? */
  2757. + bool eeprom_pda;
  2758. + const struct hermes_ops *ops;
  2759. + void *priv;
  2760. +};
  2761. +
  2762. +/* Register access convenience macros */
  2763. +#define hermes_read_reg(hw, off) \
  2764. + (ioread16((hw)->iobase + ((off) << (hw)->reg_spacing)))
  2765. +#define hermes_write_reg(hw, off, val) \
  2766. + (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing)))
  2767. +#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name)
  2768. +#define hermes_write_regn(hw, name, val) \
  2769. + hermes_write_reg((hw), HERMES_##name, (val))
  2770. +
  2771. +/* Function prototypes */
  2772. +void hermes_struct_init(struct hermes *hw, void __iomem *address,
  2773. + int reg_spacing);
  2774. +
  2775. +/* Inline functions */
  2776. +
  2777. +static inline int hermes_present(struct hermes *hw)
  2778. +{
  2779. + return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
  2780. +}
  2781. +
  2782. +static inline void hermes_set_irqmask(struct hermes *hw, u16 events)
  2783. +{
  2784. + hw->inten = events;
  2785. + hermes_write_regn(hw, INTEN, events);
  2786. +}
  2787. +
  2788. +static inline int hermes_enable_port(struct hermes *hw, int port)
  2789. +{
  2790. + return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
  2791. + 0, NULL);
  2792. +}
  2793. +
  2794. +static inline int hermes_disable_port(struct hermes *hw, int port)
  2795. +{
  2796. + return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
  2797. + 0, NULL);
  2798. +}
  2799. +
  2800. +/* Initiate an INQUIRE command (tallies or scan). The result will come as an
  2801. + * information frame in __orinoco_ev_info() */
  2802. +static inline int hermes_inquire(struct hermes *hw, u16 rid)
  2803. +{
  2804. + return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
  2805. +}
  2806. +
  2807. +#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1)
  2808. +#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2)
  2809. +
  2810. +/* Note that for the next two, the count is in 16-bit words, not bytes */
  2811. +static inline void hermes_read_words(struct hermes *hw, int off,
  2812. + void *buf, unsigned count)
  2813. +{
  2814. + off = off << hw->reg_spacing;
  2815. + ioread16_rep(hw->iobase + off, buf, count);
  2816. +}
  2817. +
  2818. +static inline void hermes_write_bytes(struct hermes *hw, int off,
  2819. + const char *buf, unsigned count)
  2820. +{
  2821. + off = off << hw->reg_spacing;
  2822. + iowrite16_rep(hw->iobase + off, buf, count >> 1);
  2823. + if (unlikely(count & 1))
  2824. + iowrite8(buf[count - 1], hw->iobase + off);
  2825. +}
  2826. +
  2827. +static inline void hermes_clear_words(struct hermes *hw, int off,
  2828. + unsigned count)
  2829. +{
  2830. + unsigned i;
  2831. +
  2832. + off = off << hw->reg_spacing;
  2833. +
  2834. + for (i = 0; i < count; i++)
  2835. + iowrite16(0, hw->iobase + off);
  2836. +}
  2837. +
  2838. +#define HERMES_READ_RECORD(hw, bap, rid, buf) \
  2839. + (hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
  2840. +#define HERMES_READ_RECORD_PR(hw, bap, rid, buf) \
  2841. + (hw->ops->read_ltv_pr((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
  2842. +#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
  2843. + (hw->ops->write_ltv((hw), (bap), (rid), \
  2844. + HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
  2845. +
  2846. +static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid,
  2847. + u16 *word)
  2848. +{
  2849. + __le16 rec;
  2850. + int err;
  2851. +
  2852. + err = HERMES_READ_RECORD(hw, bap, rid, &rec);
  2853. + *word = le16_to_cpu(rec);
  2854. + return err;
  2855. +}
  2856. +
  2857. +static inline int hermes_read_wordrec_pr(struct hermes *hw, int bap, u16 rid,
  2858. + u16 *word)
  2859. +{
  2860. + __le16 rec;
  2861. + int err;
  2862. +
  2863. + err = HERMES_READ_RECORD_PR(hw, bap, rid, &rec);
  2864. + *word = le16_to_cpu(rec);
  2865. + return err;
  2866. +}
  2867. +
  2868. +static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid,
  2869. + u16 word)
  2870. +{
  2871. + __le16 rec = cpu_to_le16(word);
  2872. + return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
  2873. +}
  2874. +
  2875. +#endif /* _HERMES_H */
  2876. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes_rid.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes_rid.h
  2877. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hermes_rid.h 1970-01-01 01:00:00.000000000 +0100
  2878. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hermes_rid.h 2025-08-03 15:01:59.341130868 +0200
  2879. @@ -0,0 +1,165 @@
  2880. +#ifndef _HERMES_RID_H
  2881. +#define _HERMES_RID_H
  2882. +
  2883. +/*
  2884. + * Configuration RIDs
  2885. + */
  2886. +#define HERMES_RID_CNFPORTTYPE 0xFC00
  2887. +#define HERMES_RID_CNFOWNMACADDR 0xFC01
  2888. +#define HERMES_RID_CNFDESIREDSSID 0xFC02
  2889. +#define HERMES_RID_CNFOWNCHANNEL 0xFC03
  2890. +#define HERMES_RID_CNFOWNSSID 0xFC04
  2891. +#define HERMES_RID_CNFOWNATIMWINDOW 0xFC05
  2892. +#define HERMES_RID_CNFSYSTEMSCALE 0xFC06
  2893. +#define HERMES_RID_CNFMAXDATALEN 0xFC07
  2894. +#define HERMES_RID_CNFWDSADDRESS 0xFC08
  2895. +#define HERMES_RID_CNFPMENABLED 0xFC09
  2896. +#define HERMES_RID_CNFPMEPS 0xFC0A
  2897. +#define HERMES_RID_CNFMULTICASTRECEIVE 0xFC0B
  2898. +#define HERMES_RID_CNFMAXSLEEPDURATION 0xFC0C
  2899. +#define HERMES_RID_CNFPMHOLDOVERDURATION 0xFC0D
  2900. +#define HERMES_RID_CNFOWNNAME 0xFC0E
  2901. +#define HERMES_RID_CNFOWNDTIMPERIOD 0xFC10
  2902. +#define HERMES_RID_CNFWDSADDRESS1 0xFC11
  2903. +#define HERMES_RID_CNFWDSADDRESS2 0xFC12
  2904. +#define HERMES_RID_CNFWDSADDRESS3 0xFC13
  2905. +#define HERMES_RID_CNFWDSADDRESS4 0xFC14
  2906. +#define HERMES_RID_CNFWDSADDRESS5 0xFC15
  2907. +#define HERMES_RID_CNFWDSADDRESS6 0xFC16
  2908. +#define HERMES_RID_CNFMULTICASTPMBUFFERING 0xFC17
  2909. +#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20
  2910. +#define HERMES_RID_CNFAUTHENTICATION_AGERE 0xFC21
  2911. +#define HERMES_RID_CNFMANDATORYBSSID_SYMBOL 0xFC21
  2912. +#define HERMES_RID_CNFDROPUNENCRYPTED 0xFC22
  2913. +#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23
  2914. +#define HERMES_RID_CNFDEFAULTKEY0 0xFC24
  2915. +#define HERMES_RID_CNFDEFAULTKEY1 0xFC25
  2916. +#define HERMES_RID_CNFMWOROBUST_AGERE 0xFC25
  2917. +#define HERMES_RID_CNFDEFAULTKEY2 0xFC26
  2918. +#define HERMES_RID_CNFDEFAULTKEY3 0xFC27
  2919. +#define HERMES_RID_CNFWEPFLAGS_INTERSIL 0xFC28
  2920. +#define HERMES_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
  2921. +#define HERMES_RID_CNFAUTHENTICATION 0xFC2A
  2922. +#define HERMES_RID_CNFMAXASSOCSTA 0xFC2B
  2923. +#define HERMES_RID_CNFKEYLENGTH_SYMBOL 0xFC2B
  2924. +#define HERMES_RID_CNFTXCONTROL 0xFC2C
  2925. +#define HERMES_RID_CNFROAMINGMODE 0xFC2D
  2926. +#define HERMES_RID_CNFHOSTAUTHENTICATION 0xFC2E
  2927. +#define HERMES_RID_CNFRCVCRCERROR 0xFC30
  2928. +#define HERMES_RID_CNFMMLIFE 0xFC31
  2929. +#define HERMES_RID_CNFALTRETRYCOUNT 0xFC32
  2930. +#define HERMES_RID_CNFBEACONINT 0xFC33
  2931. +#define HERMES_RID_CNFAPPCFINFO 0xFC34
  2932. +#define HERMES_RID_CNFSTAPCFINFO 0xFC35
  2933. +#define HERMES_RID_CNFPRIORITYQUSAGE 0xFC37
  2934. +#define HERMES_RID_CNFTIMCTRL 0xFC40
  2935. +#define HERMES_RID_CNFTHIRTY2TALLY 0xFC42
  2936. +#define HERMES_RID_CNFENHSECURITY 0xFC43
  2937. +#define HERMES_RID_CNFGROUPADDRESSES 0xFC80
  2938. +#define HERMES_RID_CNFCREATEIBSS 0xFC81
  2939. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD 0xFC82
  2940. +#define HERMES_RID_CNFRTSTHRESHOLD 0xFC83
  2941. +#define HERMES_RID_CNFTXRATECONTROL 0xFC84
  2942. +#define HERMES_RID_CNFPROMISCUOUSMODE 0xFC85
  2943. +#define HERMES_RID_CNFBASICRATES_SYMBOL 0xFC8A
  2944. +#define HERMES_RID_CNFPREAMBLE_SYMBOL 0xFC8C
  2945. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0 0xFC90
  2946. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1 0xFC91
  2947. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2 0xFC92
  2948. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD3 0xFC93
  2949. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD4 0xFC94
  2950. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD5 0xFC95
  2951. +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD6 0xFC96
  2952. +#define HERMES_RID_CNFRTSTHRESHOLD0 0xFC97
  2953. +#define HERMES_RID_CNFRTSTHRESHOLD1 0xFC98
  2954. +#define HERMES_RID_CNFRTSTHRESHOLD2 0xFC99
  2955. +#define HERMES_RID_CNFRTSTHRESHOLD3 0xFC9A
  2956. +#define HERMES_RID_CNFRTSTHRESHOLD4 0xFC9B
  2957. +#define HERMES_RID_CNFRTSTHRESHOLD5 0xFC9C
  2958. +#define HERMES_RID_CNFRTSTHRESHOLD6 0xFC9D
  2959. +#define HERMES_RID_CNFHOSTSCAN_SYMBOL 0xFCAB
  2960. +#define HERMES_RID_CNFSHORTPREAMBLE 0xFCB0
  2961. +#define HERMES_RID_CNFWEPKEYS_AGERE 0xFCB0
  2962. +#define HERMES_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
  2963. +#define HERMES_RID_CNFTXKEY_AGERE 0xFCB1
  2964. +#define HERMES_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
  2965. +#define HERMES_RID_CNFSCANSSID_AGERE 0xFCB2
  2966. +#define HERMES_RID_CNFBASICRATES 0xFCB3
  2967. +#define HERMES_RID_CNFSUPPORTEDRATES 0xFCB4
  2968. +#define HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE 0xFCB4
  2969. +#define HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE 0xFCB5
  2970. +#define HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE 0xFCB6
  2971. +#define HERMES_RID_CNFADDMAPPEDTKIPKEY_AGERE 0xFCB7
  2972. +#define HERMES_RID_CNFREMMAPPEDTKIPKEY_AGERE 0xFCB8
  2973. +#define HERMES_RID_CNFSETWPACAPABILITIES_AGERE 0xFCB9
  2974. +#define HERMES_RID_CNFCACHEDPMKADDRESS 0xFCBA
  2975. +#define HERMES_RID_CNFREMOVEPMKADDRESS 0xFCBB
  2976. +#define HERMES_RID_CNFSCANCHANNELS2GHZ 0xFCC2
  2977. +#define HERMES_RID_CNFDISASSOCIATE 0xFCC8
  2978. +#define HERMES_RID_CNFTICKTIME 0xFCE0
  2979. +#define HERMES_RID_CNFSCANREQUEST 0xFCE1
  2980. +#define HERMES_RID_CNFJOINREQUEST 0xFCE2
  2981. +#define HERMES_RID_CNFAUTHENTICATESTATION 0xFCE3
  2982. +#define HERMES_RID_CNFCHANNELINFOREQUEST 0xFCE4
  2983. +#define HERMES_RID_CNFHOSTSCAN 0xFCE5
  2984. +
  2985. +/*
  2986. + * Information RIDs
  2987. + */
  2988. +#define HERMES_RID_MAXLOADTIME 0xFD00
  2989. +#define HERMES_RID_DOWNLOADBUFFER 0xFD01
  2990. +#define HERMES_RID_PRIID 0xFD02
  2991. +#define HERMES_RID_PRISUPRANGE 0xFD03
  2992. +#define HERMES_RID_CFIACTRANGES 0xFD04
  2993. +#define HERMES_RID_NICSERNUM 0xFD0A
  2994. +#define HERMES_RID_NICID 0xFD0B
  2995. +#define HERMES_RID_MFISUPRANGE 0xFD0C
  2996. +#define HERMES_RID_CFISUPRANGE 0xFD0D
  2997. +#define HERMES_RID_CHANNELLIST 0xFD10
  2998. +#define HERMES_RID_REGULATORYDOMAINS 0xFD11
  2999. +#define HERMES_RID_TEMPTYPE 0xFD12
  3000. +#define HERMES_RID_CIS 0xFD13
  3001. +#define HERMES_RID_STAID 0xFD20
  3002. +#define HERMES_RID_STASUPRANGE 0xFD21
  3003. +#define HERMES_RID_MFIACTRANGES 0xFD22
  3004. +#define HERMES_RID_CFIACTRANGES2 0xFD23
  3005. +#define HERMES_RID_SECONDARYVERSION_SYMBOL 0xFD24
  3006. +#define HERMES_RID_PORTSTATUS 0xFD40
  3007. +#define HERMES_RID_CURRENTSSID 0xFD41
  3008. +#define HERMES_RID_CURRENTBSSID 0xFD42
  3009. +#define HERMES_RID_COMMSQUALITY 0xFD43
  3010. +#define HERMES_RID_CURRENTTXRATE 0xFD44
  3011. +#define HERMES_RID_CURRENTBEACONINTERVAL 0xFD45
  3012. +#define HERMES_RID_CURRENTSCALETHRESHOLDS 0xFD46
  3013. +#define HERMES_RID_PROTOCOLRSPTIME 0xFD47
  3014. +#define HERMES_RID_SHORTRETRYLIMIT 0xFD48
  3015. +#define HERMES_RID_LONGRETRYLIMIT 0xFD49
  3016. +#define HERMES_RID_MAXTRANSMITLIFETIME 0xFD4A
  3017. +#define HERMES_RID_MAXRECEIVELIFETIME 0xFD4B
  3018. +#define HERMES_RID_CFPOLLABLE 0xFD4C
  3019. +#define HERMES_RID_AUTHENTICATIONALGORITHMS 0xFD4D
  3020. +#define HERMES_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
  3021. +#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL 0xFD51
  3022. +#define HERMES_RID_CURRENTTXRATE1 0xFD80
  3023. +#define HERMES_RID_CURRENTTXRATE2 0xFD81
  3024. +#define HERMES_RID_CURRENTTXRATE3 0xFD82
  3025. +#define HERMES_RID_CURRENTTXRATE4 0xFD83
  3026. +#define HERMES_RID_CURRENTTXRATE5 0xFD84
  3027. +#define HERMES_RID_CURRENTTXRATE6 0xFD85
  3028. +#define HERMES_RID_OWNMACADDR 0xFD86
  3029. +#define HERMES_RID_SCANRESULTSTABLE 0xFD88
  3030. +#define HERMES_RID_CURRENT_COUNTRY_INFO 0xFD89
  3031. +#define HERMES_RID_CURRENT_WPA_IE 0xFD8A
  3032. +#define HERMES_RID_CURRENT_TKIP_IV 0xFD8B
  3033. +#define HERMES_RID_CURRENT_ASSOC_REQ_INFO 0xFD8C
  3034. +#define HERMES_RID_CURRENT_ASSOC_RESP_INFO 0xFD8D
  3035. +#define HERMES_RID_TXQUEUEEMPTY 0xFD91
  3036. +#define HERMES_RID_PHYTYPE 0xFDC0
  3037. +#define HERMES_RID_CURRENTCHANNEL 0xFDC1
  3038. +#define HERMES_RID_CURRENTPOWERSTATE 0xFDC2
  3039. +#define HERMES_RID_CCAMODE 0xFDC3
  3040. +#define HERMES_RID_SUPPORTEDDATARATES 0xFDC6
  3041. +#define HERMES_RID_BUILDSEQ 0xFFFE
  3042. +#define HERMES_RID_FWID 0xFFFF
  3043. +
  3044. +#endif
  3045. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hw.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/hw.c
  3046. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hw.c 1970-01-01 01:00:00.000000000 +0100
  3047. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hw.c 2025-08-03 15:01:59.341130868 +0200
  3048. @@ -0,0 +1,1362 @@
  3049. +/* Encapsulate basic setting changes and retrieval on Hermes hardware
  3050. + *
  3051. + * See copyright notice in main.c
  3052. + */
  3053. +#include <linux/kernel.h>
  3054. +#include <linux/device.h>
  3055. +#include <linux/if_arp.h>
  3056. +#include <linux/ieee80211.h>
  3057. +#include <linux/wireless.h>
  3058. +#include <net/cfg80211.h>
  3059. +#include "hermes.h"
  3060. +#include "hermes_rid.h"
  3061. +#include "orinoco.h"
  3062. +
  3063. +#include "hw.h"
  3064. +
  3065. +#define SYMBOL_MAX_VER_LEN (14)
  3066. +
  3067. +/* Symbol firmware has a bug allocating buffers larger than this */
  3068. +#define TX_NICBUF_SIZE_BUG 1585
  3069. +
  3070. +/********************************************************************/
  3071. +/* Data tables */
  3072. +/********************************************************************/
  3073. +
  3074. +/* This tables gives the actual meanings of the bitrate IDs returned
  3075. + * by the firmware. */
  3076. +static const struct {
  3077. + int bitrate; /* in 100s of kilobits */
  3078. + int automatic;
  3079. + u16 agere_txratectrl;
  3080. + u16 intersil_txratectrl;
  3081. +} bitrate_table[] = {
  3082. + {110, 1, 3, 15}, /* Entry 0 is the default */
  3083. + {10, 0, 1, 1},
  3084. + {10, 1, 1, 1},
  3085. + {20, 0, 2, 2},
  3086. + {20, 1, 6, 3},
  3087. + {55, 0, 4, 4},
  3088. + {55, 1, 7, 7},
  3089. + {110, 0, 5, 8},
  3090. +};
  3091. +#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
  3092. +
  3093. +/* Firmware version encoding */
  3094. +struct comp_id {
  3095. + u16 id, variant, major, minor;
  3096. +} __packed;
  3097. +
  3098. +static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
  3099. +{
  3100. + if (nic_id->id < 0x8000)
  3101. + return FIRMWARE_TYPE_AGERE;
  3102. + else if (nic_id->id == 0x8000 && nic_id->major == 0)
  3103. + return FIRMWARE_TYPE_SYMBOL;
  3104. + else
  3105. + return FIRMWARE_TYPE_INTERSIL;
  3106. +}
  3107. +
  3108. +/* Set priv->firmware type, determine firmware properties
  3109. + * This function can be called before we have registerred with netdev,
  3110. + * so all errors go out with dev_* rather than printk
  3111. + *
  3112. + * If non-NULL stores a firmware description in fw_name.
  3113. + * If non-NULL stores a HW version in hw_ver
  3114. + *
  3115. + * These are output via generic cfg80211 ethtool support.
  3116. + */
  3117. +int determine_fw_capabilities(struct orinoco_private *priv,
  3118. + char *fw_name, size_t fw_name_len,
  3119. + u32 *hw_ver)
  3120. +{
  3121. + struct device *dev = priv->dev;
  3122. + struct hermes *hw = &priv->hw;
  3123. + int err;
  3124. + struct comp_id nic_id, sta_id;
  3125. + unsigned int firmver;
  3126. + char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
  3127. +
  3128. + /* Get the hardware version */
  3129. + err = HERMES_READ_RECORD_PR(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
  3130. + if (err) {
  3131. + dev_err(dev, "Cannot read hardware identity: error %d\n",
  3132. + err);
  3133. + return err;
  3134. + }
  3135. +
  3136. + le16_to_cpus(&nic_id.id);
  3137. + le16_to_cpus(&nic_id.variant);
  3138. + le16_to_cpus(&nic_id.major);
  3139. + le16_to_cpus(&nic_id.minor);
  3140. + dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
  3141. + nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
  3142. +
  3143. + if (hw_ver)
  3144. + *hw_ver = (((nic_id.id & 0xff) << 24) |
  3145. + ((nic_id.variant & 0xff) << 16) |
  3146. + ((nic_id.major & 0xff) << 8) |
  3147. + (nic_id.minor & 0xff));
  3148. +
  3149. + priv->firmware_type = determine_firmware_type(&nic_id);
  3150. +
  3151. + /* Get the firmware version */
  3152. + err = HERMES_READ_RECORD_PR(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
  3153. + if (err) {
  3154. + dev_err(dev, "Cannot read station identity: error %d\n",
  3155. + err);
  3156. + return err;
  3157. + }
  3158. +
  3159. + le16_to_cpus(&sta_id.id);
  3160. + le16_to_cpus(&sta_id.variant);
  3161. + le16_to_cpus(&sta_id.major);
  3162. + le16_to_cpus(&sta_id.minor);
  3163. + dev_info(dev, "Station identity %04x:%04x:%04x:%04x\n",
  3164. + sta_id.id, sta_id.variant, sta_id.major, sta_id.minor);
  3165. +
  3166. + switch (sta_id.id) {
  3167. + case 0x15:
  3168. + dev_err(dev, "Primary firmware is active\n");
  3169. + return -ENODEV;
  3170. + case 0x14b:
  3171. + dev_err(dev, "Tertiary firmware is active\n");
  3172. + return -ENODEV;
  3173. + case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
  3174. + case 0x21: /* Symbol Spectrum24 Trilogy */
  3175. + break;
  3176. + default:
  3177. + dev_notice(dev, "Unknown station ID, please report\n");
  3178. + break;
  3179. + }
  3180. +
  3181. + /* Default capabilities */
  3182. + priv->has_sensitivity = 1;
  3183. + priv->has_mwo = 0;
  3184. + priv->has_preamble = 0;
  3185. + priv->has_port3 = 1;
  3186. + priv->has_ibss = 1;
  3187. + priv->has_wep = 0;
  3188. + priv->has_big_wep = 0;
  3189. + priv->has_alt_txcntl = 0;
  3190. + priv->has_ext_scan = 0;
  3191. + priv->has_wpa = 0;
  3192. + priv->do_fw_download = 0;
  3193. +
  3194. + /* Determine capabilities from the firmware version */
  3195. + switch (priv->firmware_type) {
  3196. + case FIRMWARE_TYPE_AGERE:
  3197. + /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
  3198. + ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
  3199. + if (fw_name)
  3200. + snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d",
  3201. + sta_id.major, sta_id.minor);
  3202. +
  3203. + firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
  3204. +
  3205. + priv->has_ibss = (firmver >= 0x60006);
  3206. + priv->has_wep = (firmver >= 0x40020);
  3207. + priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
  3208. + Gold cards from the others? */
  3209. + priv->has_mwo = (firmver >= 0x60000);
  3210. + priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
  3211. + priv->ibss_port = 1;
  3212. + priv->has_hostscan = (firmver >= 0x8000a);
  3213. + priv->do_fw_download = 1;
  3214. + priv->broken_monitor = (firmver >= 0x80000);
  3215. + priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
  3216. + priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
  3217. + priv->has_wpa = (firmver >= 0x9002a);
  3218. + /* Tested with Agere firmware :
  3219. + * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
  3220. + * Tested CableTron firmware : 4.32 => Anton */
  3221. + break;
  3222. + case FIRMWARE_TYPE_SYMBOL:
  3223. + /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
  3224. + /* Intel MAC : 00:02:B3:* */
  3225. + /* 3Com MAC : 00:50:DA:* */
  3226. + memset(tmp, 0, sizeof(tmp));
  3227. + /* Get the Symbol firmware version */
  3228. + err = hw->ops->read_ltv_pr(hw, USER_BAP,
  3229. + HERMES_RID_SECONDARYVERSION_SYMBOL,
  3230. + SYMBOL_MAX_VER_LEN, NULL, &tmp);
  3231. + if (err) {
  3232. + dev_warn(dev, "Error %d reading Symbol firmware info. "
  3233. + "Wildly guessing capabilities...\n", err);
  3234. + firmver = 0;
  3235. + tmp[0] = '\0';
  3236. + } else {
  3237. + /* The firmware revision is a string, the format is
  3238. + * something like : "V2.20-01".
  3239. + * Quick and dirty parsing... - Jean II
  3240. + */
  3241. + firmver = ((tmp[1] - '0') << 16)
  3242. + | ((tmp[3] - '0') << 12)
  3243. + | ((tmp[4] - '0') << 8)
  3244. + | ((tmp[6] - '0') << 4)
  3245. + | (tmp[7] - '0');
  3246. +
  3247. + tmp[SYMBOL_MAX_VER_LEN] = '\0';
  3248. + }
  3249. +
  3250. + if (fw_name)
  3251. + snprintf(fw_name, fw_name_len, "Symbol %s", tmp);
  3252. +
  3253. + priv->has_ibss = (firmver >= 0x20000);
  3254. + priv->has_wep = (firmver >= 0x15012);
  3255. + priv->has_big_wep = (firmver >= 0x20000);
  3256. + priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
  3257. + (firmver >= 0x29000 && firmver < 0x30000) ||
  3258. + firmver >= 0x31000;
  3259. + priv->has_preamble = (firmver >= 0x20000);
  3260. + priv->ibss_port = 4;
  3261. +
  3262. + /* Symbol firmware is found on various cards, but
  3263. + * there has been no attempt to check firmware
  3264. + * download on non-spectrum_cs based cards.
  3265. + *
  3266. + * Given that the Agere firmware download works
  3267. + * differently, we should avoid doing a firmware
  3268. + * download with the Symbol algorithm on non-spectrum
  3269. + * cards.
  3270. + *
  3271. + * For now we can identify a spectrum_cs based card
  3272. + * because it has a firmware reset function.
  3273. + */
  3274. + priv->do_fw_download = (priv->stop_fw != NULL);
  3275. +
  3276. + priv->broken_disableport = (firmver == 0x25013) ||
  3277. + (firmver >= 0x30000 && firmver <= 0x31000);
  3278. + priv->has_hostscan = (firmver >= 0x31001) ||
  3279. + (firmver >= 0x29057 && firmver < 0x30000);
  3280. + /* Tested with Intel firmware : 0x20015 => Jean II */
  3281. + /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
  3282. + break;
  3283. + case FIRMWARE_TYPE_INTERSIL:
  3284. + /* D-Link, Linksys, Adtron, ZoomAir, and many others...
  3285. + * Samsung, Compaq 100/200 and Proxim are slightly
  3286. + * different and less well tested */
  3287. + /* D-Link MAC : 00:40:05:* */
  3288. + /* Addtron MAC : 00:90:D1:* */
  3289. + if (fw_name)
  3290. + snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d",
  3291. + sta_id.major, sta_id.minor, sta_id.variant);
  3292. +
  3293. + firmver = ((unsigned long)sta_id.major << 16) |
  3294. + ((unsigned long)sta_id.minor << 8) | sta_id.variant;
  3295. +
  3296. + priv->has_ibss = (firmver >= 0x000700); /* FIXME */
  3297. + priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
  3298. + priv->has_pm = (firmver >= 0x000700);
  3299. + priv->has_hostscan = (firmver >= 0x010301);
  3300. +
  3301. + if (firmver >= 0x000800)
  3302. + priv->ibss_port = 0;
  3303. + else {
  3304. + dev_notice(dev, "Intersil firmware earlier than v0.8.x"
  3305. + " - several features not supported\n");
  3306. + priv->ibss_port = 1;
  3307. + }
  3308. + break;
  3309. + }
  3310. + if (fw_name)
  3311. + dev_info(dev, "Firmware determined as %s\n", fw_name);
  3312. +
  3313. +#ifndef CONFIG_HERMES_PRISM
  3314. + if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
  3315. + dev_err(dev, "Support for Prism chipset is not enabled\n");
  3316. + return -ENODEV;
  3317. + }
  3318. +#endif
  3319. +
  3320. + return 0;
  3321. +}
  3322. +
  3323. +/* Read settings from EEPROM into our private structure.
  3324. + * MAC address gets dropped into callers buffer
  3325. + * Can be called before netdev registration.
  3326. + */
  3327. +int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
  3328. +{
  3329. + struct device *dev = priv->dev;
  3330. + struct hermes_idstring nickbuf;
  3331. + struct hermes *hw = &priv->hw;
  3332. + int len;
  3333. + int err;
  3334. + u16 reclen;
  3335. +
  3336. + /* Get the MAC address */
  3337. + err = hw->ops->read_ltv_pr(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
  3338. + ETH_ALEN, NULL, dev_addr);
  3339. + if (err) {
  3340. + dev_warn(dev, "Failed to read MAC address!\n");
  3341. + goto out;
  3342. + }
  3343. +
  3344. + dev_dbg(dev, "MAC address %pM\n", dev_addr);
  3345. +
  3346. + /* Get the station name */
  3347. + err = hw->ops->read_ltv_pr(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
  3348. + sizeof(nickbuf), &reclen, &nickbuf);
  3349. + if (err) {
  3350. + dev_err(dev, "failed to read station name\n");
  3351. + goto out;
  3352. + }
  3353. + if (nickbuf.len)
  3354. + len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
  3355. + else
  3356. + len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
  3357. + memcpy(priv->nick, &nickbuf.val, len);
  3358. + priv->nick[len] = '\0';
  3359. +
  3360. + dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
  3361. +
  3362. + /* Get allowed channels */
  3363. + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CHANNELLIST,
  3364. + &priv->channel_mask);
  3365. + if (err) {
  3366. + dev_err(dev, "Failed to read channel list!\n");
  3367. + goto out;
  3368. + }
  3369. +
  3370. + /* Get initial AP density */
  3371. + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
  3372. + &priv->ap_density);
  3373. + if (err || priv->ap_density < 1 || priv->ap_density > 3)
  3374. + priv->has_sensitivity = 0;
  3375. +
  3376. + /* Get initial RTS threshold */
  3377. + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
  3378. + &priv->rts_thresh);
  3379. + if (err) {
  3380. + dev_err(dev, "Failed to read RTS threshold!\n");
  3381. + goto out;
  3382. + }
  3383. +
  3384. + /* Get initial fragmentation settings */
  3385. + if (priv->has_mwo)
  3386. + err = hermes_read_wordrec_pr(hw, USER_BAP,
  3387. + HERMES_RID_CNFMWOROBUST_AGERE,
  3388. + &priv->mwo_robust);
  3389. + else
  3390. + err = hermes_read_wordrec_pr(hw, USER_BAP,
  3391. + HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
  3392. + &priv->frag_thresh);
  3393. + if (err) {
  3394. + dev_err(dev, "Failed to read fragmentation settings!\n");
  3395. + goto out;
  3396. + }
  3397. +
  3398. + /* Power management setup */
  3399. + if (priv->has_pm) {
  3400. + priv->pm_on = 0;
  3401. + priv->pm_mcast = 1;
  3402. + err = hermes_read_wordrec_pr(hw, USER_BAP,
  3403. + HERMES_RID_CNFMAXSLEEPDURATION,
  3404. + &priv->pm_period);
  3405. + if (err) {
  3406. + dev_err(dev, "Failed to read power management "
  3407. + "period!\n");
  3408. + goto out;
  3409. + }
  3410. + err = hermes_read_wordrec_pr(hw, USER_BAP,
  3411. + HERMES_RID_CNFPMHOLDOVERDURATION,
  3412. + &priv->pm_timeout);
  3413. + if (err) {
  3414. + dev_err(dev, "Failed to read power management "
  3415. + "timeout!\n");
  3416. + goto out;
  3417. + }
  3418. + }
  3419. +
  3420. + /* Preamble setup */
  3421. + if (priv->has_preamble) {
  3422. + err = hermes_read_wordrec_pr(hw, USER_BAP,
  3423. + HERMES_RID_CNFPREAMBLE_SYMBOL,
  3424. + &priv->preamble);
  3425. + if (err) {
  3426. + dev_err(dev, "Failed to read preamble setup\n");
  3427. + goto out;
  3428. + }
  3429. + }
  3430. +
  3431. + /* Retry settings */
  3432. + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
  3433. + &priv->short_retry_limit);
  3434. + if (err) {
  3435. + dev_err(dev, "Failed to read short retry limit\n");
  3436. + goto out;
  3437. + }
  3438. +
  3439. + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
  3440. + &priv->long_retry_limit);
  3441. + if (err) {
  3442. + dev_err(dev, "Failed to read long retry limit\n");
  3443. + goto out;
  3444. + }
  3445. +
  3446. + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
  3447. + &priv->retry_lifetime);
  3448. + if (err) {
  3449. + dev_err(dev, "Failed to read max retry lifetime\n");
  3450. + goto out;
  3451. + }
  3452. +
  3453. +out:
  3454. + return err;
  3455. +}
  3456. +
  3457. +/* Can be called before netdev registration */
  3458. +int orinoco_hw_allocate_fid(struct orinoco_private *priv)
  3459. +{
  3460. + struct device *dev = priv->dev;
  3461. + struct hermes *hw = &priv->hw;
  3462. + int err;
  3463. +
  3464. + err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
  3465. + if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
  3466. + /* Try workaround for old Symbol firmware bug */
  3467. + priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
  3468. + err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
  3469. +
  3470. + dev_warn(dev, "Firmware ALLOC bug detected "
  3471. + "(old Symbol firmware?). Work around %s\n",
  3472. + err ? "failed!" : "ok.");
  3473. + }
  3474. +
  3475. + return err;
  3476. +}
  3477. +
  3478. +int orinoco_get_bitratemode(int bitrate, int automatic)
  3479. +{
  3480. + int ratemode = -1;
  3481. + int i;
  3482. +
  3483. + if ((bitrate != 10) && (bitrate != 20) &&
  3484. + (bitrate != 55) && (bitrate != 110))
  3485. + return ratemode;
  3486. +
  3487. + for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
  3488. + if ((bitrate_table[i].bitrate == bitrate) &&
  3489. + (bitrate_table[i].automatic == automatic)) {
  3490. + ratemode = i;
  3491. + break;
  3492. + }
  3493. + }
  3494. + return ratemode;
  3495. +}
  3496. +
  3497. +void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
  3498. +{
  3499. + BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
  3500. +
  3501. + *bitrate = bitrate_table[ratemode].bitrate * 100000;
  3502. + *automatic = bitrate_table[ratemode].automatic;
  3503. +}
  3504. +
  3505. +int orinoco_hw_program_rids(struct orinoco_private *priv)
  3506. +{
  3507. + struct net_device *dev = priv->ndev;
  3508. + struct wireless_dev *wdev = netdev_priv(dev);
  3509. + struct hermes *hw = &priv->hw;
  3510. + int err;
  3511. + struct hermes_idstring idbuf;
  3512. +
  3513. + /* Set the MAC address */
  3514. + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
  3515. + HERMES_BYTES_TO_RECLEN(ETH_ALEN),
  3516. + dev->dev_addr);
  3517. + if (err) {
  3518. + printk(KERN_ERR "%s: Error %d setting MAC address\n",
  3519. + dev->name, err);
  3520. + return err;
  3521. + }
  3522. +
  3523. + /* Set up the link mode */
  3524. + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
  3525. + priv->port_type);
  3526. + if (err) {
  3527. + printk(KERN_ERR "%s: Error %d setting port type\n",
  3528. + dev->name, err);
  3529. + return err;
  3530. + }
  3531. + /* Set the channel/frequency */
  3532. + if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) {
  3533. + err = hermes_write_wordrec(hw, USER_BAP,
  3534. + HERMES_RID_CNFOWNCHANNEL,
  3535. + priv->channel);
  3536. + if (err) {
  3537. + printk(KERN_ERR "%s: Error %d setting channel %d\n",
  3538. + dev->name, err, priv->channel);
  3539. + return err;
  3540. + }
  3541. + }
  3542. +
  3543. + if (priv->has_ibss) {
  3544. + u16 createibss;
  3545. +
  3546. + if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
  3547. + printk(KERN_WARNING "%s: This firmware requires an "
  3548. + "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
  3549. + /* With wvlan_cs, in this case, we would crash.
  3550. + * hopefully, this driver will behave better...
  3551. + * Jean II */
  3552. + createibss = 0;
  3553. + } else {
  3554. + createibss = priv->createibss;
  3555. + }
  3556. +
  3557. + err = hermes_write_wordrec(hw, USER_BAP,
  3558. + HERMES_RID_CNFCREATEIBSS,
  3559. + createibss);
  3560. + if (err) {
  3561. + printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
  3562. + dev->name, err);
  3563. + return err;
  3564. + }
  3565. + }
  3566. +
  3567. + /* Set the desired BSSID */
  3568. + err = __orinoco_hw_set_wap(priv);
  3569. + if (err) {
  3570. + printk(KERN_ERR "%s: Error %d setting AP address\n",
  3571. + dev->name, err);
  3572. + return err;
  3573. + }
  3574. +
  3575. + /* Set the desired ESSID */
  3576. + idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
  3577. + memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
  3578. + /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
  3579. + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
  3580. + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
  3581. + &idbuf);
  3582. + if (err) {
  3583. + printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
  3584. + dev->name, err);
  3585. + return err;
  3586. + }
  3587. + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
  3588. + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
  3589. + &idbuf);
  3590. + if (err) {
  3591. + printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
  3592. + dev->name, err);
  3593. + return err;
  3594. + }
  3595. +
  3596. + /* Set the station name */
  3597. + idbuf.len = cpu_to_le16(strlen(priv->nick));
  3598. + memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
  3599. + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
  3600. + HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
  3601. + &idbuf);
  3602. + if (err) {
  3603. + printk(KERN_ERR "%s: Error %d setting nickname\n",
  3604. + dev->name, err);
  3605. + return err;
  3606. + }
  3607. +
  3608. + /* Set AP density */
  3609. + if (priv->has_sensitivity) {
  3610. + err = hermes_write_wordrec(hw, USER_BAP,
  3611. + HERMES_RID_CNFSYSTEMSCALE,
  3612. + priv->ap_density);
  3613. + if (err) {
  3614. + printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
  3615. + "Disabling sensitivity control\n",
  3616. + dev->name, err);
  3617. +
  3618. + priv->has_sensitivity = 0;
  3619. + }
  3620. + }
  3621. +
  3622. + /* Set RTS threshold */
  3623. + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
  3624. + priv->rts_thresh);
  3625. + if (err) {
  3626. + printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
  3627. + dev->name, err);
  3628. + return err;
  3629. + }
  3630. +
  3631. + /* Set fragmentation threshold or MWO robustness */
  3632. + if (priv->has_mwo)
  3633. + err = hermes_write_wordrec(hw, USER_BAP,
  3634. + HERMES_RID_CNFMWOROBUST_AGERE,
  3635. + priv->mwo_robust);
  3636. + else
  3637. + err = hermes_write_wordrec(hw, USER_BAP,
  3638. + HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
  3639. + priv->frag_thresh);
  3640. + if (err) {
  3641. + printk(KERN_ERR "%s: Error %d setting fragmentation\n",
  3642. + dev->name, err);
  3643. + return err;
  3644. + }
  3645. +
  3646. + /* Set bitrate */
  3647. + err = __orinoco_hw_set_bitrate(priv);
  3648. + if (err) {
  3649. + printk(KERN_ERR "%s: Error %d setting bitrate\n",
  3650. + dev->name, err);
  3651. + return err;
  3652. + }
  3653. +
  3654. + /* Set power management */
  3655. + if (priv->has_pm) {
  3656. + err = hermes_write_wordrec(hw, USER_BAP,
  3657. + HERMES_RID_CNFPMENABLED,
  3658. + priv->pm_on);
  3659. + if (err) {
  3660. + printk(KERN_ERR "%s: Error %d setting up PM\n",
  3661. + dev->name, err);
  3662. + return err;
  3663. + }
  3664. +
  3665. + err = hermes_write_wordrec(hw, USER_BAP,
  3666. + HERMES_RID_CNFMULTICASTRECEIVE,
  3667. + priv->pm_mcast);
  3668. + if (err) {
  3669. + printk(KERN_ERR "%s: Error %d setting up PM\n",
  3670. + dev->name, err);
  3671. + return err;
  3672. + }
  3673. + err = hermes_write_wordrec(hw, USER_BAP,
  3674. + HERMES_RID_CNFMAXSLEEPDURATION,
  3675. + priv->pm_period);
  3676. + if (err) {
  3677. + printk(KERN_ERR "%s: Error %d setting up PM\n",
  3678. + dev->name, err);
  3679. + return err;
  3680. + }
  3681. + err = hermes_write_wordrec(hw, USER_BAP,
  3682. + HERMES_RID_CNFPMHOLDOVERDURATION,
  3683. + priv->pm_timeout);
  3684. + if (err) {
  3685. + printk(KERN_ERR "%s: Error %d setting up PM\n",
  3686. + dev->name, err);
  3687. + return err;
  3688. + }
  3689. + }
  3690. +
  3691. + /* Set preamble - only for Symbol so far... */
  3692. + if (priv->has_preamble) {
  3693. + err = hermes_write_wordrec(hw, USER_BAP,
  3694. + HERMES_RID_CNFPREAMBLE_SYMBOL,
  3695. + priv->preamble);
  3696. + if (err) {
  3697. + printk(KERN_ERR "%s: Error %d setting preamble\n",
  3698. + dev->name, err);
  3699. + return err;
  3700. + }
  3701. + }
  3702. +
  3703. + /* Set up encryption */
  3704. + if (priv->has_wep || priv->has_wpa) {
  3705. + err = __orinoco_hw_setup_enc(priv);
  3706. + if (err) {
  3707. + printk(KERN_ERR "%s: Error %d activating encryption\n",
  3708. + dev->name, err);
  3709. + return err;
  3710. + }
  3711. + }
  3712. +
  3713. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
  3714. + /* Enable monitor mode */
  3715. + dev->type = ARPHRD_IEEE80211;
  3716. + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
  3717. + HERMES_TEST_MONITOR, 0, NULL);
  3718. + } else {
  3719. + /* Disable monitor mode */
  3720. + dev->type = ARPHRD_ETHER;
  3721. + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
  3722. + HERMES_TEST_STOP, 0, NULL);
  3723. + }
  3724. + if (err)
  3725. + return err;
  3726. +
  3727. + /* Reset promiscuity / multicast*/
  3728. + priv->promiscuous = 0;
  3729. + priv->mc_count = 0;
  3730. +
  3731. + /* Record mode change */
  3732. + wdev->iftype = priv->iw_mode;
  3733. +
  3734. + return 0;
  3735. +}
  3736. +
  3737. +/* Get tsc from the firmware */
  3738. +int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
  3739. +{
  3740. + struct hermes *hw = &priv->hw;
  3741. + int err = 0;
  3742. + u8 tsc_arr[4][ORINOCO_SEQ_LEN];
  3743. +
  3744. + if ((key < 0) || (key >= 4))
  3745. + return -EINVAL;
  3746. +
  3747. + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
  3748. + sizeof(tsc_arr), NULL, &tsc_arr);
  3749. + if (!err)
  3750. + memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
  3751. +
  3752. + return err;
  3753. +}
  3754. +
  3755. +int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
  3756. +{
  3757. + struct hermes *hw = &priv->hw;
  3758. + int ratemode = priv->bitratemode;
  3759. + int err = 0;
  3760. +
  3761. + if (ratemode >= BITRATE_TABLE_SIZE) {
  3762. + printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
  3763. + priv->ndev->name, ratemode);
  3764. + return -EINVAL;
  3765. + }
  3766. +
  3767. + switch (priv->firmware_type) {
  3768. + case FIRMWARE_TYPE_AGERE:
  3769. + err = hermes_write_wordrec(hw, USER_BAP,
  3770. + HERMES_RID_CNFTXRATECONTROL,
  3771. + bitrate_table[ratemode].agere_txratectrl);
  3772. + break;
  3773. + case FIRMWARE_TYPE_INTERSIL:
  3774. + case FIRMWARE_TYPE_SYMBOL:
  3775. + err = hermes_write_wordrec(hw, USER_BAP,
  3776. + HERMES_RID_CNFTXRATECONTROL,
  3777. + bitrate_table[ratemode].intersil_txratectrl);
  3778. + break;
  3779. + default:
  3780. + BUG();
  3781. + }
  3782. +
  3783. + return err;
  3784. +}
  3785. +
  3786. +int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
  3787. +{
  3788. + struct hermes *hw = &priv->hw;
  3789. + int i;
  3790. + int err = 0;
  3791. + u16 val;
  3792. +
  3793. + err = hermes_read_wordrec(hw, USER_BAP,
  3794. + HERMES_RID_CURRENTTXRATE, &val);
  3795. + if (err)
  3796. + return err;
  3797. +
  3798. + switch (priv->firmware_type) {
  3799. + case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
  3800. + /* Note : in Lucent firmware, the return value of
  3801. + * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
  3802. + * and therefore is totally different from the
  3803. + * encoding of HERMES_RID_CNFTXRATECONTROL.
  3804. + * Don't forget that 6Mb/s is really 5.5Mb/s */
  3805. + if (val == 6)
  3806. + *bitrate = 5500000;
  3807. + else
  3808. + *bitrate = val * 1000000;
  3809. + break;
  3810. + case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
  3811. + case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
  3812. + for (i = 0; i < BITRATE_TABLE_SIZE; i++)
  3813. + if (bitrate_table[i].intersil_txratectrl == val) {
  3814. + *bitrate = bitrate_table[i].bitrate * 100000;
  3815. + break;
  3816. + }
  3817. +
  3818. + if (i >= BITRATE_TABLE_SIZE) {
  3819. + printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
  3820. + priv->ndev->name, val);
  3821. + err = -EIO;
  3822. + }
  3823. +
  3824. + break;
  3825. + default:
  3826. + BUG();
  3827. + }
  3828. +
  3829. + return err;
  3830. +}
  3831. +
  3832. +/* Set fixed AP address */
  3833. +int __orinoco_hw_set_wap(struct orinoco_private *priv)
  3834. +{
  3835. + int roaming_flag;
  3836. + int err = 0;
  3837. + struct hermes *hw = &priv->hw;
  3838. +
  3839. + switch (priv->firmware_type) {
  3840. + case FIRMWARE_TYPE_AGERE:
  3841. + /* not supported */
  3842. + break;
  3843. + case FIRMWARE_TYPE_INTERSIL:
  3844. + if (priv->bssid_fixed)
  3845. + roaming_flag = 2;
  3846. + else
  3847. + roaming_flag = 1;
  3848. +
  3849. + err = hermes_write_wordrec(hw, USER_BAP,
  3850. + HERMES_RID_CNFROAMINGMODE,
  3851. + roaming_flag);
  3852. + break;
  3853. + case FIRMWARE_TYPE_SYMBOL:
  3854. + err = HERMES_WRITE_RECORD(hw, USER_BAP,
  3855. + HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
  3856. + &priv->desired_bssid);
  3857. + break;
  3858. + }
  3859. + return err;
  3860. +}
  3861. +
  3862. +/* Change the WEP keys and/or the current keys. Can be called
  3863. + * either from __orinoco_hw_setup_enc() or directly from
  3864. + * orinoco_ioctl_setiwencode(). In the later case the association
  3865. + * with the AP is not broken (if the firmware can handle it),
  3866. + * which is needed for 802.1x implementations. */
  3867. +int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
  3868. +{
  3869. + struct hermes *hw = &priv->hw;
  3870. + int err = 0;
  3871. + int i;
  3872. +
  3873. + switch (priv->firmware_type) {
  3874. + case FIRMWARE_TYPE_AGERE:
  3875. + {
  3876. + struct orinoco_key keys[ORINOCO_MAX_KEYS];
  3877. +
  3878. + memset(&keys, 0, sizeof(keys));
  3879. + for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
  3880. + int len = min(priv->keys[i].key_len,
  3881. + ORINOCO_MAX_KEY_SIZE);
  3882. + memcpy(&keys[i].data, priv->keys[i].key, len);
  3883. + if (len > SMALL_KEY_SIZE)
  3884. + keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
  3885. + else if (len > 0)
  3886. + keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
  3887. + else
  3888. + keys[i].len = cpu_to_le16(0);
  3889. + }
  3890. +
  3891. + err = HERMES_WRITE_RECORD(hw, USER_BAP,
  3892. + HERMES_RID_CNFWEPKEYS_AGERE,
  3893. + &keys);
  3894. + if (err)
  3895. + return err;
  3896. + err = hermes_write_wordrec(hw, USER_BAP,
  3897. + HERMES_RID_CNFTXKEY_AGERE,
  3898. + priv->tx_key);
  3899. + if (err)
  3900. + return err;
  3901. + break;
  3902. + }
  3903. + case FIRMWARE_TYPE_INTERSIL:
  3904. + case FIRMWARE_TYPE_SYMBOL:
  3905. + {
  3906. + int keylen;
  3907. +
  3908. + /* Force uniform key length to work around
  3909. + * firmware bugs */
  3910. + keylen = priv->keys[priv->tx_key].key_len;
  3911. +
  3912. + if (keylen > LARGE_KEY_SIZE) {
  3913. + printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
  3914. + priv->ndev->name, priv->tx_key, keylen);
  3915. + return -E2BIG;
  3916. + } else if (keylen > SMALL_KEY_SIZE)
  3917. + keylen = LARGE_KEY_SIZE;
  3918. + else if (keylen > 0)
  3919. + keylen = SMALL_KEY_SIZE;
  3920. + else
  3921. + keylen = 0;
  3922. +
  3923. + /* Write all 4 keys */
  3924. + for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
  3925. + u8 key[LARGE_KEY_SIZE] = { 0 };
  3926. +
  3927. + memcpy(key, priv->keys[i].key,
  3928. + priv->keys[i].key_len);
  3929. +
  3930. + err = hw->ops->write_ltv(hw, USER_BAP,
  3931. + HERMES_RID_CNFDEFAULTKEY0 + i,
  3932. + HERMES_BYTES_TO_RECLEN(keylen),
  3933. + key);
  3934. + if (err)
  3935. + return err;
  3936. + }
  3937. +
  3938. + /* Write the index of the key used in transmission */
  3939. + err = hermes_write_wordrec(hw, USER_BAP,
  3940. + HERMES_RID_CNFWEPDEFAULTKEYID,
  3941. + priv->tx_key);
  3942. + if (err)
  3943. + return err;
  3944. + }
  3945. + break;
  3946. + }
  3947. +
  3948. + return 0;
  3949. +}
  3950. +
  3951. +int __orinoco_hw_setup_enc(struct orinoco_private *priv)
  3952. +{
  3953. + struct hermes *hw = &priv->hw;
  3954. + int err = 0;
  3955. + int master_wep_flag;
  3956. + int auth_flag;
  3957. + int enc_flag;
  3958. +
  3959. + /* Setup WEP keys */
  3960. + if (priv->encode_alg == ORINOCO_ALG_WEP)
  3961. + __orinoco_hw_setup_wepkeys(priv);
  3962. +
  3963. + if (priv->wep_restrict)
  3964. + auth_flag = HERMES_AUTH_SHARED_KEY;
  3965. + else
  3966. + auth_flag = HERMES_AUTH_OPEN;
  3967. +
  3968. + if (priv->wpa_enabled)
  3969. + enc_flag = 2;
  3970. + else if (priv->encode_alg == ORINOCO_ALG_WEP)
  3971. + enc_flag = 1;
  3972. + else
  3973. + enc_flag = 0;
  3974. +
  3975. + switch (priv->firmware_type) {
  3976. + case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
  3977. + if (priv->encode_alg == ORINOCO_ALG_WEP) {
  3978. + /* Enable the shared-key authentication. */
  3979. + err = hermes_write_wordrec(hw, USER_BAP,
  3980. + HERMES_RID_CNFAUTHENTICATION_AGERE,
  3981. + auth_flag);
  3982. + if (err)
  3983. + return err;
  3984. + }
  3985. + err = hermes_write_wordrec(hw, USER_BAP,
  3986. + HERMES_RID_CNFWEPENABLED_AGERE,
  3987. + enc_flag);
  3988. + if (err)
  3989. + return err;
  3990. +
  3991. + if (priv->has_wpa) {
  3992. + /* Set WPA key management */
  3993. + err = hermes_write_wordrec(hw, USER_BAP,
  3994. + HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
  3995. + priv->key_mgmt);
  3996. + if (err)
  3997. + return err;
  3998. + }
  3999. +
  4000. + break;
  4001. +
  4002. + case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
  4003. + case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
  4004. + if (priv->encode_alg == ORINOCO_ALG_WEP) {
  4005. + if (priv->wep_restrict ||
  4006. + (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
  4007. + master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
  4008. + HERMES_WEP_EXCL_UNENCRYPTED;
  4009. + else
  4010. + master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
  4011. +
  4012. + err = hermes_write_wordrec(hw, USER_BAP,
  4013. + HERMES_RID_CNFAUTHENTICATION,
  4014. + auth_flag);
  4015. + if (err)
  4016. + return err;
  4017. + } else
  4018. + master_wep_flag = 0;
  4019. +
  4020. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
  4021. + master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
  4022. +
  4023. + /* Master WEP setting : on/off */
  4024. + err = hermes_write_wordrec(hw, USER_BAP,
  4025. + HERMES_RID_CNFWEPFLAGS_INTERSIL,
  4026. + master_wep_flag);
  4027. + if (err)
  4028. + return err;
  4029. +
  4030. + break;
  4031. + }
  4032. +
  4033. + return 0;
  4034. +}
  4035. +
  4036. +/* key must be 32 bytes, including the tx and rx MIC keys.
  4037. + * rsc must be NULL or up to 8 bytes
  4038. + * tsc must be NULL or up to 8 bytes
  4039. + */
  4040. +int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
  4041. + int set_tx, const u8 *key, size_t key_len,
  4042. + const u8 *rsc, size_t rsc_len,
  4043. + const u8 *tsc, size_t tsc_len)
  4044. +{
  4045. + struct {
  4046. + __le16 idx;
  4047. + u8 rsc[ORINOCO_SEQ_LEN];
  4048. + struct {
  4049. + u8 key[TKIP_KEYLEN];
  4050. + u8 tx_mic[MIC_KEYLEN];
  4051. + u8 rx_mic[MIC_KEYLEN];
  4052. + } tkip;
  4053. + u8 tsc[ORINOCO_SEQ_LEN];
  4054. + } __packed buf;
  4055. + struct hermes *hw = &priv->hw;
  4056. + int ret;
  4057. + int err;
  4058. + int k;
  4059. + u16 xmitting;
  4060. +
  4061. + key_idx &= 0x3;
  4062. +
  4063. + if (set_tx)
  4064. + key_idx |= 0x8000;
  4065. +
  4066. + buf.idx = cpu_to_le16(key_idx);
  4067. + if (key_len != sizeof(buf.tkip))
  4068. + return -EINVAL;
  4069. + memcpy(&buf.tkip, key, sizeof(buf.tkip));
  4070. +
  4071. + if (rsc_len > sizeof(buf.rsc))
  4072. + rsc_len = sizeof(buf.rsc);
  4073. +
  4074. + if (tsc_len > sizeof(buf.tsc))
  4075. + tsc_len = sizeof(buf.tsc);
  4076. +
  4077. + memset(buf.rsc, 0, sizeof(buf.rsc));
  4078. + memset(buf.tsc, 0, sizeof(buf.tsc));
  4079. +
  4080. + if (rsc != NULL)
  4081. + memcpy(buf.rsc, rsc, rsc_len);
  4082. +
  4083. + if (tsc != NULL)
  4084. + memcpy(buf.tsc, tsc, tsc_len);
  4085. + else
  4086. + buf.tsc[4] = 0x10;
  4087. +
  4088. + /* Wait up to 100ms for tx queue to empty */
  4089. + for (k = 100; k > 0; k--) {
  4090. + udelay(1000);
  4091. + ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
  4092. + &xmitting);
  4093. + if (ret || !xmitting)
  4094. + break;
  4095. + }
  4096. +
  4097. + if (k == 0)
  4098. + ret = -ETIMEDOUT;
  4099. +
  4100. + err = HERMES_WRITE_RECORD(hw, USER_BAP,
  4101. + HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
  4102. + &buf);
  4103. +
  4104. + return ret ? ret : err;
  4105. +}
  4106. +
  4107. +int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
  4108. +{
  4109. + struct hermes *hw = &priv->hw;
  4110. + int err;
  4111. +
  4112. + err = hermes_write_wordrec(hw, USER_BAP,
  4113. + HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
  4114. + key_idx);
  4115. + if (err)
  4116. + printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
  4117. + priv->ndev->name, err, key_idx);
  4118. + return err;
  4119. +}
  4120. +
  4121. +int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
  4122. + struct net_device *dev,
  4123. + int mc_count, int promisc)
  4124. +{
  4125. + struct hermes *hw = &priv->hw;
  4126. + int err = 0;
  4127. +
  4128. + if (promisc != priv->promiscuous) {
  4129. + err = hermes_write_wordrec(hw, USER_BAP,
  4130. + HERMES_RID_CNFPROMISCUOUSMODE,
  4131. + promisc);
  4132. + if (err) {
  4133. + printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
  4134. + priv->ndev->name, err);
  4135. + } else
  4136. + priv->promiscuous = promisc;
  4137. + }
  4138. +
  4139. + /* If we're not in promiscuous mode, then we need to set the
  4140. + * group address if either we want to multicast, or if we were
  4141. + * multicasting and want to stop */
  4142. + if (!promisc && (mc_count || priv->mc_count)) {
  4143. + struct netdev_hw_addr *ha;
  4144. + struct hermes_multicast mclist;
  4145. + int i = 0;
  4146. +
  4147. + netdev_for_each_mc_addr(ha, dev) {
  4148. + if (i == mc_count)
  4149. + break;
  4150. + memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
  4151. + }
  4152. +
  4153. + err = hw->ops->write_ltv(hw, USER_BAP,
  4154. + HERMES_RID_CNFGROUPADDRESSES,
  4155. + HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
  4156. + &mclist);
  4157. + if (err)
  4158. + printk(KERN_ERR "%s: Error %d setting multicast list.\n",
  4159. + priv->ndev->name, err);
  4160. + else
  4161. + priv->mc_count = mc_count;
  4162. + }
  4163. + return err;
  4164. +}
  4165. +
  4166. +/* Return : < 0 -> error code ; >= 0 -> length */
  4167. +int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
  4168. + char buf[IW_ESSID_MAX_SIZE + 1])
  4169. +{
  4170. + struct hermes *hw = &priv->hw;
  4171. + int err = 0;
  4172. + struct hermes_idstring essidbuf;
  4173. + char *p = (char *)(&essidbuf.val);
  4174. + int len;
  4175. + unsigned long flags;
  4176. +
  4177. + if (orinoco_lock(priv, &flags) != 0)
  4178. + return -EBUSY;
  4179. +
  4180. + if (strlen(priv->desired_essid) > 0) {
  4181. + /* We read the desired SSID from the hardware rather
  4182. + than from priv->desired_essid, just in case the
  4183. + firmware is allowed to change it on us. I'm not
  4184. + sure about this */
  4185. + /* My guess is that the OWNSSID should always be whatever
  4186. + * we set to the card, whereas CURRENT_SSID is the one that
  4187. + * may change... - Jean II */
  4188. + u16 rid;
  4189. +
  4190. + *active = 1;
  4191. +
  4192. + rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
  4193. + HERMES_RID_CNFDESIREDSSID;
  4194. +
  4195. + err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
  4196. + NULL, &essidbuf);
  4197. + if (err)
  4198. + goto fail_unlock;
  4199. + } else {
  4200. + *active = 0;
  4201. +
  4202. + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
  4203. + sizeof(essidbuf), NULL, &essidbuf);
  4204. + if (err)
  4205. + goto fail_unlock;
  4206. + }
  4207. +
  4208. + len = le16_to_cpu(essidbuf.len);
  4209. + BUG_ON(len > IW_ESSID_MAX_SIZE);
  4210. +
  4211. + memset(buf, 0, IW_ESSID_MAX_SIZE);
  4212. + memcpy(buf, p, len);
  4213. + err = len;
  4214. +
  4215. + fail_unlock:
  4216. + orinoco_unlock(priv, &flags);
  4217. +
  4218. + return err;
  4219. +}
  4220. +
  4221. +int orinoco_hw_get_freq(struct orinoco_private *priv)
  4222. +{
  4223. + struct hermes *hw = &priv->hw;
  4224. + int err = 0;
  4225. + u16 channel;
  4226. + int freq = 0;
  4227. + unsigned long flags;
  4228. +
  4229. + if (orinoco_lock(priv, &flags) != 0)
  4230. + return -EBUSY;
  4231. +
  4232. + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
  4233. + &channel);
  4234. + if (err)
  4235. + goto out;
  4236. +
  4237. + /* Intersil firmware 1.3.5 returns 0 when the interface is down */
  4238. + if (channel == 0) {
  4239. + err = -EBUSY;
  4240. + goto out;
  4241. + }
  4242. +
  4243. + if ((channel < 1) || (channel > NUM_CHANNELS)) {
  4244. + printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
  4245. + priv->ndev->name, channel);
  4246. + err = -EBUSY;
  4247. + goto out;
  4248. +
  4249. + }
  4250. + freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
  4251. +
  4252. + out:
  4253. + orinoco_unlock(priv, &flags);
  4254. +
  4255. + if (err > 0)
  4256. + err = -EBUSY;
  4257. + return err ? err : freq;
  4258. +}
  4259. +
  4260. +int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
  4261. + int *numrates, s32 *rates, int max)
  4262. +{
  4263. + struct hermes *hw = &priv->hw;
  4264. + struct hermes_idstring list;
  4265. + unsigned char *p = (unsigned char *)&list.val;
  4266. + int err = 0;
  4267. + int num;
  4268. + int i;
  4269. + unsigned long flags;
  4270. +
  4271. + if (orinoco_lock(priv, &flags) != 0)
  4272. + return -EBUSY;
  4273. +
  4274. + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
  4275. + sizeof(list), NULL, &list);
  4276. + orinoco_unlock(priv, &flags);
  4277. +
  4278. + if (err)
  4279. + return err;
  4280. +
  4281. + num = le16_to_cpu(list.len);
  4282. + *numrates = num;
  4283. + num = min(num, max);
  4284. +
  4285. + for (i = 0; i < num; i++)
  4286. + rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
  4287. +
  4288. + return 0;
  4289. +}
  4290. +
  4291. +int orinoco_hw_trigger_scan(struct orinoco_private *priv,
  4292. + const struct cfg80211_ssid *ssid)
  4293. +{
  4294. + struct net_device *dev = priv->ndev;
  4295. + struct hermes *hw = &priv->hw;
  4296. + unsigned long flags;
  4297. + int err = 0;
  4298. +
  4299. + if (orinoco_lock(priv, &flags) != 0)
  4300. + return -EBUSY;
  4301. +
  4302. + /* Scanning with port 0 disabled would fail */
  4303. + if (!netif_running(dev)) {
  4304. + err = -ENETDOWN;
  4305. + goto out;
  4306. + }
  4307. +
  4308. + /* In monitor mode, the scan results are always empty.
  4309. + * Probe responses are passed to the driver as received
  4310. + * frames and could be processed in software. */
  4311. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
  4312. + err = -EOPNOTSUPP;
  4313. + goto out;
  4314. + }
  4315. +
  4316. + if (priv->has_hostscan) {
  4317. + switch (priv->firmware_type) {
  4318. + case FIRMWARE_TYPE_SYMBOL:
  4319. + err = hermes_write_wordrec(hw, USER_BAP,
  4320. + HERMES_RID_CNFHOSTSCAN_SYMBOL,
  4321. + HERMES_HOSTSCAN_SYMBOL_ONCE |
  4322. + HERMES_HOSTSCAN_SYMBOL_BCAST);
  4323. + break;
  4324. + case FIRMWARE_TYPE_INTERSIL: {
  4325. + __le16 req[3];
  4326. +
  4327. + req[0] = cpu_to_le16(0x3fff); /* All channels */
  4328. + req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
  4329. + req[2] = 0; /* Any ESSID */
  4330. + err = HERMES_WRITE_RECORD(hw, USER_BAP,
  4331. + HERMES_RID_CNFHOSTSCAN, &req);
  4332. + break;
  4333. + }
  4334. + case FIRMWARE_TYPE_AGERE:
  4335. + if (ssid->ssid_len > 0) {
  4336. + struct hermes_idstring idbuf;
  4337. + size_t len = ssid->ssid_len;
  4338. +
  4339. + idbuf.len = cpu_to_le16(len);
  4340. + memcpy(idbuf.val, ssid->ssid, len);
  4341. +
  4342. + err = hw->ops->write_ltv(hw, USER_BAP,
  4343. + HERMES_RID_CNFSCANSSID_AGERE,
  4344. + HERMES_BYTES_TO_RECLEN(len + 2),
  4345. + &idbuf);
  4346. + } else
  4347. + err = hermes_write_wordrec(hw, USER_BAP,
  4348. + HERMES_RID_CNFSCANSSID_AGERE,
  4349. + 0); /* Any ESSID */
  4350. + if (err)
  4351. + break;
  4352. +
  4353. + if (priv->has_ext_scan) {
  4354. + err = hermes_write_wordrec(hw, USER_BAP,
  4355. + HERMES_RID_CNFSCANCHANNELS2GHZ,
  4356. + 0x7FFF);
  4357. + if (err)
  4358. + goto out;
  4359. +
  4360. + err = hermes_inquire(hw,
  4361. + HERMES_INQ_CHANNELINFO);
  4362. + } else
  4363. + err = hermes_inquire(hw, HERMES_INQ_SCAN);
  4364. +
  4365. + break;
  4366. + }
  4367. + } else
  4368. + err = hermes_inquire(hw, HERMES_INQ_SCAN);
  4369. +
  4370. + out:
  4371. + orinoco_unlock(priv, &flags);
  4372. +
  4373. + return err;
  4374. +}
  4375. +
  4376. +/* Disassociate from node with BSSID addr */
  4377. +int orinoco_hw_disassociate(struct orinoco_private *priv,
  4378. + u8 *addr, u16 reason_code)
  4379. +{
  4380. + struct hermes *hw = &priv->hw;
  4381. + int err;
  4382. +
  4383. + struct {
  4384. + u8 addr[ETH_ALEN];
  4385. + __le16 reason_code;
  4386. + } __packed buf;
  4387. +
  4388. + /* Currently only supported by WPA enabled Agere fw */
  4389. + if (!priv->has_wpa)
  4390. + return -EOPNOTSUPP;
  4391. +
  4392. + memcpy(buf.addr, addr, ETH_ALEN);
  4393. + buf.reason_code = cpu_to_le16(reason_code);
  4394. + err = HERMES_WRITE_RECORD(hw, USER_BAP,
  4395. + HERMES_RID_CNFDISASSOCIATE,
  4396. + &buf);
  4397. + return err;
  4398. +}
  4399. +
  4400. +int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
  4401. + u8 *addr)
  4402. +{
  4403. + struct hermes *hw = &priv->hw;
  4404. + int err;
  4405. +
  4406. + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
  4407. + ETH_ALEN, NULL, addr);
  4408. +
  4409. + return err;
  4410. +}
  4411. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hw.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/hw.h
  4412. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/hw.h 1970-01-01 01:00:00.000000000 +0100
  4413. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/hw.h 2025-08-03 15:01:59.341130868 +0200
  4414. @@ -0,0 +1,60 @@
  4415. +/* Encapsulate basic setting changes on Hermes hardware
  4416. + *
  4417. + * See copyright notice in main.c
  4418. + */
  4419. +#ifndef _ORINOCO_HW_H_
  4420. +#define _ORINOCO_HW_H_
  4421. +
  4422. +#include <linux/types.h>
  4423. +#include <linux/wireless.h>
  4424. +#include <net/cfg80211.h>
  4425. +
  4426. +/* Hardware BAPs */
  4427. +#define USER_BAP 0
  4428. +#define IRQ_BAP 1
  4429. +
  4430. +/* WEP key sizes */
  4431. +#define SMALL_KEY_SIZE 5
  4432. +#define LARGE_KEY_SIZE 13
  4433. +
  4434. +/* Number of supported channels */
  4435. +#define NUM_CHANNELS 14
  4436. +
  4437. +/* Forward declarations */
  4438. +struct orinoco_private;
  4439. +
  4440. +int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name,
  4441. + size_t fw_name_len, u32 *hw_ver);
  4442. +int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr);
  4443. +int orinoco_hw_allocate_fid(struct orinoco_private *priv);
  4444. +int orinoco_get_bitratemode(int bitrate, int automatic);
  4445. +void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic);
  4446. +
  4447. +int orinoco_hw_program_rids(struct orinoco_private *priv);
  4448. +int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc);
  4449. +int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
  4450. +int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate);
  4451. +int __orinoco_hw_set_wap(struct orinoco_private *priv);
  4452. +int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
  4453. +int __orinoco_hw_setup_enc(struct orinoco_private *priv);
  4454. +int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
  4455. + int set_tx, const u8 *key, size_t key_len,
  4456. + const u8 *rsc, size_t rsc_len,
  4457. + const u8 *tsc, size_t tsc_len);
  4458. +int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
  4459. +int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
  4460. + struct net_device *dev,
  4461. + int mc_count, int promisc);
  4462. +int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
  4463. + char buf[IW_ESSID_MAX_SIZE + 1]);
  4464. +int orinoco_hw_get_freq(struct orinoco_private *priv);
  4465. +int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
  4466. + int *numrates, s32 *rates, int max);
  4467. +int orinoco_hw_trigger_scan(struct orinoco_private *priv,
  4468. + const struct cfg80211_ssid *ssid);
  4469. +int orinoco_hw_disassociate(struct orinoco_private *priv,
  4470. + u8 *addr, u16 reason_code);
  4471. +int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
  4472. + u8 *addr);
  4473. +
  4474. +#endif /* _ORINOCO_HW_H_ */
  4475. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/Kconfig linux-6.15.6/drivers/net/wireless/intersil/orinoco/Kconfig
  4476. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/Kconfig 1970-01-01 01:00:00.000000000 +0100
  4477. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/Kconfig 2025-08-03 15:01:59.341130868 +0200
  4478. @@ -0,0 +1,143 @@
  4479. +# SPDX-License-Identifier: GPL-2.0-only
  4480. +config HERMES
  4481. + tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
  4482. + depends on (PPC_PMAC || PCI || PCMCIA)
  4483. + depends on CFG80211
  4484. + select CFG80211_WEXT_EXPORT
  4485. + select WIRELESS_EXT
  4486. + select WEXT_SPY
  4487. + select WEXT_PRIV
  4488. + select FW_LOADER
  4489. + select CRYPTO
  4490. + select CRYPTO_MICHAEL_MIC
  4491. + help
  4492. + A driver for 802.11b wireless cards based on the "Hermes" or
  4493. + Intersil HFA384x (Prism 2) MAC controller. This includes the vast
  4494. + majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
  4495. + - except for the Cisco/Aironet cards. Cards supported include the
  4496. + Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
  4497. + Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
  4498. + IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
  4499. + MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
  4500. + IPW2011, and Symbol Spectrum24 High Rate amongst others.
  4501. +
  4502. + This option includes the guts of the driver, but in order to
  4503. + actually use a card you will also need to enable support for PCMCIA
  4504. + Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
  4505. +
  4506. + You will also very likely also need the Wireless Tools in order to
  4507. + configure your card and that /etc/pcmcia/wireless.opts works :
  4508. + <https://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
  4509. +
  4510. +config HERMES_PRISM
  4511. + bool "Support Prism 2/2.5 chipset"
  4512. + depends on HERMES
  4513. + help
  4514. +
  4515. + Say Y to enable support for Prism 2 and 2.5 chipsets. These
  4516. + chipsets are better handled by the hostap driver. This driver
  4517. + would not support WPA or firmware download for Prism chipset.
  4518. +
  4519. + If you are not sure, say N.
  4520. +
  4521. +config HERMES_CACHE_FW_ON_INIT
  4522. + bool "Cache Hermes firmware on driver initialisation"
  4523. + depends on HERMES
  4524. + default y
  4525. + help
  4526. + Say Y to cache any firmware required by the Hermes drivers
  4527. + on startup. The firmware will remain cached until the
  4528. + driver is unloaded. The cache uses 64K of RAM.
  4529. +
  4530. + Otherwise load the firmware from userspace as required. In
  4531. + this case the driver should be unloaded and restarted
  4532. + whenever the firmware is changed.
  4533. +
  4534. + If you are not sure, say Y.
  4535. +
  4536. +config APPLE_AIRPORT
  4537. + tristate "Apple Airport support (built-in)"
  4538. + depends on PPC_PMAC && HERMES
  4539. + help
  4540. + Say Y here to support the Airport 802.11b wireless Ethernet hardware
  4541. + built into the Macintosh iBook and other recent PowerPC-based
  4542. + Macintosh machines. This is essentially a Lucent Orinoco card with
  4543. + a non-standard interface.
  4544. +
  4545. + This driver does not support the Airport Extreme (802.11b/g). Use
  4546. + the BCM43xx driver for Airport Extreme cards.
  4547. +
  4548. +config PLX_HERMES
  4549. + tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
  4550. + depends on PCI && HERMES
  4551. + help
  4552. + Enable support for PCMCIA cards supported by the "Hermes" (aka
  4553. + orinoco) driver when used in PLX9052 based PCI adaptors. These
  4554. + adaptors are not a full PCMCIA controller but act as a more limited
  4555. + PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
  4556. + 802.11b PCMCIA cards can be used in desktop machines. The Netgear
  4557. + MA301 is such an adaptor.
  4558. +
  4559. +config TMD_HERMES
  4560. + tristate "Hermes in TMD7160 based PCI adaptor support"
  4561. + depends on PCI && HERMES
  4562. + help
  4563. + Enable support for PCMCIA cards supported by the "Hermes" (aka
  4564. + orinoco) driver when used in TMD7160 based PCI adaptors. These
  4565. + adaptors are not a full PCMCIA controller but act as a more limited
  4566. + PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
  4567. + 802.11b PCMCIA cards can be used in desktop machines.
  4568. +
  4569. +config NORTEL_HERMES
  4570. + tristate "Nortel emobility PCI adaptor support"
  4571. + depends on PCI && HERMES
  4572. + help
  4573. + Enable support for PCMCIA cards supported by the "Hermes" (aka
  4574. + orinoco) driver when used in Nortel emobility PCI adaptors. These
  4575. + adaptors are not full PCMCIA controllers, but act as a more limited
  4576. + PCI <-> PCMCIA bridge.
  4577. +
  4578. +config PCI_HERMES
  4579. + tristate "Prism 2.5 PCI 802.11b adaptor support"
  4580. + depends on PCI && HERMES && HERMES_PRISM
  4581. + help
  4582. + Enable support for PCI and mini-PCI 802.11b wireless NICs based on
  4583. + the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
  4584. + PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
  4585. + common. Some of the built-in wireless adaptors in laptops are of
  4586. + this variety.
  4587. +
  4588. +config PCMCIA_HERMES
  4589. + tristate "Hermes PCMCIA card support"
  4590. + depends on PCMCIA && HERMES && HAS_IOPORT_MAP
  4591. + help
  4592. + A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  4593. + as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
  4594. + EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
  4595. + others). It should also be usable on various Prism II based cards
  4596. + such as the Linksys, D-Link and Farallon Skyline. It should also
  4597. + work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
  4598. +
  4599. + You will very likely need the Wireless Tools in order to
  4600. + configure your card and that /etc/pcmcia/wireless.opts works:
  4601. + <https://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
  4602. +
  4603. +config PCMCIA_SPECTRUM
  4604. + tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
  4605. + depends on PCMCIA && HERMES && HAS_IOPORT_MAP
  4606. + help
  4607. +
  4608. + This is a driver for 802.11b cards using RAM-loadable Symbol
  4609. + firmware, such as Symbol Wireless Networker LA4100, CompactFlash
  4610. + cards by Socket Communications and Intel PRO/Wireless 2011B.
  4611. +
  4612. + This driver requires firmware download on startup. Utilities
  4613. + for downloading Symbol firmware are available at
  4614. + <http://sourceforge.net/projects/orinoco/>
  4615. +
  4616. +config ORINOCO_USB
  4617. + tristate "Agere Orinoco USB support"
  4618. + depends on USB && HERMES
  4619. + select FW_LOADER
  4620. + help
  4621. + This driver is for USB versions of the Agere Orinoco card.
  4622. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/main.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/main.c
  4623. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/main.c 1970-01-01 01:00:00.000000000 +0100
  4624. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/main.c 2025-08-03 16:31:03.372980267 +0200
  4625. @@ -0,0 +1,2414 @@
  4626. +/* main.c - (formerly known as dldwd_cs.c, orinoco_cs.c and orinoco.c)
  4627. + *
  4628. + * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
  4629. + * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
  4630. + *
  4631. + * Current maintainers (as of 29 September 2003) are:
  4632. + * Pavel Roskin <proski AT gnu.org>
  4633. + * and David Gibson <hermes AT gibson.dropbear.id.au>
  4634. + *
  4635. + * (C) Copyright David Gibson, IBM Corporation 2001-2003.
  4636. + * Copyright (C) 2000 David Gibson, Linuxcare Australia.
  4637. + * With some help from :
  4638. + * Copyright (C) 2001 Jean Tourrilhes, HP Labs
  4639. + * Copyright (C) 2001 Benjamin Herrenschmidt
  4640. + *
  4641. + * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
  4642. + *
  4643. + * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
  4644. + * AT fasta.fh-dortmund.de>
  4645. + * http://www.stud.fh-dortmund.de/~andy/wvlan/
  4646. + *
  4647. + * The contents of this file are subject to the Mozilla Public License
  4648. + * Version 1.1 (the "License"); you may not use this file except in
  4649. + * compliance with the License. You may obtain a copy of the License
  4650. + * at http://www.mozilla.org/MPL/
  4651. + *
  4652. + * Software distributed under the License is distributed on an "AS IS"
  4653. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  4654. + * the License for the specific language governing rights and
  4655. + * limitations under the License.
  4656. + *
  4657. + * The initial developer of the original code is David A. Hinds
  4658. + * <dahinds AT users.sourceforge.net>. Portions created by David
  4659. + * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
  4660. + * Reserved.
  4661. + *
  4662. + * Alternatively, the contents of this file may be used under the
  4663. + * terms of the GNU General Public License version 2 (the "GPL"), in
  4664. + * which case the provisions of the GPL are applicable instead of the
  4665. + * above. If you wish to allow the use of your version of this file
  4666. + * only under the terms of the GPL and not to allow others to use your
  4667. + * version of this file under the MPL, indicate your decision by
  4668. + * deleting the provisions above and replace them with the notice and
  4669. + * other provisions required by the GPL. If you do not delete the
  4670. + * provisions above, a recipient may use your version of this file
  4671. + * under either the MPL or the GPL. */
  4672. +
  4673. +/*
  4674. + * TODO
  4675. + * o Handle de-encapsulation within network layer, provide 802.11
  4676. + * headers (patch from Thomas 'Dent' Mirlacher)
  4677. + * o Fix possible races in SPY handling.
  4678. + * o Disconnect wireless extensions from fundamental configuration.
  4679. + * o (maybe) Software WEP support (patch from Stano Meduna).
  4680. + * o (maybe) Use multiple Tx buffers - driver handling queue
  4681. + * rather than firmware.
  4682. + */
  4683. +
  4684. +/* Locking and synchronization:
  4685. + *
  4686. + * The basic principle is that everything is serialized through a
  4687. + * single spinlock, priv->lock. The lock is used in user, bh and irq
  4688. + * context, so when taken outside hardirq context it should always be
  4689. + * taken with interrupts disabled. The lock protects both the
  4690. + * hardware and the struct orinoco_private.
  4691. + *
  4692. + * Another flag, priv->hw_unavailable indicates that the hardware is
  4693. + * unavailable for an extended period of time (e.g. suspended, or in
  4694. + * the middle of a hard reset). This flag is protected by the
  4695. + * spinlock. All code which touches the hardware should check the
  4696. + * flag after taking the lock, and if it is set, give up on whatever
  4697. + * they are doing and drop the lock again. The orinoco_lock()
  4698. + * function handles this (it unlocks and returns -EBUSY if
  4699. + * hw_unavailable is non-zero).
  4700. + */
  4701. +
  4702. +#define DRIVER_NAME "orinoco"
  4703. +
  4704. +#include <linux/module.h>
  4705. +#include <linux/kernel.h>
  4706. +#include <linux/slab.h>
  4707. +#include <linux/init.h>
  4708. +#include <linux/delay.h>
  4709. +#include <linux/device.h>
  4710. +#include <linux/netdevice.h>
  4711. +#include <linux/etherdevice.h>
  4712. +#include <linux/suspend.h>
  4713. +#include <linux/if_arp.h>
  4714. +#include <linux/wireless.h>
  4715. +#include <linux/ieee80211.h>
  4716. +#include <net/iw_handler.h>
  4717. +#include <net/cfg80211.h>
  4718. +
  4719. +#include "hermes_rid.h"
  4720. +#include "hermes_dld.h"
  4721. +#include "hw.h"
  4722. +#include "scan.h"
  4723. +#include "mic.h"
  4724. +#include "fw.h"
  4725. +#include "wext.h"
  4726. +#include "cfg.h"
  4727. +#include "main.h"
  4728. +
  4729. +#include "orinoco.h"
  4730. +
  4731. +/********************************************************************/
  4732. +/* Module information */
  4733. +/********************************************************************/
  4734. +
  4735. +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & "
  4736. + "David Gibson <hermes@gibson.dropbear.id.au>");
  4737. +MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based "
  4738. + "and similar wireless cards");
  4739. +MODULE_LICENSE("Dual MPL/GPL");
  4740. +
  4741. +/* Level of debugging. Used in the macros in orinoco.h */
  4742. +#ifdef ORINOCO_DEBUG
  4743. +int orinoco_debug = ORINOCO_DEBUG;
  4744. +EXPORT_SYMBOL(orinoco_debug);
  4745. +module_param(orinoco_debug, int, 0644);
  4746. +MODULE_PARM_DESC(orinoco_debug, "Debug level");
  4747. +#endif
  4748. +
  4749. +static bool suppress_linkstatus; /* = 0 */
  4750. +module_param(suppress_linkstatus, bool, 0644);
  4751. +MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
  4752. +
  4753. +static int ignore_disconnect; /* = 0 */
  4754. +module_param(ignore_disconnect, int, 0644);
  4755. +MODULE_PARM_DESC(ignore_disconnect,
  4756. + "Don't report lost link to the network layer");
  4757. +
  4758. +int force_monitor; /* = 0 */
  4759. +module_param(force_monitor, int, 0644);
  4760. +MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
  4761. +
  4762. +/********************************************************************/
  4763. +/* Internal constants */
  4764. +/********************************************************************/
  4765. +
  4766. +/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
  4767. +static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
  4768. +#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
  4769. +
  4770. +#define ORINOCO_MIN_MTU 256
  4771. +#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
  4772. +
  4773. +#define MAX_IRQLOOPS_PER_IRQ 10
  4774. +#define MAX_IRQLOOPS_PER_JIFFY (20000 / HZ) /* Based on a guestimate of
  4775. + * how many events the
  4776. + * device could
  4777. + * legitimately generate */
  4778. +
  4779. +#define DUMMY_FID 0xFFFF
  4780. +
  4781. +/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
  4782. + HERMES_MAX_MULTICAST : 0)*/
  4783. +#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
  4784. +
  4785. +#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
  4786. + | HERMES_EV_TX | HERMES_EV_TXEXC \
  4787. + | HERMES_EV_WTERR | HERMES_EV_INFO \
  4788. + | HERMES_EV_INFDROP)
  4789. +
  4790. +/********************************************************************/
  4791. +/* Data types */
  4792. +/********************************************************************/
  4793. +
  4794. +/* Beginning of the Tx descriptor, used in TxExc handling */
  4795. +struct hermes_txexc_data {
  4796. + struct hermes_tx_descriptor desc;
  4797. + __le16 frame_ctl;
  4798. + __le16 duration_id;
  4799. + u8 addr1[ETH_ALEN];
  4800. +} __packed;
  4801. +
  4802. +/* Rx frame header except compatibility 802.3 header */
  4803. +struct hermes_rx_descriptor {
  4804. + /* Control */
  4805. + __le16 status;
  4806. + __le32 time;
  4807. + u8 silence;
  4808. + u8 signal;
  4809. + u8 rate;
  4810. + u8 rxflow;
  4811. + __le32 reserved;
  4812. +
  4813. + /* 802.11 header */
  4814. + __le16 frame_ctl;
  4815. + __le16 duration_id;
  4816. + u8 addr1[ETH_ALEN];
  4817. + u8 addr2[ETH_ALEN];
  4818. + u8 addr3[ETH_ALEN];
  4819. + __le16 seq_ctl;
  4820. + u8 addr4[ETH_ALEN];
  4821. +
  4822. + /* Data length */
  4823. + __le16 data_len;
  4824. +} __packed;
  4825. +
  4826. +struct orinoco_rx_data {
  4827. + struct hermes_rx_descriptor *desc;
  4828. + struct sk_buff *skb;
  4829. + struct list_head list;
  4830. +};
  4831. +
  4832. +struct orinoco_scan_data {
  4833. + void *buf;
  4834. + size_t len;
  4835. + int type;
  4836. + struct list_head list;
  4837. +};
  4838. +
  4839. +/********************************************************************/
  4840. +/* Function prototypes */
  4841. +/********************************************************************/
  4842. +
  4843. +static int __orinoco_set_multicast_list(struct net_device *dev);
  4844. +static int __orinoco_up(struct orinoco_private *priv);
  4845. +static int __orinoco_down(struct orinoco_private *priv);
  4846. +static int __orinoco_commit(struct orinoco_private *priv);
  4847. +
  4848. +/********************************************************************/
  4849. +/* Internal helper functions */
  4850. +/********************************************************************/
  4851. +
  4852. +void set_port_type(struct orinoco_private *priv)
  4853. +{
  4854. + switch (priv->iw_mode) {
  4855. + case NL80211_IFTYPE_STATION:
  4856. + priv->port_type = 1;
  4857. + priv->createibss = 0;
  4858. + break;
  4859. + case NL80211_IFTYPE_ADHOC:
  4860. + if (priv->prefer_port3) {
  4861. + priv->port_type = 3;
  4862. + priv->createibss = 0;
  4863. + } else {
  4864. + priv->port_type = priv->ibss_port;
  4865. + priv->createibss = 1;
  4866. + }
  4867. + break;
  4868. + case NL80211_IFTYPE_MONITOR:
  4869. + priv->port_type = 3;
  4870. + priv->createibss = 0;
  4871. + break;
  4872. + default:
  4873. + printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
  4874. + priv->ndev->name);
  4875. + }
  4876. +}
  4877. +
  4878. +/********************************************************************/
  4879. +/* Device methods */
  4880. +/********************************************************************/
  4881. +
  4882. +int orinoco_open(struct net_device *dev)
  4883. +{
  4884. + struct orinoco_private *priv = ndev_priv(dev);
  4885. + unsigned long flags;
  4886. + int err;
  4887. +
  4888. + if (orinoco_lock(priv, &flags) != 0)
  4889. + return -EBUSY;
  4890. +
  4891. + err = __orinoco_up(priv);
  4892. +
  4893. + if (!err)
  4894. + priv->open = 1;
  4895. +
  4896. + orinoco_unlock(priv, &flags);
  4897. +
  4898. + return err;
  4899. +}
  4900. +EXPORT_SYMBOL(orinoco_open);
  4901. +
  4902. +int orinoco_stop(struct net_device *dev)
  4903. +{
  4904. + struct orinoco_private *priv = ndev_priv(dev);
  4905. + int err = 0;
  4906. +
  4907. + /* We mustn't use orinoco_lock() here, because we need to be
  4908. + able to close the interface even if hw_unavailable is set
  4909. + (e.g. as we're released after a PC Card removal) */
  4910. + orinoco_lock_irq(priv);
  4911. +
  4912. + priv->open = 0;
  4913. +
  4914. + err = __orinoco_down(priv);
  4915. +
  4916. + orinoco_unlock_irq(priv);
  4917. +
  4918. + return err;
  4919. +}
  4920. +EXPORT_SYMBOL(orinoco_stop);
  4921. +
  4922. +void orinoco_set_multicast_list(struct net_device *dev)
  4923. +{
  4924. + struct orinoco_private *priv = ndev_priv(dev);
  4925. + unsigned long flags;
  4926. +
  4927. + if (orinoco_lock(priv, &flags) != 0) {
  4928. + printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
  4929. + "called when hw_unavailable\n", dev->name);
  4930. + return;
  4931. + }
  4932. +
  4933. + __orinoco_set_multicast_list(dev);
  4934. + orinoco_unlock(priv, &flags);
  4935. +}
  4936. +EXPORT_SYMBOL(orinoco_set_multicast_list);
  4937. +
  4938. +int orinoco_change_mtu(struct net_device *dev, int new_mtu)
  4939. +{
  4940. + struct orinoco_private *priv = ndev_priv(dev);
  4941. +
  4942. + /* MTU + encapsulation + header length */
  4943. + if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
  4944. + (priv->nicbuf_size - ETH_HLEN))
  4945. + return -EINVAL;
  4946. +
  4947. + dev->mtu = new_mtu;
  4948. +
  4949. + return 0;
  4950. +}
  4951. +EXPORT_SYMBOL(orinoco_change_mtu);
  4952. +
  4953. +/********************************************************************/
  4954. +/* Tx path */
  4955. +/********************************************************************/
  4956. +
  4957. +/* Add encapsulation and MIC to the existing SKB.
  4958. + * The main xmit routine will then send the whole lot to the card.
  4959. + * Need 8 bytes headroom
  4960. + * Need 8 bytes tailroom
  4961. + *
  4962. + * With encapsulated ethernet II frame
  4963. + * --------
  4964. + * 803.3 header (14 bytes)
  4965. + * dst[6]
  4966. + * -------- src[6]
  4967. + * 803.3 header (14 bytes) len[2]
  4968. + * dst[6] 803.2 header (8 bytes)
  4969. + * src[6] encaps[6]
  4970. + * len[2] <- leave alone -> len[2]
  4971. + * -------- -------- <-- 0
  4972. + * Payload Payload
  4973. + * ... ...
  4974. + *
  4975. + * -------- --------
  4976. + * MIC (8 bytes)
  4977. + * --------
  4978. + *
  4979. + * returns 0 on success, -ENOMEM on error.
  4980. + */
  4981. +int orinoco_process_xmit_skb(struct sk_buff *skb,
  4982. + struct net_device *dev,
  4983. + struct orinoco_private *priv,
  4984. + int *tx_control,
  4985. + u8 *mic_buf)
  4986. +{
  4987. + struct orinoco_tkip_key *key;
  4988. + struct ethhdr *eh;
  4989. + int do_mic;
  4990. +
  4991. + key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
  4992. +
  4993. + do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
  4994. + (key != NULL));
  4995. +
  4996. + if (do_mic)
  4997. + *tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
  4998. + HERMES_TXCTRL_MIC;
  4999. +
  5000. + eh = (struct ethhdr *)skb->data;
  5001. +
  5002. + /* Encapsulate Ethernet-II frames */
  5003. + if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
  5004. + struct header_struct {
  5005. + struct ethhdr eth; /* 802.3 header */
  5006. + u8 encap[6]; /* 802.2 header */
  5007. + } __packed hdr;
  5008. + int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN);
  5009. +
  5010. + if (skb_headroom(skb) < ENCAPS_OVERHEAD) {
  5011. + if (net_ratelimit())
  5012. + printk(KERN_ERR
  5013. + "%s: Not enough headroom for 802.2 headers %d\n",
  5014. + dev->name, skb_headroom(skb));
  5015. + return -ENOMEM;
  5016. + }
  5017. +
  5018. + /* Fill in new header */
  5019. + memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
  5020. + hdr.eth.h_proto = htons(len);
  5021. + memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
  5022. +
  5023. + /* Make room for the new header, and copy it in */
  5024. + eh = skb_push(skb, ENCAPS_OVERHEAD);
  5025. + memcpy(eh, &hdr, sizeof(hdr));
  5026. + }
  5027. +
  5028. + /* Calculate Michael MIC */
  5029. + if (do_mic) {
  5030. + size_t len = skb->len - ETH_HLEN;
  5031. + u8 *mic = &mic_buf[0];
  5032. +
  5033. + /* Have to write to an even address, so copy the spare
  5034. + * byte across */
  5035. + if (skb->len % 2) {
  5036. + *mic = skb->data[skb->len - 1];
  5037. + mic++;
  5038. + }
  5039. +
  5040. + orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
  5041. + eh->h_dest, eh->h_source, 0 /* priority */,
  5042. + skb->data + ETH_HLEN,
  5043. + len, mic);
  5044. + }
  5045. +
  5046. + return 0;
  5047. +}
  5048. +EXPORT_SYMBOL(orinoco_process_xmit_skb);
  5049. +
  5050. +static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
  5051. +{
  5052. + struct orinoco_private *priv = ndev_priv(dev);
  5053. + struct net_device_stats *stats = &dev->stats;
  5054. + struct hermes *hw = &priv->hw;
  5055. + int err = 0;
  5056. + u16 txfid = priv->txfid;
  5057. + int tx_control;
  5058. + unsigned long flags;
  5059. + u8 mic_buf[MICHAEL_MIC_LEN + 1];
  5060. +
  5061. + if (!netif_running(dev)) {
  5062. + printk(KERN_ERR "%s: Tx on stopped device!\n",
  5063. + dev->name);
  5064. + return NETDEV_TX_BUSY;
  5065. + }
  5066. +
  5067. + if (netif_queue_stopped(dev)) {
  5068. + printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
  5069. + dev->name);
  5070. + return NETDEV_TX_BUSY;
  5071. + }
  5072. +
  5073. + if (orinoco_lock(priv, &flags) != 0) {
  5074. + printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
  5075. + dev->name);
  5076. + return NETDEV_TX_BUSY;
  5077. + }
  5078. +
  5079. + if (!netif_carrier_ok(dev) ||
  5080. + (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
  5081. + /* Oops, the firmware hasn't established a connection,
  5082. + silently drop the packet (this seems to be the
  5083. + safest approach). */
  5084. + goto drop;
  5085. + }
  5086. +
  5087. + /* Check packet length */
  5088. + if (skb->len < ETH_HLEN)
  5089. + goto drop;
  5090. +
  5091. + tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
  5092. +
  5093. + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
  5094. + &mic_buf[0]);
  5095. + if (err)
  5096. + goto drop;
  5097. +
  5098. + if (priv->has_alt_txcntl) {
  5099. + /* WPA enabled firmwares have tx_cntl at the end of
  5100. + * the 802.11 header. So write zeroed descriptor and
  5101. + * 802.11 header at the same time
  5102. + */
  5103. + char desc[HERMES_802_3_OFFSET];
  5104. + __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET];
  5105. +
  5106. + memset(&desc, 0, sizeof(desc));
  5107. +
  5108. + *txcntl = cpu_to_le16(tx_control);
  5109. + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
  5110. + txfid, 0);
  5111. + if (err) {
  5112. + if (net_ratelimit())
  5113. + printk(KERN_ERR "%s: Error %d writing Tx "
  5114. + "descriptor to BAP\n", dev->name, err);
  5115. + goto busy;
  5116. + }
  5117. + } else {
  5118. + struct hermes_tx_descriptor desc;
  5119. +
  5120. + memset(&desc, 0, sizeof(desc));
  5121. +
  5122. + desc.tx_control = cpu_to_le16(tx_control);
  5123. + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
  5124. + txfid, 0);
  5125. + if (err) {
  5126. + if (net_ratelimit())
  5127. + printk(KERN_ERR "%s: Error %d writing Tx "
  5128. + "descriptor to BAP\n", dev->name, err);
  5129. + goto busy;
  5130. + }
  5131. +
  5132. + /* Clear the 802.11 header and data length fields - some
  5133. + * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
  5134. + * if this isn't done. */
  5135. + hermes_clear_words(hw, HERMES_DATA0,
  5136. + HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
  5137. + }
  5138. +
  5139. + err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len,
  5140. + txfid, HERMES_802_3_OFFSET);
  5141. + if (err) {
  5142. + printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
  5143. + dev->name, err);
  5144. + goto busy;
  5145. + }
  5146. +
  5147. + if (tx_control & HERMES_TXCTRL_MIC) {
  5148. + size_t offset = HERMES_802_3_OFFSET + skb->len;
  5149. + size_t len = MICHAEL_MIC_LEN;
  5150. +
  5151. + if (offset % 2) {
  5152. + offset--;
  5153. + len++;
  5154. + }
  5155. + err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
  5156. + txfid, offset);
  5157. + if (err) {
  5158. + printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
  5159. + dev->name, err);
  5160. + goto busy;
  5161. + }
  5162. + }
  5163. +
  5164. + /* Finally, we actually initiate the send */
  5165. + netif_stop_queue(dev);
  5166. +
  5167. + err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
  5168. + txfid, NULL);
  5169. + if (err) {
  5170. + netif_start_queue(dev);
  5171. + if (net_ratelimit())
  5172. + printk(KERN_ERR "%s: Error %d transmitting packet\n",
  5173. + dev->name, err);
  5174. + goto busy;
  5175. + }
  5176. +
  5177. + stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
  5178. + goto ok;
  5179. +
  5180. + drop:
  5181. + stats->tx_errors++;
  5182. + stats->tx_dropped++;
  5183. +
  5184. + ok:
  5185. + orinoco_unlock(priv, &flags);
  5186. + dev_kfree_skb(skb);
  5187. + return NETDEV_TX_OK;
  5188. +
  5189. + busy:
  5190. + if (err == -EIO)
  5191. + schedule_work(&priv->reset_work);
  5192. + orinoco_unlock(priv, &flags);
  5193. + return NETDEV_TX_BUSY;
  5194. +}
  5195. +
  5196. +static void __orinoco_ev_alloc(struct net_device *dev, struct hermes *hw)
  5197. +{
  5198. + struct orinoco_private *priv = ndev_priv(dev);
  5199. + u16 fid = hermes_read_regn(hw, ALLOCFID);
  5200. +
  5201. + if (fid != priv->txfid) {
  5202. + if (fid != DUMMY_FID)
  5203. + printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
  5204. + dev->name, fid);
  5205. + return;
  5206. + }
  5207. +
  5208. + hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
  5209. +}
  5210. +
  5211. +static void __orinoco_ev_tx(struct net_device *dev, struct hermes *hw)
  5212. +{
  5213. + dev->stats.tx_packets++;
  5214. +
  5215. + netif_wake_queue(dev);
  5216. +
  5217. + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
  5218. +}
  5219. +
  5220. +static void __orinoco_ev_txexc(struct net_device *dev, struct hermes *hw)
  5221. +{
  5222. + struct net_device_stats *stats = &dev->stats;
  5223. + u16 fid = hermes_read_regn(hw, TXCOMPLFID);
  5224. + u16 status;
  5225. + struct hermes_txexc_data hdr;
  5226. + int err = 0;
  5227. +
  5228. + if (fid == DUMMY_FID)
  5229. + return; /* Nothing's really happened */
  5230. +
  5231. + /* Read part of the frame header - we need status and addr1 */
  5232. + err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr,
  5233. + sizeof(struct hermes_txexc_data),
  5234. + fid, 0);
  5235. +
  5236. + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
  5237. + stats->tx_errors++;
  5238. +
  5239. + if (err) {
  5240. + printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
  5241. + "(FID=%04X error %d)\n",
  5242. + dev->name, fid, err);
  5243. + return;
  5244. + }
  5245. +
  5246. + DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
  5247. + err, fid);
  5248. +
  5249. + /* We produce a TXDROP event only for retry or lifetime
  5250. + * exceeded, because that's the only status that really mean
  5251. + * that this particular node went away.
  5252. + * Other errors means that *we* screwed up. - Jean II */
  5253. + status = le16_to_cpu(hdr.desc.status);
  5254. + if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
  5255. + union iwreq_data wrqu;
  5256. +
  5257. + /* Copy 802.11 dest address.
  5258. + * We use the 802.11 header because the frame may
  5259. + * not be 802.3 or may be mangled...
  5260. + * In Ad-Hoc mode, it will be the node address.
  5261. + * In managed mode, it will be most likely the AP addr
  5262. + * User space will figure out how to convert it to
  5263. + * whatever it needs (IP address or else).
  5264. + * - Jean II */
  5265. + memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
  5266. + wrqu.addr.sa_family = ARPHRD_ETHER;
  5267. +
  5268. + /* Send event to user space */
  5269. + wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
  5270. + }
  5271. +
  5272. + netif_wake_queue(dev);
  5273. +}
  5274. +
  5275. +void orinoco_tx_timeout(struct net_device *dev, unsigned int txqueue)
  5276. +{
  5277. + struct orinoco_private *priv = ndev_priv(dev);
  5278. + struct net_device_stats *stats = &dev->stats;
  5279. + struct hermes *hw = &priv->hw;
  5280. +
  5281. + printk(KERN_WARNING "%s: Tx timeout! "
  5282. + "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
  5283. + dev->name, hermes_read_regn(hw, ALLOCFID),
  5284. + hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
  5285. +
  5286. + stats->tx_errors++;
  5287. +
  5288. + schedule_work(&priv->reset_work);
  5289. +}
  5290. +EXPORT_SYMBOL(orinoco_tx_timeout);
  5291. +
  5292. +/********************************************************************/
  5293. +/* Rx path (data frames) */
  5294. +/********************************************************************/
  5295. +
  5296. +/* Does the frame have a SNAP header indicating it should be
  5297. + * de-encapsulated to Ethernet-II? */
  5298. +static inline int is_ethersnap(void *_hdr)
  5299. +{
  5300. + u8 *hdr = _hdr;
  5301. +
  5302. + /* We de-encapsulate all packets which, a) have SNAP headers
  5303. + * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
  5304. + * and where b) the OUI of the SNAP header is 00:00:00 or
  5305. + * 00:00:f8 - we need both because different APs appear to use
  5306. + * different OUIs for some reason */
  5307. + return (memcmp(hdr, &encaps_hdr, 5) == 0)
  5308. + && ((hdr[5] == 0x00) || (hdr[5] == 0xf8));
  5309. +}
  5310. +
  5311. +static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
  5312. + int level, int noise)
  5313. +{
  5314. + struct iw_quality wstats;
  5315. + wstats.level = level - 0x95;
  5316. + wstats.noise = noise - 0x95;
  5317. + wstats.qual = (level > noise) ? (level - noise) : 0;
  5318. + wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
  5319. + /* Update spy records */
  5320. + //wireless_spy_update(dev, mac, &wstats);
  5321. +}
  5322. +
  5323. +static void orinoco_stat_gather(struct net_device *dev,
  5324. + struct sk_buff *skb,
  5325. + struct hermes_rx_descriptor *desc)
  5326. +{
  5327. + struct orinoco_private *priv = ndev_priv(dev);
  5328. +
  5329. + /* Using spy support with lots of Rx packets, like in an
  5330. + * infrastructure (AP), will really slow down everything, because
  5331. + * the MAC address must be compared to each entry of the spy list.
  5332. + * If the user really asks for it (set some address in the
  5333. + * spy list), we do it, but he will pay the price.
  5334. + * Note that to get here, you need both WIRELESS_SPY
  5335. + * compiled in AND some addresses in the list !!!
  5336. + */
  5337. + /* Note : gcc will optimise the whole section away if
  5338. + * WIRELESS_SPY is not defined... - Jean II */
  5339. + if (SPY_NUMBER(priv)) {
  5340. + orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN,
  5341. + desc->signal, desc->silence);
  5342. + }
  5343. +}
  5344. +
  5345. +/*
  5346. + * orinoco_rx_monitor - handle received monitor frames.
  5347. + *
  5348. + * Arguments:
  5349. + * dev network device
  5350. + * rxfid received FID
  5351. + * desc rx descriptor of the frame
  5352. + *
  5353. + * Call context: interrupt
  5354. + */
  5355. +static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
  5356. + struct hermes_rx_descriptor *desc)
  5357. +{
  5358. + u32 hdrlen = 30; /* return full header by default */
  5359. + u32 datalen = 0;
  5360. + u16 fc;
  5361. + int err;
  5362. + int len;
  5363. + struct sk_buff *skb;
  5364. + struct orinoco_private *priv = ndev_priv(dev);
  5365. + struct net_device_stats *stats = &dev->stats;
  5366. + struct hermes *hw = &priv->hw;
  5367. +
  5368. + len = le16_to_cpu(desc->data_len);
  5369. +
  5370. + /* Determine the size of the header and the data */
  5371. + fc = le16_to_cpu(desc->frame_ctl);
  5372. + switch (fc & IEEE80211_FCTL_FTYPE) {
  5373. + case IEEE80211_FTYPE_DATA:
  5374. + if ((fc & IEEE80211_FCTL_TODS)
  5375. + && (fc & IEEE80211_FCTL_FROMDS))
  5376. + hdrlen = 30;
  5377. + else
  5378. + hdrlen = 24;
  5379. + datalen = len;
  5380. + break;
  5381. + case IEEE80211_FTYPE_MGMT:
  5382. + hdrlen = 24;
  5383. + datalen = len;
  5384. + break;
  5385. + case IEEE80211_FTYPE_CTL:
  5386. + switch (fc & IEEE80211_FCTL_STYPE) {
  5387. + case IEEE80211_STYPE_PSPOLL:
  5388. + case IEEE80211_STYPE_RTS:
  5389. + case IEEE80211_STYPE_CFEND:
  5390. + case IEEE80211_STYPE_CFENDACK:
  5391. + hdrlen = 16;
  5392. + break;
  5393. + case IEEE80211_STYPE_CTS:
  5394. + case IEEE80211_STYPE_ACK:
  5395. + hdrlen = 10;
  5396. + break;
  5397. + }
  5398. + break;
  5399. + default:
  5400. + /* Unknown frame type */
  5401. + break;
  5402. + }
  5403. +
  5404. + /* sanity check the length */
  5405. + if (datalen > IEEE80211_MAX_DATA_LEN + 12) {
  5406. + printk(KERN_DEBUG "%s: oversized monitor frame, "
  5407. + "data length = %d\n", dev->name, datalen);
  5408. + stats->rx_length_errors++;
  5409. + goto update_stats;
  5410. + }
  5411. +
  5412. + skb = dev_alloc_skb(hdrlen + datalen);
  5413. + if (!skb) {
  5414. + printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
  5415. + dev->name);
  5416. + goto update_stats;
  5417. + }
  5418. +
  5419. + /* Copy the 802.11 header to the skb */
  5420. + skb_put_data(skb, &(desc->frame_ctl), hdrlen);
  5421. + skb_reset_mac_header(skb);
  5422. +
  5423. + /* If any, copy the data from the card to the skb */
  5424. + if (datalen > 0) {
  5425. + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
  5426. + ALIGN(datalen, 2), rxfid,
  5427. + HERMES_802_2_OFFSET);
  5428. + if (err) {
  5429. + printk(KERN_ERR "%s: error %d reading monitor frame\n",
  5430. + dev->name, err);
  5431. + goto drop;
  5432. + }
  5433. + }
  5434. +
  5435. + skb->dev = dev;
  5436. + skb->ip_summed = CHECKSUM_NONE;
  5437. + skb->pkt_type = PACKET_OTHERHOST;
  5438. + skb->protocol = cpu_to_be16(ETH_P_802_2);
  5439. +
  5440. + stats->rx_packets++;
  5441. + stats->rx_bytes += skb->len;
  5442. +
  5443. + netif_rx(skb);
  5444. + return;
  5445. +
  5446. + drop:
  5447. + dev_kfree_skb_irq(skb);
  5448. + update_stats:
  5449. + stats->rx_errors++;
  5450. + stats->rx_dropped++;
  5451. +}
  5452. +
  5453. +void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw)
  5454. +{
  5455. + struct orinoco_private *priv = ndev_priv(dev);
  5456. + struct net_device_stats *stats = &dev->stats;
  5457. + struct iw_statistics *wstats = &priv->wstats;
  5458. + struct sk_buff *skb = NULL;
  5459. + u16 rxfid, status;
  5460. + int length;
  5461. + struct hermes_rx_descriptor *desc;
  5462. + struct orinoco_rx_data *rx_data;
  5463. + int err;
  5464. +
  5465. + desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
  5466. + if (!desc)
  5467. + goto update_stats;
  5468. +
  5469. + rxfid = hermes_read_regn(hw, RXFID);
  5470. +
  5471. + err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
  5472. + rxfid, 0);
  5473. + if (err) {
  5474. + printk(KERN_ERR "%s: error %d reading Rx descriptor. "
  5475. + "Frame dropped.\n", dev->name, err);
  5476. + goto update_stats;
  5477. + }
  5478. +
  5479. + status = le16_to_cpu(desc->status);
  5480. +
  5481. + if (status & HERMES_RXSTAT_BADCRC) {
  5482. + DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
  5483. + dev->name);
  5484. + stats->rx_crc_errors++;
  5485. + goto update_stats;
  5486. + }
  5487. +
  5488. + /* Handle frames in monitor mode */
  5489. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
  5490. + orinoco_rx_monitor(dev, rxfid, desc);
  5491. + goto out;
  5492. + }
  5493. +
  5494. + if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
  5495. + DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
  5496. + dev->name);
  5497. + wstats->discard.code++;
  5498. + goto update_stats;
  5499. + }
  5500. +
  5501. + length = le16_to_cpu(desc->data_len);
  5502. +
  5503. + /* Sanity checks */
  5504. + if (length < 3) { /* No for even an 802.2 LLC header */
  5505. + /* At least on Symbol firmware with PCF we get quite a
  5506. + lot of these legitimately - Poll frames with no
  5507. + data. */
  5508. + goto out;
  5509. + }
  5510. + if (length > IEEE80211_MAX_DATA_LEN) {
  5511. + printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
  5512. + dev->name, length);
  5513. + stats->rx_length_errors++;
  5514. + goto update_stats;
  5515. + }
  5516. +
  5517. + /* Payload size does not include Michael MIC. Increase payload
  5518. + * size to read it together with the data. */
  5519. + if (status & HERMES_RXSTAT_MIC)
  5520. + length += MICHAEL_MIC_LEN;
  5521. +
  5522. + /* We need space for the packet data itself, plus an ethernet
  5523. + header, plus 2 bytes so we can align the IP header on a
  5524. + 32bit boundary, plus 1 byte so we can read in odd length
  5525. + packets from the card, which has an IO granularity of 16
  5526. + bits */
  5527. + skb = dev_alloc_skb(length + ETH_HLEN + 2 + 1);
  5528. + if (!skb) {
  5529. + printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
  5530. + dev->name);
  5531. + goto update_stats;
  5532. + }
  5533. +
  5534. + /* We'll prepend the header, so reserve space for it. The worst
  5535. + case is no decapsulation, when 802.3 header is prepended and
  5536. + nothing is removed. 2 is for aligning the IP header. */
  5537. + skb_reserve(skb, ETH_HLEN + 2);
  5538. +
  5539. + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length),
  5540. + ALIGN(length, 2), rxfid,
  5541. + HERMES_802_2_OFFSET);
  5542. + if (err) {
  5543. + printk(KERN_ERR "%s: error %d reading frame. "
  5544. + "Frame dropped.\n", dev->name, err);
  5545. + goto drop;
  5546. + }
  5547. +
  5548. + /* Add desc and skb to rx queue */
  5549. + rx_data = kzalloc(sizeof(*rx_data), GFP_ATOMIC);
  5550. + if (!rx_data)
  5551. + goto drop;
  5552. +
  5553. + rx_data->desc = desc;
  5554. + rx_data->skb = skb;
  5555. + list_add_tail(&rx_data->list, &priv->rx_list);
  5556. + tasklet_schedule(&priv->rx_tasklet);
  5557. +
  5558. + return;
  5559. +
  5560. +drop:
  5561. + dev_kfree_skb_irq(skb);
  5562. +update_stats:
  5563. + stats->rx_errors++;
  5564. + stats->rx_dropped++;
  5565. +out:
  5566. + kfree(desc);
  5567. +}
  5568. +EXPORT_SYMBOL(__orinoco_ev_rx);
  5569. +
  5570. +static void orinoco_rx(struct net_device *dev,
  5571. + struct hermes_rx_descriptor *desc,
  5572. + struct sk_buff *skb)
  5573. +{
  5574. + struct orinoco_private *priv = ndev_priv(dev);
  5575. + struct net_device_stats *stats = &dev->stats;
  5576. + u16 status, fc;
  5577. + int length;
  5578. + struct ethhdr *hdr;
  5579. +
  5580. + status = le16_to_cpu(desc->status);
  5581. + length = le16_to_cpu(desc->data_len);
  5582. + fc = le16_to_cpu(desc->frame_ctl);
  5583. +
  5584. + /* Calculate and check MIC */
  5585. + if (status & HERMES_RXSTAT_MIC) {
  5586. + struct orinoco_tkip_key *key;
  5587. + int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
  5588. + HERMES_MIC_KEY_ID_SHIFT);
  5589. + u8 mic[MICHAEL_MIC_LEN];
  5590. + u8 *rxmic;
  5591. + u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
  5592. + desc->addr3 : desc->addr2;
  5593. +
  5594. + /* Extract Michael MIC from payload */
  5595. + rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
  5596. +
  5597. + skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
  5598. + length -= MICHAEL_MIC_LEN;
  5599. +
  5600. + key = (struct orinoco_tkip_key *) priv->keys[key_id].key;
  5601. +
  5602. + if (!key) {
  5603. + printk(KERN_WARNING "%s: Received encrypted frame from "
  5604. + "%pM using key %i, but key is not installed\n",
  5605. + dev->name, src, key_id);
  5606. + goto drop;
  5607. + }
  5608. +
  5609. + orinoco_mic(priv->rx_tfm_mic, key->rx_mic, desc->addr1, src,
  5610. + 0, /* priority or QoS? */
  5611. + skb->data, skb->len, &mic[0]);
  5612. +
  5613. + if (memcmp(mic, rxmic,
  5614. + MICHAEL_MIC_LEN)) {
  5615. + union iwreq_data wrqu;
  5616. + struct iw_michaelmicfailure wxmic;
  5617. +
  5618. + printk(KERN_WARNING "%s: "
  5619. + "Invalid Michael MIC in data frame from %pM, "
  5620. + "using key %i\n",
  5621. + dev->name, src, key_id);
  5622. +
  5623. + /* TODO: update stats */
  5624. +
  5625. + /* Notify userspace */
  5626. + memset(&wxmic, 0, sizeof(wxmic));
  5627. + wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
  5628. + wxmic.flags |= (desc->addr1[0] & 1) ?
  5629. + IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
  5630. + wxmic.src_addr.sa_family = ARPHRD_ETHER;
  5631. + memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
  5632. +
  5633. + (void) orinoco_hw_get_tkip_iv(priv, key_id,
  5634. + &wxmic.tsc[0]);
  5635. +
  5636. + memset(&wrqu, 0, sizeof(wrqu));
  5637. + wrqu.data.length = sizeof(wxmic);
  5638. + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
  5639. + (char *) &wxmic);
  5640. +
  5641. + goto drop;
  5642. + }
  5643. + }
  5644. +
  5645. + /* Handle decapsulation
  5646. + * In most cases, the firmware tell us about SNAP frames.
  5647. + * For some reason, the SNAP frames sent by LinkSys APs
  5648. + * are not properly recognised by most firmwares.
  5649. + * So, check ourselves */
  5650. + if (length >= ENCAPS_OVERHEAD &&
  5651. + (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
  5652. + ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
  5653. + is_ethersnap(skb->data))) {
  5654. + /* These indicate a SNAP within 802.2 LLC within
  5655. + 802.11 frame which we'll need to de-encapsulate to
  5656. + the original EthernetII frame. */
  5657. + hdr = skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
  5658. + } else {
  5659. + /* 802.3 frame - prepend 802.3 header as is */
  5660. + hdr = skb_push(skb, ETH_HLEN);
  5661. + hdr->h_proto = htons(length);
  5662. + }
  5663. + memcpy(hdr->h_dest, desc->addr1, ETH_ALEN);
  5664. + if (fc & IEEE80211_FCTL_FROMDS)
  5665. + memcpy(hdr->h_source, desc->addr3, ETH_ALEN);
  5666. + else
  5667. + memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
  5668. +
  5669. + skb->protocol = eth_type_trans(skb, dev);
  5670. + skb->ip_summed = CHECKSUM_NONE;
  5671. + if (fc & IEEE80211_FCTL_TODS)
  5672. + skb->pkt_type = PACKET_OTHERHOST;
  5673. +
  5674. + /* Process the wireless stats if needed */
  5675. + orinoco_stat_gather(dev, skb, desc);
  5676. +
  5677. + /* Pass the packet to the networking stack */
  5678. + netif_rx(skb);
  5679. + stats->rx_packets++;
  5680. + stats->rx_bytes += length;
  5681. +
  5682. + return;
  5683. +
  5684. + drop:
  5685. + dev_kfree_skb(skb);
  5686. + stats->rx_errors++;
  5687. + stats->rx_dropped++;
  5688. +}
  5689. +
  5690. +static void orinoco_rx_isr_tasklet(struct tasklet_struct *t)
  5691. +{
  5692. + struct orinoco_private *priv = from_tasklet(priv, t, rx_tasklet);
  5693. + struct net_device *dev = priv->ndev;
  5694. + struct orinoco_rx_data *rx_data, *temp;
  5695. + struct hermes_rx_descriptor *desc;
  5696. + struct sk_buff *skb;
  5697. + unsigned long flags;
  5698. +
  5699. + /* orinoco_rx requires the driver lock, and we also need to
  5700. + * protect priv->rx_list, so just hold the lock over the
  5701. + * lot.
  5702. + *
  5703. + * If orinoco_lock fails, we've unplugged the card. In this
  5704. + * case just abort. */
  5705. + if (orinoco_lock(priv, &flags) != 0)
  5706. + return;
  5707. +
  5708. + /* extract desc and skb from queue */
  5709. + list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
  5710. + desc = rx_data->desc;
  5711. + skb = rx_data->skb;
  5712. + list_del(&rx_data->list);
  5713. + kfree(rx_data);
  5714. +
  5715. + orinoco_rx(dev, desc, skb);
  5716. +
  5717. + kfree(desc);
  5718. + }
  5719. +
  5720. + orinoco_unlock(priv, &flags);
  5721. +}
  5722. +
  5723. +/********************************************************************/
  5724. +/* Rx path (info frames) */
  5725. +/********************************************************************/
  5726. +
  5727. +static void print_linkstatus(struct net_device *dev, u16 status)
  5728. +{
  5729. + char *s;
  5730. +
  5731. + if (suppress_linkstatus)
  5732. + return;
  5733. +
  5734. + switch (status) {
  5735. + case HERMES_LINKSTATUS_NOT_CONNECTED:
  5736. + s = "Not Connected";
  5737. + break;
  5738. + case HERMES_LINKSTATUS_CONNECTED:
  5739. + s = "Connected";
  5740. + break;
  5741. + case HERMES_LINKSTATUS_DISCONNECTED:
  5742. + s = "Disconnected";
  5743. + break;
  5744. + case HERMES_LINKSTATUS_AP_CHANGE:
  5745. + s = "AP Changed";
  5746. + break;
  5747. + case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
  5748. + s = "AP Out of Range";
  5749. + break;
  5750. + case HERMES_LINKSTATUS_AP_IN_RANGE:
  5751. + s = "AP In Range";
  5752. + break;
  5753. + case HERMES_LINKSTATUS_ASSOC_FAILED:
  5754. + s = "Association Failed";
  5755. + break;
  5756. + default:
  5757. + s = "UNKNOWN";
  5758. + }
  5759. +
  5760. + printk(KERN_DEBUG "%s: New link status: %s (%04x)\n",
  5761. + dev->name, s, status);
  5762. +}
  5763. +
  5764. +/* Search scan results for requested BSSID, join it if found */
  5765. +static void orinoco_join_ap(struct work_struct *work)
  5766. +{
  5767. + struct orinoco_private *priv =
  5768. + container_of(work, struct orinoco_private, join_work);
  5769. + struct net_device *dev = priv->ndev;
  5770. + struct hermes *hw = &priv->hw;
  5771. + int err;
  5772. + unsigned long flags;
  5773. + struct join_req {
  5774. + u8 bssid[ETH_ALEN];
  5775. + __le16 channel;
  5776. + } __packed req;
  5777. + const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
  5778. + struct prism2_scan_apinfo *atom = NULL;
  5779. + int offset = 4;
  5780. + int found = 0;
  5781. + u8 *buf;
  5782. + u16 len;
  5783. +
  5784. + /* Allocate buffer for scan results */
  5785. + buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
  5786. + if (!buf)
  5787. + return;
  5788. +
  5789. + if (orinoco_lock(priv, &flags) != 0)
  5790. + goto fail_lock;
  5791. +
  5792. + /* Sanity checks in case user changed something in the meantime */
  5793. + if (!priv->bssid_fixed)
  5794. + goto out;
  5795. +
  5796. + if (strlen(priv->desired_essid) == 0)
  5797. + goto out;
  5798. +
  5799. + /* Read scan results from the firmware */
  5800. + err = hw->ops->read_ltv(hw, USER_BAP,
  5801. + HERMES_RID_SCANRESULTSTABLE,
  5802. + MAX_SCAN_LEN, &len, buf);
  5803. + if (err) {
  5804. + printk(KERN_ERR "%s: Cannot read scan results\n",
  5805. + dev->name);
  5806. + goto out;
  5807. + }
  5808. +
  5809. + len = HERMES_RECLEN_TO_BYTES(len);
  5810. +
  5811. + /* Go through the scan results looking for the channel of the AP
  5812. + * we were requested to join */
  5813. + for (; offset + atom_len <= len; offset += atom_len) {
  5814. + atom = (struct prism2_scan_apinfo *) (buf + offset);
  5815. + if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
  5816. + found = 1;
  5817. + break;
  5818. + }
  5819. + }
  5820. +
  5821. + if (!found) {
  5822. + DEBUG(1, "%s: Requested AP not found in scan results\n",
  5823. + dev->name);
  5824. + goto out;
  5825. + }
  5826. +
  5827. + memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
  5828. + req.channel = atom->channel; /* both are little-endian */
  5829. + err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
  5830. + &req);
  5831. + if (err)
  5832. + printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
  5833. +
  5834. + out:
  5835. + orinoco_unlock(priv, &flags);
  5836. +
  5837. + fail_lock:
  5838. + kfree(buf);
  5839. +}
  5840. +
  5841. +/* Send new BSSID to userspace */
  5842. +static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
  5843. +{
  5844. + struct net_device *dev = priv->ndev;
  5845. + struct hermes *hw = &priv->hw;
  5846. + union iwreq_data wrqu;
  5847. + int err;
  5848. +
  5849. + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
  5850. + ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
  5851. + if (err != 0)
  5852. + return;
  5853. +
  5854. + wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  5855. +
  5856. + /* Send event to user space */
  5857. + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
  5858. +}
  5859. +
  5860. +static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
  5861. +{
  5862. + struct net_device *dev = priv->ndev;
  5863. + struct hermes *hw = &priv->hw;
  5864. + union iwreq_data wrqu;
  5865. + int err;
  5866. + u8 buf[88];
  5867. + u8 *ie;
  5868. +
  5869. + if (!priv->has_wpa)
  5870. + return;
  5871. +
  5872. + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
  5873. + sizeof(buf), NULL, &buf);
  5874. + if (err != 0)
  5875. + return;
  5876. +
  5877. + ie = orinoco_get_wpa_ie(buf, sizeof(buf));
  5878. + if (ie) {
  5879. + int rem = sizeof(buf) - (ie - &buf[0]);
  5880. + wrqu.data.length = ie[1] + 2;
  5881. + if (wrqu.data.length > rem)
  5882. + wrqu.data.length = rem;
  5883. +
  5884. + if (wrqu.data.length)
  5885. + /* Send event to user space */
  5886. + wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie);
  5887. + }
  5888. +}
  5889. +
  5890. +static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
  5891. +{
  5892. + struct net_device *dev = priv->ndev;
  5893. + struct hermes *hw = &priv->hw;
  5894. + union iwreq_data wrqu;
  5895. + int err;
  5896. + u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */
  5897. + u8 *ie;
  5898. +
  5899. + if (!priv->has_wpa)
  5900. + return;
  5901. +
  5902. + err = hw->ops->read_ltv(hw, USER_BAP,
  5903. + HERMES_RID_CURRENT_ASSOC_RESP_INFO,
  5904. + sizeof(buf), NULL, &buf);
  5905. + if (err != 0)
  5906. + return;
  5907. +
  5908. + ie = orinoco_get_wpa_ie(buf, sizeof(buf));
  5909. + if (ie) {
  5910. + int rem = sizeof(buf) - (ie - &buf[0]);
  5911. + wrqu.data.length = ie[1] + 2;
  5912. + if (wrqu.data.length > rem)
  5913. + wrqu.data.length = rem;
  5914. +
  5915. + if (wrqu.data.length)
  5916. + /* Send event to user space */
  5917. + wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie);
  5918. + }
  5919. +}
  5920. +
  5921. +static void orinoco_send_wevents(struct work_struct *work)
  5922. +{
  5923. + struct orinoco_private *priv =
  5924. + container_of(work, struct orinoco_private, wevent_work);
  5925. + unsigned long flags;
  5926. +
  5927. + if (orinoco_lock(priv, &flags) != 0)
  5928. + return;
  5929. +
  5930. + orinoco_send_assocreqie_wevent(priv);
  5931. + orinoco_send_assocrespie_wevent(priv);
  5932. + orinoco_send_bssid_wevent(priv);
  5933. +
  5934. + orinoco_unlock(priv, &flags);
  5935. +}
  5936. +
  5937. +static void qbuf_scan(struct orinoco_private *priv, void *buf,
  5938. + int len, int type)
  5939. +{
  5940. + struct orinoco_scan_data *sd;
  5941. + unsigned long flags;
  5942. +
  5943. + sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
  5944. + if (!sd)
  5945. + return;
  5946. +
  5947. + sd->buf = buf;
  5948. + sd->len = len;
  5949. + sd->type = type;
  5950. +
  5951. + spin_lock_irqsave(&priv->scan_lock, flags);
  5952. + list_add_tail(&sd->list, &priv->scan_list);
  5953. + spin_unlock_irqrestore(&priv->scan_lock, flags);
  5954. +
  5955. + schedule_work(&priv->process_scan);
  5956. +}
  5957. +
  5958. +static void qabort_scan(struct orinoco_private *priv)
  5959. +{
  5960. + struct orinoco_scan_data *sd;
  5961. + unsigned long flags;
  5962. +
  5963. + sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
  5964. + if (!sd)
  5965. + return;
  5966. +
  5967. + sd->len = -1; /* Abort */
  5968. +
  5969. + spin_lock_irqsave(&priv->scan_lock, flags);
  5970. + list_add_tail(&sd->list, &priv->scan_list);
  5971. + spin_unlock_irqrestore(&priv->scan_lock, flags);
  5972. +
  5973. + schedule_work(&priv->process_scan);
  5974. +}
  5975. +
  5976. +static void orinoco_process_scan_results(struct work_struct *work)
  5977. +{
  5978. + struct orinoco_private *priv =
  5979. + container_of(work, struct orinoco_private, process_scan);
  5980. + struct orinoco_scan_data *sd, *temp;
  5981. + unsigned long flags;
  5982. + void *buf;
  5983. + int len;
  5984. + int type;
  5985. +
  5986. + spin_lock_irqsave(&priv->scan_lock, flags);
  5987. + list_for_each_entry_safe(sd, temp, &priv->scan_list, list) {
  5988. +
  5989. + buf = sd->buf;
  5990. + len = sd->len;
  5991. + type = sd->type;
  5992. +
  5993. + list_del(&sd->list);
  5994. + spin_unlock_irqrestore(&priv->scan_lock, flags);
  5995. + kfree(sd);
  5996. +
  5997. + if (len > 0) {
  5998. + if (type == HERMES_INQ_CHANNELINFO)
  5999. + orinoco_add_extscan_result(priv, buf, len);
  6000. + else
  6001. + orinoco_add_hostscan_results(priv, buf, len);
  6002. +
  6003. + kfree(buf);
  6004. + } else {
  6005. + /* Either abort or complete the scan */
  6006. + orinoco_scan_done(priv, (len < 0));
  6007. + }
  6008. +
  6009. + spin_lock_irqsave(&priv->scan_lock, flags);
  6010. + }
  6011. + spin_unlock_irqrestore(&priv->scan_lock, flags);
  6012. +}
  6013. +
  6014. +void __orinoco_ev_info(struct net_device *dev, struct hermes *hw)
  6015. +{
  6016. + struct orinoco_private *priv = ndev_priv(dev);
  6017. + u16 infofid;
  6018. + struct {
  6019. + __le16 len;
  6020. + __le16 type;
  6021. + } __packed info;
  6022. + int len, type;
  6023. + int err;
  6024. +
  6025. + /* This is an answer to an INQUIRE command that we did earlier,
  6026. + * or an information "event" generated by the card
  6027. + * The controller return to us a pseudo frame containing
  6028. + * the information in question - Jean II */
  6029. + infofid = hermes_read_regn(hw, INFOFID);
  6030. +
  6031. + /* Read the info frame header - don't try too hard */
  6032. + err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info),
  6033. + infofid, 0);
  6034. + if (err) {
  6035. + printk(KERN_ERR "%s: error %d reading info frame. "
  6036. + "Frame dropped.\n", dev->name, err);
  6037. + return;
  6038. + }
  6039. +
  6040. + len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
  6041. + type = le16_to_cpu(info.type);
  6042. +
  6043. + switch (type) {
  6044. + case HERMES_INQ_TALLIES: {
  6045. + struct hermes_tallies_frame tallies;
  6046. + struct iw_statistics *wstats = &priv->wstats;
  6047. +
  6048. + if (len > sizeof(tallies)) {
  6049. + printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
  6050. + dev->name, len);
  6051. + len = sizeof(tallies);
  6052. + }
  6053. +
  6054. + err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len,
  6055. + infofid, sizeof(info));
  6056. + if (err)
  6057. + break;
  6058. +
  6059. + /* Increment our various counters */
  6060. + /* wstats->discard.nwid - no wrong BSSID stuff */
  6061. + wstats->discard.code +=
  6062. + le16_to_cpu(tallies.RxWEPUndecryptable);
  6063. + if (len == sizeof(tallies))
  6064. + wstats->discard.code +=
  6065. + le16_to_cpu(tallies.RxDiscards_WEPICVError) +
  6066. + le16_to_cpu(tallies.RxDiscards_WEPExcluded);
  6067. + wstats->discard.misc +=
  6068. + le16_to_cpu(tallies.TxDiscardsWrongSA);
  6069. + wstats->discard.fragment +=
  6070. + le16_to_cpu(tallies.RxMsgInBadMsgFragments);
  6071. + wstats->discard.retries +=
  6072. + le16_to_cpu(tallies.TxRetryLimitExceeded);
  6073. + /* wstats->miss.beacon - no match */
  6074. + }
  6075. + break;
  6076. + case HERMES_INQ_LINKSTATUS: {
  6077. + struct hermes_linkstatus linkstatus;
  6078. + u16 newstatus;
  6079. + int connected;
  6080. +
  6081. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
  6082. + break;
  6083. +
  6084. + if (len != sizeof(linkstatus)) {
  6085. + printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
  6086. + dev->name, len);
  6087. + break;
  6088. + }
  6089. +
  6090. + err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len,
  6091. + infofid, sizeof(info));
  6092. + if (err)
  6093. + break;
  6094. + newstatus = le16_to_cpu(linkstatus.linkstatus);
  6095. +
  6096. + /* Symbol firmware uses "out of range" to signal that
  6097. + * the hostscan frame can be requested. */
  6098. + if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
  6099. + priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
  6100. + priv->has_hostscan && priv->scan_request) {
  6101. + hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
  6102. + break;
  6103. + }
  6104. +
  6105. + connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
  6106. + || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
  6107. + || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
  6108. +
  6109. + if (connected)
  6110. + netif_carrier_on(dev);
  6111. + else if (!ignore_disconnect)
  6112. + netif_carrier_off(dev);
  6113. +
  6114. + if (newstatus != priv->last_linkstatus) {
  6115. + priv->last_linkstatus = newstatus;
  6116. + print_linkstatus(dev, newstatus);
  6117. + /* The info frame contains only one word which is the
  6118. + * status (see hermes.h). The status is pretty boring
  6119. + * in itself, that's why we export the new BSSID...
  6120. + * Jean II */
  6121. + schedule_work(&priv->wevent_work);
  6122. + }
  6123. + }
  6124. + break;
  6125. + case HERMES_INQ_SCAN:
  6126. + if (!priv->scan_request && priv->bssid_fixed &&
  6127. + priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
  6128. + schedule_work(&priv->join_work);
  6129. + break;
  6130. + }
  6131. + fallthrough;
  6132. + case HERMES_INQ_HOSTSCAN:
  6133. + case HERMES_INQ_HOSTSCAN_SYMBOL: {
  6134. + /* Result of a scanning. Contains information about
  6135. + * cells in the vicinity - Jean II */
  6136. + unsigned char *buf;
  6137. +
  6138. + /* Sanity check */
  6139. + if (len > 4096) {
  6140. + printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
  6141. + dev->name, len);
  6142. + qabort_scan(priv);
  6143. + break;
  6144. + }
  6145. +
  6146. + /* Allocate buffer for results */
  6147. + buf = kmalloc(len, GFP_ATOMIC);
  6148. + if (buf == NULL) {
  6149. + /* No memory, so can't printk()... */
  6150. + qabort_scan(priv);
  6151. + break;
  6152. + }
  6153. +
  6154. + /* Read scan data */
  6155. + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len,
  6156. + infofid, sizeof(info));
  6157. + if (err) {
  6158. + kfree(buf);
  6159. + qabort_scan(priv);
  6160. + break;
  6161. + }
  6162. +
  6163. +#ifdef ORINOCO_DEBUG
  6164. + {
  6165. + int i;
  6166. + printk(KERN_DEBUG "Scan result [%02X", buf[0]);
  6167. + for (i = 1; i < (len * 2); i++)
  6168. + printk(":%02X", buf[i]);
  6169. + printk("]\n");
  6170. + }
  6171. +#endif /* ORINOCO_DEBUG */
  6172. +
  6173. + qbuf_scan(priv, buf, len, type);
  6174. + }
  6175. + break;
  6176. + case HERMES_INQ_CHANNELINFO:
  6177. + {
  6178. + struct agere_ext_scan_info *bss;
  6179. +
  6180. + if (!priv->scan_request) {
  6181. + printk(KERN_DEBUG "%s: Got chaninfo without scan, "
  6182. + "len=%d\n", dev->name, len);
  6183. + break;
  6184. + }
  6185. +
  6186. + /* An empty result indicates that the scan is complete */
  6187. + if (len == 0) {
  6188. + qbuf_scan(priv, NULL, len, type);
  6189. + break;
  6190. + }
  6191. +
  6192. + /* Sanity check */
  6193. + else if (len < (offsetof(struct agere_ext_scan_info,
  6194. + data) + 2)) {
  6195. + /* Drop this result now so we don't have to
  6196. + * keep checking later */
  6197. + printk(KERN_WARNING
  6198. + "%s: Ext scan results too short (%d bytes)\n",
  6199. + dev->name, len);
  6200. + break;
  6201. + }
  6202. +
  6203. + bss = kmalloc(len, GFP_ATOMIC);
  6204. + if (bss == NULL)
  6205. + break;
  6206. +
  6207. + /* Read scan data */
  6208. + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len,
  6209. + infofid, sizeof(info));
  6210. + if (err)
  6211. + kfree(bss);
  6212. + else
  6213. + qbuf_scan(priv, bss, len, type);
  6214. +
  6215. + break;
  6216. + }
  6217. + case HERMES_INQ_SEC_STAT_AGERE:
  6218. + /* Security status (Agere specific) */
  6219. + /* Ignore this frame for now */
  6220. + if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
  6221. + break;
  6222. + fallthrough;
  6223. + default:
  6224. + printk(KERN_DEBUG "%s: Unknown information frame received: "
  6225. + "type 0x%04x, length %d\n", dev->name, type, len);
  6226. + /* We don't actually do anything about it */
  6227. + break;
  6228. + }
  6229. +}
  6230. +EXPORT_SYMBOL(__orinoco_ev_info);
  6231. +
  6232. +static void __orinoco_ev_infdrop(struct net_device *dev, struct hermes *hw)
  6233. +{
  6234. + if (net_ratelimit())
  6235. + printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
  6236. +}
  6237. +
  6238. +/********************************************************************/
  6239. +/* Internal hardware control routines */
  6240. +/********************************************************************/
  6241. +
  6242. +static int __orinoco_up(struct orinoco_private *priv)
  6243. +{
  6244. + struct net_device *dev = priv->ndev;
  6245. + struct hermes *hw = &priv->hw;
  6246. + int err;
  6247. +
  6248. + netif_carrier_off(dev); /* just to make sure */
  6249. +
  6250. + err = __orinoco_commit(priv);
  6251. + if (err) {
  6252. + printk(KERN_ERR "%s: Error %d configuring card\n",
  6253. + dev->name, err);
  6254. + return err;
  6255. + }
  6256. +
  6257. + /* Fire things up again */
  6258. + hermes_set_irqmask(hw, ORINOCO_INTEN);
  6259. + err = hermes_enable_port(hw, 0);
  6260. + if (err) {
  6261. + printk(KERN_ERR "%s: Error %d enabling MAC port\n",
  6262. + dev->name, err);
  6263. + return err;
  6264. + }
  6265. +
  6266. + netif_start_queue(dev);
  6267. +
  6268. + return 0;
  6269. +}
  6270. +
  6271. +static int __orinoco_down(struct orinoco_private *priv)
  6272. +{
  6273. + struct net_device *dev = priv->ndev;
  6274. + struct hermes *hw = &priv->hw;
  6275. + int err;
  6276. +
  6277. + netif_stop_queue(dev);
  6278. +
  6279. + if (!priv->hw_unavailable) {
  6280. + if (!priv->broken_disableport) {
  6281. + err = hermes_disable_port(hw, 0);
  6282. + if (err) {
  6283. + /* Some firmwares (e.g. Intersil 1.3.x) seem
  6284. + * to have problems disabling the port, oh
  6285. + * well, too bad. */
  6286. + printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
  6287. + dev->name, err);
  6288. + priv->broken_disableport = 1;
  6289. + }
  6290. + }
  6291. + hermes_set_irqmask(hw, 0);
  6292. + hermes_write_regn(hw, EVACK, 0xffff);
  6293. + }
  6294. +
  6295. + orinoco_scan_done(priv, true);
  6296. +
  6297. + /* firmware will have to reassociate */
  6298. + netif_carrier_off(dev);
  6299. + priv->last_linkstatus = 0xffff;
  6300. +
  6301. + return 0;
  6302. +}
  6303. +
  6304. +static int orinoco_reinit_firmware(struct orinoco_private *priv)
  6305. +{
  6306. + struct hermes *hw = &priv->hw;
  6307. + int err;
  6308. +
  6309. + err = hw->ops->init(hw);
  6310. + if (priv->do_fw_download && !err) {
  6311. + err = orinoco_download(priv);
  6312. + if (err)
  6313. + priv->do_fw_download = 0;
  6314. + }
  6315. + if (!err)
  6316. + err = orinoco_hw_allocate_fid(priv);
  6317. +
  6318. + return err;
  6319. +}
  6320. +
  6321. +static int
  6322. +__orinoco_set_multicast_list(struct net_device *dev)
  6323. +{
  6324. + struct orinoco_private *priv = ndev_priv(dev);
  6325. + int err = 0;
  6326. + int promisc, mc_count;
  6327. +
  6328. + /* The Hermes doesn't seem to have an allmulti mode, so we go
  6329. + * into promiscuous mode and let the upper levels deal. */
  6330. + if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
  6331. + (netdev_mc_count(dev) > MAX_MULTICAST(priv))) {
  6332. + promisc = 1;
  6333. + mc_count = 0;
  6334. + } else {
  6335. + promisc = 0;
  6336. + mc_count = netdev_mc_count(dev);
  6337. + }
  6338. +
  6339. + err = __orinoco_hw_set_multicast_list(priv, dev, mc_count, promisc);
  6340. +
  6341. + return err;
  6342. +}
  6343. +
  6344. +/* This must be called from user context, without locks held - use
  6345. + * schedule_work() */
  6346. +void orinoco_reset(struct work_struct *work)
  6347. +{
  6348. + struct orinoco_private *priv =
  6349. + container_of(work, struct orinoco_private, reset_work);
  6350. + struct net_device *dev = priv->ndev;
  6351. + struct hermes *hw = &priv->hw;
  6352. + int err;
  6353. + unsigned long flags;
  6354. +
  6355. + if (orinoco_lock(priv, &flags) != 0)
  6356. + /* When the hardware becomes available again, whatever
  6357. + * detects that is responsible for re-initializing
  6358. + * it. So no need for anything further */
  6359. + return;
  6360. +
  6361. + netif_stop_queue(dev);
  6362. +
  6363. + /* Shut off interrupts. Depending on what state the hardware
  6364. + * is in, this might not work, but we'll try anyway */
  6365. + hermes_set_irqmask(hw, 0);
  6366. + hermes_write_regn(hw, EVACK, 0xffff);
  6367. +
  6368. + priv->hw_unavailable++;
  6369. + priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
  6370. + netif_carrier_off(dev);
  6371. +
  6372. + orinoco_unlock(priv, &flags);
  6373. +
  6374. + /* Scanning support: Notify scan cancellation */
  6375. + orinoco_scan_done(priv, true);
  6376. +
  6377. + if (priv->hard_reset) {
  6378. + err = (*priv->hard_reset)(priv);
  6379. + if (err) {
  6380. + printk(KERN_ERR "%s: orinoco_reset: Error %d "
  6381. + "performing hard reset\n", dev->name, err);
  6382. + goto disable;
  6383. + }
  6384. + }
  6385. +
  6386. + err = orinoco_reinit_firmware(priv);
  6387. + if (err) {
  6388. + printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
  6389. + dev->name, err);
  6390. + goto disable;
  6391. + }
  6392. +
  6393. + /* This has to be called from user context */
  6394. + orinoco_lock_irq(priv);
  6395. +
  6396. + priv->hw_unavailable--;
  6397. +
  6398. + /* priv->open or priv->hw_unavailable might have changed while
  6399. + * we dropped the lock */
  6400. + if (priv->open && (!priv->hw_unavailable)) {
  6401. + err = __orinoco_up(priv);
  6402. + if (err) {
  6403. + printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
  6404. + dev->name, err);
  6405. + } else
  6406. + netif_trans_update(dev);
  6407. + }
  6408. +
  6409. + orinoco_unlock_irq(priv);
  6410. +
  6411. + return;
  6412. + disable:
  6413. + hermes_set_irqmask(hw, 0);
  6414. + netif_device_detach(dev);
  6415. + printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
  6416. +}
  6417. +
  6418. +static int __orinoco_commit(struct orinoco_private *priv)
  6419. +{
  6420. + struct net_device *dev = priv->ndev;
  6421. + int err = 0;
  6422. +
  6423. + /* If we've called commit, we are reconfiguring or bringing the
  6424. + * interface up. Maintaining countermeasures across this would
  6425. + * be confusing, so note that we've disabled them. The port will
  6426. + * be enabled later in orinoco_commit or __orinoco_up. */
  6427. + priv->tkip_cm_active = 0;
  6428. +
  6429. + err = orinoco_hw_program_rids(priv);
  6430. +
  6431. + /* FIXME: what about netif_tx_lock */
  6432. + (void) __orinoco_set_multicast_list(dev);
  6433. +
  6434. + return err;
  6435. +}
  6436. +
  6437. +/* Ensures configuration changes are applied. May result in a reset.
  6438. + * The caller should hold priv->lock
  6439. + */
  6440. +int orinoco_commit(struct orinoco_private *priv)
  6441. +{
  6442. + struct net_device *dev = priv->ndev;
  6443. + struct hermes *hw = &priv->hw;
  6444. + int err;
  6445. +
  6446. + if (priv->broken_disableport) {
  6447. + schedule_work(&priv->reset_work);
  6448. + return 0;
  6449. + }
  6450. +
  6451. + err = hermes_disable_port(hw, 0);
  6452. + if (err) {
  6453. + printk(KERN_WARNING "%s: Unable to disable port "
  6454. + "while reconfiguring card\n", dev->name);
  6455. + priv->broken_disableport = 1;
  6456. + goto out;
  6457. + }
  6458. +
  6459. + err = __orinoco_commit(priv);
  6460. + if (err) {
  6461. + printk(KERN_WARNING "%s: Unable to reconfigure card\n",
  6462. + dev->name);
  6463. + goto out;
  6464. + }
  6465. +
  6466. + err = hermes_enable_port(hw, 0);
  6467. + if (err) {
  6468. + printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
  6469. + dev->name);
  6470. + goto out;
  6471. + }
  6472. +
  6473. + out:
  6474. + if (err) {
  6475. + printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
  6476. + schedule_work(&priv->reset_work);
  6477. + err = 0;
  6478. + }
  6479. + return err;
  6480. +}
  6481. +
  6482. +/********************************************************************/
  6483. +/* Interrupt handler */
  6484. +/********************************************************************/
  6485. +
  6486. +static void __orinoco_ev_tick(struct net_device *dev, struct hermes *hw)
  6487. +{
  6488. + printk(KERN_DEBUG "%s: TICK\n", dev->name);
  6489. +}
  6490. +
  6491. +static void __orinoco_ev_wterr(struct net_device *dev, struct hermes *hw)
  6492. +{
  6493. + /* This seems to happen a fair bit under load, but ignoring it
  6494. + seems to work fine...*/
  6495. + printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
  6496. + dev->name);
  6497. +}
  6498. +
  6499. +irqreturn_t orinoco_interrupt(int irq, void *dev_id)
  6500. +{
  6501. + struct orinoco_private *priv = dev_id;
  6502. + struct net_device *dev = priv->ndev;
  6503. + struct hermes *hw = &priv->hw;
  6504. + int count = MAX_IRQLOOPS_PER_IRQ;
  6505. + u16 evstat, events;
  6506. + /* These are used to detect a runaway interrupt situation.
  6507. + *
  6508. + * If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
  6509. + * we panic and shut down the hardware
  6510. + */
  6511. + /* jiffies value the last time we were called */
  6512. + static int last_irq_jiffy; /* = 0 */
  6513. + static int loops_this_jiffy; /* = 0 */
  6514. + unsigned long flags;
  6515. +
  6516. + if (orinoco_lock(priv, &flags) != 0) {
  6517. + /* If hw is unavailable - we don't know if the irq was
  6518. + * for us or not */
  6519. + return IRQ_HANDLED;
  6520. + }
  6521. +
  6522. + evstat = hermes_read_regn(hw, EVSTAT);
  6523. + events = evstat & hw->inten;
  6524. + if (!events) {
  6525. + orinoco_unlock(priv, &flags);
  6526. + return IRQ_NONE;
  6527. + }
  6528. +
  6529. + if (jiffies != last_irq_jiffy)
  6530. + loops_this_jiffy = 0;
  6531. + last_irq_jiffy = jiffies;
  6532. +
  6533. + while (events && count--) {
  6534. + if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
  6535. + printk(KERN_WARNING "%s: IRQ handler is looping too "
  6536. + "much! Resetting.\n", dev->name);
  6537. + /* Disable interrupts for now */
  6538. + hermes_set_irqmask(hw, 0);
  6539. + schedule_work(&priv->reset_work);
  6540. + break;
  6541. + }
  6542. +
  6543. + /* Check the card hasn't been removed */
  6544. + if (!hermes_present(hw)) {
  6545. + DEBUG(0, "orinoco_interrupt(): card removed\n");
  6546. + break;
  6547. + }
  6548. +
  6549. + if (events & HERMES_EV_TICK)
  6550. + __orinoco_ev_tick(dev, hw);
  6551. + if (events & HERMES_EV_WTERR)
  6552. + __orinoco_ev_wterr(dev, hw);
  6553. + if (events & HERMES_EV_INFDROP)
  6554. + __orinoco_ev_infdrop(dev, hw);
  6555. + if (events & HERMES_EV_INFO)
  6556. + __orinoco_ev_info(dev, hw);
  6557. + if (events & HERMES_EV_RX)
  6558. + __orinoco_ev_rx(dev, hw);
  6559. + if (events & HERMES_EV_TXEXC)
  6560. + __orinoco_ev_txexc(dev, hw);
  6561. + if (events & HERMES_EV_TX)
  6562. + __orinoco_ev_tx(dev, hw);
  6563. + if (events & HERMES_EV_ALLOC)
  6564. + __orinoco_ev_alloc(dev, hw);
  6565. +
  6566. + hermes_write_regn(hw, EVACK, evstat);
  6567. +
  6568. + evstat = hermes_read_regn(hw, EVSTAT);
  6569. + events = evstat & hw->inten;
  6570. + }
  6571. +
  6572. + orinoco_unlock(priv, &flags);
  6573. + return IRQ_HANDLED;
  6574. +}
  6575. +EXPORT_SYMBOL(orinoco_interrupt);
  6576. +
  6577. +/********************************************************************/
  6578. +/* Power management */
  6579. +/********************************************************************/
  6580. +#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
  6581. +static int orinoco_pm_notifier(struct notifier_block *notifier,
  6582. + unsigned long pm_event,
  6583. + void *unused)
  6584. +{
  6585. + struct orinoco_private *priv = container_of(notifier,
  6586. + struct orinoco_private,
  6587. + pm_notifier);
  6588. +
  6589. + /* All we need to do is cache the firmware before suspend, and
  6590. + * release it when we come out.
  6591. + *
  6592. + * Only need to do this if we're downloading firmware. */
  6593. + if (!priv->do_fw_download)
  6594. + return NOTIFY_DONE;
  6595. +
  6596. + switch (pm_event) {
  6597. + case PM_HIBERNATION_PREPARE:
  6598. + case PM_SUSPEND_PREPARE:
  6599. + orinoco_cache_fw(priv, 0);
  6600. + break;
  6601. +
  6602. + case PM_POST_RESTORE:
  6603. + /* Restore from hibernation failed. We need to clean
  6604. + * up in exactly the same way, so fall through. */
  6605. + case PM_POST_HIBERNATION:
  6606. + case PM_POST_SUSPEND:
  6607. + orinoco_uncache_fw(priv);
  6608. + break;
  6609. +
  6610. + case PM_RESTORE_PREPARE:
  6611. + default:
  6612. + break;
  6613. + }
  6614. +
  6615. + return NOTIFY_DONE;
  6616. +}
  6617. +
  6618. +static void orinoco_register_pm_notifier(struct orinoco_private *priv)
  6619. +{
  6620. + priv->pm_notifier.notifier_call = orinoco_pm_notifier;
  6621. + register_pm_notifier(&priv->pm_notifier);
  6622. +}
  6623. +
  6624. +static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
  6625. +{
  6626. + unregister_pm_notifier(&priv->pm_notifier);
  6627. +}
  6628. +#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
  6629. +#define orinoco_register_pm_notifier(priv) do { } while (0)
  6630. +#define orinoco_unregister_pm_notifier(priv) do { } while (0)
  6631. +#endif
  6632. +
  6633. +/********************************************************************/
  6634. +/* Initialization */
  6635. +/********************************************************************/
  6636. +
  6637. +int orinoco_init(struct orinoco_private *priv)
  6638. +{
  6639. + struct device *dev = priv->dev;
  6640. + struct wiphy *wiphy = priv_to_wiphy(priv);
  6641. + struct hermes *hw = &priv->hw;
  6642. + int err = 0;
  6643. +
  6644. + /* No need to lock, the hw_unavailable flag is already set in
  6645. + * alloc_orinocodev() */
  6646. + priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
  6647. +
  6648. + /* Initialize the firmware */
  6649. + err = hw->ops->init(hw);
  6650. + if (err != 0) {
  6651. + dev_err(dev, "Failed to initialize firmware (err = %d)\n",
  6652. + err);
  6653. + goto out;
  6654. + }
  6655. +
  6656. + err = determine_fw_capabilities(priv, wiphy->fw_version,
  6657. + sizeof(wiphy->fw_version),
  6658. + &wiphy->hw_version);
  6659. + if (err != 0) {
  6660. + dev_err(dev, "Incompatible firmware, aborting\n");
  6661. + goto out;
  6662. + }
  6663. +
  6664. + if (priv->do_fw_download) {
  6665. +#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
  6666. + orinoco_cache_fw(priv, 0);
  6667. +#endif
  6668. +
  6669. + err = orinoco_download(priv);
  6670. + if (err)
  6671. + priv->do_fw_download = 0;
  6672. +
  6673. + /* Check firmware version again */
  6674. + err = determine_fw_capabilities(priv, wiphy->fw_version,
  6675. + sizeof(wiphy->fw_version),
  6676. + &wiphy->hw_version);
  6677. + if (err != 0) {
  6678. + dev_err(dev, "Incompatible firmware, aborting\n");
  6679. + goto out;
  6680. + }
  6681. + }
  6682. +
  6683. + if (priv->has_port3)
  6684. + dev_info(dev, "Ad-hoc demo mode supported\n");
  6685. + if (priv->has_ibss)
  6686. + dev_info(dev, "IEEE standard IBSS ad-hoc mode supported\n");
  6687. + if (priv->has_wep)
  6688. + dev_info(dev, "WEP supported, %s-bit key\n",
  6689. + priv->has_big_wep ? "104" : "40");
  6690. + if (priv->has_wpa) {
  6691. + dev_info(dev, "WPA-PSK supported\n");
  6692. + if (orinoco_mic_init(priv)) {
  6693. + dev_err(dev, "Failed to setup MIC crypto algorithm. "
  6694. + "Disabling WPA support\n");
  6695. + priv->has_wpa = 0;
  6696. + }
  6697. + }
  6698. +
  6699. + err = orinoco_hw_read_card_settings(priv, wiphy->perm_addr);
  6700. + if (err)
  6701. + goto out;
  6702. +
  6703. + err = orinoco_hw_allocate_fid(priv);
  6704. + if (err) {
  6705. + dev_err(dev, "Failed to allocate NIC buffer!\n");
  6706. + goto out;
  6707. + }
  6708. +
  6709. + /* Set up the default configuration */
  6710. + priv->iw_mode = NL80211_IFTYPE_STATION;
  6711. + /* By default use IEEE/IBSS ad-hoc mode if we have it */
  6712. + priv->prefer_port3 = priv->has_port3 && (!priv->has_ibss);
  6713. + set_port_type(priv);
  6714. + priv->channel = 0; /* use firmware default */
  6715. +
  6716. + priv->promiscuous = 0;
  6717. + priv->encode_alg = ORINOCO_ALG_NONE;
  6718. + priv->tx_key = 0;
  6719. + priv->wpa_enabled = 0;
  6720. + priv->tkip_cm_active = 0;
  6721. + priv->key_mgmt = 0;
  6722. + priv->wpa_ie_len = 0;
  6723. + priv->wpa_ie = NULL;
  6724. +
  6725. + if (orinoco_wiphy_register(wiphy)) {
  6726. + err = -ENODEV;
  6727. + goto out;
  6728. + }
  6729. +
  6730. + /* Make the hardware available, as long as it hasn't been
  6731. + * removed elsewhere (e.g. by PCMCIA hot unplug) */
  6732. + orinoco_lock_irq(priv);
  6733. + priv->hw_unavailable--;
  6734. + orinoco_unlock_irq(priv);
  6735. +
  6736. + dev_dbg(dev, "Ready\n");
  6737. +
  6738. + out:
  6739. + return err;
  6740. +}
  6741. +EXPORT_SYMBOL(orinoco_init);
  6742. +
  6743. +static const struct net_device_ops orinoco_netdev_ops = {
  6744. + .ndo_open = orinoco_open,
  6745. + .ndo_stop = orinoco_stop,
  6746. + .ndo_start_xmit = orinoco_xmit,
  6747. + .ndo_set_rx_mode = orinoco_set_multicast_list,
  6748. + .ndo_change_mtu = orinoco_change_mtu,
  6749. + .ndo_set_mac_address = eth_mac_addr,
  6750. + .ndo_validate_addr = eth_validate_addr,
  6751. + .ndo_tx_timeout = orinoco_tx_timeout,
  6752. +};
  6753. +
  6754. +/* Allocate private data.
  6755. + *
  6756. + * This driver has a number of structures associated with it
  6757. + * netdev - Net device structure for each network interface
  6758. + * wiphy - structure associated with wireless phy
  6759. + * wireless_dev (wdev) - structure for each wireless interface
  6760. + * hw - structure for hermes chip info
  6761. + * card - card specific structure for use by the card driver
  6762. + * (airport, orinoco_cs)
  6763. + * priv - orinoco private data
  6764. + * device - generic linux device structure
  6765. + *
  6766. + * +---------+ +---------+
  6767. + * | wiphy | | netdev |
  6768. + * | +-------+ | +-------+
  6769. + * | | priv | | | wdev |
  6770. + * | | +-----+ +-+-------+
  6771. + * | | | hw |
  6772. + * | +-+-----+
  6773. + * | | card |
  6774. + * +-+-------+
  6775. + *
  6776. + * priv has a link to netdev and device
  6777. + * wdev has a link to wiphy
  6778. + */
  6779. +struct orinoco_private
  6780. +*alloc_orinocodev(int sizeof_card,
  6781. + struct device *device,
  6782. + int (*hard_reset)(struct orinoco_private *),
  6783. + int (*stop_fw)(struct orinoco_private *, int))
  6784. +{
  6785. + struct orinoco_private *priv;
  6786. + struct wiphy *wiphy;
  6787. +
  6788. + /* allocate wiphy
  6789. + * NOTE: We only support a single virtual interface
  6790. + * but this may change when monitor mode is added
  6791. + */
  6792. + wiphy = wiphy_new(&orinoco_cfg_ops,
  6793. + sizeof(struct orinoco_private) + sizeof_card);
  6794. + if (!wiphy)
  6795. + return NULL;
  6796. +
  6797. + priv = wiphy_priv(wiphy);
  6798. + priv->dev = device;
  6799. +
  6800. + if (sizeof_card)
  6801. + priv->card = (void *)((unsigned long)priv
  6802. + + sizeof(struct orinoco_private));
  6803. + else
  6804. + priv->card = NULL;
  6805. +
  6806. + orinoco_wiphy_init(wiphy);
  6807. +
  6808. +#ifdef WIRELESS_SPY
  6809. + priv->wireless_data.spy_data = &priv->spy_data;
  6810. +#endif
  6811. +
  6812. + /* Set up default callbacks */
  6813. + priv->hard_reset = hard_reset;
  6814. + priv->stop_fw = stop_fw;
  6815. +
  6816. + spin_lock_init(&priv->lock);
  6817. + priv->open = 0;
  6818. + priv->hw_unavailable = 1; /* orinoco_init() must clear this
  6819. + * before anything else touches the
  6820. + * hardware */
  6821. + INIT_WORK(&priv->reset_work, orinoco_reset);
  6822. + INIT_WORK(&priv->join_work, orinoco_join_ap);
  6823. + INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
  6824. +
  6825. + INIT_LIST_HEAD(&priv->rx_list);
  6826. + tasklet_setup(&priv->rx_tasklet, orinoco_rx_isr_tasklet);
  6827. +
  6828. + spin_lock_init(&priv->scan_lock);
  6829. + INIT_LIST_HEAD(&priv->scan_list);
  6830. + INIT_WORK(&priv->process_scan, orinoco_process_scan_results);
  6831. +
  6832. + priv->last_linkstatus = 0xffff;
  6833. +
  6834. +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
  6835. + priv->cached_pri_fw = NULL;
  6836. + priv->cached_fw = NULL;
  6837. +#endif
  6838. +
  6839. + /* Register PM notifiers */
  6840. + orinoco_register_pm_notifier(priv);
  6841. +
  6842. + return priv;
  6843. +}
  6844. +EXPORT_SYMBOL(alloc_orinocodev);
  6845. +
  6846. +/* We can only support a single interface. We provide a separate
  6847. + * function to set it up to distinguish between hardware
  6848. + * initialisation and interface setup.
  6849. + *
  6850. + * The base_addr and irq parameters are passed on to netdev for use
  6851. + * with SIOCGIFMAP.
  6852. + */
  6853. +int orinoco_if_add(struct orinoco_private *priv,
  6854. + unsigned long base_addr,
  6855. + unsigned int irq,
  6856. + const struct net_device_ops *ops)
  6857. +{
  6858. + struct wiphy *wiphy = priv_to_wiphy(priv);
  6859. + struct wireless_dev *wdev;
  6860. + struct net_device *dev;
  6861. + int ret;
  6862. +
  6863. + dev = alloc_etherdev(sizeof(struct wireless_dev));
  6864. +
  6865. + if (!dev)
  6866. + return -ENOMEM;
  6867. +
  6868. + /* Initialise wireless_dev */
  6869. + wdev = netdev_priv(dev);
  6870. + wdev->wiphy = wiphy;
  6871. + wdev->iftype = NL80211_IFTYPE_STATION;
  6872. +
  6873. + /* Setup / override net_device fields */
  6874. + dev->ieee80211_ptr = wdev;
  6875. + dev->watchdog_timeo = HZ; /* 1 second timeout */
  6876. + dev->wireless_handlers = &orinoco_handler_def;
  6877. +#ifdef WIRELESS_SPY
  6878. + dev->wireless_data = &priv->wireless_data;
  6879. +#endif
  6880. + /* Default to standard ops if not set */
  6881. + if (ops)
  6882. + dev->netdev_ops = ops;
  6883. + else
  6884. + dev->netdev_ops = &orinoco_netdev_ops;
  6885. +
  6886. + /* we use the default eth_mac_addr for setting the MAC addr */
  6887. +
  6888. + /* Reserve space in skb for the SNAP header */
  6889. + dev->needed_headroom = ENCAPS_OVERHEAD;
  6890. +
  6891. + netif_carrier_off(dev);
  6892. +
  6893. + eth_hw_addr_set(dev, wiphy->perm_addr);
  6894. +
  6895. + dev->base_addr = base_addr;
  6896. + dev->irq = irq;
  6897. +
  6898. + dev->min_mtu = ORINOCO_MIN_MTU;
  6899. + dev->max_mtu = ORINOCO_MAX_MTU;
  6900. +
  6901. + SET_NETDEV_DEV(dev, priv->dev);
  6902. + ret = register_netdev(dev);
  6903. + if (ret)
  6904. + goto fail;
  6905. +
  6906. + priv->ndev = dev;
  6907. +
  6908. + /* Report what we've done */
  6909. + dev_dbg(priv->dev, "Registered interface %s.\n", dev->name);
  6910. +
  6911. + return 0;
  6912. +
  6913. + fail:
  6914. + free_netdev(dev);
  6915. + return ret;
  6916. +}
  6917. +EXPORT_SYMBOL(orinoco_if_add);
  6918. +
  6919. +void orinoco_if_del(struct orinoco_private *priv)
  6920. +{
  6921. + struct net_device *dev = priv->ndev;
  6922. +
  6923. + unregister_netdev(dev);
  6924. + free_netdev(dev);
  6925. +}
  6926. +EXPORT_SYMBOL(orinoco_if_del);
  6927. +
  6928. +void free_orinocodev(struct orinoco_private *priv)
  6929. +{
  6930. + struct wiphy *wiphy = priv_to_wiphy(priv);
  6931. + struct orinoco_rx_data *rx_data, *temp;
  6932. + struct orinoco_scan_data *sd, *sdtemp;
  6933. +
  6934. + /* If the tasklet is scheduled when we call tasklet_kill it
  6935. + * will run one final time. However the tasklet will only
  6936. + * drain priv->rx_list if the hw is still available. */
  6937. + tasklet_kill(&priv->rx_tasklet);
  6938. +
  6939. + /* Explicitly drain priv->rx_list */
  6940. + list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
  6941. + list_del(&rx_data->list);
  6942. +
  6943. + dev_kfree_skb(rx_data->skb);
  6944. + kfree(rx_data->desc);
  6945. + kfree(rx_data);
  6946. + }
  6947. +
  6948. + cancel_work_sync(&priv->process_scan);
  6949. + /* Explicitly drain priv->scan_list */
  6950. + list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) {
  6951. + list_del(&sd->list);
  6952. +
  6953. + if (sd->len > 0)
  6954. + kfree(sd->buf);
  6955. + kfree(sd);
  6956. + }
  6957. +
  6958. + orinoco_unregister_pm_notifier(priv);
  6959. + orinoco_uncache_fw(priv);
  6960. +
  6961. + priv->wpa_ie_len = 0;
  6962. + kfree(priv->wpa_ie);
  6963. + orinoco_mic_free(priv);
  6964. + wiphy_free(wiphy);
  6965. +}
  6966. +EXPORT_SYMBOL(free_orinocodev);
  6967. +
  6968. +int orinoco_up(struct orinoco_private *priv)
  6969. +{
  6970. + struct net_device *dev = priv->ndev;
  6971. + unsigned long flags;
  6972. + int err;
  6973. +
  6974. + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
  6975. +
  6976. + err = orinoco_reinit_firmware(priv);
  6977. + if (err) {
  6978. + printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
  6979. + dev->name, err);
  6980. + goto exit;
  6981. + }
  6982. +
  6983. + netif_device_attach(dev);
  6984. + priv->hw_unavailable--;
  6985. +
  6986. + if (priv->open && !priv->hw_unavailable) {
  6987. + err = __orinoco_up(priv);
  6988. + if (err)
  6989. + printk(KERN_ERR "%s: Error %d restarting card\n",
  6990. + dev->name, err);
  6991. + }
  6992. +
  6993. +exit:
  6994. + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  6995. +
  6996. + return 0;
  6997. +}
  6998. +EXPORT_SYMBOL(orinoco_up);
  6999. +
  7000. +void orinoco_down(struct orinoco_private *priv)
  7001. +{
  7002. + struct net_device *dev = priv->ndev;
  7003. + unsigned long flags;
  7004. + int err;
  7005. +
  7006. + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
  7007. + err = __orinoco_down(priv);
  7008. + if (err)
  7009. + printk(KERN_WARNING "%s: Error %d downing interface\n",
  7010. + dev->name, err);
  7011. +
  7012. + netif_device_detach(dev);
  7013. + priv->hw_unavailable++;
  7014. + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  7015. +}
  7016. +EXPORT_SYMBOL(orinoco_down);
  7017. +
  7018. +/********************************************************************/
  7019. +/* Module initialization */
  7020. +/********************************************************************/
  7021. +
  7022. +/* Can't be declared "const" or the whole __initdata section will
  7023. + * become const */
  7024. +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  7025. + " (David Gibson <hermes@gibson.dropbear.id.au>, "
  7026. + "Pavel Roskin <proski@gnu.org>, et al)";
  7027. +
  7028. +static int __init init_orinoco(void)
  7029. +{
  7030. + printk(KERN_DEBUG "%s\n", version);
  7031. + return 0;
  7032. +}
  7033. +
  7034. +static void __exit exit_orinoco(void)
  7035. +{
  7036. +}
  7037. +
  7038. +module_init(init_orinoco);
  7039. +module_exit(exit_orinoco);
  7040. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/main.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/main.h
  7041. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/main.h 1970-01-01 01:00:00.000000000 +0100
  7042. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/main.h 2025-08-03 15:01:59.349130638 +0200
  7043. @@ -0,0 +1,50 @@
  7044. +/* Exports from main to helper modules
  7045. + *
  7046. + * See copyright notice in main.c
  7047. + */
  7048. +#ifndef _ORINOCO_MAIN_H_
  7049. +#define _ORINOCO_MAIN_H_
  7050. +
  7051. +#include <linux/ieee80211.h>
  7052. +#include "orinoco.h"
  7053. +
  7054. +/********************************************************************/
  7055. +/* Compile time configuration and compatibility stuff */
  7056. +/********************************************************************/
  7057. +
  7058. +/* We do this this way to avoid ifdefs in the actual code */
  7059. +#ifdef WIRELESS_SPY
  7060. +#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
  7061. +#else
  7062. +#define SPY_NUMBER(priv) 0
  7063. +#endif /* WIRELESS_SPY */
  7064. +
  7065. +/********************************************************************/
  7066. +
  7067. +/* Export module parameter */
  7068. +extern int force_monitor;
  7069. +
  7070. +/* Forward declarations */
  7071. +struct net_device;
  7072. +struct work_struct;
  7073. +
  7074. +void set_port_type(struct orinoco_private *priv);
  7075. +int orinoco_commit(struct orinoco_private *priv);
  7076. +void orinoco_reset(struct work_struct *work);
  7077. +
  7078. +/* Information element helpers - find a home for these... */
  7079. +#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
  7080. +#define WPA_SELECTOR_LEN 4
  7081. +static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
  7082. +{
  7083. + u8 *p = data;
  7084. + while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
  7085. + if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) &&
  7086. + (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
  7087. + return p;
  7088. + p += p[1] + 2;
  7089. + }
  7090. + return NULL;
  7091. +}
  7092. +
  7093. +#endif /* _ORINOCO_MAIN_H_ */
  7094. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/Makefile linux-6.15.6/drivers/net/wireless/intersil/orinoco/Makefile
  7095. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/Makefile 1970-01-01 01:00:00.000000000 +0100
  7096. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/Makefile 2025-08-03 15:01:59.349130638 +0200
  7097. @@ -0,0 +1,15 @@
  7098. +# SPDX-License-Identifier: GPL-2.0
  7099. +#
  7100. +# Makefile for the orinoco wireless device drivers.
  7101. +#
  7102. +orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o hermes_dld.o hermes.o cfg.o
  7103. +
  7104. +obj-$(CONFIG_HERMES) += orinoco.o
  7105. +obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
  7106. +obj-$(CONFIG_APPLE_AIRPORT) += airport.o
  7107. +obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
  7108. +obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
  7109. +obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
  7110. +obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
  7111. +obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
  7112. +obj-$(CONFIG_ORINOCO_USB) += orinoco_usb.o
  7113. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/mic.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/mic.c
  7114. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/mic.c 1970-01-01 01:00:00.000000000 +0100
  7115. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/mic.c 2025-08-03 15:01:59.349130638 +0200
  7116. @@ -0,0 +1,89 @@
  7117. +/* Orinoco MIC helpers
  7118. + *
  7119. + * See copyright notice in main.c
  7120. + */
  7121. +#include <linux/kernel.h>
  7122. +#include <linux/string.h>
  7123. +#include <linux/if_ether.h>
  7124. +#include <linux/scatterlist.h>
  7125. +#include <crypto/hash.h>
  7126. +
  7127. +#include "orinoco.h"
  7128. +#include "mic.h"
  7129. +
  7130. +/********************************************************************/
  7131. +/* Michael MIC crypto setup */
  7132. +/********************************************************************/
  7133. +int orinoco_mic_init(struct orinoco_private *priv)
  7134. +{
  7135. + priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
  7136. + if (IS_ERR(priv->tx_tfm_mic)) {
  7137. + printk(KERN_DEBUG "%s: could not allocate "
  7138. + "crypto API michael_mic\n", __func__);
  7139. + priv->tx_tfm_mic = NULL;
  7140. + return -ENOMEM;
  7141. + }
  7142. +
  7143. + priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
  7144. + if (IS_ERR(priv->rx_tfm_mic)) {
  7145. + printk(KERN_DEBUG "%s: could not allocate "
  7146. + "crypto API michael_mic\n", __func__);
  7147. + priv->rx_tfm_mic = NULL;
  7148. + return -ENOMEM;
  7149. + }
  7150. +
  7151. + return 0;
  7152. +}
  7153. +
  7154. +void orinoco_mic_free(struct orinoco_private *priv)
  7155. +{
  7156. + if (priv->tx_tfm_mic)
  7157. + crypto_free_shash(priv->tx_tfm_mic);
  7158. + if (priv->rx_tfm_mic)
  7159. + crypto_free_shash(priv->rx_tfm_mic);
  7160. +}
  7161. +
  7162. +int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
  7163. + u8 *da, u8 *sa, u8 priority,
  7164. + u8 *data, size_t data_len, u8 *mic)
  7165. +{
  7166. + SHASH_DESC_ON_STACK(desc, tfm_michael);
  7167. + u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
  7168. + int err;
  7169. +
  7170. + if (tfm_michael == NULL) {
  7171. + printk(KERN_WARNING "%s: tfm_michael == NULL\n", __func__);
  7172. + return -1;
  7173. + }
  7174. +
  7175. + /* Copy header into buffer. We need the padding on the end zeroed */
  7176. + memcpy(&hdr[0], da, ETH_ALEN);
  7177. + memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
  7178. + hdr[ETH_ALEN * 2] = priority;
  7179. + hdr[ETH_ALEN * 2 + 1] = 0;
  7180. + hdr[ETH_ALEN * 2 + 2] = 0;
  7181. + hdr[ETH_ALEN * 2 + 3] = 0;
  7182. +
  7183. + desc->tfm = tfm_michael;
  7184. +
  7185. + err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
  7186. + if (err)
  7187. + return err;
  7188. +
  7189. + err = crypto_shash_init(desc);
  7190. + if (err)
  7191. + return err;
  7192. +
  7193. + err = crypto_shash_update(desc, hdr, sizeof(hdr));
  7194. + if (err)
  7195. + return err;
  7196. +
  7197. + err = crypto_shash_update(desc, data, data_len);
  7198. + if (err)
  7199. + return err;
  7200. +
  7201. + err = crypto_shash_final(desc, mic);
  7202. + shash_desc_zero(desc);
  7203. +
  7204. + return err;
  7205. +}
  7206. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/mic.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/mic.h
  7207. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/mic.h 1970-01-01 01:00:00.000000000 +0100
  7208. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/mic.h 2025-08-03 15:01:59.349130638 +0200
  7209. @@ -0,0 +1,23 @@
  7210. +/* Orinoco MIC helpers
  7211. + *
  7212. + * See copyright notice in main.c
  7213. + */
  7214. +#ifndef _ORINOCO_MIC_H_
  7215. +#define _ORINOCO_MIC_H_
  7216. +
  7217. +#include <linux/types.h>
  7218. +#include <crypto/hash.h>
  7219. +
  7220. +#define MICHAEL_MIC_LEN 8
  7221. +
  7222. +/* Forward declarations */
  7223. +struct orinoco_private;
  7224. +struct crypto_ahash;
  7225. +
  7226. +int orinoco_mic_init(struct orinoco_private *priv);
  7227. +void orinoco_mic_free(struct orinoco_private *priv);
  7228. +int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
  7229. + u8 *da, u8 *sa, u8 priority,
  7230. + u8 *data, size_t data_len, u8 *mic);
  7231. +
  7232. +#endif /* ORINOCO_MIC_H */
  7233. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_cs.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
  7234. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_cs.c 1970-01-01 01:00:00.000000000 +0100
  7235. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_cs.c 2025-08-03 15:01:59.353130523 +0200
  7236. @@ -0,0 +1,350 @@
  7237. +/* orinoco_cs.c (formerly known as dldwd_cs.c)
  7238. + *
  7239. + * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  7240. + * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
  7241. + * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
  7242. + * It should also be usable on various Prism II based cards such as the
  7243. + * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
  7244. + * cards such as the 3Com AirConnect and Ericsson WLAN.
  7245. + *
  7246. + * Copyright notice & release notes in file main.c
  7247. + */
  7248. +
  7249. +#define DRIVER_NAME "orinoco_cs"
  7250. +#define PFX DRIVER_NAME ": "
  7251. +
  7252. +#include <linux/module.h>
  7253. +#include <linux/kernel.h>
  7254. +#include <linux/delay.h>
  7255. +#include <pcmcia/cistpl.h>
  7256. +#include <pcmcia/cisreg.h>
  7257. +#include <pcmcia/ds.h>
  7258. +
  7259. +#include "orinoco.h"
  7260. +
  7261. +/********************************************************************/
  7262. +/* Module stuff */
  7263. +/********************************************************************/
  7264. +
  7265. +MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
  7266. +MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco,"
  7267. + " Prism II based and similar wireless cards");
  7268. +MODULE_LICENSE("Dual MPL/GPL");
  7269. +
  7270. +/* Module parameters */
  7271. +
  7272. +/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
  7273. + * don't have any CIS entry for it. This workaround it... */
  7274. +static int ignore_cis_vcc; /* = 0 */
  7275. +module_param(ignore_cis_vcc, int, 0);
  7276. +MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
  7277. +
  7278. +/********************************************************************/
  7279. +/* Data structures */
  7280. +/********************************************************************/
  7281. +
  7282. +/* PCMCIA specific device information (goes in the card field of
  7283. + * struct orinoco_private */
  7284. +struct orinoco_pccard {
  7285. + struct pcmcia_device *p_dev;
  7286. +
  7287. + /* Used to handle hard reset */
  7288. + /* yuck, we need this hack to work around the insanity of the
  7289. + * PCMCIA layer */
  7290. + unsigned long hard_reset_in_progress;
  7291. +};
  7292. +
  7293. +
  7294. +/********************************************************************/
  7295. +/* Function prototypes */
  7296. +/********************************************************************/
  7297. +
  7298. +static int orinoco_cs_config(struct pcmcia_device *link);
  7299. +static void orinoco_cs_release(struct pcmcia_device *link);
  7300. +static void orinoco_cs_detach(struct pcmcia_device *p_dev);
  7301. +
  7302. +/********************************************************************/
  7303. +/* Device methods */
  7304. +/********************************************************************/
  7305. +
  7306. +static int
  7307. +orinoco_cs_hard_reset(struct orinoco_private *priv)
  7308. +{
  7309. + struct orinoco_pccard *card = priv->card;
  7310. + struct pcmcia_device *link = card->p_dev;
  7311. + int err;
  7312. +
  7313. + /* We need atomic ops here, because we're not holding the lock */
  7314. + set_bit(0, &card->hard_reset_in_progress);
  7315. +
  7316. + err = pcmcia_reset_card(link->socket);
  7317. + if (err)
  7318. + return err;
  7319. +
  7320. + msleep(100);
  7321. + clear_bit(0, &card->hard_reset_in_progress);
  7322. +
  7323. + return 0;
  7324. +}
  7325. +
  7326. +/********************************************************************/
  7327. +/* PCMCIA stuff */
  7328. +/********************************************************************/
  7329. +
  7330. +static int
  7331. +orinoco_cs_probe(struct pcmcia_device *link)
  7332. +{
  7333. + struct orinoco_private *priv;
  7334. + struct orinoco_pccard *card;
  7335. + int ret;
  7336. +
  7337. + priv = alloc_orinocodev(sizeof(*card), &link->dev,
  7338. + orinoco_cs_hard_reset, NULL);
  7339. + if (!priv)
  7340. + return -ENOMEM;
  7341. + card = priv->card;
  7342. +
  7343. + /* Link both structures together */
  7344. + card->p_dev = link;
  7345. + link->priv = priv;
  7346. +
  7347. + ret = orinoco_cs_config(link);
  7348. + if (ret)
  7349. + goto err_free_orinocodev;
  7350. +
  7351. + return 0;
  7352. +
  7353. +err_free_orinocodev:
  7354. + free_orinocodev(priv);
  7355. + return ret;
  7356. +}
  7357. +
  7358. +static void orinoco_cs_detach(struct pcmcia_device *link)
  7359. +{
  7360. + struct orinoco_private *priv = link->priv;
  7361. +
  7362. + orinoco_if_del(priv);
  7363. +
  7364. + orinoco_cs_release(link);
  7365. +
  7366. + wiphy_unregister(priv_to_wiphy(priv));
  7367. + free_orinocodev(priv);
  7368. +} /* orinoco_cs_detach */
  7369. +
  7370. +static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
  7371. +{
  7372. + if (p_dev->config_index == 0)
  7373. + return -EINVAL;
  7374. +
  7375. + return pcmcia_request_io(p_dev);
  7376. +};
  7377. +
  7378. +static int
  7379. +orinoco_cs_config(struct pcmcia_device *link)
  7380. +{
  7381. + struct orinoco_private *priv = link->priv;
  7382. + struct hermes *hw = &priv->hw;
  7383. + int ret;
  7384. + void __iomem *mem;
  7385. +
  7386. + link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
  7387. + CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
  7388. + if (ignore_cis_vcc)
  7389. + link->config_flags &= ~CONF_AUTO_CHECK_VCC;
  7390. + ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
  7391. + if (ret) {
  7392. + if (!ignore_cis_vcc)
  7393. + printk(KERN_ERR PFX "GetNextTuple(): No matching "
  7394. + "CIS configuration. Maybe you need the "
  7395. + "ignore_cis_vcc=1 parameter.\n");
  7396. + goto failed;
  7397. + }
  7398. +
  7399. + mem = ioport_map(link->resource[0]->start,
  7400. + resource_size(link->resource[0]));
  7401. + if (!mem)
  7402. + goto failed;
  7403. +
  7404. + /* We initialize the hermes structure before completing PCMCIA
  7405. + * configuration just in case the interrupt handler gets
  7406. + * called. */
  7407. + hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
  7408. +
  7409. + ret = pcmcia_request_irq(link, orinoco_interrupt);
  7410. + if (ret)
  7411. + goto failed;
  7412. +
  7413. + ret = pcmcia_enable_device(link);
  7414. + if (ret)
  7415. + goto failed;
  7416. +
  7417. + /* Initialise the main driver */
  7418. + if (orinoco_init(priv) != 0) {
  7419. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  7420. + goto failed;
  7421. + }
  7422. +
  7423. + /* Register an interface with the stack */
  7424. + if (orinoco_if_add(priv, link->resource[0]->start,
  7425. + link->irq, NULL) != 0) {
  7426. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  7427. + goto failed;
  7428. + }
  7429. +
  7430. + return 0;
  7431. +
  7432. + failed:
  7433. + orinoco_cs_release(link);
  7434. + return -ENODEV;
  7435. +} /* orinoco_cs_config */
  7436. +
  7437. +static void
  7438. +orinoco_cs_release(struct pcmcia_device *link)
  7439. +{
  7440. + struct orinoco_private *priv = link->priv;
  7441. + unsigned long flags;
  7442. +
  7443. + /* We're committed to taking the device away now, so mark the
  7444. + * hardware as unavailable */
  7445. + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
  7446. + priv->hw_unavailable++;
  7447. + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  7448. +
  7449. + pcmcia_disable_device(link);
  7450. + if (priv->hw.iobase)
  7451. + ioport_unmap(priv->hw.iobase);
  7452. +} /* orinoco_cs_release */
  7453. +
  7454. +static int orinoco_cs_suspend(struct pcmcia_device *link)
  7455. +{
  7456. + struct orinoco_private *priv = link->priv;
  7457. + struct orinoco_pccard *card = priv->card;
  7458. +
  7459. + /* This is probably racy, but I can't think of
  7460. + a better way, short of rewriting the PCMCIA
  7461. + layer to not suck :-( */
  7462. + if (!test_bit(0, &card->hard_reset_in_progress))
  7463. + orinoco_down(priv);
  7464. +
  7465. + return 0;
  7466. +}
  7467. +
  7468. +static int orinoco_cs_resume(struct pcmcia_device *link)
  7469. +{
  7470. + struct orinoco_private *priv = link->priv;
  7471. + struct orinoco_pccard *card = priv->card;
  7472. + int err = 0;
  7473. +
  7474. + if (!test_bit(0, &card->hard_reset_in_progress))
  7475. + err = orinoco_up(priv);
  7476. +
  7477. + return err;
  7478. +}
  7479. +
  7480. +
  7481. +/********************************************************************/
  7482. +/* Module initialization */
  7483. +/********************************************************************/
  7484. +
  7485. +static const struct pcmcia_device_id orinoco_cs_ids[] = {
  7486. + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
  7487. + PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
  7488. + PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
  7489. + PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
  7490. + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
  7491. + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
  7492. + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
  7493. + PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
  7494. + PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
  7495. + PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
  7496. + PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
  7497. + PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
  7498. + PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
  7499. + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
  7500. + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
  7501. + PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
  7502. + PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
  7503. + PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
  7504. + PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
  7505. + PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
  7506. + PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
  7507. + PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
  7508. + PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
  7509. + PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
  7510. + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
  7511. + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
  7512. + PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
  7513. + PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
  7514. + PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
  7515. + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
  7516. + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
  7517. + PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
  7518. + PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
  7519. + PCMCIA_DEVICE_MANF_CARD_PROD_ID3(0x0156, 0x0002, "Version 01.01", 0xd27deb1a), /* Lucent Orinoco */
  7520. +#ifdef CONFIG_HERMES_PRISM
  7521. + /* Only entries that certainly identify Prism chipset */
  7522. + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
  7523. + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
  7524. + PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
  7525. + PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
  7526. + PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
  7527. + PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
  7528. + PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
  7529. + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
  7530. + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
  7531. + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
  7532. + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
  7533. + PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
  7534. + PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
  7535. + PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
  7536. + PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
  7537. + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
  7538. + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
  7539. + PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
  7540. + PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
  7541. + PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
  7542. + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
  7543. + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
  7544. + PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
  7545. + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
  7546. + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
  7547. + PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
  7548. + PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
  7549. + PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
  7550. + PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
  7551. + PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
  7552. + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
  7553. + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
  7554. + PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
  7555. + PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
  7556. + PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
  7557. + PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
  7558. + PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
  7559. + PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
  7560. + PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
  7561. + PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
  7562. + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
  7563. + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
  7564. + PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
  7565. + PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
  7566. + PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
  7567. + PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
  7568. + PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
  7569. +
  7570. + /* This may be Agere or Intersil Firmware */
  7571. + PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
  7572. +#endif
  7573. + PCMCIA_DEVICE_NULL,
  7574. +};
  7575. +MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
  7576. +
  7577. +static struct pcmcia_driver orinoco_driver = {
  7578. + .owner = THIS_MODULE,
  7579. + .name = DRIVER_NAME,
  7580. + .probe = orinoco_cs_probe,
  7581. + .remove = orinoco_cs_detach,
  7582. + .id_table = orinoco_cs_ids,
  7583. + .suspend = orinoco_cs_suspend,
  7584. + .resume = orinoco_cs_resume,
  7585. +};
  7586. +module_pcmcia_driver(orinoco_driver);
  7587. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco.h
  7588. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco.h 1970-01-01 01:00:00.000000000 +0100
  7589. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco.h 2025-08-03 22:43:06.558981951 +0200
  7590. @@ -0,0 +1,249 @@
  7591. +/* orinoco.h
  7592. + *
  7593. + * Common definitions to all pieces of the various orinoco
  7594. + * drivers
  7595. + */
  7596. +
  7597. +#ifndef _ORINOCO_H
  7598. +#define _ORINOCO_H
  7599. +
  7600. +#define DRIVER_VERSION "0.15"
  7601. +
  7602. +#include <linux/interrupt.h>
  7603. +#include <linux/suspend.h>
  7604. +#include <linux/netdevice.h>
  7605. +#include <linux/wireless.h>
  7606. +#include <net/iw_handler.h>
  7607. +#include <net/cfg80211.h>
  7608. +
  7609. +#include "hermes.h"
  7610. +
  7611. +/* To enable debug messages */
  7612. +/*#define ORINOCO_DEBUG 3*/
  7613. +
  7614. +#define MAX_SCAN_LEN 4096
  7615. +
  7616. +#define ORINOCO_SEQ_LEN 8
  7617. +#define ORINOCO_MAX_KEY_SIZE 14
  7618. +#define ORINOCO_MAX_KEYS 4
  7619. +
  7620. +struct orinoco_key {
  7621. + __le16 len; /* always stored as little-endian */
  7622. + char data[ORINOCO_MAX_KEY_SIZE];
  7623. +} __packed;
  7624. +
  7625. +#define TKIP_KEYLEN 16
  7626. +#define MIC_KEYLEN 8
  7627. +
  7628. +struct orinoco_tkip_key {
  7629. + u8 tkip[TKIP_KEYLEN];
  7630. + u8 tx_mic[MIC_KEYLEN];
  7631. + u8 rx_mic[MIC_KEYLEN];
  7632. +};
  7633. +
  7634. +enum orinoco_alg {
  7635. + ORINOCO_ALG_NONE,
  7636. + ORINOCO_ALG_WEP,
  7637. + ORINOCO_ALG_TKIP
  7638. +};
  7639. +
  7640. +enum fwtype {
  7641. + FIRMWARE_TYPE_AGERE,
  7642. + FIRMWARE_TYPE_INTERSIL,
  7643. + FIRMWARE_TYPE_SYMBOL
  7644. +};
  7645. +
  7646. +struct firmware;
  7647. +
  7648. +struct orinoco_private {
  7649. + void *card; /* Pointer to card dependent structure */
  7650. + struct device *dev;
  7651. + int (*hard_reset)(struct orinoco_private *);
  7652. + int (*stop_fw)(struct orinoco_private *, int);
  7653. +
  7654. + struct ieee80211_supported_band band;
  7655. + struct ieee80211_channel channels[14];
  7656. + u32 cipher_suites[3];
  7657. +
  7658. + /* Synchronisation stuff */
  7659. + spinlock_t lock;
  7660. + int hw_unavailable;
  7661. + struct work_struct reset_work;
  7662. +
  7663. + /* Interrupt tasklets */
  7664. + struct tasklet_struct rx_tasklet;
  7665. + struct list_head rx_list;
  7666. +
  7667. + /* driver state */
  7668. + int open;
  7669. + u16 last_linkstatus;
  7670. + struct work_struct join_work;
  7671. + struct work_struct wevent_work;
  7672. +
  7673. + /* Net device stuff */
  7674. + struct net_device *ndev;
  7675. + struct iw_statistics wstats;
  7676. +
  7677. + /* Hardware control variables */
  7678. + struct hermes hw;
  7679. + u16 txfid;
  7680. +
  7681. + /* Capabilities of the hardware/firmware */
  7682. + enum fwtype firmware_type;
  7683. + int ibss_port;
  7684. + int nicbuf_size;
  7685. + u16 channel_mask;
  7686. +
  7687. + /* Boolean capabilities */
  7688. + unsigned int has_ibss:1;
  7689. + unsigned int has_port3:1;
  7690. + unsigned int has_wep:1;
  7691. + unsigned int has_big_wep:1;
  7692. + unsigned int has_mwo:1;
  7693. + unsigned int has_pm:1;
  7694. + unsigned int has_preamble:1;
  7695. + unsigned int has_sensitivity:1;
  7696. + unsigned int has_hostscan:1;
  7697. + unsigned int has_alt_txcntl:1;
  7698. + unsigned int has_ext_scan:1;
  7699. + unsigned int has_wpa:1;
  7700. + unsigned int do_fw_download:1;
  7701. + unsigned int broken_disableport:1;
  7702. + unsigned int broken_monitor:1;
  7703. + unsigned int prefer_port3:1;
  7704. +
  7705. + /* Configuration paramaters */
  7706. + enum nl80211_iftype iw_mode;
  7707. + enum orinoco_alg encode_alg;
  7708. + u16 wep_restrict, tx_key;
  7709. + struct key_params keys[ORINOCO_MAX_KEYS];
  7710. +
  7711. + int bitratemode;
  7712. + char nick[IW_ESSID_MAX_SIZE + 1];
  7713. + char desired_essid[IW_ESSID_MAX_SIZE + 1];
  7714. + char desired_bssid[ETH_ALEN];
  7715. + int bssid_fixed;
  7716. + u16 frag_thresh, mwo_robust;
  7717. + u16 channel;
  7718. + u16 ap_density, rts_thresh;
  7719. + u16 pm_on, pm_mcast, pm_period, pm_timeout;
  7720. + u16 preamble;
  7721. + u16 short_retry_limit, long_retry_limit;
  7722. + u16 retry_lifetime;
  7723. +#ifdef WIRELESS_SPY
  7724. + struct iw_spy_data spy_data; /* iwspy support */
  7725. + struct iw_public_data wireless_data;
  7726. +#endif
  7727. +
  7728. + /* Configuration dependent variables */
  7729. + int port_type, createibss;
  7730. + int promiscuous, mc_count;
  7731. +
  7732. + /* Scanning support */
  7733. + struct cfg80211_scan_request *scan_request;
  7734. + struct work_struct process_scan;
  7735. + struct list_head scan_list;
  7736. + spinlock_t scan_lock; /* protects the scan list */
  7737. +
  7738. + /* WPA support */
  7739. + u8 *wpa_ie;
  7740. + int wpa_ie_len;
  7741. +
  7742. + struct crypto_shash *rx_tfm_mic;
  7743. + struct crypto_shash *tx_tfm_mic;
  7744. +
  7745. + unsigned int wpa_enabled:1;
  7746. + unsigned int tkip_cm_active:1;
  7747. + unsigned int key_mgmt:3;
  7748. +
  7749. +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
  7750. + /* Cached in memory firmware to use during ->resume. */
  7751. + const struct firmware *cached_pri_fw;
  7752. + const struct firmware *cached_fw;
  7753. +#endif
  7754. +
  7755. + struct notifier_block pm_notifier;
  7756. +};
  7757. +
  7758. +#ifdef ORINOCO_DEBUG
  7759. +extern int orinoco_debug;
  7760. +#define DEBUG(n, args...) do { \
  7761. + if (orinoco_debug > (n)) \
  7762. + printk(KERN_DEBUG args); \
  7763. +} while (0)
  7764. +#else
  7765. +#define DEBUG(n, args...) do { } while (0)
  7766. +#endif /* ORINOCO_DEBUG */
  7767. +
  7768. +/********************************************************************/
  7769. +/* Exported prototypes */
  7770. +/********************************************************************/
  7771. +
  7772. +struct orinoco_private *alloc_orinocodev(int sizeof_card, struct device *device,
  7773. + int (*hard_reset)(struct orinoco_private *),
  7774. + int (*stop_fw)(struct orinoco_private *, int));
  7775. +void free_orinocodev(struct orinoco_private *priv);
  7776. +int orinoco_init(struct orinoco_private *priv);
  7777. +int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr,
  7778. + unsigned int irq, const struct net_device_ops *ops);
  7779. +void orinoco_if_del(struct orinoco_private *priv);
  7780. +int orinoco_up(struct orinoco_private *priv);
  7781. +void orinoco_down(struct orinoco_private *priv);
  7782. +irqreturn_t orinoco_interrupt(int irq, void *dev_id);
  7783. +
  7784. +void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
  7785. +void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
  7786. +
  7787. +int orinoco_process_xmit_skb(struct sk_buff *skb,
  7788. + struct net_device *dev,
  7789. + struct orinoco_private *priv,
  7790. + int *tx_control,
  7791. + u8 *mic);
  7792. +
  7793. +/* Common ndo functions exported for reuse by orinoco_usb */
  7794. +int orinoco_open(struct net_device *dev);
  7795. +int orinoco_stop(struct net_device *dev);
  7796. +void orinoco_set_multicast_list(struct net_device *dev);
  7797. +int orinoco_change_mtu(struct net_device *dev, int new_mtu);
  7798. +void orinoco_tx_timeout(struct net_device *dev, unsigned int txqueue);
  7799. +
  7800. +/********************************************************************/
  7801. +/* Locking and synchronization functions */
  7802. +/********************************************************************/
  7803. +
  7804. +static inline int orinoco_lock(struct orinoco_private *priv,
  7805. + unsigned long *flags)
  7806. +{
  7807. + priv->hw.ops->lock_irqsave(&priv->lock, flags);
  7808. + if (priv->hw_unavailable) {
  7809. + DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
  7810. + priv->ndev);
  7811. + priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
  7812. + return -EBUSY;
  7813. + }
  7814. + return 0;
  7815. +}
  7816. +
  7817. +static inline void orinoco_unlock(struct orinoco_private *priv,
  7818. + unsigned long *flags)
  7819. +{
  7820. + priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
  7821. +}
  7822. +
  7823. +static inline void orinoco_lock_irq(struct orinoco_private *priv)
  7824. +{
  7825. + priv->hw.ops->lock_irq(&priv->lock);
  7826. +}
  7827. +
  7828. +static inline void orinoco_unlock_irq(struct orinoco_private *priv)
  7829. +{
  7830. + priv->hw.ops->unlock_irq(&priv->lock);
  7831. +}
  7832. +
  7833. +/*** Navigate from net_device to orinoco_private ***/
  7834. +static inline struct orinoco_private *ndev_priv(struct net_device *dev)
  7835. +{
  7836. + struct wireless_dev *wdev = netdev_priv(dev);
  7837. + return wdev_priv(wdev);
  7838. +}
  7839. +#endif /* _ORINOCO_H */
  7840. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_nortel.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_nortel.c
  7841. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_nortel.c 1970-01-01 01:00:00.000000000 +0100
  7842. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_nortel.c 2025-08-03 15:01:59.353130523 +0200
  7843. @@ -0,0 +1,314 @@
  7844. +/* orinoco_nortel.c
  7845. + *
  7846. + * Driver for Prism II devices which would usually be driven by orinoco_cs,
  7847. + * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in
  7848. + * Nortel emobility, Symbol LA-4113 and Symbol LA-4123.
  7849. + *
  7850. + * Copyright (C) 2002 Tobias Hoffmann
  7851. + * (C) 2003 Christoph Jungegger <disdos@traum404.de>
  7852. + *
  7853. + * Some of this code is borrowed from orinoco_plx.c
  7854. + * Copyright (C) 2001 Daniel Barlow
  7855. + * Some of this code is borrowed from orinoco_pci.c
  7856. + * Copyright (C) 2001 Jean Tourrilhes
  7857. + * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
  7858. + * has been copied from it. linux-wlan-ng-0.1.10 is originally :
  7859. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  7860. + *
  7861. + * The contents of this file are subject to the Mozilla Public License
  7862. + * Version 1.1 (the "License"); you may not use this file except in
  7863. + * compliance with the License. You may obtain a copy of the License
  7864. + * at http://www.mozilla.org/MPL/
  7865. + *
  7866. + * Software distributed under the License is distributed on an "AS IS"
  7867. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  7868. + * the License for the specific language governing rights and
  7869. + * limitations under the License.
  7870. + *
  7871. + * Alternatively, the contents of this file may be used under the
  7872. + * terms of the GNU General Public License version 2 (the "GPL"), in
  7873. + * which case the provisions of the GPL are applicable instead of the
  7874. + * above. If you wish to allow the use of your version of this file
  7875. + * only under the terms of the GPL and not to allow others to use your
  7876. + * version of this file under the MPL, indicate your decision by
  7877. + * deleting the provisions above and replace them with the notice and
  7878. + * other provisions required by the GPL. If you do not delete the
  7879. + * provisions above, a recipient may use your version of this file
  7880. + * under either the MPL or the GPL.
  7881. + */
  7882. +
  7883. +#define DRIVER_NAME "orinoco_nortel"
  7884. +#define PFX DRIVER_NAME ": "
  7885. +
  7886. +#include <linux/module.h>
  7887. +#include <linux/kernel.h>
  7888. +#include <linux/init.h>
  7889. +#include <linux/delay.h>
  7890. +#include <linux/pci.h>
  7891. +#include <pcmcia/cisreg.h>
  7892. +
  7893. +#include "orinoco.h"
  7894. +#include "orinoco_pci.h"
  7895. +
  7896. +#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
  7897. +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
  7898. +
  7899. +
  7900. +/*
  7901. + * Do a soft reset of the card using the Configuration Option Register
  7902. + * We need this to get going...
  7903. + * This is the part of the code that is strongly inspired from wlan-ng
  7904. + *
  7905. + * Note bis : Don't try to access HERMES_CMD during the reset phase.
  7906. + * It just won't work !
  7907. + */
  7908. +static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
  7909. +{
  7910. + struct orinoco_pci_card *card = priv->card;
  7911. +
  7912. + /* Assert the reset until the card notices */
  7913. + iowrite16(8, card->bridge_io + 2);
  7914. + ioread16(card->attr_io + COR_OFFSET);
  7915. + iowrite16(0x80, card->attr_io + COR_OFFSET);
  7916. + mdelay(1);
  7917. +
  7918. + /* Give time for the card to recover from this hard effort */
  7919. + iowrite16(0, card->attr_io + COR_OFFSET);
  7920. + iowrite16(0, card->attr_io + COR_OFFSET);
  7921. + mdelay(1);
  7922. +
  7923. + /* Set COR as usual */
  7924. + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
  7925. + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
  7926. + mdelay(1);
  7927. +
  7928. + iowrite16(0x228, card->bridge_io + 2);
  7929. +
  7930. + return 0;
  7931. +}
  7932. +
  7933. +static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
  7934. +{
  7935. + int i;
  7936. + u32 reg;
  7937. +
  7938. + /* Setup bridge */
  7939. + if (ioread16(card->bridge_io) & 1) {
  7940. + printk(KERN_ERR PFX "brg1 answer1 wrong\n");
  7941. + return -EBUSY;
  7942. + }
  7943. + iowrite16(0x118, card->bridge_io + 2);
  7944. + iowrite16(0x108, card->bridge_io + 2);
  7945. + mdelay(30);
  7946. + iowrite16(0x8, card->bridge_io + 2);
  7947. + for (i = 0; i < 30; i++) {
  7948. + mdelay(30);
  7949. + if (ioread16(card->bridge_io) & 0x10)
  7950. + break;
  7951. + }
  7952. + if (i == 30) {
  7953. + printk(KERN_ERR PFX "brg1 timed out\n");
  7954. + return -EBUSY;
  7955. + }
  7956. + if (ioread16(card->attr_io + COR_OFFSET) & 1) {
  7957. + printk(KERN_ERR PFX "brg2 answer1 wrong\n");
  7958. + return -EBUSY;
  7959. + }
  7960. + if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
  7961. + printk(KERN_ERR PFX "brg2 answer2 wrong\n");
  7962. + return -EBUSY;
  7963. + }
  7964. + if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
  7965. + printk(KERN_ERR PFX "brg2 answer3 wrong\n");
  7966. + return -EBUSY;
  7967. + }
  7968. +
  7969. + /* Set the PCMCIA COR register */
  7970. + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
  7971. + mdelay(1);
  7972. + reg = ioread16(card->attr_io + COR_OFFSET);
  7973. + if (reg != COR_VALUE) {
  7974. + printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
  7975. + reg);
  7976. + return -EBUSY;
  7977. + }
  7978. +
  7979. + /* Set LEDs */
  7980. + iowrite16(1, card->bridge_io + 10);
  7981. + return 0;
  7982. +}
  7983. +
  7984. +static int orinoco_nortel_init_one(struct pci_dev *pdev,
  7985. + const struct pci_device_id *ent)
  7986. +{
  7987. + int err;
  7988. + struct orinoco_private *priv;
  7989. + struct orinoco_pci_card *card;
  7990. + void __iomem *hermes_io, *bridge_io, *attr_io;
  7991. +
  7992. + err = pci_enable_device(pdev);
  7993. + if (err) {
  7994. + printk(KERN_ERR PFX "Cannot enable PCI device\n");
  7995. + return err;
  7996. + }
  7997. +
  7998. + err = pci_request_regions(pdev, DRIVER_NAME);
  7999. + if (err) {
  8000. + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
  8001. + goto fail_resources;
  8002. + }
  8003. +
  8004. + bridge_io = pci_iomap(pdev, 0, 0);
  8005. + if (!bridge_io) {
  8006. + printk(KERN_ERR PFX "Cannot map bridge registers\n");
  8007. + err = -EIO;
  8008. + goto fail_map_bridge;
  8009. + }
  8010. +
  8011. + attr_io = pci_iomap(pdev, 1, 0);
  8012. + if (!attr_io) {
  8013. + printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
  8014. + err = -EIO;
  8015. + goto fail_map_attr;
  8016. + }
  8017. +
  8018. + hermes_io = pci_iomap(pdev, 2, 0);
  8019. + if (!hermes_io) {
  8020. + printk(KERN_ERR PFX "Cannot map chipset registers\n");
  8021. + err = -EIO;
  8022. + goto fail_map_hermes;
  8023. + }
  8024. +
  8025. + /* Allocate network device */
  8026. + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
  8027. + orinoco_nortel_cor_reset, NULL);
  8028. + if (!priv) {
  8029. + printk(KERN_ERR PFX "Cannot allocate network device\n");
  8030. + err = -ENOMEM;
  8031. + goto fail_alloc;
  8032. + }
  8033. +
  8034. + card = priv->card;
  8035. + card->bridge_io = bridge_io;
  8036. + card->attr_io = attr_io;
  8037. +
  8038. + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
  8039. +
  8040. + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
  8041. + DRIVER_NAME, priv);
  8042. + if (err) {
  8043. + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
  8044. + err = -EBUSY;
  8045. + goto fail_irq;
  8046. + }
  8047. +
  8048. + err = orinoco_nortel_hw_init(card);
  8049. + if (err) {
  8050. + printk(KERN_ERR PFX "Hardware initialization failed\n");
  8051. + goto fail;
  8052. + }
  8053. +
  8054. + err = orinoco_nortel_cor_reset(priv);
  8055. + if (err) {
  8056. + printk(KERN_ERR PFX "Initial reset failed\n");
  8057. + goto fail;
  8058. + }
  8059. +
  8060. + err = orinoco_init(priv);
  8061. + if (err) {
  8062. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  8063. + goto fail;
  8064. + }
  8065. +
  8066. + err = orinoco_if_add(priv, 0, 0, NULL);
  8067. + if (err) {
  8068. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  8069. + goto fail_wiphy;
  8070. + }
  8071. +
  8072. + pci_set_drvdata(pdev, priv);
  8073. +
  8074. + return 0;
  8075. +
  8076. + fail_wiphy:
  8077. + wiphy_unregister(priv_to_wiphy(priv));
  8078. + fail:
  8079. + free_irq(pdev->irq, priv);
  8080. +
  8081. + fail_irq:
  8082. + free_orinocodev(priv);
  8083. +
  8084. + fail_alloc:
  8085. + pci_iounmap(pdev, hermes_io);
  8086. +
  8087. + fail_map_hermes:
  8088. + pci_iounmap(pdev, attr_io);
  8089. +
  8090. + fail_map_attr:
  8091. + pci_iounmap(pdev, bridge_io);
  8092. +
  8093. + fail_map_bridge:
  8094. + pci_release_regions(pdev);
  8095. +
  8096. + fail_resources:
  8097. + pci_disable_device(pdev);
  8098. +
  8099. + return err;
  8100. +}
  8101. +
  8102. +static void orinoco_nortel_remove_one(struct pci_dev *pdev)
  8103. +{
  8104. + struct orinoco_private *priv = pci_get_drvdata(pdev);
  8105. + struct orinoco_pci_card *card = priv->card;
  8106. +
  8107. + /* Clear LEDs */
  8108. + iowrite16(0, card->bridge_io + 10);
  8109. +
  8110. + orinoco_if_del(priv);
  8111. + wiphy_unregister(priv_to_wiphy(priv));
  8112. + free_irq(pdev->irq, priv);
  8113. + free_orinocodev(priv);
  8114. + pci_iounmap(pdev, priv->hw.iobase);
  8115. + pci_iounmap(pdev, card->attr_io);
  8116. + pci_iounmap(pdev, card->bridge_io);
  8117. + pci_release_regions(pdev);
  8118. + pci_disable_device(pdev);
  8119. +}
  8120. +
  8121. +static const struct pci_device_id orinoco_nortel_id_table[] = {
  8122. + /* Nortel emobility PCI */
  8123. + {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
  8124. + /* Symbol LA-4123 PCI */
  8125. + {0x1562, 0x0001, PCI_ANY_ID, PCI_ANY_ID,},
  8126. + {0,},
  8127. +};
  8128. +
  8129. +MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);
  8130. +
  8131. +static struct pci_driver orinoco_nortel_driver = {
  8132. + .name = DRIVER_NAME,
  8133. + .id_table = orinoco_nortel_id_table,
  8134. + .probe = orinoco_nortel_init_one,
  8135. + .remove = orinoco_nortel_remove_one,
  8136. + .driver.pm = &orinoco_pci_pm_ops,
  8137. +};
  8138. +
  8139. +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  8140. + " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
  8141. +MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
  8142. +MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge");
  8143. +MODULE_LICENSE("Dual MPL/GPL");
  8144. +
  8145. +static int __init orinoco_nortel_init(void)
  8146. +{
  8147. + printk(KERN_DEBUG "%s\n", version);
  8148. + return pci_register_driver(&orinoco_nortel_driver);
  8149. +}
  8150. +
  8151. +static void __exit orinoco_nortel_exit(void)
  8152. +{
  8153. + pci_unregister_driver(&orinoco_nortel_driver);
  8154. +}
  8155. +
  8156. +module_init(orinoco_nortel_init);
  8157. +module_exit(orinoco_nortel_exit);
  8158. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_pci.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_pci.c
  8159. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_pci.c 1970-01-01 01:00:00.000000000 +0100
  8160. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_pci.c 2025-08-03 15:01:59.353130523 +0200
  8161. @@ -0,0 +1,257 @@
  8162. +/* orinoco_pci.c
  8163. + *
  8164. + * Driver for Prism 2.5/3 devices that have a direct PCI interface
  8165. + * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge).
  8166. + * The card contains only one PCI region, which contains all the usual
  8167. + * hermes registers, as well as the COR register.
  8168. + *
  8169. + * Current maintainers are:
  8170. + * Pavel Roskin <proski AT gnu.org>
  8171. + * and David Gibson <hermes AT gibson.dropbear.id.au>
  8172. + *
  8173. + * Some of this code is borrowed from orinoco_plx.c
  8174. + * Copyright (C) 2001 Daniel Barlow <dan AT telent.net>
  8175. + * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
  8176. + * has been copied from it. linux-wlan-ng-0.1.10 is originally :
  8177. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  8178. + * This file originally written by:
  8179. + * Copyright (C) 2001 Jean Tourrilhes <jt AT hpl.hp.com>
  8180. + * And is now maintained by:
  8181. + * (C) Copyright David Gibson, IBM Corp. 2002-2003.
  8182. + *
  8183. + * The contents of this file are subject to the Mozilla Public License
  8184. + * Version 1.1 (the "License"); you may not use this file except in
  8185. + * compliance with the License. You may obtain a copy of the License
  8186. + * at http://www.mozilla.org/MPL/
  8187. + *
  8188. + * Software distributed under the License is distributed on an "AS IS"
  8189. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  8190. + * the License for the specific language governing rights and
  8191. + * limitations under the License.
  8192. + *
  8193. + * Alternatively, the contents of this file may be used under the
  8194. + * terms of the GNU General Public License version 2 (the "GPL"), in
  8195. + * which case the provisions of the GPL are applicable instead of the
  8196. + * above. If you wish to allow the use of your version of this file
  8197. + * only under the terms of the GPL and not to allow others to use your
  8198. + * version of this file under the MPL, indicate your decision by
  8199. + * deleting the provisions above and replace them with the notice and
  8200. + * other provisions required by the GPL. If you do not delete the
  8201. + * provisions above, a recipient may use your version of this file
  8202. + * under either the MPL or the GPL.
  8203. + */
  8204. +
  8205. +#define DRIVER_NAME "orinoco_pci"
  8206. +#define PFX DRIVER_NAME ": "
  8207. +
  8208. +#include <linux/module.h>
  8209. +#include <linux/kernel.h>
  8210. +#include <linux/init.h>
  8211. +#include <linux/delay.h>
  8212. +#include <linux/pci.h>
  8213. +
  8214. +#include "orinoco.h"
  8215. +#include "orinoco_pci.h"
  8216. +
  8217. +/* Offset of the COR register of the PCI card */
  8218. +#define HERMES_PCI_COR (0x26)
  8219. +
  8220. +/* Bitmask to reset the card */
  8221. +#define HERMES_PCI_COR_MASK (0x0080)
  8222. +
  8223. +/* Magic timeouts for doing the reset.
  8224. + * Those times are straight from wlan-ng, and it is claimed that they
  8225. + * are necessary. Alan will kill me. Take your time and grab a coffee. */
  8226. +#define HERMES_PCI_COR_ONT (250) /* ms */
  8227. +#define HERMES_PCI_COR_OFFT (500) /* ms */
  8228. +#define HERMES_PCI_COR_BUSYT (500) /* ms */
  8229. +
  8230. +/*
  8231. + * Do a soft reset of the card using the Configuration Option Register
  8232. + * We need this to get going...
  8233. + * This is the part of the code that is strongly inspired from wlan-ng
  8234. + *
  8235. + * Note : This code is done with irq enabled. This mean that many
  8236. + * interrupts will occur while we are there. This is why we use the
  8237. + * jiffies to regulate time instead of a straight mdelay(). Usually we
  8238. + * need only around 245 iteration of the loop to do 250 ms delay.
  8239. + *
  8240. + * Note bis : Don't try to access HERMES_CMD during the reset phase.
  8241. + * It just won't work !
  8242. + */
  8243. +static int orinoco_pci_cor_reset(struct orinoco_private *priv)
  8244. +{
  8245. + struct hermes *hw = &priv->hw;
  8246. + unsigned long timeout;
  8247. + u16 reg;
  8248. +
  8249. + /* Assert the reset until the card notices */
  8250. + hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
  8251. + mdelay(HERMES_PCI_COR_ONT);
  8252. +
  8253. + /* Give time for the card to recover from this hard effort */
  8254. + hermes_write_regn(hw, PCI_COR, 0x0000);
  8255. + mdelay(HERMES_PCI_COR_OFFT);
  8256. +
  8257. + /* The card is ready when it's no longer busy */
  8258. + timeout = jiffies + msecs_to_jiffies(HERMES_PCI_COR_BUSYT);
  8259. + reg = hermes_read_regn(hw, CMD);
  8260. + while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
  8261. + mdelay(1);
  8262. + reg = hermes_read_regn(hw, CMD);
  8263. + }
  8264. +
  8265. + /* Still busy? */
  8266. + if (reg & HERMES_CMD_BUSY) {
  8267. + printk(KERN_ERR PFX "Busy timeout\n");
  8268. + return -ETIMEDOUT;
  8269. + }
  8270. +
  8271. + return 0;
  8272. +}
  8273. +
  8274. +static int orinoco_pci_init_one(struct pci_dev *pdev,
  8275. + const struct pci_device_id *ent)
  8276. +{
  8277. + int err;
  8278. + struct orinoco_private *priv;
  8279. + struct orinoco_pci_card *card;
  8280. + void __iomem *hermes_io;
  8281. +
  8282. + err = pci_enable_device(pdev);
  8283. + if (err) {
  8284. + printk(KERN_ERR PFX "Cannot enable PCI device\n");
  8285. + return err;
  8286. + }
  8287. +
  8288. + err = pci_request_regions(pdev, DRIVER_NAME);
  8289. + if (err) {
  8290. + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
  8291. + goto fail_resources;
  8292. + }
  8293. +
  8294. + hermes_io = pci_iomap(pdev, 0, 0);
  8295. + if (!hermes_io) {
  8296. + printk(KERN_ERR PFX "Cannot remap chipset registers\n");
  8297. + err = -EIO;
  8298. + goto fail_map_hermes;
  8299. + }
  8300. +
  8301. + /* Allocate network device */
  8302. + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
  8303. + orinoco_pci_cor_reset, NULL);
  8304. + if (!priv) {
  8305. + printk(KERN_ERR PFX "Cannot allocate network device\n");
  8306. + err = -ENOMEM;
  8307. + goto fail_alloc;
  8308. + }
  8309. +
  8310. + card = priv->card;
  8311. +
  8312. + hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
  8313. +
  8314. + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
  8315. + DRIVER_NAME, priv);
  8316. + if (err) {
  8317. + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
  8318. + err = -EBUSY;
  8319. + goto fail_irq;
  8320. + }
  8321. +
  8322. + err = orinoco_pci_cor_reset(priv);
  8323. + if (err) {
  8324. + printk(KERN_ERR PFX "Initial reset failed\n");
  8325. + goto fail;
  8326. + }
  8327. +
  8328. + err = orinoco_init(priv);
  8329. + if (err) {
  8330. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  8331. + goto fail;
  8332. + }
  8333. +
  8334. + err = orinoco_if_add(priv, 0, 0, NULL);
  8335. + if (err) {
  8336. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  8337. + goto fail_wiphy;
  8338. + }
  8339. +
  8340. + pci_set_drvdata(pdev, priv);
  8341. +
  8342. + return 0;
  8343. +
  8344. + fail_wiphy:
  8345. + wiphy_unregister(priv_to_wiphy(priv));
  8346. + fail:
  8347. + free_irq(pdev->irq, priv);
  8348. +
  8349. + fail_irq:
  8350. + free_orinocodev(priv);
  8351. +
  8352. + fail_alloc:
  8353. + pci_iounmap(pdev, hermes_io);
  8354. +
  8355. + fail_map_hermes:
  8356. + pci_release_regions(pdev);
  8357. +
  8358. + fail_resources:
  8359. + pci_disable_device(pdev);
  8360. +
  8361. + return err;
  8362. +}
  8363. +
  8364. +static void orinoco_pci_remove_one(struct pci_dev *pdev)
  8365. +{
  8366. + struct orinoco_private *priv = pci_get_drvdata(pdev);
  8367. +
  8368. + orinoco_if_del(priv);
  8369. + wiphy_unregister(priv_to_wiphy(priv));
  8370. + free_irq(pdev->irq, priv);
  8371. + free_orinocodev(priv);
  8372. + pci_iounmap(pdev, priv->hw.iobase);
  8373. + pci_release_regions(pdev);
  8374. + pci_disable_device(pdev);
  8375. +}
  8376. +
  8377. +static const struct pci_device_id orinoco_pci_id_table[] = {
  8378. + /* Intersil Prism 3 */
  8379. + {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
  8380. + /* Intersil Prism 2.5 */
  8381. + {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
  8382. + /* Samsung MagicLAN SWL-2210P */
  8383. + {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,},
  8384. + {0,},
  8385. +};
  8386. +
  8387. +MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
  8388. +
  8389. +static struct pci_driver orinoco_pci_driver = {
  8390. + .name = DRIVER_NAME,
  8391. + .id_table = orinoco_pci_id_table,
  8392. + .probe = orinoco_pci_init_one,
  8393. + .remove = orinoco_pci_remove_one,
  8394. + .driver.pm = &orinoco_pci_pm_ops,
  8395. +};
  8396. +
  8397. +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  8398. + " (Pavel Roskin <proski@gnu.org>,"
  8399. + " David Gibson <hermes@gibson.dropbear.id.au> &"
  8400. + " Jean Tourrilhes <jt@hpl.hp.com>)";
  8401. +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> &"
  8402. + " David Gibson <hermes@gibson.dropbear.id.au>");
  8403. +MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface");
  8404. +MODULE_LICENSE("Dual MPL/GPL");
  8405. +
  8406. +static int __init orinoco_pci_init(void)
  8407. +{
  8408. + printk(KERN_DEBUG "%s\n", version);
  8409. + return pci_register_driver(&orinoco_pci_driver);
  8410. +}
  8411. +
  8412. +static void __exit orinoco_pci_exit(void)
  8413. +{
  8414. + pci_unregister_driver(&orinoco_pci_driver);
  8415. +}
  8416. +
  8417. +module_init(orinoco_pci_init);
  8418. +module_exit(orinoco_pci_exit);
  8419. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_pci.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_pci.h
  8420. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_pci.h 1970-01-01 01:00:00.000000000 +0100
  8421. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_pci.h 2025-08-03 15:01:59.365130178 +0200
  8422. @@ -0,0 +1,54 @@
  8423. +/* orinoco_pci.h
  8424. + *
  8425. + * Common code for all Orinoco drivers for PCI devices, including
  8426. + * both native PCI and PCMCIA-to-PCI bridges.
  8427. + *
  8428. + * Copyright (C) 2005, Pavel Roskin.
  8429. + * See main.c for license.
  8430. + */
  8431. +
  8432. +#ifndef _ORINOCO_PCI_H
  8433. +#define _ORINOCO_PCI_H
  8434. +
  8435. +#include <linux/netdevice.h>
  8436. +
  8437. +/* Driver specific data */
  8438. +struct orinoco_pci_card {
  8439. + void __iomem *bridge_io;
  8440. + void __iomem *attr_io;
  8441. +};
  8442. +
  8443. +static int __maybe_unused orinoco_pci_suspend(struct device *dev_d)
  8444. +{
  8445. + struct pci_dev *pdev = to_pci_dev(dev_d);
  8446. + struct orinoco_private *priv = pci_get_drvdata(pdev);
  8447. +
  8448. + orinoco_down(priv);
  8449. + free_irq(pdev->irq, priv);
  8450. +
  8451. + return 0;
  8452. +}
  8453. +
  8454. +static int __maybe_unused orinoco_pci_resume(struct device *dev_d)
  8455. +{
  8456. + struct pci_dev *pdev = to_pci_dev(dev_d);
  8457. + struct orinoco_private *priv = pci_get_drvdata(pdev);
  8458. + struct net_device *dev = priv->ndev;
  8459. + int err;
  8460. +
  8461. + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
  8462. + dev->name, priv);
  8463. + if (err) {
  8464. + printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
  8465. + dev->name);
  8466. + return -EBUSY;
  8467. + }
  8468. +
  8469. + return orinoco_up(priv);
  8470. +}
  8471. +
  8472. +static SIMPLE_DEV_PM_OPS(orinoco_pci_pm_ops,
  8473. + orinoco_pci_suspend,
  8474. + orinoco_pci_resume);
  8475. +
  8476. +#endif /* _ORINOCO_PCI_H */
  8477. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_plx.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_plx.c
  8478. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_plx.c 1970-01-01 01:00:00.000000000 +0100
  8479. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_plx.c 2025-08-03 15:01:59.365130178 +0200
  8480. @@ -0,0 +1,362 @@
  8481. +/* orinoco_plx.c
  8482. + *
  8483. + * Driver for Prism II devices which would usually be driven by orinoco_cs,
  8484. + * but are connected to the PCI bus by a PLX9052.
  8485. + *
  8486. + * Current maintainers are:
  8487. + * Pavel Roskin <proski AT gnu.org>
  8488. + * and David Gibson <hermes AT gibson.dropbear.id.au>
  8489. + *
  8490. + * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  8491. + * Copyright (C) 2001 Daniel Barlow
  8492. + *
  8493. + * The contents of this file are subject to the Mozilla Public License
  8494. + * Version 1.1 (the "License"); you may not use this file except in
  8495. + * compliance with the License. You may obtain a copy of the License
  8496. + * at http://www.mozilla.org/MPL/
  8497. + *
  8498. + * Software distributed under the License is distributed on an "AS IS"
  8499. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  8500. + * the License for the specific language governing rights and
  8501. + * limitations under the License.
  8502. + *
  8503. + * Alternatively, the contents of this file may be used under the
  8504. + * terms of the GNU General Public License version 2 (the "GPL"), in
  8505. + * which case the provisions of the GPL are applicable instead of the
  8506. + * above. If you wish to allow the use of your version of this file
  8507. + * only under the terms of the GPL and not to allow others to use your
  8508. + * version of this file under the MPL, indicate your decision by
  8509. + * deleting the provisions above and replace them with the notice and
  8510. + * other provisions required by the GPL. If you do not delete the
  8511. + * provisions above, a recipient may use your version of this file
  8512. + * under either the MPL or the GPL.
  8513. + *
  8514. + * Here's the general details on how the PLX9052 adapter works:
  8515. + *
  8516. + * - Two PCI I/O address spaces, one 0x80 long which contains the
  8517. + * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
  8518. + * slot I/O address space.
  8519. + *
  8520. + * - One PCI memory address space, mapped to the PCMCIA attribute space
  8521. + * (containing the CIS).
  8522. + *
  8523. + * Using the later, you can read through the CIS data to make sure the
  8524. + * card is compatible with the driver. Keep in mind that the PCMCIA
  8525. + * spec specifies the CIS as the lower 8 bits of each word read from
  8526. + * the CIS, so to read the bytes of the CIS, read every other byte
  8527. + * (0,2,4,...). Passing that test, you need to enable the I/O address
  8528. + * space on the PCMCIA card via the PCMCIA COR register. This is the
  8529. + * first byte following the CIS. In my case (which may not have any
  8530. + * relation to what's on the PRISM2 cards), COR was at offset 0x800
  8531. + * within the PCI memory space. Write 0x41 to the COR register to
  8532. + * enable I/O mode and to select level triggered interrupts. To
  8533. + * confirm you actually succeeded, read the COR register back and make
  8534. + * sure it actually got set to 0x41, in case you have an unexpected
  8535. + * card inserted.
  8536. + *
  8537. + * Following that, you can treat the second PCI I/O address space (the
  8538. + * one that's not 0x80 in length) as the PCMCIA I/O space.
  8539. + *
  8540. + * Note that in the Eumitcom's source for their drivers, they register
  8541. + * the interrupt as edge triggered when registering it with the
  8542. + * Windows kernel. I don't recall how to register edge triggered on
  8543. + * Linux (if it can be done at all). But in some experimentation, I
  8544. + * don't see much operational difference between using either
  8545. + * interrupt mode. Don't mess with the interrupt mode in the COR
  8546. + * register though, as the PLX9052 wants level triggers with the way
  8547. + * the serial EEPROM configures it on the WL11000.
  8548. + *
  8549. + * There's some other little quirks related to timing that I bumped
  8550. + * into, but I don't recall right now. Also, there's two variants of
  8551. + * the WL11000 I've seen, revision A1 and T2. These seem to differ
  8552. + * slightly in the timings configured in the wait-state generator in
  8553. + * the PLX9052. There have also been some comments from Eumitcom that
  8554. + * cards shouldn't be hot swapped, apparently due to risk of cooking
  8555. + * the PLX9052. I'm unsure why they believe this, as I can't see
  8556. + * anything in the design that would really cause a problem, except
  8557. + * for crashing drivers not written to expect it. And having developed
  8558. + * drivers for the WL11000, I'd say it's quite tricky to write code
  8559. + * that will successfully deal with a hot unplug. Very odd things
  8560. + * happen on the I/O side of things. But anyway, be warned. Despite
  8561. + * that, I've hot-swapped a number of times during debugging and
  8562. + * driver development for various reasons (stuck WAIT# line after the
  8563. + * radio card's firmware locks up).
  8564. + */
  8565. +
  8566. +#define DRIVER_NAME "orinoco_plx"
  8567. +#define PFX DRIVER_NAME ": "
  8568. +
  8569. +#include <linux/module.h>
  8570. +#include <linux/kernel.h>
  8571. +#include <linux/init.h>
  8572. +#include <linux/delay.h>
  8573. +#include <linux/pci.h>
  8574. +#include <pcmcia/cisreg.h>
  8575. +
  8576. +#include "orinoco.h"
  8577. +#include "orinoco_pci.h"
  8578. +
  8579. +#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
  8580. +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
  8581. +#define COR_RESET (0x80) /* reset bit in the COR register */
  8582. +#define PLX_RESET_TIME (500) /* milliseconds */
  8583. +
  8584. +#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
  8585. +#define PLX_INTCSR_INTEN (1 << 6) /* Interrupt Enable bit */
  8586. +
  8587. +/*
  8588. + * Do a soft reset of the card using the Configuration Option Register
  8589. + */
  8590. +static int orinoco_plx_cor_reset(struct orinoco_private *priv)
  8591. +{
  8592. + struct hermes *hw = &priv->hw;
  8593. + struct orinoco_pci_card *card = priv->card;
  8594. + unsigned long timeout;
  8595. + u16 reg;
  8596. +
  8597. + iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
  8598. + mdelay(1);
  8599. +
  8600. + iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
  8601. + mdelay(1);
  8602. +
  8603. + /* Just in case, wait more until the card is no longer busy */
  8604. + timeout = jiffies + msecs_to_jiffies(PLX_RESET_TIME);
  8605. + reg = hermes_read_regn(hw, CMD);
  8606. + while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
  8607. + mdelay(1);
  8608. + reg = hermes_read_regn(hw, CMD);
  8609. + }
  8610. +
  8611. + /* Still busy? */
  8612. + if (reg & HERMES_CMD_BUSY) {
  8613. + printk(KERN_ERR PFX "Busy timeout\n");
  8614. + return -ETIMEDOUT;
  8615. + }
  8616. +
  8617. + return 0;
  8618. +}
  8619. +
  8620. +static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
  8621. +{
  8622. + int i;
  8623. + u32 csr_reg;
  8624. + static const u8 cis_magic[] = {
  8625. + 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
  8626. + };
  8627. +
  8628. + printk(KERN_DEBUG PFX "CIS: ");
  8629. + for (i = 0; i < 16; i++)
  8630. + printk("%02X:", ioread8(card->attr_io + (i << 1)));
  8631. + printk("\n");
  8632. +
  8633. + /* Verify whether a supported PC card is present */
  8634. + /* FIXME: we probably need to be smarted about this */
  8635. + for (i = 0; i < sizeof(cis_magic); i++) {
  8636. + if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
  8637. + printk(KERN_ERR PFX "The CIS value of Prism2 PC "
  8638. + "card is unexpected\n");
  8639. + return -ENODEV;
  8640. + }
  8641. + }
  8642. +
  8643. + /* bjoern: We need to tell the card to enable interrupts, in
  8644. + case the serial eprom didn't do this already. See the
  8645. + PLX9052 data book, p8-1 and 8-24 for reference. */
  8646. + csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
  8647. + if (!(csr_reg & PLX_INTCSR_INTEN)) {
  8648. + csr_reg |= PLX_INTCSR_INTEN;
  8649. + iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
  8650. + csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
  8651. + if (!(csr_reg & PLX_INTCSR_INTEN)) {
  8652. + printk(KERN_ERR PFX "Cannot enable interrupts\n");
  8653. + return -EIO;
  8654. + }
  8655. + }
  8656. +
  8657. + return 0;
  8658. +}
  8659. +
  8660. +static int orinoco_plx_init_one(struct pci_dev *pdev,
  8661. + const struct pci_device_id *ent)
  8662. +{
  8663. + int err;
  8664. + struct orinoco_private *priv;
  8665. + struct orinoco_pci_card *card;
  8666. + void __iomem *hermes_io, *attr_io, *bridge_io;
  8667. +
  8668. + err = pci_enable_device(pdev);
  8669. + if (err) {
  8670. + printk(KERN_ERR PFX "Cannot enable PCI device\n");
  8671. + return err;
  8672. + }
  8673. +
  8674. + err = pci_request_regions(pdev, DRIVER_NAME);
  8675. + if (err) {
  8676. + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
  8677. + goto fail_resources;
  8678. + }
  8679. +
  8680. + bridge_io = pci_iomap(pdev, 1, 0);
  8681. + if (!bridge_io) {
  8682. + printk(KERN_ERR PFX "Cannot map bridge registers\n");
  8683. + err = -EIO;
  8684. + goto fail_map_bridge;
  8685. + }
  8686. +
  8687. + attr_io = pci_iomap(pdev, 2, 0);
  8688. + if (!attr_io) {
  8689. + printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
  8690. + err = -EIO;
  8691. + goto fail_map_attr;
  8692. + }
  8693. +
  8694. + hermes_io = pci_iomap(pdev, 3, 0);
  8695. + if (!hermes_io) {
  8696. + printk(KERN_ERR PFX "Cannot map chipset registers\n");
  8697. + err = -EIO;
  8698. + goto fail_map_hermes;
  8699. + }
  8700. +
  8701. + /* Allocate network device */
  8702. + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
  8703. + orinoco_plx_cor_reset, NULL);
  8704. + if (!priv) {
  8705. + printk(KERN_ERR PFX "Cannot allocate network device\n");
  8706. + err = -ENOMEM;
  8707. + goto fail_alloc;
  8708. + }
  8709. +
  8710. + card = priv->card;
  8711. + card->bridge_io = bridge_io;
  8712. + card->attr_io = attr_io;
  8713. +
  8714. + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
  8715. +
  8716. + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
  8717. + DRIVER_NAME, priv);
  8718. + if (err) {
  8719. + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
  8720. + err = -EBUSY;
  8721. + goto fail_irq;
  8722. + }
  8723. +
  8724. + err = orinoco_plx_hw_init(card);
  8725. + if (err) {
  8726. + printk(KERN_ERR PFX "Hardware initialization failed\n");
  8727. + goto fail;
  8728. + }
  8729. +
  8730. + err = orinoco_plx_cor_reset(priv);
  8731. + if (err) {
  8732. + printk(KERN_ERR PFX "Initial reset failed\n");
  8733. + goto fail;
  8734. + }
  8735. +
  8736. + err = orinoco_init(priv);
  8737. + if (err) {
  8738. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  8739. + goto fail;
  8740. + }
  8741. +
  8742. + err = orinoco_if_add(priv, 0, 0, NULL);
  8743. + if (err) {
  8744. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  8745. + goto fail_wiphy;
  8746. + }
  8747. +
  8748. + pci_set_drvdata(pdev, priv);
  8749. +
  8750. + return 0;
  8751. +
  8752. + fail_wiphy:
  8753. + wiphy_unregister(priv_to_wiphy(priv));
  8754. + fail:
  8755. + free_irq(pdev->irq, priv);
  8756. +
  8757. + fail_irq:
  8758. + free_orinocodev(priv);
  8759. +
  8760. + fail_alloc:
  8761. + pci_iounmap(pdev, hermes_io);
  8762. +
  8763. + fail_map_hermes:
  8764. + pci_iounmap(pdev, attr_io);
  8765. +
  8766. + fail_map_attr:
  8767. + pci_iounmap(pdev, bridge_io);
  8768. +
  8769. + fail_map_bridge:
  8770. + pci_release_regions(pdev);
  8771. +
  8772. + fail_resources:
  8773. + pci_disable_device(pdev);
  8774. +
  8775. + return err;
  8776. +}
  8777. +
  8778. +static void orinoco_plx_remove_one(struct pci_dev *pdev)
  8779. +{
  8780. + struct orinoco_private *priv = pci_get_drvdata(pdev);
  8781. + struct orinoco_pci_card *card = priv->card;
  8782. +
  8783. + orinoco_if_del(priv);
  8784. + wiphy_unregister(priv_to_wiphy(priv));
  8785. + free_irq(pdev->irq, priv);
  8786. + free_orinocodev(priv);
  8787. + pci_iounmap(pdev, priv->hw.iobase);
  8788. + pci_iounmap(pdev, card->attr_io);
  8789. + pci_iounmap(pdev, card->bridge_io);
  8790. + pci_release_regions(pdev);
  8791. + pci_disable_device(pdev);
  8792. +}
  8793. +
  8794. +static const struct pci_device_id orinoco_plx_id_table[] = {
  8795. + {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */
  8796. + {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
  8797. + {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */
  8798. + {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W,
  8799. + Eumitcom PCI WL11000,
  8800. + Addtron AWA-100 */
  8801. + {0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* Global Sun Tech GL24110P */
  8802. + {0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,}, /* Reported working, but unknown */
  8803. + {0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,}, /* Linksys WDT11 */
  8804. + {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */
  8805. + {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by
  8806. + Brendan W. McAdams <rit AT jacked-in.org> */
  8807. + {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3Com AirConnect PCI tested by
  8808. + Damien Persohn <damien AT persohn.net> */
  8809. + {0,},
  8810. +};
  8811. +
  8812. +MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
  8813. +
  8814. +static struct pci_driver orinoco_plx_driver = {
  8815. + .name = DRIVER_NAME,
  8816. + .id_table = orinoco_plx_id_table,
  8817. + .probe = orinoco_plx_init_one,
  8818. + .remove = orinoco_plx_remove_one,
  8819. + .driver.pm = &orinoco_pci_pm_ops,
  8820. +};
  8821. +
  8822. +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  8823. + " (Pavel Roskin <proski@gnu.org>,"
  8824. + " David Gibson <hermes@gibson.dropbear.id.au>,"
  8825. + " Daniel Barlow <dan@telent.net>)";
  8826. +MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
  8827. +MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
  8828. +MODULE_LICENSE("Dual MPL/GPL");
  8829. +
  8830. +static int __init orinoco_plx_init(void)
  8831. +{
  8832. + printk(KERN_DEBUG "%s\n", version);
  8833. + return pci_register_driver(&orinoco_plx_driver);
  8834. +}
  8835. +
  8836. +static void __exit orinoco_plx_exit(void)
  8837. +{
  8838. + pci_unregister_driver(&orinoco_plx_driver);
  8839. +}
  8840. +
  8841. +module_init(orinoco_plx_init);
  8842. +module_exit(orinoco_plx_exit);
  8843. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_tmd.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_tmd.c
  8844. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_tmd.c 1970-01-01 01:00:00.000000000 +0100
  8845. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_tmd.c 2025-08-03 15:01:59.365130178 +0200
  8846. @@ -0,0 +1,237 @@
  8847. +/* orinoco_tmd.c
  8848. + *
  8849. + * Driver for Prism II devices which would usually be driven by orinoco_cs,
  8850. + * but are connected to the PCI bus by a TMD7160.
  8851. + *
  8852. + * Copyright (C) 2003 Joerg Dorchain <joerg AT dorchain.net>
  8853. + * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow
  8854. + *
  8855. + * The contents of this file are subject to the Mozilla Public License
  8856. + * Version 1.1 (the "License"); you may not use this file except in
  8857. + * compliance with the License. You may obtain a copy of the License
  8858. + * at http://www.mozilla.org/MPL/
  8859. + *
  8860. + * Software distributed under the License is distributed on an "AS IS"
  8861. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  8862. + * the License for the specific language governing rights and
  8863. + * limitations under the License.
  8864. + *
  8865. + * Alternatively, the contents of this file may be used under the
  8866. + * terms of the GNU General Public License version 2 (the "GPL"), in
  8867. + * which case the provisions of the GPL are applicable instead of the
  8868. + * above. If you wish to allow the use of your version of this file
  8869. + * only under the terms of the GPL and not to allow others to use your
  8870. + * version of this file under the MPL, indicate your decision by
  8871. + * deleting the provisions above and replace them with the notice and
  8872. + * other provisions required by the GPL. If you do not delete the
  8873. + * provisions above, a recipient may use your version of this file
  8874. + * under either the MPL or the GPL.
  8875. + *
  8876. + * The actual driving is done by main.c, this is just resource
  8877. + * allocation stuff.
  8878. + *
  8879. + * This driver is modeled after the orinoco_plx driver. The main
  8880. + * difference is that the TMD chip has only IO port ranges and doesn't
  8881. + * provide access to the PCMCIA attribute space.
  8882. + *
  8883. + * Pheecom sells cards with the TMD chip as "ASIC version"
  8884. + */
  8885. +
  8886. +#define DRIVER_NAME "orinoco_tmd"
  8887. +#define PFX DRIVER_NAME ": "
  8888. +
  8889. +#include <linux/module.h>
  8890. +#include <linux/kernel.h>
  8891. +#include <linux/init.h>
  8892. +#include <linux/delay.h>
  8893. +#include <linux/pci.h>
  8894. +#include <pcmcia/cisreg.h>
  8895. +
  8896. +#include "orinoco.h"
  8897. +#include "orinoco_pci.h"
  8898. +
  8899. +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
  8900. +#define COR_RESET (0x80) /* reset bit in the COR register */
  8901. +#define TMD_RESET_TIME (500) /* milliseconds */
  8902. +
  8903. +/*
  8904. + * Do a soft reset of the card using the Configuration Option Register
  8905. + */
  8906. +static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
  8907. +{
  8908. + struct hermes *hw = &priv->hw;
  8909. + struct orinoco_pci_card *card = priv->card;
  8910. + unsigned long timeout;
  8911. + u16 reg;
  8912. +
  8913. + iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
  8914. + mdelay(1);
  8915. +
  8916. + iowrite8(COR_VALUE, card->bridge_io);
  8917. + mdelay(1);
  8918. +
  8919. + /* Just in case, wait more until the card is no longer busy */
  8920. + timeout = jiffies + msecs_to_jiffies(TMD_RESET_TIME);
  8921. + reg = hermes_read_regn(hw, CMD);
  8922. + while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
  8923. + mdelay(1);
  8924. + reg = hermes_read_regn(hw, CMD);
  8925. + }
  8926. +
  8927. + /* Still busy? */
  8928. + if (reg & HERMES_CMD_BUSY) {
  8929. + printk(KERN_ERR PFX "Busy timeout\n");
  8930. + return -ETIMEDOUT;
  8931. + }
  8932. +
  8933. + return 0;
  8934. +}
  8935. +
  8936. +
  8937. +static int orinoco_tmd_init_one(struct pci_dev *pdev,
  8938. + const struct pci_device_id *ent)
  8939. +{
  8940. + int err;
  8941. + struct orinoco_private *priv;
  8942. + struct orinoco_pci_card *card;
  8943. + void __iomem *hermes_io, *bridge_io;
  8944. +
  8945. + err = pci_enable_device(pdev);
  8946. + if (err) {
  8947. + printk(KERN_ERR PFX "Cannot enable PCI device\n");
  8948. + return err;
  8949. + }
  8950. +
  8951. + err = pci_request_regions(pdev, DRIVER_NAME);
  8952. + if (err) {
  8953. + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
  8954. + goto fail_resources;
  8955. + }
  8956. +
  8957. + bridge_io = pci_iomap(pdev, 1, 0);
  8958. + if (!bridge_io) {
  8959. + printk(KERN_ERR PFX "Cannot map bridge registers\n");
  8960. + err = -EIO;
  8961. + goto fail_map_bridge;
  8962. + }
  8963. +
  8964. + hermes_io = pci_iomap(pdev, 2, 0);
  8965. + if (!hermes_io) {
  8966. + printk(KERN_ERR PFX "Cannot map chipset registers\n");
  8967. + err = -EIO;
  8968. + goto fail_map_hermes;
  8969. + }
  8970. +
  8971. + /* Allocate network device */
  8972. + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
  8973. + orinoco_tmd_cor_reset, NULL);
  8974. + if (!priv) {
  8975. + printk(KERN_ERR PFX "Cannot allocate network device\n");
  8976. + err = -ENOMEM;
  8977. + goto fail_alloc;
  8978. + }
  8979. +
  8980. + card = priv->card;
  8981. + card->bridge_io = bridge_io;
  8982. +
  8983. + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
  8984. +
  8985. + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
  8986. + DRIVER_NAME, priv);
  8987. + if (err) {
  8988. + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
  8989. + err = -EBUSY;
  8990. + goto fail_irq;
  8991. + }
  8992. +
  8993. + err = orinoco_tmd_cor_reset(priv);
  8994. + if (err) {
  8995. + printk(KERN_ERR PFX "Initial reset failed\n");
  8996. + goto fail;
  8997. + }
  8998. +
  8999. + err = orinoco_init(priv);
  9000. + if (err) {
  9001. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  9002. + goto fail;
  9003. + }
  9004. +
  9005. + err = orinoco_if_add(priv, 0, 0, NULL);
  9006. + if (err) {
  9007. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  9008. + goto fail;
  9009. + }
  9010. +
  9011. + pci_set_drvdata(pdev, priv);
  9012. +
  9013. + return 0;
  9014. +
  9015. + fail:
  9016. + free_irq(pdev->irq, priv);
  9017. +
  9018. + fail_irq:
  9019. + free_orinocodev(priv);
  9020. +
  9021. + fail_alloc:
  9022. + pci_iounmap(pdev, hermes_io);
  9023. +
  9024. + fail_map_hermes:
  9025. + pci_iounmap(pdev, bridge_io);
  9026. +
  9027. + fail_map_bridge:
  9028. + pci_release_regions(pdev);
  9029. +
  9030. + fail_resources:
  9031. + pci_disable_device(pdev);
  9032. +
  9033. + return err;
  9034. +}
  9035. +
  9036. +static void orinoco_tmd_remove_one(struct pci_dev *pdev)
  9037. +{
  9038. + struct orinoco_private *priv = pci_get_drvdata(pdev);
  9039. + struct orinoco_pci_card *card = priv->card;
  9040. +
  9041. + orinoco_if_del(priv);
  9042. + free_irq(pdev->irq, priv);
  9043. + free_orinocodev(priv);
  9044. + pci_iounmap(pdev, priv->hw.iobase);
  9045. + pci_iounmap(pdev, card->bridge_io);
  9046. + pci_release_regions(pdev);
  9047. + pci_disable_device(pdev);
  9048. +}
  9049. +
  9050. +static const struct pci_device_id orinoco_tmd_id_table[] = {
  9051. + {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */
  9052. + {0,},
  9053. +};
  9054. +
  9055. +MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
  9056. +
  9057. +static struct pci_driver orinoco_tmd_driver = {
  9058. + .name = DRIVER_NAME,
  9059. + .id_table = orinoco_tmd_id_table,
  9060. + .probe = orinoco_tmd_init_one,
  9061. + .remove = orinoco_tmd_remove_one,
  9062. + .driver.pm = &orinoco_pci_pm_ops,
  9063. +};
  9064. +
  9065. +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  9066. + " (Joerg Dorchain <joerg@dorchain.net>)";
  9067. +MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
  9068. +MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge");
  9069. +MODULE_LICENSE("Dual MPL/GPL");
  9070. +
  9071. +static int __init orinoco_tmd_init(void)
  9072. +{
  9073. + printk(KERN_DEBUG "%s\n", version);
  9074. + return pci_register_driver(&orinoco_tmd_driver);
  9075. +}
  9076. +
  9077. +static void __exit orinoco_tmd_exit(void)
  9078. +{
  9079. + pci_unregister_driver(&orinoco_tmd_driver);
  9080. +}
  9081. +
  9082. +module_init(orinoco_tmd_init);
  9083. +module_exit(orinoco_tmd_exit);
  9084. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_usb.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
  9085. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/orinoco_usb.c 1970-01-01 01:00:00.000000000 +0100
  9086. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/orinoco_usb.c 2025-08-03 15:01:59.365130178 +0200
  9087. @@ -0,0 +1,1787 @@
  9088. +/*
  9089. + * USB Orinoco driver
  9090. + *
  9091. + * Copyright (c) 2003 Manuel Estrada Sainz
  9092. + *
  9093. + * The contents of this file are subject to the Mozilla Public License
  9094. + * Version 1.1 (the "License"); you may not use this file except in
  9095. + * compliance with the License. You may obtain a copy of the License
  9096. + * at http://www.mozilla.org/MPL/
  9097. + *
  9098. + * Software distributed under the License is distributed on an "AS IS"
  9099. + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9100. + * the License for the specific language governing rights and
  9101. + * limitations under the License.
  9102. + *
  9103. + * Alternatively, the contents of this file may be used under the
  9104. + * terms of the GNU General Public License version 2 (the "GPL"), in
  9105. + * which case the provisions of the GPL are applicable instead of the
  9106. + * above. If you wish to allow the use of your version of this file
  9107. + * only under the terms of the GPL and not to allow others to use your
  9108. + * version of this file under the MPL, indicate your decision by
  9109. + * deleting the provisions above and replace them with the notice and
  9110. + * other provisions required by the GPL. If you do not delete the
  9111. + * provisions above, a recipient may use your version of this file
  9112. + * under either the MPL or the GPL.
  9113. + *
  9114. + * Queueing code based on linux-wlan-ng 0.2.1-pre5
  9115. + *
  9116. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  9117. + *
  9118. + * The license is the same as above.
  9119. + *
  9120. + * Initialy based on USB Skeleton driver - 0.7
  9121. + *
  9122. + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
  9123. + *
  9124. + * This program is free software; you can redistribute it and/or
  9125. + * modify it under the terms of the GNU General Public License as
  9126. + * published by the Free Software Foundation; either version 2 of
  9127. + * the License, or (at your option) any later version.
  9128. + *
  9129. + * NOTE: The original USB Skeleton driver is GPL, but all that code is
  9130. + * gone so MPL/GPL applies.
  9131. + */
  9132. +
  9133. +#define DRIVER_NAME "orinoco_usb"
  9134. +#define PFX DRIVER_NAME ": "
  9135. +
  9136. +#include <linux/module.h>
  9137. +#include <linux/kernel.h>
  9138. +#include <linux/sched.h>
  9139. +#include <linux/signal.h>
  9140. +#include <linux/errno.h>
  9141. +#include <linux/poll.h>
  9142. +#include <linux/slab.h>
  9143. +#include <linux/fcntl.h>
  9144. +#include <linux/spinlock.h>
  9145. +#include <linux/list.h>
  9146. +#include <linux/usb.h>
  9147. +#include <linux/timer.h>
  9148. +
  9149. +#include <linux/netdevice.h>
  9150. +#include <linux/if_arp.h>
  9151. +#include <linux/etherdevice.h>
  9152. +#include <linux/wireless.h>
  9153. +#include <linux/firmware.h>
  9154. +#include <linux/refcount.h>
  9155. +
  9156. +#include "mic.h"
  9157. +#include "orinoco.h"
  9158. +
  9159. +#ifndef URB_ASYNC_UNLINK
  9160. +#define URB_ASYNC_UNLINK 0
  9161. +#endif
  9162. +
  9163. +struct header_struct {
  9164. + /* 802.3 */
  9165. + u8 dest[ETH_ALEN];
  9166. + u8 src[ETH_ALEN];
  9167. + __be16 len;
  9168. + /* 802.2 */
  9169. + u8 dsap;
  9170. + u8 ssap;
  9171. + u8 ctrl;
  9172. + /* SNAP */
  9173. + u8 oui[3];
  9174. + __be16 ethertype;
  9175. +} __packed;
  9176. +
  9177. +struct ez_usb_fw {
  9178. + u16 size;
  9179. + const u8 *code;
  9180. +};
  9181. +
  9182. +static struct ez_usb_fw firmware = {
  9183. + .size = 0,
  9184. + .code = NULL,
  9185. +};
  9186. +
  9187. +/* Debugging macros */
  9188. +#undef err
  9189. +#define err(format, arg...) \
  9190. + do { printk(KERN_ERR PFX format "\n", ## arg); } while (0)
  9191. +
  9192. +MODULE_FIRMWARE("orinoco_ezusb_fw");
  9193. +
  9194. +/*
  9195. + * Under some conditions, the card gets stuck and stops paying attention
  9196. + * to the world (i.e. data communication stalls) until we do something to
  9197. + * it. Sending an INQ_TALLIES command seems to be enough and should be
  9198. + * harmless otherwise. This behaviour has been observed when using the
  9199. + * driver on a systemimager client during installation. In the past a
  9200. + * timer was used to send INQ_TALLIES commands when there was no other
  9201. + * activity, but it was troublesome and was removed.
  9202. + */
  9203. +
  9204. +#define USB_COMPAQ_VENDOR_ID 0x049f /* Compaq Computer Corp. */
  9205. +#define USB_COMPAQ_WL215_ID 0x001f /* Compaq WL215 USB Adapter */
  9206. +#define USB_COMPAQ_W200_ID 0x0076 /* Compaq W200 USB Adapter */
  9207. +#define USB_HP_WL215_ID 0x0082 /* Compaq WL215 USB Adapter */
  9208. +
  9209. +#define USB_MELCO_VENDOR_ID 0x0411
  9210. +#define USB_BUFFALO_L11_ID 0x0006 /* BUFFALO WLI-USB-L11 */
  9211. +#define USB_BUFFALO_L11G_WR_ID 0x000B /* BUFFALO WLI-USB-L11G-WR */
  9212. +#define USB_BUFFALO_L11G_ID 0x000D /* BUFFALO WLI-USB-L11G */
  9213. +
  9214. +#define USB_LUCENT_VENDOR_ID 0x047E /* Lucent Technologies */
  9215. +#define USB_LUCENT_ORINOCO_ID 0x0300 /* Lucent/Agere Orinoco USB Client */
  9216. +
  9217. +#define USB_AVAYA8_VENDOR_ID 0x0D98
  9218. +#define USB_AVAYAE_VENDOR_ID 0x0D9E
  9219. +#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya USB Wireless Card */
  9220. +
  9221. +#define USB_AGERE_VENDOR_ID 0x0D4E /* Agere Systems */
  9222. +#define USB_AGERE_MODEL0801_ID 0x1000 /* USB Wireless Card Model 0801 */
  9223. +#define USB_AGERE_MODEL0802_ID 0x1001 /* USB Wireless Card Model 0802 */
  9224. +#define USB_AGERE_REBRANDED_ID 0x047A /* USB WLAN Card */
  9225. +
  9226. +#define USB_ELSA_VENDOR_ID 0x05CC
  9227. +#define USB_ELSA_AIRLANCER_ID 0x3100 /* ELSA AirLancer USB-11 */
  9228. +
  9229. +#define USB_LEGEND_VENDOR_ID 0x0E7C
  9230. +#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet USB WLAN Card */
  9231. +
  9232. +#define USB_SAMSUNG_VENDOR_ID 0x04E8
  9233. +#define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */
  9234. +#define USB_SAMSUNG_SEW2001U2_ID 0x5B11 /* Samsung SEW-2001u Card */
  9235. +#define USB_SAMSUNG_SEW2003U_ID 0x7011 /* Samsung SEW-2003U Card */
  9236. +
  9237. +#define USB_IGATE_VENDOR_ID 0x0681
  9238. +#define USB_IGATE_IGATE_11M_ID 0x0012 /* I-GATE 11M USB Card */
  9239. +
  9240. +#define USB_FUJITSU_VENDOR_ID 0x0BF8
  9241. +#define USB_FUJITSU_E1100_ID 0x1002 /* connect2AIR WLAN E-1100 USB */
  9242. +
  9243. +#define USB_2WIRE_VENDOR_ID 0x1630
  9244. +#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire USB Wireless adapter */
  9245. +
  9246. +
  9247. +#define EZUSB_REQUEST_FW_TRANS 0xA0
  9248. +#define EZUSB_REQUEST_TRIGGER 0xAA
  9249. +#define EZUSB_REQUEST_TRIG_AC 0xAC
  9250. +#define EZUSB_CPUCS_REG 0x7F92
  9251. +
  9252. +#define EZUSB_RID_TX 0x0700
  9253. +#define EZUSB_RID_RX 0x0701
  9254. +#define EZUSB_RID_INIT1 0x0702
  9255. +#define EZUSB_RID_ACK 0x0710
  9256. +#define EZUSB_RID_READ_PDA 0x0800
  9257. +#define EZUSB_RID_PROG_INIT 0x0852
  9258. +#define EZUSB_RID_PROG_SET_ADDR 0x0853
  9259. +#define EZUSB_RID_PROG_BYTES 0x0854
  9260. +#define EZUSB_RID_PROG_END 0x0855
  9261. +#define EZUSB_RID_DOCMD 0x0860
  9262. +
  9263. +/* Recognize info frames */
  9264. +#define EZUSB_IS_INFO(id) ((id >= 0xF000) && (id <= 0xF2FF))
  9265. +
  9266. +#define EZUSB_MAGIC 0x0210
  9267. +
  9268. +#define EZUSB_FRAME_DATA 1
  9269. +#define EZUSB_FRAME_CONTROL 2
  9270. +
  9271. +#define DEF_TIMEOUT (3 * HZ)
  9272. +
  9273. +#define BULK_BUF_SIZE 2048
  9274. +
  9275. +#define MAX_DL_SIZE (BULK_BUF_SIZE - sizeof(struct ezusb_packet))
  9276. +
  9277. +#define FW_BUF_SIZE 64
  9278. +#define FW_VAR_OFFSET_PTR 0x359
  9279. +#define FW_VAR_VALUE 0
  9280. +#define FW_HOLE_START 0x100
  9281. +#define FW_HOLE_END 0x300
  9282. +
  9283. +struct ezusb_packet {
  9284. + __le16 magic; /* 0x0210 */
  9285. + u8 req_reply_count;
  9286. + u8 ans_reply_count;
  9287. + __le16 frame_type; /* 0x01 for data frames, 0x02 otherwise */
  9288. + __le16 size; /* transport size */
  9289. + __le16 crc; /* CRC up to here */
  9290. + __le16 hermes_len;
  9291. + __le16 hermes_rid;
  9292. + u8 data[];
  9293. +} __packed;
  9294. +
  9295. +/* Table of devices that work or may work with this driver */
  9296. +static const struct usb_device_id ezusb_table[] = {
  9297. + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_WL215_ID)},
  9298. + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_HP_WL215_ID)},
  9299. + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_W200_ID)},
  9300. + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11_ID)},
  9301. + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_WR_ID)},
  9302. + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_ID)},
  9303. + {USB_DEVICE(USB_LUCENT_VENDOR_ID, USB_LUCENT_ORINOCO_ID)},
  9304. + {USB_DEVICE(USB_AVAYA8_VENDOR_ID, USB_AVAYA_WIRELESS_ID)},
  9305. + {USB_DEVICE(USB_AVAYAE_VENDOR_ID, USB_AVAYA_WIRELESS_ID)},
  9306. + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0801_ID)},
  9307. + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0802_ID)},
  9308. + {USB_DEVICE(USB_ELSA_VENDOR_ID, USB_ELSA_AIRLANCER_ID)},
  9309. + {USB_DEVICE(USB_LEGEND_VENDOR_ID, USB_LEGEND_JOYNET_ID)},
  9310. + {USB_DEVICE_VER(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U1_ID,
  9311. + 0, 0)},
  9312. + {USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U2_ID)},
  9313. + {USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2003U_ID)},
  9314. + {USB_DEVICE(USB_IGATE_VENDOR_ID, USB_IGATE_IGATE_11M_ID)},
  9315. + {USB_DEVICE(USB_FUJITSU_VENDOR_ID, USB_FUJITSU_E1100_ID)},
  9316. + {USB_DEVICE(USB_2WIRE_VENDOR_ID, USB_2WIRE_WIRELESS_ID)},
  9317. + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_REBRANDED_ID)},
  9318. + {} /* Terminating entry */
  9319. +};
  9320. +
  9321. +MODULE_DEVICE_TABLE(usb, ezusb_table);
  9322. +
  9323. +/* Structure to hold all of our device specific stuff */
  9324. +struct ezusb_priv {
  9325. + struct usb_device *udev;
  9326. + struct net_device *dev;
  9327. + struct mutex mtx;
  9328. + spinlock_t req_lock;
  9329. + struct list_head req_pending;
  9330. + struct list_head req_active;
  9331. + spinlock_t reply_count_lock;
  9332. + u16 hermes_reg_fake[0x40];
  9333. + u8 *bap_buf;
  9334. + struct urb *read_urb;
  9335. + int read_pipe;
  9336. + int write_pipe;
  9337. + u8 reply_count;
  9338. +};
  9339. +
  9340. +enum ezusb_state {
  9341. + EZUSB_CTX_START,
  9342. + EZUSB_CTX_QUEUED,
  9343. + EZUSB_CTX_REQ_SUBMITTED,
  9344. + EZUSB_CTX_REQ_COMPLETE,
  9345. + EZUSB_CTX_RESP_RECEIVED,
  9346. + EZUSB_CTX_REQ_TIMEOUT,
  9347. + EZUSB_CTX_REQ_FAILED,
  9348. + EZUSB_CTX_RESP_TIMEOUT,
  9349. + EZUSB_CTX_REQSUBMIT_FAIL,
  9350. + EZUSB_CTX_COMPLETE,
  9351. +};
  9352. +
  9353. +struct request_context {
  9354. + struct list_head list;
  9355. + refcount_t refcount;
  9356. + struct completion done; /* Signals that CTX is dead */
  9357. + int killed;
  9358. + struct urb *outurb; /* OUT for req pkt */
  9359. + struct ezusb_priv *upriv;
  9360. + struct ezusb_packet *buf;
  9361. + int buf_length;
  9362. + struct timer_list timer; /* Timeout handling */
  9363. + enum ezusb_state state; /* Current state */
  9364. + /* the RID that we will wait for */
  9365. + u16 out_rid;
  9366. + u16 in_rid;
  9367. +};
  9368. +
  9369. +
  9370. +/* Forward declarations */
  9371. +static void ezusb_ctx_complete(struct request_context *ctx);
  9372. +static void ezusb_req_queue_run(struct ezusb_priv *upriv);
  9373. +static void ezusb_bulk_in_callback(struct urb *urb);
  9374. +
  9375. +static inline u8 ezusb_reply_inc(u8 count)
  9376. +{
  9377. + if (count < 0x7F)
  9378. + return count + 1;
  9379. + else
  9380. + return 1;
  9381. +}
  9382. +
  9383. +static void ezusb_request_context_put(struct request_context *ctx)
  9384. +{
  9385. + if (!refcount_dec_and_test(&ctx->refcount))
  9386. + return;
  9387. +
  9388. + WARN_ON(!ctx->done.done);
  9389. + BUG_ON(ctx->outurb->status == -EINPROGRESS);
  9390. + BUG_ON(timer_pending(&ctx->timer));
  9391. + usb_free_urb(ctx->outurb);
  9392. + kfree(ctx->buf);
  9393. + kfree(ctx);
  9394. +}
  9395. +
  9396. +static inline void ezusb_mod_timer(struct ezusb_priv *upriv,
  9397. + struct timer_list *timer,
  9398. + unsigned long expire)
  9399. +{
  9400. + if (!upriv->udev)
  9401. + return;
  9402. + mod_timer(timer, expire);
  9403. +}
  9404. +
  9405. +static void ezusb_request_timerfn(struct timer_list *t)
  9406. +{
  9407. + struct request_context *ctx = from_timer(ctx, t, timer);
  9408. +
  9409. + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
  9410. + if (usb_unlink_urb(ctx->outurb) == -EINPROGRESS) {
  9411. + ctx->state = EZUSB_CTX_REQ_TIMEOUT;
  9412. + } else {
  9413. + ctx->state = EZUSB_CTX_RESP_TIMEOUT;
  9414. + dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
  9415. + refcount_inc(&ctx->refcount);
  9416. + ctx->killed = 1;
  9417. + ezusb_ctx_complete(ctx);
  9418. + ezusb_request_context_put(ctx);
  9419. + }
  9420. +};
  9421. +
  9422. +static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
  9423. + u16 out_rid, u16 in_rid)
  9424. +{
  9425. + struct request_context *ctx;
  9426. +
  9427. + ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
  9428. + if (!ctx)
  9429. + return NULL;
  9430. +
  9431. + ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC);
  9432. + if (!ctx->buf) {
  9433. + kfree(ctx);
  9434. + return NULL;
  9435. + }
  9436. + ctx->outurb = usb_alloc_urb(0, GFP_ATOMIC);
  9437. + if (!ctx->outurb) {
  9438. + kfree(ctx->buf);
  9439. + kfree(ctx);
  9440. + return NULL;
  9441. + }
  9442. +
  9443. + ctx->upriv = upriv;
  9444. + ctx->state = EZUSB_CTX_START;
  9445. + ctx->out_rid = out_rid;
  9446. + ctx->in_rid = in_rid;
  9447. +
  9448. + refcount_set(&ctx->refcount, 1);
  9449. + init_completion(&ctx->done);
  9450. +
  9451. + timer_setup(&ctx->timer, ezusb_request_timerfn, 0);
  9452. + return ctx;
  9453. +}
  9454. +
  9455. +static void ezusb_ctx_complete(struct request_context *ctx)
  9456. +{
  9457. + struct ezusb_priv *upriv = ctx->upriv;
  9458. + unsigned long flags;
  9459. +
  9460. + spin_lock_irqsave(&upriv->req_lock, flags);
  9461. +
  9462. + list_del_init(&ctx->list);
  9463. + if (upriv->udev) {
  9464. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9465. + ezusb_req_queue_run(upriv);
  9466. + spin_lock_irqsave(&upriv->req_lock, flags);
  9467. + }
  9468. +
  9469. + switch (ctx->state) {
  9470. + case EZUSB_CTX_COMPLETE:
  9471. + case EZUSB_CTX_REQSUBMIT_FAIL:
  9472. + case EZUSB_CTX_REQ_FAILED:
  9473. + case EZUSB_CTX_REQ_TIMEOUT:
  9474. + case EZUSB_CTX_RESP_TIMEOUT:
  9475. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9476. +
  9477. + if ((ctx->out_rid == EZUSB_RID_TX) && upriv->dev) {
  9478. + struct net_device *dev = upriv->dev;
  9479. + struct net_device_stats *stats = &dev->stats;
  9480. +
  9481. + if (ctx->state != EZUSB_CTX_COMPLETE)
  9482. + stats->tx_errors++;
  9483. + else
  9484. + stats->tx_packets++;
  9485. +
  9486. + netif_wake_queue(dev);
  9487. + }
  9488. + complete_all(&ctx->done);
  9489. + ezusb_request_context_put(ctx);
  9490. + break;
  9491. +
  9492. + default:
  9493. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9494. + if (!upriv->udev) {
  9495. + /* This is normal, as all request contexts get flushed
  9496. + * when the device is disconnected */
  9497. + err("Called, CTX not terminating, but device gone");
  9498. + complete_all(&ctx->done);
  9499. + ezusb_request_context_put(ctx);
  9500. + break;
  9501. + }
  9502. +
  9503. + err("Called, CTX not in terminating state.");
  9504. + /* Things are really bad if this happens. Just leak
  9505. + * the CTX because it may still be linked to the
  9506. + * queue or the OUT urb may still be active.
  9507. + * Just leaking at least prevents an Oops or Panic.
  9508. + */
  9509. + break;
  9510. + }
  9511. +}
  9512. +
  9513. +/*
  9514. + * ezusb_req_queue_run:
  9515. + * Description:
  9516. + * Note: Only one active CTX at any one time, because there's no
  9517. + * other (reliable) way to match the response URB to the correct
  9518. + * CTX.
  9519. + */
  9520. +static void ezusb_req_queue_run(struct ezusb_priv *upriv)
  9521. +{
  9522. + unsigned long flags;
  9523. + struct request_context *ctx;
  9524. + int result;
  9525. +
  9526. + spin_lock_irqsave(&upriv->req_lock, flags);
  9527. +
  9528. + if (!list_empty(&upriv->req_active))
  9529. + goto unlock;
  9530. +
  9531. + if (list_empty(&upriv->req_pending))
  9532. + goto unlock;
  9533. +
  9534. + ctx =
  9535. + list_entry(upriv->req_pending.next, struct request_context,
  9536. + list);
  9537. +
  9538. + if (!ctx->upriv->udev)
  9539. + goto unlock;
  9540. +
  9541. + /* We need to split this off to avoid a race condition */
  9542. + list_move_tail(&ctx->list, &upriv->req_active);
  9543. +
  9544. + if (ctx->state == EZUSB_CTX_QUEUED) {
  9545. + refcount_inc(&ctx->refcount);
  9546. + result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
  9547. + if (result) {
  9548. + ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
  9549. +
  9550. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9551. +
  9552. + err("Fatal, failed to submit command urb."
  9553. + " error=%d\n", result);
  9554. +
  9555. + ezusb_ctx_complete(ctx);
  9556. + ezusb_request_context_put(ctx);
  9557. + goto done;
  9558. + }
  9559. +
  9560. + ctx->state = EZUSB_CTX_REQ_SUBMITTED;
  9561. + ezusb_mod_timer(ctx->upriv, &ctx->timer,
  9562. + jiffies + DEF_TIMEOUT);
  9563. + }
  9564. +
  9565. + unlock:
  9566. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9567. +
  9568. + done:
  9569. + return;
  9570. +}
  9571. +
  9572. +static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
  9573. + struct request_context *ctx)
  9574. +{
  9575. + unsigned long flags;
  9576. +
  9577. + spin_lock_irqsave(&upriv->req_lock, flags);
  9578. +
  9579. + if (!ctx->upriv->udev) {
  9580. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9581. + goto done;
  9582. + }
  9583. + refcount_inc(&ctx->refcount);
  9584. + list_add_tail(&ctx->list, &upriv->req_pending);
  9585. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9586. +
  9587. + ctx->state = EZUSB_CTX_QUEUED;
  9588. + ezusb_req_queue_run(upriv);
  9589. +
  9590. + done:
  9591. + return;
  9592. +}
  9593. +
  9594. +static void ezusb_request_out_callback(struct urb *urb)
  9595. +{
  9596. + unsigned long flags;
  9597. + enum ezusb_state state;
  9598. + struct request_context *ctx = urb->context;
  9599. + struct ezusb_priv *upriv = ctx->upriv;
  9600. +
  9601. + spin_lock_irqsave(&upriv->req_lock, flags);
  9602. +
  9603. + del_timer(&ctx->timer);
  9604. +
  9605. + if (ctx->killed) {
  9606. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9607. + pr_warn("interrupt called with dead ctx\n");
  9608. + goto out;
  9609. + }
  9610. +
  9611. + state = ctx->state;
  9612. +
  9613. + if (urb->status == 0) {
  9614. + switch (state) {
  9615. + case EZUSB_CTX_REQ_SUBMITTED:
  9616. + if (ctx->in_rid) {
  9617. + ctx->state = EZUSB_CTX_REQ_COMPLETE;
  9618. + /* reply URB still pending */
  9619. + ezusb_mod_timer(upriv, &ctx->timer,
  9620. + jiffies + DEF_TIMEOUT);
  9621. + spin_unlock_irqrestore(&upriv->req_lock,
  9622. + flags);
  9623. + break;
  9624. + }
  9625. + fallthrough;
  9626. + case EZUSB_CTX_RESP_RECEIVED:
  9627. + /* IN already received before this OUT-ACK */
  9628. + ctx->state = EZUSB_CTX_COMPLETE;
  9629. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9630. + ezusb_ctx_complete(ctx);
  9631. + break;
  9632. +
  9633. + default:
  9634. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9635. + err("Unexpected state(0x%x, %d) in OUT URB",
  9636. + state, urb->status);
  9637. + break;
  9638. + }
  9639. + } else {
  9640. + /* If someone cancels the OUT URB then its status
  9641. + * should be either -ECONNRESET or -ENOENT.
  9642. + */
  9643. + switch (state) {
  9644. + case EZUSB_CTX_REQ_SUBMITTED:
  9645. + case EZUSB_CTX_RESP_RECEIVED:
  9646. + ctx->state = EZUSB_CTX_REQ_FAILED;
  9647. + fallthrough;
  9648. +
  9649. + case EZUSB_CTX_REQ_FAILED:
  9650. + case EZUSB_CTX_REQ_TIMEOUT:
  9651. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9652. +
  9653. + ezusb_ctx_complete(ctx);
  9654. + break;
  9655. +
  9656. + default:
  9657. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9658. +
  9659. + err("Unexpected state(0x%x, %d) in OUT URB",
  9660. + state, urb->status);
  9661. + break;
  9662. + }
  9663. + }
  9664. + out:
  9665. + ezusb_request_context_put(ctx);
  9666. +}
  9667. +
  9668. +static void ezusb_request_in_callback(struct ezusb_priv *upriv,
  9669. + struct urb *urb)
  9670. +{
  9671. + struct ezusb_packet *ans = urb->transfer_buffer;
  9672. + struct request_context *ctx = NULL;
  9673. + enum ezusb_state state;
  9674. + unsigned long flags;
  9675. +
  9676. + /* Find the CTX on the active queue that requested this URB */
  9677. + spin_lock_irqsave(&upriv->req_lock, flags);
  9678. + if (upriv->udev) {
  9679. + struct list_head *item;
  9680. +
  9681. + list_for_each(item, &upriv->req_active) {
  9682. + struct request_context *c;
  9683. + int reply_count;
  9684. +
  9685. + c = list_entry(item, struct request_context, list);
  9686. + reply_count =
  9687. + ezusb_reply_inc(c->buf->req_reply_count);
  9688. + if ((ans->ans_reply_count == reply_count)
  9689. + && (le16_to_cpu(ans->hermes_rid) == c->in_rid)) {
  9690. + ctx = c;
  9691. + break;
  9692. + }
  9693. + netdev_dbg(upriv->dev, "Skipped (0x%x/0x%x) (%d/%d)\n",
  9694. + le16_to_cpu(ans->hermes_rid), c->in_rid,
  9695. + ans->ans_reply_count, reply_count);
  9696. + }
  9697. + }
  9698. +
  9699. + if (ctx == NULL) {
  9700. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9701. + err("%s: got unexpected RID: 0x%04X", __func__,
  9702. + le16_to_cpu(ans->hermes_rid));
  9703. + ezusb_req_queue_run(upriv);
  9704. + return;
  9705. + }
  9706. +
  9707. + /* The data we want is in the in buffer, exchange */
  9708. + urb->transfer_buffer = ctx->buf;
  9709. + ctx->buf = (void *) ans;
  9710. + ctx->buf_length = urb->actual_length;
  9711. +
  9712. + state = ctx->state;
  9713. + switch (state) {
  9714. + case EZUSB_CTX_REQ_SUBMITTED:
  9715. + /* We have received our response URB before
  9716. + * our request has been acknowledged. Do NOT
  9717. + * destroy our CTX yet, because our OUT URB
  9718. + * is still alive ...
  9719. + */
  9720. + ctx->state = EZUSB_CTX_RESP_RECEIVED;
  9721. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9722. +
  9723. + /* Let the machine continue running. */
  9724. + break;
  9725. +
  9726. + case EZUSB_CTX_REQ_COMPLETE:
  9727. + /* This is the usual path: our request
  9728. + * has already been acknowledged, and
  9729. + * we have now received the reply.
  9730. + */
  9731. + ctx->state = EZUSB_CTX_COMPLETE;
  9732. +
  9733. + /* Stop the intimer */
  9734. + del_timer(&ctx->timer);
  9735. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9736. +
  9737. + /* Call the completion handler */
  9738. + ezusb_ctx_complete(ctx);
  9739. + break;
  9740. +
  9741. + default:
  9742. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  9743. +
  9744. + pr_warn("Matched IN URB, unexpected context state(0x%x)\n",
  9745. + state);
  9746. + /* Throw this CTX away and try submitting another */
  9747. + del_timer(&ctx->timer);
  9748. + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
  9749. + usb_unlink_urb(ctx->outurb);
  9750. + ezusb_req_queue_run(upriv);
  9751. + break;
  9752. + } /* switch */
  9753. +}
  9754. +
  9755. +typedef void (*ezusb_ctx_wait)(struct ezusb_priv *, struct request_context *);
  9756. +
  9757. +static void ezusb_req_ctx_wait_compl(struct ezusb_priv *upriv,
  9758. + struct request_context *ctx)
  9759. +{
  9760. + switch (ctx->state) {
  9761. + case EZUSB_CTX_QUEUED:
  9762. + case EZUSB_CTX_REQ_SUBMITTED:
  9763. + case EZUSB_CTX_REQ_COMPLETE:
  9764. + case EZUSB_CTX_RESP_RECEIVED:
  9765. + wait_for_completion(&ctx->done);
  9766. + break;
  9767. + default:
  9768. + /* Done or failed - nothing to wait for */
  9769. + break;
  9770. + }
  9771. +}
  9772. +
  9773. +static void ezusb_req_ctx_wait_poll(struct ezusb_priv *upriv,
  9774. + struct request_context *ctx)
  9775. +{
  9776. + int msecs;
  9777. +
  9778. + switch (ctx->state) {
  9779. + case EZUSB_CTX_QUEUED:
  9780. + case EZUSB_CTX_REQ_SUBMITTED:
  9781. + case EZUSB_CTX_REQ_COMPLETE:
  9782. + case EZUSB_CTX_RESP_RECEIVED:
  9783. + /* If we get called from a timer or with our lock acquired, then
  9784. + * we can't wait for the completion and have to poll. This won't
  9785. + * happen if the USB controller completes the URB requests in
  9786. + * BH.
  9787. + */
  9788. + msecs = DEF_TIMEOUT * (1000 / HZ);
  9789. +
  9790. + while (!try_wait_for_completion(&ctx->done) && msecs--)
  9791. + udelay(1000);
  9792. + break;
  9793. + default:
  9794. + /* Done or failed - nothing to wait for */
  9795. + break;
  9796. + }
  9797. +}
  9798. +
  9799. +static void ezusb_req_ctx_wait_skip(struct ezusb_priv *upriv,
  9800. + struct request_context *ctx)
  9801. +{
  9802. + WARN(1, "Shouldn't be invoked for in_rid\n");
  9803. +}
  9804. +
  9805. +static inline u16 build_crc(struct ezusb_packet *data)
  9806. +{
  9807. + u16 crc = 0;
  9808. + u8 *bytes = (u8 *)data;
  9809. + int i;
  9810. +
  9811. + for (i = 0; i < 8; i++)
  9812. + crc = (crc << 1) + bytes[i];
  9813. +
  9814. + return crc;
  9815. +}
  9816. +
  9817. +/*
  9818. + * ezusb_fill_req:
  9819. + *
  9820. + * if data == NULL and length > 0 the data is assumed to be already in
  9821. + * the target buffer and only the header is filled.
  9822. + *
  9823. + */
  9824. +static int ezusb_fill_req(struct ezusb_packet *req, u16 length, u16 rid,
  9825. + const void *data, u16 frame_type, u8 reply_count)
  9826. +{
  9827. + int total_size = sizeof(*req) + length;
  9828. +
  9829. + BUG_ON(total_size > BULK_BUF_SIZE);
  9830. +
  9831. + req->magic = cpu_to_le16(EZUSB_MAGIC);
  9832. + req->req_reply_count = reply_count;
  9833. + req->ans_reply_count = 0;
  9834. + req->frame_type = cpu_to_le16(frame_type);
  9835. + req->size = cpu_to_le16(length + 4);
  9836. + req->crc = cpu_to_le16(build_crc(req));
  9837. + req->hermes_len = cpu_to_le16(HERMES_BYTES_TO_RECLEN(length));
  9838. + req->hermes_rid = cpu_to_le16(rid);
  9839. + if (data)
  9840. + memcpy(req->data, data, length);
  9841. + return total_size;
  9842. +}
  9843. +
  9844. +static int ezusb_submit_in_urb(struct ezusb_priv *upriv)
  9845. +{
  9846. + int retval = 0;
  9847. + void *cur_buf = upriv->read_urb->transfer_buffer;
  9848. +
  9849. + if (upriv->read_urb->status == -EINPROGRESS) {
  9850. + netdev_dbg(upriv->dev, "urb busy, not resubmiting\n");
  9851. + retval = -EBUSY;
  9852. + goto exit;
  9853. + }
  9854. + usb_fill_bulk_urb(upriv->read_urb, upriv->udev, upriv->read_pipe,
  9855. + cur_buf, BULK_BUF_SIZE,
  9856. + ezusb_bulk_in_callback, upriv);
  9857. + upriv->read_urb->transfer_flags = 0;
  9858. + retval = usb_submit_urb(upriv->read_urb, GFP_ATOMIC);
  9859. + if (retval)
  9860. + err("%s submit failed %d", __func__, retval);
  9861. +
  9862. + exit:
  9863. + return retval;
  9864. +}
  9865. +
  9866. +static inline int ezusb_8051_cpucs(struct ezusb_priv *upriv, int reset)
  9867. +{
  9868. + int ret;
  9869. + u8 *res_val = NULL;
  9870. +
  9871. + if (!upriv->udev) {
  9872. + err("%s: !upriv->udev", __func__);
  9873. + return -EFAULT;
  9874. + }
  9875. +
  9876. + res_val = kmalloc(sizeof(*res_val), GFP_KERNEL);
  9877. +
  9878. + if (!res_val)
  9879. + return -ENOMEM;
  9880. +
  9881. + *res_val = reset; /* avoid argument promotion */
  9882. +
  9883. + ret = usb_control_msg(upriv->udev,
  9884. + usb_sndctrlpipe(upriv->udev, 0),
  9885. + EZUSB_REQUEST_FW_TRANS,
  9886. + USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  9887. + USB_DIR_OUT, EZUSB_CPUCS_REG, 0, res_val,
  9888. + sizeof(*res_val), DEF_TIMEOUT);
  9889. +
  9890. + kfree(res_val);
  9891. +
  9892. + return ret;
  9893. +}
  9894. +
  9895. +static int ezusb_firmware_download(struct ezusb_priv *upriv,
  9896. + struct ez_usb_fw *fw)
  9897. +{
  9898. + u8 *fw_buffer;
  9899. + int retval, addr;
  9900. + int variant_offset;
  9901. +
  9902. + fw_buffer = kmalloc(FW_BUF_SIZE, GFP_KERNEL);
  9903. + if (!fw_buffer) {
  9904. + printk(KERN_ERR PFX "Out of memory for firmware buffer.\n");
  9905. + return -ENOMEM;
  9906. + }
  9907. + /*
  9908. + * This byte is 1 and should be replaced with 0. The offset is
  9909. + * 0x10AD in version 0.0.6. The byte in question should follow
  9910. + * the end of the code pointed to by the jump in the beginning
  9911. + * of the firmware. Also, it is read by code located at 0x358.
  9912. + */
  9913. + variant_offset = be16_to_cpup((__be16 *) &fw->code[FW_VAR_OFFSET_PTR]);
  9914. + if (variant_offset >= fw->size) {
  9915. + printk(KERN_ERR PFX "Invalid firmware variant offset: "
  9916. + "0x%04x\n", variant_offset);
  9917. + retval = -EINVAL;
  9918. + goto fail;
  9919. + }
  9920. +
  9921. + retval = ezusb_8051_cpucs(upriv, 1);
  9922. + if (retval < 0)
  9923. + goto fail;
  9924. + for (addr = 0; addr < fw->size; addr += FW_BUF_SIZE) {
  9925. + /* 0x100-0x300 should be left alone, it contains card
  9926. + * specific data, like USB enumeration information */
  9927. + if ((addr >= FW_HOLE_START) && (addr < FW_HOLE_END))
  9928. + continue;
  9929. +
  9930. + memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE);
  9931. + if (variant_offset >= addr &&
  9932. + variant_offset < addr + FW_BUF_SIZE) {
  9933. + netdev_dbg(upriv->dev,
  9934. + "Patching card_variant byte at 0x%04X\n",
  9935. + variant_offset);
  9936. + fw_buffer[variant_offset - addr] = FW_VAR_VALUE;
  9937. + }
  9938. + retval = usb_control_msg(upriv->udev,
  9939. + usb_sndctrlpipe(upriv->udev, 0),
  9940. + EZUSB_REQUEST_FW_TRANS,
  9941. + USB_TYPE_VENDOR | USB_RECIP_DEVICE
  9942. + | USB_DIR_OUT,
  9943. + addr, 0x0,
  9944. + fw_buffer, FW_BUF_SIZE,
  9945. + DEF_TIMEOUT);
  9946. +
  9947. + if (retval < 0)
  9948. + goto fail;
  9949. + }
  9950. + retval = ezusb_8051_cpucs(upriv, 0);
  9951. + if (retval < 0)
  9952. + goto fail;
  9953. +
  9954. + goto exit;
  9955. + fail:
  9956. + printk(KERN_ERR PFX "Firmware download failed, error %d\n",
  9957. + retval);
  9958. + exit:
  9959. + kfree(fw_buffer);
  9960. + return retval;
  9961. +}
  9962. +
  9963. +static int ezusb_access_ltv(struct ezusb_priv *upriv,
  9964. + struct request_context *ctx,
  9965. + u16 length, const void *data, u16 frame_type,
  9966. + void *ans_buff, unsigned ans_size, u16 *ans_length,
  9967. + ezusb_ctx_wait ezusb_ctx_wait_func)
  9968. +{
  9969. + int req_size;
  9970. + int retval = 0;
  9971. + enum ezusb_state state;
  9972. +
  9973. + if (!upriv->udev) {
  9974. + retval = -ENODEV;
  9975. + goto exit;
  9976. + }
  9977. +
  9978. + if (upriv->read_urb->status != -EINPROGRESS)
  9979. + err("%s: in urb not pending", __func__);
  9980. +
  9981. + /* protect upriv->reply_count, guarantee sequential numbers */
  9982. + spin_lock_bh(&upriv->reply_count_lock);
  9983. + req_size = ezusb_fill_req(ctx->buf, length, ctx->out_rid, data,
  9984. + frame_type, upriv->reply_count);
  9985. + usb_fill_bulk_urb(ctx->outurb, upriv->udev, upriv->write_pipe,
  9986. + ctx->buf, req_size,
  9987. + ezusb_request_out_callback, ctx);
  9988. +
  9989. + if (ctx->in_rid)
  9990. + upriv->reply_count = ezusb_reply_inc(upriv->reply_count);
  9991. +
  9992. + ezusb_req_enqueue_run(upriv, ctx);
  9993. +
  9994. + spin_unlock_bh(&upriv->reply_count_lock);
  9995. +
  9996. + if (ctx->in_rid)
  9997. + ezusb_ctx_wait_func(upriv, ctx);
  9998. +
  9999. + state = ctx->state;
  10000. + switch (state) {
  10001. + case EZUSB_CTX_COMPLETE:
  10002. + retval = ctx->outurb->status;
  10003. + break;
  10004. +
  10005. + case EZUSB_CTX_QUEUED:
  10006. + case EZUSB_CTX_REQ_SUBMITTED:
  10007. + if (!ctx->in_rid)
  10008. + break;
  10009. + fallthrough;
  10010. + default:
  10011. + err("%s: Unexpected context state %d", __func__,
  10012. + state);
  10013. + fallthrough;
  10014. + case EZUSB_CTX_REQ_TIMEOUT:
  10015. + case EZUSB_CTX_REQ_FAILED:
  10016. + case EZUSB_CTX_RESP_TIMEOUT:
  10017. + case EZUSB_CTX_REQSUBMIT_FAIL:
  10018. + printk(KERN_ERR PFX "Access failed, resetting (state %d,"
  10019. + " reply_count %d)\n", state, upriv->reply_count);
  10020. + upriv->reply_count = 0;
  10021. + if (state == EZUSB_CTX_REQ_TIMEOUT
  10022. + || state == EZUSB_CTX_RESP_TIMEOUT) {
  10023. + printk(KERN_ERR PFX "ctx timed out\n");
  10024. + retval = -ETIMEDOUT;
  10025. + } else {
  10026. + printk(KERN_ERR PFX "ctx failed\n");
  10027. + retval = -EFAULT;
  10028. + }
  10029. + goto exit;
  10030. + }
  10031. + if (ctx->in_rid) {
  10032. + struct ezusb_packet *ans = ctx->buf;
  10033. + unsigned exp_len;
  10034. +
  10035. + if (ans->hermes_len != 0)
  10036. + exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
  10037. + else
  10038. + exp_len = 14;
  10039. +
  10040. + if (exp_len != ctx->buf_length) {
  10041. + err("%s: length mismatch for RID 0x%04x: "
  10042. + "expected %d, got %d", __func__,
  10043. + ctx->in_rid, exp_len, ctx->buf_length);
  10044. + retval = -EIO;
  10045. + goto exit;
  10046. + }
  10047. +
  10048. + if (ans_buff)
  10049. + memcpy(ans_buff, ans->data, min(exp_len, ans_size));
  10050. + if (ans_length)
  10051. + *ans_length = le16_to_cpu(ans->hermes_len);
  10052. + }
  10053. + exit:
  10054. + ezusb_request_context_put(ctx);
  10055. + return retval;
  10056. +}
  10057. +
  10058. +static int __ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
  10059. + u16 length, const void *data,
  10060. + ezusb_ctx_wait ezusb_ctx_wait_func)
  10061. +{
  10062. + struct ezusb_priv *upriv = hw->priv;
  10063. + u16 frame_type;
  10064. + struct request_context *ctx;
  10065. +
  10066. + if (length == 0)
  10067. + return -EINVAL;
  10068. +
  10069. + length = HERMES_RECLEN_TO_BYTES(length);
  10070. +
  10071. + /* On memory mapped devices HERMES_RID_CNFGROUPADDRESSES can be
  10072. + * set to be empty, but the USB bridge doesn't like it */
  10073. + if (length == 0)
  10074. + return 0;
  10075. +
  10076. + ctx = ezusb_alloc_ctx(upriv, rid, EZUSB_RID_ACK);
  10077. + if (!ctx)
  10078. + return -ENOMEM;
  10079. +
  10080. + if (rid == EZUSB_RID_TX)
  10081. + frame_type = EZUSB_FRAME_DATA;
  10082. + else
  10083. + frame_type = EZUSB_FRAME_CONTROL;
  10084. +
  10085. + return ezusb_access_ltv(upriv, ctx, length, data, frame_type,
  10086. + NULL, 0, NULL, ezusb_ctx_wait_func);
  10087. +}
  10088. +
  10089. +static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
  10090. + u16 length, const void *data)
  10091. +{
  10092. + return __ezusb_write_ltv(hw, bap, rid, length, data,
  10093. + ezusb_req_ctx_wait_poll);
  10094. +}
  10095. +
  10096. +static int __ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
  10097. + unsigned bufsize, u16 *length, void *buf,
  10098. + ezusb_ctx_wait ezusb_ctx_wait_func)
  10099. +
  10100. +{
  10101. + struct ezusb_priv *upriv = hw->priv;
  10102. + struct request_context *ctx;
  10103. +
  10104. + if (bufsize % 2)
  10105. + return -EINVAL;
  10106. +
  10107. + ctx = ezusb_alloc_ctx(upriv, rid, rid);
  10108. + if (!ctx)
  10109. + return -ENOMEM;
  10110. +
  10111. + return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL,
  10112. + buf, bufsize, length, ezusb_req_ctx_wait_poll);
  10113. +}
  10114. +
  10115. +static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
  10116. + unsigned bufsize, u16 *length, void *buf)
  10117. +{
  10118. + return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf,
  10119. + ezusb_req_ctx_wait_poll);
  10120. +}
  10121. +
  10122. +static int ezusb_read_ltv_preempt(struct hermes *hw, int bap, u16 rid,
  10123. + unsigned bufsize, u16 *length, void *buf)
  10124. +{
  10125. + return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf,
  10126. + ezusb_req_ctx_wait_compl);
  10127. +}
  10128. +
  10129. +static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
  10130. + u16 parm2, struct hermes_response *resp)
  10131. +{
  10132. + WARN_ON_ONCE(1);
  10133. + return -EINVAL;
  10134. +}
  10135. +
  10136. +static int __ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
  10137. + struct hermes_response *resp,
  10138. + ezusb_ctx_wait ezusb_ctx_wait_func)
  10139. +{
  10140. + struct ezusb_priv *upriv = hw->priv;
  10141. + struct request_context *ctx;
  10142. +
  10143. + __le16 data[4] = {
  10144. + cpu_to_le16(cmd),
  10145. + cpu_to_le16(parm0),
  10146. + 0,
  10147. + 0,
  10148. + };
  10149. + netdev_dbg(upriv->dev, "0x%04X, parm0 0x%04X\n", cmd, parm0);
  10150. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
  10151. + if (!ctx)
  10152. + return -ENOMEM;
  10153. +
  10154. + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
  10155. + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
  10156. + ezusb_ctx_wait_func);
  10157. +}
  10158. +
  10159. +static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
  10160. + struct hermes_response *resp)
  10161. +{
  10162. + return __ezusb_docmd_wait(hw, cmd, parm0, resp, ezusb_req_ctx_wait_poll);
  10163. +}
  10164. +
  10165. +static int ezusb_bap_pread(struct hermes *hw, int bap,
  10166. + void *buf, int len, u16 id, u16 offset)
  10167. +{
  10168. + struct ezusb_priv *upriv = hw->priv;
  10169. + struct ezusb_packet *ans = (void *) upriv->read_urb->transfer_buffer;
  10170. + int actual_length = upriv->read_urb->actual_length;
  10171. +
  10172. + if (id == EZUSB_RID_RX) {
  10173. + if ((sizeof(*ans) + offset + len) > actual_length) {
  10174. + printk(KERN_ERR PFX "BAP read beyond buffer end "
  10175. + "in rx frame\n");
  10176. + return -EINVAL;
  10177. + }
  10178. + memcpy(buf, ans->data + offset, len);
  10179. + return 0;
  10180. + }
  10181. +
  10182. + if (EZUSB_IS_INFO(id)) {
  10183. + /* Include 4 bytes for length/type */
  10184. + if ((sizeof(*ans) + offset + len - 4) > actual_length) {
  10185. + printk(KERN_ERR PFX "BAP read beyond buffer end "
  10186. + "in info frame\n");
  10187. + return -EFAULT;
  10188. + }
  10189. + memcpy(buf, ans->data + offset - 4, len);
  10190. + } else {
  10191. + printk(KERN_ERR PFX "Unexpected fid 0x%04x\n", id);
  10192. + return -EINVAL;
  10193. + }
  10194. +
  10195. + return 0;
  10196. +}
  10197. +
  10198. +static int ezusb_read_pda(struct hermes *hw, __le16 *pda,
  10199. + u32 pda_addr, u16 pda_len)
  10200. +{
  10201. + struct ezusb_priv *upriv = hw->priv;
  10202. + struct request_context *ctx;
  10203. + __le16 data[] = {
  10204. + cpu_to_le16(pda_addr & 0xffff),
  10205. + cpu_to_le16(pda_len - 4)
  10206. + };
  10207. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_READ_PDA, EZUSB_RID_READ_PDA);
  10208. + if (!ctx)
  10209. + return -ENOMEM;
  10210. +
  10211. + /* wl_lkm does not include PDA size in the PDA area.
  10212. + * We will pad the information into pda, so other routines
  10213. + * don't have to be modified */
  10214. + pda[0] = cpu_to_le16(pda_len - 2);
  10215. + /* Includes CFG_PROD_DATA but not itself */
  10216. + pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
  10217. +
  10218. + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
  10219. + EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4,
  10220. + NULL, ezusb_req_ctx_wait_compl);
  10221. +}
  10222. +
  10223. +static int ezusb_program_init(struct hermes *hw, u32 entry_point)
  10224. +{
  10225. + struct ezusb_priv *upriv = hw->priv;
  10226. + struct request_context *ctx;
  10227. + __le32 data = cpu_to_le32(entry_point);
  10228. +
  10229. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_INIT, EZUSB_RID_ACK);
  10230. + if (!ctx)
  10231. + return -ENOMEM;
  10232. +
  10233. + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
  10234. + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
  10235. + ezusb_req_ctx_wait_compl);
  10236. +}
  10237. +
  10238. +static int ezusb_program_end(struct hermes *hw)
  10239. +{
  10240. + struct ezusb_priv *upriv = hw->priv;
  10241. + struct request_context *ctx;
  10242. +
  10243. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_END, EZUSB_RID_ACK);
  10244. + if (!ctx)
  10245. + return -ENOMEM;
  10246. +
  10247. + return ezusb_access_ltv(upriv, ctx, 0, NULL,
  10248. + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
  10249. + ezusb_req_ctx_wait_compl);
  10250. +}
  10251. +
  10252. +static int ezusb_program_bytes(struct hermes *hw, const char *buf,
  10253. + u32 addr, u32 len)
  10254. +{
  10255. + struct ezusb_priv *upriv = hw->priv;
  10256. + struct request_context *ctx;
  10257. + __le32 data = cpu_to_le32(addr);
  10258. + int err;
  10259. +
  10260. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_SET_ADDR, EZUSB_RID_ACK);
  10261. + if (!ctx)
  10262. + return -ENOMEM;
  10263. +
  10264. + err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
  10265. + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
  10266. + ezusb_req_ctx_wait_compl);
  10267. + if (err)
  10268. + return err;
  10269. +
  10270. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_BYTES, EZUSB_RID_ACK);
  10271. + if (!ctx)
  10272. + return -ENOMEM;
  10273. +
  10274. + return ezusb_access_ltv(upriv, ctx, len, buf,
  10275. + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
  10276. + ezusb_req_ctx_wait_compl);
  10277. +}
  10278. +
  10279. +static int ezusb_program(struct hermes *hw, const char *buf,
  10280. + u32 addr, u32 len)
  10281. +{
  10282. + u32 ch_addr;
  10283. + u32 ch_len;
  10284. + int err = 0;
  10285. +
  10286. + /* We can only send 2048 bytes out of the bulk xmit at a time,
  10287. + * so we have to split any programming into chunks of <2048
  10288. + * bytes. */
  10289. +
  10290. + ch_len = (len < MAX_DL_SIZE) ? len : MAX_DL_SIZE;
  10291. + ch_addr = addr;
  10292. +
  10293. + while (ch_addr < (addr + len)) {
  10294. + pr_debug("Programming subblock of length %d "
  10295. + "to address 0x%08x. Data @ %p\n",
  10296. + ch_len, ch_addr, &buf[ch_addr - addr]);
  10297. +
  10298. + err = ezusb_program_bytes(hw, &buf[ch_addr - addr],
  10299. + ch_addr, ch_len);
  10300. + if (err)
  10301. + break;
  10302. +
  10303. + ch_addr += ch_len;
  10304. + ch_len = ((addr + len - ch_addr) < MAX_DL_SIZE) ?
  10305. + (addr + len - ch_addr) : MAX_DL_SIZE;
  10306. + }
  10307. +
  10308. + return err;
  10309. +}
  10310. +
  10311. +static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
  10312. +{
  10313. + struct orinoco_private *priv = ndev_priv(dev);
  10314. + struct net_device_stats *stats = &dev->stats;
  10315. + struct ezusb_priv *upriv = priv->card;
  10316. + u8 mic[MICHAEL_MIC_LEN + 1];
  10317. + int err = 0;
  10318. + int tx_control;
  10319. + unsigned long flags;
  10320. + struct request_context *ctx;
  10321. + u8 *buf;
  10322. + int tx_size;
  10323. +
  10324. + if (!netif_running(dev)) {
  10325. + printk(KERN_ERR "%s: Tx on stopped device!\n",
  10326. + dev->name);
  10327. + return NETDEV_TX_BUSY;
  10328. + }
  10329. +
  10330. + if (netif_queue_stopped(dev)) {
  10331. + printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
  10332. + dev->name);
  10333. + return NETDEV_TX_BUSY;
  10334. + }
  10335. +
  10336. + if (orinoco_lock(priv, &flags) != 0) {
  10337. + printk(KERN_ERR
  10338. + "%s: ezusb_xmit() called while hw_unavailable\n",
  10339. + dev->name);
  10340. + return NETDEV_TX_BUSY;
  10341. + }
  10342. +
  10343. + if (!netif_carrier_ok(dev) ||
  10344. + (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
  10345. + /* Oops, the firmware hasn't established a connection,
  10346. + silently drop the packet (this seems to be the
  10347. + safest approach). */
  10348. + goto drop;
  10349. + }
  10350. +
  10351. + /* Check packet length */
  10352. + if (skb->len < ETH_HLEN)
  10353. + goto drop;
  10354. +
  10355. + tx_control = 0;
  10356. +
  10357. + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
  10358. + &mic[0]);
  10359. + if (err)
  10360. + goto drop;
  10361. +
  10362. + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
  10363. + if (!ctx)
  10364. + goto drop;
  10365. +
  10366. + memset(ctx->buf, 0, BULK_BUF_SIZE);
  10367. + buf = ctx->buf->data;
  10368. +
  10369. + {
  10370. + __le16 *tx_cntl = (__le16 *)buf;
  10371. + *tx_cntl = cpu_to_le16(tx_control);
  10372. + buf += sizeof(*tx_cntl);
  10373. + }
  10374. +
  10375. + memcpy(buf, skb->data, skb->len);
  10376. + buf += skb->len;
  10377. +
  10378. + if (tx_control & HERMES_TXCTRL_MIC) {
  10379. + u8 *m = mic;
  10380. + /* Mic has been offset so it can be copied to an even
  10381. + * address. We're copying eveything anyway, so we
  10382. + * don't need to copy that first byte. */
  10383. + if (skb->len % 2)
  10384. + m++;
  10385. + memcpy(buf, m, MICHAEL_MIC_LEN);
  10386. + buf += MICHAEL_MIC_LEN;
  10387. + }
  10388. +
  10389. + /* Finally, we actually initiate the send */
  10390. + netif_stop_queue(dev);
  10391. +
  10392. + /* The card may behave better if we send evenly sized usb transfers */
  10393. + tx_size = ALIGN(buf - ctx->buf->data, 2);
  10394. +
  10395. + err = ezusb_access_ltv(upriv, ctx, tx_size, NULL,
  10396. + EZUSB_FRAME_DATA, NULL, 0, NULL,
  10397. + ezusb_req_ctx_wait_skip);
  10398. +
  10399. + if (err) {
  10400. + netif_start_queue(dev);
  10401. + if (net_ratelimit())
  10402. + printk(KERN_ERR "%s: Error %d transmitting packet\n",
  10403. + dev->name, err);
  10404. + goto busy;
  10405. + }
  10406. +
  10407. + netif_trans_update(dev);
  10408. + stats->tx_bytes += skb->len;
  10409. + goto ok;
  10410. +
  10411. + drop:
  10412. + stats->tx_errors++;
  10413. + stats->tx_dropped++;
  10414. +
  10415. + ok:
  10416. + orinoco_unlock(priv, &flags);
  10417. + dev_kfree_skb(skb);
  10418. + return NETDEV_TX_OK;
  10419. +
  10420. + busy:
  10421. + orinoco_unlock(priv, &flags);
  10422. + return NETDEV_TX_BUSY;
  10423. +}
  10424. +
  10425. +static int ezusb_allocate(struct hermes *hw, u16 size, u16 *fid)
  10426. +{
  10427. + *fid = EZUSB_RID_TX;
  10428. + return 0;
  10429. +}
  10430. +
  10431. +
  10432. +static int ezusb_hard_reset(struct orinoco_private *priv)
  10433. +{
  10434. + struct ezusb_priv *upriv = priv->card;
  10435. + int retval = ezusb_8051_cpucs(upriv, 1);
  10436. +
  10437. + if (retval < 0) {
  10438. + err("Failed to reset");
  10439. + return retval;
  10440. + }
  10441. +
  10442. + retval = ezusb_8051_cpucs(upriv, 0);
  10443. + if (retval < 0) {
  10444. + err("Failed to unreset");
  10445. + return retval;
  10446. + }
  10447. +
  10448. + netdev_dbg(upriv->dev, "sending control message\n");
  10449. + retval = usb_control_msg(upriv->udev,
  10450. + usb_sndctrlpipe(upriv->udev, 0),
  10451. + EZUSB_REQUEST_TRIGGER,
  10452. + USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  10453. + USB_DIR_OUT, 0x0, 0x0, NULL, 0,
  10454. + DEF_TIMEOUT);
  10455. + if (retval < 0) {
  10456. + err("EZUSB_REQUEST_TRIGGER failed retval %d", retval);
  10457. + return retval;
  10458. + }
  10459. +#if 0
  10460. + dbg("Sending EZUSB_REQUEST_TRIG_AC");
  10461. + retval = usb_control_msg(upriv->udev,
  10462. + usb_sndctrlpipe(upriv->udev, 0),
  10463. + EZUSB_REQUEST_TRIG_AC,
  10464. + USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  10465. + USB_DIR_OUT, 0x00FA, 0x0, NULL, 0,
  10466. + DEF_TIMEOUT);
  10467. + if (retval < 0) {
  10468. + err("EZUSB_REQUEST_TRIG_AC failed retval %d", retval);
  10469. + return retval;
  10470. + }
  10471. +#endif
  10472. +
  10473. + return 0;
  10474. +}
  10475. +
  10476. +
  10477. +static int ezusb_init(struct hermes *hw)
  10478. +{
  10479. + struct ezusb_priv *upriv = hw->priv;
  10480. + int retval;
  10481. +
  10482. + if (!upriv)
  10483. + return -EINVAL;
  10484. +
  10485. + upriv->reply_count = 0;
  10486. + /* Write the MAGIC number on the simulated registers to keep
  10487. + * orinoco.c happy */
  10488. + hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
  10489. + hermes_write_regn(hw, RXFID, EZUSB_RID_RX);
  10490. +
  10491. + usb_kill_urb(upriv->read_urb);
  10492. + ezusb_submit_in_urb(upriv);
  10493. +
  10494. + retval = __ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1,
  10495. + HERMES_BYTES_TO_RECLEN(2), "\x10\x00",
  10496. + ezusb_req_ctx_wait_compl);
  10497. + if (retval < 0) {
  10498. + printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval);
  10499. + return retval;
  10500. + }
  10501. +
  10502. + retval = __ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL,
  10503. + ezusb_req_ctx_wait_compl);
  10504. + if (retval < 0) {
  10505. + printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval);
  10506. + return retval;
  10507. + }
  10508. +
  10509. + return 0;
  10510. +}
  10511. +
  10512. +static void ezusb_bulk_in_callback(struct urb *urb)
  10513. +{
  10514. + struct ezusb_priv *upriv = (struct ezusb_priv *) urb->context;
  10515. + struct ezusb_packet *ans = urb->transfer_buffer;
  10516. + u16 crc;
  10517. + u16 hermes_rid;
  10518. +
  10519. + if (upriv->udev == NULL)
  10520. + return;
  10521. +
  10522. + if (urb->status == -ETIMEDOUT) {
  10523. + /* When a device gets unplugged we get this every time
  10524. + * we resubmit, flooding the logs. Since we don't use
  10525. + * USB timeouts, it shouldn't happen any other time*/
  10526. + pr_warn("%s: urb timed out, not resubmitting\n", __func__);
  10527. + return;
  10528. + }
  10529. + if (urb->status == -ECONNABORTED) {
  10530. + pr_warn("%s: connection abort, resubmitting urb\n",
  10531. + __func__);
  10532. + goto resubmit;
  10533. + }
  10534. + if ((urb->status == -EILSEQ)
  10535. + || (urb->status == -ENOENT)
  10536. + || (urb->status == -ECONNRESET)) {
  10537. + netdev_dbg(upriv->dev, "status %d, not resubmiting\n",
  10538. + urb->status);
  10539. + return;
  10540. + }
  10541. + if (urb->status)
  10542. + netdev_dbg(upriv->dev, "status: %d length: %d\n",
  10543. + urb->status, urb->actual_length);
  10544. + if (urb->actual_length < sizeof(*ans)) {
  10545. + err("%s: short read, ignoring", __func__);
  10546. + goto resubmit;
  10547. + }
  10548. + crc = build_crc(ans);
  10549. + if (le16_to_cpu(ans->crc) != crc) {
  10550. + err("CRC error, ignoring packet");
  10551. + goto resubmit;
  10552. + }
  10553. +
  10554. + hermes_rid = le16_to_cpu(ans->hermes_rid);
  10555. + if ((hermes_rid != EZUSB_RID_RX) && !EZUSB_IS_INFO(hermes_rid)) {
  10556. + ezusb_request_in_callback(upriv, urb);
  10557. + } else if (upriv->dev) {
  10558. + struct net_device *dev = upriv->dev;
  10559. + struct orinoco_private *priv = ndev_priv(dev);
  10560. + struct hermes *hw = &priv->hw;
  10561. +
  10562. + if (hermes_rid == EZUSB_RID_RX) {
  10563. + __orinoco_ev_rx(dev, hw);
  10564. + } else {
  10565. + hermes_write_regn(hw, INFOFID,
  10566. + le16_to_cpu(ans->hermes_rid));
  10567. + __orinoco_ev_info(dev, hw);
  10568. + }
  10569. + }
  10570. +
  10571. + resubmit:
  10572. + if (upriv->udev)
  10573. + ezusb_submit_in_urb(upriv);
  10574. +}
  10575. +
  10576. +static inline void ezusb_delete(struct ezusb_priv *upriv)
  10577. +{
  10578. + struct list_head *item;
  10579. + struct list_head *tmp_item;
  10580. + unsigned long flags;
  10581. +
  10582. + BUG_ON(!upriv);
  10583. +
  10584. + mutex_lock(&upriv->mtx);
  10585. +
  10586. + upriv->udev = NULL; /* No timer will be rearmed from here */
  10587. +
  10588. + usb_kill_urb(upriv->read_urb);
  10589. +
  10590. + spin_lock_irqsave(&upriv->req_lock, flags);
  10591. + list_for_each_safe(item, tmp_item, &upriv->req_active) {
  10592. + struct request_context *ctx;
  10593. + int err;
  10594. +
  10595. + ctx = list_entry(item, struct request_context, list);
  10596. + refcount_inc(&ctx->refcount);
  10597. +
  10598. + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
  10599. + err = usb_unlink_urb(ctx->outurb);
  10600. +
  10601. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  10602. + if (err == -EINPROGRESS)
  10603. + wait_for_completion(&ctx->done);
  10604. +
  10605. + del_timer_sync(&ctx->timer);
  10606. + /* FIXME: there is an slight chance for the irq handler to
  10607. + * be running */
  10608. + if (!list_empty(&ctx->list))
  10609. + ezusb_ctx_complete(ctx);
  10610. +
  10611. + ezusb_request_context_put(ctx);
  10612. + spin_lock_irqsave(&upriv->req_lock, flags);
  10613. + }
  10614. + spin_unlock_irqrestore(&upriv->req_lock, flags);
  10615. +
  10616. + list_for_each_safe(item, tmp_item, &upriv->req_pending)
  10617. + ezusb_ctx_complete(list_entry(item,
  10618. + struct request_context, list));
  10619. +
  10620. + if (upriv->read_urb && upriv->read_urb->status == -EINPROGRESS)
  10621. + printk(KERN_ERR PFX "Some URB in progress\n");
  10622. +
  10623. + mutex_unlock(&upriv->mtx);
  10624. +
  10625. + if (upriv->read_urb) {
  10626. + kfree(upriv->read_urb->transfer_buffer);
  10627. + usb_free_urb(upriv->read_urb);
  10628. + }
  10629. + kfree(upriv->bap_buf);
  10630. + if (upriv->dev) {
  10631. + struct orinoco_private *priv = ndev_priv(upriv->dev);
  10632. + orinoco_if_del(priv);
  10633. + wiphy_unregister(priv_to_wiphy(upriv));
  10634. + free_orinocodev(priv);
  10635. + }
  10636. +}
  10637. +
  10638. +static void ezusb_lock_irqsave(spinlock_t *lock,
  10639. + unsigned long *flags) __acquires(lock)
  10640. +{
  10641. + spin_lock_bh(lock);
  10642. +}
  10643. +
  10644. +static void ezusb_unlock_irqrestore(spinlock_t *lock,
  10645. + unsigned long *flags) __releases(lock)
  10646. +{
  10647. + spin_unlock_bh(lock);
  10648. +}
  10649. +
  10650. +static void ezusb_lock_irq(spinlock_t *lock) __acquires(lock)
  10651. +{
  10652. + spin_lock_bh(lock);
  10653. +}
  10654. +
  10655. +static void ezusb_unlock_irq(spinlock_t *lock) __releases(lock)
  10656. +{
  10657. + spin_unlock_bh(lock);
  10658. +}
  10659. +
  10660. +static const struct hermes_ops ezusb_ops = {
  10661. + .init = ezusb_init,
  10662. + .cmd_wait = ezusb_docmd_wait,
  10663. + .init_cmd_wait = ezusb_doicmd_wait,
  10664. + .allocate = ezusb_allocate,
  10665. + .read_ltv = ezusb_read_ltv,
  10666. + .read_ltv_pr = ezusb_read_ltv_preempt,
  10667. + .write_ltv = ezusb_write_ltv,
  10668. + .bap_pread = ezusb_bap_pread,
  10669. + .read_pda = ezusb_read_pda,
  10670. + .program_init = ezusb_program_init,
  10671. + .program_end = ezusb_program_end,
  10672. + .program = ezusb_program,
  10673. + .lock_irqsave = ezusb_lock_irqsave,
  10674. + .unlock_irqrestore = ezusb_unlock_irqrestore,
  10675. + .lock_irq = ezusb_lock_irq,
  10676. + .unlock_irq = ezusb_unlock_irq,
  10677. +};
  10678. +
  10679. +static const struct net_device_ops ezusb_netdev_ops = {
  10680. + .ndo_open = orinoco_open,
  10681. + .ndo_stop = orinoco_stop,
  10682. + .ndo_start_xmit = ezusb_xmit,
  10683. + .ndo_set_rx_mode = orinoco_set_multicast_list,
  10684. + .ndo_change_mtu = orinoco_change_mtu,
  10685. + .ndo_set_mac_address = eth_mac_addr,
  10686. + .ndo_validate_addr = eth_validate_addr,
  10687. + .ndo_tx_timeout = orinoco_tx_timeout,
  10688. +};
  10689. +
  10690. +static int ezusb_probe(struct usb_interface *interface,
  10691. + const struct usb_device_id *id)
  10692. +{
  10693. + struct usb_device *udev = interface_to_usbdev(interface);
  10694. + struct orinoco_private *priv;
  10695. + struct hermes *hw;
  10696. + struct ezusb_priv *upriv = NULL;
  10697. + struct usb_interface_descriptor *iface_desc;
  10698. + struct usb_endpoint_descriptor *ep;
  10699. + const struct firmware *fw_entry = NULL;
  10700. + int retval = 0;
  10701. + int i;
  10702. +
  10703. + priv = alloc_orinocodev(sizeof(*upriv), &udev->dev,
  10704. + ezusb_hard_reset, NULL);
  10705. + if (!priv) {
  10706. + err("Couldn't allocate orinocodev");
  10707. + retval = -ENOMEM;
  10708. + goto exit;
  10709. + }
  10710. +
  10711. + hw = &priv->hw;
  10712. +
  10713. + upriv = priv->card;
  10714. +
  10715. + mutex_init(&upriv->mtx);
  10716. + spin_lock_init(&upriv->reply_count_lock);
  10717. +
  10718. + spin_lock_init(&upriv->req_lock);
  10719. + INIT_LIST_HEAD(&upriv->req_pending);
  10720. + INIT_LIST_HEAD(&upriv->req_active);
  10721. +
  10722. + upriv->udev = udev;
  10723. +
  10724. + hw->iobase = (void __force __iomem *) &upriv->hermes_reg_fake;
  10725. + hw->reg_spacing = HERMES_16BIT_REGSPACING;
  10726. + hw->priv = upriv;
  10727. + hw->ops = &ezusb_ops;
  10728. +
  10729. + /* set up the endpoint information */
  10730. + /* check out the endpoints */
  10731. +
  10732. + iface_desc = &interface->cur_altsetting->desc;
  10733. + for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
  10734. + ep = &interface->cur_altsetting->endpoint[i].desc;
  10735. +
  10736. + if (usb_endpoint_is_bulk_in(ep)) {
  10737. + /* we found a bulk in endpoint */
  10738. + if (upriv->read_urb != NULL) {
  10739. + pr_warn("Found a second bulk in ep, ignored\n");
  10740. + continue;
  10741. + }
  10742. +
  10743. + upriv->read_urb = usb_alloc_urb(0, GFP_KERNEL);
  10744. + if (!upriv->read_urb)
  10745. + goto error;
  10746. + if (le16_to_cpu(ep->wMaxPacketSize) != 64)
  10747. + pr_warn("bulk in: wMaxPacketSize!= 64\n");
  10748. + if (ep->bEndpointAddress != (2 | USB_DIR_IN))
  10749. + pr_warn("bulk in: bEndpointAddress: %d\n",
  10750. + ep->bEndpointAddress);
  10751. + upriv->read_pipe = usb_rcvbulkpipe(udev,
  10752. + ep->
  10753. + bEndpointAddress);
  10754. + upriv->read_urb->transfer_buffer =
  10755. + kmalloc(BULK_BUF_SIZE, GFP_KERNEL);
  10756. + if (!upriv->read_urb->transfer_buffer) {
  10757. + err("Couldn't allocate IN buffer");
  10758. + goto error;
  10759. + }
  10760. + }
  10761. +
  10762. + if (usb_endpoint_is_bulk_out(ep)) {
  10763. + /* we found a bulk out endpoint */
  10764. + if (upriv->bap_buf != NULL) {
  10765. + pr_warn("Found a second bulk out ep, ignored\n");
  10766. + continue;
  10767. + }
  10768. +
  10769. + if (le16_to_cpu(ep->wMaxPacketSize) != 64)
  10770. + pr_warn("bulk out: wMaxPacketSize != 64\n");
  10771. + if (ep->bEndpointAddress != 2)
  10772. + pr_warn("bulk out: bEndpointAddress: %d\n",
  10773. + ep->bEndpointAddress);
  10774. + upriv->write_pipe = usb_sndbulkpipe(udev,
  10775. + ep->
  10776. + bEndpointAddress);
  10777. + upriv->bap_buf = kmalloc(BULK_BUF_SIZE, GFP_KERNEL);
  10778. + if (!upriv->bap_buf) {
  10779. + err("Couldn't allocate bulk_out_buffer");
  10780. + goto error;
  10781. + }
  10782. + }
  10783. + }
  10784. + if (!upriv->bap_buf || !upriv->read_urb) {
  10785. + err("Didn't find the required bulk endpoints");
  10786. + goto error;
  10787. + }
  10788. +
  10789. + if (request_firmware(&fw_entry, "orinoco_ezusb_fw",
  10790. + &interface->dev) == 0) {
  10791. + firmware.size = fw_entry->size;
  10792. + firmware.code = fw_entry->data;
  10793. + }
  10794. + if (firmware.size && firmware.code) {
  10795. + if (ezusb_firmware_download(upriv, &firmware) < 0)
  10796. + goto error;
  10797. + } else {
  10798. + err("No firmware to download");
  10799. + goto error;
  10800. + }
  10801. +
  10802. + if (ezusb_hard_reset(priv) < 0) {
  10803. + err("Cannot reset the device");
  10804. + goto error;
  10805. + }
  10806. +
  10807. + /* If the firmware is already downloaded orinoco.c will call
  10808. + * ezusb_init but if the firmware is not already there, that will make
  10809. + * the kernel very unstable, so we try initializing here and quit in
  10810. + * case of error */
  10811. + if (ezusb_init(hw) < 0) {
  10812. + err("Couldn't initialize the device");
  10813. + err("Firmware may not be downloaded or may be wrong.");
  10814. + goto error;
  10815. + }
  10816. +
  10817. + /* Initialise the main driver */
  10818. + if (orinoco_init(priv) != 0) {
  10819. + err("orinoco_init() failed\n");
  10820. + goto error;
  10821. + }
  10822. +
  10823. + if (orinoco_if_add(priv, 0, 0, &ezusb_netdev_ops) != 0) {
  10824. + upriv->dev = NULL;
  10825. + err("%s: orinoco_if_add() failed", __func__);
  10826. + wiphy_unregister(priv_to_wiphy(priv));
  10827. + goto error;
  10828. + }
  10829. + upriv->dev = priv->ndev;
  10830. +
  10831. + goto exit;
  10832. +
  10833. + error:
  10834. + ezusb_delete(upriv);
  10835. + if (upriv->dev) {
  10836. + /* upriv->dev was 0, so ezusb_delete() didn't free it */
  10837. + free_orinocodev(priv);
  10838. + }
  10839. + upriv = NULL;
  10840. + retval = -EFAULT;
  10841. + exit:
  10842. + if (fw_entry) {
  10843. + firmware.code = NULL;
  10844. + firmware.size = 0;
  10845. + release_firmware(fw_entry);
  10846. + }
  10847. + usb_set_intfdata(interface, upriv);
  10848. + return retval;
  10849. +}
  10850. +
  10851. +
  10852. +static void ezusb_disconnect(struct usb_interface *intf)
  10853. +{
  10854. + struct ezusb_priv *upriv = usb_get_intfdata(intf);
  10855. + usb_set_intfdata(intf, NULL);
  10856. + ezusb_delete(upriv);
  10857. + printk(KERN_INFO PFX "Disconnected\n");
  10858. +}
  10859. +
  10860. +
  10861. +/* usb specific object needed to register this driver with the usb subsystem */
  10862. +static struct usb_driver orinoco_driver = {
  10863. + .name = DRIVER_NAME,
  10864. + .probe = ezusb_probe,
  10865. + .disconnect = ezusb_disconnect,
  10866. + .id_table = ezusb_table,
  10867. + .disable_hub_initiated_lpm = 1,
  10868. +};
  10869. +
  10870. +module_usb_driver(orinoco_driver);
  10871. +
  10872. +MODULE_AUTHOR("Manuel Estrada Sainz");
  10873. +MODULE_DESCRIPTION("Driver for Orinoco wireless LAN cards using EZUSB bridge");
  10874. +MODULE_LICENSE("Dual MPL/GPL");
  10875. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/scan.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/scan.c
  10876. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/scan.c 1970-01-01 01:00:00.000000000 +0100
  10877. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/scan.c 2025-08-03 15:01:59.385129604 +0200
  10878. @@ -0,0 +1,259 @@
  10879. +/* Helpers for managing scan queues
  10880. + *
  10881. + * See copyright notice in main.c
  10882. + */
  10883. +
  10884. +#include <linux/gfp.h>
  10885. +#include <linux/kernel.h>
  10886. +#include <linux/string.h>
  10887. +#include <linux/ieee80211.h>
  10888. +#include <net/cfg80211.h>
  10889. +
  10890. +#include "hermes.h"
  10891. +#include "orinoco.h"
  10892. +#include "main.h"
  10893. +
  10894. +#include "scan.h"
  10895. +
  10896. +#define ZERO_DBM_OFFSET 0x95
  10897. +#define MAX_SIGNAL_LEVEL 0x8A
  10898. +#define MIN_SIGNAL_LEVEL 0x2F
  10899. +
  10900. +#define SIGNAL_TO_DBM(x) \
  10901. + (clamp_t(s32, (x), MIN_SIGNAL_LEVEL, MAX_SIGNAL_LEVEL) \
  10902. + - ZERO_DBM_OFFSET)
  10903. +#define SIGNAL_TO_MBM(x) (SIGNAL_TO_DBM(x) * 100)
  10904. +
  10905. +static int symbol_build_supp_rates(u8 *buf, const __le16 *rates)
  10906. +{
  10907. + int i;
  10908. + u8 rate;
  10909. +
  10910. + buf[0] = WLAN_EID_SUPP_RATES;
  10911. + for (i = 0; i < 5; i++) {
  10912. + rate = le16_to_cpu(rates[i]);
  10913. + /* NULL terminated */
  10914. + if (rate == 0x0)
  10915. + break;
  10916. + buf[i + 2] = rate;
  10917. + }
  10918. + buf[1] = i;
  10919. +
  10920. + return i + 2;
  10921. +}
  10922. +
  10923. +static int prism_build_supp_rates(u8 *buf, const u8 *rates)
  10924. +{
  10925. + int i;
  10926. +
  10927. + buf[0] = WLAN_EID_SUPP_RATES;
  10928. + for (i = 0; i < 8; i++) {
  10929. + /* NULL terminated */
  10930. + if (rates[i] == 0x0)
  10931. + break;
  10932. + buf[i + 2] = rates[i];
  10933. + }
  10934. + buf[1] = i;
  10935. +
  10936. + /* We might still have another 2 rates, which need to go in
  10937. + * extended supported rates */
  10938. + if (i == 8 && rates[i] > 0) {
  10939. + buf[10] = WLAN_EID_EXT_SUPP_RATES;
  10940. + for (; i < 10; i++) {
  10941. + /* NULL terminated */
  10942. + if (rates[i] == 0x0)
  10943. + break;
  10944. + buf[i + 2] = rates[i];
  10945. + }
  10946. + buf[11] = i - 8;
  10947. + }
  10948. +
  10949. + return (i < 8) ? i + 2 : i + 4;
  10950. +}
  10951. +
  10952. +static void orinoco_add_hostscan_result(struct orinoco_private *priv,
  10953. + const union hermes_scan_info *bss)
  10954. +{
  10955. + struct wiphy *wiphy = priv_to_wiphy(priv);
  10956. + struct ieee80211_channel *channel;
  10957. + struct cfg80211_bss *cbss;
  10958. + u8 *ie;
  10959. + u8 ie_buf[46];
  10960. + u64 timestamp;
  10961. + s32 signal;
  10962. + u16 capability;
  10963. + u16 beacon_interval;
  10964. + int ie_len;
  10965. + int freq;
  10966. + int len;
  10967. +
  10968. + len = le16_to_cpu(bss->a.essid_len);
  10969. +
  10970. + /* Reconstruct SSID and bitrate IEs to pass up */
  10971. + ie_buf[0] = WLAN_EID_SSID;
  10972. + ie_buf[1] = len;
  10973. + memcpy(&ie_buf[2], bss->a.essid, len);
  10974. +
  10975. + ie = ie_buf + len + 2;
  10976. + ie_len = ie_buf[1] + 2;
  10977. + switch (priv->firmware_type) {
  10978. + case FIRMWARE_TYPE_SYMBOL:
  10979. + ie_len += symbol_build_supp_rates(ie, bss->s.rates);
  10980. + break;
  10981. +
  10982. + case FIRMWARE_TYPE_INTERSIL:
  10983. + ie_len += prism_build_supp_rates(ie, bss->p.rates);
  10984. + break;
  10985. +
  10986. + case FIRMWARE_TYPE_AGERE:
  10987. + default:
  10988. + break;
  10989. + }
  10990. +
  10991. + freq = ieee80211_channel_to_frequency(
  10992. + le16_to_cpu(bss->a.channel), NL80211_BAND_2GHZ);
  10993. + channel = ieee80211_get_channel(wiphy, freq);
  10994. + if (!channel) {
  10995. + printk(KERN_DEBUG "Invalid channel designation %04X(%04X)",
  10996. + bss->a.channel, freq);
  10997. + return; /* Then ignore it for now */
  10998. + }
  10999. + timestamp = 0;
  11000. + capability = le16_to_cpu(bss->a.capabilities);
  11001. + beacon_interval = le16_to_cpu(bss->a.beacon_interv);
  11002. + signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level));
  11003. +
  11004. + cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
  11005. + bss->a.bssid, timestamp, capability,
  11006. + beacon_interval, ie_buf, ie_len, signal,
  11007. + GFP_KERNEL);
  11008. + cfg80211_put_bss(wiphy, cbss);
  11009. +}
  11010. +
  11011. +void orinoco_add_extscan_result(struct orinoco_private *priv,
  11012. + struct agere_ext_scan_info *bss,
  11013. + size_t len)
  11014. +{
  11015. + struct wiphy *wiphy = priv_to_wiphy(priv);
  11016. + struct ieee80211_channel *channel;
  11017. + struct cfg80211_bss *cbss;
  11018. + const u8 *ie;
  11019. + u64 timestamp;
  11020. + s32 signal;
  11021. + u16 capability;
  11022. + u16 beacon_interval;
  11023. + size_t ie_len;
  11024. + int chan, freq;
  11025. +
  11026. + ie_len = len - sizeof(*bss);
  11027. + ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len);
  11028. + chan = ie ? ie[2] : 0;
  11029. + freq = ieee80211_channel_to_frequency(chan, NL80211_BAND_2GHZ);
  11030. + channel = ieee80211_get_channel(wiphy, freq);
  11031. +
  11032. + timestamp = le64_to_cpu(bss->timestamp);
  11033. + capability = le16_to_cpu(bss->capabilities);
  11034. + beacon_interval = le16_to_cpu(bss->beacon_interval);
  11035. + ie = bss->data;
  11036. + signal = SIGNAL_TO_MBM(bss->level);
  11037. +
  11038. + cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
  11039. + bss->bssid, timestamp, capability,
  11040. + beacon_interval, ie, ie_len, signal,
  11041. + GFP_KERNEL);
  11042. + cfg80211_put_bss(wiphy, cbss);
  11043. +}
  11044. +
  11045. +void orinoco_add_hostscan_results(struct orinoco_private *priv,
  11046. + unsigned char *buf,
  11047. + size_t len)
  11048. +{
  11049. + int offset; /* In the scan data */
  11050. + size_t atom_len;
  11051. + bool abort = false;
  11052. +
  11053. + switch (priv->firmware_type) {
  11054. + case FIRMWARE_TYPE_AGERE:
  11055. + atom_len = sizeof(struct agere_scan_apinfo);
  11056. + offset = 0;
  11057. + break;
  11058. +
  11059. + case FIRMWARE_TYPE_SYMBOL:
  11060. + /* Lack of documentation necessitates this hack.
  11061. + * Different firmwares have 68 or 76 byte long atoms.
  11062. + * We try modulo first. If the length divides by both,
  11063. + * we check what would be the channel in the second
  11064. + * frame for a 68-byte atom. 76-byte atoms have 0 there.
  11065. + * Valid channel cannot be 0. */
  11066. + if (len % 76)
  11067. + atom_len = 68;
  11068. + else if (len % 68)
  11069. + atom_len = 76;
  11070. + else if (len >= 1292 && buf[68] == 0)
  11071. + atom_len = 76;
  11072. + else
  11073. + atom_len = 68;
  11074. + offset = 0;
  11075. + break;
  11076. +
  11077. + case FIRMWARE_TYPE_INTERSIL:
  11078. + offset = 4;
  11079. + if (priv->has_hostscan) {
  11080. + atom_len = le16_to_cpup((__le16 *)buf);
  11081. + /* Sanity check for atom_len */
  11082. + if (atom_len < sizeof(struct prism2_scan_apinfo)) {
  11083. + printk(KERN_ERR "%s: Invalid atom_len in scan "
  11084. + "data: %zu\n", priv->ndev->name,
  11085. + atom_len);
  11086. + abort = true;
  11087. + goto scan_abort;
  11088. + }
  11089. + } else
  11090. + atom_len = offsetof(struct prism2_scan_apinfo, atim);
  11091. + break;
  11092. +
  11093. + default:
  11094. + abort = true;
  11095. + goto scan_abort;
  11096. + }
  11097. +
  11098. + /* Check that we got an whole number of atoms */
  11099. + if ((len - offset) % atom_len) {
  11100. + printk(KERN_ERR "%s: Unexpected scan data length %zu, "
  11101. + "atom_len %zu, offset %d\n", priv->ndev->name, len,
  11102. + atom_len, offset);
  11103. + abort = true;
  11104. + goto scan_abort;
  11105. + }
  11106. +
  11107. + /* Process the entries one by one */
  11108. + for (; offset + atom_len <= len; offset += atom_len) {
  11109. + union hermes_scan_info *atom;
  11110. +
  11111. + atom = (union hermes_scan_info *) (buf + offset);
  11112. +
  11113. + orinoco_add_hostscan_result(priv, atom);
  11114. + }
  11115. +
  11116. + scan_abort:
  11117. + if (priv->scan_request) {
  11118. + struct cfg80211_scan_info info = {
  11119. + .aborted = abort,
  11120. + };
  11121. +
  11122. + cfg80211_scan_done(priv->scan_request, &info);
  11123. + priv->scan_request = NULL;
  11124. + }
  11125. +}
  11126. +
  11127. +void orinoco_scan_done(struct orinoco_private *priv, bool abort)
  11128. +{
  11129. + if (priv->scan_request) {
  11130. + struct cfg80211_scan_info info = {
  11131. + .aborted = abort,
  11132. + };
  11133. +
  11134. + cfg80211_scan_done(priv->scan_request, &info);
  11135. + priv->scan_request = NULL;
  11136. + }
  11137. +}
  11138. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/scan.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/scan.h
  11139. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/scan.h 1970-01-01 01:00:00.000000000 +0100
  11140. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/scan.h 2025-08-03 15:01:59.385129604 +0200
  11141. @@ -0,0 +1,21 @@
  11142. +/* Helpers for managing scan queues
  11143. + *
  11144. + * See copyright notice in main.c
  11145. + */
  11146. +#ifndef _ORINOCO_SCAN_H_
  11147. +#define _ORINOCO_SCAN_H_
  11148. +
  11149. +/* Forward declarations */
  11150. +struct orinoco_private;
  11151. +struct agere_ext_scan_info;
  11152. +
  11153. +/* Add scan results */
  11154. +void orinoco_add_extscan_result(struct orinoco_private *priv,
  11155. + struct agere_ext_scan_info *atom,
  11156. + size_t len);
  11157. +void orinoco_add_hostscan_results(struct orinoco_private *dev,
  11158. + unsigned char *buf,
  11159. + size_t len);
  11160. +void orinoco_scan_done(struct orinoco_private *priv, bool abort);
  11161. +
  11162. +#endif /* _ORINOCO_SCAN_H_ */
  11163. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/spectrum_cs.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
  11164. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/spectrum_cs.c 1970-01-01 01:00:00.000000000 +0100
  11165. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/spectrum_cs.c 2025-08-03 15:01:59.385129604 +0200
  11166. @@ -0,0 +1,328 @@
  11167. +/*
  11168. + * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
  11169. + * Symbol Wireless Networker LA4137, CompactFlash cards by Socket
  11170. + * Communications and Intel PRO/Wireless 2011B.
  11171. + *
  11172. + * The driver implements Symbol firmware download. The rest is handled
  11173. + * in hermes.c and main.c.
  11174. + *
  11175. + * Utilities for downloading the Symbol firmware are available at
  11176. + * http://sourceforge.net/projects/orinoco/
  11177. + *
  11178. + * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
  11179. + * Portions based on orinoco_cs.c:
  11180. + * Copyright (C) David Gibson, Linuxcare Australia
  11181. + * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
  11182. + * Copyright (C) Symbol Technologies.
  11183. + *
  11184. + * See copyright notice in file main.c.
  11185. + */
  11186. +
  11187. +#define DRIVER_NAME "spectrum_cs"
  11188. +#define PFX DRIVER_NAME ": "
  11189. +
  11190. +#include <linux/module.h>
  11191. +#include <linux/kernel.h>
  11192. +#include <linux/delay.h>
  11193. +#include <pcmcia/cistpl.h>
  11194. +#include <pcmcia/cisreg.h>
  11195. +#include <pcmcia/ds.h>
  11196. +
  11197. +#include "orinoco.h"
  11198. +
  11199. +/********************************************************************/
  11200. +/* Module stuff */
  11201. +/********************************************************************/
  11202. +
  11203. +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
  11204. +MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
  11205. +MODULE_LICENSE("Dual MPL/GPL");
  11206. +
  11207. +/* Module parameters */
  11208. +
  11209. +/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
  11210. + * don't have any CIS entry for it. This workaround it... */
  11211. +static int ignore_cis_vcc; /* = 0 */
  11212. +module_param(ignore_cis_vcc, int, 0);
  11213. +MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
  11214. +
  11215. +/********************************************************************/
  11216. +/* Data structures */
  11217. +/********************************************************************/
  11218. +
  11219. +/* PCMCIA specific device information (goes in the card field of
  11220. + * struct orinoco_private */
  11221. +struct orinoco_pccard {
  11222. + struct pcmcia_device *p_dev;
  11223. +};
  11224. +
  11225. +/********************************************************************/
  11226. +/* Function prototypes */
  11227. +/********************************************************************/
  11228. +
  11229. +static int spectrum_cs_config(struct pcmcia_device *link);
  11230. +static void spectrum_cs_release(struct pcmcia_device *link);
  11231. +
  11232. +/* Constants for the CISREG_CCSR register */
  11233. +#define HCR_RUN 0x07 /* run firmware after reset */
  11234. +#define HCR_IDLE 0x0E /* don't run firmware after reset */
  11235. +#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
  11236. +
  11237. +
  11238. +/*
  11239. + * Reset the card using configuration registers COR and CCSR.
  11240. + * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
  11241. + */
  11242. +static int
  11243. +spectrum_reset(struct pcmcia_device *link, int idle)
  11244. +{
  11245. + int ret;
  11246. + u8 save_cor;
  11247. + u8 ccsr;
  11248. +
  11249. + /* Doing it if hardware is gone is guaranteed crash */
  11250. + if (!pcmcia_dev_present(link))
  11251. + return -ENODEV;
  11252. +
  11253. + /* Save original COR value */
  11254. + ret = pcmcia_read_config_byte(link, CISREG_COR, &save_cor);
  11255. + if (ret)
  11256. + goto failed;
  11257. +
  11258. + /* Soft-Reset card */
  11259. + ret = pcmcia_write_config_byte(link, CISREG_COR,
  11260. + (save_cor | COR_SOFT_RESET));
  11261. + if (ret)
  11262. + goto failed;
  11263. + udelay(1000);
  11264. +
  11265. + /* Read CCSR */
  11266. + ret = pcmcia_read_config_byte(link, CISREG_CCSR, &ccsr);
  11267. + if (ret)
  11268. + goto failed;
  11269. +
  11270. + /*
  11271. + * Start or stop the firmware. Memory width bit should be
  11272. + * preserved from the value we've just read.
  11273. + */
  11274. + ccsr = (idle ? HCR_IDLE : HCR_RUN) | (ccsr & HCR_MEM16);
  11275. + ret = pcmcia_write_config_byte(link, CISREG_CCSR, ccsr);
  11276. + if (ret)
  11277. + goto failed;
  11278. + udelay(1000);
  11279. +
  11280. + /* Restore original COR configuration index */
  11281. + ret = pcmcia_write_config_byte(link, CISREG_COR,
  11282. + (save_cor & ~COR_SOFT_RESET));
  11283. + if (ret)
  11284. + goto failed;
  11285. + udelay(1000);
  11286. + return 0;
  11287. +
  11288. +failed:
  11289. + return -ENODEV;
  11290. +}
  11291. +
  11292. +/********************************************************************/
  11293. +/* Device methods */
  11294. +/********************************************************************/
  11295. +
  11296. +static int
  11297. +spectrum_cs_hard_reset(struct orinoco_private *priv)
  11298. +{
  11299. + struct orinoco_pccard *card = priv->card;
  11300. + struct pcmcia_device *link = card->p_dev;
  11301. +
  11302. + /* Soft reset using COR and HCR */
  11303. + spectrum_reset(link, 0);
  11304. +
  11305. + return 0;
  11306. +}
  11307. +
  11308. +static int
  11309. +spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
  11310. +{
  11311. + struct orinoco_pccard *card = priv->card;
  11312. + struct pcmcia_device *link = card->p_dev;
  11313. +
  11314. + return spectrum_reset(link, idle);
  11315. +}
  11316. +
  11317. +/********************************************************************/
  11318. +/* PCMCIA stuff */
  11319. +/********************************************************************/
  11320. +
  11321. +static int
  11322. +spectrum_cs_probe(struct pcmcia_device *link)
  11323. +{
  11324. + struct orinoco_private *priv;
  11325. + struct orinoco_pccard *card;
  11326. + int ret;
  11327. +
  11328. + priv = alloc_orinocodev(sizeof(*card), &link->dev,
  11329. + spectrum_cs_hard_reset,
  11330. + spectrum_cs_stop_firmware);
  11331. + if (!priv)
  11332. + return -ENOMEM;
  11333. + card = priv->card;
  11334. +
  11335. + /* Link both structures together */
  11336. + card->p_dev = link;
  11337. + link->priv = priv;
  11338. +
  11339. + ret = spectrum_cs_config(link);
  11340. + if (ret)
  11341. + goto err_free_orinocodev;
  11342. +
  11343. + return 0;
  11344. +
  11345. +err_free_orinocodev:
  11346. + free_orinocodev(priv);
  11347. + return ret;
  11348. +}
  11349. +
  11350. +static void spectrum_cs_detach(struct pcmcia_device *link)
  11351. +{
  11352. + struct orinoco_private *priv = link->priv;
  11353. +
  11354. + orinoco_if_del(priv);
  11355. +
  11356. + spectrum_cs_release(link);
  11357. +
  11358. + free_orinocodev(priv);
  11359. +} /* spectrum_cs_detach */
  11360. +
  11361. +static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
  11362. + void *priv_data)
  11363. +{
  11364. + if (p_dev->config_index == 0)
  11365. + return -EINVAL;
  11366. +
  11367. + return pcmcia_request_io(p_dev);
  11368. +};
  11369. +
  11370. +static int
  11371. +spectrum_cs_config(struct pcmcia_device *link)
  11372. +{
  11373. + struct orinoco_private *priv = link->priv;
  11374. + struct hermes *hw = &priv->hw;
  11375. + int ret;
  11376. + void __iomem *mem;
  11377. +
  11378. + link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
  11379. + CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
  11380. + if (ignore_cis_vcc)
  11381. + link->config_flags &= ~CONF_AUTO_CHECK_VCC;
  11382. + ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
  11383. + if (ret) {
  11384. + if (!ignore_cis_vcc)
  11385. + printk(KERN_ERR PFX "GetNextTuple(): No matching "
  11386. + "CIS configuration. Maybe you need the "
  11387. + "ignore_cis_vcc=1 parameter.\n");
  11388. + goto failed;
  11389. + }
  11390. +
  11391. + mem = ioport_map(link->resource[0]->start,
  11392. + resource_size(link->resource[0]));
  11393. + if (!mem)
  11394. + goto failed;
  11395. +
  11396. + /* We initialize the hermes structure before completing PCMCIA
  11397. + * configuration just in case the interrupt handler gets
  11398. + * called. */
  11399. + hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
  11400. + hw->eeprom_pda = true;
  11401. +
  11402. + ret = pcmcia_request_irq(link, orinoco_interrupt);
  11403. + if (ret)
  11404. + goto failed;
  11405. +
  11406. + ret = pcmcia_enable_device(link);
  11407. + if (ret)
  11408. + goto failed;
  11409. +
  11410. + /* Reset card */
  11411. + if (spectrum_cs_hard_reset(priv) != 0)
  11412. + goto failed;
  11413. +
  11414. + /* Initialise the main driver */
  11415. + if (orinoco_init(priv) != 0) {
  11416. + printk(KERN_ERR PFX "orinoco_init() failed\n");
  11417. + goto failed;
  11418. + }
  11419. +
  11420. + /* Register an interface with the stack */
  11421. + if (orinoco_if_add(priv, link->resource[0]->start,
  11422. + link->irq, NULL) != 0) {
  11423. + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  11424. + goto failed;
  11425. + }
  11426. +
  11427. + return 0;
  11428. +
  11429. + failed:
  11430. + spectrum_cs_release(link);
  11431. + return -ENODEV;
  11432. +} /* spectrum_cs_config */
  11433. +
  11434. +static void
  11435. +spectrum_cs_release(struct pcmcia_device *link)
  11436. +{
  11437. + struct orinoco_private *priv = link->priv;
  11438. + unsigned long flags;
  11439. +
  11440. + /* We're committed to taking the device away now, so mark the
  11441. + * hardware as unavailable */
  11442. + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
  11443. + priv->hw_unavailable++;
  11444. + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  11445. +
  11446. + pcmcia_disable_device(link);
  11447. + if (priv->hw.iobase)
  11448. + ioport_unmap(priv->hw.iobase);
  11449. +} /* spectrum_cs_release */
  11450. +
  11451. +
  11452. +static int
  11453. +spectrum_cs_suspend(struct pcmcia_device *link)
  11454. +{
  11455. + struct orinoco_private *priv = link->priv;
  11456. +
  11457. + /* Mark the device as stopped, to block IO until later */
  11458. + orinoco_down(priv);
  11459. +
  11460. + return 0;
  11461. +}
  11462. +
  11463. +static int
  11464. +spectrum_cs_resume(struct pcmcia_device *link)
  11465. +{
  11466. + struct orinoco_private *priv = link->priv;
  11467. + int err = orinoco_up(priv);
  11468. +
  11469. + return err;
  11470. +}
  11471. +
  11472. +
  11473. +/********************************************************************/
  11474. +/* Module initialization */
  11475. +/********************************************************************/
  11476. +
  11477. +static const struct pcmcia_device_id spectrum_cs_ids[] = {
  11478. + PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
  11479. + PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
  11480. + PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
  11481. + PCMCIA_DEVICE_NULL,
  11482. +};
  11483. +MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
  11484. +
  11485. +static struct pcmcia_driver orinoco_driver = {
  11486. + .owner = THIS_MODULE,
  11487. + .name = DRIVER_NAME,
  11488. + .probe = spectrum_cs_probe,
  11489. + .remove = spectrum_cs_detach,
  11490. + .suspend = spectrum_cs_suspend,
  11491. + .resume = spectrum_cs_resume,
  11492. + .id_table = spectrum_cs_ids,
  11493. +};
  11494. +module_pcmcia_driver(orinoco_driver);
  11495. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/wext.c linux-6.15.6/drivers/net/wireless/intersil/orinoco/wext.c
  11496. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/wext.c 1970-01-01 01:00:00.000000000 +0100
  11497. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/wext.c 2025-08-03 16:32:17.782885098 +0200
  11498. @@ -0,0 +1,1415 @@
  11499. +/* Wireless extensions support.
  11500. + *
  11501. + * See copyright notice in main.c
  11502. + */
  11503. +#include <linux/slab.h>
  11504. +#include <linux/kernel.h>
  11505. +#include <linux/if_arp.h>
  11506. +#include <linux/wireless.h>
  11507. +#include <linux/ieee80211.h>
  11508. +#include <linux/etherdevice.h>
  11509. +#include <net/iw_handler.h>
  11510. +#include <net/cfg80211.h>
  11511. +#include <net/cfg80211-wext.h>
  11512. +
  11513. +#include "hermes.h"
  11514. +#include "hermes_rid.h"
  11515. +#include "orinoco.h"
  11516. +
  11517. +#include "hw.h"
  11518. +#include "mic.h"
  11519. +#include "scan.h"
  11520. +#include "main.h"
  11521. +
  11522. +#include "wext.h"
  11523. +
  11524. +#define MAX_RID_LEN 1024
  11525. +
  11526. +/* Helper routine to record keys
  11527. + * It is called under orinoco_lock so it may not sleep */
  11528. +static int orinoco_set_key(struct orinoco_private *priv, int index,
  11529. + enum orinoco_alg alg, const u8 *key, int key_len,
  11530. + const u8 *seq, int seq_len)
  11531. +{
  11532. + kfree_sensitive(priv->keys[index].key);
  11533. + kfree_sensitive(priv->keys[index].seq);
  11534. +
  11535. + if (key_len) {
  11536. + priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
  11537. + if (!priv->keys[index].key)
  11538. + goto nomem;
  11539. + } else
  11540. + priv->keys[index].key = NULL;
  11541. +
  11542. + if (seq_len) {
  11543. + priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
  11544. + if (!priv->keys[index].seq)
  11545. + goto free_key;
  11546. + } else
  11547. + priv->keys[index].seq = NULL;
  11548. +
  11549. + priv->keys[index].key_len = key_len;
  11550. + priv->keys[index].seq_len = seq_len;
  11551. +
  11552. + if (key_len)
  11553. + memcpy((void *)priv->keys[index].key, key, key_len);
  11554. + if (seq_len)
  11555. + memcpy((void *)priv->keys[index].seq, seq, seq_len);
  11556. +
  11557. + switch (alg) {
  11558. + case ORINOCO_ALG_TKIP:
  11559. + priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
  11560. + break;
  11561. +
  11562. + case ORINOCO_ALG_WEP:
  11563. + priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
  11564. + WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
  11565. + break;
  11566. +
  11567. + case ORINOCO_ALG_NONE:
  11568. + default:
  11569. + priv->keys[index].cipher = 0;
  11570. + break;
  11571. + }
  11572. +
  11573. + return 0;
  11574. +
  11575. +free_key:
  11576. + kfree(priv->keys[index].key);
  11577. + priv->keys[index].key = NULL;
  11578. +
  11579. +nomem:
  11580. + priv->keys[index].key_len = 0;
  11581. + priv->keys[index].seq_len = 0;
  11582. + priv->keys[index].cipher = 0;
  11583. +
  11584. + return -ENOMEM;
  11585. +}
  11586. +
  11587. +static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
  11588. +{
  11589. + struct orinoco_private *priv = ndev_priv(dev);
  11590. + struct hermes *hw = &priv->hw;
  11591. + struct iw_statistics *wstats = &priv->wstats;
  11592. + int err;
  11593. + unsigned long flags;
  11594. +
  11595. + if (!netif_device_present(dev)) {
  11596. + printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
  11597. + dev->name);
  11598. + return NULL; /* FIXME: Can we do better than this? */
  11599. + }
  11600. +
  11601. + /* If busy, return the old stats. Returning NULL may cause
  11602. + * the interface to disappear from /proc/net/wireless */
  11603. + if (orinoco_lock(priv, &flags) != 0)
  11604. + return wstats;
  11605. +
  11606. + /* We can't really wait for the tallies inquiry command to
  11607. + * complete, so we just use the previous results and trigger
  11608. + * a new tallies inquiry command for next time - Jean II */
  11609. + /* FIXME: Really we should wait for the inquiry to come back -
  11610. + * as it is the stats we give don't make a whole lot of sense.
  11611. + * Unfortunately, it's not clear how to do that within the
  11612. + * wireless extensions framework: I think we're in user
  11613. + * context, but a lock seems to be held by the time we get in
  11614. + * here so we're not safe to sleep here. */
  11615. + hermes_inquire(hw, HERMES_INQ_TALLIES);
  11616. +
  11617. + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
  11618. + memset(&wstats->qual, 0, sizeof(wstats->qual));
  11619. + } else {
  11620. + struct {
  11621. + __le16 qual, signal, noise, unused;
  11622. + } __packed cq;
  11623. +
  11624. + err = HERMES_READ_RECORD(hw, USER_BAP,
  11625. + HERMES_RID_COMMSQUALITY, &cq);
  11626. +
  11627. + if (!err) {
  11628. + wstats->qual.qual = (int)le16_to_cpu(cq.qual);
  11629. + wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
  11630. + wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
  11631. + wstats->qual.updated =
  11632. + IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
  11633. + }
  11634. + }
  11635. +
  11636. + orinoco_unlock(priv, &flags);
  11637. + return wstats;
  11638. +}
  11639. +
  11640. +/********************************************************************/
  11641. +/* Wireless extensions */
  11642. +/********************************************************************/
  11643. +
  11644. +static int orinoco_ioctl_setwap(struct net_device *dev,
  11645. + struct iw_request_info *info,
  11646. + union iwreq_data *wrqu,
  11647. + char *extra)
  11648. +{
  11649. + struct sockaddr *ap_addr = &wrqu->ap_addr;
  11650. + struct orinoco_private *priv = ndev_priv(dev);
  11651. + int err = -EINPROGRESS; /* Call commit handler */
  11652. + unsigned long flags;
  11653. +
  11654. + if (orinoco_lock(priv, &flags) != 0)
  11655. + return -EBUSY;
  11656. +
  11657. + /* Enable automatic roaming - no sanity checks are needed */
  11658. + if (is_zero_ether_addr(ap_addr->sa_data) ||
  11659. + is_broadcast_ether_addr(ap_addr->sa_data)) {
  11660. + priv->bssid_fixed = 0;
  11661. + eth_zero_addr(priv->desired_bssid);
  11662. +
  11663. + /* "off" means keep existing connection */
  11664. + if (ap_addr->sa_data[0] == 0) {
  11665. + __orinoco_hw_set_wap(priv);
  11666. + err = 0;
  11667. + }
  11668. + goto out;
  11669. + }
  11670. +
  11671. + if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
  11672. + printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
  11673. + "support manual roaming\n",
  11674. + dev->name);
  11675. + err = -EOPNOTSUPP;
  11676. + goto out;
  11677. + }
  11678. +
  11679. + if (priv->iw_mode != NL80211_IFTYPE_STATION) {
  11680. + printk(KERN_WARNING "%s: Manual roaming supported only in "
  11681. + "managed mode\n", dev->name);
  11682. + err = -EOPNOTSUPP;
  11683. + goto out;
  11684. + }
  11685. +
  11686. + /* Intersil firmware hangs without Desired ESSID */
  11687. + if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
  11688. + strlen(priv->desired_essid) == 0) {
  11689. + printk(KERN_WARNING "%s: Desired ESSID must be set for "
  11690. + "manual roaming\n", dev->name);
  11691. + err = -EOPNOTSUPP;
  11692. + goto out;
  11693. + }
  11694. +
  11695. + /* Finally, enable manual roaming */
  11696. + priv->bssid_fixed = 1;
  11697. + memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
  11698. +
  11699. + out:
  11700. + orinoco_unlock(priv, &flags);
  11701. + return err;
  11702. +}
  11703. +
  11704. +static int orinoco_ioctl_getwap(struct net_device *dev,
  11705. + struct iw_request_info *info,
  11706. + union iwreq_data *wrqu,
  11707. + char *extra)
  11708. +{
  11709. + struct sockaddr *ap_addr = &wrqu->ap_addr;
  11710. + struct orinoco_private *priv = ndev_priv(dev);
  11711. +
  11712. + int err = 0;
  11713. + unsigned long flags;
  11714. +
  11715. + if (orinoco_lock(priv, &flags) != 0)
  11716. + return -EBUSY;
  11717. +
  11718. + ap_addr->sa_family = ARPHRD_ETHER;
  11719. + err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
  11720. +
  11721. + orinoco_unlock(priv, &flags);
  11722. +
  11723. + return err;
  11724. +}
  11725. +
  11726. +static int orinoco_ioctl_setiwencode(struct net_device *dev,
  11727. + struct iw_request_info *info,
  11728. + union iwreq_data *wrqu,
  11729. + char *keybuf)
  11730. +{
  11731. + struct iw_point *erq = &wrqu->encoding;
  11732. + struct orinoco_private *priv = ndev_priv(dev);
  11733. + int index = (erq->flags & IW_ENCODE_INDEX) - 1;
  11734. + int setindex = priv->tx_key;
  11735. + enum orinoco_alg encode_alg = priv->encode_alg;
  11736. + int restricted = priv->wep_restrict;
  11737. + int err = -EINPROGRESS; /* Call commit handler */
  11738. + unsigned long flags;
  11739. +
  11740. + if (!priv->has_wep)
  11741. + return -EOPNOTSUPP;
  11742. +
  11743. + if (erq->pointer) {
  11744. + /* We actually have a key to set - check its length */
  11745. + if (erq->length > LARGE_KEY_SIZE)
  11746. + return -E2BIG;
  11747. +
  11748. + if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
  11749. + return -E2BIG;
  11750. + }
  11751. +
  11752. + if (orinoco_lock(priv, &flags) != 0)
  11753. + return -EBUSY;
  11754. +
  11755. + /* Clear any TKIP key we have */
  11756. + if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
  11757. + (void) orinoco_clear_tkip_key(priv, setindex);
  11758. +
  11759. + if (erq->length > 0) {
  11760. + if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
  11761. + index = priv->tx_key;
  11762. +
  11763. + /* Switch on WEP if off */
  11764. + if (encode_alg != ORINOCO_ALG_WEP) {
  11765. + setindex = index;
  11766. + encode_alg = ORINOCO_ALG_WEP;
  11767. + }
  11768. + } else {
  11769. + /* Important note : if the user do "iwconfig eth0 enc off",
  11770. + * we will arrive there with an index of -1. This is valid
  11771. + * but need to be taken care off... Jean II */
  11772. + if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
  11773. + if ((index != -1) || (erq->flags == 0)) {
  11774. + err = -EINVAL;
  11775. + goto out;
  11776. + }
  11777. + } else {
  11778. + /* Set the index : Check that the key is valid */
  11779. + if (priv->keys[index].key_len == 0) {
  11780. + err = -EINVAL;
  11781. + goto out;
  11782. + }
  11783. + setindex = index;
  11784. + }
  11785. + }
  11786. +
  11787. + if (erq->flags & IW_ENCODE_DISABLED)
  11788. + encode_alg = ORINOCO_ALG_NONE;
  11789. + if (erq->flags & IW_ENCODE_OPEN)
  11790. + restricted = 0;
  11791. + if (erq->flags & IW_ENCODE_RESTRICTED)
  11792. + restricted = 1;
  11793. +
  11794. + if (erq->pointer && erq->length > 0) {
  11795. + err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
  11796. + erq->length, NULL, 0);
  11797. + }
  11798. + priv->tx_key = setindex;
  11799. +
  11800. + /* Try fast key change if connected and only keys are changed */
  11801. + if ((priv->encode_alg == encode_alg) &&
  11802. + (priv->wep_restrict == restricted) &&
  11803. + netif_carrier_ok(dev)) {
  11804. + err = __orinoco_hw_setup_wepkeys(priv);
  11805. + /* No need to commit if successful */
  11806. + goto out;
  11807. + }
  11808. +
  11809. + priv->encode_alg = encode_alg;
  11810. + priv->wep_restrict = restricted;
  11811. +
  11812. + out:
  11813. + orinoco_unlock(priv, &flags);
  11814. +
  11815. + return err;
  11816. +}
  11817. +
  11818. +static int orinoco_ioctl_getiwencode(struct net_device *dev,
  11819. + struct iw_request_info *info,
  11820. + union iwreq_data *wrqu,
  11821. + char *keybuf)
  11822. +{
  11823. + struct iw_point *erq = &wrqu->encoding;
  11824. + struct orinoco_private *priv = ndev_priv(dev);
  11825. + int index = (erq->flags & IW_ENCODE_INDEX) - 1;
  11826. + unsigned long flags;
  11827. +
  11828. + if (!priv->has_wep)
  11829. + return -EOPNOTSUPP;
  11830. +
  11831. + if (orinoco_lock(priv, &flags) != 0)
  11832. + return -EBUSY;
  11833. +
  11834. + if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
  11835. + index = priv->tx_key;
  11836. +
  11837. + erq->flags = 0;
  11838. + if (!priv->encode_alg)
  11839. + erq->flags |= IW_ENCODE_DISABLED;
  11840. + erq->flags |= index + 1;
  11841. +
  11842. + if (priv->wep_restrict)
  11843. + erq->flags |= IW_ENCODE_RESTRICTED;
  11844. + else
  11845. + erq->flags |= IW_ENCODE_OPEN;
  11846. +
  11847. + erq->length = priv->keys[index].key_len;
  11848. +
  11849. + memcpy(keybuf, priv->keys[index].key, erq->length);
  11850. +
  11851. + orinoco_unlock(priv, &flags);
  11852. + return 0;
  11853. +}
  11854. +
  11855. +static int orinoco_ioctl_setessid(struct net_device *dev,
  11856. + struct iw_request_info *info,
  11857. + union iwreq_data *wrqu,
  11858. + char *essidbuf)
  11859. +{
  11860. + struct iw_point *erq = &wrqu->essid;
  11861. + struct orinoco_private *priv = ndev_priv(dev);
  11862. + unsigned long flags;
  11863. +
  11864. + /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
  11865. + * anyway... - Jean II */
  11866. +
  11867. + /* Hum... Should not use Wireless Extension constant (may change),
  11868. + * should use our own... - Jean II */
  11869. + if (erq->length > IW_ESSID_MAX_SIZE)
  11870. + return -E2BIG;
  11871. +
  11872. + if (orinoco_lock(priv, &flags) != 0)
  11873. + return -EBUSY;
  11874. +
  11875. + /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
  11876. + memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
  11877. +
  11878. + /* If not ANY, get the new ESSID */
  11879. + if (erq->flags)
  11880. + memcpy(priv->desired_essid, essidbuf, erq->length);
  11881. +
  11882. + orinoco_unlock(priv, &flags);
  11883. +
  11884. + return -EINPROGRESS; /* Call commit handler */
  11885. +}
  11886. +
  11887. +static int orinoco_ioctl_getessid(struct net_device *dev,
  11888. + struct iw_request_info *info,
  11889. + union iwreq_data *wrqu,
  11890. + char *essidbuf)
  11891. +{
  11892. + struct iw_point *erq = &wrqu->essid;
  11893. + struct orinoco_private *priv = ndev_priv(dev);
  11894. + int active;
  11895. + int err = 0;
  11896. + unsigned long flags;
  11897. +
  11898. + if (netif_running(dev)) {
  11899. + err = orinoco_hw_get_essid(priv, &active, essidbuf);
  11900. + if (err < 0)
  11901. + return err;
  11902. + erq->length = err;
  11903. + } else {
  11904. + if (orinoco_lock(priv, &flags) != 0)
  11905. + return -EBUSY;
  11906. + memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
  11907. + erq->length = strlen(priv->desired_essid);
  11908. + orinoco_unlock(priv, &flags);
  11909. + }
  11910. +
  11911. + erq->flags = 1;
  11912. +
  11913. + return 0;
  11914. +}
  11915. +
  11916. +static int orinoco_ioctl_setfreq(struct net_device *dev,
  11917. + struct iw_request_info *info,
  11918. + union iwreq_data *wrqu,
  11919. + char *extra)
  11920. +{
  11921. + struct iw_freq *frq = &wrqu->freq;
  11922. + struct orinoco_private *priv = ndev_priv(dev);
  11923. + int chan = -1;
  11924. + unsigned long flags;
  11925. + int err = -EINPROGRESS; /* Call commit handler */
  11926. +
  11927. + /* In infrastructure mode the AP sets the channel */
  11928. + if (priv->iw_mode == NL80211_IFTYPE_STATION)
  11929. + return -EBUSY;
  11930. +
  11931. + if ((frq->e == 0) && (frq->m <= 1000)) {
  11932. + /* Setting by channel number */
  11933. + chan = frq->m;
  11934. + } else {
  11935. + /* Setting by frequency */
  11936. + int denom = 1;
  11937. + int i;
  11938. +
  11939. + /* Calculate denominator to rescale to MHz */
  11940. + for (i = 0; i < (6 - frq->e); i++)
  11941. + denom *= 10;
  11942. +
  11943. + chan = ieee80211_frequency_to_channel(frq->m / denom);
  11944. + }
  11945. +
  11946. + if ((chan < 1) || (chan > NUM_CHANNELS) ||
  11947. + !(priv->channel_mask & (1 << (chan - 1))))
  11948. + return -EINVAL;
  11949. +
  11950. + if (orinoco_lock(priv, &flags) != 0)
  11951. + return -EBUSY;
  11952. +
  11953. + priv->channel = chan;
  11954. + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
  11955. + /* Fast channel change - no commit if successful */
  11956. + struct hermes *hw = &priv->hw;
  11957. + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
  11958. + HERMES_TEST_SET_CHANNEL,
  11959. + chan, NULL);
  11960. + }
  11961. + orinoco_unlock(priv, &flags);
  11962. +
  11963. + return err;
  11964. +}
  11965. +
  11966. +static int orinoco_ioctl_getfreq(struct net_device *dev,
  11967. + struct iw_request_info *info,
  11968. + union iwreq_data *wrqu,
  11969. + char *extra)
  11970. +{
  11971. + struct iw_freq *frq = &wrqu->freq;
  11972. + struct orinoco_private *priv = ndev_priv(dev);
  11973. + int tmp;
  11974. +
  11975. + /* Locking done in there */
  11976. + tmp = orinoco_hw_get_freq(priv);
  11977. + if (tmp < 0)
  11978. + return tmp;
  11979. +
  11980. + frq->m = tmp * 100000;
  11981. + frq->e = 1;
  11982. +
  11983. + return 0;
  11984. +}
  11985. +
  11986. +static int orinoco_ioctl_getsens(struct net_device *dev,
  11987. + struct iw_request_info *info,
  11988. + union iwreq_data *wrqu,
  11989. + char *extra)
  11990. +{
  11991. + struct iw_param *srq = &wrqu->sens;
  11992. + struct orinoco_private *priv = ndev_priv(dev);
  11993. + struct hermes *hw = &priv->hw;
  11994. + u16 val;
  11995. + int err;
  11996. + unsigned long flags;
  11997. +
  11998. + if (!priv->has_sensitivity)
  11999. + return -EOPNOTSUPP;
  12000. +
  12001. + if (orinoco_lock(priv, &flags) != 0)
  12002. + return -EBUSY;
  12003. + err = hermes_read_wordrec(hw, USER_BAP,
  12004. + HERMES_RID_CNFSYSTEMSCALE, &val);
  12005. + orinoco_unlock(priv, &flags);
  12006. +
  12007. + if (err)
  12008. + return err;
  12009. +
  12010. + srq->value = val;
  12011. + srq->fixed = 0; /* auto */
  12012. +
  12013. + return 0;
  12014. +}
  12015. +
  12016. +static int orinoco_ioctl_setsens(struct net_device *dev,
  12017. + struct iw_request_info *info,
  12018. + union iwreq_data *wrqu,
  12019. + char *extra)
  12020. +{
  12021. + struct iw_param *srq = &wrqu->sens;
  12022. + struct orinoco_private *priv = ndev_priv(dev);
  12023. + int val = srq->value;
  12024. + unsigned long flags;
  12025. +
  12026. + if (!priv->has_sensitivity)
  12027. + return -EOPNOTSUPP;
  12028. +
  12029. + if ((val < 1) || (val > 3))
  12030. + return -EINVAL;
  12031. +
  12032. + if (orinoco_lock(priv, &flags) != 0)
  12033. + return -EBUSY;
  12034. + priv->ap_density = val;
  12035. + orinoco_unlock(priv, &flags);
  12036. +
  12037. + return -EINPROGRESS; /* Call commit handler */
  12038. +}
  12039. +
  12040. +static int orinoco_ioctl_setrate(struct net_device *dev,
  12041. + struct iw_request_info *info,
  12042. + union iwreq_data *wrqu,
  12043. + char *extra)
  12044. +{
  12045. + struct iw_param *rrq = &wrqu->bitrate;
  12046. + struct orinoco_private *priv = ndev_priv(dev);
  12047. + int ratemode;
  12048. + int bitrate; /* 100s of kilobits */
  12049. + unsigned long flags;
  12050. +
  12051. + /* As the user space doesn't know our highest rate, it uses -1
  12052. + * to ask us to set the highest rate. Test it using "iwconfig
  12053. + * ethX rate auto" - Jean II */
  12054. + if (rrq->value == -1)
  12055. + bitrate = 110;
  12056. + else {
  12057. + if (rrq->value % 100000)
  12058. + return -EINVAL;
  12059. + bitrate = rrq->value / 100000;
  12060. + }
  12061. +
  12062. + ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed);
  12063. +
  12064. + if (ratemode == -1)
  12065. + return -EINVAL;
  12066. +
  12067. + if (orinoco_lock(priv, &flags) != 0)
  12068. + return -EBUSY;
  12069. + priv->bitratemode = ratemode;
  12070. + orinoco_unlock(priv, &flags);
  12071. +
  12072. + return -EINPROGRESS;
  12073. +}
  12074. +
  12075. +static int orinoco_ioctl_getrate(struct net_device *dev,
  12076. + struct iw_request_info *info,
  12077. + union iwreq_data *wrqu,
  12078. + char *extra)
  12079. +{
  12080. + struct iw_param *rrq = &wrqu->bitrate;
  12081. + struct orinoco_private *priv = ndev_priv(dev);
  12082. + int err = 0;
  12083. + int bitrate, automatic;
  12084. + unsigned long flags;
  12085. +
  12086. + if (orinoco_lock(priv, &flags) != 0)
  12087. + return -EBUSY;
  12088. +
  12089. + orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic);
  12090. +
  12091. + /* If the interface is running we try to find more about the
  12092. + current mode */
  12093. + if (netif_running(dev)) {
  12094. + int act_bitrate;
  12095. + int lerr;
  12096. +
  12097. + /* Ignore errors if we can't get the actual bitrate */
  12098. + lerr = orinoco_hw_get_act_bitrate(priv, &act_bitrate);
  12099. + if (!lerr)
  12100. + bitrate = act_bitrate;
  12101. + }
  12102. +
  12103. + orinoco_unlock(priv, &flags);
  12104. +
  12105. + rrq->value = bitrate;
  12106. + rrq->fixed = !automatic;
  12107. + rrq->disabled = 0;
  12108. +
  12109. + return err;
  12110. +}
  12111. +
  12112. +static int orinoco_ioctl_setpower(struct net_device *dev,
  12113. + struct iw_request_info *info,
  12114. + union iwreq_data *wrqu,
  12115. + char *extra)
  12116. +{
  12117. + struct iw_param *prq = &wrqu->power;
  12118. + struct orinoco_private *priv = ndev_priv(dev);
  12119. + int err = -EINPROGRESS; /* Call commit handler */
  12120. + unsigned long flags;
  12121. +
  12122. + if (orinoco_lock(priv, &flags) != 0)
  12123. + return -EBUSY;
  12124. +
  12125. + if (prq->disabled) {
  12126. + priv->pm_on = 0;
  12127. + } else {
  12128. + switch (prq->flags & IW_POWER_MODE) {
  12129. + case IW_POWER_UNICAST_R:
  12130. + priv->pm_mcast = 0;
  12131. + priv->pm_on = 1;
  12132. + break;
  12133. + case IW_POWER_ALL_R:
  12134. + priv->pm_mcast = 1;
  12135. + priv->pm_on = 1;
  12136. + break;
  12137. + case IW_POWER_ON:
  12138. + /* No flags : but we may have a value - Jean II */
  12139. + break;
  12140. + default:
  12141. + err = -EINVAL;
  12142. + goto out;
  12143. + }
  12144. +
  12145. + if (prq->flags & IW_POWER_TIMEOUT) {
  12146. + priv->pm_on = 1;
  12147. + priv->pm_timeout = prq->value / 1000;
  12148. + }
  12149. + if (prq->flags & IW_POWER_PERIOD) {
  12150. + priv->pm_on = 1;
  12151. + priv->pm_period = prq->value / 1000;
  12152. + }
  12153. + /* It's valid to not have a value if we are just toggling
  12154. + * the flags... Jean II */
  12155. + if (!priv->pm_on) {
  12156. + err = -EINVAL;
  12157. + goto out;
  12158. + }
  12159. + }
  12160. +
  12161. + out:
  12162. + orinoco_unlock(priv, &flags);
  12163. +
  12164. + return err;
  12165. +}
  12166. +
  12167. +static int orinoco_ioctl_getpower(struct net_device *dev,
  12168. + struct iw_request_info *info,
  12169. + union iwreq_data *wrqu,
  12170. + char *extra)
  12171. +{
  12172. + struct iw_param *prq = &wrqu->power;
  12173. + struct orinoco_private *priv = ndev_priv(dev);
  12174. + struct hermes *hw = &priv->hw;
  12175. + int err = 0;
  12176. + u16 enable, period, timeout, mcast;
  12177. + unsigned long flags;
  12178. +
  12179. + if (orinoco_lock(priv, &flags) != 0)
  12180. + return -EBUSY;
  12181. +
  12182. + err = hermes_read_wordrec(hw, USER_BAP,
  12183. + HERMES_RID_CNFPMENABLED, &enable);
  12184. + if (err)
  12185. + goto out;
  12186. +
  12187. + err = hermes_read_wordrec(hw, USER_BAP,
  12188. + HERMES_RID_CNFMAXSLEEPDURATION, &period);
  12189. + if (err)
  12190. + goto out;
  12191. +
  12192. + err = hermes_read_wordrec(hw, USER_BAP,
  12193. + HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
  12194. + if (err)
  12195. + goto out;
  12196. +
  12197. + err = hermes_read_wordrec(hw, USER_BAP,
  12198. + HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
  12199. + if (err)
  12200. + goto out;
  12201. +
  12202. + prq->disabled = !enable;
  12203. + /* Note : by default, display the period */
  12204. + if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
  12205. + prq->flags = IW_POWER_TIMEOUT;
  12206. + prq->value = timeout * 1000;
  12207. + } else {
  12208. + prq->flags = IW_POWER_PERIOD;
  12209. + prq->value = period * 1000;
  12210. + }
  12211. + if (mcast)
  12212. + prq->flags |= IW_POWER_ALL_R;
  12213. + else
  12214. + prq->flags |= IW_POWER_UNICAST_R;
  12215. +
  12216. + out:
  12217. + orinoco_unlock(priv, &flags);
  12218. +
  12219. + return err;
  12220. +}
  12221. +
  12222. +static int orinoco_ioctl_set_encodeext(struct net_device *dev,
  12223. + struct iw_request_info *info,
  12224. + union iwreq_data *wrqu,
  12225. + char *extra)
  12226. +{
  12227. + struct orinoco_private *priv = ndev_priv(dev);
  12228. + struct iw_point *encoding = &wrqu->encoding;
  12229. + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
  12230. + int idx, alg = ext->alg, set_key = 1;
  12231. + unsigned long flags;
  12232. + int err = -EINVAL;
  12233. +
  12234. + if (orinoco_lock(priv, &flags) != 0)
  12235. + return -EBUSY;
  12236. +
  12237. + /* Determine and validate the key index */
  12238. + idx = encoding->flags & IW_ENCODE_INDEX;
  12239. + if (idx) {
  12240. + if ((idx < 1) || (idx > 4))
  12241. + goto out;
  12242. + idx--;
  12243. + } else
  12244. + idx = priv->tx_key;
  12245. +
  12246. + if (encoding->flags & IW_ENCODE_DISABLED)
  12247. + alg = IW_ENCODE_ALG_NONE;
  12248. +
  12249. + if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
  12250. + /* Clear any TKIP TX key we had */
  12251. + (void) orinoco_clear_tkip_key(priv, priv->tx_key);
  12252. + }
  12253. +
  12254. + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
  12255. + priv->tx_key = idx;
  12256. + set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
  12257. + (ext->key_len > 0)) ? 1 : 0;
  12258. + }
  12259. +
  12260. + if (set_key) {
  12261. + /* Set the requested key first */
  12262. + switch (alg) {
  12263. + case IW_ENCODE_ALG_NONE:
  12264. + priv->encode_alg = ORINOCO_ALG_NONE;
  12265. + err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
  12266. + NULL, 0, NULL, 0);
  12267. + break;
  12268. +
  12269. + case IW_ENCODE_ALG_WEP:
  12270. + if (ext->key_len <= 0)
  12271. + goto out;
  12272. +
  12273. + priv->encode_alg = ORINOCO_ALG_WEP;
  12274. + err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
  12275. + ext->key, ext->key_len, NULL, 0);
  12276. + break;
  12277. +
  12278. + case IW_ENCODE_ALG_TKIP:
  12279. + {
  12280. + u8 *tkip_iv = NULL;
  12281. +
  12282. + if (!priv->has_wpa ||
  12283. + (ext->key_len > sizeof(struct orinoco_tkip_key)))
  12284. + goto out;
  12285. +
  12286. + priv->encode_alg = ORINOCO_ALG_TKIP;
  12287. +
  12288. + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
  12289. + tkip_iv = &ext->rx_seq[0];
  12290. +
  12291. + err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
  12292. + ext->key, ext->key_len, tkip_iv,
  12293. + ORINOCO_SEQ_LEN);
  12294. +
  12295. + err = __orinoco_hw_set_tkip_key(priv, idx,
  12296. + ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
  12297. + priv->keys[idx].key, priv->keys[idx].key_len,
  12298. + tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
  12299. + if (err)
  12300. + printk(KERN_ERR "%s: Error %d setting TKIP key"
  12301. + "\n", dev->name, err);
  12302. +
  12303. + goto out;
  12304. + }
  12305. + default:
  12306. + goto out;
  12307. + }
  12308. + }
  12309. + err = -EINPROGRESS;
  12310. + out:
  12311. + orinoco_unlock(priv, &flags);
  12312. +
  12313. + return err;
  12314. +}
  12315. +
  12316. +static int orinoco_ioctl_get_encodeext(struct net_device *dev,
  12317. + struct iw_request_info *info,
  12318. + union iwreq_data *wrqu,
  12319. + char *extra)
  12320. +{
  12321. + struct orinoco_private *priv = ndev_priv(dev);
  12322. + struct iw_point *encoding = &wrqu->encoding;
  12323. + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
  12324. + int idx, max_key_len;
  12325. + unsigned long flags;
  12326. + int err;
  12327. +
  12328. + if (orinoco_lock(priv, &flags) != 0)
  12329. + return -EBUSY;
  12330. +
  12331. + err = -EINVAL;
  12332. + max_key_len = encoding->length - sizeof(*ext);
  12333. + if (max_key_len < 0)
  12334. + goto out;
  12335. +
  12336. + idx = encoding->flags & IW_ENCODE_INDEX;
  12337. + if (idx) {
  12338. + if ((idx < 1) || (idx > 4))
  12339. + goto out;
  12340. + idx--;
  12341. + } else
  12342. + idx = priv->tx_key;
  12343. +
  12344. + encoding->flags = idx + 1;
  12345. + memset(ext, 0, sizeof(*ext));
  12346. +
  12347. + switch (priv->encode_alg) {
  12348. + case ORINOCO_ALG_NONE:
  12349. + ext->alg = IW_ENCODE_ALG_NONE;
  12350. + ext->key_len = 0;
  12351. + encoding->flags |= IW_ENCODE_DISABLED;
  12352. + break;
  12353. + case ORINOCO_ALG_WEP:
  12354. + ext->alg = IW_ENCODE_ALG_WEP;
  12355. + ext->key_len = min(priv->keys[idx].key_len, max_key_len);
  12356. + memcpy(ext->key, priv->keys[idx].key, ext->key_len);
  12357. + encoding->flags |= IW_ENCODE_ENABLED;
  12358. + break;
  12359. + case ORINOCO_ALG_TKIP:
  12360. + ext->alg = IW_ENCODE_ALG_TKIP;
  12361. + ext->key_len = min(priv->keys[idx].key_len, max_key_len);
  12362. + memcpy(ext->key, priv->keys[idx].key, ext->key_len);
  12363. + encoding->flags |= IW_ENCODE_ENABLED;
  12364. + break;
  12365. + }
  12366. +
  12367. + err = 0;
  12368. + out:
  12369. + orinoco_unlock(priv, &flags);
  12370. +
  12371. + return err;
  12372. +}
  12373. +
  12374. +static int orinoco_ioctl_set_auth(struct net_device *dev,
  12375. + struct iw_request_info *info,
  12376. + union iwreq_data *wrqu, char *extra)
  12377. +{
  12378. + struct orinoco_private *priv = ndev_priv(dev);
  12379. + struct hermes *hw = &priv->hw;
  12380. + struct iw_param *param = &wrqu->param;
  12381. + unsigned long flags;
  12382. + int ret = -EINPROGRESS;
  12383. +
  12384. + if (orinoco_lock(priv, &flags) != 0)
  12385. + return -EBUSY;
  12386. +
  12387. + switch (param->flags & IW_AUTH_INDEX) {
  12388. + case IW_AUTH_WPA_VERSION:
  12389. + case IW_AUTH_CIPHER_PAIRWISE:
  12390. + case IW_AUTH_CIPHER_GROUP:
  12391. + case IW_AUTH_RX_UNENCRYPTED_EAPOL:
  12392. + case IW_AUTH_PRIVACY_INVOKED:
  12393. + case IW_AUTH_DROP_UNENCRYPTED:
  12394. + /*
  12395. + * orinoco does not use these parameters
  12396. + */
  12397. + break;
  12398. +
  12399. + case IW_AUTH_MFP:
  12400. + /* Management Frame Protection not supported.
  12401. + * Only fail if set to required.
  12402. + */
  12403. + if (param->value == IW_AUTH_MFP_REQUIRED)
  12404. + ret = -EINVAL;
  12405. + break;
  12406. +
  12407. + case IW_AUTH_KEY_MGMT:
  12408. + /* wl_lkm implies value 2 == PSK for Hermes I
  12409. + * which ties in with WEXT
  12410. + * no other hints tho :(
  12411. + */
  12412. + priv->key_mgmt = param->value;
  12413. + break;
  12414. +
  12415. + case IW_AUTH_TKIP_COUNTERMEASURES:
  12416. + /* When countermeasures are enabled, shut down the
  12417. + * card; when disabled, re-enable the card. This must
  12418. + * take effect immediately.
  12419. + *
  12420. + * TODO: Make sure that the EAPOL message is getting
  12421. + * out before card disabled
  12422. + */
  12423. + if (param->value) {
  12424. + priv->tkip_cm_active = 1;
  12425. + ret = hermes_disable_port(hw, 0);
  12426. + } else {
  12427. + priv->tkip_cm_active = 0;
  12428. + ret = hermes_enable_port(hw, 0);
  12429. + }
  12430. + break;
  12431. +
  12432. + case IW_AUTH_80211_AUTH_ALG:
  12433. + if (param->value & IW_AUTH_ALG_SHARED_KEY)
  12434. + priv->wep_restrict = 1;
  12435. + else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
  12436. + priv->wep_restrict = 0;
  12437. + else
  12438. + ret = -EINVAL;
  12439. + break;
  12440. +
  12441. + case IW_AUTH_WPA_ENABLED:
  12442. + if (priv->has_wpa) {
  12443. + priv->wpa_enabled = param->value ? 1 : 0;
  12444. + } else {
  12445. + if (param->value)
  12446. + ret = -EOPNOTSUPP;
  12447. + /* else silently accept disable of WPA */
  12448. + priv->wpa_enabled = 0;
  12449. + }
  12450. + break;
  12451. +
  12452. + default:
  12453. + ret = -EOPNOTSUPP;
  12454. + }
  12455. +
  12456. + orinoco_unlock(priv, &flags);
  12457. + return ret;
  12458. +}
  12459. +
  12460. +static int orinoco_ioctl_get_auth(struct net_device *dev,
  12461. + struct iw_request_info *info,
  12462. + union iwreq_data *wrqu, char *extra)
  12463. +{
  12464. + struct orinoco_private *priv = ndev_priv(dev);
  12465. + struct iw_param *param = &wrqu->param;
  12466. + unsigned long flags;
  12467. + int ret = 0;
  12468. +
  12469. + if (orinoco_lock(priv, &flags) != 0)
  12470. + return -EBUSY;
  12471. +
  12472. + switch (param->flags & IW_AUTH_INDEX) {
  12473. + case IW_AUTH_KEY_MGMT:
  12474. + param->value = priv->key_mgmt;
  12475. + break;
  12476. +
  12477. + case IW_AUTH_TKIP_COUNTERMEASURES:
  12478. + param->value = priv->tkip_cm_active;
  12479. + break;
  12480. +
  12481. + case IW_AUTH_80211_AUTH_ALG:
  12482. + if (priv->wep_restrict)
  12483. + param->value = IW_AUTH_ALG_SHARED_KEY;
  12484. + else
  12485. + param->value = IW_AUTH_ALG_OPEN_SYSTEM;
  12486. + break;
  12487. +
  12488. + case IW_AUTH_WPA_ENABLED:
  12489. + param->value = priv->wpa_enabled;
  12490. + break;
  12491. +
  12492. + default:
  12493. + ret = -EOPNOTSUPP;
  12494. + }
  12495. +
  12496. + orinoco_unlock(priv, &flags);
  12497. + return ret;
  12498. +}
  12499. +
  12500. +static int orinoco_ioctl_set_genie(struct net_device *dev,
  12501. + struct iw_request_info *info,
  12502. + union iwreq_data *wrqu, char *extra)
  12503. +{
  12504. + struct orinoco_private *priv = ndev_priv(dev);
  12505. + u8 *buf;
  12506. + unsigned long flags;
  12507. +
  12508. + /* cut off at IEEE80211_MAX_DATA_LEN */
  12509. + if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
  12510. + (wrqu->data.length && (extra == NULL)))
  12511. + return -EINVAL;
  12512. +
  12513. + if (wrqu->data.length) {
  12514. + buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL);
  12515. + if (buf == NULL)
  12516. + return -ENOMEM;
  12517. + } else
  12518. + buf = NULL;
  12519. +
  12520. + if (orinoco_lock(priv, &flags) != 0) {
  12521. + kfree(buf);
  12522. + return -EBUSY;
  12523. + }
  12524. +
  12525. + kfree(priv->wpa_ie);
  12526. + priv->wpa_ie = buf;
  12527. + priv->wpa_ie_len = wrqu->data.length;
  12528. +
  12529. + if (priv->wpa_ie) {
  12530. + /* Looks like wl_lkm wants to check the auth alg, and
  12531. + * somehow pass it to the firmware.
  12532. + * Instead it just calls the key mgmt rid
  12533. + * - we do this in set auth.
  12534. + */
  12535. + }
  12536. +
  12537. + orinoco_unlock(priv, &flags);
  12538. + return 0;
  12539. +}
  12540. +
  12541. +static int orinoco_ioctl_get_genie(struct net_device *dev,
  12542. + struct iw_request_info *info,
  12543. + union iwreq_data *wrqu, char *extra)
  12544. +{
  12545. + struct orinoco_private *priv = ndev_priv(dev);
  12546. + unsigned long flags;
  12547. + int err = 0;
  12548. +
  12549. + if (orinoco_lock(priv, &flags) != 0)
  12550. + return -EBUSY;
  12551. +
  12552. + if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
  12553. + wrqu->data.length = 0;
  12554. + goto out;
  12555. + }
  12556. +
  12557. + if (wrqu->data.length < priv->wpa_ie_len) {
  12558. + err = -E2BIG;
  12559. + goto out;
  12560. + }
  12561. +
  12562. + wrqu->data.length = priv->wpa_ie_len;
  12563. + memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
  12564. +
  12565. +out:
  12566. + orinoco_unlock(priv, &flags);
  12567. + return err;
  12568. +}
  12569. +
  12570. +static int orinoco_ioctl_set_mlme(struct net_device *dev,
  12571. + struct iw_request_info *info,
  12572. + union iwreq_data *wrqu, char *extra)
  12573. +{
  12574. + struct orinoco_private *priv = ndev_priv(dev);
  12575. + struct iw_mlme *mlme = (struct iw_mlme *)extra;
  12576. + unsigned long flags;
  12577. + int ret = 0;
  12578. +
  12579. + if (orinoco_lock(priv, &flags) != 0)
  12580. + return -EBUSY;
  12581. +
  12582. + switch (mlme->cmd) {
  12583. + case IW_MLME_DEAUTH:
  12584. + /* silently ignore */
  12585. + break;
  12586. +
  12587. + case IW_MLME_DISASSOC:
  12588. +
  12589. + ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
  12590. + mlme->reason_code);
  12591. + break;
  12592. +
  12593. + default:
  12594. + ret = -EOPNOTSUPP;
  12595. + }
  12596. +
  12597. + orinoco_unlock(priv, &flags);
  12598. + return ret;
  12599. +}
  12600. +
  12601. +static int orinoco_ioctl_reset(struct net_device *dev,
  12602. + struct iw_request_info *info,
  12603. + union iwreq_data *wrqu,
  12604. + char *extra)
  12605. +{
  12606. + struct orinoco_private *priv = ndev_priv(dev);
  12607. +
  12608. + if (!capable(CAP_NET_ADMIN))
  12609. + return -EPERM;
  12610. +
  12611. + if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
  12612. + printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
  12613. +
  12614. + /* Firmware reset */
  12615. + orinoco_reset(&priv->reset_work);
  12616. + } else {
  12617. + printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
  12618. +
  12619. + schedule_work(&priv->reset_work);
  12620. + }
  12621. +
  12622. + return 0;
  12623. +}
  12624. +
  12625. +static int orinoco_ioctl_setibssport(struct net_device *dev,
  12626. + struct iw_request_info *info,
  12627. + union iwreq_data *wrqu,
  12628. + char *extra)
  12629. +
  12630. +{
  12631. + struct orinoco_private *priv = ndev_priv(dev);
  12632. + int val = *((int *) extra);
  12633. + unsigned long flags;
  12634. +
  12635. + if (orinoco_lock(priv, &flags) != 0)
  12636. + return -EBUSY;
  12637. +
  12638. + priv->ibss_port = val;
  12639. +
  12640. + /* Actually update the mode we are using */
  12641. + set_port_type(priv);
  12642. +
  12643. + orinoco_unlock(priv, &flags);
  12644. + return -EINPROGRESS; /* Call commit handler */
  12645. +}
  12646. +
  12647. +static int orinoco_ioctl_getibssport(struct net_device *dev,
  12648. + struct iw_request_info *info,
  12649. + union iwreq_data *wrqu,
  12650. + char *extra)
  12651. +{
  12652. + struct orinoco_private *priv = ndev_priv(dev);
  12653. + int *val = (int *) extra;
  12654. +
  12655. + *val = priv->ibss_port;
  12656. + return 0;
  12657. +}
  12658. +
  12659. +static int orinoco_ioctl_setport3(struct net_device *dev,
  12660. + struct iw_request_info *info,
  12661. + union iwreq_data *wrqu,
  12662. + char *extra)
  12663. +{
  12664. + struct orinoco_private *priv = ndev_priv(dev);
  12665. + int val = *((int *) extra);
  12666. + int err = 0;
  12667. + unsigned long flags;
  12668. +
  12669. + if (orinoco_lock(priv, &flags) != 0)
  12670. + return -EBUSY;
  12671. +
  12672. + switch (val) {
  12673. + case 0: /* Try to do IEEE ad-hoc mode */
  12674. + if (!priv->has_ibss) {
  12675. + err = -EINVAL;
  12676. + break;
  12677. + }
  12678. + priv->prefer_port3 = 0;
  12679. +
  12680. + break;
  12681. +
  12682. + case 1: /* Try to do Lucent proprietary ad-hoc mode */
  12683. + if (!priv->has_port3) {
  12684. + err = -EINVAL;
  12685. + break;
  12686. + }
  12687. + priv->prefer_port3 = 1;
  12688. + break;
  12689. +
  12690. + default:
  12691. + err = -EINVAL;
  12692. + }
  12693. +
  12694. + if (!err) {
  12695. + /* Actually update the mode we are using */
  12696. + set_port_type(priv);
  12697. + err = -EINPROGRESS;
  12698. + }
  12699. +
  12700. + orinoco_unlock(priv, &flags);
  12701. +
  12702. + return err;
  12703. +}
  12704. +
  12705. +static int orinoco_ioctl_getport3(struct net_device *dev,
  12706. + struct iw_request_info *info,
  12707. + union iwreq_data *wrqu,
  12708. + char *extra)
  12709. +{
  12710. + struct orinoco_private *priv = ndev_priv(dev);
  12711. + int *val = (int *) extra;
  12712. +
  12713. + *val = priv->prefer_port3;
  12714. + return 0;
  12715. +}
  12716. +
  12717. +static int orinoco_ioctl_setpreamble(struct net_device *dev,
  12718. + struct iw_request_info *info,
  12719. + union iwreq_data *wrqu,
  12720. + char *extra)
  12721. +{
  12722. + struct orinoco_private *priv = ndev_priv(dev);
  12723. + unsigned long flags;
  12724. + int val;
  12725. +
  12726. + if (!priv->has_preamble)
  12727. + return -EOPNOTSUPP;
  12728. +
  12729. + /* 802.11b has recently defined some short preamble.
  12730. + * Basically, the Phy header has been reduced in size.
  12731. + * This increase performance, especially at high rates
  12732. + * (the preamble is transmitted at 1Mb/s), unfortunately
  12733. + * this give compatibility troubles... - Jean II */
  12734. + val = *((int *) extra);
  12735. +
  12736. + if (orinoco_lock(priv, &flags) != 0)
  12737. + return -EBUSY;
  12738. +
  12739. + if (val)
  12740. + priv->preamble = 1;
  12741. + else
  12742. + priv->preamble = 0;
  12743. +
  12744. + orinoco_unlock(priv, &flags);
  12745. +
  12746. + return -EINPROGRESS; /* Call commit handler */
  12747. +}
  12748. +
  12749. +static int orinoco_ioctl_getpreamble(struct net_device *dev,
  12750. + struct iw_request_info *info,
  12751. + union iwreq_data *wrqu,
  12752. + char *extra)
  12753. +{
  12754. + struct orinoco_private *priv = ndev_priv(dev);
  12755. + int *val = (int *) extra;
  12756. +
  12757. + if (!priv->has_preamble)
  12758. + return -EOPNOTSUPP;
  12759. +
  12760. + *val = priv->preamble;
  12761. + return 0;
  12762. +}
  12763. +
  12764. +/* ioctl interface to hermes_read_ltv()
  12765. + * To use with iwpriv, pass the RID as the token argument, e.g.
  12766. + * iwpriv get_rid [0xfc00]
  12767. + * At least Wireless Tools 25 is required to use iwpriv.
  12768. + * For Wireless Tools 25 and 26 append "dummy" are the end. */
  12769. +static int orinoco_ioctl_getrid(struct net_device *dev,
  12770. + struct iw_request_info *info,
  12771. + union iwreq_data *wrqu,
  12772. + char *extra)
  12773. +{
  12774. + struct iw_point *data = &wrqu->data;
  12775. + struct orinoco_private *priv = ndev_priv(dev);
  12776. + struct hermes *hw = &priv->hw;
  12777. + int rid = data->flags;
  12778. + u16 length;
  12779. + int err;
  12780. + unsigned long flags;
  12781. +
  12782. + /* It's a "get" function, but we don't want users to access the
  12783. + * WEP key and other raw firmware data */
  12784. + if (!capable(CAP_NET_ADMIN))
  12785. + return -EPERM;
  12786. +
  12787. + if (rid < 0xfc00 || rid > 0xffff)
  12788. + return -EINVAL;
  12789. +
  12790. + if (orinoco_lock(priv, &flags) != 0)
  12791. + return -EBUSY;
  12792. +
  12793. + err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
  12794. + extra);
  12795. + if (err)
  12796. + goto out;
  12797. +
  12798. + data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
  12799. + MAX_RID_LEN);
  12800. +
  12801. + out:
  12802. + orinoco_unlock(priv, &flags);
  12803. + return err;
  12804. +}
  12805. +
  12806. +
  12807. +/* Commit handler, called after set operations */
  12808. +static int orinoco_ioctl_commit(struct net_device *dev,
  12809. + struct iw_request_info *info,
  12810. + union iwreq_data *wrqu,
  12811. + char *extra)
  12812. +{
  12813. + struct orinoco_private *priv = ndev_priv(dev);
  12814. + unsigned long flags;
  12815. + int err = 0;
  12816. +
  12817. + if (!priv->open)
  12818. + return 0;
  12819. +
  12820. + if (orinoco_lock(priv, &flags) != 0)
  12821. + return err;
  12822. +
  12823. + err = orinoco_commit(priv);
  12824. +
  12825. + orinoco_unlock(priv, &flags);
  12826. + return err;
  12827. +}
  12828. +
  12829. +static const struct iw_priv_args orinoco_privtab[] = {
  12830. + { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
  12831. + { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
  12832. + { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  12833. + 0, "set_port3" },
  12834. + { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  12835. + "get_port3" },
  12836. + { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  12837. + 0, "set_preamble" },
  12838. + { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  12839. + "get_preamble" },
  12840. + { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  12841. + 0, "set_ibssport" },
  12842. + { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  12843. + "get_ibssport" },
  12844. + { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
  12845. + "get_rid" },
  12846. +};
  12847. +
  12848. +
  12849. +/*
  12850. + * Structures to export the Wireless Handlers
  12851. + */
  12852. +
  12853. +static const iw_handler orinoco_handler[] = {
  12854. + IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
  12855. + IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
  12856. + IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
  12857. + IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
  12858. + IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode),
  12859. + IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode),
  12860. + IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
  12861. + IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
  12862. + IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange),
  12863. + IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
  12864. + IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
  12865. + IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
  12866. + IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
  12867. + IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
  12868. + IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
  12869. + IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
  12870. + IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
  12871. + IW_HANDLER(SIOCSIWRTS, cfg80211_wext_siwrts),
  12872. + IW_HANDLER(SIOCGIWRTS, cfg80211_wext_giwrts),
  12873. + IW_HANDLER(SIOCSIWFRAG, cfg80211_wext_siwfrag),
  12874. + IW_HANDLER(SIOCGIWFRAG, cfg80211_wext_giwfrag),
  12875. + IW_HANDLER(SIOCGIWRETRY, cfg80211_wext_giwretry),
  12876. + IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
  12877. + IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
  12878. + IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
  12879. + IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower),
  12880. + IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
  12881. + IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
  12882. + IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
  12883. + IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
  12884. + IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
  12885. + IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
  12886. + IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
  12887. +};
  12888. +
  12889. +
  12890. +/*
  12891. + Added typecasting since we no longer use iwreq_data -- Moustafa
  12892. + */
  12893. +static const iw_handler orinoco_private_handler[] = {
  12894. + [0] = orinoco_ioctl_reset,
  12895. + [1] = orinoco_ioctl_reset,
  12896. + [2] = orinoco_ioctl_setport3,
  12897. + [3] = orinoco_ioctl_getport3,
  12898. + [4] = orinoco_ioctl_setpreamble,
  12899. + [5] = orinoco_ioctl_getpreamble,
  12900. + [6] = orinoco_ioctl_setibssport,
  12901. + [7] = orinoco_ioctl_getibssport,
  12902. + [9] = orinoco_ioctl_getrid,
  12903. +};
  12904. +
  12905. +const struct iw_handler_def orinoco_handler_def = {
  12906. + .num_standard = ARRAY_SIZE(orinoco_handler),
  12907. + .num_private = ARRAY_SIZE(orinoco_private_handler),
  12908. + .num_private_args = ARRAY_SIZE(orinoco_privtab),
  12909. + .standard = orinoco_handler,
  12910. + .private = orinoco_private_handler,
  12911. + .private_args = orinoco_privtab,
  12912. + .get_wireless_stats = orinoco_get_wireless_stats,
  12913. +};
  12914. diff -Nur linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/wext.h linux-6.15.6/drivers/net/wireless/intersil/orinoco/wext.h
  12915. --- linux-6.15.6.orig/drivers/net/wireless/intersil/orinoco/wext.h 1970-01-01 01:00:00.000000000 +0100
  12916. +++ linux-6.15.6/drivers/net/wireless/intersil/orinoco/wext.h 2025-08-03 15:01:59.393129374 +0200
  12917. @@ -0,0 +1,13 @@
  12918. +/* Wireless extensions support.
  12919. + *
  12920. + * See copyright notice in main.c
  12921. + */
  12922. +#ifndef _ORINOCO_WEXT_H_
  12923. +#define _ORINOCO_WEXT_H_
  12924. +
  12925. +#include <net/iw_handler.h>
  12926. +
  12927. +/* Structure defining all our WEXT handlers */
  12928. +extern const struct iw_handler_def orinoco_handler_def;
  12929. +
  12930. +#endif /* _ORINOCO_WEXT_H_ */