| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745 | diff -Nur linux-2.6.37.orig/arch/cris/arch-v10/drivers/axisflashmap.c linux-2.6.37/arch/cris/arch-v10/drivers/axisflashmap.c--- linux-2.6.37.orig/arch/cris/arch-v10/drivers/axisflashmap.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/arch-v10/drivers/axisflashmap.c	2011-04-27 12:05:31.277662574 +0200@@ -113,7 +113,7 @@  /* If no partition-table was found, we use this default-set. */ #define MAX_PARTITIONS         7-#define NUM_DEFAULT_PARTITIONS 3+#define NUM_DEFAULT_PARTITIONS 4  /*  * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the@@ -122,19 +122,24 @@  */ static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = { 	{-		.name = "boot firmware",-		.size = CONFIG_ETRAX_PTABLE_SECTOR,+		.name = "kernel",+		.size = 0x00, 		.offset = 0 	}, 	{-		.name = "kernel",-		.size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),-		.offset = CONFIG_ETRAX_PTABLE_SECTOR+		.name = "rootfs",+		.size = 0x200000 ,+		.offset = 0x200000 	}, 	{-		.name = "filesystem",-		.size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,-		.offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)+		.name = "cfgfs",+		.size = 0x20000 ,+		.offset = CONFIG_ETRAX_MTD_SIZE - 0x20000+	},+	{+		.name = "linux",+		.size = CONFIG_ETRAX_MTD_SIZE - 0x20000,+		.offset = 0 	} }; @@ -281,6 +286,11 @@ 	struct partitiontable_entry *ptable; 	int use_default_ptable = 1; /* Until proven otherwise. */ 	const char pmsg[] = "  /dev/flash%d at 0x%08x, size 0x%08x\n";+	unsigned int kernel_part_size = 0;+	unsigned char *flash_mem = (unsigned char*)(FLASH_CACHED_ADDR);+	unsigned int flash_scan_count = 0;+	const char *part_magic = "ACME_PART_MAGIC";+	unsigned int magic_len = strlen(part_magic);  	if (!(mymtd = flash_probe())) { 		/* There's no reason to use this module if no flash chip can@@ -292,6 +302,31 @@ 		       mymtd->name, mymtd->size); 		axisflash_mtd = mymtd; 	}+	/* scan flash to findout where out partition starts */++	printk(KERN_INFO "Scanning flash for end of kernel magic\n");+	for(flash_scan_count = 0; flash_scan_count < 100000; flash_scan_count++){+		if(strncmp(&flash_mem[flash_scan_count], part_magic, magic_len - 1) == 0)+		{+			kernel_part_size = flash_mem[flash_scan_count + magic_len ];+			kernel_part_size <<= 8;+			kernel_part_size += flash_mem[flash_scan_count + magic_len + 2];+			kernel_part_size <<= 8;+			kernel_part_size += flash_mem[flash_scan_count + magic_len + 1];+			kernel_part_size <<= 8;+			kernel_part_size += flash_mem[flash_scan_count + magic_len + 3];+			printk(KERN_INFO "Kernel ends at 0x%.08X\n", kernel_part_size);+			flash_scan_count = 1100000;+		}+	}+++	if(kernel_part_size){+		kernel_part_size = (kernel_part_size & 0xffff0000);+		axis_default_partitions[0].size = kernel_part_size;+		axis_default_partitions[1].size =  mymtd->size - axis_default_partitions[0].size - axis_default_partitions[2].size;+		axis_default_partitions[1].offset = axis_default_partitions[0].size;+	}  	if (mymtd) { 		mymtd->owner = THIS_MODULE;@@ -360,21 +395,6 @@ 		use_default_ptable = !ptable_ok; 	} -	if (romfs_in_flash) {-		/* Add an overlapping device for the root partition (romfs). */--		axis_partitions[pidx].name = "romfs";-		axis_partitions[pidx].size = romfs_length;-		axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;-		axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;--		printk(KERN_INFO-                       " Adding readonly flash partition for romfs image:\n");-		printk(pmsg, pidx, axis_partitions[pidx].offset,-		       axis_partitions[pidx].size);-		pidx++;-	}- #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE 	if (mymtd) { 		main_partition.size = mymtd->size;@@ -397,36 +417,6 @@ 		if (err) 			panic("axisflashmap could not add MTD partitions!\n"); 	}--	if (!romfs_in_flash) {-		/* Create an RAM device for the root partition (romfs). */--#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)-		/* No use trying to boot this kernel from RAM. Panic! */-		printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "-		       "device due to kernel (mis)configuration!\n");-		panic("This kernel cannot boot from RAM!\n");-#else-		struct mtd_info *mtd_ram;--		mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);-		if (!mtd_ram)-			panic("axisflashmap couldn't allocate memory for "-			      "mtd_info!\n");--		printk(KERN_INFO " Adding RAM partition for romfs image:\n");-		printk(pmsg, pidx, (unsigned)romfs_start,-			(unsigned)romfs_length);--		err = mtdram_init_device(mtd_ram,-			(void *)romfs_start,-			romfs_length,-			"romfs");-		if (err)-			panic("axisflashmap could not initialize MTD RAM "-			      "device!\n");-#endif-	} 	return err; } diff -Nur linux-2.6.37.orig/arch/cris/arch-v10/drivers/ds1302.c linux-2.6.37/arch/cris/arch-v10/drivers/ds1302.c--- linux-2.6.37.orig/arch/cris/arch-v10/drivers/ds1302.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/arch-v10/drivers/ds1302.c	2011-04-27 12:05:31.337661896 +0200@@ -22,6 +22,7 @@ #include <linux/mutex.h> #include <linux/bcd.h> #include <linux/capability.h>+#include <linux/device.h>  #include <asm/uaccess.h> #include <asm/system.h>@@ -501,6 +502,10 @@ 	return 0; } +#ifdef CONFIG_SYSFS+static struct class *rtc_class;+#endif+ static int __init ds1302_register(void) { 	ds1302_init();@@ -509,6 +514,12 @@ 		       ds1302_name, RTC_MAJOR_NR); 		return -1; 	}+	#ifdef CONFIG_SYSFS+	rtc_class = class_create(THIS_MODULE, "rtc");+	class_device_create(rtc_class, NULL, MKDEV(RTC_MAJOR_NR, 0),+		NULL, "rtc");+	#endif+         return 0;  }diff -Nur linux-2.6.37.orig/arch/cris/arch-v10/drivers/gpio.c linux-2.6.37/arch/cris/arch-v10/drivers/gpio.c--- linux-2.6.37.orig/arch/cris/arch-v10/drivers/gpio.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/arch-v10/drivers/gpio.c	2011-04-27 12:05:31.377662210 +0200@@ -20,6 +20,7 @@ #include <linux/poll.h> #include <linux/init.h> #include <linux/interrupt.h>+#include <linux/device.h>  #include <asm/etraxgpio.h> #include <arch/svinto.h>@@ -798,6 +799,10 @@  /* main driver initialization routine, called from mem.c */ +#ifdef CONFIG_SYSFS+static struct class *gpio_class;+#endif+ static int __init gpio_init(void) { 	int res;@@ -811,6 +816,13 @@ 		return res; 	} +#ifdef CONFIG_SYSFS+	gpio_class = class_create(THIS_MODULE, "gpio");+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 0), NULL, "gpioa");+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 1), NULL, "gpiob");+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 2), NULL, "leds");+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 3), NULL, "gpiog");+#endif 	/* Clear all leds */ #if defined (CONFIG_ETRAX_CSP0_LEDS) ||  defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS) 	CRIS_LED_NETWORK_SET(0);diff -Nur linux-2.6.37.orig/arch/cris/arch-v10/lib/hw_settings.S linux-2.6.37/arch/cris/arch-v10/lib/hw_settings.S--- linux-2.6.37.orig/arch/cris/arch-v10/lib/hw_settings.S	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/arch-v10/lib/hw_settings.S	2011-04-27 12:05:31.417662330 +0200@@ -58,3 +58,5 @@ 	.dword R_PORT_PB_SET 	.dword PB_SET_VALUE 	.dword 0 ; No more register values+	.ascii "ACME_PART_MAGIC" +	.dword 0xdeadc0dediff -Nur linux-2.6.37.orig/arch/cris/arch-v10/mm/init.c linux-2.6.37/arch/cris/arch-v10/mm/init.c--- linux-2.6.37.orig/arch/cris/arch-v10/mm/init.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/arch-v10/mm/init.c	2011-04-27 12:23:55.347672203 +0200@@ -184,6 +184,9 @@  	free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); }+void free_initrd_mem(unsigned long start, unsigned long end)+{+}  /* Initialize remaps of some I/O-ports. It is important that this  * is called before any driver is initialized.diff -Nur linux-2.6.37.orig/arch/cris/boot/compressed/Makefile linux-2.6.37/arch/cris/boot/compressed/Makefile--- linux-2.6.37.orig/arch/cris/boot/compressed/Makefile	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/boot/compressed/Makefile	2011-04-27 12:05:31.567661802 +0200@@ -18,7 +18,7 @@ OBJECTS-$(CONFIG_ETRAX_ARCH_V32) = $(obj)/head_v32.o OBJECTS-$(CONFIG_ETRAX_ARCH_V10) = $(obj)/head_v10.o OBJECTS= $(OBJECTS-y) $(obj)/misc.o-OBJCOPYFLAGS = -O binary --remove-section=.bss+#OBJCOPYFLAGS = -O binary --remove-section=.bss  quiet_cmd_image = BUILD   $@ cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@diff -Nur linux-2.6.37.orig/arch/cris/boot/Makefile linux-2.6.37/arch/cris/boot/Makefile--- linux-2.6.37.orig/arch/cris/boot/Makefile	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/boot/Makefile	2011-04-27 12:05:31.527662141 +0200@@ -5,7 +5,7 @@ objcopyflags-$(CONFIG_ETRAX_ARCH_V10) += -R .note -R .comment objcopyflags-$(CONFIG_ETRAX_ARCH_V32) += --remove-section=.bss --remove-section=.note.gnu.build-id -OBJCOPYFLAGS = -O binary $(objcopyflags-y)+#OBJCOPYFLAGS = -O binary $(objcopyflags-y)   subdir- := compressed rescue@@ -17,7 +17,6 @@  $(obj)/compressed/vmlinux: $(obj)/Image FORCE 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@-	$(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin  $(obj)/zImage:  $(obj)/compressed/vmlinux 	@cp $< $@diff -Nur linux-2.6.37.orig/arch/cris/Kconfig linux-2.6.37/arch/cris/Kconfig--- linux-2.6.37.orig/arch/cris/Kconfig	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/Kconfig	2011-04-27 12:05:31.187667361 +0200@@ -170,6 +170,12 @@ 	help 	  Size of DRAM (decimal in MB) typically 2, 8 or 16. +config ETRAX_MTD_SIZE+	hex "MTD size (hex)"+	default "0x00800000"+	help+	  Size of MTD device typically 4 or 8 MB.+ config ETRAX_VMEM_SIZE        int "Video memory size (dec, in MB)"        depends on ETRAX_ARCH_V32 && !ETRAXFS@@ -275,7 +281,7 @@ 	select MTD_CFI_AMDSTD 	select MTD_JEDECPROBE if ETRAX_ARCH_V32 	select MTD_CHAR-	select MTD_BLOCK+	select MTD_BLOCK_RO 	select MTD_PARTITIONS 	select MTD_CONCAT 	select MTD_COMPLEX_MAPPINGS@@ -664,6 +670,11 @@  source "drivers/ide/Kconfig" +#mysteriously part of this standard linux driver was removed from cris build! - info@crisos.org  +source "drivers/scsi/Kconfig"++source "drivers/media/Kconfig"+ source "drivers/net/Kconfig"  source "drivers/i2c/Kconfig"@@ -679,6 +690,8 @@  source "fs/Kconfig" +source "sound/Kconfig"+ source "drivers/usb/Kconfig"  source "drivers/uwb/Kconfig"diff -Nur linux-2.6.37.orig/arch/cris/Makefile linux-2.6.37/arch/cris/Makefile--- linux-2.6.37.orig/arch/cris/Makefile	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/Makefile	2011-04-27 12:05:31.217662105 +0200@@ -40,10 +40,10 @@  LD = $(CROSS_COMPILE)ld -mcrislinux -OBJCOPYFLAGS := -O binary -R .note -R .comment -S+OBJCOPYFLAGS := -O binary -R .bss -R .note -R .note.gnu.build-id -R .comment -S  KBUILD_AFLAGS += -mlinux -march=$(arch-y) $(inc)-KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe $(inc)+KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe -fno-peephole2 $(inc) KBUILD_CPPFLAGS += $(inc)  ifdef CONFIG_FRAME_POINTERdiff -Nur linux-2.6.37.orig/arch/cris/mm/init.c linux-2.6.37/arch/cris/mm/init.c--- linux-2.6.37.orig/arch/cris/mm/init.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/arch/cris/mm/init.c	2011-04-27 12:23:46.628914539 +0200@@ -16,6 +16,7 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);  unsigned long empty_zero_page;+EXPORT_SYMBOL(empty_zero_page);  extern char _stext, _edata, _etext; /* From linkerscript */ extern char __init_begin, __init_end;@@ -81,3 +82,10 @@         printk (KERN_INFO "Freeing unused kernel memory: %luk freed\n", 		(unsigned long)((&__init_end - &__init_begin) >> 10)); }++#ifdef CONFIG_BLK_DEV_INITRD+void free_initrd_mem(unsigned long start, unsigned long end)+{+	return 0;+}+#endifdiff -Nur linux-2.6.37.orig/drivers/net/cris/eth_v10.c linux-2.6.37/drivers/net/cris/eth_v10.c--- linux-2.6.37.orig/drivers/net/cris/eth_v10.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/drivers/net/cris/eth_v10.c	2011-04-27 12:05:31.647661894 +0200@@ -1718,7 +1718,7 @@ static void e100_netpoll(struct net_device* netdev) {-	e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL);+	e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev); } #endif diff -Nur linux-2.6.37.orig/drivers/serial/crisv10.c linux-2.6.37/drivers/serial/crisv10.c--- linux-2.6.37.orig/drivers/serial/crisv10.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/drivers/serial/crisv10.c	2011-04-27 12:05:31.657662263 +0200@@ -13,6 +13,7 @@ #include <linux/errno.h> #include <linux/signal.h> #include <linux/sched.h>+#include <linux/smp_lock.h>  #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/tty.h>@@ -26,6 +27,7 @@ #include <linux/kernel.h> #include <linux/mutex.h> #include <linux/bitops.h>+#include <linux/device.h> #include <linux/seq_file.h> #include <linux/delay.h> #include <linux/module.h>@@ -4431,6 +4433,7 @@ #endif }; +static struct class *rs_class; static int __init rs_init(void) { 	int i;@@ -4565,6 +4568,24 @@ #endif #endif /* CONFIG_SVINTO_SIM */ +	rs_class = class_create(THIS_MODULE, "rs_tty");+#ifdef CONFIG_ETRAX_SERIAL_PORT0 +	device_create(rs_class, NULL,+		MKDEV(TTY_MAJOR, 64), NULL, "ttyS0");+#endif+#ifdef CONFIG_ETRAX_SERIAL_PORT1 +	device_create(rs_class, NULL,+		MKDEV(TTY_MAJOR, 65), NULL, "ttyS1");+#endif+#ifdef CONFIG_ETRAX_SERIAL_PORT2 +	device_create(rs_class, NULL,+		MKDEV(TTY_MAJOR, 66), NULL, "ttyS2");+#endif+#ifdef CONFIG_ETRAX_SERIAL_PORT3 +	device_create(rs_class, NULL,+		MKDEV(TTY_MAJOR, 67), NULL, "ttyS3");+#endif+ 	return 0; } diff -Nur linux-2.6.37.orig/drivers/usb/host/hc-cris-dbg.h linux-2.6.37/drivers/usb/host/hc-cris-dbg.h--- linux-2.6.37.orig/drivers/usb/host/hc-cris-dbg.h	1970-01-01 01:00:00.000000000 +0100+++ linux-2.6.37/drivers/usb/host/hc-cris-dbg.h	2011-04-27 12:05:31.847661851 +0200@@ -0,0 +1,146 @@++/* macros for debug output */++#define warn(fmt, args...) \+        printk(KERN_INFO "crisv10 warn: ");printk(fmt, ## args)++#define hcd_dbg(hcd, fmt, args...) \+	dev_info(hcd->self.controller, fmt, ## args)+#define hcd_err(hcd, fmt, args...) \+	dev_err(hcd->self.controller, fmt, ## args)+#define hcd_info(hcd, fmt, args...) \+	dev_info(hcd->self.controller, fmt, ## args)+#define hcd_warn(hcd, fmt, args...) \+	dev_warn(hcd->self.controller, fmt, ## args)++/*+#define devdrv_dbg(fmt, args...) \+        printk(KERN_INFO "usb_devdrv dbg: ");printk(fmt, ## args)+*/+#define devdrv_dbg(fmt, args...) {}++#define devdrv_err(fmt, args...) \+        printk(KERN_ERR "usb_devdrv error: ");printk(fmt, ## args)+#define devdrv_info(fmt, args...) \+        printk(KERN_INFO "usb_devdrv: ");printk(fmt, ## args)++#define irq_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_irq dbg: ");printk(fmt, ## args)+#define irq_err(fmt, args...) \+        printk(KERN_ERR "crisv10_irq error: ");printk(fmt, ## args)+#define irq_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_irq warn: ");printk(fmt, ## args)+#define irq_info(fmt, args...) \+        printk(KERN_INFO "crisv10_hcd: ");printk(fmt, ## args)++/*+#define rh_dbg(fmt, args...) \+  printk(KERN_DEBUG "crisv10_rh dbg: ");printk(fmt, ## args)+*/+#define rh_dbg(fmt, args...) {}++#define rh_err(fmt, args...) \+        printk(KERN_ERR "crisv10_rh error: ");printk(fmt, ## args)+#define rh_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_rh warning: ");printk(fmt, ## args)+#define rh_info(fmt, args...) \+        printk(KERN_INFO "crisv10_rh: ");printk(fmt, ## args)++/*+#define tc_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_tc dbg: ");printk(fmt, ## args)+*/+#define tc_dbg(fmt, args...) {while(0){}}++#define tc_err(fmt, args...) \+        printk(KERN_ERR "crisv10_tc error: ");printk(fmt, ## args)+/*+#define tc_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_tc warning: ");printk(fmt, ## args)+*/+#define tc_warn(fmt, args...) {while(0){}}++#define tc_info(fmt, args...) \+        printk(KERN_INFO "crisv10_tc: ");printk(fmt, ## args)+++/* Debug print-outs for various traffic types */++#define intr_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_intr warning: ");printk(fmt, ## args)++#define intr_dbg(fmt, args...) \+        printk(KERN_DEBUG "crisv10_intr dbg: ");printk(fmt, ## args)+/*+#define intr_dbg(fmt, args...) {while(0){}}+*/+++#define isoc_err(fmt, args...) \+        printk(KERN_ERR "crisv10_isoc error: ");printk(fmt, ## args)+/*+#define isoc_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_isoc warning: ");printk(fmt, ## args)+*/+#define isoc_warn(fmt, args...) {while(0){}}++/*+#define isoc_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_isoc dbg: ");printk(fmt, ## args)+*/+#define isoc_dbg(fmt, args...) {while(0){}}++/*+#define timer_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_timer warning: ");printk(fmt, ## args)+*/+#define timer_warn(fmt, args...) {while(0){}}++/*+#define timer_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_timer dbg: ");printk(fmt, ## args)+*/+#define timer_dbg(fmt, args...) {while(0){}}+++/* Debug printouts for events related to late finishing of URBs */++#define late_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_late dbg: ");printk(fmt, ## args)+/*+#define late_dbg(fmt, args...) {while(0){}}+*/++#define late_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_late warning: ");printk(fmt, ## args)+/*+#define errno_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_errno dbg: ");printk(fmt, ## args)+*/+#define errno_dbg(fmt, args...) {while(0){}}+++#define dma_dbg(fmt, args...) \+        printk(KERN_INFO "crisv10_dma dbg: ");printk(fmt, ## args)+#define dma_err(fmt, args...) \+        printk(KERN_ERR "crisv10_dma error: ");printk(fmt, ## args)+#define dma_warn(fmt, args...) \+        printk(KERN_INFO "crisv10_dma warning: ");printk(fmt, ## args)+#define dma_info(fmt, args...) \+        printk(KERN_INFO "crisv10_dma: ");printk(fmt, ## args)++++#define str_dir(pipe) \+	(usb_pipeout(pipe) ? "out" : "in")+#define str_type(pipe) \+	({								\+		char *s = "?";						\+		switch (usb_pipetype(pipe)) {				\+		case PIPE_ISOCHRONOUS:	s = "iso";  break;		\+		case PIPE_INTERRUPT:	s = "intr"; break;		\+		case PIPE_CONTROL:	s = "ctrl"; break;		\+		case PIPE_BULK:		s = "bulk"; break;		\+		};							\+		s;							\+	})diff -Nur linux-2.6.37.orig/drivers/usb/host/hc-crisv10.c linux-2.6.37/drivers/usb/host/hc-crisv10.c--- linux-2.6.37.orig/drivers/usb/host/hc-crisv10.c	1970-01-01 01:00:00.000000000 +0100+++ linux-2.6.37/drivers/usb/host/hc-crisv10.c	2011-04-27 12:05:31.867662137 +0200@@ -0,0 +1,4801 @@+/*+ *+ * ETRAX 100LX USB Host Controller Driver+ *+ * Copyright (C) 2005, 2006  Axis Communications AB+ *+ * Author: Konrad Eriksson <konrad.eriksson@axis.se>+ *+ */++#include <linux/module.h>+#include <linux/kernel.h>+#include <linux/init.h>+#include <linux/moduleparam.h>+#include <linux/slab.h>+#include <linux/spinlock.h>+#include <linux/usb.h>+#include <linux/platform_device.h>+#include <linux/usb/hcd.h>++#include <asm/io.h>+#include <asm/irq.h>+#include <arch/dma.h>+#include <arch/io_interface_mux.h>++#include "hc-crisv10.h"+#include "hc-cris-dbg.h"+++/***************************************************************************/+/***************************************************************************/+/* Host Controller settings                                                */+/***************************************************************************/+/***************************************************************************/++#define VERSION			"1.00 hinko.4"+#define COPYRIGHT		"(c) 2005, 2006 Axis Communications AB"+#define DESCRIPTION     "ETRAX 100LX USB Host Controller"++#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR+#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR+#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR++/* Number of physical ports in Etrax 100LX */+#define USB_ROOT_HUB_PORTS 2++const char hc_name[] = "hc-crisv10";+const char product_desc[] = DESCRIPTION;++/* The number of epids is, among other things, used for pre-allocating+   ctrl, bulk and isoc EP descriptors (one for each epid).+   Assumed to be > 1 when initiating the DMA lists. */+#define NBR_OF_EPIDS       32++/* Support interrupt traffic intervals up to 128 ms. */+#define MAX_INTR_INTERVAL  128++/* If periodic traffic (intr or isoc) is to be used, then one entry in the EP+   table must be "invalid". By this we mean that we shouldn't care about epid+   attentions for this epid, or at least handle them differently from epid+   attentions for "valid" epids. This define determines which one to use+   (don't change it). */+#define INVALID_EPID       31+/* A special epid for the bulk dummys. */+#define DUMMY_EPID         30++/* Module settings */++MODULE_DESCRIPTION(DESCRIPTION);+MODULE_LICENSE("GPL");+MODULE_AUTHOR("Konrad Eriksson <konrad.eriksson@axis.se>");+++/* Module parameters */++/* 0 = No ports enabled+   1 = Only port 1 enabled (on board ethernet on devboard)+   2 = Only port 2 enabled (external connector on devboard)+   3 = Both ports enabled+*/+static unsigned int ports = 3;+module_param(ports, uint, S_IRUGO);+MODULE_PARM_DESC(ports, "Bitmask indicating USB ports to use");+++/***************************************************************************/+/***************************************************************************/+/* Shared global variables for this module                                 */+/***************************************************************************/+/***************************************************************************/++/* EP descriptor lists for non period transfers. Must be 32-bit aligned. */+static volatile struct USB_EP_Desc TxBulkEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));++static volatile struct USB_EP_Desc TxCtrlEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));++/* EP descriptor lists for period transfers. Must be 32-bit aligned. */+static volatile struct USB_EP_Desc TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));+static volatile struct USB_SB_Desc TxIntrSB_zout __attribute__ ((aligned (4)));++static volatile struct USB_EP_Desc TxIsocEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));+static volatile struct USB_SB_Desc TxIsocSB_zout __attribute__ ((aligned (4)));++//static volatile struct USB_SB_Desc TxIsocSBList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); ++/* After each enabled bulk EP IN we put two disabled EP descriptors with the eol flag set,+   causing the DMA to stop the DMA channel. The first of these two has the intr flag set, which+   gives us a dma8_sub0_descr interrupt. When we receive this, we advance the DMA one step in the+   EP list and then restart the bulk channel, thus forcing a switch between bulk EP descriptors+   in each frame. */+static volatile struct USB_EP_Desc TxBulkDummyEPList[NBR_OF_EPIDS][2] __attribute__ ((aligned (4)));++/* List of URB pointers, where each points to the active URB for a epid.+   For Bulk, Ctrl and Intr this means which URB that currently is added to+   DMA lists (Isoc URBs are all directly added to DMA lists). As soon as+   URB has completed is the queue examined and the first URB in queue is+   removed and moved to the activeUrbList while its state change to STARTED and+   its transfer(s) gets added to DMA list (exception Isoc where URBs enter+   state STARTED directly and added transfers added to DMA lists). */+static struct urb *activeUrbList[NBR_OF_EPIDS];++/* Additional software state info for each epid */+static struct etrax_epid epid_state[NBR_OF_EPIDS];++/* Timer handles for bulk traffic timer used to avoid DMA bug where DMA stops+   even if there is new data waiting to be processed */+static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0);+static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0);++/* We want the start timer to expire before the eot timer, because the former+   might start traffic, thus making it unnecessary for the latter to time+   out. */+#define BULK_START_TIMER_INTERVAL (HZ/50) /* 20 ms */+#define BULK_EOT_TIMER_INTERVAL (HZ/16) /* 60 ms */++/* Delay before a URB completion happen when it's scheduled to be delayed */+#define LATER_TIMER_DELAY (HZ/50) /* 20 ms */++/* Simplifying macros for checking software state info of a epid */+/* ----------------------------------------------------------------------- */+#define epid_inuse(epid)       epid_state[epid].inuse+#define epid_out_traffic(epid) epid_state[epid].out_traffic+#define epid_isoc(epid)   (epid_state[epid].type == PIPE_ISOCHRONOUS ? 1 : 0)+#define epid_intr(epid)   (epid_state[epid].type == PIPE_INTERRUPT ? 1 : 0)+++/***************************************************************************/+/***************************************************************************/+/* DEBUG FUNCTIONS                                                         */+/***************************************************************************/+/***************************************************************************/+/* Note that these functions are always available in their "__" variants,+   for use in error situations. The "__" missing variants are controlled by+   the USB_DEBUG_DESC/USB_DEBUG_URB macros. */+static void __dump_urb(struct urb* purb)+{+  struct crisv10_urb_priv *urb_priv = purb->hcpriv;+  int urb_num = -1;+  if(urb_priv) {+    urb_num = urb_priv->urb_num;+  }+  printk("\nURB:0x%x[%d]\n", (unsigned int)purb, urb_num);+  printk("dev                   :0x%08lx\n", (unsigned long)purb->dev);+  printk("pipe                  :0x%08x\n", purb->pipe);+  printk("status                :%d\n", purb->status);+  printk("transfer_flags        :0x%08x\n", purb->transfer_flags);+  printk("transfer_buffer       :0x%08lx\n", (unsigned long)purb->transfer_buffer);+  printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);+  printk("actual_length         :%d\n", purb->actual_length);+  printk("setup_packet          :0x%08lx\n", (unsigned long)purb->setup_packet);+  printk("start_frame           :%d\n", purb->start_frame);+  printk("number_of_packets     :%d\n", purb->number_of_packets);+  printk("interval              :%d\n", purb->interval);+  printk("error_count           :%d\n", purb->error_count);+  printk("context               :0x%08lx\n", (unsigned long)purb->context);+  printk("complete              :0x%08lx\n\n", (unsigned long)purb->complete);+}++static void __dump_in_desc(volatile struct USB_IN_Desc *in)+{+  printk("\nUSB_IN_Desc at 0x%08lx\n", (unsigned long)in);+  printk("  sw_len  : 0x%04x (%d)\n", in->sw_len, in->sw_len);+  printk("  command : 0x%04x\n", in->command);+  printk("  next    : 0x%08lx\n", in->next);+  printk("  buf     : 0x%08lx\n", in->buf);+  printk("  hw_len  : 0x%04x (%d)\n", in->hw_len, in->hw_len);+  printk("  status  : 0x%04x\n\n", in->status);+}++static void __dump_sb_desc(volatile struct USB_SB_Desc *sb)+{+  char tt = (sb->command & 0x30) >> 4;+  char *tt_string;++  switch (tt) {+  case 0:+    tt_string = "zout";+    break;+  case 1:+    tt_string = "in";+    break;+  case 2:+    tt_string = "out";+    break;+  case 3:+    tt_string = "setup";+    break;+  default:+    tt_string = "unknown (weird)";+  }++  printk(" USB_SB_Desc at 0x%08lx ", (unsigned long)sb);+  printk(" command:0x%04x (", sb->command);+  printk("rem:%d ", (sb->command & 0x3f00) >> 8);+  printk("full:%d ", (sb->command & 0x40) >> 6);+  printk("tt:%d(%s) ", tt, tt_string);+  printk("intr:%d ", (sb->command & 0x8) >> 3);+  printk("eot:%d ", (sb->command & 0x2) >> 1);+  printk("eol:%d)", sb->command & 0x1);+  printk(" sw_len:0x%04x(%d)", sb->sw_len, sb->sw_len);+  printk(" next:0x%08lx", sb->next);+  printk(" buf:0x%08lx\n", sb->buf);+}+++static void __dump_ep_desc(volatile struct USB_EP_Desc *ep)+{+  printk("USB_EP_Desc at 0x%08lx ", (unsigned long)ep);+  printk(" command:0x%04x (", ep->command);+  printk("ep_id:%d ", (ep->command & 0x1f00) >> 8);+  printk("enable:%d ", (ep->command & 0x10) >> 4);+  printk("intr:%d ", (ep->command & 0x8) >> 3);+  printk("eof:%d ", (ep->command & 0x2) >> 1);+  printk("eol:%d)", ep->command & 0x1);+  printk(" hw_len:0x%04x(%d)", ep->hw_len, ep->hw_len);+  printk(" next:0x%08lx", ep->next);+  printk(" sub:0x%08lx\n", ep->sub);+}++static inline void __dump_ep_list(int pipe_type)+{+  volatile struct USB_EP_Desc *ep;+  volatile struct USB_EP_Desc *first_ep;+  volatile struct USB_SB_Desc *sb;++  switch (pipe_type)+    {+    case PIPE_BULK:+      first_ep = &TxBulkEPList[0];+      break;+    case PIPE_CONTROL:+      first_ep = &TxCtrlEPList[0];+      break;+    case PIPE_INTERRUPT:+      first_ep = &TxIntrEPList[0];+      break;+    case PIPE_ISOCHRONOUS:+      first_ep = &TxIsocEPList[0];+      break;+    default:+      warn("Cannot dump unknown traffic type");+      return;+    }+  ep = first_ep;++  printk("\n\nDumping EP list...\n\n");++  do {+    __dump_ep_desc(ep);+    /* Cannot phys_to_virt on 0 as it turns into 80000000, which is != 0. */+    sb = ep->sub ? phys_to_virt(ep->sub) : 0;+    while (sb) {+      __dump_sb_desc(sb);+      sb = sb->next ? phys_to_virt(sb->next) : 0;+    }+    ep = (volatile struct USB_EP_Desc *)(phys_to_virt(ep->next));++  } while (ep != first_ep);+}++static inline void __dump_ept_data(int epid)+{+  unsigned long flags;+  __u32 r_usb_ept_data;++  if (epid < 0 || epid > 31) {+    printk("Cannot dump ept data for invalid epid %d\n", epid);+    return;+  }++  local_irq_save(flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);+  nop();+  r_usb_ept_data = *R_USB_EPT_DATA;+  local_irq_restore(flags);++  printk(" R_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid);+  if (r_usb_ept_data == 0) {+    /* No need for more detailed printing. */+    return;+  }+  printk("  valid           : %d\n", (r_usb_ept_data & 0x80000000) >> 31);+  printk("  hold            : %d\n", (r_usb_ept_data & 0x40000000) >> 30);+  printk("  error_count_in  : %d\n", (r_usb_ept_data & 0x30000000) >> 28);+  printk("  t_in            : %d\n", (r_usb_ept_data & 0x08000000) >> 27);+  printk("  low_speed       : %d\n", (r_usb_ept_data & 0x04000000) >> 26);+  printk("  port            : %d\n", (r_usb_ept_data & 0x03000000) >> 24);+  printk("  error_code      : %d\n", (r_usb_ept_data & 0x00c00000) >> 22);+  printk("  t_out           : %d\n", (r_usb_ept_data & 0x00200000) >> 21);+  printk("  error_count_out : %d\n", (r_usb_ept_data & 0x00180000) >> 19);+  printk("  max_len         : %d\n", (r_usb_ept_data & 0x0003f800) >> 11);+  printk("  ep              : %d\n", (r_usb_ept_data & 0x00000780) >> 7);+  printk("  dev             : %d\n", (r_usb_ept_data & 0x0000003f));+}++static inline void __dump_ept_data_iso(int epid)+{+  unsigned long flags;+  __u32 ept_data;++  if (epid < 0 || epid > 31) {+    printk("Cannot dump ept data for invalid epid %d\n", epid);+    return;+  }++  local_irq_save(flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);+  nop();+  ept_data = *R_USB_EPT_DATA_ISO;+  local_irq_restore(flags);++  printk(" R_USB_EPT_DATA = 0x%x for epid %d :\n", ept_data, epid);+  if (ept_data == 0) {+    /* No need for more detailed printing. */+    return;+  }+  printk("  valid           : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, valid,+						ept_data));+  printk("  port            : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, port,+						ept_data));+  printk("  error_code      : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code,+						ept_data));+  printk("  max_len         : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len,+						ept_data));+  printk("  ep              : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, ep,+						ept_data));+  printk("  dev             : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, dev,+						ept_data));+}++static inline void __dump_ept_data_list(void)+{+  int i;++  printk("Dumping the whole R_USB_EPT_DATA list\n");++  for (i = 0; i < 32; i++) {+    __dump_ept_data(i);+  }+}++static void debug_epid(int epid) {+  int i;+  +  if(epid_isoc(epid)) {+    __dump_ept_data_iso(epid);+  } else {+    __dump_ept_data(epid);+  }++  printk("Bulk:\n");+  for(i = 0; i < 32; i++) {+    if(IO_EXTRACT(USB_EP_command, epid, TxBulkEPList[i].command) ==+       epid) {+      printk("%d: ", i); __dump_ep_desc(&(TxBulkEPList[i]));+    }+  }++  printk("Ctrl:\n");+  for(i = 0; i < 32; i++) {+    if(IO_EXTRACT(USB_EP_command, epid, TxCtrlEPList[i].command) ==+       epid) {+      printk("%d: ", i); __dump_ep_desc(&(TxCtrlEPList[i]));+    }+  }++  printk("Intr:\n");+  for(i = 0; i < MAX_INTR_INTERVAL; i++) {+    if(IO_EXTRACT(USB_EP_command, epid, TxIntrEPList[i].command) ==+       epid) {+      printk("%d: ", i); __dump_ep_desc(&(TxIntrEPList[i]));+    }+  }+  +  printk("Isoc:\n");+  for(i = 0; i < 32; i++) {+    if(IO_EXTRACT(USB_EP_command, epid, TxIsocEPList[i].command) ==+       epid) {+      printk("%d: ", i); __dump_ep_desc(&(TxIsocEPList[i]));+    }+  }++  __dump_ept_data_list();+  __dump_ep_list(PIPE_INTERRUPT);+  printk("\n\n");+}++++char* hcd_status_to_str(__u8 bUsbStatus) {+  static char hcd_status_str[128];+  hcd_status_str[0] = '\0';+  if(bUsbStatus & IO_STATE(R_USB_STATUS, ourun, yes)) {+    strcat(hcd_status_str, "ourun ");+  }+  if(bUsbStatus & IO_STATE(R_USB_STATUS, perror, yes)) {+    strcat(hcd_status_str, "perror ");+  }+  if(bUsbStatus & IO_STATE(R_USB_STATUS, device_mode, yes)) {+    strcat(hcd_status_str, "device_mode ");+  }+  if(bUsbStatus & IO_STATE(R_USB_STATUS, host_mode, yes)) {+    strcat(hcd_status_str, "host_mode ");+  }+  if(bUsbStatus & IO_STATE(R_USB_STATUS, started, yes)) {+    strcat(hcd_status_str, "started ");+  }+  if(bUsbStatus & IO_STATE(R_USB_STATUS, running, yes)) {+    strcat(hcd_status_str, "running ");+  }+  return hcd_status_str;+}+++char* sblist_to_str(struct USB_SB_Desc* sb_desc) {+  static char sblist_to_str_buff[128];+  char tmp[32], tmp2[32];+  sblist_to_str_buff[0] = '\0';+  while(sb_desc != NULL) {+    switch(IO_EXTRACT(USB_SB_command, tt, sb_desc->command)) {+    case 0: sprintf(tmp, "zout");  break;+    case 1: sprintf(tmp, "in");    break;+    case 2: sprintf(tmp, "out");   break;+    case 3: sprintf(tmp, "setup"); break;+    }+    sprintf(tmp2, "(%s %d)", tmp, sb_desc->sw_len);+    strcat(sblist_to_str_buff, tmp2);+    if(sb_desc->next != 0) {+      sb_desc = phys_to_virt(sb_desc->next);+    } else {+      sb_desc = NULL;+    }+  }+  return sblist_to_str_buff;+}++char* port_status_to_str(__u16 wPortStatus) {+  static char port_status_str[128];+  port_status_str[0] = '\0';+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) {+    strcat(port_status_str, "connected ");+  }+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes)) {+    strcat(port_status_str, "enabled ");+  }+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, suspended, yes)) {+    strcat(port_status_str, "suspended ");+  }+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, reset, yes)) {+    strcat(port_status_str, "reset ");+  }+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, speed, full)) {+    strcat(port_status_str, "full-speed ");+  } else {+    strcat(port_status_str, "low-speed ");+  }+  return port_status_str;+}+++char* endpoint_to_str(struct usb_endpoint_descriptor *ed) {+  static char endpoint_to_str_buff[128];+  char tmp[32];+  int epnum = ed->bEndpointAddress & 0x0F;+  int dir = ed->bEndpointAddress & 0x80;+  int type = ed->bmAttributes & 0x03;+  endpoint_to_str_buff[0] = '\0';+  sprintf(endpoint_to_str_buff, "ep:%d ", epnum);+  switch(type) {+  case 0:+    sprintf(tmp, " ctrl");+    break;+  case 1:+    sprintf(tmp, " isoc");+    break;+  case 2:+    sprintf(tmp, " bulk");+    break;+  case 3:+    sprintf(tmp, " intr");+    break;+  }+  strcat(endpoint_to_str_buff, tmp);+  if(dir) {+    sprintf(tmp, " in");+  } else {+    sprintf(tmp, " out");+  }+  strcat(endpoint_to_str_buff, tmp);++  return endpoint_to_str_buff;+}++/* Debug helper functions for Transfer Controller */+char* pipe_to_str(unsigned int pipe) {+  static char pipe_to_str_buff[128];+  char tmp[64];+  sprintf(pipe_to_str_buff, "dir:%s", str_dir(pipe));+  sprintf(tmp, " type:%s", str_type(pipe));+  strcat(pipe_to_str_buff, tmp);++  sprintf(tmp, " dev:%d", usb_pipedevice(pipe));+  strcat(pipe_to_str_buff, tmp);+  sprintf(tmp, " ep:%d", usb_pipeendpoint(pipe));+  strcat(pipe_to_str_buff, tmp);+  return pipe_to_str_buff;+}+++#define USB_DEBUG_DESC 1++#ifdef USB_DEBUG_DESC+#define dump_in_desc(x) __dump_in_desc(x)+#define dump_sb_desc(...) __dump_sb_desc(...)+#define dump_ep_desc(x) __dump_ep_desc(x)+#define dump_ept_data(x) __dump_ept_data(x)+#else+#define dump_in_desc(...) do {} while (0)+#define dump_sb_desc(...) do {} while (0)+#define dump_ep_desc(...) do {} while (0)+#endif+++/* Uncomment this to enable massive function call trace+   #define USB_DEBUG_TRACE */+//#define USB_DEBUG_TRACE 1++#ifdef USB_DEBUG_TRACE+#define DBFENTER (printk(": Entering: %s\n", __FUNCTION__))+#define DBFEXIT  (printk(": Exiting:  %s\n", __FUNCTION__))+#else+#define DBFENTER do {} while (0)+#define DBFEXIT  do {} while (0)+#endif++#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \+{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}++/* Most helpful debugging aid */+#define ASSERT(expr) ((void) ((expr) ? 0 : (err("assert failed at: %s %d",__FUNCTION__, __LINE__))))+++/***************************************************************************/+/***************************************************************************/+/* Forward declarations                                                    */+/***************************************************************************/+/***************************************************************************/+void crisv10_hcd_epid_attn_irq(struct crisv10_irq_reg *reg);+void crisv10_hcd_port_status_irq(struct crisv10_irq_reg *reg);+void crisv10_hcd_ctl_status_irq(struct crisv10_irq_reg *reg);+void crisv10_hcd_isoc_eof_irq(struct crisv10_irq_reg *reg);++void rh_port_status_change(__u16[]);+int  rh_clear_port_feature(__u8, __u16);+int  rh_set_port_feature(__u8, __u16);+static void rh_disable_port(unsigned int port);++static void check_finished_bulk_tx_epids(struct usb_hcd *hcd,+					 int timer);++//static int  tc_setup_epid(struct usb_host_endpoint *ep, struct urb *urb,+//			 int mem_flags);+static int tc_setup_epid(struct urb *urb, int mem_flags);+static void tc_free_epid(struct usb_host_endpoint *ep);+static int  tc_allocate_epid(void);+static void tc_finish_urb(struct usb_hcd *hcd, struct urb *urb, int status);+static void tc_finish_urb_later(struct usb_hcd *hcd, struct urb *urb,+				int status);++static int  urb_priv_create(struct usb_hcd *hcd, struct urb *urb, int epid,+			   int mem_flags);+static void urb_priv_free(struct usb_hcd *hcd, struct urb *urb);++static inline struct urb *urb_list_first(int epid);+static inline void        urb_list_add(struct urb *urb, int epid,+				      int mem_flags);+static inline urb_entry_t *urb_list_entry(struct urb *urb, int epid);+static inline void        urb_list_del(struct urb *urb, int epid);+static inline void        urb_list_move_last(struct urb *urb, int epid);+static inline struct urb *urb_list_next(struct urb *urb, int epid);++int create_sb_for_urb(struct urb *urb, int mem_flags);+int init_intr_urb(struct urb *urb, int mem_flags);++static inline void  etrax_epid_set(__u8 index, __u32 data);+static inline void  etrax_epid_clear_error(__u8 index);+static inline void  etrax_epid_set_toggle(__u8 index, __u8 dirout,+					      __u8 toggle);+static inline __u8  etrax_epid_get_toggle(__u8 index, __u8 dirout);+static inline __u32 etrax_epid_get(__u8 index);++/* We're accessing the same register position in Etrax so+   when we do full access the internal difference doesn't matter */+#define etrax_epid_iso_set(index, data) etrax_epid_set(index, data)+#define etrax_epid_iso_get(index) etrax_epid_get(index)+++//static void        tc_dma_process_isoc_urb(struct urb *urb);+static void        tc_dma_process_queue(int epid);+static void        tc_dma_unlink_intr_urb(struct urb *urb);+static irqreturn_t tc_dma_tx_interrupt(int irq, void *vhc);+static irqreturn_t tc_dma_rx_interrupt(int irq, void *vhc);++static void tc_bulk_start_timer_func(unsigned long dummy);+static void tc_bulk_eot_timer_func(unsigned long dummy);+++/*************************************************************/+/*************************************************************/+/* Host Controler Driver block                               */+/*************************************************************/+/*************************************************************/++/* HCD operations */+static irqreturn_t crisv10_hcd_top_irq(int irq, void*);+static int crisv10_hcd_reset(struct usb_hcd *);+static int crisv10_hcd_start(struct usb_hcd *);+static void crisv10_hcd_stop(struct usb_hcd *);+#ifdef CONFIG_PM+static int crisv10_hcd_suspend(struct device *, u32, u32);+static int crisv10_hcd_resume(struct device *, u32);+#endif /* CONFIG_PM */+static int crisv10_hcd_get_frame(struct usb_hcd *);++//static int  tc_urb_enqueue(struct usb_hcd *, struct usb_host_endpoint *ep, struct urb *, gfp_t mem_flags);+static int tc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);+//static int  tc_urb_dequeue(struct usb_hcd *, struct urb *);+static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);+static void tc_endpoint_disable(struct usb_hcd *, struct usb_host_endpoint *ep);++static int rh_status_data_request(struct usb_hcd *, char *);+static int rh_control_request(struct usb_hcd *, u16, u16, u16, char*, u16);++#ifdef CONFIG_PM+static int crisv10_hcd_hub_suspend(struct usb_hcd *);+static int crisv10_hcd_hub_resume(struct usb_hcd *);+#endif /* CONFIG_PM */+#ifdef CONFIG_USB_OTG+static int crisv10_hcd_start_port_reset(struct usb_hcd *, unsigned);+#endif /* CONFIG_USB_OTG */++/* host controller driver interface */+static const struct hc_driver crisv10_hc_driver = +  {+    .description =	hc_name,+    .product_desc =	product_desc,+    .hcd_priv_size =	sizeof(struct crisv10_hcd),++    /* Attaching IRQ handler manualy in probe() */+    /* .irq =		crisv10_hcd_irq, */++    .flags =		HCD_USB11,++    /* called to init HCD and root hub */+    .reset =		crisv10_hcd_reset,+    .start =		crisv10_hcd_start,	++    /* cleanly make HCD stop writing memory and doing I/O */+    .stop =		crisv10_hcd_stop,++    /* return current frame number */+    .get_frame_number =	crisv10_hcd_get_frame,+++    /* Manage i/o requests via the Transfer Controller */+    .urb_enqueue =	tc_urb_enqueue,+    .urb_dequeue =	tc_urb_dequeue,++    /* hw synch, freeing endpoint resources that urb_dequeue can't */+    .endpoint_disable = tc_endpoint_disable,+++    /* Root Hub support */+    .hub_status_data =	rh_status_data_request,+    .hub_control =	rh_control_request,+#ifdef CONFIG_PM+    .hub_suspend =	rh_suspend_request,+    .hub_resume =	rh_resume_request,+#endif /* CONFIG_PM */+#ifdef	CONFIG_USB_OTG+    .start_port_reset =	crisv10_hcd_start_port_reset,+#endif /* CONFIG_USB_OTG */+  };+++/*+ * conversion between pointers to a hcd and the corresponding+ * crisv10_hcd + */++static inline struct crisv10_hcd *hcd_to_crisv10_hcd(struct usb_hcd *hcd)+{+	return (struct crisv10_hcd *) hcd->hcd_priv;+}++static inline struct usb_hcd *crisv10_hcd_to_hcd(struct crisv10_hcd *hcd)+{+	return container_of((void *) hcd, struct usb_hcd, hcd_priv);+}++/* check if specified port is in use */+static inline int port_in_use(unsigned int port)+{+	return ports & (1 << port);+}++/* number of ports in use */+static inline unsigned int num_ports(void)+{+	unsigned int i, num = 0;+	for (i = 0; i < USB_ROOT_HUB_PORTS; i++)+		if (port_in_use(i))+			num++;+	return num;+}++/* map hub port number to the port number used internally by the HC */+static inline unsigned int map_port(unsigned int port)+{+  unsigned int i, num = 0;+  for (i = 0; i < USB_ROOT_HUB_PORTS; i++)+    if (port_in_use(i))+      if (++num == port)+	return i;+  return -1;+}++/* size of descriptors in slab cache */+#ifndef MAX+#define MAX(x, y)		((x) > (y) ? (x) : (y))+#endif+++/******************************************************************/+/* Hardware Interrupt functions                                   */+/******************************************************************/++/* Fast interrupt handler for HC */+static irqreturn_t crisv10_hcd_top_irq(int irq, void *vcd)+{+  struct usb_hcd *hcd = vcd;+  struct crisv10_irq_reg reg;+  __u32 irq_mask;+  unsigned long flags;++  DBFENTER;++  ASSERT(hcd != NULL);+  reg.hcd = hcd;++  /* Turn of other interrupts while handling these sensitive cases */+  local_irq_save(flags);+  +  /* Read out which interrupts that are flaged */+  irq_mask = *R_USB_IRQ_MASK_READ;+  reg.r_usb_irq_mask_read = irq_mask;++  /* Reading R_USB_STATUS clears the ctl_status interrupt. Note that+     R_USB_STATUS must be read before R_USB_EPID_ATTN since reading the latter+     clears the ourun and perror fields of R_USB_STATUS. */+  reg.r_usb_status = *R_USB_STATUS;+  +  /* Reading R_USB_EPID_ATTN clears the iso_eof, bulk_eot and epid_attn+     interrupts. */+  reg.r_usb_epid_attn = *R_USB_EPID_ATTN;+  +  /* Reading R_USB_RH_PORT_STATUS_1 and R_USB_RH_PORT_STATUS_2 clears the+     port_status interrupt. */+  reg.r_usb_rh_port_status_1 = *R_USB_RH_PORT_STATUS_1;+  reg.r_usb_rh_port_status_2 = *R_USB_RH_PORT_STATUS_2;+  +  /* Reading R_USB_FM_NUMBER clears the sof interrupt. */+  /* Note: the lower 11 bits contain the actual frame number, sent with each+     sof. */+  reg.r_usb_fm_number = *R_USB_FM_NUMBER;++  /* Interrupts are handled in order of priority. */+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {+    crisv10_hcd_port_status_irq(®);+  }+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, epid_attn)) {+    crisv10_hcd_epid_attn_irq(®);+  }+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, ctl_status)) {+    crisv10_hcd_ctl_status_irq(®);+  }+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, iso_eof)) {+    crisv10_hcd_isoc_eof_irq(®);+  }+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, bulk_eot)) {+    /* Update/restart the bulk start timer since obviously the channel is+       running. */+    mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);+    /* Update/restart the bulk eot timer since we just received an bulk eot+       interrupt. */+    mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);++    /* Check for finished bulk transfers on epids */+    check_finished_bulk_tx_epids(hcd, 0);+  }+  local_irq_restore(flags);++  DBFEXIT;+  return IRQ_HANDLED;+}+++void crisv10_hcd_epid_attn_irq(struct crisv10_irq_reg *reg) {+  struct usb_hcd *hcd = reg->hcd;+  struct crisv10_urb_priv *urb_priv;+  int epid;+  DBFENTER;++  for (epid = 0; epid < NBR_OF_EPIDS; epid++) {+    if (test_bit(epid, (void *)®->r_usb_epid_attn)) {+      struct urb *urb;+      __u32 ept_data;+      int error_code;++      if (epid == DUMMY_EPID || epid == INVALID_EPID) {+	/* We definitely don't care about these ones. Besides, they are+	   always disabled, so any possible disabling caused by the+	   epid attention interrupt is irrelevant. */+	warn("Got epid_attn for INVALID_EPID or DUMMY_EPID (%d).", epid);+	continue;+      }++      if(!epid_inuse(epid)) {+	irq_err("Epid attention on epid:%d that isn't in use\n", epid);+	printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);+	debug_epid(epid);+	continue;+      }++      /* Note that although there are separate R_USB_EPT_DATA and+	 R_USB_EPT_DATA_ISO registers, they are located at the same address and+	 are of the same size. In other words, this read should be ok for isoc+	 also. */+      ept_data = etrax_epid_get(epid);+      error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code, ept_data);++      /* Get the active URB for this epid. We blatantly assume+	 that only this URB could have caused the epid attention. */+      urb = activeUrbList[epid];+      if (urb == NULL) {+	irq_err("Attention on epid:%d error:%d with no active URB.\n",+		epid, error_code);+	printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);+	debug_epid(epid);+	continue;+      }++      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+      ASSERT(urb_priv);++      /* Using IO_STATE_VALUE on R_USB_EPT_DATA should be ok for isoc also. */+      if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {++	/* Isoc traffic doesn't have error_count_in/error_count_out. */+	if ((usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) &&+	    (IO_EXTRACT(R_USB_EPT_DATA, error_count_in, ept_data) == 3 ||+	     IO_EXTRACT(R_USB_EPT_DATA, error_count_out, ept_data) == 3)) {+	  /* Check if URB allready is marked for late-finish, we can get+	     several 3rd error for Intr traffic when a device is unplugged */+	  if(urb_priv->later_data == NULL) {+	    /* 3rd error. */+	    irq_warn("3rd error for epid:%d (%s %s) URB:0x%x[%d]\n", epid,+		     str_dir(urb->pipe), str_type(urb->pipe),+		     (unsigned int)urb, urb_priv->urb_num);+	  +	    tc_finish_urb_later(hcd, urb, -EPROTO);+	  }++	} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {+	  irq_warn("Perror for epid:%d\n", epid);+	  printk("FM_NUMBER: %d\n", reg->r_usb_fm_number & 0x7ff);+	  printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);+	  __dump_urb(urb);+	  debug_epid(epid);++	  if (!(ept_data & IO_MASK(R_USB_EPT_DATA, valid))) {+	    /* invalid ep_id */+	    panic("Perror because of invalid epid."+		  " Deconfigured too early?");+	  } else {+	    /* past eof1, near eof, zout transfer, setup transfer */+	    /* Dump the urb and the relevant EP descriptor. */+	    panic("Something wrong with DMA descriptor contents."+		  " Too much traffic inserted?");+	  }+	} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {+	  /* buffer ourun */+	  printk("FM_NUMBER: %d\n", reg->r_usb_fm_number & 0x7ff);+	  printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);+	  __dump_urb(urb);+	  debug_epid(epid);++	  panic("Buffer overrun/underrun for epid:%d. DMA too busy?", epid);+	} else {+	  irq_warn("Attention on epid:%d (%s %s) with no error code\n", epid,+		   str_dir(urb->pipe), str_type(urb->pipe));+	  printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);+	  __dump_urb(urb);+	  debug_epid(epid);+	}++      } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code,+					      stall)) {+	/* Not really a protocol error, just says that the endpoint gave+	   a stall response. Note that error_code cannot be stall for isoc. */+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+	  panic("Isoc traffic cannot stall");+	}++	tc_dbg("Stall for epid:%d (%s %s) URB:0x%x\n", epid,+	       str_dir(urb->pipe), str_type(urb->pipe), (unsigned int)urb);+	tc_finish_urb(hcd, urb, -EPIPE);++      } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code,+					      bus_error)) {+	/* Two devices responded to a transaction request. Must be resolved+	   by software. FIXME: Reset ports? */+	panic("Bus error for epid %d."+	      " Two devices responded to transaction request\n",+	      epid);++      } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code,+					      buffer_error)) {+	/* DMA overrun or underrun. */+	irq_warn("Buffer overrun/underrun for epid:%d (%s %s)\n", epid,+		 str_dir(urb->pipe), str_type(urb->pipe));++	/* It seems that error_code = buffer_error in+	   R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS+	   are the same error. */+	tc_finish_urb(hcd, urb, -EPROTO);+      } else {+	  irq_warn("Unknown attention on epid:%d (%s %s)\n", epid,+		   str_dir(urb->pipe), str_type(urb->pipe));+	  dump_ept_data(epid);+      }+    }+  }+  DBFEXIT;+}++void crisv10_hcd_port_status_irq(struct crisv10_irq_reg *reg)+{+  __u16 port_reg[USB_ROOT_HUB_PORTS];+  DBFENTER;+  port_reg[0] = reg->r_usb_rh_port_status_1;+  port_reg[1] = reg->r_usb_rh_port_status_2;+  rh_port_status_change(port_reg);+  DBFEXIT;+}++void crisv10_hcd_isoc_eof_irq(struct crisv10_irq_reg *reg)+{+  int epid;+  struct urb *urb;+  struct crisv10_urb_priv *urb_priv;++  DBFENTER;++  for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {++    /* Only check epids that are in use, is valid and has SB list */+    if (!epid_inuse(epid) || epid == INVALID_EPID ||+	TxIsocEPList[epid].sub == 0 || epid == DUMMY_EPID) {+      /* Nothing here to see. */+      continue;+    }+    ASSERT(epid_isoc(epid));++    /* Get the active URB for this epid (if any). */+    urb = activeUrbList[epid];+    if (urb == 0) {+      isoc_warn("Ignoring NULL urb for epid:%d\n", epid);+      continue;+    }+    if(!epid_out_traffic(epid)) {+      /* Sanity check. */+      ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);++      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+      ASSERT(urb_priv);++      if (urb_priv->urb_state == NOT_STARTED) {+	/* If ASAP is not set and urb->start_frame is the current frame,+	   start the transfer. */+	if (!(urb->transfer_flags & URB_ISO_ASAP) &&+	    (urb->start_frame == (*R_USB_FM_NUMBER & 0x7ff))) {+	  /* EP should not be enabled if we're waiting for start_frame */+	  ASSERT((TxIsocEPList[epid].command &+		  IO_STATE(USB_EP_command, enable, yes)) == 0);++	  isoc_warn("Enabling isoc IN EP descr for epid %d\n", epid);+	  TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);++	  /* This urb is now active. */+	  urb_priv->urb_state = STARTED;+	  continue;+	}+      }+    }+  }++  DBFEXIT;+}++void crisv10_hcd_ctl_status_irq(struct crisv10_irq_reg *reg)+{+  struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(reg->hcd);++  DBFENTER;+  ASSERT(crisv10_hcd);++  irq_dbg("ctr_status_irq, controller status: %s\n",+	  hcd_status_to_str(reg->r_usb_status));+  +  /* FIXME: What should we do if we get ourun or perror? Dump the EP and SB+     list for the corresponding epid? */+  if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {+    panic("USB controller got ourun.");+  }+  if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {+    +    /* Before, etrax_usb_do_intr_recover was called on this epid if it was+       an interrupt pipe. I don't see how re-enabling all EP descriptors+       will help if there was a programming error. */+    panic("USB controller got perror.");+  }++  /* Keep track of USB Controller, if it's running or not */+  if(reg->r_usb_status & IO_STATE(R_USB_STATUS, running, yes)) {+    crisv10_hcd->running = 1;+  } else {+    crisv10_hcd->running = 0;+  }+  +  if (reg->r_usb_status & IO_MASK(R_USB_STATUS, device_mode)) {+    /* We should never operate in device mode. */+    panic("USB controller in device mode.");+  }++  /* Set the flag to avoid getting "Unlink after no-IRQ? Controller is probably+     using the wrong IRQ" from hcd_unlink_urb() in drivers/usb/core/hcd.c */+  set_bit(HCD_FLAG_SAW_IRQ, ®->hcd->flags);+  +  DBFEXIT;+}+++/******************************************************************/+/* Host Controller interface functions                            */+/******************************************************************/++static inline void crisv10_ready_wait(void) {+  volatile int timeout = 10000;+  /* Check the busy bit of USB controller in Etrax */+  while((*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)) &&+	(timeout-- > 0));+  if(timeout == 0) {+    warn("Timeout while waiting for USB controller to be idle\n");+  }+}++/* reset host controller */+static int crisv10_hcd_reset(struct usb_hcd *hcd)+{+  DBFENTER;+  hcd_dbg(hcd, "reset\n");+++  /* Reset the USB interface. */+  /*+  *R_USB_COMMAND =+    IO_STATE(R_USB_COMMAND, port_sel, nop) |+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |+    IO_STATE(R_USB_COMMAND, ctrl_cmd, reset);+  nop();+  */+  DBFEXIT;+  return 0;+}++/* start host controller */+static int crisv10_hcd_start(struct usb_hcd *hcd)+{+  DBFENTER;+  hcd_dbg(hcd, "start\n");++  crisv10_ready_wait();++  /* Start processing of USB traffic. */+  *R_USB_COMMAND =+    IO_STATE(R_USB_COMMAND, port_sel, nop) |+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |+    IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);++  nop();++  hcd->state = HC_STATE_RUNNING;++  DBFEXIT;+  return 0;+}++/* stop host controller */+static void crisv10_hcd_stop(struct usb_hcd *hcd)+{+  DBFENTER;+  hcd_dbg(hcd, "stop\n");+  crisv10_hcd_reset(hcd);+  DBFEXIT;+}++/* return the current frame number */+static int crisv10_hcd_get_frame(struct usb_hcd *hcd)+{+  DBFENTER;+  DBFEXIT;+  return (*R_USB_FM_NUMBER & 0x7ff);+}++#ifdef	CONFIG_USB_OTG++static int crisv10_hcd_start_port_reset(struct usb_hcd *hcd, unsigned port)+{+  return 0; /* no-op for now */+}++#endif /* CONFIG_USB_OTG */+++/******************************************************************/+/* Root Hub functions                                             */+/******************************************************************/++/* root hub status */+static const struct usb_hub_status rh_hub_status = +  {+    .wHubStatus =		0,+    .wHubChange =		0,+  };++/* root hub descriptor */+static const u8 rh_hub_descr[] =+  {+    0x09,			/* bDescLength	       */+    0x29,			/* bDescriptorType     */+    USB_ROOT_HUB_PORTS,         /* bNbrPorts	       */+    0x00,			/* wHubCharacteristics */+    0x00,		 +    0x01,			/* bPwrOn2pwrGood      */+    0x00,			/* bHubContrCurrent    */+    0x00,			/* DeviceRemovable     */+    0xff			/* PortPwrCtrlMask     */+  };++/* Actual holder of root hub status*/+struct crisv10_rh rh;++/* Initialize root hub data structures (called from dvdrv_hcd_probe()) */+int rh_init(void) {+  int i;+  /* Reset port status flags */+  for (i = 0; i < USB_ROOT_HUB_PORTS; i++) {+    rh.wPortChange[i] = 0;+    rh.wPortStatusPrev[i] = 0;+  }+  return 0;+}++#define RH_FEAT_MASK ((1<<USB_PORT_FEAT_CONNECTION)|\+		      (1<<USB_PORT_FEAT_ENABLE)|\+		      (1<<USB_PORT_FEAT_SUSPEND)|\+		      (1<<USB_PORT_FEAT_RESET))++/* Handle port status change interrupt (called from bottom part interrupt) */+void rh_port_status_change(__u16 port_reg[]) {+  int i;+  __u16 wChange;++  for(i = 0; i < USB_ROOT_HUB_PORTS; i++) {+    /* Xor out changes since last read, masked for important flags */+    wChange = (port_reg[i] & RH_FEAT_MASK) ^ rh.wPortStatusPrev[i];+    /* Or changes together with (if any) saved changes */+    rh.wPortChange[i] |= wChange;+    /* Save new status */+    rh.wPortStatusPrev[i] = port_reg[i];++    if(wChange) {+      rh_dbg("Interrupt port_status change port%d: %s  Current-status:%s\n", i+1,+	     port_status_to_str(wChange),+	     port_status_to_str(port_reg[i]));+    }+  }+}++/* Construct port status change bitmap for the root hub */+static int rh_status_data_request(struct usb_hcd *hcd, char *buf)+{+  struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(hcd);+  unsigned int i;++//  DBFENTER;+  +  /*+   * corresponds to hub status change EP (USB 2.0 spec section 11.13.4)+   * return bitmap indicating ports with status change+   */+  *buf = 0;+  spin_lock(&crisv10_hcd->lock);+  for (i = 1; i <= crisv10_hcd->num_ports; i++) {+    if (rh.wPortChange[map_port(i)]) {+      *buf |= (1 << i);+      rh_dbg("rh_status_data_request, change on port %d: %s  Current Status: %s\n", i,+	     port_status_to_str(rh.wPortChange[map_port(i)]),+	     port_status_to_str(rh.wPortStatusPrev[map_port(i)]));+    }+  }+  spin_unlock(&crisv10_hcd->lock);++// DBFEXIT;++  return *buf == 0 ? 0 : 1;+}++/* Handle a control request for the root hub (called from hcd_driver) */+static int rh_control_request(struct usb_hcd *hcd, +			      u16 typeReq, +			      u16 wValue, +			      u16 wIndex,+			      char *buf, +			      u16 wLength) {++  struct crisv10_hcd *crisv10_hcd = hcd_to_crisv10_hcd(hcd);+  int retval = 0;+  int len;+  DBFENTER;++  switch (typeReq) {+  case GetHubDescriptor:+    rh_dbg("GetHubDescriptor\n");+    len = min_t(unsigned int, sizeof rh_hub_descr, wLength);+    memcpy(buf, rh_hub_descr, len);+    buf[2] = crisv10_hcd->num_ports;+    break;+  case GetHubStatus:+    rh_dbg("GetHubStatus\n");+    len = min_t(unsigned int, sizeof rh_hub_status, wLength);+    memcpy(buf, &rh_hub_status, len);+    break;+  case GetPortStatus:+    if (!wIndex || wIndex > crisv10_hcd->num_ports)+      goto error;+    rh_dbg("GetportStatus, port:%d change:%s  status:%s\n", wIndex,+	   port_status_to_str(rh.wPortChange[map_port(wIndex)]),+	   port_status_to_str(rh.wPortStatusPrev[map_port(wIndex)]));+    *(u16 *) buf = cpu_to_le16(rh.wPortStatusPrev[map_port(wIndex)]);+    *(u16 *) (buf + 2) = cpu_to_le16(rh.wPortChange[map_port(wIndex)]);+    break;+  case SetHubFeature:+    rh_dbg("SetHubFeature\n");+  case ClearHubFeature:+    rh_dbg("ClearHubFeature\n");+    switch (wValue) {+    case C_HUB_OVER_CURRENT:+    case C_HUB_LOCAL_POWER:+      rh_warn("Not implemented hub request:%d \n", typeReq);+      /* not implemented */+      break;+    default:+      goto error;+    }+    break;+  case SetPortFeature:+    if (!wIndex || wIndex > crisv10_hcd->num_ports)+      goto error;+    if(rh_set_port_feature(map_port(wIndex), wValue))+      goto error;+    break;+  case ClearPortFeature:+    if (!wIndex || wIndex > crisv10_hcd->num_ports)+      goto error;+    if(rh_clear_port_feature(map_port(wIndex), wValue))+      goto error;+    break;+  default:+    rh_warn("Unknown hub request: %d\n", typeReq);+  error:+    retval = -EPIPE;+  }+  DBFEXIT;+  return retval;+}++int rh_set_port_feature(__u8 bPort, __u16 wFeature) {+  __u8 bUsbCommand = 0;+  switch(wFeature) {+  case USB_PORT_FEAT_RESET:+    rh_dbg("SetPortFeature: reset\n");+    bUsbCommand |= IO_STATE(R_USB_COMMAND, port_cmd, reset);+    goto set;+    break;+  case USB_PORT_FEAT_SUSPEND:+    rh_dbg("SetPortFeature: suspend\n");+    bUsbCommand |= IO_STATE(R_USB_COMMAND, port_cmd, suspend);+    goto set;+    break;+  case USB_PORT_FEAT_POWER:+    rh_dbg("SetPortFeature: power\n");+    break;+  case USB_PORT_FEAT_C_CONNECTION:+    rh_dbg("SetPortFeature: c_connection\n");+    break;+  case USB_PORT_FEAT_C_RESET:+    rh_dbg("SetPortFeature: c_reset\n");+    break;+  case USB_PORT_FEAT_C_OVER_CURRENT:+    rh_dbg("SetPortFeature: c_over_current\n");+    break;++  set:+    /* Select which port via the port_sel field */+    bUsbCommand |= IO_FIELD(R_USB_COMMAND, port_sel, bPort+1);++    /* Make sure the controller isn't busy. */+    crisv10_ready_wait();+    /* Send out the actual command to the USB controller */+    *R_USB_COMMAND = bUsbCommand;++    /* If port reset then also bring USB controller into running state */+    if(wFeature == USB_PORT_FEAT_RESET) {+      /* Wait a while for controller to first become started after port reset */+      udelay(12000); /* 12ms blocking wait */+      +      /* Make sure the controller isn't busy. */+      crisv10_ready_wait();++      /* If all enabled ports were disabled the host controller goes down into+	 started mode, so we need to bring it back into the running state.+	 (This is safe even if it's already in the running state.) */+      *R_USB_COMMAND =+	IO_STATE(R_USB_COMMAND, port_sel, nop) |+	IO_STATE(R_USB_COMMAND, port_cmd, reset) |+	IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);+    }++    break;+  default:+    rh_dbg("SetPortFeature: unknown feature\n");+    return -1;+  }+  return 0;+}++int rh_clear_port_feature(__u8 bPort, __u16 wFeature) {+  switch(wFeature) {+  case USB_PORT_FEAT_ENABLE:+    rh_dbg("ClearPortFeature: enable\n");+    rh_disable_port(bPort);+    break;+  case USB_PORT_FEAT_SUSPEND:+    rh_dbg("ClearPortFeature: suspend\n");+    break;+  case USB_PORT_FEAT_POWER:+    rh_dbg("ClearPortFeature: power\n");+    break;++  case USB_PORT_FEAT_C_ENABLE:+    rh_dbg("ClearPortFeature: c_enable\n");+    goto clear;+  case USB_PORT_FEAT_C_SUSPEND:+    rh_dbg("ClearPortFeature: c_suspend\n");+    goto clear;+  case USB_PORT_FEAT_C_CONNECTION:+    rh_dbg("ClearPortFeature: c_connection\n");+    goto clear;+  case USB_PORT_FEAT_C_OVER_CURRENT:+    rh_dbg("ClearPortFeature: c_over_current\n");+    goto clear;+  case USB_PORT_FEAT_C_RESET:+    rh_dbg("ClearPortFeature: c_reset\n");+    goto clear;+  clear:+    rh.wPortChange[bPort] &= ~(1 << (wFeature - 16));+    break;+  default:+    rh_dbg("ClearPortFeature: unknown feature\n");+    return -1;+  }+  return 0;+}+++#ifdef	CONFIG_PM+/* Handle a suspend request for the root hub (called from hcd_driver) */+static int rh_suspend_request(struct usb_hcd *hcd)+{+  return 0; /* no-op for now */+}++/* Handle a resume request for the root hub (called from hcd_driver) */+static int rh_resume_request(struct usb_hcd *hcd)+{+  return 0; /* no-op for now */+}+#endif /* CONFIG_PM */++++/* Wrapper function for workaround port disable registers in USB controller  */+static void rh_disable_port(unsigned int port) {+  volatile int timeout = 10000;+  volatile char* usb_portx_disable;+  switch(port) {+  case 0:+    usb_portx_disable = R_USB_PORT1_DISABLE;+    break;+  case 1:+    usb_portx_disable = R_USB_PORT2_DISABLE;+    break;+  default:+    /* Invalid port index */+    return;+  }+  /* Set disable flag in special register  */+  *usb_portx_disable = IO_STATE(R_USB_PORT1_DISABLE, disable, yes);+  /* Wait until not enabled anymore */+  while((rh.wPortStatusPrev[port] &+	IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes)) &&+	(timeout-- > 0));+  if(timeout == 0) {+    warn("Timeout while waiting for port %d to become disabled\n", port);+  }+  /* clear disable flag in special register  */+  *usb_portx_disable = IO_STATE(R_USB_PORT1_DISABLE, disable, no);+  rh_info("Physical port %d disabled\n", port+1);+}+++/******************************************************************/+/* Transfer Controller (TC) functions                             */+/******************************************************************/++/* FIXME: Should RX_BUF_SIZE be a config option, or maybe we should adjust it+   dynamically?+   To adjust it dynamically we would have to get an interrupt when we reach+   the end of the rx descriptor list, or when we get close to the end, and+   then allocate more descriptors. */+#define NBR_OF_RX_DESC     512+#define RX_DESC_BUF_SIZE   1024+#define RX_BUF_SIZE        (NBR_OF_RX_DESC * RX_DESC_BUF_SIZE)+++/* Local variables for Transfer Controller */+/* --------------------------------------- */++/* This is a circular (double-linked) list of the active urbs for each epid.+   The head is never removed, and new urbs are linked onto the list as+   urb_entry_t elements. Don't reference urb_list directly; use the wrapper+   functions instead (which includes spin_locks) */+static struct list_head urb_list[NBR_OF_EPIDS];++/* Read about the need and usage of this lock in submit_ctrl_urb. */+/* Lock for URB lists for each EPID */+static spinlock_t urb_list_lock;++/* Lock for EPID array register (R_USB_EPT_x) in Etrax */+static spinlock_t etrax_epid_lock;++/* Lock for dma8 sub0 handling */+static spinlock_t etrax_dma8_sub0_lock;++/* DMA IN cache bug. Align the DMA IN buffers to 32 bytes, i.e. a cache line.+   Since RX_DESC_BUF_SIZE is 1024 is a multiple of 32, all rx buffers will be+   cache aligned. */+static volatile unsigned char RxBuf[RX_BUF_SIZE] __attribute__ ((aligned (32)));+static volatile struct USB_IN_Desc RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4)));++/* Pointers into RxDescList. */+static volatile struct USB_IN_Desc *myNextRxDesc;+static volatile struct USB_IN_Desc *myLastRxDesc;++/* A zout transfer makes a memory access at the address of its buf pointer,+   which means that setting this buf pointer to 0 will cause an access to the+   flash. In addition to this, setting sw_len to 0 results in a 16/32 bytes+   (depending on DMA burst size) transfer.+   Instead, we set it to 1, and point it to this buffer. */+static int zout_buffer[4] __attribute__ ((aligned (4)));++/* Cache for allocating new EP and SB descriptors. */+//static kmem_cache_t *usb_desc_cache;+static struct kmem_cache *usb_desc_cache;++/* Cache for the data allocated in the isoc descr top half. */+//static kmem_cache_t *isoc_compl_cache;+static struct kmem_cache *isoc_compl_cache;++/* Cache for the data allocated when delayed finishing of URBs */+//static kmem_cache_t *later_data_cache;+static struct kmem_cache *later_data_cache;++/* Counter to keep track of how many Isoc EP we have sat up. Used to enable+   and disable iso_eof interrupt. We only need these interrupts when we have+   Isoc data endpoints (consumes CPU cycles).+   FIXME: This could be more fine granular, so this interrupt is only enabled+   when we have a In Isoc URB not URB_ISO_ASAP flaged queued. */+static int isoc_epid_counter;++/* Protecting wrapper functions for R_USB_EPT_x */+/* -------------------------------------------- */+static inline void etrax_epid_set(__u8 index, __u32 data) {+  unsigned long flags;+  spin_lock_irqsave(&etrax_epid_lock, flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index);+  nop();+  *R_USB_EPT_DATA = data;+  spin_unlock_irqrestore(&etrax_epid_lock, flags);+}++static inline void etrax_epid_clear_error(__u8 index) {+  unsigned long flags;+  spin_lock_irqsave(&etrax_epid_lock, flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index);+  nop();+  *R_USB_EPT_DATA &=+    ~(IO_MASK(R_USB_EPT_DATA, error_count_in) |+      IO_MASK(R_USB_EPT_DATA, error_count_out) |+      IO_MASK(R_USB_EPT_DATA, error_code));+  spin_unlock_irqrestore(&etrax_epid_lock, flags);+}++static inline void etrax_epid_set_toggle(__u8 index, __u8 dirout,+                                             __u8 toggle) {+  unsigned long flags;+  spin_lock_irqsave(&etrax_epid_lock, flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index);+  nop();+  if(dirout) {+    *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out);+    *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle);+  } else {+    *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in);+    *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle);+  }+  spin_unlock_irqrestore(&etrax_epid_lock, flags);+}++static inline __u8 etrax_epid_get_toggle(__u8 index, __u8 dirout) {+  unsigned long flags;+  __u8 toggle;+  spin_lock_irqsave(&etrax_epid_lock, flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index);+  nop();+  if (dirout) {+    toggle = IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA);+  } else {+    toggle = IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA);+  }+  spin_unlock_irqrestore(&etrax_epid_lock, flags);+  return toggle;+}+++static inline __u32 etrax_epid_get(__u8 index) {+  unsigned long flags;+  __u32 data;+  spin_lock_irqsave(&etrax_epid_lock, flags);+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index);+  nop();+  data = *R_USB_EPT_DATA;+  spin_unlock_irqrestore(&etrax_epid_lock, flags);+  return data;+}+++++/* Main functions for Transfer Controller */+/* -------------------------------------- */++/* Init structs, memories and lists used by Transfer Controller */+int tc_init(struct usb_hcd *hcd) {+  int i;+  /* Clear software state info for all epids */+  memset(epid_state, 0, sizeof(struct etrax_epid) * NBR_OF_EPIDS);++  /* Set Invalid and Dummy as being in use and disabled */+  epid_state[INVALID_EPID].inuse = 1;+  epid_state[DUMMY_EPID].inuse = 1;+  epid_state[INVALID_EPID].disabled = 1;+  epid_state[DUMMY_EPID].disabled = 1;++  /* Clear counter for how many Isoc epids we have sat up */+  isoc_epid_counter = 0;++  /* Initialize the urb list by initiating a head for each list.+     Also reset list hodling active URB for each epid */+  for (i = 0; i < NBR_OF_EPIDS; i++) {+    INIT_LIST_HEAD(&urb_list[i]);+    activeUrbList[i] = NULL;+  }++  /* Init lock for URB lists */+  spin_lock_init(&urb_list_lock);+  /* Init lock for Etrax R_USB_EPT register */+  spin_lock_init(&etrax_epid_lock);+  /* Init lock for Etrax dma8 sub0 handling */+  spin_lock_init(&etrax_dma8_sub0_lock);++  /* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */++  /* Note that we specify sizeof(struct USB_EP_Desc) as the size, but also+     allocate SB descriptors from this cache. This is ok since+     sizeof(struct USB_EP_Desc) == sizeof(struct USB_SB_Desc). */+//  usb_desc_cache = kmem_cache_create("usb_desc_cache",+//				     sizeof(struct USB_EP_Desc), 0,+//				     SLAB_HWCACHE_ALIGN, 0, 0);+  usb_desc_cache = kmem_cache_create(+				  "usb_desc_cache",+				  sizeof(struct USB_EP_Desc),+				  0,+				  SLAB_HWCACHE_ALIGN,+				  NULL);+  if(usb_desc_cache == NULL) {+    return -ENOMEM;+  }++  /* Create slab cache for speedy allocation of memory for isoc bottom-half+     interrupt handling */+//  isoc_compl_cache =+//    kmem_cache_create("isoc_compl_cache",+//		      sizeof(struct crisv10_isoc_complete_data),+//		      0, SLAB_HWCACHE_ALIGN, 0, 0);+  isoc_compl_cache = kmem_cache_create(+				  "isoc_compl_cache",+				  sizeof(struct crisv10_isoc_complete_data),+				  0,+				  SLAB_HWCACHE_ALIGN,+				  NULL+				  );++  if(isoc_compl_cache == NULL) {+    return -ENOMEM;+  }++  /* Create slab cache for speedy allocation of memory for later URB finish+     struct */+//  later_data_cache =+//    kmem_cache_create("later_data_cache",+//		      sizeof(struct urb_later_data),+//		      0, SLAB_HWCACHE_ALIGN, 0, 0);++  later_data_cache = kmem_cache_create(+				  "later_data_cache",+				  sizeof(struct urb_later_data),+				  0,+				  SLAB_HWCACHE_ALIGN,+				  NULL+				  );+  +  if(later_data_cache == NULL) {+    return -ENOMEM;+  }+++  /* Initiate the bulk start timer. */+  init_timer(&bulk_start_timer);+  bulk_start_timer.expires = jiffies + BULK_START_TIMER_INTERVAL;+  bulk_start_timer.function = tc_bulk_start_timer_func;+  add_timer(&bulk_start_timer);+++  /* Initiate the bulk eot timer. */+  init_timer(&bulk_eot_timer);+  bulk_eot_timer.expires = jiffies + BULK_EOT_TIMER_INTERVAL;+  bulk_eot_timer.function = tc_bulk_eot_timer_func;+  bulk_eot_timer.data = (unsigned long)hcd;+  add_timer(&bulk_eot_timer);++  return 0;+}++/* Uninitialize all resources used by Transfer Controller */+void tc_destroy(void) {++  /* Destroy all slab cache */+  kmem_cache_destroy(usb_desc_cache);+  kmem_cache_destroy(isoc_compl_cache);+  kmem_cache_destroy(later_data_cache);++  /* Remove timers */+  del_timer(&bulk_start_timer);+  del_timer(&bulk_eot_timer);+}++static void restart_dma8_sub0(void) {+  unsigned long flags;+  spin_lock_irqsave(&etrax_dma8_sub0_lock, flags);+  /* Verify that the dma is not running */+  if ((*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd)) == 0) {+    struct USB_EP_Desc *ep = (struct USB_EP_Desc *)phys_to_virt(*R_DMA_CH8_SUB0_EP);+    while (DUMMY_EPID == IO_EXTRACT(USB_EP_command, epid, ep->command)) {+      ep = (struct USB_EP_Desc *)phys_to_virt(ep->next);+    }+    /* Advance the DMA to the next EP descriptor that is not a DUMMY_EPID.+	 * ep->next is already a physical address. virt_to_phys is needed, see+	 * http://mhonarc.axis.se/dev-etrax/msg08630.html+	 */+    //*R_DMA_CH8_SUB0_EP = ep->next;+	*R_DMA_CH8_SUB0_EP = virt_to_phys(ep);+    /* Restart the DMA */+    *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);+  }+  spin_unlock_irqrestore(&etrax_dma8_sub0_lock, flags);+}++/* queue an URB with the transfer controller (called from hcd_driver) */+//static int tc_urb_enqueue(struct usb_hcd *hcd, +//			  struct usb_host_endpoint *ep,+//			  struct urb *urb, +//			  gfp_t mem_flags) {+static int tc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)+{+  int epid;+  int retval;+//  int bustime = 0;+  int maxpacket;+  unsigned long flags;+  struct crisv10_urb_priv *urb_priv;+  struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(hcd);+  DBFENTER;++  if(!(crisv10_hcd->running)) {+    /* The USB Controller is not running, probably because no device is +       attached. No idea to enqueue URBs then */+    tc_warn("Rejected enqueueing of URB:0x%x because no dev attached\n",+	    (unsigned int)urb);+    return -ENOENT;+  }++  maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));+  +  /* hinko ignore usb_pipeisoc */+#if 0+  /* Special case check for In Isoc transfers. Specification states that each+     In Isoc transfer consists of one packet and therefore it should fit into+     the transfer-buffer of an URB.+     We do the check here to be sure (an invalid scenario can be produced with+     parameters to the usbtest suite) */+  if(usb_pipeisoc(urb->pipe) && usb_pipein(urb->pipe) &&+     (urb->transfer_buffer_length < maxpacket)) {+    tc_err("Submit In Isoc URB with buffer length:%d to pipe with maxpacketlen: %d\n", urb->transfer_buffer_length, maxpacket);+    return -EMSGSIZE;+  }++  /* Check if there is enough bandwidth for periodic transfer  */+  if(usb_pipeint(urb->pipe) || usb_pipeisoc(urb->pipe)) {+    /* only check (and later claim) if not already claimed */+    if (urb->bandwidth == 0) {+      bustime = usb_check_bandwidth(urb->dev, urb);+      if (bustime < 0) {+	tc_err("Not enough periodic bandwidth\n");+	return -ENOSPC;+      }+    }+  }+#endif+  +  /* Check if there is a epid for URBs destination, if not this function+     set up one. */+  //epid = tc_setup_epid(ep, urb, mem_flags);+  epid = tc_setup_epid(urb, mem_flags);+  if (epid < 0) {+    tc_err("Failed setup epid:%d for URB:0x%x\n", epid, (unsigned int)urb);+    DBFEXIT;+    return -ENOMEM;+  }++  if(urb == activeUrbList[epid]) {+    tc_err("Resubmition of allready active URB:0x%x\n", (unsigned int)urb);+    return -ENXIO;+  }++  if(urb_list_entry(urb, epid)) {+    tc_err("Resubmition of allready queued URB:0x%x\n", (unsigned int)urb);+    return -ENXIO;+  }++  /* If we actively have flaged endpoint as disabled then refuse submition */+  if(epid_state[epid].disabled) {+    return -ENOENT;+  }++  /* Allocate and init HC-private data for URB */+  if(urb_priv_create(hcd, urb, epid, mem_flags) != 0) {+    DBFEXIT;+    return -ENOMEM;+  }+  urb_priv = urb->hcpriv;++  tc_dbg("Enqueue URB:0x%x[%d] epid:%d (%s) bufflen:%d\n",+	 (unsigned int)urb, urb_priv->urb_num, epid,+	 pipe_to_str(urb->pipe), urb->transfer_buffer_length);++  /* Create and link SBs required for this URB */+  retval = create_sb_for_urb(urb, mem_flags);+  if(retval != 0) {+    tc_err("Failed to create SBs for URB:0x%x[%d]\n", (unsigned int)urb,+	   urb_priv->urb_num);+    urb_priv_free(hcd, urb);+    DBFEXIT;+    return retval;+  }++  /* Init intr EP pool if this URB is a INTR transfer. This pool is later+     used when inserting EPs in the TxIntrEPList. We do the alloc here+     so we can't run out of memory later */+  if(usb_pipeint(urb->pipe)) {+    retval = init_intr_urb(urb, mem_flags);+    if(retval != 0) {+      tc_warn("Failed to init Intr URB\n");+      urb_priv_free(hcd, urb);+      DBFEXIT;+      return retval;+    }+  }++  /* Disable other access when inserting USB */++  /* BUG on sleeping inside int disabled if using local_irq_save/local_irq_restore+   * her - because urb_list_add() and tc_dma_process_queue() save irqs again !??!+   */+//  local_irq_save(flags);++  /* hinko ignore usb_pipeisoc */+#if 0+  /* Claim bandwidth, if needed */+  if(bustime) {+    usb_claim_bandwidth(urb->dev, urb, bustime, 0);+  }+  +  /* Add URB to EP queue */+  urb_list_add(urb, epid, mem_flags);++  if(usb_pipeisoc(urb->pipe)) {+    /* Special processing of Isoc URBs. */+    tc_dma_process_isoc_urb(urb);+  } else {+    /* Process EP queue for rest of the URB types (Bulk, Ctrl, Intr) */+    tc_dma_process_queue(epid);+  }+#endif+  /* Add URB to EP queue */+  urb_list_add(urb, epid, mem_flags);++  /*hinko link/unlink urb -> ep */+  spin_lock_irqsave(&crisv10_hcd->lock, flags);+  //spin_lock(&crisv10_hcd->lock);+  retval = usb_hcd_link_urb_to_ep(hcd, urb);+  if (retval) {+    spin_unlock_irqrestore(&crisv10_hcd->lock, flags);+    tc_warn("Failed to link urb to ep\n");+    urb_priv_free(hcd, urb);+    DBFEXIT;+    return retval;+  }+  spin_unlock_irqrestore(&crisv10_hcd->lock, flags);+  //spin_unlock(&crisv10_hcd->lock);+  +  /* Process EP queue for rest of the URB types (Bulk, Ctrl, Intr) */+  tc_dma_process_queue(epid);++//  local_irq_restore(flags);++  DBFEXIT;+  return 0;+}++/* remove an URB from the transfer controller queues (called from hcd_driver)*/+//static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)+static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)+{+  struct crisv10_urb_priv *urb_priv;+  unsigned long flags;+  int epid;++  DBFENTER;+  /* Disable interrupts here since a descriptor interrupt for the isoc epid+     will modify the sb list.  This could possibly be done more granular, but+     urb_dequeue should not be used frequently anyway.+  */+  local_irq_save(flags);++  urb_priv = urb->hcpriv;++  if (!urb_priv) {+    /* This happens if a device driver calls unlink on an urb that+       was never submitted (lazy driver) or if the urb was completed+       while dequeue was being called. */+    tc_warn("Dequeing of not enqueued URB:0x%x\n", (unsigned int)urb);+    local_irq_restore(flags);+    return 0;+  }+  epid = urb_priv->epid;++  tc_warn("Dequeing %s URB:0x%x[%d] (%s %s epid:%d) status:%d %s\n",+	  (urb == activeUrbList[epid]) ? "active" : "queued",+	  (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe),+	  str_type(urb->pipe), epid, urb->status,+	  (urb_priv->later_data) ? "later-sched" : "");++  /* For Bulk, Ctrl and Intr are only one URB active at a time. So any URB+     that isn't active can be dequeued by just removing it from the queue */+  if(usb_pipebulk(urb->pipe) || usb_pipecontrol(urb->pipe) ||+     usb_pipeint(urb->pipe)) {++    /* Check if URB haven't gone further than the queue */+    if(urb != activeUrbList[epid]) {+      ASSERT(urb_priv->later_data == NULL);+      tc_warn("Dequeing URB:0x%x[%d] (%s %s epid:%d) from queue"+	      " (not active)\n", (unsigned int)urb, urb_priv->urb_num,+	      str_dir(urb->pipe), str_type(urb->pipe), epid);+      +      /* Finish the URB with error status from USB core */+      tc_finish_urb(hcd, urb, urb->status);+      local_irq_restore(flags);+      return 0;+    }+  }++  /* Set URB status to Unlink for handling when interrupt comes. */+  urb_priv->urb_state = UNLINK;++  /* Differentiate dequeing of Bulk and Ctrl from Isoc and Intr */+  switch(usb_pipetype(urb->pipe)) {+  case PIPE_BULK:+    /* Check if EP still is enabled */+    if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+      /* The EP was enabled, disable it. */+      TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+    }+    /* Kicking dummy list out of the party. */+    TxBulkEPList[epid].next = virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);+    break;+  case PIPE_CONTROL:+    /* Check if EP still is enabled */+    if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+      /* The EP was enabled, disable it. */+      TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+    }+    break;+  case PIPE_ISOCHRONOUS:+    /* Disabling, busy-wait and unlinking of Isoc SBs will be done in+       finish_isoc_urb(). Because there might the case when URB is dequeued+       but there are other valid URBs waiting */++    /* Check if In Isoc EP still is enabled */+    if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+      /* The EP was enabled, disable it. */+      TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+    }+    break;+  case PIPE_INTERRUPT:+    /* Special care is taken for interrupt URBs. EPs are unlinked in+       tc_finish_urb */+    break;+  default:+    break;+  }++  /* Asynchronous unlink, finish the URB later from scheduled or other+     event (data finished, error) */+  tc_finish_urb_later(hcd, urb, urb->status);++  local_irq_restore(flags);+  DBFEXIT;+  return 0;+}+++static void tc_sync_finish_epid(struct usb_hcd *hcd, int epid) {+  volatile int timeout = 10000;+  struct urb* urb;+  struct crisv10_urb_priv* urb_priv;+  unsigned long flags;+  +  volatile struct USB_EP_Desc *first_ep;  /* First EP in the list. */+  volatile struct USB_EP_Desc *curr_ep;   /* Current EP, the iterator. */+  volatile struct USB_EP_Desc *next_ep;   /* The EP after current. */++  int type = epid_state[epid].type;++  /* Setting this flag will cause enqueue() to return -ENOENT for new+     submitions on this endpoint and finish_urb() wont process queue further */+  epid_state[epid].disabled = 1;++  switch(type) {+  case PIPE_BULK:+    /* Check if EP still is enabled */+    if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+      /* The EP was enabled, disable it. */+      TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+      tc_warn("sync_finish: Disabling EP for epid:%d\n", epid);++      /* Do busy-wait until DMA not using this EP descriptor anymore */+      while((*R_DMA_CH8_SUB0_EP ==+	     virt_to_phys(&TxBulkEPList[epid])) &&+	    (timeout-- > 0));+      if(timeout == 0) {+	warn("Timeout while waiting for DMA-TX-Bulk to leave EP for"+	     " epid:%d\n", epid);+      }+    }+    break;++  case PIPE_CONTROL:+    /* Check if EP still is enabled */+    if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+      /* The EP was enabled, disable it. */+      TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+      tc_warn("sync_finish: Disabling EP for epid:%d\n", epid);++      /* Do busy-wait until DMA not using this EP descriptor anymore */+      while((*R_DMA_CH8_SUB1_EP ==+	     virt_to_phys(&TxCtrlEPList[epid])) &&+	    (timeout-- > 0));+      if(timeout == 0) {+	warn("Timeout while waiting for DMA-TX-Ctrl to leave EP for"+	     " epid:%d\n", epid);+      }+    }+    break;++  case PIPE_INTERRUPT:+    local_irq_save(flags);+    /* Disable all Intr EPs belonging to epid */+    first_ep = &TxIntrEPList[0];+    curr_ep = first_ep;+    do {+      next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next);+      if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) {+	/* Disable EP */+	next_ep->command &= ~IO_MASK(USB_EP_command, enable);+      }+      curr_ep = phys_to_virt(curr_ep->next);+    } while (curr_ep != first_ep);++    local_irq_restore(flags);+    break;++  case PIPE_ISOCHRONOUS:+    /* Check if EP still is enabled */+    if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+      tc_warn("sync_finish: Disabling Isoc EP for epid:%d\n", epid);+      /* The EP was enabled, disable it. */+      TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+      +      while((*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid])) &&+	    (timeout-- > 0));+      if(timeout == 0) {+	warn("Timeout while waiting for DMA-TX-Isoc to leave EP for"+	     " epid:%d\n", epid);+      }+    }+    break;+  }++  local_irq_save(flags);++  /* Finish if there is active URB for this endpoint */+  if(activeUrbList[epid] != NULL) {+    urb = activeUrbList[epid];+    urb_priv = urb->hcpriv;+    ASSERT(urb_priv);+    tc_warn("Sync finish %s URB:0x%x[%d] (%s %s epid:%d) status:%d %s\n",+	    (urb == activeUrbList[epid]) ? "active" : "queued",+	    (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe),+	    str_type(urb->pipe), epid, urb->status,+	    (urb_priv->later_data) ? "later-sched" : "");++    tc_finish_urb(hcd, activeUrbList[epid], -ENOENT);+    ASSERT(activeUrbList[epid] == NULL);+  }++  /* Finish any queued URBs for this endpoint. There won't be any resubmitions+     because epid_disabled causes enqueue() to fail for this endpoint */+  while((urb = urb_list_first(epid)) != NULL) {+    urb_priv = urb->hcpriv;+    ASSERT(urb_priv);++    tc_warn("Sync finish %s URB:0x%x[%d] (%s %s epid:%d) status:%d %s\n",+	    (urb == activeUrbList[epid]) ? "active" : "queued",+	    (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe),+	    str_type(urb->pipe), epid, urb->status,+	    (urb_priv->later_data) ? "later-sched" : "");++    tc_finish_urb(hcd, urb, -ENOENT);+  }+  epid_state[epid].disabled = 0;+  local_irq_restore(flags);+}++/* free resources associated with an endpoint (called from hcd_driver) */+static void tc_endpoint_disable(struct usb_hcd *hcd, +				struct usb_host_endpoint *ep) {+  DBFENTER;+  /* Only free epid if it has been allocated. We get two endpoint_disable+     requests for ctrl endpoints so ignore the second one */+  if(ep->hcpriv != NULL) {+    struct crisv10_ep_priv *ep_priv = ep->hcpriv;+    int epid = ep_priv->epid;+    tc_warn("endpoint_disable ep:0x%x ep-priv:0x%x (%s) (epid:%d freed)\n",+	   (unsigned int)ep, (unsigned int)ep->hcpriv,+	   endpoint_to_str(&(ep->desc)), epid);++    tc_sync_finish_epid(hcd, epid);++    ASSERT(activeUrbList[epid] == NULL);+    ASSERT(list_empty(&urb_list[epid]));++    tc_free_epid(ep);+  } else {+    tc_dbg("endpoint_disable ep:0x%x ep-priv:0x%x (%s)\n", (unsigned int)ep,+	   (unsigned int)ep->hcpriv, endpoint_to_str(&(ep->desc)));+  }+  DBFEXIT;+}++//static void tc_finish_urb_later_proc(void *data) {+static void tc_finish_urb_later_proc(struct work_struct *work) {+  unsigned long flags;+  //struct urb_later_data* uld = (struct urb_later_data*)data;+  struct urb_later_data* uld = container_of(work, struct urb_later_data, ws.work);+  local_irq_save(flags);+  if(uld->urb == NULL) {+    late_dbg("Later finish of URB = NULL (allready finished)\n");+  } else {+    struct crisv10_urb_priv* urb_priv = uld->urb->hcpriv;+    ASSERT(urb_priv);+    if(urb_priv->urb_num == uld->urb_num) {+      late_dbg("Later finish of URB:0x%x[%d]\n", (unsigned int)(uld->urb),+	       urb_priv->urb_num);+      if(uld->status != uld->urb->status) {+	errno_dbg("Later-finish URB with status:%d, later-status:%d\n",+		  uld->urb->status, uld->status);+      }+      if(uld != urb_priv->later_data) {+	panic("Scheduled uld not same as URBs uld\n");+      }+      tc_finish_urb(uld->hcd, uld->urb, uld->status);+    } else {+      late_warn("Ignoring later finish of URB:0x%x[%d]"+		", urb_num doesn't match current URB:0x%x[%d]",+		(unsigned int)(uld->urb), uld->urb_num,+		(unsigned int)(uld->urb), urb_priv->urb_num);+    }+  }+  local_irq_restore(flags);+  kmem_cache_free(later_data_cache, uld);+}++static void tc_finish_urb_later(struct usb_hcd *hcd, struct urb *urb,+				int status) {+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  struct urb_later_data* uld;++  ASSERT(urb_priv);++  if(urb_priv->later_data != NULL) {+    /* Later-finish allready scheduled for this URB, just update status to+       return when finishing later */+    errno_dbg("Later-finish schedule change URB status:%d with new"+	      " status:%d\n", urb_priv->later_data->status, status);+    +    urb_priv->later_data->status = status;+    return;+  }++  uld = kmem_cache_alloc(later_data_cache, GFP_ATOMIC);+  ASSERT(uld);++  uld->hcd = hcd;+  uld->urb = urb;+  uld->urb_num = urb_priv->urb_num;+  uld->status = status;++  //INIT_WORK(&uld->ws, tc_finish_urb_later_proc, uld);+  INIT_DELAYED_WORK(&uld->ws, tc_finish_urb_later_proc);+  urb_priv->later_data = uld;++  /* Schedule the finishing of the URB to happen later */+  schedule_delayed_work(&uld->ws, LATER_TIMER_DELAY);+}++  /* hinko ignore usb_pipeisoc */+#if 0+static void tc_finish_isoc_urb(struct usb_hcd *hcd, struct urb *urb,+			       int status);+#endif++static void tc_finish_urb(struct usb_hcd *hcd, struct urb *urb, int status) {+  struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(hcd);+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  int epid;+  char toggle;+  int urb_num;+  unsigned long flags;++  DBFENTER;+  ASSERT(urb_priv != NULL);+  epid = urb_priv->epid;+  urb_num = urb_priv->urb_num;++  if(urb != activeUrbList[epid]) {+    if(urb_list_entry(urb, epid)) {+      /* Remove this URB from the list. Only happens when URB are finished+	 before having been processed (dequeing) */+      urb_list_del(urb, epid);+    } else {+      tc_warn("Finishing of URB:0x%x[%d] neither active or in queue for"+	      " epid:%d\n", (unsigned int)urb, urb_num, epid);+    }+  }++  /* Cancel any pending later-finish of this URB */+  if(urb_priv->later_data) {+    urb_priv->later_data->urb = NULL;+  }++  /* For an IN pipe, we always set the actual length, regardless of whether+     there was an error or not (which means the device driver can use the data+     if it wants to). */+  if(usb_pipein(urb->pipe)) {+    urb->actual_length = urb_priv->rx_offset;+  } else {+    /* Set actual_length for OUT urbs also; the USB mass storage driver seems+       to want that. */+    if (status == 0 && urb->status == -EINPROGRESS) {+      urb->actual_length = urb->transfer_buffer_length;+    } else {+      /*  We wouldn't know of any partial writes if there was an error. */+      urb->actual_length = 0;+    }+  }+++  /* URB status mangling */+  if(urb->status == -EINPROGRESS) {+    /* The USB core hasn't changed the status, let's set our finish status */+    urb->status = status;++    if ((status == 0) && (urb->transfer_flags & URB_SHORT_NOT_OK) &&+	usb_pipein(urb->pipe) &&+	(urb->actual_length != urb->transfer_buffer_length)) {+      /* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's+	 max length) is to be treated as an error. */+      errno_dbg("Finishing URB:0x%x[%d] with SHORT_NOT_OK flag and short"+		" data:%d\n", (unsigned int)urb, urb_num,+		urb->actual_length);+      urb->status = -EREMOTEIO;+    }++    if(urb_priv->urb_state == UNLINK) {+      /* URB has been requested to be unlinked asynchronously */+      urb->status = -ECONNRESET;+      errno_dbg("Fixing unlink status of URB:0x%x[%d] to:%d\n",+		(unsigned int)urb, urb_num, urb->status);+    }+  } else {+    /* The USB Core wants to signal some error via the URB, pass it through */+  }++  /* hinko ignore usb_pipeisoc */+#if 0+  /* use completely different finish function for Isoc URBs */+  if(usb_pipeisoc(urb->pipe)) {+    tc_finish_isoc_urb(hcd, urb, status);+    return;+  }+#endif++  /* Do special unlinking of EPs for Intr traffic */+  if(usb_pipeint(urb->pipe)) {+    tc_dma_unlink_intr_urb(urb);+  }++  /* hinko ignore usb_pipeisoc */+#if 0+  /* Release allocated bandwidth for periodic transfers */+  if(usb_pipeint(urb->pipe) || usb_pipeisoc(urb->pipe))+    usb_release_bandwidth(urb->dev, urb, 0);+#endif+  +  /* This URB is active on EP */+  if(urb == activeUrbList[epid]) {+    /* We need to fiddle with the toggle bits because the hardware doesn't do+       it for us. */+    toggle = etrax_epid_get_toggle(epid, usb_pipeout(urb->pipe));+    usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),+		  usb_pipeout(urb->pipe), toggle);++    /* Checks for Ctrl and Bulk EPs */+    switch(usb_pipetype(urb->pipe)) {+    case PIPE_BULK:+      /* Check so Bulk EP realy is disabled before finishing active URB  */+      ASSERT((TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) ==+	     IO_STATE(USB_EP_command, enable, no));+      /* Disable sub-pointer for EP to avoid next tx_interrupt() to+	 process Bulk EP. */+      TxBulkEPList[epid].sub = 0;+      /* No need to wait for the DMA before changing the next pointer.+	 The modulo NBR_OF_EPIDS isn't actually necessary, since we will never use+	 the last one (INVALID_EPID) for actual traffic. */+      TxBulkEPList[epid].next = +	virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);+      break;+    case PIPE_CONTROL:+      /* Check so Ctrl EP realy is disabled before finishing active URB  */+      ASSERT((TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) ==+	     IO_STATE(USB_EP_command, enable, no));+      /* Disable sub-pointer for EP to avoid next tx_interrupt() to+	 process Ctrl EP. */+      TxCtrlEPList[epid].sub = 0;+      break;+    }+  }++  /* Free HC-private URB data*/+  urb_priv_free(hcd, urb);++  if(urb->status) {+    errno_dbg("finish_urb (URB:0x%x[%d] %s %s) (data:%d) status:%d\n",+	      (unsigned int)urb, urb_num, str_dir(urb->pipe),+	      str_type(urb->pipe), urb->actual_length, urb->status);+  } else {+    tc_dbg("finish_urb (URB:0x%x[%d] %s %s) (data:%d) status:%d\n",+	   (unsigned int)urb, urb_num, str_dir(urb->pipe),+	   str_type(urb->pipe), urb->actual_length, urb->status);+  }++  /* If we just finished an active URB, clear active pointer. */+  if (urb == activeUrbList[epid]) {+    /* Make URB not active on EP anymore */+    activeUrbList[epid] = NULL;++    if(urb->status == 0) {+      /* URB finished sucessfully, process queue to see if there are any more+	 URBs waiting before we call completion function.*/+      if(crisv10_hcd->running) {+	/* Only process queue if USB controller is running */+	tc_dma_process_queue(epid);+      } else {+	tc_warn("No processing of queue for epid:%d, USB Controller not"+		" running\n", epid);+      }+    }+  }++  /*  Hand the URB from HCD to its USB device driver, using its completion+      functions */+//  usb_hcd_giveback_urb (hcd, urb);+	/**+	 * usb_hcd_unlink_urb_from_ep - remove an URB from its endpoint queue+	 * @hcd: host controller to which @urb was submitted+	 * @urb: URB being unlinked+	 *+	 * Host controller drivers should call this routine before calling+	 * usb_hcd_giveback_urb().  The HCD's private spinlock must be held and+	 * interrupts must be disabled.  The actions carried out here are required+	 * for URB completion.+	 */+  +  /*hinko link/unlink urb -> ep */+  //spin_lock(&crisv10_hcd->lock);+  spin_lock_irqsave(&crisv10_hcd->lock, flags);+  usb_hcd_unlink_urb_from_ep(hcd, urb);+  usb_hcd_giveback_urb(hcd, urb, status);+  //spin_unlock(&crisv10_hcd->lock);+  spin_unlock_irqrestore(&crisv10_hcd->lock, flags);++  /* Check the queue once more if the URB returned with error, because we+     didn't do it before the completion function because the specification+     states that the queue should not restart until all it's unlinked+     URBs have been fully retired, with the completion functions run */+  if(crisv10_hcd->running) {+    /* Only process queue if USB controller is running */+    tc_dma_process_queue(epid);+  } else {+    tc_warn("No processing of queue for epid:%d, USB Controller not running\n",+	    epid);+  }++  DBFEXIT;+}++  /* hinko ignore usb_pipeisoc */+#if 0+static void tc_finish_isoc_urb(struct usb_hcd *hcd, struct urb *urb,+			       int status) {+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  int epid, i;+  volatile int timeout = 10000;++  ASSERT(urb_priv);+  epid = urb_priv->epid;++  ASSERT(usb_pipeisoc(urb->pipe));++  /* Set that all isoc packets have status and length set before+     completing the urb. */+  for (i = urb_priv->isoc_packet_counter; i < urb->number_of_packets; i++){+    urb->iso_frame_desc[i].actual_length = 0;+    urb->iso_frame_desc[i].status = -EPROTO;+  }++  /* Check if the URB is currently active (done or error) */+  if(urb == activeUrbList[epid]) {+    /* Check if there are another In Isoc URB queued for this epid */+    if (!list_empty(&urb_list[epid])&& !epid_state[epid].disabled) {+      /* Move it from queue to active and mark it started so Isoc transfers+	 won't be interrupted.+	 All Isoc URBs data transfers are already added to DMA lists so we+	 don't have to insert anything in DMA lists here. */+      activeUrbList[epid] = urb_list_first(epid);+      ((struct crisv10_urb_priv *)(activeUrbList[epid]->hcpriv))->urb_state =+	STARTED;+      urb_list_del(activeUrbList[epid], epid);++      if(urb->status) {+	errno_dbg("finish_isoc_urb (URB:0x%x[%d] %s %s) (%d of %d packets)"+		  " status:%d, new waiting URB:0x%x[%d]\n",+		  (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe),+		  str_type(urb->pipe), urb_priv->isoc_packet_counter,+		  urb->number_of_packets, urb->status,+		  (unsigned int)activeUrbList[epid],+		  ((struct crisv10_urb_priv *)(activeUrbList[epid]->hcpriv))->urb_num);+      }++    } else { /* No other URB queued for this epid */+      if(urb->status) {+	errno_dbg("finish_isoc_urb (URB:0x%x[%d] %s %s) (%d of %d packets)"+		  " status:%d, no new URB waiting\n",+		  (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe),+		  str_type(urb->pipe), urb_priv->isoc_packet_counter,+		  urb->number_of_packets, urb->status);+      }++      /* Check if EP is still enabled, then shut it down. */+      if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+	isoc_dbg("Isoc EP enabled for epid:%d, disabling it\n", epid);++	/* Should only occur for In Isoc EPs where SB isn't consumed. */+	ASSERT(usb_pipein(urb->pipe));++	/* Disable it and wait for it to stop */+	TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);+	+	/* Ah, the luxury of busy-wait. */+	while((*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid])) &&+	      (timeout-- > 0));+	if(timeout == 0) {+	  warn("Timeout while waiting for DMA-TX-Isoc to leave EP for epid:%d\n", epid);+	}+      }++      /* Unlink SB to say that epid is finished. */+      TxIsocEPList[epid].sub = 0;+      TxIsocEPList[epid].hw_len = 0;++      /* No URB active for EP anymore */+      activeUrbList[epid] = NULL;+    }+  } else { /* Finishing of not active URB (queued up with SBs thought) */+    isoc_warn("finish_isoc_urb (URB:0x%x %s) (%d of %d packets) status:%d,"+	      " SB queued but not active\n",+	      (unsigned int)urb, str_dir(urb->pipe),+	      urb_priv->isoc_packet_counter, urb->number_of_packets,+	      urb->status);+    if(usb_pipeout(urb->pipe)) {+      /* Finishing of not yet active Out Isoc URB needs unlinking of SBs. */+      struct USB_SB_Desc *iter_sb, *prev_sb, *next_sb;++      iter_sb = TxIsocEPList[epid].sub ?+	phys_to_virt(TxIsocEPList[epid].sub) : 0;+      prev_sb = 0;++      /* SB that is linked before this URBs first SB */+      while (iter_sb && (iter_sb != urb_priv->first_sb)) {+	prev_sb = iter_sb;+	iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0;+      }++      if (iter_sb == 0) {+	/* Unlink of the URB currently being transmitted. */+	prev_sb = 0;+	iter_sb = TxIsocEPList[epid].sub ? phys_to_virt(TxIsocEPList[epid].sub) : 0;+      }++      while (iter_sb && (iter_sb != urb_priv->last_sb)) {+	iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0;+      }++      if (iter_sb) {+	next_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0;+      } else {+	/* This should only happen if the DMA has completed+	   processing the SB list for this EP while interrupts+	   are disabled. */+	isoc_dbg("Isoc urb not found, already sent?\n");+	next_sb = 0;+      }+      if (prev_sb) {+	prev_sb->next = next_sb ? virt_to_phys(next_sb) : 0;+      } else {+	TxIsocEPList[epid].sub = next_sb ? virt_to_phys(next_sb) : 0;+      }+    }+  }++  /* Free HC-private URB data*/+  urb_priv_free(hcd, urb);++  usb_release_bandwidth(urb->dev, urb, 0);++  /*  Hand the URB from HCD to its USB device driver, using its completion+      functions */+  usb_hcd_giveback_urb (hcd, urb);+}+#endif++static __u32 urb_num = 0;++/* allocate and initialize URB private data */+static int urb_priv_create(struct usb_hcd *hcd, struct urb *urb, int epid,+			   int mem_flags) {+  struct crisv10_urb_priv *urb_priv;+  +  urb_priv = kmalloc(sizeof *urb_priv, mem_flags);+  if (!urb_priv)+    return -ENOMEM;+  memset(urb_priv, 0, sizeof *urb_priv);++  urb_priv->epid = epid;+  urb_priv->urb_state = NOT_STARTED;++  urb->hcpriv = urb_priv;+  /* Assign URB a sequence number, and increment counter */+  urb_priv->urb_num = urb_num;+  urb_num++;+  return 0;+}++/* free URB private data */+static void urb_priv_free(struct usb_hcd *hcd, struct urb *urb) {+  int i;+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  ASSERT(urb_priv != 0);++  /* Check it has any SBs linked that needs to be freed*/+  if(urb_priv->first_sb != NULL) {+    struct USB_SB_Desc *next_sb, *first_sb, *last_sb;+    int i = 0;+    first_sb = urb_priv->first_sb;+    last_sb = urb_priv->last_sb;+    ASSERT(last_sb);+    while(first_sb != last_sb) {+      next_sb = (struct USB_SB_Desc *)phys_to_virt(first_sb->next);+      kmem_cache_free(usb_desc_cache, first_sb);+      first_sb = next_sb;+      i++;+    }+    kmem_cache_free(usb_desc_cache, last_sb);+    i++;+  }++  /* Check if it has any EPs in its Intr pool that also needs to be freed */+  if(urb_priv->intr_ep_pool_length > 0) {+    for(i = 0; i < urb_priv->intr_ep_pool_length; i++) {+      kfree(urb_priv->intr_ep_pool[i]);+    }+    /*+    tc_dbg("Freed %d EPs from URB:0x%x EP pool\n",+	     urb_priv->intr_ep_pool_length, (unsigned int)urb);+    */+  }++  kfree(urb_priv);+  urb->hcpriv = NULL;+}++static int ep_priv_create(struct usb_host_endpoint *ep, int mem_flags) {+  struct crisv10_ep_priv *ep_priv;+  +  ep_priv = kmalloc(sizeof *ep_priv, mem_flags);+  if (!ep_priv)+    return -ENOMEM;+  memset(ep_priv, 0, sizeof *ep_priv);++  ep->hcpriv = ep_priv;+  return 0;+}++static void ep_priv_free(struct usb_host_endpoint *ep) {+  struct crisv10_ep_priv *ep_priv = ep->hcpriv;+  ASSERT(ep_priv);+  kfree(ep_priv);+  ep->hcpriv = NULL;+}++/* EPID handling functions, managing EP-list in Etrax through wrappers */+/* ------------------------------------------------------------------- */++/* Sets up a new EPID for an endpoint or returns existing if found */+//static int tc_setup_epid(struct usb_host_endpoint *ep, struct urb *urb,+//			 int mem_flags) {+static int tc_setup_epid(struct urb *urb, int mem_flags)+{+  int epid;+  char devnum, endpoint, out_traffic, slow;+  int maxlen;+  __u32 epid_data;+  struct usb_host_endpoint *ep = urb->ep;+  struct crisv10_ep_priv *ep_priv = ep->hcpriv;+  +  DBFENTER;+  +  /* Check if a valid epid already is setup for this endpoint */+  if(ep_priv != NULL) {+    return ep_priv->epid;+  }++  /* We must find and initiate a new epid for this urb. */+  epid = tc_allocate_epid();+  +  if (epid == -1) {+    /* Failed to allocate a new epid. */+    DBFEXIT;+    return epid;+  }+  +  /* We now have a new epid to use. Claim it. */+  epid_state[epid].inuse = 1;+  +  /* Init private data for new endpoint */+  if(ep_priv_create(ep, mem_flags) != 0) {+    return -ENOMEM;+  }+  ep_priv = ep->hcpriv;+  ep_priv->epid = epid;++  devnum = usb_pipedevice(urb->pipe);+  endpoint = usb_pipeendpoint(urb->pipe);+  slow = (urb->dev->speed == USB_SPEED_LOW);+  maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));++  if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {+    /* We want both IN and OUT control traffic to be put on the same+       EP/SB list. */+    out_traffic = 1;+  } else {+    out_traffic = usb_pipeout(urb->pipe);+  }+    +  if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {+    epid_data = IO_STATE(R_USB_EPT_DATA_ISO, valid, yes) |+      /* FIXME: Change any to the actual port? */+      IO_STATE(R_USB_EPT_DATA_ISO, port, any) |+      IO_FIELD(R_USB_EPT_DATA_ISO, max_len, maxlen) |+      IO_FIELD(R_USB_EPT_DATA_ISO, ep, endpoint) |+      IO_FIELD(R_USB_EPT_DATA_ISO, dev, devnum);+    etrax_epid_iso_set(epid, epid_data);+  } else {+    epid_data = IO_STATE(R_USB_EPT_DATA, valid, yes) |+      IO_FIELD(R_USB_EPT_DATA, low_speed, slow) |+      /* FIXME: Change any to the actual port? */+      IO_STATE(R_USB_EPT_DATA, port, any) |+      IO_FIELD(R_USB_EPT_DATA, max_len, maxlen) |+      IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |+      IO_FIELD(R_USB_EPT_DATA, dev, devnum);+    etrax_epid_set(epid, epid_data);+  }+  +  epid_state[epid].out_traffic = out_traffic;+  epid_state[epid].type = usb_pipetype(urb->pipe);++  tc_warn("Setting up ep:0x%x epid:%d (addr:%d endp:%d max_len:%d %s %s %s)\n",+	  (unsigned int)ep, epid, devnum, endpoint, maxlen,+	  str_type(urb->pipe), out_traffic ? "out" : "in",+	  slow ? "low" : "full");++  /* Enable Isoc eof interrupt if we set up the first Isoc epid */+  if(usb_pipeisoc(urb->pipe)) {+    isoc_epid_counter++;+    if(isoc_epid_counter == 1) {+      isoc_warn("Enabled Isoc eof interrupt\n");+      *R_USB_IRQ_MASK_SET |= IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set);+    }+  }++  DBFEXIT;+  return epid;+}++static void tc_free_epid(struct usb_host_endpoint *ep) {+  unsigned long flags;+  struct crisv10_ep_priv *ep_priv = ep->hcpriv;+  int epid;+  volatile int timeout = 10000;++  DBFENTER;++  if (ep_priv == NULL) {+    tc_warn("Trying to free unused epid on ep:0x%x\n", (unsigned int)ep);+    DBFEXIT;+    return;+  }++  epid = ep_priv->epid;++  /* Disable Isoc eof interrupt if we free the last Isoc epid */+  if(epid_isoc(epid)) {+    ASSERT(isoc_epid_counter > 0);+    isoc_epid_counter--;+    if(isoc_epid_counter == 0) {+      *R_USB_IRQ_MASK_SET &= ~IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set);+      isoc_warn("Disabled Isoc eof interrupt\n");+    }+  }++  /* Take lock manualy instead of in epid_x_x wrappers,+     because we need to be polling here */+  spin_lock_irqsave(&etrax_epid_lock, flags);+  +  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);+  nop();+  while((*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) &&+	(timeout-- > 0));+  if(timeout == 0) {+    warn("Timeout while waiting for epid:%d to drop hold\n", epid);+  }+  /* This will, among other things, set the valid field to 0. */+  *R_USB_EPT_DATA = 0;+  spin_unlock_irqrestore(&etrax_epid_lock, flags);+  +  /* Free resource in software state info list */+  epid_state[epid].inuse = 0;++  /* Free private endpoint data */+  ep_priv_free(ep);+  +  DBFEXIT;+}++static int tc_allocate_epid(void) {+  int i;+  DBFENTER;+  for (i = 0; i < NBR_OF_EPIDS; i++) {+    if (!epid_inuse(i)) {+      DBFEXIT;+      return i;+    }+  }+  +  tc_warn("Found no free epids\n");+  DBFEXIT;+  return -1;+}+++/* Wrappers around the list functions (include/linux/list.h). */+/* ---------------------------------------------------------- */+static inline int __urb_list_empty(int epid) {+  int retval;+  retval = list_empty(&urb_list[epid]);+  return retval;+}++/* Returns first urb for this epid, or NULL if list is empty. */+static inline struct urb *urb_list_first(int epid) {+  unsigned long flags;+  struct urb *first_urb = 0;+  spin_lock_irqsave(&urb_list_lock, flags);+  if (!__urb_list_empty(epid)) {+    /* Get the first urb (i.e. head->next). */+    urb_entry_t *urb_entry = list_entry((&urb_list[epid])->next, urb_entry_t, list);+    first_urb = urb_entry->urb;+  }+  spin_unlock_irqrestore(&urb_list_lock, flags);+  return first_urb;+}++/* Adds an urb_entry last in the list for this epid. */+static inline void urb_list_add(struct urb *urb, int epid, int mem_flags) {+  unsigned long flags;+  urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), mem_flags);+  ASSERT(urb_entry);+  +  urb_entry->urb = urb;+  spin_lock_irqsave(&urb_list_lock, flags);+  list_add_tail(&urb_entry->list, &urb_list[epid]);+  spin_unlock_irqrestore(&urb_list_lock, flags);+}++/* Search through the list for an element that contains this urb. (The list+   is expected to be short and the one we are about to delete will often be+   the first in the list.)+   Should be protected by spin_locks in calling function */+static inline urb_entry_t *__urb_list_entry(struct urb *urb, int epid) {+  struct list_head *entry;+  struct list_head *tmp;+  urb_entry_t *urb_entry;+  +  list_for_each_safe(entry, tmp, &urb_list[epid]) {+    urb_entry = list_entry(entry, urb_entry_t, list);+    ASSERT(urb_entry);+    ASSERT(urb_entry->urb);+    +    if (urb_entry->urb == urb) {+      return urb_entry;+    }+  }+  return 0;+}++/* Same function as above but for global use. Protects list by spinlock */+static inline urb_entry_t *urb_list_entry(struct urb *urb, int epid) {+  unsigned long flags;+  urb_entry_t *urb_entry;+  spin_lock_irqsave(&urb_list_lock, flags);+  urb_entry = __urb_list_entry(urb, epid);+  spin_unlock_irqrestore(&urb_list_lock, flags);+  return (urb_entry);+}++/* Delete an urb from the list. */+static inline void urb_list_del(struct urb *urb, int epid) {+  unsigned long flags;+  urb_entry_t *urb_entry;++  /* Delete entry and free. */+  spin_lock_irqsave(&urb_list_lock, flags);+  urb_entry = __urb_list_entry(urb, epid);+  ASSERT(urb_entry);++  list_del(&urb_entry->list);+  spin_unlock_irqrestore(&urb_list_lock, flags);+  kfree(urb_entry);+}++/* Move an urb to the end of the list. */+static inline void urb_list_move_last(struct urb *urb, int epid) {+  unsigned long flags;+  urb_entry_t *urb_entry;+  +  spin_lock_irqsave(&urb_list_lock, flags);+  urb_entry = __urb_list_entry(urb, epid);+  ASSERT(urb_entry);++  list_del(&urb_entry->list);+  list_add_tail(&urb_entry->list, &urb_list[epid]);+  spin_unlock_irqrestore(&urb_list_lock, flags);+}++/* Get the next urb in the list. */+static inline struct urb *urb_list_next(struct urb *urb, int epid) {+  unsigned long flags;+  urb_entry_t *urb_entry;++  spin_lock_irqsave(&urb_list_lock, flags);+  urb_entry = __urb_list_entry(urb, epid);+  ASSERT(urb_entry);++  if (urb_entry->list.next != &urb_list[epid]) {+    struct list_head *elem = urb_entry->list.next;+    urb_entry = list_entry(elem, urb_entry_t, list);+    spin_unlock_irqrestore(&urb_list_lock, flags);+    return urb_entry->urb;+  } else {+    spin_unlock_irqrestore(&urb_list_lock, flags);+    return NULL;+  }+}++struct USB_EP_Desc* create_ep(int epid, struct USB_SB_Desc* sb_desc,+			      int mem_flags) {+  struct USB_EP_Desc *ep_desc;+  ep_desc = (struct USB_EP_Desc *) kmem_cache_alloc(usb_desc_cache, mem_flags);+  if(ep_desc == NULL)+    return NULL;+  memset(ep_desc, 0, sizeof(struct USB_EP_Desc));++  ep_desc->hw_len = 0;+  ep_desc->command = (IO_FIELD(USB_EP_command, epid, epid) |+		      IO_STATE(USB_EP_command, enable, yes));+  if(sb_desc == NULL) {+    ep_desc->sub = 0;+  } else {+    ep_desc->sub = virt_to_phys(sb_desc);+  }+  return ep_desc;+}++#define TT_ZOUT  0+#define TT_IN    1+#define TT_OUT   2+#define TT_SETUP 3++#define CMD_EOL  IO_STATE(USB_SB_command, eol, yes)+#define CMD_INTR IO_STATE(USB_SB_command, intr, yes)+#define CMD_FULL IO_STATE(USB_SB_command, full, yes)++/* Allocation and setup of a generic SB. Used to create SETUP, OUT and ZOUT+   SBs. Also used by create_sb_in() to avoid same allocation procedure at two+   places */+struct USB_SB_Desc* create_sb(struct USB_SB_Desc* sb_prev, int tt, void* data,+			      int datalen, int mem_flags) {+  struct USB_SB_Desc *sb_desc;+  sb_desc = (struct USB_SB_Desc*)kmem_cache_alloc(usb_desc_cache, mem_flags);+  if(sb_desc == NULL)+    return NULL;+  memset(sb_desc, 0, sizeof(struct USB_SB_Desc));++  sb_desc->command = IO_FIELD(USB_SB_command, tt, tt) |+                     IO_STATE(USB_SB_command, eot, yes);++  sb_desc->sw_len = datalen;+  if(data != NULL) {+    sb_desc->buf = virt_to_phys(data);+  } else {+    sb_desc->buf = 0;+  }+  if(sb_prev != NULL) {+    sb_prev->next = virt_to_phys(sb_desc);+  }+  return sb_desc;+}++/* Creates a copy of an existing SB by allocation space for it and copy+   settings */+struct USB_SB_Desc* create_sb_copy(struct USB_SB_Desc* sb_orig, int mem_flags) {+  struct USB_SB_Desc *sb_desc;+  sb_desc = (struct USB_SB_Desc*)kmem_cache_alloc(usb_desc_cache, mem_flags);+  if(sb_desc == NULL)+    return NULL;++  memcpy(sb_desc, sb_orig, sizeof(struct USB_SB_Desc));+  return sb_desc;+}++/* A specific create_sb function for creation of in SBs. This is due to+   that datalen in In SBs shows how many packets we are expecting. It also+   sets up the rem field to show if how many bytes we expect in last packet+   if it's not a full one */+struct USB_SB_Desc* create_sb_in(struct USB_SB_Desc* sb_prev, int datalen,+				 int maxlen, int mem_flags) {+  struct USB_SB_Desc *sb_desc;+  sb_desc = create_sb(sb_prev, TT_IN, NULL,+		      datalen ? (datalen - 1) / maxlen + 1 : 0, mem_flags);+  if(sb_desc == NULL)+    return NULL;+  sb_desc->command |= IO_FIELD(USB_SB_command, rem, datalen % maxlen);+  return sb_desc;+}++void set_sb_cmds(struct USB_SB_Desc *sb_desc, __u16 flags) {+  sb_desc->command |= flags;+}++int create_sb_for_urb(struct urb *urb, int mem_flags) {+  int is_out = !usb_pipein(urb->pipe);+  int type = usb_pipetype(urb->pipe);+  int maxlen = usb_maxpacket(urb->dev, urb->pipe, is_out);+  int buf_len = urb->transfer_buffer_length;+  void *buf = buf_len > 0 ? urb->transfer_buffer : NULL;+  struct USB_SB_Desc *sb_desc = NULL;++  struct crisv10_urb_priv *urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+  ASSERT(urb_priv != NULL);++  switch(type) {+  case PIPE_CONTROL:+    /* Setup stage */+    sb_desc = create_sb(NULL, TT_SETUP, urb->setup_packet, 8, mem_flags);+    if(sb_desc == NULL)+      return -ENOMEM;+    set_sb_cmds(sb_desc, CMD_FULL);++    /* Attach first SB to URB */+    urb_priv->first_sb = sb_desc;    ++    if (is_out) { /* Out Control URB */+      /* If this Control OUT transfer has an optional data stage we add+	 an OUT token before the mandatory IN (status) token */+      if ((buf_len > 0) && buf) {+	sb_desc = create_sb(sb_desc, TT_OUT, buf, buf_len, mem_flags);+	if(sb_desc == NULL)+	  return -ENOMEM;+	set_sb_cmds(sb_desc, CMD_FULL);+      }++      /* Status stage */+      /* The data length has to be exactly 1. This is due to a requirement+         of the USB specification that a host must be prepared to receive+         data in the status phase */+      sb_desc = create_sb(sb_desc, TT_IN, NULL, 1, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;+    } else { /* In control URB */+      /* Data stage */+      sb_desc = create_sb_in(sb_desc, buf_len, maxlen, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;++      /* Status stage */+      /* Read comment at zout_buffer declaration for an explanation to this. */+      sb_desc = create_sb(sb_desc, TT_ZOUT, &zout_buffer[0], 1, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;+      /* Set descriptor interrupt flag for in URBs so we can finish URB after+         zout-packet has been sent */+      set_sb_cmds(sb_desc, CMD_INTR | CMD_FULL);+    }+    /* Set end-of-list flag in last SB */+    set_sb_cmds(sb_desc, CMD_EOL);+    /* Attach last SB to URB */+    urb_priv->last_sb = sb_desc;+    break;++  case PIPE_BULK:+    if (is_out) { /* Out Bulk URB */+      sb_desc = create_sb(NULL, TT_OUT, buf, buf_len, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;+      /* The full field is set to yes, even if we don't actually check that+	 this is a full-length transfer (i.e., that transfer_buffer_length %+	 maxlen = 0).+	 Setting full prevents the USB controller from sending an empty packet+	 in that case.  However, if URB_ZERO_PACKET was set we want that. */+      if (!(urb->transfer_flags & URB_ZERO_PACKET)) {+	set_sb_cmds(sb_desc, CMD_FULL);+      }+    } else { /* In Bulk URB */+      sb_desc = create_sb_in(NULL, buf_len, maxlen, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;+    }+    /* Set end-of-list flag for last SB */+    set_sb_cmds(sb_desc, CMD_EOL);++    /* Attach SB to URB */+    urb_priv->first_sb = sb_desc;+    urb_priv->last_sb = sb_desc;+    break;++  case PIPE_INTERRUPT:+    if(is_out) { /* Out Intr URB */+      sb_desc = create_sb(NULL, TT_OUT, buf, buf_len, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;++      /* The full field is set to yes, even if we don't actually check that+	 this is a full-length transfer (i.e., that transfer_buffer_length %+	 maxlen = 0).+	 Setting full prevents the USB controller from sending an empty packet+	 in that case.  However, if URB_ZERO_PACKET was set we want that. */+      if (!(urb->transfer_flags & URB_ZERO_PACKET)) {+	set_sb_cmds(sb_desc, CMD_FULL);+      }+      /* Only generate TX interrupt if it's a Out URB*/+      set_sb_cmds(sb_desc, CMD_INTR);++    } else { /* In Intr URB */+      sb_desc = create_sb_in(NULL, buf_len, maxlen, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;+    }+    /* Set end-of-list flag for last SB */+    set_sb_cmds(sb_desc, CMD_EOL);++    /* Attach SB to URB */+    urb_priv->first_sb = sb_desc;+    urb_priv->last_sb = sb_desc;++    break;+  case PIPE_ISOCHRONOUS:+    if(is_out) { /* Out Isoc URB */+      int i;+      if(urb->number_of_packets == 0) {+	tc_err("Can't create SBs for Isoc URB with zero packets\n");+	return -EPIPE;+      }+      /* Create one SB descriptor for each packet and link them together. */+      for(i = 0; i < urb->number_of_packets; i++) {+	if (urb->iso_frame_desc[i].length > 0) {++	  sb_desc = create_sb(sb_desc, TT_OUT, urb->transfer_buffer ++			      urb->iso_frame_desc[i].offset,+			      urb->iso_frame_desc[i].length, mem_flags);+	  if(sb_desc == NULL)+	    return -ENOMEM;++	  /* Check if it's a full length packet */+	  if (urb->iso_frame_desc[i].length ==+	      usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) {+	    set_sb_cmds(sb_desc, CMD_FULL);+	  }+	  +	} else { /* zero length packet */+	  sb_desc = create_sb(sb_desc, TT_ZOUT, &zout_buffer[0], 1, mem_flags);+	  if(sb_desc == NULL)+	    return -ENOMEM;+	  set_sb_cmds(sb_desc, CMD_FULL);+	}+	/* Attach first SB descriptor to URB */+	if (i == 0) {+	  urb_priv->first_sb = sb_desc;+	}+      }+      /* Set interrupt and end-of-list flags in last SB */+      set_sb_cmds(sb_desc, CMD_INTR | CMD_EOL);+      /* Attach last SB descriptor to URB */+      urb_priv->last_sb = sb_desc;+      tc_dbg("Created %d out SBs for Isoc URB:0x%x\n",+	       urb->number_of_packets, (unsigned int)urb);+    } else { /* In Isoc URB */+      /* Actual number of packets is not relevant for periodic in traffic as+	 long as it is more than zero.  Set to 1 always. */+      sb_desc = create_sb(sb_desc, TT_IN, NULL, 1, mem_flags);+      if(sb_desc == NULL)+	return -ENOMEM;+      /* Set end-of-list flags for SB */+      set_sb_cmds(sb_desc, CMD_EOL);++      /* Attach SB to URB */+      urb_priv->first_sb = sb_desc;+      urb_priv->last_sb = sb_desc;+    }+    break;+  default:+    tc_err("Unknown pipe-type\n");+    return -EPIPE;+    break;+  }+  return 0;+}++int init_intr_urb(struct urb *urb, int mem_flags) {+  struct crisv10_urb_priv *urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+  struct USB_EP_Desc* ep_desc;+  int interval;+  int i;+  int ep_count;++  ASSERT(urb_priv != NULL);+  ASSERT(usb_pipeint(urb->pipe));+  /* We can't support interval longer than amount of eof descriptors in+     TxIntrEPList */+  if(urb->interval > MAX_INTR_INTERVAL) {+    tc_err("Interrupt interval %dms too big (max: %dms)\n", urb->interval,+	   MAX_INTR_INTERVAL);+    return -EINVAL;+  }++  /* We assume that the SB descriptors already have been setup */+  ASSERT(urb_priv->first_sb != NULL);++  /* Round of the interval to 2^n, it is obvious that this code favours+     smaller numbers, but that is actually a good thing */+  /* FIXME: The "rounding error" for larger intervals will be quite+     large. For in traffic this shouldn't be a problem since it will only+     mean that we "poll" more often. */+  interval = urb->interval;+  for (i = 0; interval; i++) {+    interval = interval >> 1;+  }+  urb_priv->interval = 1 << (i - 1);++  /* We can only have max interval for Out Interrupt due to that we can only+     handle one linked in EP for a certain epid in the Intr descr array at the+     time. The USB Controller in the Etrax 100LX continues to process Intr EPs+     so we have no way of knowing which one that caused the actual transfer if+     we have several linked in. */+  if(usb_pipeout(urb->pipe)) {+    urb_priv->interval = MAX_INTR_INTERVAL;+  }++  /* Calculate amount of EPs needed */+  ep_count = MAX_INTR_INTERVAL / urb_priv->interval;++  for(i = 0; i < ep_count; i++) {+    ep_desc = create_ep(urb_priv->epid, urb_priv->first_sb, mem_flags);+    if(ep_desc == NULL) {+      /* Free any descriptors that we may have allocated before failure */+      while(i > 0) {+	i--;+	kfree(urb_priv->intr_ep_pool[i]);+      }+      return -ENOMEM;+    }+    urb_priv->intr_ep_pool[i] = ep_desc;+  }+  urb_priv->intr_ep_pool_length = ep_count;+  return 0;+}++/* DMA RX/TX functions */+/* ----------------------- */++static void tc_dma_init_rx_list(void) {+  int i;++  /* Setup descriptor list except last one */+  for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {+    RxDescList[i].sw_len = RX_DESC_BUF_SIZE;+    RxDescList[i].command = 0;+    RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);+    RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));+    RxDescList[i].hw_len = 0;+    RxDescList[i].status = 0;+    +    /* DMA IN cache bug. (struct etrax_dma_descr has the same layout as+       USB_IN_Desc for the relevant fields.) */+    prepare_rx_descriptor((struct etrax_dma_descr*)&RxDescList[i]);+    +  }+  /* Special handling of last descriptor */+  RxDescList[i].sw_len = RX_DESC_BUF_SIZE;+  RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes);+  RxDescList[i].next = virt_to_phys(&RxDescList[0]);+  RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));+  RxDescList[i].hw_len = 0;+  RxDescList[i].status = 0;+  +  /* Setup list pointers that show progress in list */+  myNextRxDesc = &RxDescList[0];+  myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];+  +  flush_etrax_cache();+  /* Point DMA to first descriptor in list and start it */+  *R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc);+  *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start);+}+++static void tc_dma_init_tx_bulk_list(void) {+  int i;+  volatile struct USB_EP_Desc *epDescr;++  for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {+    epDescr = &(TxBulkEPList[i]);+    CHECK_ALIGN(epDescr);+    epDescr->hw_len = 0;+    epDescr->command = IO_FIELD(USB_EP_command, epid, i);+    epDescr->sub = 0;+    epDescr->next = virt_to_phys(&TxBulkEPList[i + 1]);++    /* Initiate two EPs, disabled and with the eol flag set. No need for any+       preserved epid. */+    +    /* The first one has the intr flag set so we get an interrupt when the DMA+       channel is about to become disabled. */+    CHECK_ALIGN(&TxBulkDummyEPList[i][0]);+    TxBulkDummyEPList[i][0].hw_len = 0;+    TxBulkDummyEPList[i][0].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) |+				       IO_STATE(USB_EP_command, eol, yes) |+				       IO_STATE(USB_EP_command, intr, yes));+    TxBulkDummyEPList[i][0].sub = 0;+    TxBulkDummyEPList[i][0].next = virt_to_phys(&TxBulkDummyEPList[i][1]);+    +    /* The second one. */+    CHECK_ALIGN(&TxBulkDummyEPList[i][1]);+    TxBulkDummyEPList[i][1].hw_len = 0;+    TxBulkDummyEPList[i][1].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) |+				       IO_STATE(USB_EP_command, eol, yes));+    TxBulkDummyEPList[i][1].sub = 0;+    /* The last dummy's next pointer is the same as the current EP's next pointer. */+    TxBulkDummyEPList[i][1].next = virt_to_phys(&TxBulkEPList[i + 1]);+  }++  /* Special handling of last descr in list, make list circular */+  epDescr = &TxBulkEPList[i];+  CHECK_ALIGN(epDescr);+  epDescr->hw_len = 0;+  epDescr->command = IO_STATE(USB_EP_command, eol, yes) |+    IO_FIELD(USB_EP_command, epid, i);+  epDescr->sub = 0;+  epDescr->next = virt_to_phys(&TxBulkEPList[0]);+  +  /* Init DMA sub-channel pointers to last item in each list */+  *R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[i]);+  /* No point in starting the bulk channel yet.+   *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */+}++static void tc_dma_init_tx_ctrl_list(void) {+  int i;+  volatile struct USB_EP_Desc *epDescr;++  for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {+    epDescr = &(TxCtrlEPList[i]);+    CHECK_ALIGN(epDescr);+    epDescr->hw_len = 0;+    epDescr->command = IO_FIELD(USB_EP_command, epid, i);+    epDescr->sub = 0;+    epDescr->next = virt_to_phys(&TxCtrlEPList[i + 1]);+  }+  /* Special handling of last descr in list, make list circular */+  epDescr = &TxCtrlEPList[i];+  CHECK_ALIGN(epDescr);+  epDescr->hw_len = 0;+  epDescr->command = IO_STATE(USB_EP_command, eol, yes) |+    IO_FIELD(USB_EP_command, epid, i);+  epDescr->sub = 0;+  epDescr->next = virt_to_phys(&TxCtrlEPList[0]);+  +  /* Init DMA sub-channel pointers to last item in each list */+  *R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[i]);+  /* No point in starting the ctrl channel yet.+   *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */+}+++static void tc_dma_init_tx_intr_list(void) {+  int i;++  TxIntrSB_zout.sw_len = 1;+  TxIntrSB_zout.next = 0;+  TxIntrSB_zout.buf = virt_to_phys(&zout_buffer[0]);+  TxIntrSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) |+			   IO_STATE(USB_SB_command, tt, zout) |+			   IO_STATE(USB_SB_command, full, yes) |+			   IO_STATE(USB_SB_command, eot, yes) |+			   IO_STATE(USB_SB_command, eol, yes));+  +  for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) {+    CHECK_ALIGN(&TxIntrEPList[i]);+    TxIntrEPList[i].hw_len = 0;+    TxIntrEPList[i].command =+      (IO_STATE(USB_EP_command, eof, yes) |+       IO_STATE(USB_EP_command, enable, yes) |+       IO_FIELD(USB_EP_command, epid, INVALID_EPID));+    TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);+    TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[i + 1]);+  }++  /* Special handling of last descr in list, make list circular */+  CHECK_ALIGN(&TxIntrEPList[i]);+  TxIntrEPList[i].hw_len = 0;+  TxIntrEPList[i].command =+    (IO_STATE(USB_EP_command, eof, yes) |+     IO_STATE(USB_EP_command, eol, yes) |+     IO_STATE(USB_EP_command, enable, yes) |+     IO_FIELD(USB_EP_command, epid, INVALID_EPID));+  TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);+  TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[0]);++  intr_dbg("Initiated Intr EP descriptor list\n");+++  /* Connect DMA 8 sub-channel 2 to first in list */+  *R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);+}++static void tc_dma_init_tx_isoc_list(void) {+  int i;++  DBFENTER;++  /* Read comment at zout_buffer declaration for an explanation to this. */+  TxIsocSB_zout.sw_len = 1;+  TxIsocSB_zout.next = 0;+  TxIsocSB_zout.buf = virt_to_phys(&zout_buffer[0]);+  TxIsocSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) |+			   IO_STATE(USB_SB_command, tt, zout) |+			   IO_STATE(USB_SB_command, full, yes) |+			   IO_STATE(USB_SB_command, eot, yes) |+			   IO_STATE(USB_SB_command, eol, yes));++  /* The last isochronous EP descriptor is a dummy. */+  for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {+    CHECK_ALIGN(&TxIsocEPList[i]);+    TxIsocEPList[i].hw_len = 0;+    TxIsocEPList[i].command = IO_FIELD(USB_EP_command, epid, i);+    TxIsocEPList[i].sub = 0;+    TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[i + 1]);+  }++  CHECK_ALIGN(&TxIsocEPList[i]);+  TxIsocEPList[i].hw_len = 0;++  /* Must enable the last EP descr to get eof interrupt. */+  TxIsocEPList[i].command = (IO_STATE(USB_EP_command, enable, yes) |+			     IO_STATE(USB_EP_command, eof, yes) |+			     IO_STATE(USB_EP_command, eol, yes) |+			     IO_FIELD(USB_EP_command, epid, INVALID_EPID));+  TxIsocEPList[i].sub = virt_to_phys(&TxIsocSB_zout);+  TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[0]);++  *R_DMA_CH8_SUB3_EP = virt_to_phys(&TxIsocEPList[0]);+  *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);+}++static int tc_dma_init(struct usb_hcd *hcd) {+  tc_dma_init_rx_list();+  tc_dma_init_tx_bulk_list();+  tc_dma_init_tx_ctrl_list();+  tc_dma_init_tx_intr_list();+  tc_dma_init_tx_isoc_list();++  if (cris_request_dma(USB_TX_DMA_NBR,+		       "ETRAX 100LX built-in USB (Tx)",+		       DMA_VERBOSE_ON_ERROR,+		       dma_usb)) {+    err("Could not allocate DMA ch 8 for USB");+    return -EBUSY;+  }+ 	+  if (cris_request_dma(USB_RX_DMA_NBR,+		       "ETRAX 100LX built-in USB (Rx)",+		       DMA_VERBOSE_ON_ERROR,+		       dma_usb)) {+    err("Could not allocate DMA ch 9 for USB");+    return -EBUSY;+  }++  *R_IRQ_MASK2_SET =+    /* Note that these interrupts are not used. */+    IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) |+    /* Sub channel 1 (ctrl) descr. interrupts are used. */+    IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) |+    IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) |+    /* Sub channel 3 (isoc) descr. interrupts are used. */+    IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set);+  +  /* Note that the dma9_descr interrupt is not used. */+  *R_IRQ_MASK2_SET =+    IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) |+    IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);++  if (request_irq(ETRAX_USB_RX_IRQ, tc_dma_rx_interrupt, 0,+		  "ETRAX 100LX built-in USB (Rx)", hcd)) {+    err("Could not allocate IRQ %d for USB", ETRAX_USB_RX_IRQ);+    return -EBUSY;+  }+  +  if (request_irq(ETRAX_USB_TX_IRQ, tc_dma_tx_interrupt, 0,+		  "ETRAX 100LX built-in USB (Tx)", hcd)) {+    err("Could not allocate IRQ %d for USB", ETRAX_USB_TX_IRQ);+    return -EBUSY;+  }++  return 0;+}++static void tc_dma_destroy(void) {+  free_irq(ETRAX_USB_RX_IRQ, NULL);+  free_irq(ETRAX_USB_TX_IRQ, NULL);++  cris_free_dma(USB_TX_DMA_NBR, "ETRAX 100LX built-in USB (Tx)");+  cris_free_dma(USB_RX_DMA_NBR, "ETRAX 100LX built-in USB (Rx)");++}++static void tc_dma_link_intr_urb(struct urb *urb);++/* Handle processing of Bulk, Ctrl and Intr queues */+static void tc_dma_process_queue(int epid) {+  struct urb *urb;+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  unsigned long flags;+  char toggle;++  if(epid_state[epid].disabled) {+    /* Don't process any URBs on a disabled endpoint */+    return;+  }++  /* Do not disturb us while fiddling with EPs and epids */+  local_irq_save(flags);++  /* For bulk, Ctrl and Intr can we only have one URB active at a time for+     a specific EP. */+  if(activeUrbList[epid] != NULL) {+    /* An URB is already active on EP, skip checking queue */+    local_irq_restore(flags);+    return;+  }++  urb = urb_list_first(epid);+  if(urb == NULL) {+    /* No URB waiting in EP queue. Nothing do to */+    local_irq_restore(flags);+    return;+  }++  urb_priv = urb->hcpriv;+  ASSERT(urb_priv != NULL);+  ASSERT(urb_priv->urb_state == NOT_STARTED);+  ASSERT(!usb_pipeisoc(urb->pipe));++  /* Remove this URB from the queue and move it to active */+  activeUrbList[epid] = urb;+  urb_list_del(urb, epid);++  urb_priv->urb_state = STARTED;++  /* Reset error counters (regardless of which direction this traffic is). */+  etrax_epid_clear_error(epid);++  /* Special handling of Intr EP lists */+  if(usb_pipeint(urb->pipe)) {+    tc_dma_link_intr_urb(urb);+    local_irq_restore(flags);+    return;+  }++  /* Software must preset the toggle bits for Bulk and Ctrl */+  if(usb_pipecontrol(urb->pipe)) {+    /* Toggle bits are initialized only during setup transaction in a+       CTRL transfer */+    etrax_epid_set_toggle(epid, 0, 0);+    etrax_epid_set_toggle(epid, 1, 0);+  } else {+    toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),+			   usb_pipeout(urb->pipe));+    etrax_epid_set_toggle(epid, usb_pipeout(urb->pipe), toggle);+  }++  tc_dbg("Added SBs from (URB:0x%x %s %s) to epid %d: %s\n",+	 (unsigned int)urb, str_dir(urb->pipe), str_type(urb->pipe), epid,+	 sblist_to_str(urb_priv->first_sb));++  /* We start the DMA sub channel without checking if it's running or not,+     because:+     1) If it's already running, issuing the start command is a nop.+     2) We avoid a test-and-set race condition. */+  switch(usb_pipetype(urb->pipe)) {+  case PIPE_BULK:+    /* Assert that the EP descriptor is disabled. */+    ASSERT(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)));++    /* Set up and enable the EP descriptor. */+    TxBulkEPList[epid].sub = virt_to_phys(urb_priv->first_sb);+    TxBulkEPList[epid].hw_len = 0;+    TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);++    /* Check if the dummy list is already with us (if several urbs were queued). */+    if (usb_pipein(urb->pipe) && (TxBulkEPList[epid].next != virt_to_phys(&TxBulkDummyEPList[epid][0]))) {+      tc_dbg("Inviting dummy list to the party for urb 0x%lx, epid %d", +	     (unsigned long)urb, epid);+      +      /* We don't need to check if the DMA is at this EP or not before changing the+	 next pointer, since we will do it in one 32-bit write (EP descriptors are+	 32-bit aligned). */+      TxBulkEPList[epid].next = virt_to_phys(&TxBulkDummyEPList[epid][0]);+    }++    restart_dma8_sub0();++    /* Update/restart the bulk start timer since we just started the channel.*/+    mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);+    /* Update/restart the bulk eot timer since we just inserted traffic. */+    mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);+    break;+  case PIPE_CONTROL:+    /* Assert that the EP descriptor is disabled. */+    ASSERT(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)));++    /* Set up and enable the EP descriptor. */+    TxCtrlEPList[epid].sub = virt_to_phys(urb_priv->first_sb);+    TxCtrlEPList[epid].hw_len = 0;+    TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);++    *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);+    break;+  }+  local_irq_restore(flags);+}++static void tc_dma_link_intr_urb(struct urb *urb) {+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  volatile struct USB_EP_Desc *tmp_ep;+  struct USB_EP_Desc *ep_desc;+  int i = 0, epid;+  int pool_idx = 0;++  ASSERT(urb_priv != NULL);+  epid = urb_priv->epid;+  ASSERT(urb_priv->interval > 0);+  ASSERT(urb_priv->intr_ep_pool_length > 0);++  tmp_ep = &TxIntrEPList[0];++  /* Only insert one EP descriptor in list for Out Intr URBs.+     We can only handle Out Intr with interval of 128ms because+     it's not possible to insert several Out Intr EPs because they+     are not consumed by the DMA. */+  if(usb_pipeout(urb->pipe)) {+    ep_desc = urb_priv->intr_ep_pool[0];+    ASSERT(ep_desc);+    ep_desc->next = tmp_ep->next;+    tmp_ep->next = virt_to_phys(ep_desc);+    i++;+  } else {+    /* Loop through Intr EP descriptor list and insert EP for URB at+       specified interval */+    do {+      /* Each EP descriptor with eof flag sat signals a new frame */+      if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) {+	/* Insert a EP from URBs EP pool at correct interval */+	if ((i % urb_priv->interval) == 0) {+	  ep_desc = urb_priv->intr_ep_pool[pool_idx];+	  ASSERT(ep_desc);+	  ep_desc->next = tmp_ep->next;+	  tmp_ep->next = virt_to_phys(ep_desc);+	  pool_idx++;+	  ASSERT(pool_idx <= urb_priv->intr_ep_pool_length);+	}+	i++;+      }+      tmp_ep = (struct USB_EP_Desc *)phys_to_virt(tmp_ep->next);+    } while(tmp_ep != &TxIntrEPList[0]);+  }++  intr_dbg("Added SBs to intr epid %d: %s interval:%d (%d EP)\n", epid,+	   sblist_to_str(urb_priv->first_sb), urb_priv->interval, pool_idx);++  /* We start the DMA sub channel without checking if it's running or not,+     because:+     1) If it's already running, issuing the start command is a nop.+     2) We avoid a test-and-set race condition. */+  *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);+}++  /* hinko ignore usb_pipeisoc */+#if 0+static void tc_dma_process_isoc_urb(struct urb *urb) {+  unsigned long flags;+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  int epid;++  /* Do not disturb us while fiddling with EPs and epids */+  local_irq_save(flags);++  ASSERT(urb_priv);+  ASSERT(urb_priv->first_sb);+  epid = urb_priv->epid;++  if(activeUrbList[epid] == NULL) {+    /* EP is idle, so make this URB active */+    activeUrbList[epid] = urb;+    urb_list_del(urb, epid);+    ASSERT(TxIsocEPList[epid].sub == 0);+    ASSERT(!(TxIsocEPList[epid].command &+	     IO_STATE(USB_EP_command, enable, yes)));++    /* Differentiate between In and Out Isoc. Because In SBs are not consumed*/+    if(usb_pipein(urb->pipe)) {+    /* Each EP for In Isoc will have only one SB descriptor, setup when+       submitting the first active urb. We do it here by copying from URBs+       pre-allocated SB. */+      memcpy((void *)&(TxIsocSBList[epid]), urb_priv->first_sb,+	     sizeof(TxIsocSBList[epid]));+      TxIsocEPList[epid].hw_len = 0;+      TxIsocEPList[epid].sub = virt_to_phys(&(TxIsocSBList[epid]));+    } else {+      /* For Out Isoc we attach the pre-allocated list of SBs for the URB */+      TxIsocEPList[epid].hw_len = 0;+      TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb);++      isoc_dbg("Attached first URB:0x%x[%d] to epid:%d first_sb:0x%x"+	       " last_sb::0x%x\n",+	       (unsigned int)urb, urb_priv->urb_num, epid,+	       (unsigned int)(urb_priv->first_sb),+	       (unsigned int)(urb_priv->last_sb));+    }++    if (urb->transfer_flags & URB_ISO_ASAP) {+      /* The isoc transfer should be started as soon as possible. The+	 start_frame field is a return value if URB_ISO_ASAP was set. Comparing+	 R_USB_FM_NUMBER with a USB Chief trace shows that the first isoc IN+	 token is sent 2 frames later. I'm not sure how this affects usage of+	 the start_frame field by the device driver, or how it affects things+	 when USB_ISO_ASAP is not set, so therefore there's no compensation for+	 the 2 frame "lag" here. */+      urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff);+      TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);+      urb_priv->urb_state = STARTED;+      isoc_dbg("URB_ISO_ASAP set, urb->start_frame set to %d\n",+	       urb->start_frame);+    } else {+      /* Not started yet. */+      urb_priv->urb_state = NOT_STARTED;+      isoc_warn("urb_priv->urb_state set to NOT_STARTED for URB:0x%x\n",+		(unsigned int)urb);+    }++  } else {+    /* An URB is already active on the EP. Leave URB in queue and let+       finish_isoc_urb process it after current active URB */+    ASSERT(TxIsocEPList[epid].sub != 0);++    if(usb_pipein(urb->pipe)) {+      /* Because there already is a active In URB on this epid we do nothing+         and the finish_isoc_urb() function will handle switching to next URB*/++    } else { /* For Out Isoc, insert new URBs traffic last in SB-list. */+      struct USB_SB_Desc *temp_sb_desc;++      /* Set state STARTED to all Out Isoc URBs added to SB list because we+         don't know how many of them that are finished before descr interrupt*/+      urb_priv->urb_state = STARTED;++      /* Find end of current SB list by looking for SB with eol flag sat */+      temp_sb_desc = phys_to_virt(TxIsocEPList[epid].sub);+      while ((temp_sb_desc->command & IO_MASK(USB_SB_command, eol)) !=+	     IO_STATE(USB_SB_command, eol, yes)) {+	ASSERT(temp_sb_desc->next);+	temp_sb_desc = phys_to_virt(temp_sb_desc->next);+      }++      isoc_dbg("Appended URB:0x%x[%d] (first:0x%x last:0x%x) to epid:%d"+	       " sub:0x%x eol:0x%x\n",+	       (unsigned int)urb, urb_priv->urb_num,+	       (unsigned int)(urb_priv->first_sb),+	       (unsigned int)(urb_priv->last_sb), epid,+	       (unsigned int)phys_to_virt(TxIsocEPList[epid].sub),+	       (unsigned int)temp_sb_desc);++      /* Next pointer must be set before eol is removed. */+      temp_sb_desc->next = virt_to_phys(urb_priv->first_sb);+      /* Clear the previous end of list flag since there is a new in the+	 added SB descriptor list. */+      temp_sb_desc->command &= ~IO_MASK(USB_SB_command, eol);++      if (!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) {+	__u32 epid_data;+	/* 8.8.5 in Designer's Reference says we should check for and correct+	   any errors in the EP here.  That should not be necessary if+	   epid_attn is handled correctly, so we assume all is ok. */+	epid_data = etrax_epid_iso_get(epid);+	if (IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data) !=+	    IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {+	  isoc_err("Disabled Isoc EP with error:%d on epid:%d when appending"+		   " URB:0x%x[%d]\n",+		   IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data), epid,+		   (unsigned int)urb, urb_priv->urb_num);+	}++	/* The SB list was exhausted. */+	if (virt_to_phys(urb_priv->last_sb) != TxIsocEPList[epid].sub) {+	  /* The new sublist did not get processed before the EP was+	     disabled.  Setup the EP again. */++	  if(virt_to_phys(temp_sb_desc) == TxIsocEPList[epid].sub) {+	    isoc_dbg("EP for epid:%d stoped at SB:0x%x before newly inserted"+		     ", restarting from this URBs SB:0x%x\n",+		     epid, (unsigned int)temp_sb_desc,+		     (unsigned int)(urb_priv->first_sb));+	    TxIsocEPList[epid].hw_len = 0;+	    TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb);+	    urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff);+	    /* Enable the EP again so data gets processed this time */+	    TxIsocEPList[epid].command |=+	      IO_STATE(USB_EP_command, enable, yes);++	  } else {+	    /* The EP has been disabled but not at end this URB (god knows+	       where). This should generate an epid_attn so we should not be+	       here */+	    isoc_warn("EP was disabled on sb:0x%x before SB list for"+		     " URB:0x%x[%d] got processed\n",+		     (unsigned int)phys_to_virt(TxIsocEPList[epid].sub),+		     (unsigned int)urb, urb_priv->urb_num);+	  }+	} else {+	  /* This might happend if we are slow on this function and isn't+	     an error. */+	  isoc_dbg("EP was disabled and finished with SBs from appended"+		   " URB:0x%x[%d]\n", (unsigned int)urb, urb_priv->urb_num);+	}+      }+    }+  }+  +  /* Start the DMA sub channel */+  *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);++  local_irq_restore(flags);+}+#endif++static void tc_dma_unlink_intr_urb(struct urb *urb) {+  struct crisv10_urb_priv *urb_priv = urb->hcpriv;+  volatile struct USB_EP_Desc *first_ep;  /* First EP in the list. */+  volatile struct USB_EP_Desc *curr_ep;   /* Current EP, the iterator. */+  volatile struct USB_EP_Desc *next_ep;   /* The EP after current. */+  volatile struct USB_EP_Desc *unlink_ep; /* The one we should remove from+					     the list. */+  int count = 0;+  volatile int timeout = 10000;+  int epid;++  /* Read 8.8.4 in Designer's Reference, "Removing an EP Descriptor from the+     List". */+  ASSERT(urb_priv);+  ASSERT(urb_priv->intr_ep_pool_length > 0);+  epid = urb_priv->epid;++  /* First disable all Intr EPs belonging to epid for this URB */+  first_ep = &TxIntrEPList[0];+  curr_ep = first_ep;+  do {+    next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next);+    if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) {+      /* Disable EP */+      next_ep->command &= ~IO_MASK(USB_EP_command, enable);+    }+    curr_ep = phys_to_virt(curr_ep->next);+  } while (curr_ep != first_ep);+++  /* Now unlink all EPs belonging to this epid from Descr list */+  first_ep = &TxIntrEPList[0];+  curr_ep = first_ep;+  do {+    next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next);+    if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) {+      /* This is the one we should unlink. */+      unlink_ep = next_ep;++      /* Actually unlink the EP from the DMA list. */+      curr_ep->next = unlink_ep->next;++      /* Wait until the DMA is no longer at this descriptor. */+      while((*R_DMA_CH8_SUB2_EP == virt_to_phys(unlink_ep)) &&+	    (timeout-- > 0));+      if(timeout == 0) {+	warn("Timeout while waiting for DMA-TX-Intr to leave unlink EP\n");+      }+      +      count++;+    }+    curr_ep = phys_to_virt(curr_ep->next);+  } while (curr_ep != first_ep);++  if(count != urb_priv->intr_ep_pool_length) {+    intr_warn("Unlinked %d of %d Intr EPs for URB:0x%x[%d]\n", count,+	      urb_priv->intr_ep_pool_length, (unsigned int)urb,+	      urb_priv->urb_num);+  } else {+    intr_dbg("Unlinked %d of %d interrupt EPs for URB:0x%x\n", count,+	     urb_priv->intr_ep_pool_length, (unsigned int)urb);+  }+}++static void check_finished_bulk_tx_epids(struct usb_hcd *hcd,+						    int timer) {+  unsigned long flags;+  int epid;+  struct urb *urb;+  struct crisv10_urb_priv * urb_priv;+  __u32 epid_data;++  /* Protect TxEPList */+  local_irq_save(flags);++  for (epid = 0; epid < NBR_OF_EPIDS; epid++) {+    /* A finished EP descriptor is disabled and has a valid sub pointer */+    if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) &&+	(TxBulkEPList[epid].sub != 0)) {++      /* Get the active URB for this epid */+      urb = activeUrbList[epid];+      /* Sanity checks */+      ASSERT(urb);+      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+      ASSERT(urb_priv);+      +      /* Only handle finished out Bulk EPs here,+	 and let RX interrupt take care of the rest */+      if(!epid_out_traffic(epid)) {+	continue;+      }++      if(timer) {+	tc_warn("Found finished %s Bulk epid:%d URB:0x%x[%d] from timeout\n",+		epid_out_traffic(epid) ? "Out" : "In", epid, (unsigned int)urb,+		urb_priv->urb_num);+      } else {+	tc_dbg("Found finished %s Bulk epid:%d URB:0x%x[%d] from interrupt\n",+	       epid_out_traffic(epid) ? "Out" : "In", epid, (unsigned int)urb,+	       urb_priv->urb_num);+      }++      if(urb_priv->urb_state == UNLINK) {+	/* This Bulk URB is requested to be unlinked, that means that the EP+	   has been disabled and we might not have sent all data */+	tc_finish_urb(hcd, urb, urb->status);+	continue;+      }++      ASSERT(urb_priv->urb_state == STARTED);+      if (phys_to_virt(TxBulkEPList[epid].sub) != urb_priv->last_sb) {+	tc_err("Endpoint got disabled before reaching last sb\n");+      }+	+      epid_data = etrax_epid_get(epid);+      if (IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data) ==+	  IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {+	/* This means that the endpoint has no error, is disabled+	   and had inserted traffic, i.e. transfer successfully completed. */+	tc_finish_urb(hcd, urb, 0);+      } else {+	/* Shouldn't happen. We expect errors to be caught by epid+	   attention. */+	tc_err("Found disabled bulk EP desc (epid:%d error:%d)\n",+	       epid, IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data));+      }+    } else {+      tc_dbg("Ignoring In Bulk epid:%d, let RX interrupt handle it\n", epid);+    }+  }++  local_irq_restore(flags);+}++static void check_finished_ctrl_tx_epids(struct usb_hcd *hcd) {+  unsigned long flags;+  int epid;+  struct urb *urb;+  struct crisv10_urb_priv * urb_priv;+  __u32 epid_data;++  /* Protect TxEPList */+  local_irq_save(flags);++  for (epid = 0; epid < NBR_OF_EPIDS; epid++) {+    if(epid == DUMMY_EPID)+      continue;++    /* A finished EP descriptor is disabled and has a valid sub pointer */+    if (!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) &&+	(TxCtrlEPList[epid].sub != 0)) {+      +      /* Get the active URB for this epid */+      urb = activeUrbList[epid];++      if(urb == NULL) {+	tc_warn("Found finished Ctrl epid:%d with no active URB\n", epid);+	continue;+      }+      +      /* Sanity checks */+      ASSERT(usb_pipein(urb->pipe));+      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+      ASSERT(urb_priv);+      if (phys_to_virt(TxCtrlEPList[epid].sub) != urb_priv->last_sb) {+	tc_err("Endpoint got disabled before reaching last sb\n");+      }++      epid_data = etrax_epid_get(epid);+      if (IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data) ==+	  IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {+	/* This means that the endpoint has no error, is disabled+	   and had inserted traffic, i.e. transfer successfully completed. */++	/* Check if RX-interrupt for In Ctrl has been processed before+	   finishing the URB */+	if(urb_priv->ctrl_rx_done) {+	  tc_dbg("Finishing In Ctrl URB:0x%x[%d] in tx_interrupt\n",+		 (unsigned int)urb, urb_priv->urb_num);+	  tc_finish_urb(hcd, urb, 0);+	} else {+	  /* If we get zout descriptor interrupt before RX was done for a+	     In Ctrl transfer, then we flag that and it will be finished+	     in the RX-Interrupt */+	  urb_priv->ctrl_zout_done = 1;+	  tc_dbg("Got zout descr interrupt before RX interrupt\n");+	}+      } else {+	/* Shouldn't happen. We expect errors to be caught by epid+	   attention. */+	tc_err("Found disabled Ctrl EP desc (epid:%d URB:0x%x[%d]) error_code:%d\n", epid, (unsigned int)urb, urb_priv->urb_num, IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data));+	__dump_ep_desc(&(TxCtrlEPList[epid]));+	__dump_ept_data(epid);+      }      +    }+  }+  local_irq_restore(flags);+}++  /* hinko ignore usb_pipeisoc */+#if 0+/* This function goes through all epids that are setup for Out Isoc transfers+   and marks (isoc_out_done) all queued URBs that the DMA has finished+   transfer for.+   No URB completetion is done here to make interrupt routine return quickly.+   URBs are completed later with help of complete_isoc_bottom_half() that+   becomes schedules when this functions is finished. */+static void check_finished_isoc_tx_epids(void) {+  unsigned long flags;+  int epid;+  struct urb *urb;+  struct crisv10_urb_priv * urb_priv;+  struct USB_SB_Desc* sb_desc;+  int epid_done;++  /* Protect TxIsocEPList */+  local_irq_save(flags);++  for (epid = 0; epid < NBR_OF_EPIDS; epid++) {+    if (TxIsocEPList[epid].sub == 0 || epid == INVALID_EPID ||+	!epid_out_traffic(epid)) {+      /* Nothing here to see. */+      continue;+    }+    ASSERT(epid_inuse(epid));+    ASSERT(epid_isoc(epid));++    sb_desc = phys_to_virt(TxIsocEPList[epid].sub);+    /* Find the last descriptor of the currently active URB for this ep.+       This is the first descriptor in the sub list marked for a descriptor+       interrupt. */+    while (sb_desc && !IO_EXTRACT(USB_SB_command, intr, sb_desc->command)) {+      sb_desc = sb_desc->next ? phys_to_virt(sb_desc->next) : 0;+    }+    ASSERT(sb_desc);++    isoc_dbg("Descr IRQ checking epid:%d sub:0x%x intr:0x%x\n",+	     epid, (unsigned int)phys_to_virt(TxIsocEPList[epid].sub),+	     (unsigned int)sb_desc);++    urb = activeUrbList[epid];+    if(urb == NULL) {+      isoc_err("Isoc Descr irq on epid:%d with no active URB\n", epid);+      continue;+    }++    epid_done = 0;+    while(urb && !epid_done) {+      /* Sanity check. */+      ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);+      ASSERT(usb_pipeout(urb->pipe));+      +      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+      ASSERT(urb_priv);+      ASSERT(urb_priv->urb_state == STARTED ||+	     urb_priv->urb_state == UNLINK);+      +      if (sb_desc != urb_priv->last_sb) {+	/* This urb has been sent. */+	urb_priv->isoc_out_done = 1;++      } else { /* Found URB that has last_sb as the interrupt reason */++	/* Check if EP has been disabled, meaning that all transfers are done*/+	if(!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) {+	  ASSERT((sb_desc->command & IO_MASK(USB_SB_command, eol)) ==+		 IO_STATE(USB_SB_command, eol, yes));+	  ASSERT(sb_desc->next == 0);+	  urb_priv->isoc_out_done = 1;+	} else {+	  isoc_dbg("Skipping URB:0x%x[%d] because EP not disabled yet\n",+		   (unsigned int)urb, urb_priv->urb_num);+	}+	/* Stop looking any further in queue */+	epid_done = 1;	+      }++      if (!epid_done) {+	if(urb == activeUrbList[epid]) {+	  urb = urb_list_first(epid);+	} else {+	  urb = urb_list_next(urb, epid);+	}+      }+    } /* END: while(urb && !epid_done) */+  }++  local_irq_restore(flags);+}+++/* This is where the Out Isoc URBs are realy completed. This function is+   scheduled from tc_dma_tx_interrupt() when one or more Out Isoc transfers+   are done. This functions completes all URBs earlier marked with+   isoc_out_done by fast interrupt routine check_finished_isoc_tx_epids() */++static void complete_isoc_bottom_half(void *data) {+  struct crisv10_isoc_complete_data *comp_data;+  struct usb_iso_packet_descriptor *packet;+  struct crisv10_urb_priv * urb_priv;+  unsigned long flags;+  struct urb* urb;+  int epid_done;+  int epid;+  int i;++  comp_data = (struct crisv10_isoc_complete_data*)data;++  local_irq_save(flags);++  for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {+    if(!epid_inuse(epid) || !epid_isoc(epid) || !epid_out_traffic(epid) || epid == DUMMY_EPID) {+      /* Only check valid Out Isoc epids */+      continue;+    }++    isoc_dbg("Isoc bottom-half checking epid:%d, sub:0x%x\n", epid,+	     (unsigned int)phys_to_virt(TxIsocEPList[epid].sub));++    /* The descriptor interrupt handler has marked all transmitted Out Isoc+       URBs with isoc_out_done.  Now we traverse all epids and for all that+       have out Isoc traffic we traverse its URB list and complete the+       transmitted URBs. */+    epid_done = 0;+    while (!epid_done) {++      /* Get the active urb (if any) */+      urb = activeUrbList[epid];+      if (urb == 0) {+	isoc_dbg("No active URB on epid:%d anymore\n", epid);+	epid_done = 1;+	continue;+      }++      /* Sanity check. */+      ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);+      ASSERT(usb_pipeout(urb->pipe));++      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+      ASSERT(urb_priv);++      if (!(urb_priv->isoc_out_done)) {+	/* We have reached URB that isn't flaged done yet, stop traversing. */+	isoc_dbg("Stoped traversing Out Isoc URBs on epid:%d"+		 " before not yet flaged URB:0x%x[%d]\n",+		 epid, (unsigned int)urb, urb_priv->urb_num);+	epid_done = 1;+	continue;+      }++      /* This urb has been sent. */+      isoc_dbg("Found URB:0x%x[%d] that is flaged isoc_out_done\n",+	       (unsigned int)urb, urb_priv->urb_num);++      /* Set ok on transfered packets for this URB and finish it */+      for (i = 0; i < urb->number_of_packets; i++) {+	packet = &urb->iso_frame_desc[i];+	packet->status = 0;+	packet->actual_length = packet->length;+      }+      urb_priv->isoc_packet_counter = urb->number_of_packets;+      tc_finish_urb(comp_data->hcd, urb, 0);++    } /* END: while(!epid_done) */+  } /* END: for(epid...) */++  local_irq_restore(flags);+  kmem_cache_free(isoc_compl_cache, comp_data);+}+#endif++static void check_finished_intr_tx_epids(struct usb_hcd *hcd) {+  unsigned long flags;+  int epid;+  struct urb *urb;+  struct crisv10_urb_priv * urb_priv;+  volatile struct USB_EP_Desc *curr_ep;   /* Current EP, the iterator. */+  volatile struct USB_EP_Desc *next_ep;   /* The EP after current. */++  /* Protect TxintrEPList */+  local_irq_save(flags);++  for (epid = 0; epid < NBR_OF_EPIDS; epid++) {+    if(!epid_inuse(epid) || !epid_intr(epid) || !epid_out_traffic(epid)) {+      /* Nothing to see on this epid. Only check valid Out Intr epids */+      continue;+    }++    urb = activeUrbList[epid];+    if(urb == 0) {+      intr_warn("Found Out Intr epid:%d with no active URB\n", epid);+      continue;+    }++    /* Sanity check. */+    ASSERT(usb_pipetype(urb->pipe) == PIPE_INTERRUPT);+    ASSERT(usb_pipeout(urb->pipe));+    +    urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+    ASSERT(urb_priv);++    /* Go through EPs between first and second sof-EP. It's here Out Intr EPs+       are inserted.*/+    curr_ep = &TxIntrEPList[0];+    do {+      next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next);+      if(next_ep == urb_priv->intr_ep_pool[0]) {+	/* We found the Out Intr EP for this epid */+	+	/* Disable it so it doesn't get processed again */+	next_ep->command &= ~IO_MASK(USB_EP_command, enable);++	/* Finish the active Out Intr URB with status OK */+	tc_finish_urb(hcd, urb, 0);+      }+      curr_ep = phys_to_virt(curr_ep->next);+    } while (curr_ep != &TxIntrEPList[1]);++  }+  local_irq_restore(flags);+}++/* Interrupt handler for DMA8/IRQ24 with subchannels (called from hardware intr) */+static irqreturn_t tc_dma_tx_interrupt(int irq, void *vhc) {+  struct usb_hcd *hcd = (struct usb_hcd*)vhc;+  ASSERT(hcd);++  if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {+    /* Clear this interrupt */+    *R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);+    restart_dma8_sub0();+  }++  if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {+    /* Clear this interrupt */+    *R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);+    check_finished_ctrl_tx_epids(hcd);+  }++  if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {+    /* Clear this interrupt */+    *R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);+    check_finished_intr_tx_epids(hcd);+  }++  /* hinko ignore usb_pipeisoc */+#if 0+  if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {+    struct crisv10_isoc_complete_data* comp_data;++    /* Flag done Out Isoc for later completion */+    check_finished_isoc_tx_epids();++    /* Clear this interrupt */+    *R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);+    /* Schedule bottom half of Out Isoc completion function. This function+       finishes the URBs marked with isoc_out_done */+    comp_data = (struct crisv10_isoc_complete_data*)+      kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC);+    ASSERT(comp_data != NULL);+    comp_data ->hcd = hcd;++    //INIT_WORK(&comp_data->usb_bh, complete_isoc_bottom_half, comp_data);+    INIT_WORK(&comp_data->usb_bh, complete_isoc_bottom_half);+    schedule_work(&comp_data->usb_bh);+  }+#endif++  return IRQ_HANDLED;+}++/* Interrupt handler for DMA9/IRQ25 (called from hardware intr) */+static irqreturn_t tc_dma_rx_interrupt(int irq, void *vhc) {+  unsigned long flags;+  struct urb *urb;+  struct usb_hcd *hcd = (struct usb_hcd*)vhc;+  struct crisv10_urb_priv *urb_priv;+  int epid = 0;+  int real_error;++  ASSERT(hcd);++  /* Clear this interrupt. */+  *R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);++  /* Custom clear interrupt for this interrupt */+  /* The reason we cli here is that we call the driver's callback functions. */+  local_irq_save(flags);++  /* Note that this while loop assumes that all packets span only+     one rx descriptor. */+  while(myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {+    epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);+    /* Get the active URB for this epid */+    urb = activeUrbList[epid];++    ASSERT(epid_inuse(epid));+    if (!urb) {+      dma_err("No urb for epid %d in rx interrupt\n", epid);+      goto skip_out;+    }++    /* Check if any errors on epid */+    real_error = 0;+    if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {+      __u32 r_usb_ept_data;++      if (usb_pipeisoc(urb->pipe)) {+	r_usb_ept_data = etrax_epid_iso_get(epid);+	if((r_usb_ept_data & IO_MASK(R_USB_EPT_DATA_ISO, valid)) &&+	   (IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data) == 0) &&+	   (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata))) {+	  /* Not an error, just a failure to receive an expected iso+	     in packet in this frame.  This is not documented+	     in the designers reference. Continue processing.+	  */+	} else real_error = 1;+      } else real_error = 1;+    }++    if(real_error) {+      dma_err("Error in RX descr on epid:%d for URB 0x%x",+	      epid, (unsigned int)urb);+      dump_ept_data(epid);+      dump_in_desc(myNextRxDesc);+      goto skip_out;+    }++    urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;+    ASSERT(urb_priv);+    ASSERT(urb_priv->urb_state == STARTED ||+	   urb_priv->urb_state == UNLINK);++    if ((usb_pipetype(urb->pipe) == PIPE_BULK) ||+	(usb_pipetype(urb->pipe) == PIPE_CONTROL) ||+	(usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {++      /* We get nodata for empty data transactions, and the rx descriptor's+	 hw_len field is not valid in that case. No data to copy in other+	 words. */+      if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {+	/* No data to copy */+      } else {+	/*+	dma_dbg("Processing RX for URB:0x%x epid:%d (data:%d ofs:%d)\n",+		(unsigned int)urb, epid, myNextRxDesc->hw_len,+		urb_priv->rx_offset);+	*/+	/* Only copy data if URB isn't flaged to be unlinked*/+	if(urb_priv->urb_state != UNLINK) {+	  /* Make sure the data fits in the buffer. */+	  if(urb_priv->rx_offset + myNextRxDesc->hw_len+	     <= urb->transfer_buffer_length) {++	    /* Copy the data to URBs buffer */+	    memcpy(urb->transfer_buffer + urb_priv->rx_offset,+		   phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len);+	    urb_priv->rx_offset += myNextRxDesc->hw_len;+	  } else {+	    /* Signal overflow when returning URB */+	    urb->status = -EOVERFLOW;+	    tc_finish_urb_later(hcd, urb, urb->status);+	  }+	}+      }++      /* Check if it was the last packet in the transfer */+      if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) {+	/* Special handling for In Ctrl URBs. */+	if(usb_pipecontrol(urb->pipe) && usb_pipein(urb->pipe) &&+	   !(urb_priv->ctrl_zout_done)) {+	  /* Flag that RX part of Ctrl transfer is done. Because zout descr+	     interrupt hasn't happend yet will the URB be finished in the+	     TX-Interrupt. */+	  urb_priv->ctrl_rx_done = 1;+	  tc_dbg("Not finishing In Ctrl URB:0x%x from rx_interrupt, waiting"+		 " for zout\n", (unsigned int)urb);+	} else {+	  tc_finish_urb(hcd, urb, 0);+	}+      }+    } else { /* ISOC RX */+      /*+      isoc_dbg("Processing RX for epid:%d (URB:0x%x) ISOC pipe\n",+	       epid, (unsigned int)urb);+      */++      struct usb_iso_packet_descriptor *packet;++      if (urb_priv->urb_state == UNLINK) {+	isoc_warn("Ignoring Isoc Rx data for urb being unlinked.\n");+	goto skip_out;+      } else if (urb_priv->urb_state == NOT_STARTED) {+	isoc_err("What? Got Rx data for Isoc urb that isn't started?\n");+	goto skip_out;+      }++      packet = &urb->iso_frame_desc[urb_priv->isoc_packet_counter];+      ASSERT(packet);+      packet->status = 0;++      if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {+	/* We get nodata for empty data transactions, and the rx descriptor's+	   hw_len field is not valid in that case. We copy 0 bytes however to+	   stay in synch. */+	packet->actual_length = 0;+      } else {+	packet->actual_length = myNextRxDesc->hw_len;+	/* Make sure the data fits in the buffer. */+	ASSERT(packet->actual_length <= packet->length);+	memcpy(urb->transfer_buffer + packet->offset,+	       phys_to_virt(myNextRxDesc->buf), packet->actual_length);+	if(packet->actual_length > 0)+	  isoc_dbg("Copied %d bytes, packet %d for URB:0x%x[%d]\n",+		   packet->actual_length, urb_priv->isoc_packet_counter,+		   (unsigned int)urb, urb_priv->urb_num);+      }++      /* Increment the packet counter. */+      urb_priv->isoc_packet_counter++;++      /* Note that we don't care about the eot field in the rx descriptor's+	 status. It will always be set for isoc traffic. */+      if (urb->number_of_packets == urb_priv->isoc_packet_counter) {+	/* Complete the urb with status OK. */+	tc_finish_urb(hcd, urb, 0);+      }+    }++  skip_out:+    myNextRxDesc->status = 0;+    myNextRxDesc->command |= IO_MASK(USB_IN_command, eol);+    myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol);+    myLastRxDesc = myNextRxDesc;+    myNextRxDesc = phys_to_virt(myNextRxDesc->next);+    flush_etrax_cache();+    *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, restart);+  }++  local_irq_restore(flags);++  return IRQ_HANDLED;+}++static void tc_bulk_start_timer_func(unsigned long dummy) {+  /* We might enable an EP descriptor behind the current DMA position when+     it's about to decide that there are no more bulk traffic and it should+     stop the bulk channel.+     Therefore we periodically check if the bulk channel is stopped and there+     is an enabled bulk EP descriptor, in which case we start the bulk+     channel. */+  +  if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {+    int epid;++    timer_dbg("bulk_start_timer: Bulk DMA channel not running.\n");++    for (epid = 0; epid < NBR_OF_EPIDS; epid++) {+      if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {+	timer_warn("Found enabled EP for epid %d, starting bulk channel.\n",+		   epid);+	restart_dma8_sub0();++	/* Restart the bulk eot timer since we just started the bulk channel.*/+	mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);++	/* No need to search any further. */+	break;+      }+    }+  } else {+    timer_dbg("bulk_start_timer: Bulk DMA channel running.\n");+  }+}++static void tc_bulk_eot_timer_func(unsigned long dummy) {+  struct usb_hcd *hcd = (struct usb_hcd*)dummy;+  ASSERT(hcd);+  /* Because of a race condition in the top half, we might miss a bulk eot.+     This timer "simulates" a bulk eot if we don't get one for a while,+     hopefully correcting the situation. */+  timer_dbg("bulk_eot_timer timed out.\n");+  check_finished_bulk_tx_epids(hcd, 1);+}+++/*************************************************************/+/*************************************************************/+/* Device driver block                                       */+/*************************************************************/+/*************************************************************/++/* Forward declarations for device driver functions */+static int devdrv_hcd_probe(struct device *);+static int devdrv_hcd_remove(struct device *);+#ifdef CONFIG_PM+static int devdrv_hcd_suspend(struct device *, u32, u32);+static int devdrv_hcd_resume(struct device *, u32);+#endif /* CONFIG_PM */++/* the device */+static struct platform_device *devdrv_hc_platform_device;++/* device driver interface */+static struct device_driver devdrv_hc_device_driver = {+  .name =			(char *) hc_name,+  .bus =			&platform_bus_type,++  .probe =		devdrv_hcd_probe,+  .remove =		devdrv_hcd_remove,++#ifdef CONFIG_PM+  .suspend =		devdrv_hcd_suspend,+  .resume =		devdrv_hcd_resume,+#endif /* CONFIG_PM */+};++/* initialize the host controller and driver  */+static int __init_or_module devdrv_hcd_probe(struct device *dev)+{+  struct usb_hcd *hcd;+  struct crisv10_hcd *crisv10_hcd;+  int retval;+  int rev_maj, rev_min;++  /* Check DMA burst length */+  if(IO_EXTRACT(R_BUS_CONFIG, dma_burst, *R_BUS_CONFIG) !=+     IO_STATE(R_BUS_CONFIG, dma_burst, burst32)) {+    devdrv_err("Invalid DMA burst length in Etrax 100LX,"+	       " needs to be 32\n");+    return -EPERM;+  }++  hcd = usb_create_hcd(&crisv10_hc_driver, dev, dev_name(dev));+  if (!hcd)+    return -ENOMEM;++  crisv10_hcd = hcd_to_crisv10_hcd(hcd);+  spin_lock_init(&crisv10_hcd->lock);+  crisv10_hcd->num_ports = num_ports();+  crisv10_hcd->running = 0;++  dev_set_drvdata(dev, crisv10_hcd);++  devdrv_dbg("ETRAX USB IRQs HC:%d  RX:%d  TX:%d\n", ETRAX_USB_HC_IRQ,+	  ETRAX_USB_RX_IRQ, ETRAX_USB_TX_IRQ);++  /* Print out chip version read from registers */+  rev_maj = *R_USB_REVISION & IO_MASK(R_USB_REVISION, major);+  rev_min = *R_USB_REVISION & IO_MASK(R_USB_REVISION, minor);+  if(rev_min == 0) {+    devdrv_info("Etrax 100LX USB Revision %d v1,2\n", rev_maj);+  } else {+    devdrv_info("Etrax 100LX USB Revision %d v%d\n", rev_maj, rev_min);+  }++  devdrv_info("Bulk timer interval, start:%d eot:%d\n",+	      BULK_START_TIMER_INTERVAL,+	      BULK_EOT_TIMER_INTERVAL);+++  /* Init root hub data structures */+  if(rh_init()) {+    devdrv_err("Failed init data for Root Hub\n");+    retval = -ENOMEM;+  }++  if(port_in_use(0)) {+    if (cris_request_io_interface(if_usb_1, "ETRAX100LX USB-HCD")) {+      printk(KERN_CRIT "usb-host: request IO interface usb1 failed");+      retval = -EBUSY;+      goto out;+    }+    devdrv_info("Claimed interface for USB physical port 1\n");+  }+  if(port_in_use(1)) {+    if (cris_request_io_interface(if_usb_2, "ETRAX100LX USB-HCD")) {+      /* Free first interface if second failed to be claimed */+      if(port_in_use(0)) {+	cris_free_io_interface(if_usb_1);+      }+      printk(KERN_CRIT "usb-host: request IO interface usb2 failed");+      retval = -EBUSY;+      goto out;+    }+    devdrv_info("Claimed interface for USB physical port 2\n");+  }+  +  /* Init transfer controller structs and locks */+  if((retval = tc_init(hcd)) != 0) {+    goto out;+  }++  /* Attach interrupt functions for DMA and init DMA controller */+  if((retval = tc_dma_init(hcd)) != 0) {+    goto out;+  }++  /* Attach the top IRQ handler for USB controller interrupts */+  if (request_irq(ETRAX_USB_HC_IRQ, crisv10_hcd_top_irq, 0,+		  "ETRAX 100LX built-in USB (HC)", hcd)) {+    err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ);+    retval = -EBUSY;+    goto out;+  }++  /* iso_eof is only enabled when isoc traffic is running. */+  *R_USB_IRQ_MASK_SET =+    /* IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set) | */+    IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) |+    IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) |+    IO_STATE(R_USB_IRQ_MASK_SET, port_status, set) |+    IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set);+++  crisv10_ready_wait();+  /* Reset the USB interface. */+  *R_USB_COMMAND =+    IO_STATE(R_USB_COMMAND, port_sel, nop) |+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |+    IO_STATE(R_USB_COMMAND, ctrl_cmd, reset);++  /* Designer's Reference, p. 8 - 10 says we should Initate R_USB_FM_PSTART to+     0x2A30 (10800), to guarantee that control traffic gets 10% of the+     bandwidth, and periodic transfer may allocate the rest (90%).+     This doesn't work though.+     The value 11960 is chosen to be just after the SOF token, with a couple+     of bit times extra for possible bit stuffing. */+  *R_USB_FM_PSTART = IO_FIELD(R_USB_FM_PSTART, value, 11960);++  crisv10_ready_wait();+  /* Configure the USB interface as a host controller. */+  *R_USB_COMMAND =+    IO_STATE(R_USB_COMMAND, port_sel, nop) |+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |+    IO_STATE(R_USB_COMMAND, ctrl_cmd, host_config);+++  /* Check so controller not busy before enabling ports */+  crisv10_ready_wait();++  /* Enable selected USB ports */+  if(port_in_use(0)) {+    *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);+  } else {+    *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes);+  }+  if(port_in_use(1)) {+    *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);+  } else {+    *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes);+  }++  crisv10_ready_wait();+  /* Start processing of USB traffic. */+  *R_USB_COMMAND =+    IO_STATE(R_USB_COMMAND, port_sel, nop) |+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |+    IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);++  /* Do not continue probing initialization before USB interface is done */+  crisv10_ready_wait();++  /* Register our Host Controller to USB Core+   * Finish the remaining parts of generic HCD initialization: allocate the+   * buffers of consistent memory, register the bus+   * and call the driver's reset() and start() routines. */+  retval = usb_add_hcd(hcd, ETRAX_USB_HC_IRQ, IRQF_DISABLED);+  if (retval != 0) {+    devdrv_err("Failed registering HCD driver\n");+    goto out;+  }++  return 0;++ out:+  devdrv_hcd_remove(dev);+  return retval;+}+++/* cleanup after the host controller and driver */+static int __init_or_module devdrv_hcd_remove(struct device *dev)+{+  struct crisv10_hcd *crisv10_hcd = dev_get_drvdata(dev);+  struct usb_hcd *hcd;++  if (!crisv10_hcd)+    return 0;+  hcd = crisv10_hcd_to_hcd(crisv10_hcd);+++  /* Stop USB Controller in Etrax 100LX */+  crisv10_hcd_reset(hcd);++  usb_remove_hcd(hcd);+  devdrv_dbg("Removed HCD from USB Core\n");++  /* Free USB Controller IRQ */+  free_irq(ETRAX_USB_HC_IRQ, NULL);++  /* Free resources */+  tc_dma_destroy();+  tc_destroy();+++  if(port_in_use(0)) {+    cris_free_io_interface(if_usb_1);+  }+  if(port_in_use(1)) {+    cris_free_io_interface(if_usb_2);+  }++  devdrv_dbg("Freed all claimed resources\n");++  return 0;+}+++#ifdef	CONFIG_PM++static int devdrv_hcd_suspend(struct usb_hcd *hcd, u32 state, u32 level)+{+  return 0; /* no-op for now */+}++static int devdrv_hcd_resume(struct usb_hcd *hcd, u32 level)+{+  return 0; /* no-op for now */+}++#endif /* CONFIG_PM */++++/*************************************************************/+/*************************************************************/+/* Module block                                              */+/*************************************************************/+/*************************************************************/+ +/* register driver */+static int __init module_hcd_init(void) +{+  +  if (usb_disabled())+    return -ENODEV;++  /* Here we select enabled ports by following defines created from+     menuconfig */+#ifndef CONFIG_ETRAX_USB_HOST_PORT1+  ports &= ~(1<<0);+#endif+#ifndef CONFIG_ETRAX_USB_HOST_PORT2+  ports &= ~(1<<1);+#endif++  printk(KERN_INFO "%s version "VERSION" "COPYRIGHT"\n", product_desc);++  devdrv_hc_platform_device =+    platform_device_register_simple((char *) hc_name, 0, NULL, 0);++  if (IS_ERR(devdrv_hc_platform_device))+    return PTR_ERR(devdrv_hc_platform_device);+  return driver_register(&devdrv_hc_device_driver);+  /* +   * Note that we do not set the DMA mask for the device,+   * i.e. we pretend that we will use PIO, since no specific+   * allocation routines are needed for DMA buffers. This will+   * cause the HCD buffer allocation routines to fall back to+   * kmalloc().+   */+}++/* unregister driver */+static void __exit module_hcd_exit(void) +{	+  driver_unregister(&devdrv_hc_device_driver);+}+++/* Module hooks */+module_init(module_hcd_init);+module_exit(module_hcd_exit);diff -Nur linux-2.6.37.orig/drivers/usb/host/hc-crisv10.h linux-2.6.37/drivers/usb/host/hc-crisv10.h--- linux-2.6.37.orig/drivers/usb/host/hc-crisv10.h	1970-01-01 01:00:00.000000000 +0100+++ linux-2.6.37/drivers/usb/host/hc-crisv10.h	2011-04-27 12:05:31.917663433 +0200@@ -0,0 +1,331 @@+#ifndef __LINUX_ETRAX_USB_H+#define __LINUX_ETRAX_USB_H++#include <linux/types.h>+#include <linux/list.h>++struct USB_IN_Desc {+  volatile __u16 sw_len;+  volatile __u16 command;+  volatile unsigned long next;+  volatile unsigned long buf;+  volatile __u16 hw_len;+  volatile __u16 status;+};++struct USB_SB_Desc {+  volatile __u16 sw_len;+  volatile __u16 command;+  volatile unsigned long next;+  volatile unsigned long buf;+};++struct USB_EP_Desc {+  volatile __u16 hw_len;+  volatile __u16 command;+  volatile unsigned long sub;+  volatile unsigned long next;+};+++/* Root Hub port status struct */+struct crisv10_rh {+  volatile __u16 wPortChange[2];+  volatile __u16 wPortStatusPrev[2];+};++/* HCD description */+struct crisv10_hcd {+  spinlock_t		lock;+  __u8			num_ports;+  __u8                  running;+};+++/* Endpoint HC private data description */+struct crisv10_ep_priv {+  int epid;+};++/* Additional software state info for a USB Controller epid */+struct etrax_epid {+  __u8 inuse;       /* !0 = setup in Etrax and used for a endpoint */+  __u8 disabled;    /* !0 = Temporarly disabled to avoid resubmission */+  __u8 type;        /* Setup as: PIPE_BULK, PIPE_CONTROL ... */+  __u8 out_traffic; /* !0 = This epid is for out traffic */+};++/* Struct to hold information of scheduled later URB completion */+struct urb_later_data {+//  struct work_struct ws;+  struct delayed_work ws;+  struct usb_hcd *hcd;+  struct urb *urb;+  int urb_num;+  int status;+};+++typedef enum {+  STARTED,+  NOT_STARTED,+  UNLINK,+} crisv10_urb_state_t;+++struct crisv10_urb_priv {+  /* Sequence number for this URB. Every new submited URB gets this from+     a incrementing counter. Used when a URB is scheduled for later finish to+     be sure that the intended URB hasn't already been completed (device+     drivers has a tendency to reuse URBs once they are completed, causing us+     to not be able to single old ones out only based on the URB pointer.) */+  __u32 urb_num;++  /* The first_sb field is used for freeing all SB descriptors belonging+     to an urb. The corresponding ep descriptor's sub pointer cannot be+     used for this since the DMA advances the sub pointer as it processes+     the sb list. */+  struct USB_SB_Desc *first_sb;++  /* The last_sb field referes to the last SB descriptor that belongs to+     this urb. This is important to know so we can free the SB descriptors+     that ranges between first_sb and last_sb. */+  struct USB_SB_Desc *last_sb;+  +  /* The rx_offset field is used in ctrl and bulk traffic to keep track+     of the offset in the urb's transfer_buffer where incoming data should be+     copied to. */+  __u32 rx_offset;+  +  /* Counter used in isochronous transfers to keep track of the+     number of packets received/transmitted.  */+  __u32 isoc_packet_counter;++  /* Flag that marks if this Isoc Out URB has finished it's transfer. Used+     because several URBs can be finished before list is processed */+  __u8  isoc_out_done;+  +  /* This field is used to pass information about the urb's current state+     between the various interrupt handlers (thus marked volatile). */+  volatile crisv10_urb_state_t urb_state;+  +  /* In Ctrl transfers consist of (at least) 3 packets: SETUP, IN and ZOUT.+     When DMA8 sub-channel 2 has processed the SB list for this sequence we+     get a interrupt. We also get a interrupt for In transfers and which+     one of these interrupts that comes first depends of data size and device.+     To be sure that we have got both interrupts before we complete the URB+     we have these to flags that shows which part that has completed.+     We can then check when we get one of the interrupts that if the other has+     occured it's safe for us to complete the URB, otherwise we set appropriate+     flag and do the completion when we get the other interrupt. */+  volatile unsigned char ctrl_zout_done;+  volatile unsigned char ctrl_rx_done;++  /* Connection between the submitted urb and ETRAX epid number */+  __u8 epid;+  +  /* The rx_data_list field is used for periodic traffic, to hold+     received data for later processing in the the complete_urb functions,+     where the data us copied to the urb's transfer_buffer. Basically, we+     use this intermediate storage because we don't know when it's safe to+     reuse the transfer_buffer (FIXME?). */+  struct list_head rx_data_list;+++  /* The interval time rounded up to closest 2^N */+  int interval;++  /* Pool of EP descriptors needed if it's a INTR transfer.+     Amount of EPs in pool correspons to how many INTR that should+     be inserted in TxIntrEPList (max 128, defined by MAX_INTR_INTERVAL) */+  struct USB_EP_Desc* intr_ep_pool[128];++  /* The mount of EPs allocated for this INTR URB */+  int intr_ep_pool_length;++  /* Pointer to info struct if URB is scheduled to be finished later */+  struct urb_later_data* later_data;+};+++/* This struct is for passing data from the top half to the bottom half irq+   handlers */+struct crisv10_irq_reg {+  struct usb_hcd* hcd;+  __u32 r_usb_epid_attn;+  __u8 r_usb_status;+  __u16 r_usb_rh_port_status_1;+  __u16 r_usb_rh_port_status_2;+  __u32 r_usb_irq_mask_read;+  __u32 r_usb_fm_number;+  struct work_struct usb_bh;+};+++/* This struct is for passing data from the isoc top half to the isoc bottom+   half. */+struct crisv10_isoc_complete_data {+  struct usb_hcd *hcd;+  struct urb *urb;+  struct work_struct usb_bh;+};++/* Entry item for URB lists for each endpint */+typedef struct urb_entry+{+	struct urb *urb;+	struct list_head list;+} urb_entry_t;++/* ---------------------------------------------------------------------------+   Virtual Root HUB+   ------------------------------------------------------------------------- */+/* destination of request */+#define RH_INTERFACE               0x01+#define RH_ENDPOINT                0x02+#define RH_OTHER                   0x03++#define RH_CLASS                   0x20+#define RH_VENDOR                  0x40++/* Requests: bRequest << 8 | bmRequestType */+#define RH_GET_STATUS           0x0080+#define RH_CLEAR_FEATURE        0x0100+#define RH_SET_FEATURE          0x0300+#define RH_SET_ADDRESS		0x0500+#define RH_GET_DESCRIPTOR	0x0680+#define RH_SET_DESCRIPTOR       0x0700+#define RH_GET_CONFIGURATION	0x0880+#define RH_SET_CONFIGURATION	0x0900+#define RH_GET_STATE            0x0280+#define RH_GET_INTERFACE        0x0A80+#define RH_SET_INTERFACE        0x0B00+#define RH_SYNC_FRAME           0x0C80+/* Our Vendor Specific Request */+#define RH_SET_EP               0x2000+++/* Hub port features */+#define RH_PORT_CONNECTION         0x00+#define RH_PORT_ENABLE             0x01+#define RH_PORT_SUSPEND            0x02+#define RH_PORT_OVER_CURRENT       0x03+#define RH_PORT_RESET              0x04+#define RH_PORT_POWER              0x08+#define RH_PORT_LOW_SPEED          0x09+#define RH_C_PORT_CONNECTION       0x10+#define RH_C_PORT_ENABLE           0x11+#define RH_C_PORT_SUSPEND          0x12+#define RH_C_PORT_OVER_CURRENT     0x13+#define RH_C_PORT_RESET            0x14++/* Hub features */+#define RH_C_HUB_LOCAL_POWER       0x00+#define RH_C_HUB_OVER_CURRENT      0x01++#define RH_DEVICE_REMOTE_WAKEUP    0x00+#define RH_ENDPOINT_STALL          0x01++/* Our Vendor Specific feature */+#define RH_REMOVE_EP               0x00+++#define RH_ACK                     0x01+#define RH_REQ_ERR                 -1+#define RH_NACK                    0x00++/* Field definitions for */++#define USB_IN_command__eol__BITNR      0 /* command macros */+#define USB_IN_command__eol__WIDTH      1+#define USB_IN_command__eol__no         0+#define USB_IN_command__eol__yes        1++#define USB_IN_command__intr__BITNR     3+#define USB_IN_command__intr__WIDTH     1+#define USB_IN_command__intr__no        0+#define USB_IN_command__intr__yes       1++#define USB_IN_status__eop__BITNR       1 /* status macros. */+#define USB_IN_status__eop__WIDTH       1+#define USB_IN_status__eop__no          0+#define USB_IN_status__eop__yes         1++#define USB_IN_status__eot__BITNR       5+#define USB_IN_status__eot__WIDTH       1+#define USB_IN_status__eot__no          0+#define USB_IN_status__eot__yes         1++#define USB_IN_status__error__BITNR     6+#define USB_IN_status__error__WIDTH     1+#define USB_IN_status__error__no        0+#define USB_IN_status__error__yes       1++#define USB_IN_status__nodata__BITNR    7+#define USB_IN_status__nodata__WIDTH    1+#define USB_IN_status__nodata__no       0+#define USB_IN_status__nodata__yes      1++#define USB_IN_status__epid__BITNR      8+#define USB_IN_status__epid__WIDTH      5++#define USB_EP_command__eol__BITNR      0+#define USB_EP_command__eol__WIDTH      1+#define USB_EP_command__eol__no         0+#define USB_EP_command__eol__yes        1++#define USB_EP_command__eof__BITNR      1+#define USB_EP_command__eof__WIDTH      1+#define USB_EP_command__eof__no         0+#define USB_EP_command__eof__yes        1++#define USB_EP_command__intr__BITNR     3+#define USB_EP_command__intr__WIDTH     1+#define USB_EP_command__intr__no        0+#define USB_EP_command__intr__yes       1++#define USB_EP_command__enable__BITNR   4+#define USB_EP_command__enable__WIDTH   1+#define USB_EP_command__enable__no      0+#define USB_EP_command__enable__yes     1++#define USB_EP_command__hw_valid__BITNR 5+#define USB_EP_command__hw_valid__WIDTH 1+#define USB_EP_command__hw_valid__no    0+#define USB_EP_command__hw_valid__yes   1++#define USB_EP_command__epid__BITNR     8+#define USB_EP_command__epid__WIDTH     5++#define USB_SB_command__eol__BITNR      0 /* command macros. */+#define USB_SB_command__eol__WIDTH      1+#define USB_SB_command__eol__no         0+#define USB_SB_command__eol__yes        1++#define USB_SB_command__eot__BITNR      1+#define USB_SB_command__eot__WIDTH      1+#define USB_SB_command__eot__no         0+#define USB_SB_command__eot__yes        1++#define USB_SB_command__intr__BITNR     3+#define USB_SB_command__intr__WIDTH     1+#define USB_SB_command__intr__no        0+#define USB_SB_command__intr__yes       1++#define USB_SB_command__tt__BITNR       4+#define USB_SB_command__tt__WIDTH       2+#define USB_SB_command__tt__zout        0+#define USB_SB_command__tt__in          1+#define USB_SB_command__tt__out         2+#define USB_SB_command__tt__setup       3+++#define USB_SB_command__rem__BITNR      8+#define USB_SB_command__rem__WIDTH      6++#define USB_SB_command__full__BITNR     6+#define USB_SB_command__full__WIDTH     1+#define USB_SB_command__full__no        0+#define USB_SB_command__full__yes       1++#endifdiff -Nur linux-2.6.37.orig/drivers/usb/host/Makefile linux-2.6.37/drivers/usb/host/Makefile--- linux-2.6.37.orig/drivers/usb/host/Makefile	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/drivers/usb/host/Makefile	2011-04-27 12:05:31.787668204 +0200@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o+obj-$(CONFIG_ETRAX_USB_HOST)	+= hc-crisv10.o obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.odiff -Nur linux-2.6.37.orig/drivers/usb/Makefile linux-2.6.37/drivers/usb/Makefile--- linux-2.6.37.orig/drivers/usb/Makefile	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/drivers/usb/Makefile	2011-04-27 12:05:31.717665249 +0200@@ -21,6 +21,7 @@ obj-$(CONFIG_USB_R8A66597_HCD)	+= host/ obj-$(CONFIG_USB_HWA_HCD)	+= host/ obj-$(CONFIG_USB_ISP1760_HCD)	+= host/+obj-$(CONFIG_ETRAX_USB_HOST)	+= host/ obj-$(CONFIG_USB_IMX21_HCD)	+= host/  obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/diff -Nur linux-2.6.37.orig/lib/klist.c linux-2.6.37/lib/klist.c--- linux-2.6.37.orig/lib/klist.c	2011-01-05 01:50:19.000000000 +0100+++ linux-2.6.37/lib/klist.c	2011-04-27 12:05:31.967661872 +0200@@ -60,7 +60,7 @@ { 	knode->n_klist = klist; 	/* no knode deserves to start its life dead */-	WARN_ON(knode_dead(knode));+	//WARN_ON(knode_dead(knode)); }  static void knode_kill(struct klist_node *knode)
 |