cpqfcTSworker.c 207 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516
  1. /* Copyright(c) 2000, Compaq Computer Corporation
  2. * Fibre Channel Host Bus Adapter
  3. * 64-bit, 66MHz PCI
  4. * Originally developed and tested on:
  5. * (front): [chip] Tachyon TS HPFC-5166A/1.2 L2C1090 ...
  6. * SP# P225CXCBFIEL6T, Rev XC
  7. * SP# 161290-001, Rev XD
  8. * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by the
  12. * Free Software Foundation; either version 2, or (at your option) any
  13. * later version.
  14. *
  15. * This program is distributed in the hope that it will be useful, but
  16. * WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * General Public License for more details.
  19. * Written by Don Zimmerman
  20. */
  21. #include <linux/sched.h>
  22. #include <linux/timer.h>
  23. #include <linux/string.h>
  24. #include <linux/slab.h>
  25. #include <linux/ioport.h>
  26. #include <linux/kernel.h>
  27. #include <linux/stat.h>
  28. #include <linux/blkdev.h>
  29. #include <linux/interrupt.h>
  30. #include <linux/delay.h>
  31. #include <linux/smp_lock.h>
  32. #include <linux/pci.h>
  33. #define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
  34. #include <asm/system.h>
  35. #include <asm/irq.h>
  36. #include <asm/dma.h>
  37. #include "scsi.h"
  38. #include <scsi/scsi_host.h> // struct Scsi_Host definition for T handler
  39. #include "cpqfcTSchip.h"
  40. #include "cpqfcTSstructs.h"
  41. #include "cpqfcTStrigger.h"
  42. //#define LOGIN_DBG 1
  43. // REMARKS:
  44. // Since Tachyon chips may be permitted to wait from 500ms up to 2 sec
  45. // to empty an outgoing frame from its FIFO to the Fibre Channel stream,
  46. // we cannot do everything we need to in the interrupt handler. Specifically,
  47. // every time a link re-init (e.g. LIP) takes place, all SCSI I/O has to be
  48. // suspended until the login sequences have been completed. Login commands
  49. // are frames just like SCSI commands are frames; they are subject to the same
  50. // timeout issues and delays. Also, various specs provide up to 2 seconds for
  51. // devices to log back in (i.e. respond with ACC to a login frame), so I/O to
  52. // that device has to be suspended.
  53. // A serious problem here occurs on highly loaded FC-AL systems. If our FC port
  54. // has a low priority (e.g. high arbitrated loop physical address, alpa), and
  55. // some other device is hogging bandwidth (permissible under FC-AL), we might
  56. // time out thinking the link is hung, when it's simply busy. Many such
  57. // considerations complicate the design. Although Tachyon assumes control
  58. // (in silicon) for many link-specific issues, the Linux driver is left with the
  59. // rest, which turns out to be a difficult, time critical chore.
  60. // These "worker" functions will handle things like FC Logins; all
  61. // processes with I/O to our device must wait for the Login to complete
  62. // and (if successful) I/O to resume. In the event of a malfunctioning or
  63. // very busy loop, it may take hundreds of millisecs or even seconds to complete
  64. // a frame send. We don't want to hang up the entire server (and all
  65. // processes which don't depend on Fibre) during this wait.
  66. // The Tachyon chip can have around 30,000 I/O operations ("exchanges")
  67. // open at one time. However, each exchange must be initiated
  68. // synchronously (i.e. each of the 30k I/O had to be started one at a
  69. // time by sending a starting frame via Tachyon's outbound que).
  70. // To accommodate kernel "module" build, this driver limits the exchanges
  71. // to 256, because of the contiguous physical memory limitation of 128M.
  72. // Typical FC Exchanges are opened presuming the FC frames start without errors,
  73. // while Exchange completion is handled in the interrupt handler. This
  74. // optimizes performance for the "everything's working" case.
  75. // However, when we have FC related errors or hot plugging of FC ports, we pause
  76. // I/O and handle FC-specific tasks in the worker thread. These FC-specific
  77. // functions will handle things like FC Logins and Aborts. As the Login sequence
  78. // completes to each and every target, I/O can resume to that target.
  79. // Our kernel "worker thread" must share the HBA with threads calling
  80. // "queuecommand". We define a "BoardLock" semaphore which indicates
  81. // to "queuecommand" that the HBA is unavailable, and Cmnds are added to a
  82. // board lock Q. When the worker thread finishes with the board, the board
  83. // lock Q commands are completed with status causing immediate retry.
  84. // Typically, the board is locked while Logins are in progress after an
  85. // FC Link Down condition. When Cmnds are re-queued after board lock, the
  86. // particular Scsi channel/target may or may not have logged back in. When
  87. // the device is waiting for login, the "prli" flag is clear, in which case
  88. // commands are passed to a Link Down Q. Whenever the login finally completes,
  89. // the LinkDown Q is completed, again with status causing immediate retry.
  90. // When FC devices are logged in, we build and start FC commands to the
  91. // devices.
  92. // NOTE!! As of May 2000, kernel 2.2.14, the error recovery logic for devices
  93. // that never log back in (e.g. physically removed) is NOT completely
  94. // understood. I've still seen instances of system hangs on failed Write
  95. // commands (possibly from the ext2 layer?) on device removal. Such special
  96. // cases need to be evaluated from a system/application view - e.g., how
  97. // exactly does the system want me to complete commands when the device is
  98. // physically removed??
  99. // local functions
  100. static void SetLoginFields(
  101. PFC_LOGGEDIN_PORT pLoggedInPort,
  102. TachFCHDR_GCMND* fchs,
  103. BOOLEAN PDisc,
  104. BOOLEAN Originator);
  105. static void AnalyzeIncomingFrame(
  106. CPQFCHBA *cpqfcHBAdata,
  107. ULONG QNdx );
  108. static void SendLogins( CPQFCHBA *cpqfcHBAdata, __u32 *FabricPortIds );
  109. static int verify_PLOGI( PTACHYON fcChip,
  110. TachFCHDR_GCMND* fchs, ULONG* reject_explain);
  111. static int verify_PRLI( TachFCHDR_GCMND* fchs, ULONG* reject_explain);
  112. static void LoadWWN( PTACHYON fcChip, UCHAR* dest, UCHAR type);
  113. static void BuildLinkServicePayload(
  114. PTACHYON fcChip, ULONG type, void* payload);
  115. static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
  116. PFC_LOGGEDIN_PORT pLoggedInPort);
  117. static void cpqfcTSCheckandSnoopFCP( PTACHYON fcChip, ULONG x_ID);
  118. static void CompleteBoardLockCmnd( CPQFCHBA *cpqfcHBAdata);
  119. static void RevalidateSEST( struct Scsi_Host *HostAdapter,
  120. PFC_LOGGEDIN_PORT pLoggedInPort);
  121. static void IssueReportLunsCommand(
  122. CPQFCHBA* cpqfcHBAdata,
  123. TachFCHDR_GCMND* fchs);
  124. // (see scsi_error.c comments on kernel task creation)
  125. void cpqfcTSWorkerThread( void *host)
  126. {
  127. struct Scsi_Host *HostAdapter = (struct Scsi_Host*)host;
  128. CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  129. #ifdef PCI_KERNEL_TRACE
  130. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  131. #endif
  132. DECLARE_MUTEX_LOCKED(fcQueReady);
  133. DECLARE_MUTEX_LOCKED(fcTYOBcomplete);
  134. DECLARE_MUTEX_LOCKED(TachFrozen);
  135. DECLARE_MUTEX_LOCKED(BoardLock);
  136. ENTER("WorkerThread");
  137. lock_kernel();
  138. daemonize("cpqfcTS_wt_%d", HostAdapter->host_no);
  139. siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
  140. cpqfcHBAdata->fcQueReady = &fcQueReady; // primary wait point
  141. cpqfcHBAdata->TYOBcomplete = &fcTYOBcomplete;
  142. cpqfcHBAdata->TachFrozen = &TachFrozen;
  143. cpqfcHBAdata->worker_thread = current;
  144. unlock_kernel();
  145. if( cpqfcHBAdata->notify_wt != NULL )
  146. up( cpqfcHBAdata->notify_wt); // OK to continue
  147. while(1)
  148. {
  149. unsigned long flags;
  150. down_interruptible( &fcQueReady); // wait for something to do
  151. if (signal_pending(current) )
  152. break;
  153. PCI_TRACE( 0x90)
  154. // first, take the IO lock so the SCSI upper layers can't call
  155. // into our _quecommand function (this also disables INTs)
  156. spin_lock_irqsave( HostAdapter->host_lock, flags); // STOP _que function
  157. PCI_TRACE( 0x90)
  158. CPQ_SPINLOCK_HBA( cpqfcHBAdata)
  159. // next, set this pointer to indicate to the _quecommand function
  160. // that the board is in use, so it should que the command and
  161. // immediately return (we don't actually require the semaphore function
  162. // in this driver rev)
  163. cpqfcHBAdata->BoardLock = &BoardLock;
  164. PCI_TRACE( 0x90)
  165. // release the IO lock (and re-enable interrupts)
  166. spin_unlock_irqrestore( HostAdapter->host_lock, flags);
  167. // disable OUR HBA interrupt (keep them off as much as possible
  168. // during error recovery)
  169. disable_irq( cpqfcHBAdata->HostAdapter->irq);
  170. // OK, let's process the Fibre Channel Link Q and do the work
  171. cpqfcTS_WorkTask( HostAdapter);
  172. // hopefully, no more "work" to do;
  173. // re-enable our INTs for "normal" completion processing
  174. enable_irq( cpqfcHBAdata->HostAdapter->irq);
  175. cpqfcHBAdata->BoardLock = NULL; // allow commands to be queued
  176. CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)
  177. // Now, complete any Cmnd we Q'd up while BoardLock was held
  178. CompleteBoardLockCmnd( cpqfcHBAdata);
  179. }
  180. // hopefully, the signal was for our module exit...
  181. if( cpqfcHBAdata->notify_wt != NULL )
  182. up( cpqfcHBAdata->notify_wt); // yep, we're outta here
  183. }
  184. // Freeze Tachyon routine.
  185. // If Tachyon is already frozen, return FALSE
  186. // If Tachyon is not frozen, call freeze function, return TRUE
  187. //
  188. static BOOLEAN FreezeTach( CPQFCHBA *cpqfcHBAdata)
  189. {
  190. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  191. BOOLEAN FrozeTach = FALSE;
  192. // It's possible that the chip is already frozen; if so,
  193. // "Freezing" again will NOT! generate another Freeze
  194. // Completion Message.
  195. if( (fcChip->Registers.TYstatus.value & 0x70000) != 0x70000)
  196. { // (need to freeze...)
  197. fcChip->FreezeTachyon( fcChip, 2); // both ERQ and FCP assists
  198. // 2. Get Tach freeze confirmation
  199. // (synchronize SEST manipulation with Freeze Completion Message)
  200. // we need INTs on so semaphore can be set.
  201. enable_irq( cpqfcHBAdata->HostAdapter->irq); // only way to get Semaphore
  202. down_interruptible( cpqfcHBAdata->TachFrozen); // wait for INT handler sem.
  203. // can we TIMEOUT semaphore wait?? TBD
  204. disable_irq( cpqfcHBAdata->HostAdapter->irq);
  205. FrozeTach = TRUE;
  206. } // (else, already frozen)
  207. return FrozeTach;
  208. }
  209. // This is the kernel worker thread task, which processes FC
  210. // tasks which were queued by the Interrupt handler or by
  211. // other WorkTask functions.
  212. #define DBG 1
  213. //#undef DBG
  214. void cpqfcTS_WorkTask( struct Scsi_Host *HostAdapter)
  215. {
  216. CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  217. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  218. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  219. ULONG QconsumerNdx;
  220. LONG ExchangeID;
  221. ULONG ulStatus=0;
  222. TachFCHDR_GCMND fchs;
  223. PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
  224. ENTER("WorkTask");
  225. // copy current index to work on
  226. QconsumerNdx = fcLQ->consumer;
  227. PCI_TRACEO( fcLQ->Qitem[QconsumerNdx].Type, 0x90)
  228. // NOTE: when this switch completes, we will "consume" the Que item
  229. // printk("Que type %Xh\n", fcLQ->Qitem[QconsumerNdx].Type);
  230. switch( fcLQ->Qitem[QconsumerNdx].Type )
  231. {
  232. // incoming frame - link service (ACC, UNSOL REQ, etc.)
  233. // or FCP-SCSI command
  234. case SFQ_UNKNOWN:
  235. AnalyzeIncomingFrame( cpqfcHBAdata, QconsumerNdx );
  236. break;
  237. case EXCHANGE_QUEUED: // an Exchange (i.e. FCP-SCSI) was previously
  238. // Queued because the link was down. The
  239. // heartbeat timer detected it and Queued it here.
  240. // We attempt to start it again, and if
  241. // successful we clear the EXCHANGE_Q flag.
  242. // If the link doesn't come up, the Exchange
  243. // will eventually time-out.
  244. ExchangeID = (LONG) // x_ID copied from DPC timeout function
  245. fcLQ->Qitem[QconsumerNdx].ulBuff[0];
  246. // It's possible that a Q'd exchange could have already
  247. // been started by other logic (e.g. ABTS process)
  248. // Don't start if already started (Q'd flag clear)
  249. if( Exchanges->fcExchange[ExchangeID].status & EXCHANGE_QUEUED )
  250. {
  251. // printk(" *Start Q'd x_ID %Xh: type %Xh ",
  252. // ExchangeID, Exchanges->fcExchange[ExchangeID].type);
  253. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID);
  254. if( !ulStatus )
  255. {
  256. // printk("success* ");
  257. }
  258. else
  259. {
  260. #ifdef DBG
  261. if( ulStatus == EXCHANGE_QUEUED)
  262. printk("Queued* ");
  263. else
  264. printk("failed* ");
  265. #endif
  266. }
  267. }
  268. break;
  269. case LINKDOWN:
  270. // (lots of things already done in INT handler) future here?
  271. break;
  272. case LINKACTIVE: // Tachyon set the Lup bit in FM status
  273. // NOTE: some misbehaving FC ports (like Tach2.1)
  274. // can re-LIP immediately after a LIP completes.
  275. // if "initiator", need to verify LOGs with ports
  276. // printk("\n*LNKUP* ");
  277. if( fcChip->Options.initiator )
  278. SendLogins( cpqfcHBAdata, NULL ); // PLOGI or PDISC, based on fcPort data
  279. // if SendLogins successfully completes, PortDiscDone
  280. // will be set.
  281. // If SendLogins was successful, then we expect to get incoming
  282. // ACCepts or REJECTs, which are handled below.
  283. break;
  284. // LinkService and Fabric request/reply processing
  285. case ELS_FDISC: // need to send Fabric Discovery (Login)
  286. case ELS_FLOGI: // need to send Fabric Login
  287. case ELS_SCR: // need to send State Change Registration
  288. case FCS_NSR: // need to send Name Service Request
  289. case ELS_PLOGI: // need to send PLOGI
  290. case ELS_ACC: // send generic ACCept
  291. case ELS_PLOGI_ACC: // need to send ELS ACCept frame to recv'd PLOGI
  292. case ELS_PRLI_ACC: // need to send ELS ACCept frame to recv'd PRLI
  293. case ELS_LOGO: // need to send ELS LOGO (logout)
  294. case ELS_LOGO_ACC: // need to send ELS ACCept frame to recv'd PLOGI
  295. case ELS_RJT: // ReJecT reply
  296. case ELS_PRLI: // need to send ELS PRLI
  297. // printk(" *ELS %Xh* ", fcLQ->Qitem[QconsumerNdx].Type);
  298. // if PortDiscDone is not set, it means the SendLogins routine
  299. // failed to complete -- assume that LDn occurred, so login frames
  300. // are invalid
  301. if( !cpqfcHBAdata->PortDiscDone) // cleared by LDn
  302. {
  303. printk("Discard Q'd ELS login frame\n");
  304. break;
  305. }
  306. ulStatus = cpqfcTSBuildExchange(
  307. cpqfcHBAdata,
  308. fcLQ->Qitem[QconsumerNdx].Type, // e.g. PLOGI
  309. (TachFCHDR_GCMND*)
  310. fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs
  311. NULL, // no data (no scatter/gather list)
  312. &ExchangeID );// fcController->fcExchanges index, -1 if failed
  313. if( !ulStatus ) // Exchange setup?
  314. {
  315. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
  316. if( !ulStatus )
  317. {
  318. // submitted to Tach's Outbound Que (ERQ PI incremented)
  319. // waited for completion for ELS type (Login frames issued
  320. // synchronously)
  321. }
  322. else
  323. // check reason for Exchange not being started - we might
  324. // want to Queue and start later, or fail with error
  325. {
  326. }
  327. }
  328. else // Xchange setup failed...
  329. printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus );
  330. break;
  331. case SCSI_REPORT_LUNS:
  332. // pass the incoming frame (actually, it's a PRLI frame)
  333. // so we can send REPORT_LUNS, in order to determine VSA/PDU
  334. // FCP-SCSI Lun address mode
  335. IssueReportLunsCommand( cpqfcHBAdata, (TachFCHDR_GCMND*)
  336. fcLQ->Qitem[QconsumerNdx].ulBuff);
  337. break;
  338. case BLS_ABTS: // need to ABORT one or more exchanges
  339. {
  340. LONG x_ID = fcLQ->Qitem[QconsumerNdx].ulBuff[0];
  341. BOOLEAN FrozeTach = FALSE;
  342. if ( x_ID >= TACH_SEST_LEN ) // (in)sanity check
  343. {
  344. // printk( " cpqfcTS ERROR! BOGUS x_ID %Xh", x_ID);
  345. break;
  346. }
  347. if( Exchanges->fcExchange[ x_ID].Cmnd == NULL ) // should be RARE
  348. {
  349. // printk(" ABTS %Xh Scsi Cmnd null! ", x_ID);
  350. break; // nothing to abort!
  351. }
  352. //#define ABTS_DBG
  353. #ifdef ABTS_DBG
  354. printk("INV SEST[%X] ", x_ID);
  355. if( Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT)
  356. {
  357. printk("FC2TO");
  358. }
  359. if( Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)
  360. {
  361. printk("IA");
  362. }
  363. if( Exchanges->fcExchange[x_ID].status & PORTID_CHANGED)
  364. {
  365. printk("PORTID");
  366. }
  367. if( Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)
  368. {
  369. printk("DEVRM");
  370. }
  371. if( Exchanges->fcExchange[x_ID].status & LINKFAIL_TX)
  372. {
  373. printk("LKF");
  374. }
  375. if( Exchanges->fcExchange[x_ID].status & FRAME_TO)
  376. {
  377. printk("FRMTO");
  378. }
  379. if( Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY)
  380. {
  381. printk("ABSQ");
  382. }
  383. if( Exchanges->fcExchange[x_ID].status & SFQ_FRAME)
  384. {
  385. printk("SFQFR");
  386. }
  387. if( Exchanges->fcExchange[ x_ID].type == 0x2000)
  388. printk(" WR");
  389. else if( Exchanges->fcExchange[ x_ID].type == 0x3000)
  390. printk(" RD");
  391. else if( Exchanges->fcExchange[ x_ID].type == 0x10)
  392. printk(" ABTS");
  393. else
  394. printk(" %Xh", Exchanges->fcExchange[ x_ID].type);
  395. if( !(Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT))
  396. {
  397. printk(" Cmd %p, ",
  398. Exchanges->fcExchange[ x_ID].Cmnd);
  399. printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n",
  400. cpqfcHBAdata->HBAnum,
  401. Exchanges->fcExchange[ x_ID].Cmnd->channel,
  402. Exchanges->fcExchange[ x_ID].Cmnd->target,
  403. Exchanges->fcExchange[ x_ID].Cmnd->lun,
  404. Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF);
  405. }
  406. else // assume that Cmnd ptr is invalid on _abort()
  407. {
  408. printk(" Cmd ptr invalid\n");
  409. }
  410. #endif
  411. // Steps to ABORT a SEST exchange:
  412. // 1. Freeze TL SCSI assists & ERQ (everything)
  413. // 2. Receive FROZEN inbound CM (must succeed!)
  414. // 3. Invalidate x_ID SEST entry
  415. // 4. Resume TL SCSI assists & ERQ (everything)
  416. // 5. Build/start on exchange - change "type" to BLS_ABTS,
  417. // timeout to X sec (RA_TOV from PLDA is actually 0)
  418. // 6. Set Exchange Q'd status if ABTS cannot be started,
  419. // or simply complete Exchange in "Terminate" condition
  420. PCI_TRACEO( x_ID, 0xB4)
  421. // 1 & 2 . Freeze Tach & get confirmation of freeze
  422. FrozeTach = FreezeTach( cpqfcHBAdata);
  423. // 3. OK, Tachyon is frozen, so we can invalidate SEST exchange.
  424. // FC2_TIMEOUT means we are originating the abort, while
  425. // TARGET_ABORT means we are ACCepting an abort.
  426. // LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are
  427. // all from Tachyon:
  428. // Exchange was corrupted by LDn or other FC physical failure
  429. // INITIATOR_ABORT means the upper layer driver/application
  430. // requested the abort.
  431. // clear bit 31 (VALid), to invalidate & take control from TL
  432. fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;
  433. // examine and Tach's "Linked List" for IWEs that
  434. // received (nearly) simultaneous transfer ready (XRDY)
  435. // repair linked list if necessary (TBD!)
  436. // (If we ignore the "Linked List", we will time out
  437. // WRITE commands where we received the FCP-SCSI XFRDY
  438. // frame (because Tachyon didn't processes it). Linked List
  439. // management should be done as an optimization.
  440. // readl( fcChip->Registers.ReMapMemBase+TL_MEM_SEST_LINKED_LIST ));
  441. // 4. Resume all Tachlite functions (for other open Exchanges)
  442. // as quickly as possible to allow other exchanges to other ports
  443. // to resume. Freezing Tachyon may cause cascading errors, because
  444. // any received SEST frame cannot be processed by the SEST.
  445. // Don't "unfreeze" unless Link is operational
  446. if( FrozeTach ) // did we just freeze it (above)?
  447. fcChip->UnFreezeTachyon( fcChip, 2); // both ERQ and FCP assists
  448. PCI_TRACEO( x_ID, 0xB4)
  449. // Note there is no confirmation that the chip is "unfrozen". Also,
  450. // if the Link is down when unfreeze is called, it has no effect.
  451. // Chip will unfreeze when the Link is back up.
  452. // 5. Now send out Abort commands if possible
  453. // Some Aborts can't be "sent" (Port_id changed or gone);
  454. // if the device is gone, there is no port_id to send the ABTS to.
  455. if( !(Exchanges->fcExchange[ x_ID].status & PORTID_CHANGED)
  456. &&
  457. !(Exchanges->fcExchange[ x_ID].status & DEVICE_REMOVED) )
  458. {
  459. Exchanges->fcExchange[ x_ID].type = BLS_ABTS;
  460. fchs.s_id = Exchanges->fcExchange[ x_ID].fchs.d_id;
  461. ulStatus = cpqfcTSBuildExchange(
  462. cpqfcHBAdata,
  463. BLS_ABTS,
  464. &fchs, // (uses only s_id)
  465. NULL, // (no scatter/gather list for ABTS)
  466. &x_ID );// ABTS on this Exchange ID
  467. if( !ulStatus ) // Exchange setup build OK?
  468. {
  469. // ABTS may be needed because an Exchange was corrupted
  470. // by a Link disruption. If the Link is UP, we can
  471. // presume that this ABTS can start immediately; otherwise,
  472. // set Que'd status so the Login functions
  473. // can restart it when the FC physical Link is restored
  474. if( ((fcChip->Registers.FMstatus.value &0xF0) &0x80)) // loop init?
  475. {
  476. // printk(" *set Q status x_ID %Xh on LDn* ", x_ID);
  477. Exchanges->fcExchange[ x_ID].status |= EXCHANGE_QUEUED;
  478. }
  479. else // what FC device (port_id) does the Cmd belong to?
  480. {
  481. PFC_LOGGEDIN_PORT pLoggedInPort =
  482. Exchanges->fcExchange[ x_ID].pLoggedInPort;
  483. // if Port is logged in, we might start the abort.
  484. if( (pLoggedInPort != NULL)
  485. &&
  486. (pLoggedInPort->prli == TRUE) )
  487. {
  488. // it's possible that an Exchange has already been Queued
  489. // to start after Login completes. Check and don't
  490. // start it (again) here if Q'd status set
  491. // printk(" ABTS xchg %Xh ", x_ID);
  492. if( Exchanges->fcExchange[x_ID].status & EXCHANGE_QUEUED)
  493. {
  494. // printk("already Q'd ");
  495. }
  496. else
  497. {
  498. // printk("starting ");
  499. fcChip->fcStats.FC2aborted++;
  500. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, x_ID );
  501. if( !ulStatus )
  502. {
  503. // OK
  504. // submitted to Tach's Outbound Que (ERQ PI incremented)
  505. }
  506. else
  507. {
  508. /* printk("ABTS exchange start failed -status %Xh, x_ID %Xh ",
  509. ulStatus, x_ID);
  510. */
  511. }
  512. }
  513. }
  514. else
  515. {
  516. /* printk(" ABTS NOT starting xchg %Xh, %p ",
  517. x_ID, pLoggedInPort);
  518. if( pLoggedInPort )
  519. printk("prli %d ", pLoggedInPort->prli);
  520. */
  521. }
  522. }
  523. }
  524. else // what the #@!
  525. { // how do we fail to build an Exchange for ABTS??
  526. printk("ABTS exchange build failed -status %Xh, x_ID %Xh\n",
  527. ulStatus, x_ID);
  528. }
  529. }
  530. else // abort without ABTS -- just complete exchange/Cmnd to Linux
  531. {
  532. // printk(" *Terminating x_ID %Xh on %Xh* ",
  533. // x_ID, Exchanges->fcExchange[x_ID].status);
  534. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, x_ID);
  535. }
  536. } // end of ABTS case
  537. break;
  538. case BLS_ABTS_ACC: // need to ACCept one ABTS
  539. // (NOTE! this code not updated for Linux yet..)
  540. printk(" *ABTS_ACC* ");
  541. // 1. Freeze TL
  542. fcChip->FreezeTachyon( fcChip, 2); // both ERQ and FCP assists
  543. memcpy( // copy the incoming ABTS frame
  544. &fchs,
  545. fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs
  546. sizeof( fchs));
  547. // 3. OK, Tachyon is frozen so we can invalidate SEST entry
  548. // (if necessary)
  549. // Status FC2_TIMEOUT means we are originating the abort, while
  550. // TARGET_ABORT means we are ACCepting an abort
  551. ExchangeID = fchs.ox_rx_id & 0x7FFF; // RX_ID for exchange
  552. // printk("ABTS ACC for Target ExchangeID %Xh\n", ExchangeID);
  553. // sanity check on received ExchangeID
  554. if( Exchanges->fcExchange[ ExchangeID].status == TARGET_ABORT )
  555. {
  556. // clear bit 31 (VALid), to invalidate & take control from TL
  557. // printk("Invalidating SEST exchange %Xh\n", ExchangeID);
  558. fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len &= 0x7FFFFFFF;
  559. }
  560. // 4. Resume all Tachlite functions (for other open Exchanges)
  561. // as quickly as possible to allow other exchanges to other ports
  562. // to resume. Freezing Tachyon for too long may royally screw
  563. // up everything!
  564. fcChip->UnFreezeTachyon( fcChip, 2); // both ERQ and FCP assists
  565. // Note there is no confirmation that the chip is "unfrozen". Also,
  566. // if the Link is down when unfreeze is called, it has no effect.
  567. // Chip will unfreeze when the Link is back up.
  568. // 5. Now send out Abort ACC reply for this exchange
  569. Exchanges->fcExchange[ ExchangeID].type = BLS_ABTS_ACC;
  570. fchs.s_id = Exchanges->fcExchange[ ExchangeID].fchs.d_id;
  571. ulStatus = cpqfcTSBuildExchange(
  572. cpqfcHBAdata,
  573. BLS_ABTS_ACC,
  574. &fchs,
  575. NULL, // no data (no scatter/gather list)
  576. &ExchangeID );// fcController->fcExchanges index, -1 if failed
  577. if( !ulStatus ) // Exchange setup?
  578. {
  579. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
  580. if( !ulStatus )
  581. {
  582. // submitted to Tach's Outbound Que (ERQ PI incremented)
  583. // waited for completion for ELS type (Login frames issued
  584. // synchronously)
  585. }
  586. else
  587. // check reason for Exchange not being started - we might
  588. // want to Queue and start later, or fail with error
  589. {
  590. }
  591. }
  592. break;
  593. case BLS_ABTS_RJT: // need to ReJecT one ABTS; reject implies the
  594. // exchange doesn't exist in the TARGET context.
  595. // ExchangeID has to come from LinkService space.
  596. printk(" *ABTS_RJT* ");
  597. ulStatus = cpqfcTSBuildExchange(
  598. cpqfcHBAdata,
  599. BLS_ABTS_RJT,
  600. (TachFCHDR_GCMND*)
  601. fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs
  602. NULL, // no data (no scatter/gather list)
  603. &ExchangeID );// fcController->fcExchanges index, -1 if failed
  604. if( !ulStatus ) // Exchange setup OK?
  605. {
  606. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
  607. // If it fails, we aren't required to retry.
  608. }
  609. if( ulStatus )
  610. {
  611. printk("Failed to send BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
  612. }
  613. else
  614. {
  615. printk("Sent BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
  616. }
  617. break;
  618. default:
  619. break;
  620. } // end switch
  621. //doNothing:
  622. // done with this item - now set the NEXT index
  623. if( QconsumerNdx+1 >= FC_LINKQ_DEPTH ) // rollover test
  624. {
  625. fcLQ->consumer = 0;
  626. }
  627. else
  628. {
  629. fcLQ->consumer++;
  630. }
  631. PCI_TRACEO( fcLQ->Qitem[QconsumerNdx].Type, 0x94)
  632. LEAVE("WorkTask");
  633. return;
  634. }
  635. // When Tachyon reports link down, bad al_pa, or Link Service (e.g. Login)
  636. // commands come in, post to the LinkQ so that action can be taken outside the
  637. // interrupt handler.
  638. // This circular Q works like Tachyon's que - the producer points to the next
  639. // (unused) entry. Called by Interrupt handler, WorkerThread, Timer
  640. // sputlinkq
  641. void cpqfcTSPutLinkQue( CPQFCHBA *cpqfcHBAdata,
  642. int Type,
  643. void *QueContent)
  644. {
  645. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  646. // FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  647. PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
  648. ULONG ndx;
  649. ENTER("cpqfcTSPutLinkQ");
  650. ndx = fcLQ->producer;
  651. ndx += 1; // test for Que full
  652. if( ndx >= FC_LINKQ_DEPTH ) // rollover test
  653. ndx = 0;
  654. if( ndx == fcLQ->consumer ) // QUE full test
  655. {
  656. // QUE was full! lost LK command (fatal to logic)
  657. fcChip->fcStats.lnkQueFull++;
  658. printk("*LinkQ Full!*");
  659. TriggerHBA( fcChip->Registers.ReMapMemBase, 1);
  660. /*
  661. {
  662. int i;
  663. printk("LinkQ PI %d, CI %d\n", fcLQ->producer,
  664. fcLQ->consumer);
  665. for( i=0; i< FC_LINKQ_DEPTH; )
  666. {
  667. printk(" [%d]%Xh ", i, fcLQ->Qitem[i].Type);
  668. if( (++i %8) == 0) printk("\n");
  669. }
  670. }
  671. */
  672. printk( "cpqfcTS: WARNING!! PutLinkQue - FULL!\n"); // we're hung
  673. }
  674. else // QUE next element
  675. {
  676. // Prevent certain multiple (back-to-back) requests.
  677. // This is important in that we don't want to issue multiple
  678. // ABTS for the same Exchange, or do multiple FM inits, etc.
  679. // We can never be sure of the timing of events reported to
  680. // us by Tach's IMQ, which can depend on system/bus speeds,
  681. // FC physical link circumstances, etc.
  682. if( (fcLQ->producer != fcLQ->consumer)
  683. &&
  684. (Type == FMINIT) )
  685. {
  686. LONG lastNdx; // compute previous producer index
  687. if( fcLQ->producer)
  688. lastNdx = fcLQ->producer- 1;
  689. else
  690. lastNdx = FC_LINKQ_DEPTH-1;
  691. if( fcLQ->Qitem[lastNdx].Type == FMINIT)
  692. {
  693. // printk(" *skip FMINIT Q post* ");
  694. // goto DoneWithPutQ;
  695. }
  696. }
  697. // OK, add the Q'd item...
  698. fcLQ->Qitem[fcLQ->producer].Type = Type;
  699. memcpy(
  700. fcLQ->Qitem[fcLQ->producer].ulBuff,
  701. QueContent,
  702. sizeof(fcLQ->Qitem[fcLQ->producer].ulBuff));
  703. fcLQ->producer = ndx; // increment Que producer
  704. // set semaphore to wake up Kernel (worker) thread
  705. //
  706. up( cpqfcHBAdata->fcQueReady );
  707. }
  708. //DoneWithPutQ:
  709. LEAVE("cpqfcTSPutLinkQ");
  710. }
  711. // reset device ext FC link Q
  712. void cpqfcTSLinkQReset( CPQFCHBA *cpqfcHBAdata)
  713. {
  714. PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
  715. fcLQ->producer = 0;
  716. fcLQ->consumer = 0;
  717. }
  718. // When Tachyon gets an unassisted FCP-SCSI frame, post here so
  719. // an arbitrary context thread (e.g. IOCTL loopback test function)
  720. // can process it.
  721. // (NOTE: Not revised for Linux)
  722. // This Q works like Tachyon's que - the producer points to the next
  723. // (unused) entry.
  724. void cpqfcTSPutScsiQue( CPQFCHBA *cpqfcHBAdata,
  725. int Type,
  726. void *QueContent)
  727. {
  728. // CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  729. // PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  730. // ULONG ndx;
  731. // ULONG *pExchangeID;
  732. // LONG ExchangeID;
  733. /*
  734. KeAcquireSpinLockAtDpcLevel( &pDevExt->fcScsiQueLock);
  735. ndx = pDevExt->fcScsiQue.producer + 1; // test for Que full
  736. if( ndx >= FC_SCSIQ_DEPTH ) // rollover test
  737. ndx = 0;
  738. if( ndx == pDevExt->fcScsiQue.consumer ) // QUE full test
  739. {
  740. // QUE was full! lost LK command (fatal to logic)
  741. fcChip->fcStats.ScsiQueFull++;
  742. #ifdef DBG
  743. printk( "fcPutScsiQue - FULL!\n");
  744. #endif
  745. }
  746. else // QUE next element
  747. {
  748. pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].Type = Type;
  749. if( Type == FCP_RSP )
  750. {
  751. // this TL inbound message type means that a TL SEST exchange has
  752. // copied an FCP response frame into a buffer pointed to by the SEST
  753. // entry. That buffer is allocated in the SEST structure at ->RspHDR.
  754. // Copy the RspHDR for use by the Que handler.
  755. pExchangeID = (ULONG *)QueContent;
  756. memcpy(
  757. pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff,
  758. &fcChip->SEST->RspHDR[ *pExchangeID ],
  759. sizeof(pDevExt->fcScsiQue.Qitem[0].ulBuff)); // (any element for size)
  760. }
  761. else
  762. {
  763. memcpy(
  764. pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff,
  765. QueContent,
  766. sizeof(pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff));
  767. }
  768. pDevExt->fcScsiQue.producer = ndx; // increment Que
  769. KeSetEvent( &pDevExt->TYIBscsi, // signal any waiting thread
  770. 0, // no priority boost
  771. FALSE ); // no waiting later for this event
  772. }
  773. KeReleaseSpinLockFromDpcLevel( &pDevExt->fcScsiQueLock);
  774. */
  775. }
  776. static void ProcessELS_Request( CPQFCHBA*,TachFCHDR_GCMND*);
  777. static void ProcessELS_Reply( CPQFCHBA*,TachFCHDR_GCMND*);
  778. static void ProcessFCS_Reply( CPQFCHBA*,TachFCHDR_GCMND*);
  779. void cpqfcTSImplicitLogout( CPQFCHBA* cpqfcHBAdata,
  780. PFC_LOGGEDIN_PORT pFcPort)
  781. {
  782. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  783. if( pFcPort->port_id != 0xFFFC01 ) // don't care about Fabric
  784. {
  785. fcChip->fcStats.logouts++;
  786. printk("cpqfcTS: Implicit logout of WWN %08X%08X, port_id %06X\n",
  787. (ULONG)pFcPort->u.liWWN,
  788. (ULONG)(pFcPort->u.liWWN >>32),
  789. pFcPort->port_id);
  790. // Terminate I/O with this (Linux) Scsi target
  791. cpqfcTSTerminateExchange( cpqfcHBAdata,
  792. &pFcPort->ScsiNexus,
  793. DEVICE_REMOVED);
  794. }
  795. // Do an "implicit logout" - we can't really Logout the device
  796. // (i.e. with LOGOut Request) because of port_id confusion
  797. // (i.e. the Other port has no port_id).
  798. // A new login for that WWN will have to re-write port_id (0 invalid)
  799. pFcPort->port_id = 0; // invalid!
  800. pFcPort->pdisc = FALSE;
  801. pFcPort->prli = FALSE;
  802. pFcPort->plogi = FALSE;
  803. pFcPort->flogi = FALSE;
  804. pFcPort->LOGO_timer = 0;
  805. pFcPort->device_blocked = TRUE; // block Scsi Requests
  806. pFcPort->ScsiNexus.VolumeSetAddressing=0;
  807. }
  808. // On FC-AL, there is a chance that a previously known device can
  809. // be quietly removed (e.g. with non-managed hub),
  810. // while a NEW device (with different WWN) took the same alpa or
  811. // even 24-bit port_id. This chance is unlikely but we must always
  812. // check for it.
  813. static void TestDuplicatePortId( CPQFCHBA* cpqfcHBAdata,
  814. PFC_LOGGEDIN_PORT pLoggedInPort)
  815. {
  816. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  817. // set "other port" at beginning of fcPorts list
  818. PFC_LOGGEDIN_PORT pOtherPortWithPortId = fcChip->fcPorts.pNextPort;
  819. while( pOtherPortWithPortId )
  820. {
  821. if( (pOtherPortWithPortId->port_id ==
  822. pLoggedInPort->port_id)
  823. &&
  824. (pOtherPortWithPortId != pLoggedInPort) )
  825. {
  826. // trouble! (Implicitly) Log the other guy out
  827. printk(" *port_id %Xh is duplicated!* ",
  828. pOtherPortWithPortId->port_id);
  829. cpqfcTSImplicitLogout( cpqfcHBAdata, pOtherPortWithPortId);
  830. }
  831. pOtherPortWithPortId = pOtherPortWithPortId->pNextPort;
  832. }
  833. }
  834. // Dynamic Memory Allocation for newly discovered FC Ports.
  835. // For simplicity, maintain fcPorts structs for ALL
  836. // for discovered devices, including those we never do I/O with
  837. // (e.g. Fabric addresses)
  838. static PFC_LOGGEDIN_PORT CreateFcPort(
  839. CPQFCHBA* cpqfcHBAdata,
  840. PFC_LOGGEDIN_PORT pLastLoggedInPort,
  841. TachFCHDR_GCMND* fchs,
  842. LOGIN_PAYLOAD* plogi)
  843. {
  844. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  845. PFC_LOGGEDIN_PORT pNextLoggedInPort = NULL;
  846. int i;
  847. printk("cpqfcTS: New FC port %06Xh WWN: ", fchs->s_id);
  848. for( i=3; i>=0; i--) // copy the LOGIN port's WWN
  849. printk("%02X", plogi->port_name[i]);
  850. for( i=7; i>3; i--) // copy the LOGIN port's WWN
  851. printk("%02X", plogi->port_name[i]);
  852. // allocate mem for new port
  853. // (these are small and rare allocations...)
  854. pNextLoggedInPort = kmalloc( sizeof( FC_LOGGEDIN_PORT), GFP_ATOMIC );
  855. // allocation succeeded? Fill out NEW PORT
  856. if( pNextLoggedInPort )
  857. {
  858. // clear out any garbage (sometimes exists)
  859. memset( pNextLoggedInPort, 0, sizeof( FC_LOGGEDIN_PORT));
  860. // If we login to a Fabric, we don't want to treat it
  861. // as a SCSI device...
  862. if( (fchs->s_id & 0xFFF000) != 0xFFF000)
  863. {
  864. int i;
  865. // create a unique "virtual" SCSI Nexus (for now, just a
  866. // new target ID) -- we will update channel/target on REPORT_LUNS
  867. // special case for very first SCSI target...
  868. if( cpqfcHBAdata->HostAdapter->max_id == 0)
  869. {
  870. pNextLoggedInPort->ScsiNexus.target = 0;
  871. fcChip->fcPorts.ScsiNexus.target = -1; // don't use "stub"
  872. }
  873. else
  874. {
  875. pNextLoggedInPort->ScsiNexus.target =
  876. cpqfcHBAdata->HostAdapter->max_id;
  877. }
  878. // initialize the lun[] Nexus struct for lun masking
  879. for( i=0; i< CPQFCTS_MAX_LUN; i++)
  880. pNextLoggedInPort->ScsiNexus.lun[i] = 0xFF; // init to NOT USED
  881. pNextLoggedInPort->ScsiNexus.channel = 0; // cpqfcTS has 1 FC port
  882. printk(" SCSI Chan/Trgt %d/%d",
  883. pNextLoggedInPort->ScsiNexus.channel,
  884. pNextLoggedInPort->ScsiNexus.target);
  885. // tell Scsi layers about the new target...
  886. cpqfcHBAdata->HostAdapter->max_id++;
  887. // printk("HostAdapter->max_id = %d\n",
  888. // cpqfcHBAdata->HostAdapter->max_id);
  889. }
  890. else
  891. {
  892. // device is NOT SCSI (in case of Fabric)
  893. pNextLoggedInPort->ScsiNexus.target = -1; // invalid
  894. }
  895. // create forward link to new port
  896. pLastLoggedInPort->pNextPort = pNextLoggedInPort;
  897. printk("\n");
  898. }
  899. return pNextLoggedInPort; // NULL on allocation failure
  900. } // end NEW PORT (WWN) logic
  901. // For certain cases, we want to terminate exchanges without
  902. // sending ABTS to the device. Examples include when an FC
  903. // device changed it's port_id after Loop re-init, or when
  904. // the device sent us a logout. In the case of changed port_id,
  905. // we want to complete the command and return SOFT_ERROR to
  906. // force a re-try. In the case of LOGOut, we might return
  907. // BAD_TARGET if the device is really gone.
  908. // Since we must ensure that Tachyon is not operating on the
  909. // exchange, we have to freeze the chip
  910. // sterminateex
  911. void cpqfcTSTerminateExchange(
  912. CPQFCHBA* cpqfcHBAdata, SCSI_NEXUS *ScsiNexus, int TerminateStatus)
  913. {
  914. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  915. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  916. ULONG x_ID;
  917. if( ScsiNexus )
  918. {
  919. // printk("TerminateExchange: ScsiNexus chan/target %d/%d\n",
  920. // ScsiNexus->channel, ScsiNexus->target);
  921. }
  922. for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
  923. {
  924. if( Exchanges->fcExchange[x_ID].type ) // in use?
  925. {
  926. if( ScsiNexus == NULL ) // our HBA changed - term. all
  927. {
  928. Exchanges->fcExchange[x_ID].status = TerminateStatus;
  929. cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID );
  930. }
  931. else
  932. {
  933. // If a device, according to WWN, has been removed, it's
  934. // port_id may be used by another working device, so we
  935. // have to terminate by SCSI target, NOT port_id.
  936. if( Exchanges->fcExchange[x_ID].Cmnd) // Cmnd in progress?
  937. {
  938. if( (Exchanges->fcExchange[x_ID].Cmnd->device->id == ScsiNexus->target)
  939. &&
  940. (Exchanges->fcExchange[x_ID].Cmnd->device->channel == ScsiNexus->channel))
  941. {
  942. Exchanges->fcExchange[x_ID].status = TerminateStatus;
  943. cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID ); // timed-out
  944. }
  945. }
  946. // (in case we ever need it...)
  947. // all SEST structures have a remote node ID at SEST DWORD 2
  948. // if( (fcChip->SEST->u[ x_ID ].TWE.Remote_Node_ID >> 8)
  949. // == port_id)
  950. }
  951. }
  952. }
  953. }
  954. static void ProcessELS_Request(
  955. CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs)
  956. {
  957. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  958. // FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  959. // ULONG ox_id = (fchs->ox_rx_id >>16);
  960. PFC_LOGGEDIN_PORT pLoggedInPort=NULL, pLastLoggedInPort;
  961. BOOLEAN NeedReject = FALSE;
  962. ULONG ls_reject_code = 0; // default don'n know??
  963. // Check the incoming frame for a supported ELS type
  964. switch( fchs->pl[0] & 0xFFFF)
  965. {
  966. case 0x0050: // PDISC?
  967. // Payload for PLOGI and PDISC is identical (request & reply)
  968. if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) // valid payload?
  969. {
  970. LOGIN_PAYLOAD logi; // FC-PH Port Login
  971. // PDISC payload OK. If critical login fields
  972. // (e.g. WWN) matches last login for this port_id,
  973. // we may resume any prior exchanges
  974. // with the other port
  975. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
  976. pLoggedInPort = fcFindLoggedInPort(
  977. fcChip,
  978. NULL, // don't search Scsi Nexus
  979. 0, // don't search linked list for port_id
  980. &logi.port_name[0], // search linked list for WWN
  981. &pLastLoggedInPort); // must return non-NULL; when a port_id
  982. // is not found, this pointer marks the
  983. // end of the singly linked list
  984. if( pLoggedInPort != NULL) // WWN found (prior login OK)
  985. {
  986. if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id)
  987. {
  988. // Yes. We were expecting PDISC?
  989. if( pLoggedInPort->pdisc )
  990. {
  991. // Yes; set fields accordingly. (PDISC, not Originator)
  992. SetLoginFields( pLoggedInPort, fchs, TRUE, FALSE);
  993. // send 'ACC' reply
  994. cpqfcTSPutLinkQue( cpqfcHBAdata,
  995. ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC)
  996. fchs );
  997. // OK to resume I/O...
  998. }
  999. else
  1000. {
  1001. printk("Not expecting PDISC (pdisc=FALSE)\n");
  1002. NeedReject = TRUE;
  1003. // set reject reason code
  1004. ls_reject_code =
  1005. LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
  1006. }
  1007. }
  1008. else
  1009. {
  1010. if( pLoggedInPort->port_id != 0)
  1011. {
  1012. printk("PDISC PortID change: old %Xh, new %Xh\n",
  1013. pLoggedInPort->port_id, fchs->s_id &0xFFFFFF);
  1014. }
  1015. NeedReject = TRUE;
  1016. // set reject reason code
  1017. ls_reject_code =
  1018. LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
  1019. }
  1020. }
  1021. else
  1022. {
  1023. printk("PDISC Request from unknown WWN\n");
  1024. NeedReject = TRUE;
  1025. // set reject reason code
  1026. ls_reject_code =
  1027. LS_RJT_REASON( LOGICAL_ERROR, INVALID_PORT_NAME);
  1028. }
  1029. }
  1030. else // Payload unacceptable
  1031. {
  1032. printk("payload unacceptable\n");
  1033. NeedReject = TRUE; // reject code already set
  1034. }
  1035. if( NeedReject)
  1036. {
  1037. ULONG port_id;
  1038. // The PDISC failed. Set login struct flags accordingly,
  1039. // terminate any I/O to this port, and Q a PLOGI
  1040. if( pLoggedInPort )
  1041. {
  1042. pLoggedInPort->pdisc = FALSE;
  1043. pLoggedInPort->prli = FALSE;
  1044. pLoggedInPort->plogi = FALSE;
  1045. cpqfcTSTerminateExchange( cpqfcHBAdata,
  1046. &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
  1047. port_id = pLoggedInPort->port_id;
  1048. }
  1049. else
  1050. {
  1051. port_id = fchs->s_id &0xFFFFFF;
  1052. }
  1053. fchs->reserved = ls_reject_code; // borrow this (unused) field
  1054. cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_RJT, fchs );
  1055. }
  1056. break;
  1057. case 0x0003: // PLOGI?
  1058. // Payload for PLOGI and PDISC is identical (request & reply)
  1059. if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) // valid payload?
  1060. {
  1061. LOGIN_PAYLOAD logi; // FC-PH Port Login
  1062. BOOLEAN NeedReject = FALSE;
  1063. // PDISC payload OK. If critical login fields
  1064. // (e.g. WWN) matches last login for this port_id,
  1065. // we may resume any prior exchanges
  1066. // with the other port
  1067. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
  1068. pLoggedInPort = fcFindLoggedInPort(
  1069. fcChip,
  1070. NULL, // don't search Scsi Nexus
  1071. 0, // don't search linked list for port_id
  1072. &logi.port_name[0], // search linked list for WWN
  1073. &pLastLoggedInPort); // must return non-NULL; when a port_id
  1074. // is not found, this pointer marks the
  1075. // end of the singly linked list
  1076. if( pLoggedInPort == NULL) // WWN not found -New Port
  1077. {
  1078. pLoggedInPort = CreateFcPort(
  1079. cpqfcHBAdata,
  1080. pLastLoggedInPort,
  1081. fchs,
  1082. &logi);
  1083. if( pLoggedInPort == NULL )
  1084. {
  1085. printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
  1086. // Now Q a LOGOut Request, since we won't be talking to that device
  1087. NeedReject = TRUE;
  1088. // set reject reason code
  1089. ls_reject_code =
  1090. LS_RJT_REASON( LOGICAL_ERROR, NO_LOGIN_RESOURCES);
  1091. }
  1092. }
  1093. if( !NeedReject )
  1094. {
  1095. // OK - we have valid fcPort ptr; set fields accordingly.
  1096. // (not PDISC, not Originator)
  1097. SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);
  1098. // send 'ACC' reply
  1099. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1100. ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC)
  1101. fchs );
  1102. }
  1103. }
  1104. else // Payload unacceptable
  1105. {
  1106. printk("payload unacceptable\n");
  1107. NeedReject = TRUE; // reject code already set
  1108. }
  1109. if( NeedReject)
  1110. {
  1111. // The PDISC failed. Set login struct flags accordingly,
  1112. // terminate any I/O to this port, and Q a PLOGI
  1113. pLoggedInPort->pdisc = FALSE;
  1114. pLoggedInPort->prli = FALSE;
  1115. pLoggedInPort->plogi = FALSE;
  1116. fchs->reserved = ls_reject_code; // borrow this (unused) field
  1117. // send 'RJT' reply
  1118. cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_RJT, fchs );
  1119. }
  1120. // terminate any exchanges with this device...
  1121. if( pLoggedInPort )
  1122. {
  1123. cpqfcTSTerminateExchange( cpqfcHBAdata,
  1124. &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
  1125. }
  1126. break;
  1127. case 0x1020: // PRLI?
  1128. {
  1129. BOOLEAN NeedReject = TRUE;
  1130. pLoggedInPort = fcFindLoggedInPort(
  1131. fcChip,
  1132. NULL, // don't search Scsi Nexus
  1133. (fchs->s_id & 0xFFFFFF), // search linked list for port_id
  1134. NULL, // DON'T search linked list for WWN
  1135. NULL); // don't care
  1136. if( pLoggedInPort == NULL )
  1137. {
  1138. // huh?
  1139. printk(" Unexpected PRLI Request -not logged in!\n");
  1140. // set reject reason code
  1141. ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
  1142. // Q a LOGOut here?
  1143. }
  1144. else
  1145. {
  1146. // verify the PRLI ACC payload
  1147. if( !verify_PRLI( fchs, &ls_reject_code) )
  1148. {
  1149. // PRLI Reply is acceptable; were we expecting it?
  1150. if( pLoggedInPort->plogi )
  1151. {
  1152. // yes, we expected the PRLI ACC (not PDISC; not Originator)
  1153. SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);
  1154. // Q an ACCept Reply
  1155. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1156. ELS_PRLI_ACC,
  1157. fchs );
  1158. NeedReject = FALSE;
  1159. }
  1160. else
  1161. {
  1162. // huh?
  1163. printk(" (unexpected) PRLI REQEST with plogi FALSE\n");
  1164. // set reject reason code
  1165. ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
  1166. // Q a LOGOut here?
  1167. }
  1168. }
  1169. else
  1170. {
  1171. printk(" PRLI REQUEST payload failed verify\n");
  1172. // (reject code set by "verify")
  1173. // Q a LOGOut here?
  1174. }
  1175. }
  1176. if( NeedReject )
  1177. {
  1178. // Q a ReJecT Reply with reason code
  1179. fchs->reserved = ls_reject_code;
  1180. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1181. ELS_RJT, // Q Type
  1182. fchs );
  1183. }
  1184. }
  1185. break;
  1186. case 0x0005: // LOGOut?
  1187. {
  1188. // was this LOGOUT because we sent a ELS_PDISC to an FC device
  1189. // with changed (or new) port_id, or does the port refuse
  1190. // to communicate to us?
  1191. // We maintain a logout counter - if we get 3 consecutive LOGOuts,
  1192. // give up!
  1193. LOGOUT_PAYLOAD logo;
  1194. BOOLEAN GiveUpOnDevice = FALSE;
  1195. ULONG ls_reject_code = 0;
  1196. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logo, sizeof(logo));
  1197. pLoggedInPort = fcFindLoggedInPort(
  1198. fcChip,
  1199. NULL, // don't search Scsi Nexus
  1200. 0, // don't search linked list for port_id
  1201. &logo.port_name[0], // search linked list for WWN
  1202. NULL); // don't care about end of list
  1203. if( pLoggedInPort ) // found the device?
  1204. {
  1205. // Q an ACC reply
  1206. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1207. ELS_LOGO_ACC, // Q Type
  1208. fchs ); // device to respond to
  1209. // set login struct fields (LOGO_counter increment)
  1210. SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);
  1211. // are we an Initiator?
  1212. if( fcChip->Options.initiator)
  1213. {
  1214. // we're an Initiator, so check if we should
  1215. // try (another?) login
  1216. // Fabrics routinely log out from us after
  1217. // getting device info - don't try to log them
  1218. // back in.
  1219. if( (fchs->s_id & 0xFFF000) == 0xFFF000 )
  1220. {
  1221. ; // do nothing
  1222. }
  1223. else if( pLoggedInPort->LOGO_counter <= 3)
  1224. {
  1225. // try (another) login (PLOGI request)
  1226. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1227. ELS_PLOGI, // Q Type
  1228. fchs );
  1229. // Terminate I/O with "retry" potential
  1230. cpqfcTSTerminateExchange( cpqfcHBAdata,
  1231. &pLoggedInPort->ScsiNexus,
  1232. PORTID_CHANGED);
  1233. }
  1234. else
  1235. {
  1236. printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n",
  1237. fchs->s_id &&0xFFFFFF);
  1238. GiveUpOnDevice = TRUE;
  1239. }
  1240. }
  1241. else
  1242. {
  1243. GiveUpOnDevice = TRUE;
  1244. }
  1245. if( GiveUpOnDevice == TRUE )
  1246. {
  1247. cpqfcTSTerminateExchange( cpqfcHBAdata,
  1248. &pLoggedInPort->ScsiNexus,
  1249. DEVICE_REMOVED);
  1250. }
  1251. }
  1252. else // we don't know this WWN!
  1253. {
  1254. // Q a ReJecT Reply with reason code
  1255. fchs->reserved = ls_reject_code;
  1256. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1257. ELS_RJT, // Q Type
  1258. fchs );
  1259. }
  1260. }
  1261. break;
  1262. // FABRIC only case
  1263. case 0x0461: // ELS RSCN (Registered State Change Notification)?
  1264. {
  1265. int Ports;
  1266. int i;
  1267. __u32 Buff;
  1268. // Typically, one or more devices have been added to or dropped
  1269. // from the Fabric.
  1270. // The format of this frame is defined in FC-FLA (Rev 2.7, Aug 1997)
  1271. // The first 32-bit word has a 2-byte Payload Length, which
  1272. // includes the 4 bytes of the first word. Consequently,
  1273. // this PL len must never be less than 4, must be a multiple of 4,
  1274. // and has a specified max value 256.
  1275. // (Endianess!)
  1276. Ports = ((fchs->pl[0] >>24) - 4) / 4;
  1277. Ports = Ports > 63 ? 63 : Ports;
  1278. printk(" RSCN ports: %d\n", Ports);
  1279. if( Ports <= 0 ) // huh?
  1280. {
  1281. // ReJecT the command
  1282. fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, 0);
  1283. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1284. ELS_RJT, // Q Type
  1285. fchs );
  1286. break;
  1287. }
  1288. else // Accept the command
  1289. {
  1290. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1291. ELS_ACC, // Q Type
  1292. fchs );
  1293. }
  1294. // Check the "address format" to determine action.
  1295. // We have 3 cases:
  1296. // 0 = Port Address; 24-bit address of affected device
  1297. // 1 = Area Address; MS 16 bits valid
  1298. // 2 = Domain Address; MS 8 bits valid
  1299. for( i=0; i<Ports; i++)
  1300. {
  1301. BigEndianSwap( (UCHAR*)&fchs->pl[i+1],(UCHAR*)&Buff, 4);
  1302. switch( Buff & 0xFF000000)
  1303. {
  1304. case 0: // Port Address?
  1305. case 0x01000000: // Area Domain?
  1306. case 0x02000000: // Domain Address
  1307. // For example, "port_id" 0x201300
  1308. // OK, let's try a Name Service Request (Query)
  1309. fchs->s_id = 0xFFFFFC; // Name Server Address
  1310. cpqfcTSPutLinkQue( cpqfcHBAdata, FCS_NSR, fchs);
  1311. break;
  1312. default: // huh? new value on version change?
  1313. break;
  1314. }
  1315. }
  1316. }
  1317. break;
  1318. default: // don't support this request (yet)
  1319. // set reject reason code
  1320. fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM,
  1321. REQUEST_NOT_SUPPORTED);
  1322. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1323. ELS_RJT, // Q Type
  1324. fchs );
  1325. break;
  1326. }
  1327. }
  1328. static void ProcessELS_Reply(
  1329. CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs)
  1330. {
  1331. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  1332. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  1333. ULONG ox_id = (fchs->ox_rx_id >>16);
  1334. ULONG ls_reject_code;
  1335. PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
  1336. // If this is a valid reply, then we MUST have sent a request.
  1337. // Verify that we can find a valid request OX_ID corresponding to
  1338. // this reply
  1339. if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0)
  1340. {
  1341. printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ",
  1342. ox_id, fchs->ox_rx_id & 0xffff);
  1343. goto Quit; // exit this routine
  1344. }
  1345. // Is the reply a RJT (reject)?
  1346. if( (fchs->pl[0] & 0xFFFFL) == 0x01) // Reject reply?
  1347. {
  1348. // ****** REJECT REPLY ********
  1349. switch( Exchanges->fcExchange[ox_id].type )
  1350. {
  1351. case ELS_FDISC: // we sent out Fabric Discovery
  1352. case ELS_FLOGI: // we sent out FLOGI
  1353. printk("RJT received on Fabric Login from %Xh, reason %Xh\n",
  1354. fchs->s_id, fchs->pl[1]);
  1355. break;
  1356. default:
  1357. break;
  1358. }
  1359. goto Done;
  1360. }
  1361. // OK, we have an ACCept...
  1362. // What's the ACC type? (according to what we sent)
  1363. switch( Exchanges->fcExchange[ox_id].type )
  1364. {
  1365. case ELS_PLOGI: // we sent out PLOGI
  1366. if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) )
  1367. {
  1368. LOGIN_PAYLOAD logi; // FC-PH Port Login
  1369. // login ACC payload acceptable; search for WWN in our list
  1370. // of fcPorts
  1371. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
  1372. pLoggedInPort = fcFindLoggedInPort(
  1373. fcChip,
  1374. NULL, // don't search Scsi Nexus
  1375. 0, // don't search linked list for port_id
  1376. &logi.port_name[0], // search linked list for WWN
  1377. &pLastLoggedInPort); // must return non-NULL; when a port_id
  1378. // is not found, this pointer marks the
  1379. // end of the singly linked list
  1380. if( pLoggedInPort == NULL) // WWN not found - new port
  1381. {
  1382. pLoggedInPort = CreateFcPort(
  1383. cpqfcHBAdata,
  1384. pLastLoggedInPort,
  1385. fchs,
  1386. &logi);
  1387. if( pLoggedInPort == NULL )
  1388. {
  1389. printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
  1390. // Now Q a LOGOut Request, since we won't be talking to that device
  1391. goto Done; // exit with error! dropped login frame
  1392. }
  1393. }
  1394. else // WWN was already known. Ensure that any open
  1395. // exchanges for this WWN are terminated.
  1396. // NOTE: It's possible that a device can change its
  1397. // 24-bit port_id after a Link init or Fabric change
  1398. // (e.g. LIP or Fabric RSCN). In that case, the old
  1399. // 24-bit port_id may be duplicated, or no longer exist.
  1400. {
  1401. cpqfcTSTerminateExchange( cpqfcHBAdata,
  1402. &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
  1403. }
  1404. // We have an fcPort struct - set fields accordingly
  1405. // not PDISC, originator
  1406. SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE);
  1407. // We just set a "port_id"; is it duplicated?
  1408. TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort);
  1409. // For Fabric operation, we issued PLOGI to 0xFFFFFC
  1410. // so we can send SCR (State Change Registration)
  1411. // Check for this special case...
  1412. if( fchs->s_id == 0xFFFFFC )
  1413. {
  1414. // PLOGI ACC was a Fabric response... issue SCR
  1415. fchs->s_id = 0xFFFFFD; // address for SCR
  1416. cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_SCR, fchs);
  1417. }
  1418. else
  1419. {
  1420. // Now we need a PRLI to enable FCP-SCSI operation
  1421. // set flags and Q up a ELS_PRLI
  1422. cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PRLI, fchs);
  1423. }
  1424. }
  1425. else
  1426. {
  1427. // login payload unacceptable - reason in ls_reject_code
  1428. // Q up a Logout Request
  1429. printk("Login Payload unacceptable\n");
  1430. }
  1431. break;
  1432. // PDISC logic very similar to PLOGI, except we never want
  1433. // to allocate mem for "new" port, and we set flags differently
  1434. // (might combine later with PLOGI logic for efficiency)
  1435. case ELS_PDISC: // we sent out PDISC
  1436. if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) )
  1437. {
  1438. LOGIN_PAYLOAD logi; // FC-PH Port Login
  1439. BOOLEAN NeedLogin = FALSE;
  1440. // login payload acceptable; search for WWN in our list
  1441. // of (previously seen) fcPorts
  1442. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
  1443. pLoggedInPort = fcFindLoggedInPort(
  1444. fcChip,
  1445. NULL, // don't search Scsi Nexus
  1446. 0, // don't search linked list for port_id
  1447. &logi.port_name[0], // search linked list for WWN
  1448. &pLastLoggedInPort); // must return non-NULL; when a port_id
  1449. // is not found, this pointer marks the
  1450. // end of the singly linked list
  1451. if( pLoggedInPort != NULL) // WWN found?
  1452. {
  1453. // WWN has same port_id as last login? (Of course, a properly
  1454. // working FC device should NEVER ACCept a PDISC if it's
  1455. // port_id changed, but check just in case...)
  1456. if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id)
  1457. {
  1458. // Yes. We were expecting PDISC?
  1459. if( pLoggedInPort->pdisc )
  1460. {
  1461. int i;
  1462. // PDISC expected -- set fields. (PDISC, Originator)
  1463. SetLoginFields( pLoggedInPort, fchs, TRUE, TRUE);
  1464. // We are ready to resume FCP-SCSI to this device...
  1465. // Do we need to start anything that was Queued?
  1466. for( i=0; i< TACH_SEST_LEN; i++)
  1467. {
  1468. // see if any exchange for this PDISC'd port was queued
  1469. if( ((fchs->s_id &0xFFFFFF) ==
  1470. (Exchanges->fcExchange[i].fchs.d_id & 0xFFFFFF))
  1471. &&
  1472. (Exchanges->fcExchange[i].status & EXCHANGE_QUEUED))
  1473. {
  1474. fchs->reserved = i; // copy ExchangeID
  1475. // printk(" *Q x_ID %Xh after PDISC* ",i);
  1476. cpqfcTSPutLinkQue( cpqfcHBAdata, EXCHANGE_QUEUED, fchs );
  1477. }
  1478. }
  1479. // Complete commands Q'd while we were waiting for Login
  1480. UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort);
  1481. }
  1482. else
  1483. {
  1484. printk("Not expecting PDISC (pdisc=FALSE)\n");
  1485. NeedLogin = TRUE;
  1486. }
  1487. }
  1488. else
  1489. {
  1490. printk("PDISC PortID change: old %Xh, new %Xh\n",
  1491. pLoggedInPort->port_id, fchs->s_id &0xFFFFFF);
  1492. NeedLogin = TRUE;
  1493. }
  1494. }
  1495. else
  1496. {
  1497. printk("PDISC ACC from unknown WWN\n");
  1498. NeedLogin = TRUE;
  1499. }
  1500. if( NeedLogin)
  1501. {
  1502. // The PDISC failed. Set login struct flags accordingly,
  1503. // terminate any I/O to this port, and Q a PLOGI
  1504. if( pLoggedInPort ) // FC device previously known?
  1505. {
  1506. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1507. ELS_LOGO, // Q Type
  1508. fchs ); // has port_id to send to
  1509. // There are a variety of error scenarios which can result
  1510. // in PDISC failure, so as a catchall, add the check for
  1511. // duplicate port_id.
  1512. TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort);
  1513. // TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
  1514. pLoggedInPort->pdisc = FALSE;
  1515. pLoggedInPort->prli = FALSE;
  1516. pLoggedInPort->plogi = FALSE;
  1517. cpqfcTSTerminateExchange( cpqfcHBAdata,
  1518. &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
  1519. }
  1520. cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI, fchs );
  1521. }
  1522. }
  1523. else
  1524. {
  1525. // login payload unacceptable - reason in ls_reject_code
  1526. // Q up a Logout Request
  1527. printk("ERROR: Login Payload unacceptable!\n");
  1528. }
  1529. break;
  1530. case ELS_PRLI: // we sent out PRLI
  1531. pLoggedInPort = fcFindLoggedInPort(
  1532. fcChip,
  1533. NULL, // don't search Scsi Nexus
  1534. (fchs->s_id & 0xFFFFFF), // search linked list for port_id
  1535. NULL, // DON'T search linked list for WWN
  1536. NULL); // don't care
  1537. if( pLoggedInPort == NULL )
  1538. {
  1539. // huh?
  1540. printk(" Unexpected PRLI ACCept frame!\n");
  1541. // Q a LOGOut here?
  1542. goto Done;
  1543. }
  1544. // verify the PRLI ACC payload
  1545. if( !verify_PRLI( fchs, &ls_reject_code) )
  1546. {
  1547. // PRLI Reply is acceptable; were we expecting it?
  1548. if( pLoggedInPort->plogi )
  1549. {
  1550. // yes, we expected the PRLI ACC (not PDISC; Originator)
  1551. SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE);
  1552. // OK, let's send a REPORT_LUNS command to determine
  1553. // whether VSA or PDA FCP-LUN addressing is used.
  1554. cpqfcTSPutLinkQue( cpqfcHBAdata, SCSI_REPORT_LUNS, fchs );
  1555. // It's possible that a device we were talking to changed
  1556. // port_id, and has logged back in. This function ensures
  1557. // that I/O will resume.
  1558. UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort);
  1559. }
  1560. else
  1561. {
  1562. // huh?
  1563. printk(" (unexpected) PRLI ACCept with plogi FALSE\n");
  1564. // Q a LOGOut here?
  1565. goto Done;
  1566. }
  1567. }
  1568. else
  1569. {
  1570. printk(" PRLI ACCept payload failed verify\n");
  1571. // Q a LOGOut here?
  1572. }
  1573. break;
  1574. case ELS_FLOGI: // we sent out FLOGI (Fabric Login)
  1575. // update the upper 16 bits of our port_id in Tachyon
  1576. // the switch adds those upper 16 bits when responding
  1577. // to us (i.e. we are the destination_id)
  1578. fcChip->Registers.my_al_pa = (fchs->d_id & 0xFFFFFF);
  1579. writel( fcChip->Registers.my_al_pa,
  1580. fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
  1581. // now send out a PLOGI to the well known port_id 0xFFFFFC
  1582. fchs->s_id = 0xFFFFFC;
  1583. cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI, fchs);
  1584. break;
  1585. case ELS_FDISC: // we sent out FDISC (Fabric Discovery (Login))
  1586. printk( " ELS_FDISC success ");
  1587. break;
  1588. case ELS_SCR: // we sent out State Change Registration
  1589. // now we can issue Name Service Request to find any
  1590. // Fabric-connected devices we might want to login to.
  1591. fchs->s_id = 0xFFFFFC; // Name Server Address
  1592. cpqfcTSPutLinkQue( cpqfcHBAdata, FCS_NSR, fchs);
  1593. break;
  1594. default:
  1595. printk(" *Discarding unknown ACC frame, xID %04X/%04X* ",
  1596. ox_id, fchs->ox_rx_id & 0xffff);
  1597. break;
  1598. }
  1599. Done:
  1600. // Regardless of whether the Reply is valid or not, the
  1601. // the exchange is done - complete
  1602. cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16));
  1603. Quit:
  1604. return;
  1605. }
  1606. // **************** Fibre Channel Services **************
  1607. // This is where we process the Directory (Name) Service Reply
  1608. // to know which devices are on the Fabric
  1609. static void ProcessFCS_Reply(
  1610. CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs)
  1611. {
  1612. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  1613. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  1614. ULONG ox_id = (fchs->ox_rx_id >>16);
  1615. // ULONG ls_reject_code;
  1616. // PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
  1617. // If this is a valid reply, then we MUST have sent a request.
  1618. // Verify that we can find a valid request OX_ID corresponding to
  1619. // this reply
  1620. if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0)
  1621. {
  1622. printk(" *Discarding Reply frame, xID %04X/%04X* ",
  1623. ox_id, fchs->ox_rx_id & 0xffff);
  1624. goto Quit; // exit this routine
  1625. }
  1626. // OK, we were expecting it. Now check to see if it's a
  1627. // "Name Service" Reply, and if so force a re-validation of
  1628. // Fabric device logins (i.e. Start the login timeout and
  1629. // send PDISC or PLOGI)
  1630. // (Endianess Byte Swap?)
  1631. if( fchs->pl[1] == 0x02FC ) // Name Service
  1632. {
  1633. // got a new (or NULL) list of Fabric attach devices...
  1634. // Invalidate current logins
  1635. PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
  1636. while( pLoggedInPort ) // for all ports which are expecting
  1637. // PDISC after the next LIP, set the
  1638. // logoutTimer
  1639. {
  1640. if( (pLoggedInPort->port_id & 0xFFFF00) // Fabric device?
  1641. &&
  1642. (pLoggedInPort->port_id != 0xFFFFFC) ) // NOT the F_Port
  1643. {
  1644. pLoggedInPort->LOGO_timer = 6; // what's the Fabric timeout??
  1645. // suspend any I/O in progress until
  1646. // PDISC received...
  1647. pLoggedInPort->prli = FALSE; // block FCP-SCSI commands
  1648. }
  1649. pLoggedInPort = pLoggedInPort->pNextPort;
  1650. }
  1651. if( fchs->pl[2] == 0x0280) // ACCept?
  1652. {
  1653. // Send PLOGI or PDISC to these Fabric devices
  1654. SendLogins( cpqfcHBAdata, &fchs->pl[4] );
  1655. }
  1656. // As of this writing, the only reason to reject is because NO
  1657. // devices are left on the Fabric. We already started
  1658. // "logged out" timers; if the device(s) don't come
  1659. // back, we'll do the implicit logout in the heart beat
  1660. // timer routine
  1661. else // ReJecT
  1662. {
  1663. // this just means no Fabric device is visible at this instant
  1664. }
  1665. }
  1666. // Regardless of whether the Reply is valid or not, the
  1667. // the exchange is done - complete
  1668. cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16));
  1669. Quit:
  1670. return;
  1671. }
  1672. static void AnalyzeIncomingFrame(
  1673. CPQFCHBA *cpqfcHBAdata,
  1674. ULONG QNdx )
  1675. {
  1676. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  1677. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  1678. PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
  1679. TachFCHDR_GCMND* fchs =
  1680. (TachFCHDR_GCMND*)fcLQ->Qitem[QNdx].ulBuff;
  1681. // ULONG ls_reject_code; // reason for rejecting login
  1682. LONG ExchangeID;
  1683. // FC_LOGGEDIN_PORT *pLoggedInPort;
  1684. BOOLEAN AbortAccept;
  1685. ENTER("AnalyzeIncomingFrame");
  1686. switch( fcLQ->Qitem[QNdx].Type) // FCP or Unknown
  1687. {
  1688. case SFQ_UNKNOWN: // unknown frame (e.g. LIP position frame, NOP, etc.)
  1689. // ********* FC-4 Device Data/ Fibre Channel Service *************
  1690. if( ((fchs->d_id &0xF0000000) == 0) // R_CTL (upper nibble) 0x0?
  1691. &&
  1692. (fchs->f_ctl & 0x20000000) ) // TYPE 20h is Fibre Channel Service
  1693. {
  1694. // ************** FCS Reply **********************
  1695. if( (fchs->d_id & 0xff000000L) == 0x03000000L) // (31:23 R_CTL)
  1696. {
  1697. ProcessFCS_Reply( cpqfcHBAdata, fchs );
  1698. } // end of FCS logic
  1699. }
  1700. // *********** Extended Link Service **************
  1701. else if( fchs->d_id & 0x20000000 // R_CTL 0x2?
  1702. &&
  1703. (fchs->f_ctl & 0x01000000) ) // TYPE = 1
  1704. {
  1705. // these frames are either a response to
  1706. // something we sent (0x23) or "unsolicited"
  1707. // frames (0x22).
  1708. // **************Extended Link REPLY **********************
  1709. // R_CTL Solicited Control Reply
  1710. if( (fchs->d_id & 0xff000000L) == 0x23000000L) // (31:23 R_CTL)
  1711. {
  1712. ProcessELS_Reply( cpqfcHBAdata, fchs );
  1713. } // end of "R_CTL Solicited Control Reply"
  1714. // **************Extended Link REQUEST **********************
  1715. // (unsolicited commands from another port or task...)
  1716. // R_CTL Ext Link REQUEST
  1717. else if( (fchs->d_id & 0xff000000L) == 0x22000000L &&
  1718. (fchs->ox_rx_id != 0xFFFFFFFFL) ) // (ignore LIP frame)
  1719. {
  1720. ProcessELS_Request( cpqfcHBAdata, fchs );
  1721. }
  1722. // ************** LILP **********************
  1723. else if( (fchs->d_id & 0xff000000L) == 0x22000000L &&
  1724. (fchs->ox_rx_id == 0xFFFFFFFFL)) // (e.g., LIP frames)
  1725. {
  1726. // SANMark specifies that when available, we must use
  1727. // the LILP frame to determine which ALPAs to send Port Discovery
  1728. // to...
  1729. if( fchs->pl[0] == 0x0711L) // ELS_PLOGI?
  1730. {
  1731. // UCHAR *ptr = (UCHAR*)&fchs->pl[1];
  1732. // printk(" %d ALPAs found\n", *ptr);
  1733. memcpy( fcChip->LILPmap, &fchs->pl[1], 32*4); // 32 DWORDs
  1734. fcChip->Options.LILPin = 1; // our LILPmap is valid!
  1735. // now post to make Port Discovery happen...
  1736. cpqfcTSPutLinkQue( cpqfcHBAdata, LINKACTIVE, fchs);
  1737. }
  1738. }
  1739. }
  1740. // ***************** BASIC LINK SERVICE *****************
  1741. else if( fchs->d_id & 0x80000000 // R_CTL:
  1742. && // Basic Link Service Request
  1743. !(fchs->f_ctl & 0xFF000000) ) // type=0 for BLS
  1744. {
  1745. // Check for ABTS (Abort Sequence)
  1746. if( (fchs->d_id & 0x8F000000) == 0x81000000)
  1747. {
  1748. // look for OX_ID, S_ID pair that matches in our
  1749. // fcExchanges table; if found, reply with ACCept and complete
  1750. // the exchange
  1751. // Per PLDA, an ABTS is sent by an initiator; therefore
  1752. // assume that if we have an exhange open to the port who
  1753. // sent ABTS, it will be the d_id of what we sent.
  1754. for( ExchangeID = 0, AbortAccept=FALSE;
  1755. ExchangeID < TACH_SEST_LEN; ExchangeID++)
  1756. {
  1757. // Valid "target" exchange 24-bit port_id matches?
  1758. // NOTE: For the case of handling Intiator AND Target
  1759. // functions on the same chip, we can have TWO Exchanges
  1760. // with the same OX_ID -- OX_ID/FFFF for the CMND, and
  1761. // OX_ID/RX_ID for the XRDY or DATA frame(s). Ideally,
  1762. // we would like to support ABTS from Initiators or Targets,
  1763. // but it's not clear that can be supported on Tachyon for
  1764. // all cases (requires more investigation).
  1765. if( (Exchanges->fcExchange[ ExchangeID].type == SCSI_TWE ||
  1766. Exchanges->fcExchange[ ExchangeID].type == SCSI_TRE)
  1767. &&
  1768. ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) ==
  1769. (fchs->s_id & 0xFFFFFF)) )
  1770. {
  1771. // target xchnge port_id matches -- how about OX_ID?
  1772. if( (Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id &0xFFFF0000)
  1773. == (fchs->ox_rx_id & 0xFFFF0000) )
  1774. // yes! post ACCept response; will be completed by fcStart
  1775. {
  1776. Exchanges->fcExchange[ ExchangeID].status = TARGET_ABORT;
  1777. // copy (add) rx_id field for simplified ACCept reply
  1778. fchs->ox_rx_id =
  1779. Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id;
  1780. cpqfcTSPutLinkQue( cpqfcHBAdata,
  1781. BLS_ABTS_ACC, // Q Type
  1782. fchs ); // void QueContent
  1783. AbortAccept = TRUE;
  1784. printk("ACCepting ABTS for x_ID %8.8Xh, SEST pair %8.8Xh\n",
  1785. fchs->ox_rx_id, Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id);
  1786. break; // ABTS can affect only ONE exchange -exit loop
  1787. }
  1788. }
  1789. } // end of FOR loop
  1790. if( !AbortAccept ) // can't ACCept ABTS - send Reject
  1791. {
  1792. printk("ReJecTing: can't find ExchangeID %8.8Xh for ABTS command\n",
  1793. fchs->ox_rx_id);
  1794. if( Exchanges->fcExchange[ ExchangeID].type
  1795. &&
  1796. !(fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len
  1797. & 0x80000000))
  1798. {
  1799. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);
  1800. }
  1801. else
  1802. {
  1803. printk("Unexpected ABTS ReJecT! SEST[%X] Dword 0: %Xh\n",
  1804. ExchangeID, fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len);
  1805. }
  1806. }
  1807. }
  1808. // Check for BLS {ABTS? (Abort Sequence)} ACCept
  1809. else if( (fchs->d_id & 0x8F000000) == 0x84000000)
  1810. {
  1811. // target has responded with ACC for our ABTS;
  1812. // complete the indicated exchange with ABORTED status
  1813. // Make no checks for correct RX_ID, since
  1814. // all we need to conform ABTS ACC is the OX_ID.
  1815. // Verify that the d_id matches!
  1816. ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF; // x_id from ACC
  1817. // printk("ABTS ACC x_ID 0x%04X 0x%04X, status %Xh\n",
  1818. // fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff,
  1819. // Exchanges->fcExchange[ExchangeID].status);
  1820. if( ExchangeID < TACH_SEST_LEN ) // x_ID makes sense
  1821. {
  1822. // Does "target" exchange 24-bit port_id match?
  1823. // (See "NOTE" above for handling Intiator AND Target in
  1824. // the same device driver)
  1825. // First, if this is a target response, then we originated
  1826. // (initiated) it with BLS_ABTS:
  1827. if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS)
  1828. &&
  1829. // Second, does the source of this ACC match the destination
  1830. // of who we originally sent it to?
  1831. ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) ==
  1832. (fchs->s_id & 0xFFFFFF)) )
  1833. {
  1834. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID );
  1835. }
  1836. }
  1837. }
  1838. // Check for BLS {ABTS? (Abort Sequence)} ReJecT
  1839. else if( (fchs->d_id & 0x8F000000) == 0x85000000)
  1840. {
  1841. // target has responded with RJT for our ABTS;
  1842. // complete the indicated exchange with ABORTED status
  1843. // Make no checks for correct RX_ID, since
  1844. // all we need to conform ABTS ACC is the OX_ID.
  1845. // Verify that the d_id matches!
  1846. ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF; // x_id from ACC
  1847. // printk("BLS_ABTS RJT on Exchange 0x%04X 0x%04X\n",
  1848. // fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff);
  1849. if( ExchangeID < TACH_SEST_LEN ) // x_ID makes sense
  1850. {
  1851. // Does "target" exchange 24-bit port_id match?
  1852. // (See "NOTE" above for handling Intiator AND Target in
  1853. // the same device driver)
  1854. // First, if this is a target response, then we originated
  1855. // (initiated) it with BLS_ABTS:
  1856. if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS)
  1857. &&
  1858. // Second, does the source of this ACC match the destination
  1859. // of who we originally sent it to?
  1860. ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) ==
  1861. (fchs->s_id & 0xFFFFFF)) )
  1862. {
  1863. // YES! NOTE: There is a bug in CPQ's RA-4000 box
  1864. // where the "reason code" isn't returned in the payload
  1865. // For now, simply presume the reject is because the target
  1866. // already completed the exchange...
  1867. // printk("complete x_ID %Xh on ABTS RJT\n", ExchangeID);
  1868. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID );
  1869. }
  1870. }
  1871. } // end of ABTS check
  1872. } // end of Basic Link Service Request
  1873. break;
  1874. default:
  1875. printk("AnalyzeIncomingFrame: unknown type: %Xh(%d)\n",
  1876. fcLQ->Qitem[QNdx].Type,
  1877. fcLQ->Qitem[QNdx].Type);
  1878. break;
  1879. }
  1880. }
  1881. // Function for Port Discovery necessary after every FC
  1882. // initialization (e.g. LIP).
  1883. // Also may be called if from Fabric Name Service logic.
  1884. static void SendLogins( CPQFCHBA *cpqfcHBAdata, __u32 *FabricPortIds )
  1885. {
  1886. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  1887. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  1888. ULONG ulStatus=0;
  1889. TachFCHDR_GCMND fchs; // copy fields for transmission
  1890. int i;
  1891. ULONG loginType;
  1892. LONG ExchangeID;
  1893. PFC_LOGGEDIN_PORT pLoggedInPort;
  1894. __u32 PortIds[ number_of_al_pa];
  1895. int NumberOfPorts=0;
  1896. // We're going to presume (for now) that our limit of Fabric devices
  1897. // is the same as the number of alpa on a private loop (126 devices).
  1898. // (Of course this could be changed to support however many we have
  1899. // memory for).
  1900. memset( &PortIds[0], 0, sizeof(PortIds));
  1901. // First, check if this login is for our own Link Initialization
  1902. // (e.g. LIP on FC-AL), or if we have knowledge of Fabric devices
  1903. // from a switch. If we are logging into Fabric devices, we'll
  1904. // have a non-NULL FabricPortId pointer
  1905. if( FabricPortIds != NULL) // may need logins
  1906. {
  1907. int LastPort=FALSE;
  1908. i = 0;
  1909. while( !LastPort)
  1910. {
  1911. // port IDs From NSR payload; byte swap needed?
  1912. BigEndianSwap( (UCHAR*)FabricPortIds, (UCHAR*)&PortIds[i], 4);
  1913. // printk("FPortId[%d] %Xh ", i, PortIds[i]);
  1914. if( PortIds[i] & 0x80000000)
  1915. LastPort = TRUE;
  1916. PortIds[i] &= 0xFFFFFF; // get 24-bit port_id
  1917. // some non-Fabric devices (like the Crossroads Fibre/Scsi bridge)
  1918. // erroneously use ALPA 0.
  1919. if( PortIds[i] ) // need non-zero port_id...
  1920. i++;
  1921. if( i >= number_of_al_pa ) // (in)sanity check
  1922. break;
  1923. FabricPortIds++; // next...
  1924. }
  1925. NumberOfPorts = i;
  1926. // printk("NumberOf Fabric ports %d", NumberOfPorts);
  1927. }
  1928. else // need to send logins on our "local" link
  1929. {
  1930. // are we a loop port? If so, check for reception of LILP frame,
  1931. // and if received use it (SANMark requirement)
  1932. if( fcChip->Options.LILPin )
  1933. {
  1934. int j=0;
  1935. // sanity check on number of ALPAs from LILP frame...
  1936. // For format of LILP frame, see FC-AL specs or
  1937. // "Fibre Channel Bench Reference", J. Stai, 1995 (ISBN 1-879936-17-8)
  1938. // First byte is number of ALPAs
  1939. i = fcChip->LILPmap[0] >= (32*4) ? 32*4 : fcChip->LILPmap[0];
  1940. NumberOfPorts = i;
  1941. // printk(" LILP alpa count %d ", i);
  1942. while( i > 0)
  1943. {
  1944. PortIds[j] = fcChip->LILPmap[1+ j];
  1945. j++; i--;
  1946. }
  1947. }
  1948. else // have to send login to everybody
  1949. {
  1950. int j=0;
  1951. i = number_of_al_pa;
  1952. NumberOfPorts = i;
  1953. while( i > 0)
  1954. {
  1955. PortIds[j] = valid_al_pa[j]; // all legal ALPAs
  1956. j++; i--;
  1957. }
  1958. }
  1959. }
  1960. // Now we have a copy of the port_ids (and how many)...
  1961. for( i = 0; i < NumberOfPorts; i++)
  1962. {
  1963. // 24-bit FC Port ID
  1964. fchs.s_id = PortIds[i]; // note: only 8-bits used for ALPA
  1965. // don't log into ourselves (Linux Scsi disk scan will stop on
  1966. // no TARGET support error on us, and quit trying for rest of devices)
  1967. if( (fchs.s_id & 0xFF ) == (fcChip->Registers.my_al_pa & 0xFF) )
  1968. continue;
  1969. // fabric login needed?
  1970. if( (fchs.s_id == 0) ||
  1971. (fcChip->Options.fabric == 1) )
  1972. {
  1973. fcChip->Options.flogi = 1; // fabric needs longer for login
  1974. // Do we need FLOGI or FDISC?
  1975. pLoggedInPort = fcFindLoggedInPort(
  1976. fcChip,
  1977. NULL, // don't search SCSI Nexus
  1978. 0xFFFFFC, // search linked list for Fabric port_id
  1979. NULL, // don't search WWN
  1980. NULL); // (don't care about end of list)
  1981. if( pLoggedInPort ) // If found, we have prior experience with
  1982. // this port -- check whether PDISC is needed
  1983. {
  1984. if( pLoggedInPort->flogi )
  1985. {
  1986. // does the switch support FDISC?? (FLOGI for now...)
  1987. loginType = ELS_FLOGI; // prior FLOGI still valid
  1988. }
  1989. else
  1990. loginType = ELS_FLOGI; // expired FLOGI
  1991. }
  1992. else // first FLOGI?
  1993. loginType = ELS_FLOGI;
  1994. fchs.s_id = 0xFFFFFE; // well known F_Port address
  1995. // Fabrics are not required to support FDISC, and
  1996. // it's not clear if that helps us anyway, since
  1997. // we'll want a Name Service Request to re-verify
  1998. // visible devices...
  1999. // Consequently, we always want our upper 16 bit
  2000. // port_id to be zero (we'll be rejected if we
  2001. // use our prior port_id if we've been plugged into
  2002. // a different switch port).
  2003. // Trick Tachyon to send to ALPA 0 (see TL/TS UG, pg 87)
  2004. // If our ALPA is 55h for instance, we want the FC frame
  2005. // s_id to be 0x000055, while Tach's my_al_pa register
  2006. // must be 0x000155, to force an OPN at ALPA 0
  2007. // (the Fabric port)
  2008. fcChip->Registers.my_al_pa &= 0xFF; // only use ALPA for FLOGI
  2009. writel( fcChip->Registers.my_al_pa | 0x0100,
  2010. fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
  2011. }
  2012. else // not FLOGI...
  2013. {
  2014. // should we send PLOGI or PDISC? Check if any prior port_id
  2015. // (e.g. alpa) completed a PLOGI/PRLI exchange by checking
  2016. // the pdisc flag.
  2017. pLoggedInPort = fcFindLoggedInPort(
  2018. fcChip,
  2019. NULL, // don't search SCSI Nexus
  2020. fchs.s_id, // search linked list for al_pa
  2021. NULL, // don't search WWN
  2022. NULL); // (don't care about end of list)
  2023. if( pLoggedInPort ) // If found, we have prior experience with
  2024. // this port -- check whether PDISC is needed
  2025. {
  2026. if( pLoggedInPort->pdisc )
  2027. {
  2028. loginType = ELS_PDISC; // prior PLOGI and PRLI maybe still valid
  2029. }
  2030. else
  2031. loginType = ELS_PLOGI; // prior knowledge, but can't use PDISC
  2032. }
  2033. else // never talked to this port_id before
  2034. loginType = ELS_PLOGI; // prior knowledge, but can't use PDISC
  2035. }
  2036. ulStatus = cpqfcTSBuildExchange(
  2037. cpqfcHBAdata,
  2038. loginType, // e.g. PLOGI
  2039. &fchs, // no incoming frame (we are originator)
  2040. NULL, // no data (no scatter/gather list)
  2041. &ExchangeID );// fcController->fcExchanges index, -1 if failed
  2042. if( !ulStatus ) // Exchange setup OK?
  2043. {
  2044. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
  2045. if( !ulStatus )
  2046. {
  2047. // submitted to Tach's Outbound Que (ERQ PI incremented)
  2048. // waited for completion for ELS type (Login frames issued
  2049. // synchronously)
  2050. if( loginType == ELS_PDISC )
  2051. {
  2052. // now, we really shouldn't Revalidate SEST exchanges until
  2053. // we get an ACC reply from our target and verify that
  2054. // the target address/WWN is unchanged. However, when a fast
  2055. // target gets the PDISC, they can send SEST Exchange data
  2056. // before we even get around to processing the PDISC ACC.
  2057. // Consequently, we lose the I/O.
  2058. // To avoid this, go ahead and Revalidate when the PDISC goes
  2059. // out, anticipating that the ACC will be truly acceptable
  2060. // (this happens 99.9999....% of the time).
  2061. // If we revalidate a SEST write, and write data goes to a
  2062. // target that is NOT the one we originated the WRITE to,
  2063. // that target is required (FCP-SCSI specs, etc) to discard
  2064. // our WRITE data.
  2065. // Re-validate SEST entries (Tachyon hardware assists)
  2066. RevalidateSEST( cpqfcHBAdata->HostAdapter, pLoggedInPort);
  2067. //TriggerHBA( fcChip->Registers.ReMapMemBase, 1);
  2068. }
  2069. }
  2070. else // give up immediately on error
  2071. {
  2072. #ifdef LOGIN_DBG
  2073. printk("SendLogins: fcStartExchange failed: %Xh\n", ulStatus );
  2074. #endif
  2075. break;
  2076. }
  2077. if( fcChip->Registers.FMstatus.value & 0x080 ) // LDn during Port Disc.
  2078. {
  2079. ulStatus = LNKDWN_OSLS;
  2080. #ifdef LOGIN_DBG
  2081. printk("SendLogins: PortDisc aborted (LDn) @alpa %Xh\n", fchs.s_id);
  2082. #endif
  2083. break;
  2084. }
  2085. // Check the exchange for bad status (i.e. FrameTimeOut),
  2086. // and complete on bad status (most likely due to BAD_ALPA)
  2087. // on LDn, DPC function may already complete (ABORT) a started
  2088. // exchange, so check type first (type = 0 on complete).
  2089. if( Exchanges->fcExchange[ExchangeID].status )
  2090. {
  2091. #ifdef LOGIN_DBG
  2092. printk("completing x_ID %X on status %Xh\n",
  2093. ExchangeID, Exchanges->fcExchange[ExchangeID].status);
  2094. #endif
  2095. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);
  2096. }
  2097. }
  2098. else // Xchange setup failed...
  2099. {
  2100. #ifdef LOGIN_DBG
  2101. printk("FC: cpqfcTSBuildExchange failed: %Xh\n", ulStatus );
  2102. #endif
  2103. break;
  2104. }
  2105. }
  2106. if( !ulStatus )
  2107. {
  2108. // set the event signifying that all ALPAs were sent out.
  2109. #ifdef LOGIN_DBG
  2110. printk("SendLogins: PortDiscDone\n");
  2111. #endif
  2112. cpqfcHBAdata->PortDiscDone = 1;
  2113. // TL/TS UG, pg. 184
  2114. // 0x0065 = 100ms for RT_TOV
  2115. // 0x01f5 = 500ms for ED_TOV
  2116. fcChip->Registers.ed_tov.value = 0x006501f5L;
  2117. writel( fcChip->Registers.ed_tov.value,
  2118. (fcChip->Registers.ed_tov.address));
  2119. // set the LP_TOV back to ED_TOV (i.e. 500 ms)
  2120. writel( 0x00000010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);
  2121. }
  2122. else
  2123. {
  2124. printk("SendLogins: failed at xchng %Xh, alpa %Xh, status %Xh\n",
  2125. ExchangeID, fchs.s_id, ulStatus);
  2126. }
  2127. LEAVE("SendLogins");
  2128. }
  2129. // for REPORT_LUNS documentation, see "In-Depth Exploration of Scsi",
  2130. // D. Deming, 1994, pg 7-19 (ISBN 1-879936-08-9)
  2131. static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
  2132. {
  2133. struct Scsi_Host *HostAdapter = Cmnd->device->host;
  2134. CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  2135. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  2136. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  2137. PFC_LOGGEDIN_PORT pLoggedInPort;
  2138. int LunListLen=0;
  2139. int i;
  2140. ULONG x_ID = 0xFFFFFFFF;
  2141. UCHAR *ucBuff = Cmnd->request_buffer;
  2142. // printk("cpqfcTS: ReportLunsDone \n");
  2143. // first, we need to find the Exchange for this command,
  2144. // so we can find the fcPort struct to make the indicated
  2145. // changes.
  2146. for( i=0; i< TACH_SEST_LEN; i++)
  2147. {
  2148. if( Exchanges->fcExchange[i].type // exchange defined?
  2149. &&
  2150. (Exchanges->fcExchange[i].Cmnd == Cmnd) ) // matches?
  2151. {
  2152. x_ID = i; // found exchange!
  2153. break;
  2154. }
  2155. }
  2156. if( x_ID == 0xFFFFFFFF)
  2157. {
  2158. // printk("cpqfcTS: ReportLuns failed - no FC Exchange\n");
  2159. goto Done; // Report Luns FC Exchange gone;
  2160. // exchange probably Terminated by Implicit logout
  2161. }
  2162. // search linked list for the port_id we sent INQUIRY to
  2163. pLoggedInPort = fcFindLoggedInPort( fcChip,
  2164. NULL, // DON'T search Scsi Nexus (we will set it)
  2165. Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF,
  2166. NULL, // DON'T search linked list for FC WWN
  2167. NULL); // DON'T care about end of list
  2168. if( !pLoggedInPort )
  2169. {
  2170. // printk("cpqfcTS: ReportLuns failed - device gone\n");
  2171. goto Done; // error! can't find logged in Port
  2172. }
  2173. LunListLen = ucBuff[3];
  2174. LunListLen += ucBuff[2]>>8;
  2175. if( !LunListLen ) // failed
  2176. {
  2177. // generically speaking, a soft error means we should retry...
  2178. if( (Cmnd->result >> 16) == DID_SOFT_ERROR )
  2179. {
  2180. if( ((Cmnd->sense_buffer[2] & 0xF) == 0x6) &&
  2181. (Cmnd->sense_buffer[12] == 0x29) ) // Sense Code "reset"
  2182. {
  2183. TachFCHDR_GCMND *fchs = &Exchanges->fcExchange[ x_ID].fchs;
  2184. // did we fail because of "check condition, device reset?"
  2185. // e.g. the device was reset (i.e., at every power up)
  2186. // retry the Report Luns
  2187. // who are we sending it to?
  2188. // we know this because we have a copy of the command
  2189. // frame from the original Report Lun command -
  2190. // switch the d_id/s_id fields, because the Exchange Build
  2191. // context is "reply to source".
  2192. fchs->s_id = fchs->d_id; // (temporarily re-use the struct)
  2193. cpqfcTSPutLinkQue( cpqfcHBAdata, SCSI_REPORT_LUNS, fchs );
  2194. }
  2195. }
  2196. else // probably, the device doesn't support Report Luns
  2197. pLoggedInPort->ScsiNexus.VolumeSetAddressing = 0;
  2198. }
  2199. else // we have LUN info - check VSA mode
  2200. {
  2201. // for now, assume all LUNs will have same addr mode
  2202. // for VSA, payload byte 8 will be 0x40; otherwise, 0
  2203. pLoggedInPort->ScsiNexus.VolumeSetAddressing = ucBuff[8];
  2204. // Since we got a Report Luns answer, set lun masking flag
  2205. pLoggedInPort->ScsiNexus.LunMasking = 1;
  2206. if( LunListLen > 8*CPQFCTS_MAX_LUN) // We expect CPQFCTS_MAX_LUN max
  2207. LunListLen = 8*CPQFCTS_MAX_LUN;
  2208. /*
  2209. printk("Device WWN %08X%08X Reports Luns @: ",
  2210. (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF),
  2211. (ULONG)(pLoggedInPort->u.liWWN>>32));
  2212. for( i=8; i<LunListLen+8; i+=8)
  2213. {
  2214. printk("%02X%02X ", ucBuff[i], ucBuff[i+1] );
  2215. }
  2216. printk("\n");
  2217. */
  2218. // Since the device was kind enough to tell us where the
  2219. // LUNs are, lets ensure they are contiguous for Linux's
  2220. // SCSI driver scan, which expects them to start at 0.
  2221. // Since Linux only supports 8 LUNs, only copy the first
  2222. // eight from the report luns command
  2223. // e.g., the Compaq RA4x00 f/w Rev 2.54 and above may report
  2224. // LUNs 4001, 4004, etc., because other LUNs are masked from
  2225. // this HBA (owned by someone else). We'll make those appear as
  2226. // LUN 0, 1... to Linux
  2227. {
  2228. int j;
  2229. int AppendLunList = 0;
  2230. // Walk through the LUN list. The 'j' array number is
  2231. // Linux's lun #, while the value of .lun[j] is the target's
  2232. // lun #.
  2233. // Once we build a LUN list, it's possible for a known device
  2234. // to go offline while volumes (LUNs) are added. Later,
  2235. // the device will do another PLOGI ... Report Luns command,
  2236. // and we must not alter the existing Linux Lun map.
  2237. // (This will be very rare).
  2238. for( j=0; j < CPQFCTS_MAX_LUN; j++)
  2239. {
  2240. if( pLoggedInPort->ScsiNexus.lun[j] != 0xFF )
  2241. {
  2242. AppendLunList = 1;
  2243. break;
  2244. }
  2245. }
  2246. if( AppendLunList )
  2247. {
  2248. int k;
  2249. int FreeLunIndex;
  2250. // printk("cpqfcTS: AppendLunList\n");
  2251. // If we get a new Report Luns, we cannot change
  2252. // any existing LUN mapping! (Only additive entry)
  2253. // For all LUNs in ReportLun list
  2254. // if RL lun != ScsiNexus lun
  2255. // if RL lun present in ScsiNexus lun[], continue
  2256. // else find ScsiNexus lun[]==FF and add, continue
  2257. for( i=8, j=0; i<LunListLen+8 && j< CPQFCTS_MAX_LUN; i+=8, j++)
  2258. {
  2259. if( pLoggedInPort->ScsiNexus.lun[j] != ucBuff[i+1] )
  2260. {
  2261. // something changed from the last Report Luns
  2262. printk(" cpqfcTS: Report Lun change!\n");
  2263. for( k=0, FreeLunIndex=CPQFCTS_MAX_LUN;
  2264. k < CPQFCTS_MAX_LUN; k++)
  2265. {
  2266. if( pLoggedInPort->ScsiNexus.lun[k] == 0xFF)
  2267. {
  2268. FreeLunIndex = k;
  2269. break;
  2270. }
  2271. if( pLoggedInPort->ScsiNexus.lun[k] == ucBuff[i+1] )
  2272. break; // we already masked this lun
  2273. }
  2274. if( k >= CPQFCTS_MAX_LUN )
  2275. {
  2276. printk(" no room for new LUN %d\n", ucBuff[i+1]);
  2277. }
  2278. else if( k == FreeLunIndex ) // need to add LUN
  2279. {
  2280. pLoggedInPort->ScsiNexus.lun[k] = ucBuff[i+1];
  2281. // printk("add [%d]->%02d\n", k, pLoggedInPort->ScsiNexus.lun[k]);
  2282. }
  2283. else
  2284. {
  2285. // lun already known
  2286. }
  2287. break;
  2288. }
  2289. }
  2290. // print out the new list...
  2291. for( j=0; j< CPQFCTS_MAX_LUN; j++)
  2292. {
  2293. if( pLoggedInPort->ScsiNexus.lun[j] == 0xFF)
  2294. break; // done
  2295. // printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
  2296. }
  2297. }
  2298. else
  2299. {
  2300. // printk("Linux SCSI LUNs[] -> Device LUNs: ");
  2301. // first time - this is easy
  2302. for( i=8, j=0; i<LunListLen+8 && j< CPQFCTS_MAX_LUN; i+=8, j++)
  2303. {
  2304. pLoggedInPort->ScsiNexus.lun[j] = ucBuff[i+1];
  2305. // printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
  2306. }
  2307. // printk("\n");
  2308. }
  2309. }
  2310. }
  2311. Done: ;
  2312. }
  2313. extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer);
  2314. extern void cpqfc_free_private_data(CPQFCHBA *hba, cpqfc_passthru_private_t *data);
  2315. static void
  2316. call_scsi_done(Scsi_Cmnd *Cmnd)
  2317. {
  2318. CPQFCHBA *hba;
  2319. hba = (CPQFCHBA *) Cmnd->device->host->hostdata;
  2320. // Was this command a cpqfc passthru ioctl ?
  2321. if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL &&
  2322. Cmnd->device->host->hostdata != NULL &&
  2323. is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->device->host->hostdata,
  2324. Cmnd->sc_request->upper_private_data)) {
  2325. cpqfc_free_private_data(hba,
  2326. Cmnd->sc_request->upper_private_data);
  2327. Cmnd->sc_request->upper_private_data = NULL;
  2328. Cmnd->result &= 0xff00ffff;
  2329. Cmnd->result |= (DID_PASSTHROUGH << 16); // prevents retry
  2330. }
  2331. if (Cmnd->scsi_done != NULL)
  2332. (*Cmnd->scsi_done)(Cmnd);
  2333. }
  2334. // After successfully getting a "Process Login" (PRLI) from an
  2335. // FC port, we want to Discover the LUNs so that we know the
  2336. // addressing type (e.g., FCP-SCSI Volume Set Address, Peripheral
  2337. // Unit Device), and whether SSP (Selective Storage Presentation or
  2338. // Lun Masking) has made the LUN numbers non-zero based or
  2339. // non-contiguous. To remain backward compatible with the SCSI-2
  2340. // driver model, which expects a contiguous LUNs starting at 0,
  2341. // will use the ReportLuns info to map from "device" to "Linux"
  2342. // LUNs.
  2343. static void IssueReportLunsCommand(
  2344. CPQFCHBA* cpqfcHBAdata,
  2345. TachFCHDR_GCMND* fchs)
  2346. {
  2347. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  2348. PFC_LOGGEDIN_PORT pLoggedInPort;
  2349. struct scsi_cmnd *Cmnd = NULL;
  2350. struct scsi_device *ScsiDev = NULL;
  2351. LONG x_ID;
  2352. ULONG ulStatus;
  2353. UCHAR *ucBuff;
  2354. if( !cpqfcHBAdata->PortDiscDone) // cleared by LDn
  2355. {
  2356. printk("Discard Q'd ReportLun command\n");
  2357. goto Done;
  2358. }
  2359. // find the device (from port_id) we're talking to
  2360. pLoggedInPort = fcFindLoggedInPort( fcChip,
  2361. NULL, // DON'T search Scsi Nexus
  2362. fchs->s_id & 0xFFFFFF,
  2363. NULL, // DON'T search linked list for FC WWN
  2364. NULL); // DON'T care about end of list
  2365. if( pLoggedInPort ) // we'd BETTER find it!
  2366. {
  2367. if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) )
  2368. goto Done; // forget it - FC device not a "target"
  2369. ScsiDev = scsi_get_host_dev (cpqfcHBAdata->HostAdapter);
  2370. if (!ScsiDev)
  2371. goto Done;
  2372. Cmnd = scsi_get_command (ScsiDev, GFP_KERNEL);
  2373. if (!Cmnd)
  2374. goto Done;
  2375. ucBuff = pLoggedInPort->ReportLunsPayload;
  2376. memset( ucBuff, 0, REPORT_LUNS_PL);
  2377. Cmnd->scsi_done = ScsiReportLunsDone;
  2378. Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload;
  2379. Cmnd->request_bufflen = REPORT_LUNS_PL;
  2380. Cmnd->cmnd[0] = 0xA0;
  2381. Cmnd->cmnd[8] = REPORT_LUNS_PL >> 8;
  2382. Cmnd->cmnd[9] = (UCHAR)REPORT_LUNS_PL;
  2383. Cmnd->cmd_len = 12;
  2384. Cmnd->device->channel = pLoggedInPort->ScsiNexus.channel;
  2385. Cmnd->device->id = pLoggedInPort->ScsiNexus.target;
  2386. ulStatus = cpqfcTSBuildExchange(
  2387. cpqfcHBAdata,
  2388. SCSI_IRE,
  2389. fchs,
  2390. Cmnd, // buffer for Report Lun data
  2391. &x_ID );// fcController->fcExchanges index, -1 if failed
  2392. if( !ulStatus ) // Exchange setup?
  2393. {
  2394. ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, x_ID );
  2395. if( !ulStatus )
  2396. {
  2397. // submitted to Tach's Outbound Que (ERQ PI incremented)
  2398. // waited for completion for ELS type (Login frames issued
  2399. // synchronously)
  2400. }
  2401. else
  2402. // check reason for Exchange not being started - we might
  2403. // want to Queue and start later, or fail with error
  2404. {
  2405. }
  2406. }
  2407. else // Xchange setup failed...
  2408. printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus );
  2409. }
  2410. else // like, we just got a PRLI ACC, and now the port is gone?
  2411. {
  2412. printk(" can't send ReportLuns - no login for port_id %Xh\n",
  2413. fchs->s_id & 0xFFFFFF);
  2414. }
  2415. Done:
  2416. if (Cmnd)
  2417. scsi_put_command (Cmnd);
  2418. if (ScsiDev)
  2419. scsi_free_host_dev (ScsiDev);
  2420. }
  2421. static void CompleteBoardLockCmnd( CPQFCHBA *cpqfcHBAdata)
  2422. {
  2423. int i;
  2424. for( i = CPQFCTS_REQ_QUEUE_LEN-1; i>= 0; i--)
  2425. {
  2426. if( cpqfcHBAdata->BoardLockCmnd[i] != NULL )
  2427. {
  2428. Scsi_Cmnd *Cmnd = cpqfcHBAdata->BoardLockCmnd[i];
  2429. cpqfcHBAdata->BoardLockCmnd[i] = NULL;
  2430. Cmnd->result = (DID_SOFT_ERROR << 16); // ask for retry
  2431. // printk(" BoardLockCmnd[%d] %p Complete, chnl/target/lun %d/%d/%d\n",
  2432. // i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
  2433. call_scsi_done(Cmnd);
  2434. }
  2435. }
  2436. }
  2437. // runs every 1 second for FC exchange timeouts and implicit FC device logouts
  2438. void cpqfcTSheartbeat( unsigned long ptr )
  2439. {
  2440. CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)ptr;
  2441. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  2442. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  2443. PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
  2444. ULONG i;
  2445. unsigned long flags;
  2446. DECLARE_MUTEX_LOCKED(BoardLock);
  2447. PCI_TRACE( 0xA8)
  2448. if( cpqfcHBAdata->BoardLock) // Worker Task Running?
  2449. goto Skip;
  2450. // STOP _que function
  2451. spin_lock_irqsave( cpqfcHBAdata->HostAdapter->host_lock, flags);
  2452. PCI_TRACE( 0xA8)
  2453. cpqfcHBAdata->BoardLock = &BoardLock; // stop Linux SCSI command queuing
  2454. // release the IO lock (and re-enable interrupts)
  2455. spin_unlock_irqrestore( cpqfcHBAdata->HostAdapter->host_lock, flags);
  2456. // Ensure no contention from _quecommand or Worker process
  2457. CPQ_SPINLOCK_HBA( cpqfcHBAdata)
  2458. PCI_TRACE( 0xA8)
  2459. disable_irq( cpqfcHBAdata->HostAdapter->irq); // our IRQ
  2460. // Complete the "bad target" commands (normally only used during
  2461. // initialization, since we aren't supposed to call "scsi_done"
  2462. // inside the queuecommand() function). (this is overly contorted,
  2463. // scsi_done can be safely called from queuecommand for
  2464. // this bad target case. May want to simplify this later)
  2465. for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)
  2466. {
  2467. if( cpqfcHBAdata->BadTargetCmnd[i] )
  2468. {
  2469. Scsi_Cmnd *Cmnd = cpqfcHBAdata->BadTargetCmnd[i];
  2470. cpqfcHBAdata->BadTargetCmnd[i] = NULL;
  2471. Cmnd->result = (DID_BAD_TARGET << 16);
  2472. call_scsi_done(Cmnd);
  2473. }
  2474. else
  2475. break;
  2476. }
  2477. // logged in ports -- re-login check (ports required to verify login with
  2478. // PDISC after LIP within 2 secs)
  2479. // prevent contention
  2480. while( pLoggedInPort ) // for all ports which are expecting
  2481. // PDISC after the next LIP, check to see if
  2482. // time is up!
  2483. {
  2484. // Important: we only detect "timeout" condition on TRANSITION
  2485. // from non-zero to zero
  2486. if( pLoggedInPort->LOGO_timer ) // time-out "armed"?
  2487. {
  2488. if( !(--pLoggedInPort->LOGO_timer) ) // DEC from 1 to 0?
  2489. {
  2490. // LOGOUT time! Per PLDA, PDISC hasn't complete in 2 secs, so
  2491. // issue LOGO request and destroy all I/O with other FC port(s).
  2492. /*
  2493. printk(" ~cpqfcTS heartbeat: LOGOut!~ ");
  2494. printk("Linux SCSI Chanl/Target %d/%d (port_id %06Xh) WWN %08X%08X\n",
  2495. pLoggedInPort->ScsiNexus.channel,
  2496. pLoggedInPort->ScsiNexus.target,
  2497. pLoggedInPort->port_id,
  2498. (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF),
  2499. (ULONG)(pLoggedInPort->u.liWWN>>32));
  2500. */
  2501. cpqfcTSImplicitLogout( cpqfcHBAdata, pLoggedInPort);
  2502. }
  2503. // else simply decremented - maybe next time...
  2504. }
  2505. pLoggedInPort = pLoggedInPort->pNextPort;
  2506. }
  2507. // ************ FC EXCHANGE TIMEOUT CHECK **************
  2508. for( i=0; i< TACH_MAX_XID; i++)
  2509. {
  2510. if( Exchanges->fcExchange[i].type ) // exchange defined?
  2511. {
  2512. if( !Exchanges->fcExchange[i].timeOut ) // time expired
  2513. {
  2514. // Set Exchange timeout status
  2515. Exchanges->fcExchange[i].status |= FC2_TIMEOUT;
  2516. if( i >= TACH_SEST_LEN ) // Link Service Exchange
  2517. {
  2518. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, i); // Don't "abort" LinkService
  2519. }
  2520. else // SEST Exchange TO -- may post ABTS to Worker Thread Que
  2521. {
  2522. // (Make sure we don't keep timing it out; let other functions
  2523. // complete it or set the timeOut as needed)
  2524. Exchanges->fcExchange[i].timeOut = 30000; // seconds default
  2525. if( Exchanges->fcExchange[i].type
  2526. &
  2527. (BLS_ABTS | BLS_ABTS_ACC ) )
  2528. {
  2529. // For BLS_ABTS*, an upper level might still have
  2530. // an outstanding command waiting for low-level completion.
  2531. // Also, in the case of a WRITE, we MUST get confirmation
  2532. // of either ABTS ACC or RJT before re-using the Exchange.
  2533. // It's possible that the RAID cache algorithm can hang
  2534. // if we fail to complete a WRITE to a LBA, when a READ
  2535. // comes later to that same LBA. Therefore, we must
  2536. // ensure that the target verifies receipt of ABTS for
  2537. // the exchange
  2538. printk("~TO Q'd ABTS (x_ID %Xh)~ ", i);
  2539. // TriggerHBA( fcChip->Registers.ReMapMemBase);
  2540. // On timeout of a ABTS exchange, check to
  2541. // see if the FC device has a current valid login.
  2542. // If so, restart it.
  2543. pLoggedInPort = fcFindLoggedInPort( fcChip,
  2544. Exchanges->fcExchange[i].Cmnd, // find Scsi Nexus
  2545. 0, // DON'T search linked list for FC port id
  2546. NULL, // DON'T search linked list for FC WWN
  2547. NULL); // DON'T care about end of list
  2548. // device exists?
  2549. if( pLoggedInPort ) // device exists?
  2550. {
  2551. if( pLoggedInPort->prli ) // logged in for FCP-SCSI?
  2552. {
  2553. // attempt to restart the ABTS
  2554. printk(" ~restarting ABTS~ ");
  2555. cpqfcTSStartExchange( cpqfcHBAdata, i );
  2556. }
  2557. }
  2558. }
  2559. else // not an ABTS
  2560. {
  2561. // We expect the WorkerThread to change the xchng type to
  2562. // abort and set appropriate timeout.
  2563. cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &i ); // timed-out
  2564. }
  2565. }
  2566. }
  2567. else // time not expired...
  2568. {
  2569. // decrement timeout: 1 or more seconds left
  2570. --Exchanges->fcExchange[i].timeOut;
  2571. }
  2572. }
  2573. }
  2574. enable_irq( cpqfcHBAdata->HostAdapter->irq);
  2575. CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)
  2576. cpqfcHBAdata->BoardLock = NULL; // Linux SCSI commands may be queued
  2577. // Now, complete any Cmnd we Q'd up while BoardLock was held
  2578. CompleteBoardLockCmnd( cpqfcHBAdata);
  2579. // restart the timer to run again (1 sec later)
  2580. Skip:
  2581. mod_timer( &cpqfcHBAdata->cpqfcTStimer, jiffies + HZ);
  2582. PCI_TRACEO( i, 0xA8)
  2583. return;
  2584. }
  2585. // put valid FC-AL physical address in spec order
  2586. static const UCHAR valid_al_pa[]={
  2587. 0xef, 0xe8, 0xe4, 0xe2,
  2588. 0xe1, 0xE0, 0xDC, 0xDA,
  2589. 0xD9, 0xD6, 0xD5, 0xD4,
  2590. 0xD3, 0xD2, 0xD1, 0xCe,
  2591. 0xCd, 0xCc, 0xCb, 0xCa,
  2592. 0xC9, 0xC7, 0xC6, 0xC5,
  2593. 0xC3, 0xBc, 0xBa, 0xB9,
  2594. 0xB6, 0xB5, 0xB4, 0xB3,
  2595. 0xB2, 0xB1, 0xae, 0xad,
  2596. 0xAc, 0xAb, 0xAa, 0xA9,
  2597. 0xA7, 0xA6, 0xA5, 0xA3,
  2598. 0x9f, 0x9e, 0x9d, 0x9b,
  2599. 0x98, 0x97, 0x90, 0x8f,
  2600. 0x88, 0x84, 0x82, 0x81,
  2601. 0x80, 0x7c, 0x7a, 0x79,
  2602. 0x76, 0x75, 0x74, 0x73,
  2603. 0x72, 0x71, 0x6e, 0x6d,
  2604. 0x6c, 0x6b, 0x6a, 0x69,
  2605. 0x67, 0x66, 0x65, 0x63,
  2606. 0x5c, 0x5a, 0x59, 0x56,
  2607. 0x55, 0x54, 0x53, 0x52,
  2608. 0x51, 0x4e, 0x4d, 0x4c,
  2609. 0x4b, 0x4a, 0x49, 0x47,
  2610. 0x46, 0x45, 0x43, 0x3c,
  2611. 0x3a, 0x39, 0x36, 0x35,
  2612. 0x34, 0x33, 0x32, 0x31,
  2613. 0x2e, 0x2d, 0x2c, 0x2b,
  2614. 0x2a, 0x29, 0x27, 0x26,
  2615. 0x25, 0x23, 0x1f, 0x1E,
  2616. 0x1d, 0x1b, 0x18, 0x17,
  2617. 0x10, 0x0f, 8, 4, 2, 1 }; // ALPA 0 (Fabric) is special case
  2618. const int number_of_al_pa = (sizeof(valid_al_pa) );
  2619. // this function looks up an al_pa from the table of valid al_pa's
  2620. // we decrement from the last decimal loop ID, because soft al_pa
  2621. // (our typical case) are assigned with highest priority (and high al_pa)
  2622. // first. See "In-Depth FC-AL", R. Kembel pg. 38
  2623. // INPUTS:
  2624. // al_pa - 24 bit port identifier (8 bit al_pa on private loop)
  2625. // RETURN:
  2626. // Loop ID - serves are index to array of logged in ports
  2627. // -1 - invalid al_pa (not all 8 bit values are legal)
  2628. #if (0)
  2629. static int GetLoopID( ULONG al_pa )
  2630. {
  2631. int i;
  2632. for( i = number_of_al_pa -1; i >= 0; i--) // dec.
  2633. {
  2634. if( valid_al_pa[i] == (UCHAR)al_pa ) // take lowest 8 bits
  2635. return i; // success - found valid al_pa; return decimal LoopID
  2636. }
  2637. return -1; // failed - not found
  2638. }
  2639. #endif
  2640. extern cpqfc_passthru_private_t *cpqfc_private(Scsi_Request *sr);
  2641. // Search the singly (forward) linked list "fcPorts" looking for
  2642. // either the SCSI target (if != -1), port_id (if not NULL),
  2643. // or WWN (if not null), in that specific order.
  2644. // If we find a SCSI nexus (from Cmnd arg), set the SCp.phase
  2645. // field according to VSA or PDU
  2646. // RETURNS:
  2647. // Ptr to logged in port struct if found
  2648. // (NULL if not found)
  2649. // pLastLoggedInPort - ptr to last struct (for adding new ones)
  2650. //
  2651. PFC_LOGGEDIN_PORT fcFindLoggedInPort(
  2652. PTACHYON fcChip,
  2653. Scsi_Cmnd *Cmnd, // search linked list for Scsi Nexus (channel/target/lun)
  2654. ULONG port_id, // search linked list for al_pa, or
  2655. UCHAR wwn[8], // search linked list for WWN, or...
  2656. PFC_LOGGEDIN_PORT *pLastLoggedInPort )
  2657. {
  2658. PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
  2659. BOOLEAN target_id_valid=FALSE;
  2660. BOOLEAN port_id_valid=FALSE;
  2661. BOOLEAN wwn_valid=FALSE;
  2662. int i;
  2663. if( Cmnd != NULL )
  2664. target_id_valid = TRUE;
  2665. else if( port_id ) // note! 24-bit NULL address is illegal
  2666. port_id_valid = TRUE;
  2667. else
  2668. {
  2669. if( wwn ) // non-null arg? (OK to pass NULL when not searching WWN)
  2670. {
  2671. for( i=0; i<8; i++) // valid WWN passed? NULL WWN invalid
  2672. {
  2673. if( wwn[i] != 0 )
  2674. wwn_valid = TRUE; // any non-zero byte makes (presumably) valid
  2675. }
  2676. }
  2677. }
  2678. // check other options ...
  2679. // In case multiple search options are given, we use a priority
  2680. // scheme:
  2681. // While valid pLoggedIn Ptr
  2682. // If port_id is valid
  2683. // if port_id matches, return Ptr
  2684. // If wwn is valid
  2685. // if wwn matches, return Ptr
  2686. // Next Ptr in list
  2687. //
  2688. // Return NULL (not found)
  2689. while( pLoggedInPort ) // NULL marks end of list (1st ptr always valid)
  2690. {
  2691. if( pLastLoggedInPort ) // caller's pointer valid?
  2692. *pLastLoggedInPort = pLoggedInPort; // end of linked list
  2693. if( target_id_valid )
  2694. {
  2695. // check Linux Scsi Cmnd for channel/target Nexus match
  2696. // (all luns are accessed through matching "pLoggedInPort")
  2697. if( (pLoggedInPort->ScsiNexus.target == Cmnd->device->id)
  2698. &&
  2699. (pLoggedInPort->ScsiNexus.channel == Cmnd->device->channel))
  2700. {
  2701. // For "passthru" modes, the IOCTL caller is responsible
  2702. // for setting the FCP-LUN addressing
  2703. if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL &&
  2704. Cmnd->device->host->hostdata != NULL &&
  2705. is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->device->host->hostdata,
  2706. Cmnd->sc_request->upper_private_data)) {
  2707. /* This is a passthru... */
  2708. cpqfc_passthru_private_t *pd;
  2709. pd = Cmnd->sc_request->upper_private_data;
  2710. Cmnd->SCp.phase = pd->bus;
  2711. // Cmnd->SCp.have_data_in = pd->pdrive;
  2712. Cmnd->SCp.have_data_in = Cmnd->device->lun;
  2713. } else {
  2714. /* This is not a passthru... */
  2715. // set the FCP-LUN addressing type
  2716. Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;
  2717. // set the Device Type we got from the snooped INQUIRY string
  2718. Cmnd->SCp.Message = pLoggedInPort->ScsiNexus.InqDeviceType;
  2719. // handle LUN masking; if not "default" (illegal) lun value,
  2720. // the use it. These lun values are set by a successful
  2721. // Report Luns command
  2722. if( pLoggedInPort->ScsiNexus.LunMasking == 1)
  2723. {
  2724. if (Cmnd->device->lun > sizeof(pLoggedInPort->ScsiNexus.lun))
  2725. return NULL;
  2726. // we KNOW all the valid LUNs... 0xFF is invalid!
  2727. Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->device->lun];
  2728. if (pLoggedInPort->ScsiNexus.lun[Cmnd->device->lun] == 0xFF)
  2729. return NULL;
  2730. // printk("xlating lun %d to 0x%02x\n", Cmnd->lun,
  2731. // pLoggedInPort->ScsiNexus.lun[Cmnd->lun]);
  2732. }
  2733. else
  2734. Cmnd->SCp.have_data_in = Cmnd->device->lun; // Linux & target luns match
  2735. }
  2736. break; // found it!
  2737. }
  2738. }
  2739. if( port_id_valid ) // look for alpa first
  2740. {
  2741. if( pLoggedInPort->port_id == port_id )
  2742. break; // found it!
  2743. }
  2744. if( wwn_valid ) // look for wwn second
  2745. {
  2746. if( !memcmp( &pLoggedInPort->u.ucWWN[0], &wwn[0], 8))
  2747. {
  2748. // all 8 bytes of WWN match
  2749. break; // found it!
  2750. }
  2751. }
  2752. pLoggedInPort = pLoggedInPort->pNextPort; // try next port
  2753. }
  2754. return pLoggedInPort;
  2755. }
  2756. //
  2757. // We need to examine the SEST table and re-validate
  2758. // any open Exchanges for this LoggedInPort
  2759. // To make Tachyon pay attention, Freeze FCP assists,
  2760. // set VAL bits, Unfreeze FCP assists
  2761. static void RevalidateSEST( struct Scsi_Host *HostAdapter,
  2762. PFC_LOGGEDIN_PORT pLoggedInPort)
  2763. {
  2764. CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  2765. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  2766. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  2767. ULONG x_ID;
  2768. BOOLEAN TachFroze = FALSE;
  2769. // re-validate any SEST exchanges that are permitted
  2770. // to survive the link down (e.g., good PDISC performed)
  2771. for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
  2772. {
  2773. // If the SEST entry port_id matches the pLoggedInPort,
  2774. // we need to re-validate
  2775. if( (Exchanges->fcExchange[ x_ID].type == SCSI_IRE)
  2776. ||
  2777. (Exchanges->fcExchange[ x_ID].type == SCSI_IWE))
  2778. {
  2779. if( (Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF) // (24-bit port ID)
  2780. == pLoggedInPort->port_id)
  2781. {
  2782. // printk(" re-val xID %Xh ", x_ID);
  2783. if( !TachFroze ) // freeze if not already frozen
  2784. TachFroze |= FreezeTach( cpqfcHBAdata);
  2785. fcChip->SEST->u[ x_ID].IWE.Hdr_Len |= 0x80000000; // set VAL bit
  2786. }
  2787. }
  2788. }
  2789. if( TachFroze)
  2790. {
  2791. fcChip->UnFreezeTachyon( fcChip, 2); // both ERQ and FCP assists
  2792. }
  2793. }
  2794. // Complete an Linux Cmnds that we Queued because
  2795. // our FC link was down (cause immediate retry)
  2796. static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
  2797. PFC_LOGGEDIN_PORT pLoggedInPort)
  2798. {
  2799. CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  2800. Scsi_Cmnd* *SCptr = &cpqfcHBAdata->LinkDnCmnd[0];
  2801. Scsi_Cmnd *Cmnd;
  2802. int indx;
  2803. // if the device was previously "blocked", make sure
  2804. // we unblock it so Linux SCSI will resume
  2805. pLoggedInPort->device_blocked = FALSE; // clear our flag
  2806. // check the Link Down command ptr buffer;
  2807. // we can complete now causing immediate retry
  2808. for( indx=0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++, SCptr++)
  2809. {
  2810. if( *SCptr != NULL ) // scsi command to complete?
  2811. {
  2812. #ifdef DUMMYCMND_DBG
  2813. printk("complete Cmnd %p in LinkDnCmnd[%d]\n", *SCptr,indx);
  2814. #endif
  2815. Cmnd = *SCptr;
  2816. // Are there any Q'd commands for this target?
  2817. if( (Cmnd->device->id == pLoggedInPort->ScsiNexus.target)
  2818. &&
  2819. (Cmnd->device->channel == pLoggedInPort->ScsiNexus.channel) )
  2820. {
  2821. Cmnd->result = (DID_SOFT_ERROR <<16); // force retry
  2822. if( Cmnd->scsi_done == NULL)
  2823. {
  2824. printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n",
  2825. pLoggedInPort->port_id);
  2826. }
  2827. else
  2828. call_scsi_done(Cmnd);
  2829. *SCptr = NULL; // free this slot for next use
  2830. }
  2831. }
  2832. }
  2833. }
  2834. //#define WWN_DBG 1
  2835. static void SetLoginFields(
  2836. PFC_LOGGEDIN_PORT pLoggedInPort,
  2837. TachFCHDR_GCMND* fchs,
  2838. BOOLEAN PDisc,
  2839. BOOLEAN Originator)
  2840. {
  2841. LOGIN_PAYLOAD logi; // FC-PH Port Login
  2842. PRLI_REQUEST prli; // copy for BIG ENDIAN switch
  2843. int i;
  2844. #ifdef WWN_DBG
  2845. ULONG ulBuff;
  2846. #endif
  2847. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
  2848. pLoggedInPort->Originator = Originator;
  2849. pLoggedInPort->port_id = fchs->s_id & 0xFFFFFF;
  2850. switch( fchs->pl[0] & 0xffff )
  2851. {
  2852. case 0x00000002: // PLOGI or PDISC ACCept?
  2853. if( PDisc ) // PDISC accept
  2854. goto PDISC_case;
  2855. case 0x00000003: // ELS_PLOGI or ELS_PLOGI_ACC
  2856. // Login BB_credit typically 0 for Tachyons
  2857. pLoggedInPort->BB_credit = logi.cmn_services.bb_credit;
  2858. // e.g. 128, 256, 1024, 2048 per FC-PH spec
  2859. // We have to use this when setting up SEST Writes,
  2860. // since that determines frame size we send.
  2861. pLoggedInPort->rx_data_size = logi.class3.rx_data_size;
  2862. pLoggedInPort->plogi = TRUE;
  2863. pLoggedInPort->pdisc = FALSE;
  2864. pLoggedInPort->prli = FALSE; // ELS_PLOGI resets
  2865. pLoggedInPort->flogi = FALSE; // ELS_PLOGI resets
  2866. pLoggedInPort->logo = FALSE; // ELS_PLOGI resets
  2867. pLoggedInPort->LOGO_counter = 0;// ELS_PLOGI resets
  2868. pLoggedInPort->LOGO_timer = 0;// ELS_PLOGI resets
  2869. // was this PLOGI to a Fabric?
  2870. if( pLoggedInPort->port_id == 0xFFFFFC ) // well know address
  2871. pLoggedInPort->flogi = TRUE;
  2872. for( i=0; i<8; i++) // copy the LOGIN port's WWN
  2873. pLoggedInPort->u.ucWWN[i] = logi.port_name[i];
  2874. #ifdef WWN_DBG
  2875. ulBuff = (ULONG)pLoggedInPort->u.liWWN;
  2876. if( pLoggedInPort->Originator)
  2877. printk("o");
  2878. else
  2879. printk("r");
  2880. printk("PLOGI port_id %Xh, WWN %08X",
  2881. pLoggedInPort->port_id, ulBuff);
  2882. ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
  2883. printk("%08Xh fcPort %p\n", ulBuff, pLoggedInPort);
  2884. #endif
  2885. break;
  2886. case 0x00000005: // ELS_LOGO (logout)
  2887. pLoggedInPort->plogi = FALSE;
  2888. pLoggedInPort->pdisc = FALSE;
  2889. pLoggedInPort->prli = FALSE; // ELS_PLOGI resets
  2890. pLoggedInPort->flogi = FALSE; // ELS_PLOGI resets
  2891. pLoggedInPort->logo = TRUE; // ELS_PLOGI resets
  2892. pLoggedInPort->LOGO_counter++; // ELS_PLOGI resets
  2893. pLoggedInPort->LOGO_timer = 0;
  2894. #ifdef WWN_DBG
  2895. ulBuff = (ULONG)pLoggedInPort->u.liWWN;
  2896. if( pLoggedInPort->Originator)
  2897. printk("o");
  2898. else
  2899. printk("r");
  2900. printk("LOGO port_id %Xh, WWN %08X",
  2901. pLoggedInPort->port_id, ulBuff);
  2902. ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
  2903. printk("%08Xh\n", ulBuff);
  2904. #endif
  2905. break;
  2906. PDISC_case:
  2907. case 0x00000050: // ELS_PDISC or ELS_PDISC_ACC
  2908. pLoggedInPort->LOGO_timer = 0; // stop the time-out
  2909. pLoggedInPort->prli = TRUE; // ready to accept FCP-SCSI I/O
  2910. #ifdef WWN_DBG
  2911. ulBuff = (ULONG)pLoggedInPort->u.liWWN;
  2912. if( pLoggedInPort->Originator)
  2913. printk("o");
  2914. else
  2915. printk("r");
  2916. printk("PDISC port_id %Xh, WWN %08X",
  2917. pLoggedInPort->port_id, ulBuff);
  2918. ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
  2919. printk("%08Xh\n", ulBuff);
  2920. #endif
  2921. break;
  2922. case 0x1020L: // PRLI?
  2923. case 0x1002L: // PRLI ACCept?
  2924. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&prli, sizeof(prli));
  2925. pLoggedInPort->fcp_info = prli.fcp_info; // target/initiator flags
  2926. pLoggedInPort->prli = TRUE; // PLOGI resets, PDISC doesn't
  2927. pLoggedInPort->pdisc = TRUE; // expect to send (or receive) PDISC
  2928. // next time
  2929. pLoggedInPort->LOGO_timer = 0; // will be set next LinkDown
  2930. #ifdef WWN_DBG
  2931. ulBuff = (ULONG)pLoggedInPort->u.liWWN;
  2932. if( pLoggedInPort->Originator)
  2933. printk("o");
  2934. else
  2935. printk("r");
  2936. printk("PRLI port_id %Xh, WWN %08X",
  2937. pLoggedInPort->port_id, ulBuff);
  2938. ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
  2939. printk("%08Xh\n", ulBuff);
  2940. #endif
  2941. break;
  2942. }
  2943. return;
  2944. }
  2945. static void BuildLinkServicePayload( PTACHYON fcChip, ULONG type, void* payload)
  2946. {
  2947. LOGIN_PAYLOAD *plogi; // FC-PH Port Login
  2948. LOGIN_PAYLOAD PlogiPayload; // copy for BIG ENDIAN switch
  2949. PRLI_REQUEST *prli; // FCP-SCSI Process Login
  2950. PRLI_REQUEST PrliPayload; // copy for BIG ENDIAN switch
  2951. LOGOUT_PAYLOAD *logo;
  2952. LOGOUT_PAYLOAD LogoutPayload;
  2953. // PRLO_REQUEST *prlo;
  2954. // PRLO_REQUEST PrloPayload;
  2955. REJECT_MESSAGE rjt, *prjt;
  2956. memset( &PlogiPayload, 0, sizeof( PlogiPayload));
  2957. plogi = &PlogiPayload; // load into stack buffer,
  2958. // then BIG-ENDIAN switch a copy to caller
  2959. switch( type ) // payload type can be ELS_PLOGI, ELS_PRLI, ADISC, ...
  2960. {
  2961. case ELS_FDISC:
  2962. case ELS_FLOGI:
  2963. case ELS_PLOGI_ACC: // FC-PH PORT Login Accept
  2964. case ELS_PLOGI: // FC-PH PORT Login
  2965. case ELS_PDISC: // FC-PH2 Port Discovery - same payload as ELS_PLOGI
  2966. plogi->login_cmd = LS_PLOGI;
  2967. if( type == ELS_PDISC)
  2968. plogi->login_cmd = LS_PDISC;
  2969. else if( type == ELS_PLOGI_ACC )
  2970. plogi->login_cmd = LS_ACC;
  2971. plogi->cmn_services.bb_credit = 0x00;
  2972. plogi->cmn_services.lowest_ver = fcChip->lowest_FCPH_ver;
  2973. plogi->cmn_services.highest_ver = fcChip->highest_FCPH_ver;
  2974. plogi->cmn_services.bb_rx_size = TACHLITE_TS_RX_SIZE;
  2975. plogi->cmn_services.common_features = CONTINUOSLY_INCREASING |
  2976. RANDOM_RELATIVE_OFFSET;
  2977. // fill in with World Wide Name based Port Name - 8 UCHARs
  2978. // get from Tach registers WWN hi & lo
  2979. LoadWWN( fcChip, plogi->port_name, 0);
  2980. // fill in with World Wide Name based Node/Fabric Name - 8 UCHARs
  2981. // get from Tach registers WWN hi & lo
  2982. LoadWWN( fcChip, plogi->node_name, 1);
  2983. // For Seagate Drives.
  2984. //
  2985. plogi->cmn_services.common_features |= 0x800;
  2986. plogi->cmn_services.rel_offset = 0xFE;
  2987. plogi->cmn_services.concurrent_seq = 1;
  2988. plogi->class1.service_options = 0x00;
  2989. plogi->class2.service_options = 0x00;
  2990. plogi->class3.service_options = CLASS_VALID;
  2991. plogi->class3.initiator_control = 0x00;
  2992. plogi->class3.rx_data_size = MAX_RX_PAYLOAD;
  2993. plogi->class3.recipient_control =
  2994. ERROR_DISCARD | ONE_CATEGORY_SEQUENCE;
  2995. plogi->class3.concurrent_sequences = 1;
  2996. plogi->class3.open_sequences = 1;
  2997. plogi->vendor_id[0] = 'C'; plogi->vendor_id[1] = 'Q';
  2998. plogi->vendor_version[0] = 'C'; plogi->vendor_version[1] = 'Q';
  2999. plogi->vendor_version[2] = ' '; plogi->vendor_version[3] = '0';
  3000. plogi->vendor_version[4] = '0'; plogi->vendor_version[5] = '0';
  3001. // FLOGI specific fields... (see FC-FLA, Rev 2.7, Aug 1999, sec 5.1)
  3002. if( (type == ELS_FLOGI) || (type == ELS_FDISC) )
  3003. {
  3004. if( type == ELS_FLOGI )
  3005. plogi->login_cmd = LS_FLOGI;
  3006. else
  3007. plogi->login_cmd = LS_FDISC;
  3008. plogi->cmn_services.lowest_ver = 0x20;
  3009. plogi->cmn_services.common_features = 0x0800;
  3010. plogi->cmn_services.rel_offset = 0;
  3011. plogi->cmn_services.concurrent_seq = 0;
  3012. plogi->class3.service_options = 0x8800;
  3013. plogi->class3.rx_data_size = 0;
  3014. plogi->class3.recipient_control = 0;
  3015. plogi->class3.concurrent_sequences = 0;
  3016. plogi->class3.open_sequences = 0;
  3017. }
  3018. // copy back to caller's buff, w/ BIG ENDIAN swap
  3019. BigEndianSwap( (UCHAR*)&PlogiPayload, payload, sizeof(PlogiPayload));
  3020. break;
  3021. case ELS_ACC: // generic Extended Link Service ACCept
  3022. plogi->login_cmd = LS_ACC;
  3023. // copy back to caller's buff, w/ BIG ENDIAN swap
  3024. BigEndianSwap( (UCHAR*)&PlogiPayload, payload, 4);
  3025. break;
  3026. case ELS_SCR: // Fabric State Change Registration
  3027. {
  3028. SCR_PL scr; // state change registration
  3029. memset( &scr, 0, sizeof(scr));
  3030. scr.command = LS_SCR; // 0x62000000
  3031. // see FC-FLA, Rev 2.7, Table A.22 (pg 82)
  3032. scr.function = 3; // 1 = Events detected by Fabric
  3033. // 2 = N_Port detected registration
  3034. // 3 = Full registration
  3035. // copy back to caller's buff, w/ BIG ENDIAN swap
  3036. BigEndianSwap( (UCHAR*)&scr, payload, sizeof(SCR_PL));
  3037. }
  3038. break;
  3039. case FCS_NSR: // Fabric Name Service Request
  3040. {
  3041. NSR_PL nsr; // Name Server Req. payload
  3042. memset( &nsr, 0, sizeof(NSR_PL));
  3043. // see Brocade Fabric Programming Guide,
  3044. // Rev 1.3, pg 4-44
  3045. nsr.CT_Rev = 0x01000000;
  3046. nsr.FCS_Type = 0xFC020000;
  3047. nsr.Command_code = 0x01710000;
  3048. nsr.FCP = 8;
  3049. // copy back to caller's buff, w/ BIG ENDIAN swap
  3050. BigEndianSwap( (UCHAR*)&nsr, payload, sizeof(NSR_PL));
  3051. }
  3052. break;
  3053. case ELS_LOGO: // FC-PH PORT LogOut
  3054. logo = &LogoutPayload; // load into stack buffer,
  3055. // then BIG-ENDIAN switch a copy to caller
  3056. logo->cmd = LS_LOGO;
  3057. // load the 3 UCHARs of the node name
  3058. // (if private loop, upper two UCHARs 0)
  3059. logo->reserved = 0;
  3060. logo->n_port_identifier[0] = (UCHAR)(fcChip->Registers.my_al_pa);
  3061. logo->n_port_identifier[1] =
  3062. (UCHAR)(fcChip->Registers.my_al_pa>>8);
  3063. logo->n_port_identifier[2] =
  3064. (UCHAR)(fcChip->Registers.my_al_pa>>16);
  3065. // fill in with World Wide Name based Port Name - 8 UCHARs
  3066. // get from Tach registers WWN hi & lo
  3067. LoadWWN( fcChip, logo->port_name, 0);
  3068. BigEndianSwap( (UCHAR*)&LogoutPayload,
  3069. payload, sizeof(LogoutPayload) ); // 16 UCHAR struct
  3070. break;
  3071. case ELS_LOGO_ACC: // Logout Accept (FH-PH pg 149, table 74)
  3072. logo = &LogoutPayload; // load into stack buffer,
  3073. // then BIG-ENDIAN switch a copy to caller
  3074. logo->cmd = LS_ACC;
  3075. BigEndianSwap( (UCHAR*)&LogoutPayload, payload, 4 ); // 4 UCHAR cmnd
  3076. break;
  3077. case ELS_RJT: // ELS_RJT link service reject (FH-PH pg 155)
  3078. prjt = (REJECT_MESSAGE*)payload; // pick up passed data
  3079. rjt.command_code = ELS_RJT;
  3080. // reverse fields, because of Swap that follows...
  3081. rjt.vendor = prjt->reserved; // vendor specific
  3082. rjt.explain = prjt->reason; //
  3083. rjt.reason = prjt->explain; //
  3084. rjt.reserved = prjt->vendor; //
  3085. // BIG-ENDIAN switch a copy to caller
  3086. BigEndianSwap( (UCHAR*)&rjt, payload, 8 ); // 8 UCHAR cmnd
  3087. break;
  3088. case ELS_PRLI_ACC: // Process Login ACCept
  3089. case ELS_PRLI: // Process Login
  3090. case ELS_PRLO: // Process Logout
  3091. memset( &PrliPayload, 0, sizeof( PrliPayload));
  3092. prli = &PrliPayload; // load into stack buffer,
  3093. if( type == ELS_PRLI )
  3094. prli->cmd = 0x20; // Login
  3095. else if( type == ELS_PRLO )
  3096. prli->cmd = 0x21; // Logout
  3097. else if( type == ELS_PRLI_ACC )
  3098. {
  3099. prli->cmd = 0x02; // Login ACCept
  3100. prli->valid = REQUEST_EXECUTED;
  3101. }
  3102. prli->valid |= SCSI_FCP | ESTABLISH_PAIR;
  3103. prli->fcp_info = READ_XFER_RDY;
  3104. prli->page_length = 0x10;
  3105. prli->payload_length = 20;
  3106. // Can be initiator AND target
  3107. if( fcChip->Options.initiator )
  3108. prli->fcp_info |= INITIATOR_FUNCTION;
  3109. if( fcChip->Options.target )
  3110. prli->fcp_info |= TARGET_FUNCTION;
  3111. BigEndianSwap( (UCHAR*)&PrliPayload, payload, prli->payload_length);
  3112. break;
  3113. default: // no can do - programming error
  3114. printk(" BuildLinkServicePayload unknown!\n");
  3115. break;
  3116. }
  3117. }
  3118. // loads 8 UCHARs for PORT name or NODE name base on
  3119. // controller's WWN.
  3120. void LoadWWN( PTACHYON fcChip, UCHAR* dest, UCHAR type)
  3121. {
  3122. UCHAR* bPtr, i;
  3123. switch( type )
  3124. {
  3125. case 0: // Port_Name
  3126. bPtr = (UCHAR*)&fcChip->Registers.wwn_hi;
  3127. for( i =0; i<4; i++)
  3128. dest[i] = *bPtr++;
  3129. bPtr = (UCHAR*)&fcChip->Registers.wwn_lo;
  3130. for( i =4; i<8; i++)
  3131. dest[i] = *bPtr++;
  3132. break;
  3133. case 1: // Node/Fabric _Name
  3134. bPtr = (UCHAR*)&fcChip->Registers.wwn_hi;
  3135. for( i =0; i<4; i++)
  3136. dest[i] = *bPtr++;
  3137. bPtr = (UCHAR*)&fcChip->Registers.wwn_lo;
  3138. for( i =4; i<8; i++)
  3139. dest[i] = *bPtr++;
  3140. break;
  3141. }
  3142. }
  3143. // We check the Port Login payload for required values. Note that
  3144. // ELS_PLOGI and ELS_PDISC (Port DISCover) use the same payload.
  3145. int verify_PLOGI( PTACHYON fcChip,
  3146. TachFCHDR_GCMND* fchs,
  3147. ULONG* reject_explain)
  3148. {
  3149. LOGIN_PAYLOAD login;
  3150. // source, dest, len (should be mult. of 4)
  3151. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&login, sizeof(login));
  3152. // check FC version
  3153. // if other port's highest supported version
  3154. // is less than our lowest, and
  3155. // if other port's lowest
  3156. if( login.cmn_services.highest_ver < fcChip->lowest_FCPH_ver ||
  3157. login.cmn_services.lowest_ver > fcChip->highest_FCPH_ver )
  3158. {
  3159. *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, OPTIONS_ERROR);
  3160. return LOGICAL_ERROR;
  3161. }
  3162. // Receive Data Field Size must be >=128
  3163. // per FC-PH
  3164. if (login.cmn_services.bb_rx_size < 128)
  3165. {
  3166. *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, DATA_FIELD_SIZE_ERROR);
  3167. return LOGICAL_ERROR;
  3168. }
  3169. // Only check Class 3 params
  3170. if( login.class3.service_options & CLASS_VALID)
  3171. {
  3172. if (login.class3.rx_data_size < 128)
  3173. {
  3174. *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, INVALID_CSP);
  3175. return LOGICAL_ERROR;
  3176. }
  3177. if( login.class3.initiator_control & XID_REQUIRED)
  3178. {
  3179. *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, INITIATOR_CTL_ERROR);
  3180. return LOGICAL_ERROR;
  3181. }
  3182. }
  3183. return 0; // success
  3184. }
  3185. int verify_PRLI( TachFCHDR_GCMND* fchs, ULONG* reject_explain)
  3186. {
  3187. PRLI_REQUEST prli; // buffer for BIG ENDIAN
  3188. // source, dest, len (should be mult. of 4)
  3189. BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&prli, sizeof(prli));
  3190. if( prli.fcp_info == 0 ) // i.e., not target or initiator?
  3191. {
  3192. *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, OPTIONS_ERROR);
  3193. return LOGICAL_ERROR;
  3194. }
  3195. return 0; // success
  3196. }
  3197. // SWAP UCHARs as required by Fibre Channel (i.e. BIG ENDIAN)
  3198. // INPUTS:
  3199. // source - ptr to LITTLE ENDIAN ULONGS
  3200. // cnt - number of UCHARs to switch (should be mult. of ULONG)
  3201. // OUTPUTS:
  3202. // dest - ptr to BIG ENDIAN copy
  3203. // RETURN:
  3204. // none
  3205. //
  3206. void BigEndianSwap( UCHAR *source, UCHAR *dest, USHORT cnt)
  3207. {
  3208. int i,j;
  3209. source+=3; // start at MSB of 1st ULONG
  3210. for( j=0; j < cnt; j+=4, source+=4, dest+=4) // every ULONG
  3211. {
  3212. for( i=0; i<4; i++) // every UCHAR in ULONG
  3213. *(dest+i) = *(source-i);
  3214. }
  3215. }
  3216. // Build FC Exchanges............
  3217. static void buildFCPstatus(
  3218. PTACHYON fcChip,
  3219. ULONG ExchangeID);
  3220. static LONG FindFreeExchange( PTACHYON fcChip, ULONG type );
  3221. static ULONG build_SEST_sgList(
  3222. struct pci_dev *pcidev,
  3223. ULONG *SESTalPairStart,
  3224. Scsi_Cmnd *Cmnd,
  3225. ULONG *sgPairs,
  3226. PSGPAGES *sgPages_head // link list of TL Ext. S/G pages from O/S Pool
  3227. );
  3228. static int build_FCP_payload( Scsi_Cmnd *Cmnd,
  3229. UCHAR* payload, ULONG type, ULONG fcp_dl );
  3230. /*
  3231. IRB
  3232. ERQ __________________
  3233. | | / | Req_A_SFS_Len | ____________________
  3234. |----------| / | Req_A_SFS_Addr |------->| Reserved |
  3235. | IRB | / | Req_A_D_ID | | SOF EOF TimeStamp |
  3236. |-----------/ | Req_A_SEST_Index |-+ | R_CTL | D_ID |
  3237. | IRB | | Req_B... | | | CS_CTL| S_ID |
  3238. |-----------\ | | | | TYPE | F_CTL |
  3239. | IRB | \ | | | | SEQ_ID | SEQ_CNT |
  3240. |----------- \ | | +-->+--| OX_ID | RX_ID |
  3241. | | \ |__________________| | | RO |
  3242. | | pl (payload/cmnd) |
  3243. | | ..... |
  3244. | |___________________|
  3245. |
  3246. |
  3247. +-------------------------------------------+
  3248. |
  3249. |
  3250. | e.g. IWE
  3251. | SEST __________________ for FCP_DATA
  3252. | | | / | | Hdr_Len | ____________________
  3253. | |----------| / | Hdr_Addr_Addr |------->| Reserved |
  3254. | | [0] | / |Remote_ID| RSP_Len| | SOF EOF TimeStamp |
  3255. | |-----------/ | RSP_Addr |---+ | R_CTL | D_ID |
  3256. +-> [1] | | | Buff_Off | | | CS_CTL| S_ID |
  3257. |-----------\ |BuffIndex| Link | | | TYPE | F_CTL |
  3258. | [2] | \ | Rsvd | RX_ID | | | SEQ_ID | SEQ_CNT |
  3259. |----------- \ | Data_Len | | | OX_ID | RX_ID |
  3260. | ... | \ | Exp_RO | | | RO |
  3261. |----------| | Exp_Byte_Cnt | | |___________________|
  3262. | SEST_LEN | +--| Len | |
  3263. |__________| | | Address | |
  3264. | | ... | | for FCP_RSP
  3265. | |__________________| | ____________________
  3266. | +----| Reserved |
  3267. | | SOF EOF TimeStamp |
  3268. | | R_CTL | D_ID |
  3269. | | CS_CTL| S_ID |
  3270. +--- local or extended | .... |
  3271. scatter/gather lists
  3272. defining upper-layer
  3273. data (e.g. from user's App)
  3274. */
  3275. // All TachLite commands must start with a SFS (Single Frame Sequence)
  3276. // command. In the simplest case (a NOP Basic Link command),
  3277. // only one frame header and ERQ entry is required. The most complex
  3278. // case is the SCSI assisted command, which requires an ERQ entry,
  3279. // SEST entry, and several frame headers and data buffers all
  3280. // logically linked together.
  3281. // Inputs:
  3282. // cpqfcHBAdata - controller struct
  3283. // type - PLOGI, SCSI_IWE, etc.
  3284. // InFCHS - Incoming Tachlite FCHS which prompted this exchange
  3285. // (only s_id set if we are originating)
  3286. // Data - PVOID to data struct consistent with "type"
  3287. // fcExchangeIndex - pointer to OX/RD ID value of built exchange
  3288. // Return:
  3289. // fcExchangeIndex - OX/RD ID value if successful
  3290. // 0 - success
  3291. // INVALID_ARGS - NULL/ invalid passed args
  3292. // BAD_ALPA - Bad source al_pa address
  3293. // LNKDWN_OSLS - Link Down (according to this controller)
  3294. // OUTQUE_FULL - Outbound Que full
  3295. // DRIVERQ_FULL - controller's Exchange array full
  3296. // SEST_FULL - SEST table full
  3297. //
  3298. // Remarks:
  3299. // Psuedo code:
  3300. // Check for NULL pointers / bad args
  3301. // Build outgoing FCHS - the header/payload struct
  3302. // Build IRB (for ERQ entry)
  3303. // if SCSI command, build SEST entry (e.g. IWE, TRE,...)
  3304. // return success
  3305. //sbuildex
  3306. ULONG cpqfcTSBuildExchange(
  3307. CPQFCHBA *cpqfcHBAdata,
  3308. ULONG type, // e.g. PLOGI
  3309. TachFCHDR_GCMND* InFCHS, // incoming FCHS
  3310. void *Data, // the CDB, scatter/gather, etc.
  3311. LONG *fcExchangeIndex ) // points to allocated exchange,
  3312. {
  3313. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  3314. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  3315. ULONG ulStatus = 0; // assume OK
  3316. USHORT ox_ID, rx_ID=0xFFFF;
  3317. ULONG SfsLen=0L;
  3318. TachLiteIRB* pIRB;
  3319. IRBflags IRB_flags;
  3320. UCHAR *pIRB_flags = (UCHAR*)&IRB_flags;
  3321. TachFCHDR_GCMND* CMDfchs;
  3322. TachFCHDR* dataHDR; // 32 byte HEADER ONLY FCP-DATA buffer
  3323. TachFCHDR_RSP* rspHDR; // 32 byte header + RSP payload
  3324. Scsi_Cmnd *Cmnd = (Scsi_Cmnd*)Data; // Linux Scsi CDB, S/G, ...
  3325. TachLiteIWE* pIWE;
  3326. TachLiteIRE* pIRE;
  3327. TachLiteTWE* pTWE;
  3328. TachLiteTRE* pTRE;
  3329. ULONG fcp_dl; // total byte length of DATA transferred
  3330. ULONG fl; // frame length (FC frame size, 128, 256, 512, 1024)
  3331. ULONG sgPairs; // number of valid scatter/gather pairs
  3332. int FCP_SCSI_command;
  3333. BA_ACC_PAYLOAD *ba_acc;
  3334. BA_RJT_PAYLOAD *ba_rjt;
  3335. // check passed ARGS
  3336. if( !fcChip->ERQ ) // NULL ptr means uninitialized Tachlite chip
  3337. return INVALID_ARGS;
  3338. if( type == SCSI_IRE ||
  3339. type == SCSI_TRE ||
  3340. type == SCSI_IWE ||
  3341. type == SCSI_TWE)
  3342. FCP_SCSI_command = 1;
  3343. else
  3344. FCP_SCSI_command = 0;
  3345. // for commands that pass payload data (e.g. SCSI write)
  3346. // examine command struct - verify that the
  3347. // length of s/g buffers is adequate for total payload
  3348. // length (end of list is NULL address)
  3349. if( FCP_SCSI_command )
  3350. {
  3351. if( Data ) // must have data descriptor (S/G list -- at least
  3352. // one address with at least 1 byte of data)
  3353. {
  3354. // something to do (later)?
  3355. }
  3356. else
  3357. return INVALID_ARGS; // invalid DATA ptr
  3358. }
  3359. // we can build an Exchange for later Queuing (on the TL chip)
  3360. // if an empty slot is available in the DevExt for this controller
  3361. // look for available Exchange slot...
  3362. if( type != FCP_RESPONSE &&
  3363. type != BLS_ABTS &&
  3364. type != BLS_ABTS_ACC ) // already have Exchange slot!
  3365. *fcExchangeIndex = FindFreeExchange( fcChip, type );
  3366. if( *fcExchangeIndex != -1 ) // Exchange is available?
  3367. {
  3368. // assign tmp ptr (shorthand)
  3369. CMDfchs = &Exchanges->fcExchange[ *fcExchangeIndex].fchs;
  3370. if( Cmnd != NULL ) // (necessary for ABTS cases)
  3371. {
  3372. Exchanges->fcExchange[ *fcExchangeIndex].Cmnd = Cmnd; // Linux Scsi
  3373. Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort =
  3374. fcFindLoggedInPort( fcChip,
  3375. Exchanges->fcExchange[ *fcExchangeIndex].Cmnd, // find Scsi Nexus
  3376. 0, // DON'T search linked list for FC port id
  3377. NULL, // DON'T search linked list for FC WWN
  3378. NULL); // DON'T care about end of list
  3379. }
  3380. // Build the command frame header (& data) according
  3381. // to command type
  3382. // fields common for all SFS frame types
  3383. CMDfchs->reserved = 0L; // must clear
  3384. CMDfchs->sof_eof = 0x75000000L; // SOFi3:EOFn no UAM; LCr=0, no TS
  3385. // get the destination port_id from incoming FCHS
  3386. // (initialized before calling if we're Originator)
  3387. // Frame goes to port it was from - the source_id
  3388. CMDfchs->d_id = InFCHS->s_id &0xFFFFFF; // destination (add R_CTL later)
  3389. CMDfchs->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
  3390. // now enter command-specific fields
  3391. switch( type )
  3392. {
  3393. case BLS_NOP: // FC defined basic link service command NO-OP
  3394. // ensure unique X_IDs! (use tracking function)
  3395. *pIRB_flags = 0; // clear IRB flags
  3396. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3397. SfsLen = *pIRB_flags;
  3398. SfsLen <<= 24; // shift flags to MSB
  3399. SfsLen += 32L; // add len to LSB (header only - no payload)
  3400. // TYPE[31-24] 00 Basic Link Service
  3401. // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
  3402. CMDfchs->d_id |= 0x80000000L; // R_CTL = 80 for NOP (Basic Link Ser.)
  3403. CMDfchs->f_ctl = 0x00310000L; // xchng originator, 1st seq,....
  3404. CMDfchs->seq_cnt = 0x0L;
  3405. CMDfchs->ox_rx_id = 0xFFFF; // RX_ID for now; OX_ID on start
  3406. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3407. CMDfchs->pl[0] = 0xaabbccddL; // words 8-15 frame data payload (n/a)
  3408. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 1; // seconds
  3409. // (NOP should complete ~instantly)
  3410. break;
  3411. case BLS_ABTS_ACC: // Abort Sequence ACCept
  3412. *pIRB_flags = 0; // clear IRB flags
  3413. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3414. SfsLen = *pIRB_flags;
  3415. SfsLen <<= 24; // shift flags to MSB
  3416. SfsLen += 32 + 12; // add len to LSB (header + 3 DWORD payload)
  3417. CMDfchs->d_id |= 0x84000000L; // R_CTL = 84 for BASIC ACCept
  3418. // TYPE[31-24] 00 Basic Link Service
  3419. // f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
  3420. CMDfchs->f_ctl = 0x00910000L; // xchnge responder, last seq, xfer SI
  3421. // CMDfchs->seq_id & count might be set from DataHdr?
  3422. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3423. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 5; // seconds
  3424. // (Timeout in case of weird error)
  3425. // now set the ACCept payload...
  3426. ba_acc = (BA_ACC_PAYLOAD*)&CMDfchs->pl[0];
  3427. memset( ba_acc, 0, sizeof( BA_ACC_PAYLOAD));
  3428. // Since PLDA requires (only) entire Exchange aborts, we don't need
  3429. // to worry about what the last sequence was.
  3430. // We expect that a "target" task is accepting the abort, so we
  3431. // can use the OX/RX ID pair
  3432. ba_acc->ox_rx_id = CMDfchs->ox_rx_id;
  3433. // source, dest, #bytes
  3434. BigEndianSwap((UCHAR *)&CMDfchs->ox_rx_id, (UCHAR *)&ba_acc->ox_rx_id, 4);
  3435. ba_acc->low_seq_cnt = 0;
  3436. ba_acc->high_seq_cnt = 0xFFFF;
  3437. break;
  3438. case BLS_ABTS_RJT: // Abort Sequence ACCept
  3439. *pIRB_flags = 0; // clear IRB flags
  3440. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3441. SfsLen = *pIRB_flags;
  3442. SfsLen <<= 24; // shift flags to MSB
  3443. SfsLen += 32 + 12; // add len to LSB (header + 3 DWORD payload)
  3444. CMDfchs->d_id |= 0x85000000L; // R_CTL = 85 for BASIC ReJecT
  3445. // f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
  3446. // TYPE[31-24] 00 Basic Link Service
  3447. CMDfchs->f_ctl = 0x00910000L; // xchnge responder, last seq, xfer SI
  3448. // CMDfchs->seq_id & count might be set from DataHdr?
  3449. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3450. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 5; // seconds
  3451. // (Timeout in case of weird error)
  3452. CMDfchs->ox_rx_id = InFCHS->ox_rx_id; // copy from sender!
  3453. // now set the ReJecT payload...
  3454. ba_rjt = (BA_RJT_PAYLOAD*)&CMDfchs->pl[0];
  3455. memset( ba_rjt, 0, sizeof( BA_RJT_PAYLOAD));
  3456. // We expect that a "target" task couldn't find the Exhange in the
  3457. // array of active exchanges, so we use a new LinkService X_ID.
  3458. // See Reject payload description in FC-PH (Rev 4.3), pg. 140
  3459. ba_rjt->reason_code = 0x09; // "unable to perform command request"
  3460. ba_rjt->reason_explain = 0x03; // invalid OX/RX ID pair
  3461. break;
  3462. case BLS_ABTS: // FC defined basic link service command ABTS
  3463. // Abort Sequence
  3464. *pIRB_flags = 0; // clear IRB flags
  3465. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3466. SfsLen = *pIRB_flags;
  3467. SfsLen <<= 24; // shift flags to MSB
  3468. SfsLen += 32L; // add len to LSB (header only - no payload)
  3469. // TYPE[31-24] 00 Basic Link Service
  3470. // f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
  3471. CMDfchs->d_id |= 0x81000000L; // R_CTL = 81 for ABTS
  3472. CMDfchs->f_ctl = 0x00110000L; // xchnge originator, last seq, xfer SI
  3473. // CMDfchs->seq_id & count might be set from DataHdr?
  3474. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3475. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds
  3476. // (ABTS must timeout when responder is gone)
  3477. break;
  3478. case FCS_NSR: // Fabric Name Service Request
  3479. Exchanges->fcExchange[ *fcExchangeIndex].reTries = 2;
  3480. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds
  3481. // OX_ID, linked to Driver Transaction ID
  3482. // (fix-up at Queing time)
  3483. CMDfchs->ox_rx_id = 0xFFFF; // RX_ID - Responder (target) to modify
  3484. // OX_ID set at ERQueing time
  3485. *pIRB_flags = 0; // clear IRB flags
  3486. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3487. SfsLen = *pIRB_flags;
  3488. SfsLen <<= 24; // shift flags to MSB
  3489. SfsLen += (32L + sizeof(NSR_PL)); // add len (header & NSR payload)
  3490. CMDfchs->d_id |= 0x02000000L; // R_CTL = 02 for -
  3491. // Name Service Request: Unsolicited
  3492. // TYPE[31-24] 01 Extended Link Service
  3493. // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
  3494. CMDfchs->f_ctl = 0x20210000L;
  3495. // OX_ID will be fixed-up at Tachyon enqueing time
  3496. CMDfchs->seq_cnt = 0; // seq ID, DF_ctl, seq cnt
  3497. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3498. BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]);
  3499. break;
  3500. case ELS_PLOGI: // FC-PH extended link service command Port Login
  3501. // (May, 2000)
  3502. // NOTE! This special case facilitates SANMark testing. The SANMark
  3503. // test script for initialization-timeout.fcal.SANMark-1.fc
  3504. // "eats" the OPN() primitive without issuing an R_RDY, causing
  3505. // Tachyon to report LST (loop state timeout), which causes a
  3506. // LIP. To avoid this, simply send out the frame (i.e. assuming a
  3507. // buffer credit of 1) without waiting for R_RDY. Many FC devices
  3508. // (other than Tachyon) have been doing this for years. We don't
  3509. // ever want to do this for non-Link Service frames unless the
  3510. // other device really did report non-zero login BB credit (i.e.
  3511. // in the PLOGI ACCept frame).
  3512. // CMDfchs->sof_eof |= 0x00000400L; // LCr=1
  3513. case ELS_FDISC: // Fabric Discovery (Login)
  3514. case ELS_FLOGI: // Fabric Login
  3515. case ELS_SCR: // Fabric State Change Registration
  3516. case ELS_LOGO: // FC-PH extended link service command Port Logout
  3517. case ELS_PDISC: // FC-PH extended link service cmnd Port Discovery
  3518. case ELS_PRLI: // FC-PH extended link service cmnd Process Login
  3519. Exchanges->fcExchange[ *fcExchangeIndex].reTries = 2;
  3520. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds
  3521. // OX_ID, linked to Driver Transaction ID
  3522. // (fix-up at Queing time)
  3523. CMDfchs->ox_rx_id = 0xFFFF; // RX_ID - Responder (target) to modify
  3524. // OX_ID set at ERQueing time
  3525. *pIRB_flags = 0; // clear IRB flags
  3526. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3527. SfsLen = *pIRB_flags;
  3528. SfsLen <<= 24; // shift flags to MSB
  3529. if( type == ELS_LOGO )
  3530. SfsLen += (32L + 16L); // add len (header & PLOGI payload)
  3531. else if( type == ELS_PRLI )
  3532. SfsLen += (32L + 20L); // add len (header & PRLI payload)
  3533. else if( type == ELS_SCR )
  3534. SfsLen += (32L + sizeof(SCR_PL)); // add len (header & SCR payload)
  3535. else
  3536. SfsLen += (32L + 116L); // add len (header & PLOGI payload)
  3537. CMDfchs->d_id |= 0x22000000L; // R_CTL = 22 for -
  3538. // Extended Link_Data: Unsolicited Control
  3539. // TYPE[31-24] 01 Extended Link Service
  3540. // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
  3541. CMDfchs->f_ctl = 0x01210000L;
  3542. // OX_ID will be fixed-up at Tachyon enqueing time
  3543. CMDfchs->seq_cnt = 0; // seq ID, DF_ctl, seq cnt
  3544. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3545. BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]);
  3546. break;
  3547. case ELS_LOGO_ACC: // FC-PH extended link service logout accept
  3548. case ELS_RJT: // extended link service reject (add reason)
  3549. case ELS_ACC: // ext. link service generic accept
  3550. case ELS_PLOGI_ACC:// ext. link service login accept (PLOGI or PDISC)
  3551. case ELS_PRLI_ACC: // ext. link service process login accept
  3552. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 1; // assume done
  3553. // ensure unique X_IDs! (use tracking function)
  3554. // OX_ID from initiator cmd
  3555. ox_ID = (USHORT)(InFCHS->ox_rx_id >> 16);
  3556. rx_ID = 0xFFFF; // RX_ID, linked to Driver Exchange ID
  3557. *pIRB_flags = 0; // clear IRB flags
  3558. IRB_flags.SFA = 1; // send SFS (not SEST index)
  3559. SfsLen = *pIRB_flags;
  3560. SfsLen <<= 24; // shift flags to MSB
  3561. if( type == ELS_RJT )
  3562. {
  3563. SfsLen += (32L + 8L); // add len (header + payload)
  3564. // ELS_RJT reason codes (utilize unused "reserved" field)
  3565. CMDfchs->pl[0] = 1;
  3566. CMDfchs->pl[1] = InFCHS->reserved;
  3567. }
  3568. else if( (type == ELS_LOGO_ACC) || (type == ELS_ACC) )
  3569. SfsLen += (32L + 4L); // add len (header + payload)
  3570. else if( type == ELS_PLOGI_ACC )
  3571. SfsLen += (32L + 116L); // add len (header + payload)
  3572. else if( type == ELS_PRLI_ACC )
  3573. SfsLen += (32L + 20L); // add len (header + payload)
  3574. CMDfchs->d_id |= 0x23000000L; // R_CTL = 23 for -
  3575. // Extended Link_Data: Control Reply
  3576. // TYPE[31-24] 01 Extended Link Service
  3577. // f_ctl[23:0] exchg responder, last seq, e_s, tsi
  3578. CMDfchs->f_ctl = 0x01990000L;
  3579. CMDfchs->seq_cnt = 0x0L;
  3580. CMDfchs->ox_rx_id = 0L; // clear
  3581. CMDfchs->ox_rx_id = ox_ID; // load upper 16 bits
  3582. CMDfchs->ox_rx_id <<= 16; // shift them
  3583. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3584. BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]);
  3585. break;
  3586. // Fibre Channel SCSI 'originator' sequences...
  3587. // (originator means 'initiator' in FCP-SCSI)
  3588. case SCSI_IWE: // TachLite Initiator Write Entry
  3589. {
  3590. PFC_LOGGEDIN_PORT pLoggedInPort =
  3591. Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort;
  3592. Exchanges->fcExchange[ *fcExchangeIndex].reTries = 1;
  3593. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 7; // FC2 timeout
  3594. // first, build FCP_CMND
  3595. // unique X_ID fix-ups in StartExchange
  3596. *pIRB_flags = 0; // clear IRB flags
  3597. IRB_flags.SFA = 1; // send SFS FCP-CMND (not SEST index)
  3598. // NOTE: unlike FC LinkService login frames, normal
  3599. // SCSI commands are sent without outgoing verification
  3600. IRB_flags.DCM = 1; // Disable completion message for Cmnd frame
  3601. SfsLen = *pIRB_flags;
  3602. SfsLen <<= 24; // shift flags to MSB
  3603. SfsLen += 64L; // add len to LSB (header & CMND payload)
  3604. CMDfchs->d_id |= (0x06000000L); // R_CTL = 6 for command
  3605. // TYPE[31-24] 8 for FCP SCSI
  3606. // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
  3607. // valid RO
  3608. CMDfchs->f_ctl = 0x08210008L;
  3609. CMDfchs->seq_cnt = 0x0L;
  3610. CMDfchs->ox_rx_id = 0L; // clear for now (-or- in later)
  3611. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3612. // now, fill out FCP-DATA header
  3613. // (use buffer inside SEST object)
  3614. dataHDR = &fcChip->SEST->DataHDR[ *fcExchangeIndex ];
  3615. dataHDR->reserved = 0L; // must clear
  3616. dataHDR->sof_eof = 0x75002000L; // SOFi3:EOFn no UAM; no CLS, noLCr, no TS
  3617. dataHDR->d_id = (InFCHS->s_id | 0x01000000L); // R_CTL= FCP_DATA
  3618. dataHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
  3619. // TYPE[31-24] 8 for FCP SCSI
  3620. // f_ctl[23:0] xfer S.I.| valid RO
  3621. dataHDR->f_ctl = 0x08010008L;
  3622. dataHDR->seq_cnt = 0x02000000L; // sequence ID: df_ctl : seqence count
  3623. dataHDR->ox_rx_id = 0L; // clear; fix-up dataHDR fields later
  3624. dataHDR->ro = 0x0L; // relative offset (n/a)
  3625. // Now setup the SEST entry
  3626. pIWE = &fcChip->SEST->u[ *fcExchangeIndex ].IWE;
  3627. // fill out the IWE:
  3628. // VALid entry:Dir outbound:DCM:enable CM:enal INT: FC frame len
  3629. pIWE->Hdr_Len = 0x8e000020L; // data frame Len always 32 bytes
  3630. // from login parameters with other port, what's the largest frame
  3631. // we can send?
  3632. if( pLoggedInPort == NULL)
  3633. {
  3634. ulStatus = INVALID_ARGS; // failed! give up
  3635. break;
  3636. }
  3637. if( pLoggedInPort->rx_data_size >= 2048)
  3638. fl = 0x00020000; // 2048 code (only support 1024!)
  3639. else if( pLoggedInPort->rx_data_size >= 1024)
  3640. fl = 0x00020000; // 1024 code
  3641. else if( pLoggedInPort->rx_data_size >= 512)
  3642. fl = 0x00010000; // 512 code
  3643. else
  3644. fl = 0; // 128 bytes -- should never happen
  3645. pIWE->Hdr_Len |= fl; // add xmit FC frame len for data phase
  3646. pIWE->Hdr_Addr = fcChip->SEST->base +
  3647. ((unsigned long)&fcChip->SEST->DataHDR[*fcExchangeIndex] -
  3648. (unsigned long)fcChip->SEST);
  3649. pIWE->RSP_Len = sizeof(TachFCHDR_RSP) ; // hdr+data (recv'd RSP frame)
  3650. pIWE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
  3651. memset( &fcChip->SEST->RspHDR[ *fcExchangeIndex].pl, 0,
  3652. sizeof( FCP_STATUS_RESPONSE) ); // clear out previous status
  3653. pIWE->RSP_Addr = fcChip->SEST->base +
  3654. ((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] -
  3655. (unsigned long)fcChip->SEST);
  3656. // Do we need local or extended gather list?
  3657. // depends on size - we can handle 3 len/addr pairs
  3658. // locally.
  3659. fcp_dl = build_SEST_sgList(
  3660. cpqfcHBAdata->PciDev,
  3661. &pIWE->GLen1,
  3662. Cmnd, // S/G list
  3663. &sgPairs, // return # of pairs in S/G list (from "Data" descriptor)
  3664. &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
  3665. if( !fcp_dl ) // error building S/G list?
  3666. {
  3667. ulStatus = MEMPOOL_FAIL;
  3668. break; // give up
  3669. }
  3670. // Now that we know total data length in
  3671. // the passed S/G buffer, set FCP CMND frame
  3672. build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl );
  3673. if( sgPairs > 3 ) // need extended s/g list
  3674. pIWE->Buff_Off = 0x78000000L; // extended data | (no offset)
  3675. else // local data pointers (in SEST)
  3676. pIWE->Buff_Off = 0xf8000000L; // local data | (no offset)
  3677. // ULONG 5
  3678. pIWE->Link = 0x0000ffffL; // Buff_Index | Link
  3679. pIWE->RX_ID = 0x0L; // DWord 6: RX_ID set by target XFER_RDY
  3680. // DWord 7
  3681. pIWE->Data_Len = 0L; // TL enters rcv'd XFER_RDY BURST_LEN
  3682. pIWE->Exp_RO = 0L; // DWord 8
  3683. // DWord 9
  3684. pIWE->Exp_Byte_Cnt = fcp_dl; // sum of gather buffers
  3685. }
  3686. break;
  3687. case SCSI_IRE: // TachLite Initiator Read Entry
  3688. if( Cmnd->timeout != 0)
  3689. {
  3690. // printk("Cmnd->timeout %d\n", Cmnd->timeout);
  3691. // per Linux Scsi
  3692. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = Cmnd->timeout;
  3693. }
  3694. else // use our best guess, based on FC & device
  3695. {
  3696. if( Cmnd->SCp.Message == 1 ) // Tape device? (from INQUIRY)
  3697. {
  3698. // turn off our timeouts (for now...)
  3699. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 0xFFFFFFFF;
  3700. }
  3701. else
  3702. {
  3703. Exchanges->fcExchange[ *fcExchangeIndex].reTries = 1;
  3704. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 7; // per SCSI req.
  3705. }
  3706. }
  3707. // first, build FCP_CMND
  3708. *pIRB_flags = 0; // clear IRB flags
  3709. IRB_flags.SFA = 1; // send SFS FCP-CMND (not SEST index)
  3710. // NOTE: unlike FC LinkService login frames,
  3711. // normal SCSI commands are sent "open loop"
  3712. IRB_flags.DCM = 1; // Disable completion message for Cmnd frame
  3713. SfsLen = *pIRB_flags;
  3714. SfsLen <<= 24; // shift flags to MSB
  3715. SfsLen += 64L; // add len to LSB (header & CMND payload)
  3716. CMDfchs->d_id |= (0x06000000L); // R_CTL = 6 for command
  3717. // TYPE[31-24] 8 for FCP SCSI
  3718. // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
  3719. // valid RO
  3720. CMDfchs->f_ctl = 0x08210008L;
  3721. CMDfchs->seq_cnt = 0x0L;
  3722. // x_ID & data direction bit set later
  3723. CMDfchs->ox_rx_id = 0xFFFF; // clear
  3724. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3725. // Now setup the SEST entry
  3726. pIRE = &fcChip->SEST->u[ *fcExchangeIndex ].IRE;
  3727. // fill out the IRE:
  3728. // VALid entry:Dir outbound:enable CM:enal INT:
  3729. pIRE->Seq_Accum = 0xCE000000L; // VAL,DIR inbound,DCM| INI,DAT,RSP
  3730. pIRE->reserved = 0L;
  3731. pIRE->RSP_Len = sizeof(TachFCHDR_RSP) ; // hdr+data (recv'd RSP frame)
  3732. pIRE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
  3733. pIRE->RSP_Addr = fcChip->SEST->base +
  3734. ((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] -
  3735. (unsigned long)fcChip->SEST);
  3736. // Do we need local or extended gather list?
  3737. // depends on size - we can handle 3 len/addr pairs
  3738. // locally.
  3739. fcp_dl = build_SEST_sgList(
  3740. cpqfcHBAdata->PciDev,
  3741. &pIRE->SLen1,
  3742. Cmnd, // SCSI command Data desc. with S/G list
  3743. &sgPairs, // return # of pairs in S/G list (from "Data" descriptor)
  3744. &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
  3745. if( !fcp_dl ) // error building S/G list?
  3746. {
  3747. // It is permissible to have a ZERO LENGTH Read command.
  3748. // If there is the case, simply set fcp_dl (and Exp_Byte_Cnt)
  3749. // to 0 and continue.
  3750. if( Cmnd->request_bufflen == 0 )
  3751. {
  3752. fcp_dl = 0; // no FC DATA frames expected
  3753. }
  3754. else
  3755. {
  3756. ulStatus = MEMPOOL_FAIL;
  3757. break; // give up
  3758. }
  3759. }
  3760. // now that we know the S/G length, build CMND payload
  3761. build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl );
  3762. if( sgPairs > 3 ) // need extended s/g list
  3763. pIRE->Buff_Off = 0x00000000; // DWord 4: extended s/g list, no offset
  3764. else
  3765. pIRE->Buff_Off = 0x80000000; // local data, no offset
  3766. pIRE->Buff_Index = 0x0L; // DWord 5: Buff_Index | Reserved
  3767. pIRE->Exp_RO = 0x0L; // DWord 6: Expected Rel. Offset
  3768. pIRE->Byte_Count = 0; // DWord 7: filled in by TL on err
  3769. pIRE->reserved_ = 0; // DWord 8: reserved
  3770. // NOTE: 0 length READ is OK.
  3771. pIRE->Exp_Byte_Cnt = fcp_dl;// DWord 9: sum of scatter buffers
  3772. break;
  3773. // Fibre Channel SCSI 'responder' sequences...
  3774. // (originator means 'target' in FCP-SCSI)
  3775. case SCSI_TWE: // TachLite Target Write Entry
  3776. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 10; // per SCSI req.
  3777. // first, build FCP_CMND
  3778. *pIRB_flags = 0; // clear IRB flags
  3779. IRB_flags.SFA = 1; // send SFS (XFER_RDY)
  3780. SfsLen = *pIRB_flags;
  3781. SfsLen <<= 24; // shift flags to MSB
  3782. SfsLen += (32L + 12L);// add SFS len (header & XFER_RDY payload)
  3783. CMDfchs->d_id |= (0x05000000L); // R_CTL = 5 for XFER_RDY
  3784. // TYPE[31-24] 8 for FCP SCSI
  3785. // f_ctl[23:0] exchg responder, 1st seq, xfer S.I.
  3786. // valid RO
  3787. CMDfchs->f_ctl = 0x08810008L;
  3788. CMDfchs->seq_cnt = 0x01000000; // sequence ID: df_ctl: sequence count
  3789. // use originator (other port's) OX_ID
  3790. CMDfchs->ox_rx_id = InFCHS->ox_rx_id; // we want upper 16 bits
  3791. CMDfchs->ro = 0x0L; // relative offset (n/a)
  3792. // now, fill out FCP-RSP header
  3793. // (use buffer inside SEST object)
  3794. rspHDR = &fcChip->SEST->RspHDR[ *fcExchangeIndex ];
  3795. rspHDR->reserved = 0L; // must clear
  3796. rspHDR->sof_eof = 0x75000000L; // SOFi3:EOFn no UAM; no CLS, noLCr, no TS
  3797. rspHDR->d_id = (InFCHS->s_id | 0x07000000L); // R_CTL= FCP_RSP
  3798. rspHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
  3799. // TYPE[31-24] 8 for FCP SCSI
  3800. // f_ctl[23:0] responder|last seq| xfer S.I.
  3801. rspHDR->f_ctl = 0x08910000L;
  3802. rspHDR->seq_cnt = 0x03000000; // sequence ID
  3803. rspHDR->ox_rx_id = InFCHS->ox_rx_id; // gives us OX_ID
  3804. rspHDR->ro = 0x0L; // relative offset (n/a)
  3805. // Now setup the SEST entry
  3806. pTWE = &fcChip->SEST->u[ *fcExchangeIndex ].TWE;
  3807. // fill out the TWE:
  3808. // VALid entry:Dir outbound:enable CM:enal INT:
  3809. pTWE->Seq_Accum = 0xC4000000L; // upper word flags
  3810. pTWE->reserved = 0L;
  3811. pTWE->Remote_Node_ID = 0L; // no more auto RSP frame! (TL/TS change)
  3812. pTWE->Remote_Node_ID |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
  3813. // Do we need local or extended gather list?
  3814. // depends on size - we can handle 3 len/addr pairs
  3815. // locally.
  3816. fcp_dl = build_SEST_sgList(
  3817. cpqfcHBAdata->PciDev,
  3818. &pTWE->SLen1,
  3819. Cmnd, // S/G list
  3820. &sgPairs, // return # of pairs in S/G list (from "Data" descriptor)
  3821. &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
  3822. if( !fcp_dl ) // error building S/G list?
  3823. {
  3824. ulStatus = MEMPOOL_FAIL;
  3825. break; // give up
  3826. }
  3827. // now that we know the S/G length, build CMND payload
  3828. build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl );
  3829. if( sgPairs > 3 ) // need extended s/g list
  3830. pTWE->Buff_Off = 0x00000000; // extended s/g list, no offset
  3831. else
  3832. pTWE->Buff_Off = 0x80000000; // local data, no offset
  3833. pTWE->Buff_Index = 0; // Buff_Index | Link
  3834. pTWE->Exp_RO = 0;
  3835. pTWE->Byte_Count = 0; // filled in by TL on err
  3836. pTWE->reserved_ = 0;
  3837. pTWE->Exp_Byte_Cnt = fcp_dl;// sum of scatter buffers
  3838. break;
  3839. case SCSI_TRE: // TachLite Target Read Entry
  3840. // It doesn't make much sense for us to "time-out" a READ,
  3841. // but we'll use it for design consistency and internal error recovery.
  3842. Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 10; // per SCSI req.
  3843. // I/O request block settings...
  3844. *pIRB_flags = 0; // clear IRB flags
  3845. // check PRLI (process login) info
  3846. // to see if Initiator Requires XFER_RDY
  3847. // if not, don't send one!
  3848. // { PRLI check...}
  3849. IRB_flags.SFA = 0; // don't send XFER_RDY - start data
  3850. SfsLen = *pIRB_flags;
  3851. SfsLen <<= 24; // shift flags to MSB
  3852. SfsLen += (32L + 12L);// add SFS len (header & XFER_RDY payload)
  3853. // now, fill out FCP-DATA header
  3854. // (use buffer inside SEST object)
  3855. dataHDR = &fcChip->SEST->DataHDR[ *fcExchangeIndex ];
  3856. dataHDR->reserved = 0L; // must clear
  3857. dataHDR->sof_eof = 0x75000000L; // SOFi3:EOFn no UAM; no CLS,noLCr,no TS
  3858. dataHDR->d_id = (InFCHS->s_id | 0x01000000L); // R_CTL= FCP_DATA
  3859. dataHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
  3860. // TYPE[31-24] 8 for FCP SCSI
  3861. // f_ctl[23:0] exchg responder, not 1st seq, xfer S.I.
  3862. // valid RO
  3863. dataHDR->f_ctl = 0x08810008L;
  3864. dataHDR->seq_cnt = 0x01000000; // sequence ID (no XRDY)
  3865. dataHDR->ox_rx_id = InFCHS->ox_rx_id & 0xFFFF0000; // we want upper 16 bits
  3866. dataHDR->ro = 0x0L; // relative offset (n/a)
  3867. // now, fill out FCP-RSP header
  3868. // (use buffer inside SEST object)
  3869. rspHDR = &fcChip->SEST->RspHDR[ *fcExchangeIndex ];
  3870. rspHDR->reserved = 0L; // must clear
  3871. rspHDR->sof_eof = 0x75000000L; // SOFi3:EOFn no UAM; no CLS, noLCr, no TS
  3872. rspHDR->d_id = (InFCHS->s_id | 0x07000000L); // R_CTL= FCP_RSP
  3873. rspHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
  3874. // TYPE[31-24] 8 for FCP SCSI
  3875. // f_ctl[23:0] responder|last seq| xfer S.I.
  3876. rspHDR->f_ctl = 0x08910000L;
  3877. rspHDR->seq_cnt = 0x02000000; // sequence ID: df_ctl: sequence count
  3878. rspHDR->ro = 0x0L; // relative offset (n/a)
  3879. // Now setup the SEST entry
  3880. pTRE = &fcChip->SEST->u[ *fcExchangeIndex ].TRE;
  3881. // VALid entry:Dir outbound:enable CM:enal INT:
  3882. pTRE->Hdr_Len = 0x86010020L; // data frame Len always 32 bytes
  3883. pTRE->Hdr_Addr = // bus address of dataHDR;
  3884. fcChip->SEST->base +
  3885. ((unsigned long)&fcChip->SEST->DataHDR[ *fcExchangeIndex ] -
  3886. (unsigned long)fcChip->SEST);
  3887. pTRE->RSP_Len = 64L; // hdr+data (TL assisted RSP frame)
  3888. pTRE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
  3889. pTRE->RSP_Addr = // bus address of rspHDR
  3890. fcChip->SEST->base +
  3891. ((unsigned long)&fcChip->SEST->RspHDR[ *fcExchangeIndex ] -
  3892. (unsigned long)fcChip->SEST);
  3893. // Do we need local or extended gather list?
  3894. // depends on size - we can handle 3 len/addr pairs
  3895. // locally.
  3896. fcp_dl = build_SEST_sgList(
  3897. cpqfcHBAdata->PciDev,
  3898. &pTRE->GLen1,
  3899. Cmnd, // S/G list
  3900. &sgPairs, // return # of pairs in S/G list (from "Data" descriptor)
  3901. &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
  3902. if( !fcp_dl ) // error building S/G list?
  3903. {
  3904. ulStatus = MEMPOOL_FAIL;
  3905. break; // give up
  3906. }
  3907. // no payload or command to build -- READ doesn't need XRDY
  3908. if( sgPairs > 3 ) // need extended s/g list
  3909. pTRE->Buff_Off = 0x78000000L; // extended data | (no offset)
  3910. else // local data pointers (in SEST)
  3911. pTRE->Buff_Off = 0xf8000000L; // local data | (no offset)
  3912. // ULONG 5
  3913. pTRE->Buff_Index = 0L; // Buff_Index | reserved
  3914. pTRE->reserved = 0x0L; // DWord 6
  3915. // DWord 7: NOTE: zero length will
  3916. // hang TachLite!
  3917. pTRE->Data_Len = fcp_dl; // e.g. sum of scatter buffers
  3918. pTRE->reserved_ = 0L; // DWord 8
  3919. pTRE->reserved__ = 0L; // DWord 9
  3920. break;
  3921. case FCP_RESPONSE:
  3922. // Target response frame: this sequence uses an OX/RX ID
  3923. // pair from a completed SEST exchange. We built most
  3924. // of the response frame when we created the TWE/TRE.
  3925. *pIRB_flags = 0; // clear IRB flags
  3926. IRB_flags.SFA = 1; // send SFS (RSP)
  3927. SfsLen = *pIRB_flags;
  3928. SfsLen <<= 24; // shift flags to MSB
  3929. SfsLen += sizeof(TachFCHDR_RSP);// add SFS len (header & RSP payload)
  3930. Exchanges->fcExchange[ *fcExchangeIndex].type =
  3931. FCP_RESPONSE; // change Exchange type to "response" phase
  3932. // take advantage of prior knowledge of OX/RX_ID pair from
  3933. // previous XFER outbound frame (still in fchs of exchange)
  3934. fcChip->SEST->RspHDR[ *fcExchangeIndex ].ox_rx_id =
  3935. CMDfchs->ox_rx_id;
  3936. // Check the status of the DATA phase of the exchange so we can report
  3937. // status to the initiator
  3938. buildFCPstatus( fcChip, *fcExchangeIndex); // set RSP payload fields
  3939. memcpy(
  3940. CMDfchs, // re-use same XFER fchs for Response frame
  3941. &fcChip->SEST->RspHDR[ *fcExchangeIndex ],
  3942. sizeof( TachFCHDR_RSP ));
  3943. break;
  3944. default:
  3945. printk("cpqfcTS: don't know how to build FC type: %Xh(%d)\n", type,type);
  3946. break;
  3947. }
  3948. if( !ulStatus) // no errors above?
  3949. {
  3950. // FCHS is built; now build IRB
  3951. // link the just built FCHS (the "command") to the IRB entry
  3952. // for this Exchange.
  3953. pIRB = &Exchanges->fcExchange[ *fcExchangeIndex].IRB;
  3954. // len & flags according to command type above
  3955. pIRB->Req_A_SFS_Len = SfsLen; // includes IRB flags & len
  3956. pIRB->Req_A_SFS_Addr = // TL needs physical addr of frame to send
  3957. fcChip->exch_dma_handle + (unsigned long)CMDfchs -
  3958. (unsigned long)Exchanges;
  3959. pIRB->Req_A_SFS_D_ID = CMDfchs->d_id << 8; // Dest_ID must be consistent!
  3960. // Exchange is complete except for "fix-up" fields to be set
  3961. // at Tachyon Queuing time:
  3962. // IRB->Req_A_Trans_ID (OX_ID/ RX_ID):
  3963. // for SEST entry, lower bits correspond to actual FC Exchange ID
  3964. // fchs->OX_ID or RX_ID
  3965. }
  3966. else
  3967. {
  3968. #ifdef DBG
  3969. printk( "FC Error: SEST build Pool Allocation failed\n");
  3970. #endif
  3971. // return resources...
  3972. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, *fcExchangeIndex); // SEST build failed
  3973. }
  3974. }
  3975. else // no Exchanges available
  3976. {
  3977. ulStatus = SEST_FULL;
  3978. printk( "FC Error: no fcExchanges available\n");
  3979. }
  3980. return ulStatus;
  3981. }
  3982. // set RSP payload fields
  3983. static void buildFCPstatus( PTACHYON fcChip, ULONG ExchangeID)
  3984. {
  3985. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  3986. FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID]; // shorthand
  3987. PFCP_STATUS_RESPONSE pFcpStatus;
  3988. memset( &fcChip->SEST->RspHDR[ ExchangeID ].pl, 0,
  3989. sizeof( FCP_STATUS_RESPONSE) );
  3990. if( pExchange->status ) // something wrong?
  3991. {
  3992. pFcpStatus = (PFCP_STATUS_RESPONSE) // cast RSP buffer for this xchng
  3993. &fcChip->SEST->RspHDR[ ExchangeID ].pl;
  3994. if( pExchange->status & COUNT_ERROR )
  3995. {
  3996. // set FCP response len valid (so we can report count error)
  3997. pFcpStatus->fcp_status |= FCP_RSP_LEN_VALID;
  3998. pFcpStatus->fcp_rsp_len = 0x04000000; // 4 byte len (BIG Endian)
  3999. pFcpStatus->fcp_rsp_info = FCP_DATA_LEN_NOT_BURST_LEN; // RSP_CODE
  4000. }
  4001. }
  4002. }
  4003. static dma_addr_t
  4004. cpqfc_pci_map_sg_page(
  4005. struct pci_dev *pcidev,
  4006. ULONG *hw_paddr, // where to put phys addr for HW use
  4007. void *sgp_vaddr, // the virtual address of the sg page
  4008. dma_addr_t *umap_paddr, // where to put phys addr for unmap
  4009. unsigned int *maplen, // where to store sg entry length
  4010. int PairCount) // number of sg pairs used in the page.
  4011. {
  4012. unsigned long aligned_addr = (unsigned long) sgp_vaddr;
  4013. *maplen = PairCount * 8;
  4014. aligned_addr += TL_EXT_SG_PAGE_BYTELEN;
  4015. aligned_addr &= ~(TL_EXT_SG_PAGE_BYTELEN -1);
  4016. *umap_paddr = pci_map_single(pcidev, (void *) aligned_addr,
  4017. *maplen, PCI_DMA_TODEVICE);
  4018. *hw_paddr = (ULONG) *umap_paddr;
  4019. # if BITS_PER_LONG > 32
  4020. if( *umap_paddr >>32 ) {
  4021. printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n",
  4022. (void*)umap_paddr);
  4023. return 0;
  4024. }
  4025. # endif
  4026. return *umap_paddr;
  4027. }
  4028. static void
  4029. cpqfc_undo_SEST_mappings(struct pci_dev *pcidev,
  4030. unsigned long contigaddr, int len, int dir,
  4031. struct scatterlist *sgl, int use_sg,
  4032. PSGPAGES *sgPages_head,
  4033. int allocated_pages)
  4034. {
  4035. PSGPAGES i, next;
  4036. if (contigaddr != (unsigned long) NULL)
  4037. pci_unmap_single(pcidev, contigaddr, len, dir);
  4038. if (sgl != NULL)
  4039. pci_unmap_sg(pcidev, sgl, use_sg, dir);
  4040. for (i=*sgPages_head; i != NULL ;i = next)
  4041. {
  4042. pci_unmap_single(pcidev, i->busaddr, i->maplen,
  4043. PCI_DMA_TODEVICE);
  4044. i->busaddr = (dma_addr_t) NULL;
  4045. i->maplen = 0L;
  4046. next = i->next;
  4047. kfree(i);
  4048. }
  4049. *sgPages_head = NULL;
  4050. }
  4051. // This routine builds scatter/gather lists into SEST entries
  4052. // INPUTS:
  4053. // SESTalPair - SEST address @DWordA "Local Buffer Length"
  4054. // sgList - Scatter/Gather linked list of Len/Address data buffers
  4055. // OUTPUT:
  4056. // sgPairs - number of valid address/length pairs
  4057. // Remarks:
  4058. // The SEST data buffer pointers only depend on number of
  4059. // length/ address pairs, NOT on the type (IWE, TRE,...)
  4060. // Up to 3 pairs can be referenced in the SEST - more than 3
  4061. // require this Extended S/G list page. The page holds 4, 8, 16...
  4062. // len/addr pairs, per Scatter/Gather List Page Length Reg.
  4063. // TachLite allows pages to be linked to any depth.
  4064. //#define DBG_SEST_SGLIST 1 // for printing out S/G pairs with Ext. pages
  4065. static int ap_hi_water = TL_DANGER_SGPAGES;
  4066. static ULONG build_SEST_sgList(
  4067. struct pci_dev *pcidev,
  4068. ULONG *SESTalPairStart, // the 3 len/address buffers in SEST
  4069. Scsi_Cmnd *Cmnd,
  4070. ULONG *sgPairs,
  4071. PSGPAGES *sgPages_head) // link list of TL Ext. S/G pages from O/S Pool
  4072. {
  4073. ULONG i, AllocatedPages=0; // Tach Ext. S/G page allocations
  4074. ULONG* alPair = SESTalPairStart;
  4075. ULONG* ext_sg_page_phys_addr_place = NULL;
  4076. int PairCount;
  4077. unsigned long ulBuff, contigaddr;
  4078. ULONG total_data_len=0; // (in bytes)
  4079. ULONG bytes_to_go = Cmnd->request_bufflen; // total xfer (S/G sum)
  4080. ULONG thisMappingLen;
  4081. struct scatterlist *sgl = NULL; // S/G list (Linux format)
  4082. int sg_count, totalsgs;
  4083. dma_addr_t busaddr;
  4084. unsigned long thislen, offset;
  4085. PSGPAGES *sgpage = sgPages_head;
  4086. PSGPAGES prev_page = NULL;
  4087. # define WE_HAVE_SG_LIST (sgl != (unsigned long) NULL)
  4088. contigaddr = (unsigned long) NULL;
  4089. if( !Cmnd->use_sg ) // no S/G list?
  4090. {
  4091. if (bytes_to_go <= TL_MAX_SG_ELEM_LEN)
  4092. {
  4093. *sgPairs = 1; // use "local" S/G pair in SEST entry
  4094. // (for now, ignore address bits above #31)
  4095. *alPair++ = bytes_to_go; // bits 18-0, length
  4096. if (bytes_to_go != 0) {
  4097. contigaddr = ulBuff = pci_map_single(pcidev,
  4098. Cmnd->request_buffer,
  4099. Cmnd->request_bufflen,
  4100. Cmnd->sc_data_direction);
  4101. // printk("ms %p ", ulBuff);
  4102. }
  4103. else {
  4104. // No data transfer, (e.g.: Test Unit Ready)
  4105. // printk("btg=0 ");
  4106. *sgPairs = 0;
  4107. memset(alPair, 0, sizeof(*alPair));
  4108. return 0;
  4109. }
  4110. # if BITS_PER_LONG > 32
  4111. if( ulBuff >>32 ) {
  4112. printk("FATAL! Tachyon DMA address %p "
  4113. "exceeds 32 bits\n", (void*)ulBuff );
  4114. return 0;
  4115. }
  4116. # endif
  4117. *alPair = (ULONG)ulBuff;
  4118. return bytes_to_go;
  4119. }
  4120. else // We have a single large (too big) contiguous buffer.
  4121. { // We will have to break it up. We'll use the scatter
  4122. // gather code way below, but use contigaddr instead
  4123. // of sg_dma_addr(). (this is a very rare case).
  4124. unsigned long btg;
  4125. contigaddr = pci_map_single(pcidev, Cmnd->request_buffer,
  4126. Cmnd->request_bufflen,
  4127. Cmnd->sc_data_direction);
  4128. // printk("contigaddr = %p, len = %d\n",
  4129. // (void *) contigaddr, bytes_to_go);
  4130. totalsgs = 0;
  4131. for (btg = bytes_to_go; btg > 0; ) {
  4132. btg -= ( btg > TL_MAX_SG_ELEM_LEN ?
  4133. TL_MAX_SG_ELEM_LEN : btg );
  4134. totalsgs++;
  4135. }
  4136. sgl = NULL;
  4137. *sgPairs = totalsgs;
  4138. }
  4139. }
  4140. else // we do have a scatter gather list
  4141. {
  4142. // [TBD - update for Linux to support > 32 bits addressing]
  4143. // since the format for local & extended S/G lists is different,
  4144. // check if S/G pairs exceeds 3.
  4145. // *sgPairs = Cmnd->use_sg; Nope, that's wrong.
  4146. sgl = (struct scatterlist*)Cmnd->request_buffer;
  4147. sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg,
  4148. Cmnd->sc_data_direction);
  4149. if( sg_count <= 3 ) {
  4150. // we need to be careful here that no individual mapping
  4151. // is too large, and if any is, that breaking it up
  4152. // doesn't push us over 3 sgs, or, if it does, that we
  4153. // handle that case. Tachyon can take 0x7FFFF bits for length,
  4154. // but sg structure uses "unsigned int", on the face of it,
  4155. // up to 0xFFFFFFFF or even more.
  4156. int i;
  4157. unsigned long thislen;
  4158. totalsgs = 0;
  4159. for (i=0;i<sg_count;i++) {
  4160. thislen = sg_dma_len(&sgl[i]);
  4161. while (thislen >= TL_MAX_SG_ELEM_LEN) {
  4162. totalsgs++;
  4163. thislen -= TL_MAX_SG_ELEM_LEN;
  4164. }
  4165. if (thislen > 0) totalsgs++;
  4166. }
  4167. *sgPairs = totalsgs;
  4168. } else totalsgs = 999; // as a first estimate, definitely >3,
  4169. // if (totalsgs != sg_count)
  4170. // printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
  4171. }
  4172. if( totalsgs <= 3 ) // can (must) use "local" SEST list
  4173. {
  4174. while( bytes_to_go)
  4175. {
  4176. offset = 0L;
  4177. if ( WE_HAVE_SG_LIST )
  4178. thisMappingLen = sg_dma_len(sgl);
  4179. else // or contiguous buffer?
  4180. thisMappingLen = bytes_to_go;
  4181. while (thisMappingLen > 0)
  4182. {
  4183. thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ?
  4184. TL_MAX_SG_ELEM_LEN : thisMappingLen;
  4185. bytes_to_go = bytes_to_go - thislen;
  4186. // we have L/A pair; L = thislen, A = physicalAddress
  4187. // load into SEST...
  4188. total_data_len += thislen;
  4189. *alPair = thislen; // bits 18-0, length
  4190. alPair++;
  4191. if ( WE_HAVE_SG_LIST )
  4192. ulBuff = sg_dma_address(sgl) + offset;
  4193. else
  4194. ulBuff = contigaddr + offset;
  4195. offset += thislen;
  4196. # if BITS_PER_LONG > 32
  4197. if( ulBuff >>32 ) {
  4198. printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n",
  4199. (void*)ulBuff );
  4200. printk("%s = %p, offset = %ld\n",
  4201. WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr",
  4202. WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr,
  4203. offset);
  4204. return 0;
  4205. }
  4206. # endif
  4207. *alPair++ = (ULONG)ulBuff; // lower 32 bits (31-0)
  4208. thisMappingLen -= thislen;
  4209. }
  4210. if ( WE_HAVE_SG_LIST ) ++sgl; // next S/G pair
  4211. else if (bytes_to_go != 0) printk("BTG not zero!\n");
  4212. # ifdef DBG_SEST_SGLIST
  4213. printk("L=%d ", thisMappingLen);
  4214. printk("btg=%d ", bytes_to_go);
  4215. # endif
  4216. }
  4217. // printk("i:%d\n", *sgPairs);
  4218. }
  4219. else // more than 3 pairs requires Extended S/G page (Pool Allocation)
  4220. {
  4221. // clear out SEST DWORDs (local S/G addr) C-F (A-B set in following logic)
  4222. for( i=2; i<6; i++)
  4223. alPair[i] = 0;
  4224. PairCount = TL_EXT_SG_PAGE_COUNT; // forces initial page allocation
  4225. totalsgs = 0;
  4226. while( bytes_to_go )
  4227. {
  4228. // Per SEST format, we can support 524287 byte lengths per
  4229. // S/G pair. Typical user buffers are 4k, and very rarely
  4230. // exceed 12k due to fragmentation of physical memory pages.
  4231. // However, on certain O/S system (not "user") buffers (on platforms
  4232. // with huge memories), it's possible to exceed this
  4233. // length in a single S/G address/len mapping, so we have to handle
  4234. // that.
  4235. offset = 0L;
  4236. if ( WE_HAVE_SG_LIST )
  4237. thisMappingLen = sg_dma_len(sgl);
  4238. else
  4239. thisMappingLen = bytes_to_go;
  4240. while (thisMappingLen > 0)
  4241. {
  4242. thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ?
  4243. TL_MAX_SG_ELEM_LEN : thisMappingLen;
  4244. // printk("%d/%d/%d\n", thislen, thisMappingLen, bytes_to_go);
  4245. // should we load into "this" extended S/G page, or allocate
  4246. // new page?
  4247. if( PairCount >= TL_EXT_SG_PAGE_COUNT )
  4248. {
  4249. // Now, we have to map the previous page, (triggering buffer bounce)
  4250. // The first time thru the loop, there won't be a previous page.
  4251. if (prev_page != NULL) // is there a prev page?
  4252. {
  4253. // this code is normally kind of hard to trigger,
  4254. // you have to use up more than 256 scatter gather
  4255. // elements to get here. Cranking down TL_MAX_SG_ELEM_LEN
  4256. // to an absurdly low value (128 bytes or so) to artificially
  4257. // break i/o's into a zillion pieces is how I tested it.
  4258. busaddr = cpqfc_pci_map_sg_page(pcidev,
  4259. ext_sg_page_phys_addr_place,
  4260. prev_page->page,
  4261. &prev_page->busaddr,
  4262. &prev_page->maplen,
  4263. PairCount);
  4264. }
  4265. // Allocate the TL Extended S/G list page. We have
  4266. // to allocate twice what we want to ensure required TL alignment
  4267. // (Tachlite TL/TS User Man. Rev 6.0, p 168)
  4268. // We store the original allocated PVOID so we can free later
  4269. *sgpage = kmalloc( sizeof(SGPAGES), GFP_ATOMIC);
  4270. if ( ! *sgpage )
  4271. {
  4272. printk("cpqfc: Allocation failed @ %d S/G page allocations\n",
  4273. AllocatedPages);
  4274. total_data_len = 0; // failure!! Ext. S/G is All-or-none affair
  4275. // unmap the previous mappings, if any.
  4276. cpqfc_undo_SEST_mappings(pcidev, contigaddr,
  4277. Cmnd->request_bufflen,
  4278. Cmnd->sc_data_direction,
  4279. sgl, Cmnd->use_sg, sgPages_head, AllocatedPages+1);
  4280. // FIXME: testing shows that if we get here,
  4281. // it's bad news. (this has been this way for a long
  4282. // time though, AFAIK. Not that that excuses it.)
  4283. return 0; // give up (and probably hang the system)
  4284. }
  4285. // clear out memory we just allocated
  4286. memset( (*sgpage)->page,0,TL_EXT_SG_PAGE_BYTELEN*2);
  4287. (*sgpage)->next = NULL;
  4288. (*sgpage)->busaddr = (dma_addr_t) NULL;
  4289. (*sgpage)->maplen = 0L;
  4290. // align the memory - TL requires sizeof() Ext. S/G page alignment.
  4291. // We doubled the actual required size so we could mask off LSBs
  4292. // to get desired offset
  4293. ulBuff = (unsigned long) (*sgpage)->page;
  4294. ulBuff += TL_EXT_SG_PAGE_BYTELEN;
  4295. ulBuff &= ~(TL_EXT_SG_PAGE_BYTELEN -1);
  4296. // set pointer, in SEST if first Ext. S/G page, or in last pair
  4297. // of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just
  4298. // load lower 32 bits)
  4299. // NOTE: the Len field must be '0' if this is the first Ext. S/G
  4300. // pointer in SEST, and not 0 otherwise (we know thislen != 0).
  4301. *alPair = (alPair != SESTalPairStart) ? thislen : 0;
  4302. # ifdef DBG_SEST_SGLIST
  4303. printk("PairCount %d @%p even %Xh, ",
  4304. PairCount, alPair, *alPair);
  4305. # endif
  4306. // Save the place where we need to store the physical
  4307. // address of this scatter gather page which we get when we map it
  4308. // (and mapping we can do only after we fill it in.)
  4309. alPair++; // next DWORD, will contain phys addr of the ext page
  4310. ext_sg_page_phys_addr_place = alPair;
  4311. // Now, set alPair = the virtual addr of the (Extended) S/G page
  4312. // which will accept the Len/ PhysicalAddress pairs
  4313. alPair = (ULONG *) ulBuff;
  4314. AllocatedPages++;
  4315. if (AllocatedPages >= ap_hi_water)
  4316. {
  4317. // This message should rarely, if ever, come out.
  4318. // Previously (cpqfc version <= 2.0.5) the driver would
  4319. // just puke if more than 4 SG pages were used, and nobody
  4320. // ever complained about that. This only comes out if
  4321. // more than 8 pages are used.
  4322. printk(KERN_WARNING
  4323. "cpqfc: Possible danger. %d scatter gather pages used.\n"
  4324. "cpqfc: detected seemingly extreme memory "
  4325. "fragmentation or huge data transfers.\n",
  4326. AllocatedPages);
  4327. ap_hi_water = AllocatedPages+1;
  4328. }
  4329. PairCount = 1; // starting new Ext. S/G page
  4330. prev_page = (*sgpage); // remember this page, for next time thru
  4331. sgpage = &((*sgpage)->next);
  4332. } // end of new TL Ext. S/G page allocation
  4333. *alPair = thislen; // bits 18-0, length (range check above)
  4334. # ifdef DBG_SEST_SGLIST
  4335. printk("PairCount %d @%p, even %Xh, ", PairCount, alPair, *alPair);
  4336. # endif
  4337. alPair++; // next DWORD, physical address
  4338. if ( WE_HAVE_SG_LIST )
  4339. ulBuff = sg_dma_address(sgl) + offset;
  4340. else
  4341. ulBuff = contigaddr + offset;
  4342. offset += thislen;
  4343. # if BITS_PER_LONG > 32
  4344. if( ulBuff >>32 )
  4345. {
  4346. printk("cqpfcTS: 1Tach DMA address %p > 32 bits\n", (void*)ulBuff );
  4347. printk("%s = %p, offset = %ld\n",
  4348. WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr",
  4349. WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr,
  4350. offset);
  4351. return 0;
  4352. }
  4353. # endif
  4354. *alPair = (ULONG) ulBuff; // lower 32 bits (31-0)
  4355. # ifdef DBG_SEST_SGLIST
  4356. printk("odd %Xh\n", *alPair);
  4357. # endif
  4358. alPair++; // next DWORD, next address/length pair
  4359. PairCount++; // next Length/Address pair
  4360. // if (PairCount > pc_hi_water)
  4361. // {
  4362. // printk("pc hi = %d ", PairCount);
  4363. // pc_hi_water = PairCount;
  4364. // }
  4365. bytes_to_go -= thislen;
  4366. total_data_len += thislen;
  4367. thisMappingLen -= thislen;
  4368. totalsgs++;
  4369. } // while (thisMappingLen > 0)
  4370. if ( WE_HAVE_SG_LIST ) sgl++; // next S/G pair
  4371. } // while (bytes_to_go)
  4372. // printk("Totalsgs=%d\n", totalsgs);
  4373. *sgPairs = totalsgs;
  4374. // PCI map (and bounce) the last (and usually only) extended SG page
  4375. busaddr = cpqfc_pci_map_sg_page(pcidev,
  4376. ext_sg_page_phys_addr_place,
  4377. prev_page->page,
  4378. &prev_page->busaddr,
  4379. &prev_page->maplen,
  4380. PairCount);
  4381. }
  4382. return total_data_len;
  4383. }
  4384. // The Tachlite SEST table is referenced to OX_ID (or RX_ID). To optimize
  4385. // performance and debuggability, we index the Exchange structure to FC X_ID
  4386. // This enables us to build exchanges for later en-queing to Tachyon,
  4387. // provided we have an open X_ID slot. At Tachyon queing time, we only
  4388. // need an ERQ slot; then "fix-up" references in the
  4389. // IRB, FCHS, etc. as needed.
  4390. // RETURNS:
  4391. // 0 if successful
  4392. // non-zero on error
  4393. //sstartex
  4394. ULONG cpqfcTSStartExchange(
  4395. CPQFCHBA *cpqfcHBAdata,
  4396. LONG ExchangeID )
  4397. {
  4398. PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  4399. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  4400. FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ ExchangeID ]; // shorthand
  4401. USHORT producer, consumer;
  4402. ULONG ulStatus=0;
  4403. short int ErqIndex;
  4404. BOOLEAN CompleteExchange = FALSE; // e.g. ACC replies are complete
  4405. BOOLEAN SestType=FALSE;
  4406. ULONG InboundData=0;
  4407. // We will manipulate Tachlite chip registers here to successfully
  4408. // start exchanges.
  4409. // Check that link is not down -- we can't start an exchange on a
  4410. // down link!
  4411. if( fcChip->Registers.FMstatus.value & 0x80) // LPSM offline?
  4412. {
  4413. printk("fcStartExchange: PSM offline (%Xh), x_ID %Xh, type %Xh, port_id %Xh\n",
  4414. fcChip->Registers.FMstatus.value & 0xFF,
  4415. ExchangeID,
  4416. pExchange->type,
  4417. pExchange->fchs.d_id);
  4418. if( ExchangeID >= TACH_SEST_LEN ) // Link Service Outbound frame?
  4419. {
  4420. // Our most popular LinkService commands are port discovery types
  4421. // (PLOGI/ PDISC...), which are implicitly nullified by Link Down
  4422. // events, so it makes no sense to Que them. However, ABTS should
  4423. // be queued, since exchange sequences are likely destroyed by
  4424. // Link Down events, and we want to notify other ports of broken
  4425. // sequences by aborting the corresponding exchanges.
  4426. if( pExchange->type != BLS_ABTS )
  4427. {
  4428. ulStatus = LNKDWN_OSLS;
  4429. goto Done;
  4430. // don't Que most LinkServ exchanges on LINK DOWN
  4431. }
  4432. }
  4433. printk("fcStartExchange: Que x_ID %Xh, type %Xh\n",
  4434. ExchangeID, pExchange->type);
  4435. pExchange->status |= EXCHANGE_QUEUED;
  4436. ulStatus = EXCHANGE_QUEUED;
  4437. goto Done;
  4438. }
  4439. // Make sure ERQ has available space.
  4440. producer = (USHORT)fcChip->ERQ->producerIndex; // copies for logical arith.
  4441. consumer = (USHORT)fcChip->ERQ->consumerIndex;
  4442. producer++; // We are testing for full que by incrementing
  4443. if( producer >= ERQ_LEN ) // rollover condition?
  4444. producer = 0;
  4445. if( consumer != producer ) // ERQ not full?
  4446. {
  4447. // ****************** Need Atomic access to chip registers!!********
  4448. // remember ERQ PI for copying IRB
  4449. ErqIndex = (USHORT)fcChip->ERQ->producerIndex;
  4450. fcChip->ERQ->producerIndex = producer; // this is written to Tachyon
  4451. // we have an ERQ slot! If SCSI command, need SEST slot
  4452. // otherwise we are done.
  4453. // Note that Tachyon requires that bit 15 of the OX_ID or RX_ID be
  4454. // set according to direction of data to/from Tachyon for SEST assists.
  4455. // For consistency, enforce this rule for Link Service (non-SEST)
  4456. // exchanges as well.
  4457. // fix-up the X_ID field in IRB
  4458. pExchange->IRB.Req_A_Trans_ID = ExchangeID & 0x7FFF; // 15-bit field
  4459. // fix-up the X_ID field in fchs -- depends on Originator or Responder,
  4460. // outgoing or incoming data?
  4461. switch( pExchange->type )
  4462. {
  4463. // ORIGINATOR types... we're setting our OX_ID and
  4464. // defaulting the responder's RX_ID to 0xFFFF
  4465. case SCSI_IRE:
  4466. // Requirement: set MSB of x_ID for Incoming TL data
  4467. // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
  4468. InboundData = 0x8000;
  4469. case SCSI_IWE:
  4470. SestType = TRUE;
  4471. pExchange->fchs.ox_rx_id = (ExchangeID | InboundData);
  4472. pExchange->fchs.ox_rx_id <<= 16; // MSW shift
  4473. pExchange->fchs.ox_rx_id |= 0xffff; // add default RX_ID
  4474. // now fix-up the Data HDR OX_ID (TL automatically does rx_id)
  4475. // (not necessary for IRE -- data buffer unused)
  4476. if( pExchange->type == SCSI_IWE)
  4477. {
  4478. fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id =
  4479. pExchange->fchs.ox_rx_id;
  4480. }
  4481. break;
  4482. case FCS_NSR: // ext. link service Name Service Request
  4483. case ELS_SCR: // ext. link service State Change Registration
  4484. case ELS_FDISC:// ext. link service login
  4485. case ELS_FLOGI:// ext. link service login
  4486. case ELS_LOGO: // FC-PH extended link service logout
  4487. case BLS_NOP: // Basic link service No OPeration
  4488. case ELS_PLOGI:// ext. link service login (PLOGI)
  4489. case ELS_PDISC:// ext. link service login (PDISC)
  4490. case ELS_PRLI: // ext. link service process login
  4491. pExchange->fchs.ox_rx_id = ExchangeID;
  4492. pExchange->fchs.ox_rx_id <<= 16; // MSW shift
  4493. pExchange->fchs.ox_rx_id |= 0xffff; // and RX_ID
  4494. break;
  4495. // RESPONDER types... we must set our RX_ID while preserving
  4496. // sender's OX_ID
  4497. // outgoing (or no) data
  4498. case ELS_RJT: // extended link service reject
  4499. case ELS_LOGO_ACC: // FC-PH extended link service logout accept
  4500. case ELS_ACC: // ext. generic link service accept
  4501. case ELS_PLOGI_ACC:// ext. link service login accept (PLOGI or PDISC)
  4502. case ELS_PRLI_ACC: // ext. link service process login accept
  4503. CompleteExchange = TRUE; // Reply (ACC or RJT) is end of exchange
  4504. pExchange->fchs.ox_rx_id |= (ExchangeID & 0xFFFF);
  4505. break;
  4506. // since we are a Responder, OX_ID should already be set by
  4507. // cpqfcTSBuildExchange(). We need to -OR- in RX_ID
  4508. case SCSI_TWE:
  4509. SestType = TRUE;
  4510. // Requirement: set MSB of x_ID for Incoming TL data
  4511. // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
  4512. pExchange->fchs.ox_rx_id &= 0xFFFF0000; // clear RX_ID
  4513. // Requirement: set MSB of RX_ID for Incoming TL data
  4514. // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
  4515. pExchange->fchs.ox_rx_id |= (ExchangeID | 0x8000);
  4516. break;
  4517. case SCSI_TRE:
  4518. SestType = TRUE;
  4519. // there is no XRDY for SEST target read; the data
  4520. // header needs to be updated. Also update the RSP
  4521. // exchange IDs for the status frame, in case it is sent automatically
  4522. fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id |= ExchangeID;
  4523. fcChip->SEST->RspHDR[ ExchangeID ].ox_rx_id =
  4524. fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id;
  4525. // for easier FCP response logic (works for TWE and TRE),
  4526. // copy exchange IDs. (Not needed if TRE 'RSP' bit set)
  4527. pExchange->fchs.ox_rx_id =
  4528. fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id;
  4529. break;
  4530. case FCP_RESPONSE: // using existing OX_ID/ RX_ID pair,
  4531. // start SFS FCP-RESPONSE frame
  4532. // OX/RX_ID should already be set! (See "fcBuild" above)
  4533. CompleteExchange = TRUE; // RSP is end of FCP-SCSI exchange
  4534. break;
  4535. case BLS_ABTS_RJT: // uses new RX_ID, since SEST x_ID non-existent
  4536. case BLS_ABTS_ACC: // using existing OX_ID/ RX_ID pair from SEST entry
  4537. CompleteExchange = TRUE; // ACC or RJT marks end of FCP-SCSI exchange
  4538. case BLS_ABTS: // using existing OX_ID/ RX_ID pair from SEST entry
  4539. break;
  4540. default:
  4541. printk("Error on fcStartExchange: undefined type %Xh(%d)\n",
  4542. pExchange->type, pExchange->type);
  4543. return INVALID_ARGS;
  4544. }
  4545. // X_ID fields are entered -- copy IRB to Tachyon's ERQ
  4546. memcpy(
  4547. &fcChip->ERQ->QEntry[ ErqIndex ], // dest.
  4548. &pExchange->IRB,
  4549. 32); // fixed (hardware) length!
  4550. PCI_TRACEO( ExchangeID, 0xA0)
  4551. // ACTION! May generate INT and IMQ entry
  4552. writel( fcChip->ERQ->producerIndex,
  4553. fcChip->Registers.ERQproducerIndex.address);
  4554. if( ExchangeID >= TACH_SEST_LEN ) // Link Service Outbound frame?
  4555. {
  4556. // wait for completion! (TDB -- timeout and chip reset)
  4557. PCI_TRACEO( ExchangeID, 0xA4)
  4558. enable_irq( cpqfcHBAdata->HostAdapter->irq); // only way to get Sem.
  4559. down_interruptible( cpqfcHBAdata->TYOBcomplete);
  4560. disable_irq( cpqfcHBAdata->HostAdapter->irq);
  4561. PCI_TRACE( 0xA4)
  4562. // On login exchanges, BAD_ALPA (non-existent port_id) results in
  4563. // FTO (Frame Time Out) on the Outbound Completion message.
  4564. // If we got an FTO status, complete the exchange (free up slot)
  4565. if( CompleteExchange || // flag from Reply frames
  4566. pExchange->status ) // typically, can get FRAME_TO
  4567. {
  4568. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);
  4569. }
  4570. }
  4571. else // SEST Exchange
  4572. {
  4573. ulStatus = 0; // ship & pray success (e.g. FCP-SCSI)
  4574. if( CompleteExchange ) // by Type of exchange (e.g. end-of-xchng)
  4575. {
  4576. cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);
  4577. }
  4578. else
  4579. pExchange->status &= ~EXCHANGE_QUEUED; // clear ExchangeQueued flag
  4580. }
  4581. }
  4582. else // ERQ 'producer' = 'consumer' and QUE is full
  4583. {
  4584. ulStatus = OUTQUE_FULL; // Outbound (ERQ) Que full
  4585. }
  4586. Done:
  4587. PCI_TRACE( 0xA0)
  4588. return ulStatus;
  4589. }
  4590. // Scan fcController->fcExchanges array for a usuable index (a "free"
  4591. // exchange).
  4592. // Inputs:
  4593. // fcChip - pointer to TachLite chip structure
  4594. // Return:
  4595. // index - exchange array element where exchange can be built
  4596. // -1 - exchange array is full
  4597. // REMARKS:
  4598. // Although this is a (yuk!) linear search, we presume
  4599. // that the system will complete exchanges about as quickly as
  4600. // they are submitted. A full Exchange array (and hence, max linear
  4601. // search time for free exchange slot) almost guarantees a Fibre problem
  4602. // of some sort.
  4603. // In the interest of making exchanges easier to debug, we want a LRU
  4604. // (Least Recently Used) scheme.
  4605. static LONG FindFreeExchange( PTACHYON fcChip, ULONG type )
  4606. {
  4607. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  4608. ULONG i;
  4609. ULONG ulStatus=-1; // assume failure
  4610. if( type == SCSI_IRE ||
  4611. type == SCSI_TRE ||
  4612. type == SCSI_IWE ||
  4613. type == SCSI_TWE)
  4614. {
  4615. // SCSI type - X_IDs should be from 0 to TACH_SEST_LEN-1
  4616. if( fcChip->fcSestExchangeLRU >= TACH_SEST_LEN) // rollover?
  4617. fcChip->fcSestExchangeLRU = 0;
  4618. i = fcChip->fcSestExchangeLRU; // typically it's already free!
  4619. if( Exchanges->fcExchange[i].type == 0 ) // check for "free" element
  4620. {
  4621. ulStatus = 0; // success!
  4622. }
  4623. else
  4624. { // YUK! we need to do a linear search for free element.
  4625. // Fragmentation of the fcExchange array is due to excessively
  4626. // long completions or timeouts.
  4627. while( TRUE )
  4628. {
  4629. if( ++i >= TACH_SEST_LEN ) // rollover check
  4630. i = 0; // beginning of SEST X_IDs
  4631. // printk( "looping for SCSI xchng ID: i=%d, type=%Xh\n",
  4632. // i, Exchanges->fcExchange[i].type);
  4633. if( Exchanges->fcExchange[i].type == 0 ) // "free"?
  4634. {
  4635. ulStatus = 0; // success!
  4636. break;
  4637. }
  4638. if( i == fcChip->fcSestExchangeLRU ) // wrapped-around array?
  4639. {
  4640. printk( "SEST X_ID space full\n");
  4641. break; // failed - prevent inf. loop
  4642. }
  4643. }
  4644. }
  4645. fcChip->fcSestExchangeLRU = i + 1; // next! (rollover check next pass)
  4646. }
  4647. else // Link Service type - X_IDs should be from TACH_SEST_LEN
  4648. // to TACH_MAX_XID
  4649. {
  4650. if( fcChip->fcLsExchangeLRU >= TACH_MAX_XID || // range check
  4651. fcChip->fcLsExchangeLRU < TACH_SEST_LEN ) // (e.g. startup)
  4652. fcChip->fcLsExchangeLRU = TACH_SEST_LEN;
  4653. i = fcChip->fcLsExchangeLRU; // typically it's already free!
  4654. if( Exchanges->fcExchange[i].type == 0 ) // check for "free" element
  4655. {
  4656. ulStatus = 0; // success!
  4657. }
  4658. else
  4659. { // YUK! we need to do a linear search for free element
  4660. // Fragmentation of the fcExchange array is due to excessively
  4661. // long completions or timeouts.
  4662. while( TRUE )
  4663. {
  4664. if( ++i >= TACH_MAX_XID ) // rollover check
  4665. i = TACH_SEST_LEN;// beginning of Link Service X_IDs
  4666. // printk( "looping for xchng ID: i=%d, type=%Xh\n",
  4667. // i, Exchanges->fcExchange[i].type);
  4668. if( Exchanges->fcExchange[i].type == 0 ) // "free"?
  4669. {
  4670. ulStatus = 0; // success!
  4671. break;
  4672. }
  4673. if( i == fcChip->fcLsExchangeLRU ) // wrapped-around array?
  4674. {
  4675. printk( "LinkService X_ID space full\n");
  4676. break; // failed - prevent inf. loop
  4677. }
  4678. }
  4679. }
  4680. fcChip->fcLsExchangeLRU = i + 1; // next! (rollover check next pass)
  4681. }
  4682. if( !ulStatus ) // success?
  4683. Exchanges->fcExchange[i].type = type; // allocate it.
  4684. else
  4685. i = -1; // error - all exchanges "open"
  4686. return i;
  4687. }
  4688. static void
  4689. cpqfc_pci_unmap_extended_sg(struct pci_dev *pcidev,
  4690. PTACHYON fcChip,
  4691. ULONG x_ID)
  4692. {
  4693. // Unmaps the memory regions used to hold the scatter gather lists
  4694. PSGPAGES i;
  4695. // Were there any such regions needing unmapping?
  4696. if (! USES_EXTENDED_SGLIST(fcChip->SEST, x_ID))
  4697. return; // No such regions, we're outta here.
  4698. // for each extended scatter gather region needing unmapping...
  4699. for (i=fcChip->SEST->sgPages[x_ID] ; i != NULL ; i = i->next)
  4700. pci_unmap_single(pcidev, i->busaddr, i->maplen,
  4701. PCI_DMA_TODEVICE);
  4702. }
  4703. // Called also from cpqfcTScontrol.o, so can't be static
  4704. void
  4705. cpqfc_pci_unmap(struct pci_dev *pcidev,
  4706. Scsi_Cmnd *cmd,
  4707. PTACHYON fcChip,
  4708. ULONG x_ID)
  4709. {
  4710. // Undo the DMA mappings
  4711. if (cmd->use_sg) { // Used scatter gather list for data buffer?
  4712. cpqfc_pci_unmap_extended_sg(pcidev, fcChip, x_ID);
  4713. pci_unmap_sg(pcidev, cmd->buffer, cmd->use_sg,
  4714. cmd->sc_data_direction);
  4715. // printk("umsg %d\n", cmd->use_sg);
  4716. }
  4717. else if (cmd->request_bufflen) {
  4718. // printk("ums %p ", fcChip->SEST->u[ x_ID ].IWE.GAddr1);
  4719. pci_unmap_single(pcidev, fcChip->SEST->u[ x_ID ].IWE.GAddr1,
  4720. cmd->request_bufflen,
  4721. cmd->sc_data_direction);
  4722. }
  4723. }
  4724. // We call this routine to free an Exchange for any reason:
  4725. // completed successfully, completed with error, aborted, etc.
  4726. // returns FALSE if Exchange failed and "retry" is acceptable
  4727. // returns TRUE if Exchange was successful, or retry is impossible
  4728. // (e.g. port/device gone).
  4729. //scompleteexchange
  4730. void cpqfcTSCompleteExchange(
  4731. struct pci_dev *pcidev,
  4732. PTACHYON fcChip,
  4733. ULONG x_ID)
  4734. {
  4735. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  4736. int already_unmapped = 0;
  4737. if( x_ID < TACH_SEST_LEN ) // SEST-based (or LinkServ for FCP exchange)
  4738. {
  4739. if( Exchanges->fcExchange[ x_ID ].Cmnd == NULL ) // what#@!
  4740. {
  4741. // TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
  4742. printk(" x_ID %Xh, type %Xh, NULL ptr!\n", x_ID,
  4743. Exchanges->fcExchange[ x_ID ].type);
  4744. goto CleanUpSestResources; // this path should be very rare.
  4745. }
  4746. // we have Linux Scsi Cmnd ptr..., now check our Exchange status
  4747. // to decide how to complete this SEST FCP exchange
  4748. if( Exchanges->fcExchange[ x_ID ].status ) // perhaps a Tach indicated problem,
  4749. // or abnormal exchange completion
  4750. {
  4751. // set FCP Link statistics
  4752. if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT)
  4753. fcChip->fcStats.timeouts++;
  4754. if( Exchanges->fcExchange[ x_ID ].status & INITIATOR_ABORT)
  4755. fcChip->fcStats.FC4aborted++;
  4756. if( Exchanges->fcExchange[ x_ID ].status & COUNT_ERROR)
  4757. fcChip->fcStats.CntErrors++;
  4758. if( Exchanges->fcExchange[ x_ID ].status & LINKFAIL_TX)
  4759. fcChip->fcStats.linkFailTX++;
  4760. if( Exchanges->fcExchange[ x_ID ].status & LINKFAIL_RX)
  4761. fcChip->fcStats.linkFailRX++;
  4762. if( Exchanges->fcExchange[ x_ID ].status & OVERFLOW)
  4763. fcChip->fcStats.CntErrors++;
  4764. // First, see if the Scsi upper level initiated an ABORT on this
  4765. // exchange...
  4766. if( Exchanges->fcExchange[ x_ID ].status == INITIATOR_ABORT )
  4767. {
  4768. printk(" DID_ABORT, x_ID %Xh, Cmnd %p ",
  4769. x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
  4770. goto CleanUpSestResources; // (we don't expect Linux _aborts)
  4771. }
  4772. // Did our driver timeout the Exchange, or did Tachyon indicate
  4773. // a failure during transmission? Ask for retry with "SOFT_ERROR"
  4774. else if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT)
  4775. {
  4776. // printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n",
  4777. // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
  4778. Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
  4779. }
  4780. // Did frame(s) for an open exchange arrive in the SFQ,
  4781. // meaning the SEST was unable to process them?
  4782. else if( Exchanges->fcExchange[ x_ID ].status & SFQ_FRAME)
  4783. {
  4784. // printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n",
  4785. // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
  4786. Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
  4787. }
  4788. // Did our driver timeout the Exchange, or did Tachyon indicate
  4789. // a failure during transmission? Ask for retry with "SOFT_ERROR"
  4790. else if(
  4791. (Exchanges->fcExchange[ x_ID ].status & LINKFAIL_TX) ||
  4792. (Exchanges->fcExchange[ x_ID ].status & PORTID_CHANGED) ||
  4793. (Exchanges->fcExchange[ x_ID ].status & FRAME_TO) ||
  4794. (Exchanges->fcExchange[ x_ID ].status & INV_ENTRY) ||
  4795. (Exchanges->fcExchange[ x_ID ].status & ABORTSEQ_NOTIFY) )
  4796. {
  4797. // printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n",
  4798. // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
  4799. Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
  4800. }
  4801. // e.g., a LOGOut happened, or device never logged back in.
  4802. else if( Exchanges->fcExchange[ x_ID ].status & DEVICE_REMOVED)
  4803. {
  4804. // printk(" *LOGOut or timeout on login!* ");
  4805. // trigger?
  4806. // TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
  4807. Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_BAD_TARGET <<16);
  4808. }
  4809. // Did Tachyon indicate a CNT error? We need further analysis
  4810. // to determine if the exchange is acceptable
  4811. else if( Exchanges->fcExchange[ x_ID ].status == COUNT_ERROR)
  4812. {
  4813. UCHAR ScsiStatus;
  4814. FCP_STATUS_RESPONSE *pFcpStatus =
  4815. (PFCP_STATUS_RESPONSE)&fcChip->SEST->RspHDR[ x_ID ].pl;
  4816. ScsiStatus = pFcpStatus->fcp_status >>24;
  4817. // If the command is a SCSI Read/Write type, we don't tolerate
  4818. // count errors of any kind; assume the count error is due to
  4819. // a dropped frame and ask for retry...
  4820. if(( (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x8) ||
  4821. (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x28) ||
  4822. (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0xA) ||
  4823. (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x2A) )
  4824. &&
  4825. ScsiStatus == 0 )
  4826. {
  4827. // ask for retry
  4828. /* printk("COUNT_ERROR retry, x_ID %Xh, status %Xh, Cmnd %p\n",
  4829. x_ID, Exchanges->fcExchange[ x_ID ].status,
  4830. Exchanges->fcExchange[ x_ID ].Cmnd);*/
  4831. Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
  4832. }
  4833. else // need more analysis
  4834. {
  4835. cpqfcTSCheckandSnoopFCP(fcChip, x_ID); // (will set ->result)
  4836. }
  4837. }
  4838. // default: NOTE! We don't ever want to get here. Getting here
  4839. // implies something new is happening that we've never had a test
  4840. // case for. Need code maintenance! Return "ERROR"
  4841. else
  4842. {
  4843. unsigned int stat = Exchanges->fcExchange[ x_ID ].status;
  4844. printk("DEFAULT result %Xh, x_ID %Xh, Cmnd %p",
  4845. Exchanges->fcExchange[ x_ID ].status, x_ID,
  4846. Exchanges->fcExchange[ x_ID ].Cmnd);
  4847. if (stat & INVALID_ARGS) printk(" INVALID_ARGS ");
  4848. if (stat & LNKDWN_OSLS) printk(" LNKDWN_OSLS ");
  4849. if (stat & LNKDWN_LASER) printk(" LNKDWN_LASER ");
  4850. if (stat & OUTQUE_FULL) printk(" OUTQUE_FULL ");
  4851. if (stat & DRIVERQ_FULL) printk(" DRIVERQ_FULL ");
  4852. if (stat & SEST_FULL) printk(" SEST_FULL ");
  4853. if (stat & BAD_ALPA) printk(" BAD_ALPA ");
  4854. if (stat & OVERFLOW) printk(" OVERFLOW ");
  4855. if (stat & COUNT_ERROR) printk(" COUNT_ERROR ");
  4856. if (stat & LINKFAIL_RX) printk(" LINKFAIL_RX ");
  4857. if (stat & ABORTSEQ_NOTIFY) printk(" ABORTSEQ_NOTIFY ");
  4858. if (stat & LINKFAIL_TX) printk(" LINKFAIL_TX ");
  4859. if (stat & HOSTPROG_ERR) printk(" HOSTPROG_ERR ");
  4860. if (stat & FRAME_TO) printk(" FRAME_TO ");
  4861. if (stat & INV_ENTRY) printk(" INV_ENTRY ");
  4862. if (stat & SESTPROG_ERR) printk(" SESTPROG_ERR ");
  4863. if (stat & OUTBOUND_TIMEOUT) printk(" OUTBOUND_TIMEOUT ");
  4864. if (stat & INITIATOR_ABORT) printk(" INITIATOR_ABORT ");
  4865. if (stat & MEMPOOL_FAIL) printk(" MEMPOOL_FAIL ");
  4866. if (stat & FC2_TIMEOUT) printk(" FC2_TIMEOUT ");
  4867. if (stat & TARGET_ABORT) printk(" TARGET_ABORT ");
  4868. if (stat & EXCHANGE_QUEUED) printk(" EXCHANGE_QUEUED ");
  4869. if (stat & PORTID_CHANGED) printk(" PORTID_CHANGED ");
  4870. if (stat & DEVICE_REMOVED) printk(" DEVICE_REMOVED ");
  4871. if (stat & SFQ_FRAME) printk(" SFQ_FRAME ");
  4872. printk("\n");
  4873. Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_ERROR <<16);
  4874. }
  4875. }
  4876. else // definitely no Tach problem, but perhaps an FCP problem
  4877. {
  4878. // set FCP Link statistic
  4879. fcChip->fcStats.ok++;
  4880. cpqfcTSCheckandSnoopFCP( fcChip, x_ID); // (will set ->result)
  4881. }
  4882. cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd,
  4883. fcChip, x_ID); // undo DMA mappings.
  4884. already_unmapped = 1;
  4885. // OK, we've set the Scsi "->result" field, so proceed with calling
  4886. // Linux Scsi "done" (if not NULL), and free any kernel memory we
  4887. // may have allocated for the exchange.
  4888. PCI_TRACEO( (ULONG)Exchanges->fcExchange[x_ID].Cmnd, 0xAC);
  4889. // complete the command back to upper Scsi drivers
  4890. if( Exchanges->fcExchange[ x_ID ].Cmnd->scsi_done != NULL)
  4891. {
  4892. // Calling "done" on an Linux _abort() aborted
  4893. // Cmnd causes a kernel panic trying to re-free mem.
  4894. // Actually, we shouldn't do anything with an _abort CMND
  4895. if( Exchanges->fcExchange[ x_ID ].Cmnd->result != (DID_ABORT<<16) )
  4896. {
  4897. PCI_TRACE(0xAC)
  4898. call_scsi_done(Exchanges->fcExchange[ x_ID ].Cmnd);
  4899. }
  4900. else
  4901. {
  4902. // printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
  4903. // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
  4904. }
  4905. }
  4906. else{
  4907. printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID,
  4908. Exchanges->fcExchange[ x_ID ].type,
  4909. Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]);
  4910. printk(" cpqfcTS: Null scsi_done function pointer!\n");
  4911. }
  4912. // Now, clean up non-Scsi_Cmnd items...
  4913. CleanUpSestResources:
  4914. if (!already_unmapped)
  4915. cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd,
  4916. fcChip, x_ID); // undo DMA mappings.
  4917. // Was an Extended Scatter/Gather page allocated? We know
  4918. // this by checking DWORD 4, bit 31 ("LOC") of SEST entry
  4919. if( !(fcChip->SEST->u[ x_ID ].IWE.Buff_Off & 0x80000000))
  4920. {
  4921. PSGPAGES p, next;
  4922. // extended S/G list was used -- Free the allocated ext. S/G pages
  4923. for (p = fcChip->SEST->sgPages[x_ID]; p != NULL; p = next) {
  4924. next = p->next;
  4925. kfree(p);
  4926. }
  4927. fcChip->SEST->sgPages[x_ID] = NULL;
  4928. }
  4929. Exchanges->fcExchange[ x_ID ].Cmnd = NULL;
  4930. } // Done with FCP (SEST) exchanges
  4931. // the remaining logic is common to ALL Exchanges:
  4932. // FCP(SEST) and LinkServ.
  4933. Exchanges->fcExchange[ x_ID ].type = 0; // there -- FREE!
  4934. Exchanges->fcExchange[ x_ID ].status = 0;
  4935. PCI_TRACEO( x_ID, 0xAC)
  4936. return;
  4937. } // (END of CompleteExchange function)
  4938. // Unfortunately, we must snoop all command completions in
  4939. // order to manipulate certain return fields, and take note of
  4940. // device types, etc., to facilitate the Fibre-Channel to SCSI
  4941. // "mapping".
  4942. // (Watch for BIG Endian confusion on some payload fields)
  4943. void cpqfcTSCheckandSnoopFCP( PTACHYON fcChip, ULONG x_ID)
  4944. {
  4945. FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  4946. Scsi_Cmnd *Cmnd = Exchanges->fcExchange[ x_ID].Cmnd;
  4947. FCP_STATUS_RESPONSE *pFcpStatus =
  4948. (PFCP_STATUS_RESPONSE)&fcChip->SEST->RspHDR[ x_ID ].pl;
  4949. UCHAR ScsiStatus;
  4950. ScsiStatus = pFcpStatus->fcp_status >>24;
  4951. #ifdef FCP_COMPLETION_DBG
  4952. printk("ScsiStatus = 0x%X\n", ScsiStatus);
  4953. #endif
  4954. // First, check FCP status
  4955. if( pFcpStatus->fcp_status & FCP_RSP_LEN_VALID )
  4956. {
  4957. // check response code (RSP_CODE) -- most popular is bad len
  4958. // 1st 4 bytes of rsp info -- only byte 3 interesting
  4959. if( pFcpStatus->fcp_rsp_info & FCP_DATA_LEN_NOT_BURST_LEN )
  4960. {
  4961. // do we EVER get here?
  4962. printk("cpqfcTS: FCP data len not burst len, x_ID %Xh\n", x_ID);
  4963. }
  4964. }
  4965. // for now, go by the ScsiStatus, and manipulate certain
  4966. // commands when necessary...
  4967. if( ScsiStatus == 0) // SCSI status byte "good"?
  4968. {
  4969. Cmnd->result = 0; // everything's OK
  4970. if( (Cmnd->cmnd[0] == INQUIRY))
  4971. {
  4972. UCHAR *InquiryData = Cmnd->request_buffer;
  4973. PFC_LOGGEDIN_PORT pLoggedInPort;
  4974. // We need to manipulate INQUIRY
  4975. // strings for COMPAQ RAID controllers to force
  4976. // Linux to scan additional LUNs. Namely, set
  4977. // the Inquiry string byte 2 (ANSI-approved version)
  4978. // to 2.
  4979. if( !memcmp( &InquiryData[8], "COMPAQ", 6 ))
  4980. {
  4981. InquiryData[2] = 0x2; // claim SCSI-2 compliance,
  4982. // so multiple LUNs may be scanned.
  4983. // (no SCSI-2 problems known in CPQ)
  4984. }
  4985. // snoop the Inquiry to detect Disk, Tape, etc. type
  4986. // (search linked list for the port_id we sent INQUIRY to)
  4987. pLoggedInPort = fcFindLoggedInPort( fcChip,
  4988. NULL, // DON'T search Scsi Nexus (we will set it)
  4989. Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF,
  4990. NULL, // DON'T search linked list for FC WWN
  4991. NULL); // DON'T care about end of list
  4992. if( pLoggedInPort )
  4993. {
  4994. pLoggedInPort->ScsiNexus.InqDeviceType = InquiryData[0];
  4995. }
  4996. else
  4997. {
  4998. printk("cpqfcTS: can't find LoggedIn FC port %06X for INQUIRY\n",
  4999. Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF);
  5000. }
  5001. }
  5002. }
  5003. // Scsi Status not good -- pass it back to caller
  5004. else
  5005. {
  5006. Cmnd->result = ScsiStatus; // SCSI status byte is 1st
  5007. // check for valid "sense" data
  5008. if( pFcpStatus->fcp_status & FCP_SNS_LEN_VALID )
  5009. { // limit Scsi Sense field length!
  5010. int SenseLen = pFcpStatus->fcp_sns_len >>24; // (BigEndian) lower byte
  5011. SenseLen = SenseLen > sizeof( Cmnd->sense_buffer) ?
  5012. sizeof( Cmnd->sense_buffer) : SenseLen;
  5013. #ifdef FCP_COMPLETION_DBG
  5014. printk("copy sense_buffer %p, len %d, result %Xh\n",
  5015. Cmnd->sense_buffer, SenseLen, Cmnd->result);
  5016. #endif
  5017. // NOTE: There is some dispute over the FCP response
  5018. // format. Most FC devices assume that FCP_RSP_INFO
  5019. // is 8 bytes long, in spite of the fact that FCP_RSP_LEN
  5020. // is (virtually) always 0 and the field is "invalid".
  5021. // Some other devices assume that
  5022. // the FCP_SNS_INFO begins after FCP_RSP_LEN bytes (i.e. 0)
  5023. // when the FCP_RSP is invalid (this almost appears to be
  5024. // one of those "religious" issues).
  5025. // Consequently, we test the usual position of FCP_SNS_INFO
  5026. // for 7Xh, since the SCSI sense format says the first
  5027. // byte ("error code") should be 0x70 or 0x71. In practice,
  5028. // we find that every device does in fact have 0x70 or 0x71
  5029. // in the first byte position, so this test works for all
  5030. // FC devices.
  5031. // (This logic is especially effective for the CPQ/DEC HSG80
  5032. // & HSG60 controllers).
  5033. if( (pFcpStatus->fcp_sns_info[0] & 0x70) == 0x70 )
  5034. memcpy( Cmnd->sense_buffer,
  5035. &pFcpStatus->fcp_sns_info[0], SenseLen);
  5036. else
  5037. {
  5038. unsigned char *sbPtr =
  5039. (unsigned char *)&pFcpStatus->fcp_sns_info[0];
  5040. sbPtr -= 8; // back up 8 bytes hoping to find the
  5041. // start of the sense buffer
  5042. memcpy( Cmnd->sense_buffer, sbPtr, SenseLen);
  5043. }
  5044. // in the special case of Device Reset, tell upper layer
  5045. // to immediately retry (with SOFT_ERROR status)
  5046. // look for Sense Key Unit Attention (0x6) with ASC Device
  5047. // Reset (0x29)
  5048. // printk("SenseLen %d, Key = 0x%X, ASC = 0x%X\n",
  5049. // SenseLen, Cmnd->sense_buffer[2],
  5050. // Cmnd->sense_buffer[12]);
  5051. if( ((Cmnd->sense_buffer[2] & 0xF) == 0x6) &&
  5052. (Cmnd->sense_buffer[12] == 0x29) ) // Sense Code "reset"
  5053. {
  5054. Cmnd->result |= (DID_SOFT_ERROR << 16); // "Host" status byte 3rd
  5055. }
  5056. // check for SenseKey "HARDWARE ERROR", ASC InternalTargetFailure
  5057. else if( ((Cmnd->sense_buffer[2] & 0xF) == 0x4) && // "hardware error"
  5058. (Cmnd->sense_buffer[12] == 0x44) ) // Addtl. Sense Code
  5059. {
  5060. // printk("HARDWARE_ERROR, Channel/Target/Lun %d/%d/%d\n",
  5061. // Cmnd->channel, Cmnd->target, Cmnd->lun);
  5062. Cmnd->result |= (DID_ERROR << 16); // "Host" status byte 3rd
  5063. }
  5064. } // (end of sense len valid)
  5065. // there is no sense data to help out Linux's Scsi layers...
  5066. // We'll just return the Scsi status and hope he will "do the
  5067. // right thing"
  5068. else
  5069. {
  5070. // as far as we know, the Scsi status is sufficient
  5071. Cmnd->result |= (DID_OK << 16); // "Host" status byte 3rd
  5072. }
  5073. }
  5074. }
  5075. //PPPPPPPPPPPPPPPPPPPPPPPPP PAYLOAD PPPPPPPPP
  5076. // build data PAYLOAD; SCSI FCP_CMND I.U.
  5077. // remember BIG ENDIAN payload - DWord values must be byte-reversed
  5078. // (hence the affinity for byte pointer building).
  5079. static int build_FCP_payload( Scsi_Cmnd *Cmnd,
  5080. UCHAR* payload, ULONG type, ULONG fcp_dl )
  5081. {
  5082. int i;
  5083. switch( type)
  5084. {
  5085. case SCSI_IWE:
  5086. case SCSI_IRE:
  5087. // 8 bytes FCP_LUN
  5088. // Peripheral Device or Volume Set addressing, and LUN mapping
  5089. // When the FC port was looked up, we copied address mode
  5090. // and any LUN mask to the scratch pad SCp.phase & .mode
  5091. *payload++ = (UCHAR)Cmnd->SCp.phase;
  5092. // Now, because of "lun masking"
  5093. // (aka selective storage presentation),
  5094. // the contiguous Linux Scsi lun number may not match the
  5095. // device's lun number, so we may have to "map".
  5096. *payload++ = (UCHAR)Cmnd->SCp.have_data_in;
  5097. // We don't know of anyone in the FC business using these
  5098. // extra "levels" of addressing. In fact, confusion still exists
  5099. // just using the FIRST level... ;-)
  5100. *payload++ = 0; // 2nd level addressing
  5101. *payload++ = 0;
  5102. *payload++ = 0; // 3rd level addressing
  5103. *payload++ = 0;
  5104. *payload++ = 0; // 4th level addressing
  5105. *payload++ = 0;
  5106. // 4 bytes Control Field FCP_CNTL
  5107. *payload++ = 0; // byte 0: (MSB) reserved
  5108. *payload++ = 0; // byte 1: task codes
  5109. // byte 2: task management flags
  5110. // another "use" of the spare field to accomplish TDR
  5111. // note combination needed
  5112. if( (Cmnd->cmnd[0] == RELEASE) &&
  5113. (Cmnd->SCp.buffers_residual == FCP_TARGET_RESET) )
  5114. {
  5115. Cmnd->cmnd[0] = 0; // issue "Test Unit Ready" for TDR
  5116. *payload++ = 0x20; // target device reset bit
  5117. }
  5118. else
  5119. *payload++ = 0; // no TDR
  5120. // byte 3: (LSB) execution management codes
  5121. // bit 0 write, bit 1 read (don't set together)
  5122. if( fcp_dl != 0 )
  5123. {
  5124. if( type == SCSI_IWE ) // WRITE
  5125. *payload++ = 1;
  5126. else // READ
  5127. *payload++ = 2;
  5128. }
  5129. else
  5130. {
  5131. // On some devices, if RD or WR bits are set,
  5132. // and fcp_dl is 0, they will generate an error on the command.
  5133. // (i.e., if direction is specified, they insist on a length).
  5134. *payload++ = 0; // no data (necessary for CPQ)
  5135. }
  5136. // NOTE: clean this up if/when MAX_COMMAND_SIZE is increased to 16
  5137. // FCP_CDB allows 16 byte SCSI command descriptor blk;
  5138. // Linux SCSI CDB array is MAX_COMMAND_SIZE (12 at this time...)
  5139. for( i=0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
  5140. *payload++ = Cmnd->cmnd[i];
  5141. // if( Cmnd->cmd_len == 16 )
  5142. // {
  5143. // memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
  5144. // }
  5145. payload+= (16 - i);
  5146. // FCP_DL is largest number of expected data bytes
  5147. // per CDB (i.e. read/write command)
  5148. *payload++ = (UCHAR)(fcp_dl >>24); // (MSB) 8 bytes data len FCP_DL
  5149. *payload++ = (UCHAR)(fcp_dl >>16);
  5150. *payload++ = (UCHAR)(fcp_dl >>8);
  5151. *payload++ = (UCHAR)fcp_dl; // (LSB)
  5152. break;
  5153. case SCSI_TWE: // need FCP_XFER_RDY
  5154. *payload++ = 0; // (4 bytes) DATA_RO (MSB byte 0)
  5155. *payload++ = 0;
  5156. *payload++ = 0;
  5157. *payload++ = 0; // LSB (byte 3)
  5158. // (4 bytes) BURST_LEN
  5159. // size of following FCP_DATA payload
  5160. *payload++ = (UCHAR)(fcp_dl >>24); // (MSB) 8 bytes data len FCP_DL
  5161. *payload++ = (UCHAR)(fcp_dl >>16);
  5162. *payload++ = (UCHAR)(fcp_dl >>8);
  5163. *payload++ = (UCHAR)fcp_dl; // (LSB)
  5164. // 4 bytes RESERVED
  5165. *payload++ = 0;
  5166. *payload++ = 0;
  5167. *payload++ = 0;
  5168. *payload++ = 0;
  5169. break;
  5170. default:
  5171. break;
  5172. }
  5173. return 0;
  5174. }