001-patch-2.4.26-vrs1 2.4 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050390513905239053390543905539056390573905839059390603906139062390633906439065390663906739068390693907039071390723907339074390753907639077390783907939080390813908239083390843908539086390873908839089390903909139092390933909439095390963909739098390993910039101391023910339104391053910639107391083910939110391113911239113391143911539116391173911839119391203912139122391233912439125391263912739128391293913039131391323913339134391353913639137391383913939140391413914239143391443914539146391473914839149391503915139152391533915439155391563915739158391593916039161391623916339164391653916639167391683916939170391713917239173391743917539176391773917839179391803918139182391833918439185391863918739188391893919039191391923919339194391953919639197391983919939200392013920239203392043920539206392073920839209392103921139212392133921439215392163921739218392193922039221392223922339224392253922639227392283922939230392313923239233392343923539236392373923839239392403924139242392433924439245392463924739248392493925039251392523925339254392553925639257392583925939260392613926239263392643926539266392673926839269392703927139272392733927439275392763927739278392793928039281392823928339284392853928639287392883928939290392913929239293392943929539296392973929839299393003930139302393033930439305393063930739308393093931039311393123931339314393153931639317393183931939320393213932239323393243932539326393273932839329393303933139332393333933439335393363933739338393393934039341393423934339344393453934639347393483934939350393513935239353393543935539356393573935839359393603936139362393633936439365393663936739368393693937039371393723937339374393753937639377393783937939380393813938239383393843938539386393873938839389393903939139392393933939439395393963939739398393993940039401394023940339404394053940639407394083940939410394113941239413394143941539416394173941839419394203942139422394233942439425394263942739428394293943039431394323943339434394353943639437394383943939440394413944239443394443944539446394473944839449394503945139452394533945439455394563945739458394593946039461394623946339464394653946639467394683946939470394713947239473394743947539476394773947839479394803948139482394833948439485394863948739488394893949039491394923949339494394953949639497394983949939500395013950239503395043950539506395073950839509395103951139512395133951439515395163951739518395193952039521395223952339524395253952639527395283952939530395313953239533395343953539536395373953839539395403954139542395433954439545395463954739548395493955039551395523955339554395553955639557395583955939560395613956239563395643956539566395673956839569395703957139572395733957439575395763957739578395793958039581395823958339584395853958639587395883958939590395913959239593395943959539596395973959839599396003960139602396033960439605396063960739608396093961039611396123961339614396153961639617396183961939620396213962239623396243962539626396273962839629396303963139632396333963439635396363963739638396393964039641396423964339644396453964639647396483964939650396513965239653396543965539656396573965839659396603966139662396633966439665396663966739668396693967039671396723967339674396753967639677396783967939680396813968239683396843968539686396873968839689396903969139692396933969439695396963969739698396993970039701397023970339704397053970639707397083970939710397113971239713397143971539716397173971839719397203972139722397233972439725397263972739728397293973039731397323973339734397353973639737397383973939740397413974239743397443974539746397473974839749397503975139752397533975439755397563975739758397593976039761397623976339764397653976639767397683976939770397713977239773397743977539776397773977839779397803978139782397833978439785397863978739788397893979039791397923979339794397953979639797397983979939800398013980239803398043980539806398073980839809398103981139812398133981439815398163981739818398193982039821398223982339824398253982639827398283982939830398313983239833398343983539836398373983839839398403984139842398433984439845398463984739848398493985039851398523985339854398553985639857398583985939860398613986239863398643986539866398673986839869398703987139872398733987439875398763987739878398793988039881398823988339884398853988639887398883988939890398913989239893398943989539896398973989839899399003990139902399033990439905399063990739908399093991039911399123991339914399153991639917399183991939920399213992239923399243992539926399273992839929399303993139932399333993439935399363993739938399393994039941399423994339944399453994639947399483994939950399513995239953399543995539956399573995839959399603996139962399633996439965399663996739968399693997039971399723997339974399753997639977399783997939980399813998239983399843998539986399873998839989399903999139992399933999439995399963999739998399994000040001400024000340004400054000640007400084000940010400114001240013400144001540016400174001840019400204002140022400234002440025400264002740028400294003040031400324003340034400354003640037400384003940040400414004240043400444004540046400474004840049400504005140052400534005440055400564005740058400594006040061400624006340064400654006640067400684006940070400714007240073400744007540076400774007840079400804008140082400834008440085400864008740088400894009040091400924009340094400954009640097400984009940100401014010240103401044010540106401074010840109401104011140112401134011440115401164011740118401194012040121401224012340124401254012640127401284012940130401314013240133401344013540136401374013840139401404014140142401434014440145401464014740148401494015040151401524015340154401554015640157401584015940160401614016240163401644016540166401674016840169401704017140172401734017440175401764017740178401794018040181401824018340184401854018640187401884018940190401914019240193401944019540196401974019840199402004020140202402034020440205402064020740208402094021040211402124021340214402154021640217402184021940220402214022240223402244022540226402274022840229402304023140232402334023440235402364023740238402394024040241402424024340244402454024640247402484024940250402514025240253402544025540256402574025840259402604026140262402634026440265402664026740268402694027040271402724027340274402754027640277402784027940280402814028240283402844028540286402874028840289402904029140292402934029440295402964029740298402994030040301403024030340304403054030640307403084030940310403114031240313403144031540316403174031840319403204032140322403234032440325403264032740328403294033040331403324033340334403354033640337403384033940340403414034240343403444034540346403474034840349403504035140352403534035440355403564035740358403594036040361403624036340364403654036640367403684036940370403714037240373403744037540376403774037840379403804038140382403834038440385403864038740388403894039040391403924039340394403954039640397403984039940400404014040240403404044040540406404074040840409404104041140412404134041440415404164041740418404194042040421404224042340424404254042640427404284042940430404314043240433404344043540436404374043840439404404044140442404434044440445404464044740448404494045040451404524045340454404554045640457404584045940460404614046240463404644046540466404674046840469404704047140472404734047440475404764047740478404794048040481404824048340484404854048640487404884048940490404914049240493404944049540496404974049840499405004050140502405034050440505405064050740508405094051040511405124051340514405154051640517405184051940520405214052240523405244052540526405274052840529405304053140532405334053440535405364053740538405394054040541405424054340544405454054640547405484054940550405514055240553405544055540556405574055840559405604056140562405634056440565405664056740568405694057040571405724057340574405754057640577405784057940580405814058240583405844058540586405874058840589405904059140592405934059440595405964059740598405994060040601406024060340604406054060640607406084060940610406114061240613406144061540616406174061840619406204062140622406234062440625406264062740628406294063040631406324063340634406354063640637406384063940640406414064240643406444064540646406474064840649406504065140652406534065440655406564065740658406594066040661406624066340664406654066640667406684066940670406714067240673406744067540676406774067840679406804068140682406834068440685406864068740688406894069040691406924069340694406954069640697406984069940700407014070240703407044070540706407074070840709407104071140712407134071440715407164071740718407194072040721407224072340724407254072640727407284072940730407314073240733407344073540736407374073840739407404074140742407434074440745407464074740748407494075040751407524075340754407554075640757407584075940760407614076240763407644076540766407674076840769407704077140772407734077440775407764077740778407794078040781407824078340784407854078640787407884078940790407914079240793407944079540796407974079840799408004080140802408034080440805408064080740808408094081040811408124081340814408154081640817408184081940820408214082240823408244082540826408274082840829408304083140832408334083440835408364083740838408394084040841408424084340844408454084640847408484084940850408514085240853408544085540856408574085840859408604086140862408634086440865408664086740868408694087040871408724087340874408754087640877408784087940880408814088240883408844088540886408874088840889408904089140892408934089440895408964089740898408994090040901409024090340904409054090640907409084090940910409114091240913409144091540916409174091840919409204092140922409234092440925409264092740928409294093040931409324093340934409354093640937409384093940940409414094240943409444094540946409474094840949409504095140952409534095440955409564095740958409594096040961409624096340964409654096640967409684096940970409714097240973409744097540976409774097840979409804098140982409834098440985409864098740988409894099040991409924099340994409954099640997409984099941000410014100241003410044100541006410074100841009410104101141012410134101441015410164101741018410194102041021410224102341024410254102641027410284102941030410314103241033410344103541036410374103841039410404104141042410434104441045410464104741048410494105041051410524105341054410554105641057410584105941060410614106241063410644106541066410674106841069410704107141072410734107441075410764107741078410794108041081410824108341084410854108641087410884108941090410914109241093410944109541096410974109841099411004110141102411034110441105411064110741108411094111041111411124111341114411154111641117411184111941120411214112241123411244112541126411274112841129411304113141132411334113441135411364113741138411394114041141411424114341144411454114641147411484114941150411514115241153411544115541156411574115841159411604116141162411634116441165411664116741168411694117041171411724117341174411754117641177411784117941180411814118241183411844118541186411874118841189411904119141192411934119441195411964119741198411994120041201412024120341204412054120641207412084120941210412114121241213412144121541216412174121841219412204122141222412234122441225412264122741228412294123041231412324123341234412354123641237412384123941240412414124241243412444124541246412474124841249412504125141252412534125441255412564125741258412594126041261412624126341264412654126641267412684126941270412714127241273412744127541276412774127841279412804128141282412834128441285412864128741288412894129041291412924129341294412954129641297412984129941300413014130241303413044130541306413074130841309413104131141312413134131441315413164131741318413194132041321413224132341324413254132641327413284132941330413314133241333413344133541336413374133841339413404134141342413434134441345413464134741348413494135041351413524135341354413554135641357413584135941360413614136241363413644136541366413674136841369413704137141372413734137441375413764137741378413794138041381413824138341384413854138641387413884138941390413914139241393413944139541396413974139841399414004140141402414034140441405414064140741408414094141041411414124141341414414154141641417414184141941420414214142241423414244142541426414274142841429414304143141432414334143441435414364143741438414394144041441414424144341444414454144641447414484144941450414514145241453414544145541456414574145841459414604146141462414634146441465414664146741468414694147041471414724147341474414754147641477414784147941480414814148241483414844148541486414874148841489414904149141492414934149441495414964149741498414994150041501415024150341504415054150641507415084150941510415114151241513415144151541516415174151841519415204152141522415234152441525415264152741528415294153041531415324153341534415354153641537415384153941540415414154241543415444154541546415474154841549415504155141552415534155441555415564155741558415594156041561415624156341564415654156641567415684156941570415714157241573415744157541576415774157841579415804158141582415834158441585415864158741588415894159041591415924159341594415954159641597415984159941600416014160241603416044160541606416074160841609416104161141612416134161441615416164161741618416194162041621416224162341624416254162641627416284162941630416314163241633416344163541636416374163841639416404164141642416434164441645416464164741648416494165041651416524165341654416554165641657416584165941660416614166241663416644166541666416674166841669416704167141672416734167441675416764167741678416794168041681416824168341684416854168641687416884168941690416914169241693416944169541696416974169841699417004170141702417034170441705417064170741708417094171041711417124171341714417154171641717417184171941720417214172241723417244172541726417274172841729417304173141732417334173441735417364173741738417394174041741417424174341744417454174641747417484174941750417514175241753417544175541756417574175841759417604176141762417634176441765417664176741768417694177041771417724177341774417754177641777417784177941780417814178241783417844178541786417874178841789417904179141792417934179441795417964179741798417994180041801418024180341804418054180641807418084180941810418114181241813418144181541816418174181841819418204182141822418234182441825418264182741828418294183041831418324183341834418354183641837418384183941840418414184241843418444184541846418474184841849418504185141852418534185441855418564185741858418594186041861418624186341864418654186641867418684186941870418714187241873418744187541876418774187841879418804188141882418834188441885418864188741888418894189041891418924189341894418954189641897418984189941900419014190241903419044190541906419074190841909419104191141912419134191441915419164191741918419194192041921419224192341924419254192641927419284192941930419314193241933419344193541936419374193841939419404194141942419434194441945419464194741948419494195041951419524195341954419554195641957419584195941960419614196241963419644196541966419674196841969419704197141972419734197441975419764197741978419794198041981419824198341984419854198641987419884198941990419914199241993419944199541996419974199841999420004200142002420034200442005420064200742008420094201042011420124201342014420154201642017420184201942020420214202242023420244202542026420274202842029420304203142032420334203442035420364203742038420394204042041420424204342044420454204642047420484204942050420514205242053420544205542056420574205842059420604206142062420634206442065420664206742068420694207042071420724207342074420754207642077420784207942080420814208242083420844208542086420874208842089420904209142092420934209442095420964209742098420994210042101421024210342104421054210642107421084210942110421114211242113421144211542116421174211842119421204212142122421234212442125421264212742128421294213042131421324213342134421354213642137421384213942140421414214242143421444214542146421474214842149421504215142152421534215442155421564215742158421594216042161421624216342164421654216642167421684216942170421714217242173421744217542176421774217842179421804218142182421834218442185421864218742188421894219042191421924219342194421954219642197421984219942200422014220242203422044220542206422074220842209422104221142212422134221442215422164221742218422194222042221422224222342224422254222642227422284222942230422314223242233422344223542236422374223842239422404224142242422434224442245422464224742248422494225042251422524225342254422554225642257422584225942260422614226242263422644226542266422674226842269422704227142272422734227442275422764227742278422794228042281422824228342284422854228642287422884228942290422914229242293422944229542296422974229842299423004230142302423034230442305423064230742308423094231042311423124231342314423154231642317423184231942320423214232242323423244232542326423274232842329423304233142332423334233442335423364233742338423394234042341423424234342344423454234642347423484234942350423514235242353423544235542356423574235842359423604236142362423634236442365423664236742368423694237042371423724237342374423754237642377423784237942380423814238242383423844238542386423874238842389423904239142392423934239442395423964239742398423994240042401424024240342404424054240642407424084240942410424114241242413424144241542416424174241842419424204242142422424234242442425424264242742428424294243042431424324243342434424354243642437424384243942440424414244242443424444244542446424474244842449424504245142452424534245442455424564245742458424594246042461424624246342464424654246642467424684246942470424714247242473424744247542476424774247842479424804248142482424834248442485424864248742488424894249042491424924249342494424954249642497424984249942500425014250242503425044250542506425074250842509425104251142512425134251442515425164251742518425194252042521425224252342524425254252642527425284252942530425314253242533425344253542536425374253842539425404254142542425434254442545425464254742548425494255042551425524255342554425554255642557425584255942560425614256242563425644256542566425674256842569425704257142572425734257442575425764257742578425794258042581425824258342584425854258642587425884258942590425914259242593425944259542596425974259842599426004260142602426034260442605426064260742608426094261042611426124261342614426154261642617426184261942620426214262242623426244262542626426274262842629426304263142632426334263442635426364263742638426394264042641426424264342644426454264642647426484264942650426514265242653426544265542656426574265842659426604266142662426634266442665426664266742668426694267042671426724267342674426754267642677426784267942680426814268242683426844268542686426874268842689426904269142692426934269442695426964269742698426994270042701427024270342704427054270642707427084270942710427114271242713427144271542716427174271842719427204272142722427234272442725427264272742728427294273042731427324273342734427354273642737427384273942740427414274242743427444274542746427474274842749427504275142752427534275442755427564275742758427594276042761427624276342764427654276642767427684276942770427714277242773427744277542776427774277842779427804278142782427834278442785427864278742788427894279042791427924279342794427954279642797427984279942800428014280242803428044280542806428074280842809428104281142812428134281442815428164281742818428194282042821428224282342824428254282642827428284282942830428314283242833428344283542836428374283842839428404284142842428434284442845428464284742848428494285042851428524285342854428554285642857428584285942860428614286242863428644286542866428674286842869428704287142872428734287442875428764287742878428794288042881428824288342884428854288642887428884288942890428914289242893428944289542896428974289842899429004290142902429034290442905429064290742908429094291042911429124291342914429154291642917429184291942920429214292242923429244292542926429274292842929429304293142932429334293442935429364293742938429394294042941429424294342944429454294642947429484294942950429514295242953429544295542956429574295842959429604296142962429634296442965429664296742968429694297042971429724297342974429754297642977429784297942980429814298242983429844298542986429874298842989429904299142992429934299442995429964299742998429994300043001430024300343004430054300643007430084300943010430114301243013430144301543016430174301843019430204302143022430234302443025430264302743028430294303043031430324303343034430354303643037430384303943040430414304243043430444304543046430474304843049430504305143052430534305443055430564305743058430594306043061430624306343064430654306643067430684306943070430714307243073430744307543076430774307843079430804308143082430834308443085430864308743088430894309043091430924309343094430954309643097430984309943100431014310243103431044310543106431074310843109431104311143112431134311443115431164311743118431194312043121431224312343124431254312643127431284312943130431314313243133431344313543136431374313843139431404314143142431434314443145431464314743148431494315043151431524315343154431554315643157431584315943160431614316243163431644316543166431674316843169431704317143172431734317443175431764317743178431794318043181431824318343184431854318643187431884318943190431914319243193431944319543196431974319843199432004320143202432034320443205432064320743208432094321043211432124321343214432154321643217432184321943220432214322243223432244322543226432274322843229432304323143232432334323443235432364323743238432394324043241432424324343244432454324643247432484324943250432514325243253432544325543256432574325843259432604326143262432634326443265432664326743268432694327043271432724327343274432754327643277432784327943280432814328243283432844328543286432874328843289432904329143292432934329443295432964329743298432994330043301433024330343304433054330643307433084330943310433114331243313433144331543316433174331843319433204332143322433234332443325433264332743328433294333043331433324333343334433354333643337433384333943340433414334243343433444334543346433474334843349433504335143352433534335443355433564335743358433594336043361433624336343364433654336643367433684336943370433714337243373433744337543376433774337843379433804338143382433834338443385433864338743388433894339043391433924339343394433954339643397433984339943400434014340243403434044340543406434074340843409434104341143412434134341443415434164341743418434194342043421434224342343424434254342643427434284342943430434314343243433434344343543436434374343843439434404344143442434434344443445434464344743448434494345043451434524345343454434554345643457434584345943460434614346243463434644346543466434674346843469434704347143472434734347443475434764347743478434794348043481434824348343484434854348643487434884348943490434914349243493434944349543496434974349843499435004350143502435034350443505435064350743508435094351043511435124351343514435154351643517435184351943520435214352243523435244352543526435274352843529435304353143532435334353443535435364353743538435394354043541435424354343544435454354643547435484354943550435514355243553435544355543556435574355843559435604356143562435634356443565435664356743568435694357043571435724357343574435754357643577435784357943580435814358243583435844358543586435874358843589435904359143592435934359443595435964359743598435994360043601436024360343604436054360643607436084360943610436114361243613436144361543616436174361843619436204362143622436234362443625436264362743628436294363043631436324363343634436354363643637436384363943640436414364243643436444364543646436474364843649436504365143652436534365443655436564365743658436594366043661436624366343664436654366643667436684366943670436714367243673436744367543676436774367843679436804368143682436834368443685436864368743688436894369043691436924369343694436954369643697436984369943700437014370243703437044370543706437074370843709437104371143712437134371443715437164371743718437194372043721437224372343724437254372643727437284372943730437314373243733437344373543736437374373843739437404374143742437434374443745437464374743748437494375043751437524375343754437554375643757437584375943760437614376243763437644376543766437674376843769437704377143772437734377443775437764377743778437794378043781437824378343784437854378643787437884378943790437914379243793437944379543796437974379843799438004380143802438034380443805438064380743808438094381043811438124381343814438154381643817438184381943820438214382243823438244382543826438274382843829438304383143832438334383443835438364383743838438394384043841438424384343844438454384643847438484384943850438514385243853438544385543856438574385843859438604386143862438634386443865438664386743868438694387043871438724387343874438754387643877438784387943880438814388243883438844388543886438874388843889438904389143892438934389443895438964389743898438994390043901439024390343904439054390643907439084390943910439114391243913439144391543916439174391843919439204392143922439234392443925439264392743928439294393043931439324393343934439354393643937439384393943940439414394243943439444394543946439474394843949439504395143952439534395443955439564395743958439594396043961439624396343964439654396643967439684396943970439714397243973439744397543976439774397843979439804398143982439834398443985439864398743988439894399043991439924399343994439954399643997439984399944000440014400244003440044400544006440074400844009440104401144012440134401444015440164401744018440194402044021440224402344024440254402644027440284402944030440314403244033440344403544036440374403844039440404404144042440434404444045440464404744048440494405044051440524405344054440554405644057440584405944060440614406244063440644406544066440674406844069440704407144072440734407444075440764407744078440794408044081440824408344084440854408644087440884408944090440914409244093440944409544096440974409844099441004410144102441034410444105441064410744108441094411044111441124411344114441154411644117441184411944120441214412244123441244412544126441274412844129441304413144132441334413444135441364413744138441394414044141441424414344144441454414644147441484414944150441514415244153441544415544156441574415844159441604416144162441634416444165441664416744168441694417044171441724417344174441754417644177441784417944180441814418244183441844418544186441874418844189441904419144192441934419444195441964419744198441994420044201442024420344204442054420644207442084420944210442114421244213442144421544216442174421844219442204422144222442234422444225442264422744228442294423044231442324423344234442354423644237442384423944240442414424244243442444424544246442474424844249442504425144252442534425444255442564425744258442594426044261442624426344264442654426644267442684426944270442714427244273442744427544276442774427844279442804428144282442834428444285442864428744288442894429044291442924429344294442954429644297442984429944300443014430244303443044430544306443074430844309443104431144312443134431444315443164431744318443194432044321443224432344324443254432644327443284432944330443314433244333443344433544336443374433844339443404434144342443434434444345443464434744348443494435044351443524435344354443554435644357443584435944360443614436244363443644436544366443674436844369443704437144372443734437444375443764437744378443794438044381443824438344384443854438644387443884438944390443914439244393443944439544396443974439844399444004440144402444034440444405444064440744408444094441044411444124441344414444154441644417444184441944420444214442244423444244442544426444274442844429444304443144432444334443444435444364443744438444394444044441444424444344444444454444644447444484444944450444514445244453444544445544456444574445844459444604446144462444634446444465444664446744468444694447044471444724447344474444754447644477444784447944480444814448244483444844448544486444874448844489444904449144492444934449444495444964449744498444994450044501445024450344504445054450644507445084450944510445114451244513445144451544516445174451844519445204452144522445234452444525445264452744528445294453044531445324453344534445354453644537445384453944540445414454244543445444454544546445474454844549445504455144552445534455444555445564455744558445594456044561445624456344564445654456644567445684456944570445714457244573445744457544576445774457844579445804458144582445834458444585445864458744588445894459044591445924459344594445954459644597445984459944600446014460244603446044460544606446074460844609446104461144612446134461444615446164461744618446194462044621446224462344624446254462644627446284462944630446314463244633446344463544636446374463844639446404464144642446434464444645446464464744648446494465044651446524465344654446554465644657446584465944660446614466244663446644466544666446674466844669446704467144672446734467444675446764467744678446794468044681446824468344684446854468644687446884468944690446914469244693446944469544696446974469844699447004470144702447034470444705447064470744708447094471044711447124471344714447154471644717447184471944720447214472244723447244472544726447274472844729447304473144732447334473444735447364473744738447394474044741447424474344744447454474644747447484474944750447514475244753447544475544756447574475844759447604476144762447634476444765447664476744768447694477044771447724477344774447754477644777447784477944780447814478244783447844478544786447874478844789447904479144792447934479444795447964479744798447994480044801448024480344804448054480644807448084480944810448114481244813448144481544816448174481844819448204482144822448234482444825448264482744828448294483044831448324483344834448354483644837448384483944840448414484244843448444484544846448474484844849448504485144852448534485444855448564485744858448594486044861448624486344864448654486644867448684486944870448714487244873448744487544876448774487844879448804488144882448834488444885448864488744888448894489044891448924489344894448954489644897448984489944900449014490244903449044490544906449074490844909449104491144912449134491444915449164491744918449194492044921449224492344924449254492644927449284492944930449314493244933449344493544936449374493844939449404494144942449434494444945449464494744948449494495044951449524495344954449554495644957449584495944960449614496244963449644496544966449674496844969449704497144972449734497444975449764497744978449794498044981449824498344984449854498644987449884498944990449914499244993449944499544996449974499844999450004500145002450034500445005450064500745008450094501045011450124501345014450154501645017450184501945020450214502245023450244502545026450274502845029450304503145032450334503445035450364503745038450394504045041450424504345044450454504645047450484504945050450514505245053450544505545056450574505845059450604506145062450634506445065450664506745068450694507045071450724507345074450754507645077450784507945080450814508245083450844508545086450874508845089450904509145092450934509445095450964509745098450994510045101451024510345104451054510645107451084510945110451114511245113451144511545116451174511845119451204512145122451234512445125451264512745128451294513045131451324513345134451354513645137451384513945140451414514245143451444514545146451474514845149451504515145152451534515445155451564515745158451594516045161451624516345164451654516645167451684516945170451714517245173451744517545176451774517845179451804518145182451834518445185451864518745188451894519045191451924519345194451954519645197451984519945200452014520245203452044520545206452074520845209452104521145212452134521445215452164521745218452194522045221452224522345224452254522645227452284522945230452314523245233452344523545236452374523845239452404524145242452434524445245452464524745248452494525045251452524525345254452554525645257452584525945260452614526245263452644526545266452674526845269452704527145272452734527445275452764527745278452794528045281452824528345284452854528645287452884528945290452914529245293452944529545296452974529845299453004530145302453034530445305453064530745308453094531045311453124531345314453154531645317453184531945320453214532245323453244532545326453274532845329453304533145332453334533445335453364533745338453394534045341453424534345344453454534645347453484534945350453514535245353453544535545356453574535845359453604536145362453634536445365453664536745368453694537045371453724537345374453754537645377453784537945380453814538245383453844538545386453874538845389453904539145392453934539445395453964539745398453994540045401454024540345404454054540645407454084540945410454114541245413454144541545416454174541845419454204542145422454234542445425454264542745428454294543045431454324543345434454354543645437454384543945440454414544245443454444544545446454474544845449454504545145452454534545445455454564545745458454594546045461454624546345464454654546645467454684546945470454714547245473454744547545476454774547845479454804548145482454834548445485454864548745488454894549045491454924549345494454954549645497454984549945500455014550245503455044550545506455074550845509455104551145512455134551445515455164551745518455194552045521455224552345524455254552645527455284552945530455314553245533455344553545536455374553845539455404554145542455434554445545455464554745548455494555045551455524555345554455554555645557455584555945560455614556245563455644556545566455674556845569455704557145572455734557445575455764557745578455794558045581455824558345584455854558645587455884558945590455914559245593455944559545596455974559845599456004560145602456034560445605456064560745608456094561045611456124561345614456154561645617456184561945620456214562245623456244562545626456274562845629456304563145632456334563445635456364563745638456394564045641456424564345644456454564645647456484564945650456514565245653456544565545656456574565845659456604566145662456634566445665456664566745668456694567045671456724567345674456754567645677456784567945680456814568245683456844568545686456874568845689456904569145692456934569445695456964569745698456994570045701457024570345704457054570645707457084570945710457114571245713457144571545716457174571845719457204572145722457234572445725457264572745728457294573045731457324573345734457354573645737457384573945740457414574245743457444574545746457474574845749457504575145752457534575445755457564575745758457594576045761457624576345764457654576645767457684576945770457714577245773457744577545776457774577845779457804578145782457834578445785457864578745788457894579045791457924579345794457954579645797457984579945800458014580245803458044580545806458074580845809458104581145812458134581445815458164581745818458194582045821458224582345824458254582645827458284582945830458314583245833458344583545836458374583845839458404584145842458434584445845458464584745848458494585045851458524585345854458554585645857458584585945860458614586245863458644586545866458674586845869458704587145872458734587445875458764587745878458794588045881458824588345884458854588645887458884588945890458914589245893458944589545896458974589845899459004590145902459034590445905459064590745908459094591045911459124591345914459154591645917459184591945920459214592245923459244592545926459274592845929459304593145932459334593445935459364593745938459394594045941459424594345944459454594645947459484594945950459514595245953459544595545956459574595845959459604596145962459634596445965459664596745968459694597045971459724597345974459754597645977459784597945980459814598245983459844598545986459874598845989459904599145992459934599445995459964599745998459994600046001460024600346004460054600646007460084600946010460114601246013460144601546016460174601846019460204602146022460234602446025460264602746028460294603046031460324603346034460354603646037460384603946040460414604246043460444604546046460474604846049460504605146052460534605446055460564605746058460594606046061460624606346064460654606646067460684606946070460714607246073460744607546076460774607846079460804608146082460834608446085460864608746088460894609046091460924609346094460954609646097460984609946100461014610246103461044610546106461074610846109461104611146112461134611446115461164611746118461194612046121461224612346124461254612646127461284612946130461314613246133461344613546136461374613846139461404614146142461434614446145461464614746148461494615046151461524615346154461554615646157461584615946160461614616246163461644616546166461674616846169461704617146172461734617446175461764617746178461794618046181461824618346184461854618646187461884618946190461914619246193461944619546196461974619846199462004620146202462034620446205462064620746208462094621046211462124621346214462154621646217462184621946220462214622246223462244622546226462274622846229462304623146232462334623446235462364623746238462394624046241462424624346244462454624646247462484624946250462514625246253462544625546256462574625846259462604626146262462634626446265462664626746268462694627046271462724627346274462754627646277462784627946280462814628246283462844628546286462874628846289462904629146292462934629446295462964629746298462994630046301463024630346304463054630646307463084630946310463114631246313463144631546316463174631846319463204632146322463234632446325463264632746328463294633046331463324633346334463354633646337463384633946340463414634246343463444634546346463474634846349463504635146352463534635446355463564635746358463594636046361463624636346364463654636646367463684636946370463714637246373463744637546376463774637846379463804638146382463834638446385463864638746388463894639046391463924639346394463954639646397463984639946400464014640246403464044640546406464074640846409464104641146412464134641446415464164641746418464194642046421464224642346424464254642646427464284642946430464314643246433464344643546436464374643846439464404644146442464434644446445464464644746448464494645046451464524645346454464554645646457464584645946460464614646246463464644646546466464674646846469464704647146472464734647446475464764647746478464794648046481464824648346484464854648646487464884648946490464914649246493464944649546496464974649846499465004650146502465034650446505465064650746508465094651046511465124651346514465154651646517465184651946520465214652246523465244652546526465274652846529465304653146532465334653446535465364653746538465394654046541465424654346544465454654646547465484654946550465514655246553465544655546556465574655846559465604656146562465634656446565465664656746568465694657046571465724657346574465754657646577465784657946580465814658246583465844658546586465874658846589465904659146592465934659446595465964659746598465994660046601466024660346604466054660646607466084660946610466114661246613466144661546616466174661846619466204662146622466234662446625466264662746628466294663046631466324663346634466354663646637466384663946640466414664246643466444664546646466474664846649466504665146652466534665446655466564665746658466594666046661466624666346664466654666646667466684666946670466714667246673466744667546676466774667846679466804668146682466834668446685466864668746688466894669046691466924669346694466954669646697466984669946700467014670246703467044670546706467074670846709467104671146712467134671446715467164671746718467194672046721467224672346724467254672646727467284672946730467314673246733467344673546736467374673846739467404674146742467434674446745467464674746748467494675046751467524675346754467554675646757467584675946760467614676246763467644676546766467674676846769467704677146772467734677446775467764677746778467794678046781467824678346784467854678646787467884678946790467914679246793467944679546796467974679846799468004680146802468034680446805468064680746808468094681046811468124681346814468154681646817468184681946820468214682246823468244682546826468274682846829468304683146832468334683446835468364683746838468394684046841468424684346844468454684646847468484684946850468514685246853468544685546856468574685846859468604686146862468634686446865468664686746868468694687046871468724687346874468754687646877468784687946880468814688246883468844688546886468874688846889468904689146892468934689446895468964689746898468994690046901469024690346904469054690646907469084690946910469114691246913469144691546916469174691846919469204692146922469234692446925469264692746928469294693046931469324693346934469354693646937469384693946940469414694246943469444694546946469474694846949469504695146952469534695446955469564695746958469594696046961469624696346964469654696646967469684696946970469714697246973469744697546976469774697846979469804698146982469834698446985469864698746988469894699046991469924699346994469954699646997469984699947000470014700247003470044700547006470074700847009470104701147012470134701447015470164701747018470194702047021470224702347024470254702647027470284702947030470314703247033470344703547036470374703847039470404704147042470434704447045470464704747048470494705047051470524705347054470554705647057470584705947060470614706247063470644706547066470674706847069470704707147072470734707447075470764707747078470794708047081470824708347084470854708647087470884708947090470914709247093470944709547096470974709847099471004710147102471034710447105471064710747108471094711047111471124711347114471154711647117471184711947120471214712247123471244712547126471274712847129471304713147132471334713447135471364713747138471394714047141471424714347144471454714647147471484714947150471514715247153471544715547156471574715847159471604716147162471634716447165471664716747168471694717047171471724717347174471754717647177471784717947180471814718247183471844718547186471874718847189471904719147192471934719447195471964719747198471994720047201472024720347204472054720647207472084720947210472114721247213472144721547216472174721847219472204722147222472234722447225472264722747228472294723047231472324723347234472354723647237472384723947240472414724247243472444724547246472474724847249472504725147252472534725447255472564725747258472594726047261472624726347264472654726647267472684726947270472714727247273472744727547276472774727847279472804728147282472834728447285472864728747288472894729047291472924729347294472954729647297472984729947300473014730247303473044730547306473074730847309473104731147312473134731447315473164731747318473194732047321473224732347324473254732647327473284732947330473314733247333473344733547336473374733847339473404734147342473434734447345473464734747348473494735047351473524735347354473554735647357473584735947360473614736247363473644736547366473674736847369473704737147372473734737447375473764737747378473794738047381473824738347384473854738647387473884738947390473914739247393473944739547396473974739847399474004740147402474034740447405474064740747408474094741047411474124741347414474154741647417474184741947420474214742247423474244742547426474274742847429474304743147432474334743447435474364743747438474394744047441474424744347444474454744647447474484744947450474514745247453474544745547456474574745847459474604746147462474634746447465474664746747468474694747047471474724747347474474754747647477474784747947480474814748247483474844748547486474874748847489474904749147492474934749447495474964749747498474994750047501475024750347504475054750647507475084750947510475114751247513475144751547516475174751847519475204752147522475234752447525475264752747528475294753047531475324753347534475354753647537475384753947540475414754247543475444754547546475474754847549475504755147552475534755447555475564755747558475594756047561475624756347564475654756647567475684756947570475714757247573475744757547576475774757847579475804758147582475834758447585475864758747588475894759047591475924759347594475954759647597475984759947600476014760247603476044760547606476074760847609476104761147612476134761447615476164761747618476194762047621476224762347624476254762647627476284762947630476314763247633476344763547636476374763847639476404764147642476434764447645476464764747648476494765047651476524765347654476554765647657476584765947660476614766247663476644766547666476674766847669476704767147672476734767447675476764767747678476794768047681476824768347684476854768647687476884768947690476914769247693476944769547696476974769847699477004770147702477034770447705477064770747708477094771047711477124771347714477154771647717477184771947720477214772247723477244772547726477274772847729477304773147732477334773447735477364773747738477394774047741477424774347744477454774647747477484774947750477514775247753477544775547756477574775847759477604776147762477634776447765477664776747768477694777047771477724777347774477754777647777477784777947780477814778247783477844778547786477874778847789477904779147792477934779447795477964779747798477994780047801478024780347804478054780647807478084780947810478114781247813478144781547816478174781847819478204782147822478234782447825478264782747828478294783047831478324783347834478354783647837478384783947840478414784247843478444784547846478474784847849478504785147852478534785447855478564785747858478594786047861478624786347864478654786647867478684786947870478714787247873478744787547876478774787847879478804788147882478834788447885478864788747888478894789047891478924789347894478954789647897478984789947900479014790247903479044790547906479074790847909479104791147912479134791447915479164791747918479194792047921479224792347924479254792647927479284792947930479314793247933479344793547936479374793847939479404794147942479434794447945479464794747948479494795047951479524795347954479554795647957479584795947960479614796247963479644796547966479674796847969479704797147972479734797447975479764797747978479794798047981479824798347984479854798647987479884798947990479914799247993479944799547996479974799847999480004800148002480034800448005480064800748008480094801048011480124801348014480154801648017480184801948020480214802248023480244802548026480274802848029480304803148032480334803448035480364803748038480394804048041480424804348044480454804648047480484804948050480514805248053480544805548056480574805848059480604806148062480634806448065480664806748068480694807048071480724807348074480754807648077480784807948080480814808248083480844808548086480874808848089480904809148092480934809448095480964809748098480994810048101481024810348104481054810648107481084810948110481114811248113481144811548116481174811848119481204812148122481234812448125481264812748128481294813048131481324813348134481354813648137481384813948140481414814248143481444814548146481474814848149481504815148152481534815448155481564815748158481594816048161481624816348164481654816648167481684816948170481714817248173481744817548176481774817848179481804818148182481834818448185481864818748188481894819048191481924819348194481954819648197481984819948200482014820248203482044820548206482074820848209482104821148212482134821448215482164821748218482194822048221482224822348224482254822648227482284822948230482314823248233482344823548236482374823848239482404824148242482434824448245482464824748248482494825048251482524825348254482554825648257482584825948260482614826248263482644826548266482674826848269482704827148272482734827448275482764827748278482794828048281482824828348284482854828648287482884828948290482914829248293482944829548296482974829848299483004830148302483034830448305483064830748308483094831048311483124831348314483154831648317483184831948320483214832248323483244832548326483274832848329483304833148332483334833448335483364833748338483394834048341483424834348344483454834648347483484834948350483514835248353483544835548356483574835848359483604836148362483634836448365483664836748368483694837048371483724837348374483754837648377483784837948380483814838248383483844838548386483874838848389483904839148392483934839448395483964839748398483994840048401484024840348404484054840648407484084840948410484114841248413484144841548416484174841848419484204842148422484234842448425484264842748428484294843048431484324843348434484354843648437484384843948440484414844248443484444844548446484474844848449484504845148452484534845448455484564845748458484594846048461484624846348464484654846648467484684846948470484714847248473484744847548476484774847848479484804848148482484834848448485484864848748488484894849048491484924849348494484954849648497484984849948500485014850248503485044850548506485074850848509485104851148512485134851448515485164851748518485194852048521485224852348524485254852648527485284852948530485314853248533485344853548536485374853848539485404854148542485434854448545485464854748548485494855048551485524855348554485554855648557485584855948560485614856248563485644856548566485674856848569485704857148572485734857448575485764857748578485794858048581485824858348584485854858648587485884858948590485914859248593485944859548596485974859848599486004860148602486034860448605486064860748608486094861048611486124861348614486154861648617486184861948620486214862248623486244862548626486274862848629486304863148632486334863448635486364863748638486394864048641486424864348644486454864648647486484864948650486514865248653486544865548656486574865848659486604866148662486634866448665486664866748668486694867048671486724867348674486754867648677486784867948680486814868248683486844868548686486874868848689486904869148692486934869448695486964869748698486994870048701487024870348704487054870648707487084870948710487114871248713487144871548716487174871848719487204872148722487234872448725487264872748728487294873048731487324873348734487354873648737487384873948740487414874248743487444874548746487474874848749487504875148752487534875448755487564875748758487594876048761487624876348764487654876648767487684876948770487714877248773487744877548776487774877848779487804878148782487834878448785487864878748788487894879048791487924879348794487954879648797487984879948800488014880248803488044880548806488074880848809488104881148812488134881448815488164881748818488194882048821488224882348824488254882648827488284882948830488314883248833488344883548836488374883848839488404884148842488434884448845488464884748848488494885048851488524885348854488554885648857488584885948860488614886248863488644886548866488674886848869488704887148872488734887448875488764887748878488794888048881488824888348884488854888648887488884888948890488914889248893488944889548896488974889848899489004890148902489034890448905489064890748908489094891048911489124891348914489154891648917489184891948920489214892248923489244892548926489274892848929489304893148932489334893448935489364893748938489394894048941489424894348944489454894648947489484894948950489514895248953489544895548956489574895848959489604896148962489634896448965489664896748968489694897048971489724897348974489754897648977489784897948980489814898248983489844898548986489874898848989489904899148992489934899448995489964899748998489994900049001490024900349004490054900649007490084900949010490114901249013490144901549016490174901849019490204902149022490234902449025490264902749028490294903049031490324903349034490354903649037490384903949040490414904249043490444904549046490474904849049490504905149052490534905449055490564905749058490594906049061490624906349064490654906649067490684906949070490714907249073490744907549076490774907849079490804908149082490834908449085490864908749088490894909049091490924909349094490954909649097490984909949100491014910249103491044910549106491074910849109491104911149112491134911449115491164911749118491194912049121491224912349124491254912649127491284912949130491314913249133491344913549136491374913849139491404914149142491434914449145491464914749148491494915049151491524915349154491554915649157491584915949160491614916249163491644916549166491674916849169491704917149172491734917449175491764917749178491794918049181491824918349184491854918649187491884918949190491914919249193491944919549196491974919849199492004920149202492034920449205492064920749208492094921049211492124921349214492154921649217492184921949220492214922249223492244922549226492274922849229492304923149232492334923449235492364923749238492394924049241492424924349244492454924649247492484924949250492514925249253492544925549256492574925849259492604926149262492634926449265492664926749268492694927049271492724927349274492754927649277492784927949280492814928249283492844928549286492874928849289492904929149292492934929449295492964929749298492994930049301493024930349304493054930649307493084930949310493114931249313493144931549316493174931849319493204932149322493234932449325493264932749328493294933049331493324933349334493354933649337493384933949340493414934249343493444934549346493474934849349493504935149352493534935449355493564935749358493594936049361493624936349364493654936649367493684936949370493714937249373493744937549376493774937849379493804938149382493834938449385493864938749388493894939049391493924939349394493954939649397493984939949400494014940249403494044940549406494074940849409494104941149412494134941449415494164941749418494194942049421494224942349424494254942649427494284942949430494314943249433494344943549436494374943849439494404944149442494434944449445494464944749448494494945049451494524945349454494554945649457494584945949460494614946249463494644946549466494674946849469494704947149472494734947449475494764947749478494794948049481494824948349484494854948649487494884948949490494914949249493494944949549496494974949849499495004950149502495034950449505495064950749508495094951049511495124951349514495154951649517495184951949520495214952249523495244952549526495274952849529495304953149532495334953449535495364953749538495394954049541495424954349544495454954649547495484954949550495514955249553495544955549556495574955849559495604956149562495634956449565495664956749568495694957049571495724957349574495754957649577495784957949580495814958249583495844958549586495874958849589495904959149592495934959449595495964959749598495994960049601496024960349604496054960649607496084960949610496114961249613496144961549616496174961849619496204962149622496234962449625496264962749628496294963049631496324963349634496354963649637496384963949640496414964249643496444964549646496474964849649496504965149652496534965449655496564965749658496594966049661496624966349664496654966649667496684966949670496714967249673496744967549676496774967849679496804968149682496834968449685496864968749688496894969049691496924969349694496954969649697496984969949700497014970249703497044970549706497074970849709497104971149712497134971449715497164971749718497194972049721497224972349724497254972649727497284972949730497314973249733497344973549736497374973849739497404974149742497434974449745497464974749748497494975049751497524975349754497554975649757497584975949760497614976249763497644976549766497674976849769497704977149772497734977449775497764977749778497794978049781497824978349784497854978649787497884978949790497914979249793497944979549796497974979849799498004980149802498034980449805498064980749808498094981049811498124981349814498154981649817498184981949820498214982249823498244982549826498274982849829498304983149832498334983449835498364983749838498394984049841498424984349844498454984649847498484984949850498514985249853498544985549856498574985849859498604986149862498634986449865498664986749868498694987049871498724987349874498754987649877498784987949880498814988249883498844988549886498874988849889498904989149892498934989449895498964989749898498994990049901499024990349904499054990649907499084990949910499114991249913499144991549916499174991849919499204992149922499234992449925499264992749928499294993049931499324993349934499354993649937499384993949940499414994249943499444994549946499474994849949499504995149952499534995449955499564995749958499594996049961499624996349964499654996649967499684996949970499714997249973499744997549976499774997849979499804998149982499834998449985499864998749988499894999049991499924999349994499954999649997499984999950000500015000250003500045000550006500075000850009500105001150012500135001450015500165001750018500195002050021500225002350024500255002650027500285002950030500315003250033500345003550036500375003850039500405004150042500435004450045500465004750048500495005050051500525005350054500555005650057500585005950060500615006250063500645006550066500675006850069500705007150072500735007450075500765007750078500795008050081500825008350084500855008650087500885008950090500915009250093500945009550096500975009850099501005010150102501035010450105501065010750108501095011050111501125011350114501155011650117501185011950120501215012250123501245012550126501275012850129501305013150132501335013450135501365013750138501395014050141501425014350144501455014650147501485014950150501515015250153501545015550156501575015850159501605016150162501635016450165501665016750168501695017050171501725017350174501755017650177501785017950180501815018250183501845018550186501875018850189501905019150192501935019450195501965019750198501995020050201502025020350204502055020650207502085020950210502115021250213502145021550216502175021850219502205022150222502235022450225502265022750228502295023050231502325023350234502355023650237502385023950240502415024250243502445024550246502475024850249502505025150252502535025450255502565025750258502595026050261502625026350264502655026650267502685026950270502715027250273502745027550276502775027850279502805028150282502835028450285502865028750288502895029050291502925029350294502955029650297502985029950300503015030250303503045030550306503075030850309503105031150312503135031450315503165031750318503195032050321503225032350324503255032650327503285032950330503315033250333503345033550336503375033850339503405034150342503435034450345503465034750348503495035050351503525035350354503555035650357503585035950360503615036250363503645036550366503675036850369503705037150372503735037450375503765037750378503795038050381503825038350384503855038650387503885038950390503915039250393503945039550396503975039850399504005040150402504035040450405504065040750408504095041050411504125041350414504155041650417504185041950420504215042250423504245042550426504275042850429504305043150432504335043450435504365043750438504395044050441504425044350444504455044650447504485044950450504515045250453504545045550456504575045850459504605046150462504635046450465504665046750468504695047050471504725047350474504755047650477504785047950480504815048250483504845048550486504875048850489504905049150492504935049450495504965049750498504995050050501505025050350504505055050650507505085050950510505115051250513505145051550516505175051850519505205052150522505235052450525505265052750528505295053050531505325053350534505355053650537505385053950540505415054250543505445054550546505475054850549505505055150552505535055450555505565055750558505595056050561505625056350564505655056650567505685056950570505715057250573505745057550576505775057850579505805058150582505835058450585505865058750588505895059050591505925059350594505955059650597505985059950600506015060250603506045060550606506075060850609506105061150612506135061450615506165061750618506195062050621506225062350624506255062650627506285062950630506315063250633506345063550636506375063850639506405064150642506435064450645506465064750648506495065050651506525065350654506555065650657506585065950660506615066250663506645066550666506675066850669506705067150672506735067450675506765067750678506795068050681506825068350684506855068650687506885068950690506915069250693506945069550696506975069850699507005070150702507035070450705507065070750708507095071050711507125071350714507155071650717507185071950720507215072250723507245072550726507275072850729507305073150732507335073450735507365073750738507395074050741507425074350744507455074650747507485074950750507515075250753507545075550756507575075850759507605076150762507635076450765507665076750768507695077050771507725077350774507755077650777507785077950780507815078250783507845078550786507875078850789507905079150792507935079450795507965079750798507995080050801508025080350804508055080650807508085080950810508115081250813508145081550816508175081850819508205082150822508235082450825508265082750828508295083050831508325083350834508355083650837508385083950840508415084250843508445084550846508475084850849508505085150852508535085450855508565085750858508595086050861508625086350864508655086650867508685086950870508715087250873508745087550876508775087850879508805088150882508835088450885508865088750888508895089050891508925089350894508955089650897508985089950900509015090250903509045090550906509075090850909509105091150912509135091450915509165091750918509195092050921509225092350924509255092650927509285092950930509315093250933509345093550936509375093850939509405094150942509435094450945509465094750948509495095050951509525095350954509555095650957509585095950960509615096250963509645096550966509675096850969509705097150972509735097450975509765097750978509795098050981509825098350984509855098650987509885098950990509915099250993509945099550996509975099850999510005100151002510035100451005510065100751008510095101051011510125101351014510155101651017510185101951020510215102251023510245102551026510275102851029510305103151032510335103451035510365103751038510395104051041510425104351044510455104651047510485104951050510515105251053510545105551056510575105851059510605106151062510635106451065510665106751068510695107051071510725107351074510755107651077510785107951080510815108251083510845108551086510875108851089510905109151092510935109451095510965109751098510995110051101511025110351104511055110651107511085110951110511115111251113511145111551116511175111851119511205112151122511235112451125511265112751128511295113051131511325113351134511355113651137511385113951140511415114251143511445114551146511475114851149511505115151152511535115451155511565115751158511595116051161511625116351164511655116651167511685116951170511715117251173511745117551176511775117851179511805118151182511835118451185511865118751188511895119051191511925119351194511955119651197511985119951200512015120251203512045120551206512075120851209512105121151212512135121451215512165121751218512195122051221512225122351224512255122651227512285122951230512315123251233512345123551236512375123851239512405124151242512435124451245512465124751248512495125051251512525125351254512555125651257512585125951260512615126251263512645126551266512675126851269512705127151272512735127451275512765127751278512795128051281512825128351284512855128651287512885128951290512915129251293512945129551296512975129851299513005130151302513035130451305513065130751308513095131051311513125131351314513155131651317513185131951320513215132251323513245132551326513275132851329513305133151332513335133451335513365133751338513395134051341513425134351344513455134651347513485134951350513515135251353513545135551356513575135851359513605136151362513635136451365513665136751368513695137051371513725137351374513755137651377513785137951380513815138251383513845138551386513875138851389513905139151392513935139451395513965139751398513995140051401514025140351404514055140651407514085140951410514115141251413514145141551416514175141851419514205142151422514235142451425514265142751428514295143051431514325143351434514355143651437514385143951440514415144251443514445144551446514475144851449514505145151452514535145451455514565145751458514595146051461514625146351464514655146651467514685146951470514715147251473514745147551476514775147851479514805148151482514835148451485514865148751488514895149051491514925149351494514955149651497514985149951500515015150251503515045150551506515075150851509515105151151512515135151451515515165151751518515195152051521515225152351524515255152651527515285152951530515315153251533515345153551536515375153851539515405154151542515435154451545515465154751548515495155051551515525155351554515555155651557515585155951560515615156251563515645156551566515675156851569515705157151572515735157451575515765157751578515795158051581515825158351584515855158651587515885158951590515915159251593515945159551596515975159851599516005160151602516035160451605516065160751608516095161051611516125161351614516155161651617516185161951620516215162251623516245162551626516275162851629516305163151632516335163451635516365163751638516395164051641516425164351644516455164651647516485164951650516515165251653516545165551656516575165851659516605166151662516635166451665516665166751668516695167051671516725167351674516755167651677516785167951680516815168251683516845168551686516875168851689516905169151692516935169451695516965169751698516995170051701517025170351704517055170651707517085170951710517115171251713517145171551716517175171851719517205172151722517235172451725517265172751728517295173051731517325173351734517355173651737517385173951740517415174251743517445174551746517475174851749517505175151752517535175451755517565175751758517595176051761517625176351764517655176651767517685176951770517715177251773517745177551776517775177851779517805178151782517835178451785517865178751788517895179051791517925179351794517955179651797517985179951800518015180251803518045180551806518075180851809518105181151812518135181451815518165181751818518195182051821518225182351824518255182651827518285182951830518315183251833518345183551836518375183851839518405184151842518435184451845518465184751848518495185051851518525185351854518555185651857518585185951860518615186251863518645186551866518675186851869518705187151872518735187451875518765187751878518795188051881518825188351884518855188651887518885188951890518915189251893518945189551896518975189851899519005190151902519035190451905519065190751908519095191051911519125191351914519155191651917519185191951920519215192251923519245192551926519275192851929519305193151932519335193451935519365193751938519395194051941519425194351944519455194651947519485194951950519515195251953519545195551956519575195851959519605196151962519635196451965519665196751968519695197051971519725197351974519755197651977519785197951980519815198251983519845198551986519875198851989519905199151992519935199451995519965199751998519995200052001520025200352004520055200652007520085200952010520115201252013520145201552016520175201852019520205202152022520235202452025520265202752028520295203052031520325203352034520355203652037520385203952040520415204252043520445204552046520475204852049520505205152052520535205452055520565205752058520595206052061520625206352064520655206652067520685206952070520715207252073520745207552076520775207852079520805208152082520835208452085520865208752088520895209052091520925209352094520955209652097520985209952100521015210252103521045210552106521075210852109521105211152112521135211452115521165211752118521195212052121521225212352124521255212652127521285212952130521315213252133521345213552136521375213852139521405214152142521435214452145521465214752148521495215052151521525215352154521555215652157521585215952160521615216252163521645216552166521675216852169521705217152172521735217452175521765217752178521795218052181521825218352184521855218652187521885218952190521915219252193521945219552196521975219852199522005220152202522035220452205522065220752208522095221052211522125221352214522155221652217522185221952220522215222252223522245222552226522275222852229522305223152232522335223452235522365223752238522395224052241522425224352244522455224652247522485224952250522515225252253522545225552256522575225852259522605226152262522635226452265522665226752268522695227052271522725227352274522755227652277522785227952280522815228252283522845228552286522875228852289522905229152292522935229452295522965229752298522995230052301523025230352304523055230652307523085230952310523115231252313523145231552316523175231852319523205232152322523235232452325523265232752328523295233052331523325233352334523355233652337523385233952340523415234252343523445234552346523475234852349523505235152352523535235452355523565235752358523595236052361523625236352364523655236652367523685236952370523715237252373523745237552376523775237852379523805238152382523835238452385523865238752388523895239052391523925239352394523955239652397523985239952400524015240252403524045240552406524075240852409524105241152412524135241452415524165241752418524195242052421524225242352424524255242652427524285242952430524315243252433524345243552436524375243852439524405244152442524435244452445524465244752448524495245052451524525245352454524555245652457524585245952460524615246252463524645246552466524675246852469524705247152472524735247452475524765247752478524795248052481524825248352484524855248652487524885248952490524915249252493524945249552496524975249852499525005250152502525035250452505525065250752508525095251052511525125251352514525155251652517525185251952520525215252252523525245252552526525275252852529525305253152532525335253452535525365253752538525395254052541525425254352544525455254652547525485254952550525515255252553525545255552556525575255852559525605256152562525635256452565525665256752568525695257052571525725257352574525755257652577525785257952580525815258252583525845258552586525875258852589525905259152592525935259452595525965259752598525995260052601526025260352604526055260652607526085260952610526115261252613526145261552616526175261852619526205262152622526235262452625526265262752628526295263052631526325263352634526355263652637526385263952640526415264252643526445264552646526475264852649526505265152652526535265452655526565265752658526595266052661526625266352664526655266652667526685266952670526715267252673526745267552676526775267852679526805268152682526835268452685526865268752688526895269052691526925269352694526955269652697526985269952700527015270252703527045270552706527075270852709527105271152712527135271452715527165271752718527195272052721527225272352724527255272652727527285272952730527315273252733527345273552736527375273852739527405274152742527435274452745527465274752748527495275052751527525275352754527555275652757527585275952760527615276252763527645276552766527675276852769527705277152772527735277452775527765277752778527795278052781527825278352784527855278652787527885278952790527915279252793527945279552796527975279852799528005280152802528035280452805528065280752808528095281052811528125281352814528155281652817528185281952820528215282252823528245282552826528275282852829528305283152832528335283452835528365283752838528395284052841528425284352844528455284652847528485284952850528515285252853528545285552856528575285852859528605286152862528635286452865528665286752868528695287052871528725287352874528755287652877528785287952880528815288252883528845288552886528875288852889528905289152892528935289452895528965289752898528995290052901529025290352904529055290652907529085290952910529115291252913529145291552916529175291852919529205292152922529235292452925529265292752928529295293052931529325293352934529355293652937529385293952940529415294252943529445294552946529475294852949529505295152952529535295452955529565295752958529595296052961529625296352964529655296652967529685296952970529715297252973529745297552976529775297852979529805298152982529835298452985529865298752988529895299052991529925299352994529955299652997529985299953000530015300253003530045300553006530075300853009530105301153012530135301453015530165301753018530195302053021530225302353024530255302653027530285302953030530315303253033530345303553036530375303853039530405304153042530435304453045530465304753048530495305053051530525305353054530555305653057530585305953060530615306253063530645306553066530675306853069530705307153072530735307453075530765307753078530795308053081530825308353084530855308653087530885308953090530915309253093530945309553096530975309853099531005310153102531035310453105531065310753108531095311053111531125311353114531155311653117531185311953120531215312253123531245312553126531275312853129531305313153132531335313453135531365313753138531395314053141531425314353144531455314653147531485314953150531515315253153531545315553156531575315853159531605316153162531635316453165531665316753168531695317053171531725317353174531755317653177531785317953180531815318253183531845318553186531875318853189531905319153192531935319453195531965319753198531995320053201532025320353204532055320653207532085320953210532115321253213532145321553216532175321853219532205322153222532235322453225532265322753228532295323053231532325323353234532355323653237532385323953240532415324253243532445324553246532475324853249532505325153252532535325453255532565325753258532595326053261532625326353264532655326653267532685326953270532715327253273532745327553276532775327853279532805328153282532835328453285532865328753288532895329053291532925329353294532955329653297532985329953300533015330253303533045330553306533075330853309533105331153312533135331453315533165331753318533195332053321533225332353324533255332653327533285332953330533315333253333533345333553336533375333853339533405334153342533435334453345533465334753348533495335053351533525335353354533555335653357533585335953360533615336253363533645336553366533675336853369533705337153372533735337453375533765337753378533795338053381533825338353384533855338653387533885338953390533915339253393533945339553396533975339853399534005340153402534035340453405534065340753408534095341053411534125341353414534155341653417534185341953420534215342253423534245342553426534275342853429534305343153432534335343453435534365343753438534395344053441534425344353444534455344653447534485344953450534515345253453534545345553456534575345853459534605346153462534635346453465534665346753468534695347053471534725347353474534755347653477534785347953480534815348253483534845348553486534875348853489534905349153492534935349453495534965349753498534995350053501535025350353504535055350653507535085350953510535115351253513535145351553516535175351853519535205352153522535235352453525535265352753528535295353053531535325353353534535355353653537535385353953540535415354253543535445354553546535475354853549535505355153552535535355453555535565355753558535595356053561535625356353564535655356653567535685356953570535715357253573535745357553576535775357853579535805358153582535835358453585535865358753588535895359053591535925359353594535955359653597535985359953600536015360253603536045360553606536075360853609536105361153612536135361453615536165361753618536195362053621536225362353624536255362653627536285362953630536315363253633536345363553636536375363853639536405364153642536435364453645536465364753648536495365053651536525365353654536555365653657536585365953660536615366253663536645366553666536675366853669536705367153672536735367453675536765367753678536795368053681536825368353684536855368653687536885368953690536915369253693536945369553696536975369853699537005370153702537035370453705537065370753708537095371053711537125371353714537155371653717537185371953720537215372253723537245372553726537275372853729537305373153732537335373453735537365373753738537395374053741537425374353744537455374653747537485374953750537515375253753537545375553756537575375853759537605376153762537635376453765537665376753768537695377053771537725377353774537755377653777537785377953780537815378253783537845378553786537875378853789537905379153792537935379453795537965379753798537995380053801538025380353804538055380653807538085380953810538115381253813538145381553816538175381853819538205382153822538235382453825538265382753828538295383053831538325383353834538355383653837538385383953840538415384253843538445384553846538475384853849538505385153852538535385453855538565385753858538595386053861538625386353864538655386653867538685386953870538715387253873538745387553876538775387853879538805388153882538835388453885538865388753888538895389053891538925389353894538955389653897538985389953900539015390253903539045390553906539075390853909539105391153912539135391453915539165391753918539195392053921539225392353924539255392653927539285392953930539315393253933539345393553936539375393853939539405394153942539435394453945539465394753948539495395053951539525395353954539555395653957539585395953960539615396253963539645396553966539675396853969539705397153972539735397453975539765397753978539795398053981539825398353984539855398653987539885398953990539915399253993539945399553996539975399853999540005400154002540035400454005540065400754008540095401054011540125401354014540155401654017540185401954020540215402254023540245402554026540275402854029540305403154032540335403454035540365403754038540395404054041540425404354044540455404654047540485404954050540515405254053540545405554056540575405854059540605406154062540635406454065540665406754068540695407054071540725407354074540755407654077540785407954080540815408254083540845408554086540875408854089540905409154092540935409454095540965409754098540995410054101541025410354104541055410654107541085410954110541115411254113541145411554116541175411854119541205412154122541235412454125541265412754128541295413054131541325413354134541355413654137541385413954140541415414254143541445414554146541475414854149541505415154152541535415454155541565415754158541595416054161541625416354164541655416654167541685416954170541715417254173541745417554176541775417854179541805418154182541835418454185541865418754188541895419054191541925419354194541955419654197541985419954200542015420254203542045420554206542075420854209542105421154212542135421454215542165421754218542195422054221542225422354224542255422654227542285422954230542315423254233542345423554236542375423854239542405424154242542435424454245542465424754248542495425054251542525425354254542555425654257542585425954260542615426254263542645426554266542675426854269542705427154272542735427454275542765427754278542795428054281542825428354284542855428654287542885428954290542915429254293542945429554296542975429854299543005430154302543035430454305543065430754308543095431054311543125431354314543155431654317543185431954320543215432254323543245432554326543275432854329543305433154332543335433454335543365433754338543395434054341543425434354344543455434654347543485434954350543515435254353543545435554356543575435854359543605436154362543635436454365543665436754368543695437054371543725437354374543755437654377543785437954380543815438254383543845438554386543875438854389543905439154392543935439454395543965439754398543995440054401544025440354404544055440654407544085440954410544115441254413544145441554416544175441854419544205442154422544235442454425544265442754428544295443054431544325443354434544355443654437544385443954440544415444254443544445444554446544475444854449544505445154452544535445454455544565445754458544595446054461544625446354464544655446654467544685446954470544715447254473544745447554476544775447854479544805448154482544835448454485544865448754488544895449054491544925449354494544955449654497544985449954500545015450254503545045450554506545075450854509545105451154512545135451454515545165451754518545195452054521545225452354524545255452654527545285452954530545315453254533545345453554536545375453854539545405454154542545435454454545545465454754548545495455054551545525455354554545555455654557545585455954560545615456254563545645456554566545675456854569545705457154572545735457454575545765457754578545795458054581545825458354584545855458654587545885458954590545915459254593545945459554596545975459854599546005460154602546035460454605546065460754608546095461054611546125461354614546155461654617546185461954620546215462254623546245462554626546275462854629546305463154632546335463454635546365463754638546395464054641546425464354644546455464654647546485464954650546515465254653546545465554656546575465854659546605466154662546635466454665546665466754668546695467054671546725467354674546755467654677546785467954680546815468254683546845468554686546875468854689546905469154692546935469454695546965469754698546995470054701547025470354704547055470654707547085470954710547115471254713547145471554716547175471854719547205472154722547235472454725547265472754728547295473054731547325473354734547355473654737547385473954740547415474254743547445474554746547475474854749547505475154752547535475454755547565475754758547595476054761547625476354764547655476654767547685476954770547715477254773547745477554776547775477854779547805478154782547835478454785547865478754788547895479054791547925479354794547955479654797547985479954800548015480254803548045480554806548075480854809548105481154812548135481454815548165481754818548195482054821548225482354824548255482654827548285482954830548315483254833548345483554836548375483854839548405484154842548435484454845548465484754848548495485054851548525485354854548555485654857548585485954860548615486254863548645486554866548675486854869548705487154872548735487454875548765487754878548795488054881548825488354884548855488654887548885488954890548915489254893548945489554896548975489854899549005490154902549035490454905549065490754908549095491054911549125491354914549155491654917549185491954920549215492254923549245492554926549275492854929549305493154932549335493454935549365493754938549395494054941549425494354944549455494654947549485494954950549515495254953549545495554956549575495854959549605496154962549635496454965549665496754968549695497054971549725497354974549755497654977549785497954980549815498254983549845498554986549875498854989549905499154992549935499454995549965499754998549995500055001550025500355004550055500655007550085500955010550115501255013550145501555016550175501855019550205502155022550235502455025550265502755028550295503055031550325503355034550355503655037550385503955040550415504255043550445504555046550475504855049550505505155052550535505455055550565505755058550595506055061550625506355064550655506655067550685506955070550715507255073550745507555076550775507855079550805508155082550835508455085550865508755088550895509055091550925509355094550955509655097550985509955100551015510255103551045510555106551075510855109551105511155112551135511455115551165511755118551195512055121551225512355124551255512655127551285512955130551315513255133551345513555136551375513855139551405514155142551435514455145551465514755148551495515055151551525515355154551555515655157551585515955160551615516255163551645516555166551675516855169551705517155172551735517455175551765517755178551795518055181551825518355184551855518655187551885518955190551915519255193551945519555196551975519855199552005520155202552035520455205552065520755208552095521055211552125521355214552155521655217552185521955220552215522255223552245522555226552275522855229552305523155232552335523455235552365523755238552395524055241552425524355244552455524655247552485524955250552515525255253552545525555256552575525855259552605526155262552635526455265552665526755268552695527055271552725527355274552755527655277552785527955280552815528255283552845528555286552875528855289552905529155292552935529455295552965529755298552995530055301553025530355304553055530655307553085530955310553115531255313553145531555316553175531855319553205532155322553235532455325553265532755328553295533055331553325533355334553355533655337553385533955340553415534255343553445534555346553475534855349553505535155352553535535455355553565535755358553595536055361553625536355364553655536655367553685536955370553715537255373553745537555376553775537855379553805538155382553835538455385553865538755388553895539055391553925539355394553955539655397553985539955400554015540255403554045540555406554075540855409554105541155412554135541455415554165541755418554195542055421554225542355424554255542655427554285542955430554315543255433554345543555436554375543855439554405544155442554435544455445554465544755448554495545055451554525545355454554555545655457554585545955460554615546255463554645546555466554675546855469554705547155472554735547455475554765547755478554795548055481554825548355484554855548655487554885548955490554915549255493554945549555496554975549855499555005550155502555035550455505555065550755508555095551055511555125551355514555155551655517555185551955520555215552255523555245552555526555275552855529555305553155532555335553455535555365553755538555395554055541555425554355544555455554655547555485554955550555515555255553555545555555556555575555855559555605556155562555635556455565555665556755568555695557055571555725557355574555755557655577555785557955580555815558255583555845558555586555875558855589555905559155592555935559455595555965559755598555995560055601556025560355604556055560655607556085560955610556115561255613556145561555616556175561855619556205562155622556235562455625556265562755628556295563055631556325563355634556355563655637556385563955640556415564255643556445564555646556475564855649556505565155652556535565455655556565565755658556595566055661556625566355664556655566655667556685566955670556715567255673556745567555676556775567855679556805568155682556835568455685556865568755688556895569055691556925569355694556955569655697556985569955700557015570255703557045570555706557075570855709557105571155712557135571455715557165571755718557195572055721557225572355724557255572655727557285572955730557315573255733557345573555736557375573855739557405574155742557435574455745557465574755748557495575055751557525575355754557555575655757557585575955760557615576255763557645576555766557675576855769557705577155772557735577455775557765577755778557795578055781557825578355784557855578655787557885578955790557915579255793557945579555796557975579855799558005580155802558035580455805558065580755808558095581055811558125581355814558155581655817558185581955820558215582255823558245582555826558275582855829558305583155832558335583455835558365583755838558395584055841558425584355844558455584655847558485584955850558515585255853558545585555856558575585855859558605586155862558635586455865558665586755868558695587055871558725587355874558755587655877558785587955880558815588255883558845588555886558875588855889558905589155892558935589455895558965589755898558995590055901559025590355904559055590655907559085590955910559115591255913559145591555916559175591855919559205592155922559235592455925559265592755928559295593055931559325593355934559355593655937559385593955940559415594255943559445594555946559475594855949559505595155952559535595455955559565595755958559595596055961559625596355964559655596655967559685596955970559715597255973559745597555976559775597855979559805598155982559835598455985559865598755988559895599055991559925599355994559955599655997559985599956000560015600256003560045600556006560075600856009560105601156012560135601456015560165601756018560195602056021560225602356024560255602656027560285602956030560315603256033560345603556036560375603856039560405604156042560435604456045560465604756048560495605056051560525605356054560555605656057560585605956060560615606256063560645606556066560675606856069560705607156072560735607456075560765607756078560795608056081560825608356084560855608656087560885608956090560915609256093560945609556096560975609856099561005610156102561035610456105561065610756108561095611056111561125611356114561155611656117561185611956120561215612256123561245612556126561275612856129561305613156132561335613456135561365613756138561395614056141561425614356144561455614656147561485614956150561515615256153561545615556156561575615856159561605616156162561635616456165561665616756168561695617056171561725617356174561755617656177561785617956180561815618256183561845618556186561875618856189561905619156192561935619456195561965619756198561995620056201562025620356204562055620656207562085620956210562115621256213562145621556216562175621856219562205622156222562235622456225562265622756228562295623056231562325623356234562355623656237562385623956240562415624256243562445624556246562475624856249562505625156252562535625456255562565625756258562595626056261562625626356264562655626656267562685626956270562715627256273562745627556276562775627856279562805628156282562835628456285562865628756288562895629056291562925629356294562955629656297562985629956300563015630256303563045630556306563075630856309563105631156312563135631456315563165631756318563195632056321563225632356324563255632656327563285632956330563315633256333563345633556336563375633856339563405634156342563435634456345563465634756348563495635056351563525635356354563555635656357563585635956360563615636256363563645636556366563675636856369563705637156372563735637456375563765637756378563795638056381563825638356384563855638656387563885638956390563915639256393563945639556396563975639856399564005640156402564035640456405564065640756408564095641056411564125641356414564155641656417564185641956420564215642256423564245642556426564275642856429564305643156432564335643456435564365643756438564395644056441564425644356444564455644656447564485644956450564515645256453564545645556456564575645856459564605646156462564635646456465564665646756468564695647056471564725647356474564755647656477564785647956480564815648256483564845648556486564875648856489564905649156492564935649456495564965649756498564995650056501565025650356504565055650656507565085650956510565115651256513565145651556516565175651856519565205652156522565235652456525565265652756528565295653056531565325653356534565355653656537565385653956540565415654256543565445654556546565475654856549565505655156552565535655456555565565655756558565595656056561565625656356564565655656656567565685656956570565715657256573565745657556576565775657856579565805658156582565835658456585565865658756588565895659056591565925659356594565955659656597565985659956600566015660256603566045660556606566075660856609566105661156612566135661456615566165661756618566195662056621566225662356624566255662656627566285662956630566315663256633566345663556636566375663856639566405664156642566435664456645566465664756648566495665056651566525665356654566555665656657566585665956660566615666256663566645666556666566675666856669566705667156672566735667456675566765667756678566795668056681566825668356684566855668656687566885668956690566915669256693566945669556696566975669856699567005670156702567035670456705567065670756708567095671056711567125671356714567155671656717567185671956720567215672256723567245672556726567275672856729567305673156732567335673456735567365673756738567395674056741567425674356744567455674656747567485674956750567515675256753567545675556756567575675856759567605676156762567635676456765567665676756768567695677056771567725677356774567755677656777567785677956780567815678256783567845678556786567875678856789567905679156792567935679456795567965679756798567995680056801568025680356804568055680656807568085680956810568115681256813568145681556816568175681856819568205682156822568235682456825568265682756828568295683056831568325683356834568355683656837568385683956840568415684256843568445684556846568475684856849568505685156852568535685456855568565685756858568595686056861568625686356864568655686656867568685686956870568715687256873568745687556876568775687856879568805688156882568835688456885568865688756888568895689056891568925689356894568955689656897568985689956900569015690256903569045690556906569075690856909569105691156912569135691456915569165691756918569195692056921569225692356924569255692656927569285692956930569315693256933569345693556936569375693856939569405694156942569435694456945569465694756948569495695056951569525695356954569555695656957569585695956960569615696256963569645696556966569675696856969569705697156972569735697456975569765697756978569795698056981569825698356984569855698656987569885698956990569915699256993569945699556996569975699856999570005700157002570035700457005570065700757008570095701057011570125701357014570155701657017570185701957020570215702257023570245702557026570275702857029570305703157032570335703457035570365703757038570395704057041570425704357044570455704657047570485704957050570515705257053570545705557056570575705857059570605706157062570635706457065570665706757068570695707057071570725707357074570755707657077570785707957080570815708257083570845708557086570875708857089570905709157092570935709457095570965709757098570995710057101571025710357104571055710657107571085710957110571115711257113571145711557116571175711857119571205712157122571235712457125571265712757128571295713057131571325713357134571355713657137571385713957140571415714257143571445714557146571475714857149571505715157152571535715457155571565715757158571595716057161571625716357164571655716657167571685716957170571715717257173571745717557176571775717857179571805718157182571835718457185571865718757188571895719057191571925719357194571955719657197571985719957200572015720257203572045720557206572075720857209572105721157212572135721457215572165721757218572195722057221572225722357224572255722657227572285722957230572315723257233572345723557236572375723857239572405724157242572435724457245572465724757248572495725057251572525725357254572555725657257572585725957260572615726257263572645726557266572675726857269572705727157272572735727457275572765727757278572795728057281572825728357284572855728657287572885728957290572915729257293572945729557296572975729857299573005730157302573035730457305573065730757308573095731057311573125731357314573155731657317573185731957320573215732257323573245732557326573275732857329573305733157332573335733457335573365733757338573395734057341573425734357344573455734657347573485734957350573515735257353573545735557356573575735857359573605736157362573635736457365573665736757368573695737057371573725737357374573755737657377573785737957380573815738257383573845738557386573875738857389573905739157392573935739457395573965739757398573995740057401574025740357404574055740657407574085740957410574115741257413574145741557416574175741857419574205742157422574235742457425574265742757428574295743057431574325743357434574355743657437574385743957440574415744257443574445744557446574475744857449574505745157452574535745457455574565745757458574595746057461574625746357464574655746657467574685746957470574715747257473574745747557476574775747857479574805748157482574835748457485574865748757488574895749057491574925749357494574955749657497574985749957500575015750257503575045750557506575075750857509575105751157512575135751457515575165751757518575195752057521575225752357524575255752657527575285752957530575315753257533575345753557536575375753857539575405754157542575435754457545575465754757548575495755057551575525755357554575555755657557575585755957560575615756257563575645756557566575675756857569575705757157572575735757457575575765757757578575795758057581575825758357584575855758657587575885758957590575915759257593575945759557596575975759857599576005760157602576035760457605576065760757608576095761057611576125761357614576155761657617576185761957620576215762257623576245762557626576275762857629576305763157632576335763457635576365763757638576395764057641576425764357644576455764657647576485764957650576515765257653576545765557656576575765857659576605766157662576635766457665576665766757668576695767057671576725767357674576755767657677576785767957680576815768257683576845768557686576875768857689576905769157692576935769457695576965769757698576995770057701577025770357704577055770657707577085770957710577115771257713577145771557716577175771857719577205772157722577235772457725577265772757728577295773057731577325773357734577355773657737577385773957740577415774257743577445774557746577475774857749577505775157752577535775457755577565775757758577595776057761577625776357764577655776657767577685776957770577715777257773577745777557776577775777857779577805778157782577835778457785577865778757788577895779057791577925779357794577955779657797577985779957800578015780257803578045780557806578075780857809578105781157812578135781457815578165781757818578195782057821578225782357824578255782657827578285782957830578315783257833578345783557836578375783857839578405784157842578435784457845578465784757848578495785057851578525785357854578555785657857578585785957860578615786257863578645786557866578675786857869578705787157872578735787457875578765787757878578795788057881578825788357884578855788657887578885788957890578915789257893578945789557896578975789857899579005790157902579035790457905579065790757908579095791057911579125791357914579155791657917579185791957920579215792257923579245792557926579275792857929579305793157932579335793457935579365793757938579395794057941579425794357944579455794657947579485794957950579515795257953579545795557956579575795857959579605796157962579635796457965579665796757968579695797057971579725797357974579755797657977579785797957980579815798257983579845798557986579875798857989579905799157992579935799457995579965799757998579995800058001580025800358004580055800658007580085800958010580115801258013580145801558016580175801858019580205802158022580235802458025580265802758028580295803058031580325803358034580355803658037580385803958040580415804258043580445804558046580475804858049580505805158052580535805458055580565805758058580595806058061580625806358064580655806658067580685806958070580715807258073580745807558076580775807858079580805808158082580835808458085580865808758088580895809058091580925809358094580955809658097580985809958100581015810258103581045810558106581075810858109581105811158112581135811458115581165811758118581195812058121581225812358124581255812658127581285812958130581315813258133581345813558136581375813858139581405814158142581435814458145581465814758148581495815058151581525815358154581555815658157581585815958160581615816258163581645816558166581675816858169581705817158172581735817458175581765817758178581795818058181581825818358184581855818658187581885818958190581915819258193581945819558196581975819858199582005820158202582035820458205582065820758208582095821058211582125821358214582155821658217582185821958220582215822258223582245822558226582275822858229582305823158232582335823458235582365823758238582395824058241582425824358244582455824658247582485824958250582515825258253582545825558256582575825858259582605826158262582635826458265582665826758268582695827058271582725827358274582755827658277582785827958280582815828258283582845828558286582875828858289582905829158292582935829458295582965829758298582995830058301583025830358304583055830658307583085830958310583115831258313583145831558316583175831858319583205832158322583235832458325583265832758328583295833058331583325833358334583355833658337583385833958340583415834258343583445834558346583475834858349583505835158352583535835458355583565835758358583595836058361583625836358364583655836658367583685836958370583715837258373583745837558376583775837858379583805838158382583835838458385583865838758388583895839058391583925839358394583955839658397583985839958400584015840258403584045840558406584075840858409584105841158412584135841458415584165841758418584195842058421584225842358424584255842658427584285842958430584315843258433584345843558436584375843858439584405844158442584435844458445584465844758448584495845058451584525845358454584555845658457584585845958460584615846258463584645846558466584675846858469584705847158472584735847458475584765847758478584795848058481584825848358484584855848658487584885848958490584915849258493584945849558496584975849858499585005850158502585035850458505585065850758508585095851058511585125851358514585155851658517585185851958520585215852258523585245852558526585275852858529585305853158532585335853458535585365853758538585395854058541585425854358544585455854658547585485854958550585515855258553585545855558556585575855858559585605856158562585635856458565585665856758568585695857058571585725857358574585755857658577585785857958580585815858258583585845858558586585875858858589585905859158592585935859458595585965859758598585995860058601586025860358604586055860658607586085860958610586115861258613586145861558616586175861858619586205862158622586235862458625586265862758628586295863058631586325863358634586355863658637586385863958640586415864258643586445864558646586475864858649586505865158652586535865458655586565865758658586595866058661586625866358664586655866658667586685866958670586715867258673586745867558676586775867858679586805868158682586835868458685586865868758688586895869058691586925869358694586955869658697586985869958700587015870258703587045870558706587075870858709587105871158712587135871458715587165871758718587195872058721587225872358724587255872658727587285872958730587315873258733587345873558736587375873858739587405874158742587435874458745587465874758748587495875058751587525875358754587555875658757587585875958760587615876258763587645876558766587675876858769587705877158772587735877458775587765877758778587795878058781587825878358784587855878658787587885878958790587915879258793587945879558796587975879858799588005880158802588035880458805588065880758808588095881058811588125881358814588155881658817588185881958820588215882258823588245882558826588275882858829588305883158832588335883458835588365883758838588395884058841588425884358844588455884658847588485884958850588515885258853588545885558856588575885858859588605886158862588635886458865588665886758868588695887058871588725887358874588755887658877588785887958880588815888258883588845888558886588875888858889588905889158892588935889458895588965889758898588995890058901589025890358904589055890658907589085890958910589115891258913589145891558916589175891858919589205892158922589235892458925589265892758928589295893058931589325893358934589355893658937589385893958940589415894258943589445894558946589475894858949589505895158952589535895458955589565895758958589595896058961589625896358964589655896658967589685896958970589715897258973589745897558976589775897858979589805898158982589835898458985589865898758988589895899058991589925899358994589955899658997589985899959000590015900259003590045900559006590075900859009590105901159012590135901459015590165901759018590195902059021590225902359024590255902659027590285902959030590315903259033590345903559036590375903859039590405904159042590435904459045590465904759048590495905059051590525905359054590555905659057590585905959060590615906259063590645906559066590675906859069590705907159072590735907459075590765907759078590795908059081590825908359084590855908659087590885908959090590915909259093590945909559096590975909859099591005910159102591035910459105591065910759108591095911059111591125911359114591155911659117591185911959120591215912259123591245912559126591275912859129591305913159132591335913459135591365913759138591395914059141591425914359144591455914659147591485914959150591515915259153591545915559156591575915859159591605916159162591635916459165591665916759168591695917059171591725917359174591755917659177591785917959180591815918259183591845918559186591875918859189591905919159192591935919459195591965919759198591995920059201592025920359204592055920659207592085920959210592115921259213592145921559216592175921859219592205922159222592235922459225592265922759228592295923059231592325923359234592355923659237592385923959240592415924259243592445924559246592475924859249592505925159252592535925459255592565925759258592595926059261592625926359264592655926659267592685926959270592715927259273592745927559276592775927859279592805928159282592835928459285592865928759288592895929059291592925929359294592955929659297592985929959300593015930259303593045930559306593075930859309593105931159312593135931459315593165931759318593195932059321593225932359324593255932659327593285932959330593315933259333593345933559336593375933859339593405934159342593435934459345593465934759348593495935059351593525935359354593555935659357593585935959360593615936259363593645936559366593675936859369593705937159372593735937459375593765937759378593795938059381593825938359384593855938659387593885938959390593915939259393593945939559396593975939859399594005940159402594035940459405594065940759408594095941059411594125941359414594155941659417594185941959420594215942259423594245942559426594275942859429594305943159432594335943459435594365943759438594395944059441594425944359444594455944659447594485944959450594515945259453594545945559456594575945859459594605946159462594635946459465594665946759468594695947059471594725947359474594755947659477594785947959480594815948259483594845948559486594875948859489594905949159492594935949459495594965949759498594995950059501595025950359504595055950659507595085950959510595115951259513595145951559516595175951859519595205952159522595235952459525595265952759528595295953059531595325953359534595355953659537595385953959540595415954259543595445954559546595475954859549595505955159552595535955459555595565955759558595595956059561595625956359564595655956659567595685956959570595715957259573595745957559576595775957859579595805958159582595835958459585595865958759588595895959059591595925959359594595955959659597595985959959600596015960259603596045960559606596075960859609596105961159612596135961459615596165961759618596195962059621596225962359624596255962659627596285962959630596315963259633596345963559636596375963859639596405964159642596435964459645596465964759648596495965059651596525965359654596555965659657596585965959660596615966259663596645966559666596675966859669596705967159672596735967459675596765967759678596795968059681596825968359684596855968659687596885968959690596915969259693596945969559696596975969859699597005970159702597035970459705597065970759708597095971059711597125971359714597155971659717597185971959720597215972259723597245972559726597275972859729597305973159732597335973459735597365973759738597395974059741597425974359744597455974659747597485974959750597515975259753597545975559756597575975859759597605976159762597635976459765597665976759768597695977059771597725977359774597755977659777597785977959780597815978259783597845978559786597875978859789597905979159792597935979459795597965979759798597995980059801598025980359804598055980659807598085980959810598115981259813598145981559816598175981859819598205982159822598235982459825598265982759828598295983059831598325983359834598355983659837598385983959840598415984259843598445984559846598475984859849598505985159852598535985459855598565985759858598595986059861598625986359864598655986659867598685986959870598715987259873598745987559876598775987859879598805988159882598835988459885598865988759888598895989059891598925989359894598955989659897598985989959900599015990259903599045990559906599075990859909599105991159912599135991459915599165991759918599195992059921599225992359924599255992659927599285992959930599315993259933599345993559936599375993859939599405994159942599435994459945599465994759948599495995059951599525995359954599555995659957599585995959960599615996259963599645996559966599675996859969599705997159972599735997459975599765997759978599795998059981599825998359984599855998659987599885998959990599915999259993599945999559996599975999859999600006000160002600036000460005600066000760008600096001060011600126001360014600156001660017600186001960020600216002260023600246002560026600276002860029600306003160032600336003460035600366003760038600396004060041600426004360044600456004660047600486004960050600516005260053600546005560056600576005860059600606006160062600636006460065600666006760068600696007060071600726007360074600756007660077600786007960080600816008260083600846008560086600876008860089600906009160092600936009460095600966009760098600996010060101601026010360104601056010660107601086010960110601116011260113601146011560116601176011860119601206012160122601236012460125601266012760128601296013060131601326013360134601356013660137601386013960140601416014260143601446014560146601476014860149601506015160152601536015460155601566015760158601596016060161601626016360164601656016660167601686016960170601716017260173601746017560176601776017860179601806018160182601836018460185601866018760188601896019060191601926019360194601956019660197601986019960200602016020260203602046020560206602076020860209602106021160212602136021460215602166021760218602196022060221602226022360224602256022660227602286022960230602316023260233602346023560236602376023860239602406024160242602436024460245602466024760248602496025060251602526025360254602556025660257602586025960260602616026260263602646026560266602676026860269602706027160272602736027460275602766027760278602796028060281602826028360284602856028660287602886028960290602916029260293602946029560296602976029860299603006030160302603036030460305603066030760308603096031060311603126031360314603156031660317603186031960320603216032260323603246032560326603276032860329603306033160332603336033460335603366033760338603396034060341603426034360344603456034660347603486034960350603516035260353603546035560356603576035860359603606036160362603636036460365603666036760368603696037060371603726037360374603756037660377603786037960380603816038260383603846038560386603876038860389603906039160392603936039460395603966039760398603996040060401604026040360404604056040660407604086040960410604116041260413604146041560416604176041860419604206042160422604236042460425604266042760428604296043060431604326043360434604356043660437604386043960440604416044260443604446044560446604476044860449604506045160452604536045460455604566045760458604596046060461604626046360464604656046660467604686046960470604716047260473604746047560476604776047860479604806048160482604836048460485604866048760488604896049060491604926049360494604956049660497604986049960500605016050260503605046050560506605076050860509605106051160512605136051460515605166051760518605196052060521605226052360524605256052660527605286052960530605316053260533605346053560536605376053860539605406054160542605436054460545605466054760548605496055060551605526055360554605556055660557605586055960560605616056260563605646056560566605676056860569605706057160572605736057460575605766057760578605796058060581605826058360584605856058660587605886058960590605916059260593605946059560596605976059860599606006060160602606036060460605606066060760608606096061060611606126061360614606156061660617606186061960620606216062260623606246062560626606276062860629606306063160632606336063460635606366063760638606396064060641606426064360644606456064660647606486064960650606516065260653606546065560656606576065860659606606066160662606636066460665606666066760668606696067060671606726067360674606756067660677606786067960680606816068260683606846068560686606876068860689606906069160692606936069460695606966069760698606996070060701607026070360704607056070660707607086070960710607116071260713607146071560716607176071860719607206072160722607236072460725607266072760728607296073060731607326073360734607356073660737607386073960740607416074260743607446074560746607476074860749607506075160752607536075460755607566075760758607596076060761607626076360764607656076660767607686076960770607716077260773607746077560776607776077860779607806078160782607836078460785607866078760788607896079060791607926079360794607956079660797607986079960800608016080260803608046080560806608076080860809608106081160812608136081460815608166081760818608196082060821608226082360824608256082660827608286082960830608316083260833608346083560836608376083860839608406084160842608436084460845608466084760848608496085060851608526085360854608556085660857608586085960860608616086260863608646086560866608676086860869608706087160872608736087460875608766087760878608796088060881608826088360884608856088660887608886088960890608916089260893608946089560896608976089860899609006090160902609036090460905609066090760908609096091060911609126091360914609156091660917609186091960920609216092260923609246092560926609276092860929609306093160932609336093460935609366093760938609396094060941609426094360944609456094660947609486094960950609516095260953609546095560956609576095860959609606096160962609636096460965609666096760968609696097060971609726097360974609756097660977609786097960980609816098260983609846098560986609876098860989609906099160992609936099460995609966099760998609996100061001610026100361004610056100661007610086100961010610116101261013610146101561016610176101861019610206102161022610236102461025610266102761028610296103061031610326103361034610356103661037610386103961040610416104261043610446104561046610476104861049610506105161052610536105461055610566105761058610596106061061610626106361064610656106661067610686106961070610716107261073610746107561076610776107861079610806108161082610836108461085610866108761088610896109061091610926109361094610956109661097610986109961100611016110261103611046110561106611076110861109611106111161112611136111461115611166111761118611196112061121611226112361124611256112661127611286112961130611316113261133611346113561136611376113861139611406114161142611436114461145611466114761148611496115061151611526115361154611556115661157611586115961160611616116261163611646116561166611676116861169611706117161172611736117461175611766117761178611796118061181611826118361184611856118661187611886118961190611916119261193611946119561196611976119861199612006120161202612036120461205612066120761208612096121061211612126121361214612156121661217612186121961220612216122261223612246122561226612276122861229612306123161232612336123461235612366123761238612396124061241612426124361244612456124661247612486124961250612516125261253612546125561256612576125861259612606126161262612636126461265612666126761268612696127061271612726127361274612756127661277612786127961280612816128261283612846128561286612876128861289612906129161292612936129461295612966129761298612996130061301613026130361304613056130661307613086130961310613116131261313613146131561316613176131861319613206132161322613236132461325613266132761328613296133061331613326133361334613356133661337613386133961340613416134261343613446134561346613476134861349613506135161352613536135461355613566135761358613596136061361613626136361364613656136661367613686136961370613716137261373613746137561376613776137861379613806138161382613836138461385613866138761388613896139061391613926139361394613956139661397613986139961400614016140261403614046140561406614076140861409614106141161412614136141461415614166141761418614196142061421614226142361424614256142661427614286142961430614316143261433614346143561436614376143861439614406144161442614436144461445614466144761448614496145061451614526145361454614556145661457614586145961460614616146261463614646146561466614676146861469614706147161472614736147461475614766147761478614796148061481614826148361484614856148661487614886148961490614916149261493614946149561496614976149861499615006150161502615036150461505615066150761508615096151061511615126151361514615156151661517615186151961520615216152261523615246152561526615276152861529615306153161532615336153461535615366153761538615396154061541615426154361544615456154661547615486154961550615516155261553615546155561556615576155861559615606156161562615636156461565615666156761568615696157061571615726157361574615756157661577615786157961580615816158261583615846158561586615876158861589615906159161592615936159461595615966159761598615996160061601616026160361604616056160661607616086160961610616116161261613616146161561616616176161861619616206162161622616236162461625616266162761628616296163061631616326163361634616356163661637616386163961640616416164261643616446164561646616476164861649616506165161652616536165461655616566165761658616596166061661616626166361664616656166661667616686166961670616716167261673616746167561676616776167861679616806168161682616836168461685616866168761688616896169061691616926169361694616956169661697616986169961700617016170261703617046170561706617076170861709617106171161712617136171461715617166171761718617196172061721617226172361724617256172661727617286172961730617316173261733617346173561736617376173861739617406174161742617436174461745617466174761748617496175061751617526175361754617556175661757617586175961760617616176261763617646176561766617676176861769617706177161772617736177461775617766177761778617796178061781617826178361784617856178661787617886178961790617916179261793617946179561796617976179861799618006180161802618036180461805618066180761808618096181061811618126181361814618156181661817618186181961820618216182261823618246182561826618276182861829618306183161832618336183461835618366183761838618396184061841618426184361844618456184661847618486184961850618516185261853618546185561856618576185861859618606186161862618636186461865618666186761868618696187061871618726187361874618756187661877618786187961880618816188261883618846188561886618876188861889618906189161892618936189461895618966189761898618996190061901619026190361904619056190661907619086190961910619116191261913619146191561916619176191861919619206192161922619236192461925619266192761928619296193061931619326193361934619356193661937619386193961940619416194261943619446194561946619476194861949619506195161952619536195461955619566195761958619596196061961619626196361964619656196661967619686196961970619716197261973619746197561976619776197861979619806198161982619836198461985619866198761988619896199061991619926199361994619956199661997619986199962000620016200262003620046200562006620076200862009620106201162012620136201462015620166201762018620196202062021620226202362024620256202662027620286202962030620316203262033620346203562036620376203862039620406204162042620436204462045620466204762048620496205062051620526205362054620556205662057620586205962060620616206262063620646206562066620676206862069620706207162072620736207462075620766207762078620796208062081620826208362084620856208662087620886208962090620916209262093620946209562096620976209862099621006210162102621036210462105621066210762108621096211062111621126211362114621156211662117621186211962120621216212262123621246212562126621276212862129621306213162132621336213462135621366213762138621396214062141621426214362144621456214662147621486214962150621516215262153621546215562156621576215862159621606216162162621636216462165621666216762168621696217062171621726217362174621756217662177621786217962180621816218262183621846218562186621876218862189621906219162192621936219462195621966219762198621996220062201622026220362204622056220662207622086220962210622116221262213622146221562216622176221862219622206222162222622236222462225622266222762228622296223062231622326223362234622356223662237622386223962240622416224262243622446224562246622476224862249622506225162252622536225462255622566225762258622596226062261622626226362264622656226662267622686226962270622716227262273622746227562276622776227862279622806228162282622836228462285622866228762288622896229062291622926229362294622956229662297622986229962300623016230262303623046230562306623076230862309623106231162312623136231462315623166231762318623196232062321623226232362324623256232662327623286232962330623316233262333623346233562336623376233862339623406234162342623436234462345623466234762348623496235062351623526235362354623556235662357623586235962360623616236262363623646236562366623676236862369623706237162372623736237462375623766237762378623796238062381623826238362384623856238662387623886238962390623916239262393623946239562396623976239862399624006240162402624036240462405624066240762408624096241062411624126241362414624156241662417624186241962420624216242262423624246242562426624276242862429624306243162432624336243462435624366243762438624396244062441624426244362444624456244662447624486244962450624516245262453624546245562456624576245862459624606246162462624636246462465624666246762468624696247062471624726247362474624756247662477624786247962480624816248262483624846248562486624876248862489624906249162492624936249462495624966249762498624996250062501625026250362504625056250662507625086250962510625116251262513625146251562516625176251862519625206252162522625236252462525625266252762528625296253062531625326253362534625356253662537625386253962540625416254262543625446254562546625476254862549625506255162552625536255462555625566255762558625596256062561625626256362564625656256662567625686256962570625716257262573625746257562576625776257862579625806258162582625836258462585625866258762588625896259062591625926259362594625956259662597625986259962600626016260262603626046260562606626076260862609626106261162612626136261462615626166261762618626196262062621626226262362624626256262662627626286262962630626316263262633626346263562636626376263862639626406264162642626436264462645626466264762648626496265062651626526265362654626556265662657626586265962660626616266262663626646266562666626676266862669626706267162672626736267462675626766267762678626796268062681626826268362684626856268662687626886268962690626916269262693626946269562696626976269862699627006270162702627036270462705627066270762708627096271062711627126271362714627156271662717627186271962720627216272262723627246272562726627276272862729627306273162732627336273462735627366273762738627396274062741627426274362744627456274662747627486274962750627516275262753627546275562756627576275862759627606276162762627636276462765627666276762768627696277062771627726277362774627756277662777627786277962780627816278262783627846278562786627876278862789627906279162792627936279462795627966279762798627996280062801628026280362804628056280662807628086280962810628116281262813628146281562816628176281862819628206282162822628236282462825628266282762828628296283062831628326283362834628356283662837628386283962840628416284262843628446284562846628476284862849628506285162852628536285462855628566285762858628596286062861628626286362864628656286662867628686286962870628716287262873628746287562876628776287862879628806288162882628836288462885628866288762888628896289062891628926289362894628956289662897628986289962900629016290262903629046290562906629076290862909629106291162912629136291462915629166291762918629196292062921629226292362924629256292662927629286292962930629316293262933629346293562936629376293862939629406294162942629436294462945629466294762948629496295062951629526295362954629556295662957629586295962960629616296262963629646296562966629676296862969629706297162972629736297462975629766297762978629796298062981629826298362984629856298662987629886298962990629916299262993629946299562996629976299862999630006300163002630036300463005630066300763008630096301063011630126301363014630156301663017630186301963020630216302263023630246302563026630276302863029630306303163032630336303463035630366303763038630396304063041630426304363044630456304663047630486304963050630516305263053630546305563056630576305863059630606306163062630636306463065630666306763068630696307063071630726307363074630756307663077630786307963080630816308263083630846308563086630876308863089630906309163092630936309463095630966309763098630996310063101631026310363104631056310663107631086310963110631116311263113631146311563116631176311863119631206312163122631236312463125631266312763128631296313063131631326313363134631356313663137631386313963140631416314263143631446314563146631476314863149631506315163152631536315463155631566315763158631596316063161631626316363164631656316663167631686316963170631716317263173631746317563176631776317863179631806318163182631836318463185631866318763188631896319063191631926319363194631956319663197631986319963200632016320263203632046320563206632076320863209632106321163212632136321463215632166321763218632196322063221632226322363224632256322663227632286322963230632316323263233632346323563236632376323863239632406324163242632436324463245632466324763248632496325063251632526325363254632556325663257632586325963260632616326263263632646326563266632676326863269632706327163272632736327463275632766327763278632796328063281632826328363284632856328663287632886328963290632916329263293632946329563296632976329863299633006330163302633036330463305633066330763308633096331063311633126331363314633156331663317633186331963320633216332263323633246332563326633276332863329633306333163332633336333463335633366333763338633396334063341633426334363344633456334663347633486334963350633516335263353633546335563356633576335863359633606336163362633636336463365633666336763368633696337063371633726337363374633756337663377633786337963380633816338263383633846338563386633876338863389633906339163392633936339463395633966339763398633996340063401634026340363404634056340663407634086340963410634116341263413634146341563416634176341863419634206342163422634236342463425634266342763428634296343063431634326343363434634356343663437634386343963440634416344263443634446344563446634476344863449634506345163452634536345463455634566345763458634596346063461634626346363464634656346663467634686346963470634716347263473634746347563476634776347863479634806348163482634836348463485634866348763488634896349063491634926349363494634956349663497634986349963500635016350263503635046350563506635076350863509635106351163512635136351463515635166351763518635196352063521635226352363524635256352663527635286352963530635316353263533635346353563536635376353863539635406354163542635436354463545635466354763548635496355063551635526355363554635556355663557635586355963560635616356263563635646356563566635676356863569635706357163572635736357463575635766357763578635796358063581635826358363584635856358663587635886358963590635916359263593635946359563596635976359863599636006360163602636036360463605636066360763608636096361063611636126361363614636156361663617636186361963620636216362263623636246362563626636276362863629636306363163632636336363463635636366363763638636396364063641636426364363644636456364663647636486364963650636516365263653636546365563656636576365863659636606366163662636636366463665636666366763668636696367063671636726367363674636756367663677636786367963680636816368263683636846368563686636876368863689636906369163692636936369463695636966369763698636996370063701637026370363704637056370663707637086370963710637116371263713637146371563716637176371863719637206372163722637236372463725637266372763728637296373063731637326373363734637356373663737637386373963740637416374263743637446374563746637476374863749637506375163752637536375463755637566375763758637596376063761637626376363764637656376663767637686376963770637716377263773637746377563776637776377863779637806378163782637836378463785637866378763788637896379063791637926379363794637956379663797637986379963800638016380263803638046380563806638076380863809638106381163812638136381463815638166381763818638196382063821638226382363824638256382663827638286382963830638316383263833638346383563836638376383863839638406384163842638436384463845638466384763848638496385063851638526385363854638556385663857638586385963860638616386263863638646386563866638676386863869638706387163872638736387463875638766387763878638796388063881638826388363884638856388663887638886388963890638916389263893638946389563896638976389863899639006390163902639036390463905639066390763908639096391063911639126391363914639156391663917639186391963920639216392263923639246392563926639276392863929639306393163932639336393463935639366393763938639396394063941639426394363944639456394663947639486394963950639516395263953639546395563956639576395863959639606396163962639636396463965639666396763968639696397063971639726397363974639756397663977639786397963980639816398263983639846398563986639876398863989639906399163992639936399463995639966399763998639996400064001640026400364004640056400664007640086400964010640116401264013640146401564016640176401864019640206402164022640236402464025640266402764028640296403064031640326403364034640356403664037640386403964040640416404264043640446404564046640476404864049640506405164052640536405464055640566405764058640596406064061640626406364064640656406664067640686406964070640716407264073640746407564076640776407864079640806408164082640836408464085640866408764088640896409064091640926409364094640956409664097640986409964100641016410264103641046410564106641076410864109641106411164112641136411464115641166411764118641196412064121641226412364124641256412664127641286412964130641316413264133641346413564136641376413864139641406414164142641436414464145641466414764148641496415064151641526415364154641556415664157641586415964160641616416264163641646416564166641676416864169641706417164172641736417464175641766417764178641796418064181641826418364184641856418664187641886418964190641916419264193641946419564196641976419864199642006420164202642036420464205642066420764208642096421064211642126421364214642156421664217642186421964220642216422264223642246422564226642276422864229642306423164232642336423464235642366423764238642396424064241642426424364244642456424664247642486424964250642516425264253642546425564256642576425864259642606426164262642636426464265642666426764268642696427064271642726427364274642756427664277642786427964280642816428264283642846428564286642876428864289642906429164292642936429464295642966429764298642996430064301643026430364304643056430664307643086430964310643116431264313643146431564316643176431864319643206432164322643236432464325643266432764328643296433064331643326433364334643356433664337643386433964340643416434264343643446434564346643476434864349643506435164352643536435464355643566435764358643596436064361643626436364364643656436664367643686436964370643716437264373643746437564376643776437864379643806438164382643836438464385643866438764388643896439064391643926439364394643956439664397643986439964400644016440264403644046440564406644076440864409644106441164412644136441464415644166441764418644196442064421644226442364424644256442664427644286442964430644316443264433644346443564436644376443864439644406444164442644436444464445644466444764448644496445064451644526445364454644556445664457644586445964460644616446264463644646446564466644676446864469644706447164472644736447464475644766447764478644796448064481644826448364484644856448664487644886448964490644916449264493644946449564496644976449864499645006450164502645036450464505645066450764508645096451064511645126451364514645156451664517645186451964520645216452264523645246452564526645276452864529645306453164532645336453464535645366453764538645396454064541645426454364544645456454664547645486454964550645516455264553645546455564556645576455864559645606456164562645636456464565645666456764568645696457064571645726457364574645756457664577645786457964580645816458264583645846458564586645876458864589645906459164592645936459464595645966459764598645996460064601646026460364604646056460664607646086460964610646116461264613646146461564616646176461864619646206462164622646236462464625646266462764628646296463064631646326463364634646356463664637646386463964640646416464264643646446464564646646476464864649646506465164652646536465464655646566465764658646596466064661646626466364664646656466664667646686466964670646716467264673646746467564676646776467864679646806468164682646836468464685646866468764688646896469064691646926469364694646956469664697646986469964700647016470264703647046470564706647076470864709647106471164712647136471464715647166471764718647196472064721647226472364724647256472664727647286472964730647316473264733647346473564736647376473864739647406474164742647436474464745647466474764748647496475064751647526475364754647556475664757647586475964760647616476264763647646476564766647676476864769647706477164772647736477464775647766477764778647796478064781647826478364784647856478664787647886478964790647916479264793647946479564796647976479864799648006480164802648036480464805648066480764808648096481064811648126481364814648156481664817648186481964820648216482264823648246482564826648276482864829648306483164832648336483464835648366483764838648396484064841648426484364844648456484664847648486484964850648516485264853648546485564856648576485864859648606486164862648636486464865648666486764868648696487064871648726487364874648756487664877648786487964880648816488264883648846488564886648876488864889648906489164892648936489464895648966489764898648996490064901649026490364904649056490664907649086490964910649116491264913649146491564916649176491864919649206492164922649236492464925649266492764928649296493064931649326493364934649356493664937649386493964940649416494264943649446494564946649476494864949649506495164952649536495464955649566495764958649596496064961649626496364964649656496664967649686496964970649716497264973649746497564976649776497864979649806498164982649836498464985649866498764988649896499064991649926499364994649956499664997649986499965000650016500265003650046500565006650076500865009650106501165012650136501465015650166501765018650196502065021650226502365024650256502665027650286502965030650316503265033650346503565036650376503865039650406504165042650436504465045650466504765048650496505065051650526505365054650556505665057650586505965060650616506265063650646506565066650676506865069650706507165072650736507465075650766507765078650796508065081650826508365084650856508665087650886508965090650916509265093650946509565096650976509865099651006510165102651036510465105651066510765108651096511065111651126511365114651156511665117651186511965120651216512265123651246512565126651276512865129651306513165132651336513465135651366513765138651396514065141651426514365144651456514665147651486514965150651516515265153651546515565156651576515865159651606516165162651636516465165651666516765168651696517065171651726517365174651756517665177651786517965180651816518265183651846518565186651876518865189651906519165192651936519465195651966519765198651996520065201652026520365204652056520665207652086520965210652116521265213652146521565216652176521865219652206522165222652236522465225652266522765228652296523065231652326523365234652356523665237652386523965240652416524265243652446524565246652476524865249652506525165252652536525465255652566525765258652596526065261652626526365264652656526665267652686526965270652716527265273652746527565276652776527865279652806528165282652836528465285652866528765288652896529065291652926529365294652956529665297652986529965300653016530265303653046530565306653076530865309653106531165312653136531465315653166531765318653196532065321653226532365324653256532665327653286532965330653316533265333653346533565336653376533865339653406534165342653436534465345653466534765348653496535065351653526535365354653556535665357653586535965360653616536265363653646536565366653676536865369653706537165372653736537465375653766537765378653796538065381653826538365384653856538665387653886538965390653916539265393653946539565396653976539865399654006540165402654036540465405654066540765408654096541065411654126541365414654156541665417654186541965420654216542265423654246542565426654276542865429654306543165432654336543465435654366543765438654396544065441654426544365444654456544665447654486544965450654516545265453654546545565456654576545865459654606546165462654636546465465654666546765468654696547065471654726547365474654756547665477654786547965480654816548265483654846548565486654876548865489654906549165492654936549465495654966549765498654996550065501655026550365504655056550665507655086550965510655116551265513655146551565516655176551865519655206552165522655236552465525655266552765528655296553065531655326553365534655356553665537655386553965540655416554265543655446554565546655476554865549655506555165552655536555465555655566555765558655596556065561655626556365564655656556665567655686556965570655716557265573655746557565576655776557865579655806558165582655836558465585655866558765588655896559065591655926559365594655956559665597655986559965600656016560265603656046560565606656076560865609656106561165612656136561465615656166561765618656196562065621656226562365624656256562665627656286562965630656316563265633656346563565636656376563865639656406564165642656436564465645656466564765648656496565065651656526565365654656556565665657656586565965660656616566265663656646566565666656676566865669656706567165672656736567465675656766567765678656796568065681656826568365684656856568665687656886568965690656916569265693656946569565696656976569865699657006570165702657036570465705657066570765708657096571065711657126571365714657156571665717657186571965720657216572265723657246572565726657276572865729657306573165732657336573465735657366573765738657396574065741657426574365744657456574665747657486574965750657516575265753657546575565756657576575865759657606576165762657636576465765657666576765768657696577065771657726577365774657756577665777657786577965780657816578265783657846578565786657876578865789657906579165792657936579465795657966579765798657996580065801658026580365804658056580665807658086580965810658116581265813658146581565816658176581865819658206582165822658236582465825658266582765828658296583065831658326583365834658356583665837658386583965840658416584265843658446584565846658476584865849658506585165852658536585465855658566585765858658596586065861658626586365864658656586665867658686586965870658716587265873658746587565876658776587865879658806588165882658836588465885658866588765888658896589065891658926589365894658956589665897658986589965900659016590265903659046590565906659076590865909659106591165912659136591465915659166591765918659196592065921659226592365924659256592665927659286592965930659316593265933659346593565936659376593865939659406594165942659436594465945659466594765948659496595065951659526595365954659556595665957659586595965960659616596265963659646596565966659676596865969659706597165972659736597465975659766597765978659796598065981659826598365984659856598665987659886598965990659916599265993659946599565996659976599865999660006600166002660036600466005660066600766008660096601066011660126601366014660156601666017660186601966020660216602266023660246602566026660276602866029660306603166032660336603466035660366603766038660396604066041660426604366044660456604666047660486604966050660516605266053660546605566056660576605866059660606606166062660636606466065660666606766068660696607066071660726607366074660756607666077660786607966080660816608266083660846608566086660876608866089660906609166092660936609466095660966609766098660996610066101661026610366104661056610666107661086610966110661116611266113661146611566116661176611866119661206612166122661236612466125661266612766128661296613066131661326613366134661356613666137661386613966140661416614266143661446614566146661476614866149661506615166152661536615466155661566615766158661596616066161661626616366164661656616666167661686616966170661716617266173661746617566176661776617866179661806618166182661836618466185661866618766188661896619066191661926619366194661956619666197661986619966200662016620266203662046620566206662076620866209662106621166212662136621466215662166621766218662196622066221662226622366224662256622666227662286622966230662316623266233662346623566236662376623866239662406624166242662436624466245662466624766248662496625066251662526625366254662556625666257662586625966260662616626266263662646626566266662676626866269662706627166272662736627466275662766627766278662796628066281662826628366284662856628666287662886628966290662916629266293662946629566296662976629866299663006630166302663036630466305663066630766308663096631066311663126631366314663156631666317663186631966320663216632266323663246632566326663276632866329663306633166332663336633466335663366633766338663396634066341663426634366344663456634666347663486634966350663516635266353663546635566356663576635866359663606636166362663636636466365663666636766368663696637066371663726637366374663756637666377663786637966380663816638266383663846638566386663876638866389663906639166392663936639466395663966639766398663996640066401664026640366404664056640666407664086640966410664116641266413664146641566416664176641866419664206642166422664236642466425664266642766428664296643066431664326643366434664356643666437664386643966440664416644266443664446644566446664476644866449664506645166452664536645466455664566645766458664596646066461664626646366464664656646666467664686646966470664716647266473664746647566476664776647866479664806648166482664836648466485664866648766488664896649066491664926649366494664956649666497664986649966500665016650266503665046650566506665076650866509665106651166512665136651466515665166651766518665196652066521665226652366524665256652666527665286652966530665316653266533665346653566536665376653866539665406654166542665436654466545665466654766548665496655066551665526655366554665556655666557665586655966560665616656266563665646656566566665676656866569665706657166572665736657466575665766657766578665796658066581665826658366584665856658666587665886658966590665916659266593665946659566596665976659866599666006660166602666036660466605666066660766608666096661066611666126661366614666156661666617666186661966620666216662266623666246662566626666276662866629666306663166632666336663466635666366663766638666396664066641666426664366644666456664666647666486664966650666516665266653666546665566656666576665866659666606666166662666636666466665666666666766668666696667066671666726667366674666756667666677666786667966680666816668266683666846668566686666876668866689666906669166692666936669466695666966669766698666996670066701667026670366704667056670666707667086670966710667116671266713667146671566716667176671866719667206672166722667236672466725667266672766728667296673066731667326673366734667356673666737667386673966740667416674266743667446674566746667476674866749667506675166752667536675466755667566675766758667596676066761667626676366764667656676666767667686676966770667716677266773667746677566776667776677866779667806678166782667836678466785667866678766788667896679066791667926679366794667956679666797667986679966800668016680266803668046680566806668076680866809668106681166812668136681466815668166681766818668196682066821668226682366824668256682666827668286682966830668316683266833668346683566836668376683866839668406684166842668436684466845668466684766848668496685066851668526685366854668556685666857668586685966860668616686266863668646686566866668676686866869668706687166872668736687466875668766687766878668796688066881668826688366884668856688666887668886688966890668916689266893668946689566896668976689866899669006690166902669036690466905669066690766908669096691066911669126691366914669156691666917669186691966920669216692266923669246692566926669276692866929669306693166932669336693466935669366693766938669396694066941669426694366944669456694666947669486694966950669516695266953669546695566956669576695866959669606696166962669636696466965669666696766968669696697066971669726697366974669756697666977669786697966980669816698266983669846698566986669876698866989669906699166992669936699466995669966699766998669996700067001670026700367004670056700667007670086700967010670116701267013670146701567016670176701867019670206702167022670236702467025670266702767028670296703067031670326703367034670356703667037670386703967040670416704267043670446704567046670476704867049670506705167052670536705467055670566705767058670596706067061670626706367064670656706667067670686706967070670716707267073670746707567076670776707867079670806708167082670836708467085670866708767088670896709067091670926709367094670956709667097670986709967100671016710267103671046710567106671076710867109671106711167112671136711467115671166711767118671196712067121671226712367124671256712667127671286712967130671316713267133671346713567136671376713867139671406714167142671436714467145671466714767148671496715067151671526715367154671556715667157671586715967160671616716267163671646716567166671676716867169671706717167172671736717467175671766717767178671796718067181671826718367184671856718667187671886718967190671916719267193671946719567196671976719867199672006720167202672036720467205672066720767208672096721067211672126721367214672156721667217672186721967220672216722267223672246722567226672276722867229672306723167232672336723467235672366723767238672396724067241672426724367244672456724667247672486724967250672516725267253672546725567256672576725867259672606726167262672636726467265672666726767268672696727067271672726727367274672756727667277672786727967280672816728267283672846728567286672876728867289672906729167292672936729467295672966729767298672996730067301673026730367304673056730667307673086730967310673116731267313673146731567316673176731867319673206732167322673236732467325673266732767328673296733067331673326733367334673356733667337673386733967340673416734267343673446734567346673476734867349673506735167352673536735467355673566735767358673596736067361673626736367364673656736667367673686736967370673716737267373673746737567376673776737867379673806738167382673836738467385673866738767388673896739067391673926739367394673956739667397673986739967400674016740267403674046740567406674076740867409674106741167412674136741467415674166741767418674196742067421674226742367424674256742667427674286742967430674316743267433674346743567436674376743867439674406744167442674436744467445674466744767448674496745067451674526745367454674556745667457674586745967460674616746267463674646746567466674676746867469674706747167472674736747467475674766747767478674796748067481674826748367484674856748667487674886748967490674916749267493674946749567496674976749867499675006750167502675036750467505675066750767508675096751067511675126751367514675156751667517675186751967520675216752267523675246752567526675276752867529675306753167532675336753467535675366753767538675396754067541675426754367544675456754667547675486754967550675516755267553675546755567556675576755867559675606756167562675636756467565675666756767568675696757067571675726757367574675756757667577675786757967580675816758267583675846758567586675876758867589675906759167592675936759467595675966759767598675996760067601676026760367604676056760667607676086760967610676116761267613676146761567616676176761867619676206762167622676236762467625676266762767628676296763067631676326763367634676356763667637676386763967640676416764267643676446764567646676476764867649676506765167652676536765467655676566765767658676596766067661676626766367664676656766667667676686766967670676716767267673676746767567676676776767867679676806768167682676836768467685676866768767688676896769067691676926769367694676956769667697676986769967700677016770267703677046770567706677076770867709677106771167712677136771467715677166771767718677196772067721677226772367724677256772667727677286772967730677316773267733677346773567736677376773867739677406774167742677436774467745677466774767748677496775067751677526775367754677556775667757677586775967760677616776267763677646776567766677676776867769677706777167772677736777467775677766777767778677796778067781677826778367784677856778667787677886778967790677916779267793677946779567796677976779867799678006780167802678036780467805678066780767808678096781067811678126781367814678156781667817678186781967820678216782267823678246782567826678276782867829678306783167832678336783467835678366783767838678396784067841678426784367844678456784667847678486784967850678516785267853678546785567856678576785867859678606786167862678636786467865678666786767868678696787067871678726787367874678756787667877678786787967880678816788267883678846788567886678876788867889678906789167892678936789467895678966789767898678996790067901679026790367904679056790667907679086790967910679116791267913679146791567916679176791867919679206792167922679236792467925679266792767928679296793067931679326793367934679356793667937679386793967940679416794267943679446794567946679476794867949679506795167952679536795467955679566795767958679596796067961679626796367964679656796667967679686796967970679716797267973679746797567976679776797867979679806798167982679836798467985679866798767988679896799067991679926799367994679956799667997679986799968000680016800268003680046800568006680076800868009680106801168012680136801468015680166801768018680196802068021680226802368024680256802668027680286802968030680316803268033680346803568036680376803868039680406804168042680436804468045680466804768048680496805068051680526805368054680556805668057680586805968060680616806268063680646806568066680676806868069680706807168072680736807468075680766807768078680796808068081680826808368084680856808668087680886808968090680916809268093680946809568096680976809868099681006810168102681036810468105681066810768108681096811068111681126811368114681156811668117681186811968120681216812268123681246812568126681276812868129681306813168132681336813468135681366813768138681396814068141681426814368144681456814668147681486814968150681516815268153681546815568156681576815868159681606816168162681636816468165681666816768168681696817068171681726817368174681756817668177681786817968180681816818268183681846818568186681876818868189681906819168192681936819468195681966819768198681996820068201682026820368204682056820668207682086820968210682116821268213682146821568216682176821868219682206822168222682236822468225682266822768228682296823068231682326823368234682356823668237682386823968240682416824268243682446824568246682476824868249682506825168252682536825468255682566825768258682596826068261682626826368264682656826668267682686826968270682716827268273682746827568276682776827868279682806828168282682836828468285682866828768288682896829068291682926829368294682956829668297682986829968300683016830268303683046830568306683076830868309683106831168312683136831468315683166831768318683196832068321683226832368324683256832668327683286832968330683316833268333683346833568336683376833868339683406834168342683436834468345683466834768348683496835068351683526835368354683556835668357683586835968360683616836268363683646836568366683676836868369683706837168372683736837468375683766837768378683796838068381683826838368384683856838668387683886838968390683916839268393683946839568396683976839868399684006840168402684036840468405684066840768408684096841068411684126841368414684156841668417684186841968420684216842268423684246842568426684276842868429684306843168432684336843468435684366843768438684396844068441684426844368444684456844668447684486844968450684516845268453684546845568456684576845868459684606846168462684636846468465684666846768468684696847068471684726847368474684756847668477684786847968480684816848268483684846848568486684876848868489684906849168492684936849468495684966849768498684996850068501685026850368504685056850668507685086850968510685116851268513685146851568516685176851868519685206852168522685236852468525685266852768528685296853068531685326853368534685356853668537685386853968540685416854268543685446854568546685476854868549685506855168552685536855468555685566855768558685596856068561685626856368564685656856668567685686856968570685716857268573685746857568576685776857868579685806858168582685836858468585685866858768588685896859068591685926859368594685956859668597685986859968600686016860268603686046860568606686076860868609686106861168612686136861468615686166861768618686196862068621686226862368624686256862668627686286862968630686316863268633686346863568636686376863868639686406864168642686436864468645686466864768648686496865068651686526865368654686556865668657686586865968660686616866268663686646866568666686676866868669686706867168672686736867468675686766867768678686796868068681686826868368684686856868668687686886868968690686916869268693686946869568696686976869868699687006870168702687036870468705687066870768708687096871068711687126871368714687156871668717687186871968720687216872268723687246872568726687276872868729687306873168732687336873468735687366873768738687396874068741687426874368744687456874668747687486874968750687516875268753687546875568756687576875868759687606876168762687636876468765687666876768768687696877068771687726877368774687756877668777687786877968780687816878268783687846878568786687876878868789687906879168792687936879468795687966879768798687996880068801688026880368804688056880668807688086880968810688116881268813688146881568816688176881868819688206882168822688236882468825688266882768828688296883068831688326883368834688356883668837688386883968840688416884268843688446884568846688476884868849688506885168852688536885468855688566885768858688596886068861688626886368864688656886668867688686886968870688716887268873688746887568876688776887868879688806888168882688836888468885688866888768888688896889068891688926889368894688956889668897688986889968900689016890268903689046890568906689076890868909689106891168912689136891468915689166891768918689196892068921689226892368924689256892668927689286892968930689316893268933689346893568936689376893868939689406894168942689436894468945689466894768948689496895068951689526895368954689556895668957689586895968960689616896268963689646896568966689676896868969689706897168972689736897468975689766897768978689796898068981689826898368984689856898668987689886898968990689916899268993689946899568996689976899868999690006900169002690036900469005690066900769008690096901069011690126901369014690156901669017690186901969020690216902269023690246902569026690276902869029690306903169032690336903469035690366903769038690396904069041690426904369044690456904669047690486904969050690516905269053690546905569056690576905869059690606906169062690636906469065690666906769068690696907069071690726907369074690756907669077690786907969080690816908269083690846908569086690876908869089690906909169092690936909469095690966909769098690996910069101691026910369104691056910669107691086910969110691116911269113691146911569116691176911869119691206912169122691236912469125691266912769128691296913069131691326913369134691356913669137691386913969140691416914269143691446914569146691476914869149691506915169152691536915469155691566915769158691596916069161691626916369164691656916669167691686916969170691716917269173691746917569176691776917869179691806918169182691836918469185691866918769188691896919069191691926919369194691956919669197691986919969200692016920269203692046920569206692076920869209692106921169212692136921469215692166921769218692196922069221692226922369224692256922669227692286922969230692316923269233692346923569236692376923869239692406924169242692436924469245692466924769248692496925069251692526925369254692556925669257692586925969260692616926269263692646926569266692676926869269692706927169272692736927469275692766927769278692796928069281692826928369284692856928669287692886928969290692916929269293692946929569296692976929869299693006930169302693036930469305693066930769308693096931069311693126931369314693156931669317693186931969320693216932269323693246932569326693276932869329693306933169332693336933469335693366933769338693396934069341693426934369344693456934669347693486934969350693516935269353693546935569356693576935869359693606936169362693636936469365693666936769368693696937069371693726937369374693756937669377693786937969380693816938269383693846938569386693876938869389693906939169392693936939469395693966939769398693996940069401694026940369404694056940669407694086940969410694116941269413694146941569416694176941869419694206942169422694236942469425694266942769428694296943069431694326943369434694356943669437694386943969440694416944269443694446944569446694476944869449694506945169452694536945469455694566945769458694596946069461694626946369464694656946669467694686946969470694716947269473694746947569476694776947869479694806948169482694836948469485694866948769488694896949069491694926949369494694956949669497694986949969500695016950269503695046950569506695076950869509695106951169512695136951469515695166951769518695196952069521695226952369524695256952669527695286952969530695316953269533695346953569536695376953869539695406954169542695436954469545695466954769548695496955069551695526955369554695556955669557695586955969560695616956269563695646956569566695676956869569695706957169572695736957469575695766957769578695796958069581695826958369584695856958669587695886958969590695916959269593695946959569596695976959869599696006960169602696036960469605696066960769608696096961069611696126961369614696156961669617696186961969620696216962269623696246962569626696276962869629696306963169632696336963469635696366963769638696396964069641696426964369644696456964669647696486964969650696516965269653696546965569656696576965869659696606966169662696636966469665696666966769668696696967069671696726967369674696756967669677696786967969680696816968269683696846968569686696876968869689696906969169692696936969469695696966969769698696996970069701697026970369704697056970669707697086970969710697116971269713697146971569716697176971869719697206972169722697236972469725697266972769728697296973069731697326973369734697356973669737697386973969740697416974269743697446974569746697476974869749697506975169752697536975469755697566975769758697596976069761697626976369764697656976669767697686976969770697716977269773697746977569776697776977869779697806978169782697836978469785697866978769788697896979069791697926979369794697956979669797697986979969800698016980269803698046980569806698076980869809698106981169812698136981469815698166981769818698196982069821698226982369824698256982669827698286982969830698316983269833698346983569836698376983869839698406984169842698436984469845698466984769848698496985069851698526985369854698556985669857698586985969860698616986269863698646986569866698676986869869698706987169872698736987469875698766987769878698796988069881698826988369884698856988669887698886988969890698916989269893698946989569896698976989869899699006990169902699036990469905699066990769908699096991069911699126991369914699156991669917699186991969920699216992269923699246992569926699276992869929699306993169932699336993469935699366993769938699396994069941699426994369944699456994669947699486994969950699516995269953699546995569956699576995869959699606996169962699636996469965699666996769968699696997069971699726997369974699756997669977699786997969980699816998269983699846998569986699876998869989699906999169992699936999469995699966999769998699997000070001700027000370004700057000670007700087000970010700117001270013700147001570016700177001870019700207002170022700237002470025700267002770028700297003070031700327003370034700357003670037700387003970040700417004270043700447004570046700477004870049700507005170052700537005470055700567005770058700597006070061700627006370064700657006670067700687006970070700717007270073700747007570076700777007870079700807008170082700837008470085700867008770088700897009070091700927009370094700957009670097700987009970100701017010270103701047010570106701077010870109701107011170112701137011470115701167011770118701197012070121701227012370124701257012670127701287012970130701317013270133701347013570136701377013870139701407014170142701437014470145701467014770148701497015070151701527015370154701557015670157701587015970160701617016270163701647016570166701677016870169701707017170172701737017470175701767017770178701797018070181701827018370184701857018670187701887018970190701917019270193701947019570196701977019870199702007020170202702037020470205702067020770208702097021070211702127021370214702157021670217702187021970220702217022270223702247022570226702277022870229702307023170232702337023470235702367023770238702397024070241702427024370244702457024670247702487024970250702517025270253702547025570256702577025870259702607026170262702637026470265702667026770268702697027070271702727027370274702757027670277702787027970280702817028270283702847028570286702877028870289702907029170292702937029470295702967029770298702997030070301703027030370304703057030670307703087030970310703117031270313703147031570316703177031870319703207032170322703237032470325703267032770328703297033070331703327033370334703357033670337703387033970340703417034270343703447034570346703477034870349703507035170352703537035470355703567035770358703597036070361703627036370364703657036670367703687036970370703717037270373703747037570376703777037870379703807038170382703837038470385703867038770388703897039070391703927039370394703957039670397703987039970400704017040270403704047040570406704077040870409704107041170412704137041470415704167041770418704197042070421704227042370424704257042670427704287042970430704317043270433704347043570436704377043870439704407044170442704437044470445704467044770448704497045070451704527045370454704557045670457704587045970460704617046270463704647046570466704677046870469704707047170472704737047470475704767047770478704797048070481704827048370484704857048670487704887048970490704917049270493704947049570496704977049870499705007050170502705037050470505705067050770508705097051070511705127051370514705157051670517705187051970520705217052270523705247052570526705277052870529705307053170532705337053470535705367053770538705397054070541705427054370544705457054670547705487054970550705517055270553705547055570556705577055870559705607056170562705637056470565705667056770568705697057070571705727057370574705757057670577705787057970580705817058270583705847058570586705877058870589705907059170592705937059470595705967059770598705997060070601706027060370604706057060670607706087060970610706117061270613706147061570616706177061870619706207062170622706237062470625706267062770628706297063070631706327063370634706357063670637706387063970640706417064270643706447064570646706477064870649706507065170652706537065470655706567065770658706597066070661706627066370664706657066670667706687066970670706717067270673706747067570676706777067870679706807068170682706837068470685706867068770688706897069070691706927069370694706957069670697706987069970700707017070270703707047070570706707077070870709707107071170712707137071470715707167071770718707197072070721707227072370724707257072670727707287072970730707317073270733707347073570736707377073870739707407074170742707437074470745707467074770748707497075070751707527075370754707557075670757707587075970760707617076270763707647076570766707677076870769707707077170772707737077470775707767077770778707797078070781707827078370784707857078670787707887078970790707917079270793707947079570796707977079870799708007080170802708037080470805708067080770808708097081070811708127081370814708157081670817708187081970820708217082270823708247082570826708277082870829708307083170832708337083470835708367083770838708397084070841708427084370844708457084670847708487084970850708517085270853708547085570856708577085870859708607086170862708637086470865708667086770868708697087070871708727087370874708757087670877708787087970880708817088270883708847088570886708877088870889708907089170892708937089470895708967089770898708997090070901709027090370904709057090670907709087090970910709117091270913709147091570916709177091870919709207092170922709237092470925709267092770928709297093070931709327093370934709357093670937709387093970940709417094270943709447094570946709477094870949709507095170952709537095470955709567095770958709597096070961709627096370964709657096670967709687096970970709717097270973709747097570976709777097870979709807098170982709837098470985709867098770988709897099070991709927099370994709957099670997709987099971000710017100271003710047100571006710077100871009710107101171012710137101471015710167101771018710197102071021710227102371024710257102671027710287102971030710317103271033710347103571036710377103871039710407104171042710437104471045710467104771048710497105071051710527105371054710557105671057710587105971060710617106271063710647106571066710677106871069710707107171072710737107471075710767107771078710797108071081710827108371084710857108671087710887108971090710917109271093710947109571096710977109871099711007110171102711037110471105711067110771108711097111071111711127111371114711157111671117711187111971120711217112271123711247112571126711277112871129711307113171132711337113471135711367113771138711397114071141711427114371144711457114671147711487114971150711517115271153711547115571156711577115871159711607116171162711637116471165711667116771168711697117071171711727117371174711757117671177711787117971180711817118271183711847118571186711877118871189711907119171192711937119471195711967119771198711997120071201712027120371204712057120671207712087120971210712117121271213712147121571216712177121871219712207122171222712237122471225712267122771228712297123071231712327123371234712357123671237712387123971240712417124271243712447124571246712477124871249712507125171252712537125471255712567125771258712597126071261712627126371264712657126671267712687126971270712717127271273712747127571276712777127871279712807128171282712837128471285712867128771288712897129071291712927129371294712957129671297712987129971300713017130271303713047130571306713077130871309713107131171312713137131471315713167131771318713197132071321713227132371324713257132671327713287132971330713317133271333713347133571336713377133871339713407134171342713437134471345713467134771348713497135071351713527135371354713557135671357713587135971360713617136271363713647136571366713677136871369713707137171372713737137471375713767137771378713797138071381713827138371384713857138671387713887138971390713917139271393713947139571396713977139871399714007140171402714037140471405714067140771408714097141071411714127141371414714157141671417714187141971420714217142271423714247142571426714277142871429714307143171432714337143471435714367143771438714397144071441714427144371444714457144671447714487144971450714517145271453714547145571456714577145871459714607146171462714637146471465714667146771468714697147071471714727147371474714757147671477714787147971480714817148271483714847148571486714877148871489714907149171492714937149471495714967149771498714997150071501715027150371504715057150671507715087150971510715117151271513715147151571516715177151871519715207152171522715237152471525715267152771528715297153071531715327153371534715357153671537715387153971540715417154271543715447154571546715477154871549715507155171552715537155471555715567155771558715597156071561715627156371564715657156671567715687156971570715717157271573715747157571576715777157871579715807158171582715837158471585715867158771588715897159071591715927159371594715957159671597715987159971600716017160271603716047160571606716077160871609716107161171612716137161471615716167161771618716197162071621716227162371624716257162671627716287162971630716317163271633716347163571636716377163871639716407164171642716437164471645716467164771648716497165071651716527165371654716557165671657716587165971660716617166271663716647166571666716677166871669716707167171672716737167471675716767167771678716797168071681716827168371684716857168671687716887168971690716917169271693716947169571696716977169871699717007170171702717037170471705717067170771708717097171071711717127171371714717157171671717717187171971720717217172271723717247172571726717277172871729717307173171732717337173471735717367173771738717397174071741717427174371744717457174671747717487174971750717517175271753717547175571756717577175871759717607176171762717637176471765717667176771768717697177071771717727177371774717757177671777717787177971780717817178271783717847178571786717877178871789717907179171792717937179471795717967179771798717997180071801718027180371804718057180671807718087180971810718117181271813718147181571816718177181871819718207182171822718237182471825718267182771828718297183071831718327183371834718357183671837718387183971840718417184271843718447184571846718477184871849718507185171852718537185471855718567185771858718597186071861718627186371864718657186671867718687186971870718717187271873718747187571876718777187871879718807188171882718837188471885718867188771888718897189071891718927189371894718957189671897718987189971900719017190271903719047190571906719077190871909719107191171912719137191471915719167191771918719197192071921719227192371924719257192671927719287192971930719317193271933719347193571936719377193871939719407194171942719437194471945719467194771948719497195071951719527195371954719557195671957719587195971960719617196271963719647196571966719677196871969719707197171972719737197471975719767197771978719797198071981719827198371984719857198671987719887198971990719917199271993719947199571996719977199871999720007200172002720037200472005720067200772008720097201072011720127201372014720157201672017720187201972020720217202272023720247202572026720277202872029720307203172032720337203472035720367203772038720397204072041720427204372044720457204672047720487204972050720517205272053720547205572056720577205872059720607206172062720637206472065720667206772068720697207072071720727207372074720757207672077720787207972080720817208272083720847208572086720877208872089720907209172092720937209472095720967209772098720997210072101721027210372104721057210672107721087210972110721117211272113721147211572116721177211872119721207212172122721237212472125721267212772128721297213072131721327213372134721357213672137721387213972140721417214272143721447214572146721477214872149721507215172152721537215472155721567215772158721597216072161721627216372164721657216672167721687216972170721717217272173721747217572176721777217872179721807218172182721837218472185721867218772188721897219072191721927219372194721957219672197721987219972200722017220272203722047220572206722077220872209722107221172212722137221472215722167221772218722197222072221722227222372224722257222672227722287222972230722317223272233722347223572236722377223872239722407224172242722437224472245722467224772248722497225072251722527225372254722557225672257722587225972260722617226272263722647226572266722677226872269722707227172272722737227472275722767227772278722797228072281722827228372284722857228672287722887228972290722917229272293722947229572296722977229872299723007230172302723037230472305723067230772308723097231072311723127231372314723157231672317723187231972320723217232272323723247232572326723277232872329723307233172332723337233472335723367233772338723397234072341723427234372344723457234672347723487234972350723517235272353723547235572356723577235872359723607236172362723637236472365723667236772368723697237072371723727237372374723757237672377723787237972380723817238272383723847238572386723877238872389723907239172392723937239472395723967239772398723997240072401724027240372404724057240672407724087240972410724117241272413724147241572416724177241872419724207242172422724237242472425724267242772428724297243072431724327243372434724357243672437724387243972440724417244272443724447244572446724477244872449724507245172452724537245472455724567245772458724597246072461724627246372464724657246672467724687246972470724717247272473724747247572476724777247872479724807248172482724837248472485724867248772488724897249072491724927249372494724957249672497724987249972500725017250272503725047250572506725077250872509725107251172512725137251472515725167251772518725197252072521725227252372524725257252672527725287252972530725317253272533725347253572536725377253872539725407254172542725437254472545725467254772548725497255072551725527255372554725557255672557725587255972560725617256272563725647256572566725677256872569725707257172572725737257472575725767257772578725797258072581725827258372584725857258672587725887258972590725917259272593725947259572596725977259872599726007260172602726037260472605726067260772608726097261072611726127261372614726157261672617726187261972620726217262272623726247262572626726277262872629726307263172632726337263472635726367263772638726397264072641726427264372644726457264672647726487264972650726517265272653726547265572656726577265872659726607266172662726637266472665726667266772668726697267072671726727267372674726757267672677726787267972680726817268272683726847268572686726877268872689726907269172692726937269472695726967269772698726997270072701727027270372704727057270672707727087270972710727117271272713727147271572716727177271872719727207272172722727237272472725727267272772728727297273072731727327273372734727357273672737727387273972740727417274272743727447274572746727477274872749727507275172752727537275472755727567275772758727597276072761727627276372764727657276672767727687276972770727717277272773727747277572776727777277872779727807278172782727837278472785727867278772788727897279072791727927279372794727957279672797727987279972800728017280272803728047280572806728077280872809728107281172812728137281472815728167281772818728197282072821728227282372824728257282672827728287282972830728317283272833728347283572836728377283872839728407284172842728437284472845728467284772848728497285072851728527285372854728557285672857728587285972860728617286272863728647286572866728677286872869728707287172872728737287472875728767287772878728797288072881728827288372884728857288672887728887288972890728917289272893728947289572896728977289872899729007290172902729037290472905729067290772908729097291072911729127291372914729157291672917729187291972920729217292272923729247292572926729277292872929729307293172932729337293472935729367293772938729397294072941729427294372944729457294672947729487294972950729517295272953729547295572956729577295872959729607296172962729637296472965729667296772968729697297072971729727297372974729757297672977729787297972980729817298272983729847298572986729877298872989729907299172992729937299472995729967299772998729997300073001730027300373004730057300673007730087300973010730117301273013730147301573016730177301873019730207302173022730237302473025730267302773028730297303073031730327303373034730357303673037730387303973040730417304273043730447304573046730477304873049730507305173052730537305473055730567305773058730597306073061730627306373064730657306673067730687306973070730717307273073730747307573076730777307873079730807308173082730837308473085730867308773088730897309073091730927309373094730957309673097730987309973100731017310273103731047310573106731077310873109731107311173112731137311473115731167311773118731197312073121731227312373124731257312673127731287312973130731317313273133731347313573136731377313873139731407314173142731437314473145731467314773148731497315073151731527315373154731557315673157731587315973160731617316273163731647316573166731677316873169731707317173172731737317473175731767317773178731797318073181731827318373184731857318673187731887318973190731917319273193731947319573196731977319873199732007320173202732037320473205732067320773208732097321073211732127321373214732157321673217732187321973220732217322273223732247322573226732277322873229732307323173232732337323473235732367323773238732397324073241732427324373244732457324673247732487324973250732517325273253732547325573256732577325873259732607326173262732637326473265732667326773268732697327073271732727327373274732757327673277732787327973280732817328273283732847328573286732877328873289732907329173292732937329473295732967329773298732997330073301733027330373304733057330673307733087330973310733117331273313733147331573316733177331873319733207332173322733237332473325733267332773328733297333073331733327333373334733357333673337733387333973340733417334273343733447334573346733477334873349733507335173352733537335473355733567335773358733597336073361733627336373364733657336673367733687336973370733717337273373733747337573376733777337873379733807338173382733837338473385733867338773388733897339073391733927339373394733957339673397733987339973400734017340273403734047340573406734077340873409734107341173412734137341473415734167341773418734197342073421734227342373424734257342673427734287342973430734317343273433734347343573436734377343873439734407344173442734437344473445734467344773448734497345073451734527345373454734557345673457734587345973460734617346273463734647346573466734677346873469734707347173472734737347473475734767347773478734797348073481734827348373484734857348673487734887348973490734917349273493734947349573496734977349873499735007350173502735037350473505735067350773508735097351073511735127351373514735157351673517735187351973520735217352273523735247352573526735277352873529735307353173532735337353473535735367353773538735397354073541735427354373544735457354673547735487354973550735517355273553735547355573556735577355873559735607356173562735637356473565735667356773568735697357073571735727357373574735757357673577735787357973580735817358273583735847358573586735877358873589735907359173592735937359473595735967359773598735997360073601736027360373604736057360673607736087360973610736117361273613736147361573616736177361873619736207362173622736237362473625736267362773628736297363073631736327363373634736357363673637736387363973640736417364273643736447364573646736477364873649736507365173652736537365473655736567365773658736597366073661736627366373664736657366673667736687366973670736717367273673736747367573676736777367873679736807368173682736837368473685736867368773688736897369073691736927369373694736957369673697736987369973700737017370273703737047370573706737077370873709737107371173712737137371473715737167371773718737197372073721737227372373724737257372673727737287372973730737317373273733737347373573736737377373873739737407374173742737437374473745737467374773748737497375073751737527375373754737557375673757737587375973760737617376273763737647376573766737677376873769737707377173772737737377473775737767377773778737797378073781737827378373784737857378673787737887378973790737917379273793737947379573796737977379873799738007380173802738037380473805738067380773808738097381073811738127381373814738157381673817738187381973820738217382273823738247382573826738277382873829738307383173832738337383473835738367383773838738397384073841738427384373844738457384673847738487384973850738517385273853738547385573856738577385873859738607386173862738637386473865738667386773868738697387073871738727387373874738757387673877738787387973880738817388273883738847388573886738877388873889738907389173892738937389473895738967389773898738997390073901739027390373904739057390673907739087390973910739117391273913739147391573916739177391873919739207392173922739237392473925739267392773928739297393073931739327393373934739357393673937739387393973940739417394273943739447394573946739477394873949739507395173952739537395473955739567395773958739597396073961739627396373964739657396673967739687396973970739717397273973739747397573976739777397873979739807398173982739837398473985739867398773988739897399073991739927399373994739957399673997739987399974000740017400274003740047400574006740077400874009740107401174012740137401474015740167401774018740197402074021740227402374024740257402674027740287402974030740317403274033740347403574036740377403874039740407404174042740437404474045740467404774048740497405074051740527405374054740557405674057740587405974060740617406274063740647406574066740677406874069740707407174072740737407474075740767407774078740797408074081740827408374084740857408674087740887408974090740917409274093740947409574096740977409874099741007410174102741037410474105741067410774108741097411074111741127411374114741157411674117741187411974120741217412274123741247412574126741277412874129741307413174132741337413474135741367413774138741397414074141741427414374144741457414674147741487414974150741517415274153741547415574156741577415874159741607416174162741637416474165741667416774168741697417074171741727417374174741757417674177741787417974180741817418274183741847418574186741877418874189741907419174192741937419474195741967419774198741997420074201742027420374204742057420674207742087420974210742117421274213742147421574216742177421874219742207422174222742237422474225742267422774228742297423074231742327423374234742357423674237742387423974240742417424274243742447424574246742477424874249742507425174252742537425474255742567425774258742597426074261742627426374264742657426674267742687426974270742717427274273742747427574276742777427874279742807428174282742837428474285742867428774288742897429074291742927429374294742957429674297742987429974300743017430274303743047430574306743077430874309743107431174312743137431474315743167431774318743197432074321743227432374324743257432674327743287432974330743317433274333743347433574336743377433874339743407434174342743437434474345743467434774348743497435074351743527435374354743557435674357743587435974360743617436274363743647436574366743677436874369743707437174372743737437474375743767437774378743797438074381743827438374384743857438674387743887438974390743917439274393743947439574396743977439874399744007440174402744037440474405744067440774408744097441074411744127441374414744157441674417744187441974420744217442274423744247442574426744277442874429744307443174432744337443474435744367443774438744397444074441744427444374444744457444674447744487444974450744517445274453744547445574456744577445874459744607446174462744637446474465744667446774468744697447074471744727447374474744757447674477744787447974480744817448274483744847448574486744877448874489744907449174492744937449474495744967449774498744997450074501745027450374504745057450674507745087450974510745117451274513745147451574516745177451874519745207452174522745237452474525745267452774528745297453074531745327453374534745357453674537745387453974540745417454274543745447454574546745477454874549745507455174552745537455474555745567455774558745597456074561745627456374564745657456674567745687456974570745717457274573745747457574576745777457874579745807458174582745837458474585745867458774588745897459074591745927459374594745957459674597745987459974600746017460274603746047460574606746077460874609746107461174612746137461474615746167461774618746197462074621746227462374624746257462674627746287462974630746317463274633746347463574636746377463874639746407464174642746437464474645746467464774648746497465074651746527465374654746557465674657746587465974660746617466274663746647466574666746677466874669746707467174672746737467474675746767467774678746797468074681746827468374684746857468674687746887468974690746917469274693746947469574696746977469874699747007470174702747037470474705747067470774708747097471074711747127471374714747157471674717747187471974720747217472274723747247472574726747277472874729747307473174732747337473474735747367473774738747397474074741747427474374744747457474674747747487474974750747517475274753747547475574756747577475874759747607476174762747637476474765747667476774768747697477074771747727477374774747757477674777747787477974780747817478274783747847478574786747877478874789747907479174792747937479474795747967479774798747997480074801748027480374804748057480674807748087480974810748117481274813748147481574816748177481874819748207482174822748237482474825748267482774828748297483074831748327483374834748357483674837748387483974840748417484274843748447484574846748477484874849748507485174852748537485474855748567485774858748597486074861748627486374864748657486674867748687486974870748717487274873748747487574876748777487874879748807488174882748837488474885748867488774888748897489074891748927489374894748957489674897748987489974900749017490274903749047490574906749077490874909749107491174912749137491474915749167491774918749197492074921749227492374924749257492674927749287492974930749317493274933749347493574936749377493874939749407494174942749437494474945749467494774948749497495074951749527495374954749557495674957749587495974960749617496274963749647496574966749677496874969749707497174972749737497474975749767497774978749797498074981749827498374984749857498674987749887498974990749917499274993749947499574996749977499874999750007500175002750037500475005750067500775008750097501075011750127501375014750157501675017750187501975020750217502275023750247502575026750277502875029750307503175032750337503475035750367503775038750397504075041750427504375044750457504675047750487504975050750517505275053750547505575056750577505875059750607506175062750637506475065750667506775068750697507075071750727507375074750757507675077750787507975080750817508275083750847508575086750877508875089750907509175092750937509475095750967509775098750997510075101751027510375104751057510675107751087510975110751117511275113751147511575116751177511875119751207512175122751237512475125751267512775128751297513075131751327513375134751357513675137751387513975140751417514275143751447514575146751477514875149751507515175152751537515475155751567515775158751597516075161751627516375164751657516675167751687516975170751717517275173751747517575176751777517875179751807518175182751837518475185751867518775188751897519075191751927519375194751957519675197751987519975200752017520275203752047520575206752077520875209752107521175212752137521475215752167521775218752197522075221752227522375224752257522675227752287522975230752317523275233752347523575236752377523875239752407524175242752437524475245752467524775248752497525075251752527525375254752557525675257752587525975260752617526275263752647526575266752677526875269752707527175272752737527475275752767527775278752797528075281752827528375284752857528675287752887528975290752917529275293752947529575296752977529875299753007530175302753037530475305753067530775308753097531075311753127531375314753157531675317753187531975320753217532275323753247532575326753277532875329753307533175332753337533475335753367533775338753397534075341753427534375344753457534675347753487534975350753517535275353753547535575356753577535875359753607536175362753637536475365753667536775368753697537075371753727537375374753757537675377753787537975380753817538275383753847538575386753877538875389753907539175392753937539475395753967539775398753997540075401754027540375404754057540675407754087540975410754117541275413754147541575416754177541875419754207542175422754237542475425754267542775428754297543075431754327543375434754357543675437754387543975440754417544275443754447544575446754477544875449754507545175452754537545475455754567545775458754597546075461754627546375464754657546675467754687546975470754717547275473754747547575476754777547875479754807548175482754837548475485754867548775488754897549075491754927549375494754957549675497754987549975500755017550275503755047550575506755077550875509755107551175512755137551475515755167551775518755197552075521755227552375524755257552675527755287552975530755317553275533755347553575536755377553875539755407554175542755437554475545755467554775548755497555075551755527555375554755557555675557755587555975560755617556275563755647556575566755677556875569755707557175572755737557475575755767557775578755797558075581755827558375584755857558675587755887558975590755917559275593755947559575596755977559875599756007560175602756037560475605756067560775608756097561075611756127561375614756157561675617756187561975620756217562275623756247562575626756277562875629756307563175632756337563475635756367563775638756397564075641756427564375644756457564675647756487564975650756517565275653756547565575656756577565875659756607566175662756637566475665756667566775668756697567075671756727567375674756757567675677756787567975680756817568275683756847568575686756877568875689756907569175692756937569475695756967569775698756997570075701757027570375704757057570675707757087570975710757117571275713757147571575716757177571875719757207572175722757237572475725757267572775728757297573075731757327573375734757357573675737757387573975740757417574275743757447574575746757477574875749757507575175752757537575475755757567575775758757597576075761757627576375764757657576675767757687576975770757717577275773757747577575776757777577875779757807578175782757837578475785757867578775788757897579075791757927579375794757957579675797757987579975800758017580275803758047580575806758077580875809758107581175812758137581475815758167581775818758197582075821758227582375824758257582675827758287582975830758317583275833758347583575836758377583875839758407584175842758437584475845758467584775848758497585075851758527585375854758557585675857758587585975860758617586275863758647586575866758677586875869758707587175872758737587475875758767587775878758797588075881758827588375884758857588675887758887588975890758917589275893758947589575896758977589875899759007590175902759037590475905759067590775908759097591075911759127591375914759157591675917759187591975920759217592275923759247592575926759277592875929759307593175932759337593475935759367593775938759397594075941759427594375944759457594675947759487594975950759517595275953759547595575956759577595875959759607596175962759637596475965759667596775968759697597075971759727597375974759757597675977759787597975980759817598275983759847598575986759877598875989759907599175992759937599475995759967599775998759997600076001760027600376004760057600676007760087600976010760117601276013760147601576016760177601876019760207602176022760237602476025760267602776028760297603076031760327603376034760357603676037760387603976040760417604276043760447604576046760477604876049760507605176052760537605476055760567605776058760597606076061760627606376064760657606676067760687606976070760717607276073760747607576076760777607876079760807608176082760837608476085760867608776088760897609076091760927609376094760957609676097760987609976100761017610276103761047610576106761077610876109761107611176112761137611476115761167611776118761197612076121761227612376124761257612676127761287612976130761317613276133761347613576136761377613876139761407614176142761437614476145761467614776148761497615076151761527615376154761557615676157761587615976160761617616276163761647616576166761677616876169761707617176172761737617476175761767617776178761797618076181761827618376184761857618676187761887618976190761917619276193761947619576196761977619876199762007620176202762037620476205762067620776208762097621076211762127621376214762157621676217762187621976220762217622276223762247622576226762277622876229762307623176232762337623476235762367623776238762397624076241762427624376244762457624676247762487624976250762517625276253762547625576256762577625876259762607626176262762637626476265762667626776268762697627076271762727627376274762757627676277762787627976280762817628276283762847628576286762877628876289762907629176292762937629476295762967629776298762997630076301763027630376304763057630676307763087630976310763117631276313763147631576316763177631876319763207632176322763237632476325763267632776328763297633076331763327633376334763357633676337763387633976340763417634276343763447634576346763477634876349763507635176352763537635476355763567635776358763597636076361763627636376364763657636676367763687636976370763717637276373763747637576376763777637876379763807638176382763837638476385763867638776388763897639076391763927639376394763957639676397763987639976400764017640276403764047640576406764077640876409764107641176412764137641476415764167641776418764197642076421764227642376424764257642676427764287642976430764317643276433764347643576436764377643876439764407644176442764437644476445764467644776448764497645076451764527645376454764557645676457764587645976460764617646276463764647646576466764677646876469764707647176472764737647476475764767647776478764797648076481764827648376484764857648676487764887648976490764917649276493764947649576496764977649876499765007650176502765037650476505765067650776508765097651076511765127651376514765157651676517765187651976520765217652276523765247652576526765277652876529765307653176532765337653476535765367653776538765397654076541765427654376544765457654676547765487654976550765517655276553765547655576556765577655876559765607656176562765637656476565765667656776568765697657076571765727657376574765757657676577765787657976580765817658276583765847658576586765877658876589765907659176592765937659476595765967659776598765997660076601766027660376604766057660676607766087660976610766117661276613766147661576616766177661876619766207662176622766237662476625766267662776628766297663076631766327663376634766357663676637766387663976640766417664276643766447664576646766477664876649766507665176652766537665476655766567665776658766597666076661766627666376664766657666676667766687666976670766717667276673766747667576676766777667876679766807668176682766837668476685766867668776688766897669076691766927669376694766957669676697766987669976700767017670276703767047670576706767077670876709767107671176712767137671476715767167671776718767197672076721767227672376724767257672676727767287672976730767317673276733767347673576736767377673876739767407674176742767437674476745767467674776748767497675076751767527675376754767557675676757767587675976760767617676276763767647676576766767677676876769767707677176772767737677476775767767677776778767797678076781767827678376784767857678676787767887678976790767917679276793767947679576796767977679876799768007680176802768037680476805768067680776808768097681076811768127681376814768157681676817768187681976820768217682276823768247682576826768277682876829768307683176832768337683476835768367683776838768397684076841768427684376844768457684676847768487684976850768517685276853768547685576856768577685876859768607686176862768637686476865768667686776868768697687076871768727687376874768757687676877768787687976880768817688276883768847688576886768877688876889768907689176892768937689476895768967689776898768997690076901769027690376904769057690676907769087690976910769117691276913769147691576916769177691876919769207692176922769237692476925769267692776928769297693076931769327693376934769357693676937769387693976940769417694276943769447694576946769477694876949769507695176952769537695476955769567695776958769597696076961769627696376964769657696676967769687696976970769717697276973769747697576976769777697876979769807698176982769837698476985769867698776988769897699076991769927699376994769957699676997769987699977000770017700277003770047700577006770077700877009770107701177012770137701477015770167701777018770197702077021770227702377024770257702677027770287702977030770317703277033770347703577036770377703877039770407704177042770437704477045770467704777048770497705077051770527705377054770557705677057770587705977060770617706277063770647706577066770677706877069770707707177072770737707477075770767707777078770797708077081770827708377084770857708677087770887708977090770917709277093770947709577096770977709877099771007710177102771037710477105771067710777108771097711077111771127711377114771157711677117771187711977120771217712277123771247712577126771277712877129771307713177132771337713477135771367713777138771397714077141771427714377144771457714677147771487714977150771517715277153771547715577156771577715877159771607716177162771637716477165771667716777168771697717077171771727717377174771757717677177771787717977180771817718277183771847718577186771877718877189771907719177192771937719477195771967719777198771997720077201772027720377204772057720677207772087720977210772117721277213772147721577216772177721877219772207722177222772237722477225772267722777228772297723077231772327723377234772357723677237772387723977240772417724277243772447724577246772477724877249772507725177252772537725477255772567725777258772597726077261772627726377264772657726677267772687726977270772717727277273772747727577276772777727877279772807728177282772837728477285772867728777288772897729077291772927729377294772957729677297772987729977300773017730277303773047730577306773077730877309773107731177312773137731477315773167731777318773197732077321773227732377324773257732677327773287732977330773317733277333773347733577336773377733877339773407734177342773437734477345773467734777348773497735077351773527735377354773557735677357773587735977360773617736277363773647736577366773677736877369773707737177372773737737477375773767737777378773797738077381773827738377384773857738677387773887738977390773917739277393773947739577396773977739877399774007740177402774037740477405774067740777408774097741077411774127741377414774157741677417774187741977420774217742277423774247742577426774277742877429774307743177432774337743477435774367743777438774397744077441774427744377444774457744677447774487744977450774517745277453774547745577456774577745877459774607746177462774637746477465774667746777468774697747077471774727747377474774757747677477774787747977480774817748277483774847748577486774877748877489774907749177492774937749477495774967749777498774997750077501775027750377504775057750677507775087750977510775117751277513775147751577516775177751877519775207752177522775237752477525775267752777528775297753077531775327753377534775357753677537775387753977540775417754277543775447754577546775477754877549775507755177552775537755477555775567755777558775597756077561775627756377564775657756677567775687756977570775717757277573775747757577576775777757877579775807758177582775837758477585775867758777588775897759077591775927759377594775957759677597775987759977600776017760277603776047760577606776077760877609776107761177612776137761477615776167761777618776197762077621776227762377624776257762677627776287762977630776317763277633776347763577636776377763877639776407764177642776437764477645776467764777648776497765077651776527765377654776557765677657776587765977660776617766277663776647766577666776677766877669776707767177672776737767477675776767767777678776797768077681776827768377684776857768677687776887768977690776917769277693776947769577696776977769877699777007770177702777037770477705777067770777708777097771077711777127771377714777157771677717777187771977720777217772277723777247772577726777277772877729777307773177732777337773477735777367773777738777397774077741777427774377744777457774677747777487774977750777517775277753777547775577756777577775877759777607776177762777637776477765777667776777768777697777077771777727777377774777757777677777777787777977780777817778277783777847778577786777877778877789777907779177792777937779477795777967779777798777997780077801778027780377804778057780677807778087780977810778117781277813778147781577816778177781877819778207782177822778237782477825778267782777828778297783077831778327783377834778357783677837778387783977840778417784277843778447784577846778477784877849778507785177852778537785477855778567785777858778597786077861778627786377864778657786677867778687786977870778717787277873778747787577876778777787877879778807788177882778837788477885778867788777888778897789077891778927789377894778957789677897778987789977900779017790277903779047790577906779077790877909779107791177912779137791477915779167791777918779197792077921779227792377924779257792677927779287792977930779317793277933779347793577936779377793877939779407794177942779437794477945779467794777948779497795077951779527795377954779557795677957779587795977960779617796277963779647796577966779677796877969779707797177972779737797477975779767797777978779797798077981779827798377984779857798677987779887798977990779917799277993779947799577996779977799877999780007800178002780037800478005780067800778008780097801078011780127801378014780157801678017780187801978020780217802278023780247802578026780277802878029780307803178032780337803478035780367803778038780397804078041780427804378044780457804678047780487804978050780517805278053780547805578056780577805878059780607806178062780637806478065780667806778068780697807078071780727807378074780757807678077780787807978080780817808278083780847808578086780877808878089780907809178092780937809478095780967809778098780997810078101781027810378104781057810678107781087810978110781117811278113781147811578116781177811878119781207812178122781237812478125781267812778128781297813078131781327813378134781357813678137781387813978140781417814278143781447814578146781477814878149781507815178152781537815478155781567815778158781597816078161781627816378164781657816678167781687816978170781717817278173781747817578176781777817878179781807818178182781837818478185781867818778188781897819078191781927819378194781957819678197781987819978200782017820278203782047820578206782077820878209782107821178212782137821478215782167821778218782197822078221782227822378224782257822678227782287822978230782317823278233782347823578236782377823878239782407824178242782437824478245782467824778248782497825078251782527825378254782557825678257782587825978260782617826278263782647826578266782677826878269782707827178272782737827478275782767827778278782797828078281782827828378284782857828678287782887828978290782917829278293782947829578296782977829878299783007830178302783037830478305783067830778308783097831078311783127831378314783157831678317783187831978320783217832278323783247832578326783277832878329783307833178332783337833478335783367833778338783397834078341783427834378344783457834678347783487834978350783517835278353783547835578356783577835878359783607836178362783637836478365783667836778368783697837078371783727837378374783757837678377783787837978380783817838278383783847838578386783877838878389783907839178392783937839478395783967839778398783997840078401784027840378404784057840678407784087840978410784117841278413784147841578416784177841878419784207842178422784237842478425784267842778428784297843078431784327843378434784357843678437784387843978440784417844278443784447844578446784477844878449784507845178452784537845478455784567845778458784597846078461784627846378464784657846678467784687846978470784717847278473784747847578476784777847878479784807848178482784837848478485784867848778488784897849078491784927849378494784957849678497784987849978500785017850278503785047850578506785077850878509785107851178512785137851478515785167851778518785197852078521785227852378524785257852678527785287852978530785317853278533785347853578536785377853878539785407854178542785437854478545785467854778548785497855078551785527855378554785557855678557785587855978560785617856278563785647856578566785677856878569785707857178572785737857478575785767857778578785797858078581785827858378584785857858678587785887858978590785917859278593785947859578596785977859878599786007860178602786037860478605786067860778608786097861078611786127861378614786157861678617786187861978620786217862278623786247862578626786277862878629786307863178632786337863478635786367863778638786397864078641786427864378644786457864678647786487864978650786517865278653786547865578656786577865878659786607866178662786637866478665786667866778668786697867078671786727867378674786757867678677786787867978680786817868278683786847868578686786877868878689786907869178692786937869478695786967869778698786997870078701787027870378704787057870678707787087870978710787117871278713787147871578716787177871878719787207872178722787237872478725787267872778728787297873078731787327873378734787357873678737787387873978740787417874278743787447874578746787477874878749787507875178752787537875478755787567875778758787597876078761787627876378764787657876678767787687876978770787717877278773787747877578776787777877878779787807878178782787837878478785787867878778788787897879078791787927879378794787957879678797787987879978800788017880278803788047880578806788077880878809788107881178812788137881478815788167881778818788197882078821788227882378824788257882678827788287882978830788317883278833788347883578836788377883878839788407884178842788437884478845788467884778848788497885078851788527885378854788557885678857788587885978860788617886278863788647886578866788677886878869788707887178872788737887478875788767887778878788797888078881788827888378884788857888678887788887888978890788917889278893788947889578896788977889878899789007890178902789037890478905789067890778908789097891078911789127891378914789157891678917789187891978920789217892278923789247892578926789277892878929789307893178932789337893478935789367893778938789397894078941789427894378944789457894678947789487894978950789517895278953789547895578956789577895878959789607896178962789637896478965789667896778968789697897078971789727897378974789757897678977789787897978980789817898278983789847898578986789877898878989789907899178992789937899478995789967899778998789997900079001790027900379004790057900679007790087900979010790117901279013790147901579016790177901879019790207902179022790237902479025790267902779028790297903079031790327903379034790357903679037790387903979040790417904279043790447904579046790477904879049790507905179052790537905479055790567905779058790597906079061790627906379064790657906679067790687906979070790717907279073790747907579076790777907879079790807908179082790837908479085790867908779088790897909079091790927909379094790957909679097790987909979100791017910279103791047910579106791077910879109791107911179112791137911479115791167911779118791197912079121791227912379124791257912679127791287912979130791317913279133791347913579136791377913879139791407914179142791437914479145791467914779148791497915079151791527915379154791557915679157791587915979160791617916279163791647916579166791677916879169791707917179172791737917479175791767917779178791797918079181791827918379184791857918679187791887918979190791917919279193791947919579196791977919879199792007920179202792037920479205792067920779208792097921079211792127921379214792157921679217792187921979220792217922279223792247922579226792277922879229792307923179232792337923479235792367923779238792397924079241792427924379244792457924679247792487924979250792517925279253792547925579256792577925879259792607926179262792637926479265792667926779268792697927079271792727927379274792757927679277792787927979280792817928279283792847928579286792877928879289792907929179292792937929479295792967929779298792997930079301793027930379304793057930679307793087930979310793117931279313793147931579316793177931879319793207932179322793237932479325793267932779328793297933079331793327933379334793357933679337793387933979340793417934279343793447934579346793477934879349793507935179352793537935479355793567935779358793597936079361793627936379364793657936679367793687936979370793717937279373793747937579376793777937879379793807938179382793837938479385793867938779388793897939079391793927939379394793957939679397793987939979400794017940279403794047940579406794077940879409794107941179412794137941479415794167941779418794197942079421794227942379424794257942679427794287942979430794317943279433794347943579436794377943879439794407944179442794437944479445794467944779448794497945079451794527945379454794557945679457794587945979460794617946279463794647946579466794677946879469794707947179472794737947479475794767947779478794797948079481794827948379484794857948679487794887948979490794917949279493794947949579496794977949879499795007950179502795037950479505795067950779508795097951079511795127951379514795157951679517795187951979520795217952279523795247952579526795277952879529795307953179532795337953479535795367953779538795397954079541795427954379544795457954679547795487954979550795517955279553795547955579556795577955879559795607956179562795637956479565795667956779568795697957079571795727957379574795757957679577795787957979580795817958279583795847958579586795877958879589795907959179592795937959479595795967959779598795997960079601796027960379604796057960679607796087960979610796117961279613796147961579616796177961879619796207962179622796237962479625796267962779628796297963079631796327963379634796357963679637796387963979640796417964279643796447964579646796477964879649796507965179652796537965479655796567965779658796597966079661796627966379664796657966679667796687966979670796717967279673796747967579676796777967879679796807968179682796837968479685796867968779688796897969079691796927969379694796957969679697796987969979700797017970279703797047970579706797077970879709797107971179712797137971479715797167971779718797197972079721797227972379724797257972679727797287972979730797317973279733797347973579736797377973879739797407974179742797437974479745797467974779748797497975079751797527975379754797557975679757797587975979760797617976279763797647976579766797677976879769797707977179772797737977479775797767977779778797797978079781797827978379784797857978679787797887978979790797917979279793797947979579796797977979879799798007980179802798037980479805798067980779808798097981079811798127981379814798157981679817798187981979820798217982279823798247982579826798277982879829798307983179832798337983479835798367983779838798397984079841798427984379844798457984679847798487984979850798517985279853798547985579856798577985879859798607986179862798637986479865798667986779868798697987079871798727987379874798757987679877798787987979880798817988279883798847988579886798877988879889798907989179892798937989479895798967989779898798997990079901799027990379904799057990679907799087990979910799117991279913799147991579916799177991879919799207992179922799237992479925799267992779928799297993079931799327993379934799357993679937799387993979940799417994279943799447994579946799477994879949799507995179952799537995479955799567995779958799597996079961799627996379964799657996679967799687996979970799717997279973799747997579976799777997879979799807998179982799837998479985799867998779988799897999079991799927999379994799957999679997799987999980000800018000280003800048000580006800078000880009800108001180012800138001480015800168001780018800198002080021800228002380024800258002680027800288002980030800318003280033800348003580036800378003880039800408004180042800438004480045800468004780048800498005080051800528005380054800558005680057800588005980060800618006280063800648006580066800678006880069800708007180072800738007480075800768007780078800798008080081800828008380084800858008680087800888008980090800918009280093800948009580096800978009880099801008010180102801038010480105801068010780108801098011080111801128011380114801158011680117801188011980120801218012280123801248012580126801278012880129801308013180132801338013480135801368013780138801398014080141801428014380144801458014680147801488014980150801518015280153801548015580156801578015880159801608016180162801638016480165801668016780168801698017080171801728017380174801758017680177801788017980180801818018280183801848018580186801878018880189801908019180192801938019480195801968019780198801998020080201802028020380204802058020680207802088020980210802118021280213802148021580216802178021880219802208022180222802238022480225802268022780228802298023080231802328023380234802358023680237802388023980240802418024280243802448024580246802478024880249802508025180252802538025480255802568025780258802598026080261802628026380264802658026680267802688026980270802718027280273802748027580276802778027880279802808028180282802838028480285802868028780288802898029080291802928029380294802958029680297802988029980300803018030280303803048030580306803078030880309803108031180312803138031480315803168031780318803198032080321803228032380324803258032680327803288032980330803318033280333803348033580336803378033880339803408034180342803438034480345803468034780348803498035080351803528035380354803558035680357803588035980360803618036280363803648036580366803678036880369803708037180372803738037480375803768037780378803798038080381803828038380384803858038680387803888038980390803918039280393803948039580396803978039880399804008040180402804038040480405804068040780408804098041080411804128041380414804158041680417804188041980420804218042280423804248042580426804278042880429804308043180432804338043480435804368043780438804398044080441804428044380444804458044680447804488044980450804518045280453804548045580456804578045880459804608046180462804638046480465804668046780468804698047080471804728047380474804758047680477804788047980480804818048280483804848048580486804878048880489804908049180492804938049480495804968049780498804998050080501805028050380504805058050680507805088050980510805118051280513805148051580516805178051880519805208052180522805238052480525805268052780528805298053080531805328053380534805358053680537805388053980540805418054280543805448054580546805478054880549805508055180552805538055480555805568055780558805598056080561805628056380564805658056680567805688056980570805718057280573805748057580576805778057880579805808058180582805838058480585805868058780588805898059080591805928059380594805958059680597805988059980600806018060280603806048060580606806078060880609806108061180612806138061480615806168061780618806198062080621806228062380624806258062680627806288062980630806318063280633806348063580636806378063880639806408064180642806438064480645806468064780648806498065080651806528065380654806558065680657806588065980660806618066280663806648066580666806678066880669806708067180672806738067480675806768067780678806798068080681806828068380684806858068680687806888068980690806918069280693806948069580696806978069880699807008070180702807038070480705807068070780708807098071080711807128071380714807158071680717807188071980720807218072280723807248072580726807278072880729807308073180732807338073480735807368073780738807398074080741807428074380744807458074680747807488074980750807518075280753807548075580756807578075880759807608076180762807638076480765807668076780768807698077080771807728077380774807758077680777807788077980780807818078280783807848078580786807878078880789807908079180792807938079480795807968079780798807998080080801808028080380804808058080680807808088080980810808118081280813808148081580816808178081880819808208082180822808238082480825808268082780828808298083080831808328083380834808358083680837808388083980840808418084280843808448084580846808478084880849808508085180852808538085480855808568085780858808598086080861808628086380864808658086680867808688086980870808718087280873808748087580876808778087880879808808088180882808838088480885808868088780888808898089080891808928089380894808958089680897808988089980900809018090280903809048090580906809078090880909809108091180912809138091480915809168091780918809198092080921809228092380924809258092680927809288092980930809318093280933809348093580936809378093880939809408094180942809438094480945809468094780948809498095080951809528095380954809558095680957809588095980960809618096280963809648096580966809678096880969809708097180972809738097480975809768097780978809798098080981809828098380984809858098680987809888098980990809918099280993809948099580996809978099880999810008100181002810038100481005810068100781008810098101081011810128101381014810158101681017810188101981020810218102281023810248102581026810278102881029810308103181032810338103481035810368103781038810398104081041810428104381044810458104681047810488104981050810518105281053810548105581056810578105881059810608106181062810638106481065810668106781068810698107081071810728107381074810758107681077810788107981080810818108281083810848108581086810878108881089810908109181092810938109481095810968109781098810998110081101811028110381104811058110681107811088110981110811118111281113811148111581116811178111881119811208112181122811238112481125811268112781128811298113081131811328113381134811358113681137811388113981140811418114281143811448114581146811478114881149811508115181152811538115481155811568115781158811598116081161811628116381164811658116681167811688116981170811718117281173811748117581176811778117881179811808118181182811838118481185811868118781188811898119081191811928119381194811958119681197811988119981200812018120281203812048120581206812078120881209812108121181212812138121481215812168121781218812198122081221812228122381224812258122681227812288122981230812318123281233812348123581236812378123881239812408124181242812438124481245812468124781248812498125081251812528125381254812558125681257812588125981260812618126281263812648126581266812678126881269812708127181272812738127481275812768127781278812798128081281812828128381284812858128681287812888128981290812918129281293812948129581296812978129881299813008130181302813038130481305813068130781308813098131081311813128131381314813158131681317813188131981320813218132281323813248132581326813278132881329813308133181332813338133481335813368133781338813398134081341813428134381344813458134681347813488134981350813518135281353813548135581356813578135881359813608136181362813638136481365813668136781368813698137081371813728137381374813758137681377813788137981380813818138281383813848138581386813878138881389813908139181392813938139481395813968139781398813998140081401814028140381404814058140681407814088140981410814118141281413814148141581416814178141881419814208142181422814238142481425814268142781428814298143081431814328143381434814358143681437814388143981440814418144281443814448144581446814478144881449814508145181452814538145481455814568145781458814598146081461814628146381464814658146681467814688146981470814718147281473814748147581476814778147881479814808148181482814838148481485814868148781488814898149081491814928149381494814958149681497814988149981500815018150281503815048150581506815078150881509815108151181512815138151481515815168151781518815198152081521815228152381524815258152681527815288152981530815318153281533815348153581536815378153881539815408154181542815438154481545815468154781548815498155081551815528155381554815558155681557815588155981560815618156281563815648156581566815678156881569815708157181572815738157481575815768157781578815798158081581815828158381584815858158681587815888158981590815918159281593815948159581596815978159881599816008160181602816038160481605816068160781608816098161081611816128161381614816158161681617816188161981620816218162281623816248162581626816278162881629816308163181632816338163481635816368163781638816398164081641816428164381644816458164681647816488164981650816518165281653816548165581656816578165881659816608166181662816638166481665816668166781668816698167081671816728167381674816758167681677816788167981680816818168281683816848168581686816878168881689816908169181692816938169481695816968169781698816998170081701817028170381704817058170681707817088170981710817118171281713817148171581716817178171881719817208172181722817238172481725817268172781728817298173081731817328173381734817358173681737817388173981740817418174281743817448174581746817478174881749817508175181752817538175481755817568175781758817598176081761817628176381764817658176681767817688176981770817718177281773817748177581776817778177881779817808178181782817838178481785817868178781788817898179081791817928179381794817958179681797817988179981800818018180281803818048180581806818078180881809818108181181812818138181481815818168181781818818198182081821818228182381824818258182681827818288182981830818318183281833818348183581836818378183881839818408184181842818438184481845818468184781848818498185081851818528185381854818558185681857818588185981860818618186281863818648186581866818678186881869818708187181872818738187481875818768187781878818798188081881818828188381884818858188681887818888188981890818918189281893818948189581896818978189881899819008190181902819038190481905819068190781908819098191081911819128191381914819158191681917819188191981920819218192281923819248192581926819278192881929819308193181932819338193481935819368193781938819398194081941819428194381944819458194681947819488194981950819518195281953819548195581956819578195881959819608196181962819638196481965819668196781968819698197081971819728197381974819758197681977819788197981980819818198281983819848198581986819878198881989819908199181992819938199481995819968199781998819998200082001820028200382004820058200682007820088200982010820118201282013820148201582016820178201882019820208202182022820238202482025820268202782028820298203082031820328203382034820358203682037820388203982040820418204282043820448204582046820478204882049820508205182052820538205482055820568205782058820598206082061820628206382064820658206682067820688206982070820718207282073820748207582076820778207882079820808208182082820838208482085820868208782088820898209082091820928209382094820958209682097820988209982100821018210282103821048210582106821078210882109821108211182112821138211482115821168211782118821198212082121821228212382124821258212682127821288212982130821318213282133821348213582136821378213882139821408214182142821438214482145821468214782148821498215082151821528215382154821558215682157821588215982160821618216282163821648216582166821678216882169821708217182172821738217482175821768217782178821798218082181821828218382184821858218682187821888218982190821918219282193821948219582196821978219882199822008220182202822038220482205822068220782208822098221082211822128221382214822158221682217822188221982220822218222282223822248222582226822278222882229822308223182232822338223482235822368223782238822398224082241822428224382244822458224682247822488224982250822518225282253822548225582256822578225882259822608226182262822638226482265822668226782268822698227082271822728227382274822758227682277822788227982280822818228282283822848228582286822878228882289822908229182292822938229482295822968229782298822998230082301823028230382304823058230682307823088230982310823118231282313823148231582316823178231882319823208232182322823238232482325823268232782328823298233082331823328233382334823358233682337823388233982340823418234282343823448234582346823478234882349823508235182352823538235482355823568235782358823598236082361823628236382364823658236682367823688236982370823718237282373823748237582376823778237882379823808238182382823838238482385823868238782388823898239082391823928239382394823958239682397823988239982400824018240282403824048240582406824078240882409824108241182412824138241482415824168241782418824198242082421824228242382424824258242682427824288242982430824318243282433824348243582436824378243882439824408244182442824438244482445824468244782448824498245082451824528245382454824558245682457824588245982460824618246282463824648246582466824678246882469824708247182472824738247482475824768247782478824798248082481824828248382484824858248682487824888248982490824918249282493824948249582496824978249882499825008250182502825038250482505825068250782508825098251082511825128251382514825158251682517825188251982520825218252282523825248252582526825278252882529825308253182532825338253482535825368253782538825398254082541825428254382544825458254682547825488254982550825518255282553825548255582556825578255882559825608256182562825638256482565825668256782568825698257082571825728257382574825758257682577825788257982580825818258282583825848258582586825878258882589825908259182592825938259482595825968259782598825998260082601826028260382604826058260682607826088260982610826118261282613826148261582616826178261882619826208262182622826238262482625826268262782628826298263082631826328263382634826358263682637826388263982640826418264282643826448264582646826478264882649826508265182652826538265482655826568265782658826598266082661826628266382664826658266682667826688266982670826718267282673826748267582676826778267882679826808268182682826838268482685826868268782688826898269082691826928269382694826958269682697826988269982700827018270282703827048270582706827078270882709827108271182712827138271482715827168271782718827198272082721827228272382724827258272682727827288272982730827318273282733827348273582736827378273882739827408274182742827438274482745827468274782748827498275082751827528275382754827558275682757827588275982760827618276282763827648276582766827678276882769827708277182772827738277482775827768277782778827798278082781827828278382784827858278682787827888278982790827918279282793827948279582796827978279882799828008280182802828038280482805828068280782808828098281082811828128281382814828158281682817828188281982820828218282282823828248282582826828278282882829828308283182832828338283482835828368283782838828398284082841828428284382844828458284682847828488284982850828518285282853828548285582856828578285882859828608286182862828638286482865828668286782868828698287082871828728287382874828758287682877828788287982880828818288282883828848288582886828878288882889828908289182892828938289482895828968289782898828998290082901829028290382904829058290682907829088290982910829118291282913829148291582916829178291882919829208292182922829238292482925829268292782928829298293082931829328293382934829358293682937829388293982940829418294282943829448294582946829478294882949829508295182952829538295482955829568295782958829598296082961829628296382964829658296682967829688296982970829718297282973829748297582976829778297882979829808298182982829838298482985829868298782988829898299082991829928299382994829958299682997829988299983000830018300283003830048300583006830078300883009830108301183012830138301483015830168301783018830198302083021830228302383024830258302683027830288302983030830318303283033830348303583036830378303883039830408304183042830438304483045830468304783048830498305083051830528305383054830558305683057830588305983060830618306283063830648306583066830678306883069830708307183072830738307483075830768307783078830798308083081830828308383084830858308683087830888308983090830918309283093830948309583096830978309883099831008310183102831038310483105831068310783108831098311083111831128311383114831158311683117831188311983120831218312283123831248312583126831278312883129831308313183132831338313483135831368313783138831398314083141831428314383144831458314683147831488314983150831518315283153831548315583156831578315883159831608316183162831638316483165831668316783168831698317083171831728317383174831758317683177831788317983180831818318283183831848318583186831878318883189831908319183192831938319483195831968319783198831998320083201832028320383204832058320683207832088320983210832118321283213832148321583216832178321883219832208322183222832238322483225832268322783228832298323083231832328323383234832358323683237832388323983240832418324283243832448324583246832478324883249832508325183252832538325483255832568325783258832598326083261832628326383264832658326683267832688326983270832718327283273832748327583276832778327883279832808328183282832838328483285832868328783288832898329083291832928329383294832958329683297832988329983300833018330283303833048330583306833078330883309833108331183312833138331483315833168331783318833198332083321833228332383324833258332683327833288332983330833318333283333833348333583336833378333883339833408334183342833438334483345833468334783348833498335083351833528335383354833558335683357833588335983360833618336283363833648336583366833678336883369833708337183372833738337483375833768337783378833798338083381833828338383384833858338683387833888338983390833918339283393833948339583396833978339883399834008340183402834038340483405834068340783408834098341083411834128341383414834158341683417834188341983420834218342283423834248342583426834278342883429834308343183432834338343483435834368343783438834398344083441834428344383444834458344683447834488344983450834518345283453834548345583456834578345883459834608346183462834638346483465834668346783468834698347083471834728347383474834758347683477834788347983480834818348283483834848348583486834878348883489834908349183492834938349483495834968349783498834998350083501835028350383504835058350683507835088350983510835118351283513835148351583516835178351883519835208352183522835238352483525835268352783528835298353083531835328353383534835358353683537835388353983540835418354283543835448354583546835478354883549835508355183552835538355483555835568355783558835598356083561835628356383564835658356683567835688356983570835718357283573835748357583576835778357883579835808358183582835838358483585835868358783588835898359083591835928359383594835958359683597835988359983600836018360283603836048360583606836078360883609836108361183612836138361483615836168361783618836198362083621836228362383624836258362683627836288362983630836318363283633836348363583636836378363883639836408364183642836438364483645836468364783648836498365083651836528365383654836558365683657836588365983660836618366283663836648366583666836678366883669836708367183672836738367483675836768367783678836798368083681836828368383684836858368683687836888368983690836918369283693836948369583696836978369883699837008370183702837038370483705837068370783708837098371083711837128371383714837158371683717837188371983720837218372283723837248372583726837278372883729837308373183732837338373483735837368373783738837398374083741837428374383744837458374683747837488374983750837518375283753837548375583756837578375883759837608376183762837638376483765837668376783768837698377083771837728377383774837758377683777837788377983780837818378283783837848378583786837878378883789837908379183792837938379483795837968379783798837998380083801838028380383804838058380683807838088380983810838118381283813838148381583816838178381883819838208382183822838238382483825838268382783828838298383083831838328383383834838358383683837838388383983840838418384283843838448384583846838478384883849838508385183852838538385483855838568385783858838598386083861838628386383864838658386683867838688386983870838718387283873838748387583876838778387883879838808388183882838838388483885838868388783888838898389083891838928389383894838958389683897838988389983900839018390283903839048390583906839078390883909839108391183912839138391483915839168391783918839198392083921839228392383924839258392683927839288392983930839318393283933839348393583936839378393883939839408394183942839438394483945839468394783948839498395083951839528395383954839558395683957839588395983960839618396283963839648396583966839678396883969839708397183972839738397483975839768397783978839798398083981839828398383984839858398683987839888398983990839918399283993839948399583996839978399883999840008400184002840038400484005840068400784008840098401084011840128401384014840158401684017840188401984020840218402284023840248402584026840278402884029840308403184032840338403484035840368403784038840398404084041840428404384044840458404684047840488404984050840518405284053840548405584056840578405884059840608406184062840638406484065840668406784068840698407084071840728407384074840758407684077840788407984080840818408284083840848408584086840878408884089840908409184092840938409484095840968409784098840998410084101841028410384104841058410684107841088410984110841118411284113841148411584116841178411884119841208412184122841238412484125841268412784128841298413084131841328413384134841358413684137841388413984140841418414284143841448414584146841478414884149841508415184152841538415484155841568415784158841598416084161841628416384164841658416684167841688416984170841718417284173841748417584176841778417884179841808418184182841838418484185841868418784188841898419084191841928419384194841958419684197841988419984200842018420284203842048420584206842078420884209842108421184212842138421484215842168421784218842198422084221842228422384224842258422684227842288422984230842318423284233842348423584236842378423884239842408424184242842438424484245842468424784248842498425084251842528425384254842558425684257842588425984260842618426284263842648426584266842678426884269842708427184272842738427484275842768427784278842798428084281842828428384284842858428684287842888428984290842918429284293842948429584296842978429884299843008430184302843038430484305843068430784308843098431084311843128431384314843158431684317843188431984320843218432284323843248432584326843278432884329843308433184332843338433484335843368433784338843398434084341843428434384344843458434684347843488434984350843518435284353843548435584356843578435884359843608436184362843638436484365843668436784368843698437084371843728437384374843758437684377843788437984380843818438284383843848438584386843878438884389843908439184392843938439484395843968439784398843998440084401844028440384404844058440684407844088440984410844118441284413844148441584416844178441884419844208442184422844238442484425844268442784428844298443084431844328443384434844358443684437844388443984440844418444284443844448444584446844478444884449844508445184452844538445484455844568445784458844598446084461844628446384464844658446684467844688446984470844718447284473844748447584476844778447884479844808448184482844838448484485844868448784488844898449084491844928449384494844958449684497844988449984500845018450284503845048450584506845078450884509845108451184512845138451484515845168451784518845198452084521845228452384524845258452684527845288452984530845318453284533845348453584536845378453884539845408454184542845438454484545845468454784548845498455084551845528455384554845558455684557845588455984560845618456284563845648456584566845678456884569845708457184572845738457484575845768457784578845798458084581845828458384584845858458684587845888458984590845918459284593845948459584596845978459884599846008460184602846038460484605846068460784608846098461084611846128461384614846158461684617846188461984620846218462284623846248462584626846278462884629846308463184632846338463484635846368463784638846398464084641846428464384644846458464684647846488464984650846518465284653846548465584656846578465884659846608466184662846638466484665846668466784668846698467084671846728467384674846758467684677846788467984680846818468284683846848468584686846878468884689846908469184692846938469484695846968469784698846998470084701847028470384704847058470684707847088470984710847118471284713847148471584716847178471884719847208472184722847238472484725847268472784728847298473084731847328473384734847358473684737847388473984740847418474284743847448474584746847478474884749847508475184752847538475484755847568475784758847598476084761847628476384764847658476684767847688476984770847718477284773847748477584776847778477884779847808478184782847838478484785847868478784788847898479084791847928479384794847958479684797847988479984800848018480284803848048480584806848078480884809848108481184812848138481484815848168481784818848198482084821848228482384824848258482684827848288482984830848318483284833848348483584836848378483884839848408484184842848438484484845848468484784848848498485084851848528485384854848558485684857848588485984860848618486284863848648486584866848678486884869848708487184872848738487484875848768487784878848798488084881848828488384884848858488684887848888488984890848918489284893848948489584896848978489884899849008490184902849038490484905849068490784908849098491084911849128491384914849158491684917849188491984920849218492284923849248492584926849278492884929849308493184932849338493484935849368493784938849398494084941849428494384944849458494684947849488494984950849518495284953849548495584956849578495884959849608496184962849638496484965849668496784968849698497084971849728497384974849758497684977849788497984980849818498284983849848498584986849878498884989849908499184992849938499484995849968499784998849998500085001850028500385004850058500685007850088500985010850118501285013850148501585016850178501885019850208502185022850238502485025850268502785028850298503085031850328503385034850358503685037850388503985040850418504285043850448504585046850478504885049850508505185052850538505485055850568505785058850598506085061850628506385064850658506685067850688506985070850718507285073850748507585076850778507885079850808508185082850838508485085850868508785088850898509085091850928509385094850958509685097850988509985100851018510285103851048510585106851078510885109851108511185112851138511485115851168511785118851198512085121851228512385124851258512685127851288512985130851318513285133851348513585136851378513885139851408514185142851438514485145851468514785148851498515085151851528515385154851558515685157851588515985160851618516285163851648516585166851678516885169851708517185172851738517485175851768517785178851798518085181851828518385184851858518685187851888518985190851918519285193851948519585196851978519885199852008520185202852038520485205852068520785208852098521085211852128521385214852158521685217852188521985220852218522285223852248522585226852278522885229852308523185232852338523485235852368523785238852398524085241852428524385244852458524685247852488524985250852518525285253852548525585256852578525885259852608526185262852638526485265852668526785268852698527085271852728527385274852758527685277852788527985280852818528285283852848528585286852878528885289852908529185292852938529485295852968529785298852998530085301853028530385304853058530685307853088530985310853118531285313853148531585316853178531885319853208532185322853238532485325853268532785328853298533085331853328533385334853358533685337853388533985340853418534285343853448534585346853478534885349853508535185352853538535485355853568535785358853598536085361853628536385364853658536685367853688536985370853718537285373853748537585376853778537885379853808538185382853838538485385853868538785388853898539085391853928539385394853958539685397853988539985400854018540285403854048540585406854078540885409854108541185412854138541485415854168541785418854198542085421854228542385424854258542685427854288542985430854318543285433854348543585436854378543885439854408544185442854438544485445854468544785448854498545085451854528545385454854558545685457854588545985460854618546285463854648546585466854678546885469854708547185472854738547485475854768547785478854798548085481854828548385484854858548685487854888548985490854918549285493854948549585496854978549885499855008550185502855038550485505855068550785508855098551085511855128551385514855158551685517855188551985520855218552285523855248552585526855278552885529855308553185532855338553485535855368553785538855398554085541855428554385544855458554685547855488554985550855518555285553855548555585556855578555885559855608556185562855638556485565855668556785568855698557085571855728557385574855758557685577855788557985580855818558285583855848558585586855878558885589855908559185592855938559485595855968559785598855998560085601856028560385604856058560685607856088560985610856118561285613856148561585616856178561885619856208562185622856238562485625856268562785628856298563085631856328563385634856358563685637856388563985640856418564285643856448564585646856478564885649856508565185652856538565485655856568565785658856598566085661856628566385664856658566685667856688566985670856718567285673856748567585676856778567885679856808568185682856838568485685856868568785688856898569085691856928569385694856958569685697856988569985700857018570285703857048570585706857078570885709857108571185712857138571485715857168571785718857198572085721857228572385724857258572685727857288572985730857318573285733857348573585736857378573885739857408574185742857438574485745857468574785748857498575085751857528575385754857558575685757857588575985760857618576285763857648576585766857678576885769857708577185772857738577485775857768577785778857798578085781857828578385784857858578685787857888578985790857918579285793857948579585796857978579885799858008580185802858038580485805858068580785808858098581085811858128581385814858158581685817858188581985820858218582285823858248582585826858278582885829858308583185832858338583485835858368583785838858398584085841858428584385844858458584685847858488584985850858518585285853858548585585856858578585885859858608586185862858638586485865858668586785868858698587085871858728587385874858758587685877858788587985880858818588285883858848588585886858878588885889858908589185892858938589485895858968589785898858998590085901859028590385904859058590685907859088590985910859118591285913859148591585916859178591885919859208592185922859238592485925859268592785928859298593085931859328593385934859358593685937859388593985940859418594285943859448594585946859478594885949859508595185952859538595485955859568595785958859598596085961859628596385964859658596685967859688596985970859718597285973859748597585976859778597885979859808598185982859838598485985859868598785988859898599085991859928599385994859958599685997859988599986000860018600286003860048600586006860078600886009860108601186012860138601486015860168601786018860198602086021860228602386024860258602686027860288602986030860318603286033860348603586036860378603886039860408604186042860438604486045860468604786048860498605086051860528605386054860558605686057860588605986060860618606286063860648606586066860678606886069860708607186072860738607486075860768607786078860798608086081860828608386084860858608686087860888608986090860918609286093860948609586096860978609886099861008610186102861038610486105861068610786108861098611086111861128611386114861158611686117861188611986120861218612286123861248612586126861278612886129861308613186132861338613486135861368613786138861398614086141861428614386144861458614686147861488614986150861518615286153861548615586156861578615886159861608616186162861638616486165861668616786168861698617086171861728617386174861758617686177861788617986180861818618286183861848618586186861878618886189861908619186192861938619486195861968619786198861998620086201862028620386204862058620686207862088620986210862118621286213862148621586216862178621886219862208622186222862238622486225862268622786228862298623086231862328623386234862358623686237862388623986240862418624286243862448624586246862478624886249862508625186252862538625486255862568625786258862598626086261862628626386264862658626686267862688626986270862718627286273862748627586276862778627886279862808628186282862838628486285862868628786288862898629086291862928629386294862958629686297862988629986300863018630286303863048630586306863078630886309863108631186312863138631486315863168631786318863198632086321863228632386324863258632686327863288632986330863318633286333863348633586336863378633886339863408634186342863438634486345863468634786348863498635086351863528635386354863558635686357863588635986360863618636286363863648636586366863678636886369863708637186372863738637486375863768637786378863798638086381863828638386384863858638686387863888638986390863918639286393863948639586396863978639886399864008640186402864038640486405864068640786408864098641086411864128641386414864158641686417864188641986420864218642286423864248642586426864278642886429864308643186432864338643486435864368643786438864398644086441864428644386444864458644686447864488644986450864518645286453864548645586456864578645886459864608646186462864638646486465864668646786468864698647086471864728647386474864758647686477864788647986480864818648286483864848648586486864878648886489864908649186492864938649486495864968649786498864998650086501865028650386504865058650686507865088650986510865118651286513865148651586516865178651886519865208652186522865238652486525865268652786528865298653086531865328653386534865358653686537865388653986540865418654286543865448654586546865478654886549865508655186552865538655486555865568655786558865598656086561865628656386564865658656686567865688656986570865718657286573865748657586576865778657886579865808658186582865838658486585865868658786588865898659086591865928659386594865958659686597865988659986600866018660286603866048660586606866078660886609866108661186612866138661486615866168661786618866198662086621866228662386624866258662686627866288662986630866318663286633866348663586636866378663886639866408664186642866438664486645866468664786648866498665086651866528665386654866558665686657866588665986660866618666286663866648666586666866678666886669866708667186672866738667486675866768667786678866798668086681866828668386684866858668686687866888668986690866918669286693866948669586696866978669886699867008670186702867038670486705867068670786708867098671086711867128671386714867158671686717867188671986720867218672286723867248672586726867278672886729867308673186732867338673486735867368673786738867398674086741867428674386744867458674686747867488674986750867518675286753867548675586756867578675886759867608676186762867638676486765867668676786768867698677086771867728677386774867758677686777867788677986780867818678286783867848678586786867878678886789867908679186792867938679486795867968679786798867998680086801868028680386804868058680686807868088680986810868118681286813868148681586816868178681886819868208682186822868238682486825868268682786828868298683086831868328683386834868358683686837868388683986840868418684286843868448684586846868478684886849868508685186852868538685486855868568685786858868598686086861868628686386864868658686686867868688686986870868718687286873868748687586876868778687886879868808688186882868838688486885868868688786888868898689086891868928689386894868958689686897868988689986900869018690286903869048690586906869078690886909869108691186912869138691486915869168691786918869198692086921869228692386924869258692686927869288692986930869318693286933869348693586936869378693886939869408694186942869438694486945869468694786948869498695086951869528695386954869558695686957869588695986960869618696286963869648696586966869678696886969869708697186972869738697486975869768697786978869798698086981869828698386984869858698686987869888698986990869918699286993869948699586996869978699886999870008700187002870038700487005870068700787008870098701087011870128701387014870158701687017870188701987020870218702287023870248702587026870278702887029870308703187032870338703487035870368703787038870398704087041870428704387044870458704687047870488704987050870518705287053870548705587056870578705887059870608706187062870638706487065870668706787068870698707087071870728707387074870758707687077870788707987080870818708287083870848708587086870878708887089870908709187092870938709487095870968709787098870998710087101871028710387104871058710687107871088710987110871118711287113871148711587116871178711887119871208712187122871238712487125871268712787128871298713087131871328713387134871358713687137871388713987140871418714287143871448714587146871478714887149871508715187152871538715487155871568715787158871598716087161871628716387164871658716687167871688716987170871718717287173871748717587176871778717887179871808718187182871838718487185871868718787188871898719087191871928719387194871958719687197871988719987200872018720287203872048720587206872078720887209872108721187212872138721487215872168721787218872198722087221872228722387224872258722687227872288722987230872318723287233872348723587236872378723887239872408724187242872438724487245872468724787248872498725087251872528725387254872558725687257872588725987260872618726287263872648726587266872678726887269872708727187272872738727487275872768727787278872798728087281872828728387284872858728687287872888728987290872918729287293872948729587296872978729887299873008730187302873038730487305873068730787308873098731087311873128731387314873158731687317873188731987320873218732287323873248732587326873278732887329873308733187332873338733487335873368733787338873398734087341873428734387344873458734687347873488734987350873518735287353873548735587356873578735887359873608736187362873638736487365873668736787368873698737087371873728737387374873758737687377873788737987380873818738287383873848738587386873878738887389873908739187392873938739487395873968739787398873998740087401874028740387404874058740687407874088740987410874118741287413874148741587416874178741887419874208742187422874238742487425874268742787428874298743087431874328743387434874358743687437874388743987440874418744287443874448744587446874478744887449874508745187452874538745487455874568745787458874598746087461874628746387464874658746687467874688746987470874718747287473874748747587476874778747887479874808748187482874838748487485874868748787488874898749087491874928749387494874958749687497874988749987500875018750287503875048750587506875078750887509875108751187512875138751487515875168751787518875198752087521875228752387524875258752687527875288752987530875318753287533875348753587536875378753887539875408754187542875438754487545875468754787548875498755087551875528755387554875558755687557875588755987560875618756287563875648756587566875678756887569875708757187572875738757487575875768757787578875798758087581875828758387584875858758687587875888758987590875918759287593875948759587596875978759887599876008760187602876038760487605876068760787608876098761087611876128761387614876158761687617876188761987620876218762287623876248762587626876278762887629876308763187632876338763487635876368763787638876398764087641876428764387644876458764687647876488764987650876518765287653876548765587656876578765887659876608766187662876638766487665876668766787668876698767087671876728767387674876758767687677876788767987680876818768287683876848768587686876878768887689876908769187692876938769487695876968769787698876998770087701877028770387704877058770687707877088770987710877118771287713877148771587716877178771887719877208772187722877238772487725877268772787728877298773087731877328773387734877358773687737877388773987740877418774287743877448774587746877478774887749877508775187752877538775487755877568775787758877598776087761877628776387764877658776687767877688776987770877718777287773877748777587776877778777887779877808778187782877838778487785877868778787788877898779087791877928779387794877958779687797877988779987800878018780287803878048780587806878078780887809878108781187812878138781487815878168781787818878198782087821878228782387824878258782687827878288782987830878318783287833878348783587836878378783887839878408784187842878438784487845878468784787848878498785087851878528785387854878558785687857878588785987860878618786287863878648786587866878678786887869878708787187872878738787487875878768787787878878798788087881878828788387884878858788687887878888788987890878918789287893878948789587896878978789887899879008790187902879038790487905879068790787908879098791087911879128791387914879158791687917879188791987920879218792287923879248792587926879278792887929879308793187932879338793487935879368793787938879398794087941879428794387944879458794687947879488794987950879518795287953879548795587956879578795887959879608796187962879638796487965879668796787968879698797087971879728797387974879758797687977879788797987980879818798287983879848798587986879878798887989879908799187992879938799487995879968799787998879998800088001880028800388004880058800688007880088800988010880118801288013880148801588016880178801888019880208802188022880238802488025880268802788028880298803088031880328803388034880358803688037880388803988040880418804288043880448804588046880478804888049880508805188052880538805488055880568805788058880598806088061880628806388064880658806688067880688806988070880718807288073880748807588076880778807888079880808808188082880838808488085880868808788088880898809088091880928809388094880958809688097880988809988100881018810288103881048810588106881078810888109881108811188112881138811488115881168811788118881198812088121881228812388124881258812688127881288812988130881318813288133881348813588136881378813888139881408814188142881438814488145881468814788148881498815088151881528815388154881558815688157881588815988160881618816288163881648816588166881678816888169881708817188172881738817488175881768817788178881798818088181881828818388184881858818688187881888818988190881918819288193881948819588196881978819888199882008820188202882038820488205882068820788208882098821088211882128821388214882158821688217882188821988220882218822288223882248822588226882278822888229882308823188232882338823488235882368823788238882398824088241882428824388244882458824688247882488824988250882518825288253882548825588256882578825888259882608826188262882638826488265882668826788268882698827088271882728827388274882758827688277882788827988280882818828288283882848828588286882878828888289882908829188292882938829488295882968829788298882998830088301883028830388304883058830688307883088830988310883118831288313883148831588316883178831888319883208832188322883238832488325883268832788328883298833088331883328833388334883358833688337883388833988340883418834288343883448834588346883478834888349883508835188352883538835488355883568835788358883598836088361883628836388364883658836688367883688836988370883718837288373883748837588376883778837888379883808838188382883838838488385883868838788388883898839088391883928839388394883958839688397883988839988400884018840288403884048840588406884078840888409884108841188412884138841488415884168841788418884198842088421884228842388424884258842688427884288842988430884318843288433884348843588436884378843888439884408844188442884438844488445884468844788448884498845088451884528845388454884558845688457884588845988460884618846288463884648846588466884678846888469884708847188472884738847488475884768847788478884798848088481884828848388484884858848688487884888848988490884918849288493884948849588496884978849888499885008850188502885038850488505885068850788508885098851088511885128851388514885158851688517885188851988520885218852288523885248852588526885278852888529885308853188532885338853488535885368853788538885398854088541885428854388544885458854688547885488854988550885518855288553885548855588556885578855888559885608856188562885638856488565885668856788568885698857088571885728857388574885758857688577885788857988580885818858288583885848858588586885878858888589885908859188592885938859488595885968859788598885998860088601886028860388604886058860688607886088860988610886118861288613886148861588616886178861888619886208862188622886238862488625886268862788628886298863088631886328863388634886358863688637886388863988640886418864288643886448864588646886478864888649886508865188652886538865488655886568865788658886598866088661886628866388664886658866688667886688866988670886718867288673886748867588676886778867888679886808868188682886838868488685886868868788688886898869088691886928869388694886958869688697886988869988700887018870288703887048870588706887078870888709887108871188712887138871488715887168871788718887198872088721887228872388724887258872688727887288872988730887318873288733887348873588736887378873888739887408874188742887438874488745887468874788748887498875088751887528875388754887558875688757887588875988760887618876288763887648876588766887678876888769887708877188772887738877488775887768877788778887798878088781887828878388784887858878688787887888878988790887918879288793887948879588796887978879888799888008880188802888038880488805888068880788808888098881088811888128881388814888158881688817888188881988820888218882288823888248882588826888278882888829888308883188832888338883488835888368883788838888398884088841888428884388844888458884688847888488884988850888518885288853888548885588856888578885888859888608886188862888638886488865888668886788868888698887088871888728887388874888758887688877888788887988880888818888288883888848888588886888878888888889888908889188892888938889488895888968889788898888998890088901889028890388904889058890688907889088890988910889118891288913889148891588916889178891888919889208892188922889238892488925889268892788928889298893088931889328893388934889358893688937889388893988940889418894288943889448894588946889478894888949889508895188952889538895488955889568895788958889598896088961889628896388964889658896688967889688896988970889718897288973889748897588976889778897888979889808898188982889838898488985889868898788988889898899088991889928899388994889958899688997889988899989000890018900289003890048900589006890078900889009890108901189012890138901489015890168901789018890198902089021890228902389024890258902689027890288902989030890318903289033890348903589036890378903889039890408904189042890438904489045890468904789048890498905089051890528905389054890558905689057890588905989060890618906289063890648906589066890678906889069890708907189072890738907489075890768907789078890798908089081890828908389084890858908689087890888908989090890918909289093890948909589096890978909889099891008910189102891038910489105891068910789108891098911089111891128911389114891158911689117891188911989120891218912289123891248912589126891278912889129891308913189132891338913489135891368913789138891398914089141891428914389144891458914689147891488914989150891518915289153891548915589156891578915889159891608916189162891638916489165891668916789168891698917089171891728917389174891758917689177891788917989180891818918289183
  1. diff -urN linux-2.4.26/Documentation/Configure.help linux-2.4.26-vrs1/Documentation/Configure.help
  2. --- linux-2.4.26/Documentation/Configure.help 2004-04-19 11:44:14.000000000 +0100
  3. +++ linux-2.4.26-vrs1/Documentation/Configure.help 2004-04-18 21:47:49.000000000 +0100
  4. @@ -4879,6 +4879,13 @@
  5. Say Y to enable support for Permedia2 AGP frame buffer card from
  6. 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus.
  7. +Permedia3 support (EXPERIMENTAL)
  8. +CONFIG_FB_PM3
  9. + This is the frame buffer device driver for the 3DLabs Permedia3
  10. + chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
  11. + similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
  12. + and maybe other boards.
  13. +
  14. Phase5 CVisionPPC/BVisionPPC support
  15. CONFIG_FB_PM2_CVPPC
  16. Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC
  17. @@ -13213,6 +13220,17 @@
  18. The module will be called tmspci.o. If you want to compile it
  19. as a module, say M here and read <file:Documentation/modules.txt>.
  20. +Altera ether00 support
  21. +CONFIG_ETHER00
  22. + This is the driver for Altera's ether00 ethernet mac IP core. Say
  23. + Y here if you want to build support for this into the kernel. It
  24. + is also available as a module (say M here) that can be inserted/
  25. + removed from the kernel at the same time as the PLD is configured.
  26. + If this driver is running on an epxa10 development board then it
  27. + will generate a suitable hw address based on the board serial
  28. + number (MTD support is required for this). Otherwise you will
  29. + need to set a suitable hw address using ifconfig.
  30. +
  31. Generic TMS380 ISA support
  32. CONFIG_TMSISA
  33. This tms380 module supports generic TMS380-based ISA cards.
  34. @@ -15157,6 +15175,16 @@
  35. support" be compiled as a module for this driver to be used
  36. properly.
  37. +Altera's uart00 serial driver
  38. +CONFIG_SERIAL_UART00
  39. + Say Y here if you want to use the hard logic uart on Excalibur. This
  40. + driver also supports soft logic implentations of this uart core.
  41. +
  42. +Serial console on uart00
  43. +CONFIG_SERIAL_UART00_CONSOLE
  44. + Say Y here if you want to support a serial console on an Excalibur
  45. + hard logic uart or uart00 IP core.
  46. +
  47. USB ConnectTech WhiteHEAT Serial Driver
  48. CONFIG_USB_SERIAL_WHITEHEAT
  49. Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
  50. @@ -19173,6 +19201,20 @@
  51. <file:Documentation/modules.txt>.
  52. The module will be called i2c-velleman.o.
  53. +Guide GPIO adapter
  54. +CONFIG_I2C_GUIDE
  55. + This supports the Iders GUIDE I2C bit-bashing adapter. If you have
  56. + selected the GUIDE A07 as your ARM system type, you cannot deselect
  57. + this option, as it is required for proper operation of the GUIDE.
  58. +
  59. + This interface uses /dev/i2c-0 (major 89, minor 0).
  60. +
  61. + Say Y if you own such an adapter.
  62. +
  63. + This driver is also available as a module. If you want to compile
  64. + it as a module, say M here and read Documentation/modules.txt. The
  65. + module will be called i2c-guide.o.
  66. +
  67. I2C PCF 8584 interfaces
  68. CONFIG_I2C_ALGOPCF
  69. This allows you to use a range of I2C adapters called PCF adapters.
  70. @@ -20310,6 +20352,17 @@
  71. <file:Documentation/modules.txt>. The module will be called
  72. softdog.o.
  73. +SA1100 Internal Watchdog
  74. +CONFIG_SA1100_WATCHDOG
  75. + Watchdog timer embedded into SA11x0 chips. This will reboot your
  76. + system when timeout is reached.
  77. + NOTE, that once enabled, this timer cannot be disabled.
  78. +
  79. + This driver is also available as a module ( = code which can be
  80. + inserted in and removed from the running kernel whenever you want).
  81. + If you want to compile it as a module, say M here and read
  82. + Documentation/modules.txt. The module will be called sa1100_wdt.o.
  83. +
  84. Berkshire Products PC Watchdog
  85. CONFIG_PCWATCHDOG
  86. This is the driver for the Berkshire Products PC Watchdog card.
  87. @@ -21971,6 +22024,30 @@
  88. from RME. If you want to acess advanced features of the card, read
  89. Documentation/sound/rme96xx.
  90. +Assabet audio (UDA1341) support
  91. +CONFIG_SOUND_ASSABET_UDA1341
  92. + Say Y or M if you have an Intel Assabet evaluation board and want to
  93. + use the Philips UDA 1341 audio chip (the one that drives the stereo
  94. + audio output) on the SA1100 SSP port.
  95. +
  96. +Compaq iPAQ audio support
  97. +CONFIG_SOUND_H3600_UDA1341
  98. + Say Y or M if you have a Compaq iPaq handheld computer and want to
  99. + use its Philips UDA 1341 audio chip.
  100. +
  101. +Audio support for SA1111/UDA1341
  102. +CONFIG_SOUND_SA1111_UDA1341
  103. + Say Y or M if you have an SA11x0 system with a Philips UDA 1341
  104. + connected to the SA11x1. An example of such a system is the Intel
  105. + Assabet evaluation board connected to a Neponset expansion board.
  106. +
  107. +Generic DAC on the SA11x0 SSP port
  108. +CONFIG_SOUND_SA1100SSP
  109. + Say Y or M if you have an SA-11x0 system with a DAC on the SSP port.
  110. + The LART has an Burr-Brown PCM 1710 digital to analog convertor on
  111. + the SSP port, so you want to say Y or M for the LART. It might work
  112. + on other SA-1100 platforms, too, but this is not tested.
  113. +
  114. Are you using a crosscompiler
  115. CONFIG_CROSSCOMPILE
  116. Say Y here if you are compiling the kernel on a different
  117. @@ -25674,6 +25751,20 @@
  118. Say Y if configuring for a Pangolin.
  119. Say N otherwise.
  120. +Shannon
  121. +CONFIG_SA1100_SHANNON
  122. + The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
  123. + limited edition webphone produced by Philips. The Shannon is a SA1100
  124. + platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots,
  125. + and a telco interface.
  126. +
  127. +Simputer
  128. +CONFIG_SA1100_SIMPUTER
  129. + Say Y here if you are using an Intel(R) StrongARM(R) SA-1110
  130. + based Simputer. See http://www.simputer.org/ for information
  131. + on the Simputer. The Simputer software is actively maintained
  132. + by PicoPeta Simputers Pvt. Ltd. (http://www.picopeta.com)
  133. +
  134. Victor
  135. CONFIG_SA1100_VICTOR
  136. Say Y here if you are using a Visu Aide Intel(R) StrongARM(R)
  137. @@ -25681,6 +25772,14 @@
  138. <http://www.visuaide.com/pagevictor.en.html> for information on
  139. this system.
  140. +Radisys Corp. Tulsa
  141. +CONFIG_SA1100_PFS168
  142. + The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based
  143. + computer which includes the SA-1111 Microprocessor Companion Chip and other
  144. + custom I/O designed to add connectivity and multimedia features for vending
  145. + and business machine applications. Say Y here if you require support for
  146. + this target.
  147. +
  148. # Choice: cerf_ram
  149. Cerf on-board RAM size
  150. CONFIG_SA1100_CERF_8MB
  151. @@ -25748,37 +25847,65 @@
  152. Say Y if you want support for the ARM920T processor.
  153. Otherwise, say N.
  154. -Support ARM1020 processor
  155. -CONFIG_CPU_ARM1020
  156. - The ARM1020 is the cached version of the ARM10 processor,
  157. - with an addition of a floating-point unit.
  158. +Support ARM922T processor
  159. +CONFIG_CPU_ARM922T
  160. + The ARM922T is a version of the ARM920T, but with smaller
  161. + instruction and data caches. It is used in Altera's
  162. + Excalibur XA device family.
  163. - Say Y if you want support for the ARM1020 processor.
  164. + Say Y if you want support for the ARM922T processor.
  165. Otherwise, say N.
  166. -Disable I-Cache
  167. +Disable instruction cache
  168. CONFIG_CPU_ICACHE_DISABLE
  169. - Say Y here to disable the processor instruction cache. Unless
  170. - you have a reason not to or are unsure, say N.
  171. + Say Y here to disable the processor instruction cache. Unless
  172. + you have a reason to do this, say N.
  173. -Disable D-Cache
  174. +Disable data cache
  175. CONFIG_CPU_DCACHE_DISABLE
  176. - Say Y here to disable the processor data cache. Unless
  177. - you have a reason not to or are unsure, say N.
  178. + Say Y here to disable the processor data cache. Unless
  179. + you have a reason to do this, say N.
  180. -Force write through D-cache
  181. +Use data cache in writethrough mode
  182. CONFIG_CPU_DCACHE_WRITETHROUGH
  183. - Say Y here to use the data cache in write-through mode. Unless you
  184. - specifically require this or are unsure, say N.
  185. + Say Y here to use the data cache in writethough mode. Unless you
  186. + specifically require this, say N.
  187. +
  188. +Support ARM1020 processor
  189. +CONFIG_CPU_ARM1020
  190. + The ARM1020 is the 32K cached version of the ARM10 processor,
  191. + with an addition of a floating-point unit.
  192. +
  193. + Say Y if you want support for the ARM1020 processor.
  194. + Otherwise, say N.
  195. +
  196. +Support ARM1022 processor
  197. +CONFIG_CPU_ARM1022
  198. + The ARM1022E is the 16K cached version of the ARM10 processor,
  199. + with an addition of a floating-point unit.
  200. +
  201. + Say Y if you want support for the ARM1022 processor.
  202. + Otherwise, say N.
  203. -Round robin I and D cache replacement algorithm
  204. +Force round-robin cache line replacement
  205. CONFIG_CPU_CACHE_ROUND_ROBIN
  206. - Say Y here to use the predictable round-robin cache replacement
  207. - policy. Unless you specifically require this or are unsure, say N.
  208. + Say Y here to force the caches to use a round-robin
  209. + algorithm when picking a cache line to evict. Unless you
  210. + specifically require this, say N.
  211. +
  212. +Disable the write buffer
  213. +CONFIG_CPU_WB_DISABLE
  214. + Say Y here to turn off the write buffer (if possible)
  215. + Unless you specifically require this, say N. Note that
  216. + not all ARM processors allow the write buffer to be
  217. + disabled.
  218. Disable branch prediction
  219. CONFIG_CPU_BPREDICT_DISABLE
  220. - Say Y here to disable branch prediction. If unsure, say N.
  221. + The ARM10 family of processors support branch prediction,
  222. + which can significantly speed up execution of loops.
  223. + Say Y here to disable branch prediction. Unless you
  224. + specifically require this, say N.
  225. Compressed boot loader in ROM/flash
  226. CONFIG_ZBOOT_ROM
  227. @@ -25825,6 +25952,11 @@
  228. Say Y here if you are using the inhand electronics OmniMeter. See
  229. <http://www.inhandelectronics.com/html/omni1.html> for details.
  230. +HP Laboratories BadgePAD 4
  231. +CONFIG_SA1100_BADGE4
  232. + Say Y here if you want to build a kernel for the HP Laboratories
  233. + BadgePAD 4.
  234. +
  235. Load kernel using Angel Debug Monitor
  236. CONFIG_ANGELBOOT
  237. Say Y if you plan to load the kernel using Angel, ARM Ltd's target
  238. @@ -25837,6 +25969,15 @@
  239. board includes 2 serial ports, Ethernet, IRDA, and expansion headers.
  240. It comes with 16 MB SDRAM and 8 MB flash ROM.
  241. +GUIDEA07
  242. +CONFIG_ARCH_GUIDEA07
  243. + Say Y if you are using a GUIDE (A07) board.
  244. +
  245. + This board is based on the cs89712 processor and shares much common
  246. + hardware with the CDB89712 configuration. When you select this
  247. + option and the CDB89712 becomes enabled also, don't worry. It's
  248. + supposed to be that way.
  249. +
  250. CLPS-711X internal ROM bootstrap
  251. CONFIG_EP72XX_ROM_BOOT
  252. If you say Y here, your CLPS711x-based kernel will use the bootstrap
  253. @@ -25865,19 +26006,27 @@
  254. You may say N here if you are going to load the Acorn FPEmulator
  255. early in the bootup.
  256. +Math emulation 80-bit support
  257. +CONFIG_FPE_NWFPE_XP
  258. + Say Y to include 80-bit support in the kernel floating-point
  259. + emulator. Otherwise, only 32 and 64-bit support is compiled in.
  260. + Note that gcc does not generate 80-bit operations by default,
  261. + so in most cases this option only enlarges the size of the
  262. + floating point emulator without any good reason.
  263. +
  264. + You almost surely want to say N here.
  265. +
  266. FastFPE math emulation
  267. CONFIG_FPE_FASTFPE
  268. Say Y here to include the FAST floating point emulator in the kernel.
  269. - This is an experimental much faster emulator which has only 32 bit
  270. + This is an experimental much faster emulator which now also has full
  271. precision for the mantissa. It does not support any exceptions.
  272. - This makes it very simple, it is approximately 4-8 times faster than
  273. - NWFPE.
  274. + It is very simple, and approximately 3-6 times faster than NWFPE.
  275. - It should be sufficient for most programs. It is definitely not
  276. - suitable if you do scientific calculations that need double
  277. - precision for iteration formulas that sum up lots of very small
  278. - numbers. If you do not feel you need a faster FP emulation you
  279. - should better choose NWFPE.
  280. + It should be sufficient for most programs. It may be not suitable
  281. + for scientific calculations, but you have to check this for yourself.
  282. + If you do not feel you need a faster FP emulation you should better
  283. + choose NWFPE.
  284. It is also possible to say M to build the emulator as a module
  285. (fastfpe.o). But keep in mind that you should only load the FP
  286. diff -urN linux-2.4.26/Documentation/arm/Porting linux-2.4.26-vrs1/Documentation/arm/Porting
  287. --- linux-2.4.26/Documentation/arm/Porting 1970-01-01 01:00:00.000000000 +0100
  288. +++ linux-2.4.26-vrs1/Documentation/arm/Porting 2004-02-22 17:29:23.000000000 +0000
  289. @@ -0,0 +1,135 @@
  290. +Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html
  291. +
  292. +Initial definitions
  293. +-------------------
  294. +
  295. +The following symbol definitions rely on you knowing the translation that
  296. +__virt_to_phys() does for your machine. This macro converts the passed
  297. +virtual address to a physical address. Normally, it is simply:
  298. +
  299. + phys = virt - PAGE_OFFSET + PHYS_OFFSET
  300. +
  301. +
  302. +Decompressor Symbols
  303. +--------------------
  304. +
  305. +ZTEXTADDR
  306. + Start address of decompressor. There's no point in talking about
  307. + virtual or physical addresses here, since the MMU will be off at
  308. + the time when you call the decompressor code. You normally call
  309. + the kernel at this address to start it booting. This doesn't have
  310. + to be located in RAM, it can be in flash or other read-only or
  311. + read-write addressable medium.
  312. +
  313. +ZBSSADDR
  314. + Start address of zero-initialised work area for the decompressor.
  315. + This must be pointing at RAM. The decompressor will zero initialise
  316. + this for you. Again, the MMU will be off.
  317. +
  318. +ZRELADDR
  319. + This is the address where the decompressed kernel will be written,
  320. + and eventually executed. The following constraint must be valid:
  321. +
  322. + __virt_to_phys(TEXTADDR) == ZRELADDR
  323. +
  324. + The initial part of the kernel is carefully coded to be position
  325. + independent.
  326. +
  327. +INITRD_PHYS
  328. + Physical address to place the initial RAM disk. Only relevant if
  329. + you are using the bootpImage stuff (which only works on the old
  330. + struct param_struct).
  331. +
  332. +INITRD_VIRT
  333. + Virtual address of the initial RAM disk. The following constraint
  334. + must be valid:
  335. +
  336. + __virt_to_phys(INITRD_VIRT) == INITRD_PHYS
  337. +
  338. +PARAMS_PHYS
  339. + Physical address of the struct param_struct or tag list, giving the
  340. + kernel various parameters about its execution environment.
  341. +
  342. +
  343. +Kernel Symbols
  344. +--------------
  345. +
  346. +PHYS_OFFSET
  347. + Physical start address of the first bank of RAM.
  348. +
  349. +PAGE_OFFSET
  350. + Virtual start address of the first bank of RAM. During the kernel
  351. + boot phase, virtual address PAGE_OFFSET will be mapped to physical
  352. + address PHYS_OFFSET, along with any other mappings you supply.
  353. + This should be the same value as TASK_SIZE.
  354. +
  355. +TASK_SIZE
  356. + The maximum size of a user process in bytes. Since user space
  357. + always starts at zero, this is the maximum address that a user
  358. + process can access+1. The user space stack grows down from this
  359. + address.
  360. +
  361. + Any virtual address below TASK_SIZE is deemed to be user process
  362. + area, and therefore managed dynamically on a process by process
  363. + basis by the kernel. I'll call this the user segment.
  364. +
  365. + Anything above TASK_SIZE is common to all processes. I'll call
  366. + this the kernel segment.
  367. +
  368. + (In other words, you can't put IO mappings below TASK_SIZE, and
  369. + hence PAGE_OFFSET).
  370. +
  371. +TEXTADDR
  372. + Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.
  373. + This is where the kernel image ends up. With the latest kernels,
  374. + it must be located at 32768 bytes into a 128MB region. Previous
  375. + kernels placed a restriction of 256MB here.
  376. +
  377. +DATAADDR
  378. + Virtual address for the kernel data segment. Must not be defined
  379. + when using the decompressor.
  380. +
  381. +VMALLOC_START
  382. +VMALLOC_END
  383. + Virtual addresses bounding the vmalloc() area. There must not be
  384. + any static mappings in this area; vmalloc will overwrite them.
  385. + The addresses must also be in the kernel segment (see above).
  386. + Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the
  387. + last virtual RAM address (found using variable high_memory).
  388. +
  389. +VMALLOC_OFFSET
  390. + Offset normally incorporated into VMALLOC_START to provide a hole
  391. + between virtual RAM and the vmalloc area. We do this to allow
  392. + out of bounds memory accesses (eg, something writing off the end
  393. + of the mapped memory map) to be caught. Normally set to 8MB.
  394. +
  395. +Architecture Specific Macros
  396. +----------------------------
  397. +
  398. +BOOT_MEM(pram,pio,vio)
  399. + `pram' specifies the physical start address of RAM. Must always
  400. + be present, and should be the same as PHYS_OFFSET.
  401. +
  402. + `pio' is the physical address of an 8MB region containing IO for
  403. + use with the debugging macros in arch/arm/kernel/debug-armv.S.
  404. +
  405. + `vio' is the virtual address of the 8MB debugging region.
  406. +
  407. + It is expected that the debugging region will be re-initialised
  408. + by the architecture specific code later in the code (via the
  409. + MAPIO function).
  410. +
  411. +BOOT_PARAMS
  412. + Same as, and see PARAMS_PHYS.
  413. +
  414. +FIXUP(func)
  415. + Machine specific fixups, run before memory subsystems have been
  416. + initialised.
  417. +
  418. +MAPIO(func)
  419. + Machine specific function to map IO areas (including the debug
  420. + region above).
  421. +
  422. +INITIRQ(func)
  423. + Machine specific function to initialise interrupts.
  424. +
  425. diff -urN linux-2.4.26/Documentation/arm/mem_alignment linux-2.4.26-vrs1/Documentation/arm/mem_alignment
  426. --- linux-2.4.26/Documentation/arm/mem_alignment 1970-01-01 01:00:00.000000000 +0100
  427. +++ linux-2.4.26-vrs1/Documentation/arm/mem_alignment 2004-04-09 15:09:44.000000000 +0100
  428. @@ -0,0 +1,58 @@
  429. +Too many problems poped up because of unnoticed misaligned memory access in
  430. +kernel code lately. Therefore the alignment fixup is now unconditionally
  431. +configured in for SA11x0 based targets. According to Alan Cox, this is a
  432. +bad idea to configure it out, but Russell King has some good reasons for
  433. +doing so on some f***ed up ARM architectures like the EBSA110. However
  434. +this is not the case on many design I'm aware of, like all SA11x0 based
  435. +ones.
  436. +
  437. +Of course this is a bad idea to rely on the alignment trap to perform
  438. +unaligned memory access in general. If those access are predictable, you
  439. +are better to use the macros provided by include/asm/unaligned.h. The
  440. +alignment trap can fixup misaligned access for the exception cases, but at
  441. +a high performance cost. It better be rare.
  442. +
  443. +Now for user space applications, it is possible to configure the alignment
  444. +trap to SIGBUS any code performing unaligned access (good for debugging bad
  445. +code), or even fixup the access by software like for kernel code. The later
  446. +mode isn't recommended for performance reasons (just think about the
  447. +floating point emulation that works about the same way). Fix your code
  448. +instead!
  449. +
  450. +Please note that randomly changing the behaviour without good thought is
  451. +real bad - it changes the behaviour of all unaligned instructions in user
  452. +space, and might cause programs to fail unexpectedly.
  453. +
  454. +To change the alignment trap behavior, simply echo a number into
  455. +/proc/cpu/alignment. The number is made up from various bits:
  456. +
  457. +bit behavior when set
  458. +--- -----------------
  459. +
  460. +0 A user process performing an unaligned memory access
  461. + will cause the kernel to print a message indicating
  462. + process name, pid, pc, instruction, address, and the
  463. + fault code.
  464. +
  465. +1 The kernel will attempt to fix up the user process
  466. + performing the unaligned access. This is of course
  467. + slow (think about the floating point emulator) and
  468. + not recommended for production use.
  469. +
  470. +2 The kernel will send a SIGBUS signal to the user process
  471. + performing the unaligned access.
  472. +
  473. +Note that not all combinations are supported - only values 0 through 5.
  474. +(6 and 7 don't make sense).
  475. +
  476. +For example, the following will turn on the warnings, but without
  477. +fixing up or sending SIGBUS signals:
  478. +
  479. + echo 1 > /proc/cpu/alignment
  480. +
  481. +You can also read the content of the same file to get statistical
  482. +information on unaligned access occurrences plus the current mode of
  483. +operation for user space code.
  484. +
  485. +
  486. +Nicolas Pitre, Mar 13, 2001. Modified Russell King, Nov 30, 2001.
  487. diff -urN linux-2.4.26/Documentation/arm/memory.txt linux-2.4.26-vrs1/Documentation/arm/memory.txt
  488. --- linux-2.4.26/Documentation/arm/memory.txt 1970-01-01 01:00:00.000000000 +0100
  489. +++ linux-2.4.26-vrs1/Documentation/arm/memory.txt 2004-02-22 17:32:57.000000000 +0000
  490. @@ -0,0 +1,74 @@
  491. + Kernel Memory Layout on ARM Linux
  492. +
  493. + Russell King <rmk@arm.linux.org.uk>
  494. + April 27, 2003 (2.5.68)
  495. +
  496. +This document describes the virtual memory layout which the Linux
  497. +kernel uses for ARM processors. It indicates which regions are
  498. +free for platforms to use, and which are used by generic code.
  499. +
  500. +The ARM CPU is capable of addressing a maximum of 4GB virtual memory
  501. +space, and this must be shared between user space processes, the
  502. +kernel, and hardware devices.
  503. +
  504. +As the ARM architecture matures, it becomes necessary to reserve
  505. +certain regions of VM space for use for new facilities; therefore
  506. +this document may reserve more VM space over time.
  507. +
  508. +Start End Use
  509. +--------------------------------------------------------------------------
  510. +ffff8000 ffffffff copy_user_page / clear_user_page use.
  511. + For SA11xx and Xscale, this is used to
  512. + setup a minicache mapping.
  513. +
  514. +ffff1000 ffff7fff Reserved.
  515. + Platforms must not use this address range.
  516. +
  517. +ffff0000 ffff0fff CPU vector page.
  518. + The CPU vectors are mapped here if the
  519. + CPU supports vector relocation (control
  520. + register V bit.)
  521. +
  522. +ffe00000 fffeffff Free for platform use, not recommended.
  523. +
  524. +ffc00000 ffdfffff 2MB consistent memory mapping.
  525. + Memory returned by the consistent_alloc
  526. + low level function will be dynamically
  527. + mapped here.
  528. +
  529. +ff000000 ffbfffff Free for platform use, not recommended.
  530. +
  531. +VMALLOC_END ff000000 Free for platform use, recommended.
  532. +
  533. +VMALLOC_START VMALLOC_END vmalloc() / ioremap() space.
  534. + Memory returned by vmalloc/ioremap will
  535. + be dynamically placed in this region.
  536. + VMALLOC_START may be based upon the value
  537. + of the high_memory variable.
  538. +
  539. +PAGE_OFFSET high_memory Kernel direct-mapped RAM region.
  540. + This maps the platforms RAM, and typically
  541. + maps all platform RAM in a 1:1 relationship.
  542. +
  543. +TASK_SIZE PAGE_OFFSET Kernel module space
  544. + Kernel modules inserted via insmod are
  545. + placed here using dynamic mappings.
  546. +
  547. +00001000 TASK_SIZE User space mappings
  548. + Per-thread mappings are placed here via
  549. + the mmap() system call.
  550. +
  551. +00000000 00000fff CPU vector page / null pointer trap
  552. + CPUs which do not support vector remapping
  553. + place their vector page here. NULL pointer
  554. + dereferences by both the kernel and user
  555. + space are also caught via this mapping.
  556. +
  557. +Please note that mappings which collide with the above areas may result
  558. +in a non-bootable kernel, or may cause the kernel to (eventually) panic
  559. +at run time.
  560. +
  561. +Since future CPUs may impact the kernel mapping layout, user programs
  562. +must not access any memory which is not mapped inside their 0x0001000
  563. +to TASK_SIZE address range. If they wish to access these areas, they
  564. +must set up their own mappings using open() and mmap().
  565. diff -urN linux-2.4.26/Documentation/cpufreq/core.txt linux-2.4.26-vrs1/Documentation/cpufreq/core.txt
  566. --- linux-2.4.26/Documentation/cpufreq/core.txt 1970-01-01 01:00:00.000000000 +0100
  567. +++ linux-2.4.26-vrs1/Documentation/cpufreq/core.txt 2004-01-14 21:32:23.000000000 +0000
  568. @@ -0,0 +1,94 @@
  569. + CPU frequency and voltage scaling code in the Linux(TM) kernel
  570. +
  571. +
  572. + L i n u x C P U F r e q
  573. +
  574. + C P U F r e q C o r e
  575. +
  576. +
  577. + Dominik Brodowski <linux@brodo.de>
  578. + David Kimdon <dwhedon@debian.org>
  579. +
  580. +
  581. +
  582. + Clock scaling allows you to change the clock speed of the CPUs on the
  583. + fly. This is a nice method to save battery power, because the lower
  584. + the clock speed, the less power the CPU consumes.
  585. +
  586. +
  587. +Contents:
  588. +---------
  589. +1. CPUFreq core and interfaces
  590. +2. CPUFreq notifiers
  591. +
  592. +1. General Information
  593. +=======================
  594. +
  595. +The CPUFreq core code is located in linux/kernel/cpufreq.c. This
  596. +cpufreq code offers a standardized interface for the CPUFreq
  597. +architecture drivers (those pieces of code that do actual
  598. +frequency transitions), as well as to "notifiers". These are device
  599. +drivers or other part of the kernel that need to be informed of
  600. +policy changes (ex. thermal modules like ACPI) or of all
  601. +frequency changes (ex. timing code) or even need to force certain
  602. +speed limits (like LCD drivers on ARM architecture). Additionally, the
  603. +kernel "constant" loops_per_jiffy is updated on frequency changes
  604. +here.
  605. +
  606. +Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
  607. +which make sure that the cpufreq processor driver is correctly
  608. +registered with the core, and will not be unloaded until
  609. +cpufreq_put_cpu is called.
  610. +
  611. +2. CPUFreq notifiers
  612. +====================
  613. +
  614. +CPUFreq notifiers conform to the standard kernel notifier interface.
  615. +See linux/include/linux/notifier.h for details on notifiers.
  616. +
  617. +There are two different CPUFreq notifiers - policy notifiers and
  618. +transition notifiers.
  619. +
  620. +
  621. +2.1 CPUFreq policy notifiers
  622. +----------------------------
  623. +
  624. +These are notified when a new policy is intended to be set. Each
  625. +CPUFreq policy notifier is called three times for a policy transition:
  626. +
  627. +1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if
  628. + they see a need for this - may it be thermal considerations or
  629. + hardware limitations.
  630. +
  631. +2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid
  632. + hardware failure.
  633. +
  634. +3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy
  635. + - if two hardware drivers failed to agree on a new policy before this
  636. + stage, the incompatible hardware shall be shut down, and the user
  637. + informed of this.
  638. +
  639. +The phase is specified in the second argument to the notifier.
  640. +
  641. +The third argument, a void *pointer, points to a struct cpufreq_policy
  642. +consisting of five values: cpu, min, max, policy and max_cpu_freq. min
  643. +and max are the lower and upper frequencies (in kHz) of the new
  644. +policy, policy the new policy, cpu the number of the affected CPU or
  645. +CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported
  646. +CPU frequency. This value is given for informational purposes only.
  647. +
  648. +
  649. +2.2 CPUFreq transition notifiers
  650. +--------------------------------
  651. +
  652. +These are notified twice when the CPUfreq driver switches the CPU core
  653. +frequency and this change has any external implications.
  654. +
  655. +The second argument specifies the phase - CPUFREQ_PRECHANGE or
  656. +CPUFREQ_POSTCHANGE.
  657. +
  658. +The third argument is a struct cpufreq_freqs with the following
  659. +values:
  660. +cpu - number of the affected CPU or CPUFREQ_ALL_CPUS
  661. +old - old frequency
  662. +new - new frequency
  663. diff -urN linux-2.4.26/Documentation/cpufreq/cpu-drivers.txt linux-2.4.26-vrs1/Documentation/cpufreq/cpu-drivers.txt
  664. --- linux-2.4.26/Documentation/cpufreq/cpu-drivers.txt 1970-01-01 01:00:00.000000000 +0100
  665. +++ linux-2.4.26-vrs1/Documentation/cpufreq/cpu-drivers.txt 2004-01-14 21:32:23.000000000 +0000
  666. @@ -0,0 +1,210 @@
  667. + CPU frequency and voltage scaling code in the Linux(TM) kernel
  668. +
  669. +
  670. + L i n u x C P U F r e q
  671. +
  672. + C P U D r i v e r s
  673. +
  674. + - information for developers -
  675. +
  676. +
  677. + Dominik Brodowski <linux@brodo.de>
  678. +
  679. +
  680. +
  681. + Clock scaling allows you to change the clock speed of the CPUs on the
  682. + fly. This is a nice method to save battery power, because the lower
  683. + the clock speed, the less power the CPU consumes.
  684. +
  685. +
  686. +Contents:
  687. +---------
  688. +1. What To Do?
  689. +1.1 Initialization
  690. +1.2 Per-CPU Initialization
  691. +1.3 verify
  692. +1.4 target or setpolicy?
  693. +1.5 target
  694. +1.6 setpolicy
  695. +2. Frequency Table Helpers
  696. +
  697. +
  698. +
  699. +1. What To Do?
  700. +==============
  701. +
  702. +So, you just got a brand-new CPU / chipset with datasheets and want to
  703. +add cpufreq support for this CPU / chipset? Great. Here are some hints
  704. +on what is neccessary:
  705. +
  706. +
  707. +1.1 Initialization
  708. +------------------
  709. +
  710. +First of all, in an __initcall level 7 or later (preferrably
  711. +module_init() so that your driver is modularized) function check
  712. +whether this kernel runs on the right CPU and the right chipset. If
  713. +so, register a struct cpufreq_driver with the CPUfreq core using
  714. +cpufreq_register_driver()
  715. +
  716. +What shall this struct cpufreq_driver contain?
  717. +
  718. +cpufreq_driver.name - The name of this driver.
  719. +
  720. +cpufreq_driver.init - A pointer to the per-CPU initialization
  721. + function.
  722. +
  723. +cpufreq_driver.verify - A pointer to a "verfication" funciton.
  724. +
  725. +cpufreq_driver.setpolicy _or_
  726. +cpufreq_driver.target - See below on the differences.
  727. +
  728. +And optionally
  729. +
  730. +cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
  731. +
  732. +cpufreq_driver.attr - A pointer to a NULL-terminated list of
  733. + "struct freq_attr" which allow to
  734. + export values to sysfs.
  735. +
  736. +
  737. +1.2 Per-CPU Initialization
  738. +--------------------------
  739. +
  740. +Whenever a new CPU is registered with the device model, or after the
  741. +cpufreq driver registers itself, the per-CPU initialization fucntion
  742. +cpufreq_driver.init is called. It takes a struct cpufreq_policy
  743. +*policy as argument. What to do now?
  744. +
  745. +If necessary, activate the CPUfreq support on your CPU (unlock that
  746. +register etc.).
  747. +
  748. +Then, the driver must fill in the following values:
  749. +
  750. +policy->cpuinfo.min_freq _and_
  751. +policy->cpuinfo.max_freq - the minimum and maximum frequency
  752. + (in kHz) which is supported by
  753. + this CPU
  754. +policy->cpuinfo.transition_latency the time it takes on this CPU to
  755. + switch between two frequencies (if
  756. + appropriate, else specify
  757. + CPUFREQ_ETERNAL)
  758. +
  759. +policy->cur The current operating frequency of
  760. + this CPU (if appropriate)
  761. +policy->min,
  762. +policy->max,
  763. +policy->policy and, if neccessary,
  764. +policy->governor must contain the "default policy" for
  765. + this CPU. A few moments later,
  766. + cpufreq_driver.verify and either
  767. + cpufreq_driver.setpolicy or
  768. + cpufreq_driver.target is called with
  769. + these values.
  770. +
  771. +For setting some of these values, the frequency table helpers might be
  772. +helpful. See the section 2 for more information on them.
  773. +
  774. +
  775. +1.3 verify
  776. +------------
  777. +
  778. +When the user decides a new policy (consisting of
  779. +"policy,governor,min,max") shall be set, this policy must be validated
  780. +so that incompatible values can be corrected. For verifying these
  781. +values, a frequency table helper and/or the
  782. +cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned
  783. +int min_freq, unsigned int max_freq) function might be helpful. See
  784. +section 2 for details on frequency table helpers.
  785. +
  786. +You need to make sure that at least one valid frequency (or operating
  787. +range) is within policy->min and policy->max. If necessary, increase
  788. +policy->max fist, and only if this is no solution, decreas policy->min.
  789. +
  790. +
  791. +1.4 target or setpolicy?
  792. +----------------------------
  793. +
  794. +Most cpufreq drivers or even most cpu frequency scaling algorithms
  795. +only allow the CPU to be set to one frequency. For these, you use the
  796. +->target call.
  797. +
  798. +Some cpufreq-capable processors switch the frequency between certain
  799. +limits on their own. These shall use the ->setpolicy call
  800. +
  801. +
  802. +1.4. target
  803. +-------------
  804. +
  805. +The target call has three arguments: struct cpufreq_policy *policy,
  806. +unsigned int target_frequency, unsigned int relation.
  807. +
  808. +The CPUfreq driver must set the new frequency when called here. The
  809. +actual frequency must be determined using the following rules:
  810. +
  811. +- keep close to "target_freq"
  812. +- policy->min <= new_freq <= policy->max (THIS MUST BE VALID!!!)
  813. +- if relation==CPUFREQ_REL_L, try to select a new_freq higher than or equal
  814. + target_freq. ("L for lowest, but no lower than")
  815. +- if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal
  816. + target_freq. ("H for highest, but no higher than")
  817. +
  818. +Here again the frequency table helper might assist you - see section 3
  819. +for details.
  820. +
  821. +
  822. +1.5 setpolicy
  823. +---------------
  824. +
  825. +The setpolicy call only takes a struct cpufreq_policy *policy as
  826. +argument. You need to set the lower limit of the in-processor or
  827. +in-chipset dynamic frequency switching to policy->min, the upper limit
  828. +to policy->max, and -if supported- select a performance-oriented
  829. +setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a
  830. +powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check
  831. +the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c
  832. +
  833. +
  834. +
  835. +2. Frequency Table Helpers
  836. +==========================
  837. +
  838. +As most cpufreq processors only allow for being set to a few specific
  839. +frequencies, a "frequency table" with some functions might assist in
  840. +some work of the processor driver. Such a "frequency table" consists
  841. +of an array of struct cpufreq_freq_table entries, with any value in
  842. +"index" you want to use, and the corresponding frequency in
  843. +"frequency". At the end of the table, you need to add a
  844. +cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And
  845. +if you want to skip one entry in the table, set the frequency to
  846. +CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
  847. +order.
  848. +
  849. +By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
  850. + struct cpufreq_frequency_table *table);
  851. +the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
  852. +policy->min and policy->max are set to the same values. This is
  853. +helpful for the per-CPU initialization stage.
  854. +
  855. +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
  856. + struct cpufreq_frequency_table *table);
  857. +assures that at least one valid frequency is within policy->min and
  858. +policy->max, and all other criteria are met. This is helpful for the
  859. +->verify call.
  860. +
  861. +int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
  862. + struct cpufreq_frequency_table *table,
  863. + unsigned int target_freq,
  864. + unsigned int relation,
  865. + unsigned int *index);
  866. +
  867. +is the corresponding frequency table helper for the ->target
  868. +stage. Just pass the values to this function, and the unsigned int
  869. +index returns the number of the frequency table entry which contains
  870. +the frequency the CPU shall be set to. PLEASE NOTE: This is not the
  871. +"index" which is in this cpufreq_table_entry.index, but instead
  872. +cpufreq_table[index]. So, the new frequency is
  873. +cpufreq_table[index].frequency, and the value you stored into the
  874. +frequency table "index" field is
  875. +cpufreq_table[index].index.
  876. +
  877. diff -urN linux-2.4.26/Documentation/cpufreq/governors.txt linux-2.4.26-vrs1/Documentation/cpufreq/governors.txt
  878. --- linux-2.4.26/Documentation/cpufreq/governors.txt 1970-01-01 01:00:00.000000000 +0100
  879. +++ linux-2.4.26-vrs1/Documentation/cpufreq/governors.txt 2004-01-14 21:32:23.000000000 +0000
  880. @@ -0,0 +1,155 @@
  881. + CPU frequency and voltage scaling code in the Linux(TM) kernel
  882. +
  883. +
  884. + L i n u x C P U F r e q
  885. +
  886. + C P U F r e q G o v e r n o r s
  887. +
  888. + - information for users and developers -
  889. +
  890. +
  891. + Dominik Brodowski <linux@brodo.de>
  892. +
  893. +
  894. +
  895. + Clock scaling allows you to change the clock speed of the CPUs on the
  896. + fly. This is a nice method to save battery power, because the lower
  897. + the clock speed, the less power the CPU consumes.
  898. +
  899. +
  900. +Contents:
  901. +---------
  902. +1. What is a CPUFreq Governor?
  903. +
  904. +2. Governors In the Linux Kernel
  905. +2.1 Performance
  906. +2.2 Powersave
  907. +2.3 Userspace
  908. +
  909. +3. The Governor Interface in the CPUfreq Core
  910. +
  911. +
  912. +
  913. +1. What Is A CPUFreq Governor?
  914. +==============================
  915. +
  916. +Most cpufreq drivers (in fact, all except one, longrun) or even most
  917. +cpu frequency scaling algorithms only offer the CPU to be set to one
  918. +frequency. In order to offer dynamic frequency scaling, the cpufreq
  919. +core must be able to tell these drivers of a "target frequency". So
  920. +these specific drivers will be transformed to offer a "->target"
  921. +call instead of the existing "->setpolicy" call. For "longrun", all
  922. +stays the same, though.
  923. +
  924. +How to decide what frequency within the CPUfreq policy should be used?
  925. +That's done using "cpufreq governors". Two are already in this patch
  926. +-- they're the already existing "powersave" and "performance" which
  927. +set the frequency statically to the lowest or highest frequency,
  928. +respectively. At least two more such governors will be ready for
  929. +addition in the near future, but likely many more as there are various
  930. +different theories and models about dynamic frequency scaling
  931. +around. Using such a generic interface as cpufreq offers to scaling
  932. +governors, these can be tested extensively, and the best one can be
  933. +selected for each specific use.
  934. +
  935. +Basically, it's the following flow graph:
  936. +
  937. +CPU can be set to switch independetly | CPU can only be set
  938. + within specific "limits" | to specific frequencies
  939. +
  940. + "CPUfreq policy"
  941. + consists of frequency limits (policy->{min,max})
  942. + and CPUfreq governor to be used
  943. + / \
  944. + / \
  945. + / the cpufreq governor decides
  946. + / (dynamically or statically)
  947. + / what target_freq to set within
  948. + / the limits of policy->{min,max}
  949. + / \
  950. + / \
  951. + Using the ->setpolicy call, Using the ->target call,
  952. + the limits and the the frequency closest
  953. + "policy" is set. to target_freq is set.
  954. + It is assured that it
  955. + is within policy->{min,max}
  956. +
  957. +
  958. +2. Governors In the Linux Kernel
  959. +================================
  960. +
  961. +2.1 Performance
  962. +---------------
  963. +
  964. +The CPUfreq governor "performance" sets the CPU statically to the
  965. +highest frequency within the borders of scaling_min_freq and
  966. +scaling_max_freq.
  967. +
  968. +
  969. +2.1 Powersave
  970. +-------------
  971. +
  972. +The CPUfreq governor "powersave" sets the CPU statically to the
  973. +lowest frequency within the borders of scaling_min_freq and
  974. +scaling_max_freq.
  975. +
  976. +
  977. +2.2 Userspace
  978. +-------------
  979. +
  980. +The CPUfreq governor "userspace" allows the user, or any userspace
  981. +program running with UID "root", to set the CPU to a specifc frequency
  982. +by making a sysfs file "scaling_setspeed" available in the CPU-device
  983. +directory.
  984. +
  985. +
  986. +
  987. +3. The Governor Interface in the CPUfreq Core
  988. +=============================================
  989. +
  990. +A new governor must register itself with the CPUfreq core using
  991. +"cpufreq_register_governor". The struct cpufreq_governor, which has to
  992. +be passed to that function, must contain the following values:
  993. +
  994. +governor->name - A unique name for this governor
  995. +governor->governor - The governor callback function
  996. +governor->owner - .THIS_MODULE for the governor module (if
  997. + appropriate)
  998. +
  999. +The governor->governor callback is called with the current (or to-be-set)
  1000. +cpufreq_policy struct for that CPU, and an unsigned int event. The
  1001. +following events are currently defined:
  1002. +
  1003. +CPUFREQ_GOV_START: This governor shall start its duty for the CPU
  1004. + policy->cpu
  1005. +CPUFREQ_GOV_STOP: This governor shall end its duty for the CPU
  1006. + policy->cpu
  1007. +CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed to
  1008. + policy->min and policy->max.
  1009. +
  1010. +If you need other "events" externally of your driver, _only_ use the
  1011. +cpufreq_governor_l(unsigned int cpu, unsigned int event) call to the
  1012. +CPUfreq core to ensure proper locking.
  1013. +
  1014. +
  1015. +The CPUfreq governor may call the CPU processor driver using one of
  1016. +these two functions:
  1017. +
  1018. +inline int cpufreq_driver_target(struct cpufreq_policy *policy,
  1019. + unsigned int target_freq,
  1020. + unsigned int relation);
  1021. +
  1022. +inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
  1023. + unsigned int target_freq,
  1024. + unsigned int relation);
  1025. +
  1026. +target_freq must be within policy->min and policy->max, of course.
  1027. +What's the difference between these two functions? When your governor
  1028. +still is in a direct code path of a call to governor->governor, the
  1029. +cpufreq_driver_sem lock is still held in the cpufreq core, and there's
  1030. +no need to lock it again (in fact, this would cause a deadlock). So
  1031. +use cpufreq_driver_target only in these cases. In all other cases (for
  1032. +example, when there's a "daemonized" function that wakes up every
  1033. +second), use cpufreq_driver_target_l to lock the cpufreq_driver_sem
  1034. +before the command is passed to the cpufreq processor driver.
  1035. +
  1036. diff -urN linux-2.4.26/Documentation/cpufreq/index.txt linux-2.4.26-vrs1/Documentation/cpufreq/index.txt
  1037. --- linux-2.4.26/Documentation/cpufreq/index.txt 1970-01-01 01:00:00.000000000 +0100
  1038. +++ linux-2.4.26-vrs1/Documentation/cpufreq/index.txt 2004-01-14 21:32:23.000000000 +0000
  1039. @@ -0,0 +1,56 @@
  1040. + CPU frequency and voltage scaling code in the Linux(TM) kernel
  1041. +
  1042. +
  1043. + L i n u x C P U F r e q
  1044. +
  1045. +
  1046. +
  1047. +
  1048. + Dominik Brodowski <linux@brodo.de>
  1049. +
  1050. +
  1051. +
  1052. + Clock scaling allows you to change the clock speed of the CPUs on the
  1053. + fly. This is a nice method to save battery power, because the lower
  1054. + the clock speed, the less power the CPU consumes.
  1055. +
  1056. +
  1057. +
  1058. +Documents in this directory:
  1059. +----------------------------
  1060. +core.txt - General description of the CPUFreq core and
  1061. + of CPUFreq notifiers
  1062. +
  1063. +cpu-drivers.txt - How to implement a new cpufreq processor driver
  1064. +
  1065. +governors.txt - What are cpufreq governors and how to
  1066. + implement them?
  1067. +
  1068. +index.txt - File index, Mailing list and Links (this document)
  1069. +
  1070. +user-guide.txt - User Guide to CPUFreq
  1071. +
  1072. +
  1073. +Mailing List
  1074. +------------
  1075. +There is a CPU frequency changing CVS commit and general list where
  1076. +you can report bugs, problems or submit patches. To post a message,
  1077. +send an email to cpufreq@www.linux.org.uk, to subscribe go to
  1078. +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
  1079. +mailing list are available to subscribers at
  1080. +http://www.linux.org.uk/mailman/private/cpufreq/.
  1081. +
  1082. +
  1083. +Links
  1084. +-----
  1085. +the FTP archives:
  1086. +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
  1087. +
  1088. +how to access the CVS repository:
  1089. +* http://cvs.arm.linux.org.uk/
  1090. +
  1091. +the CPUFreq Mailing list:
  1092. +* http://www.linux.org.uk/mailman/listinfo/cpufreq
  1093. +
  1094. +Clock and voltage scaling for the SA-1100:
  1095. +* http://www.lart.tudelft.nl/projects/scaling
  1096. diff -urN linux-2.4.26/Documentation/cpufreq/user-guide.txt linux-2.4.26-vrs1/Documentation/cpufreq/user-guide.txt
  1097. --- linux-2.4.26/Documentation/cpufreq/user-guide.txt 1970-01-01 01:00:00.000000000 +0100
  1098. +++ linux-2.4.26-vrs1/Documentation/cpufreq/user-guide.txt 2004-01-14 21:32:23.000000000 +0000
  1099. @@ -0,0 +1,166 @@
  1100. + CPU frequency and voltage scaling code in the Linux(TM) kernel
  1101. +
  1102. +
  1103. + L i n u x C P U F r e q
  1104. +
  1105. + U S E R G U I D E
  1106. +
  1107. +
  1108. + Dominik Brodowski <linux@brodo.de>
  1109. +
  1110. +
  1111. +
  1112. + Clock scaling allows you to change the clock speed of the CPUs on the
  1113. + fly. This is a nice method to save battery power, because the lower
  1114. + the clock speed, the less power the CPU consumes.
  1115. +
  1116. +
  1117. +Contents:
  1118. +---------
  1119. +1. Supported Architectures and Processors
  1120. +1.1 ARM
  1121. +1.2 x86
  1122. +1.3 sparc64
  1123. +
  1124. +2. "Policy" / "Governor"?
  1125. +2.1 Policy
  1126. +2.2 Governor
  1127. +
  1128. +3. How to change the CPU cpufreq policy and/or speed
  1129. +3.1 Preferred interface: sysfs
  1130. +3.2 Deprecated interfaces
  1131. +
  1132. +
  1133. +
  1134. +1. Supported Architectures and Processors
  1135. +=========================================
  1136. +
  1137. +1.1 ARM
  1138. +-------
  1139. +
  1140. +The following ARM processors are supported by cpufreq:
  1141. +
  1142. +ARM Integrator
  1143. +ARM-SA1100
  1144. +ARM-SA1110
  1145. +
  1146. +
  1147. +1.2 x86
  1148. +-------
  1149. +
  1150. +The following processors for the x86 architecture are supported by cpufreq:
  1151. +
  1152. +AMD Elan - SC400, SC410
  1153. +AMD mobile K6-2+
  1154. +AMD mobile K6-3+
  1155. +Cyrix Media GXm
  1156. +Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets
  1157. +Intel Pentium 4, Intel Xeon
  1158. +National Semiconductors Geode GX
  1159. +Transmeta Crusoe
  1160. +varios processors on some ACPI 2.0-compatible systems [**]
  1161. +
  1162. +[*] only certain Intel mobile PIII processors are supported. If you
  1163. +know that you own a speedstep-capable processor, pass the option
  1164. +"speedstep_coppermine=1" to the module speedstep.o
  1165. +
  1166. +[**] Only if "ACPI Processor Performance States" are available
  1167. +to the ACPI<->BIOS interface.
  1168. +
  1169. +
  1170. +1.3 sparc64
  1171. +-----------
  1172. +
  1173. +The following processors for the sparc64 architecture are supported by
  1174. +cpufreq:
  1175. +
  1176. +UltraSPARC-III
  1177. +
  1178. +
  1179. +
  1180. +2. "Policy" / "Governor" ?
  1181. +==========================
  1182. +
  1183. +Some CPU frequency scaling-capable processor switch between varios
  1184. +frequencies and operating voltages "on the fly" without any kernel or
  1185. +user involvement. This guarantuees very fast switching to a frequency
  1186. +which is high enough to serve the user's needs, but low enough to save
  1187. +power.
  1188. +
  1189. +
  1190. +2.1 Policy
  1191. +----------
  1192. +
  1193. +On these systems, all you can do is select the lower and upper
  1194. +frequency limit as well as whether you want more aggressive
  1195. +power-saving or more instantly avaialble processing power.
  1196. +
  1197. +
  1198. +2.2 Governor
  1199. +------------
  1200. +
  1201. +On all other cpufreq implementations, these boundaries still need to
  1202. +be set. Then, a "governor" must be selected. Such a "governor" decides
  1203. +what speed the processor shall run within the boundaries. One such
  1204. +"governor" is the "userspace" governor. This one allows the user - or
  1205. +a yet-to-implement userspace program - to decide what specific speed
  1206. +the processor shall run at.
  1207. +
  1208. +
  1209. +3. How to change the CPU cpufreq policy and/or speed
  1210. +====================================================
  1211. +
  1212. +3.1 Preferred Interface: sysfs
  1213. +------------------------------
  1214. +
  1215. +The preferred interface is located in the sysfs filesystem. If you
  1216. +mounted it at /sys, the cpufreq interface is located in a subdirectory
  1217. +"cpufreq" within the cpu-device directory
  1218. +(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
  1219. +
  1220. +cpuinfo_min_freq : this file shows the minimum operating
  1221. + frequency the processor can run at(in kHz)
  1222. +cpuinfo_max_freq : this file shows the maximum operating
  1223. + frequency the processor can run at(in kHz)
  1224. +scaling_driver : this file shows what cpufreq driver is
  1225. + used to set the frequency on this CPU
  1226. +
  1227. +scaling_available_governors : this file shows the CPUfreq governors
  1228. + available in this kernel. You can see the
  1229. + currently activated governor in
  1230. +
  1231. +scaling_governor, and by "echoing" the name of another
  1232. + governor you can change it. Please note
  1233. + that some governors won't load - they only
  1234. + work on some specific architectures or
  1235. + processors.
  1236. +scaling_min_freq and
  1237. +scaling_max_freq show the current "policy limits" (in
  1238. + kHz). By echoing new values into these
  1239. + files, you can change these limits.
  1240. +
  1241. +
  1242. +If you have selected the "userspace" governor which allows you to
  1243. +set the CPU operating frequency to a specific value, you can read out
  1244. +the current frequency in
  1245. +
  1246. +scaling_setspeed. By "echoing" a new frequency into this
  1247. + you can change the speed of the CPU,
  1248. + but only within the limits of
  1249. + scaling_min_freq and scaling_max_freq.
  1250. +
  1251. +
  1252. +3.2 Deprecated Interfaces
  1253. +-------------------------
  1254. +
  1255. +Depending on your kernel configuration, you might find the following
  1256. +cpufreq-related files:
  1257. +/proc/cpufreq
  1258. +/proc/sys/cpu/*/speed
  1259. +/proc/sys/cpu/*/speed-min
  1260. +/proc/sys/cpu/*/speed-max
  1261. +
  1262. +These are files for deprecated interfaces to cpufreq, which offer far
  1263. +less functionality. Because of this, these interfaces aren't described
  1264. +here.
  1265. +
  1266. diff -urN linux-2.4.26/Documentation/cpufreq-old linux-2.4.26-vrs1/Documentation/cpufreq-old
  1267. --- linux-2.4.26/Documentation/cpufreq-old 1970-01-01 01:00:00.000000000 +0100
  1268. +++ linux-2.4.26-vrs1/Documentation/cpufreq-old 2004-01-14 21:32:23.000000000 +0000
  1269. @@ -0,0 +1,332 @@
  1270. + CPU frequency and voltage scaling code in the Linux(TM) kernel
  1271. +
  1272. +
  1273. + L i n u x C P U F r e q
  1274. +
  1275. +
  1276. +
  1277. +
  1278. + Dominik Brodowski <devel@brodo.de>
  1279. +
  1280. +
  1281. +
  1282. + Clock scaling allows you to change the clock speed of the CPUs on the
  1283. + fly. This is a nice method to save battery power, because the lower
  1284. + the clock speed, the less power the CPU consumes.
  1285. +
  1286. +
  1287. +
  1288. +Contents:
  1289. +---------
  1290. +1. Supported architectures
  1291. +2. User interface
  1292. +2.1 Sample script for command line interface
  1293. +3. CPUFreq core and interfaces
  1294. +3.1 General information
  1295. +3.2 CPUFreq notifiers
  1296. +3.3 CPUFreq architecture drivers
  1297. +4. Mailing list and Links
  1298. +
  1299. +
  1300. +
  1301. +1. Supported architectures
  1302. +==========================
  1303. +
  1304. +Some architectures detect the lowest and highest possible speed
  1305. +settings, while others rely on user information on this. For the
  1306. +latter, a boot parameter is required, for the former, you can specify
  1307. +one to set the limits between speed settings may occur.
  1308. +The boot parameter has the following syntax:
  1309. +
  1310. + cpufreq=minspeed-maxspeed
  1311. +
  1312. +with both minspeed and maxspeed being given in kHz. To set the lower
  1313. +limit to 59 MHz and the upper limit to 221 MHz, specify:
  1314. +
  1315. + cpufreq=59000-221000
  1316. +
  1317. +Check the "Speed Limits Detection" information below on whether
  1318. +the driver detects the lowest and highest allowed speed setting
  1319. +automatically.
  1320. +
  1321. +
  1322. +ARM Integrator:
  1323. + SA 1100, SA1110
  1324. +--------------------------------
  1325. + Speed Limits Detection: On Integrators, the minimum speed is set
  1326. + and the maximum speed has to be specified using the boot
  1327. + parameter. On SA11x0s, the frequencies are fixed (59 - 287 MHz)
  1328. +
  1329. +
  1330. +AMD Elan:
  1331. + SC400, SC410
  1332. +--------------------------------
  1333. + Speed Limits Detection: Not implemented. You need to specify the
  1334. + minimum and maximum frequency in the boot parameter (see above).
  1335. +
  1336. +
  1337. +VIA Cyrix Longhaul:
  1338. + VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3,
  1339. + VIA Cyrix Ezra, VIA Cyrix Ezra-T
  1340. +--------------------------------
  1341. + Speed Limits Detection: working. No need for boot parameters.
  1342. + NOTE: Support for certain processors is currently disabled,
  1343. + waiting on updated docs from VIA.
  1344. +
  1345. +
  1346. +Intel SpeedStep:
  1347. + certain mobile Intel Pentium III (Coppermine), and all mobile
  1348. + Intel Pentium III-M (Tulatin) and mobile Intel Pentium 4 P4-Ms.
  1349. +--------------------------------
  1350. + Speed Limits Detection: working. No need for boot parameters.
  1351. + NOTE:
  1352. + 1.) mobile Intel Pentium III (Coppermine):
  1353. + The SpeedStep interface may only be used on SpeedStep
  1354. + capable processors. Unforunately, due to lack of documentation,
  1355. + such detection is not yet possible on mobile Intel PIII
  1356. + (Coppermine) processors. In order to activate SpeedStep on such a
  1357. + processor, you have to remove one line manually in
  1358. + linux/drivers/arch/i386/speedstep.c
  1359. +
  1360. +
  1361. +P4 CPU Clock Modulation:
  1362. + Intel Pentium 4 Xeon processors
  1363. +--------------------------------
  1364. + Speed Limits Detection: Not implemented. You need to specify the
  1365. + minimum and maximum frequency in the boot parameter (see above).
  1366. +
  1367. +
  1368. +
  1369. +2. User Interface
  1370. +=================
  1371. +
  1372. +CPUFreq uses a "sysctl" interface which is located in
  1373. + /proc/sys/cpu/0/ on UP (uniprocessor) kernels, or
  1374. + /proc/sys/cpu/any/ on SMP (symmetric multiprocessoring) kernels.
  1375. +
  1376. +
  1377. +In this directory, you will find three files of importance for
  1378. +CPUFreq: speed-max, speed-min, and speed:
  1379. +
  1380. +speed shows the current CPU frequency in kHz,
  1381. +speed-min the minimal supported CPU frequency, and
  1382. +speed-max the maximal supported CPU frequency.
  1383. +
  1384. +Please note that you might have to specify these limits as a boot
  1385. +parameter depending on the architecture (see above).
  1386. +
  1387. +
  1388. +To change the CPU frequency, "echo" the desired CPU frequency (in kHz)
  1389. +to speed. For example, to set the CPU speed to the lowest/highest
  1390. +allowed frequency do:
  1391. +
  1392. +root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed
  1393. +root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed
  1394. +
  1395. +
  1396. +2.1 Sample script for command line interface
  1397. +**********************************************
  1398. +
  1399. +
  1400. +Michael Ossmann <mike@ossmann.com> has written a small command line
  1401. +interface for the infinitely lazy.
  1402. +
  1403. +#!/bin/bash
  1404. +#
  1405. +# /usr/local/bin/freq
  1406. +# simple command line interface to cpufreq
  1407. +
  1408. +[ -n "$1" ] && case "$1" in
  1409. + "min" )
  1410. + # set frequency to minimum
  1411. + cat /proc/sys/cpu/0/speed-min >/proc/sys/cpu/0/speed
  1412. + ;;
  1413. + "max" )
  1414. + # set frequency to maximum
  1415. + cat /proc/sys/cpu/0/speed-max >/proc/sys/cpu/0/speed
  1416. + ;;
  1417. + * )
  1418. + echo "Usage: $0 [min|max]"
  1419. + echo " min: set frequency to minimum and display new frequency"
  1420. + echo " max: set frequency to maximum and display new frequency"
  1421. + echo " no options: display current frequency"
  1422. + exit 1
  1423. + ;;
  1424. +esac
  1425. +
  1426. +# display current frequency
  1427. +cat /proc/sys/cpu/0/speed
  1428. +exit 0
  1429. +
  1430. +
  1431. +
  1432. +3. CPUFreq core and interfaces
  1433. +===============================
  1434. +
  1435. +3.1 General information
  1436. +*************************
  1437. +
  1438. +The CPUFreq core code is located in linux/kernel/cpufreq.c. This
  1439. +cpufreq code offers a standardized interface for the CPUFreq
  1440. +architecture drivers (those pieces of code that do the actual
  1441. +frequency transition), as well as to "notifiers". These are device
  1442. +drivers or other part of the kernel that need to be informed of
  1443. +frequency changes (like timing code) or even need to force certain
  1444. +speed limits (like LCD drivers on ARM architecture). Aditionally, the
  1445. +kernel "constant" loops_per_jiffy is updated on frequency changes
  1446. +here.
  1447. +
  1448. +
  1449. +3.2 CPUFreq notifiers
  1450. +***********************
  1451. +
  1452. +CPUFreq notifiers are kernel code that need to be called to either
  1453. +a) define certain minimum or maximum speed settings,
  1454. +b) be informed of frequency changes in advance of the transition, or
  1455. +c) be informed of frequency changes directly after the transition.
  1456. +
  1457. +A standard kernel notifier interface is offered for this. See
  1458. +linux/include/linux/notifier.h for details on notifiers.
  1459. +
  1460. +
  1461. +Data and value passed to CPUFreq notifiers
  1462. +------------------------------------------
  1463. +The second argument passed to any notifier is an unsigned int stating
  1464. +the phase of the transition:
  1465. +CPUFREQ_MINMAX during the process of determing a valid new CPU
  1466. + frequency,
  1467. +CPUFREQ_PRECHANGE right before the transition, and
  1468. +CPUFREQ_POSTCHANGE right after the transition.
  1469. +
  1470. +The third argument, a void *pointer, points to a struct
  1471. +cpufreq_freqs. This consists of four values: min, max, cur and new.
  1472. +
  1473. +min and max are the current speed limits. Please note: Never update
  1474. +these values directly, use cpufreq_updateminmax(struct cpufreq_freqs
  1475. +*freqs, unsigned int min, unsigned int max) instead. cur is the
  1476. +current/old speed, and new is the new speed, but might only be valid
  1477. +on CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE.
  1478. +
  1479. +Each notifier gets called all three times on any transition:
  1480. +
  1481. +CPUFREQ_MINMAX
  1482. +Here the notifier is supposed to update the min and max values to the
  1483. +limits the protected device / kernel code needs. As stated above,
  1484. +always use cpufreq_updateminmax for this.
  1485. +
  1486. +CPUFREQ_PRECHANGE
  1487. +CPUFREQ_POSTCHANGE
  1488. +Here the notifier is supposed to update all internal (e.g. device
  1489. +driver) code which is dependend on the CPU frequency.
  1490. +
  1491. +
  1492. +3.3 CPUFreq architecture drivers
  1493. +**********************************
  1494. +
  1495. +CPUFreq architecture drivers are the pieces of kernel code that
  1496. +actually perform CPU frequency transitions. These need to be
  1497. +initialised separately (separate initcalls), and may be
  1498. +modularized. They interact with the CPUFreq core in the following way:
  1499. +
  1500. +
  1501. +cpufreq_register()
  1502. +------------------
  1503. +cpufreq_register registers an arch driver to the CPUFreq core. Please
  1504. +note that only one arch driver may be registered at any time, -EBUSY
  1505. +is returned when an arch driver is already registered. The argument to
  1506. +cpufreq_register, cpufreq_driver_t driver, is described later.
  1507. +
  1508. +
  1509. +cpufreq_unregister()
  1510. +--------------------
  1511. +cpufreq_unregister unregisters an arch driver, e.g. on module
  1512. +unloading. Please note that there is no check done that this is called
  1513. +from the driver which actually registered itself to the core, so
  1514. +please only call this function when you are sure the arch driver got
  1515. +registered correctly before.
  1516. +
  1517. +
  1518. +struct cpufreq_driver
  1519. +----------------
  1520. +On initialisation, the arch driver is supposed to pass the following
  1521. +entries in struct cpufreq_driver cpufreq_driver:
  1522. +
  1523. +cpufreq_verify_t validate: This is a pointer to a function with the
  1524. +following definition:
  1525. + unsigned int validating_function (unsigned int kHz).
  1526. +It is called right before a transition occurs. The proposed new
  1527. +speed setting is passed as an argument in kHz; the validating code
  1528. +should verify this is a valid speed setting which is currently
  1529. +supported by the CPU. It shall return the closest valid CPU frequency
  1530. +in kHz.
  1531. +
  1532. +cpufreq_setspeed_t setspeed: This is a pointer to a function with the
  1533. +following definition:
  1534. + void setspeed_function (unsigned int kHz).
  1535. +This function shall perform the transition to the new CPU frequency
  1536. +given as argument in kHz. Note that this argument is exactly the same
  1537. +as the one returned by cpufreq_verify_t validate.
  1538. +
  1539. +
  1540. +unsigned int freq.cur: The current CPU core frequency. Note that this
  1541. +is a requirement while the next two entries are optional.
  1542. +
  1543. +
  1544. +unsigned int freq.min (optional): The minimal CPU core frequency this
  1545. +CPU supports. This value may be limited further by the
  1546. +cpufreq_verify_t validate function, and so this value should be the
  1547. +minimal core frequency allowed "theoretically" on this system in this
  1548. +configuration.
  1549. +
  1550. +
  1551. +unsigned int freq.max (optional): The maximum CPU core frequency this
  1552. +CPU supports. This value may be limited further by the
  1553. +cpufreq_verify_t validate function, and so this value should be the
  1554. +maximum core frequency allowed "theoretically" on this system in this
  1555. +configuration.
  1556. +
  1557. +
  1558. +Some Requirements to CPUFreq architecture drivers
  1559. +-------------------------------------------------
  1560. +* Only call cpufreq_register() when the ability to switch CPU
  1561. + frequencies is _verified_ or can't be missing
  1562. +* cpufreq_unregister() may only be called if cpufreq_register() has
  1563. + been successfully(!) called before
  1564. +* All CPUs have to be set to the same speed whenever setspeed() is
  1565. + called
  1566. +* Be aware that there is currently no error management in the
  1567. + setspeed() code in the CPUFreq core. So only call yourself a
  1568. + cpufreq_driver if you are really a working cpufreq_driver!
  1569. +
  1570. +
  1571. +
  1572. +4. Mailing list and Links
  1573. +**************************
  1574. +
  1575. +
  1576. +Mailing List
  1577. +------------
  1578. +There is a CPU frequency changing CVS commit and general list where
  1579. +you can report bugs, problems or submit patches. To post a message,
  1580. +send an email to cpufreq@www.linux.org.uk, to subscribe go to
  1581. +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
  1582. +mailing list are available to subscribers at
  1583. +http://www.linux.org.uk/mailman/private/cpufreq/.
  1584. +
  1585. +
  1586. +Links
  1587. +-----
  1588. +the FTP archives:
  1589. +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
  1590. +
  1591. +how to access the CVS repository:
  1592. +* http://www.arm.linux.org.uk/cvs/
  1593. +
  1594. +the CPUFreq Mailing list:
  1595. +* http://www.linux.org.uk/mailman/listinfo/cpufreq
  1596. +
  1597. +Clock and voltage scaling for the SA-1100:
  1598. +* http://www.lart.tudelft.nl/projects/scaling
  1599. +
  1600. +CPUFreq project homepage
  1601. +* http://www.brodo.de/cpufreq/
  1602. diff -urN linux-2.4.26/Documentation/l3/structure linux-2.4.26-vrs1/Documentation/l3/structure
  1603. --- linux-2.4.26/Documentation/l3/structure 1970-01-01 01:00:00.000000000 +0100
  1604. +++ linux-2.4.26-vrs1/Documentation/l3/structure 2004-01-14 21:32:23.000000000 +0000
  1605. @@ -0,0 +1,36 @@
  1606. +L3 Bus Driver
  1607. +-------------
  1608. +
  1609. +The structure of the driver is as follows:
  1610. +
  1611. + +----------+ +----------+ +----------+
  1612. + | client 1 | | client 2 | | client 3 |
  1613. + +-----^----+ +----^-----+ +----^-----+
  1614. + | | |
  1615. + +-----v--------------v---------------v-----+
  1616. + | |
  1617. + +-----^-------+ +-------^-----+
  1618. + | | core | |
  1619. + +-----v----+ | | +----v-----+
  1620. + | device | | | | device |
  1621. + | driver 1 | | | | driver 2 |
  1622. + +-----^----+ | | +----^-----+
  1623. + | | services | |
  1624. + +-----v-------+ +-------v-----+
  1625. + | |
  1626. + +-----------------^----^-------------------+
  1627. + | |
  1628. + | +-v---------+
  1629. + | | algorithm |
  1630. + | | driver |
  1631. + | +-v---------+
  1632. + | |
  1633. + +-v----v-+
  1634. + | bus |
  1635. + | driver |
  1636. + +--------+
  1637. +
  1638. +Clients talk to the core to attach device drivers and bus adapters, and
  1639. +to instruct device drivers to perform actions. Device drivers then talk
  1640. +to the core to perform L3 bus transactions via the algorithm driver and
  1641. +ultimately bus driver.
  1642. diff -urN linux-2.4.26/Documentation/serial/driver linux-2.4.26-vrs1/Documentation/serial/driver
  1643. --- linux-2.4.26/Documentation/serial/driver 1970-01-01 01:00:00.000000000 +0100
  1644. +++ linux-2.4.26-vrs1/Documentation/serial/driver 2004-01-14 21:32:23.000000000 +0000
  1645. @@ -0,0 +1,208 @@
  1646. +
  1647. + Low Level Serial API
  1648. + --------------------
  1649. +
  1650. +
  1651. + $Id: driver,v 1.3 2001/11/24 23:24:47 rmk Exp $
  1652. +
  1653. +
  1654. +This document is meant as a brief overview of some aspects of the new serial
  1655. +driver. It is not complete, any questions you have should be directed to
  1656. +<rmk@arm.linux.org.uk>
  1657. +
  1658. +The reference implementation is contained within serial_amba.c.
  1659. +
  1660. +
  1661. +
  1662. +Low Level Serial Hardware Driver
  1663. +--------------------------------
  1664. +
  1665. +The low level serial hardware driver is responsible for supplying port
  1666. +information (defined by uart_port) and a set of control methods (defined
  1667. +by uart_ops) to the core serial driver. The low level driver is also
  1668. +responsible for handling interrupts for the port, and providing any
  1669. +console support.
  1670. +
  1671. +
  1672. +Console Support
  1673. +---------------
  1674. +
  1675. +The serial core provides a few helper functions. This includes identifing
  1676. +the correct port structure (via uart_get_console) and decoding command line
  1677. +arguments (uart_parse_options).
  1678. +
  1679. +
  1680. +Locking
  1681. +-------
  1682. +
  1683. +Generally, all locking is done by the core driver, except for the interrupt
  1684. +functions. It is the responsibility of the low level hardware driver to
  1685. +perform the necessary locking there using info->lock. (since it is running
  1686. +in an interrupt, you only need to use spin_lock() and spin_unlock() from
  1687. +the interrupt handler).
  1688. +
  1689. +
  1690. +uart_ops
  1691. +--------
  1692. +
  1693. +The uart_ops structure is the main interface between serial_core and the
  1694. +hardware specific driver. It contains all the methods to control the
  1695. +hardware.
  1696. +
  1697. + tx_empty(port)
  1698. + This function tests whether the transmitter fifo and shifter
  1699. + for the port described by 'port' is empty. If it is empty,
  1700. + this function should return TIOCSER_TEMT, otherwise return 0.
  1701. + If the port does not support this operation, then it should
  1702. + return TIOCSER_TEMT.
  1703. +
  1704. + set_mctrl(port, mctrl)
  1705. + This function sets the modem control lines for port described
  1706. + by 'port' to the state described by mctrl. The relevant bits
  1707. + of mctrl are:
  1708. + - TIOCM_RTS RTS signal.
  1709. + - TIOCM_DTR DTR signal.
  1710. + - TIOCM_OUT1 OUT1 signal.
  1711. + - TIOCM_OUT2 OUT2 signal.
  1712. + If the appropriate bit is set, the signal should be driven
  1713. + active. If the bit is clear, the signal should be driven
  1714. + inactive.
  1715. +
  1716. + get_mctrl(port)
  1717. + Returns the current state of modem control inputs. The state
  1718. + of the outputs should not be returned, since the core keeps
  1719. + track of their state. The state information should include:
  1720. + - TIOCM_DCD state of DCD signal
  1721. + - TIOCM_CTS state of CTS signal
  1722. + - TIOCM_DSR state of DSR signal
  1723. + - TIOCM_RI state of RI signal
  1724. + The bit is set if the signal is currently driven active. If
  1725. + the port does not support CTS, DCD or DSR, the driver should
  1726. + indicate that the signal is permanently active. If RI is
  1727. + not available, the signal should not be indicated as active.
  1728. +
  1729. + stop_tx(port,from_tty)
  1730. + Stop transmitting characters. This might be due to the CTS
  1731. + line becoming inactive or the tty layer indicating we want
  1732. + to stop transmission.
  1733. +
  1734. + start_tx(port,nonempty,from_tty)
  1735. + start transmitting characters. (incidentally, nonempty will
  1736. + always be nonzero, and shouldn't be used - it will be dropped).
  1737. +
  1738. + stop_rx(port)
  1739. + Stop receiving characters; the port is in the process of
  1740. + being closed.
  1741. +
  1742. + enable_ms(port)
  1743. + Enable the modem status interrupts.
  1744. +
  1745. + break_ctl(port,ctl)
  1746. + Control the transmission of a break signal. If ctl is
  1747. + nonzero, the break signal should be transmitted. The signal
  1748. + should be terminated when another call is made with a zero
  1749. + ctl.
  1750. +
  1751. + startup(port,info)
  1752. + Grab any interrupt resources and initialise any low level driver
  1753. + state. Enable the port for reception. It should not activate
  1754. + RTS nor DTR; this will be done via a separate call to set_mctrl.
  1755. +
  1756. + shutdown(port,info)
  1757. + Disable the port, disable any break condition that may be in
  1758. + effect, and free any interrupt resources. It should not disable
  1759. + RTS nor DTR; this will have already been done via a separate
  1760. + call to set_mctrl.
  1761. +
  1762. + change_speed(port,cflag,iflag,quot)
  1763. + Change the port parameters, including word length, parity, stop
  1764. + bits. Update read_status_mask and ignore_status_mask to indicate
  1765. + the types of events we are interested in receiving. Relevant
  1766. + cflag bits are:
  1767. + CSIZE - word size
  1768. + CSTOPB - 2 stop bits
  1769. + PARENB - parity enable
  1770. + PARODD - odd parity (when PARENB is in force)
  1771. + CREAD - enable reception of characters (if not set,
  1772. + still receive characters from the port, but
  1773. + throw them away.
  1774. + CRTSCTS - if set, enable CTS status change reporting
  1775. + CLOCAL - if not set, enable modem status change
  1776. + reporting.
  1777. + Relevant iflag bits are:
  1778. + INPCK - enable frame and parity error events to be
  1779. + passed to the TTY layer.
  1780. + BRKINT
  1781. + PARMRK - both of these enable break events to be
  1782. + passed to the TTY layer.
  1783. +
  1784. + IGNPAR - ignore parity and framing errors
  1785. + IGNBRK - ignore break errors, If IGNPAR is also
  1786. + set, ignore overrun errors as well.
  1787. + The interaction of the iflag bits is as follows (parity error
  1788. + given as an example):
  1789. + Parity error INPCK IGNPAR
  1790. + None n/a n/a character received
  1791. + Yes n/a 0 character discarded
  1792. + Yes 0 1 character received, marked as
  1793. + TTY_NORMAL
  1794. + Yes 1 1 character received, marked as
  1795. + TTY_PARITY
  1796. +
  1797. + pm(port,state,oldstate)
  1798. + perform any power management related activities on the specified
  1799. + port. state indicates the new state (defined by ACPI D0-D3),
  1800. + oldstate indicates the previous state. Essentially, D0 means
  1801. + fully on, D3 means powered down.
  1802. +
  1803. + This function should not be used to grab any resources.
  1804. +
  1805. + type(port)
  1806. + Return a pointer to a string constant describing the specified
  1807. + port, or return NULL, in which case the string 'unknown' is
  1808. + substituted.
  1809. +
  1810. + release_port(port)
  1811. + Release any memory and IO region resources currently in use by
  1812. + the port.
  1813. +
  1814. + request_port(port)
  1815. + Request any memory and IO region resources required by the port.
  1816. + If any fail, no resources should be registered when this function
  1817. + returns, and it should return -EBUSY on failure.
  1818. +
  1819. + config_port(port,type)
  1820. + Perform any autoconfiguration steps required for the port. `type`
  1821. + contains a bit mask of the required configuration. UART_CONFIG_TYPE
  1822. + indicates that the port requires detection and identification.
  1823. + port->type should be set to the type found, or PORT_UNKNOWN if
  1824. + no port was detected.
  1825. +
  1826. + UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal,
  1827. + which should be probed using standard kernel autoprobing techniques.
  1828. + This is not necessary on platforms where ports have interrupts
  1829. + internally hard wired (eg, system on a chip implementations).
  1830. +
  1831. + verify_port(port,serinfo)
  1832. + Verify the new serial port information contained within serinfo is
  1833. + suitable for this port type.
  1834. +
  1835. + ioctl(port,cmd,arg)
  1836. + Perform any port specific IOCTLs. IOCTL commands must be defined
  1837. + using the standard numbering system found in <asm/ioctl.h>
  1838. +
  1839. +
  1840. +Other notes
  1841. +-----------
  1842. +
  1843. +It is intended some day to drop the 'unused' entries from uart_port, and
  1844. +allow low level drivers to register their own individual uart_port's with
  1845. +the core. This will allow drivers to use uart_port as a pointer to a
  1846. +structure containing both the uart_port entry with their own extensions,
  1847. +thus:
  1848. +
  1849. + struct my_port {
  1850. + struct uart_port port;
  1851. + int my_stuff;
  1852. + };
  1853. +
  1854. diff -urN linux-2.4.26/MAINTAINERS linux-2.4.26-vrs1/MAINTAINERS
  1855. --- linux-2.4.26/MAINTAINERS 2004-04-19 11:44:14.000000000 +0100
  1856. +++ linux-2.4.26-vrs1/MAINTAINERS 2004-04-18 21:47:49.000000000 +0100
  1857. @@ -256,6 +256,8 @@
  1858. ARM/STRONGARM110 PORT
  1859. P: Russell King
  1860. M: rmk@arm.linux.org.uk
  1861. +P: Vincent Sanders
  1862. +M: vince@arm.linux.org.uk
  1863. L: linux-arm-kernel@lists.arm.linux.org.uk
  1864. W: http://www.arm.linux.org.uk/
  1865. S: Maintained
  1866. diff -urN linux-2.4.26/Makefile linux-2.4.26-vrs1/Makefile
  1867. --- linux-2.4.26/Makefile 2004-04-19 11:44:14.000000000 +0100
  1868. +++ linux-2.4.26-vrs1/Makefile 2004-04-18 21:50:41.000000000 +0100
  1869. @@ -1,7 +1,7 @@
  1870. VERSION = 2
  1871. PATCHLEVEL = 4
  1872. SUBLEVEL = 26
  1873. -EXTRAVERSION =
  1874. +EXTRAVERSION =-vrs1
  1875. KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
  1876. @@ -137,7 +137,10 @@
  1877. DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o
  1878. DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
  1879. -DRIVERS-y += drivers/char/char.o \
  1880. +DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
  1881. +DRIVERS-$(CONFIG_L3) += drivers/l3/l3.o
  1882. +DRIVERS-y += drivers/serial/serial.o \
  1883. + drivers/char/char.o \
  1884. drivers/block/block.o \
  1885. drivers/misc/misc.o \
  1886. drivers/net/net.o
  1887. @@ -161,6 +164,7 @@
  1888. DRIVERS-y += drivers/cdrom/driver.o
  1889. endif
  1890. +DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o
  1891. DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
  1892. DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
  1893. DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
  1894. @@ -186,7 +190,6 @@
  1895. DRIVERS-$(CONFIG_HIL) += drivers/hil/hil.o
  1896. DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
  1897. DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
  1898. -DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
  1899. DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
  1900. DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
  1901. DRIVERS-$(CONFIG_GSC) += drivers/gsc/gscbus.o
  1902. @@ -194,6 +197,8 @@
  1903. DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
  1904. DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
  1905. DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o
  1906. +DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o
  1907. +DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o
  1908. DRIVERS := $(DRIVERS-y)
  1909. @@ -274,11 +279,6 @@
  1910. export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
  1911. -.S.s:
  1912. - $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $<
  1913. -.S.o:
  1914. - $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $<
  1915. -
  1916. Version: dummy
  1917. @rm -f include/linux/compile.h
  1918. diff -urN linux-2.4.26/Rules.make linux-2.4.26-vrs1/Rules.make
  1919. --- linux-2.4.26/Rules.make 2004-02-27 20:03:23.000000000 +0000
  1920. +++ linux-2.4.26-vrs1/Rules.make 2004-02-23 13:36:21.000000000 +0000
  1921. @@ -51,15 +51,15 @@
  1922. #
  1923. %.s: %.c
  1924. - $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
  1925. + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o $@
  1926. %.i: %.c
  1927. - $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
  1928. + $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) $< > $@
  1929. %.o: %.c
  1930. - $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
  1931. + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -c -o $@ $<
  1932. @ ( \
  1933. - echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \
  1934. + echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$(*F)) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$(*F)) $$(CFLAGS_$@))))' ; \
  1935. echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
  1936. echo 'endif' \
  1937. ) > $(dir $@)/.$(notdir $@).flags
  1938. @@ -272,7 +272,8 @@
  1939. endif # CONFIG_MODVERSIONS
  1940. ifneq "$(strip $(export-objs))" ""
  1941. -$(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h
  1942. +$(export-objs): $(TOPDIR)/include/linux/modversions.h
  1943. +$(export-objs): %.o: %.c
  1944. $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
  1945. @ ( \
  1946. echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
  1947. diff -urN linux-2.4.26/arch/alpha/config.in linux-2.4.26-vrs1/arch/alpha/config.in
  1948. --- linux-2.4.26/arch/alpha/config.in 2004-02-27 20:03:23.000000000 +0000
  1949. +++ linux-2.4.26-vrs1/arch/alpha/config.in 2004-02-23 13:36:21.000000000 +0000
  1950. @@ -7,6 +7,7 @@
  1951. define_bool CONFIG_UID16 n
  1952. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
  1953. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
  1954. +define_bool CONFIG_GENERIC_ISA_DMA y
  1955. mainmenu_name "Kernel configuration of Linux for Alpha machines"
  1956. diff -urN linux-2.4.26/arch/arm/Makefile linux-2.4.26-vrs1/arch/arm/Makefile
  1957. --- linux-2.4.26/arch/arm/Makefile 2003-08-25 12:44:39.000000000 +0100
  1958. +++ linux-2.4.26-vrs1/arch/arm/Makefile 2004-01-14 21:32:23.000000000 +0000
  1959. @@ -52,7 +52,7 @@
  1960. CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
  1961. CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
  1962. -AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
  1963. +AFLAGS +=$(apcs-y) $(arch-y) -msoft-float
  1964. ifeq ($(CONFIG_CPU_26),y)
  1965. PROCESSOR := armo
  1966. diff -urN linux-2.4.26/arch/arm/boot/compressed/head.S linux-2.4.26-vrs1/arch/arm/boot/compressed/head.S
  1967. --- linux-2.4.26/arch/arm/boot/compressed/head.S 2003-08-25 12:44:39.000000000 +0100
  1968. +++ linux-2.4.26-vrs1/arch/arm/boot/compressed/head.S 2004-03-04 20:31:57.000000000 +0000
  1969. @@ -40,6 +40,14 @@
  1970. .macro writeb, rb
  1971. strb \rb, [r3, #0x3f8 << 2]
  1972. .endm
  1973. +#elif defined(CONFIG_ARCH_RISCSTATION)
  1974. + .macro loadsp, rb
  1975. + mov \rb, #0x03000000
  1976. + orr \rb, \rb, #0x00010000
  1977. + .endm
  1978. + .macro writeb, rb
  1979. + strb \rb, [r3, #0x3f8 << 2]
  1980. + .endm
  1981. #elif defined(CONFIG_ARCH_INTEGRATOR)
  1982. .macro loadsp, rb
  1983. mov \rb, #0x16000000
  1984. @@ -396,6 +404,20 @@
  1985. mcr p15, 0, r0, c1, c0, 0 @ load control register
  1986. mov pc, r12
  1987. +__arm7_cache_on:
  1988. + mov r12, lr
  1989. + bl __setup_mmu
  1990. + mov r0, #0
  1991. + mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
  1992. + mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
  1993. + mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
  1994. + mov r0, #-1
  1995. + mcr p15, 0, r0, c3, c0, 0 @ load domain access control
  1996. + mov r0, #0x7d
  1997. + mcr p15, 0, r0, c1, c0, 0 @ load control register
  1998. + mov pc, r12
  1999. +
  2000. +
  2001. /*
  2002. * All code following this line is relocatable. It is relocated by
  2003. * the above code to the end of the decompressed kernel image and
  2004. @@ -480,9 +502,9 @@
  2005. .word 0x41007000 @ ARM7/710
  2006. .word 0xfff8fe00
  2007. + b __arm7_cache_on
  2008. b __arm7_cache_off
  2009. - b __arm7_cache_off
  2010. - mov pc, lr
  2011. + b __armv3_cache_flush
  2012. .word 0x41807200 @ ARM720T (writethrough)
  2013. .word 0xffffff00
  2014. @@ -490,14 +512,14 @@
  2015. b __armv4_cache_off
  2016. mov pc, lr
  2017. - .word 0x41129200 @ ARM920T
  2018. - .word 0xff00fff0
  2019. + .word 0x41009200 @ ARM920T, ARM922T, ARM926TEJ-S
  2020. + .word 0xff00ff90
  2021. b __armv4_cache_on
  2022. b __armv4_cache_off
  2023. b __armv4_cache_flush
  2024. - .word 0x41029220 @ ARM922T
  2025. - .word 0xff00fff0
  2026. + .word 0x4100a200 @ ARM1020T/E, ARM1022E, ARM1026TEJ-S
  2027. + .word 0xff00ff90
  2028. b __armv4_cache_on
  2029. b __armv4_cache_off
  2030. b __armv4_cache_flush
  2031. diff -urN linux-2.4.26/arch/arm/config.in linux-2.4.26-vrs1/arch/arm/config.in
  2032. --- linux-2.4.26/arch/arm/config.in 2004-02-27 20:03:23.000000000 +0000
  2033. +++ linux-2.4.26-vrs1/arch/arm/config.in 2004-04-10 12:21:08.000000000 +0100
  2034. @@ -144,6 +144,7 @@
  2035. mainmenu_option next_comment
  2036. comment 'AT91RM9200 Implementations'
  2037. dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200
  2038. +dep_bool ' Cogent CSB337' CONFIG_MACH_CSB337 $CONFIG_ARCH_AT91RM9200
  2039. endmenu
  2040. mainmenu_option next_comment
  2041. @@ -189,6 +190,12 @@
  2042. define_bool CONFIG_ARCH_ACORN n
  2043. fi
  2044. +if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
  2045. + define_bool CONFIG_PLD y
  2046. +else
  2047. + define_bool CONFIG_PLD n
  2048. +fi
  2049. +
  2050. #####################################################################
  2051. # Footbridge support
  2052. if [ "$CONFIG_ARCH_CO285" = "y" -o \
  2053. @@ -315,26 +322,42 @@
  2054. # ARM922T
  2055. if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
  2056. define_bool CONFIG_CPU_ARM922T y
  2057. - define_bool CONFIG_PLD y
  2058. else
  2059. - define_bool CONFIG_CPU_ARM922T n
  2060. - define_bool CONFIG_PLD n
  2061. + if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
  2062. + bool 'Support ARM922T(Excalibur) processor' CONFIG_ARM922T
  2063. + else
  2064. + define_bool CONFIG_CPU_ARM922T n
  2065. + fi
  2066. fi
  2067. # ARM926T
  2068. if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
  2069. - bool 'Support ARM926T processor' CONFIG_CPU_ARM926T
  2070. + bool 'Support ARM926TEJ-S processor' CONFIG_CPU_ARM926T
  2071. else
  2072. define_bool CONFIG_CPU_ARM926T n
  2073. fi
  2074. # ARM1020
  2075. if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
  2076. - bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
  2077. + bool 'Support ARM1020T (Rev0) processor' CONFIG_CPU_ARM1020
  2078. else
  2079. define_bool CONFIG_CPU_ARM1020 n
  2080. fi
  2081. +# ARM1020E
  2082. +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
  2083. + bool 'Support ARM1020E (Rev1) processor' CONFIG_CPU_ARM1020E
  2084. +else
  2085. + define_bool CONFIG_CPU_ARM1020E n
  2086. +fi
  2087. +
  2088. +# ARM1022
  2089. +if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
  2090. + bool 'Support ARM1022 processor' CONFIG_CPU_ARM1020E
  2091. +else
  2092. + define_bool CONFIG_CPU_ARM1022 n
  2093. +fi
  2094. +
  2095. # ARM1026EJ-S
  2096. if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
  2097. bool 'Support ARM1026EJ-S processor' CONFIG_CPU_ARM1026
  2098. @@ -388,25 +411,29 @@
  2099. if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
  2100. "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
  2101. - "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
  2102. + "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
  2103. + "$CONFIG_CPU_ARM1022" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
  2104. dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
  2105. fi
  2106. if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
  2107. "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
  2108. + "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
  2109. "$CONFIG_CPU_ARM1026" = "y" ]; then
  2110. bool 'Disable I-Cache' CONFIG_CPU_ICACHE_DISABLE
  2111. bool 'Disable D-Cache' CONFIG_CPU_DCACHE_DISABLE
  2112. - if [ "$CONFIG_CPU_DISABLE_DCACHE" = "n" ]; then
  2113. + if [ "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
  2114. bool 'Force write through D-cache' CONFIG_CPU_DCACHE_WRITETHROUGH
  2115. fi
  2116. fi
  2117. if [ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
  2118. + "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
  2119. "$CONFIG_CPU_ARM1026" = "y" ]; then
  2120. if [ "$CONFIG_CPU_ICACHE_DISABLE" = "n" -o "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
  2121. bool 'Round robin I and D cache replacement algorithm' CONFIG_CPU_CACHE_ROUND_ROBIN
  2122. fi
  2123. fi
  2124. -if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
  2125. +if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
  2126. + "$CONFIG_CPU_ARM1026" = "y" -o "$CONFIG_CPU_ARM1022" = "y" ]; then
  2127. bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE
  2128. fi
  2129. @@ -514,7 +541,8 @@
  2130. "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
  2131. "$CONFIG_ARCH_CDB89712" = "y" -o \
  2132. "$CONFIG_ARCH_P720T" = "y" -o \
  2133. - "$CONFIG_ARCH_OMAHA" = "y" ]; then
  2134. + "$CONFIG_ARCH_OMAHA" = "y" -o \
  2135. + "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  2136. bool 'Timer and CPU usage LEDs' CONFIG_LEDS
  2137. if [ "$CONFIG_LEDS" = "y" ]; then
  2138. if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
  2139. @@ -524,7 +552,8 @@
  2140. "$CONFIG_ARCH_SA1100" = "y" -o \
  2141. "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
  2142. "$CONFIG_ARCH_P720T" = "y" -o \
  2143. - "$CONFIG_ARCH_OMAHA" = "y" ]; then
  2144. + "$CONFIG_ARCH_OMAHA" = "y" -o \
  2145. + "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  2146. bool ' Timer LED' CONFIG_LEDS_TIMER
  2147. bool ' CPU usage LED' CONFIG_LEDS_CPU
  2148. fi
  2149. @@ -729,10 +758,7 @@
  2150. dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
  2151. dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
  2152. dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
  2153. -
  2154. -int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
  2155. -
  2156. endmenu
  2157. -source crypto/Config.in
  2158. source lib/Config.in
  2159. +
  2160. diff -urN linux-2.4.26/arch/arm/def-configs/at91rm9200dk linux-2.4.26-vrs1/arch/arm/def-configs/at91rm9200dk
  2161. --- linux-2.4.26/arch/arm/def-configs/at91rm9200dk 2004-02-27 20:03:23.000000000 +0000
  2162. +++ linux-2.4.26-vrs1/arch/arm/def-configs/at91rm9200dk 2004-03-04 22:47:46.000000000 +0000
  2163. @@ -111,6 +111,7 @@
  2164. # AT91RM9200 Implementations
  2165. #
  2166. CONFIG_ARCH_AT91RM9200DK=y
  2167. +# CONFIG_MACH_CSB337 is not set
  2168. #
  2169. # CLPS711X/EP721X Implementations
  2170. @@ -125,6 +126,7 @@
  2171. # CONFIG_ARCH_EP7211 is not set
  2172. # CONFIG_ARCH_EP7212 is not set
  2173. # CONFIG_ARCH_ACORN is not set
  2174. +# CONFIG_PLD is not set
  2175. # CONFIG_FOOTBRIDGE is not set
  2176. # CONFIG_FOOTBRIDGE_HOST is not set
  2177. # CONFIG_FOOTBRIDGE_ADDIN is not set
  2178. @@ -135,9 +137,10 @@
  2179. # CONFIG_CPU_ARM720T is not set
  2180. CONFIG_CPU_ARM920T=y
  2181. # CONFIG_CPU_ARM922T is not set
  2182. -# CONFIG_PLD is not set
  2183. # CONFIG_CPU_ARM926T is not set
  2184. # CONFIG_CPU_ARM1020 is not set
  2185. +# CONFIG_CPU_ARM1020E is not set
  2186. +# CONFIG_CPU_ARM1022 is not set
  2187. # CONFIG_CPU_ARM1026 is not set
  2188. # CONFIG_CPU_SA110 is not set
  2189. # CONFIG_CPU_SA1100 is not set
  2190. @@ -146,6 +149,7 @@
  2191. # CONFIG_ARM_THUMB is not set
  2192. # CONFIG_CPU_ICACHE_DISABLE is not set
  2193. # CONFIG_CPU_DCACHE_DISABLE is not set
  2194. +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
  2195. # CONFIG_DISCONTIGMEM is not set
  2196. #
  2197. @@ -164,6 +168,7 @@
  2198. # CONFIG_BSD_PROCESS_ACCT is not set
  2199. CONFIG_SYSCTL=y
  2200. CONFIG_FPE_NWFPE=y
  2201. +# CONFIG_FPE_NWFPE_XP is not set
  2202. # CONFIG_FPE_FASTFPE is not set
  2203. CONFIG_KCORE_ELF=y
  2204. # CONFIG_KCORE_AOUT is not set
  2205. @@ -173,6 +178,9 @@
  2206. # CONFIG_PM is not set
  2207. # CONFIG_ARTHUR is not set
  2208. CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20210000,3145728 root=/dev/ram rw"
  2209. +CONFIG_LEDS=y
  2210. +CONFIG_LEDS_TIMER=y
  2211. +# CONFIG_LEDS_CPU is not set
  2212. CONFIG_ALIGNMENT_TRAP=y
  2213. #
  2214. @@ -204,6 +212,7 @@
  2215. # CONFIG_MTD_CFI_ADV_OPTIONS is not set
  2216. # CONFIG_MTD_CFI_INTELEXT is not set
  2217. CONFIG_MTD_CFI_AMDSTD=y
  2218. +# CONFIG_MTD_CFI_STAA is not set
  2219. # CONFIG_MTD_RAM is not set
  2220. # CONFIG_MTD_ROM is not set
  2221. # CONFIG_MTD_ABSENT is not set
  2222. @@ -230,7 +239,9 @@
  2223. # CONFIG_MTD_AUTCPU12 is not set
  2224. # CONFIG_MTD_EDB7312 is not set
  2225. # CONFIG_MTD_IMPA7 is not set
  2226. +# CONFIG_MTD_CEIVA is not set
  2227. # CONFIG_MTD_PCI is not set
  2228. +# CONFIG_MTD_PCMCIA is not set
  2229. #
  2230. # Self-contained MTD device drivers
  2231. @@ -250,9 +261,9 @@
  2232. # NAND Flash Device Drivers
  2233. #
  2234. CONFIG_MTD_NAND=y
  2235. -CONFIG_MTD_NAND_ECC=y
  2236. # CONFIG_MTD_NAND_VERIFY_WRITE is not set
  2237. -CONFIG_MTD_AT91_SMARTMEDIA=y
  2238. +CONFIG_MTD_NAND_IDS=y
  2239. +# CONFIG_MTD_AT91_SMARTMEDIA is not set
  2240. #
  2241. # Plug and Play configuration
  2242. @@ -269,6 +280,7 @@
  2243. # CONFIG_BLK_CPQ_DA is not set
  2244. # CONFIG_BLK_CPQ_CISS_DA is not set
  2245. # CONFIG_CISS_SCSI_TAPE is not set
  2246. +# CONFIG_CISS_MONITOR_THREAD is not set
  2247. # CONFIG_BLK_DEV_DAC960 is not set
  2248. # CONFIG_BLK_DEV_UMEM is not set
  2249. # CONFIG_BLK_DEV_LOOP is not set
  2250. @@ -276,6 +288,7 @@
  2251. CONFIG_BLK_DEV_RAM=y
  2252. CONFIG_BLK_DEV_RAM_SIZE=8192
  2253. CONFIG_BLK_DEV_INITRD=y
  2254. +# CONFIG_BLK_STATS is not set
  2255. #
  2256. # Multi-device support (RAID and LVM)
  2257. @@ -312,6 +325,12 @@
  2258. # CONFIG_SYN_COOKIES is not set
  2259. # CONFIG_IPV6 is not set
  2260. # CONFIG_KHTTPD is not set
  2261. +
  2262. +#
  2263. +# SCTP Configuration (EXPERIMENTAL)
  2264. +#
  2265. +CONFIG_IPV6_SCTP__=y
  2266. +# CONFIG_IP_SCTP is not set
  2267. # CONFIG_ATM is not set
  2268. # CONFIG_VLAN_8021Q is not set
  2269. # CONFIG_IPX is not set
  2270. @@ -382,10 +401,12 @@
  2271. #
  2272. # CONFIG_ACENIC is not set
  2273. # CONFIG_DL2K is not set
  2274. +# CONFIG_E1000 is not set
  2275. # CONFIG_MYRI_SBUS is not set
  2276. # CONFIG_NS83820 is not set
  2277. # CONFIG_HAMACHI is not set
  2278. # CONFIG_YELLOWFIN is not set
  2279. +# CONFIG_R8169 is not set
  2280. # CONFIG_SK98LIN is not set
  2281. # CONFIG_TIGON3 is not set
  2282. # CONFIG_FDDI is not set
  2283. @@ -455,6 +476,8 @@
  2284. # CONFIG_INPUT_MOUSEDEV is not set
  2285. # CONFIG_INPUT_JOYDEV is not set
  2286. # CONFIG_INPUT_EVDEV is not set
  2287. +# CONFIG_INPUT_UINPUT is not set
  2288. +# CONFIG_INPUT_MX1TS is not set
  2289. #
  2290. # Character devices
  2291. @@ -502,6 +525,7 @@
  2292. #
  2293. CONFIG_I2C=y
  2294. # CONFIG_I2C_ALGOBIT is not set
  2295. +# CONFIG_SCx200_ACB is not set
  2296. # CONFIG_I2C_ALGOPCF is not set
  2297. CONFIG_I2C_AT91=y
  2298. CONFIG_I2C_CHARDEV=y
  2299. @@ -528,6 +552,11 @@
  2300. #
  2301. # CONFIG_INPUT_GAMEPORT is not set
  2302. # CONFIG_QIC02_TAPE is not set
  2303. +# CONFIG_IPMI_HANDLER is not set
  2304. +# CONFIG_IPMI_PANIC_EVENT is not set
  2305. +# CONFIG_IPMI_DEVICE_INTERFACE is not set
  2306. +# CONFIG_IPMI_KCS is not set
  2307. +# CONFIG_IPMI_WATCHDOG is not set
  2308. #
  2309. # Watchdog Cards
  2310. @@ -536,12 +565,14 @@
  2311. CONFIG_WATCHDOG_NOWAYOUT=y
  2312. # CONFIG_ACQUIRE_WDT is not set
  2313. # CONFIG_ADVANTECH_WDT is not set
  2314. +# CONFIG_ALIM1535_WDT is not set
  2315. # CONFIG_ALIM7101_WDT is not set
  2316. # CONFIG_SC520_WDT is not set
  2317. # CONFIG_PCWATCHDOG is not set
  2318. # CONFIG_21285_WATCHDOG is not set
  2319. # CONFIG_977_WATCHDOG is not set
  2320. # CONFIG_SA1100_WATCHDOG is not set
  2321. +# CONFIG_EPXA_WATCHDOG is not set
  2322. # CONFIG_OMAHA_WATCHDOG is not set
  2323. CONFIG_AT91_WATCHDOG=y
  2324. # CONFIG_EUROTECH_WDT is not set
  2325. @@ -551,11 +582,16 @@
  2326. # CONFIG_MIXCOMWD is not set
  2327. # CONFIG_60XX_WDT is not set
  2328. # CONFIG_SC1200_WDT is not set
  2329. +# CONFIG_SCx200_WDT is not set
  2330. # CONFIG_SOFT_WATCHDOG is not set
  2331. # CONFIG_W83877F_WDT is not set
  2332. # CONFIG_WDT is not set
  2333. # CONFIG_WDTPCI is not set
  2334. # CONFIG_MACHZ_WDT is not set
  2335. +# CONFIG_AMD7XX_TCO is not set
  2336. +# CONFIG_SCx200 is not set
  2337. +# CONFIG_SCx200_GPIO is not set
  2338. +# CONFIG_AMD_PM768 is not set
  2339. # CONFIG_NVRAM is not set
  2340. # CONFIG_RTC is not set
  2341. CONFIG_AT91_RTC=y
  2342. @@ -568,6 +604,10 @@
  2343. #
  2344. # CONFIG_FTAPE is not set
  2345. # CONFIG_AGP is not set
  2346. +
  2347. +#
  2348. +# Direct Rendering Manager (XFree86 DRI support)
  2349. +#
  2350. # CONFIG_DRM is not set
  2351. #
  2352. @@ -579,6 +619,7 @@
  2353. # File systems
  2354. #
  2355. # CONFIG_QUOTA is not set
  2356. +# CONFIG_QFMT_V2 is not set
  2357. # CONFIG_AUTOFS_FS is not set
  2358. # CONFIG_AUTOFS4_FS is not set
  2359. # CONFIG_REISERFS_FS is not set
  2360. @@ -588,6 +629,9 @@
  2361. # CONFIG_ADFS_FS_RW is not set
  2362. # CONFIG_AFFS_FS is not set
  2363. # CONFIG_HFS_FS is not set
  2364. +# CONFIG_HFSPLUS_FS is not set
  2365. +# CONFIG_BEFS_FS is not set
  2366. +# CONFIG_BEFS_DEBUG is not set
  2367. # CONFIG_BFS_FS is not set
  2368. # CONFIG_EXT3_FS is not set
  2369. # CONFIG_JBD is not set
  2370. @@ -605,6 +649,9 @@
  2371. # CONFIG_ISO9660_FS is not set
  2372. # CONFIG_JOLIET is not set
  2373. # CONFIG_ZISOFS is not set
  2374. +# CONFIG_JFS_FS is not set
  2375. +# CONFIG_JFS_DEBUG is not set
  2376. +# CONFIG_JFS_STATISTICS is not set
  2377. # CONFIG_MINIX_FS is not set
  2378. # CONFIG_VXFS_FS is not set
  2379. # CONFIG_NTFS_FS is not set
  2380. @@ -624,6 +671,11 @@
  2381. # CONFIG_UDF_RW is not set
  2382. # CONFIG_UFS_FS is not set
  2383. # CONFIG_UFS_FS_WRITE is not set
  2384. +# CONFIG_XFS_FS is not set
  2385. +# CONFIG_XFS_QUOTA is not set
  2386. +# CONFIG_XFS_RT is not set
  2387. +# CONFIG_XFS_TRACE is not set
  2388. +# CONFIG_XFS_DEBUG is not set
  2389. #
  2390. # Network File Systems
  2391. @@ -632,9 +684,11 @@
  2392. # CONFIG_INTERMEZZO_FS is not set
  2393. # CONFIG_NFS_FS is not set
  2394. # CONFIG_NFS_V3 is not set
  2395. +# CONFIG_NFS_DIRECTIO is not set
  2396. # CONFIG_ROOT_NFS is not set
  2397. # CONFIG_NFSD is not set
  2398. # CONFIG_NFSD_V3 is not set
  2399. +# CONFIG_NFSD_TCP is not set
  2400. # CONFIG_SUNRPC is not set
  2401. # CONFIG_LOCKD is not set
  2402. # CONFIG_SMB_FS is not set
  2403. @@ -648,7 +702,6 @@
  2404. # CONFIG_NCPFS_NLS is not set
  2405. # CONFIG_NCPFS_EXTRAS is not set
  2406. # CONFIG_ZISOFS_FS is not set
  2407. -# CONFIG_ZLIB_FS_INFLATE is not set
  2408. #
  2409. # Partition Types
  2410. @@ -674,16 +727,18 @@
  2411. # CONFIG_USB_DEBUG is not set
  2412. # CONFIG_USB_DEVICEFS is not set
  2413. # CONFIG_USB_BANDWIDTH is not set
  2414. -# CONFIG_USB_LONG_TIMEOUT is not set
  2415. # CONFIG_USB_EHCI_HCD is not set
  2416. # CONFIG_USB_UHCI is not set
  2417. # CONFIG_USB_UHCI_ALT is not set
  2418. # CONFIG_USB_OHCI is not set
  2419. # CONFIG_USB_OHCI_SA1111 is not set
  2420. +# CONFIG_USB_SL811HS_ALT is not set
  2421. +# CONFIG_USB_SL811HS is not set
  2422. CONFIG_USB_OHCI_AT91=y
  2423. # CONFIG_USB_AUDIO is not set
  2424. # CONFIG_USB_EMI26 is not set
  2425. # CONFIG_USB_BLUETOOTH is not set
  2426. +# CONFIG_USB_MIDI is not set
  2427. # CONFIG_USB_STORAGE is not set
  2428. # CONFIG_USB_STORAGE_DEBUG is not set
  2429. # CONFIG_USB_STORAGE_DATAFAB is not set
  2430. @@ -692,6 +747,7 @@
  2431. # CONFIG_USB_STORAGE_DPCM is not set
  2432. # CONFIG_USB_STORAGE_HP8200e is not set
  2433. # CONFIG_USB_STORAGE_SDDR09 is not set
  2434. +# CONFIG_USB_STORAGE_SDDR55 is not set
  2435. # CONFIG_USB_STORAGE_JUMPSHOT is not set
  2436. # CONFIG_USB_ACM is not set
  2437. # CONFIG_USB_PRINTER is not set
  2438. @@ -700,7 +756,10 @@
  2439. # CONFIG_USB_HIDDEV is not set
  2440. # CONFIG_USB_KBD is not set
  2441. # CONFIG_USB_MOUSE is not set
  2442. +# CONFIG_USB_AIPTEK is not set
  2443. # CONFIG_USB_WACOM is not set
  2444. +# CONFIG_USB_KBTAB is not set
  2445. +# CONFIG_USB_POWERMATE is not set
  2446. # CONFIG_USB_DC2XX is not set
  2447. # CONFIG_USB_MDC800 is not set
  2448. # CONFIG_USB_SCANNER is not set
  2449. @@ -718,35 +777,16 @@
  2450. # USB Serial Converter support
  2451. #
  2452. # CONFIG_USB_SERIAL is not set
  2453. -# CONFIG_USB_SERIAL_GENERIC is not set
  2454. -# CONFIG_USB_SERIAL_BELKIN is not set
  2455. -# CONFIG_USB_SERIAL_WHITEHEAT is not set
  2456. -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
  2457. -# CONFIG_USB_SERIAL_EMPEG is not set
  2458. -# CONFIG_USB_SERIAL_FTDI_SIO is not set
  2459. -# CONFIG_USB_SERIAL_VISOR is not set
  2460. -# CONFIG_USB_SERIAL_IPAQ is not set
  2461. -# CONFIG_USB_SERIAL_IR is not set
  2462. -# CONFIG_USB_SERIAL_EDGEPORT is not set
  2463. -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
  2464. -# CONFIG_USB_SERIAL_KEYSPAN is not set
  2465. -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
  2466. -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
  2467. -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
  2468. -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
  2469. -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
  2470. -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
  2471. -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
  2472. -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
  2473. -# CONFIG_USB_SERIAL_MCT_U232 is not set
  2474. -# CONFIG_USB_SERIAL_KLSI is not set
  2475. -# CONFIG_USB_SERIAL_PL2303 is not set
  2476. -# CONFIG_USB_SERIAL_CYBERJACK is not set
  2477. -# CONFIG_USB_SERIAL_XIRCOM is not set
  2478. -# CONFIG_USB_SERIAL_OMNINET is not set
  2479. # CONFIG_USB_RIO500 is not set
  2480. # CONFIG_USB_AUERSWALD is not set
  2481. +# CONFIG_USB_TIGL is not set
  2482. # CONFIG_USB_BRLVGER is not set
  2483. +# CONFIG_USB_LCD is not set
  2484. +
  2485. +#
  2486. +# Support for USB gadgets
  2487. +#
  2488. +# CONFIG_USB_GADGET is not set
  2489. #
  2490. # Bluetooth support
  2491. @@ -770,3 +810,10 @@
  2492. CONFIG_DEBUG_LL=y
  2493. # CONFIG_DEBUG_DC21285_PORT is not set
  2494. # CONFIG_DEBUG_CLPS711X_UART2 is not set
  2495. +
  2496. +#
  2497. +# Library routines
  2498. +#
  2499. +CONFIG_CRC32=y
  2500. +# CONFIG_ZLIB_INFLATE is not set
  2501. +# CONFIG_ZLIB_DEFLATE is not set
  2502. diff -urN linux-2.4.26/arch/arm/def-configs/csb337 linux-2.4.26-vrs1/arch/arm/def-configs/csb337
  2503. --- linux-2.4.26/arch/arm/def-configs/csb337 1970-01-01 01:00:00.000000000 +0100
  2504. +++ linux-2.4.26-vrs1/arch/arm/def-configs/csb337 2004-03-04 22:44:33.000000000 +0000
  2505. @@ -0,0 +1,760 @@
  2506. +#
  2507. +# Automatically generated by make menuconfig: don't edit
  2508. +#
  2509. +CONFIG_ARM=y
  2510. +# CONFIG_EISA is not set
  2511. +# CONFIG_SBUS is not set
  2512. +# CONFIG_MCA is not set
  2513. +CONFIG_UID16=y
  2514. +CONFIG_RWSEM_GENERIC_SPINLOCK=y
  2515. +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
  2516. +# CONFIG_GENERIC_BUST_SPINLOCK is not set
  2517. +# CONFIG_GENERIC_ISA_DMA is not set
  2518. +
  2519. +#
  2520. +# Code maturity level options
  2521. +#
  2522. +CONFIG_EXPERIMENTAL=y
  2523. +# CONFIG_OBSOLETE is not set
  2524. +
  2525. +#
  2526. +# Loadable module support
  2527. +#
  2528. +CONFIG_MODULES=y
  2529. +# CONFIG_MODVERSIONS is not set
  2530. +CONFIG_KMOD=y
  2531. +
  2532. +#
  2533. +# System Type
  2534. +#
  2535. +# CONFIG_ARCH_ANAKIN is not set
  2536. +# CONFIG_ARCH_ARCA5K is not set
  2537. +# CONFIG_ARCH_CLPS7500 is not set
  2538. +# CONFIG_ARCH_CLPS711X is not set
  2539. +# CONFIG_ARCH_CO285 is not set
  2540. +# CONFIG_ARCH_EBSA110 is not set
  2541. +# CONFIG_ARCH_CAMELOT is not set
  2542. +# CONFIG_ARCH_FOOTBRIDGE is not set
  2543. +# CONFIG_ARCH_INTEGRATOR is not set
  2544. +# CONFIG_ARCH_OMAHA is not set
  2545. +# CONFIG_ARCH_L7200 is not set
  2546. +# CONFIG_ARCH_MX1ADS is not set
  2547. +# CONFIG_ARCH_RPC is not set
  2548. +# CONFIG_ARCH_RISCSTATION is not set
  2549. +# CONFIG_ARCH_SA1100 is not set
  2550. +# CONFIG_ARCH_SHARK is not set
  2551. +CONFIG_ARCH_AT91RM9200=y
  2552. +
  2553. +#
  2554. +# Archimedes/A5000 Implementations
  2555. +#
  2556. +# CONFIG_ARCH_ARC is not set
  2557. +# CONFIG_ARCH_A5K is not set
  2558. +
  2559. +#
  2560. +# Footbridge Implementations
  2561. +#
  2562. +# CONFIG_ARCH_CATS is not set
  2563. +# CONFIG_ARCH_PERSONAL_SERVER is not set
  2564. +# CONFIG_ARCH_EBSA285_ADDIN is not set
  2565. +# CONFIG_ARCH_EBSA285_HOST is not set
  2566. +# CONFIG_ARCH_NETWINDER is not set
  2567. +
  2568. +#
  2569. +# SA11x0 Implementations
  2570. +#
  2571. +# CONFIG_SA1100_ACCELENT is not set
  2572. +# CONFIG_SA1100_ASSABET is not set
  2573. +# CONFIG_ASSABET_NEPONSET is not set
  2574. +# CONFIG_SA1100_ADSAGC is not set
  2575. +# CONFIG_SA1100_ADSBITSY is not set
  2576. +# CONFIG_SA1100_ADSBITSYPLUS is not set
  2577. +# CONFIG_SA1100_BRUTUS is not set
  2578. +# CONFIG_SA1100_CEP is not set
  2579. +# CONFIG_SA1100_CERF is not set
  2580. +# CONFIG_SA1100_H3100 is not set
  2581. +# CONFIG_SA1100_H3600 is not set
  2582. +# CONFIG_SA1100_H3800 is not set
  2583. +# CONFIG_SA1100_H3XXX is not set
  2584. +# CONFIG_H3600_SLEEVE is not set
  2585. +# CONFIG_SA1100_EXTENEX1 is not set
  2586. +# CONFIG_SA1100_FLEXANET is not set
  2587. +# CONFIG_SA1100_FREEBIRD is not set
  2588. +# CONFIG_SA1100_FRODO is not set
  2589. +# CONFIG_SA1100_GRAPHICSCLIENT is not set
  2590. +# CONFIG_SA1100_GRAPHICSMASTER is not set
  2591. +# CONFIG_SA1100_HACKKIT is not set
  2592. +# CONFIG_SA1100_BADGE4 is not set
  2593. +# CONFIG_SA1100_JORNADA720 is not set
  2594. +# CONFIG_SA1100_HUW_WEBPANEL is not set
  2595. +# CONFIG_SA1100_ITSY is not set
  2596. +# CONFIG_SA1100_LART is not set
  2597. +# CONFIG_SA1100_NANOENGINE is not set
  2598. +# CONFIG_SA1100_OMNIMETER is not set
  2599. +# CONFIG_SA1100_PANGOLIN is not set
  2600. +# CONFIG_SA1100_PLEB is not set
  2601. +# CONFIG_SA1100_PT_SYSTEM3 is not set
  2602. +# CONFIG_SA1100_SHANNON is not set
  2603. +# CONFIG_SA1100_SHERMAN is not set
  2604. +# CONFIG_SA1100_SIMPAD is not set
  2605. +# CONFIG_SA1100_SIMPUTER is not set
  2606. +# CONFIG_SA1100_PFS168 is not set
  2607. +# CONFIG_SA1100_VICTOR is not set
  2608. +# CONFIG_SA1100_XP860 is not set
  2609. +# CONFIG_SA1100_YOPY is not set
  2610. +# CONFIG_SA1100_USB is not set
  2611. +# CONFIG_SA1100_USB_NETLINK is not set
  2612. +# CONFIG_SA1100_USB_CHAR is not set
  2613. +# CONFIG_SA1100_SSP is not set
  2614. +
  2615. +#
  2616. +# AT91RM9200 Implementations
  2617. +#
  2618. +# CONFIG_ARCH_AT91RM9200DK is not set
  2619. +CONFIG_MACH_CSB337=y
  2620. +
  2621. +#
  2622. +# CLPS711X/EP721X Implementations
  2623. +#
  2624. +# CONFIG_ARCH_AUTCPU12 is not set
  2625. +# CONFIG_ARCH_CDB89712 is not set
  2626. +# CONFIG_ARCH_CLEP7312 is not set
  2627. +# CONFIG_ARCH_EDB7211 is not set
  2628. +# CONFIG_ARCH_FORTUNET is not set
  2629. +# CONFIG_ARCH_GUIDEA07 is not set
  2630. +# CONFIG_ARCH_P720T is not set
  2631. +# CONFIG_ARCH_EP7211 is not set
  2632. +# CONFIG_ARCH_EP7212 is not set
  2633. +# CONFIG_ARCH_ACORN is not set
  2634. +# CONFIG_PLD is not set
  2635. +# CONFIG_FOOTBRIDGE is not set
  2636. +# CONFIG_FOOTBRIDGE_HOST is not set
  2637. +# CONFIG_FOOTBRIDGE_ADDIN is not set
  2638. +CONFIG_CPU_32=y
  2639. +# CONFIG_CPU_26 is not set
  2640. +# CONFIG_CPU_ARM610 is not set
  2641. +# CONFIG_CPU_ARM710 is not set
  2642. +# CONFIG_CPU_ARM720T is not set
  2643. +CONFIG_CPU_ARM920T=y
  2644. +# CONFIG_CPU_ARM922T is not set
  2645. +# CONFIG_CPU_ARM926T is not set
  2646. +# CONFIG_CPU_ARM1020 is not set
  2647. +# CONFIG_CPU_ARM1020E is not set
  2648. +# CONFIG_CPU_ARM1022 is not set
  2649. +# CONFIG_CPU_ARM1026 is not set
  2650. +# CONFIG_CPU_SA110 is not set
  2651. +# CONFIG_CPU_SA1100 is not set
  2652. +# CONFIG_CPU_32v3 is not set
  2653. +CONFIG_CPU_32v4=y
  2654. +# CONFIG_ARM_THUMB is not set
  2655. +# CONFIG_CPU_ICACHE_DISABLE is not set
  2656. +# CONFIG_CPU_DCACHE_DISABLE is not set
  2657. +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
  2658. +# CONFIG_DISCONTIGMEM is not set
  2659. +
  2660. +#
  2661. +# General setup
  2662. +#
  2663. +# CONFIG_PCI is not set
  2664. +# CONFIG_ISA is not set
  2665. +# CONFIG_ISA_DMA is not set
  2666. +# CONFIG_ZBOOT_ROM is not set
  2667. +CONFIG_ZBOOT_ROM_TEXT=0
  2668. +CONFIG_ZBOOT_ROM_BSS=0
  2669. +# CONFIG_HOTPLUG is not set
  2670. +# CONFIG_PCMCIA is not set
  2671. +CONFIG_NET=y
  2672. +CONFIG_SYSVIPC=y
  2673. +# CONFIG_BSD_PROCESS_ACCT is not set
  2674. +CONFIG_SYSCTL=y
  2675. +CONFIG_FPE_NWFPE=y
  2676. +# CONFIG_FPE_NWFPE_XP is not set
  2677. +# CONFIG_FPE_FASTFPE is not set
  2678. +CONFIG_KCORE_ELF=y
  2679. +# CONFIG_KCORE_AOUT is not set
  2680. +# CONFIG_BINFMT_AOUT is not set
  2681. +CONFIG_BINFMT_ELF=y
  2682. +# CONFIG_BINFMT_MISC is not set
  2683. +# CONFIG_PM is not set
  2684. +# CONFIG_ARTHUR is not set
  2685. +CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20210000,3145728 root=/dev/ram rw"
  2686. +# CONFIG_LEDS is not set
  2687. +CONFIG_ALIGNMENT_TRAP=y
  2688. +
  2689. +#
  2690. +# Parallel port support
  2691. +#
  2692. +# CONFIG_PARPORT is not set
  2693. +
  2694. +#
  2695. +# Memory Technology Devices (MTD)
  2696. +#
  2697. +CONFIG_MTD=y
  2698. +# CONFIG_MTD_DEBUG is not set
  2699. +# CONFIG_MTD_PARTITIONS is not set
  2700. +# CONFIG_MTD_CONCAT is not set
  2701. +# CONFIG_MTD_REDBOOT_PARTS is not set
  2702. +# CONFIG_MTD_CMDLINE_PARTS is not set
  2703. +# CONFIG_MTD_AFS_PARTS is not set
  2704. +CONFIG_MTD_CHAR=y
  2705. +CONFIG_MTD_BLOCK=y
  2706. +# CONFIG_FTL is not set
  2707. +# CONFIG_NFTL is not set
  2708. +
  2709. +#
  2710. +# RAM/ROM/Flash chip drivers
  2711. +#
  2712. +CONFIG_MTD_CFI=y
  2713. +CONFIG_MTD_JEDECPROBE=y
  2714. +CONFIG_MTD_GEN_PROBE=y
  2715. +# CONFIG_MTD_CFI_ADV_OPTIONS is not set
  2716. +CONFIG_MTD_CFI_INTELEXT=y
  2717. +# CONFIG_MTD_CFI_AMDSTD is not set
  2718. +# CONFIG_MTD_CFI_STAA is not set
  2719. +# CONFIG_MTD_RAM is not set
  2720. +CONFIG_MTD_ROM=y
  2721. +# CONFIG_MTD_ABSENT is not set
  2722. +# CONFIG_MTD_OBSOLETE_CHIPS is not set
  2723. +# CONFIG_MTD_AMDSTD is not set
  2724. +# CONFIG_MTD_SHARP is not set
  2725. +# CONFIG_MTD_JEDEC is not set
  2726. +
  2727. +#
  2728. +# Mapping drivers for chip access
  2729. +#
  2730. +CONFIG_MTD_PHYSMAP=y
  2731. +CONFIG_MTD_PHYSMAP_START=10000000
  2732. +CONFIG_MTD_PHYSMAP_LEN=200000
  2733. +CONFIG_MTD_PHYSMAP_BUSWIDTH=2
  2734. +# CONFIG_MTD_NORA is not set
  2735. +# CONFIG_MTD_ARM_INTEGRATOR is not set
  2736. +# CONFIG_MTD_CDB89712 is not set
  2737. +# CONFIG_MTD_SA1100 is not set
  2738. +# CONFIG_MTD_DC21285 is not set
  2739. +# CONFIG_MTD_IQ80310 is not set
  2740. +# CONFIG_MTD_FORTUNET is not set
  2741. +# CONFIG_MTD_EPXA is not set
  2742. +# CONFIG_MTD_AUTCPU12 is not set
  2743. +# CONFIG_MTD_EDB7312 is not set
  2744. +# CONFIG_MTD_IMPA7 is not set
  2745. +# CONFIG_MTD_CEIVA is not set
  2746. +# CONFIG_MTD_PCI is not set
  2747. +# CONFIG_MTD_PCMCIA is not set
  2748. +
  2749. +#
  2750. +# Self-contained MTD device drivers
  2751. +#
  2752. +# CONFIG_MTD_PMC551 is not set
  2753. +# CONFIG_MTD_SLRAM is not set
  2754. +CONFIG_MTD_AT91_DATAFLASH=y
  2755. +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
  2756. +# CONFIG_MTD_MTDRAM is not set
  2757. +# CONFIG_MTD_BLKMTD is not set
  2758. +# CONFIG_MTD_DOC1000 is not set
  2759. +# CONFIG_MTD_DOC2000 is not set
  2760. +# CONFIG_MTD_DOC2001 is not set
  2761. +# CONFIG_MTD_DOCPROBE is not set
  2762. +
  2763. +#
  2764. +# NAND Flash Device Drivers
  2765. +#
  2766. +CONFIG_MTD_NAND=y
  2767. +# CONFIG_MTD_NAND_VERIFY_WRITE is not set
  2768. +CONFIG_MTD_NAND_IDS=y
  2769. +# CONFIG_MTD_AT91_SMARTMEDIA is not set
  2770. +
  2771. +#
  2772. +# Plug and Play configuration
  2773. +#
  2774. +# CONFIG_PNP is not set
  2775. +# CONFIG_ISAPNP is not set
  2776. +
  2777. +#
  2778. +# Block devices
  2779. +#
  2780. +# CONFIG_BLK_DEV_FD is not set
  2781. +# CONFIG_BLK_DEV_XD is not set
  2782. +# CONFIG_PARIDE is not set
  2783. +# CONFIG_BLK_CPQ_DA is not set
  2784. +# CONFIG_BLK_CPQ_CISS_DA is not set
  2785. +# CONFIG_CISS_SCSI_TAPE is not set
  2786. +# CONFIG_CISS_MONITOR_THREAD is not set
  2787. +# CONFIG_BLK_DEV_DAC960 is not set
  2788. +# CONFIG_BLK_DEV_UMEM is not set
  2789. +# CONFIG_BLK_DEV_LOOP is not set
  2790. +# CONFIG_BLK_DEV_NBD is not set
  2791. +CONFIG_BLK_DEV_RAM=y
  2792. +CONFIG_BLK_DEV_RAM_SIZE=8192
  2793. +# CONFIG_BLK_DEV_INITRD is not set
  2794. +# CONFIG_BLK_STATS is not set
  2795. +
  2796. +#
  2797. +# Multi-device support (RAID and LVM)
  2798. +#
  2799. +# CONFIG_MD is not set
  2800. +# CONFIG_BLK_DEV_MD is not set
  2801. +# CONFIG_MD_LINEAR is not set
  2802. +# CONFIG_MD_RAID0 is not set
  2803. +# CONFIG_MD_RAID1 is not set
  2804. +# CONFIG_MD_RAID5 is not set
  2805. +# CONFIG_MD_MULTIPATH is not set
  2806. +# CONFIG_BLK_DEV_LVM is not set
  2807. +
  2808. +#
  2809. +# Networking options
  2810. +#
  2811. +CONFIG_PACKET=y
  2812. +# CONFIG_PACKET_MMAP is not set
  2813. +# CONFIG_NETLINK_DEV is not set
  2814. +# CONFIG_NETFILTER is not set
  2815. +# CONFIG_FILTER is not set
  2816. +CONFIG_UNIX=y
  2817. +CONFIG_INET=y
  2818. +# CONFIG_IP_MULTICAST is not set
  2819. +# CONFIG_IP_ADVANCED_ROUTER is not set
  2820. +CONFIG_IP_PNP=y
  2821. +CONFIG_IP_PNP_DHCP=y
  2822. +CONFIG_IP_PNP_BOOTP=y
  2823. +# CONFIG_IP_PNP_RARP is not set
  2824. +# CONFIG_NET_IPIP is not set
  2825. +# CONFIG_NET_IPGRE is not set
  2826. +# CONFIG_ARPD is not set
  2827. +# CONFIG_INET_ECN is not set
  2828. +# CONFIG_SYN_COOKIES is not set
  2829. +# CONFIG_IPV6 is not set
  2830. +# CONFIG_KHTTPD is not set
  2831. +
  2832. +#
  2833. +# SCTP Configuration (EXPERIMENTAL)
  2834. +#
  2835. +CONFIG_IPV6_SCTP__=y
  2836. +# CONFIG_IP_SCTP is not set
  2837. +# CONFIG_ATM is not set
  2838. +# CONFIG_VLAN_8021Q is not set
  2839. +# CONFIG_IPX is not set
  2840. +# CONFIG_ATALK is not set
  2841. +
  2842. +#
  2843. +# Appletalk devices
  2844. +#
  2845. +# CONFIG_DEV_APPLETALK is not set
  2846. +# CONFIG_DECNET is not set
  2847. +# CONFIG_BRIDGE is not set
  2848. +# CONFIG_X25 is not set
  2849. +# CONFIG_LAPB is not set
  2850. +# CONFIG_LLC is not set
  2851. +# CONFIG_NET_DIVERT is not set
  2852. +# CONFIG_ECONET is not set
  2853. +# CONFIG_WAN_ROUTER is not set
  2854. +# CONFIG_NET_FASTROUTE is not set
  2855. +# CONFIG_NET_HW_FLOWCONTROL is not set
  2856. +
  2857. +#
  2858. +# QoS and/or fair queueing
  2859. +#
  2860. +# CONFIG_NET_SCHED is not set
  2861. +
  2862. +#
  2863. +# Network testing
  2864. +#
  2865. +# CONFIG_NET_PKTGEN is not set
  2866. +
  2867. +#
  2868. +# Network device support
  2869. +#
  2870. +CONFIG_NETDEVICES=y
  2871. +
  2872. +#
  2873. +# ARCnet devices
  2874. +#
  2875. +# CONFIG_ARCNET is not set
  2876. +# CONFIG_DUMMY is not set
  2877. +# CONFIG_BONDING is not set
  2878. +# CONFIG_EQUALIZER is not set
  2879. +# CONFIG_TUN is not set
  2880. +# CONFIG_ETHERTAP is not set
  2881. +
  2882. +#
  2883. +# Ethernet (10 or 100Mbit)
  2884. +#
  2885. +CONFIG_NET_ETHERNET=y
  2886. +# CONFIG_ARM_AM79C961A is not set
  2887. +# CONFIG_ARM_CIRRUS is not set
  2888. +CONFIG_AT91_ETHER=y
  2889. +# CONFIG_AT91_ETHER_RMII is not set
  2890. +# CONFIG_SUNLANCE is not set
  2891. +# CONFIG_SUNBMAC is not set
  2892. +# CONFIG_SUNQE is not set
  2893. +# CONFIG_SUNGEM is not set
  2894. +# CONFIG_NET_VENDOR_3COM is not set
  2895. +# CONFIG_LANCE is not set
  2896. +# CONFIG_NET_VENDOR_SMC is not set
  2897. +# CONFIG_NET_VENDOR_RACAL is not set
  2898. +# CONFIG_NET_ISA is not set
  2899. +# CONFIG_NET_PCI is not set
  2900. +# CONFIG_NET_POCKET is not set
  2901. +
  2902. +#
  2903. +# Ethernet (1000 Mbit)
  2904. +#
  2905. +# CONFIG_ACENIC is not set
  2906. +# CONFIG_DL2K is not set
  2907. +# CONFIG_E1000 is not set
  2908. +# CONFIG_MYRI_SBUS is not set
  2909. +# CONFIG_NS83820 is not set
  2910. +# CONFIG_HAMACHI is not set
  2911. +# CONFIG_YELLOWFIN is not set
  2912. +# CONFIG_R8169 is not set
  2913. +# CONFIG_SK98LIN is not set
  2914. +# CONFIG_TIGON3 is not set
  2915. +# CONFIG_FDDI is not set
  2916. +# CONFIG_HIPPI is not set
  2917. +# CONFIG_PLIP is not set
  2918. +# CONFIG_PPP is not set
  2919. +# CONFIG_SLIP is not set
  2920. +
  2921. +#
  2922. +# Wireless LAN (non-hamradio)
  2923. +#
  2924. +# CONFIG_NET_RADIO is not set
  2925. +
  2926. +#
  2927. +# Token Ring devices
  2928. +#
  2929. +# CONFIG_TR is not set
  2930. +# CONFIG_NET_FC is not set
  2931. +# CONFIG_RCPCI is not set
  2932. +# CONFIG_SHAPER is not set
  2933. +
  2934. +#
  2935. +# Wan interfaces
  2936. +#
  2937. +# CONFIG_WAN is not set
  2938. +
  2939. +#
  2940. +# Amateur Radio support
  2941. +#
  2942. +# CONFIG_HAMRADIO is not set
  2943. +
  2944. +#
  2945. +# IrDA (infrared) support
  2946. +#
  2947. +# CONFIG_IRDA is not set
  2948. +
  2949. +#
  2950. +# ATA/ATAPI/MFM/RLL support
  2951. +#
  2952. +# CONFIG_IDE is not set
  2953. +# CONFIG_BLK_DEV_HD is not set
  2954. +
  2955. +#
  2956. +# SCSI support
  2957. +#
  2958. +# CONFIG_SCSI is not set
  2959. +
  2960. +#
  2961. +# I2O device support
  2962. +#
  2963. +# CONFIG_I2O is not set
  2964. +# CONFIG_I2O_BLOCK is not set
  2965. +# CONFIG_I2O_LAN is not set
  2966. +# CONFIG_I2O_SCSI is not set
  2967. +# CONFIG_I2O_PROC is not set
  2968. +
  2969. +#
  2970. +# ISDN subsystem
  2971. +#
  2972. +# CONFIG_ISDN is not set
  2973. +
  2974. +#
  2975. +# Input core support
  2976. +#
  2977. +# CONFIG_INPUT is not set
  2978. +# CONFIG_INPUT_KEYBDEV is not set
  2979. +# CONFIG_INPUT_MOUSEDEV is not set
  2980. +# CONFIG_INPUT_JOYDEV is not set
  2981. +# CONFIG_INPUT_EVDEV is not set
  2982. +# CONFIG_INPUT_UINPUT is not set
  2983. +# CONFIG_INPUT_MX1TS is not set
  2984. +
  2985. +#
  2986. +# Character devices
  2987. +#
  2988. +# CONFIG_VT is not set
  2989. +# CONFIG_SERIAL is not set
  2990. +# CONFIG_SERIAL_EXTENDED is not set
  2991. +# CONFIG_SERIAL_NONSTANDARD is not set
  2992. +CONFIG_AT91_SPIDEV=y
  2993. +
  2994. +#
  2995. +# Serial drivers
  2996. +#
  2997. +# CONFIG_SERIAL_ANAKIN is not set
  2998. +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
  2999. +# CONFIG_SERIAL_AMBA is not set
  3000. +# CONFIG_SERIAL_AMBA_CONSOLE is not set
  3001. +# CONFIG_SERIAL_CLPS711X is not set
  3002. +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
  3003. +# CONFIG_SERIAL_21285 is not set
  3004. +# CONFIG_SERIAL_21285_OLD is not set
  3005. +# CONFIG_SERIAL_21285_CONSOLE is not set
  3006. +# CONFIG_SERIAL_UART00 is not set
  3007. +# CONFIG_SERIAL_UART00_CONSOLE is not set
  3008. +# CONFIG_SERIAL_SA1100 is not set
  3009. +# CONFIG_SERIAL_SA1100_CONSOLE is not set
  3010. +# CONFIG_SERIAL_OMAHA is not set
  3011. +# CONFIG_SERIAL_OMAHA_CONSOLE is not set
  3012. +CONFIG_SERIAL_AT91=y
  3013. +CONFIG_SERIAL_AT91_CONSOLE=y
  3014. +# CONFIG_SERIAL_8250 is not set
  3015. +# CONFIG_SERIAL_8250_CONSOLE is not set
  3016. +# CONFIG_SERIAL_8250_EXTENDED is not set
  3017. +# CONFIG_SERIAL_8250_MANY_PORTS is not set
  3018. +# CONFIG_SERIAL_8250_SHARE_IRQ is not set
  3019. +# CONFIG_SERIAL_8250_DETECT_IRQ is not set
  3020. +# CONFIG_SERIAL_8250_MULTIPORT is not set
  3021. +# CONFIG_SERIAL_8250_HUB6 is not set
  3022. +CONFIG_SERIAL_CORE=y
  3023. +CONFIG_SERIAL_CORE_CONSOLE=y
  3024. +# CONFIG_UNIX98_PTYS is not set
  3025. +
  3026. +#
  3027. +# I2C support
  3028. +#
  3029. +CONFIG_I2C=y
  3030. +# CONFIG_I2C_ALGOBIT is not set
  3031. +# CONFIG_SCx200_ACB is not set
  3032. +# CONFIG_I2C_ALGOPCF is not set
  3033. +CONFIG_I2C_AT91=y
  3034. +CONFIG_I2C_CHARDEV=y
  3035. +CONFIG_I2C_PROC=y
  3036. +CONFIG_I2C_DS1307=y
  3037. +
  3038. +#
  3039. +# L3 serial bus support
  3040. +#
  3041. +# CONFIG_L3 is not set
  3042. +# CONFIG_L3_ALGOBIT is not set
  3043. +# CONFIG_L3_BIT_SA1100_GPIO is not set
  3044. +# CONFIG_L3_SA1111 is not set
  3045. +# CONFIG_BIT_SA1100_GPIO is not set
  3046. +
  3047. +#
  3048. +# Mice
  3049. +#
  3050. +# CONFIG_BUSMOUSE is not set
  3051. +# CONFIG_MOUSE is not set
  3052. +
  3053. +#
  3054. +# Joysticks
  3055. +#
  3056. +# CONFIG_INPUT_GAMEPORT is not set
  3057. +# CONFIG_QIC02_TAPE is not set
  3058. +# CONFIG_IPMI_HANDLER is not set
  3059. +# CONFIG_IPMI_PANIC_EVENT is not set
  3060. +# CONFIG_IPMI_DEVICE_INTERFACE is not set
  3061. +# CONFIG_IPMI_KCS is not set
  3062. +# CONFIG_IPMI_WATCHDOG is not set
  3063. +
  3064. +#
  3065. +# Watchdog Cards
  3066. +#
  3067. +CONFIG_WATCHDOG=y
  3068. +CONFIG_WATCHDOG_NOWAYOUT=y
  3069. +# CONFIG_ACQUIRE_WDT is not set
  3070. +# CONFIG_ADVANTECH_WDT is not set
  3071. +# CONFIG_ALIM1535_WDT is not set
  3072. +# CONFIG_ALIM7101_WDT is not set
  3073. +# CONFIG_SC520_WDT is not set
  3074. +# CONFIG_PCWATCHDOG is not set
  3075. +# CONFIG_21285_WATCHDOG is not set
  3076. +# CONFIG_977_WATCHDOG is not set
  3077. +# CONFIG_SA1100_WATCHDOG is not set
  3078. +# CONFIG_EPXA_WATCHDOG is not set
  3079. +# CONFIG_OMAHA_WATCHDOG is not set
  3080. +CONFIG_AT91_WATCHDOG=y
  3081. +# CONFIG_EUROTECH_WDT is not set
  3082. +# CONFIG_IB700_WDT is not set
  3083. +# CONFIG_WAFER_WDT is not set
  3084. +# CONFIG_I810_TCO is not set
  3085. +# CONFIG_MIXCOMWD is not set
  3086. +# CONFIG_60XX_WDT is not set
  3087. +# CONFIG_SC1200_WDT is not set
  3088. +# CONFIG_SCx200_WDT is not set
  3089. +# CONFIG_SOFT_WATCHDOG is not set
  3090. +# CONFIG_W83877F_WDT is not set
  3091. +# CONFIG_WDT is not set
  3092. +# CONFIG_WDTPCI is not set
  3093. +# CONFIG_MACHZ_WDT is not set
  3094. +# CONFIG_AMD7XX_TCO is not set
  3095. +# CONFIG_SCx200 is not set
  3096. +# CONFIG_SCx200_GPIO is not set
  3097. +# CONFIG_AMD_PM768 is not set
  3098. +# CONFIG_NVRAM is not set
  3099. +# CONFIG_RTC is not set
  3100. +CONFIG_AT91_RTC=y
  3101. +# CONFIG_DTLK is not set
  3102. +# CONFIG_R3964 is not set
  3103. +# CONFIG_APPLICOM is not set
  3104. +
  3105. +#
  3106. +# Ftape, the floppy tape device driver
  3107. +#
  3108. +# CONFIG_FTAPE is not set
  3109. +# CONFIG_AGP is not set
  3110. +
  3111. +#
  3112. +# Direct Rendering Manager (XFree86 DRI support)
  3113. +#
  3114. +# CONFIG_DRM is not set
  3115. +
  3116. +#
  3117. +# Multimedia devices
  3118. +#
  3119. +# CONFIG_VIDEO_DEV is not set
  3120. +
  3121. +#
  3122. +# File systems
  3123. +#
  3124. +# CONFIG_QUOTA is not set
  3125. +# CONFIG_QFMT_V2 is not set
  3126. +# CONFIG_AUTOFS_FS is not set
  3127. +# CONFIG_AUTOFS4_FS is not set
  3128. +# CONFIG_REISERFS_FS is not set
  3129. +# CONFIG_REISERFS_CHECK is not set
  3130. +# CONFIG_REISERFS_PROC_INFO is not set
  3131. +# CONFIG_ADFS_FS is not set
  3132. +# CONFIG_ADFS_FS_RW is not set
  3133. +# CONFIG_AFFS_FS is not set
  3134. +# CONFIG_HFS_FS is not set
  3135. +# CONFIG_HFSPLUS_FS is not set
  3136. +# CONFIG_BEFS_FS is not set
  3137. +# CONFIG_BEFS_DEBUG is not set
  3138. +# CONFIG_BFS_FS is not set
  3139. +# CONFIG_EXT3_FS is not set
  3140. +# CONFIG_JBD is not set
  3141. +# CONFIG_JBD_DEBUG is not set
  3142. +# CONFIG_FAT_FS is not set
  3143. +# CONFIG_MSDOS_FS is not set
  3144. +# CONFIG_UMSDOS_FS is not set
  3145. +# CONFIG_VFAT_FS is not set
  3146. +# CONFIG_EFS_FS is not set
  3147. +# CONFIG_JFFS_FS is not set
  3148. +# CONFIG_JFFS2_FS is not set
  3149. +# CONFIG_CRAMFS is not set
  3150. +# CONFIG_TMPFS is not set
  3151. +CONFIG_RAMFS=y
  3152. +# CONFIG_ISO9660_FS is not set
  3153. +# CONFIG_JOLIET is not set
  3154. +# CONFIG_ZISOFS is not set
  3155. +# CONFIG_JFS_FS is not set
  3156. +# CONFIG_JFS_DEBUG is not set
  3157. +# CONFIG_JFS_STATISTICS is not set
  3158. +# CONFIG_MINIX_FS is not set
  3159. +# CONFIG_VXFS_FS is not set
  3160. +# CONFIG_NTFS_FS is not set
  3161. +# CONFIG_NTFS_RW is not set
  3162. +# CONFIG_HPFS_FS is not set
  3163. +CONFIG_PROC_FS=y
  3164. +CONFIG_DEVFS_FS=y
  3165. +CONFIG_DEVFS_MOUNT=y
  3166. +# CONFIG_DEVFS_DEBUG is not set
  3167. +# CONFIG_DEVPTS_FS is not set
  3168. +# CONFIG_QNX4FS_FS is not set
  3169. +# CONFIG_QNX4FS_RW is not set
  3170. +# CONFIG_ROMFS_FS is not set
  3171. +CONFIG_EXT2_FS=y
  3172. +# CONFIG_SYSV_FS is not set
  3173. +# CONFIG_UDF_FS is not set
  3174. +# CONFIG_UDF_RW is not set
  3175. +# CONFIG_UFS_FS is not set
  3176. +# CONFIG_UFS_FS_WRITE is not set
  3177. +# CONFIG_XFS_FS is not set
  3178. +# CONFIG_XFS_QUOTA is not set
  3179. +# CONFIG_XFS_RT is not set
  3180. +# CONFIG_XFS_TRACE is not set
  3181. +# CONFIG_XFS_DEBUG is not set
  3182. +
  3183. +#
  3184. +# Network File Systems
  3185. +#
  3186. +# CONFIG_CODA_FS is not set
  3187. +# CONFIG_INTERMEZZO_FS is not set
  3188. +CONFIG_NFS_FS=y
  3189. +CONFIG_NFS_V3=y
  3190. +# CONFIG_NFS_DIRECTIO is not set
  3191. +CONFIG_ROOT_NFS=y
  3192. +# CONFIG_NFSD is not set
  3193. +# CONFIG_NFSD_V3 is not set
  3194. +# CONFIG_NFSD_TCP is not set
  3195. +CONFIG_SUNRPC=y
  3196. +CONFIG_LOCKD=y
  3197. +CONFIG_LOCKD_V4=y
  3198. +# CONFIG_SMB_FS is not set
  3199. +# CONFIG_NCP_FS is not set
  3200. +# CONFIG_NCPFS_PACKET_SIGNING is not set
  3201. +# CONFIG_NCPFS_IOCTL_LOCKING is not set
  3202. +# CONFIG_NCPFS_STRONG is not set
  3203. +# CONFIG_NCPFS_NFS_NS is not set
  3204. +# CONFIG_NCPFS_OS2_NS is not set
  3205. +# CONFIG_NCPFS_SMALLDOS is not set
  3206. +# CONFIG_NCPFS_NLS is not set
  3207. +# CONFIG_NCPFS_EXTRAS is not set
  3208. +# CONFIG_ZISOFS_FS is not set
  3209. +
  3210. +#
  3211. +# Partition Types
  3212. +#
  3213. +# CONFIG_PARTITION_ADVANCED is not set
  3214. +CONFIG_MSDOS_PARTITION=y
  3215. +# CONFIG_SMB_NLS is not set
  3216. +# CONFIG_NLS is not set
  3217. +
  3218. +#
  3219. +# Multimedia Capabilities Port drivers
  3220. +#
  3221. +# CONFIG_MCP is not set
  3222. +# CONFIG_MCP_SA1100 is not set
  3223. +# CONFIG_MCP_UCB1200 is not set
  3224. +# CONFIG_MCP_UCB1200_AUDIO is not set
  3225. +# CONFIG_MCP_UCB1200_TS is not set
  3226. +
  3227. +#
  3228. +# USB support
  3229. +#
  3230. +# CONFIG_USB is not set
  3231. +
  3232. +#
  3233. +# Support for USB gadgets
  3234. +#
  3235. +# CONFIG_USB_GADGET is not set
  3236. +
  3237. +#
  3238. +# Bluetooth support
  3239. +#
  3240. +# CONFIG_BLUEZ is not set
  3241. +
  3242. +#
  3243. +# Kernel hacking
  3244. +#
  3245. +CONFIG_FRAME_POINTER=y
  3246. +CONFIG_DEBUG_USER=y
  3247. +# CONFIG_DEBUG_INFO is not set
  3248. +# CONFIG_NO_PGT_CACHE is not set
  3249. +CONFIG_DEBUG_KERNEL=y
  3250. +# CONFIG_DEBUG_SLAB is not set
  3251. +# CONFIG_MAGIC_SYSRQ is not set
  3252. +# CONFIG_DEBUG_SPINLOCK is not set
  3253. +# CONFIG_DEBUG_WAITQ is not set
  3254. +# CONFIG_DEBUG_BUGVERBOSE is not set
  3255. +# CONFIG_DEBUG_ERRORS is not set
  3256. +CONFIG_DEBUG_LL=y
  3257. +# CONFIG_DEBUG_DC21285_PORT is not set
  3258. +# CONFIG_DEBUG_CLPS711X_UART2 is not set
  3259. +
  3260. +#
  3261. +# Library routines
  3262. +#
  3263. +CONFIG_CRC32=y
  3264. +# CONFIG_ZLIB_INFLATE is not set
  3265. +# CONFIG_ZLIB_DEFLATE is not set
  3266. diff -urN linux-2.4.26/arch/arm/fastfpe/CPDO.S linux-2.4.26-vrs1/arch/arm/fastfpe/CPDO.S
  3267. --- linux-2.4.26/arch/arm/fastfpe/CPDO.S 1970-01-01 01:00:00.000000000 +0100
  3268. +++ linux-2.4.26-vrs1/arch/arm/fastfpe/CPDO.S 2004-01-14 21:32:23.000000000 +0000
  3269. @@ -0,0 +1,682 @@
  3270. +/*
  3271. +The FP structure has 4 words reserved for each register, the first is used just
  3272. +for the sign in bit 31, the second and third are for the mantissa (unsigned
  3273. +integer, high 32 bit first) and the fourth is the exponent (signed integer).
  3274. +The mantissa is always normalized.
  3275. +
  3276. +If the exponent is 0x80000000, that is the most negative value, the number
  3277. +represented is 0 and both mantissa words are also 0.
  3278. +
  3279. +If the exponent is 0x7fffffff, that is the biggest positive value, the number
  3280. +represented is infinity if the high 32 mantissa bit are also 0, otherwise it is
  3281. +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
  3282. +
  3283. +Decimal and packed decimal numbers are not supported yet.
  3284. +
  3285. +The parameters to these functions are r0=destination pointer, r1 and r2
  3286. +source pointers. r4 is the instruction. They may use r0-r8 and r14. They return
  3287. +to fastfpe_next, except CPDO_rnf_core which expects the return address in r14.
  3288. +*/
  3289. +
  3290. +/*---------------------------------------------------------------------------*/
  3291. +
  3292. + .globl CPDO_adf
  3293. +CPDO_adf:
  3294. + ldmia r1,{r1,r3,r5,r7}
  3295. + ldmia r2,{r2,r4,r6,r8}
  3296. +
  3297. + cmp r7,#0x7fffffff
  3298. + cmpne r8,#0x7fffffff
  3299. + beq CPDO_adf_extra
  3300. +
  3301. + cmp r1,r2
  3302. + bne CPDO_suf_s
  3303. +
  3304. +CPDO_adf_s:
  3305. + subs r2,r7,r8
  3306. + bge CPDO_adf_2nd
  3307. +
  3308. + mov r7,r8
  3309. + rsb r2,r2,#0
  3310. + cmp r2,#32
  3311. + ble CPDO_adf_1st2
  3312. +
  3313. + sub r2,r2,#32
  3314. + cmp r2,#32
  3315. + movgt r2,#32
  3316. + mov r5,r3,lsr r2
  3317. + mov r3,#0
  3318. + b CPDO_adf_add
  3319. +
  3320. +CPDO_adf_1st2:
  3321. + rsb r8,r2,#32
  3322. + mov r5,r5,lsr r2
  3323. + orr r5,r5,r3,lsl r8
  3324. + mov r3,r3,lsr r2 @ 1. op normalized
  3325. + b CPDO_adf_add
  3326. +
  3327. +CPDO_adf_2nd:
  3328. + cmp r2,#32
  3329. + ble CPDO_adf_2nd2
  3330. +
  3331. + sub r2,r2,#32
  3332. + cmp r2,#32
  3333. + movgt r2,#32
  3334. + mov r6,r4,lsr r2
  3335. + mov r4,#0
  3336. + b CPDO_adf_add
  3337. +
  3338. +CPDO_adf_2nd2:
  3339. + rsb r8,r2,#32
  3340. + mov r6,r6,lsr r2
  3341. + orr r6,r6,r4,lsl r8
  3342. + mov r4,r4,lsr r2 @ 2. op normalized
  3343. +
  3344. +CPDO_adf_add:
  3345. + adds r5,r5,r6
  3346. + adcs r3,r3,r4 @ do addition
  3347. + bcc CPDO_adf_end
  3348. +
  3349. + add r7,r7,#1
  3350. + movs r3,r3,rrx
  3351. + mov r5,r5,rrx @ correct for overflow
  3352. +
  3353. +CPDO_adf_end:
  3354. + cmp r7,#0x20000000
  3355. + bge CPDO_inf
  3356. +
  3357. + stmia r0,{r1,r3,r5,r7}
  3358. + b fastfpe_next
  3359. +
  3360. +CPDO_adf_extra:
  3361. + cmp r7,#0x7fffffff @ was it the 1st ?
  3362. + bne CPDO_infnan_2 @ no it was the 2nd
  3363. + cmp r8,#0x7fffffff @ if 1st, 2nd too ?
  3364. + bne CPDO_infnan_1 @ no only 1st
  3365. + cmp r3,#0
  3366. + cmpeq r4,#0
  3367. + bne CPDO_nan_12
  3368. + b CPDO_inf
  3369. +
  3370. +/*---------------------------------------------------------------------------*/
  3371. +
  3372. +CPDO_infnan_1:
  3373. + stmia r0,{r1,r3,r5,r7}
  3374. + b fastfpe_next
  3375. +
  3376. +CPDO_infnan_2:
  3377. + stmia r0,{r2,r4,r6,r8}
  3378. + b fastfpe_next
  3379. +
  3380. +CPDO_nan_12:
  3381. + orr r2,r3,r4
  3382. + b CPDO_inf_1
  3383. +
  3384. +CPDO_nan:
  3385. + mov r2,#0x40000000 @ create non signalling NaN
  3386. + b CPDO_inf_1
  3387. +
  3388. +CPDO_inf:
  3389. + mov r2,#0
  3390. +CPDO_inf_1:
  3391. + mov r3,#0
  3392. + mov r4,#0x7fffffff
  3393. +CPDO_store_1234:
  3394. + stmia r0,{r1,r2,r3,r4}
  3395. + b fastfpe_next
  3396. +
  3397. +CPDO_zero:
  3398. + mov r1,#0
  3399. +CPDO_zero_1:
  3400. + mov r2,#0
  3401. + mov r3,#0
  3402. + mov r4,#0x80000000
  3403. + stmia r0,{r1,r2,r3,r4}
  3404. + b fastfpe_next
  3405. +
  3406. +/*---------------------------------------------------------------------------*/
  3407. +
  3408. + .globl CPDO_suf
  3409. +CPDO_suf:
  3410. + ldmia r1,{r1,r3,r5,r7}
  3411. + ldmia r2,{r2,r4,r6,r8}
  3412. +
  3413. +CPDO_suf_l:
  3414. + cmp r7,#0x7fffffff
  3415. + cmpne r8,#0x7fffffff
  3416. + beq CPDO_suf_extra
  3417. +
  3418. + cmp r1,r2
  3419. + bne CPDO_adf_s
  3420. +
  3421. +CPDO_suf_s:
  3422. + subs r2,r7,r8 @ determine greater number
  3423. + bgt CPDO_suf_2nd @ first number is greater
  3424. + blt CPDO_suf_1st @ second number is greater
  3425. + cmp r3,r4 @ also mantissa is important
  3426. + cmpeq r5,r6
  3427. + bhi CPDO_suf_2nd @ first number is greater
  3428. + beq CPDO_zero
  3429. +
  3430. +CPDO_suf_1st:
  3431. + eor r1,r1,#0x80000000 @ second number is greater, invert sign
  3432. + mov r7,r8
  3433. + rsb r2,r2,#0
  3434. + cmp r2,#32
  3435. + ble CPDO_suf_1st2
  3436. +
  3437. + sub r2,r2,#32
  3438. + cmp r2,#32
  3439. + movgt r2,#32
  3440. + mov r5,r3,lsr r2
  3441. + mov r3,#0
  3442. + b CPDO_suf_1st_sub
  3443. +
  3444. +CPDO_suf_1st2:
  3445. + rsb r8,r2,#32
  3446. + mov r5,r5,lsr r2
  3447. + orr r5,r5,r3,lsl r8
  3448. + mov r3,r3,lsr r2 @ 1. op normalized
  3449. +
  3450. +CPDO_suf_1st_sub:
  3451. + subs r5,r6,r5 @ do subtraction
  3452. + sbc r3,r4,r3
  3453. + b CPDO_suf_norm
  3454. +
  3455. +CPDO_suf_2nd:
  3456. + cmp r2,#32
  3457. + ble CPDO_suf_2nd2
  3458. +
  3459. + sub r2,r2,#32
  3460. + cmp r2,#32
  3461. + movgt r2,#32
  3462. + mov r6,r4,lsr r2
  3463. + mov r4,#0
  3464. + b CPDO_suf_2nd_sub
  3465. +
  3466. +CPDO_suf_2nd2:
  3467. + rsb r8,r2,#32
  3468. + mov r6,r6,lsr r2
  3469. + orr r6,r6,r4,lsl r8
  3470. + mov r4,r4,lsr r2 @ 2. op normalized
  3471. +
  3472. +CPDO_suf_2nd_sub:
  3473. + subs r5,r5,r6
  3474. + sbc r3,r3,r4 @ do subtraction
  3475. +
  3476. +CPDO_suf_norm:
  3477. + teq r3,#0 @ normalize 32bit
  3478. + moveq r3,r5
  3479. + moveq r5,#0
  3480. + subeq r7,r7,#32
  3481. +
  3482. + cmp r3,#0x00010000 @ 16bit
  3483. + movcc r3,r3,lsl#16
  3484. + orrcc r3,r3,r5,lsr#16
  3485. + movcc r5,r5,lsl#16
  3486. + subcc r7,r7,#16
  3487. +
  3488. + cmp r3,#0x01000000 @ 8bit
  3489. + movcc r3,r3,lsl#8
  3490. + orrcc r3,r3,r5,lsr#24
  3491. + movcc r5,r5,lsl#8
  3492. + subcc r7,r7,#8
  3493. +
  3494. + cmp r3,#0x10000000 @ 4bit
  3495. + movcc r3,r3,lsl#4
  3496. + orrcc r3,r3,r5,lsr#28
  3497. + movcc r5,r5,lsl#4
  3498. + subcc r7,r7,#4
  3499. +
  3500. + cmp r3,#0x40000000 @ 2bit
  3501. + movcc r3,r3,lsl#2
  3502. + orrcc r3,r3,r5,lsr#30
  3503. + movcc r5,r5,lsl#2
  3504. + subcc r7,r7,#2
  3505. +
  3506. + cmp r3,#0x80000000 @ 1bit
  3507. + movcc r3,r3,lsl#1
  3508. + orrcc r3,r3,r5,lsr#31
  3509. + movcc r5,r5,lsl#1
  3510. + subcc r7,r7,#1
  3511. +
  3512. + cmp r7,#0xe0000000
  3513. + ble CPDO_zero_1
  3514. +
  3515. + stmia r0,{r1,r3,r5,r7}
  3516. + b fastfpe_next
  3517. +
  3518. +CPDO_suf_extra:
  3519. + cmp r7,#0x7fffffff @ was it the 1st ?
  3520. + eorne r2,r2,#0x80000000 @ change sign, might have been INF
  3521. + bne CPDO_infnan_2 @ no it was the 2nd
  3522. + cmp r8,#0x7fffffff @ if 1st, 2nd too ?
  3523. + bne CPDO_infnan_1 @ no only 1st
  3524. + cmp r3,#0
  3525. + cmpeq r4,#0
  3526. + bne CPDO_nan_12
  3527. + b CPDO_nan @ here is difference with adf !
  3528. +
  3529. +/*---------------------------------------------------------------------------*/
  3530. +
  3531. + .globl CPDO_rsf
  3532. +CPDO_rsf:
  3533. + mov r3,r2
  3534. + ldmia r1,{r2,r4,r6,r8}
  3535. + ldmia r3,{r1,r3,r5,r7}
  3536. + b CPDO_suf_l
  3537. +
  3538. +/*---------------------------------------------------------------------------*/
  3539. +
  3540. + .globl CPDO_muf
  3541. +CPDO_muf:
  3542. + ldmia r1,{r1,r3,r5,r7}
  3543. + ldmia r2,{r2,r4,r6,r8}
  3544. +
  3545. + cmp r7,#0x7fffffff
  3546. + cmpne r8,#0x7fffffff
  3547. + beq CPDO_muf_extra
  3548. +
  3549. + eor r1,r1,r2
  3550. + adds r8,r7,r8
  3551. + bvs CPDO_zero_1
  3552. +
  3553. + umull r7,r2,r3,r4
  3554. + umull r14,r3,r6,r3
  3555. + adds r7,r7,r3 @ r2|r7|r14 = r2|r7|#0 + #0|r3|r14
  3556. + adc r2,r2,#0
  3557. + umull r4,r3,r5,r4
  3558. + adds r14,r14,r4 @ r2|r7|r14 += #0|r3|r4
  3559. + adcs r7,r7,r3
  3560. + adc r2,r2,#0
  3561. + umull r4,r3,r5,r6
  3562. + adds r14,r14,r3 @ r2|r7|r14 += #0|#0|r3
  3563. + adcs r7,r7,#0
  3564. + adcs r2,r2,#0
  3565. +
  3566. + bpl CPDO_muf_norm
  3567. +
  3568. + add r8,r8,#1
  3569. + b CPDO_muf_end
  3570. +
  3571. +CPDO_muf_norm:
  3572. + adds r14,r14,r14
  3573. + adcs r7,r7,r7
  3574. + adcs r2,r2,r2
  3575. +
  3576. +CPDO_muf_end:
  3577. + cmp r8,#0x20000000
  3578. + bge CPDO_inf
  3579. + cmp r8,#0xe0000000
  3580. + ble CPDO_zero_1
  3581. + stmia r0,{r1,r2,r7,r8}
  3582. + b fastfpe_next
  3583. +
  3584. +CPDO_muf_extra:
  3585. + cmp r7,#0x7fffffff @ was it the first?
  3586. + bne CPDO_muf_extra_2nd @ no, so it was the second
  3587. + cmp r8,#0x7fffffff @ yes, second too?
  3588. + bne CPDO_muf_extra_1st @ no, only first
  3589. + orr r3,r3,r4 @ if both inf -> inf, otherwise nan
  3590. + eor r1,r1,r2 @ sign for the inf case
  3591. + b CPDO_infnan_1
  3592. +
  3593. +CPDO_muf_extra_1st:
  3594. + cmp r3,#0 @ is it a nan?
  3595. + bne CPDO_infnan_1
  3596. + cmp r8,#0x80000000 @ is the second 0?
  3597. + beq CPDO_nan
  3598. + eor r1,r1,r2 @ correct sign for inf
  3599. + b CPDO_inf
  3600. +
  3601. +CPDO_muf_extra_2nd:
  3602. + cmp r4,#0 @ is it a nan?
  3603. + bne CPDO_infnan_2
  3604. + cmp r7,#0x80000000 @ is the first 0?
  3605. + beq CPDO_nan
  3606. + eor r1,r1,r2 @ correct sign for inf
  3607. + b CPDO_inf
  3608. +
  3609. +/*---------------------------------------------------------------------------*/
  3610. +
  3611. + .globl CPDO_dvf
  3612. +CPDO_dvf:
  3613. + ldmia r1,{r1,r3,r5,r7}
  3614. + ldmia r2,{r2,r4,r6,r8}
  3615. +
  3616. +CPDO_dvf_l:
  3617. + cmp r7,#0x7fffffff
  3618. + cmpne r8,#0x7fffffff
  3619. + beq CPDO_dvf_extra
  3620. + cmp r8,#0x80000000
  3621. + beq CPDO_dvf_by0
  3622. +
  3623. + eor r1,r1,r2
  3624. + cmp r7,#0x80000000
  3625. + beq CPDO_zero_1
  3626. +
  3627. + sub r8,r7,r8
  3628. +
  3629. + mov r2,#0
  3630. + mov r7,#1
  3631. +
  3632. + cmp r3,r4
  3633. + cmpeq r5,r6
  3634. + bcs CPDO_dvf_loop_
  3635. +
  3636. + sub r8,r8,#1
  3637. +
  3638. +CPDO_dvf_loop:
  3639. + adds r5,r5,r5
  3640. + adcs r3,r3,r3
  3641. + bcs CPDO_dvf_anyway
  3642. +CPDO_dvf_loop_:
  3643. + subs r5,r5,r6
  3644. + sbcs r3,r3,r4
  3645. + bcs CPDO_dvf_okay
  3646. +
  3647. + adds r5,r5,r6
  3648. + adc r3,r3,r4
  3649. + adds r7,r7,r7
  3650. + adcs r2,r2,r2
  3651. + bcc CPDO_dvf_loop
  3652. + b CPDO_dvf_end
  3653. +
  3654. +CPDO_dvf_anyway:
  3655. + adcs r7,r7,r7
  3656. + adcs r2,r2,r2
  3657. + bcs CPDO_dvf_end
  3658. + subs r5,r5,r6
  3659. + sbc r3,r3,r4
  3660. + b CPDO_dvf_loop
  3661. +
  3662. +CPDO_dvf_okay:
  3663. + adcs r7,r7,r7
  3664. + adcs r2,r2,r2
  3665. + bcc CPDO_dvf_loop
  3666. +
  3667. +CPDO_dvf_end:
  3668. + b CPDO_muf_end
  3669. +
  3670. +CPDO_dvf_by0:
  3671. + cmp R7,#0x80000000
  3672. + beq CPDO_nan @ first also 0 -> nan
  3673. + eor r1,r1,r2 @ otherwise calculatesign for inf
  3674. + b CPDO_inf
  3675. +
  3676. +CPDO_dvf_extra:
  3677. + cmp r7,#0x7fffffff @ was it the first?
  3678. + bne CPDO_dvf_extra_2nd @ no, so it was the second
  3679. + cmp r8,#0x7fffffff @ yes, second too?
  3680. + bne CPDO_dvf_extra_1st @ no, only first
  3681. + orrs r3,r3,r4
  3682. + beq CPDO_nan @ if both inf -> create nan
  3683. + b CPDO_nan_12 @ otherwise keep nan
  3684. +
  3685. +CPDO_dvf_extra_1st:
  3686. + eor r1,r1,r2 @ correct sign for inf
  3687. + b CPDO_infnan_1
  3688. +
  3689. +CPDO_dvf_extra_2nd:
  3690. + cmp r4,#0 @ is it a nan?
  3691. + bne CPDO_infnan_2
  3692. + eor r1,r1,r2 @ correct sign for zero
  3693. + b CPDO_zero_1
  3694. +
  3695. +/*---------------------------------------------------------------------------*/
  3696. +
  3697. + .globl CPDO_rdf
  3698. +CPDO_rdf:
  3699. + mov r3,r2
  3700. + ldmia r1,{r2,r4,r6,r8}
  3701. + ldmia r3,{r1,r3,r5,r7}
  3702. + b CPDO_dvf_l
  3703. +
  3704. +/*---------------------------------------------------------------------------*/
  3705. +
  3706. + .globl CPDO_rmf
  3707. +CPDO_rmf:
  3708. + b fastfpe_next
  3709. +
  3710. +/*---------------------------------------------------------------------------*/
  3711. +
  3712. +
  3713. +
  3714. +/*---------------------------------------------------------------------------*/
  3715. +
  3716. + .globl CPDO_mvf
  3717. +CPDO_mvf:
  3718. + ldmia r2,{r1,r2,r3,r4}
  3719. + stmia r0,{r1,r2,r3,r4}
  3720. + b fastfpe_next
  3721. +
  3722. +/*---------------------------------------------------------------------------*/
  3723. +
  3724. + .globl CPDO_mnf
  3725. +CPDO_mnf:
  3726. + ldmia r2,{r1,r2,r3,r4}
  3727. + eor r1,r1,#0x80000000
  3728. + stmia r0,{r1,r2,r3,r4}
  3729. + b fastfpe_next
  3730. +
  3731. +/*---------------------------------------------------------------------------*/
  3732. +
  3733. + .globl CPDO_abs
  3734. +CPDO_abs:
  3735. + ldmia r2,{r1,r2,r3,r4}
  3736. + bic r1,r1,#0x80000000
  3737. + stmia r0,{r1,r2,r3,r4}
  3738. + b fastfpe_next
  3739. +
  3740. +/*---------------------------------------------------------------------------*/
  3741. +
  3742. + .globl CPDO_sqt
  3743. +CPDO_sqt:
  3744. + ldmia r2,{r1,r2,r3,r4}
  3745. + cmp r1,#0
  3746. + bne CPDO_nan
  3747. + cmp r4,#0x7fffffff
  3748. + beq CPDO_store_1234
  3749. +
  3750. + tst r4,r4,lsr#1 @carry=exponent bit 0
  3751. + bcc CPDO_sqt_exponenteven
  3752. + adds r3,r3,r3
  3753. + adcs r2,r2,r2 @carry is needed in loop!
  3754. +CPDO_sqt_exponenteven:
  3755. + mov r4,r4,asr #1
  3756. + str r4,[r0,#12]
  3757. +
  3758. + mov r4,#0x80000000
  3759. + mov r5,#0
  3760. + sub r2,r2,#0x80000000
  3761. +
  3762. + mov r8,#0x40000000
  3763. + mov r14,#0x80000000
  3764. +
  3765. + mov r1,#1
  3766. + b CPDO_sqt_loop1_first
  3767. +CPDO_sqt_loop1:
  3768. + adds r3,r3,r3
  3769. + adcs r2,r2,r2
  3770. +CPDO_sqt_loop1_first:
  3771. + add r6,r4,r8,lsr r1 @r7 const = r5
  3772. + bcs CPDO_sqt_loop1_1
  3773. + cmp r2,r6
  3774. + cmpeq r3,r5 @r5 for r7
  3775. + bcc CPDO_sqt_loop1_0
  3776. +CPDO_sqt_loop1_1:
  3777. + orr r4,r4,r14,lsr r1
  3778. + subs r3,r3,r5 @r5 for r7
  3779. + sbc r2,r2,r6
  3780. +CPDO_sqt_loop1_0:
  3781. + add r1,r1,#1
  3782. + cmp r1,#30
  3783. + ble CPDO_sqt_loop1
  3784. +
  3785. + adds r3,r3,r3
  3786. + adcs r2,r2,r2
  3787. + bcs CPDO_sqt_between_1
  3788. + adds r7,r5,#0x80000000
  3789. + adc r6,r4,#0
  3790. + cmp r2,r6
  3791. + cmpeq r3,r7
  3792. + bcc CPDO_sqt_between_0
  3793. +CPDO_sqt_between_1:
  3794. + orr r4,r4,#0x00000001
  3795. + subs r3,r3,r5
  3796. + sbc r2,r2,r4
  3797. + subs r3,r3,#0x80000000
  3798. + sbc r2,r2,#0
  3799. +CPDO_sqt_between_0:
  3800. + mov r1,#0
  3801. +
  3802. +CPDO_sqt_loop2:
  3803. + adds r3,r3,r3
  3804. + adcs r2,r2,r2
  3805. + bcs CPDO_sqt_loop2_1
  3806. + adds r7,r5,r8,lsr r1
  3807. + adc r6,r4,#0
  3808. + cmp r2,r6
  3809. + cmpeq r3,r7
  3810. + bcc CPDO_sqt_loop2_0
  3811. +CPDO_sqt_loop2_1:
  3812. + orr r5,r5,r14,lsr r1
  3813. + subs r3,r3,r5
  3814. + sbc r2,r2,r4
  3815. + subs r3,r3,r8,lsr r1
  3816. + sbc r2,r2,#0
  3817. +CPDO_sqt_loop2_0:
  3818. + add r1,r1,#1
  3819. + cmp r1,#30
  3820. + ble CPDO_sqt_loop2
  3821. +
  3822. + adds r3,r3,r3
  3823. + adcs r2,r2,r2
  3824. + bcs CPDO_sqt_after_1
  3825. + cmp r2,r6
  3826. + cmpeq r3,r7
  3827. + bcc CPDO_sqt_after_0
  3828. +CPDO_sqt_after_1:
  3829. + orr r5,r5,#0x00000001
  3830. +CPDO_sqt_after_0:
  3831. +
  3832. + mov r1,#0
  3833. + stmia r0,{r1,r4,r5}
  3834. + b fastfpe_next
  3835. +
  3836. +/*---------------------------------------------------------------------------*/
  3837. +
  3838. + .globl CPDO_rnd
  3839. +CPDO_rnd:
  3840. + ldmia r2,{r1,r2,r3,r5}
  3841. + bl CPDO_rnd_core
  3842. +
  3843. +CPDO_rnd_store:
  3844. + stmia r0,{r1,r2,r3,r5}
  3845. + b fastfpe_next
  3846. +
  3847. +/*---------------------------------------------------------------------------*/
  3848. +
  3849. + .globl CPDO_rnd_core
  3850. +CPDO_rnd_core:
  3851. + and r4,r4,#0x00000060
  3852. + add pc,pc,r4,lsr#3
  3853. + mov r0,r0
  3854. + b CPDO_rnd_N
  3855. + b CPDO_rnd_P
  3856. + b CPDO_rnd_M
  3857. + b CPDO_rnd_Z
  3858. +
  3859. +CPDO_rnd_N:
  3860. + cmp r5,#-1
  3861. + blt CPDO_rnd_zero
  3862. + cmp r5,#63
  3863. + movge pc,r14
  3864. + mov r4,#0x40000000
  3865. + cmp r5,#31
  3866. + bge CPDO_rnd_N_2
  3867. +
  3868. + adds r2,r2,r4,lsr r5
  3869. + bcc CPDO_rnd_end
  3870. + b CPDO_rnd_end_norm
  3871. +
  3872. +CPDO_rnd_N_2:
  3873. +CPDO_rnd_P_2:
  3874. + sub r6,r5,#32
  3875. + adds r3,r3,r4,ror r6 @ror ist needed to handle a -1 correctly
  3876. + adcs r2,r2,#0
  3877. + bcc CPDO_rnd_end
  3878. + b CPDO_rnd_end_norm
  3879. +
  3880. +CPDO_rnd_P:
  3881. + tst r1,#0x80000000
  3882. + bne CPDO_rnd_M_entry
  3883. +CPDO_rnd_P_entry:
  3884. + cmp r5,#0
  3885. + blt CPDO_rnd_P_small
  3886. + cmp r5,#63
  3887. + movge pc,r14
  3888. + mov r4,#0x7fffffff
  3889. + cmp r5,#32
  3890. + bge CPDO_rnd_P_2
  3891. +
  3892. + adds r3,r3,#0xffffffff
  3893. + adcs r2,r2,r4,lsr r5
  3894. + bcc CPDO_rnd_end
  3895. + b CPDO_rnd_end_norm
  3896. +
  3897. +CPDO_rnd_P_small:
  3898. + cmp r5,#0x80000000
  3899. + moveq pc,r14
  3900. + b CPDO_rnd_one
  3901. +
  3902. +CPDO_rnd_M:
  3903. + tst r1,#0x80000000
  3904. + bne CPDO_rnd_P_entry
  3905. +CPDO_rnd_M_entry:
  3906. + cmp r5,#0
  3907. + blt CPDO_rnd_zero
  3908. + cmp r5,#63
  3909. + movge pc,r14
  3910. +
  3911. + b CPDO_rnd_end
  3912. +
  3913. +CPDO_rnd_Z:
  3914. + cmp r5,#0
  3915. + blt CPDO_rnd_zero
  3916. + cmp r5,#63
  3917. + movge pc,r14
  3918. + b CPDO_rnd_end
  3919. +
  3920. +CPDO_rnd_end_norm:
  3921. + add r5,r5,#1
  3922. + movs r2,r2,rrx
  3923. + mov r3,r3,rrx
  3924. +CPDO_rnd_end:
  3925. + rsbs r4,r5,#31
  3926. + bmi CPDO_rnd_end_2
  3927. + mov r3,#0
  3928. + mov r2,r2,lsr r4
  3929. + mov r2,r2,lsl r4
  3930. + mov pc,r14
  3931. +
  3932. +CPDO_rnd_end_2:
  3933. + rsb r4,r5,#63
  3934. + mov r3,r3,lsr r4
  3935. + mov r3,r3,lsl r4
  3936. + mov pc,r14
  3937. +
  3938. +CPDO_rnd_one:
  3939. + mov r2,#0x80000000
  3940. + mov r3,#0
  3941. + mov r5,#0
  3942. + mov pc,r14
  3943. +
  3944. +CPDO_rnd_zero:
  3945. + mov r1,#0
  3946. + mov r2,#0
  3947. + mov r3,#0
  3948. + mov r5,#0x80000000
  3949. + mov pc,r14
  3950. +
  3951. +/*---------------------------------------------------------------------------*/
  3952. diff -urN linux-2.4.26/arch/arm/fastfpe/CPDT.S linux-2.4.26-vrs1/arch/arm/fastfpe/CPDT.S
  3953. --- linux-2.4.26/arch/arm/fastfpe/CPDT.S 1970-01-01 01:00:00.000000000 +0100
  3954. +++ linux-2.4.26-vrs1/arch/arm/fastfpe/CPDT.S 2004-01-14 21:32:23.000000000 +0000
  3955. @@ -0,0 +1,430 @@
  3956. +/*
  3957. +The FP structure has 4 words reserved for each register, the first is used just
  3958. +for the sign in bit 31, the second and third are for the mantissa (unsigned
  3959. +integer, high 32 bit first) and the fourth is the exponent (signed integer).
  3960. +The mantissa is always normalized.
  3961. +
  3962. +If the exponent is 0x80000000, that is the most negative value, the number
  3963. +represented is 0 and both mantissa words are also 0.
  3964. +
  3965. +If the exponent is 0x7fffffff, that is the biggest positive value, the number
  3966. +represented is infinity if the high 32 mantissa bit are also 0, otherwise it is
  3967. +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
  3968. +
  3969. +Decimal and packed decimal numbers are not supported yet.
  3970. +*/
  3971. +
  3972. +/*---------------------------------------------------------------------------*/
  3973. +
  3974. + .globl CPDT_load_single
  3975. +CPDT_load_single:
  3976. + ldr r1,[r6]
  3977. +
  3978. + and r2,r1,#0x80000000 @ r2 = sign
  3979. +
  3980. + mov r5,r1,lsr#23
  3981. + bics r5,r5,#0x100
  3982. + beq CPDT_ls_e0 @ exponent = 0; zero/denormalized
  3983. + teq r5,#255
  3984. + beq CPDT_ls_e255 @ exponent = 255; infinity/NaN
  3985. +
  3986. + sub r5,r5,#127 @ r5 = exponent, remove normalized bias
  3987. +
  3988. + mov r3,r1,lsl#8
  3989. + orr r3,r3,#0x80000000
  3990. + mov r4,#0 @ r3,r4 = mantissa
  3991. +
  3992. + stmia r0,{r2-r5}
  3993. + b fastfpe_next
  3994. +
  3995. +CPDT_ls_e0:
  3996. + movs r3,r1,lsl#9
  3997. + beq CPDT_load_zero
  3998. +
  3999. + mov r5,#-127
  4000. +
  4001. +CPDT_ls_e0_norm:
  4002. + tst r3,#0x80000000
  4003. + subeq r5,r5,#1
  4004. + moveq r3,r3,lsl#1
  4005. + beq CPDT_ls_e0_norm
  4006. +
  4007. + mov r4,#0
  4008. + stmia r0,{r2-r5}
  4009. + b fastfpe_next
  4010. +
  4011. +CPDT_ls_e255:
  4012. + mov r3,r1,lsl#9
  4013. + mov r4,#0
  4014. + mov r5,#0x7fffffff
  4015. + stmia r0,{r2-r5}
  4016. + b fastfpe_next
  4017. +
  4018. +CPDT_load_zero:
  4019. + mov r3,#0
  4020. + mov r4,#0
  4021. + mov r5,#0x80000000
  4022. + stmia r0,{r2-r5}
  4023. + b fastfpe_next
  4024. +
  4025. +/*---------------------------------------------------------------------------*/
  4026. +
  4027. + .globl CPDT_load_double
  4028. +CPDT_load_double:
  4029. + ldr r1,[r6]
  4030. + ldr r6,[r6,#4]
  4031. +
  4032. + and r2,r1,#0x80000000 @ r2 = sign
  4033. +
  4034. + mov r5,r1,lsr#20
  4035. + bics r5,r5,#0x800
  4036. + beq CPDT_ld_e0 @ exponent = 0; zero/denormalized
  4037. + add r4,r5,#1
  4038. + teq r4,#2048
  4039. + beq CPDT_ld_e2047 @ exponent = 2047; infinity/NaN
  4040. +
  4041. + add r5,r5,#1
  4042. + sub r5,r5,#1024 @ r5 = exponent, remove normalized bias
  4043. +
  4044. + mov r3,r1,lsl#11
  4045. + orr r3,r3,#0x80000000
  4046. + orr r3,r3,r6,lsr #21
  4047. + mov r4,r6,lsl#11 @ r3,r4 = mantissa
  4048. +
  4049. + stmia r0,{r2-r5}
  4050. + b fastfpe_next
  4051. +
  4052. +CPDT_ld_e0:
  4053. + mov r3,r1,lsl#12
  4054. + orr r3,r3,r6,lsr#20
  4055. + movs r4,r6,lsl#12
  4056. + teqeq r3,#0
  4057. + beq CPDT_load_zero
  4058. +
  4059. + mov r5,#1
  4060. + sub r5,r5,#1024
  4061. +
  4062. +CPDT_ld_e0_norm:
  4063. + tst r3,#0x80000000
  4064. + subeq r5,r5,#1
  4065. + moveqs r4,r4,lsl#1
  4066. + adceq r3,r3,r3
  4067. + beq CPDT_ld_e0_norm
  4068. +
  4069. + stmia r0,{r2-r5}
  4070. + b fastfpe_next
  4071. +
  4072. +CPDT_ld_e2047:
  4073. + mov r3,r1,lsl#12
  4074. + orr r3,r3,r6,lsr#1
  4075. + bic r6,r6,#0x80000000
  4076. + orr r3,r3,r6 @ to get all fraction bits !
  4077. + mov r4,#0
  4078. + mov r5,#0x7fffffff
  4079. + stmia r0,{r2-r5}
  4080. + b fastfpe_next
  4081. +
  4082. +/*---------------------------------------------------------------------------*/
  4083. +
  4084. + .globl CPDT_load_extended
  4085. +CPDT_load_extended:
  4086. + ldr r1,[r6]
  4087. + ldr r3,[r6,#4]
  4088. + ldr r4,[r6,#8]
  4089. +
  4090. + and r2,r1,#0x80000000
  4091. + bics r5,r1,#0x80000000
  4092. + beq CPDT_le_e0
  4093. + add r1,r5,#1
  4094. + teq r4,#32768
  4095. + beq CPDT_le_e32767
  4096. +
  4097. + add r5,r5,#1
  4098. + sub r5,r5,#16384
  4099. +
  4100. + stmia r0,{r2-r5}
  4101. + b fastfpe_next
  4102. +
  4103. +CPDT_le_e0:
  4104. + teq r3,#0
  4105. + teqeq r4,#0
  4106. + beq CPDT_load_zero
  4107. +
  4108. + mov r5,#2
  4109. + sub r5,r5,#16384
  4110. + b CPDT_ld_e0_norm
  4111. +
  4112. +CPDT_le_e32767:
  4113. + mov r3,r3,lsl#1
  4114. + orr r3,r3,r4,lsr#1
  4115. + bic r4,r4,#0x80000000
  4116. + orr r3,r3,r4
  4117. + mov r5,#0x7fffffff
  4118. + stmia r0,{r2-r5}
  4119. + b fastfpe_next
  4120. +
  4121. +/*---------------------------------------------------------------------------*/
  4122. +
  4123. + .globl CPDT_load_decimal
  4124. +CPDT_load_decimal:
  4125. +
  4126. + b fastfpe_next
  4127. +
  4128. +/*---------------------------------------------------------------------------*/
  4129. +
  4130. + .globl CPDT_store_single
  4131. +CPDT_store_single:
  4132. + ldmia r0,{r1-r4}
  4133. +
  4134. + cmp r4,#-127
  4135. + ble CPDT_ss_e0
  4136. + cmp r4,#128
  4137. + bge CPDT_ss_e255
  4138. +
  4139. + adds r2,r2,#1<<7 @ round to nearest
  4140. + bcs CPDT_ss_rnd_ovfl @ very very seldom taken
  4141. +
  4142. +CPDT_ss_store:
  4143. + add r4,r4,#127
  4144. + orr r1,r1,r4,lsl#23
  4145. +
  4146. + bic r2,r2,#0x80000000
  4147. + orr r1,r1,r2,lsr#8
  4148. +
  4149. + str r1,[r6]
  4150. + b fastfpe_next
  4151. +
  4152. +CPDT_ss_rnd_ovfl:
  4153. + add r4,r4,#1
  4154. + cmp r4,#128
  4155. + bge CPDT_ss_e255
  4156. +
  4157. + mov r2,#0x80000000
  4158. + mov r3,#0
  4159. + b CPDT_ss_store
  4160. +
  4161. +CPDT_ss_e0:
  4162. + cmp r4,#-150
  4163. + ble CPDT_ss_zero
  4164. +
  4165. + add r4,r4,#126
  4166. +CPDT_ss_unnormalize:
  4167. + mov r2,r2,lsr#1
  4168. + adds r4,r4,#1
  4169. + bne CPDT_ss_unnormalize
  4170. +
  4171. + orr r1,r1,r2,lsr#8
  4172. +
  4173. +CPDT_ss_zero:
  4174. + str r1,[r6]
  4175. + b fastfpe_next
  4176. +
  4177. +CPDT_ss_e255:
  4178. + cmp r4,#0x7fffffff
  4179. + bne CPDT_ss_inf
  4180. + cmp r2,#0
  4181. + beq CPDT_ss_inf
  4182. +
  4183. + orr r1,r1,#0x00200000 @ for safety so that it is not INF
  4184. + orr r1,r1,r2,lsr#9 @ get highest bit of mantissa
  4185. +
  4186. +CPDT_ss_inf:
  4187. + orr r1,r1,#0x7f000000
  4188. + orr r1,r1,#0x00800000
  4189. + str r1,[r6]
  4190. + b fastfpe_next
  4191. +
  4192. +/*---------------------------------------------------------------------------*/
  4193. +
  4194. + .globl CPDT_store_double
  4195. +CPDT_store_double:
  4196. + ldmia r0,{r1-r4}
  4197. +
  4198. + cmp r4,#1024 @ this check has to be first, or
  4199. + bge CPDT_sd_e2047 @ overflow can occur on second !
  4200. + add r0,r4,#3
  4201. + cmp r0,#-1023+3 @ cmp with -1023
  4202. + ble CPDT_sd_e0
  4203. +
  4204. + adds r3,r3,#1<<10 @ round to nearest
  4205. + adcs r2,r2,#0
  4206. + bcs CPDT_sd_rnd_ovfl @ very very seldom taken
  4207. +
  4208. +CPDT_sd_store:
  4209. + sub r4,r4,#1
  4210. + add r4,r4,#1024
  4211. + orr r1,r1,r4,lsl#20
  4212. +
  4213. + bic r2,r2,#0x80000000
  4214. + orr r1,r1,r2,lsr#11
  4215. +
  4216. + mov r2,r2,lsl#21
  4217. + orr r2,r2,r3,lsr#11
  4218. +
  4219. + stmia r6,{r1,r2}
  4220. + b fastfpe_next
  4221. +
  4222. +CPDT_sd_rnd_ovfl:
  4223. + add r4,r4,#1
  4224. + cmp r4,#1024
  4225. + bge CPDT_sd_e2047
  4226. +
  4227. + mov r2,#0x80000000
  4228. + mov r3,#0
  4229. + b CPDT_sd_store
  4230. +
  4231. +CPDT_sd_e0:
  4232. + add r0,r4,#1075-1024
  4233. + cmp r0,#-1024
  4234. + ble CPDT_sd_zero
  4235. +
  4236. + add r4,r4,#1024
  4237. + sub r4,r4,#2
  4238. +CPDT_sd_unnormalize:
  4239. + movs r2,r2,lsr#1
  4240. + mov r3,r3,rrx
  4241. + adds r4,r4,#1
  4242. + bne CPDT_sd_unnormalize
  4243. +
  4244. + orr r1,r1,r2,lsr#11
  4245. + mov r2,r2,lsl#21
  4246. + orr r2,r2,r3,lsr#11
  4247. +
  4248. + stmia r6,{r1,r2}
  4249. + b fastfpe_next
  4250. +
  4251. +CPDT_sd_zero:
  4252. + mov r2,#0
  4253. + stmia r6,{r1,r2}
  4254. + b fastfpe_next
  4255. +
  4256. +CPDT_sd_e2047:
  4257. + cmp r4,#0x7fffffff
  4258. + bne CPDT_sd_inf
  4259. + cmp r2,#0
  4260. + beq CPDT_sd_inf
  4261. +
  4262. + orr r1,r1,#0x00040000 @ for safety so that it is not INF
  4263. + orr r1,r1,r2,lsr#12 @ get highest bit of mantissa
  4264. +
  4265. +CPDT_sd_inf:
  4266. + orr r1,r1,#0x7f000000
  4267. + orr r1,r1,#0x00f00000
  4268. + stmia r6,{r1,r2}
  4269. + b fastfpe_next
  4270. +
  4271. +/*---------------------------------------------------------------------------*/
  4272. +
  4273. + .globl CPDT_store_extended
  4274. +CPDT_store_extended:
  4275. + ldmia r0,{r1-r4}
  4276. +
  4277. + cmp r4,#16384 @ this check has to be first, or
  4278. + bge CPDT_se_e32767 @ overflow can occur with second !
  4279. + add r0,r4,#63
  4280. + cmp r0,#-16383+63
  4281. + ble CPDT_se_e0
  4282. +
  4283. + sub r4,r4,#1
  4284. + add r4,r4,#16384
  4285. + orr r1,r1,r4
  4286. +
  4287. + stmia r6,{r1-r3}
  4288. + b fastfpe_next
  4289. +
  4290. +CPDT_se_e0:
  4291. + add r0,r4,#16446-16384
  4292. + cmp r0,#-16384
  4293. + ble CPDT_se_zero
  4294. +
  4295. + add r4,r4,#16384
  4296. + sub r4,r4,#2
  4297. +CPDT_se_unnormalize:
  4298. + movs r2,r2,lsr#1
  4299. + mov r3,r3,rrx
  4300. + adds r4,r4,#1
  4301. + bne CPDT_se_unnormalize
  4302. +
  4303. + stmia r6,{r1-r3}
  4304. + b fastfpe_next
  4305. +
  4306. +CPDT_se_zero:
  4307. + mov r2,#0
  4308. + mov r3,#0
  4309. + stmia r6,{r1-r3}
  4310. + b fastfpe_next
  4311. +
  4312. +CPDT_se_e32767:
  4313. + cmp r4,#0x7fffffff
  4314. + bne CPDT_se_inf
  4315. + cmp r2,#0
  4316. + beq CPDT_se_inf
  4317. +
  4318. + mov r2,r2,lsl#1
  4319. + orr r2,r2,#0x20000000
  4320. +
  4321. +CPDT_se_inf:
  4322. + orr r1,r1,#0x00007f00
  4323. + orr r1,r1,#0x000000ff
  4324. + stmia r6,{r1-r3}
  4325. + b fastfpe_next
  4326. +
  4327. +/*---------------------------------------------------------------------------*/
  4328. +
  4329. + .globl CPDT_store_decimal
  4330. +CPDT_store_decimal:
  4331. +
  4332. + b fastfpe_next
  4333. +
  4334. +/*---------------------------------------------------------------------------*/
  4335. +
  4336. + .globl CPDT_sfm
  4337. +CPDT_sfm:
  4338. + add r2,r10,r0,lsr#8
  4339. + ldr r4,[r2,#0]
  4340. + ldr r3,[r2,#4]
  4341. + bic r3,r3,#0x80000000
  4342. + orr r3,r3,r4
  4343. + str r3,[r6],#4
  4344. + ldr r3,[r2,#8]
  4345. + str r3,[r6],#4
  4346. + ldr r3,[r2,#12]
  4347. + str r3,[r6],#4
  4348. +
  4349. + add r0,r0,#1<<12
  4350. + and r0,r0,#7<<12
  4351. + subs r1,r1,#1
  4352. + bne CPDT_sfm
  4353. + b fastfpe_next
  4354. +
  4355. +/*---------------------------------------------------------------------------*/
  4356. +
  4357. + .globl CPDT_lfm
  4358. +CPDT_lfm:
  4359. + add r2,r10,r0,lsr#8
  4360. + ldr r4,[r6],#4
  4361. + and r3,r4,#0x80000000
  4362. + str r3,[r2,#0]
  4363. + ldr r3,[r6],#4
  4364. + str r3,[r2,#8]
  4365. + ldr r3,[r6],#4
  4366. + str r3,[r2,#12]
  4367. +
  4368. + cmp r3,#0x80000000 @ does the exp indicate zero?
  4369. + biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized'
  4370. + beq CPDT_lfm_storer4
  4371. + cmp r3,#0x7fffffff @ does the exp indicate inf or NaN?
  4372. + biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized'
  4373. + beq CPDT_lfm_storer4
  4374. + orrne r4,r4,#0x80000000 @ otherwise, set normalized bit
  4375. +
  4376. +CPDT_lfm_storer4:
  4377. + str r4,[r2,#4]
  4378. +
  4379. + add r0,r0,#1<<12
  4380. + and r0,r0,#7<<12
  4381. + subs r1,r1,#1
  4382. + bne CPDT_lfm
  4383. + b fastfpe_next
  4384. +
  4385. +/*---------------------------------------------------------------------------*/
  4386. diff -urN linux-2.4.26/arch/arm/fastfpe/CPRT.S linux-2.4.26-vrs1/arch/arm/fastfpe/CPRT.S
  4387. --- linux-2.4.26/arch/arm/fastfpe/CPRT.S 1970-01-01 01:00:00.000000000 +0100
  4388. +++ linux-2.4.26-vrs1/arch/arm/fastfpe/CPRT.S 2004-01-14 21:32:23.000000000 +0000
  4389. @@ -0,0 +1,185 @@
  4390. +/*
  4391. +The FP structure has 4 words reserved for each register, the first is used
  4392. +just
  4393. +for the sign in bit 31, the second and third are for the mantissa (unsigned
  4394. +integer, high 32 bit first) and the fourth is the exponent (signed integer).
  4395. +The mantissa is always normalized.
  4396. +
  4397. +If the exponent is 0x80000000, that is the most negative value, the number
  4398. +represented is 0 and both mantissa words are also 0.
  4399. +
  4400. +If the exponent is 0x7fffffff, that is the biggest positive value, the
  4401. +number
  4402. +represented is infinity if the high 32 mantissa bit are also 0, otherwise it
  4403. +is
  4404. +a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
  4405. +
  4406. +Decimal and packed decimal numbers are not supported yet.
  4407. +*/
  4408. +
  4409. +/*---------------------------------------------------------------------------*/
  4410. +
  4411. + .text
  4412. + .globl CPRT_flt
  4413. +CPRT_flt:
  4414. + add r0,r13,r0,lsr#10
  4415. + ldr r2,[r0]
  4416. + mov r3,#0
  4417. + cmp r2,#0
  4418. + beq CPRT_flt_zero
  4419. +
  4420. + ands r0,r2,#0x80000000
  4421. + rsbne r2,r2,#0
  4422. + mov r4,#31
  4423. +
  4424. + cmp r2,#0x00010000
  4425. + movcc r2,r2,lsl#16
  4426. + subcc r4,r4,#16
  4427. +
  4428. + cmp r2,#0x01000000
  4429. + movcc r2,r2,lsl#8
  4430. + subcc r4,r4,#8
  4431. +
  4432. + cmp r2,#0x10000000
  4433. + movcc r2,r2,lsl#4
  4434. + subcc r4,r4,#4
  4435. +
  4436. + cmp r2,#0x40000000
  4437. + movcc r2,r2,lsl#2
  4438. + subcc r4,r4,#2
  4439. +
  4440. + cmp r2,#0x80000000
  4441. + movcc r2,r2,lsl#1
  4442. + subcc r4,r4,#1
  4443. +
  4444. + stmia r1,{r0,r2,r3,r4}
  4445. + b fastfpe_next
  4446. +
  4447. +CPRT_flt_zero:
  4448. + mov r0,#0
  4449. + mov r4,#0x80000000
  4450. + stmia r1,{r0,r2,r3,r4}
  4451. + b fastfpe_next
  4452. +
  4453. +/*---------------------------------------------------------------------------*/
  4454. +
  4455. + .globl CPRT_fix
  4456. +CPRT_fix:
  4457. + ldmia r2,{r1,r2,r3,r5}
  4458. + bl CPDO_rnd_core
  4459. +
  4460. +CPRT_back:
  4461. + add r0,r13,r0,lsr#10
  4462. + cmp r5,#0
  4463. + blt CPRT_int_zero
  4464. + cmp r5,#30
  4465. + bgt CPRT_overflow
  4466. +
  4467. + rsb r5,r5,#31
  4468. + mov r2,r2,lsr r5
  4469. + tst r1,#0x80000000
  4470. + rsbne r2,r2,#0
  4471. +
  4472. + str r2,[r0]
  4473. + b fastfpe_next
  4474. +
  4475. +CPRT_int_zero:
  4476. + mov r2,#0
  4477. + str r2,[r0]
  4478. + b fastfpe_next
  4479. +
  4480. +CPRT_overflow:
  4481. + mov r2,#0x80000000
  4482. + tst r1,#0x80000000
  4483. + subeq r2,r2,#1
  4484. + str r2,[r0]
  4485. + b fastfpe_next
  4486. +
  4487. +/*---------------------------------------------------------------------------*/
  4488. +
  4489. + .globl CPRT_wfs
  4490. +CPRT_wfs:
  4491. + b fastfpe_next
  4492. +
  4493. +/*---------------------------------------------------------------------------*/
  4494. +
  4495. + .globl CPRT_rfs
  4496. +CPRT_rfs:
  4497. + add r0,r13,r0,lsr#10
  4498. + mov r1,#0x02000000 @ Software Emulation, not Acorn FPE
  4499. + str r1,[r0]
  4500. + b fastfpe_next
  4501. +
  4502. +/*---------------------------------------------------------------------------*/
  4503. +
  4504. + .globl CPRT_cmf
  4505. +CPRT_cmf:
  4506. + ldmia r1,{r1,r3,r5,r7}
  4507. + ldmia r2,{r2,r4,r6,r8}
  4508. +
  4509. +CPRT_cmf_e:
  4510. + ldr r0,[r13,#16*4]
  4511. +
  4512. + cmp r7,#0x7fffffff
  4513. + bic r0,r0,#0xf0000000
  4514. +
  4515. + cmpeq r3,#0xffffffff
  4516. + beq CPRT_cmf_unordered
  4517. + cmp r8,#0x7fffffff
  4518. + cmpeq r4,#0xffffffff
  4519. + beq CPRT_cmf_unordered
  4520. +
  4521. + cmp r1,r2
  4522. + beq CPRT_cmf_equalsign
  4523. + b CPRT_cmf_sign
  4524. +
  4525. +CPRT_cmf_equalsign:
  4526. + cmp r7,r8
  4527. + beq CPRT_cmf_equalexponent
  4528. + bgt CPRT_cmf_sign
  4529. + b CPRT_cmf_signb
  4530. +
  4531. +CPRT_cmf_equalexponent:
  4532. + cmp r3,r4
  4533. + cmpeq r5,r6
  4534. + beq CPRT_cmf_equal
  4535. + bhi CPRT_cmf_sign
  4536. + b CPRT_cmf_signb
  4537. +
  4538. +CPRT_cmf_sign:
  4539. + cmp r7,#0x80000000 @ (0.0 == -0.0)?
  4540. + cmpeq r7,r8
  4541. + beq CPRT_cmf_equal
  4542. + tst r1,#0x80000000
  4543. + orreq r0,r0,#0x20000000
  4544. + orrne r0,r0,#0x80000000
  4545. + str r0,[r13,#16*4]
  4546. + b fastfpe_next
  4547. +
  4548. +CPRT_cmf_signb:
  4549. + tst r1,#0x80000000
  4550. + orrne r0,r0,#0x20000000
  4551. + orreq r0,r0,#0x80000000
  4552. + str r0,[r13,#16*4]
  4553. + b fastfpe_next
  4554. +
  4555. +CPRT_cmf_equal:
  4556. + orr r0,r0,#0x60000000
  4557. + str r0,[r13,#16*4]
  4558. + b fastfpe_next
  4559. +
  4560. +CPRT_cmf_unordered:
  4561. + orr r0,r0,#0x10000000
  4562. + str r0,[r13,#16*4]
  4563. + b fastfpe_next
  4564. +
  4565. +/*---------------------------------------------------------------------------*/
  4566. +
  4567. + .globl CPRT_cnf
  4568. +CPRT_cnf:
  4569. + ldmia r1,{r1,r3,r5,r7}
  4570. + ldmia r2,{r2,r4,r6,r8}
  4571. + eor r2,r2,#0x80000000
  4572. + b CPRT_cmf_e
  4573. +
  4574. +/*---------------------------------------------------------------------------*/
  4575. diff -urN linux-2.4.26/arch/arm/fastfpe/Makefile linux-2.4.26-vrs1/arch/arm/fastfpe/Makefile
  4576. --- linux-2.4.26/arch/arm/fastfpe/Makefile 1970-01-01 01:00:00.000000000 +0100
  4577. +++ linux-2.4.26-vrs1/arch/arm/fastfpe/Makefile 2004-01-14 21:32:23.000000000 +0000
  4578. @@ -0,0 +1,25 @@
  4579. +#
  4580. +# linux/arch/arm/fastfpe/Makefile
  4581. +#
  4582. +# Copyright (C) Peter Teichmann
  4583. +#
  4584. +
  4585. +O_TARGET := fast-math-emu.o
  4586. +
  4587. +obj-y :=
  4588. +obj-m :=
  4589. +obj-n :=
  4590. +obj- :=
  4591. +
  4592. +fastfpe-objs := module.o entry.o CPDO.o CPRT.o CPDT.o
  4593. +
  4594. +list-multi := fastfpe.o
  4595. +
  4596. +obj-$(CONFIG_FPE_FASTFPE) += fastfpe.o
  4597. +
  4598. +USE_STANDARD_AS_RULE := true
  4599. +
  4600. +include $(TOPDIR)/Rules.make
  4601. +
  4602. +fastfpe.o: $(fastfpe-objs)
  4603. + $(LD) -r -o $@ $(fastfpe-objs)
  4604. diff -urN linux-2.4.26/arch/arm/fastfpe/entry.S linux-2.4.26-vrs1/arch/arm/fastfpe/entry.S
  4605. --- linux-2.4.26/arch/arm/fastfpe/entry.S 1970-01-01 01:00:00.000000000 +0100
  4606. +++ linux-2.4.26-vrs1/arch/arm/fastfpe/entry.S 2004-01-14 21:32:23.000000000 +0000
  4607. @@ -0,0 +1,295 @@
  4608. +/*
  4609. +At entry the registers contain the following information:
  4610. +
  4611. +r14 return address for undefined exception return
  4612. +r9 return address for return from exception
  4613. +r13 user registers on stack, offset 0 up to offset 4*15 contains
  4614. + registers r0..15, then the psr
  4615. +r10 FP workspace 35 words (init, reg[8][4], fpsr, fpcr)
  4616. +
  4617. +*/
  4618. +
  4619. +/*---------------------------------------------------------------------------*/
  4620. +
  4621. + .data
  4622. +fp_const:
  4623. + .word 0, 0x00000000, 0, 0x80000000 @ 0
  4624. + .word 0, 0x80000000, 0, 0 @ 1
  4625. + .word 0, 0x80000000, 0, 1 @ 2
  4626. + .word 0, 0xc0000000, 0, 1 @ 3
  4627. + .word 0, 0x80000000, 0, 2 @ 4
  4628. + .word 0, 0xa0000000, 0, 2 @ 5
  4629. + .word 0, 0x80000000, 0, -1 @ 0.5
  4630. + .word 0, 0xa0000000, 0, 3 @ 10
  4631. +fp_undef:
  4632. + .word 0
  4633. +fp_cond:
  4634. + .word 0xf0f0 @ eq
  4635. + .word 0x0f0f @ ne
  4636. + .word 0xcccc @ cs
  4637. + .word 0x3333 @ cc
  4638. + .word 0xff00 @ mi
  4639. + .word 0x00ff @ pl
  4640. + .word 0xaaaa @ vs
  4641. + .word 0x5555 @ vc
  4642. + .word 0x0c0c @ hi
  4643. + .word 0xf3f3 @ ls
  4644. + .word 0xaa55 @ ge
  4645. + .word 0x55aa @ lt
  4646. + .word 0x0a05 @ gt
  4647. + .word 0xf5fa @ le
  4648. + .word 0xffff @ al
  4649. + .word 0x0000 @ nv
  4650. +
  4651. +/*---------------------------------------------------------------------------*/
  4652. +
  4653. + .text
  4654. + .globl fastfpe_enter
  4655. +fastfpe_enter:
  4656. + ldr r4,=fp_undef
  4657. + str r14,[r4] @ to free one register
  4658. + add r10,r10,#4 @ to make the code simpler
  4659. + ldr r4,[r13,#60] @ r4=saved PC
  4660. + ldr r4,[r4,#-4] @ r4=trapped instruction
  4661. + and r1,r4,#0x00000f00 @ r1=coprocessor << 8
  4662. +next_enter:
  4663. + cmp r1,#1<<8 @ copro 1 ?
  4664. + beq copro_1
  4665. + cmp r1,#2<<8
  4666. + movne pc,r14
  4667. +
  4668. +copro_2:
  4669. + and r1,r4,#0x0f000000
  4670. + cmp r1,#0x0c000000 @ CPDT with post indexing
  4671. + cmpne r1,#0x0d000000 @ CPDT with pre indexing
  4672. + beq CPDT_M_enter
  4673. + mov pc,r14
  4674. +
  4675. +copro_1:
  4676. + and r1,r4,#0x0f000000
  4677. + cmp r1,#0x0e000000 @ CPDO
  4678. + beq CPDO_CPRT_enter
  4679. + cmp r1,#0x0c000000 @ CPDT with post indexing
  4680. + cmpne r1,#0x0d000000 @ CPDT with pre indexing
  4681. + beq CPDT_1_enter
  4682. + mov pc,r14
  4683. +
  4684. +/*---------------------------------------------------------------------------*/
  4685. +
  4686. + .globl fastfpe_next
  4687. +fastfpe_next:
  4688. + ldr r5,[r13,#60]
  4689. +next_after_cond:
  4690. +__x1:
  4691. + ldrt r4,[r5],#4
  4692. +
  4693. + ldr r0,=fp_cond @ check condition of next instruction
  4694. + ldr r1,[r13,#64] @ psr containing flags
  4695. + mov r2,r4,lsr#28
  4696. + mov r1,r1,lsr#28
  4697. + ldr r0,[r0,r2,lsl#2]
  4698. + mov r0,r0,lsr r1
  4699. + tst r0,#1
  4700. + beq next_after_cond @ must not necessarily have been an
  4701. + @ FP instruction !
  4702. + and r1,r4,#0x0f000000 @ Test for copro instruction
  4703. + cmp r1,#0x0c000000
  4704. + rsbgts r0,r1,#0x0e000000 @ cmpgt #0x0e000000,r1
  4705. + movlt pc,r9 @ next is no copro instruction, return
  4706. +
  4707. + ands r1,r4,#0x00000f00 @ r1 = coprocessor << 8
  4708. + cmpne r1,#3<<8
  4709. + movge pc,r9 @ copro = 0 or >=3, return
  4710. +
  4711. + str r5,[r13,#60] @ save updated pc
  4712. + b next_enter
  4713. +
  4714. +/*---------------------------------------------------------------------------*/
  4715. +
  4716. +undefined:
  4717. + ldr r4,=fp_undef
  4718. + ldr pc,[r4]
  4719. +
  4720. +/*---------------------------------------------------------------------------*/
  4721. +
  4722. +CPDT_1_enter:
  4723. + and r5,r4,#0x000f0000 @ r5=base register number << 16
  4724. + ldr r6,[r13,r5,lsr#14] @ r6=base address
  4725. + cmp r5,#0x000f0000 @ base register = pc ?
  4726. + addeq r6,r6,#4
  4727. + and r7,r4,#0x000000ff @ r7=offset value
  4728. +
  4729. + tst r4,#0x00800000 @ up or down?
  4730. + addne r7,r6,r7,lsl#2
  4731. + subeq r7,r6,r7,lsl#2 @ r6=base address +/- offset
  4732. + tst r4,#0x01000000 @ preindexing ?
  4733. + movne r6,r7
  4734. + tst r4,#0x00200000 @ write back ?
  4735. + cmpne r5,#0x000f0000 @ base register = pc ?
  4736. + strne r7,[r13,r5,lsr#14]
  4737. +
  4738. + and r0,r4,#0x00007000 @ r0=fp register number << 12
  4739. + add r0,r10,r0,lsr#8 @ r0=address of fp register
  4740. + mov r1,#0
  4741. + tst r4,#0x00008000
  4742. + orrne r1,r1,#1 @ T0
  4743. + tst r4,#0x00400000
  4744. + orrne r1,r1,#2 @ T1
  4745. + tst r4,#0x00100000
  4746. + orrne r1,r1,#4 @ L/S
  4747. +
  4748. + add pc,pc,r1,lsl#2
  4749. + mov r0,r0
  4750. + b CPDT_store_single @ these functions get
  4751. + b CPDT_store_double @ r0=address of fp register
  4752. + b CPDT_store_extended @ r6=address of data
  4753. + b undefined @ CPDT_store_decimal
  4754. + b CPDT_load_single
  4755. + b CPDT_load_double
  4756. + b CPDT_load_extended
  4757. + b undefined @ CPDT_load_decimal
  4758. +
  4759. +/*---------------------------------------------------------------------------*/
  4760. +
  4761. +CPDT_M_enter:
  4762. + and r5,r4,#0x000f0000 @ r5=base register number << 16
  4763. + ldr r6,[r13,r5,lsr#14] @ r6=base address
  4764. + cmp r5,#0x000f0000 @ base register = pc ?
  4765. + addeq r6,r6,#4
  4766. + and r7,r4,#0x000000ff @ r7=offset value
  4767. +
  4768. + tst r4,#0x00800000 @ up or down?
  4769. + addne r7,r6,r7,lsl#2
  4770. + subeq r7,r6,r7,lsl#2 @ r7=base address +/- offset
  4771. + tst r4,#0x01000000 @ preindexing ?
  4772. + movne r6,r7
  4773. + tst r4,#0x00200000 @ write back ?
  4774. + cmpne r5,#0x000f0000 @ base register = pc ?
  4775. + strne r7,[r13,r5,lsr#14]
  4776. +
  4777. + and r0,r4,#0x00007000 @ r0=fp register number << 12
  4778. + and r1,r4,#0x00008000
  4779. + mov r1,r1,lsr#15 @ N0
  4780. + and r2,r4,#0x00400000
  4781. + orrs r1,r1,r2,lsr#21 @ N1
  4782. + addeq r1,r1,#4 @ r1=register count
  4783. +
  4784. + tst r4,#0x00100000 @ load/store
  4785. + beq CPDT_sfm
  4786. + b CPDT_lfm
  4787. +
  4788. +/*---------------------------------------------------------------------------*/
  4789. +
  4790. +CPDO_CPRT_enter:
  4791. + tst r4,#0x00000010
  4792. + bne CPRT_enter
  4793. +
  4794. + and r0,r4,#0x00007000
  4795. + add r0,r10,r0,lsr#8 @ r0=address of Fd
  4796. + and r1,r4,#0x00070000
  4797. + add r1,r10,r1,lsr#12 @ r1=address of Fn
  4798. + tst r4,#0x00000008
  4799. + bne CPDO_const
  4800. + and r2,r4,#0x00000007
  4801. + add r2,r10,r2,lsl#4 @ r2=address of Fm
  4802. +
  4803. +CPDO_constback:
  4804. + and r3,r4,#0x00f00000
  4805. + tst r4,#0x00008000
  4806. + orrne r3,r3,#0x01000000
  4807. +
  4808. + add pc,pc,r3,lsr#18
  4809. + mov r0,r0
  4810. + b CPDO_adf
  4811. + b CPDO_muf
  4812. + b CPDO_suf
  4813. + b CPDO_rsf
  4814. + b CPDO_dvf
  4815. + b CPDO_rdf
  4816. + b undefined
  4817. + b undefined
  4818. + b undefined @ CPDO_rmf
  4819. + b CPDO_muf
  4820. + b CPDO_dvf
  4821. + b CPDO_rdf
  4822. + b undefined
  4823. + b undefined
  4824. + b undefined
  4825. + b undefined
  4826. + b CPDO_mvf
  4827. + b CPDO_mnf
  4828. + b CPDO_abs
  4829. + b CPDO_rnd
  4830. + b CPDO_sqt
  4831. + b undefined
  4832. + b undefined
  4833. + b undefined
  4834. + b undefined
  4835. + b undefined
  4836. + b undefined
  4837. + b undefined
  4838. + b undefined
  4839. + b undefined
  4840. + b CPDO_rnd
  4841. + b fastfpe_next
  4842. +
  4843. +CPDO_const:
  4844. + ldr r2,=fp_const
  4845. + and r3,r4,#0x00000007
  4846. + add r2,r2,r3,lsl#4
  4847. + b CPDO_constback
  4848. +
  4849. +/*---------------------------------------------------------------------------*/
  4850. +
  4851. +CPRT_enter:
  4852. + and r0,r4,#0x0000f000 @ r0=Rd<<12
  4853. + and r1,r4,#0x00070000
  4854. + add r1,r10,r1,lsr#12 @ r1=address of Fn
  4855. + tst r4,#0x00000008
  4856. + bne CPRT_const
  4857. + and r2,r4,#0x00000007
  4858. + add r2,r10,r2,lsl#4 @ r2=address of Fm
  4859. +
  4860. +CPRT_constback:
  4861. + and r3,r4,#0x00f00000
  4862. +
  4863. + add pc,pc,r3,lsr#18
  4864. + mov r0,r0
  4865. + b CPRT_flt
  4866. + b CPRT_fix
  4867. + b CPRT_wfs
  4868. + b CPRT_rfs
  4869. + b undefined
  4870. + b undefined
  4871. + b undefined
  4872. + b undefined
  4873. + b undefined
  4874. + b CPRT_cmf
  4875. + b undefined
  4876. + b CPRT_cnf
  4877. + b undefined
  4878. + b CPRT_cmf
  4879. + b undefined
  4880. + b CPRT_cnf
  4881. +
  4882. +CPRT_const:
  4883. + ldr r2,=fp_const
  4884. + and r3,r4,#0x00000007
  4885. + add r2,r2,r3,lsl#4
  4886. + b CPRT_constback
  4887. +
  4888. +/*---------------------------------------------------------------------------*/
  4889. +
  4890. + @ The fetch of the next instruction to emulate could fault
  4891. +
  4892. + .section .fixup,"ax"
  4893. + .align
  4894. +__f1:
  4895. + mov pc,r9
  4896. + .previous
  4897. + .section __ex_table,"a"
  4898. + .align 3
  4899. + .long __x1,__f1
  4900. + .previous
  4901. +
  4902. +/*---------------------------------------------------------------------------*/
  4903. diff -urN linux-2.4.26/arch/arm/fastfpe/module.c linux-2.4.26-vrs1/arch/arm/fastfpe/module.c
  4904. --- linux-2.4.26/arch/arm/fastfpe/module.c 1970-01-01 01:00:00.000000000 +0100
  4905. +++ linux-2.4.26-vrs1/arch/arm/fastfpe/module.c 2004-01-14 21:32:23.000000000 +0000
  4906. @@ -0,0 +1,78 @@
  4907. +/*
  4908. + Fast Floating Point Emulator
  4909. + (c) Peter Teichmann <mail@peter-teichmann.de>
  4910. +
  4911. + This program is free software; you can redistribute it and/or modify
  4912. + it under the terms of the GNU General Public License as published by
  4913. + the Free Software Foundation; either version 2 of the License, or
  4914. + (at your option) any later version.
  4915. +
  4916. + This program is distributed in the hope that it will be useful,
  4917. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  4918. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  4919. + GNU General Public License for more details.
  4920. +
  4921. + You should have received a copy of the GNU General Public License
  4922. + along with this program; if not, write to the Free Software
  4923. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  4924. +*/
  4925. +
  4926. +#include <linux/module.h>
  4927. +#include <linux/types.h>
  4928. +#include <linux/kernel.h>
  4929. +#include <linux/signal.h>
  4930. +#include <linux/sched.h>
  4931. +#include <linux/init.h>
  4932. +
  4933. +#ifndef MODULE
  4934. +#define kern_fp_enter fp_enter
  4935. +
  4936. +extern char fpe_type[];
  4937. +#endif
  4938. +
  4939. +static void (*orig_fp_enter)(void); /* old kern_fp_enter value */
  4940. +extern void (*kern_fp_enter)(void); /* current FP handler */
  4941. +extern void fastfpe_enter(void); /* forward declarations */
  4942. +
  4943. +#ifdef MODULE
  4944. +/*
  4945. + * Return 0 if we can be unloaded. This can only happen if
  4946. + * kern_fp_enter is still pointing at fastfpe_enter
  4947. + */
  4948. +static int fpe_unload(void)
  4949. +{
  4950. + return (kern_fp_enter == fastfpe_enter) ? 0 : 1;
  4951. +}
  4952. +#endif
  4953. +
  4954. +static int __init fpe_init(void)
  4955. +{
  4956. +#ifdef MODULE
  4957. + if (!mod_member_present(&__this_module, can_unload))
  4958. + return -EINVAL;
  4959. + __this_module.can_unload = fpe_unload;
  4960. +#else
  4961. + if (fpe_type[0] && strcmp(fpe_type, "fastfpe"))
  4962. + return 0;
  4963. +#endif
  4964. +
  4965. + printk("Fast Floating Point Emulator V0.9 (c) Peter Teichmann.\n");
  4966. +
  4967. + /* Save pointer to the old FP handler and then patch ourselves in */
  4968. + orig_fp_enter = kern_fp_enter;
  4969. + kern_fp_enter = fastfpe_enter;
  4970. +
  4971. + return 0;
  4972. +}
  4973. +
  4974. +static void __exit fpe_exit(void)
  4975. +{
  4976. + /* Restore the values we saved earlier. */
  4977. + kern_fp_enter = orig_fp_enter;
  4978. +}
  4979. +
  4980. +module_init(fpe_init);
  4981. +module_exit(fpe_exit);
  4982. +
  4983. +MODULE_AUTHOR("Peter Teichmann <mail@peter-teichmann.de>");
  4984. +MODULE_DESCRIPTION("Fast floating point emulator with full precision");
  4985. diff -urN linux-2.4.26/arch/arm/kernel/calls.S linux-2.4.26-vrs1/arch/arm/kernel/calls.S
  4986. --- linux-2.4.26/arch/arm/kernel/calls.S 2003-08-25 12:44:39.000000000 +0100
  4987. +++ linux-2.4.26-vrs1/arch/arm/kernel/calls.S 2004-03-04 21:01:56.000000000 +0000
  4988. @@ -115,7 +115,7 @@
  4989. .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */
  4990. .long SYMBOL_NAME(sys_statfs)
  4991. /* 100 */ .long SYMBOL_NAME(sys_fstatfs)
  4992. - .long SYMBOL_NAME(sys_ni_syscall)
  4993. + .long SYMBOL_NAME(sys_ni_syscall) /* 101 was sys_ioperm */
  4994. .long SYMBOL_NAME(sys_socketcall)
  4995. .long SYMBOL_NAME(sys_syslog)
  4996. .long SYMBOL_NAME(sys_setitimer)
  4997. @@ -126,7 +126,7 @@
  4998. .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */
  4999. /* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */
  5000. .long SYMBOL_NAME(sys_vhangup)
  5001. - .long SYMBOL_NAME(sys_ni_syscall)
  5002. + .long SYMBOL_NAME(sys_ni_syscall) /* 112 was sys_idle */
  5003. .long SYMBOL_NAME(sys_syscall) /* call a syscall */
  5004. .long SYMBOL_NAME(sys_wait4)
  5005. /* 115 */ .long SYMBOL_NAME(sys_swapoff)
  5006. @@ -137,7 +137,7 @@
  5007. /* 120 */ .long SYMBOL_NAME(sys_clone_wapper)
  5008. .long SYMBOL_NAME(sys_setdomainname)
  5009. .long SYMBOL_NAME(sys_newuname)
  5010. - .long SYMBOL_NAME(sys_ni_syscall)
  5011. + .long SYMBOL_NAME(sys_ni_syscall) /* 123 was sys_modify_ldt */
  5012. .long SYMBOL_NAME(sys_adjtimex)
  5013. /* 125 */ .long SYMBOL_NAME(sys_mprotect)
  5014. .long SYMBOL_NAME(sys_sigprocmask)
  5015. @@ -180,7 +180,7 @@
  5016. .long SYMBOL_NAME(sys_arm_mremap)
  5017. .long SYMBOL_NAME(sys_setresuid16)
  5018. /* 165 */ .long SYMBOL_NAME(sys_getresuid16)
  5019. - .long SYMBOL_NAME(sys_ni_syscall)
  5020. + .long SYMBOL_NAME(sys_ni_syscall) /* 166 was sys_vm86 */
  5021. .long SYMBOL_NAME(sys_query_module)
  5022. .long SYMBOL_NAME(sys_poll)
  5023. .long SYMBOL_NAME(sys_nfsservctl)
  5024. diff -urN linux-2.4.26/arch/arm/kernel/dma-rpc.c linux-2.4.26-vrs1/arch/arm/kernel/dma-rpc.c
  5025. --- linux-2.4.26/arch/arm/kernel/dma-rpc.c 2003-08-25 12:44:39.000000000 +0100
  5026. +++ linux-2.4.26-vrs1/arch/arm/kernel/dma-rpc.c 2004-01-14 21:38:42.000000000 +0000
  5027. @@ -26,19 +26,6 @@
  5028. #include <asm/mach/dma.h>
  5029. #include <asm/hardware/iomd.h>
  5030. -#if 0
  5031. -typedef enum {
  5032. - dma_size_8 = 1,
  5033. - dma_size_16 = 2,
  5034. - dma_size_32 = 4,
  5035. - dma_size_128 = 16
  5036. -} dma_size_t;
  5037. -
  5038. -typedef struct {
  5039. - dma_size_t transfersize;
  5040. -} dma_t;
  5041. -#endif
  5042. -
  5043. #define TRANSFER_SIZE 2
  5044. #define CURA (0)
  5045. @@ -48,10 +35,6 @@
  5046. #define CR (IOMD_IO0CR - IOMD_IO0CURA)
  5047. #define ST (IOMD_IO0ST - IOMD_IO0CURA)
  5048. -#define state_prog_a 0
  5049. -#define state_wait_a 1
  5050. -#define state_wait_b 2
  5051. -
  5052. static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
  5053. {
  5054. unsigned long end, offset, flags = 0;
  5055. @@ -65,7 +48,7 @@
  5056. if (end > PAGE_SIZE)
  5057. end = PAGE_SIZE;
  5058. - if (offset + (int) TRANSFER_SIZE > end)
  5059. + if (offset + TRANSFER_SIZE >= end)
  5060. flags |= DMA_END_L;
  5061. sg->length = end - TRANSFER_SIZE;
  5062. @@ -103,27 +86,31 @@
  5063. if (!(status & DMA_ST_INT))
  5064. return;
  5065. - if (status & DMA_ST_OFL && !dma->sg)
  5066. - break;
  5067. -
  5068. - iomd_get_next_sg(&dma->cur_sg, dma);
  5069. + if ((dma->state ^ status) & DMA_ST_AB)
  5070. + iomd_get_next_sg(&dma->cur_sg, dma);
  5071. switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
  5072. case DMA_ST_OFL: /* OIA */
  5073. case DMA_ST_AB: /* .IB */
  5074. iomd_writel(dma->cur_sg.dma_address, base + CURA);
  5075. iomd_writel(dma->cur_sg.length, base + ENDA);
  5076. + dma->state = DMA_ST_AB;
  5077. break;
  5078. case DMA_ST_OFL | DMA_ST_AB: /* OIB */
  5079. case 0: /* .IA */
  5080. iomd_writel(dma->cur_sg.dma_address, base + CURB);
  5081. iomd_writel(dma->cur_sg.length, base + ENDB);
  5082. + dma->state = 0;
  5083. break;
  5084. }
  5085. +
  5086. + if (status & DMA_ST_OFL &&
  5087. + dma->cur_sg.length == (DMA_END_S|DMA_END_L))
  5088. + break;
  5089. } while (1);
  5090. - iomd_writeb(0, base + CR);
  5091. + dma->state = ~DMA_ST_AB;
  5092. disable_irq(irq);
  5093. }
  5094. @@ -158,6 +145,7 @@
  5095. }
  5096. iomd_writeb(DMA_CR_C, dma_base + CR);
  5097. + dma->state = DMA_ST_AB;
  5098. }
  5099. if (dma->dma_mode == DMA_MODE_READ)
  5100. @@ -171,13 +159,11 @@
  5101. {
  5102. unsigned long dma_base = dma->dma_base;
  5103. unsigned long flags;
  5104. - unsigned int ctrl;
  5105. local_irq_save(flags);
  5106. - ctrl = iomd_readb(dma_base + CR);
  5107. - if (ctrl & DMA_CR_E)
  5108. + if (dma->state != ~DMA_ST_AB)
  5109. disable_irq(dma->dma_irq);
  5110. - iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR);
  5111. + iomd_writeb(0, dma_base + CR);
  5112. local_irq_restore(flags);
  5113. }
  5114. diff -urN linux-2.4.26/arch/arm/kernel/entry-armv.S linux-2.4.26-vrs1/arch/arm/kernel/entry-armv.S
  5115. --- linux-2.4.26/arch/arm/kernel/entry-armv.S 2003-08-25 12:44:39.000000000 +0100
  5116. +++ linux-2.4.26-vrs1/arch/arm/kernel/entry-armv.S 2004-01-14 21:32:24.000000000 +0000
  5117. @@ -677,12 +677,11 @@
  5118. mrs r9, cpsr @ Enable interrupts if they were
  5119. tst r3, #I_BIT
  5120. biceq r9, r9, #I_BIT @ previously
  5121. - mov r0, r2 @ *** remove once everyones in sync
  5122. /*
  5123. * This routine must not corrupt r9
  5124. */
  5125. #ifdef MULTI_CPU
  5126. - ldr r4, .LCprocfns @ pass r0, r3 to
  5127. + ldr r4, .LCprocfns @ pass r2, r3 to
  5128. mov lr, pc @ processor code
  5129. ldr pc, [r4] @ call processor specific code
  5130. #else
  5131. @@ -788,9 +787,8 @@
  5132. stmdb r5, {sp, lr}^
  5133. alignment_trap r7, r7, __temp_abt
  5134. zero_fp
  5135. - mov r0, r2 @ remove once everyones in sync
  5136. #ifdef MULTI_CPU
  5137. - ldr r4, .LCprocfns @ pass r0, r3 to
  5138. + ldr r4, .LCprocfns @ pass r2, r3 to
  5139. mov lr, pc @ processor code
  5140. ldr pc, [r4] @ call processor specific code
  5141. #else
  5142. @@ -840,7 +838,8 @@
  5143. adrsvc al, r9, ret_from_exception @ r9 = normal FP return
  5144. adrsvc al, lr, fpundefinstr @ lr = undefined instr return
  5145. -call_fpe: get_current_task r10
  5146. +call_fpe: enable_irq r10
  5147. + get_current_task r10
  5148. mov r8, #1
  5149. strb r8, [r10, #TSK_USED_MATH] @ set current->used_math
  5150. ldr r4, .LCfp
  5151. diff -urN linux-2.4.26/arch/arm/kernel/fiq.c linux-2.4.26-vrs1/arch/arm/kernel/fiq.c
  5152. --- linux-2.4.26/arch/arm/kernel/fiq.c 2003-06-13 15:51:29.000000000 +0100
  5153. +++ linux-2.4.26-vrs1/arch/arm/kernel/fiq.c 2004-04-09 19:55:21.000000000 +0100
  5154. @@ -122,23 +122,23 @@
  5155. register unsigned long tmp, tmp2;
  5156. __asm__ volatile (
  5157. #ifdef CONFIG_CPU_26
  5158. - "mov %0, pc
  5159. - bic %1, %0, #0x3
  5160. - orr %1, %1, %3
  5161. - teqp %1, #0 @ select FIQ mode
  5162. - mov r0, r0
  5163. - ldmia %2, {r8 - r14}
  5164. - teqp %0, #0 @ return to SVC mode
  5165. - mov r0, r0"
  5166. + "mov %0, pc \n"
  5167. + "bic %1, %0, #0x3 \n"
  5168. + "orr %1, %1, %3 \n"
  5169. + "teqp %1, #0 @ select FIQ mode \n"
  5170. + "mov r0, r0 \n"
  5171. + "ldmia %2, {r8 - r14} \n"
  5172. + "teqp %0, #0 @ return to SVC mode \n"
  5173. + "mov r0, r0 \n"
  5174. #endif
  5175. #ifdef CONFIG_CPU_32
  5176. - "mrs %0, cpsr
  5177. - mov %1, %3
  5178. - msr cpsr_c, %1 @ select FIQ mode
  5179. - mov r0, r0
  5180. - ldmia %2, {r8 - r14}
  5181. - msr cpsr_c, %0 @ return to SVC mode
  5182. - mov r0, r0"
  5183. + "mrs %0, cpsr \n"
  5184. + "mov %1, %3 \n"
  5185. + "msr cpsr_c, %1 @ select FIQ mode \n"
  5186. + "mov r0, r0 \n"
  5187. + "ldmia %2, {r8 - r14} \n"
  5188. + "msr cpsr_c, %0 @ return to SVC mode \n"
  5189. + "mov r0, r0 \n"
  5190. #endif
  5191. : "=&r" (tmp), "=&r" (tmp2)
  5192. : "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
  5193. @@ -154,23 +154,23 @@
  5194. register unsigned long tmp, tmp2;
  5195. __asm__ volatile (
  5196. #ifdef CONFIG_CPU_26
  5197. - "mov %0, pc
  5198. - bic %1, %0, #0x3
  5199. - orr %1, %1, %3
  5200. - teqp %1, #0 @ select FIQ mode
  5201. - mov r0, r0
  5202. - stmia %2, {r8 - r14}
  5203. - teqp %0, #0 @ return to SVC mode
  5204. - mov r0, r0"
  5205. + "mov %0, pc \n"
  5206. + "bic %1, %0, #0x3 \n"
  5207. + "orr %1, %1, %3 \n"
  5208. + "teqp %1, #0 @ select FIQ mode \n"
  5209. + "mov r0, r0 \n"
  5210. + "stmia %2, {r8 - r14} \n"
  5211. + "teqp %0, #0 @ return to SVC mode \n"
  5212. + "mov r0, r0 \n"
  5213. #endif
  5214. #ifdef CONFIG_CPU_32
  5215. - "mrs %0, cpsr
  5216. - mov %1, %3
  5217. - msr cpsr_c, %1 @ select FIQ mode
  5218. - mov r0, r0
  5219. - stmia %2, {r8 - r14}
  5220. - msr cpsr_c, %0 @ return to SVC mode
  5221. - mov r0, r0"
  5222. + "mrs %0, cpsr \n"
  5223. + "mov %1, %3 \n"
  5224. + "msr cpsr_c, %1 @ select FIQ mode \n"
  5225. + "mov r0, r0 \n"
  5226. + "stmia %2, {r8 - r14} \n"
  5227. + "msr cpsr_c, %0 @ return to SVC mode \n"
  5228. + "mov r0, r0 \n"
  5229. #endif
  5230. : "=&r" (tmp), "=&r" (tmp2)
  5231. : "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
  5232. diff -urN linux-2.4.26/arch/arm/kernel/head-armv.S linux-2.4.26-vrs1/arch/arm/kernel/head-armv.S
  5233. --- linux-2.4.26/arch/arm/kernel/head-armv.S 2003-08-25 12:44:39.000000000 +0100
  5234. +++ linux-2.4.26-vrs1/arch/arm/kernel/head-armv.S 2004-01-14 21:32:24.000000000 +0000
  5235. @@ -1,7 +1,7 @@
  5236. /*
  5237. * linux/arch/arm/kernel/head-armv.S
  5238. *
  5239. - * Copyright (C) 1994-1999 Russell King
  5240. + * Copyright (C) 1994-2003 Russell King
  5241. *
  5242. * This program is free software; you can redistribute it and/or modify
  5243. * it under the terms of the GNU General Public License version 2 as
  5244. @@ -163,10 +163,10 @@
  5245. */
  5246. .type __ret, %function
  5247. __ret: ldr lr, __switch_data
  5248. - mcr p15, 0, r0, c1, c0
  5249. - mrc p15, 0, r0, c1, c0, 0 @ read it back.
  5250. - mov r0, r0
  5251. - mov r0, r0
  5252. + mcr p15, 0, r0, c1, c0, 0
  5253. + mrc p15, 0, r3, c0, c0, 0
  5254. + mov r3, r3
  5255. + mov r3, r3
  5256. mov pc, lr
  5257. /*
  5258. @@ -214,6 +214,11 @@
  5259. */
  5260. __create_page_tables:
  5261. pgtbl r4, r5 @ page table address
  5262. +#if defined(CONFIG_CPU_DCACHE_DISABLE)
  5263. + bic r8, r8, #0x00c @ clear B, C
  5264. +#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
  5265. + bic r8, r8, #0x004 @ clear B
  5266. +#endif
  5267. /*
  5268. * Clear the 16K level 1 swapper page table
  5269. diff -urN linux-2.4.26/arch/arm/kernel/irq.c linux-2.4.26-vrs1/arch/arm/kernel/irq.c
  5270. --- linux-2.4.26/arch/arm/kernel/irq.c 2003-08-25 12:44:39.000000000 +0100
  5271. +++ linux-2.4.26-vrs1/arch/arm/kernel/irq.c 2004-01-14 21:32:24.000000000 +0000
  5272. @@ -549,7 +549,7 @@
  5273. kfree(action);
  5274. goto out;
  5275. }
  5276. - printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
  5277. + printk(KERN_ERR "Trying to free IRQ%d\n",irq);
  5278. #ifdef CONFIG_DEBUG_ERRORS
  5279. __backtrace();
  5280. #endif
  5281. diff -urN linux-2.4.26/arch/arm/kernel/ptrace.c linux-2.4.26-vrs1/arch/arm/kernel/ptrace.c
  5282. --- linux-2.4.26/arch/arm/kernel/ptrace.c 2003-08-25 12:44:39.000000000 +0100
  5283. +++ linux-2.4.26-vrs1/arch/arm/kernel/ptrace.c 2004-01-14 21:32:24.000000000 +0000
  5284. @@ -725,11 +725,8 @@
  5285. goto out_tsk;
  5286. }
  5287. ret = -ESRCH;
  5288. - if (!(child->ptrace & PT_PTRACED))
  5289. - goto out_tsk;
  5290. - if (child->state != TASK_STOPPED && request != PTRACE_KILL)
  5291. - goto out_tsk;
  5292. - if (child->p_pptr != current)
  5293. + ret = ptrace_check_attach(child, request == PTRACE_KILL);
  5294. + if (ret)
  5295. goto out_tsk;
  5296. ret = do_ptrace(request, child, addr, data);
  5297. diff -urN linux-2.4.26/arch/arm/kernel/semaphore.c linux-2.4.26-vrs1/arch/arm/kernel/semaphore.c
  5298. --- linux-2.4.26/arch/arm/kernel/semaphore.c 2003-08-25 12:44:39.000000000 +0100
  5299. +++ linux-2.4.26-vrs1/arch/arm/kernel/semaphore.c 2004-01-14 21:38:42.000000000 +0000
  5300. @@ -193,7 +193,7 @@
  5301. bl __down_interruptible \n\
  5302. mov ip, r0 \n\
  5303. ldmfd sp!, {r0 - r3, pc}^ \n\
  5304. -
  5305. + \n\
  5306. .align 5 \n\
  5307. .globl __down_trylock_failed \n\
  5308. __down_trylock_failed: \n\
  5309. diff -urN linux-2.4.26/arch/arm/kernel/signal.c linux-2.4.26-vrs1/arch/arm/kernel/signal.c
  5310. --- linux-2.4.26/arch/arm/kernel/signal.c 2003-08-25 12:44:39.000000000 +0100
  5311. +++ linux-2.4.26-vrs1/arch/arm/kernel/signal.c 2004-01-14 21:32:24.000000000 +0000
  5312. @@ -641,10 +641,7 @@
  5313. /* FALLTHRU */
  5314. default:
  5315. - sigaddset(&current->pending.signal, signr);
  5316. - recalc_sigpending(current);
  5317. - current->flags |= PF_SIGNALED;
  5318. - do_exit(exit_code);
  5319. + sig_exit(signr, exit_code, &info);
  5320. /* NOTREACHED */
  5321. }
  5322. }
  5323. diff -urN linux-2.4.26/arch/arm/lib/Makefile linux-2.4.26-vrs1/arch/arm/lib/Makefile
  5324. --- linux-2.4.26/arch/arm/lib/Makefile 2003-08-25 12:44:39.000000000 +0100
  5325. +++ linux-2.4.26-vrs1/arch/arm/lib/Makefile 2004-01-14 21:32:24.000000000 +0000
  5326. @@ -15,7 +15,7 @@
  5327. strnlen_user.o strchr.o strrchr.o testchangebit.o \
  5328. testclearbit.o testsetbit.o uaccess.o getuser.o \
  5329. putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
  5330. - ucmpdi2.o udivdi3.o lib1funcs.o
  5331. + ucmpdi2.o udivdi3.o lib1funcs.o div64.o
  5332. obj-m :=
  5333. obj-n :=
  5334. diff -urN linux-2.4.26/arch/arm/lib/div64.S linux-2.4.26-vrs1/arch/arm/lib/div64.S
  5335. --- linux-2.4.26/arch/arm/lib/div64.S 1970-01-01 01:00:00.000000000 +0100
  5336. +++ linux-2.4.26-vrs1/arch/arm/lib/div64.S 2004-01-14 21:32:24.000000000 +0000
  5337. @@ -0,0 +1,59 @@
  5338. +#include <linux/linkage.h>
  5339. +
  5340. +#ifndef __ARMEB__
  5341. +ql .req r0 @ quotient low
  5342. +qh .req r1 @ quotient high
  5343. +onl .req r0 @ original dividend low
  5344. +onh .req r1 @ original dividend high
  5345. +nl .req r4 @ dividend low
  5346. +nh .req r5 @ dividend high
  5347. +res .req r4 @ result
  5348. +#else
  5349. +ql .req r1
  5350. +qh .req r0
  5351. +onl .req r1
  5352. +onh .req r0
  5353. +nl .req r5
  5354. +nh .req r4
  5355. +res .req r5
  5356. +#endif
  5357. +
  5358. +dl .req r3 @ divisor low
  5359. +dh .req r2 @ divsor high
  5360. +
  5361. +
  5362. +ENTRY(do_div64)
  5363. + stmfd sp!, {r4, r5, lr}
  5364. + mov nl, onl
  5365. + movs nh, onh @ if high bits are zero
  5366. + movne lr, #33
  5367. + moveq lr, #1 @ only divide low bits
  5368. + moveq nh, onl
  5369. +
  5370. + tst dh, #0x80000000
  5371. + bne 2f
  5372. +1: cmp nh, dh
  5373. + bls 2f
  5374. + add lr, lr, #1
  5375. + movs dh, dh, lsl #1 @ left justify disor
  5376. + bpl 1b
  5377. +
  5378. +2: movs nh, onh
  5379. + moveq dl, dh
  5380. + moveq dh, #0
  5381. + movne dl, #0
  5382. + mov ql, #0
  5383. + mov qh, #0
  5384. +3: subs ip, nl, dl @ trial subtraction
  5385. + sbcs ip, nh, dh
  5386. + movcs nh, ip @ only update if successful
  5387. + subcs nl, nl, dl @ (repeat the subtraction)
  5388. + adcs ql, ql, ql @ C=1 if successful, shift into
  5389. + adc qh, qh, qh @ quotient
  5390. + movs dh, dh, lsr #1 @ shift base high part right
  5391. + mov dl, dl, rrx @ shift base low part right
  5392. + subs lr, lr, #1
  5393. + bne 3b
  5394. +
  5395. + mov r2, res
  5396. + ldmfd sp!, {r4, r5, pc}
  5397. diff -urN linux-2.4.26/arch/arm/lib/putuser.S linux-2.4.26-vrs1/arch/arm/lib/putuser.S
  5398. --- linux-2.4.26/arch/arm/lib/putuser.S 2001-10-11 17:04:57.000000000 +0100
  5399. +++ linux-2.4.26-vrs1/arch/arm/lib/putuser.S 2004-01-14 21:32:24.000000000 +0000
  5400. @@ -30,11 +30,11 @@
  5401. .global __put_user_1
  5402. __put_user_1:
  5403. - bic r2, sp, #0x1f00
  5404. - bic r2, r2, #0x00ff
  5405. - ldr r2, [r2, #TSK_ADDR_LIMIT]
  5406. - sub r2, r2, #1
  5407. - cmp r0, r2
  5408. + bic ip, sp, #0x1f00
  5409. + bic ip, ip, #0x00ff
  5410. + ldr ip, [ip, #TSK_ADDR_LIMIT]
  5411. + sub ip, ip, #1
  5412. + cmp r0, ip
  5413. 1: strlsbt r1, [r0]
  5414. movls r0, #0
  5415. movls pc, lr
  5416. @@ -42,11 +42,11 @@
  5417. .global __put_user_2
  5418. __put_user_2:
  5419. - bic r2, sp, #0x1f00
  5420. - bic r2, r2, #0x00ff
  5421. - ldr r2, [r2, #TSK_ADDR_LIMIT]
  5422. - sub r2, r2, #2
  5423. - cmp r0, r2
  5424. + bic ip, sp, #0x1f00
  5425. + bic ip, ip, #0x00ff
  5426. + ldr ip, [ip, #TSK_ADDR_LIMIT]
  5427. + sub ip, ip, #2
  5428. + cmp r0, ip
  5429. 2: strlsbt r1, [r0], #1
  5430. movls r1, r1, lsr #8
  5431. 3: strlsbt r1, [r0]
  5432. @@ -56,11 +56,11 @@
  5433. .global __put_user_4
  5434. __put_user_4:
  5435. - bic r2, sp, #0x1f00
  5436. - bic r2, r2, #0x00ff
  5437. - ldr r2, [r2, #TSK_ADDR_LIMIT]
  5438. - sub r2, r2, #4
  5439. - cmp r0, r2
  5440. + bic ip, sp, #0x1f00
  5441. + bic ip, ip, #0x00ff
  5442. + ldr ip, [ip, #TSK_ADDR_LIMIT]
  5443. + sub ip, ip, #4
  5444. + cmp r0, ip
  5445. 4: strlst r1, [r0]
  5446. movls r0, #0
  5447. movls pc, lr
  5448. diff -urN linux-2.4.26/arch/arm/mach-at91rm9200/Makefile linux-2.4.26-vrs1/arch/arm/mach-at91rm9200/Makefile
  5449. --- linux-2.4.26/arch/arm/mach-at91rm9200/Makefile 2003-08-25 12:44:39.000000000 +0100
  5450. +++ linux-2.4.26-vrs1/arch/arm/mach-at91rm9200/Makefile 2004-04-10 12:21:08.000000000 +0100
  5451. @@ -18,4 +18,8 @@
  5452. export-objs :=
  5453. +# LEDs support
  5454. +leds-$(CONFIG_ARCH_AT91RM9200DK) += dk-leds.o
  5455. +obj-$(CONFIG_LEDS) += $(leds-y)
  5456. +
  5457. include $(TOPDIR)/Rules.make
  5458. diff -urN linux-2.4.26/arch/arm/mach-at91rm9200/dk-leds.c linux-2.4.26-vrs1/arch/arm/mach-at91rm9200/dk-leds.c
  5459. --- linux-2.4.26/arch/arm/mach-at91rm9200/dk-leds.c 1970-01-01 01:00:00.000000000 +0100
  5460. +++ linux-2.4.26-vrs1/arch/arm/mach-at91rm9200/dk-leds.c 2004-04-10 12:21:08.000000000 +0100
  5461. @@ -0,0 +1,97 @@
  5462. +/*
  5463. + * LED driver for the Atmel AT91RM9200 Development Kit.
  5464. + *
  5465. + * (c) SAN People (Pty) Ltd
  5466. + *
  5467. + * This program is free software; you can redistribute it and/or
  5468. + * modify it under the terms of the GNU General Public License
  5469. + * as published by the Free Software Foundation; either version
  5470. + * 2 of the License, or (at your option) any later version.
  5471. +*/
  5472. +
  5473. +#include <linux/config.h>
  5474. +#include <linux/kernel.h>
  5475. +#include <linux/module.h>
  5476. +#include <linux/init.h>
  5477. +
  5478. +#include <asm/mach-types.h>
  5479. +#include <asm/leds.h>
  5480. +#include <asm/arch/hardware.h>
  5481. +#include <asm/arch/pio.h>
  5482. +
  5483. +
  5484. +static inline void at91_led_on(void)
  5485. +{
  5486. + AT91_SYS->PIOB_CODR = AT91C_PIO_PB2;
  5487. +}
  5488. +
  5489. +static inline void at91_led_off(void)
  5490. +{
  5491. + AT91_SYS->PIOB_SODR = AT91C_PIO_PB2;
  5492. +}
  5493. +
  5494. +static inline void at91_led_toggle(void)
  5495. +{
  5496. + unsigned long curr = AT91_SYS->PIOB_ODSR;
  5497. + if (curr & AT91C_PIO_PB2)
  5498. + AT91_SYS->PIOB_CODR = AT91C_PIO_PB2;
  5499. + else
  5500. + AT91_SYS->PIOB_SODR = AT91C_PIO_PB2;
  5501. +}
  5502. +
  5503. +
  5504. +/*
  5505. + * Handle LED events.
  5506. + */
  5507. +static void at91rm9200dk_leds_event(led_event_t evt)
  5508. +{
  5509. + unsigned long flags;
  5510. +
  5511. + local_irq_save(flags);
  5512. +
  5513. + switch(evt) {
  5514. + case led_start: /* System startup */
  5515. + at91_led_on();
  5516. + break;
  5517. +
  5518. + case led_stop: /* System stop / suspend */
  5519. + at91_led_off();
  5520. + break;
  5521. +
  5522. +#ifdef CONFIG_LEDS_TIMER
  5523. + case led_timer: /* Every 50 timer ticks */
  5524. + at91_led_toggle();
  5525. + break;
  5526. +#endif
  5527. +
  5528. +#ifdef CONFIG_LEDS_CPU
  5529. + case led_idle_start: /* Entering idle state */
  5530. + at91_led_off();
  5531. + break;
  5532. +
  5533. + case led_idle_end: /* Exit idle state */
  5534. + at91_led_on();
  5535. + break;
  5536. +#endif
  5537. +
  5538. + default:
  5539. + break;
  5540. + }
  5541. +
  5542. + local_irq_restore(flags);
  5543. +}
  5544. +
  5545. +
  5546. +static int __init leds_init(void)
  5547. +{
  5548. + /* Enable PIO to access the LEDs */
  5549. + AT91_SYS->PIOB_PER = AT91C_PIO_PB2;
  5550. + AT91_SYS->PIOB_OER = AT91C_PIO_PB2;
  5551. +
  5552. + leds_event = at91rm9200dk_leds_event;
  5553. +
  5554. + leds_event(led_start);
  5555. + return 0;
  5556. +}
  5557. +
  5558. +__initcall(leds_init);
  5559. diff -urN linux-2.4.26/arch/arm/mach-integrator/pci_v3.c linux-2.4.26-vrs1/arch/arm/mach-integrator/pci_v3.c
  5560. --- linux-2.4.26/arch/arm/mach-integrator/pci_v3.c 2003-06-13 15:51:29.000000000 +0100
  5561. +++ linux-2.4.26-vrs1/arch/arm/mach-integrator/pci_v3.c 2004-01-14 21:32:24.000000000 +0000
  5562. @@ -21,7 +21,6 @@
  5563. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  5564. */
  5565. #include <linux/config.h>
  5566. -#include <linux/sched.h>
  5567. #include <linux/kernel.h>
  5568. #include <linux/pci.h>
  5569. #include <linux/ptrace.h>
  5570. @@ -32,6 +31,7 @@
  5571. #include <linux/init.h>
  5572. #include <asm/hardware.h>
  5573. +#include <asm/io.h>
  5574. #include <asm/irq.h>
  5575. #include <asm/system.h>
  5576. #include <asm/mach/pci.h>
  5577. @@ -447,15 +447,16 @@
  5578. #define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20)
  5579. #define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24)
  5580. -static int v3_fault(unsigned long addr, struct pt_regs *regs)
  5581. +static int
  5582. +v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  5583. {
  5584. unsigned long pc = instruction_pointer(regs);
  5585. unsigned long instr = *(unsigned long *)pc;
  5586. #if 0
  5587. char buf[128];
  5588. - sprintf(buf, "V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
  5589. - addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
  5590. + sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
  5591. + addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
  5592. v3_readb(V3_LB_ISTAT));
  5593. printk(KERN_DEBUG "%s", buf);
  5594. printascii(buf);
  5595. @@ -523,8 +524,6 @@
  5596. #endif
  5597. }
  5598. -extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
  5599. -
  5600. /*
  5601. * V3_LB_BASE? - local bus address
  5602. * V3_LB_MAP? - pci bus address
  5603. @@ -539,7 +538,10 @@
  5604. /*
  5605. * Hook in our fault handler for PCI errors
  5606. */
  5607. - external_fault = v3_fault;
  5608. + hook_fault_code(4, v3_pci_fault, SIGBUS, "external abort on linefetch");
  5609. + hook_fault_code(6, v3_pci_fault, SIGBUS, "external abort on linefetch");
  5610. + hook_fault_code(8, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
  5611. + hook_fault_code(10, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
  5612. spin_lock_irqsave(&v3_lock, flags);
  5613. @@ -629,7 +631,7 @@
  5614. #if 0
  5615. ret = request_irq(IRQ_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
  5616. if (ret)
  5617. - printk(KERN_ERR "PCI: unable to grab local bus timeout ".
  5618. + printk(KERN_ERR "PCI: unable to grab local bus timeout "
  5619. "interrupt: %d\n", ret);
  5620. #endif
  5621. }
  5622. diff -urN linux-2.4.26/arch/arm/mach-sa1100/pm.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/pm.c
  5623. --- linux-2.4.26/arch/arm/mach-sa1100/pm.c 2003-08-25 12:44:39.000000000 +0100
  5624. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/pm.c 2004-01-14 21:38:43.000000000 +0000
  5625. @@ -21,6 +21,8 @@
  5626. *
  5627. * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
  5628. * Storage is local on the stack now.
  5629. + * 2003-06-25: Jeff Corrall <jcorrall@mac.com>
  5630. + * Saved the GPIO levels for resume after sleep.
  5631. */
  5632. #include <linux/config.h>
  5633. #include <linux/init.h>
  5634. @@ -70,13 +72,20 @@
  5635. int pm_do_suspend(void)
  5636. {
  5637. unsigned long sleep_save[SLEEP_SAVE_SIZE];
  5638. + unsigned long sleep_save_gpsr;
  5639. + unsigned long sleep_save_gpcr;
  5640. + unsigned long delta;
  5641. cli();
  5642. leds_event(led_stop);
  5643. /* preserve current time */
  5644. - RCNR = xtime.tv_sec;
  5645. + delta = xtime.tv_sec - RCNR;
  5646. +
  5647. + /* save the current state of the GPIO output pins */
  5648. + sleep_save_gpsr = GPDR & GPLR;
  5649. + sleep_save_gpcr = GPDR & ~GPLR;
  5650. /* save vital registers */
  5651. SAVE(OSCR);
  5652. @@ -121,6 +130,10 @@
  5653. printk(KERN_DEBUG "*** made it back from resume\n");
  5654. #endif
  5655. + /* restore GPIO output state before enabling the pins */
  5656. + GPSR = sleep_save_gpsr;
  5657. + GPCR = sleep_save_gpcr;
  5658. +
  5659. /* restore registers */
  5660. RESTORE(GPDR);
  5661. RESTORE(GRER);
  5662. @@ -151,7 +164,7 @@
  5663. RESTORE(ICMR);
  5664. /* restore current time */
  5665. - xtime.tv_sec = RCNR;
  5666. + xtime.tv_sec = RCNR + delta;
  5667. leds_event(led_start);
  5668. diff -urN linux-2.4.26/arch/arm/mach-sa1100/sa1100_usb.h linux-2.4.26-vrs1/arch/arm/mach-sa1100/sa1100_usb.h
  5669. --- linux-2.4.26/arch/arm/mach-sa1100/sa1100_usb.h 1970-01-01 01:00:00.000000000 +0100
  5670. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/sa1100_usb.h 2004-01-14 21:32:24.000000000 +0000
  5671. @@ -0,0 +1,193 @@
  5672. +/*
  5673. + * sa1100_usb.h
  5674. + *
  5675. + * Public interface to the sa1100 USB core. For use by client modules
  5676. + * like usb-eth and usb-char.
  5677. + *
  5678. + */
  5679. +
  5680. +#ifndef _SA1100_USB_H
  5681. +#define _SA1100_USB_H
  5682. +#include <asm/byteorder.h>
  5683. +
  5684. +typedef void (*usb_callback_t)(int flag, int size);
  5685. +
  5686. +/* in usb_ctl.c (see also descriptor methods at bottom of file) */
  5687. +
  5688. +// Open the USB client for client and initialize data structures
  5689. +// to default values, but _do not_ start UDC.
  5690. +int sa1100_usb_open( const char * client_name );
  5691. +
  5692. +// Start UDC running
  5693. +int sa1100_usb_start( void );
  5694. +
  5695. +// Immediately stop udc, fire off completion routines w/-EINTR
  5696. +int sa1100_usb_stop( void ) ;
  5697. +
  5698. +// Disconnect client from usb core
  5699. +int sa1100_usb_close( void ) ;
  5700. +
  5701. +// set notify callback for when core reaches configured state
  5702. +// return previous pointer (if any)
  5703. +typedef void (*usb_notify_t)(void);
  5704. +usb_notify_t sa1100_set_configured_callback( usb_notify_t callback );
  5705. +
  5706. +/* in usb_send.c */
  5707. +int sa1100_usb_xmitter_avail( void );
  5708. +int sa1100_usb_send(char *buf, int len, usb_callback_t callback);
  5709. +void sa1100_usb_send_reset(void);
  5710. +
  5711. +/* in usb_recev.c */
  5712. +int sa1100_usb_recv(char *buf, int len, usb_callback_t callback);
  5713. +void sa1100_usb_recv_reset(void);
  5714. +
  5715. +//////////////////////////////////////////////////////////////////////////////
  5716. +// Descriptor Management
  5717. +//////////////////////////////////////////////////////////////////////////////
  5718. +
  5719. +#define DescriptorHeader \
  5720. + __u8 bLength; \
  5721. + __u8 bDescriptorType
  5722. +
  5723. +
  5724. +// --- Device Descriptor -------------------
  5725. +
  5726. +typedef struct {
  5727. + DescriptorHeader;
  5728. + __u16 bcdUSB; /* USB specification revision number in BCD */
  5729. + __u8 bDeviceClass; /* USB class for entire device */
  5730. + __u8 bDeviceSubClass; /* USB subclass information for entire device */
  5731. + __u8 bDeviceProtocol; /* USB protocol information for entire device */
  5732. + __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */
  5733. + __u16 idVendor; /* USB vendor ID */
  5734. + __u16 idProduct; /* USB product ID */
  5735. + __u16 bcdDevice; /* vendor assigned device release number */
  5736. + __u8 iManufacturer; /* index of manufacturer string */
  5737. + __u8 iProduct; /* index of string that describes product */
  5738. + __u8 iSerialNumber; /* index of string containing device serial number */
  5739. + __u8 bNumConfigurations; /* number fo configurations */
  5740. +} __attribute__ ((packed)) device_desc_t;
  5741. +
  5742. +// --- Configuration Descriptor ------------
  5743. +
  5744. +typedef struct {
  5745. + DescriptorHeader;
  5746. + __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */
  5747. + __u8 bNumInterfaces; /* number of interfaces in this cfg */
  5748. + __u8 bConfigurationValue; /* used to uniquely ID this cfg */
  5749. + __u8 iConfiguration; /* index of string describing configuration */
  5750. + __u8 bmAttributes; /* bitmap of attributes for ths cfg */
  5751. + __u8 MaxPower; /* power draw in 2ma units */
  5752. +} __attribute__ ((packed)) config_desc_t;
  5753. +
  5754. +// bmAttributes:
  5755. +enum { USB_CONFIG_REMOTEWAKE=0x20, USB_CONFIG_SELFPOWERED=0x40,
  5756. + USB_CONFIG_BUSPOWERED=0x80 };
  5757. +// MaxPower:
  5758. +#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
  5759. +
  5760. +// --- Interface Descriptor ---------------
  5761. +
  5762. +typedef struct {
  5763. + DescriptorHeader;
  5764. + __u8 bInterfaceNumber; /* Index uniquely identfying this interface */
  5765. + __u8 bAlternateSetting; /* ids an alternate setting for this interface */
  5766. + __u8 bNumEndpoints; /* number of endpoints in this interface */
  5767. + __u8 bInterfaceClass; /* USB class info applying to this interface */
  5768. + __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */
  5769. + __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */
  5770. + __u8 iInterface; /* index of string describing interface */
  5771. +} __attribute__ ((packed)) intf_desc_t;
  5772. +
  5773. +// --- Endpoint Descriptor ---------------
  5774. +
  5775. +typedef struct {
  5776. + DescriptorHeader;
  5777. + __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
  5778. + __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
  5779. + __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */
  5780. + __u8 bInterval; /* polling interval for this ep in this cfg */
  5781. +} __attribute__ ((packed)) ep_desc_t;
  5782. +
  5783. +// bEndpointAddress:
  5784. +enum { USB_OUT= 0, USB_IN=1 };
  5785. +#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
  5786. +// bmAttributes:
  5787. +enum { USB_EP_CNTRL=0, USB_EP_BULK=2, USB_EP_INT=3 };
  5788. +
  5789. +// --- String Descriptor -------------------
  5790. +
  5791. +typedef struct {
  5792. + DescriptorHeader;
  5793. + __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */
  5794. +} __attribute__ ((packed)) string_desc_t;
  5795. +
  5796. +/*=======================================================
  5797. + * Handy helpers when working with above
  5798. + *
  5799. + */
  5800. +// these are x86-style 16 bit "words" ...
  5801. +#define make_word_c( w ) __constant_cpu_to_le16(w)
  5802. +#define make_word( w ) __cpu_to_le16(w)
  5803. +
  5804. +// descriptor types
  5805. +enum { USB_DESC_DEVICE=1, USB_DESC_CONFIG=2, USB_DESC_STRING=3,
  5806. + USB_DESC_INTERFACE=4, USB_DESC_ENDPOINT=5 };
  5807. +
  5808. +
  5809. +/*=======================================================
  5810. + * Default descriptor layout for SA-1100 and SA-1110 UDC
  5811. + */
  5812. +
  5813. +/* "config descriptor buffer" - that is, one config,
  5814. + ..one interface and 2 endpoints */
  5815. +struct cdb {
  5816. + config_desc_t cfg;
  5817. + intf_desc_t intf;
  5818. + ep_desc_t ep1;
  5819. + ep_desc_t ep2;
  5820. +} __attribute__ ((packed));
  5821. +
  5822. +
  5823. +/* all SA device descriptors */
  5824. +typedef struct {
  5825. + device_desc_t dev; /* device descriptor */
  5826. + struct cdb b; /* bundle of descriptors for this cfg */
  5827. +} __attribute__ ((packed)) desc_t;
  5828. +
  5829. +
  5830. +/*=======================================================
  5831. + * Descriptor API
  5832. + */
  5833. +
  5834. +/* Get the address of the statically allocated desc_t structure
  5835. + in the usb core driver. Clients can modify this between
  5836. + the time they call sa1100_usb_open() and sa1100_usb_start()
  5837. +*/
  5838. +desc_t *
  5839. +sa1100_usb_get_descriptor_ptr( void );
  5840. +
  5841. +
  5842. +/* Set a pointer to the string descriptor at "index". The driver
  5843. + ..has room for 8 string indicies internally. Index zero holds
  5844. + ..a LANGID code and is set to US English by default. Inidices
  5845. + ..1-7 are available for use in the config descriptors as client's
  5846. + ..see fit. This pointer is assumed to be good as long as the
  5847. + ..SA usb core is open (so statically allocate them). Returnes -EINVAL
  5848. + ..if index out of range */
  5849. +int sa1100_usb_set_string_descriptor( int index, string_desc_t * p );
  5850. +
  5851. +/* reverse of above */
  5852. +string_desc_t *
  5853. +sa1100_usb_get_string_descriptor( int index );
  5854. +
  5855. +/* kmalloc() a string descriptor and convert "p" to unicode in it */
  5856. +string_desc_t *
  5857. +sa1100_usb_kmalloc_string_descriptor( const char * p );
  5858. +
  5859. +
  5860. +
  5861. +
  5862. +
  5863. +
  5864. +#endif /* _SA1100_USB_H */
  5865. diff -urN linux-2.4.26/arch/arm/mach-sa1100/sa1111-ohci.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/sa1111-ohci.c
  5866. --- linux-2.4.26/arch/arm/mach-sa1100/sa1111-ohci.c 1970-01-01 01:00:00.000000000 +0100
  5867. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/sa1111-ohci.c 2004-01-14 21:32:24.000000000 +0000
  5868. @@ -0,0 +1,140 @@
  5869. +#include <linux/config.h>
  5870. +#include <linux/sched.h>
  5871. +#include <linux/pci.h>
  5872. +#include <linux/mm.h>
  5873. +
  5874. +#ifdef CONFIG_USB_OHCI
  5875. +
  5876. +/*
  5877. + * The SA-1111 errata says that the DMA hardware needs to be exercised
  5878. + * before the clocks are turned on to work properly. This code does
  5879. + * a tiny dma transfer to prime to hardware.
  5880. + *
  5881. + * What DMA errata? I've checked October 1999 and February 2001, both
  5882. + * of which do not mention such a bug, let alone any details of this
  5883. + * work-around.
  5884. + */
  5885. +static void __init sa1111_dma_setup(void)
  5886. +{
  5887. + dma_addr_t dma_buf;
  5888. + void * vbuf;
  5889. +
  5890. + /* DMA init & setup */
  5891. +
  5892. + /* WARNING: The SA-1111 L3 function is used as part of this
  5893. + * SA-1111 DMA errata workaround.
  5894. + *
  5895. + * N.B., When the L3 function is enabled, it uses GPIO_B<4:5>
  5896. + * and takes precedence over the PS/2 mouse and GPIO_B
  5897. + * functions. Refer to "Intel StrongARM SA-1111 Microprocessor
  5898. + * Companion Chip, Sect 10.2" for details. So this "fix" may
  5899. + * "break" support of either PS/2 mouse or GPIO_B if
  5900. + * precautions are not taken to avoid collisions in
  5901. + * configuration and use of these pins. AFAIK, no precautions
  5902. + * are taken at this time. So it is likely that the action
  5903. + * taken here may cause problems in PS/2 mouse and/or GPIO_B
  5904. + * pin use elsewhere.
  5905. + *
  5906. + * But wait, there's more... What we're doing here is
  5907. + * obviously altogether a bad idea. We're indiscrimanately bit
  5908. + * flipping config for a few different functions here which
  5909. + * are "owned" by other drivers. This needs to be handled
  5910. + * better than it is being done here at this time. */
  5911. +
  5912. + /* prime the dma engine with a tiny dma */
  5913. + SKPCR |= SKPCR_I2SCLKEN;
  5914. + SKAUD |= SKPCR_L3CLKEN | SKPCR_SCLKEN;
  5915. +
  5916. + SACR0 |= 0x00003305;
  5917. + SACR1 = 0x00000000;
  5918. +
  5919. + /*
  5920. + * We need memory below 1MB.
  5921. + * NOTE: consistent_alloc gives you some random virtual
  5922. + * address as its return value, and the DMA address via
  5923. + * the dma_addr_t pointer.
  5924. + */
  5925. + vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
  5926. +
  5927. + SADTSA = (unsigned long)dma_buf;
  5928. + SADTCA = 4;
  5929. +
  5930. + SADTCS |= 0x00000011;
  5931. + SKPCR |= SKPCR_DCLKEN;
  5932. +
  5933. + /* wait */
  5934. + udelay(100);
  5935. +
  5936. + /* clear reserved but, then disable SAC */
  5937. + SACR0 &= ~(0x00000002);
  5938. + SACR0 &= ~(0x00000001);
  5939. +
  5940. + /* toggle bit clock direction */
  5941. + SACR0 |= 0x00000004;
  5942. + SACR0 &= ~(0x00000004);
  5943. +
  5944. + SKAUD &= ~(SKPCR_L3CLKEN | SKPCR_SCLKEN);
  5945. +
  5946. + SKPCR &= ~SKPCR_I2SCLKEN;
  5947. +
  5948. + consistent_free(vbuf, 4, dma_buf);
  5949. +}
  5950. +
  5951. +/*
  5952. + * reset the SA-1111 usb controller and turn on it's clocks
  5953. + */
  5954. +int __init sa1111_ohci_hcd_init(void)
  5955. +{
  5956. + unsigned int usb_reset = 0;
  5957. +
  5958. + if (machine_is_xp860() ||
  5959. + machine_has_neponset() ||
  5960. + machine_is_pfs168() ||
  5961. + machine_is_badge4())
  5962. + usb_reset = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
  5963. +
  5964. + /*
  5965. + * turn on USB clocks
  5966. + */
  5967. + SKPCR |= SKPCR_UCLKEN;
  5968. + udelay(100);
  5969. +
  5970. + /*
  5971. + * Force USB reset
  5972. + */
  5973. + USB_RESET = USB_RESET_FORCEIFRESET;
  5974. + USB_RESET |= USB_RESET_FORCEHCRESET;
  5975. + udelay(100);
  5976. +
  5977. + /*
  5978. + * Take out of reset
  5979. + */
  5980. + USB_RESET = 0;
  5981. +
  5982. + /*
  5983. + * set power sense and control lines (this from the diags code)
  5984. + */
  5985. + USB_RESET = usb_reset;
  5986. +
  5987. + /*
  5988. + * Huh? This is a _read only_ register --rmk
  5989. + */
  5990. + USB_STATUS = 0;
  5991. +
  5992. + udelay(10);
  5993. +
  5994. + /*
  5995. + * compensate for dma bug
  5996. + */
  5997. + sa1111_dma_setup();
  5998. +
  5999. + return 0;
  6000. +}
  6001. +
  6002. +void sa1111_ohci_hcd_cleanup(void)
  6003. +{
  6004. + /* turn the USB clock off */
  6005. + SKPCR &= ~SKPCR_UCLKEN;
  6006. +}
  6007. +
  6008. +#endif /* CONFIG_USB_OHCI */
  6009. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb-char.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb-char.c
  6010. --- linux-2.4.26/arch/arm/mach-sa1100/usb-char.c 1970-01-01 01:00:00.000000000 +0100
  6011. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb-char.c 2004-01-14 21:32:24.000000000 +0000
  6012. @@ -0,0 +1,723 @@
  6013. +/*
  6014. + * (C) Copyright 2000-2001 Extenex Corporation
  6015. + *
  6016. + * This program is free software; you can redistribute it and/or modify
  6017. + * it under the terms of the GNU General Public License as published by
  6018. + * the Free Software Foundation; either version 2 of the License, or
  6019. + * (at your option) any later version.
  6020. + *
  6021. + * This program is distributed in the hope that it will be useful,
  6022. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6023. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6024. + * GNU General Public License for more details.
  6025. + *
  6026. + * You should have received a copy of the GNU General Public License
  6027. + * along with this program; if not, write to the Free Software
  6028. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  6029. + *
  6030. + * usb-char.c
  6031. + *
  6032. + * Miscellaneous character device interface for SA1100 USB function
  6033. + * driver.
  6034. + *
  6035. + * Background:
  6036. + * The SA1100 function driver ported from the Compaq Itsy project
  6037. + * has an interface, usb-eth.c, to feed network packets over the
  6038. + * usb wire and into the Linux TCP/IP stack.
  6039. + *
  6040. + * This file replaces that one with a simple character device
  6041. + * interface that allows unstructured "byte pipe" style reads and
  6042. + * writes over the USB bulk endpoints by userspace programs.
  6043. + *
  6044. + * A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
  6045. + * when set, (the default) causes the ethernet interface to be used.
  6046. + * When not set, this more pedestrian character interface is linked
  6047. + * in instead.
  6048. + *
  6049. + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
  6050. + *
  6051. + * ward.willats@extenex.com
  6052. + *
  6053. + * To do:
  6054. + * - Can't dma into ring buffer directly with pci_map/unmap usb_recv
  6055. + * uses and get bytes out at the same time DMA is going on. Investigate:
  6056. + * a) changing usb_recv to use alloc_consistent() at client request; or
  6057. + * b) non-ring-buffer based data structures. In the meantime, I am using
  6058. + * a bounce buffer. Simple, but wasteful.
  6059. + */
  6060. +
  6061. +#include <linux/module.h>
  6062. +#include <linux/config.h>
  6063. +#include <linux/miscdevice.h>
  6064. +#include <linux/slab.h>
  6065. +#include <linux/init.h>
  6066. +#include <linux/cache.h>
  6067. +#include <linux/poll.h>
  6068. +#include <linux/circ_buf.h>
  6069. +#include <linux/timer.h>
  6070. +
  6071. +#include <asm/io.h>
  6072. +#include <asm/semaphore.h>
  6073. +#include <asm/proc/page.h>
  6074. +#include <asm/mach-types.h>
  6075. +
  6076. +#include "usb-char.h"
  6077. +#include "sa1100_usb.h"
  6078. +
  6079. +
  6080. +
  6081. +//////////////////////////////////////////////////////////////////////////////
  6082. +// Driver Options
  6083. +//////////////////////////////////////////////////////////////////////////////
  6084. +
  6085. +#define VERSION "0.4"
  6086. +
  6087. +
  6088. +#define VERBOSITY 1
  6089. +
  6090. +#if VERBOSITY
  6091. +# define PRINTK(x, a...) printk (x, ## a)
  6092. +#else
  6093. +# define PRINTK(x, a...) /**/
  6094. +#endif
  6095. +
  6096. +//////////////////////////////////////////////////////////////////////////////
  6097. +// Globals - Macros - Enums - Structures
  6098. +//////////////////////////////////////////////////////////////////////////////
  6099. +#ifndef MIN
  6100. +#define MIN( a, b ) ((a)<(b)?(a):(b))
  6101. +#endif
  6102. +
  6103. +typedef int bool; enum { false = 0, true = 1 };
  6104. +
  6105. +static const char pszMe[] = "usbchr: ";
  6106. +
  6107. +static wait_queue_head_t wq_read;
  6108. +static wait_queue_head_t wq_write;
  6109. +static wait_queue_head_t wq_poll;
  6110. +
  6111. +/* Serialze multiple writers onto the transmit hardware
  6112. +.. since we sleep the writer during transmit to stay in
  6113. +.. sync. (Multiple writers don't make much sense, but..) */
  6114. +static DECLARE_MUTEX( xmit_sem );
  6115. +
  6116. +// size of usb DATA0/1 packets. 64 is standard maximum
  6117. +// for bulk transport, though most hosts seem to be able
  6118. +// to handle larger.
  6119. +#define TX_PACKET_SIZE 64
  6120. +#define RX_PACKET_SIZE 64
  6121. +#define RBUF_SIZE (4*PAGE_SIZE)
  6122. +
  6123. +static struct wcirc_buf {
  6124. + char *buf;
  6125. + int in;
  6126. + int out;
  6127. +} rx_ring = { NULL, 0, 0 };
  6128. +
  6129. +static struct {
  6130. + unsigned long cnt_rx_complete;
  6131. + unsigned long cnt_rx_errors;
  6132. + unsigned long bytes_rx;
  6133. + unsigned long cnt_tx_timeouts;
  6134. + unsigned long cnt_tx_errors;
  6135. + unsigned long bytes_tx;
  6136. +} charstats;
  6137. +
  6138. +
  6139. +static char * tx_buf = NULL;
  6140. +static char * packet_buffer = NULL;
  6141. +static int sending = 0;
  6142. +static int usb_ref_count = 0;
  6143. +static int last_tx_result = 0;
  6144. +static int last_rx_result = 0;
  6145. +static int last_tx_size = 0;
  6146. +static struct timer_list tx_timer;
  6147. +
  6148. +//////////////////////////////////////////////////////////////////////////////
  6149. +// Prototypes
  6150. +//////////////////////////////////////////////////////////////////////////////
  6151. +static char * what_the_f( int e );
  6152. +static void free_txrx_buffers( void );
  6153. +static void twiddle_descriptors( void );
  6154. +static void free_string_descriptors( void ) ;
  6155. +static int usbc_open( struct inode *pInode, struct file *pFile );
  6156. +static void rx_done_callback_packet_buffer( int flag, int size );
  6157. +
  6158. +static void tx_timeout( unsigned long );
  6159. +static void tx_done_callback( int flag, int size );
  6160. +
  6161. +static ssize_t usbc_read( struct file *, char *, size_t, loff_t * );
  6162. +static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * );
  6163. +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
  6164. +static int usbc_ioctl( struct inode *pInode, struct file *pFile,
  6165. + unsigned int nCmd, unsigned long argument );
  6166. +static int usbc_close( struct inode *pInode, struct file *pFile );
  6167. +
  6168. +#ifdef CONFIG_SA1100_EXTENEX1
  6169. +static void extenex_configured_notify_proc( void );
  6170. +#endif
  6171. +//////////////////////////////////////////////////////////////////////////////
  6172. +// Private Helpers
  6173. +//////////////////////////////////////////////////////////////////////////////
  6174. +
  6175. +static char * what_the_f( int e )
  6176. +{
  6177. + char * p;
  6178. + switch( e ) {
  6179. + case 0:
  6180. + p = "noErr";
  6181. + break;
  6182. + case -ENODEV:
  6183. + p = "ENODEV - usb not in config state";
  6184. + break;
  6185. + case -EBUSY:
  6186. + p = "EBUSY - another request on the hardware";
  6187. + break;
  6188. + case -EAGAIN:
  6189. + p = "EAGAIN";
  6190. + break;
  6191. + case -EINTR:
  6192. + p = "EINTR - interrupted\n";
  6193. + break;
  6194. + case -EPIPE:
  6195. + p = "EPIPE - zero length xfer\n";
  6196. + break;
  6197. + default:
  6198. + p = "????";
  6199. + break;
  6200. + }
  6201. + return p;
  6202. +}
  6203. +
  6204. +static void free_txrx_buffers( void )
  6205. +{
  6206. + if ( rx_ring.buf != NULL ) {
  6207. + kfree( rx_ring.buf );
  6208. + rx_ring.buf = NULL;
  6209. + }
  6210. + if ( packet_buffer != NULL ) {
  6211. + kfree( packet_buffer );
  6212. + packet_buffer = NULL;
  6213. + }
  6214. + if ( tx_buf != NULL ) {
  6215. + kfree( tx_buf );
  6216. + tx_buf = NULL;
  6217. + }
  6218. +}
  6219. +
  6220. +/* twiddle_descriptors()
  6221. + * It is between open() and start(). Setup descriptors.
  6222. + */
  6223. +static void twiddle_descriptors( void )
  6224. +{
  6225. + desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
  6226. + string_desc_t * pString;
  6227. +
  6228. + pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
  6229. + pDesc->b.ep1.bmAttributes = USB_EP_BULK;
  6230. + pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
  6231. + pDesc->b.ep2.bmAttributes = USB_EP_BULK;
  6232. +
  6233. + if ( machine_is_extenex1() ) {
  6234. +#ifdef CONFIG_SA1100_EXTENEX1
  6235. + pDesc->dev.idVendor = make_word_c( 0xC9F );
  6236. + pDesc->dev.idProduct = 1;
  6237. + pDesc->dev.bcdDevice = make_word_c( 0x0001 );
  6238. + pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
  6239. + pDesc->b.cfg.MaxPower = 0;
  6240. +
  6241. + pString = sa1100_usb_kmalloc_string_descriptor( "Extenex" );
  6242. + if ( pString ) {
  6243. + sa1100_usb_set_string_descriptor( 1, pString );
  6244. + pDesc->dev.iManufacturer = 1;
  6245. + }
  6246. +
  6247. + pString = sa1100_usb_kmalloc_string_descriptor( "Handheld Theater" );
  6248. + if ( pString ) {
  6249. + sa1100_usb_set_string_descriptor( 2, pString );
  6250. + pDesc->dev.iProduct = 2;
  6251. + }
  6252. +
  6253. + pString = sa1100_usb_kmalloc_string_descriptor( "00000000" );
  6254. + if ( pString ) {
  6255. + sa1100_usb_set_string_descriptor( 3, pString );
  6256. + pDesc->dev.iSerialNumber = 3;
  6257. + }
  6258. +
  6259. + pString = sa1100_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
  6260. + if ( pString ) {
  6261. + sa1100_usb_set_string_descriptor( 4, pString );
  6262. + pDesc->b.intf.iInterface = 4;
  6263. + }
  6264. + sa1100_set_configured_callback( extenex_configured_notify_proc );
  6265. +#endif
  6266. + }
  6267. +}
  6268. +
  6269. +static void free_string_descriptors( void )
  6270. +{
  6271. + if ( machine_is_extenex1() ) {
  6272. + string_desc_t * pString;
  6273. + int i;
  6274. + for( i = 1 ; i <= 4 ; i++ ) {
  6275. + pString = sa1100_usb_get_string_descriptor( i );
  6276. + if ( pString )
  6277. + kfree( pString );
  6278. + }
  6279. + }
  6280. +}
  6281. +
  6282. +//////////////////////////////////////////////////////////////////////////////
  6283. +// ASYNCHRONOUS
  6284. +//////////////////////////////////////////////////////////////////////////////
  6285. +static void kick_start_rx( void )
  6286. +{
  6287. + if ( usb_ref_count ) {
  6288. + int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
  6289. + if ( total_space >= RX_PACKET_SIZE ) {
  6290. + sa1100_usb_recv( packet_buffer,
  6291. + RX_PACKET_SIZE,
  6292. + rx_done_callback_packet_buffer
  6293. + );
  6294. + }
  6295. + }
  6296. +}
  6297. +/*
  6298. + * rx_done_callback_packet_buffer()
  6299. + * We have completed a DMA xfer into the temp packet buffer.
  6300. + * Move to ring.
  6301. + *
  6302. + * flag values:
  6303. + * on init, -EAGAIN
  6304. + * on reset, -EINTR
  6305. + * on RPE, -EIO
  6306. + * on short packet -EPIPE
  6307. + */
  6308. +static void
  6309. +rx_done_callback_packet_buffer( int flag, int size )
  6310. +{
  6311. + charstats.cnt_rx_complete++;
  6312. +
  6313. + if ( flag == 0 || flag == -EPIPE ) {
  6314. + size_t n;
  6315. +
  6316. + charstats.bytes_rx += size;
  6317. +
  6318. + n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
  6319. + n = MIN( n, size );
  6320. + size -= n;
  6321. +
  6322. + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
  6323. + rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
  6324. + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
  6325. + rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
  6326. +
  6327. + wake_up_interruptible( &wq_read );
  6328. + wake_up_interruptible( &wq_poll );
  6329. +
  6330. + last_rx_result = 0;
  6331. +
  6332. + kick_start_rx();
  6333. +
  6334. + } else if ( flag != -EAGAIN ) {
  6335. + charstats.cnt_rx_errors++;
  6336. + last_rx_result = flag;
  6337. + wake_up_interruptible( &wq_read );
  6338. + wake_up_interruptible( &wq_poll );
  6339. + }
  6340. + else /* init, start a read */
  6341. + kick_start_rx();
  6342. +}
  6343. +
  6344. +
  6345. +static void tx_timeout( unsigned long unused )
  6346. +{
  6347. + printk( "%stx timeout\n", pszMe );
  6348. + sa1100_usb_send_reset();
  6349. + charstats.cnt_tx_timeouts++;
  6350. +}
  6351. +
  6352. +
  6353. +// on init, -EAGAIN
  6354. +// on reset, -EINTR
  6355. +// on TPE, -EIO
  6356. +static void tx_done_callback( int flags, int size )
  6357. +{
  6358. + if ( flags == 0 )
  6359. + charstats.bytes_tx += size;
  6360. + else
  6361. + charstats.cnt_tx_errors++;
  6362. + last_tx_size = size;
  6363. + last_tx_result = flags;
  6364. + sending = 0;
  6365. + wake_up_interruptible( &wq_write );
  6366. + wake_up_interruptible( &wq_poll );
  6367. +}
  6368. +
  6369. +
  6370. +//////////////////////////////////////////////////////////////////////////////
  6371. +// Workers
  6372. +//////////////////////////////////////////////////////////////////////////////
  6373. +
  6374. +static int usbc_open( struct inode *pInode, struct file *pFile )
  6375. +{
  6376. + int retval = 0;
  6377. +
  6378. + PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
  6379. +
  6380. + /* start usb core */
  6381. + retval = sa1100_usb_open( "usb-char" );
  6382. + if ( retval ) return retval;
  6383. +
  6384. + /* allocate memory */
  6385. + if ( usb_ref_count == 0 ) {
  6386. + tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
  6387. + if ( tx_buf == NULL ) {
  6388. + printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
  6389. + goto malloc_fail;
  6390. + }
  6391. + rx_ring.buf =
  6392. + (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
  6393. +
  6394. + if ( rx_ring.buf == NULL ) {
  6395. + printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
  6396. + goto malloc_fail;
  6397. + }
  6398. +
  6399. + packet_buffer =
  6400. + (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
  6401. +
  6402. + if ( packet_buffer == NULL ) {
  6403. + printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
  6404. + goto malloc_fail;
  6405. + }
  6406. + rx_ring.in = rx_ring.out = 0;
  6407. + memset( &charstats, 0, sizeof( charstats ) );
  6408. + sending = 0;
  6409. + last_tx_result = 0;
  6410. + last_tx_size = 0;
  6411. + }
  6412. +
  6413. + /* modify default descriptors */
  6414. + twiddle_descriptors();
  6415. +
  6416. + retval = sa1100_usb_start();
  6417. + if ( retval ) {
  6418. + printk( "%sAGHH! Could not USB core\n", pszMe );
  6419. + free_txrx_buffers();
  6420. + return retval;
  6421. + }
  6422. + usb_ref_count++; /* must do _before_ kick_start() */
  6423. + MOD_INC_USE_COUNT;
  6424. + kick_start_rx();
  6425. + return 0;
  6426. +
  6427. + malloc_fail:
  6428. + free_txrx_buffers();
  6429. + return -ENOMEM;
  6430. +}
  6431. +
  6432. +/*
  6433. + * Read endpoint. Note that you can issue a read to an
  6434. + * unconfigured endpoint. Eventually, the host may come along
  6435. + * and configure underneath this module and data will appear.
  6436. + */
  6437. +static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
  6438. + size_t stCount, loff_t *pPos )
  6439. +{
  6440. + ssize_t retval;
  6441. + int flags;
  6442. + DECLARE_WAITQUEUE( wait, current );
  6443. +
  6444. + PRINTK( KERN_DEBUG "%sread()\n", pszMe );
  6445. +
  6446. + local_irq_save( flags );
  6447. + if ( last_rx_result == 0 ) {
  6448. + local_irq_restore( flags );
  6449. + } else { /* an error happended and receiver is paused */
  6450. + local_irq_restore( flags );
  6451. + last_rx_result = 0;
  6452. + kick_start_rx();
  6453. + }
  6454. +
  6455. + add_wait_queue( &wq_read, &wait );
  6456. + while( 1 ) {
  6457. + ssize_t bytes_avail;
  6458. + ssize_t bytes_to_end;
  6459. +
  6460. + set_current_state( TASK_INTERRUPTIBLE );
  6461. +
  6462. + /* snap ring buf state */
  6463. + local_irq_save( flags );
  6464. + bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
  6465. + bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
  6466. + local_irq_restore( flags );
  6467. +
  6468. + if ( bytes_avail != 0 ) {
  6469. + ssize_t bytes_to_move = MIN( stCount, bytes_avail );
  6470. + retval = 0; // will be bytes transfered
  6471. + if ( bytes_to_move != 0 ) {
  6472. + size_t n = MIN( bytes_to_end, bytes_to_move );
  6473. + if ( copy_to_user( pUserBuffer,
  6474. + &rx_ring.buf[ rx_ring.out ],
  6475. + n ) ) {
  6476. + retval = -EFAULT;
  6477. + break;
  6478. + }
  6479. + bytes_to_move -= n;
  6480. + retval += n;
  6481. + // might go 1 char off end, so wrap
  6482. + rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
  6483. + if ( copy_to_user( pUserBuffer + n,
  6484. + &rx_ring.buf[ rx_ring.out ],
  6485. + bytes_to_move )
  6486. + ) {
  6487. + retval = -EFAULT;
  6488. + break;
  6489. + }
  6490. + rx_ring.out += bytes_to_move; // cannot wrap
  6491. + retval += bytes_to_move;
  6492. + kick_start_rx();
  6493. + }
  6494. + break;
  6495. + }
  6496. + else if ( last_rx_result ) {
  6497. + retval = last_rx_result;
  6498. + break;
  6499. + }
  6500. + else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep
  6501. + retval = -EAGAIN;
  6502. + break;
  6503. + }
  6504. + else if ( signal_pending( current ) ) { // no data, can sleep, but signal
  6505. + retval = -ERESTARTSYS;
  6506. + break;
  6507. + }
  6508. + schedule(); // no data, can sleep
  6509. + }
  6510. + set_current_state( TASK_RUNNING );
  6511. + remove_wait_queue( &wq_read, &wait );
  6512. +
  6513. + if ( retval < 0 )
  6514. + printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
  6515. + return retval;
  6516. +}
  6517. +
  6518. +/*
  6519. + * Write endpoint. This routine attempts to break the passed in buffer
  6520. + * into usb DATA0/1 packet size chunks and send them to the host.
  6521. + * (The lower-level driver tries to do this too, but easier for us
  6522. + * to manage things here.)
  6523. + *
  6524. + * We are at the mercy of the host here, in that it must send an IN
  6525. + * token to us to pull this data back, so hopefully some higher level
  6526. + * protocol is expecting traffic to flow in that direction so the host
  6527. + * is actually polling us. To guard against hangs, a 5 second timeout
  6528. + * is used.
  6529. + *
  6530. + * This routine takes some care to only report bytes sent that have
  6531. + * actually made it across the wire. Thus we try to stay in lockstep
  6532. + * with the completion routine and only have one packet on the xmit
  6533. + * hardware at a time. Multiple simultaneous writers will get
  6534. + * "undefined" results.
  6535. + *
  6536. + */
  6537. +static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,
  6538. + size_t stCount, loff_t *pPos )
  6539. +{
  6540. + ssize_t retval = 0;
  6541. + ssize_t stSent = 0;
  6542. +
  6543. + DECLARE_WAITQUEUE( wait, current );
  6544. +
  6545. + PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
  6546. +
  6547. + down( &xmit_sem ); // only one thread onto the hardware at a time
  6548. +
  6549. + while( stCount != 0 && retval == 0 ) {
  6550. + int nThisTime = MIN( TX_PACKET_SIZE, stCount );
  6551. + copy_from_user( tx_buf, pUserBuffer, nThisTime );
  6552. + sending = nThisTime;
  6553. + retval = sa1100_usb_send( tx_buf, nThisTime, tx_done_callback );
  6554. + if ( retval < 0 ) {
  6555. + char * p = what_the_f( retval );
  6556. + printk( "%sCould not queue xmission. rc=%d - %s\n",
  6557. + pszMe, retval, p );
  6558. + sending = 0;
  6559. + break;
  6560. + }
  6561. + /* now have something on the diving board */
  6562. + add_wait_queue( &wq_write, &wait );
  6563. + tx_timer.expires = jiffies + ( HZ * 5 );
  6564. + add_timer( &tx_timer );
  6565. + while( 1 ) {
  6566. + set_current_state( TASK_INTERRUPTIBLE );
  6567. + if ( sending == 0 ) { /* it jumped into the pool */
  6568. + del_timer( &tx_timer );
  6569. + retval = last_tx_result;
  6570. + if ( retval == 0 ) {
  6571. + stSent += last_tx_size;
  6572. + pUserBuffer += last_tx_size;
  6573. + stCount -= last_tx_size;
  6574. + }
  6575. + else
  6576. + printk( "%sxmission error rc=%d - %s\n",
  6577. + pszMe, retval, what_the_f(retval) );
  6578. + break;
  6579. + }
  6580. + else if ( signal_pending( current ) ) {
  6581. + del_timer( &tx_timer );
  6582. + printk( "%ssignal\n", pszMe );
  6583. + retval = -ERESTARTSYS;
  6584. + break;
  6585. + }
  6586. + schedule();
  6587. + }
  6588. + set_current_state( TASK_RUNNING );
  6589. + remove_wait_queue( &wq_write, &wait );
  6590. + }
  6591. +
  6592. + up( &xmit_sem );
  6593. +
  6594. + if ( 0 == retval )
  6595. + retval = stSent;
  6596. + return retval;
  6597. +}
  6598. +
  6599. +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
  6600. +{
  6601. + unsigned int retval = 0;
  6602. +
  6603. + PRINTK( KERN_DEBUG "%poll()\n", pszMe );
  6604. +
  6605. + poll_wait( pFile, &wq_poll, pWait );
  6606. +
  6607. + if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
  6608. + retval |= POLLIN | POLLRDNORM;
  6609. + if ( sa1100_usb_xmitter_avail() )
  6610. + retval |= POLLOUT | POLLWRNORM;
  6611. + return retval;
  6612. +}
  6613. +
  6614. +static int usbc_ioctl( struct inode *pInode, struct file *pFile,
  6615. + unsigned int nCmd, unsigned long argument )
  6616. +{
  6617. + int retval = 0;
  6618. +
  6619. + switch( nCmd ) {
  6620. +
  6621. + case USBC_IOC_FLUSH_RECEIVER:
  6622. + sa1100_usb_recv_reset();
  6623. + rx_ring.in = rx_ring.out = 0;
  6624. + break;
  6625. +
  6626. + case USBC_IOC_FLUSH_TRANSMITTER:
  6627. + sa1100_usb_send_reset();
  6628. + break;
  6629. +
  6630. + case USBC_IOC_FLUSH_ALL:
  6631. + sa1100_usb_recv_reset();
  6632. + rx_ring.in = rx_ring.out = 0;
  6633. + sa1100_usb_send_reset();
  6634. + break;
  6635. +
  6636. + default:
  6637. + retval = -ENOIOCTLCMD;
  6638. + break;
  6639. +
  6640. + }
  6641. + return retval;
  6642. +}
  6643. +
  6644. +
  6645. +static int usbc_close( struct inode *pInode, struct file * pFile )
  6646. +{
  6647. + PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
  6648. + if ( --usb_ref_count == 0 ) {
  6649. + down( &xmit_sem );
  6650. + sa1100_usb_stop();
  6651. + free_txrx_buffers();
  6652. + free_string_descriptors();
  6653. + del_timer( &tx_timer );
  6654. + sa1100_usb_close();
  6655. + up( &xmit_sem );
  6656. + }
  6657. + MOD_DEC_USE_COUNT;
  6658. + return 0;
  6659. +}
  6660. +
  6661. +#ifdef CONFIG_SA1100_EXTENEX1
  6662. +#include "../../../drivers/char/ex_gpio.h"
  6663. +void extenex_configured_notify_proc( void )
  6664. +{
  6665. + if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
  6666. + printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
  6667. +}
  6668. +#endif
  6669. +//////////////////////////////////////////////////////////////////////////////
  6670. +// Initialization
  6671. +//////////////////////////////////////////////////////////////////////////////
  6672. +
  6673. +static struct file_operations usbc_fops = {
  6674. + owner: THIS_MODULE,
  6675. + open: usbc_open,
  6676. + read: usbc_read,
  6677. + write: usbc_write,
  6678. + poll: usbc_poll,
  6679. + ioctl: usbc_ioctl,
  6680. + release: usbc_close,
  6681. +};
  6682. +
  6683. +static struct miscdevice usbc_misc_device = {
  6684. + USBC_MINOR, "usb_char", &usbc_fops
  6685. +};
  6686. +
  6687. +/*
  6688. + * usbc_init()
  6689. + */
  6690. +
  6691. +int __init usbc_init( void )
  6692. +{
  6693. + int rc;
  6694. +
  6695. +#if !defined( CONFIG_ARCH_SA1100 )
  6696. + return -ENODEV;
  6697. +#endif
  6698. +
  6699. + if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
  6700. + printk( KERN_WARNING "%sCould not register device 10, "
  6701. + "%d. (%d)\n", pszMe, USBC_MINOR, rc );
  6702. + return -EBUSY;
  6703. + }
  6704. +
  6705. + // initialize wait queues
  6706. + init_waitqueue_head( &wq_read );
  6707. + init_waitqueue_head( &wq_write );
  6708. + init_waitqueue_head( &wq_poll );
  6709. +
  6710. + // initialize tx timeout timer
  6711. + init_timer( &tx_timer );
  6712. + tx_timer.function = tx_timeout;
  6713. +
  6714. + printk( KERN_INFO "USB Function Character Driver Interface"
  6715. + " - %s, (C) 2001, Extenex Corp.\n", VERSION
  6716. + );
  6717. +
  6718. + return rc;
  6719. +}
  6720. +
  6721. +void __exit usbc_exit( void )
  6722. +{
  6723. +}
  6724. +
  6725. +EXPORT_NO_SYMBOLS;
  6726. +
  6727. +module_init(usbc_init);
  6728. +module_exit(usbc_exit);
  6729. +
  6730. +
  6731. +
  6732. +// end: usb-char.c
  6733. +
  6734. +
  6735. +
  6736. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb-char.h linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb-char.h
  6737. --- linux-2.4.26/arch/arm/mach-sa1100/usb-char.h 1970-01-01 01:00:00.000000000 +0100
  6738. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb-char.h 2004-01-14 21:32:24.000000000 +0000
  6739. @@ -0,0 +1,34 @@
  6740. +/*
  6741. + * Copyright (C) 2001 Extenex Corporation
  6742. + *
  6743. + * usb-char.h
  6744. + *
  6745. + * Character device emulation client for SA-1100 client usb core.
  6746. + *
  6747. + *
  6748. + *
  6749. + */
  6750. +#ifndef _USB_CHAR_H
  6751. +#define _USB_CHAR_H
  6752. +
  6753. +#define USBC_MAJOR 10 /* miscellaneous character device */
  6754. +#define USBC_MINOR 240 /* in the "reserved for local use" range */
  6755. +
  6756. +#define USBC_MAGIC 0x8E
  6757. +
  6758. +/* zap everything in receive ring buffer */
  6759. +#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 )
  6760. +
  6761. +/* reset transmitter */
  6762. +#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
  6763. +
  6764. +/* do both of above */
  6765. +#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 )
  6766. +
  6767. +
  6768. +
  6769. +
  6770. +
  6771. +
  6772. +#endif /* _USB_CHAR_H */
  6773. +
  6774. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb-eth.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb-eth.c
  6775. --- linux-2.4.26/arch/arm/mach-sa1100/usb-eth.c 1970-01-01 01:00:00.000000000 +0100
  6776. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb-eth.c 2004-01-14 21:32:24.000000000 +0000
  6777. @@ -0,0 +1,447 @@
  6778. + /*
  6779. + * Ethernet driver for the SA1100 USB client function
  6780. + * Copyright (c) 2001 by Nicolas Pitre
  6781. + *
  6782. + * This code was loosely inspired by the original initial ethernet test driver
  6783. + * Copyright (c) Compaq Computer Corporation, 1999
  6784. + *
  6785. + * This program is free software; you can redistribute it and/or modify
  6786. + * it under the terms of the GNU General Public License version 2 as
  6787. + * published by the Free Software Foundation.
  6788. + *
  6789. + * This is still work in progress...
  6790. + *
  6791. + * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
  6792. + * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
  6793. + * Now, since we do not know what size of packet we are receiving
  6794. + * last usb packet in sequence will always be less than max packet
  6795. + * receive endpoint can accept.
  6796. + * Now the only way to check correct start of frame is to compare
  6797. + * MAC address. Also now we are stalling on each receive error.
  6798. + *
  6799. + * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
  6800. + * aligned buffer, but this breaks IP code (unaligned access).
  6801. + *
  6802. + * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
  6803. + * they are disabled now.
  6804. + *
  6805. + * 03/06/2001 - Readded "zerocopy" receive path (tunable).
  6806. + *
  6807. + */
  6808. +
  6809. +// Define DMA_NO_COPY if you want data to arrive directly into the
  6810. +// receive network buffers, instead of arriving into bounce buffer
  6811. +// and then get copied to network buffer.
  6812. +// This does not work correctly right now.
  6813. +#undef DMA_NO_COPY
  6814. +
  6815. +#include <linux/module.h>
  6816. +#include <linux/init.h>
  6817. +#include <linux/sched.h>
  6818. +#include <linux/kernel.h>
  6819. +#include <linux/errno.h>
  6820. +#include <linux/timer.h>
  6821. +
  6822. +#include <linux/netdevice.h>
  6823. +#include <linux/etherdevice.h>
  6824. +#include <linux/skbuff.h>
  6825. +#include <linux/random.h>
  6826. +
  6827. +#include "sa1100_usb.h"
  6828. +
  6829. +
  6830. +#define ETHERNET_VENDOR_ID 0x49f
  6831. +#define ETHERNET_PRODUCT_ID 0x505A
  6832. +#define MAX_PACKET 32768
  6833. +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
  6834. +
  6835. +// Should be global, so that insmod can change these
  6836. +int usb_rsize=64;
  6837. +int usb_wsize=64;
  6838. +
  6839. +static struct usbe_info_t {
  6840. + struct net_device *dev;
  6841. + u16 packet_id;
  6842. + struct net_device_stats stats;
  6843. +} usbe_info;
  6844. +
  6845. +static char usb_eth_name[16] = "usbf";
  6846. +static struct net_device usb_eth_device;
  6847. +static struct sk_buff *cur_tx_skb, *next_tx_skb;
  6848. +static struct sk_buff *cur_rx_skb, *next_rx_skb;
  6849. +static volatile int terminating;
  6850. +#ifndef DMA_NO_COPY
  6851. +static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
  6852. +#endif
  6853. +
  6854. +static int usb_change_mtu (struct net_device *net, int new_mtu)
  6855. +{
  6856. + if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
  6857. + return -EINVAL;
  6858. + // no second zero-length packet read wanted after mtu-sized packets
  6859. + if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
  6860. + return -EDOM;
  6861. +
  6862. + net->mtu = new_mtu;
  6863. + return 0;
  6864. +}
  6865. +
  6866. +static struct sk_buff *
  6867. +usb_new_recv_skb(void)
  6868. +{
  6869. + struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
  6870. +
  6871. + if (skb) {
  6872. + skb_reserve(skb, 2);
  6873. + }
  6874. + return skb;
  6875. +}
  6876. +
  6877. +static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
  6878. +static void
  6879. +usb_recv_callback(int flag, int size)
  6880. +{
  6881. + struct sk_buff *skb;
  6882. +
  6883. + if (terminating)
  6884. + return;
  6885. +
  6886. + skb = cur_rx_skb;
  6887. +
  6888. + /* flag validation */
  6889. + if (flag == 0) {
  6890. + if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
  6891. + usbe_info.stats.rx_over_errors++;
  6892. + goto error;
  6893. + }
  6894. +#ifndef DMA_NO_COPY
  6895. + memcpy(skb->tail,dmabuf,size);
  6896. +#endif
  6897. + skb_put(skb, size);
  6898. + } else {
  6899. + if (flag == -EIO) {
  6900. + usbe_info.stats.rx_errors++;
  6901. + }
  6902. + goto error;
  6903. + }
  6904. +
  6905. + /* validate packet length */
  6906. + if (size == usb_rsize ) {
  6907. + /* packet not complete yet */
  6908. + skb = NULL;
  6909. + }
  6910. +
  6911. + /*
  6912. + * At this point skb is non null if we have a complete packet.
  6913. + * If so take a fresh skb right away and restart USB receive without
  6914. + * further delays, then process the packet. Otherwise resume USB
  6915. + * receive on the current skb and exit.
  6916. + */
  6917. +
  6918. + if (skb)
  6919. + cur_rx_skb = next_rx_skb;
  6920. +#ifndef DMA_NO_COPY
  6921. + sa1100_usb_recv(dmabuf, usb_rsize,
  6922. + usb_recv_callback);
  6923. +#else
  6924. + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
  6925. + usb_recv_callback);
  6926. +#endif
  6927. + if (!skb)
  6928. + return;
  6929. +
  6930. + next_rx_skb = usb_new_recv_skb();
  6931. + if (!next_rx_skb) {
  6932. + /*
  6933. + * We can't aford loosing buffer space...
  6934. + * So we drop the current packet and recycle its skb.
  6935. + */
  6936. + printk("%s: can't allocate new skb\n", __FUNCTION__);
  6937. + usbe_info.stats.rx_dropped++;
  6938. + skb_trim(skb, 0);
  6939. + next_rx_skb = skb;
  6940. + return;
  6941. + }
  6942. + if ( skb->len >= sizeof(struct ethhdr)) {
  6943. + if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
  6944. + // This frame is not for us. nor it is broadcast
  6945. + usbe_info.stats.rx_frame_errors++;
  6946. + kfree_skb(skb);
  6947. + goto error;
  6948. + }
  6949. + }
  6950. +
  6951. + if (skb->len) {
  6952. + int status;
  6953. +// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
  6954. +
  6955. + skb->dev = &usb_eth_device;
  6956. + skb->protocol = eth_type_trans (skb, &usb_eth_device);
  6957. + usbe_info.stats.rx_packets++;
  6958. + usbe_info.stats.rx_bytes += skb->len;
  6959. + skb->ip_summed = CHECKSUM_NONE;
  6960. + status = netif_rx (skb);
  6961. + if (status != NET_RX_SUCCESS)
  6962. + printk("netif_rx failed with code %d\n",status);
  6963. + } else {
  6964. +error:
  6965. + /*
  6966. + * Error due to HW addr mismatch, or IO error.
  6967. + * Recycle the current skb and reset USB reception.
  6968. + */
  6969. + skb_trim(cur_rx_skb, 0);
  6970. +// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
  6971. +#ifndef DMA_NO_COPY
  6972. + sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
  6973. +#else
  6974. + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
  6975. +#endif
  6976. + }
  6977. +}
  6978. +
  6979. +
  6980. +static void
  6981. +usb_send_callback(int flag, int size)
  6982. +{
  6983. + struct net_device *dev = usbe_info.dev;
  6984. + struct net_device_stats *stats;
  6985. + struct sk_buff *skb=cur_tx_skb;
  6986. + int ret;
  6987. +
  6988. + if (terminating)
  6989. + return;
  6990. +
  6991. + stats = &usbe_info.stats;
  6992. + switch (flag) {
  6993. + case 0:
  6994. + stats->tx_packets++;
  6995. + stats->tx_bytes += size;
  6996. + break;
  6997. + case -EIO:
  6998. + stats->tx_errors++;
  6999. + break;
  7000. + default:
  7001. + stats->tx_dropped++;
  7002. + break;
  7003. + }
  7004. +
  7005. + cur_tx_skb = next_tx_skb;
  7006. + next_tx_skb = NULL;
  7007. + dev_kfree_skb_irq(skb);
  7008. + if (!cur_tx_skb)
  7009. + return;
  7010. +
  7011. + dev->trans_start = jiffies;
  7012. + ret = sa1100_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
  7013. + if (ret) {
  7014. + /* If the USB core can't accept the packet, we drop it. */
  7015. + dev_kfree_skb_irq(cur_tx_skb);
  7016. + cur_tx_skb = NULL;
  7017. + usbe_info.stats.tx_carrier_errors++;
  7018. + }
  7019. + netif_wake_queue(dev);
  7020. +}
  7021. +
  7022. +static int
  7023. +usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
  7024. +{
  7025. + int ret;
  7026. + unsigned long flags;
  7027. +
  7028. + if (next_tx_skb) {
  7029. + printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
  7030. + return 1;
  7031. + }
  7032. +
  7033. + if (skb_shared (skb)) {
  7034. + struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC);
  7035. + if (!skb2) {
  7036. + usbe_info.stats.tx_dropped++;
  7037. + dev_kfree_skb(skb);
  7038. + return 1;
  7039. + }
  7040. + skb = skb2;
  7041. + }
  7042. +
  7043. + if ((skb->len % usb_wsize) == 0) {
  7044. + skb->len++; // other side will ignore this one, anyway.
  7045. + }
  7046. +
  7047. + local_irq_save(flags);
  7048. + if (cur_tx_skb) {
  7049. + next_tx_skb = skb;
  7050. + netif_stop_queue(dev);
  7051. + } else {
  7052. + cur_tx_skb = skb;
  7053. + dev->trans_start = jiffies;
  7054. + ret = sa1100_usb_send(skb->data, skb->len, usb_send_callback);
  7055. + if (ret) {
  7056. + /* If the USB core can't accept the packet, we drop it. */
  7057. + dev_kfree_skb(skb);
  7058. + cur_tx_skb = NULL;
  7059. + usbe_info.stats.tx_carrier_errors++;
  7060. + }
  7061. + }
  7062. + local_irq_restore(flags);
  7063. + return 0;
  7064. +}
  7065. +
  7066. +static void
  7067. +usb_xmit_timeout(struct net_device *dev )
  7068. +{
  7069. + sa1100_usb_send_reset();
  7070. + dev->trans_start = jiffies;
  7071. + netif_wake_queue(dev);
  7072. +}
  7073. +
  7074. +
  7075. +static int
  7076. +usb_eth_open(struct net_device *dev)
  7077. +{
  7078. + terminating = 0;
  7079. + cur_tx_skb = next_tx_skb = NULL;
  7080. + cur_rx_skb = usb_new_recv_skb();
  7081. + next_rx_skb = usb_new_recv_skb();
  7082. + if (!cur_rx_skb || !next_rx_skb) {
  7083. + printk("%s: can't allocate new skb\n", __FUNCTION__);
  7084. + if (cur_rx_skb)
  7085. + kfree_skb(cur_rx_skb);
  7086. + if (next_rx_skb)
  7087. + kfree_skb(next_rx_skb);
  7088. + return -ENOMEM;;
  7089. + }
  7090. +
  7091. + MOD_INC_USE_COUNT;
  7092. +#ifndef DMA_NO_COPY
  7093. + sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
  7094. +#else
  7095. + sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
  7096. + usb_recv_callback);
  7097. +#endif
  7098. + return 0;
  7099. +}
  7100. +
  7101. +static int
  7102. +usb_eth_release(struct net_device *dev)
  7103. +{
  7104. + terminating = 1;
  7105. + sa1100_usb_send_reset();
  7106. + sa1100_usb_recv_reset();
  7107. + if (cur_tx_skb)
  7108. + kfree_skb(cur_tx_skb);
  7109. + if (next_tx_skb)
  7110. + kfree_skb(next_tx_skb);
  7111. + if (cur_rx_skb)
  7112. + kfree_skb(cur_rx_skb);
  7113. + if (next_rx_skb)
  7114. + kfree_skb(next_rx_skb);
  7115. + MOD_DEC_USE_COUNT;
  7116. + return 0;
  7117. +}
  7118. +
  7119. +static struct net_device_stats *
  7120. +usb_eth_stats(struct net_device *dev)
  7121. +{
  7122. + struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv;
  7123. + struct net_device_stats *stats=NULL;
  7124. +
  7125. + if (priv)
  7126. + stats = &priv->stats;
  7127. + return stats;
  7128. +}
  7129. +
  7130. +static int
  7131. +usb_eth_probe(struct net_device *dev)
  7132. +{
  7133. + u8 node_id [ETH_ALEN];
  7134. +
  7135. + get_random_bytes (node_id, sizeof node_id);
  7136. + node_id [0] &= 0xfe; // clear multicast bit
  7137. +
  7138. + /*
  7139. + * Assign the hardware address of the board:
  7140. + * generate it randomly, as there can be many such
  7141. + * devices on the bus.
  7142. + */
  7143. + memcpy (dev->dev_addr, node_id, sizeof node_id);
  7144. +
  7145. + dev->open = usb_eth_open;
  7146. + dev->change_mtu = usb_change_mtu;
  7147. + dev->stop = usb_eth_release;
  7148. + dev->hard_start_xmit = usb_eth_xmit;
  7149. + dev->get_stats = usb_eth_stats;
  7150. + dev->watchdog_timeo = 1*HZ;
  7151. + dev->tx_timeout = usb_xmit_timeout;
  7152. + dev->priv = &usbe_info;
  7153. +
  7154. + usbe_info.dev = dev;
  7155. +
  7156. + /* clear the statistics */
  7157. + memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
  7158. +
  7159. + ether_setup(dev);
  7160. + dev->flags &= ~IFF_MULTICAST;
  7161. + dev->flags &= ~IFF_BROADCAST;
  7162. + //dev->flags |= IFF_NOARP;
  7163. +
  7164. + return 0;
  7165. +}
  7166. +
  7167. +#ifdef MODULE
  7168. +MODULE_PARM(usb_rsize, "1i");
  7169. +MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to sa1100");
  7170. +MODULE_PARM(usb_wsize, "1i");
  7171. +MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from sa1100 to host");
  7172. +#endif
  7173. +
  7174. +static int __init
  7175. +usb_eth_init(void)
  7176. +{
  7177. + int rc;
  7178. +
  7179. +#ifndef DMA_NO_COPY
  7180. + dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
  7181. + if (!dmabuf)
  7182. + return -ENOMEM;
  7183. +#endif
  7184. + strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
  7185. + usb_eth_device.init = usb_eth_probe;
  7186. + if (register_netdev(&usb_eth_device) != 0)
  7187. + return -EIO;
  7188. +
  7189. + rc = sa1100_usb_open( "usb-eth" );
  7190. + if ( rc == 0 ) {
  7191. + string_desc_t * pstr;
  7192. + desc_t * pd = sa1100_usb_get_descriptor_ptr();
  7193. +
  7194. + pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
  7195. + pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
  7196. + pd->dev.idVendor = ETHERNET_VENDOR_ID;
  7197. + pd->dev.idProduct = ETHERNET_PRODUCT_ID;
  7198. + pstr = sa1100_usb_kmalloc_string_descriptor( "SA1100 USB NIC" );
  7199. + if ( pstr ) {
  7200. + sa1100_usb_set_string_descriptor( 1, pstr );
  7201. + pd->dev.iProduct = 1;
  7202. + }
  7203. + rc = sa1100_usb_start();
  7204. + }
  7205. + return rc;
  7206. +}
  7207. +
  7208. +module_init(usb_eth_init);
  7209. +
  7210. +static void __exit
  7211. +usb_eth_cleanup(void)
  7212. +{
  7213. + string_desc_t * pstr;
  7214. + sa1100_usb_stop();
  7215. + sa1100_usb_close();
  7216. + if ( (pstr = sa1100_usb_get_string_descriptor(1)) != NULL )
  7217. + kfree( pstr );
  7218. +#ifndef DMA_NO_COPY
  7219. + kfree(dmabuf);
  7220. +#endif
  7221. + unregister_netdev(&usb_eth_device);
  7222. +}
  7223. +
  7224. +module_exit(usb_eth_cleanup);
  7225. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb_ctl.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_ctl.c
  7226. --- linux-2.4.26/arch/arm/mach-sa1100/usb_ctl.c 1970-01-01 01:00:00.000000000 +0100
  7227. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_ctl.c 2004-01-14 21:32:24.000000000 +0000
  7228. @@ -0,0 +1,774 @@
  7229. + /*
  7230. + * Copyright (C) Compaq Computer Corporation, 1998, 1999
  7231. + * Copyright (C) Extenex Corporation, 2001
  7232. + *
  7233. + * usb_ctl.c
  7234. + *
  7235. + * SA1100 USB controller core driver.
  7236. + *
  7237. + * This file provides interrupt routing and overall coordination
  7238. + * of the three endpoints in usb_ep0, usb_receive (1), and usb_send (2).
  7239. + *
  7240. + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
  7241. + *
  7242. + */
  7243. +#include <linux/config.h>
  7244. +#include <linux/module.h>
  7245. +#include <linux/init.h>
  7246. +#include <linux/proc_fs.h>
  7247. +#include <linux/tqueue.h>
  7248. +#include <linux/delay.h>
  7249. +#include <linux/sched.h>
  7250. +#include <linux/slab.h>
  7251. +#include <asm/io.h>
  7252. +#include <asm/dma.h>
  7253. +#include <asm/irq.h>
  7254. +#include <asm/mach-types.h>
  7255. +
  7256. +#include "sa1100_usb.h"
  7257. +#include "usb_ctl.h"
  7258. +
  7259. +//////////////////////////////////////////////////////////////////////////////
  7260. +// Prototypes
  7261. +//////////////////////////////////////////////////////////////////////////////
  7262. +
  7263. +int usbctl_next_state_on_event( int event );
  7264. +static void udc_int_hndlr(int, void *, struct pt_regs *);
  7265. +static void initialize_descriptors( void );
  7266. +static void soft_connect_hook( int enable );
  7267. +static void udc_disable(void);
  7268. +static void udc_enable(void);
  7269. +
  7270. +#if CONFIG_PROC_FS
  7271. +#define PROC_NODE_NAME "sausb"
  7272. +static int usbctl_read_proc(char *page, char **start, off_t off,
  7273. + int count, int *eof, void *data);
  7274. +#endif
  7275. +
  7276. +//////////////////////////////////////////////////////////////////////////////
  7277. +// Globals
  7278. +//////////////////////////////////////////////////////////////////////////////
  7279. +static const char pszMe[] = "usbctl: ";
  7280. +struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */
  7281. +
  7282. +/* device descriptors */
  7283. +static desc_t desc;
  7284. +
  7285. +#define MAX_STRING_DESC 8
  7286. +static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
  7287. +static string_desc_t sd_zero; /* special sd_zero holds language codes */
  7288. +
  7289. +// called when configured
  7290. +static usb_notify_t configured_callback = NULL;
  7291. +
  7292. +enum { kStateZombie = 0, kStateZombieSuspend = 1,
  7293. + kStateDefault = 2, kStateDefaultSuspend = 3,
  7294. + kStateAddr = 4, kStateAddrSuspend = 5,
  7295. + kStateConfig = 6, kStateConfigSuspend = 7
  7296. +};
  7297. +
  7298. +static int device_state_machine[8][6] = {
  7299. +// suspend reset resume adddr config deconfig
  7300. +/* zombie */ { kStateZombieSuspend, kStateDefault, kError, kError, kError, kError },
  7301. +/* zom sus */ { kError, kStateDefault, kStateZombie, kError, kError, kError },
  7302. +/* default */ { kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError },
  7303. +/* def sus */ { kError, kStateDefault, kStateDefault, kError, kError, kError },
  7304. +/* addr */ { kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError },
  7305. +/* addr sus */{ kError, kStateDefault, kStateAddr, kError, kError, kError },
  7306. +/* config */ { kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr },
  7307. +/* cfg sus */ { kError, kStateDefault, kStateConfig, kError, kError, kError }
  7308. +};
  7309. +
  7310. +/* "device state" is the usb device framework state, as opposed to the
  7311. + "state machine state" which is whatever the driver needs and is much
  7312. + more fine grained
  7313. +*/
  7314. +static int sm_state_to_device_state[8] =
  7315. +// zombie zom suspend default default sus
  7316. +{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
  7317. +// addr addr sus config config sus
  7318. + USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
  7319. +};
  7320. +
  7321. +static char * state_names[8] =
  7322. +{ "zombie", "zombie suspended", "default", "default suspended",
  7323. + "address", "address suspended", "configured", "config suspended"
  7324. +};
  7325. +
  7326. +static char * event_names[6] =
  7327. +{ "suspend", "reset", "resume",
  7328. + "address assigned", "configure", "de-configure"
  7329. +};
  7330. +
  7331. +static char * device_state_names[] =
  7332. +{ "not attached", "attached", "powered", "default",
  7333. + "address", "configured", "suspended" };
  7334. +
  7335. +static int sm_state = kStateZombie;
  7336. +
  7337. +//////////////////////////////////////////////////////////////////////////////
  7338. +// Async
  7339. +//////////////////////////////////////////////////////////////////////////////
  7340. +static void core_kicker(void);
  7341. +
  7342. +static inline void enable_resume_mask_suspend( void );
  7343. +static inline void enable_suspend_mask_resume(void);
  7344. +
  7345. +static void
  7346. +udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
  7347. +{
  7348. + __u32 status = Ser0UDCSR;
  7349. +
  7350. + /* ReSeT Interrupt Request - UDC has been reset */
  7351. + if ( status & UDCSR_RSTIR )
  7352. + {
  7353. + if ( usbctl_next_state_on_event( kEvReset ) != kError )
  7354. + {
  7355. + /* starting 20ms or so reset sequence now... */
  7356. + printk("%sResetting\n", pszMe);
  7357. + ep0_reset(); // just set state to idle
  7358. + ep1_reset(); // flush dma, clear false stall
  7359. + ep2_reset(); // flush dma, clear false stall
  7360. + }
  7361. + // mask reset ints, they flood during sequence, enable
  7362. + // suspend and resume
  7363. + Ser0UDCCR |= UDCCR_REM; // mask reset
  7364. + Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume
  7365. + UDC_flip( Ser0UDCSR, status ); // clear all pending sources
  7366. + return; // <-- no reason to continue if resetting
  7367. + }
  7368. + // else we have done something other than reset, so be sure reset enabled
  7369. + UDC_clear( Ser0UDCCR, UDCCR_REM );
  7370. +
  7371. + /* RESume Interrupt Request */
  7372. + if ( status & UDCSR_RESIR )
  7373. + {
  7374. + usbctl_next_state_on_event( kEvResume );
  7375. + core_kicker();
  7376. + enable_suspend_mask_resume();
  7377. + }
  7378. +
  7379. + /* SUSpend Interrupt Request */
  7380. + if ( status & UDCSR_SUSIR )
  7381. + {
  7382. + usbctl_next_state_on_event( kEvSuspend );
  7383. + enable_resume_mask_suspend();
  7384. + }
  7385. +
  7386. + UDC_flip(Ser0UDCSR, status); // clear all pending sources
  7387. +
  7388. + if (status & UDCSR_EIR)
  7389. + ep0_int_hndlr();
  7390. +
  7391. + if (status & UDCSR_RIR)
  7392. + ep1_int_hndlr(status);
  7393. +
  7394. + if (status & UDCSR_TIR)
  7395. + ep2_int_hndlr(status);
  7396. +}
  7397. +
  7398. +static inline void enable_resume_mask_suspend( void )
  7399. +{
  7400. + int i = 0;
  7401. +
  7402. + while( 1 ) {
  7403. + Ser0UDCCR |= UDCCR_SUSIM; // mask future suspend events
  7404. + udelay( i );
  7405. + if ( (Ser0UDCCR & UDCCR_SUSIM) || (Ser0UDCSR & UDCSR_RSTIR) )
  7406. + break;
  7407. + if ( ++i == 50 ) {
  7408. + printk( "%senable_resume(): Could not set SUSIM %8.8X\n",
  7409. + pszMe, Ser0UDCCR );
  7410. + break;
  7411. + }
  7412. + }
  7413. +
  7414. + i = 0;
  7415. + while( 1 ) {
  7416. + Ser0UDCCR &= ~UDCCR_RESIM;
  7417. + udelay( i );
  7418. + if ( ( Ser0UDCCR & UDCCR_RESIM ) == 0
  7419. + ||
  7420. + (Ser0UDCSR & UDCSR_RSTIR)
  7421. + )
  7422. + break;
  7423. + if ( ++i == 50 ) {
  7424. + printk( "%senable_resume(): Could not clear RESIM %8.8X\n",
  7425. + pszMe, Ser0UDCCR );
  7426. + break;
  7427. + }
  7428. + }
  7429. +}
  7430. +
  7431. +static inline void enable_suspend_mask_resume(void)
  7432. +{
  7433. + int i = 0;
  7434. + while( 1 ) {
  7435. + Ser0UDCCR |= UDCCR_RESIM; // mask future resume events
  7436. + udelay( i );
  7437. + if ( Ser0UDCCR & UDCCR_RESIM || (Ser0UDCSR & UDCSR_RSTIR) )
  7438. + break;
  7439. + if ( ++i == 50 ) {
  7440. + printk( "%senable_suspend(): Could not set RESIM %8.8X\n",
  7441. + pszMe, Ser0UDCCR );
  7442. + break;
  7443. + }
  7444. + }
  7445. + i = 0;
  7446. + while( 1 ) {
  7447. + Ser0UDCCR &= ~UDCCR_SUSIM;
  7448. + udelay( i );
  7449. + if ( ( Ser0UDCCR & UDCCR_SUSIM ) == 0
  7450. + ||
  7451. + (Ser0UDCSR & UDCSR_RSTIR)
  7452. + )
  7453. + break;
  7454. + if ( ++i == 50 ) {
  7455. + printk( "%senable_suspend(): Could not clear SUSIM %8.8X\n",
  7456. + pszMe, Ser0UDCCR );
  7457. + break;
  7458. + }
  7459. + }
  7460. +}
  7461. +
  7462. +
  7463. +//////////////////////////////////////////////////////////////////////////////
  7464. +// Public Interface
  7465. +//////////////////////////////////////////////////////////////////////////////
  7466. +
  7467. +/* Open SA usb core on behalf of a client, but don't start running */
  7468. +
  7469. +int
  7470. +sa1100_usb_open( const char * client )
  7471. +{
  7472. + if ( usbd_info.client_name != NULL )
  7473. + return -EBUSY;
  7474. +
  7475. + usbd_info.client_name = (char*) client;
  7476. + memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
  7477. + memset(string_desc_array, 0, sizeof(string_desc_array));
  7478. +
  7479. + /* hack to start in zombie suspended state */
  7480. + sm_state = kStateZombieSuspend;
  7481. + usbd_info.state = USB_STATE_SUSPENDED;
  7482. +
  7483. + /* create descriptors for enumeration */
  7484. + initialize_descriptors();
  7485. +
  7486. + printk( "%sOpened for %s\n", pszMe, client );
  7487. + return 0;
  7488. +}
  7489. +
  7490. +/* Start running. Must have called usb_open (above) first */
  7491. +int
  7492. +sa1100_usb_start( void )
  7493. +{
  7494. + if ( usbd_info.client_name == NULL ) {
  7495. + printk( "%s%s - no client registered\n",
  7496. + pszMe, __FUNCTION__ );
  7497. + return -EPERM;
  7498. + }
  7499. +
  7500. + /* start UDC internal machinery running */
  7501. + udc_enable();
  7502. + udelay( 100 );
  7503. +
  7504. + /* clear stall - receiver seems to start stalled? 19Jan01ww */
  7505. + /* also clear other stuff just to be thurough 22Feb01ww */
  7506. + UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC );
  7507. + UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC );
  7508. +
  7509. + /* mask everything */
  7510. + Ser0UDCCR = 0xFC;
  7511. +
  7512. + /* flush DMA and fire through some -EAGAINs */
  7513. + ep1_init( usbd_info.dmach_rx );
  7514. + ep2_init( usbd_info.dmach_tx );
  7515. +
  7516. + /* give endpoint notification we are starting */
  7517. + ep1_state_change_notify( USB_STATE_SUSPENDED );
  7518. + ep2_state_change_notify( USB_STATE_SUSPENDED );
  7519. +
  7520. + /* enable any platform specific hardware */
  7521. + soft_connect_hook( 1 );
  7522. +
  7523. + /* clear all top-level sources */
  7524. + Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR |
  7525. + UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
  7526. +
  7527. + /* EXERIMENT - a short line in the spec says toggling this
  7528. + ..bit diddles the internal state machine in the udc to
  7529. + ..expect a suspend */
  7530. + Ser0UDCCR |= UDCCR_RESIM;
  7531. + /* END EXPERIMENT 10Feb01ww */
  7532. +
  7533. + /* enable any platform specific hardware */
  7534. + soft_connect_hook( 1 );
  7535. +
  7536. + /* enable interrupts. If you are unplugged you will
  7537. + immediately get a suspend interrupt. If you are plugged
  7538. + and have a soft connect-circuit, you will get a reset
  7539. + If you are plugged without a soft-connect, I think you
  7540. + also get suspend. In short, start with suspend masked
  7541. + and everything else enabled */
  7542. + UDC_write( Ser0UDCCR, UDCCR_SUSIM );
  7543. +
  7544. + printk( "%sStarted for %s\n", pszMe, usbd_info.client_name );
  7545. + return 0;
  7546. +}
  7547. +
  7548. +/* Stop USB core from running */
  7549. +int
  7550. +sa1100_usb_stop( void )
  7551. +{
  7552. + if ( usbd_info.client_name == NULL ) {
  7553. + printk( "%s%s - no client registered\n",
  7554. + pszMe, __FUNCTION__ );
  7555. + return -EPERM;
  7556. + }
  7557. + /* mask everything */
  7558. + Ser0UDCCR = 0xFC;
  7559. + ep1_reset();
  7560. + ep2_reset();
  7561. + udc_disable();
  7562. + printk( "%sStopped\n", pszMe );
  7563. + return 0;
  7564. +}
  7565. +
  7566. +/* Tell SA core client is through using it */
  7567. +int
  7568. +sa1100_usb_close( void )
  7569. +{
  7570. + if ( usbd_info.client_name == NULL ) {
  7571. + printk( "%s%s - no client registered\n",
  7572. + pszMe, __FUNCTION__ );
  7573. + return -EPERM;
  7574. + }
  7575. + usbd_info.client_name = NULL;
  7576. + printk( "%sClosed\n", pszMe );
  7577. + return 0;
  7578. +}
  7579. +
  7580. +/* set a proc to be called when device is configured */
  7581. +usb_notify_t sa1100_set_configured_callback( usb_notify_t func )
  7582. +{
  7583. + usb_notify_t retval = configured_callback;
  7584. + configured_callback = func;
  7585. + return retval;
  7586. +}
  7587. +
  7588. +/*====================================================
  7589. + * Descriptor Manipulation.
  7590. + * Use these between open() and start() above to setup
  7591. + * the descriptors for your device.
  7592. + *
  7593. + */
  7594. +
  7595. +/* get pointer to static default descriptor */
  7596. +desc_t *
  7597. +sa1100_usb_get_descriptor_ptr( void ) { return &desc; }
  7598. +
  7599. +/* optional: set a string descriptor */
  7600. +int
  7601. +sa1100_usb_set_string_descriptor( int i, string_desc_t * p )
  7602. +{
  7603. + int retval;
  7604. + if ( i < MAX_STRING_DESC ) {
  7605. + string_desc_array[i] = p;
  7606. + retval = 0;
  7607. + } else {
  7608. + retval = -EINVAL;
  7609. + }
  7610. + return retval;
  7611. +}
  7612. +
  7613. +/* optional: get a previously set string descriptor */
  7614. +string_desc_t *
  7615. +sa1100_usb_get_string_descriptor( int i )
  7616. +{
  7617. + return ( i < MAX_STRING_DESC )
  7618. + ? string_desc_array[i]
  7619. + : NULL;
  7620. +}
  7621. +
  7622. +
  7623. +/* optional: kmalloc and unicode up a string descriptor */
  7624. +string_desc_t *
  7625. +sa1100_usb_kmalloc_string_descriptor( const char * p )
  7626. +{
  7627. + string_desc_t * pResult = NULL;
  7628. +
  7629. + if ( p ) {
  7630. + int len = strlen( p );
  7631. + int uni_len = len * sizeof( __u16 );
  7632. + pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
  7633. + if ( pResult != NULL ) {
  7634. + int i;
  7635. + pResult->bLength = uni_len + 2;
  7636. + pResult->bDescriptorType = USB_DESC_STRING;
  7637. + for( i = 0; i < len ; i++ ) {
  7638. + pResult->bString[i] = make_word( (__u16) p[i] );
  7639. + }
  7640. + }
  7641. + }
  7642. + return pResult;
  7643. +}
  7644. +
  7645. +//////////////////////////////////////////////////////////////////////////////
  7646. +// Exports to rest of driver
  7647. +//////////////////////////////////////////////////////////////////////////////
  7648. +
  7649. +/* called by the int handler here and the two endpoint files when interesting
  7650. + .."events" happen */
  7651. +
  7652. +int
  7653. +usbctl_next_state_on_event( int event )
  7654. +{
  7655. + int next_state = device_state_machine[ sm_state ][ event ];
  7656. + if ( next_state != kError )
  7657. + {
  7658. + int next_device_state = sm_state_to_device_state[ next_state ];
  7659. + printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
  7660. + pszMe, state_names[ sm_state ], event_names[ event ],
  7661. + state_names[ next_state ], device_state_names[ next_device_state ] );
  7662. +
  7663. + sm_state = next_state;
  7664. + if ( usbd_info.state != next_device_state )
  7665. + {
  7666. + if ( configured_callback != NULL
  7667. + &&
  7668. + next_device_state == USB_STATE_CONFIGURED
  7669. + &&
  7670. + usbd_info.state != USB_STATE_SUSPENDED
  7671. + ) {
  7672. + configured_callback();
  7673. + }
  7674. + usbd_info.state = next_device_state;
  7675. + ep1_state_change_notify( next_device_state );
  7676. + ep2_state_change_notify( next_device_state );
  7677. + }
  7678. + }
  7679. +#if 0
  7680. + else
  7681. + printk( "%s%s --> [%s] --> ??? is an error.\n",
  7682. + pszMe, state_names[ sm_state ], event_names[ event ] );
  7683. +#endif
  7684. + return next_state;
  7685. +}
  7686. +
  7687. +//////////////////////////////////////////////////////////////////////////////
  7688. +// Private Helpers
  7689. +//////////////////////////////////////////////////////////////////////////////
  7690. +
  7691. +/* setup default descriptors */
  7692. +
  7693. +static void
  7694. +initialize_descriptors(void)
  7695. +{
  7696. + desc.dev.bLength = sizeof( device_desc_t );
  7697. + desc.dev.bDescriptorType = USB_DESC_DEVICE;
  7698. + desc.dev.bcdUSB = 0x100; /* 1.0 */
  7699. + desc.dev.bDeviceClass = 0xFF; /* vendor specific */
  7700. + desc.dev.bDeviceSubClass = 0;
  7701. + desc.dev.bDeviceProtocol = 0;
  7702. + desc.dev.bMaxPacketSize0 = 8; /* ep0 max fifo size */
  7703. + desc.dev.idVendor = 0; /* vendor ID undefined */
  7704. + desc.dev.idProduct = 0; /* product */
  7705. + desc.dev.bcdDevice = 0; /* vendor assigned device release num */
  7706. + desc.dev.iManufacturer = 0; /* index of manufacturer string */
  7707. + desc.dev.iProduct = 0; /* index of product description string */
  7708. + desc.dev.iSerialNumber = 0; /* index of string holding product s/n */
  7709. + desc.dev.bNumConfigurations = 1;
  7710. +
  7711. + desc.b.cfg.bLength = sizeof( config_desc_t );
  7712. + desc.b.cfg.bDescriptorType = USB_DESC_CONFIG;
  7713. + desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) );
  7714. + desc.b.cfg.bNumInterfaces = 1;
  7715. + desc.b.cfg.bConfigurationValue = 1;
  7716. + desc.b.cfg.iConfiguration = 0;
  7717. + desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED;
  7718. + desc.b.cfg.MaxPower = USB_POWER( 500 );
  7719. +
  7720. + desc.b.intf.bLength = sizeof( intf_desc_t );
  7721. + desc.b.intf.bDescriptorType = USB_DESC_INTERFACE;
  7722. + desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/
  7723. + desc.b.intf.bAlternateSetting = 0;
  7724. + desc.b.intf.bNumEndpoints = 2;
  7725. + desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */
  7726. + desc.b.intf.bInterfaceSubClass = 0;
  7727. + desc.b.intf.bInterfaceProtocol = 0;
  7728. + desc.b.intf.iInterface = 0;
  7729. +
  7730. + desc.b.ep1.bLength = sizeof( ep_desc_t );
  7731. + desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT;
  7732. + desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_OUT );
  7733. + desc.b.ep1.bmAttributes = USB_EP_BULK;
  7734. + desc.b.ep1.wMaxPacketSize = make_word_c( 64 );
  7735. + desc.b.ep1.bInterval = 0;
  7736. +
  7737. + desc.b.ep2.bLength = sizeof( ep_desc_t );
  7738. + desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT;
  7739. + desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_IN );
  7740. + desc.b.ep2.bmAttributes = USB_EP_BULK;
  7741. + desc.b.ep2.wMaxPacketSize = make_word_c( 64 );
  7742. + desc.b.ep2.bInterval = 0;
  7743. +
  7744. + /* set language */
  7745. + /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
  7746. + sd_zero.bDescriptorType = USB_DESC_STRING;
  7747. + sd_zero.bLength = sizeof( string_desc_t );
  7748. + sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */
  7749. + sa1100_usb_set_string_descriptor( 0, &sd_zero );
  7750. +}
  7751. +
  7752. +/* soft_connect_hook()
  7753. + * Some devices have platform-specific circuitry to make USB
  7754. + * not seem to be plugged in, even when it is. This allows
  7755. + * software to control when a device 'appears' on the USB bus
  7756. + * (after Linux has booted and this driver has loaded, for
  7757. + * example). If you have such a circuit, control it here.
  7758. + */
  7759. +static void
  7760. +soft_connect_hook( int enable )
  7761. +{
  7762. +#ifdef CONFIG_SA1100_EXTENEX1
  7763. + if (machine_is_extenex1() ) {
  7764. + if ( enable ) {
  7765. + PPDR |= PPC_USB_SOFT_CON;
  7766. + PPSR |= PPC_USB_SOFT_CON;
  7767. + } else {
  7768. + PPSR &= ~PPC_USB_SOFT_CON;
  7769. + PPDR &= ~PPC_USB_SOFT_CON;
  7770. + }
  7771. + }
  7772. +#endif
  7773. +}
  7774. +
  7775. +/* disable the UDC at the source */
  7776. +static void
  7777. +udc_disable(void)
  7778. +{
  7779. + soft_connect_hook( 0 );
  7780. + UDC_set( Ser0UDCCR, UDCCR_UDD );
  7781. +}
  7782. +
  7783. +
  7784. +/* enable the udc at the source */
  7785. +static void
  7786. +udc_enable(void)
  7787. +{
  7788. + UDC_clear(Ser0UDCCR, UDCCR_UDD);
  7789. +}
  7790. +
  7791. +// HACK DEBUG 3Mar01ww
  7792. +// Well, maybe not, it really seems to help! 08Mar01ww
  7793. +static void
  7794. +core_kicker( void )
  7795. +{
  7796. + __u32 car = Ser0UDCAR;
  7797. + __u32 imp = Ser0UDCIMP;
  7798. + __u32 omp = Ser0UDCOMP;
  7799. +
  7800. + UDC_set( Ser0UDCCR, UDCCR_UDD );
  7801. + udelay( 300 );
  7802. + UDC_clear(Ser0UDCCR, UDCCR_UDD);
  7803. +
  7804. + Ser0UDCAR = car;
  7805. + Ser0UDCIMP = imp;
  7806. + Ser0UDCOMP = omp;
  7807. +}
  7808. +
  7809. +//////////////////////////////////////////////////////////////////////////////
  7810. +// Proc Filesystem Support
  7811. +//////////////////////////////////////////////////////////////////////////////
  7812. +
  7813. +#if CONFIG_PROC_FS
  7814. +
  7815. +#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )
  7816. +#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )
  7817. +#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )
  7818. +#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )
  7819. +
  7820. +static int usbctl_read_proc(char *page, char **start, off_t off,
  7821. + int count, int *eof, void *data)
  7822. +{
  7823. + const char * num_fmt = "%25.25s: %8.8lX\n";
  7824. + const char * cnt_fmt = "%25.25s: %lu\n";
  7825. + const char * yn_fmt = "%25.25s: %s\n";
  7826. + const char * yes = "YES";
  7827. + const char * no = "NO";
  7828. + unsigned long v;
  7829. + char * p = page;
  7830. + int len;
  7831. +
  7832. + SAY( "SA1100 USB Controller Core\n" );
  7833. + SAY( "USB state: %s (%s) %d\n",
  7834. + device_state_names[ sm_state_to_device_state[ sm_state ] ],
  7835. + state_names[ sm_state ],
  7836. + sm_state );
  7837. +
  7838. + SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
  7839. + SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
  7840. + SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
  7841. + SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
  7842. +
  7843. + SAY( "\n" );
  7844. +
  7845. + v = Ser0UDCAR;
  7846. + SAY( "%25.25s: 0x%8.8lX - %ld\n", "Address Register", v, v );
  7847. + v = Ser0UDCIMP;
  7848. + SAY( "%25.25s: %ld (%8.8lX)\n", "IN max packet size", v+1, v );
  7849. + v = Ser0UDCOMP;
  7850. + SAY( "%25.25s: %ld (%8.8lX)\n", "OUT max packet size", v+1, v );
  7851. +
  7852. + v = Ser0UDCCR;
  7853. + SAY( "\nUDC Mask Register\n" );
  7854. + SAYV( v );
  7855. + SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no );
  7856. + SAYC( "Suspend interrupts masked", ( v & UDCCR_SUSIM ) ? yes : no );
  7857. + SAYC( "Resume interrupts masked", ( v & UDCCR_RESIM ) ? yes : no );
  7858. + SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no );
  7859. +
  7860. + v = Ser0UDCSR;
  7861. + SAY( "\nUDC Interrupt Request Register\n" );
  7862. + SAYV( v );
  7863. + SAYC( "Reset pending", ( v & UDCSR_RSTIR ) ? yes : no );
  7864. + SAYC( "Suspend pending", ( v & UDCSR_SUSIR ) ? yes : no );
  7865. + SAYC( "Resume pending", ( v & UDCSR_RESIR ) ? yes : no );
  7866. + SAYC( "ep0 pending", ( v & UDCSR_EIR ) ? yes : no );
  7867. + SAYC( "receiver pending", ( v & UDCSR_RIR ) ? yes : no );
  7868. + SAYC( "tramsitter pending", ( v & UDCSR_TIR ) ? yes : no );
  7869. +
  7870. +#ifdef CONFIG_SA1100_EXTENEX1
  7871. + SAYC( "\nSoft connect", (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden" );
  7872. +#endif
  7873. +
  7874. +#if 0
  7875. + v = Ser0UDCCS0;
  7876. + SAY( "\nUDC Endpoint Zero Status Register\n" );
  7877. + SAYV( v );
  7878. + SAYC( "Out Packet Ready", ( v & UDCCS0_OPR ) ? yes : no );
  7879. + SAYC( "In Packet Ready", ( v & UDCCS0_IPR ) ? yes : no );
  7880. + SAYC( "Sent Stall", ( v & UDCCS0_SST ) ? yes : no );
  7881. + SAYC( "Force Stall", ( v & UDCCS0_FST ) ? yes : no );
  7882. + SAYC( "Data End", ( v & UDCCS0_DE ) ? yes : no );
  7883. + SAYC( "Data Setup End", ( v & UDCCS0_SE ) ? yes : no );
  7884. + SAYC( "Serviced (SO)", ( v & UDCCS0_SO ) ? yes : no );
  7885. +
  7886. + v = Ser0UDCCS1;
  7887. + SAY( "\nUDC Receiver Status Register\n" );
  7888. + SAYV( v );
  7889. + SAYC( "Receive Packet Complete", ( v & UDCCS1_RPC ) ? yes : no );
  7890. + SAYC( "Sent Stall", ( v & UDCCS1_SST ) ? yes : no );
  7891. + SAYC( "Force Stall", ( v & UDCCS1_FST ) ? yes : no );
  7892. + SAYC( "Receive Packet Error", ( v & UDCCS1_RPE ) ? yes : no );
  7893. + SAYC( "Receive FIFO not empty", ( v & UDCCS1_RNE ) ? yes : no );
  7894. +
  7895. + v = Ser0UDCCS2;
  7896. + SAY( "\nUDC Transmitter Status Register\n" );
  7897. + SAYV( v );
  7898. + SAYC( "FIFO has < 8 of 16 chars", ( v & UDCCS2_TFS ) ? yes : no );
  7899. + SAYC( "Transmit Packet Complete", ( v & UDCCS2_TPC ) ? yes : no );
  7900. + SAYC( "Transmit FIFO underrun", ( v & UDCCS2_TUR ) ? yes : no );
  7901. + SAYC( "Transmit Packet Error", ( v & UDCCS2_TPE ) ? yes : no );
  7902. + SAYC( "Sent Stall", ( v & UDCCS2_SST ) ? yes : no );
  7903. + SAYC( "Force Stall", ( v & UDCCS2_FST ) ? yes : no );
  7904. +#endif
  7905. +
  7906. + len = ( p - page ) - off;
  7907. + if ( len < 0 )
  7908. + len = 0;
  7909. + *eof = ( len <=count ) ? 1 : 0;
  7910. + *start = page + off;
  7911. + return len;
  7912. +}
  7913. +
  7914. +#endif /* CONFIG_PROC_FS */
  7915. +
  7916. +//////////////////////////////////////////////////////////////////////////////
  7917. +// Module Initialization and Shutdown
  7918. +//////////////////////////////////////////////////////////////////////////////
  7919. +/*
  7920. + * usbctl_init()
  7921. + * Module load time. Allocate dma and interrupt resources. Setup /proc fs
  7922. + * entry. Leave UDC disabled.
  7923. + */
  7924. +int __init usbctl_init( void )
  7925. +{
  7926. + int retval = 0;
  7927. +
  7928. + udc_disable();
  7929. +
  7930. + memset( &usbd_info, 0, sizeof( usbd_info ) );
  7931. +
  7932. +#if CONFIG_PROC_FS
  7933. + create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
  7934. +#endif
  7935. +
  7936. + /* setup rx dma */
  7937. + retval = sa1100_request_dma(&usbd_info.dmach_rx, "USB receive", DMA_Ser0UDCRd);
  7938. + if (retval) {
  7939. + printk("%sunable to register for rx dma rc=%d\n", pszMe, retval );
  7940. + goto err_rx_dma;
  7941. + }
  7942. +
  7943. + /* setup tx dma */
  7944. + retval = sa1100_request_dma(&usbd_info.dmach_tx, "USB transmit", DMA_Ser0UDCWr);
  7945. + if (retval) {
  7946. + printk("%sunable to register for tx dma rc=%d\n",pszMe,retval);
  7947. + goto err_tx_dma;
  7948. + }
  7949. +
  7950. + /* now allocate the IRQ. */
  7951. + retval = request_irq(IRQ_Ser0UDC, udc_int_hndlr, SA_INTERRUPT,
  7952. + "SA USB core", NULL);
  7953. + if (retval) {
  7954. + printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
  7955. + goto err_irq;
  7956. + }
  7957. +
  7958. + printk( "SA1100 USB Controller Core Initialized\n");
  7959. + return 0;
  7960. +
  7961. +err_irq:
  7962. + sa1100_free_dma(usbd_info.dmach_tx);
  7963. + usbd_info.dmach_tx = 0;
  7964. +err_tx_dma:
  7965. + sa1100_free_dma(usbd_info.dmach_rx);
  7966. + usbd_info.dmach_rx = 0;
  7967. +err_rx_dma:
  7968. + return retval;
  7969. +}
  7970. +/*
  7971. + * usbctl_exit()
  7972. + * Release DMA and interrupt resources
  7973. + */
  7974. +void __exit usbctl_exit( void )
  7975. +{
  7976. + printk("Unloading SA1100 USB Controller\n");
  7977. +
  7978. + udc_disable();
  7979. +
  7980. +#if CONFIG_PROC_FS
  7981. + remove_proc_entry ( PROC_NODE_NAME, NULL);
  7982. +#endif
  7983. +
  7984. + sa1100_free_dma(usbd_info.dmach_rx);
  7985. + sa1100_free_dma(usbd_info.dmach_tx);
  7986. + free_irq(IRQ_Ser0UDC, NULL);
  7987. +}
  7988. +
  7989. +EXPORT_SYMBOL( sa1100_usb_open );
  7990. +EXPORT_SYMBOL( sa1100_usb_start );
  7991. +EXPORT_SYMBOL( sa1100_usb_stop );
  7992. +EXPORT_SYMBOL( sa1100_usb_close );
  7993. +
  7994. +
  7995. +EXPORT_SYMBOL( sa1100_usb_get_descriptor_ptr );
  7996. +EXPORT_SYMBOL( sa1100_usb_set_string_descriptor );
  7997. +EXPORT_SYMBOL( sa1100_usb_get_string_descriptor );
  7998. +EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor );
  7999. +
  8000. +
  8001. +module_init( usbctl_init );
  8002. +module_exit( usbctl_exit );
  8003. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb_ctl.h linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_ctl.h
  8004. --- linux-2.4.26/arch/arm/mach-sa1100/usb_ctl.h 1970-01-01 01:00:00.000000000 +0100
  8005. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_ctl.h 2004-01-14 21:32:24.000000000 +0000
  8006. @@ -0,0 +1,123 @@
  8007. +/*
  8008. + * Copyright (C) Compaq Computer Corporation, 1998, 1999
  8009. + * Copyright (C) Extenex Corporation 2001
  8010. + *
  8011. + * usb_ctl.h
  8012. + *
  8013. + * PRIVATE interface used to share info among components of the SA-1100 USB
  8014. + * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
  8015. + * should use sa1100_usb.h.
  8016. + *
  8017. + */
  8018. +
  8019. +#ifndef _USB_CTL_H
  8020. +#define _USB_CTL_H
  8021. +
  8022. +#include <asm/dma.h> /* dmach_t */
  8023. +
  8024. +
  8025. +/*
  8026. + * These states correspond to those in the USB specification v1.0
  8027. + * in chapter 8, Device Framework.
  8028. + */
  8029. +enum { USB_STATE_NOTATTACHED=0, USB_STATE_ATTACHED=1,USB_STATE_POWERED=2,
  8030. + USB_STATE_DEFAULT=3, USB_STATE_ADDRESS=4, USB_STATE_CONFIGURED=5,
  8031. + USB_STATE_SUSPENDED=6};
  8032. +
  8033. +struct usb_stats_t {
  8034. + unsigned long ep0_fifo_write_failures;
  8035. + unsigned long ep0_bytes_written;
  8036. + unsigned long ep0_fifo_read_failures;
  8037. + unsigned long ep0_bytes_read;
  8038. +};
  8039. +
  8040. +struct usb_info_t
  8041. +{
  8042. + char * client_name;
  8043. + dmach_t dmach_tx, dmach_rx;
  8044. + int state;
  8045. + unsigned char address;
  8046. + struct usb_stats_t stats;
  8047. +};
  8048. +
  8049. +/* in usb_ctl.c */
  8050. +extern struct usb_info_t usbd_info;
  8051. +
  8052. +/*
  8053. + * Function Prototypes
  8054. + */
  8055. +enum { kError=-1, kEvSuspend=0, kEvReset=1,
  8056. + kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 };
  8057. +int usbctl_next_state_on_event( int event );
  8058. +
  8059. +/* endpoint zero */
  8060. +void ep0_reset(void);
  8061. +void ep0_int_hndlr(void);
  8062. +
  8063. +/* receiver */
  8064. +void ep1_state_change_notify( int new_state );
  8065. +int ep1_recv(void);
  8066. +int ep1_init(int chn);
  8067. +void ep1_int_hndlr(int status);
  8068. +void ep1_reset(void);
  8069. +void ep1_stall(void);
  8070. +
  8071. +/* xmitter */
  8072. +void ep2_state_change_notify( int new_state );
  8073. +void ep2_reset(void);
  8074. +int ep2_init(int chn);
  8075. +void ep2_int_hndlr(int status);
  8076. +void ep2_stall(void);
  8077. +
  8078. +#define UDC_write(reg, val) { \
  8079. + int i = 10000; \
  8080. + do { \
  8081. + (reg) = (val); \
  8082. + if (i-- <= 0) { \
  8083. + printk( "%s [%d]: write %#x to %p (%#x) failed\n", \
  8084. + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
  8085. + break; \
  8086. + } \
  8087. + } while((reg) != (val)); \
  8088. +}
  8089. +
  8090. +#define UDC_set(reg, val) { \
  8091. + int i = 10000; \
  8092. + do { \
  8093. + (reg) |= (val); \
  8094. + if (i-- <= 0) { \
  8095. + printk( "%s [%d]: set %#x of %p (%#x) failed\n", \
  8096. + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
  8097. + break; \
  8098. + } \
  8099. + } while(!((reg) & (val))); \
  8100. +}
  8101. +
  8102. +#define UDC_clear(reg, val) { \
  8103. + int i = 10000; \
  8104. + do { \
  8105. + (reg) &= ~(val); \
  8106. + if (i-- <= 0) { \
  8107. + printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \
  8108. + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
  8109. + break; \
  8110. + } \
  8111. + } while((reg) & (val)); \
  8112. +}
  8113. +
  8114. +#define UDC_flip(reg, val) { \
  8115. + int i = 10000; \
  8116. + (reg) = (val); \
  8117. + do { \
  8118. + (reg) = (val); \
  8119. + if (i-- <= 0) { \
  8120. + printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \
  8121. + __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
  8122. + break; \
  8123. + } \
  8124. + } while(((reg) & (val))); \
  8125. +}
  8126. +
  8127. +
  8128. +#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}}
  8129. +#endif /* _USB_CTL_H */
  8130. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb_ep0.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_ep0.c
  8131. --- linux-2.4.26/arch/arm/mach-sa1100/usb_ep0.c 1970-01-01 01:00:00.000000000 +0100
  8132. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_ep0.c 2004-01-14 21:32:24.000000000 +0000
  8133. @@ -0,0 +1,911 @@
  8134. +/*
  8135. + * Copyright (C) Extenex Corporation 2001
  8136. + * Much folklore gleaned from original code:
  8137. + * Copyright (C) Compaq Computer Corporation, 1998, 1999
  8138. + *
  8139. + * usb_ep0.c - SA1100 USB controller driver.
  8140. + * Endpoint zero management
  8141. + *
  8142. + * Please see:
  8143. + * linux/Documentation/arm/SA1100/SA1100_USB
  8144. + * for details. (Especially since Intel docs are full of
  8145. + * errors about ep0 operation.) ward.willats@extenex.com.
  8146. + *
  8147. + * Intel also has a "Universal Serial Bus Client Device
  8148. + * Validation for the StrongARM SA-1100 Microprocessor"
  8149. + * document, which has flow charts and assembler test driver,
  8150. + * but be careful, since it is just for validation and not
  8151. + * a "real world" solution.
  8152. + *
  8153. + * A summary of three types of data-returning setups:
  8154. + *
  8155. + * 1. Setup request <= 8 bytes. That is, requests that can
  8156. + * be fullfilled in one write to the FIFO. DE is set
  8157. + * with IPR in queue_and_start_write(). (I don't know
  8158. + * if there really are any of these!)
  8159. + *
  8160. + * 2. Setup requests > 8 bytes (requiring more than one
  8161. + * IN to get back to the host), and we have at least
  8162. + * as much or more data than the host requested. In
  8163. + * this case we pump out everything we've got, and
  8164. + * when the final interrupt comes in due to the UDC
  8165. + * clearing the last IPR, we just set DE.
  8166. + *
  8167. + * 3. Setup requests > 8 bytes, but we don't have enough
  8168. + * data to satisfy the request. In this case, we send
  8169. + * everything we've got, and when the final interrupt
  8170. + * comes in due to the UDC clearing the last IPR
  8171. + * we write nothing to the FIFO and set both IPR and DE
  8172. + * so the UDC sends an empty packet and forces the host
  8173. + * to perform short packet retirement instead of stalling
  8174. + * out.
  8175. + *
  8176. + */
  8177. +
  8178. +#include <linux/delay.h>
  8179. +#include "sa1100_usb.h" /* public interface */
  8180. +#include "usb_ctl.h" /* private stuff */
  8181. +
  8182. +
  8183. +// 1 == lots of trace noise, 0 = only "important' stuff
  8184. +#define VERBOSITY 0
  8185. +
  8186. +enum { true = 1, false = 0 };
  8187. +typedef int bool;
  8188. +#ifndef MIN
  8189. +#define MIN( a, b ) ((a)<(b)?(a):(b))
  8190. +#endif
  8191. +
  8192. +#if 1 && !defined( ASSERT )
  8193. +# define ASSERT(expr) \
  8194. + if(!(expr)) { \
  8195. + printk( "Assertion failed! %s,%s,%s,line=%d\n",\
  8196. + #expr,__FILE__,__FUNCTION__,__LINE__); \
  8197. + }
  8198. +#else
  8199. +# define ASSERT(expr)
  8200. +#endif
  8201. +
  8202. +#if VERBOSITY
  8203. +#define PRINTKD(fmt, args...) printk( fmt , ## args)
  8204. +#else
  8205. +#define PRINTKD(fmt, args...)
  8206. +#endif
  8207. +
  8208. +/*================================================
  8209. + * USB Protocol Stuff
  8210. + */
  8211. +
  8212. +/* Request Codes */
  8213. +enum { GET_STATUS=0, CLEAR_FEATURE=1, SET_FEATURE=3,
  8214. + SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR=7,
  8215. + GET_CONFIGURATION=8, SET_CONFIGURATION=9, GET_INTERFACE=10,
  8216. + SET_INTERFACE=11 };
  8217. +
  8218. +
  8219. +/* USB Device Requests */
  8220. +typedef struct
  8221. +{
  8222. + __u8 bmRequestType;
  8223. + __u8 bRequest;
  8224. + __u16 wValue;
  8225. + __u16 wIndex;
  8226. + __u16 wLength;
  8227. +} usb_dev_request_t __attribute__ ((packed));
  8228. +
  8229. +/***************************************************************************
  8230. +Prototypes
  8231. +***************************************************************************/
  8232. +/* "setup handlers" -- the main functions dispatched to by the
  8233. + .. isr. These represent the major "modes" of endpoint 0 operaton */
  8234. +static void sh_setup_begin(void); /* setup begin (idle) */
  8235. +static void sh_write( void ); /* writing data */
  8236. +static void sh_write_with_empty_packet( void ); /* empty packet at end of xfer*/
  8237. +/* called before both sh_write routines above */
  8238. +static void common_write_preamble( void );
  8239. +
  8240. +/* other subroutines */
  8241. +static __u32 queue_and_start_write( void * p, int req, int act );
  8242. +static void write_fifo( void );
  8243. +static int read_fifo( usb_dev_request_t * p );
  8244. +static void get_descriptor( usb_dev_request_t * pReq );
  8245. +
  8246. +/* some voodo helpers 01Mar01ww */
  8247. +static void set_cs_bits( __u32 set_bits );
  8248. +static void set_de( void );
  8249. +static void set_ipr( void );
  8250. +static void set_ipr_and_de( void );
  8251. +static bool clear_opr( void );
  8252. +
  8253. +/***************************************************************************
  8254. +Inline Helpers
  8255. +***************************************************************************/
  8256. +
  8257. +/* Data extraction from usb_request_t fields */
  8258. +enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 };
  8259. +static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); }
  8260. +
  8261. +static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); }
  8262. +inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
  8263. +
  8264. +/* following is hook for self-powered flag in GET_STATUS. Some devices
  8265. + .. might like to override and return real info */
  8266. +static inline bool self_powered_hook( void ) { return true; }
  8267. +
  8268. +/* print string descriptor */
  8269. +static inline void psdesc( string_desc_t * p )
  8270. +{
  8271. + int i;
  8272. + int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
  8273. + printk( "'" );
  8274. + for( i = 0 ; i < nchars ; i++ ) {
  8275. + printk( "%c", (char) p->bString[i] );
  8276. + }
  8277. + printk( "'\n" );
  8278. +}
  8279. +
  8280. +
  8281. +#if VERBOSITY
  8282. +/* "pcs" == "print control status" */
  8283. +static inline void pcs( void )
  8284. +{
  8285. + __u32 foo = Ser0UDCCS0;
  8286. + printk( "%8.8X: %s %s %s %s\n",
  8287. + foo,
  8288. + foo & UDCCS0_SE ? "SE" : "",
  8289. + foo & UDCCS0_OPR ? "OPR" : "",
  8290. + foo & UDCCS0_IPR ? "IPR" : "",
  8291. + foo & UDCCS0_SST ? "SST" : ""
  8292. + );
  8293. +}
  8294. +static inline void preq( usb_dev_request_t * pReq )
  8295. +{
  8296. + static char * tnames[] = { "dev", "intf", "ep", "oth" };
  8297. + static char * rnames[] = { "std", "class", "vendor", "???" };
  8298. + char * psz;
  8299. + switch( pReq->bRequest ) {
  8300. + case GET_STATUS: psz = "get stat"; break;
  8301. + case CLEAR_FEATURE: psz = "clr feat"; break;
  8302. + case SET_FEATURE: psz = "set feat"; break;
  8303. + case SET_ADDRESS: psz = "set addr"; break;
  8304. + case GET_DESCRIPTOR: psz = "get desc"; break;
  8305. + case SET_DESCRIPTOR: psz = "set desc"; break;
  8306. + case GET_CONFIGURATION: psz = "get cfg"; break;
  8307. + case SET_CONFIGURATION: psz = "set cfg"; break;
  8308. + case GET_INTERFACE: psz = "get intf"; break;
  8309. + case SET_INTERFACE: psz = "set intf"; break;
  8310. + default: psz = "unknown"; break;
  8311. + }
  8312. + printk( "- [%s: %s req to %s. dir=%s]\n", psz,
  8313. + rnames[ (pReq->bmRequestType >> 5) & 3 ],
  8314. + tnames[ pReq->bmRequestType & 3 ],
  8315. + ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
  8316. +}
  8317. +
  8318. +#else
  8319. +static inline void pcs( void ){}
  8320. +static inline void preq( void ){}
  8321. +#endif
  8322. +
  8323. +/***************************************************************************
  8324. +Globals
  8325. +***************************************************************************/
  8326. +static const char pszMe[] = "usbep0: ";
  8327. +
  8328. +/* pointer to current setup handler */
  8329. +static void (*current_handler)(void) = sh_setup_begin;
  8330. +
  8331. +/* global write struct to keep write
  8332. + ..state around across interrupts */
  8333. +static struct {
  8334. + unsigned char *p;
  8335. + int bytes_left;
  8336. +} wr;
  8337. +
  8338. +/***************************************************************************
  8339. +Public Interface
  8340. +***************************************************************************/
  8341. +
  8342. +/* reset received from HUB (or controller just went nuts and reset by itself!)
  8343. + so udc core has been reset, track this state here */
  8344. +void
  8345. +ep0_reset(void)
  8346. +{
  8347. + /* reset state machine */
  8348. + current_handler = sh_setup_begin;
  8349. + wr.p = NULL;
  8350. + wr.bytes_left = 0;
  8351. + usbd_info.address=0;
  8352. +}
  8353. +
  8354. +/* handle interrupt for endpoint zero */
  8355. +void
  8356. +ep0_int_hndlr( void )
  8357. +{
  8358. + PRINTKD( "/\\(%d)\n", Ser0UDCAR );
  8359. + pcs();
  8360. +
  8361. + /* if not in setup begin, we are returning data.
  8362. + execute a common preamble to both write handlers
  8363. + */
  8364. + if ( current_handler != sh_setup_begin )
  8365. + common_write_preamble();
  8366. +
  8367. + (*current_handler)();
  8368. +
  8369. + PRINTKD( "---\n" );
  8370. + pcs();
  8371. + PRINTKD( "\\/\n" );
  8372. +}
  8373. +
  8374. +/***************************************************************************
  8375. +Setup Handlers
  8376. +***************************************************************************/
  8377. +/*
  8378. + * sh_setup_begin()
  8379. + * This setup handler is the "idle" state of endpoint zero. It looks for OPR
  8380. + * (OUT packet ready) to see if a setup request has been been received from the
  8381. + * host. Requests without a return data phase are immediately handled. Otherwise,
  8382. + * in the case of GET_XXXX the handler may be set to one of the sh_write_xxxx
  8383. + * data pumpers if more than 8 bytes need to get back to the host.
  8384. + *
  8385. + */
  8386. +static void
  8387. +sh_setup_begin( void )
  8388. +{
  8389. + unsigned char status_buf[2]; /* returned in GET_STATUS */
  8390. + usb_dev_request_t req;
  8391. + int request_type;
  8392. + int n;
  8393. + __u32 cs_bits;
  8394. + __u32 address;
  8395. + __u32 cs_reg_in = Ser0UDCCS0;
  8396. +
  8397. + if (cs_reg_in & UDCCS0_SST) {
  8398. + PRINTKD( "%ssetup begin: sent stall. Continuing\n", pszMe );
  8399. + set_cs_bits( UDCCS0_SST );
  8400. + }
  8401. +
  8402. + if ( cs_reg_in & UDCCS0_SE ) {
  8403. + PRINTKD( "%ssetup begin: Early term of setup. Continuing\n", pszMe );
  8404. + set_cs_bits( UDCCS0_SSE ); /* clear setup end */
  8405. + }
  8406. +
  8407. + /* Be sure out packet ready, otherwise something is wrong */
  8408. + if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
  8409. + /* we can get here early...if so, we'll int again in a moment */
  8410. + PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
  8411. + goto sh_sb_end;
  8412. + }
  8413. +
  8414. + /* read the setup request */
  8415. + n = read_fifo( &req );
  8416. + if ( n != sizeof( req ) ) {
  8417. + printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
  8418. + " Stalling out...\n",
  8419. + pszMe, sizeof( req ), n );
  8420. + /* force stall, serviced out */
  8421. + set_cs_bits( UDCCS0_FST | UDCCS0_SO );
  8422. + goto sh_sb_end;
  8423. + }
  8424. +
  8425. + /* Is it a standard request? (not vendor or class request) */
  8426. + request_type = type_code_from_request( req.bmRequestType );
  8427. + if ( request_type != 0 ) {
  8428. + printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
  8429. + pszMe, request_type );
  8430. + set_cs_bits( UDCCS0_DE | UDCCS0_SO );
  8431. + goto sh_sb_end;
  8432. + }
  8433. +
  8434. +#if VERBOSITY
  8435. + {
  8436. + unsigned char * pdb = (unsigned char *) &req;
  8437. + PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
  8438. + pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
  8439. + );
  8440. + preq( &req );
  8441. + }
  8442. +#endif
  8443. +
  8444. + /* Handle it */
  8445. + switch( req.bRequest ) {
  8446. +
  8447. + /* This first bunch have no data phase */
  8448. +
  8449. + case SET_ADDRESS:
  8450. + address = (__u32) (req.wValue & 0x7F);
  8451. + /* when SO and DE sent, UDC will enter status phase and ack,
  8452. + ..propagating new address to udc core. Next control transfer
  8453. + ..will be on the new address. You can't see the change in a
  8454. + ..read back of CAR until then. (about 250us later, on my box).
  8455. + ..The original Intel driver sets S0 and DE and code to check
  8456. + ..that address has propagated here. I tried this, but it
  8457. + ..would only work sometimes! The rest of the time it would
  8458. + ..never propagate and we'd spin forever. So now I just set
  8459. + ..it and pray...
  8460. + */
  8461. + Ser0UDCAR = address;
  8462. + usbd_info.address = address;
  8463. + usbctl_next_state_on_event( kEvAddress );
  8464. + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
  8465. + printk( "%sI have been assigned address: %d\n", pszMe, address );
  8466. + break;
  8467. +
  8468. +
  8469. + case SET_CONFIGURATION:
  8470. + if ( req.wValue == 1 ) {
  8471. + /* configured */
  8472. + if (usbctl_next_state_on_event( kEvConfig ) != kError){
  8473. + /* (re)set the out and in max packet sizes */
  8474. + desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
  8475. + __u32 out = __le16_to_cpu( pDesc->b.ep1.wMaxPacketSize );
  8476. + __u32 in = __le16_to_cpu( pDesc->b.ep2.wMaxPacketSize );
  8477. + Ser0UDCOMP = ( out - 1 );
  8478. + Ser0UDCIMP = ( in - 1 );
  8479. + printk( "%sConfigured (OMP=%8.8X IMP=%8.8X)\n", pszMe, out, in );
  8480. + }
  8481. + } else if ( req.wValue == 0 ) {
  8482. + /* de-configured */
  8483. + if (usbctl_next_state_on_event( kEvDeConfig ) != kError )
  8484. + printk( "%sDe-Configured\n", pszMe );
  8485. + } else {
  8486. + printk( "%ssetup phase: Unknown "
  8487. + "\"set configuration\" data %d\n",
  8488. + pszMe, req.wValue );
  8489. + }
  8490. + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
  8491. + break;
  8492. +
  8493. + case CLEAR_FEATURE:
  8494. + /* could check data length, direction...26Jan01ww */
  8495. + if ( req.wValue == 0 ) { /* clearing ENDPOINT_HALT/STALL */
  8496. + int ep = windex_to_ep_num( req.wIndex );
  8497. + if ( ep == 1 ) {
  8498. + printk( "%sclear feature \"endpoint halt\" "
  8499. + " on receiver\n", pszMe );
  8500. + ep1_reset();
  8501. + }
  8502. + else if ( ep == 2 ) {
  8503. + printk( "%sclear feature \"endpoint halt\" "
  8504. + "on xmitter\n", pszMe );
  8505. + ep2_reset();
  8506. + } else {
  8507. + printk( "%sclear feature \"endpoint halt\" "
  8508. + "on unsupported ep # %d\n",
  8509. + pszMe, ep );
  8510. + }
  8511. + } else {
  8512. + printk( "%sUnsupported feature selector (%d) "
  8513. + "in clear feature. Ignored.\n" ,
  8514. + pszMe, req.wValue );
  8515. + }
  8516. + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
  8517. + break;
  8518. +
  8519. + case SET_FEATURE:
  8520. + if ( req.wValue == 0 ) { /* setting ENDPOINT_HALT/STALL */
  8521. + int ep = windex_to_ep_num( req.wValue );
  8522. + if ( ep == 1 ) {
  8523. + printk( "%set feature \"endpoint halt\" "
  8524. + "on receiver\n", pszMe );
  8525. + ep1_stall();
  8526. + }
  8527. + else if ( ep == 2 ) {
  8528. + printk( "%sset feature \"endpoint halt\" "
  8529. + " on xmitter\n", pszMe );
  8530. + ep2_stall();
  8531. + } else {
  8532. + printk( "%sset feature \"endpoint halt\" "
  8533. + "on unsupported ep # %d\n",
  8534. + pszMe, ep );
  8535. + }
  8536. + }
  8537. + else {
  8538. + printk( "%sUnsupported feature selector "
  8539. + "(%d) in set feature\n",
  8540. + pszMe, req.wValue );
  8541. + }
  8542. + set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
  8543. + break;
  8544. +
  8545. +
  8546. + /* The rest have a data phase that writes back to the host */
  8547. + case GET_STATUS:
  8548. + /* return status bit flags */
  8549. + status_buf[0] = status_buf[1] = 0;
  8550. + n = request_target(req.bmRequestType);
  8551. + switch( n ) {
  8552. + case kTargetDevice:
  8553. + if ( self_powered_hook() )
  8554. + status_buf[0] |= 1;
  8555. + break;
  8556. + case kTargetInterface:
  8557. + break;
  8558. + case kTargetEndpoint:
  8559. + /* return stalled bit */
  8560. + n = windex_to_ep_num( req.wIndex );
  8561. + if ( n == 1 )
  8562. + status_buf[0] |= (Ser0UDCCS1 & UDCCS1_FST) >> 4;
  8563. + else if ( n == 2 )
  8564. + status_buf[0] |= (Ser0UDCCS2 & UDCCS2_FST) >> 5;
  8565. + else {
  8566. + printk( "%sUnknown endpoint (%d) "
  8567. + "in GET_STATUS\n", pszMe, n );
  8568. + }
  8569. + break;
  8570. + default:
  8571. + printk( "%sUnknown target (%d) in GET_STATUS\n",
  8572. + pszMe, n );
  8573. + /* fall thru */
  8574. + break;
  8575. + }
  8576. + cs_bits = queue_and_start_write( status_buf,
  8577. + req.wLength,
  8578. + sizeof( status_buf ) );
  8579. + set_cs_bits( cs_bits );
  8580. + break;
  8581. + case GET_DESCRIPTOR:
  8582. + get_descriptor( &req );
  8583. + break;
  8584. +
  8585. + case GET_CONFIGURATION:
  8586. + status_buf[0] = (usbd_info.state == USB_STATE_CONFIGURED)
  8587. + ? 1
  8588. + : 0;
  8589. + cs_bits = queue_and_start_write( status_buf, req.wLength, 1 );
  8590. + set_cs_bits( cs_bits );
  8591. + break;
  8592. + case GET_INTERFACE:
  8593. + printk( "%sfixme: get interface not supported\n", pszMe );
  8594. + cs_bits = queue_and_start_write( NULL, req.wLength, 0 );
  8595. + set_cs_bits( cs_bits );
  8596. + break;
  8597. + case SET_INTERFACE:
  8598. + printk( "%sfixme: set interface not supported\n", pszMe );
  8599. + set_cs_bits( UDCCS0_DE | UDCCS0_SO );
  8600. + break;
  8601. + default :
  8602. + printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
  8603. + break;
  8604. + } /* switch( bRequest ) */
  8605. +
  8606. +sh_sb_end:
  8607. + return;
  8608. +
  8609. +}
  8610. +/*
  8611. + * common_wrtie_preamble()
  8612. + * Called before execution of sh_write() or sh_write_with_empty_packet()
  8613. + * Handles common abort conditions.
  8614. + *
  8615. + */
  8616. +static void common_write_preamble( void )
  8617. +{
  8618. + /* If "setup end" has been set, the usb controller has
  8619. + ..terminated a setup transaction before we set DE. This
  8620. + ..happens during enumeration with some hosts. For example,
  8621. + ..the host will ask for our device descriptor and specify
  8622. + ..a return of 64 bytes. When we hand back the first 8, the
  8623. + ..host will know our max packet size and turn around and
  8624. + ..issue a new setup immediately. This causes the UDC to auto-ack
  8625. + ..the new setup and set SE. We must then "unload" (process)
  8626. + ..the new setup, which is what will happen after this preamble
  8627. + ..is finished executing.
  8628. + */
  8629. + __u32 cs_reg_in = Ser0UDCCS0;
  8630. +
  8631. + if ( cs_reg_in & UDCCS0_SE ) {
  8632. + PRINTKD( "%swrite_preamble(): Early termination of setup\n", pszMe );
  8633. + Ser0UDCCS0 = UDCCS0_SSE; /* clear setup end */
  8634. + current_handler = sh_setup_begin;
  8635. + }
  8636. +
  8637. + if ( cs_reg_in & UDCCS0_SST ) {
  8638. + PRINTKD( "%swrite_preamble(): UDC sent stall\n", pszMe );
  8639. + Ser0UDCCS0 = UDCCS0_SST; /* clear setup end */
  8640. + current_handler = sh_setup_begin;
  8641. + }
  8642. +
  8643. + if ( cs_reg_in & UDCCS0_OPR ) {
  8644. + PRINTKD( "%swrite_preamble(): see OPR. Stopping write to "
  8645. + "handle new SETUP\n", pszMe );
  8646. + /* very rarely, you can get OPR and leftover IPR. Try to clear */
  8647. + UDC_clear( Ser0UDCCS0, UDCCS0_IPR );
  8648. + current_handler = sh_setup_begin;
  8649. + }
  8650. +}
  8651. +
  8652. +/*
  8653. + * sh_write()
  8654. + * This is the setup handler when we are in the data return phase of
  8655. + * a setup request and have as much (or more) data than the host
  8656. + * requested. If we enter this routine and bytes left is zero, the
  8657. + * last data packet has gone (int is because IPR was just cleared)
  8658. + * so we just set DE and reset. Otheriwse, we write another packet
  8659. + * and set IPR.
  8660. + */
  8661. +static void sh_write()
  8662. +{
  8663. + PRINTKD( "W\n" );
  8664. +
  8665. + if ( Ser0UDCCS0 & UDCCS0_IPR ) {
  8666. + PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
  8667. + return;
  8668. + }
  8669. +
  8670. + /* If bytes left is zero, we are coming in on the
  8671. + ..interrupt after the last packet went out. And
  8672. + ..we know we don't have to empty packet this transfer
  8673. + ..so just set DE and we are done */
  8674. +
  8675. + if ( 0 == wr.bytes_left ) {
  8676. + /* that's it, so data end */
  8677. + set_de();
  8678. + wr.p = NULL; /* be anal */
  8679. + current_handler = sh_setup_begin;
  8680. + } else {
  8681. + /* Otherwise, more data to go */
  8682. + write_fifo();
  8683. + set_ipr();
  8684. + }
  8685. +}
  8686. +/*
  8687. + * sh_write_with_empty_packet()
  8688. + * This is the setup handler when we don't have enough data to
  8689. + * satisfy the host's request. After we send everything we've got
  8690. + * we must send an empty packet (by setting IPR and DE) so the
  8691. + * host can perform "short packet retirement" and not stall.
  8692. + *
  8693. + */
  8694. +static void sh_write_with_empty_packet( void )
  8695. +{
  8696. + __u32 cs_reg_out = 0;
  8697. + PRINTKD( "WE\n" );
  8698. +
  8699. + if ( Ser0UDCCS0 & UDCCS0_IPR ) {
  8700. + PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
  8701. + return;
  8702. + }
  8703. +
  8704. + /* If bytes left is zero, we are coming in on the
  8705. + ..interrupt after the last packet went out.
  8706. + ..we must do short packet suff, so set DE and IPR
  8707. + */
  8708. +
  8709. + if ( 0 == wr.bytes_left ) {
  8710. + set_ipr_and_de();
  8711. + wr.p = NULL;
  8712. + current_handler = sh_setup_begin;
  8713. + PRINTKD( "%ssh_write empty() Sent empty packet \n", pszMe );
  8714. + } else {
  8715. + write_fifo(); /* send data */
  8716. + set_ipr(); /* flag a packet is ready */
  8717. + }
  8718. + Ser0UDCCS0 = cs_reg_out;
  8719. +}
  8720. +
  8721. +/***************************************************************************
  8722. +Other Private Subroutines
  8723. +***************************************************************************/
  8724. +/*
  8725. + * queue_and_start_write()
  8726. + * p == data to send
  8727. + * req == bytes host requested
  8728. + * act == bytes we actually have
  8729. + * Returns: bits to be flipped in ep0 control/status register
  8730. + *
  8731. + * Called from sh_setup_begin() to begin a data return phase. Sets up the
  8732. + * global "wr"-ite structure and load the outbound FIFO with data.
  8733. + * If can't send all the data, set appropriate handler for next interrupt.
  8734. + *
  8735. + */
  8736. +static __u32 queue_and_start_write( void * in, int req, int act )
  8737. +{
  8738. + __u32 cs_reg_bits = UDCCS0_IPR;
  8739. + unsigned char * p = (unsigned char*) in;
  8740. +
  8741. + PRINTKD( "Qr=%d a=%d\n",req,act );
  8742. +
  8743. + /* thou shalt not enter data phase until the serviced OUT is clear */
  8744. + if ( ! clear_opr() ) {
  8745. + printk( "%sSO did not clear OPR\n", pszMe );
  8746. + return ( UDCCS0_DE | UDCCS0_SO ) ;
  8747. + }
  8748. + wr.p = p;
  8749. + wr.bytes_left = MIN( act, req );
  8750. +
  8751. + write_fifo();
  8752. +
  8753. + if ( 0 == wr.bytes_left ) {
  8754. + cs_reg_bits |= UDCCS0_DE; /* out in 1 so data end */
  8755. + wr.p = NULL; /* be anal */
  8756. + }
  8757. + else if ( act < req ) /* we are going to short-change host */
  8758. + current_handler = sh_write_with_empty_packet; /* so need nul to not stall */
  8759. + else /* we have as much or more than requested */
  8760. + current_handler = sh_write;
  8761. +
  8762. + return cs_reg_bits; /* note: IPR was set uncondtionally at start of routine */
  8763. +}
  8764. +/*
  8765. + * write_fifo()
  8766. + * Stick bytes in the 8 bytes endpoint zero FIFO.
  8767. + * This version uses a variety of tricks to make sure the bytes
  8768. + * are written correctly. 1. The count register is checked to
  8769. + * see if the byte went in, and the write is attempted again
  8770. + * if not. 2. An overall counter is used to break out so we
  8771. + * don't hang in those (rare) cases where the UDC reverses
  8772. + * direction of the FIFO underneath us without notification
  8773. + * (in response to host aborting a setup transaction early).
  8774. + *
  8775. + */
  8776. +static void write_fifo( void )
  8777. +{
  8778. + int bytes_this_time = MIN( wr.bytes_left, 8 );
  8779. + int bytes_written = 0;
  8780. + int i=0;
  8781. +
  8782. + PRINTKD( "WF=%d: ", bytes_this_time );
  8783. +
  8784. + while( bytes_this_time-- ) {
  8785. + PRINTKD( "%2.2X ", *wr.p );
  8786. + i = 0;
  8787. + do {
  8788. + Ser0UDCD0 = *wr.p;
  8789. + udelay( 20 ); /* voodo 28Feb01ww */
  8790. + i++;
  8791. + } while( Ser0UDCWC == bytes_written && i < 10 );
  8792. + if ( i == 50 ) {
  8793. + printk( "%swrite_fifo: write failure\n", pszMe );
  8794. + usbd_info.stats.ep0_fifo_write_failures++;
  8795. + }
  8796. +
  8797. + wr.p++;
  8798. + bytes_written++;
  8799. + }
  8800. + wr.bytes_left -= bytes_written;
  8801. +
  8802. + /* following propagation voodo so maybe caller writing IPR in
  8803. + ..a moment might actually get it to stick 28Feb01ww */
  8804. + udelay( 300 );
  8805. +
  8806. + usbd_info.stats.ep0_bytes_written += bytes_written;
  8807. + PRINTKD( "L=%d WCR=%8.8X\n", wr.bytes_left, Ser0UDCWC );
  8808. +}
  8809. +/*
  8810. + * read_fifo()
  8811. + * Read 1-8 bytes out of FIFO and put in request.
  8812. + * Called to do the initial read of setup requests
  8813. + * from the host. Return number of bytes read.
  8814. + *
  8815. + * Like write fifo above, this driver uses multiple
  8816. + * reads checked agains the count register with an
  8817. + * overall timeout.
  8818. + *
  8819. + */
  8820. +static int
  8821. +read_fifo( usb_dev_request_t * request )
  8822. +{
  8823. + int bytes_read = 0;
  8824. + int fifo_count;
  8825. + int i;
  8826. +
  8827. + unsigned char * pOut = (unsigned char*) request;
  8828. +
  8829. + fifo_count = ( Ser0UDCWC & 0xFF );
  8830. +
  8831. + ASSERT( fifo_count <= 8 );
  8832. + PRINTKD( "RF=%d ", fifo_count );
  8833. +
  8834. + while( fifo_count-- ) {
  8835. + i = 0;
  8836. + do {
  8837. + *pOut = (unsigned char) Ser0UDCD0;
  8838. + udelay( 10 );
  8839. + } while( ( Ser0UDCWC & 0xFF ) != fifo_count && i < 10 );
  8840. + if ( i == 10 ) {
  8841. + printk( "%sread_fifo(): read failure\n", pszMe );
  8842. + usbd_info.stats.ep0_fifo_read_failures++;
  8843. + }
  8844. + pOut++;
  8845. + bytes_read++;
  8846. + }
  8847. +
  8848. + PRINTKD( "fc=%d\n", bytes_read );
  8849. + usbd_info.stats.ep0_bytes_read++;
  8850. + return bytes_read;
  8851. +}
  8852. +
  8853. +/*
  8854. + * get_descriptor()
  8855. + * Called from sh_setup_begin to handle data return
  8856. + * for a GET_DESCRIPTOR setup request.
  8857. + */
  8858. +static void get_descriptor( usb_dev_request_t * pReq )
  8859. +{
  8860. + __u32 cs_bits = 0;
  8861. + string_desc_t * pString;
  8862. + ep_desc_t * pEndpoint;
  8863. +
  8864. + desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
  8865. + int type = pReq->wValue >> 8;
  8866. + int idx = pReq->wValue & 0xFF;
  8867. +
  8868. + switch( type ) {
  8869. + case USB_DESC_DEVICE:
  8870. + cs_bits =
  8871. + queue_and_start_write( &pDesc->dev,
  8872. + pReq->wLength,
  8873. + pDesc->dev.bLength );
  8874. + break;
  8875. +
  8876. + // return config descriptor buffer, cfg, intf, 2 ep
  8877. + case USB_DESC_CONFIG:
  8878. + cs_bits =
  8879. + queue_and_start_write( &pDesc->b,
  8880. + pReq->wLength,
  8881. + sizeof( struct cdb ) );
  8882. + break;
  8883. +
  8884. + // not quite right, since doesn't do language code checking
  8885. + case USB_DESC_STRING:
  8886. + pString = sa1100_usb_get_string_descriptor( idx );
  8887. + if ( pString ) {
  8888. + if ( idx != 0 ) { // if not language index
  8889. + printk( "%sReturn string %d: ", pszMe, idx );
  8890. + psdesc( pString );
  8891. + }
  8892. + cs_bits =
  8893. + queue_and_start_write( pString,
  8894. + pReq->wLength,
  8895. + pString->bLength );
  8896. + }
  8897. + else {
  8898. + printk("%sunkown string index %d Stall.\n", pszMe, idx );
  8899. + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
  8900. + }
  8901. + break;
  8902. +
  8903. + case USB_DESC_INTERFACE:
  8904. + if ( idx == pDesc->b.intf.bInterfaceNumber ) {
  8905. + cs_bits =
  8906. + queue_and_start_write( &pDesc->b.intf,
  8907. + pReq->wLength,
  8908. + pDesc->b.intf.bLength );
  8909. + }
  8910. + break;
  8911. +
  8912. + case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
  8913. + if ( idx == 1 )
  8914. + pEndpoint = &pDesc->b.ep1;
  8915. + else if ( idx == 2 )
  8916. + pEndpoint = &pDesc->b.ep2;
  8917. + else
  8918. + pEndpoint = NULL;
  8919. + if ( pEndpoint ) {
  8920. + cs_bits =
  8921. + queue_and_start_write( pEndpoint,
  8922. + pReq->wLength,
  8923. + pEndpoint->bLength );
  8924. + } else {
  8925. + printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
  8926. + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
  8927. + }
  8928. + break;
  8929. +
  8930. +
  8931. + default :
  8932. + printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
  8933. + cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
  8934. + break;
  8935. +
  8936. + }
  8937. + set_cs_bits( cs_bits );
  8938. +}
  8939. +
  8940. +
  8941. +/* some voodo I am adding, since the vanilla macros just aren't doing it 1Mar01ww */
  8942. +
  8943. +#define ABORT_BITS ( UDCCS0_SST | UDCCS0_SE )
  8944. +#define OK_TO_WRITE (!( Ser0UDCCS0 & ABORT_BITS ))
  8945. +#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE)
  8946. +
  8947. +static void set_cs_bits( __u32 bits )
  8948. +{
  8949. + if ( bits & ( UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST ) )
  8950. + Ser0UDCCS0 = bits;
  8951. + else if ( (bits & BOTH_BITS) == BOTH_BITS )
  8952. + set_ipr_and_de();
  8953. + else if ( bits & UDCCS0_IPR )
  8954. + set_ipr();
  8955. + else if ( bits & UDCCS0_DE )
  8956. + set_de();
  8957. +}
  8958. +
  8959. +static void set_de( void )
  8960. +{
  8961. + int i = 1;
  8962. + while( 1 ) {
  8963. + if ( OK_TO_WRITE ) {
  8964. + Ser0UDCCS0 |= UDCCS0_DE;
  8965. + } else {
  8966. + PRINTKD( "%sQuitting set DE because SST or SE set\n", pszMe );
  8967. + break;
  8968. + }
  8969. + if ( Ser0UDCCS0 & UDCCS0_DE )
  8970. + break;
  8971. + udelay( i );
  8972. + if ( ++i == 50 ) {
  8973. + printk( "%sDangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8X)\n",
  8974. + pszMe, UDCCS0_DE, Ser0UDCCS0 );
  8975. + break;
  8976. + }
  8977. + }
  8978. +}
  8979. +
  8980. +static void set_ipr( void )
  8981. +{
  8982. + int i = 1;
  8983. + while( 1 ) {
  8984. + if ( OK_TO_WRITE ) {
  8985. + Ser0UDCCS0 |= UDCCS0_IPR;
  8986. + } else {
  8987. + PRINTKD( "%sQuitting set IPR because SST or SE set\n", pszMe );
  8988. + break;
  8989. + }
  8990. + if ( Ser0UDCCS0 & UDCCS0_IPR )
  8991. + break;
  8992. + udelay( i );
  8993. + if ( ++i == 50 ) {
  8994. + printk( "%sDangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8X)\n",
  8995. + pszMe, UDCCS0_IPR, Ser0UDCCS0 );
  8996. + break;
  8997. + }
  8998. + }
  8999. +}
  9000. +
  9001. +
  9002. +
  9003. +static void set_ipr_and_de( void )
  9004. +{
  9005. + int i = 1;
  9006. + while( 1 ) {
  9007. + if ( OK_TO_WRITE ) {
  9008. + Ser0UDCCS0 |= BOTH_BITS;
  9009. + } else {
  9010. + PRINTKD( "%sQuitting set IPR/DE because SST or SE set\n", pszMe );
  9011. + break;
  9012. + }
  9013. + if ( (Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS)
  9014. + break;
  9015. + udelay( i );
  9016. + if ( ++i == 50 ) {
  9017. + printk( "%sDangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8X)\n",
  9018. + pszMe, UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0 );
  9019. + break;
  9020. + }
  9021. + }
  9022. +}
  9023. +
  9024. +static bool clear_opr( void )
  9025. +{
  9026. + int i = 10000;
  9027. + bool is_clear;
  9028. + do {
  9029. + Ser0UDCCS0 = UDCCS0_SO;
  9030. + is_clear = ! ( Ser0UDCCS0 & UDCCS0_OPR );
  9031. + if ( i-- <= 0 ) {
  9032. + printk( "%sclear_opr(): failed\n", pszMe );
  9033. + break;
  9034. + }
  9035. + } while( ! is_clear );
  9036. + return is_clear;
  9037. +}
  9038. +
  9039. +
  9040. +
  9041. +
  9042. +
  9043. +/* end usb_ep0.c */
  9044. +
  9045. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb_recv.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_recv.c
  9046. --- linux-2.4.26/arch/arm/mach-sa1100/usb_recv.c 1970-01-01 01:00:00.000000000 +0100
  9047. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_recv.c 2004-01-14 21:32:24.000000000 +0000
  9048. @@ -0,0 +1,205 @@
  9049. +/*
  9050. + * Generic receive layer for the SA1100 USB client function
  9051. + * Copyright (c) 2001 by Nicolas Pitre
  9052. + *
  9053. + * This code was loosely inspired by the original version which was
  9054. + * Copyright (c) Compaq Computer Corporation, 1998-1999
  9055. + *
  9056. + * This program is free software; you can redistribute it and/or modify
  9057. + * it under the terms of the GNU General Public License version 2 as
  9058. + * published by the Free Software Foundation.
  9059. + *
  9060. + * This is still work in progress...
  9061. + *
  9062. + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
  9063. + */
  9064. +
  9065. +#include <linux/module.h>
  9066. +#include <linux/pci.h>
  9067. +#include <linux/errno.h>
  9068. +#include <asm/dma.h>
  9069. +#include <asm/system.h>
  9070. +
  9071. +#include "sa1100_usb.h"
  9072. +#include "usb_ctl.h"
  9073. +
  9074. +
  9075. +static char *ep1_buf;
  9076. +static int ep1_len;
  9077. +static usb_callback_t ep1_callback;
  9078. +static char *ep1_curdmabuf;
  9079. +static dma_addr_t ep1_curdmapos;
  9080. +static int ep1_curdmalen;
  9081. +static int ep1_remain;
  9082. +static int dmachn_rx;
  9083. +static int rx_pktsize;
  9084. +
  9085. +static int naking;
  9086. +
  9087. +static void
  9088. +ep1_start(void)
  9089. +{
  9090. + sa1100_dma_flush_all(dmachn_rx);
  9091. + if (!ep1_curdmalen) {
  9092. + ep1_curdmalen = rx_pktsize;
  9093. + if (ep1_curdmalen > ep1_remain)
  9094. + ep1_curdmalen = ep1_remain;
  9095. + ep1_curdmapos = pci_map_single(NULL, ep1_curdmabuf, ep1_curdmalen,
  9096. + PCI_DMA_FROMDEVICE);
  9097. + }
  9098. + sa1100_dma_queue_buffer(dmachn_rx, NULL, ep1_curdmapos, ep1_curdmalen);
  9099. + if ( naking ) {
  9100. + /* turn off NAK of OUT packets, if set */
  9101. + UDC_flip( Ser0UDCCS1, UDCCS1_RPC );
  9102. + naking = 0;
  9103. + }
  9104. +}
  9105. +
  9106. +static void
  9107. +ep1_done(int flag)
  9108. +{
  9109. + int size = ep1_len - ep1_remain;
  9110. +
  9111. + if (!ep1_len)
  9112. + return;
  9113. + if (ep1_curdmalen)
  9114. + pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
  9115. + PCI_DMA_FROMDEVICE);
  9116. + ep1_len = ep1_curdmalen = 0;
  9117. + if (ep1_callback) {
  9118. + ep1_callback(flag, size);
  9119. + }
  9120. +}
  9121. +
  9122. +void
  9123. +ep1_state_change_notify( int new_state )
  9124. +{
  9125. +
  9126. +}
  9127. +
  9128. +void
  9129. +ep1_stall( void )
  9130. +{
  9131. + /* SET_FEATURE force stall at UDC */
  9132. + UDC_set( Ser0UDCCS1, UDCCS1_FST );
  9133. +}
  9134. +
  9135. +int
  9136. +ep1_init(int chn)
  9137. +{
  9138. + desc_t * pd = sa1100_usb_get_descriptor_ptr();
  9139. + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
  9140. + dmachn_rx = chn;
  9141. + sa1100_dma_flush_all(dmachn_rx);
  9142. + ep1_done(-EAGAIN);
  9143. + return 0;
  9144. +}
  9145. +
  9146. +void
  9147. +ep1_reset(void)
  9148. +{
  9149. + desc_t * pd = sa1100_usb_get_descriptor_ptr();
  9150. + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
  9151. + sa1100_dma_flush_all(dmachn_rx);
  9152. + UDC_clear(Ser0UDCCS1, UDCCS1_FST);
  9153. + ep1_done(-EINTR);
  9154. +}
  9155. +
  9156. +void
  9157. +ep1_int_hndlr(int udcsr)
  9158. +{
  9159. + dma_addr_t dma_addr;
  9160. + unsigned int len;
  9161. + int status = Ser0UDCCS1;
  9162. +
  9163. + if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );
  9164. +
  9165. + if (status & UDCCS1_RPC) {
  9166. +
  9167. + if (!ep1_curdmalen) {
  9168. + printk("usb_recv: RPC for non-existent buffer\n");
  9169. + naking=1;
  9170. + return;
  9171. + }
  9172. +
  9173. + sa1100_dma_stop(dmachn_rx);
  9174. +
  9175. + if (status & UDCCS1_SST) {
  9176. + printk("usb_recv: stall sent OMP=%d\n",Ser0UDCOMP);
  9177. + UDC_flip(Ser0UDCCS1, UDCCS1_SST);
  9178. + ep1_done(-EIO); // UDC aborted current transfer, so we do
  9179. + return;
  9180. + }
  9181. +
  9182. + if (status & UDCCS1_RPE) {
  9183. + printk("usb_recv: RPError %x\n", status);
  9184. + UDC_flip(Ser0UDCCS1, UDCCS1_RPC);
  9185. + ep1_done(-EIO);
  9186. + return;
  9187. + }
  9188. +
  9189. + sa1100_dma_get_current(dmachn_rx, NULL, &dma_addr);
  9190. + pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
  9191. + PCI_DMA_FROMDEVICE);
  9192. + len = dma_addr - ep1_curdmapos;
  9193. + if (len < ep1_curdmalen) {
  9194. + char *buf = ep1_curdmabuf + len;
  9195. + while (Ser0UDCCS1 & UDCCS1_RNE) {
  9196. + if (len >= ep1_curdmalen) {
  9197. + printk("usb_recv: too much data in fifo\n");
  9198. + break;
  9199. + }
  9200. + *buf++ = Ser0UDCDR;
  9201. + len++;
  9202. + }
  9203. + } else if (Ser0UDCCS1 & UDCCS1_RNE) {
  9204. + printk("usb_recv: fifo screwed, shouldn't contain data\n");
  9205. + len = 0;
  9206. + }
  9207. + ep1_curdmalen = 0; /* dma unmap already done */
  9208. + ep1_remain -= len;
  9209. + naking = 1;
  9210. + ep1_done((len) ? 0 : -EPIPE);
  9211. + }
  9212. + /* else, you can get here if we are holding NAK */
  9213. +}
  9214. +
  9215. +int
  9216. +sa1100_usb_recv(char *buf, int len, usb_callback_t callback)
  9217. +{
  9218. + int flags;
  9219. +
  9220. + if (ep1_len)
  9221. + return -EBUSY;
  9222. +
  9223. + local_irq_save(flags);
  9224. + ep1_buf = buf;
  9225. + ep1_len = len;
  9226. + ep1_callback = callback;
  9227. + ep1_remain = len;
  9228. + ep1_curdmabuf = buf;
  9229. + ep1_curdmalen = 0;
  9230. + ep1_start();
  9231. + local_irq_restore(flags);
  9232. +
  9233. + return 0;
  9234. +}
  9235. +
  9236. +EXPORT_SYMBOL(sa1100_usb_recv);
  9237. +
  9238. +void
  9239. +sa1100_usb_recv_reset(void)
  9240. +{
  9241. + ep1_reset();
  9242. +}
  9243. +
  9244. +EXPORT_SYMBOL(sa1100_usb_recv_reset);
  9245. +
  9246. +void
  9247. +sa1100_usb_recv_stall(void)
  9248. +{
  9249. + ep1_stall();
  9250. +}
  9251. +
  9252. +EXPORT_SYMBOL(sa1100_usb_recv_stall);
  9253. +
  9254. diff -urN linux-2.4.26/arch/arm/mach-sa1100/usb_send.c linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_send.c
  9255. --- linux-2.4.26/arch/arm/mach-sa1100/usb_send.c 1970-01-01 01:00:00.000000000 +0100
  9256. +++ linux-2.4.26-vrs1/arch/arm/mach-sa1100/usb_send.c 2004-01-14 21:32:24.000000000 +0000
  9257. @@ -0,0 +1,205 @@
  9258. +/*
  9259. + * Generic xmit layer for the SA1100 USB client function
  9260. + * Copyright (c) 2001 by Nicolas Pitre
  9261. + *
  9262. + * This code was loosely inspired by the original version which was
  9263. + * Copyright (c) Compaq Computer Corporation, 1998-1999
  9264. + *
  9265. + * This program is free software; you can redistribute it and/or modify
  9266. + * it under the terms of the GNU General Public License version 2 as
  9267. + * published by the Free Software Foundation.
  9268. + *
  9269. + * This is still work in progress...
  9270. + *
  9271. + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
  9272. + * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware
  9273. + * bug, I think. green@iXcelerator.com
  9274. + */
  9275. +
  9276. +#include <linux/module.h>
  9277. +#include <linux/pci.h>
  9278. +#include <linux/errno.h>
  9279. +#include <linux/delay.h> // for the massive_attack hack 28Feb01ww
  9280. +#include <asm/hardware.h>
  9281. +#include <asm/dma.h>
  9282. +#include <asm/system.h>
  9283. +#include <asm/byteorder.h>
  9284. +
  9285. +#include "sa1100_usb.h"
  9286. +#include "usb_ctl.h"
  9287. +
  9288. +
  9289. +static char *ep2_buf;
  9290. +static int ep2_len;
  9291. +static usb_callback_t ep2_callback;
  9292. +static dma_addr_t ep2_dma;
  9293. +static dma_addr_t ep2_curdmapos;
  9294. +static int ep2_curdmalen;
  9295. +static int ep2_remain;
  9296. +static int dmachn_tx;
  9297. +static int tx_pktsize;
  9298. +
  9299. +/* device state is changing, async */
  9300. +void
  9301. +ep2_state_change_notify( int new_state )
  9302. +{
  9303. +}
  9304. +
  9305. +/* set feature stall executing, async */
  9306. +void
  9307. +ep2_stall( void )
  9308. +{
  9309. + UDC_set( Ser0UDCCS2, UDCCS2_FST ); /* force stall at UDC */
  9310. +}
  9311. +
  9312. +static void
  9313. +ep2_start(void)
  9314. +{
  9315. + if (!ep2_len)
  9316. + return;
  9317. +
  9318. + ep2_curdmalen = tx_pktsize;
  9319. + if (ep2_curdmalen > ep2_remain)
  9320. + ep2_curdmalen = ep2_remain;
  9321. +
  9322. + /* must do this _before_ queue buffer.. */
  9323. + UDC_flip( Ser0UDCCS2,UDCCS2_TPC ); /* stop NAKing IN tokens */
  9324. + UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
  9325. +
  9326. + /* Remove if never seen...8Mar01ww */
  9327. + {
  9328. + int massive_attack = 20;
  9329. + while ( Ser0UDCIMP != ep2_curdmalen-1 && massive_attack-- ) {
  9330. + printk( "usbsnd: Oh no you don't! Let me spin..." );
  9331. + udelay( 500 );
  9332. + printk( "and try again...\n" );
  9333. + UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
  9334. + }
  9335. + if ( massive_attack != 20 ) {
  9336. + if ( Ser0UDCIMP != ep2_curdmalen-1 )
  9337. + printk( "usbsnd: Massive attack FAILED :-( %d\n",
  9338. + 20 - massive_attack );
  9339. + else
  9340. + printk( "usbsnd: Massive attack WORKED :-) %d\n",
  9341. + 20 - massive_attack );
  9342. + }
  9343. + }
  9344. + /* End remove if never seen... 8Mar01ww */
  9345. +
  9346. + Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug
  9347. + sa1100_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen);
  9348. +}
  9349. +
  9350. +static void
  9351. +ep2_done(int flag)
  9352. +{
  9353. + int size = ep2_len - ep2_remain;
  9354. + if (ep2_len) {
  9355. + pci_unmap_single(NULL, ep2_dma, ep2_len, PCI_DMA_TODEVICE);
  9356. + ep2_len = 0;
  9357. + if (ep2_callback)
  9358. + ep2_callback(flag, size);
  9359. + }
  9360. +}
  9361. +
  9362. +int
  9363. +ep2_init(int chn)
  9364. +{
  9365. + desc_t * pd = sa1100_usb_get_descriptor_ptr();
  9366. + tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
  9367. + dmachn_tx = chn;
  9368. + sa1100_dma_flush_all(dmachn_tx);
  9369. + ep2_done(-EAGAIN);
  9370. + return 0;
  9371. +}
  9372. +
  9373. +void
  9374. +ep2_reset(void)
  9375. +{
  9376. + desc_t * pd = sa1100_usb_get_descriptor_ptr();
  9377. + tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
  9378. + UDC_clear(Ser0UDCCS2, UDCCS2_FST);
  9379. + sa1100_dma_flush_all(dmachn_tx);
  9380. + ep2_done(-EINTR);
  9381. +}
  9382. +
  9383. +void
  9384. +ep2_int_hndlr(int udcsr)
  9385. +{
  9386. + int status = Ser0UDCCS2;
  9387. +
  9388. + if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug.
  9389. + Ser0UDCAR = usbd_info.address;
  9390. +
  9391. + UDC_flip(Ser0UDCCS2, UDCCS2_SST);
  9392. +
  9393. + if (status & UDCCS2_TPC) {
  9394. + sa1100_dma_flush_all(dmachn_tx);
  9395. +
  9396. + if (status & (UDCCS2_TPE | UDCCS2_TUR)) {
  9397. + printk("usb_send: transmit error %x\n", status);
  9398. + ep2_done(-EIO);
  9399. + } else {
  9400. +#if 1 // 22Feb01ww/Oleg
  9401. + ep2_curdmapos += ep2_curdmalen;
  9402. + ep2_remain -= ep2_curdmalen;
  9403. +#else
  9404. + ep2_curdmapos += Ser0UDCIMP + 1; // this is workaround
  9405. + ep2_remain -= Ser0UDCIMP + 1; // for case when setting of Ser0UDCIMP was failed
  9406. +#endif
  9407. +
  9408. + if (ep2_remain != 0) {
  9409. + ep2_start();
  9410. + } else {
  9411. + ep2_done(0);
  9412. + }
  9413. + }
  9414. + } else {
  9415. + printk("usb_send: Not TPC: UDCCS2 = %x\n", status);
  9416. + }
  9417. +}
  9418. +
  9419. +int
  9420. +sa1100_usb_send(char *buf, int len, usb_callback_t callback)
  9421. +{
  9422. + int flags;
  9423. +
  9424. + if (usbd_info.state != USB_STATE_CONFIGURED)
  9425. + return -ENODEV;
  9426. +
  9427. + if (ep2_len)
  9428. + return -EBUSY;
  9429. +
  9430. + local_irq_save(flags);
  9431. + ep2_buf = buf;
  9432. + ep2_len = len;
  9433. + ep2_dma = pci_map_single(NULL, buf, len, PCI_DMA_TODEVICE);
  9434. + ep2_callback = callback;
  9435. + ep2_remain = len;
  9436. + ep2_curdmapos = ep2_dma;
  9437. + ep2_start();
  9438. + local_irq_restore(flags);
  9439. +
  9440. + return 0;
  9441. +}
  9442. +
  9443. +
  9444. +void
  9445. +sa1100_usb_send_reset(void)
  9446. +{
  9447. + ep2_reset();
  9448. +}
  9449. +
  9450. +int sa1100_usb_xmitter_avail( void )
  9451. +{
  9452. + if (usbd_info.state != USB_STATE_CONFIGURED)
  9453. + return -ENODEV;
  9454. + if (ep2_len)
  9455. + return -EBUSY;
  9456. + return 0;
  9457. +}
  9458. +
  9459. +
  9460. +EXPORT_SYMBOL(sa1100_usb_xmitter_avail);
  9461. +EXPORT_SYMBOL(sa1100_usb_send);
  9462. +EXPORT_SYMBOL(sa1100_usb_send_reset);
  9463. diff -urN linux-2.4.26/arch/arm/mm/Makefile linux-2.4.26-vrs1/arch/arm/mm/Makefile
  9464. --- linux-2.4.26/arch/arm/mm/Makefile 2003-08-25 12:44:39.000000000 +0100
  9465. +++ linux-2.4.26-vrs1/arch/arm/mm/Makefile 2004-01-14 21:38:43.000000000 +0000
  9466. @@ -39,6 +39,8 @@
  9467. p-$(CONFIG_CPU_ARM925T) += proc-arm925.o
  9468. p-$(CONFIG_CPU_ARM926T) += proc-arm926.o
  9469. p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
  9470. +p-$(CONFIG_CPU_ARM1020E) += proc-arm1020E.o
  9471. +p-$(CONFIG_CPU_ARM1022) += proc-arm1022.o
  9472. p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
  9473. p-$(CONFIG_CPU_SA110) += proc-sa110.o
  9474. p-$(CONFIG_CPU_SA1100) += proc-sa110.o
  9475. diff -urN linux-2.4.26/arch/arm/mm/alignment.c linux-2.4.26-vrs1/arch/arm/mm/alignment.c
  9476. --- linux-2.4.26/arch/arm/mm/alignment.c 2003-08-25 12:44:39.000000000 +0100
  9477. +++ linux-2.4.26-vrs1/arch/arm/mm/alignment.c 2004-04-09 15:09:44.000000000 +0100
  9478. @@ -11,7 +11,6 @@
  9479. #include <linux/config.h>
  9480. #include <linux/compiler.h>
  9481. #include <linux/signal.h>
  9482. -#include <linux/sched.h>
  9483. #include <linux/kernel.h>
  9484. #include <linux/errno.h>
  9485. #include <linux/string.h>
  9486. @@ -19,7 +18,6 @@
  9487. #include <linux/ptrace.h>
  9488. #include <linux/mman.h>
  9489. #include <linux/mm.h>
  9490. -#include <linux/interrupt.h>
  9491. #include <linux/proc_fs.h>
  9492. #include <linux/bitops.h>
  9493. #include <linux/init.h>
  9494. @@ -30,13 +28,11 @@
  9495. #include <asm/pgtable.h>
  9496. #include <asm/unaligned.h>
  9497. -extern void
  9498. -do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
  9499. - int error_code, struct pt_regs *regs);
  9500. +#include "fault.h"
  9501. /*
  9502. * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
  9503. - * /proc/sys/debug/alignment, modified and integrated into
  9504. + * /proc/cpu/alignment, modified and integrated into
  9505. * Linux 2.1 by Russell King
  9506. *
  9507. * Speed optimisations and better fault handling by Russell King.
  9508. @@ -130,31 +126,6 @@
  9509. return count;
  9510. }
  9511. -/*
  9512. - * This needs to be done after sysctl_init, otherwise sys/ will be
  9513. - * overwritten. Actually, this shouldn't be in sys/ at all since
  9514. - * it isn't a sysctl, and it doesn't contain sysctl information.
  9515. - * We now locate it in /proc/cpu/alignment instead.
  9516. - */
  9517. -static int __init alignment_init(void)
  9518. -{
  9519. - struct proc_dir_entry *res;
  9520. -
  9521. - res = proc_mkdir("cpu", NULL);
  9522. - if (!res)
  9523. - return -ENOMEM;
  9524. -
  9525. - res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
  9526. - if (!res)
  9527. - return -ENOMEM;
  9528. -
  9529. - res->read_proc = proc_alignment_read;
  9530. - res->write_proc = proc_alignment_write;
  9531. -
  9532. - return 0;
  9533. -}
  9534. -
  9535. -__initcall(alignment_init);
  9536. #endif /* CONFIG_PROC_FS */
  9537. union offset_union {
  9538. @@ -429,7 +400,7 @@
  9539. * For alignment faults on the ARM922T/ARM920T the MMU makes
  9540. * the FSR (and hence addr) equal to the updated base address
  9541. * of the multiple access rather than the restored value.
  9542. - * Switch this messsage off if we've got a ARM92[02], otherwise
  9543. + * Switch this message off if we've got a ARM92[02], otherwise
  9544. * [ls]dm alignment faults are noisy!
  9545. */
  9546. #if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T)
  9547. @@ -486,7 +457,8 @@
  9548. return TYPE_ERROR;
  9549. }
  9550. -int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
  9551. +static int
  9552. +do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  9553. {
  9554. union offset_union offset;
  9555. unsigned long instr, instrptr;
  9556. @@ -541,7 +513,7 @@
  9557. case SHIFT_RORRRX:
  9558. if (shiftval == 0) {
  9559. offset.un >>= 1;
  9560. - if (regs->ARM_cpsr & CC_C_BIT)
  9561. + if (regs->ARM_cpsr & PSR_C_BIT)
  9562. offset.un |= 1 << 31;
  9563. } else
  9564. offset.un = offset.un >> shiftval |
  9565. @@ -577,7 +549,7 @@
  9566. /*
  9567. * We got a fault - fix it up, or die.
  9568. */
  9569. - do_bad_area(current, current->mm, addr, error_code, regs);
  9570. + do_bad_area(current, current->mm, addr, fsr, regs);
  9571. return 0;
  9572. bad:
  9573. @@ -594,8 +566,8 @@
  9574. if (ai_usermode & 1)
  9575. printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx "
  9576. - "Address=0x%08lx Code 0x%02x\n", current->comm,
  9577. - current->pid, instrptr, instr, addr, error_code);
  9578. + "Address=0x%08lx FSR 0x%03x\n", current->comm,
  9579. + current->pid, instrptr, instr, addr, fsr);
  9580. if (ai_usermode & 2)
  9581. goto fixup;
  9582. @@ -607,3 +579,34 @@
  9583. return 0;
  9584. }
  9585. +
  9586. +/*
  9587. + * This needs to be done after sysctl_init, otherwise sys/ will be
  9588. + * overwritten. Actually, this shouldn't be in sys/ at all since
  9589. + * it isn't a sysctl, and it doesn't contain sysctl information.
  9590. + * We now locate it in /proc/cpu/alignment instead.
  9591. + */
  9592. +static int __init alignment_init(void)
  9593. +{
  9594. +#ifdef CONFIG_PROC_FS
  9595. + struct proc_dir_entry *res;
  9596. +
  9597. + res = proc_mkdir("cpu", NULL);
  9598. + if (!res)
  9599. + return -ENOMEM;
  9600. +
  9601. + res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
  9602. + if (!res)
  9603. + return -ENOMEM;
  9604. +
  9605. + res->read_proc = proc_alignment_read;
  9606. + res->write_proc = proc_alignment_write;
  9607. +#endif
  9608. +
  9609. + hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
  9610. + hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
  9611. +
  9612. + return 0;
  9613. +}
  9614. +
  9615. +__initcall(alignment_init);
  9616. diff -urN linux-2.4.26/arch/arm/mm/fault-armv.c linux-2.4.26-vrs1/arch/arm/mm/fault-armv.c
  9617. --- linux-2.4.26/arch/arm/mm/fault-armv.c 2003-08-25 12:44:39.000000000 +0100
  9618. +++ linux-2.4.26-vrs1/arch/arm/mm/fault-armv.c 2004-04-09 21:22:20.000000000 +0100
  9619. @@ -2,116 +2,90 @@
  9620. * linux/arch/arm/mm/fault-armv.c
  9621. *
  9622. * Copyright (C) 1995 Linus Torvalds
  9623. - * Modifications for ARM processor (c) 1995-2001 Russell King
  9624. + * Modifications for ARM processor (c) 1995-2003 Russell King
  9625. *
  9626. * This program is free software; you can redistribute it and/or modify
  9627. * it under the terms of the GNU General Public License version 2 as
  9628. * published by the Free Software Foundation.
  9629. */
  9630. -#include <linux/config.h>
  9631. -#include <linux/signal.h>
  9632. #include <linux/sched.h>
  9633. #include <linux/kernel.h>
  9634. -#include <linux/errno.h>
  9635. -#include <linux/string.h>
  9636. #include <linux/types.h>
  9637. #include <linux/ptrace.h>
  9638. -#include <linux/mman.h>
  9639. #include <linux/mm.h>
  9640. -#include <linux/interrupt.h>
  9641. -#include <linux/proc_fs.h>
  9642. #include <linux/bitops.h>
  9643. #include <linux/init.h>
  9644. -#include <asm/system.h>
  9645. -#include <asm/uaccess.h>
  9646. #include <asm/pgalloc.h>
  9647. #include <asm/pgtable.h>
  9648. +#include <asm/io.h>
  9649. -extern void show_pte(struct mm_struct *mm, unsigned long addr);
  9650. -extern int do_page_fault(unsigned long addr, int error_code,
  9651. - struct pt_regs *regs);
  9652. -extern int do_translation_fault(unsigned long addr, int error_code,
  9653. - struct pt_regs *regs);
  9654. -extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
  9655. - unsigned long addr, int error_code,
  9656. - struct pt_regs *regs);
  9657. -
  9658. -#ifdef CONFIG_ALIGNMENT_TRAP
  9659. -extern int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs);
  9660. -#else
  9661. -#define do_alignment do_bad
  9662. -#endif
  9663. -
  9664. +#include "fault.h"
  9665. /*
  9666. * Some section permission faults need to be handled gracefully.
  9667. * They can happen due to a __{get,put}_user during an oops.
  9668. */
  9669. static int
  9670. -do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
  9671. +do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  9672. {
  9673. struct task_struct *tsk = current;
  9674. - do_bad_area(tsk, tsk->active_mm, addr, error_code, regs);
  9675. + do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
  9676. return 0;
  9677. }
  9678. /*
  9679. - * Hook for things that need to trap external faults. Note that
  9680. - * we don't guarantee that this will be the final version of the
  9681. - * interface.
  9682. - */
  9683. -int (*external_fault)(unsigned long addr, struct pt_regs *regs);
  9684. -
  9685. -static int
  9686. -do_external_fault(unsigned long addr, int error_code, struct pt_regs *regs)
  9687. -{
  9688. - if (external_fault)
  9689. - return external_fault(addr, regs);
  9690. - return 1;
  9691. -}
  9692. -
  9693. -/*
  9694. * This abort handler always returns "fault".
  9695. */
  9696. static int
  9697. -do_bad(unsigned long addr, int error_code, struct pt_regs *regs)
  9698. +do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  9699. {
  9700. return 1;
  9701. }
  9702. -static const struct fsr_info {
  9703. - int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
  9704. +static struct fsr_info {
  9705. + int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
  9706. int sig;
  9707. const char *name;
  9708. } fsr_info[] = {
  9709. { do_bad, SIGSEGV, "vector exception" },
  9710. - { do_alignment, SIGILL, "alignment exception" },
  9711. + { do_bad, SIGILL, "alignment exception" },
  9712. { do_bad, SIGKILL, "terminal exception" },
  9713. - { do_alignment, SIGILL, "alignment exception" },
  9714. - { do_external_fault, SIGBUS, "external abort on linefetch" },
  9715. + { do_bad, SIGILL, "alignment exception" },
  9716. + { do_bad, SIGBUS, "external abort on linefetch" },
  9717. { do_translation_fault, SIGSEGV, "section translation fault" },
  9718. - { do_external_fault, SIGBUS, "external abort on linefetch" },
  9719. + { do_bad, SIGBUS, "external abort on linefetch" },
  9720. { do_page_fault, SIGSEGV, "page translation fault" },
  9721. - { do_external_fault, SIGBUS, "external abort on non-linefetch" },
  9722. + { do_bad, SIGBUS, "external abort on non-linefetch" },
  9723. { do_bad, SIGSEGV, "section domain fault" },
  9724. - { do_external_fault, SIGBUS, "external abort on non-linefetch" },
  9725. + { do_bad, SIGBUS, "external abort on non-linefetch" },
  9726. { do_bad, SIGSEGV, "page domain fault" },
  9727. { do_bad, SIGBUS, "external abort on translation" },
  9728. { do_sect_fault, SIGSEGV, "section permission fault" },
  9729. { do_bad, SIGBUS, "external abort on translation" },
  9730. - { do_page_fault, SIGSEGV, "page permission fault" }
  9731. + { do_page_fault, SIGSEGV, "page permission fault" },
  9732. };
  9733. +void __init
  9734. +hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
  9735. + int sig, const char *name)
  9736. +{
  9737. + if (nr >= 0 && nr < ARRAY_SIZE(fsr_info)) {
  9738. + fsr_info[nr].fn = fn;
  9739. + fsr_info[nr].sig = sig;
  9740. + fsr_info[nr].name = name;
  9741. + }
  9742. +}
  9743. +
  9744. /*
  9745. * Dispatch a data abort to the relevant handler.
  9746. */
  9747. asmlinkage void
  9748. -do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr)
  9749. +do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  9750. {
  9751. const struct fsr_info *inf = fsr_info + (fsr & 15);
  9752. - if (!inf->fn(addr, error_code, regs))
  9753. + if (!inf->fn(addr, fsr, regs))
  9754. return;
  9755. printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
  9756. @@ -127,25 +101,28 @@
  9757. do_translation_fault(addr, 0, regs);
  9758. }
  9759. +static unsigned long shared_pte_mask = L_PTE_CACHEABLE;
  9760. +
  9761. /*
  9762. * We take the easy way out of this problem - we make the
  9763. * PTE uncacheable. However, we leave the write buffer on.
  9764. */
  9765. -static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
  9766. +static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
  9767. {
  9768. pgd_t *pgd;
  9769. pmd_t *pmd;
  9770. pte_t *pte, entry;
  9771. + int ret = 0;
  9772. pgd = pgd_offset(vma->vm_mm, address);
  9773. if (pgd_none(*pgd))
  9774. - return;
  9775. + goto no_pgd;
  9776. if (pgd_bad(*pgd))
  9777. goto bad_pgd;
  9778. pmd = pmd_offset(pgd, address);
  9779. if (pmd_none(*pmd))
  9780. - return;
  9781. + goto no_pmd;
  9782. if (pmd_bad(*pmd))
  9783. goto bad_pmd;
  9784. @@ -156,33 +133,38 @@
  9785. * If this page isn't present, or is already setup to
  9786. * fault (ie, is old), we can safely ignore any issues.
  9787. */
  9788. - if (pte_present(entry) && pte_val(entry) & L_PTE_CACHEABLE) {
  9789. + if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
  9790. flush_cache_page(vma, address);
  9791. - pte_val(entry) &= ~L_PTE_CACHEABLE;
  9792. + pte_val(entry) &= ~shared_pte_mask;
  9793. set_pte(pte, entry);
  9794. flush_tlb_page(vma, address);
  9795. + ret = 1;
  9796. }
  9797. - return;
  9798. + return ret;
  9799. bad_pgd:
  9800. pgd_ERROR(*pgd);
  9801. pgd_clear(pgd);
  9802. - return;
  9803. +no_pgd:
  9804. + return 0;
  9805. bad_pmd:
  9806. pmd_ERROR(*pmd);
  9807. pmd_clear(pmd);
  9808. - return;
  9809. +no_pmd:
  9810. + return 0;
  9811. }
  9812. static void
  9813. -make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
  9814. +make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
  9815. {
  9816. struct vm_area_struct *mpnt;
  9817. struct mm_struct *mm = vma->vm_mm;
  9818. - unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
  9819. + unsigned long pgoff;
  9820. int aliases = 0;
  9821. + pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
  9822. +
  9823. /*
  9824. * If we have any shared mappings that are in the same mm
  9825. * space, then we need to handle them specially to maintain
  9826. @@ -194,7 +176,7 @@
  9827. /*
  9828. * If this VMA is not in our MM, we can ignore it.
  9829. - * Note that we intentionally don't mask out the VMA
  9830. + * Note that we intentionally mask out the VMA
  9831. * that we are fixing up.
  9832. */
  9833. if (mpnt->vm_mm != mm || mpnt == vma)
  9834. @@ -210,14 +192,17 @@
  9835. if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
  9836. continue;
  9837. + off = mpnt->vm_start + (off << PAGE_SHIFT);
  9838. +
  9839. /*
  9840. * Ok, it is within mpnt. Fix it up.
  9841. */
  9842. - adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
  9843. - aliases ++;
  9844. + aliases += adjust_pte(mpnt, off);
  9845. }
  9846. if (aliases)
  9847. adjust_pte(vma, addr);
  9848. + else if (dirty)
  9849. + flush_cache_page(vma, addr);
  9850. }
  9851. /*
  9852. @@ -242,11 +227,85 @@
  9853. return;
  9854. page = pfn_to_page(pfn);
  9855. if (page->mapping) {
  9856. - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
  9857. + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
  9858. +
  9859. + if (dirty) {
  9860. unsigned long kvirt = (unsigned long)page_address(page);
  9861. cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
  9862. }
  9863. - make_coherent(vma, addr, page);
  9864. + make_coherent(vma, addr, page, dirty);
  9865. + }
  9866. +}
  9867. +
  9868. +/*
  9869. + * Check whether the write buffer has physical address aliasing
  9870. + * issues. If it has, we need to avoid them for the case where
  9871. + * we have several shared mappings of the same object in user
  9872. + * space.
  9873. + */
  9874. +static int __init check_writebuffer(unsigned long *p1, unsigned long *p2)
  9875. +{
  9876. + register unsigned long zero = 0, one = 1, val;
  9877. +
  9878. + mb();
  9879. + *p1 = one;
  9880. + mb();
  9881. + *p2 = zero;
  9882. + mb();
  9883. + val = *p1;
  9884. + mb();
  9885. + return val != zero;
  9886. +}
  9887. +
  9888. +static inline void *map_page(struct page *page)
  9889. +{
  9890. + void *map;
  9891. +
  9892. + map = __ioremap(page_to_phys(page), PAGE_SIZE, L_PTE_BUFFERABLE);
  9893. + if (map)
  9894. + get_page(page);
  9895. + return map;
  9896. +}
  9897. +
  9898. +static inline void unmap_page(void *map)
  9899. +{
  9900. + iounmap(map);
  9901. +}
  9902. +
  9903. +void __init check_writebuffer_bugs(void)
  9904. +{
  9905. + struct page *page;
  9906. + const char *reason;
  9907. + unsigned long v = 1;
  9908. +
  9909. + printk(KERN_INFO "CPU: Testing write buffer: ");
  9910. +
  9911. + page = alloc_page(GFP_KERNEL);
  9912. + if (page) {
  9913. + unsigned long *p1, *p2;
  9914. +
  9915. + p1 = map_page(page);
  9916. + p2 = map_page(page);
  9917. +
  9918. + if (p1 && p2) {
  9919. + v = check_writebuffer(p1, p2);
  9920. + reason = "enabling work-around";
  9921. + } else {
  9922. + reason = "unable to map memory\n";
  9923. + }
  9924. +
  9925. + unmap_page(p1);
  9926. + unmap_page(p2);
  9927. + put_page(page);
  9928. + } else {
  9929. + reason = "unable to grab page\n";
  9930. + }
  9931. +
  9932. + if (v) {
  9933. + printk("FAIL - %s\n", reason);
  9934. + shared_pte_mask |= L_PTE_BUFFERABLE;
  9935. + } else {
  9936. + printk("pass\n");
  9937. }
  9938. }
  9939. diff -urN linux-2.4.26/arch/arm/mm/fault-common.c linux-2.4.26-vrs1/arch/arm/mm/fault-common.c
  9940. --- linux-2.4.26/arch/arm/mm/fault-common.c 2003-08-25 12:44:39.000000000 +0100
  9941. +++ linux-2.4.26-vrs1/arch/arm/mm/fault-common.c 2004-01-14 21:38:43.000000000 +0000
  9942. @@ -11,21 +11,17 @@
  9943. #include <linux/config.h>
  9944. #include <linux/signal.h>
  9945. #include <linux/sched.h>
  9946. -#include <linux/kernel.h>
  9947. -#include <linux/errno.h>
  9948. #include <linux/string.h>
  9949. -#include <linux/types.h>
  9950. #include <linux/ptrace.h>
  9951. -#include <linux/mman.h>
  9952. #include <linux/mm.h>
  9953. #include <linux/interrupt.h>
  9954. -#include <linux/proc_fs.h>
  9955. #include <linux/init.h>
  9956. #include <asm/system.h>
  9957. -#include <asm/uaccess.h>
  9958. #include <asm/pgtable.h>
  9959. -#include <asm/unaligned.h>
  9960. +#include <asm/uaccess.h>
  9961. +
  9962. +#include "fault.h"
  9963. #ifdef CONFIG_CPU_26
  9964. #define FAULT_CODE_WRITE 0x02
  9965. @@ -34,13 +30,11 @@
  9966. #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
  9967. #else
  9968. /*
  9969. - * On 32-bit processors, we define "mode" to be zero when reading,
  9970. - * non-zero when writing. This now ties up nicely with the polarity
  9971. - * of the 26-bit machines, and also means that we avoid the horrible
  9972. - * gcc code for "int val = !other_val;".
  9973. + * "code" is actually the FSR register. Bit 11 set means the
  9974. + * instruction was performing a write.
  9975. */
  9976. -#define DO_COW(m) (m)
  9977. -#define READ_FAULT(m) (!(m))
  9978. +#define DO_COW(code) ((code) & (1 << 11))
  9979. +#define READ_FAULT(code) (!DO_COW(code))
  9980. #endif
  9981. /*
  9982. @@ -54,16 +48,17 @@
  9983. if (!mm)
  9984. mm = &init_mm;
  9985. - printk(KERN_ALERT "mm = %p pgd = %p\n", mm, mm->pgd);
  9986. -
  9987. fs = get_fs();
  9988. set_fs(get_ds());
  9989. +
  9990. do {
  9991. - pgd_t pg, *pgd = pgd_offset(mm, addr);
  9992. + pgd_t pg, *pgd;
  9993. pmd_t pm, *pmd;
  9994. pte_t pt, *pte;
  9995. - printk(KERN_ALERT "*pgd = ");
  9996. + printk(KERN_ALERT "pgd = %p\n", mm->pgd);
  9997. + pgd = pgd_offset(mm, addr);
  9998. + printk(KERN_ALERT "[%08lx] *pgd=", addr);
  9999. if (__get_user(pgd_val(pg), (unsigned long *)pgd)) {
  10000. printk("(faulted)");
  10001. @@ -122,7 +117,7 @@
  10002. * Oops. The kernel tried to access some page that wasn't present.
  10003. */
  10004. static void
  10005. -__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code,
  10006. +__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
  10007. struct pt_regs *regs)
  10008. {
  10009. unsigned long fixup;
  10010. @@ -148,7 +143,7 @@
  10011. "paging request", addr);
  10012. show_pte(mm, addr);
  10013. - die("Oops", regs, error_code);
  10014. + die("Oops", regs, fsr);
  10015. do_exit(SIGKILL);
  10016. }
  10017. @@ -157,20 +152,20 @@
  10018. * User mode accesses just cause a SIGSEGV
  10019. */
  10020. static void
  10021. -__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code,
  10022. - int code, struct pt_regs *regs)
  10023. +__do_user_fault(struct task_struct *tsk, unsigned long addr,
  10024. + unsigned int fsr, int code, struct pt_regs *regs)
  10025. {
  10026. struct siginfo si;
  10027. #ifdef CONFIG_DEBUG_USER
  10028. printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
  10029. "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
  10030. - tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code);
  10031. + tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, fsr);
  10032. show_regs(regs);
  10033. #endif
  10034. tsk->thread.address = addr;
  10035. - tsk->thread.error_code = error_code;
  10036. + tsk->thread.error_code = fsr;
  10037. tsk->thread.trap_no = 14;
  10038. si.si_signo = SIGSEGV;
  10039. si.si_errno = 0;
  10040. @@ -181,20 +176,20 @@
  10041. void
  10042. do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
  10043. - int error_code, struct pt_regs *regs)
  10044. + unsigned int fsr, struct pt_regs *regs)
  10045. {
  10046. /*
  10047. * If we are in kernel mode at this point, we
  10048. * have no context to handle this fault with.
  10049. */
  10050. if (user_mode(regs))
  10051. - __do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs);
  10052. + __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
  10053. else
  10054. - __do_kernel_fault(mm, addr, error_code, regs);
  10055. + __do_kernel_fault(mm, addr, fsr, regs);
  10056. }
  10057. static int
  10058. -__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code,
  10059. +__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
  10060. struct task_struct *tsk)
  10061. {
  10062. struct vm_area_struct *vma;
  10063. @@ -212,7 +207,7 @@
  10064. * memory access, so we can handle it.
  10065. */
  10066. good_area:
  10067. - if (READ_FAULT(error_code)) /* read? */
  10068. + if (READ_FAULT(fsr)) /* read? */
  10069. mask = VM_READ|VM_EXEC;
  10070. else
  10071. mask = VM_WRITE;
  10072. @@ -227,7 +222,7 @@
  10073. * than endlessly redo the fault.
  10074. */
  10075. survive:
  10076. - fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code));
  10077. + fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
  10078. /*
  10079. * Handle the "normal" cases first - successful and sigbus
  10080. @@ -260,7 +255,7 @@
  10081. return fault;
  10082. }
  10083. -int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs)
  10084. +int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  10085. {
  10086. struct task_struct *tsk;
  10087. struct mm_struct *mm;
  10088. @@ -277,7 +272,7 @@
  10089. goto no_context;
  10090. down_read(&mm->mmap_sem);
  10091. - fault = __do_page_fault(mm, addr, error_code, tsk);
  10092. + fault = __do_page_fault(mm, addr, fsr, tsk);
  10093. up_read(&mm->mmap_sem);
  10094. /*
  10095. @@ -308,7 +303,7 @@
  10096. printk("VM: killing process %s\n", tsk->comm);
  10097. do_exit(SIGKILL);
  10098. } else
  10099. - __do_user_fault(tsk, addr, error_code, fault == -1 ?
  10100. + __do_user_fault(tsk, addr, fsr, fault == -1 ?
  10101. SEGV_ACCERR : SEGV_MAPERR, regs);
  10102. return 0;
  10103. @@ -323,7 +318,7 @@
  10104. * or user mode.
  10105. */
  10106. tsk->thread.address = addr;
  10107. - tsk->thread.error_code = error_code;
  10108. + tsk->thread.error_code = fsr;
  10109. tsk->thread.trap_no = 14;
  10110. force_sig(SIGBUS, tsk);
  10111. #ifdef CONFIG_DEBUG_USER
  10112. @@ -336,7 +331,7 @@
  10113. return 0;
  10114. no_context:
  10115. - __do_kernel_fault(mm, addr, error_code, regs);
  10116. + __do_kernel_fault(mm, addr, fsr, regs);
  10117. return 0;
  10118. }
  10119. @@ -357,21 +352,23 @@
  10120. * interrupt or a critical region, and should only copy the information
  10121. * from the master page table, nothing more.
  10122. */
  10123. -int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs)
  10124. +int do_translation_fault(unsigned long addr, unsigned int fsr,
  10125. + struct pt_regs *regs)
  10126. {
  10127. struct task_struct *tsk;
  10128. - struct mm_struct *mm;
  10129. int offset;
  10130. pgd_t *pgd, *pgd_k;
  10131. pmd_t *pmd, *pmd_k;
  10132. if (addr < TASK_SIZE)
  10133. - return do_page_fault(addr, error_code, regs);
  10134. + return do_page_fault(addr, fsr, regs);
  10135. offset = __pgd_offset(addr);
  10136. /*
  10137. * FIXME: CP15 C1 is write only on ARMv3 architectures.
  10138. + * You really need to read the value in the page table
  10139. + * register, not a copy.
  10140. */
  10141. pgd = cpu_get_pgd() + offset;
  10142. pgd_k = init_mm.pgd + offset;
  10143. @@ -395,8 +392,7 @@
  10144. bad_area:
  10145. tsk = current;
  10146. - mm = tsk->active_mm;
  10147. - do_bad_area(tsk, mm, addr, error_code, regs);
  10148. + do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
  10149. return 0;
  10150. }
  10151. diff -urN linux-2.4.26/arch/arm/mm/fault.h linux-2.4.26-vrs1/arch/arm/mm/fault.h
  10152. --- linux-2.4.26/arch/arm/mm/fault.h 1970-01-01 01:00:00.000000000 +0100
  10153. +++ linux-2.4.26-vrs1/arch/arm/mm/fault.h 2004-01-14 21:32:24.000000000 +0000
  10154. @@ -0,0 +1,9 @@
  10155. +void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
  10156. + unsigned long addr, unsigned int fsr, struct pt_regs *regs);
  10157. +
  10158. +void show_pte(struct mm_struct *mm, unsigned long addr);
  10159. +
  10160. +int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
  10161. +
  10162. +int do_translation_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
  10163. +
  10164. diff -urN linux-2.4.26/arch/arm/mm/init.c linux-2.4.26-vrs1/arch/arm/mm/init.c
  10165. --- linux-2.4.26/arch/arm/mm/init.c 2003-08-25 12:44:39.000000000 +0100
  10166. +++ linux-2.4.26-vrs1/arch/arm/mm/init.c 2004-01-14 21:32:24.000000000 +0000
  10167. @@ -9,7 +9,6 @@
  10168. */
  10169. #include <linux/config.h>
  10170. #include <linux/signal.h>
  10171. -#include <linux/sched.h>
  10172. #include <linux/kernel.h>
  10173. #include <linux/errno.h>
  10174. #include <linux/string.h>
  10175. @@ -18,7 +17,6 @@
  10176. #include <linux/mman.h>
  10177. #include <linux/mm.h>
  10178. #include <linux/swap.h>
  10179. -#include <linux/swapctl.h>
  10180. #include <linux/smp.h>
  10181. #include <linux/init.h>
  10182. #include <linux/bootmem.h>
  10183. diff -urN linux-2.4.26/arch/arm/mm/ioremap.c linux-2.4.26-vrs1/arch/arm/mm/ioremap.c
  10184. --- linux-2.4.26/arch/arm/mm/ioremap.c 2003-08-25 12:44:39.000000000 +0100
  10185. +++ linux-2.4.26-vrs1/arch/arm/mm/ioremap.c 2004-02-25 22:03:38.000000000 +0000
  10186. @@ -144,7 +144,7 @@
  10187. */
  10188. offset = phys_addr & ~PAGE_MASK;
  10189. phys_addr &= PAGE_MASK;
  10190. - size = PAGE_ALIGN(last_addr) - phys_addr;
  10191. + size = PAGE_ALIGN(last_addr + 1) - phys_addr;
  10192. /*
  10193. * Ok, go for it..
  10194. diff -urN linux-2.4.26/arch/arm/mm/mm-armv.c linux-2.4.26-vrs1/arch/arm/mm/mm-armv.c
  10195. --- linux-2.4.26/arch/arm/mm/mm-armv.c 2003-11-28 18:26:19.000000000 +0000
  10196. +++ linux-2.4.26-vrs1/arch/arm/mm/mm-armv.c 2004-01-14 21:38:43.000000000 +0000
  10197. @@ -9,7 +9,6 @@
  10198. *
  10199. * Page table sludge for ARM v3 and v4 processor architectures.
  10200. */
  10201. -#include <linux/sched.h>
  10202. #include <linux/mm.h>
  10203. #include <linux/init.h>
  10204. #include <linux/bootmem.h>
  10205. @@ -390,6 +389,9 @@
  10206. init_maps->bufferable = 0;
  10207. create_mapping(init_maps);
  10208. +
  10209. + flush_cache_all();
  10210. + flush_tlb_all();
  10211. }
  10212. /*
  10213. diff -urN linux-2.4.26/arch/arm/mm/proc-arm1020.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm1020.S
  10214. --- linux-2.4.26/arch/arm/mm/proc-arm1020.S 2003-08-25 12:44:39.000000000 +0100
  10215. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm1020.S 2004-01-14 21:32:24.000000000 +0000
  10216. @@ -65,18 +65,21 @@
  10217. *
  10218. * Returns:
  10219. * r0 = address of abort
  10220. - * r1 != 0 if writing
  10221. - * r3 = FSR
  10222. + * r1 = FSR
  10223. + * r3 = corrupted
  10224. * r4 = corrupted
  10225. */
  10226. .align 5
  10227. ENTRY(cpu_arm1020_data_abort)
  10228. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  10229. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  10230. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  10231. - ldr r1, [r2] @ read aborted instruction
  10232. - and r3, r3, #255
  10233. - tst r1, r1, lsr #21 @ C = bit 20
  10234. - sbc r1, r1, r1 @ r1 = C - 1
  10235. + tst r3, #PSR_T_BIT
  10236. + ldrneh r3, [r2] @ read aborted thumb instruction
  10237. + ldreq r3, [r2] @ read aborted ARM instruction
  10238. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  10239. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  10240. + tst r3, #1 << 20 @ check write
  10241. + orreq r1, r1, #1 << 11
  10242. mov pc, lr
  10243. /*
  10244. @@ -170,10 +173,10 @@
  10245. #endif
  10246. subs r3, r3, #1
  10247. cmp r3, #0
  10248. - bge 2b @ entries 3F to 0
  10249. + bhs 2b @ entries 3F to 0
  10250. subs r1, r1, #1
  10251. cmp r1, #0
  10252. - bge 1b @ segments 7 to 0
  10253. + bhs 1b @ segments 7 to 0
  10254. #endif
  10255. #ifndef CONFIG_CPU_ICACHE_DISABLE
  10256. @@ -201,7 +204,7 @@
  10257. bic r0, r0, #DCACHELINESIZE - 1
  10258. sub r3, r1, r0
  10259. cmp r3, #MAX_AREA_SIZE
  10260. - bgt cpu_arm1020_cache_clean_invalidate_all_r2
  10261. + bhi cpu_arm1020_cache_clean_invalidate_all_r2
  10262. mcr p15, 0, r3, c7, c10, 4
  10263. #ifndef CONFIG_CPU_DCACHE_DISABLE
  10264. 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
  10265. @@ -214,7 +217,7 @@
  10266. #endif
  10267. add r0, r0, #DCACHELINESIZE
  10268. cmp r0, r1
  10269. - blt 1b
  10270. + blo 1b
  10271. #endif
  10272. #ifndef CONFIG_CPU_ICACHE_DISABLE
  10273. @@ -302,7 +305,7 @@
  10274. #endif
  10275. add r0, r0, #DCACHELINESIZE
  10276. cmp r0, r1
  10277. - blt 1b
  10278. + blo 1b
  10279. #else
  10280. /* D cache off, but still drain the write buffer */
  10281. mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
  10282. @@ -328,7 +331,7 @@
  10283. bic r0, r0, #DCACHELINESIZE - 1
  10284. sub r3, r1, r0
  10285. cmp r3, #MAX_AREA_SIZE
  10286. - bgt cpu_arm1020_cache_clean_invalidate_all_r2
  10287. + bhi cpu_arm1020_cache_clean_invalidate_all_r2
  10288. mcr p15, 0, r3, c7, c10, 4
  10289. #ifndef CONFIG_CPU_DCACHE_DISABLE
  10290. 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
  10291. @@ -341,7 +344,7 @@
  10292. #endif
  10293. add r0, r0, #DCACHELINESIZE
  10294. cmp r0, r1
  10295. - blt 1b
  10296. + blo 1b
  10297. #endif
  10298. #ifndef CONFIG_CPU_BPREDICT_DISABLE
  10299. @@ -488,7 +491,7 @@
  10300. mov r0, r0
  10301. #endif
  10302. cmp r0, r1
  10303. - blt 1b
  10304. + blo 1b
  10305. mov pc, lr
  10306. /*
  10307. @@ -541,10 +544,10 @@
  10308. #endif
  10309. subs r3, r3, #1
  10310. cmp r3, #0
  10311. - bge 2b @ entries 3F to 0
  10312. + bhs 2b @ entries 3F to 0
  10313. subs r1, r1, #1
  10314. cmp r1, #0
  10315. - bge 1b @ segments 15 to 0
  10316. + bhs 1b @ segments 15 to 0
  10317. #endif
  10318. mov r1, #0
  10319. @@ -603,7 +606,7 @@
  10320. bic r2, r2, #3
  10321. orr r2, r2, #HPTE_TYPE_SMALL
  10322. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  10323. + tst r1, #LPTE_USER @ User?
  10324. orrne r2, r2, #HPTE_AP_READ
  10325. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  10326. @@ -740,12 +743,12 @@
  10327. .type cpu_arch_name, #object
  10328. cpu_arch_name:
  10329. - .asciz "armv4"
  10330. + .asciz "armv5t"
  10331. .size cpu_arch_name, . - cpu_arch_name
  10332. .type cpu_elf_name, #object
  10333. cpu_elf_name:
  10334. - .asciz "v4"
  10335. + .asciz "v5"
  10336. .size cpu_elf_name, . - cpu_elf_name
  10337. .align
  10338. @@ -753,9 +756,9 @@
  10339. .type __arm1020_proc_info,#object
  10340. __arm1020_proc_info:
  10341. - .long 0x4100a200
  10342. - .long 0xff00fff0
  10343. - .long 0x00000c02 @ mmuflags
  10344. + .long 0x4104a200 @ ARM 1020T (Architecture v5T)
  10345. + .long 0xff0ffff0
  10346. + .long 0x00000c0e @ mmuflags
  10347. b __arm1020_setup
  10348. .long cpu_arch_name
  10349. .long cpu_elf_name
  10350. diff -urN linux-2.4.26/arch/arm/mm/proc-arm1020E.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm1020E.S
  10351. --- linux-2.4.26/arch/arm/mm/proc-arm1020E.S 1970-01-01 01:00:00.000000000 +0100
  10352. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm1020E.S 2004-01-14 21:32:24.000000000 +0000
  10353. @@ -0,0 +1,718 @@
  10354. +/*
  10355. + * linux/arch/arm/mm/proc-arm1020E.S: MMU functions for ARM1020E
  10356. + *
  10357. + * Copyright (C) 2000 ARM Limited
  10358. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  10359. + *
  10360. + * This program is free software; you can redistribute it and/or modify
  10361. + * it under the terms of the GNU General Public License as published by
  10362. + * the Free Software Foundation; either version 2 of the License, or
  10363. + * (at your option) any later version.
  10364. + *
  10365. + * This program is distributed in the hope that it will be useful,
  10366. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10367. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10368. + * GNU General Public License for more details.
  10369. + *
  10370. + * You should have received a copy of the GNU General Public License
  10371. + * along with this program; if not, write to the Free Software
  10372. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  10373. + *
  10374. + *
  10375. + * These are the low level assembler for performing cache and TLB
  10376. + * functions on the arm1020E.
  10377. + */
  10378. +#include <linux/linkage.h>
  10379. +#include <linux/config.h>
  10380. +#include <asm/assembler.h>
  10381. +#include <asm/constants.h>
  10382. +#include <asm/procinfo.h>
  10383. +#include <asm/hardware.h>
  10384. +
  10385. +/*
  10386. + * This is the maximum size of an area which will be invalidated
  10387. + * using the single invalidate entry instructions. Anything larger
  10388. + * than this, and we go for the whole cache.
  10389. + *
  10390. + * This value should be chosen such that we choose the cheapest
  10391. + * alternative.
  10392. + */
  10393. +#define MAX_AREA_SIZE 32768
  10394. +
  10395. +/*
  10396. + * the cache line size of the I and D cache
  10397. + */
  10398. +#define DCACHELINESIZE 32
  10399. +#define ICACHELINESIZE 32
  10400. +
  10401. +/*
  10402. + * and the page size
  10403. + */
  10404. +#define LOG2PAGESIZE 12 /* == 4096 Bytes */
  10405. +#define PAGESIZE (1 << LOG2PAGESIZE)
  10406. +
  10407. +/*
  10408. + * create some useful conditional macro definitions
  10409. + * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
  10410. + */
  10411. +#ifdef CONFIG_CPU_DCACHE_DISABLE
  10412. + #undef CONFIG_CPU_DCACHE_WRITETHROUGH
  10413. + #undef CONFIG_CPU_DCACHE_WRITEBACK
  10414. + #undef CONFIG_CPU_DCACHE_ENABLE
  10415. +#else
  10416. + #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10417. + #undef CONFIG_CPU_DCACHE_WRITEBACK
  10418. + #else
  10419. + #define CONFIG_CPU_DCACHE_WRITEBACK
  10420. + #endif
  10421. + #define CONFIG_CPU_DCACHE_ENABLE
  10422. +#endif
  10423. +
  10424. +#ifdef CONFIG_CPU_ICACHE_DISABLE
  10425. + #undef CONFIG_CPU_ICACHE_ENABLE
  10426. +#else
  10427. + #define CONFIG_CPU_ICACHE_ENABLE
  10428. +#endif
  10429. +
  10430. + .text
  10431. +
  10432. +/*
  10433. + * cpu_arm1020E_data_abort()
  10434. + *
  10435. + * obtain information about current aborted instruction
  10436. + * Note: we read user space. This means we might cause a data
  10437. + * abort here if the I-TLB and D-TLB aren't seeing the same
  10438. + * picture. Unfortunately, this does happen. We live with it.
  10439. + *
  10440. + * r2 = address of aborted instruction
  10441. + * r3 = cpsr
  10442. + *
  10443. + * Returns:
  10444. + * r0 = address of abort
  10445. + * r1 = FSR
  10446. + * r3 = corrupted
  10447. + * r4 = corrupted
  10448. + */
  10449. + .align 5
  10450. +ENTRY(cpu_arm1020E_data_abort)
  10451. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  10452. + mrc p15, 0, r0, c6, c0, 0 @ get FAR
  10453. + tst r3, #PSR_T_BIT
  10454. + ldrneh r3, [r2] @ read aborted thumb instruction
  10455. + ldreq r3, [r2] @ read aborted ARM instruction
  10456. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  10457. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  10458. + tst r3, #1 << 20 @ check write
  10459. + orreq r1, r1, #1 << 11
  10460. + mov pc, lr
  10461. +
  10462. +/*
  10463. + * cpu_arm1020E_check_bugs()
  10464. + */
  10465. +ENTRY(cpu_arm1020E_check_bugs)
  10466. + mrs ip, cpsr
  10467. + bic ip, ip, #F_BIT
  10468. + msr cpsr, ip
  10469. + mov pc, lr
  10470. +
  10471. +/*
  10472. + * cpu_arm1020E_proc_init()
  10473. + */
  10474. +ENTRY(cpu_arm1020E_proc_init)
  10475. + mov pc, lr
  10476. +
  10477. +/*
  10478. + * cpu_arm1020E_proc_fin()
  10479. + */
  10480. +ENTRY(cpu_arm1020E_proc_fin)
  10481. + stmfd sp!, {lr}
  10482. + mov ip, #F_BIT | I_BIT | SVC_MODE
  10483. + msr cpsr_c, ip
  10484. + bl cpu_arm1020E_cache_clean_invalidate_all
  10485. + mrc p15, 0, r0, c1, c0, 0 @ ctrl register
  10486. + bic r0, r0, #0x1000 @ ...i............
  10487. + bic r0, r0, #0x000e @ ............wca.
  10488. + mcr p15, 0, r0, c1, c0, 0 @ disable caches
  10489. + ldmfd sp!, {pc}
  10490. +
  10491. +/*
  10492. + * cpu_arm1020E_reset(loc)
  10493. + *
  10494. + * Perform a soft reset of the system. Put the CPU into the
  10495. + * same state as it would be if it had been reset, and branch
  10496. + * to what would be the reset vector.
  10497. + *
  10498. + * loc: location to jump to for soft reset
  10499. + */
  10500. + .align 5
  10501. +ENTRY(cpu_arm1020E_reset)
  10502. + mov ip, #0
  10503. + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
  10504. + mcr p15, 0, ip, c7, c10, 4 @ drain WB
  10505. + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
  10506. + mrc p15, 0, ip, c1, c0, 0 @ ctrl register
  10507. + bic ip, ip, #0x000f @ ............wcam
  10508. + bic ip, ip, #0x1100 @ ...i...s........
  10509. + mcr p15, 0, ip, c1, c0, 0 @ ctrl register
  10510. + mov pc, r0
  10511. +
  10512. +/*
  10513. + * cpu_arm1020E_do_idle()
  10514. + */
  10515. + .align 5
  10516. +ENTRY(cpu_arm1020E_do_idle)
  10517. + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
  10518. + mov pc, lr
  10519. +
  10520. +/* ================================= CACHE ================================ */
  10521. +
  10522. +
  10523. +/*
  10524. + * cpu_arm1020E_cache_clean_invalidate_all()
  10525. + *
  10526. + * clean and invalidate all cache lines
  10527. + *
  10528. + * Note:
  10529. + * 1. we should preserve r0 and ip at all times
  10530. + */
  10531. + .align 5
  10532. +ENTRY(cpu_arm1020E_cache_clean_invalidate_all)
  10533. + mov r2, #1
  10534. +cpu_arm1020E_cache_clean_invalidate_all_r2:
  10535. +
  10536. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10537. + mov r1, #0x0F << 5 @ 16 segments
  10538. +1: orr r3, r1, #63 << 26 @ 64 entries
  10539. +2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
  10540. + subs r3, r3, #1 << 26
  10541. + bcs 2b
  10542. + subs r1, r1, #1 << 5
  10543. + bcs 1b @ segments 15 to 0
  10544. +#endif
  10545. +
  10546. + mov r1, #0
  10547. +
  10548. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10549. + mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
  10550. +#endif
  10551. +
  10552. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10553. + teq r2, #0
  10554. + mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
  10555. +#endif
  10556. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  10557. + mov pc, lr
  10558. +
  10559. +/*
  10560. + * cpu_arm1020E_cache_clean_invalidate_range(start, end, flags)
  10561. + *
  10562. + * clean and invalidate all cache lines associated with this area of memory
  10563. + *
  10564. + * start: Area start address
  10565. + * end: Area end address
  10566. + * flags: nonzero for I cache as well
  10567. + */
  10568. + .align 5
  10569. +ENTRY(cpu_arm1020E_cache_clean_invalidate_range)
  10570. + bic r0, r0, #DCACHELINESIZE - 1
  10571. + sub r3, r1, r0
  10572. + cmp r3, #MAX_AREA_SIZE
  10573. + bhs cpu_arm1020E_cache_clean_invalidate_all_r2
  10574. +1:
  10575. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10576. + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  10577. +#endif
  10578. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10579. + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
  10580. +#endif
  10581. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10582. + teq r2, #0
  10583. + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
  10584. +#endif
  10585. + add r0, r0, #DCACHELINESIZE
  10586. + cmp r0, r1
  10587. + bls 1b @ unsigned lower or same - must include end point (r1)!
  10588. +
  10589. + mov r1, #0
  10590. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  10591. + mov pc, lr
  10592. +
  10593. +/*
  10594. + * cpu_arm1020E_flush_ram_page(page)
  10595. + *
  10596. + * clean and invalidate all cache lines associated with this area of memory
  10597. + *
  10598. + * page: page to clean and invalidate
  10599. + */
  10600. + .align 5
  10601. +ENTRY(cpu_arm1020E_flush_ram_page)
  10602. + mov r1, #PAGESIZE
  10603. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  10604. + mov r0, r0, LSL #LOG2PAGESIZE
  10605. +1:
  10606. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10607. + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  10608. +#endif
  10609. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10610. + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
  10611. +#endif
  10612. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10613. + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
  10614. +#endif
  10615. + add r0, r0, #DCACHELINESIZE
  10616. + subs r1, r1, #DCACHELINESIZE
  10617. + bne 1b
  10618. +
  10619. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  10620. + mov pc, lr
  10621. +
  10622. +/* ================================ D-CACHE =============================== */
  10623. +
  10624. +/*
  10625. + * cpu_arm1020E_dcache_invalidate_range(start, end)
  10626. + *
  10627. + * throw away all D-cached data in specified region without an obligation
  10628. + * to write them back. Note however that we must clean the D-cached entries
  10629. + * around the boundaries if the start and/or end address are not cache
  10630. + * aligned.
  10631. + *
  10632. + * start: virtual start address
  10633. + * end: virtual end address
  10634. + */
  10635. + .align 5
  10636. +ENTRY(cpu_arm1020E_dcache_invalidate_range)
  10637. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10638. + bic r0, r0, #DCACHELINESIZE - 1
  10639. +#endif
  10640. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10641. + tst r0, #DCACHELINESIZE - 1
  10642. + bic r0, r0, #DCACHELINESIZE - 1
  10643. + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
  10644. + tst r1, #DCACHELINESIZE - 1
  10645. + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
  10646. +#endif
  10647. +
  10648. +1:
  10649. +#ifdef CONFIG_CPU_DCACHE_ENABLE
  10650. + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  10651. +#endif
  10652. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10653. + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
  10654. +#endif
  10655. + add r0, r0, #DCACHELINESIZE
  10656. + cmp r0, r1
  10657. + bls 1b
  10658. +
  10659. + /* Even if the D cache is off still drain the write buffer */
  10660. + mov r0, #0
  10661. + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
  10662. + mov pc, lr
  10663. +
  10664. +/*
  10665. + * cpu_arm1020E_dcache_clean_range(start, end)
  10666. + *
  10667. + * For the specified virtual address range, ensure that all caches contain
  10668. + * clean data, such that peripheral accesses to the physical RAM fetch
  10669. + * correct data.
  10670. + *
  10671. + * start: virtual start address
  10672. + * end: virtual end address
  10673. + */
  10674. + .align 5
  10675. +ENTRY(cpu_arm1020E_dcache_clean_range)
  10676. +
  10677. + mov r2, #0
  10678. +
  10679. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10680. + bic r0, r0, #DCACHELINESIZE - 1
  10681. + sub r3, r1, r0
  10682. + cmp r3, #MAX_AREA_SIZE
  10683. + bhs cpu_arm1020E_cache_clean_invalidate_all_r2
  10684. +
  10685. +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  10686. + add r0, r0, #DCACHELINESIZE
  10687. + cmp r0, r1
  10688. + bls 1b
  10689. +#endif
  10690. +
  10691. + mcr p15, 0, r2, c7, c10, 4 @ drain WB
  10692. + mov pc, lr
  10693. +
  10694. +/*
  10695. + * cpu_arm1020E_dcache_clean_page(page)
  10696. + *
  10697. + * Cleans a single page of dcache so that if we have any future aliased
  10698. + * mappings, they will be consistent at the time that they are created.
  10699. + *
  10700. + * page: virtual address of page to clean from dcache
  10701. + *
  10702. + * Note:
  10703. + * we don't invalidate the entries since when we write the page
  10704. + * out to disk, the entries may get reloaded into the cache.
  10705. + */
  10706. + .align 5
  10707. +ENTRY(cpu_arm1020E_dcache_clean_page)
  10708. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10709. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  10710. + mov r0, r0, LSL #LOG2PAGESIZE
  10711. + mov r1, #PAGESIZE
  10712. +1:
  10713. + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  10714. + add r0, r0, #DCACHELINESIZE
  10715. + subs r1, r1, #DCACHELINESIZE
  10716. + bne 1b
  10717. +#endif
  10718. + mov r1, #0
  10719. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  10720. + mov pc, lr
  10721. +
  10722. +/*
  10723. + * cpu_arm1020E_dcache_clean_entry(addr)
  10724. + *
  10725. + * Clean the specified entry of any caches such that the MMU
  10726. + * translation fetches will obtain correct data.
  10727. + *
  10728. + * addr: cache-unaligned virtual address
  10729. + */
  10730. + .align 5
  10731. +ENTRY(cpu_arm1020E_dcache_clean_entry)
  10732. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10733. + bic r0, r0, #DCACHELINESIZE - 1
  10734. + mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
  10735. +#endif
  10736. + mov r1, #0
  10737. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  10738. + mov pc, lr
  10739. +
  10740. +/* ================================ I-CACHE =============================== */
  10741. +
  10742. +/*
  10743. + * cpu_arm1020E_icache_invalidate_range(start, end)
  10744. + *
  10745. + * invalidate a range of virtual addresses from the Icache
  10746. + *
  10747. + * This is a little misleading, it is not intended to clean out
  10748. + * the i-cache but to make sure that any data written to the
  10749. + * range is made consistent. This means that when we execute code
  10750. + * in that region, everything works as we expect.
  10751. + *
  10752. + * This generally means writing back data in the Dcache and
  10753. + * write buffer and invalidating the Icache over that region
  10754. + *
  10755. + * start: virtual start address
  10756. + * end: virtual end address
  10757. + *
  10758. + * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
  10759. + * loop twice, once for i-cache, once for d-cache)
  10760. + */
  10761. + .align 5
  10762. +ENTRY(cpu_arm1020E_icache_invalidate_range)
  10763. + bic r0, r0, #ICACHELINESIZE - 1
  10764. + sub r3, r1, r0
  10765. + cmp r3, #MAX_AREA_SIZE
  10766. + movhs r2, #1
  10767. + bhs cpu_arm1020E_cache_clean_invalidate_all_r2
  10768. +
  10769. +1:
  10770. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10771. + mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
  10772. +#endif
  10773. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10774. + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
  10775. +#endif
  10776. + add r0, r0, #DCACHELINESIZE
  10777. + cmp r0, r1
  10778. + bls 1b @ unsigned lower or same - includes r1 entry
  10779. +
  10780. + mov r0, #0
  10781. + mcr p15, 0, r0, c7, c10, 4 @ drain WB
  10782. + mov pc, lr
  10783. +
  10784. +ENTRY(cpu_arm1020E_icache_invalidate_page)
  10785. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  10786. + mov r0, r0, LSL #LOG2PAGESIZE
  10787. + add r1, r0, #PAGESIZE
  10788. + b cpu_arm1020E_icache_invalidate_range
  10789. +
  10790. +/* ================================== TLB ================================= */
  10791. +
  10792. +/*
  10793. + * cpu_arm1020E_tlb_invalidate_all()
  10794. + *
  10795. + * Invalidate all TLB entries
  10796. + */
  10797. + .align 5
  10798. +ENTRY(cpu_arm1020E_tlb_invalidate_all)
  10799. + mov r0, #0
  10800. + mcr p15, 0, r0, c7, c10, 4 @ drain WB
  10801. + mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
  10802. + mov pc, lr
  10803. +
  10804. +/*
  10805. + * cpu_arm1020E_tlb_invalidate_range(start, end)
  10806. + *
  10807. + * invalidate TLB entries covering the specified range
  10808. + *
  10809. + * start: range start address
  10810. + * end: range end address
  10811. + */
  10812. + .align 5
  10813. +ENTRY(cpu_arm1020E_tlb_invalidate_range)
  10814. + sub r3, r1, r0
  10815. + cmp r3, #256 * PAGESIZE
  10816. + bhs cpu_arm1020E_tlb_invalidate_all
  10817. + mov r3, #0
  10818. + mcr p15, 0, r3, c7, c10, 4 @ drain WB
  10819. + mov r3, #PAGESIZE
  10820. + sub r3, r3, #1
  10821. + bic r0, r0, r3
  10822. +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  10823. + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  10824. + add r0, r0, #PAGESIZE
  10825. + cmp r0, r1
  10826. + bls 1b
  10827. + mov pc, lr
  10828. +
  10829. +/*
  10830. + * cpu_arm1020E_tlb_invalidate_page(page, flags)
  10831. + *
  10832. + * invalidate the TLB entries for the specified page.
  10833. + *
  10834. + * page: page to invalidate
  10835. + * flags: non-zero if we include the I TLB
  10836. + */
  10837. + .align 5
  10838. +ENTRY(cpu_arm1020E_tlb_invalidate_page)
  10839. + mov r3, #0
  10840. + mcr p15, 0, r3, c7, c10, 4 @ drain WB
  10841. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  10842. + mov r0, r0, LSL #LOG2PAGESIZE
  10843. + teq r1, #0
  10844. + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  10845. + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  10846. + mov pc, lr
  10847. +
  10848. +/* =============================== PageTable ============================== */
  10849. +
  10850. +/*
  10851. + * cpu_arm1020E_set_pgd(pgd)
  10852. + *
  10853. + * Set the translation base pointer to be as described by pgd.
  10854. + *
  10855. + * pgd: new page tables
  10856. + */
  10857. + .align 5
  10858. +ENTRY(cpu_arm1020E_set_pgd)
  10859. + stmfd sp!, {lr}
  10860. + bl cpu_arm1020E_cache_clean_invalidate_all @ preserves r0
  10861. + mov r1, #0
  10862. + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
  10863. + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
  10864. + ldmfd sp!, {pc}
  10865. +
  10866. +/*
  10867. + * cpu_arm1020E_set_pmd(pmdp, pmd)
  10868. + *
  10869. + * Set a level 1 translation table entry, and clean it out of
  10870. + * any caches such that the MMUs can load it correctly.
  10871. + *
  10872. + * pmdp: pointer to PMD entry
  10873. + * pmd: PMD value to store
  10874. + */
  10875. + .align 5
  10876. +ENTRY(cpu_arm1020E_set_pmd)
  10877. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10878. + eor r2, r1, #0x0a @ C & Section
  10879. + tst r2, #0x0b
  10880. + biceq r1, r1, #4 @ clear bufferable bit
  10881. +#endif
  10882. + str r1, [r0]
  10883. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10884. + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  10885. +#endif
  10886. + mov r0, #0
  10887. + mcr p15, 0, r0, c7, c10, 4 @ drain WB
  10888. + mov pc, lr
  10889. +
  10890. +/*
  10891. + * cpu_arm1020E_set_pte(ptep, pte)
  10892. + *
  10893. + * Set a PTE and flush it out
  10894. + */
  10895. + .align 5
  10896. +ENTRY(cpu_arm1020E_set_pte)
  10897. + str r1, [r0], #-1024 @ linux version
  10898. +
  10899. + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
  10900. +
  10901. + bic r2, r1, #0xff0
  10902. + bic r2, r2, #3
  10903. + orr r2, r2, #HPTE_TYPE_SMALL
  10904. +
  10905. + tst r1, #LPTE_USER @ User?
  10906. + orrne r2, r2, #HPTE_AP_READ
  10907. +
  10908. + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  10909. + orreq r2, r2, #HPTE_AP_WRITE
  10910. +
  10911. + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
  10912. + movne r2, #0
  10913. +
  10914. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10915. + eor r3, r2, #0x0a @ C and Small Page?
  10916. + tst r3, #0x0b @ if so..
  10917. + biceq r2, r2, #0x04 @ clear the bufferable bit
  10918. +#endif
  10919. + str r2, [r0] @ hardware version
  10920. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10921. + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  10922. +#endif
  10923. + mov r1, #0
  10924. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  10925. + mov pc, lr
  10926. +
  10927. +
  10928. +cpu_manu_name:
  10929. + .asciz "ARM"
  10930. +ENTRY(cpu_arm1020E_name)
  10931. + .ascii "Arm1020E"
  10932. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10933. + .ascii "i"
  10934. +#endif
  10935. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10936. + .ascii "d"
  10937. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  10938. + .ascii "(wt)"
  10939. +#endif
  10940. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  10941. + .ascii "(wb)"
  10942. +#endif
  10943. +#endif
  10944. +#ifndef CONFIG_CPU_BPREDICT_DISABLE
  10945. + .ascii "B"
  10946. +#endif
  10947. +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
  10948. + .ascii "RR"
  10949. +#endif
  10950. + .ascii "\0"
  10951. + .align
  10952. +
  10953. + .section ".text.init", #alloc, #execinstr
  10954. +
  10955. +__arm1020E_setup:
  10956. + mov r0, #0
  10957. + mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
  10958. + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
  10959. + mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
  10960. + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
  10961. + mov r0, #0x1f @ Domains 0, 1 = client
  10962. + mcr p15, 0, r0, c3, c0, 0 @ load domain access register
  10963. +
  10964. + mrc p15, 0, r0, c1, c0, 0 @ Read current control register
  10965. +/*
  10966. + * The only thing worth keeping from the initial control register is the endian bit
  10967. + */
  10968. +
  10969. + and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
  10970. + orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
  10971. +/*
  10972. + * Turn on what we want.
  10973. + */
  10974. + orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
  10975. + orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
  10976. + orr r0, r0, #0x2000 @ ..V............. Enable high vectors
  10977. +
  10978. +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
  10979. + orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
  10980. +#endif
  10981. +
  10982. +#ifndef CONFIG_CPU_BPREDICT_DISABLE
  10983. + orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
  10984. +#endif
  10985. +
  10986. +#ifdef CONFIG_CPU_DCACHE_ENABLE
  10987. + orr r0, r0, #0x0004 @ .............C.. Enable D cache
  10988. +#endif
  10989. +#ifndef CONFIG_CPU_WB_DISABLE
  10990. + orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
  10991. +#endif
  10992. +
  10993. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  10994. + orr r0, r0, #0x1000 @ ...I............ Enable I Cache
  10995. +#endif
  10996. +
  10997. + mov pc, lr
  10998. +
  10999. + .text
  11000. +
  11001. +/*
  11002. + * Purpose : Function pointers used to access above functions - all calls
  11003. + * come through these
  11004. + */
  11005. + .type arm1020E_processor_functions, #object
  11006. +arm1020E_processor_functions:
  11007. + .word cpu_arm1020E_data_abort
  11008. + .word cpu_arm1020E_check_bugs
  11009. + .word cpu_arm1020E_proc_init
  11010. + .word cpu_arm1020E_proc_fin
  11011. + .word cpu_arm1020E_reset
  11012. + .word cpu_arm1020E_do_idle
  11013. +
  11014. + /* cache */
  11015. + .word cpu_arm1020E_cache_clean_invalidate_all
  11016. + .word cpu_arm1020E_cache_clean_invalidate_range
  11017. + .word cpu_arm1020E_flush_ram_page
  11018. +
  11019. + /* dcache */
  11020. + .word cpu_arm1020E_dcache_invalidate_range
  11021. + .word cpu_arm1020E_dcache_clean_range
  11022. + .word cpu_arm1020E_dcache_clean_page
  11023. + .word cpu_arm1020E_dcache_clean_entry
  11024. +
  11025. + /* icache */
  11026. + .word cpu_arm1020E_icache_invalidate_range
  11027. + .word cpu_arm1020E_icache_invalidate_page
  11028. +
  11029. + /* tlb */
  11030. + .word cpu_arm1020E_tlb_invalidate_all
  11031. + .word cpu_arm1020E_tlb_invalidate_range
  11032. + .word cpu_arm1020E_tlb_invalidate_page
  11033. +
  11034. + /* pgtable */
  11035. + .word cpu_arm1020E_set_pgd
  11036. + .word cpu_arm1020E_set_pmd
  11037. + .word cpu_arm1020E_set_pte
  11038. + .size arm1020E_processor_functions, . - arm1020E_processor_functions
  11039. +
  11040. + .type cpu_arm1020E_info, #object
  11041. +cpu_arm1020E_info:
  11042. + .long cpu_manu_name
  11043. + .long cpu_arm1020E_name
  11044. + .size cpu_arm1020E_info, . - cpu_arm1020E_info
  11045. +
  11046. + .type cpu_arch_name, #object
  11047. +cpu_arch_name:
  11048. + .asciz "armv5te"
  11049. + .size cpu_arch_name, . - cpu_arch_name
  11050. +
  11051. + .type cpu_elf_name, #object
  11052. +cpu_elf_name:
  11053. + .asciz "v5"
  11054. + .size cpu_elf_name, . - cpu_elf_name
  11055. + .align
  11056. +
  11057. + .section ".proc.info", #alloc, #execinstr
  11058. +
  11059. + .type __arm1020E_proc_info,#object
  11060. +__arm1020E_proc_info:
  11061. + .long 0x4105a200 @ ARM 1020E (Architecture v5TE)
  11062. + .long 0xff0ffff0
  11063. + .long 0x00000c1e @ mmuflags
  11064. + b __arm1020E_setup
  11065. + .long cpu_arch_name
  11066. + .long cpu_elf_name
  11067. + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
  11068. + .long cpu_arm1020E_info
  11069. + .long arm1020E_processor_functions
  11070. + .size __arm1020E_proc_info, . - __arm1020E_proc_info
  11071. +
  11072. diff -urN linux-2.4.26/arch/arm/mm/proc-arm1022.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm1022.S
  11073. --- linux-2.4.26/arch/arm/mm/proc-arm1022.S 1970-01-01 01:00:00.000000000 +0100
  11074. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm1022.S 2004-01-14 21:32:24.000000000 +0000
  11075. @@ -0,0 +1,716 @@
  11076. +/*
  11077. + * linux/arch/arm/mm/proc-arm1022.S: MMU functions for ARM1022E
  11078. + *
  11079. + * Copyright (C) 2000 ARM Limited
  11080. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  11081. + *
  11082. + * This program is free software; you can redistribute it and/or modify
  11083. + * it under the terms of the GNU General Public License as published by
  11084. + * the Free Software Foundation; either version 2 of the License, or
  11085. + * (at your option) any later version.
  11086. + *
  11087. + * This program is distributed in the hope that it will be useful,
  11088. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11089. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11090. + * GNU General Public License for more details.
  11091. + *
  11092. + * You should have received a copy of the GNU General Public License
  11093. + * along with this program; if not, write to the Free Software
  11094. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  11095. + *
  11096. + *
  11097. + * These are the low level assembler for performing cache and TLB
  11098. + * functions on the arm1022E.
  11099. + */
  11100. +#include <linux/linkage.h>
  11101. +#include <linux/config.h>
  11102. +#include <asm/assembler.h>
  11103. +#include <asm/constants.h>
  11104. +#include <asm/procinfo.h>
  11105. +#include <asm/hardware.h>
  11106. +
  11107. +/*
  11108. + * This is the maximum size of an area which will be invalidated
  11109. + * using the single invalidate entry instructions. Anything larger
  11110. + * than this, and we go for the whole cache.
  11111. + *
  11112. + * This value should be chosen such that we choose the cheapest
  11113. + * alternative.
  11114. + */
  11115. +#define MAX_AREA_SIZE 16384
  11116. +
  11117. +/*
  11118. + * the cache line size of the I and D cache
  11119. + */
  11120. +#define DCACHELINESIZE 32
  11121. +#define ICACHELINESIZE 32
  11122. +
  11123. +/*
  11124. + * and the page size
  11125. + */
  11126. +#define LOG2PAGESIZE 12 /* == 4096 Bytes */
  11127. +#define PAGESIZE (1 << LOG2PAGESIZE)
  11128. +
  11129. +/*
  11130. + * create some useful conditional macro definitions
  11131. + * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
  11132. + */
  11133. +#ifdef CONFIG_CPU_DCACHE_DISABLE
  11134. + #undef CONFIG_CPU_DCACHE_WRITETHROUGH
  11135. + #undef CONFIG_CPU_DCACHE_WRITEBACK
  11136. + #undef CONFIG_CPU_DCACHE_ENABLE
  11137. +#else
  11138. + #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11139. + #undef CONFIG_CPU_DCACHE_WRITEBACK
  11140. + #else
  11141. + #define CONFIG_CPU_DCACHE_WRITEBACK
  11142. + #endif
  11143. + #define CONFIG_CPU_DCACHE_ENABLE
  11144. +#endif
  11145. +
  11146. +#ifdef CONFIG_CPU_ICACHE_DISABLE
  11147. + #undef CONFIG_CPU_ICACHE_ENABLE
  11148. +#else
  11149. + #define CONFIG_CPU_ICACHE_ENABLE
  11150. +#endif
  11151. +
  11152. + .text
  11153. +
  11154. +/*
  11155. + * cpu_arm1022_data_abort()
  11156. + *
  11157. + * obtain information about current aborted instruction
  11158. + * Note: we read user space. This means we might cause a data
  11159. + * abort here if the I-TLB and D-TLB aren't seeing the same
  11160. + * picture. Unfortunately, this does happen. We live with it.
  11161. + *
  11162. + * r2 = address of aborted instruction
  11163. + * r3 = cpsr
  11164. + *
  11165. + * Returns:
  11166. + * r0 = address of abort
  11167. + * r1 = FSR
  11168. + * r3 = corrupted
  11169. + * r4 = corrupted
  11170. + */
  11171. + .align 5
  11172. +ENTRY(cpu_arm1022_data_abort)
  11173. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  11174. + mrc p15, 0, r0, c6, c0, 0 @ get FAR
  11175. + tst r3, #PSR_T_BIT
  11176. + ldrneh r3, [r2] @ read aborted thumb instruction
  11177. + ldreq r3, [r2] @ read aborted ARM instruction
  11178. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  11179. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  11180. + tst r3, #1 << 20 @ check write
  11181. + orreq r1, r1, #1 << 11
  11182. + mov pc, lr
  11183. +
  11184. +/*
  11185. + * cpu_arm1022_check_bugs()
  11186. + */
  11187. +ENTRY(cpu_arm1022_check_bugs)
  11188. + mrs ip, cpsr
  11189. + bic ip, ip, #F_BIT
  11190. + msr cpsr, ip
  11191. + mov pc, lr
  11192. +
  11193. +/*
  11194. + * cpu_arm1022_proc_init()
  11195. + */
  11196. +ENTRY(cpu_arm1022_proc_init)
  11197. + mov pc, lr
  11198. +
  11199. +/*
  11200. + * cpu_arm1022_proc_fin()
  11201. + */
  11202. +ENTRY(cpu_arm1022_proc_fin)
  11203. + stmfd sp!, {lr}
  11204. + mov ip, #F_BIT | I_BIT | SVC_MODE
  11205. + msr cpsr_c, ip
  11206. + bl cpu_arm1022_cache_clean_invalidate_all
  11207. + mrc p15, 0, r0, c1, c0, 0 @ ctrl register
  11208. + bic r0, r0, #0x1000 @ ...i............
  11209. + bic r0, r0, #0x000e @ ............wca.
  11210. + mcr p15, 0, r0, c1, c0, 0 @ disable caches
  11211. + ldmfd sp!, {pc}
  11212. +
  11213. +/*
  11214. + * cpu_arm1022_reset(loc)
  11215. + *
  11216. + * Perform a soft reset of the system. Put the CPU into the
  11217. + * same state as it would be if it had been reset, and branch
  11218. + * to what would be the reset vector.
  11219. + *
  11220. + * loc: location to jump to for soft reset
  11221. + */
  11222. + .align 5
  11223. +ENTRY(cpu_arm1022_reset)
  11224. + mov ip, #0
  11225. + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
  11226. + mcr p15, 0, ip, c7, c10, 4 @ drain WB
  11227. + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
  11228. + mrc p15, 0, ip, c1, c0, 0 @ ctrl register
  11229. + bic ip, ip, #0x000f @ ............wcam
  11230. + bic ip, ip, #0x1100 @ ...i...s........
  11231. + mcr p15, 0, ip, c1, c0, 0 @ ctrl register
  11232. + mov pc, r0
  11233. +
  11234. +/*
  11235. + * cpu_arm1022_do_idle()
  11236. + */
  11237. + .align 5
  11238. +ENTRY(cpu_arm1022_do_idle)
  11239. + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
  11240. + mov pc, lr
  11241. +
  11242. +/* ================================= CACHE ================================ */
  11243. +
  11244. +
  11245. +/*
  11246. + * cpu_arm1022_cache_clean_invalidate_all()
  11247. + *
  11248. + * clean and invalidate all cache lines
  11249. + *
  11250. + * Note:
  11251. + * 1. we should preserve r0 and ip at all times
  11252. + */
  11253. + .align 5
  11254. +ENTRY(cpu_arm1022_cache_clean_invalidate_all)
  11255. + mov r2, #1
  11256. +cpu_arm1022_cache_clean_invalidate_all_r2:
  11257. +
  11258. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11259. + mov r1, #7 << 5 @ 8 segments
  11260. +1: orr r3, r1, #63 << 26 @ 64 entries
  11261. +2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
  11262. + subs r3, r3, #1 << 26
  11263. + bcs 2b
  11264. + subs r1, r1, #1 << 5
  11265. + bcs 1b @ segments 7 to 0
  11266. +#endif
  11267. +
  11268. + mov r1, #0
  11269. +
  11270. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11271. + mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
  11272. +#endif
  11273. +
  11274. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11275. + teq r2, #0
  11276. + mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
  11277. +#endif
  11278. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  11279. + mov pc, lr
  11280. +
  11281. +/*
  11282. + * cpu_arm1022_cache_clean_invalidate_range(start, end, flags)
  11283. + *
  11284. + * clean and invalidate all cache lines associated with this area of memory
  11285. + *
  11286. + * start: Area start address
  11287. + * end: Area end address
  11288. + * flags: nonzero for I cache as well
  11289. + */
  11290. + .align 5
  11291. +ENTRY(cpu_arm1022_cache_clean_invalidate_range)
  11292. + bic r0, r0, #DCACHELINESIZE - 1
  11293. + sub r3, r1, r0
  11294. + cmp r3, #MAX_AREA_SIZE
  11295. + bhs cpu_arm1022_cache_clean_invalidate_all_r2
  11296. +1:
  11297. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11298. + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  11299. +#endif
  11300. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11301. + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
  11302. +#endif
  11303. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11304. + teq r2, #0
  11305. + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
  11306. +#endif
  11307. + add r0, r0, #DCACHELINESIZE
  11308. + cmp r0, r1
  11309. + bls 1b @ unsigned lower or same - must include end point (r1)!
  11310. +
  11311. + mov r1, #0
  11312. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  11313. + mov pc, lr
  11314. +
  11315. +/*
  11316. + * cpu_arm1022_flush_ram_page(page)
  11317. + *
  11318. + * clean and invalidate all cache lines associated with this area of memory
  11319. + *
  11320. + * page: page to clean and invalidate
  11321. + */
  11322. + .align 5
  11323. +ENTRY(cpu_arm1022_flush_ram_page)
  11324. + mov r1, #PAGESIZE
  11325. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  11326. + mov r0, r0, LSL #LOG2PAGESIZE
  11327. +1:
  11328. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11329. + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  11330. +#endif
  11331. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11332. + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
  11333. +#endif
  11334. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11335. + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
  11336. +#endif
  11337. + add r0, r0, #DCACHELINESIZE
  11338. + subs r1, r1, #DCACHELINESIZE
  11339. + bne 1b
  11340. +
  11341. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  11342. + mov pc, lr
  11343. +
  11344. +/* ================================ D-CACHE =============================== */
  11345. +
  11346. +/*
  11347. + * cpu_arm1022_dcache_invalidate_range(start, end)
  11348. + *
  11349. + * throw away all D-cached data in specified region without an obligation
  11350. + * to write them back. Note however that we must clean the D-cached entries
  11351. + * around the boundaries if the start and/or end address are not cache
  11352. + * aligned.
  11353. + *
  11354. + * start: virtual start address
  11355. + * end: virtual end address
  11356. + */
  11357. + .align 5
  11358. +ENTRY(cpu_arm1022_dcache_invalidate_range)
  11359. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11360. + bic r0, r0, #DCACHELINESIZE - 1
  11361. +#endif
  11362. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11363. + tst r0, #DCACHELINESIZE - 1
  11364. + bic r0, r0, #DCACHELINESIZE - 1
  11365. + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
  11366. + tst r1, #DCACHELINESIZE - 1
  11367. + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
  11368. +#endif
  11369. +
  11370. +1:
  11371. +#ifdef CONFIG_CPU_DCACHE_ENABLE
  11372. + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  11373. +#endif
  11374. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11375. + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
  11376. +#endif
  11377. + add r0, r0, #DCACHELINESIZE
  11378. + cmp r0, r1
  11379. + bls 1b
  11380. +
  11381. + /* Even if the D cache is off still drain the write buffer */
  11382. + mov r0, #0
  11383. + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
  11384. + mov pc, lr
  11385. +
  11386. +/*
  11387. + * cpu_arm1022_dcache_clean_range(start, end)
  11388. + *
  11389. + * For the specified virtual address range, ensure that all caches contain
  11390. + * clean data, such that peripheral accesses to the physical RAM fetch
  11391. + * correct data.
  11392. + *
  11393. + * start: virtual start address
  11394. + * end: virtual end address
  11395. + */
  11396. + .align 5
  11397. +ENTRY(cpu_arm1022_dcache_clean_range)
  11398. +
  11399. + mov r2, #0
  11400. +
  11401. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11402. + bic r0, r0, #DCACHELINESIZE - 1
  11403. + sub r3, r1, r0
  11404. + cmp r3, #MAX_AREA_SIZE
  11405. + bhs cpu_arm1022_cache_clean_invalidate_all_r2
  11406. +
  11407. +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11408. + add r0, r0, #DCACHELINESIZE
  11409. + cmp r0, r1
  11410. + bls 1b
  11411. +#endif
  11412. +
  11413. + mcr p15, 0, r2, c7, c10, 4 @ drain WB
  11414. + mov pc, lr
  11415. +
  11416. +/*
  11417. + * cpu_arm1022_dcache_clean_page(page)
  11418. + *
  11419. + * Cleans a single page of dcache so that if we have any future aliased
  11420. + * mappings, they will be consistent at the time that they are created.
  11421. + *
  11422. + * page: virtual address of page to clean from dcache
  11423. + *
  11424. + * Note:
  11425. + * we don't invalidate the entries since when we write the page
  11426. + * out to disk, the entries may get reloaded into the cache.
  11427. + */
  11428. + .align 5
  11429. +ENTRY(cpu_arm1022_dcache_clean_page)
  11430. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11431. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  11432. + mov r0, r0, LSL #LOG2PAGESIZE
  11433. + mov r1, #PAGESIZE
  11434. +1:
  11435. + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11436. + add r0, r0, #DCACHELINESIZE
  11437. + subs r1, r1, #DCACHELINESIZE
  11438. + bne 1b
  11439. +#endif
  11440. + mov r1, #0
  11441. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  11442. + mov pc, lr
  11443. +
  11444. +/*
  11445. + * cpu_arm1022_dcache_clean_entry(addr)
  11446. + *
  11447. + * Clean the specified entry of any caches such that the MMU
  11448. + * translation fetches will obtain correct data.
  11449. + *
  11450. + * addr: cache-unaligned virtual address
  11451. + */
  11452. + .align 5
  11453. +ENTRY(cpu_arm1022_dcache_clean_entry)
  11454. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11455. + bic r0, r0, #DCACHELINESIZE - 1
  11456. + mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
  11457. +#endif
  11458. + mov r1, #0
  11459. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  11460. + mov pc, lr
  11461. +
  11462. +/* ================================ I-CACHE =============================== */
  11463. +
  11464. +/*
  11465. + * cpu_arm1022_icache_invalidate_range(start, end)
  11466. + *
  11467. + * invalidate a range of virtual addresses from the Icache
  11468. + *
  11469. + * This is a little misleading, it is not intended to clean out
  11470. + * the i-cache but to make sure that any data written to the
  11471. + * range is made consistent. This means that when we execute code
  11472. + * in that region, everything works as we expect.
  11473. + *
  11474. + * This generally means writing back data in the Dcache and
  11475. + * write buffer and invalidating the Icache over that region
  11476. + *
  11477. + * start: virtual start address
  11478. + * end: virtual end address
  11479. + *
  11480. + * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
  11481. + * loop twice, once for i-cache, once for d-cache)
  11482. + */
  11483. + .align 5
  11484. +ENTRY(cpu_arm1022_icache_invalidate_range)
  11485. + bic r0, r0, #ICACHELINESIZE - 1
  11486. + sub r3, r1, r0
  11487. + cmp r3, #MAX_AREA_SIZE
  11488. + movhs r2, #1
  11489. + bhs cpu_arm1022_cache_clean_invalidate_all_r2
  11490. +1:
  11491. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11492. + mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
  11493. +#endif
  11494. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11495. + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
  11496. +#endif
  11497. + add r0, r0, #DCACHELINESIZE
  11498. + cmp r0, r1
  11499. + bls 1b @ unsigned lower or same - includes r1 entry
  11500. +
  11501. + mov r0, #0
  11502. + mcr p15, 0, r0, c7, c10, 4 @ drain WB
  11503. + mov pc, lr
  11504. +
  11505. +ENTRY(cpu_arm1022_icache_invalidate_page)
  11506. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  11507. + mov r0, r0, LSL #LOG2PAGESIZE
  11508. + add r1, r0, #PAGESIZE
  11509. + b cpu_arm1022_icache_invalidate_range
  11510. +
  11511. +/* ================================== TLB ================================= */
  11512. +
  11513. +/*
  11514. + * cpu_arm1022_tlb_invalidate_all()
  11515. + *
  11516. + * Invalidate all TLB entries
  11517. + */
  11518. + .align 5
  11519. +ENTRY(cpu_arm1022_tlb_invalidate_all)
  11520. + mov r0, #0
  11521. + mcr p15, 0, r0, c7, c10, 4 @ drain WB
  11522. + mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
  11523. + mov pc, lr
  11524. +
  11525. +/*
  11526. + * cpu_arm1022_tlb_invalidate_range(start, end)
  11527. + *
  11528. + * invalidate TLB entries covering the specified range
  11529. + *
  11530. + * start: range start address
  11531. + * end: range end address
  11532. + */
  11533. + .align 5
  11534. +ENTRY(cpu_arm1022_tlb_invalidate_range)
  11535. + sub r3, r1, r0
  11536. + cmp r3, #256 * PAGESIZE
  11537. + bhs cpu_arm1022_tlb_invalidate_all
  11538. + mov r3, #0
  11539. + mcr p15, 0, r3, c7, c10, 4 @ drain WB
  11540. + mov r3, #PAGESIZE
  11541. + sub r3, r3, #1
  11542. + bic r0, r0, r3
  11543. +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  11544. + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  11545. + add r0, r0, #PAGESIZE
  11546. + cmp r0, r1
  11547. + bls 1b
  11548. + mov pc, lr
  11549. +
  11550. +/*
  11551. + * cpu_arm1022_tlb_invalidate_page(page, flags)
  11552. + *
  11553. + * invalidate the TLB entries for the specified page.
  11554. + *
  11555. + * page: page to invalidate
  11556. + * flags: non-zero if we include the I TLB
  11557. + */
  11558. + .align 5
  11559. +ENTRY(cpu_arm1022_tlb_invalidate_page)
  11560. + mov r3, #0
  11561. + mcr p15, 0, r3, c7, c10, 4 @ drain WB
  11562. + mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
  11563. + mov r0, r0, LSL #LOG2PAGESIZE
  11564. + teq r1, #0
  11565. + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  11566. + mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  11567. + mov pc, lr
  11568. +
  11569. +/* =============================== PageTable ============================== */
  11570. +
  11571. +/*
  11572. + * cpu_arm1022_set_pgd(pgd)
  11573. + *
  11574. + * Set the translation base pointer to be as described by pgd.
  11575. + *
  11576. + * pgd: new page tables
  11577. + */
  11578. + .align 5
  11579. +ENTRY(cpu_arm1022_set_pgd)
  11580. + stmfd sp!, {lr}
  11581. + bl cpu_arm1022_cache_clean_invalidate_all @ preserves r0
  11582. + mov r1, #0
  11583. + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
  11584. + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
  11585. + ldmfd sp!, {pc}
  11586. +
  11587. +/*
  11588. + * cpu_arm1022_set_pmd(pmdp, pmd)
  11589. + *
  11590. + * Set a level 1 translation table entry, and clean it out of
  11591. + * any caches such that the MMUs can load it correctly.
  11592. + *
  11593. + * pmdp: pointer to PMD entry
  11594. + * pmd: PMD value to store
  11595. + */
  11596. + .align 5
  11597. +ENTRY(cpu_arm1022_set_pmd)
  11598. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11599. + eor r2, r1, #0x0a @ C & Section
  11600. + tst r2, #0x0b
  11601. + biceq r1, r1, #4 @ clear bufferable bit
  11602. +#endif
  11603. + str r1, [r0]
  11604. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11605. + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11606. +#endif
  11607. + mov r0, #0
  11608. + mcr p15, 0, r0, c7, c10, 4 @ drain WB
  11609. + mov pc, lr
  11610. +
  11611. +/*
  11612. + * cpu_arm1022_set_pte(ptep, pte)
  11613. + *
  11614. + * Set a PTE and flush it out
  11615. + */
  11616. + .align 5
  11617. +ENTRY(cpu_arm1022_set_pte)
  11618. + str r1, [r0], #-1024 @ linux version
  11619. +
  11620. + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
  11621. +
  11622. + bic r2, r1, #0xff0
  11623. + bic r2, r2, #3
  11624. + orr r2, r2, #HPTE_TYPE_SMALL
  11625. +
  11626. + tst r1, #LPTE_USER @ User?
  11627. + orrne r2, r2, #HPTE_AP_READ
  11628. +
  11629. + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  11630. + orreq r2, r2, #HPTE_AP_WRITE
  11631. +
  11632. + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
  11633. + movne r2, #0
  11634. +
  11635. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11636. + eor r3, r2, #0x0a @ C and Small Page?
  11637. + tst r3, #0x0b @ if so..
  11638. + biceq r2, r2, #0x04 @ clear the bufferable bit
  11639. +#endif
  11640. + str r2, [r0] @ hardware version
  11641. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11642. + mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11643. +#endif
  11644. + mov r1, #0
  11645. + mcr p15, 0, r1, c7, c10, 4 @ drain WB
  11646. + mov pc, lr
  11647. +
  11648. +
  11649. +cpu_manu_name:
  11650. + .asciz "ARM"
  11651. +ENTRY(cpu_arm1022_name)
  11652. + .ascii "Arm1022E"
  11653. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11654. + .ascii "i"
  11655. +#endif
  11656. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11657. + .ascii "d"
  11658. +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  11659. + .ascii "(wt)"
  11660. +#endif
  11661. +#ifdef CONFIG_CPU_DCACHE_WRITEBACK
  11662. + .ascii "(wb)"
  11663. +#endif
  11664. +#endif
  11665. +#ifndef CONFIG_CPU_BPREDICT_DISABLE
  11666. + .ascii "B"
  11667. +#endif
  11668. +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
  11669. + .ascii "RR"
  11670. +#endif
  11671. + .ascii "\0"
  11672. + .align
  11673. +
  11674. + .section ".text.init", #alloc, #execinstr
  11675. +
  11676. +__arm1022_setup:
  11677. + mov r0, #0
  11678. + mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
  11679. + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
  11680. + mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
  11681. + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
  11682. + mov r0, #0x1f @ Domains 0, 1 = client
  11683. + mcr p15, 0, r0, c3, c0, 0 @ load domain access register
  11684. +
  11685. + mrc p15, 0, r0, c1, c0, 0 @ Read current control register
  11686. +/*
  11687. + * The only thing worth keeping from the initial control register is the endian bit
  11688. + */
  11689. +
  11690. + and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
  11691. + orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
  11692. +/*
  11693. + * Turn on what we want.
  11694. + */
  11695. + orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
  11696. + orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
  11697. + orr r0, r0, #0x2000 @ ..V............. Enable high vectors
  11698. +
  11699. +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
  11700. + orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
  11701. +#endif
  11702. +
  11703. +#ifndef CONFIG_CPU_BPREDICT_DISABLE
  11704. + orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
  11705. +#endif
  11706. +
  11707. +#ifdef CONFIG_CPU_DCACHE_ENABLE
  11708. + orr r0, r0, #0x0004 @ .............C.. Enable D cache
  11709. +#endif
  11710. +#ifndef CONFIG_CPU_WB_DISABLE
  11711. + orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
  11712. +#endif
  11713. +
  11714. +#ifdef CONFIG_CPU_ICACHE_ENABLE
  11715. + orr r0, r0, #0x1000 @ ...I............ Enable I Cache
  11716. +#endif
  11717. +
  11718. + mov pc, lr
  11719. +
  11720. + .text
  11721. +
  11722. +/*
  11723. + * Purpose : Function pointers used to access above functions - all calls
  11724. + * come through these
  11725. + */
  11726. + .type arm1022_processor_functions, #object
  11727. +arm1022_processor_functions:
  11728. + .word cpu_arm1022_data_abort
  11729. + .word cpu_arm1022_check_bugs
  11730. + .word cpu_arm1022_proc_init
  11731. + .word cpu_arm1022_proc_fin
  11732. + .word cpu_arm1022_reset
  11733. + .word cpu_arm1022_do_idle
  11734. +
  11735. + /* cache */
  11736. + .word cpu_arm1022_cache_clean_invalidate_all
  11737. + .word cpu_arm1022_cache_clean_invalidate_range
  11738. + .word cpu_arm1022_flush_ram_page
  11739. +
  11740. + /* dcache */
  11741. + .word cpu_arm1022_dcache_invalidate_range
  11742. + .word cpu_arm1022_dcache_clean_range
  11743. + .word cpu_arm1022_dcache_clean_page
  11744. + .word cpu_arm1022_dcache_clean_entry
  11745. +
  11746. + /* icache */
  11747. + .word cpu_arm1022_icache_invalidate_range
  11748. + .word cpu_arm1022_icache_invalidate_page
  11749. +
  11750. + /* tlb */
  11751. + .word cpu_arm1022_tlb_invalidate_all
  11752. + .word cpu_arm1022_tlb_invalidate_range
  11753. + .word cpu_arm1022_tlb_invalidate_page
  11754. +
  11755. + /* pgtable */
  11756. + .word cpu_arm1022_set_pgd
  11757. + .word cpu_arm1022_set_pmd
  11758. + .word cpu_arm1022_set_pte
  11759. + .size arm1022_processor_functions, . - arm1022_processor_functions
  11760. +
  11761. + .type cpu_arm1022_info, #object
  11762. +cpu_arm1022_info:
  11763. + .long cpu_manu_name
  11764. + .long cpu_arm1022_name
  11765. + .size cpu_arm1022_info, . - cpu_arm1022_info
  11766. +
  11767. + .type cpu_arch_name, #object
  11768. +cpu_arch_name:
  11769. + .asciz "armv5t"
  11770. + .size cpu_arch_name, . - cpu_arch_name
  11771. +
  11772. + .type cpu_elf_name, #object
  11773. +cpu_elf_name:
  11774. + .asciz "v5"
  11775. + .size cpu_elf_name, . - cpu_elf_name
  11776. + .align
  11777. +
  11778. + .section ".proc.info", #alloc, #execinstr
  11779. +
  11780. + .type __arm1022_proc_info,#object
  11781. +__arm1022_proc_info:
  11782. + .long 0x4100a220 @ ARM 1022
  11783. + .long 0xff00fff0
  11784. + .long 0x00000c1e @ mmuflags
  11785. + b __arm1022_setup
  11786. + .long cpu_arch_name
  11787. + .long cpu_elf_name
  11788. + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
  11789. + .long cpu_arm1022_info
  11790. + .long arm1022_processor_functions
  11791. + .size __arm1022_proc_info, . - __arm1022_proc_info
  11792. diff -urN linux-2.4.26/arch/arm/mm/proc-arm1026.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm1026.S
  11793. --- linux-2.4.26/arch/arm/mm/proc-arm1026.S 2003-08-25 12:44:39.000000000 +0100
  11794. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm1026.S 2004-02-10 23:03:10.000000000 +0000
  11795. @@ -66,19 +66,24 @@
  11796. *
  11797. * Returns:
  11798. * r0 = address of abort
  11799. - * r1 != 0 if writing
  11800. - * r3 = FSR
  11801. + * r1 = FSR, bit 11 set if writing
  11802. + * r3 = corrupted
  11803. * r4 = corrupted
  11804. */
  11805. .align 5
  11806. ENTRY(cpu_arm1026_data_abort)
  11807. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  11808. - and r2, r3, #0b1101 @ Check for translation error
  11809. - sub r1, r2, #0b0101
  11810. -
  11811. - and r3, r3, #255
  11812. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  11813. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  11814. -
  11815. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  11816. + tst r3, #PSR_J_BIT @ Java?
  11817. + orrne r1, r1, #1 << 11 @ always assume write
  11818. + movne pc, lr
  11819. + tst r3, #PSR_T_BIT
  11820. + ldrneh r3, [r2] @ read aborted thumb instruction
  11821. + ldreq r3, [r2] @ read aborted ARM instruction
  11822. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  11823. + tst r3, #1 << 20 @ check write
  11824. + orreq r1, r1, #1 << 11
  11825. mov pc, lr
  11826. /*
  11827. @@ -254,7 +259,7 @@
  11828. */
  11829. .align 5
  11830. ENTRY(cpu_arm1026_dcache_invalidate_range)
  11831. -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
  11832. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  11833. tst r0, #DCACHELINESIZE - 1
  11834. mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
  11835. tst r1, #DCACHELINESIZE - 1
  11836. @@ -279,7 +284,7 @@
  11837. */
  11838. .align 5
  11839. ENTRY(cpu_arm1026_dcache_clean_range)
  11840. -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
  11841. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  11842. bic r0, r0, #DCACHELINESIZE - 1
  11843. sub r3, r1, r0
  11844. cmp r3, #MAX_AREA_SIZE
  11845. @@ -309,7 +314,7 @@
  11846. */
  11847. .align 5
  11848. ENTRY(cpu_arm1026_dcache_clean_page)
  11849. -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
  11850. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  11851. mov r1, #PAGESIZE
  11852. 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11853. add r0, r0, #DCACHELINESIZE
  11854. @@ -330,7 +335,7 @@
  11855. */
  11856. .align 5
  11857. ENTRY(cpu_arm1026_dcache_clean_entry)
  11858. -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
  11859. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  11860. mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11861. #endif
  11862. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  11863. @@ -473,7 +478,7 @@
  11864. biceq r1, r1, #4 @ clear bufferable bit
  11865. #endif
  11866. str r1, [r0]
  11867. -#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
  11868. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  11869. mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  11870. #endif
  11871. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  11872. @@ -494,7 +499,7 @@
  11873. bic r2, r2, #3
  11874. orr r2, r2, #HPTE_TYPE_SMALL
  11875. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  11876. + tst r1, #LPTE_USER @ User?
  11877. orrne r2, r2, #HPTE_AP_READ
  11878. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  11879. @@ -634,12 +639,12 @@
  11880. .type cpu_arch_name, #object
  11881. cpu_arch_name:
  11882. - .asciz "armv5EJ"
  11883. + .asciz "armv5tej"
  11884. .size cpu_arch_name, . - cpu_arch_name
  11885. .type cpu_elf_name, #object
  11886. cpu_elf_name:
  11887. - .asciz "v5EJ"
  11888. + .asciz "v5"
  11889. .size cpu_elf_name, . - cpu_elf_name
  11890. .align
  11891. diff -urN linux-2.4.26/arch/arm/mm/proc-arm6,7.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm6,7.S
  11892. --- linux-2.4.26/arch/arm/mm/proc-arm6,7.S 2003-08-25 12:44:39.000000000 +0100
  11893. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm6,7.S 2004-01-14 21:38:43.000000000 +0000
  11894. @@ -72,7 +72,7 @@
  11895. 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
  11896. add r0, r0, #4096
  11897. cmp r0, r1
  11898. - blt 1b
  11899. + blo 1b
  11900. mov pc, lr
  11901. ENTRY(cpu_arm7_tlb_invalidate_range)
  11902. @@ -85,7 +85,7 @@
  11903. 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
  11904. add r0, r0, #0x4000
  11905. cmp r0, r1
  11906. - blt 1b
  11907. + blo 1b
  11908. mov pc, lr
  11909. #endif
  11910. @@ -110,15 +110,13 @@
  11911. * Purpose : obtain information about current aborted instruction
  11912. *
  11913. * Returns : r0 = address of abort
  11914. - * : r1 != 0 if writing
  11915. - * : r3 = FSR
  11916. + * : r1 = FSR, bit 11 set if writing
  11917. + * : r3 = corrupted
  11918. * : sp = pointer to registers
  11919. */
  11920. ENTRY(cpu_arm6_data_abort)
  11921. ldr r4, [r0] @ read instruction causing problem
  11922. - tst r4, r4, lsr #21 @ C = bit 20
  11923. - sbc r1, r1, r1 @ r1 = C - 1
  11924. and r2, r4, #14 << 24
  11925. teq r2, #8 << 24 @ was it ldm/stm
  11926. bne Ldata_simple
  11927. @@ -144,14 +142,14 @@
  11928. addeq r7, r0, r7, lsl #2 @ Do correction (signed)
  11929. Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
  11930. Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
  11931. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  11932. - and r3, r3, #255
  11933. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  11934. + bic r1, r1, #1 << 11 | 1 << 10
  11935. + tst r4, #1 << 20
  11936. + orreq r1, r1, #1 << 11
  11937. mov pc, lr
  11938. ENTRY(cpu_arm7_data_abort)
  11939. ldr r4, [r0] @ read instruction causing problem
  11940. - tst r4, r4, lsr #21 @ C = bit 20
  11941. - sbc r1, r1, r1 @ r1 = C - 1
  11942. and r2, r4, #15 << 24
  11943. add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
  11944. movs pc, lr
  11945. @@ -336,7 +334,7 @@
  11946. bic r2, r2, #3
  11947. orr r2, r2, #HPTE_TYPE_SMALL
  11948. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  11949. + tst r1, #LPTE_USER @ User?
  11950. orrne r2, r2, #HPTE_AP_READ
  11951. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  11952. diff -urN linux-2.4.26/arch/arm/mm/proc-arm720.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm720.S
  11953. --- linux-2.4.26/arch/arm/mm/proc-arm720.S 2003-08-25 12:44:39.000000000 +0100
  11954. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm720.S 2004-02-24 09:30:43.000000000 +0000
  11955. @@ -97,7 +97,7 @@
  11956. 1: mcr p15, 0, r0, c8, c7, 1 @ flush TLB (v4)
  11957. add r0, r0, #PAGESIZE
  11958. cmp r0, r1
  11959. - blt 1b
  11960. + blo 1b
  11961. mov pc, lr
  11962. /*
  11963. @@ -124,8 +124,8 @@
  11964. * picture. Unfortunately, this does happen. We live with it.
  11965. *
  11966. * Returns : r0 = address of abort
  11967. - * : r1 != 0 if writing
  11968. - * : r3 = FSR
  11969. + * : r1 = FSR, bit 11 set if writing
  11970. + * : r3 = corrupted
  11971. * : sp = pointer to registers
  11972. */
  11973. @@ -150,16 +150,16 @@
  11974. addeq r7, r0, r7, lsl #2 @ Do correction (signed)
  11975. Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
  11976. Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
  11977. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  11978. - and r3, r3, #255
  11979. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  11980. + bic r1, r1, #1 << 11 | 1 << 10
  11981. + tst r4, #1 << 20
  11982. + orreq r1, r1, #1 << 11
  11983. mov pc, lr
  11984. ENTRY(cpu_arm720_data_abort)
  11985. - tst r3, #T_BIT
  11986. + tst r3, #PSR_T_BIT
  11987. bne .data_thumb_abort
  11988. - ldr r4, [r0] @ read instruction causing problem
  11989. - tst r4, r4, lsr #21 @ C = bit 20
  11990. - sbc r1, r1, r1 @ r1 = C - 1
  11991. + ldr r4, [r2] @ read instruction causing problem
  11992. and r2, r4, #15 << 24
  11993. add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
  11994. movs pc, lr
  11995. @@ -270,9 +270,9 @@
  11996. b Ldata_saver7
  11997. .data_thumb_abort:
  11998. - ldrh r4, [r0] @ read instruction
  11999. - tst r4, r4, lsr #12 @ C = bit 11
  12000. - sbc r1, r1, r1 @ r1 = C - 1
  12001. + ldrh r4, [r2] @ read instruction
  12002. + tst r4, #1 << 11
  12003. + orrne r4, r4, #1 << 20
  12004. and r2, r4, #15 << 12
  12005. add pc, pc, r2, lsr #10 @ lookup in table
  12006. nop
  12007. @@ -318,8 +318,8 @@
  12008. and r0, r0, #15 @ number of regs to transfer
  12009. ldr r7, [sp, #13 << 2]
  12010. tst r4, #1 << 11
  12011. - addne r7, r7, r0, lsl #2 @ increment SP if PUSH
  12012. - subeq r7, r7, r0, lsr #2 @ decrement SP if POP
  12013. + addeq r7, r7, r0, lsl #2 @ increment SP if PUSH
  12014. + subne r7, r7, r0, lsl #2 @ decrement SP if POP
  12015. str r7, [sp, #13 << 2]
  12016. b Ldata_simple
  12017. @@ -336,7 +336,7 @@
  12018. and r0, r0, #15 @ number of regs to transfer
  12019. and r5, r4, #7 << 8
  12020. ldr r7, [sp, r5, lsr #6]
  12021. - sub r7, r7, r0, lsr #2 @ always decrement
  12022. + sub r7, r7, r0, lsl #2 @ always decrement
  12023. str r7, [sp, r5, lsr #6]
  12024. b Ldata_simple
  12025. @@ -418,7 +418,7 @@
  12026. bic r2, r2, #3
  12027. orr r2, r2, #HPTE_TYPE_SMALL
  12028. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  12029. + tst r1, #LPTE_USER @ User?
  12030. orrne r2, r2, #HPTE_AP_READ
  12031. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  12032. diff -urN linux-2.4.26/arch/arm/mm/proc-arm920.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm920.S
  12033. --- linux-2.4.26/arch/arm/mm/proc-arm920.S 2003-08-25 12:44:39.000000000 +0100
  12034. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm920.S 2004-01-14 21:32:24.000000000 +0000
  12035. @@ -71,12 +71,16 @@
  12036. */
  12037. .align 5
  12038. ENTRY(cpu_arm920_data_abort)
  12039. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  12040. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  12041. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  12042. - ldr r1, [r2] @ read aborted instruction
  12043. - and r3, r3, #255
  12044. - tst r1, r1, lsr #21 @ C = bit 20
  12045. - sbc r1, r1, r1 @ r1 = C - 1
  12046. +
  12047. + tst r3, #PSR_T_BIT
  12048. + ldrneh r3, [r2] @ read aborted thumb instruction
  12049. + ldreq r3, [r2] @ read aborted ARM instruction
  12050. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  12051. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  12052. + tst r3, #1 << 20 @ check write
  12053. + orreq r1, r1, #1 << 11
  12054. mov pc, lr
  12055. /*
  12056. @@ -186,10 +190,9 @@
  12057. .align 5
  12058. ENTRY(cpu_arm920_cache_clean_invalidate_range)
  12059. bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM
  12060. - bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
  12061. sub r3, r1, r0
  12062. cmp r3, #MAX_AREA_SIZE
  12063. - bgt cpu_arm920_cache_clean_invalidate_all_r2
  12064. + bhi cpu_arm920_cache_clean_invalidate_all_r2
  12065. 1: teq r2, #0
  12066. #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  12067. mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  12068. @@ -207,7 +210,7 @@
  12069. add r0, r0, #DCACHELINESIZE
  12070. #endif
  12071. cmp r0, r1
  12072. - blt 1b
  12073. + blo 1b
  12074. mcr p15, 0, r1, c7, c10, 4 @ drain WB
  12075. mov pc, lr
  12076. @@ -253,18 +256,17 @@
  12077. */
  12078. .align 5
  12079. ENTRY(cpu_arm920_dcache_invalidate_range)
  12080. -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
  12081. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12082. tst r0, #DCACHELINESIZE - 1
  12083. mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
  12084. tst r1, #DCACHELINESIZE - 1
  12085. mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
  12086. #endif @ clean D entry
  12087. bic r0, r0, #DCACHELINESIZE - 1
  12088. - bic r1, r1, #DCACHELINESIZE - 1
  12089. 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  12090. add r0, r0, #DCACHELINESIZE
  12091. cmp r0, r1
  12092. - blt 1b
  12093. + blo 1b
  12094. mov pc, lr
  12095. /*
  12096. @@ -279,20 +281,17 @@
  12097. */
  12098. .align 5
  12099. ENTRY(cpu_arm920_dcache_clean_range)
  12100. -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
  12101. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12102. bic r0, r0, #DCACHELINESIZE - 1
  12103. sub r1, r1, r0
  12104. cmp r1, #MAX_AREA_SIZE
  12105. mov r2, #0
  12106. - bgt cpu_arm920_cache_clean_invalidate_all_r2
  12107. -
  12108. - bic r1, r1, #DCACHELINESIZE -1
  12109. - add r1, r1, #DCACHELINESIZE
  12110. + bhi cpu_arm920_cache_clean_invalidate_all_r2
  12111. 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12112. add r0, r0, #DCACHELINESIZE
  12113. subs r1, r1, #DCACHELINESIZE
  12114. - bpl 1b
  12115. + bcs 1b
  12116. #endif
  12117. mcr p15, 0, r2, c7, c10, 4 @ drain WB
  12118. mov pc, lr
  12119. @@ -312,7 +311,7 @@
  12120. */
  12121. .align 5
  12122. ENTRY(cpu_arm920_dcache_clean_page)
  12123. -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
  12124. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12125. mov r1, #PAGESIZE
  12126. 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12127. add r0, r0, #DCACHELINESIZE
  12128. @@ -333,7 +332,7 @@
  12129. */
  12130. .align 5
  12131. ENTRY(cpu_arm920_dcache_clean_entry)
  12132. -#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
  12133. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12134. mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12135. #endif
  12136. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  12137. @@ -365,16 +364,13 @@
  12138. bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
  12139. sub r1, r1, r0
  12140. cmp r1, #MAX_AREA_SIZE
  12141. - bgt cpu_arm920_cache_clean_invalidate_all_r2
  12142. -
  12143. - bic r1, r1, #ICACHELINESIZE - 1
  12144. - add r1, r1, #ICACHELINESIZE
  12145. + bhi cpu_arm920_cache_clean_invalidate_all_r2
  12146. 1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry
  12147. mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
  12148. add r0, r0, #ICACHELINESIZE
  12149. subs r1, r1, #ICACHELINESIZE
  12150. - bne 1b
  12151. + bcs 1b
  12152. mov r0, #0
  12153. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  12154. @@ -418,13 +414,12 @@
  12155. mov r3, #PAGESIZE
  12156. sub r3, r3, #1
  12157. bic r0, r0, r3
  12158. - bic r1, r1, r3
  12159. 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  12160. mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  12161. add r0, r0, #PAGESIZE
  12162. cmp r0, r1
  12163. - blt 1b
  12164. + blo 1b
  12165. mov pc, lr
  12166. /*
  12167. @@ -457,7 +452,6 @@
  12168. ENTRY(cpu_arm920_set_pgd)
  12169. mov ip, #0
  12170. #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  12171. - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
  12172. mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
  12173. #else
  12174. @ && 'Clean & Invalidate whole DCache'
  12175. @@ -514,7 +508,7 @@
  12176. bic r2, r2, #3
  12177. orr r2, r2, #HPTE_TYPE_SMALL
  12178. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  12179. + tst r1, #LPTE_USER @ User?
  12180. orrne r2, r2, #HPTE_AP_READ
  12181. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  12182. diff -urN linux-2.4.26/arch/arm/mm/proc-arm922.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm922.S
  12183. --- linux-2.4.26/arch/arm/mm/proc-arm922.S 2003-08-25 12:44:39.000000000 +0100
  12184. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm922.S 2004-01-14 21:32:24.000000000 +0000
  12185. @@ -62,17 +62,20 @@
  12186. *
  12187. * Returns:
  12188. * r0 = address of abort
  12189. - * r1 != 0 if writing
  12190. - * r3 = FSR
  12191. + * r1 = FSR, bit 11 set if writing
  12192. + * r3 = corrupted
  12193. */
  12194. .align 5
  12195. ENTRY(cpu_arm922_data_abort)
  12196. - ldr r1, [r0] @ read aborted instruction
  12197. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  12198. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  12199. - tst r1, r1, lsr #21 @ C = bit 20
  12200. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  12201. - sbc r1, r1, r1 @ r1 = C - 1
  12202. - and r3, r3, #255
  12203. + tst r3, #PSR_T_BIT
  12204. + ldrneh r3, [r2] @ read aborted thumb instruction
  12205. + ldreq r3, [r2] @ read aborted ARM instruction
  12206. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  12207. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  12208. + tst r3, #1 << 20 @ check write
  12209. + orreq r1, r1, #1 << 11
  12210. mov pc, lr
  12211. /*
  12212. @@ -185,7 +188,7 @@
  12213. bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
  12214. sub r3, r1, r0
  12215. cmp r3, #MAX_AREA_SIZE
  12216. - bgt cpu_arm922_cache_clean_invalidate_all_r2
  12217. + bhi cpu_arm922_cache_clean_invalidate_all_r2
  12218. 1: teq r2, #0
  12219. #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
  12220. mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  12221. @@ -203,7 +206,7 @@
  12222. add r0, r0, #DCACHELINESIZE
  12223. #endif
  12224. cmp r0, r1
  12225. - blt 1b
  12226. + blo 1b
  12227. mcr p15, 0, r1, c7, c10, 4 @ drain WB
  12228. mov pc, lr
  12229. @@ -249,7 +252,7 @@
  12230. */
  12231. .align 5
  12232. ENTRY(cpu_arm922_dcache_invalidate_range)
  12233. -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
  12234. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12235. tst r0, #DCACHELINESIZE - 1
  12236. mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
  12237. tst r1, #DCACHELINESIZE - 1
  12238. @@ -260,7 +263,7 @@
  12239. 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  12240. add r0, r0, #DCACHELINESIZE
  12241. cmp r0, r1
  12242. - blt 1b
  12243. + blo 1b
  12244. mov pc, lr
  12245. /*
  12246. @@ -275,12 +278,12 @@
  12247. */
  12248. .align 5
  12249. ENTRY(cpu_arm922_dcache_clean_range)
  12250. -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
  12251. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12252. bic r0, r0, #DCACHELINESIZE - 1
  12253. sub r1, r1, r0
  12254. cmp r1, #MAX_AREA_SIZE
  12255. mov r2, #0
  12256. - bgt cpu_arm922_cache_clean_invalidate_all_r2
  12257. + bhi cpu_arm922_cache_clean_invalidate_all_r2
  12258. bic r1, r1, #DCACHELINESIZE -1
  12259. add r1, r1, #DCACHELINESIZE
  12260. @@ -308,7 +311,7 @@
  12261. */
  12262. .align 5
  12263. ENTRY(cpu_arm922_dcache_clean_page)
  12264. -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
  12265. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12266. mov r1, #PAGESIZE
  12267. 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12268. add r0, r0, #DCACHELINESIZE
  12269. @@ -329,7 +332,7 @@
  12270. */
  12271. .align 5
  12272. ENTRY(cpu_arm922_dcache_clean_entry)
  12273. -#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
  12274. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12275. mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12276. #endif
  12277. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  12278. @@ -361,7 +364,7 @@
  12279. bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
  12280. sub r1, r1, r0
  12281. cmp r1, #MAX_AREA_SIZE
  12282. - bgt cpu_arm922_cache_clean_invalidate_all_r2
  12283. + bhi cpu_arm922_cache_clean_invalidate_all_r2
  12284. bic r1, r1, #ICACHELINESIZE - 1
  12285. add r1, r1, #ICACHELINESIZE
  12286. @@ -420,7 +423,7 @@
  12287. mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  12288. add r0, r0, #PAGESIZE
  12289. cmp r0, r1
  12290. - blt 1b
  12291. + blo 1b
  12292. mov pc, lr
  12293. /*
  12294. @@ -510,7 +513,7 @@
  12295. bic r2, r2, #3
  12296. orr r2, r2, #HPTE_TYPE_SMALL
  12297. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  12298. + tst r1, #LPTE_USER @ User?
  12299. orrne r2, r2, #HPTE_AP_READ
  12300. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  12301. diff -urN linux-2.4.26/arch/arm/mm/proc-arm925.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm925.S
  12302. --- linux-2.4.26/arch/arm/mm/proc-arm925.S 2003-08-25 12:44:39.000000000 +0100
  12303. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm925.S 2004-01-14 21:32:24.000000000 +0000
  12304. @@ -69,24 +69,24 @@
  12305. *
  12306. * Returns:
  12307. * r0 = address of abort
  12308. - * r1 != 0 if writing
  12309. - * r3 = FSR
  12310. + * r1 = FSR, bit 11 set if writing
  12311. + * r3 = corrupted
  12312. * r4 = corrupted
  12313. */
  12314. .align 5
  12315. ENTRY(cpu_arm925_data_abort)
  12316. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  12317. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  12318. - mrc p15, 0, r4, c5, c0, 0 @ get FSR
  12319. -
  12320. - tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
  12321. - ldrneh r1, [r2] @ Read aborted Thumb instruction
  12322. - tstne r1, r1, lsr #12 @ C = bit 11
  12323. -
  12324. - ldreq r1, [r2] @ Read aborted ARM instruction
  12325. - tsteq r1, r1, lsr #21 @ C = bit 20
  12326. -
  12327. - sbc r1, r1, r1 @ r1 = C - 1
  12328. - and r3, r4, #255
  12329. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  12330. + tst r3, #PSR_J_BIT @ Java?
  12331. + orrne r1, r1, #1 << 11 @ always assume write
  12332. + movne pc, lr
  12333. + tst r3, #PSR_T_BIT @ Thumb?
  12334. + ldrneh r3, [r2] @ read aborted thumb instruction
  12335. + ldreq r3, [r2] @ read aborted ARM instruction
  12336. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  12337. + tst r3, #1 << 20 @ L = 0 -> write
  12338. + orreq r1, r1, #1 << 11 @ yes.
  12339. mov pc, lr
  12340. /*
  12341. @@ -207,7 +207,7 @@
  12342. bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
  12343. sub r3, r1, r0
  12344. cmp r3, #MAX_AREA_SIZE
  12345. - bgt cpu_arm925_cache_clean_invalidate_all_r2
  12346. + bhi cpu_arm925_cache_clean_invalidate_all_r2
  12347. 1: teq r2, #0
  12348. #ifdef CONFIG_CPU_ARM925_WRITETHROUGH
  12349. mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  12350. @@ -225,7 +225,7 @@
  12351. add r0, r0, #DCACHELINESIZE
  12352. #endif
  12353. cmp r0, r1
  12354. - blt 1b
  12355. + blo 1b
  12356. mcr p15, 0, r1, c7, c10, 4 @ drain WB
  12357. mov pc, lr
  12358. @@ -282,7 +282,7 @@
  12359. 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
  12360. add r0, r0, #DCACHELINESIZE
  12361. cmp r0, r1
  12362. - blt 1b
  12363. + blo 1b
  12364. mov pc, lr
  12365. /*
  12366. @@ -302,7 +302,7 @@
  12367. sub r1, r1, r0
  12368. cmp r1, #MAX_AREA_SIZE
  12369. mov r2, #0
  12370. - bgt cpu_arm925_cache_clean_invalidate_all_r2
  12371. + bhi cpu_arm925_cache_clean_invalidate_all_r2
  12372. bic r1, r1, #DCACHELINESIZE -1
  12373. add r1, r1, #DCACHELINESIZE
  12374. @@ -383,7 +383,7 @@
  12375. bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
  12376. sub r1, r1, r0
  12377. cmp r1, #MAX_AREA_SIZE
  12378. - bgt cpu_arm925_cache_clean_invalidate_all_r2
  12379. + bhi cpu_arm925_cache_clean_invalidate_all_r2
  12380. bic r1, r1, #ICACHELINESIZE - 1
  12381. add r1, r1, #ICACHELINESIZE
  12382. @@ -443,7 +443,7 @@
  12383. mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  12384. add r0, r0, #PAGESIZE
  12385. cmp r0, r1
  12386. - blt 1b
  12387. + blo 1b
  12388. mov pc, lr
  12389. /*
  12390. @@ -532,7 +532,7 @@
  12391. bic r2, r2, #3
  12392. orr r2, r2, #HPTE_TYPE_SMALL
  12393. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  12394. + tst r1, #LPTE_USER @ User?
  12395. orrne r2, r2, #HPTE_AP_READ
  12396. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  12397. diff -urN linux-2.4.26/arch/arm/mm/proc-arm926.S linux-2.4.26-vrs1/arch/arm/mm/proc-arm926.S
  12398. --- linux-2.4.26/arch/arm/mm/proc-arm926.S 2003-08-25 12:44:39.000000000 +0100
  12399. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-arm926.S 2004-01-14 21:38:43.000000000 +0000
  12400. @@ -66,28 +66,24 @@
  12401. *
  12402. * Returns:
  12403. * r0 = address of abort
  12404. - * r1 != 0 if writing
  12405. - * r3 = FSR
  12406. + * r1 = FSR, bit 11 set if writing
  12407. + * r3 = corrupted
  12408. * r4 = corrupted
  12409. */
  12410. .align 5
  12411. ENTRY(cpu_arm926_data_abort)
  12412. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  12413. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  12414. - mrc p15, 0, r4, c5, c0, 0 @ get FSR
  12415. -
  12416. - tst r3, #1<<24 @ Check for Jbit (NE -> found)
  12417. - movne r3, #-1 @ Mark as writing
  12418. - bne 2f
  12419. -
  12420. - tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
  12421. - ldrneh r1, [r2] @ Read aborted Thumb instruction
  12422. - ldreq r1, [r2] @ Read aborted ARM instruction
  12423. - movne r1, r1, lsl #(20-12) @ shift thumb bit 10 to ARM bit 20
  12424. - tsteq r1, r1, lsr #21 @ C = bit 20
  12425. -
  12426. - sbc r1, r1, r1 @ r1 = C - 1
  12427. -2:
  12428. - and r3, r4, #255
  12429. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  12430. + tst r3, #PSR_J_BIT @ Java?
  12431. + orrne r1, r1, #1 << 11 @ always assume write
  12432. + movne pc, lr
  12433. + tst r3, #PSR_T_BIT @ Thumb?
  12434. + ldrneh r3, [r2] @ read aborted thumb instruction
  12435. + ldreq r3, [r2] @ read aborted ARM instruction
  12436. + movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
  12437. + tst r3, #1 << 20 @ L = 0 -> write
  12438. + orreq r1, r1, #1 << 11 @ yes.
  12439. mov pc, lr
  12440. /*
  12441. @@ -263,7 +259,7 @@
  12442. */
  12443. .align 5
  12444. ENTRY(cpu_arm926_dcache_invalidate_range)
  12445. -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
  12446. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12447. tst r0, #DCACHELINESIZE - 1
  12448. mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
  12449. tst r1, #DCACHELINESIZE - 1
  12450. @@ -288,7 +284,7 @@
  12451. */
  12452. .align 5
  12453. ENTRY(cpu_arm926_dcache_clean_range)
  12454. -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
  12455. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12456. bic r0, r0, #DCACHELINESIZE - 1
  12457. sub r3, r1, r0
  12458. cmp r3, #MAX_AREA_SIZE
  12459. @@ -318,7 +314,7 @@
  12460. */
  12461. .align 5
  12462. ENTRY(cpu_arm926_dcache_clean_page)
  12463. -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
  12464. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12465. mov r1, #PAGESIZE
  12466. 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12467. add r0, r0, #DCACHELINESIZE
  12468. @@ -339,7 +335,7 @@
  12469. */
  12470. .align 5
  12471. ENTRY(cpu_arm926_dcache_clean_entry)
  12472. -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
  12473. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12474. mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12475. #endif
  12476. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  12477. @@ -482,7 +478,7 @@
  12478. biceq r1, r1, #4 @ clear bufferable bit
  12479. #endif
  12480. str r1, [r0]
  12481. -#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
  12482. +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
  12483. mcr p15, 0, r0, c7, c10, 1 @ clean D entry
  12484. #endif
  12485. mcr p15, 0, r0, c7, c10, 4 @ drain WB
  12486. @@ -503,7 +499,7 @@
  12487. bic r2, r2, #3
  12488. orr r2, r2, #HPTE_TYPE_SMALL
  12489. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  12490. + tst r1, #LPTE_USER @ User?
  12491. orrne r2, r2, #HPTE_AP_READ
  12492. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  12493. diff -urN linux-2.4.26/arch/arm/mm/proc-sa110.S linux-2.4.26-vrs1/arch/arm/mm/proc-sa110.S
  12494. --- linux-2.4.26/arch/arm/mm/proc-sa110.S 2003-08-25 12:44:39.000000000 +0100
  12495. +++ linux-2.4.26-vrs1/arch/arm/mm/proc-sa110.S 2004-01-14 21:32:24.000000000 +0000
  12496. @@ -86,12 +86,12 @@
  12497. .align 5
  12498. ENTRY(cpu_sa110_data_abort)
  12499. ENTRY(cpu_sa1100_data_abort)
  12500. - mrc p15, 0, r3, c5, c0, 0 @ get FSR
  12501. + mrc p15, 0, r1, c5, c0, 0 @ get FSR
  12502. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  12503. - ldr r1, [r2] @ read aborted instruction
  12504. - and r3, r3, #255
  12505. - tst r1, r1, lsr #21 @ C = bit 20
  12506. - sbc r1, r1, r1 @ r1 = C - 1
  12507. + ldr r3, [r2] @ read aborted instruction
  12508. + bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
  12509. + tst r3, #1 << 20 @ check write
  12510. + orreq r1, r1, #1 << 11
  12511. mov pc, lr
  12512. /*
  12513. @@ -551,7 +551,7 @@
  12514. bic r2, r2, #3
  12515. orr r2, r2, #HPTE_TYPE_SMALL
  12516. - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
  12517. + tst r1, #LPTE_USER @ User?
  12518. orrne r2, r2, #HPTE_AP_READ
  12519. tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
  12520. diff -urN linux-2.4.26/arch/arm/tools/mach-types linux-2.4.26-vrs1/arch/arm/tools/mach-types
  12521. --- linux-2.4.26/arch/arm/tools/mach-types 2003-08-25 12:44:39.000000000 +0100
  12522. +++ linux-2.4.26-vrs1/arch/arm/tools/mach-types 2004-04-19 21:11:38.000000000 +0100
  12523. @@ -6,7 +6,7 @@
  12524. # To add an entry into this database, please see Documentation/arm/README,
  12525. # or contact rmk@arm.linux.org.uk
  12526. #
  12527. -# Last update: Sat Jun 28 12:10:54 2003
  12528. +# Last update: Mon Apr 19 21:11:35 2004
  12529. #
  12530. # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
  12531. #
  12532. @@ -202,7 +202,7 @@
  12533. fester SA1100_FESTER FESTER 191
  12534. gpi ARCH_GPI GPI 192
  12535. smdk2410 ARCH_SMDK2410 SMDK2410 193
  12536. -premium ARCH_PREMIUM PREMIUM 194
  12537. +i519 ARCH_I519 I519 194
  12538. nexio SA1100_NEXIO NEXIO 195
  12539. bitbox SA1100_BITBOX BITBOX 196
  12540. g200 SA1100_G200 G200 197
  12541. @@ -228,7 +228,7 @@
  12542. arnold SA1100_ARNOLD ARNOLD 217
  12543. psiboard SA1100_PSIBOARD PSIBOARD 218
  12544. jz8028 ARCH_JZ8028 JZ8028 219
  12545. -h5400 ARCH_IPAQ3 IPAQ3 220
  12546. +h5400 ARCH_H5400 H5400 220
  12547. forte SA1100_FORTE FORTE 221
  12548. acam SA1100_ACAM ACAM 222
  12549. abox SA1100_ABOX ABOX 223
  12550. @@ -259,7 +259,7 @@
  12551. stork_egg ARCH_STORK_EGG STORK_EGG 248
  12552. wismo SA1100_WISMO WISMO 249
  12553. ezlinx ARCH_EZLINX EZLINX 250
  12554. -at91rm9200 ARCH_AT91 AT91 251
  12555. +at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
  12556. orion ARCH_ORION ORION 252
  12557. neptune ARCH_NEPTUNE NEPTUNE 253
  12558. hackkit SA1100_HACKKIT HACKKIT 254
  12559. @@ -295,12 +295,12 @@
  12560. adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
  12561. adsagc SA1100_ADSAGC ADSAGC 285
  12562. stp7312 ARCH_STP7312 STP7312 286
  12563. -nx_phnx ARCH_PXA255 PXA255 287
  12564. +nx_phnx MACH_NX_PHNX NX_PHNX 287
  12565. wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
  12566. inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
  12567. adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
  12568. iyonix ARCH_IYONIX IYONIX 291
  12569. -damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
  12570. +damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
  12571. meg03 ARCH_MEG03 MEG03 293
  12572. pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
  12573. nwsc ARCH_NWSC NWSC 295
  12574. @@ -356,3 +356,172 @@
  12575. seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
  12576. ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
  12577. h1940 ARCH_H1940 H1940 347
  12578. +scorpio ARCH_SCORPIO SCORPIO 348
  12579. +viva ARCH_VIVA VIVA 349
  12580. +pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
  12581. +csb335 ARCH_CSB335 CSB335 351
  12582. +ixrd425 ARCH_IXRD425 IXRD425 352
  12583. +iq80315 ARCH_IQ80315 IQ80315 353
  12584. +nmp7312 ARCH_NMP7312 NMP7312 354
  12585. +cx861xx ARCH_CX861XX CX861XX 355
  12586. +enp2611 ARCH_ENP2611 ENP2611 356
  12587. +xda SA1100_XDA XDA 357
  12588. +csir_ims ARCH_CSIR_IMS CSIR_IMS 358
  12589. +ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
  12590. +pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
  12591. +toto ARCH_TOTO TOTO 361
  12592. +s3c2440 ARCH_S3C2440 S3C2440 362
  12593. +ks8695p ARCH_KS8695P KS8695P 363
  12594. +se4000 ARCH_SE4000 SE4000 364
  12595. +quadriceps ARCH_QUADRICEPS QUADRICEPS 365
  12596. +bronco ARCH_BRONCO BRONCO 366
  12597. +esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367
  12598. +esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
  12599. +s5c7375 ARCH_S5C7375 S5C7375 369
  12600. +spearhead ARCH_SPEARHEAD SPEARHEAD 370
  12601. +pantera ARCH_PANTERA PANTERA 371
  12602. +prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
  12603. +gumstik ARCH_GUMSTIK GUMSTIK 373
  12604. +rcube ARCH_RCUBE RCUBE 374
  12605. +rea_olv ARCH_REA_OLV REA_OLV 375
  12606. +pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
  12607. +s3c3410 ARCH_S3C3410 S3C3410 377
  12608. +espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
  12609. +mp1x ARCH_MP1X MP1X 379
  12610. +at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
  12611. +adsvgx ARCH_ADSVGX ADSVGX 381
  12612. +omap_h2 ARCH_OMAP_H2 OMAP_H2 382
  12613. +pelee ARCH_PELEE PELEE 383
  12614. +e740 MACH_E740 E740 384
  12615. +iq80331 ARCH_IQ80331 IQ80331 385
  12616. +versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
  12617. +kev7a400 MACH_KEV7A400 KEV7A400 388
  12618. +lpd7a400 MACH_LPD7A400 LPD7A400 389
  12619. +lpd7a404 MACH_LPD7A404 LPD7A404 390
  12620. +fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
  12621. +janus2m ARCH_JANUS2M JANUS2M 392
  12622. +embtf MACH_EMBTF EMBTF 393
  12623. +hpm MACH_HPM HPM 394
  12624. +smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
  12625. +smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
  12626. +streetracer MACH_STREETRACER STREETRACER 397
  12627. +eframe MACH_EFRAME EFRAME 398
  12628. +csb337 MACH_CSB337 CSB337 399
  12629. +pxa_lark MACH_PXA_LARK PXA_LARK 400
  12630. +pxa_pnp2110 MACH_PNP2110 PNP2110 401
  12631. +tcc72x MACH_TCC72X TCC72X 402
  12632. +altair MACH_ALTAIR ALTAIR 403
  12633. +kc3 MACH_KC3 KC3 404
  12634. +sinteftd MACH_SINTEFTD SINTEFTD 405
  12635. +mainstone MACH_MAINSTONE MAINSTONE 406
  12636. +aday4x MACH_ADAY4X ADAY4X 407
  12637. +lite300 MACH_LITE300 LITE300 408
  12638. +s5c7376 MACH_S5C7376 S5C7376 409
  12639. +mt02 MACH_MT02 MT02 410
  12640. +mport3s MACH_MPORT3S MPORT3S 411
  12641. +ra_alpha MACH_RA_ALPHA RA_ALPHA 412
  12642. +xcep MACH_XCEP XCEP 413
  12643. +arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414
  12644. +stargate MACH_STARGATE STARGATE 415
  12645. +armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
  12646. +elroy_jack MACH_ELROY_JACK ELROY_JACK 417
  12647. +backend MACH_BACKEND BACKEND 418
  12648. +s5linbox MACH_S5LINBOX S5LINBOX 419
  12649. +nomadik MACH_NOMADIK NOMADIK 420
  12650. +ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
  12651. +at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
  12652. +corgi MACH_CORGI CORGI 423
  12653. +poodle MACH_POODLE POODLE 424
  12654. +ten MACH_TEN TEN 425
  12655. +roverp5p MACH_ROVERP5P ROVERP5P 426
  12656. +sc2700 MACH_SC2700 SC2700 427
  12657. +ex_eagle MACH_EX_EAGLE EX_EAGLE 428
  12658. +nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
  12659. +nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
  12660. +blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
  12661. +i819 MACH_I819 I819 432
  12662. +ixmb995e MACH_IXMB995E IXMB995E 433
  12663. +skyrider MACH_SKYRIDER SKYRIDER 434
  12664. +skyhawk MACH_SKYHAWK SKYHAWK 435
  12665. +enterprise MACH_ENTERPRISE ENTERPRISE 436
  12666. +dep2410 MACH_DEP2410 DEP2410 437
  12667. +armcore MACH_ARMCORE ARMCORE 438
  12668. +hobbit MACH_HOBBIT HOBBIT 439
  12669. +h7210 MACH_H7210 H7210 440
  12670. +pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
  12671. +acc MACH_ACC ACC 442
  12672. +esl_sarva MACH_ESL_SARVA ESL_SARVA 443
  12673. +xm250 MACH_XM250 XM250 444
  12674. +t6tc1xb MACH_T6TC1XB T6TC1XB 445
  12675. +ess710 MACH_ESS710 ESS710 446
  12676. +mx3ads MACH_MX3ADS MX3ADS 447
  12677. +himalaya MACH_HIMALAYA HIMALAYA 448
  12678. +bolfenk MACH_BOLFENK BOLFENK 449
  12679. +at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
  12680. +edb9312 MACH_EDB9312 EDB9312 451
  12681. +omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
  12682. +aximx3 MACH_AXIMX3 AXIMX3 453
  12683. +eb67xdip MACH_EB67XDIP EB67XDIP 454
  12684. +webtxs MACH_WEBTXS WEBTXS 455
  12685. +hawk MACH_HAWK HAWK 456
  12686. +ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457
  12687. +expresso MACH_EXPRESSO EXPRESSO 458
  12688. +h4000 MACH_H4000 H4000 459
  12689. +dino MACH_DINO DINO 460
  12690. +ml675k MACH_ML675K ML675K 461
  12691. +edb9301 MACH_EDB9301 EDB9301 462
  12692. +edb9315 MACH_EDB9315 EDB9315 463
  12693. +reciva_tt MACH_RECIVA_TT RECIVA_TT 464
  12694. +cstcb01 MACH_CSTCB01 CSTCB01 465
  12695. +cstcb1 MACH_CSTCB1 CSTCB1 466
  12696. +shadwell MACH_SHADWELL SHADWELL 467
  12697. +goepel263 MACH_GOEPEL263 GOEPEL263 468
  12698. +acq100 MACH_ACQ100 ACQ100 469
  12699. +mx1fs2 MACH_MX1FS2 MX1FS2 470
  12700. +hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471
  12701. +sparky MACH_SPARKY SPARKY 472
  12702. +ns9750 MACH_NS9750 NS9750 473
  12703. +phoenix MACH_PHOENIX PHOENIX 474
  12704. +vr1000 MACH_VR1000 VR1000 475
  12705. +deisterpxa MACH_DEISTERPXA DEISTERPXA 476
  12706. +bcm1160 MACH_BCM1160 BCM1160 477
  12707. +pcm022 MACH_PCM022 PCM022 478
  12708. +adsgcx MACH_ADSGCX ADSGCX 479
  12709. +dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480
  12710. +dm320 MACH_DM320 DM320 481
  12711. +markov MACH_MARKOV MARKOV 482
  12712. +cos7a400 MACH_COS7A400 COS7A400 483
  12713. +milano MACH_MILANO MILANO 484
  12714. +ue9328 MACH_UE9328 UE9328 485
  12715. +uex255 MACH_UEX255 UEX255 486
  12716. +ue2410 MACH_UE2410 UE2410 487
  12717. +a620 MACH_A620 A620 488
  12718. +ocelot MACH_OCELOT OCELOT 489
  12719. +cheetah MACH_CHEETAH CHEETAH 490
  12720. +omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491
  12721. +zvue MACH_ZVUE ZVUE 492
  12722. +roverp1 MACH_ROVERP1 ROVERP1 493
  12723. +asidial2 MACH_ASIDIAL2 ASIDIAL2 494
  12724. +s3c24a0 MACH_S3C24A0 S3C24A0 495
  12725. +e800 MACH_E800 E800 496
  12726. +e750 MACH_E750 E750 497
  12727. +s3c5500 MACH_S3C5500 S3C5500 498
  12728. +smdk5500 MACH_SMDK5500 SMDK5500 499
  12729. +signalsync MACH_SIGNALSYNC SIGNALSYNC 500
  12730. +nbc MACH_NBC NBC 501
  12731. +er4525 MACH_ER4525 ER4525 502
  12732. +netbookpro MACH_NETBOOKPRO NETBOOKPRO 503
  12733. +hw90200 MACH_HW90200 HW90200 504
  12734. +condor MACH_CONDOR CONDOR 505
  12735. +cup MACH_CUP CUP 506
  12736. +kite MACH_KITE KITE 507
  12737. +scb9328 MACH_SCB9328 SCB9328 508
  12738. +omap_h3 MACH_OMAP_H3 OMAP_H3 509
  12739. +omap_h4 MACH_OMAP_H4 OMAP_H4 510
  12740. +n10 MACH_N10 N10 511
  12741. +montajade MACH_MONTAJADE MONTAJADE 512
  12742. +sg560 MACH_SG560 SG560 513
  12743. +dp1000 MACH_DP1000 DP1000 514
  12744. +omap_osk MACH_OMAP_OSK OMAP_OSK 515
  12745. +rg100v3 MACH_RG100V3 RG100V3 516
  12746. +mx2ads MACH_MX2ADS MX2ADS 517
  12747. diff -urN linux-2.4.26/arch/i386/config.in linux-2.4.26-vrs1/arch/i386/config.in
  12748. --- linux-2.4.26/arch/i386/config.in 2004-02-27 20:03:23.000000000 +0000
  12749. +++ linux-2.4.26-vrs1/arch/i386/config.in 2004-02-23 13:36:21.000000000 +0000
  12750. @@ -9,6 +9,7 @@
  12751. define_bool CONFIG_UID16 y
  12752. +define_bool CONFIG_GENERIC_ISA_DMA y
  12753. mainmenu_option next_comment
  12754. comment 'Code maturity level options'
  12755. bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
  12756. diff -urN linux-2.4.26/arch/i386/kernel/Makefile linux-2.4.26-vrs1/arch/i386/kernel/Makefile
  12757. --- linux-2.4.26/arch/i386/kernel/Makefile 2003-11-28 18:26:19.000000000 +0000
  12758. +++ linux-2.4.26-vrs1/arch/i386/kernel/Makefile 2004-01-14 21:38:44.000000000 +0000
  12759. @@ -7,8 +7,8 @@
  12760. #
  12761. # Note 2! The CFLAGS definitions are now in the main makefile...
  12762. -.S.o:
  12763. - $(CC) $(AFLAGS) -traditional -c $< -o $*.o
  12764. +USE_STANDARD_AS_RULE := true
  12765. +EXTRA_AFLAGS := -traditional
  12766. all: kernel.o head.o init_task.o
  12767. diff -urN linux-2.4.26/arch/i386/kernel/apm.c linux-2.4.26-vrs1/arch/i386/kernel/apm.c
  12768. --- linux-2.4.26/arch/i386/kernel/apm.c 2003-08-25 12:44:39.000000000 +0100
  12769. +++ linux-2.4.26-vrs1/arch/i386/kernel/apm.c 2004-01-14 21:38:44.000000000 +0000
  12770. @@ -1267,6 +1267,7 @@
  12771. as->suspend_wait = 0;
  12772. as->suspend_result = err;
  12773. }
  12774. + ignore_normal_resume = 1;
  12775. wake_up_interruptible(&apm_suspend_waitqueue);
  12776. return err;
  12777. }
  12778. @@ -1319,6 +1320,8 @@
  12779. if (ignore_bounce
  12780. && ((jiffies - last_resume) > bounce_interval))
  12781. ignore_bounce = 0;
  12782. + if (ignore_normal_resume && (event != APM_NORMAL_RESUME))
  12783. + ignore_normal_resume = 0;
  12784. switch (event) {
  12785. case APM_SYS_STANDBY:
  12786. diff -urN linux-2.4.26/arch/i386/lib/Makefile linux-2.4.26-vrs1/arch/i386/lib/Makefile
  12787. --- linux-2.4.26/arch/i386/lib/Makefile 2001-09-10 15:31:30.000000000 +0100
  12788. +++ linux-2.4.26-vrs1/arch/i386/lib/Makefile 2004-01-14 21:32:24.000000000 +0000
  12789. @@ -2,8 +2,7 @@
  12790. # Makefile for i386-specific library files..
  12791. #
  12792. -.S.o:
  12793. - $(CC) $(AFLAGS) -c $< -o $*.o
  12794. +USE_STANDARD_AS_RULE := true
  12795. L_TARGET = lib.a
  12796. diff -urN linux-2.4.26/arch/i386/math-emu/Makefile linux-2.4.26-vrs1/arch/i386/math-emu/Makefile
  12797. --- linux-2.4.26/arch/i386/math-emu/Makefile 2000-12-29 22:07:20.000000000 +0000
  12798. +++ linux-2.4.26-vrs1/arch/i386/math-emu/Makefile 2004-01-14 21:32:24.000000000 +0000
  12799. @@ -2,15 +2,15 @@
  12800. # Makefile for wm-FPU-emu
  12801. #
  12802. +USE_STANDARD_AS_RULE := true
  12803. +
  12804. O_TARGET := math.o
  12805. #DEBUG = -DDEBUGGING
  12806. DEBUG =
  12807. PARANOID = -DPARANOID
  12808. CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION)
  12809. -
  12810. -.S.o:
  12811. - $(CC) $(AFLAGS) $(PARANOID) -c $<
  12812. +EXTRA_AFLAGS := $(PARANOID)
  12813. # From 'C' language sources:
  12814. C_OBJS =fpu_entry.o errors.o \
  12815. diff -urN linux-2.4.26/arch/ia64/config.in linux-2.4.26-vrs1/arch/ia64/config.in
  12816. --- linux-2.4.26/arch/ia64/config.in 2004-02-27 20:03:23.000000000 +0000
  12817. +++ linux-2.4.26-vrs1/arch/ia64/config.in 2004-02-23 13:36:21.000000000 +0000
  12818. @@ -25,6 +25,7 @@
  12819. define_bool CONFIG_SBUS n
  12820. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
  12821. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
  12822. +define_bool CONFIG_GENERIC_ISA_DMA y
  12823. choice 'IA-64 processor type' \
  12824. "Itanium CONFIG_ITANIUM \
  12825. diff -urN linux-2.4.26/arch/m68k/config.in linux-2.4.26-vrs1/arch/m68k/config.in
  12826. --- linux-2.4.26/arch/m68k/config.in 2004-02-27 20:03:23.000000000 +0000
  12827. +++ linux-2.4.26-vrs1/arch/m68k/config.in 2004-02-23 13:36:22.000000000 +0000
  12828. @@ -6,6 +6,7 @@
  12829. define_bool CONFIG_UID16 y
  12830. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
  12831. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
  12832. +define_bool CONFIG_GENERIC_ISA_DMA y
  12833. mainmenu_name "Linux/68k Kernel Configuration"
  12834. diff -urN linux-2.4.26/arch/mips/config.in linux-2.4.26-vrs1/arch/mips/config.in
  12835. --- linux-2.4.26/arch/mips/config.in 2002-11-28 23:53:09.000000000 +0000
  12836. +++ linux-2.4.26-vrs1/arch/mips/config.in 2004-01-14 21:32:24.000000000 +0000
  12837. @@ -5,5 +5,6 @@
  12838. define_bool CONFIG_MIPS y
  12839. define_bool CONFIG_MIPS32 y
  12840. define_bool CONFIG_MIPS64 n
  12841. +define_bool CONFIG_GENERIC_ISA_DMA y
  12842. source arch/mips/config-shared.in
  12843. diff -urN linux-2.4.26/arch/parisc/config.in linux-2.4.26-vrs1/arch/parisc/config.in
  12844. --- linux-2.4.26/arch/parisc/config.in 2004-02-27 20:03:24.000000000 +0000
  12845. +++ linux-2.4.26-vrs1/arch/parisc/config.in 2004-02-23 13:36:26.000000000 +0000
  12846. @@ -9,6 +9,7 @@
  12847. define_bool CONFIG_UID16 n
  12848. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
  12849. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
  12850. +define_bool CONFIG_GENERIC_ISA_DMA y
  12851. mainmenu_option next_comment
  12852. comment 'Code maturity level options'
  12853. diff -urN linux-2.4.26/arch/ppc/config.in linux-2.4.26-vrs1/arch/ppc/config.in
  12854. --- linux-2.4.26/arch/ppc/config.in 2004-04-19 11:44:15.000000000 +0100
  12855. +++ linux-2.4.26-vrs1/arch/ppc/config.in 2004-04-18 21:47:50.000000000 +0100
  12856. @@ -6,6 +6,7 @@
  12857. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
  12858. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
  12859. define_bool CONFIG_HAVE_DEC_LOCK y
  12860. +define_bool CONFIG_GENERIC_ISA_DMA y
  12861. mainmenu_name "Linux/PowerPC Kernel Configuration"
  12862. diff -urN linux-2.4.26/arch/sh/config.in linux-2.4.26-vrs1/arch/sh/config.in
  12863. --- linux-2.4.26/arch/sh/config.in 2004-02-27 20:03:25.000000000 +0000
  12864. +++ linux-2.4.26-vrs1/arch/sh/config.in 2004-02-23 13:36:27.000000000 +0000
  12865. @@ -9,6 +9,7 @@
  12866. define_bool CONFIG_UID16 y
  12867. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
  12868. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
  12869. +define_bool CONFIG_GENERIC_ISA_DMA y
  12870. mainmenu_option next_comment
  12871. comment 'Code maturity level options'
  12872. diff -urN linux-2.4.26/arch/sparc/config.in linux-2.4.26-vrs1/arch/sparc/config.in
  12873. --- linux-2.4.26/arch/sparc/config.in 2004-02-27 20:03:25.000000000 +0000
  12874. +++ linux-2.4.26-vrs1/arch/sparc/config.in 2004-02-23 13:36:27.000000000 +0000
  12875. @@ -6,6 +6,7 @@
  12876. define_bool CONFIG_UID16 y
  12877. define_bool CONFIG_HIGHMEM y
  12878. +define_bool CONFIG_GENERIC_ISA_DMA y
  12879. mainmenu_option next_comment
  12880. comment 'Code maturity level options'
  12881. diff -urN linux-2.4.26/arch/sparc64/config.in linux-2.4.26-vrs1/arch/sparc64/config.in
  12882. --- linux-2.4.26/arch/sparc64/config.in 2004-02-27 20:03:25.000000000 +0000
  12883. +++ linux-2.4.26-vrs1/arch/sparc64/config.in 2004-02-23 13:36:27.000000000 +0000
  12884. @@ -41,6 +41,7 @@
  12885. define_bool CONFIG_HAVE_DEC_LOCK y
  12886. define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
  12887. define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
  12888. +define_bool CONFIG_GENERIC_ISA_DMA y
  12889. define_bool CONFIG_ISA n
  12890. define_bool CONFIG_ISAPNP n
  12891. define_bool CONFIG_EISA n
  12892. diff -urN linux-2.4.26/drivers/Makefile linux-2.4.26-vrs1/drivers/Makefile
  12893. --- linux-2.4.26/drivers/Makefile 2003-11-28 18:26:19.000000000 +0000
  12894. +++ linux-2.4.26-vrs1/drivers/Makefile 2004-02-04 04:11:33.000000000 +0000
  12895. @@ -8,9 +8,9 @@
  12896. mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide \
  12897. message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
  12898. - fc4 net/hamradio i2c acpi bluetooth usb/gadget
  12899. + fc4 net/hamradio i2c l3 acpi bluetooth serial usb/gadget
  12900. -subdir-y := parport char block net sound misc media cdrom hotplug
  12901. +subdir-y := parport serial char block net sound misc media cdrom hotplug pld
  12902. subdir-m := $(subdir-y)
  12903. @@ -45,8 +45,12 @@
  12904. # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch
  12905. subdir-$(CONFIG_HAMRADIO) += net/hamradio
  12906. subdir-$(CONFIG_I2C) += i2c
  12907. +subdir-$(CONFIG_L3) += l3
  12908. subdir-$(CONFIG_ACPI_BOOT) += acpi
  12909. subdir-$(CONFIG_BLUEZ) += bluetooth
  12910. +subdir-$(CONFIG_SSI) += ssi
  12911. +
  12912. +subdir-$(CONFIG_ARCH_AT91RM9200)+= at91
  12913. include $(TOPDIR)/Rules.make
  12914. diff -urN linux-2.4.26/drivers/acorn/char/i2c.c linux-2.4.26-vrs1/drivers/acorn/char/i2c.c
  12915. --- linux-2.4.26/drivers/acorn/char/i2c.c 2004-01-05 13:53:56.000000000 +0000
  12916. +++ linux-2.4.26-vrs1/drivers/acorn/char/i2c.c 2004-04-10 11:43:00.000000000 +0100
  12917. @@ -33,9 +33,13 @@
  12918. static struct i2c_client *rtc_client;
  12919. static const unsigned char days_in_mon[] =
  12920. { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  12921. -static unsigned int rtc_epoch = 1900;
  12922. #define CMOS_CHECKSUM (63)
  12923. +
  12924. +/*
  12925. + * Acorn machines store the year in the static RAM at
  12926. + * location 128.
  12927. + */
  12928. #define CMOS_YEAR (64 + 128)
  12929. static inline int rtc_command(int cmd, void *data)
  12930. @@ -49,51 +53,91 @@
  12931. }
  12932. /*
  12933. + * Update the century + year bytes in the CMOS RAM, ensuring
  12934. + * that the check byte is correctly adjusted for the change.
  12935. + */
  12936. +static int rtc_update_year(unsigned int new_year)
  12937. +{
  12938. + unsigned char yr[2], chk;
  12939. + struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr };
  12940. + struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
  12941. + int ret;
  12942. +
  12943. + ret = rtc_command(MEM_READ, &cmos_check);
  12944. + if (ret)
  12945. + goto out;
  12946. + ret = rtc_command(MEM_READ, &cmos_year);
  12947. + if (ret)
  12948. + goto out;
  12949. +
  12950. + chk -= yr[1] + yr[0];
  12951. +
  12952. + yr[1] = new_year / 100;
  12953. + yr[0] = new_year % 100;
  12954. +
  12955. + chk += yr[1] + yr[0];
  12956. +
  12957. + ret = rtc_command(MEM_WRITE, &cmos_year);
  12958. + if (ret == 0)
  12959. + ret = rtc_command(MEM_WRITE, &cmos_check);
  12960. + out:
  12961. + return ret;
  12962. +}
  12963. +
  12964. +
  12965. +/*
  12966. * Read the current RTC time and date, and update xtime.
  12967. */
  12968. static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year)
  12969. {
  12970. unsigned char ctrl, yr[2];
  12971. struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr };
  12972. + int real_year, year_offset;
  12973. /*
  12974. * Ensure that the RTC is running.
  12975. */
  12976. rtc_command(RTC_GETCTRL, &ctrl);
  12977. if (ctrl & 0xc0) {
  12978. - unsigned char new_ctrl;
  12979. -
  12980. - new_ctrl = ctrl & ~0xc0;
  12981. + unsigned char new_ctrl = ctrl & ~0xc0;
  12982. - printk("RTC: resetting control %02X -> %02X\n",
  12983. - ctrl, new_ctrl);
  12984. + printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
  12985. + ctrl, new_ctrl);
  12986. rtc_command(RTC_SETCTRL, &new_ctrl);
  12987. }
  12988. + if (rtc_command(RTC_GETDATETIME, rtctm) ||
  12989. + rtc_command(MEM_READ, &rtcmem))
  12990. + return;
  12991. +
  12992. + real_year = yr[0];
  12993. +
  12994. /*
  12995. - * Acorn machines store the year in
  12996. - * the static RAM at location 192.
  12997. + * The RTC year holds the LSB two bits of the current
  12998. + * year, which should reflect the LSB two bits of the
  12999. + * CMOS copy of the year. Any difference indicates
  13000. + * that we have to correct the CMOS version.
  13001. */
  13002. - if (rtc_command(MEM_READ, &rtcmem))
  13003. - return;
  13004. + year_offset = rtctm->year_off - (real_year & 3);
  13005. + if (year_offset < 0)
  13006. + /*
  13007. + * RTC year wrapped. Adjust it appropriately.
  13008. + */
  13009. + year_offset += 4;
  13010. - if (rtc_command(RTC_GETDATETIME, rtctm))
  13011. - return;
  13012. + *year = real_year + year_offset + yr[1] * 100;
  13013. - *year = yr[1] * 100 + yr[0];
  13014. }
  13015. static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year)
  13016. {
  13017. - unsigned char yr[2], leap, chk;
  13018. - struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr };
  13019. - struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
  13020. + unsigned char leap;
  13021. int ret;
  13022. leap = (!(year % 4) && (year % 100)) || !(year % 400);
  13023. - if (rtctm->mon > 12 || rtctm->mday == 0)
  13024. + if (rtctm->mon > 12 || rtctm->mon == 0 || rtctm->mday == 0)
  13025. return -EINVAL;
  13026. if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap)))
  13027. @@ -102,21 +146,16 @@
  13028. if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60)
  13029. return -EINVAL;
  13030. - ret = rtc_command(RTC_SETDATETIME, rtctm);
  13031. - if (ret == 0) {
  13032. - rtc_command(MEM_READ, &cmos_check);
  13033. - rtc_command(MEM_READ, &cmos_year);
  13034. -
  13035. - chk -= yr[1] + yr[0];
  13036. -
  13037. - yr[1] = year / 100;
  13038. - yr[0] = year % 100;
  13039. + /*
  13040. + * The RTC's own 2-bit year must reflect the least
  13041. + * significant two bits of the CMOS year.
  13042. + */
  13043. + rtctm->year_off = (year % 100) & 3;
  13044. - chk += yr[1] + yr[0];
  13045. + ret = rtc_command(RTC_SETDATETIME, rtctm);
  13046. + if (ret == 0)
  13047. + ret = rtc_update_year(year);
  13048. - rtc_command(MEM_WRITE, &cmos_year);
  13049. - rtc_command(MEM_WRITE, &cmos_check);
  13050. - }
  13051. return ret;
  13052. }
  13053. @@ -166,7 +205,6 @@
  13054. break;
  13055. case RTC_RD_TIME:
  13056. - memset(&rtctm, 0, sizeof(struct rtc_time));
  13057. get_rtc_time(&rtc_raw, &year);
  13058. rtctm.tm_sec = rtc_raw.secs;
  13059. rtctm.tm_min = rtc_raw.mins;
  13060. @@ -188,13 +226,12 @@
  13061. rtc_raw.hours = rtctm.tm_hour;
  13062. rtc_raw.mday = rtctm.tm_mday;
  13063. rtc_raw.mon = rtctm.tm_mon + 1;
  13064. - rtc_raw.year_off = 2;
  13065. year = rtctm.tm_year + 1900;
  13066. return set_rtc_time(&rtc_raw, year);
  13067. break;
  13068. case RTC_EPOCH_READ:
  13069. - return put_user(rtc_epoch, (unsigned long *)arg);
  13070. + return put_user(1900, (unsigned long *)arg);
  13071. }
  13072. return -EINVAL;
  13073. diff -urN linux-2.4.26/drivers/acorn/net/ether1.c linux-2.4.26-vrs1/drivers/acorn/net/ether1.c
  13074. --- linux-2.4.26/drivers/acorn/net/ether1.c 2003-08-25 12:44:40.000000000 +0100
  13075. +++ linux-2.4.26-vrs1/drivers/acorn/net/ether1.c 2004-04-09 19:55:21.000000000 +0100
  13076. @@ -80,7 +80,7 @@
  13077. #define BUS_16 16
  13078. #define BUS_8 8
  13079. -static const card_ids __init ether1_cids[] = {
  13080. +static card_ids __initdata ether1_cids[] = {
  13081. { MANU_ACORN, PROD_ACORN_ETHER1 },
  13082. { 0xffff, 0xffff }
  13083. };
  13084. @@ -153,35 +153,35 @@
  13085. length -= thislen;
  13086. __asm__ __volatile__(
  13087. - "subs %3, %3, #2
  13088. - bmi 2f
  13089. -1: ldr %0, [%1], #2
  13090. - mov %0, %0, lsl #16
  13091. - orr %0, %0, %0, lsr #16
  13092. - str %0, [%2], #4
  13093. - subs %3, %3, #2
  13094. - bmi 2f
  13095. - ldr %0, [%1], #2
  13096. - mov %0, %0, lsl #16
  13097. - orr %0, %0, %0, lsr #16
  13098. - str %0, [%2], #4
  13099. - subs %3, %3, #2
  13100. - bmi 2f
  13101. - ldr %0, [%1], #2
  13102. - mov %0, %0, lsl #16
  13103. - orr %0, %0, %0, lsr #16
  13104. - str %0, [%2], #4
  13105. - subs %3, %3, #2
  13106. - bmi 2f
  13107. - ldr %0, [%1], #2
  13108. - mov %0, %0, lsl #16
  13109. - orr %0, %0, %0, lsr #16
  13110. - str %0, [%2], #4
  13111. - subs %3, %3, #2
  13112. - bpl 1b
  13113. -2: adds %3, %3, #1
  13114. - ldreqb %0, [%1]
  13115. - streqb %0, [%2]"
  13116. +" subs %3, %3, #2 \n"
  13117. +" bmi 2f \n"
  13118. +"1: ldr %0, [%1], #2 \n"
  13119. +" mov %0, %0, lsl #16 \n"
  13120. +" orr %0, %0, %0, lsr #16 \n"
  13121. +" str %0, [%2], #4 \n"
  13122. +" subs %3, %3, #2 \n"
  13123. +" bmi 2f \n"
  13124. +" ldr %0, [%1], #2 \n"
  13125. +" mov %0, %0, lsl #16 \n"
  13126. +" orr %0, %0, %0, lsr #16 \n"
  13127. +" str %0, [%2], #4 \n"
  13128. +" subs %3, %3, #2 \n"
  13129. +" bmi 2f \n"
  13130. +" ldr %0, [%1], #2 \n"
  13131. +" mov %0, %0, lsl #16 \n"
  13132. +" orr %0, %0, %0, lsr #16 \n"
  13133. +" str %0, [%2], #4 \n"
  13134. +" subs %3, %3, #2 \n"
  13135. +" bmi 2f \n"
  13136. +" ldr %0, [%1], #2 \n"
  13137. +" mov %0, %0, lsl #16 \n"
  13138. +" orr %0, %0, %0, lsr #16 \n"
  13139. +" str %0, [%2], #4 \n"
  13140. +" subs %3, %3, #2 \n"
  13141. +" bpl 1b \n"
  13142. +"2: adds %3, %3, #1 \n"
  13143. +" ldreqb %0, [%1] \n"
  13144. +" streqb %0, [%2] \n"
  13145. : "=&r" (used), "=&r" (data)
  13146. : "r" (addr), "r" (thislen), "1" (data));
  13147. @@ -215,35 +215,35 @@
  13148. length -= thislen;
  13149. __asm__ __volatile__(
  13150. - "subs %3, %3, #2
  13151. - bmi 2f
  13152. -1: ldr %0, [%2], #4
  13153. - strb %0, [%1], #1
  13154. - mov %0, %0, lsr #8
  13155. - strb %0, [%1], #1
  13156. - subs %3, %3, #2
  13157. - bmi 2f
  13158. - ldr %0, [%2], #4
  13159. - strb %0, [%1], #1
  13160. - mov %0, %0, lsr #8
  13161. - strb %0, [%1], #1
  13162. - subs %3, %3, #2
  13163. - bmi 2f
  13164. - ldr %0, [%2], #4
  13165. - strb %0, [%1], #1
  13166. - mov %0, %0, lsr #8
  13167. - strb %0, [%1], #1
  13168. - subs %3, %3, #2
  13169. - bmi 2f
  13170. - ldr %0, [%2], #4
  13171. - strb %0, [%1], #1
  13172. - mov %0, %0, lsr #8
  13173. - strb %0, [%1], #1
  13174. - subs %3, %3, #2
  13175. - bpl 1b
  13176. -2: adds %3, %3, #1
  13177. - ldreqb %0, [%2]
  13178. - streqb %0, [%1]"
  13179. +" subs %3, %3, #2 \n"
  13180. +" bmi 2f \n"
  13181. +"1: ldr %0, [%2], #4 \n"
  13182. +" strb %0, [%1], #1 \n"
  13183. +" mov %0, %0, lsr #8 \n"
  13184. +" strb %0, [%1], #1 \n"
  13185. +" subs %3, %3, #2 \n"
  13186. +" bmi 2f \n"
  13187. +" ldr %0, [%2], #4 \n"
  13188. +" strb %0, [%1], #1 \n"
  13189. +" mov %0, %0, lsr #8 \n"
  13190. +" strb %0, [%1], #1 \n"
  13191. +" subs %3, %3, #2 \n"
  13192. +" bmi 2f \n"
  13193. +" ldr %0, [%2], #4 \n"
  13194. +" strb %0, [%1], #1 \n"
  13195. +" mov %0, %0, lsr #8 \n"
  13196. +" strb %0, [%1], #1 \n"
  13197. +" subs %3, %3, #2 \n"
  13198. +" bmi 2f \n"
  13199. +" ldr %0, [%2], #4 \n"
  13200. +" strb %0, [%1], #1 \n"
  13201. +" mov %0, %0, lsr #8 \n"
  13202. +" strb %0, [%1], #1 \n"
  13203. +" subs %3, %3, #2 \n"
  13204. +" bpl 1b \n"
  13205. +"2: adds %3, %3, #1 \n"
  13206. +" ldreqb %0, [%2] \n"
  13207. +" streqb %0, [%1] \n"
  13208. : "=&r" (used), "=&r" (data)
  13209. : "r" (addr), "r" (thislen), "1" (data));
  13210. diff -urN linux-2.4.26/drivers/acorn/net/ether3.c linux-2.4.26-vrs1/drivers/acorn/net/ether3.c
  13211. --- linux-2.4.26/drivers/acorn/net/ether3.c 2003-08-25 12:44:40.000000000 +0100
  13212. +++ linux-2.4.26-vrs1/drivers/acorn/net/ether3.c 2004-01-14 21:32:24.000000000 +0000
  13213. @@ -75,7 +75,7 @@
  13214. #include "ether3.h"
  13215. static unsigned int net_debug = NET_DEBUG;
  13216. -static const card_ids __init ether3_cids[] = {
  13217. +static card_ids __initdata ether3_cids[] = {
  13218. { MANU_ANT2, PROD_ANT_ETHER3 },
  13219. { MANU_ANT, PROD_ANT_ETHER3 },
  13220. { MANU_ANT, PROD_ANT_ETHERB },
  13221. diff -urN linux-2.4.26/drivers/acorn/net/etherh.c linux-2.4.26-vrs1/drivers/acorn/net/etherh.c
  13222. --- linux-2.4.26/drivers/acorn/net/etherh.c 2003-08-25 12:44:40.000000000 +0100
  13223. +++ linux-2.4.26-vrs1/drivers/acorn/net/etherh.c 2004-01-14 21:32:24.000000000 +0000
  13224. @@ -57,7 +57,7 @@
  13225. static unsigned int net_debug = NET_DEBUG;
  13226. -static const card_ids __init etherh_cids[] = {
  13227. +static card_ids __initdata etherh_cids[] = {
  13228. { MANU_ANT, PROD_ANT_ETHERM },
  13229. { MANU_I3, PROD_I3_ETHERLAN500 },
  13230. { MANU_I3, PROD_I3_ETHERLAN600 },
  13231. diff -urN linux-2.4.26/drivers/acorn/scsi/cumana_1.c linux-2.4.26-vrs1/drivers/acorn/scsi/cumana_1.c
  13232. --- linux-2.4.26/drivers/acorn/scsi/cumana_1.c 2001-09-13 23:21:32.000000000 +0100
  13233. +++ linux-2.4.26-vrs1/drivers/acorn/scsi/cumana_1.c 2004-03-07 11:05:38.000000000 +0000
  13234. @@ -153,20 +153,20 @@
  13235. ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
  13236. outb(0x00, instance->io_port - 577);
  13237. - if (instance->irq != IRQ_NONE)
  13238. + if (instance->irq != SCSI_IRQ_NONE)
  13239. if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
  13240. printk("scsi%d: IRQ%d not free, interrupts disabled\n",
  13241. instance->host_no, instance->irq);
  13242. - instance->irq = IRQ_NONE;
  13243. + instance->irq = SCSI_IRQ_NONE;
  13244. }
  13245. - if (instance->irq == IRQ_NONE) {
  13246. + if (instance->irq == SCSI_IRQ_NONE) {
  13247. printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
  13248. printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
  13249. }
  13250. printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
  13251. - if (instance->irq == IRQ_NONE)
  13252. + if (instance->irq == SCSI_IRQ_NONE)
  13253. printk ("s disabled");
  13254. else
  13255. printk (" %d", instance->irq);
  13256. @@ -185,7 +185,7 @@
  13257. {
  13258. int i;
  13259. - if (shpnt->irq != IRQ_NONE)
  13260. + if (shpnt->irq != SCSI_IRQ_NONE)
  13261. free_irq (shpnt->irq, NULL);
  13262. if (shpnt->io_port)
  13263. release_region (shpnt->io_port, shpnt->n_io_port);
  13264. diff -urN linux-2.4.26/drivers/acorn/scsi/ecoscsi.c linux-2.4.26-vrs1/drivers/acorn/scsi/ecoscsi.c
  13265. --- linux-2.4.26/drivers/acorn/scsi/ecoscsi.c 2002-08-03 01:39:43.000000000 +0100
  13266. +++ linux-2.4.26-vrs1/drivers/acorn/scsi/ecoscsi.c 2004-03-07 11:06:45.000000000 +0000
  13267. @@ -106,7 +106,7 @@
  13268. instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
  13269. instance->io_port = 0x80ce8000;
  13270. instance->n_io_port = 144;
  13271. - instance->irq = IRQ_NONE;
  13272. + instance->irq = SCSI_IRQ_NONE;
  13273. if (check_region (instance->io_port, instance->n_io_port)) {
  13274. scsi_unregister (instance);
  13275. @@ -130,20 +130,20 @@
  13276. return 0;
  13277. }
  13278. - if (instance->irq != IRQ_NONE)
  13279. + if (instance->irq != SCSI_IRQ_NONE)
  13280. if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
  13281. printk("scsi%d: IRQ%d not free, interrupts disabled\n",
  13282. instance->host_no, instance->irq);
  13283. - instance->irq = IRQ_NONE;
  13284. + instance->irq = SCSI_IRQ_NONE;
  13285. }
  13286. - if (instance->irq != IRQ_NONE) {
  13287. + if (instance->irq != SCSI_IRQ_NONE) {
  13288. printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
  13289. printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
  13290. }
  13291. printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
  13292. - if (instance->irq == IRQ_NONE)
  13293. + if (instance->irq == SCSI_IRQ_NONE)
  13294. printk ("s disabled");
  13295. else
  13296. printk (" %d", instance->irq);
  13297. @@ -157,7 +157,7 @@
  13298. int ecoscsi_release (struct Scsi_Host *shpnt)
  13299. {
  13300. - if (shpnt->irq != IRQ_NONE)
  13301. + if (shpnt->irq != SCSI_IRQ_NONE)
  13302. free_irq (shpnt->irq, NULL);
  13303. if (shpnt->io_port)
  13304. release_region (shpnt->io_port, shpnt->n_io_port);
  13305. diff -urN linux-2.4.26/drivers/acorn/scsi/oak.c linux-2.4.26-vrs1/drivers/acorn/scsi/oak.c
  13306. --- linux-2.4.26/drivers/acorn/scsi/oak.c 2001-10-11 17:04:57.000000000 +0100
  13307. +++ linux-2.4.26-vrs1/drivers/acorn/scsi/oak.c 2004-03-07 11:05:55.000000000 +0000
  13308. @@ -97,7 +97,7 @@
  13309. };
  13310. #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
  13311. -#define OAK_IRQ(card) (IRQ_NONE)
  13312. +#define OAK_IRQ(card) (SCSI_IRQ_NONE)
  13313. /*
  13314. * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
  13315. *
  13316. @@ -136,20 +136,20 @@
  13317. instance->n_io_port = 255;
  13318. request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
  13319. - if (instance->irq != IRQ_NONE)
  13320. + if (instance->irq != SCSI_IRQ_NONE)
  13321. if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
  13322. printk("scsi%d: IRQ%d not free, interrupts disabled\n",
  13323. instance->host_no, instance->irq);
  13324. - instance->irq = IRQ_NONE;
  13325. + instance->irq = SCSI_IRQ_NONE;
  13326. }
  13327. - if (instance->irq != IRQ_NONE) {
  13328. + if (instance->irq != SCSI_IRQ_NONE) {
  13329. printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
  13330. printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
  13331. }
  13332. printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
  13333. - if (instance->irq == IRQ_NONE)
  13334. + if (instance->irq == SCSI_IRQ_NONE)
  13335. printk ("s disabled");
  13336. else
  13337. printk (" %d", instance->irq);
  13338. @@ -172,7 +172,7 @@
  13339. {
  13340. int i;
  13341. - if (shpnt->irq != IRQ_NONE)
  13342. + if (shpnt->irq != SCSI_IRQ_NONE)
  13343. free_irq (shpnt->irq, NULL);
  13344. if (shpnt->io_port)
  13345. release_region (shpnt->io_port, shpnt->n_io_port);
  13346. diff -urN linux-2.4.26/drivers/at91/Makefile linux-2.4.26-vrs1/drivers/at91/Makefile
  13347. --- linux-2.4.26/drivers/at91/Makefile 1970-01-01 01:00:00.000000000 +0100
  13348. +++ linux-2.4.26-vrs1/drivers/at91/Makefile 2004-01-14 21:32:25.000000000 +0000
  13349. @@ -0,0 +1,23 @@
  13350. +#
  13351. +# Makefile for the AT91RM9200-specific Linux kernel device drivers.
  13352. +#
  13353. +# Note! Dependencies are done automagically by 'make dep', which also
  13354. +# removes any old dependencies. DON'T put your own dependencies here
  13355. +# unless it's something special (not a .c file).
  13356. +
  13357. +O_TARGET := at91drv.o
  13358. +
  13359. +subdir-y := serial net watchdog rtc usb i2c spi mtd
  13360. +subdir-m := $(subdir-y)
  13361. +
  13362. +obj-$(CONFIG_SERIAL_AT91) += serial/at91serial.o
  13363. +obj-$(CONFIG_AT91_ETHER) += net/at91net.o
  13364. +obj-$(CONFIG_AT91_WATCHDOG) += watchdog/at91wdt.o
  13365. +obj-$(CONFIG_AT91_RTC) += rtc/at91rtc.o
  13366. +obj-$(CONFIG_USB) += usb/at91usb.o
  13367. +obj-$(CONFIG_I2C_AT91) += i2c/at91i2c.o
  13368. +obj-$(CONFIG_AT91_SPIDEV) += spi/at91spi.o
  13369. +obj-$(CONFIG_MTD_AT91_DATAFLASH) += spi/at91spi.o mtd/at91mtd.o
  13370. +obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += mtd/at91mtd.o
  13371. +
  13372. +include $(TOPDIR)/Rules.make
  13373. diff -urN linux-2.4.26/drivers/at91/i2c/Makefile linux-2.4.26-vrs1/drivers/at91/i2c/Makefile
  13374. --- linux-2.4.26/drivers/at91/i2c/Makefile 1970-01-01 01:00:00.000000000 +0100
  13375. +++ linux-2.4.26-vrs1/drivers/at91/i2c/Makefile 2004-01-14 21:32:25.000000000 +0000
  13376. @@ -0,0 +1,15 @@
  13377. +# File: drivers/at91/i2c/Makefile
  13378. +#
  13379. +# Makefile for the Atmel AT91RM9200 I2C (TWI) device drivers
  13380. +#
  13381. +
  13382. +O_TARGET := at91i2c.o
  13383. +
  13384. +obj-y :=
  13385. +obj-m :=
  13386. +obj-n :=
  13387. +obj- :=
  13388. +
  13389. +obj-$(CONFIG_I2C_AT91) += at91_i2c.o
  13390. +
  13391. +include $(TOPDIR)/Rules.make
  13392. diff -urN linux-2.4.26/drivers/at91/i2c/at91_i2c.c linux-2.4.26-vrs1/drivers/at91/i2c/at91_i2c.c
  13393. --- linux-2.4.26/drivers/at91/i2c/at91_i2c.c 1970-01-01 01:00:00.000000000 +0100
  13394. +++ linux-2.4.26-vrs1/drivers/at91/i2c/at91_i2c.c 2004-03-07 15:59:15.000000000 +0000
  13395. @@ -0,0 +1,257 @@
  13396. +/*
  13397. + i2c Support for Atmel's AT91RM9200 Two-Wire Interface
  13398. +
  13399. + (c) Rick Bronson
  13400. +
  13401. + Borrowed heavily from original work by:
  13402. + Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
  13403. +
  13404. + This program is free software; you can redistribute it and/or modify
  13405. + it under the terms of the GNU General Public License as published by
  13406. + the Free Software Foundation; either version 2 of the License, or
  13407. + (at your option) any later version.
  13408. +
  13409. + This program is distributed in the hope that it will be useful,
  13410. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  13411. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13412. + GNU General Public License for more details.
  13413. +
  13414. + You should have received a copy of the GNU General Public License
  13415. + along with this program; if not, write to the Free Software
  13416. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  13417. +
  13418. +*/
  13419. +
  13420. +#include <linux/module.h>
  13421. +#include <linux/version.h>
  13422. +#include <linux/kernel.h>
  13423. +#include <linux/slab.h>
  13424. +#include <linux/pci.h>
  13425. +#include <linux/types.h>
  13426. +#include <linux/delay.h>
  13427. +#include <linux/i2c.h>
  13428. +#include <linux/init.h>
  13429. +
  13430. +#include <asm/arch/AT91RM9200_TWI.h>
  13431. +#include <asm/arch/pio.h>
  13432. +#include "at91_i2c.h"
  13433. +
  13434. +#define DBG(x...) do {\
  13435. + if (debug > 0) \
  13436. + printk(KERN_DEBUG "i2c:" x); \
  13437. + } while(0)
  13438. +
  13439. +int debug = 0;
  13440. +
  13441. +static struct at91_i2c_local *at91_i2c_device;
  13442. +
  13443. +/*
  13444. + * Poll the i2c status register until the specified bit is set.
  13445. + * Returns 0 if timed out (100 msec)
  13446. + */
  13447. +static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) {
  13448. + int loop_cntr = 10000;
  13449. + do {
  13450. + udelay(10);
  13451. + } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0));
  13452. +
  13453. + return (loop_cntr > 0);
  13454. +}
  13455. +
  13456. +/*
  13457. + * Generic i2c master transfer entrypoint
  13458. + */
  13459. +static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
  13460. +{
  13461. + struct at91_i2c_local *device = (struct at91_i2c_local *) adap->data;
  13462. + AT91PS_TWI twi = (AT91PS_TWI) device->base_addr;
  13463. +
  13464. + struct i2c_msg *pmsg;
  13465. + int length;
  13466. + unsigned char *buf;
  13467. +
  13468. + /*
  13469. + * i2c_smbus_xfer_emulated() in drivers/i2c/i2c-core.c states:
  13470. + * "... In the case of writing, we need to use only one message;
  13471. + * when reading, we need two..."
  13472. + */
  13473. +
  13474. + pmsg = msgs; /* look at 1st message, it contains the address/command */
  13475. + if (num >= 1 && num <= 2) {
  13476. + DBG("xfer: doing %s %d bytes to 0x%02x - %d messages\n",
  13477. + pmsg->flags & I2C_M_RD ? "read" : "write",
  13478. + pmsg->len, pmsg->buf[0], num);
  13479. +
  13480. + /* Set the TWI Master Mode Register */
  13481. + twi->TWI_MMR = (pmsg->addr << 16) | (pmsg->len << 8)
  13482. + | ((pmsg + 1)->flags & I2C_M_RD ? AT91C_TWI_MREAD : 0);
  13483. +
  13484. + /* Set TWI Internal Address Register with first messages data field */
  13485. + if (pmsg->len == 1)
  13486. + twi->TWI_IADR = pmsg->buf[0];
  13487. + else if (pmsg->len == 2)
  13488. + twi->TWI_IADR = pmsg->buf[0] << 8 | pmsg->buf[1];
  13489. + else /* must be 3 */
  13490. + twi->TWI_IADR = pmsg->buf[0] << 16 | pmsg->buf[1] << 8 | pmsg->buf[2];
  13491. +
  13492. + /* 1st message contains the address/command */
  13493. + if (num > 1)
  13494. + pmsg++; /* go to real message */
  13495. +
  13496. + length = pmsg->len;
  13497. + buf = pmsg->buf;
  13498. + if (length && buf) { /* sanity check */
  13499. + if (pmsg->flags & I2C_M_RD) {
  13500. + twi->TWI_CR = AT91C_TWI_START;
  13501. + while (length--) {
  13502. + if (!length)
  13503. + twi->TWI_CR = AT91C_TWI_STOP;
  13504. + /* Wait until transfer is finished */
  13505. + if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) {
  13506. + printk(KERN_ERR "at91_i2c: timeout 1\n");
  13507. + return 0;
  13508. + }
  13509. + *buf++ = twi->TWI_RHR;
  13510. + }
  13511. + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
  13512. + printk(KERN_ERR "at91_i2c: timeout 2\n");
  13513. + return 0;
  13514. + }
  13515. + } else {
  13516. + twi->TWI_CR = AT91C_TWI_START;
  13517. + while (length--) {
  13518. + twi->TWI_THR = *buf++;
  13519. + if (!length)
  13520. + twi->TWI_CR = AT91C_TWI_STOP;
  13521. + if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) {
  13522. + printk(KERN_ERR "at91_i2c: timeout 3\n");
  13523. + return 0;
  13524. + }
  13525. + }
  13526. + /* Wait until transfer is finished */
  13527. + if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
  13528. + printk(KERN_ERR "at91_i2c: timeout 4\n");
  13529. + return 0;
  13530. + }
  13531. + }
  13532. + }
  13533. + DBG("transfer complete\n");
  13534. + return num;
  13535. + }
  13536. + else {
  13537. + printk(KERN_ERR "at91_i2c: unexpected number of messages: %d\n", num);
  13538. + return 0;
  13539. + }
  13540. +}
  13541. +
  13542. +/*
  13543. + * Return list of supported functionality
  13544. + */
  13545. +static u32 at91_func(struct i2c_adapter *adapter)
  13546. +{
  13547. + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE
  13548. + | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
  13549. + | I2C_FUNC_SMBUS_BLOCK_DATA;
  13550. +}
  13551. +
  13552. +/*
  13553. + * Open
  13554. + */
  13555. +static void at91_inc(struct i2c_adapter *adapter)
  13556. +{
  13557. + MOD_INC_USE_COUNT;
  13558. +}
  13559. +
  13560. +/*
  13561. + * Close
  13562. + */
  13563. +static void at91_dec(struct i2c_adapter *adapter)
  13564. +{
  13565. + MOD_DEC_USE_COUNT;
  13566. +}
  13567. +
  13568. +/* For now, we only handle combined mode (smbus) */
  13569. +static struct i2c_algorithm at91_algorithm = {
  13570. + name:"at91 i2c",
  13571. + id:I2C_ALGO_SMBUS,
  13572. + master_xfer:at91_xfer,
  13573. + functionality:at91_func,
  13574. +};
  13575. +
  13576. +/*
  13577. + * Main initialization routine
  13578. + */
  13579. +static int __init i2c_at91_init(void)
  13580. +{
  13581. + AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI;
  13582. + struct at91_i2c_local *device;
  13583. + int rc;
  13584. +
  13585. + AT91_CfgPIO_TWI();
  13586. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */
  13587. +
  13588. + twi->TWI_IDR = 0x3ff; /* Disable all interrupts */
  13589. + twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */
  13590. + twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */
  13591. +
  13592. + /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */
  13593. + twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8);
  13594. +
  13595. + device = (struct at91_i2c_local *) kmalloc(sizeof(struct at91_i2c_local), GFP_KERNEL);
  13596. + if (device == NULL) {
  13597. + printk(KERN_ERR "at91_i2c: can't allocate inteface!\n");
  13598. + return -ENOMEM;
  13599. + }
  13600. + memset(device, 0, sizeof(struct at91_i2c_local));
  13601. + at91_i2c_device = device;
  13602. +
  13603. + sprintf(device->adapter.name, "AT91RM9200");
  13604. + device->adapter.data = (void *) device;
  13605. + device->adapter.id = I2C_ALGO_SMBUS;
  13606. + device->adapter.algo = &at91_algorithm;
  13607. + device->adapter.algo_data = NULL;
  13608. + device->adapter.inc_use = at91_inc;
  13609. + device->adapter.dec_use = at91_dec;
  13610. + device->adapter.client_register = NULL;
  13611. + device->adapter.client_unregister = NULL;
  13612. + device->base_addr = AT91C_VA_BASE_TWI;
  13613. +
  13614. + rc = i2c_add_adapter(&device->adapter);
  13615. + if (rc) {
  13616. + printk(KERN_ERR "at91_i2c: Adapter %s registration failed\n", device->adapter.name);
  13617. + device->adapter.data = NULL;
  13618. + kfree(device);
  13619. + }
  13620. + else
  13621. + printk(KERN_INFO "Found AT91 i2c\n");
  13622. + return rc;
  13623. +}
  13624. +
  13625. +/*
  13626. + * Clean up routine
  13627. + */
  13628. +static void __exit i2c_at91_cleanup(void)
  13629. +{
  13630. + struct at91_i2c_local *device = at91_i2c_device;
  13631. + int rc;
  13632. +
  13633. + rc = i2c_del_adapter(&device->adapter);
  13634. + device->adapter.data = NULL;
  13635. + kfree(device);
  13636. +
  13637. + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_TWI; /* disable peripheral clock */
  13638. +
  13639. + /* We aren't that prepared to deal with this... */
  13640. + if (rc)
  13641. + printk(KERN_ERR "at91_i2c: i2c_del_adapter failed (%i), that's bad!\n", rc);
  13642. +}
  13643. +
  13644. +module_init(i2c_at91_init);
  13645. +module_exit(i2c_at91_cleanup);
  13646. +
  13647. +MODULE_AUTHOR("Rick Bronson");
  13648. +MODULE_DESCRIPTION("I2C driver for Atmel AT91RM9200");
  13649. +MODULE_LICENSE("GPL");
  13650. +MODULE_PARM(debug, "i");
  13651. +
  13652. +EXPORT_NO_SYMBOLS;
  13653. diff -urN linux-2.4.26/drivers/at91/i2c/at91_i2c.h linux-2.4.26-vrs1/drivers/at91/i2c/at91_i2c.h
  13654. --- linux-2.4.26/drivers/at91/i2c/at91_i2c.h 1970-01-01 01:00:00.000000000 +0100
  13655. +++ linux-2.4.26-vrs1/drivers/at91/i2c/at91_i2c.h 2004-03-07 15:59:15.000000000 +0000
  13656. @@ -0,0 +1,43 @@
  13657. +/*
  13658. + i2c Support for Atmel's AT91RM9200 Two-Wire Interface
  13659. +
  13660. + (c) Rick Bronson
  13661. +
  13662. + This program is free software; you can redistribute it and/or modify
  13663. + it under the terms of the GNU General Public License as published by
  13664. + the Free Software Foundation; either version 2 of the License, or
  13665. + (at your option) any later version.
  13666. +
  13667. + This program is distributed in the hope that it will be useful,
  13668. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  13669. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13670. + GNU General Public License for more details.
  13671. +
  13672. + You should have received a copy of the GNU General Public License
  13673. + along with this program; if not, write to the Free Software
  13674. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  13675. +*/
  13676. +
  13677. +#ifndef AT91_I2C_H
  13678. +#define AT91_I2C_H
  13679. +
  13680. +#define AT91C_TWI_CLOCK 100000
  13681. +#define AT91C_TWI_SCLOCK (10 * AT91C_MASTER_CLOCK / AT91C_TWI_CLOCK)
  13682. +#define AT91C_TWI_CKDIV1 (2 << 16) /* TWI clock divider. NOTE: see Errata #22 */
  13683. +
  13684. +#if (AT91C_TWI_SCLOCK % 10) >= 5
  13685. +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 5)
  13686. +#else
  13687. +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 6)
  13688. +#endif
  13689. +#define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2)
  13690. +
  13691. +#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16)
  13692. +
  13693. +/* Physical interface */
  13694. +struct at91_i2c_local {
  13695. + struct i2c_adapter adapter;
  13696. + unsigned long base_addr;
  13697. +};
  13698. +
  13699. +#endif
  13700. diff -urN linux-2.4.26/drivers/at91/mtd/Makefile linux-2.4.26-vrs1/drivers/at91/mtd/Makefile
  13701. --- linux-2.4.26/drivers/at91/mtd/Makefile 1970-01-01 01:00:00.000000000 +0100
  13702. +++ linux-2.4.26-vrs1/drivers/at91/mtd/Makefile 2004-01-14 21:32:25.000000000 +0000
  13703. @@ -0,0 +1,19 @@
  13704. +# File: drivers/at91/mtd/Makefile
  13705. +#
  13706. +# Makefile for the Atmel AT91RM9200 MTD devices.
  13707. +# Includes: NAND flash (SmartMedia) & DataFlash
  13708. +#
  13709. +
  13710. +O_TARGET := at91mtd.o
  13711. +
  13712. +export-objs :=
  13713. +
  13714. +obj-y :=
  13715. +obj-m :=
  13716. +obj-n :=
  13717. +obj- :=
  13718. +
  13719. +obj-$(CONFIG_MTD_AT91_DATAFLASH) += at91_dataflash.o
  13720. +obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += at91_nand.o
  13721. +
  13722. +include $(TOPDIR)/Rules.make
  13723. diff -urN linux-2.4.26/drivers/at91/mtd/at91_dataflash.c linux-2.4.26-vrs1/drivers/at91/mtd/at91_dataflash.c
  13724. --- linux-2.4.26/drivers/at91/mtd/at91_dataflash.c 1970-01-01 01:00:00.000000000 +0100
  13725. +++ linux-2.4.26-vrs1/drivers/at91/mtd/at91_dataflash.c 2004-04-10 12:48:53.000000000 +0100
  13726. @@ -0,0 +1,509 @@
  13727. +/*
  13728. + * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder)
  13729. + *
  13730. + * (c) SAN People (Pty) Ltd
  13731. + *
  13732. + * This program is free software; you can redistribute it and/or
  13733. + * modify it under the terms of the GNU General Public License
  13734. + * as published by the Free Software Foundation; either version
  13735. + * 2 of the License, or (at your option) any later version.
  13736. +*/
  13737. +
  13738. +#include <linux/config.h>
  13739. +#include <linux/module.h>
  13740. +#include <linux/slab.h>
  13741. +#include <linux/pci.h>
  13742. +#include <linux/mtd/mtd.h>
  13743. +#include <linux/mtd/partitions.h>
  13744. +
  13745. +#include <asm/arch/AT91RM9200_SPI.h>
  13746. +#include <asm/arch/pio.h>
  13747. +#include "at91_dataflash.h"
  13748. +#include "../spi/at91_spi.h"
  13749. +
  13750. +#undef DEBUG_DATAFLASH
  13751. +
  13752. +/* Detected DataFlash devices */
  13753. +static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES];
  13754. +static int nr_devices = 0;
  13755. +
  13756. +/* ......................................................................... */
  13757. +
  13758. +#ifdef CONFIG_MTD_PARTITIONS
  13759. +
  13760. +static struct mtd_partition *mtd_parts = 0;
  13761. +static int mtd_parts_nr = 0;
  13762. +
  13763. +#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
  13764. +
  13765. +static struct mtd_partition static_partitions[] =
  13766. +{
  13767. + {
  13768. + name: "bootloader",
  13769. + offset: 0,
  13770. + size: 64 * 1024, /* 64 Kb */
  13771. + mask_flags: MTD_WRITEABLE /* read-only */
  13772. + },
  13773. + {
  13774. + name: "kernel",
  13775. + offset: MTDPART_OFS_NXTBLK,
  13776. + size: 768 *1024, /* 768 Kb */
  13777. + },
  13778. + {
  13779. + name: "filesystem",
  13780. + offset: MTDPART_OFS_NXTBLK,
  13781. + size: MTDPART_SIZ_FULL,
  13782. + }
  13783. +};
  13784. +
  13785. +int parse_cmdline_partitions(struct mtd_info *master,
  13786. + struct mtd_partition **pparts, const char *mtd_id);
  13787. +
  13788. +#endif
  13789. +
  13790. +/* ......................................................................... */
  13791. +
  13792. +/* Allocate a single SPI transfer descriptor. We're assuming that if multiple
  13793. + SPI transfers occur at the same time, spi_access_bus() will serialize them.
  13794. + If this is not valid, then either (i) each dataflash 'priv' structure
  13795. + needs it's own transfer descriptor, (ii) we lock this one, or (iii) use
  13796. + another mechanism. */
  13797. +struct spi_transfer_list* spi_transfer_desc;
  13798. +
  13799. +/*
  13800. + * Perform a SPI transfer to access the DataFlash device.
  13801. + */
  13802. +int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len,
  13803. + char* txnext, int txnext_len, char* rxnext, int rxnext_len)
  13804. +{
  13805. + struct spi_transfer_list* list = spi_transfer_desc;
  13806. +
  13807. + list->tx[0] = tx; list->txlen[0] = tx_len;
  13808. + list->rx[0] = rx; list->rxlen[0] = rx_len;
  13809. +
  13810. + list->tx[1] = txnext; list->txlen[1] = txnext_len;
  13811. + list->rx[1] = rxnext; list->rxlen[1] = rxnext_len;
  13812. +
  13813. + list->nr_transfers = nr;
  13814. +
  13815. + return spi_transfer(list);
  13816. +}
  13817. +
  13818. +/* ......................................................................... */
  13819. +
  13820. +/*
  13821. + * Poll the DataFlash device until it is READY.
  13822. + */
  13823. +void at91_dataflash_waitready(void)
  13824. +{
  13825. + char* command = kmalloc(2, GFP_KERNEL);
  13826. +
  13827. + if (!command)
  13828. + return;
  13829. +
  13830. + do {
  13831. + command[0] = OP_READ_STATUS;
  13832. + command[1] = 0;
  13833. +
  13834. + do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
  13835. + } while ((command[1] & 0x80) == 0);
  13836. +
  13837. + kfree(command);
  13838. +}
  13839. +
  13840. +/*
  13841. + * Return the status of the DataFlash device.
  13842. + */
  13843. +unsigned short at91_dataflash_status(void)
  13844. +{
  13845. + unsigned short status;
  13846. + char* command = kmalloc(2, GFP_KERNEL);
  13847. +
  13848. + if (!command)
  13849. + return 0;
  13850. +
  13851. + command[0] = OP_READ_STATUS;
  13852. + command[1] = 0;
  13853. +
  13854. + do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
  13855. + status = command[1];
  13856. +
  13857. + kfree(command);
  13858. + return status;
  13859. +}
  13860. +
  13861. +/* ......................................................................... */
  13862. +
  13863. +/*
  13864. + * Erase blocks of flash.
  13865. + */
  13866. +int at91_dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
  13867. +{
  13868. + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
  13869. + unsigned int pageaddr;
  13870. + char* command;
  13871. +
  13872. +#ifdef DEBUG_DATAFLASH
  13873. + printk("dataflash_erase: addr=%i len=%i\n", instr->addr, instr->len);
  13874. +#endif
  13875. +
  13876. + /* Sanity checks */
  13877. + if (instr->addr + instr->len > mtd->size)
  13878. + return -EINVAL;
  13879. + if ((instr->len % mtd->erasesize != 0) || (instr->len % priv->page_size != 0))
  13880. + return -EINVAL;
  13881. + if ((instr->addr % priv->page_size) != 0)
  13882. + return -EINVAL;
  13883. +
  13884. + command = kmalloc(4, GFP_KERNEL);
  13885. + if (!command)
  13886. + return -ENOMEM;
  13887. +
  13888. + while (instr->len > 0) {
  13889. + /* Calculate flash page address */
  13890. + pageaddr = (instr->addr / priv->page_size) << priv->page_offset;
  13891. +
  13892. + command[0] = OP_ERASE_PAGE;
  13893. + command[1] = (pageaddr & 0x00FF0000) >> 16;
  13894. + command[2] = (pageaddr & 0x0000FF00) >> 8;
  13895. + command[3] = 0;
  13896. +#ifdef DEBUG_DATAFLASH
  13897. + printk("ERASE: (%x) %x %x %x [%i]\n", command[0], command[1], command[2], command[3], pageaddr);
  13898. +#endif
  13899. +
  13900. + /* Send command to SPI device */
  13901. + spi_access_bus(priv->spi);
  13902. + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
  13903. +
  13904. + at91_dataflash_waitready(); /* poll status until ready */
  13905. + spi_release_bus(priv->spi);
  13906. +
  13907. + instr->addr += priv->page_size; /* next page */
  13908. + instr->len -= priv->page_size;
  13909. + }
  13910. +
  13911. + kfree(command);
  13912. +
  13913. + /* Inform MTD subsystem that erase is complete */
  13914. + instr->state = MTD_ERASE_DONE;
  13915. + if (instr->callback)
  13916. + instr->callback(instr);
  13917. +
  13918. + return 0;
  13919. +}
  13920. +
  13921. +/*
  13922. + * Read from the DataFlash device.
  13923. + * from : Start offset in flash device
  13924. + * len : Amount to read
  13925. + * retlen : About of data actually read
  13926. + * buf : Buffer containing the data
  13927. + */
  13928. +int at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
  13929. +{
  13930. + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
  13931. + unsigned int addr;
  13932. + char* command;
  13933. +
  13934. +#ifdef DEBUG_DATAFLASH
  13935. + printk("dataflash_read: %lli .. %lli\n", from, from+len);
  13936. +#endif
  13937. +
  13938. + *retlen = 0;
  13939. +
  13940. + /* Sanity checks */
  13941. + if (!len)
  13942. + return 0;
  13943. + if (from + len > mtd->size)
  13944. + return -EINVAL;
  13945. +
  13946. + /* Calculate flash page/byte address */
  13947. + addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size);
  13948. +
  13949. + command = kmalloc(8, GFP_KERNEL);
  13950. + if (!command)
  13951. + return -ENOMEM;
  13952. +
  13953. + command[0] = OP_READ_CONTINUOUS;
  13954. + command[1] = (addr & 0x00FF0000) >> 16;
  13955. + command[2] = (addr & 0x0000FF00) >> 8;
  13956. + command[3] = (addr & 0x000000FF);
  13957. +#ifdef DEBUG_DATAFLASH
  13958. + printk("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
  13959. +#endif
  13960. +
  13961. + /* Send command to SPI device */
  13962. + spi_access_bus(priv->spi);
  13963. + do_spi_transfer(2, command, 8, command, 8, buf, len, buf, len);
  13964. + spi_release_bus(priv->spi);
  13965. +
  13966. + *retlen = len;
  13967. + kfree(command);
  13968. + return 0;
  13969. +}
  13970. +
  13971. +/*
  13972. + * Write to the DataFlash device.
  13973. + * to : Start offset in flash device
  13974. + * len : Amount to write
  13975. + * retlen : Amount of data actually written
  13976. + * buf : Buffer containing the data
  13977. + */
  13978. +int at91_dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
  13979. +{
  13980. + struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
  13981. + unsigned int pageaddr, addr, offset, writelen;
  13982. + size_t remaining;
  13983. + u_char *writebuf;
  13984. + unsigned short status;
  13985. + int res = 0;
  13986. + char* command;
  13987. + char* tmpbuf = NULL;
  13988. +
  13989. +#ifdef DEBUG_DATAFLASH
  13990. + printk("dataflash_write: %lli .. %lli\n", to, to+len);
  13991. +#endif
  13992. +
  13993. + *retlen = 0;
  13994. +
  13995. + /* Sanity checks */
  13996. + if (!len)
  13997. + return 0;
  13998. + if (to + len > mtd->size)
  13999. + return -EINVAL;
  14000. +
  14001. + command = kmalloc(4, GFP_KERNEL);
  14002. + if (!command)
  14003. + return -ENOMEM;
  14004. +
  14005. + pageaddr = ((unsigned)to / priv->page_size);
  14006. + offset = ((unsigned)to % priv->page_size);
  14007. + if (offset + len > priv->page_size)
  14008. + writelen = priv->page_size - offset;
  14009. + else
  14010. + writelen = len;
  14011. + writebuf = buf;
  14012. + remaining = len;
  14013. +
  14014. + /* Allocate temporary buffer */
  14015. + tmpbuf = kmalloc(priv->page_size, GFP_KERNEL);
  14016. + if (!tmpbuf) {
  14017. + kfree(command);
  14018. + return -ENOMEM;
  14019. + }
  14020. +
  14021. + /* Gain access to the SPI bus */
  14022. + spi_access_bus(priv->spi);
  14023. +
  14024. + while (remaining > 0) {
  14025. +#ifdef DEBUG_DATAFLASH
  14026. + printk("write @ %i:%i len=%i\n", pageaddr, offset, writelen);
  14027. +#endif
  14028. +
  14029. + /* (1) Transfer to Buffer1 */
  14030. + if (writelen != priv->page_size) {
  14031. + addr = pageaddr << priv->page_offset;
  14032. + command[0] = OP_TRANSFER_BUF1;
  14033. + command[1] = (addr & 0x00FF0000) >> 16;
  14034. + command[2] = (addr & 0x0000FF00) >> 8;
  14035. + command[3] = 0;
  14036. +#ifdef DEBUG_DATAFLASH
  14037. + printk("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
  14038. +#endif
  14039. + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
  14040. + at91_dataflash_waitready();
  14041. + }
  14042. +
  14043. + /* (2) Program via Buffer1 */
  14044. + addr = (pageaddr << priv->page_offset) + offset;
  14045. + command[0] = OP_PROGRAM_VIA_BUF1;
  14046. + command[1] = (addr & 0x00FF0000) >> 16;
  14047. + command[2] = (addr & 0x0000FF00) >> 8;
  14048. + command[3] = (addr & 0x000000FF);
  14049. +#ifdef DEBUG_DATAFLASH
  14050. + printk("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
  14051. +#endif
  14052. + do_spi_transfer(2, command, 4, command, 4, writebuf, writelen, tmpbuf, writelen);
  14053. + at91_dataflash_waitready();
  14054. +
  14055. + /* (3) Compare to Buffer1 */
  14056. + addr = pageaddr << priv->page_offset;
  14057. + command[0] = OP_COMPARE_BUF1;
  14058. + command[1] = (addr & 0x00FF0000) >> 16;
  14059. + command[2] = (addr & 0x0000FF00) >> 8;
  14060. + command[3] = 0;
  14061. +#ifdef DEBUG_DATAFLASH
  14062. + printk("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
  14063. +#endif
  14064. + do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
  14065. + at91_dataflash_waitready();
  14066. +
  14067. + /* Get result of the compare operation */
  14068. + status = at91_dataflash_status();
  14069. + if ((status & 0x40) == 1) {
  14070. + printk("at91_dataflash: Write error on page %i\n", pageaddr);
  14071. + remaining = 0;
  14072. + res = -EIO;
  14073. + }
  14074. +
  14075. + remaining = remaining - writelen;
  14076. + pageaddr++;
  14077. + offset = 0;
  14078. + writebuf += writelen;
  14079. + *retlen += writelen;
  14080. +
  14081. + if (remaining > priv->page_size)
  14082. + writelen = priv->page_size;
  14083. + else
  14084. + writelen = remaining;
  14085. + }
  14086. +
  14087. + /* Release SPI bus */
  14088. + spi_release_bus(priv->spi);
  14089. +
  14090. + kfree(tmpbuf);
  14091. + kfree(command);
  14092. + return res;
  14093. +}
  14094. +
  14095. +/* ......................................................................... */
  14096. +
  14097. +/*
  14098. + * Initialize and register DataFlash device with MTD subsystem.
  14099. + */
  14100. +int add_dataflash(int channel, char *name, int size, int pagesize, int pageoffset)
  14101. +{
  14102. + struct mtd_info *device;
  14103. + struct dataflash_local *priv;
  14104. +#ifdef CONFIG_MTD_CMDLINE_PARTS
  14105. + char mtdID[14];
  14106. +#endif
  14107. +
  14108. + if (nr_devices >= DATAFLASH_MAX_DEVICES) {
  14109. + printk(KERN_ERR "at91_dataflash: Too many devices detected\n");
  14110. + return 0;
  14111. + }
  14112. +
  14113. + device = (struct mtd_info *) kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
  14114. + if (!device)
  14115. + return -ENOMEM;
  14116. + memset(device, 0, sizeof(struct mtd_info));
  14117. +
  14118. + device->name = name;
  14119. + device->size = size;
  14120. + device->erasesize = pagesize;
  14121. + device->module = THIS_MODULE;
  14122. + device->type = MTD_NORFLASH;
  14123. + device->flags = MTD_CAP_NORFLASH;
  14124. + device->erase = at91_dataflash_erase;
  14125. + device->read = at91_dataflash_read;
  14126. + device->write = at91_dataflash_write;
  14127. +
  14128. + priv = (struct dataflash_local *) kmalloc(sizeof(struct dataflash_local), GFP_KERNEL);
  14129. + if (!priv) {
  14130. + kfree(device);
  14131. + return -ENOMEM;
  14132. + }
  14133. + memset(priv, 0, sizeof(struct dataflash_local));
  14134. +
  14135. + priv->spi = channel;
  14136. + priv->page_size = pagesize;
  14137. + priv->page_offset = pageoffset;
  14138. + device->priv = priv;
  14139. +
  14140. + mtd_devices[nr_devices] = device;
  14141. + nr_devices++;
  14142. + printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, size);
  14143. +
  14144. +#ifdef CONFIG_MTD_PARTITIONS
  14145. +#ifdef CONFIG_MTD_CMDLINE_PARTS
  14146. + sprintf(mtdID, "dataflash%i", nr_devices-1);
  14147. + mtd_parts_nr = parse_cmdline_partitions(device, &mtd_parts, mtdID);
  14148. +#endif
  14149. + if (mtd_parts_nr <= 0) {
  14150. + mtd_parts = static_partitions;
  14151. + mtd_parts_nr = NB_OF(static_partitions);
  14152. + }
  14153. +
  14154. + return add_mtd_partitions(device, mtd_parts, mtd_parts_nr);
  14155. +#else
  14156. + return add_mtd_device(device);
  14157. +#endif
  14158. +}
  14159. +
  14160. +/*
  14161. + * Detect and initialize DataFlash device connected to specified SPI channel.
  14162. + */
  14163. +int at91_dataflash_detect(int channel)
  14164. +{
  14165. + int res = 0;
  14166. + unsigned short status;
  14167. +
  14168. + spi_access_bus(channel);
  14169. + status = at91_dataflash_status();
  14170. + if (status != 0xff) { /* no dataflash device there */
  14171. + switch (status & 0x3c) {
  14172. + case 0x2c: /* 1 0 1 1 */
  14173. + res = add_dataflash(channel, "Atmel AT45DB161B", 4096*528, 528, 10);
  14174. + break;
  14175. + case 0x34: /* 1 1 0 1 */
  14176. + res = add_dataflash(channel, "Atmel AT45DB321B", 8192*528, 528, 10);
  14177. + break;
  14178. + case 0x3c: /* 1 1 1 1 */
  14179. + res = add_dataflash(channel, "Atmel AT45DB642", 8192*1056, 1056, 11);
  14180. + break;
  14181. + default:
  14182. + printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c);
  14183. + }
  14184. + }
  14185. + spi_release_bus(channel);
  14186. +
  14187. + return res;
  14188. +}
  14189. +
  14190. +int __init at91_dataflash_init(void)
  14191. +{
  14192. + spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
  14193. + if (!spi_transfer_desc)
  14194. + return -ENOMEM;
  14195. +
  14196. + /* DataFlash (SPI chip select 0) */
  14197. + at91_dataflash_detect(0);
  14198. +
  14199. +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
  14200. + /* DataFlash card (SPI chip select 3) */
  14201. + AT91_CfgPIO_DataFlashCard();
  14202. + at91_dataflash_detect(3);
  14203. +#endif
  14204. +
  14205. + return 0;
  14206. +}
  14207. +
  14208. +void __exit at91_dataflash_exit(void)
  14209. +{
  14210. + int i;
  14211. +
  14212. + for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) {
  14213. + if (mtd_devices[i]) {
  14214. +#ifdef CONFIG_MTD_PARTITIONS
  14215. + del_mtd_partitions(mtd_devices[i]);
  14216. +#else
  14217. + del_mtd_device(mtd_devices[i]);
  14218. +#endif
  14219. + kfree(mtd_devices[i]->priv);
  14220. + kfree(mtd_devices[i]);
  14221. + }
  14222. + }
  14223. + nr_devices = 0;
  14224. + kfree(spi_transfer_desc);
  14225. +}
  14226. +
  14227. +
  14228. +EXPORT_NO_SYMBOLS;
  14229. +
  14230. +module_init(at91_dataflash_init);
  14231. +module_exit(at91_dataflash_exit);
  14232. +
  14233. +MODULE_LICENSE("GPL")
  14234. +MODULE_AUTHOR("Andrew Victor")
  14235. +MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200")
  14236. diff -urN linux-2.4.26/drivers/at91/mtd/at91_dataflash.h linux-2.4.26-vrs1/drivers/at91/mtd/at91_dataflash.h
  14237. --- linux-2.4.26/drivers/at91/mtd/at91_dataflash.h 1970-01-01 01:00:00.000000000 +0100
  14238. +++ linux-2.4.26-vrs1/drivers/at91/mtd/at91_dataflash.h 2004-01-14 21:32:25.000000000 +0000
  14239. @@ -0,0 +1,42 @@
  14240. +/*
  14241. + * Atmel DataFlash driver for the Atmel AT91RM9200 (Thunder)
  14242. + *
  14243. + * (c) SAN People (Pty) Ltd
  14244. + *
  14245. + * This program is free software; you can redistribute it and/or
  14246. + * modify it under the terms of the GNU General Public License
  14247. + * as published by the Free Software Foundation; either version
  14248. + * 2 of the License, or (at your option) any later version.
  14249. + */
  14250. +
  14251. +#ifndef AT91_DATAFLASH_H
  14252. +#define AT91_DATAFLASH_H
  14253. +
  14254. +#define DATAFLASH_MAX_DEVICES 4 /* max number of dataflash devices */
  14255. +
  14256. +#define OP_READ_CONTINUOUS 0xE8
  14257. +#define OP_READ_PAGE 0xD2
  14258. +#define OP_READ_BUFFER1 0xD4
  14259. +#define OP_READ_BUFFER2 0xD6
  14260. +#define OP_READ_STATUS 0xD7
  14261. +
  14262. +#define OP_ERASE_PAGE 0x81
  14263. +#define OP_ERASE_BLOCK 0x50
  14264. +
  14265. +#define OP_TRANSFER_BUF1 0x53
  14266. +#define OP_TRANSFER_BUF2 0x55
  14267. +#define OP_COMPARE_BUF1 0x60
  14268. +#define OP_COMPARE_BUF2 0x61
  14269. +
  14270. +#define OP_PROGRAM_VIA_BUF1 0x82
  14271. +#define OP_PROGRAM_VIA_BUF2 0x85
  14272. +
  14273. +struct dataflash_local
  14274. +{
  14275. + int spi; /* SPI chip-select number */
  14276. +
  14277. + unsigned int page_size; /* number of bytes per page */
  14278. + unsigned short page_offset; /* page offset in flash address */
  14279. +};
  14280. +
  14281. +#endif
  14282. diff -urN linux-2.4.26/drivers/at91/mtd/at91_nand.c linux-2.4.26-vrs1/drivers/at91/mtd/at91_nand.c
  14283. --- linux-2.4.26/drivers/at91/mtd/at91_nand.c 1970-01-01 01:00:00.000000000 +0100
  14284. +++ linux-2.4.26-vrs1/drivers/at91/mtd/at91_nand.c 2004-03-04 22:11:35.000000000 +0000
  14285. @@ -0,0 +1,328 @@
  14286. +/*
  14287. + * drivers/at91/mtd/at91_nand.c
  14288. + *
  14289. + * Copyright (c) 2003 Rick Bronson
  14290. + *
  14291. + * Derived from drivers/mtd/nand/autcpu12.c
  14292. + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  14293. + *
  14294. + * Derived from drivers/mtd/spia.c
  14295. + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
  14296. + *
  14297. + * This program is free software; you can redistribute it and/or modify
  14298. + * it under the terms of the GNU General Public License version 2 as
  14299. + * published by the Free Software Foundation.
  14300. + *
  14301. + */
  14302. +
  14303. +#include <linux/slab.h>
  14304. +#include <linux/module.h>
  14305. +#include <linux/mtd/mtd.h>
  14306. +#include <linux/mtd/nand.h>
  14307. +#include <linux/mtd/partitions.h>
  14308. +#include <asm/io.h>
  14309. +#include <asm/arch/hardware.h>
  14310. +#include <asm/sizes.h>
  14311. +
  14312. +#include <asm/arch/pio.h>
  14313. +#include "at91_nand.h"
  14314. +
  14315. +/*
  14316. + * MTD structure for AT91 board
  14317. + */
  14318. +static struct mtd_info *at91_mtd = NULL;
  14319. +static struct nand_chip *my_nand_chip = NULL;
  14320. +
  14321. +static int at91_fio_base;
  14322. +
  14323. +#ifdef CONFIG_MTD_PARTITIONS
  14324. +
  14325. +/*
  14326. + * Define partitions for flash devices
  14327. + */
  14328. +
  14329. +static struct mtd_partition partition_info32k[] = {
  14330. + { name: "AT91 NAND partition 1, kernel",
  14331. + offset: 0,
  14332. + size: 1 * SZ_1M },
  14333. + { name: "AT91 NAND partition 2, filesystem",
  14334. + offset: 1 * SZ_1M,
  14335. + size: 16 * SZ_1M },
  14336. + { name: "AT91 NAND partition 3a, storage",
  14337. + offset: (1 * SZ_1M) + (16 * SZ_1M),
  14338. + size: 1 * SZ_1M },
  14339. + { name: "AT91 NAND partition 3b, storage",
  14340. + offset: (2 * SZ_1M) + (16 * SZ_1M),
  14341. + size: 1 * SZ_1M },
  14342. + { name: "AT91 NAND partition 3c, storage",
  14343. + offset: (3 * SZ_1M) + (16 * SZ_1M),
  14344. + size: 1 * SZ_1M },
  14345. + { name: "AT91 NAND partition 3d, storage",
  14346. + offset: (4 * SZ_1M) + (16 * SZ_1M),
  14347. + size: 1 * SZ_1M },
  14348. +};
  14349. +
  14350. +static struct mtd_partition partition_info64k[] = {
  14351. + { name: "AT91 NAND partition 1, kernel",
  14352. + offset: 0,
  14353. + size: 1 * SZ_1M },
  14354. + { name: "AT91 NAND partition 2, filesystem",
  14355. + offset: 1 * SZ_1M,
  14356. + size: 16 * SZ_1M },
  14357. + { name: "AT91 NAND partition 3, storage",
  14358. + offset: (1 * SZ_1M) + (16 * SZ_1M),
  14359. + size: 47 * SZ_1M },
  14360. +};
  14361. +
  14362. +#endif
  14363. +
  14364. +/*
  14365. + * Hardware specific access to control-lines
  14366. + */
  14367. +static void at91_hwcontrol(int cmd)
  14368. +{
  14369. + struct nand_chip *my_nand = my_nand_chip;
  14370. + switch(cmd)
  14371. + {
  14372. + case NAND_CTL_SETCLE:
  14373. + my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_CLE;
  14374. + break;
  14375. + case NAND_CTL_CLRCLE:
  14376. + my_nand->IO_ADDR_W = at91_fio_base;
  14377. + break;
  14378. + case NAND_CTL_SETALE:
  14379. + my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_ALE;
  14380. + break;
  14381. + case NAND_CTL_CLRALE:
  14382. + my_nand->IO_ADDR_W = at91_fio_base;
  14383. + break;
  14384. + case NAND_CTL_SETNCE:
  14385. + break;
  14386. + case NAND_CTL_CLRNCE:
  14387. + break;
  14388. + }
  14389. +}
  14390. +
  14391. +/*
  14392. + * Send command to NAND device
  14393. + */
  14394. +static void at91_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
  14395. +{
  14396. + register struct nand_chip *my_nand = mtd->priv;
  14397. +
  14398. + /* Begin command latch cycle */
  14399. + register unsigned long NAND_IO_ADDR = my_nand->IO_ADDR_W + AT91_SMART_MEDIA_CLE;
  14400. +
  14401. + /*
  14402. + * Write out the command to the device.
  14403. + */
  14404. + if (command != NAND_CMD_SEQIN)
  14405. + writeb (command, NAND_IO_ADDR);
  14406. + else {
  14407. + if (mtd->oobblock == 256 && column >= 256) {
  14408. + column -= 256;
  14409. + writeb (NAND_CMD_RESET, NAND_IO_ADDR);
  14410. + writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
  14411. + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
  14412. + }
  14413. + else
  14414. + if (mtd->oobblock == 512 && column >= 256) {
  14415. + if (column < 512) {
  14416. + column -= 256;
  14417. + writeb (NAND_CMD_READ1, NAND_IO_ADDR);
  14418. + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
  14419. + } else {
  14420. + column -= 512;
  14421. + writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
  14422. + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
  14423. + }
  14424. + } else {
  14425. + writeb (NAND_CMD_READ0, NAND_IO_ADDR);
  14426. + writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
  14427. + }
  14428. + }
  14429. +
  14430. + /* Set ALE and clear CLE to start address cycle */
  14431. + NAND_IO_ADDR = at91_fio_base;
  14432. +
  14433. + if (column != -1 || page_addr != -1)
  14434. + NAND_IO_ADDR += AT91_SMART_MEDIA_ALE;
  14435. +
  14436. + /* Serially input address */
  14437. + if (column != -1)
  14438. + writeb (column, NAND_IO_ADDR);
  14439. + if (page_addr != -1) {
  14440. + writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR);
  14441. + writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR);
  14442. + /* One more address cycle for higher density devices */
  14443. + if (mtd->size & 0x0c000000) {
  14444. + writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR);
  14445. + }
  14446. + }
  14447. +
  14448. + /* wait until command is processed */
  14449. + while (!my_nand->dev_ready())
  14450. + ;
  14451. +}
  14452. +
  14453. +/*
  14454. + * Read the Device Ready pin.
  14455. + */
  14456. +static int at91_device_ready(void)
  14457. +{
  14458. + return AT91_PIO_SmartMedia_RDY();
  14459. +}
  14460. +/*
  14461. + * Main initialization routine
  14462. + */
  14463. +static int __init at91_init (void)
  14464. +{
  14465. + struct nand_chip *my_nand;
  14466. + int err = 0;
  14467. +
  14468. + /* Allocate memory for MTD device structure and private data */
  14469. + at91_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
  14470. + if (!at91_mtd) {
  14471. + printk ("Unable to allocate AT91 NAND MTD device structure.\n");
  14472. + err = -ENOMEM;
  14473. + goto out;
  14474. + }
  14475. +
  14476. + /* map physical adress */
  14477. + at91_fio_base = (unsigned long) ioremap(AT91_SMARTMEDIA_BASE, SZ_8M);
  14478. + if(!at91_fio_base) {
  14479. + printk("ioremap AT91 NAND failed\n");
  14480. + err = -EIO;
  14481. + goto out_mtd;
  14482. + }
  14483. +
  14484. + /* Get pointer to private data */
  14485. + my_nand_chip = my_nand = (struct nand_chip *) (&at91_mtd[1]);
  14486. +
  14487. + /* Initialize structures */
  14488. + memset((char *) at91_mtd, 0, sizeof(struct mtd_info));
  14489. + memset((char *) my_nand, 0, sizeof(struct nand_chip));
  14490. +
  14491. + /* Link the private data with the MTD structure */
  14492. + at91_mtd->priv = my_nand;
  14493. +
  14494. + /* Set address of NAND IO lines */
  14495. + my_nand->IO_ADDR_R = at91_fio_base;
  14496. + my_nand->IO_ADDR_W = at91_fio_base;
  14497. + my_nand->hwcontrol = at91_hwcontrol;
  14498. + my_nand->dev_ready = at91_device_ready;
  14499. + my_nand->cmdfunc = at91_nand_command; /* we need our own */
  14500. + my_nand->eccmode = NAND_ECC_SOFT; /* enable ECC */
  14501. + /* 20 us command delay time */
  14502. + my_nand->chip_delay = 20;
  14503. +
  14504. + /* Setup Smart Media, first enable the address range of CS3 */
  14505. + AT91_SYS->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia;
  14506. + /* set the bus interface characteristics based on
  14507. + tDS Data Set up Time 30 - ns
  14508. + tDH Data Hold Time 20 - ns
  14509. + tALS ALE Set up Time 20 - ns
  14510. + 16ns at 60 MHz ~= 3 */
  14511. +#define AT91C_SM_ID_RWH (5 << 28) /* orig = 5 */
  14512. +#define AT91C_SM_RWH (1 << 28) /* orig = 1 */
  14513. +#define AT91C_SM_RWS (0 << 24) /* orig = 0 */
  14514. +#define AT91C_SM_TDF (1 << 8) /* orig = 1 */
  14515. +#define AT91C_SM_NWS (5) /* orig = 3 */
  14516. + AT91_SYS->EBI_SMC2_CSR[3] = ( AT91C_SM_RWH | AT91C_SM_RWS |
  14517. + AT91C_SMC2_ACSS_STANDARD |
  14518. + AT91C_SMC2_DBW_8 | AT91C_SM_TDF |
  14519. + AT91C_SMC2_WSEN | AT91C_SM_NWS);
  14520. +
  14521. + AT91_CfgPIO_SmartMedia();
  14522. +
  14523. + if (AT91_PIO_SmartMedia_CardDetect())
  14524. + printk ("No ");
  14525. + printk ("SmartMedia card inserted.\n");
  14526. +
  14527. + /* Scan to find existance of the device */
  14528. + if (nand_scan (at91_mtd)) {
  14529. + err = -ENXIO;
  14530. + goto out_ior;
  14531. + }
  14532. +
  14533. + /* Allocate memory for internal data buffer */
  14534. + my_nand->data_buf = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
  14535. + if (!my_nand->data_buf) {
  14536. + printk ("Unable to allocate AT91 NAND data buffer.\n");
  14537. + err = -ENOMEM;
  14538. + goto out_ior;
  14539. + }
  14540. +
  14541. + /* Allocate memory for internal data buffer */
  14542. + my_nand->data_cache = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
  14543. + if (!my_nand->data_cache) {
  14544. + printk ("Unable to allocate AT91 NAND data cache.\n");
  14545. + err = -ENOMEM;
  14546. + goto out_buf;
  14547. + }
  14548. + my_nand->cache_page = -1;
  14549. +
  14550. +#ifdef CONFIG_MTD_PARTITIONS
  14551. + /* Register the partitions */
  14552. + switch(at91_mtd->size)
  14553. + {
  14554. + case SZ_32M:
  14555. + err = add_mtd_partitions(at91_mtd, partition_info32k,
  14556. + ARRAY_SIZE (partition_info32k));
  14557. + break;
  14558. + case SZ_64M:
  14559. + err = add_mtd_partitions(at91_mtd, partition_info64k,
  14560. + ARRAY_SIZE (partition_info64k));
  14561. + break;
  14562. + default:
  14563. + printk ("Unsupported SmartMedia device\n");
  14564. + err = -ENXIO;
  14565. + goto out_cac;
  14566. + }
  14567. +#else
  14568. + err = add_mtd_device(at91_mtd);
  14569. +#endif
  14570. + goto out;
  14571. +
  14572. + out_cac:
  14573. + kfree (my_nand->data_cache);
  14574. + out_buf:
  14575. + kfree (my_nand->data_buf);
  14576. + out_ior:
  14577. + iounmap((void *)at91_fio_base);
  14578. + out_mtd:
  14579. + kfree (at91_mtd);
  14580. + out:
  14581. + return err;
  14582. +}
  14583. +
  14584. +/*
  14585. + * Clean up routine
  14586. + */
  14587. +static void __exit at91_cleanup (void)
  14588. +{
  14589. + struct nand_chip *my_nand = (struct nand_chip *) &at91_mtd[1];
  14590. +
  14591. + /* Unregister partitions */
  14592. + del_mtd_partitions(at91_mtd);
  14593. +
  14594. + /* Unregister the device */
  14595. + del_mtd_device (at91_mtd);
  14596. +
  14597. + /* Free internal data buffers */
  14598. + kfree (my_nand->data_buf);
  14599. + kfree (my_nand->data_cache);
  14600. +
  14601. + /* unmap physical adress */
  14602. + iounmap((void *)at91_fio_base);
  14603. +
  14604. + /* Free the MTD device structure */
  14605. + kfree (at91_mtd);
  14606. +}
  14607. +
  14608. +module_init(at91_init);
  14609. +module_exit(at91_cleanup);
  14610. +
  14611. +MODULE_LICENSE("GPL");
  14612. +MODULE_AUTHOR("Rick Bronson");
  14613. +MODULE_DESCRIPTION("Glue layer for SmartMediaCard on ATMEL AT91RM9200");
  14614. diff -urN linux-2.4.26/drivers/at91/mtd/at91_nand.h linux-2.4.26-vrs1/drivers/at91/mtd/at91_nand.h
  14615. --- linux-2.4.26/drivers/at91/mtd/at91_nand.h 1970-01-01 01:00:00.000000000 +0100
  14616. +++ linux-2.4.26-vrs1/drivers/at91/mtd/at91_nand.h 2004-01-14 21:32:25.000000000 +0000
  14617. @@ -0,0 +1,27 @@
  14618. +/*
  14619. + * AT91RM9200 specific NAND (SmartMedia) defines
  14620. + *
  14621. + * (c) 2003 Rick Bronson
  14622. + *
  14623. + * This program is free software; you can redistribute it and/or modify
  14624. + * it under the terms of the GNU General Public License as published by
  14625. + * the Free Software Foundation; either version 2 of the License, or
  14626. + * (at your option) any later version.
  14627. + *
  14628. + * This program is distributed in the hope that it will be useful,
  14629. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14630. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14631. + * GNU General Public License for more details.
  14632. + *
  14633. + * You should have received a copy of the GNU General Public License
  14634. + * along with this program; if not, write to the Free Software
  14635. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14636. + */
  14637. +
  14638. +#ifndef __AT91_NAND_H
  14639. +#define __AT91_NAND_H
  14640. +
  14641. +#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */
  14642. +#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */
  14643. +
  14644. +#endif
  14645. diff -urN linux-2.4.26/drivers/at91/net/Makefile linux-2.4.26-vrs1/drivers/at91/net/Makefile
  14646. --- linux-2.4.26/drivers/at91/net/Makefile 1970-01-01 01:00:00.000000000 +0100
  14647. +++ linux-2.4.26-vrs1/drivers/at91/net/Makefile 2004-01-14 21:32:25.000000000 +0000
  14648. @@ -0,0 +1,15 @@
  14649. +# File: drivers/at91/net/Makefile
  14650. +#
  14651. +# Makefile for the Atmel AT91RM9200 ethernet device drivers
  14652. +#
  14653. +
  14654. +O_TARGET := at91net.o
  14655. +
  14656. +obj-y :=
  14657. +obj-m :=
  14658. +obj-n :=
  14659. +obj- :=
  14660. +
  14661. +obj-$(CONFIG_AT91_ETHER) += at91_ether.o
  14662. +
  14663. +include $(TOPDIR)/Rules.make
  14664. diff -urN linux-2.4.26/drivers/at91/net/at91_ether.c linux-2.4.26-vrs1/drivers/at91/net/at91_ether.c
  14665. --- linux-2.4.26/drivers/at91/net/at91_ether.c 1970-01-01 01:00:00.000000000 +0100
  14666. +++ linux-2.4.26-vrs1/drivers/at91/net/at91_ether.c 2004-03-04 22:07:29.000000000 +0000
  14667. @@ -0,0 +1,877 @@
  14668. +/*
  14669. + * Ethernet driver for the Atmel AT91RM9200 (Thunder)
  14670. + *
  14671. + * (c) SAN People (Pty) Ltd
  14672. + *
  14673. + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
  14674. + * Initial version by Rick Bronson 01/11/2003
  14675. + *
  14676. + * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
  14677. + * (Polaroid Corporation)
  14678. + *
  14679. + * This program is free software; you can redistribute it and/or
  14680. + * modify it under the terms of the GNU General Public License
  14681. + * as published by the Free Software Foundation; either version
  14682. + * 2 of the License, or (at your option) any later version.
  14683. + */
  14684. +
  14685. +#include <linux/module.h>
  14686. +#include <linux/init.h>
  14687. +#include <linux/config.h>
  14688. +#include <linux/mii.h>
  14689. +#include <linux/netdevice.h>
  14690. +#include <linux/etherdevice.h>
  14691. +#include <linux/skbuff.h>
  14692. +#include <asm/io.h>
  14693. +#include <linux/pci.h>
  14694. +#include <linux/crc32.h>
  14695. +#include <asm/uaccess.h>
  14696. +#include <linux/ethtool.h>
  14697. +
  14698. +#include <asm/arch/AT91RM9200_EMAC.h>
  14699. +#include <asm/arch/pio.h>
  14700. +#include "at91_ether.h"
  14701. +
  14702. +static struct net_device at91_dev;
  14703. +
  14704. +/* ........................... PHY INTERFACE ........................... */
  14705. +
  14706. +/*
  14707. + * Enable the MDIO bit in MAC control register
  14708. + * When not called from an interrupt-handler, access to the PHY must be
  14709. + * protected by a spinlock.
  14710. + */
  14711. +static void enable_mdi(AT91PS_EMAC regs)
  14712. +{
  14713. + regs->EMAC_CTL |= AT91C_EMAC_MPE; /* enable management port */
  14714. +}
  14715. +
  14716. +/*
  14717. + * Disable the MDIO bit in the MAC control register
  14718. + */
  14719. +static void disable_mdi(AT91PS_EMAC regs)
  14720. +{
  14721. + regs->EMAC_CTL &= ~AT91C_EMAC_MPE; /* disable management port */
  14722. +}
  14723. +
  14724. +/*
  14725. + * Write value to the a PHY register
  14726. + * Note: MDI interface is assumed to already have been enabled.
  14727. + */
  14728. +static void write_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int value)
  14729. +{
  14730. + regs->EMAC_MAN = (AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W
  14731. + | ((phy_addr & 0x1f) << 23) | (address << 18)) + (value & 0xffff);
  14732. +
  14733. + /* Wait until IDLE bit in Network Status register is cleared */
  14734. + // TODO: Enforce some maximum loop-count?
  14735. + while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
  14736. +}
  14737. +
  14738. +/*
  14739. + * Read value stored in a PHY register.
  14740. + * Note: MDI interface is assumed to already have been enabled.
  14741. + */
  14742. +static void read_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int *value)
  14743. +{
  14744. + regs->EMAC_MAN = AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_R
  14745. + | ((phy_addr & 0x1f) << 23) | (address << 18);
  14746. +
  14747. + /* Wait until IDLE bit in Network Status register is cleared */
  14748. + // TODO: Enforce some maximum loop-count?
  14749. + while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
  14750. +
  14751. + *value = (regs->EMAC_MAN & 0x0000ffff);
  14752. +}
  14753. +
  14754. +/* ........................... PHY MANAGEMENT .......................... */
  14755. +
  14756. +/*
  14757. + * Access the PHY to determine the current Link speed and Mode, and update the
  14758. + * MAC accordingly.
  14759. + * If no link or auto-negotiation is busy, then no changes are made.
  14760. + * Returns: 0 : OK
  14761. + * -1 : No link
  14762. + * -2 : AutoNegotiation still in progress
  14763. + */
  14764. +static int update_linkspeed(struct net_device *dev, AT91PS_EMAC regs) {
  14765. + unsigned int bmsr, bmcr, lpa, mac_cfg;
  14766. + unsigned int speed, duplex;
  14767. +
  14768. + /* Link status is latched, so read twice to get current value */
  14769. + read_phy(regs, 0, MII_BMSR, &bmsr);
  14770. + read_phy(regs, 0, MII_BMSR, &bmsr);
  14771. + if (!(bmsr & BMSR_LSTATUS)) return -1; /* no link */
  14772. +
  14773. + read_phy(regs, 0, MII_BMCR, &bmcr);
  14774. + if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
  14775. + if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */
  14776. +
  14777. + read_phy(regs, 0, MII_LPA, &lpa);
  14778. + if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
  14779. + else speed = SPEED_10;
  14780. + if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
  14781. + else duplex = DUPLEX_HALF;
  14782. + } else {
  14783. + speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
  14784. + duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
  14785. + }
  14786. +
  14787. + /* Update the MAC */
  14788. + mac_cfg = regs->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
  14789. + if (speed == SPEED_100) {
  14790. + if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
  14791. + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
  14792. + else /* 100 Half Duplex */
  14793. + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD;
  14794. + } else {
  14795. + if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
  14796. + regs->EMAC_CFG = mac_cfg | AT91C_EMAC_FD;
  14797. + else /* 10 Half Duplex */
  14798. + regs->EMAC_CFG = mac_cfg;
  14799. + }
  14800. +
  14801. + printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
  14802. + return 0;
  14803. +}
  14804. +
  14805. +/*
  14806. + * Handle interrupts from the PHY
  14807. + */
  14808. +static void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  14809. +{
  14810. + struct net_device *dev = (struct net_device *) dev_id;
  14811. + struct at91_private *lp = (struct at91_private *) dev->priv;
  14812. + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
  14813. + int status;
  14814. + unsigned int phy;
  14815. +
  14816. + enable_mdi(emac);
  14817. + if (lp->phy_type == MII_DM9161_ID)
  14818. + read_phy(emac, 0, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
  14819. + else if (lp->phy_type == MII_LXT971A_ID)
  14820. + read_phy(emac, 0, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
  14821. +
  14822. + status = AT91_SYS->PIOC_ISR; /* acknowledge interrupt in PIO */
  14823. +
  14824. + status = update_linkspeed(dev, emac);
  14825. + if (status == -1) { /* link is down */
  14826. + netif_carrier_off(dev);
  14827. + printk(KERN_INFO "%s: Link down.\n", dev->name);
  14828. + } else if (status == -2) { /* auto-negotiation in progress */
  14829. + /* Do nothing - another interrupt generated when negotiation complete */
  14830. + } else { /* link is operational */
  14831. + netif_carrier_on(dev);
  14832. + }
  14833. + disable_mdi(emac);
  14834. +}
  14835. +
  14836. +/*
  14837. + * Initialize and enable the PHY interrupt when link-state changes
  14838. + */
  14839. +static void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
  14840. +{
  14841. + struct at91_private *lp = (struct at91_private *) dev->priv;
  14842. + unsigned int dsintr, status;
  14843. +
  14844. + // TODO: Check error code. Really need a generic PIO (interrupt)
  14845. + // layer since we're really only interested in the PC4 (DK) or PC2 (CSB337) line.
  14846. + (void) request_irq(AT91C_ID_PIOC, at91ether_phy_interrupt, 0, dev->name, dev);
  14847. +
  14848. + status = AT91_SYS->PIOC_ISR; /* clear any pending PIO interrupts */
  14849. +#ifdef CONFIG_MACH_CSB337
  14850. + AT91_SYS->PIOC_IER = AT91C_PIO_PC2; /* Enable interrupt */
  14851. +#else
  14852. + AT91_SYS->PIOC_IER = AT91C_PIO_PC4; /* Enable interrupt */
  14853. +#endif
  14854. +
  14855. + spin_lock_irq(&lp->lock);
  14856. + enable_mdi(regs);
  14857. +
  14858. + if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
  14859. + read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
  14860. + dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
  14861. + write_phy(regs, 0, MII_DSINTR_REG, dsintr);
  14862. + }
  14863. + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
  14864. + read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
  14865. + dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
  14866. + write_phy(regs, 0, MII_ISINTE_REG, dsintr);
  14867. + }
  14868. +
  14869. + disable_mdi(regs);
  14870. + spin_unlock_irq(&lp->lock);
  14871. +}
  14872. +
  14873. +/*
  14874. + * Disable the PHY interrupt
  14875. + */
  14876. +static void disable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
  14877. +{
  14878. + struct at91_private *lp = (struct at91_private *) dev->priv;
  14879. + unsigned int dsintr;
  14880. +
  14881. + spin_lock_irq(&lp->lock);
  14882. + enable_mdi(regs);
  14883. +
  14884. + if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
  14885. + read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
  14886. + dsintr = dsintr | 0xf00; /* set bits 8..11 */
  14887. + write_phy(regs, 0, MII_DSINTR_REG, dsintr);
  14888. + }
  14889. + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
  14890. + read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
  14891. + dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
  14892. + write_phy(regs, 0, MII_ISINTE_REG, dsintr);
  14893. + }
  14894. +
  14895. + disable_mdi(regs);
  14896. + spin_unlock_irq(&lp->lock);
  14897. +
  14898. +#ifdef CONFIG_MACH_CSB337
  14899. + AT91_SYS->PIOC_IDR = AT91C_PIO_PC2; /* Disable interrupt */
  14900. +#else
  14901. + AT91_SYS->PIOC_IDR = AT91C_PIO_PC4; /* Disable interrupt */
  14902. +#endif
  14903. + free_irq(AT91C_ID_PIOC, dev); /* Free interrupt handler */
  14904. +}
  14905. +
  14906. +/*
  14907. + * Perform a software reset of the PHY.
  14908. + */
  14909. +static void reset_phy(struct net_device *dev, AT91PS_EMAC regs)
  14910. +{
  14911. + struct at91_private *lp = (struct at91_private *) dev->priv;
  14912. + unsigned int bmcr;
  14913. +
  14914. + spin_lock_irq(&lp->lock);
  14915. + enable_mdi(regs);
  14916. +
  14917. + /* Perform PHY reset */
  14918. + write_phy(regs, 0, MII_BMCR, BMCR_RESET);
  14919. +
  14920. + /* Wait until PHY reset is complete */
  14921. + do {
  14922. + read_phy(regs, 0, MII_BMCR, &bmcr);
  14923. + } while (!(bmcr && BMCR_RESET));
  14924. +
  14925. + disable_mdi(regs);
  14926. + spin_unlock_irq(&lp->lock);
  14927. +}
  14928. +
  14929. +
  14930. +/* ......................... ADDRESS MANAGEMENT ........................ */
  14931. +
  14932. +/*
  14933. + * Set the ethernet MAC address in dev->dev_addr
  14934. + */
  14935. +static void get_mac_address(struct net_device *dev) {
  14936. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  14937. + char addr[6];
  14938. + unsigned int hi, lo;
  14939. +
  14940. + /* Check if bootloader set address in Specific-Address 1 */
  14941. + hi = regs->EMAC_SA1H;
  14942. + lo = regs->EMAC_SA1L;
  14943. + addr[0] = (lo & 0xff);
  14944. + addr[1] = (lo & 0xff00) >> 8;
  14945. + addr[2] = (lo & 0xff0000) >> 16;
  14946. + addr[3] = (lo & 0xff000000) >> 24;
  14947. + addr[4] = (hi & 0xff);
  14948. + addr[5] = (hi & 0xff00) >> 8;
  14949. +
  14950. + if (is_valid_ether_addr(addr)) {
  14951. + memcpy(dev->dev_addr, &addr, 6);
  14952. + return;
  14953. + }
  14954. +
  14955. + /* Check if bootloader set address in Specific-Address 2 */
  14956. + hi = regs->EMAC_SA2H;
  14957. + lo = regs->EMAC_SA2L;
  14958. + addr[0] = (lo & 0xff);
  14959. + addr[1] = (lo & 0xff00) >> 8;
  14960. + addr[2] = (lo & 0xff0000) >> 16;
  14961. + addr[3] = (lo & 0xff000000) >> 24;
  14962. + addr[4] = (hi & 0xff);
  14963. + addr[5] = (hi & 0xff00) >> 8;
  14964. +
  14965. + if (is_valid_ether_addr(addr)) {
  14966. + memcpy(dev->dev_addr, &addr, 6);
  14967. + return;
  14968. + }
  14969. +}
  14970. +
  14971. +/*
  14972. + * Program the hardware MAC address from dev->dev_addr.
  14973. + */
  14974. +static void update_mac_address(struct net_device *dev)
  14975. +{
  14976. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  14977. +
  14978. + regs->EMAC_SA1L = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]);
  14979. + regs->EMAC_SA1H = (dev->dev_addr[5] << 8) | (dev->dev_addr[4]);
  14980. +}
  14981. +
  14982. +#ifdef AT91_ETHER_ADDR_CONFIGURABLE
  14983. +/*
  14984. + * Store the new hardware address in dev->dev_addr, and update the MAC.
  14985. + */
  14986. +static int set_mac_address(struct net_device *dev, void* addr)
  14987. +{
  14988. + struct sockaddr *address = addr;
  14989. +
  14990. + if (!is_valid_ether_addr(address->sa_data))
  14991. + return -EADDRNOTAVAIL;
  14992. +
  14993. + memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
  14994. + update_mac_address(dev);
  14995. +
  14996. + printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
  14997. + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
  14998. + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
  14999. +
  15000. + return 0;
  15001. +}
  15002. +#endif
  15003. +
  15004. +/*
  15005. + * Add multicast addresses to the internal multicast-hash table.
  15006. + */
  15007. +static void at91ether_sethashtable(struct net_device *dev, AT91PS_EMAC regs)
  15008. +{
  15009. + struct dev_mc_list *curr;
  15010. + unsigned char mc_filter[2];
  15011. + unsigned int i, bitnr;
  15012. +
  15013. + mc_filter[0] = mc_filter[1] = 0;
  15014. +
  15015. + curr = dev->mc_list;
  15016. + for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
  15017. + if (!curr) break; /* unexpected end of list */
  15018. +
  15019. + bitnr = ether_crc(ETH_ALEN, curr->dmi_addr) >> 26;
  15020. + mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
  15021. + }
  15022. +
  15023. + regs->EMAC_HSH = mc_filter[1];
  15024. + regs->EMAC_HSL = mc_filter[0];
  15025. +}
  15026. +
  15027. +/*
  15028. + * Enable/Disable promiscuous and multicast modes.
  15029. + */
  15030. +static void at91ether_set_rx_mode(struct net_device *dev)
  15031. +{
  15032. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15033. +
  15034. + if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */
  15035. + regs->EMAC_CFG |= AT91C_EMAC_CAF;
  15036. + } else if (dev->flags & (~IFF_PROMISC)) { /* Disable promiscuous mode */
  15037. + regs->EMAC_CFG &= ~AT91C_EMAC_CAF;
  15038. + }
  15039. +
  15040. + if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
  15041. + regs->EMAC_HSH = -1;
  15042. + regs->EMAC_HSL = -1;
  15043. + regs->EMAC_CFG |= AT91C_EMAC_MTI;
  15044. + } else if (dev->mc_count > 0) { /* Enable specific multicasts */
  15045. + at91ether_sethashtable(dev, regs);
  15046. + regs->EMAC_CFG |= AT91C_EMAC_MTI;
  15047. + } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
  15048. + regs->EMAC_HSH = 0;
  15049. + regs->EMAC_HSL = 0;
  15050. + regs->EMAC_CFG &= ~AT91C_EMAC_MTI;
  15051. + }
  15052. +}
  15053. +
  15054. +/* ............................... IOCTL ............................... */
  15055. +
  15056. +static int mdio_read(struct net_device *dev, int phy_id, int location)
  15057. +{
  15058. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15059. + unsigned int value;
  15060. +
  15061. + read_phy(regs, phy_id, location, &value);
  15062. + return value;
  15063. +}
  15064. +
  15065. +static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
  15066. +{
  15067. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15068. +
  15069. + write_phy(regs, phy_id, location, value);
  15070. +}
  15071. +
  15072. +/*
  15073. + * ethtool support.
  15074. + */
  15075. +static int at91ether_ethtool_ioctl (struct net_device *dev, void *useraddr)
  15076. +{
  15077. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15078. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15079. + u32 ethcmd;
  15080. + int res = 0;
  15081. +
  15082. + if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
  15083. + return -EFAULT;
  15084. +
  15085. + spin_lock_irq(&lp->lock);
  15086. + enable_mdi(regs);
  15087. +
  15088. + switch (ethcmd) {
  15089. + case ETHTOOL_GSET: {
  15090. + struct ethtool_cmd ecmd = { ETHTOOL_GSET };
  15091. + res = mii_ethtool_gset(&lp->mii, &ecmd);
  15092. + if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
  15093. + ecmd.supported = SUPPORTED_FIBRE;
  15094. + ecmd.port = PORT_FIBRE;
  15095. + }
  15096. + if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
  15097. + res = -EFAULT;
  15098. + break;
  15099. + }
  15100. + case ETHTOOL_SSET: {
  15101. + struct ethtool_cmd ecmd;
  15102. + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
  15103. + res = -EFAULT;
  15104. + else
  15105. + res = mii_ethtool_sset(&lp->mii, &ecmd);
  15106. + break;
  15107. + }
  15108. + case ETHTOOL_NWAY_RST: {
  15109. + res = mii_nway_restart(&lp->mii);
  15110. + break;
  15111. + }
  15112. + case ETHTOOL_GLINK: {
  15113. + struct ethtool_value edata = { ETHTOOL_GLINK };
  15114. + edata.data = mii_link_ok(&lp->mii);
  15115. + if (copy_to_user(useraddr, &edata, sizeof(edata)))
  15116. + res = -EFAULT;
  15117. + break;
  15118. + }
  15119. + default:
  15120. + res = -EOPNOTSUPP;
  15121. + }
  15122. +
  15123. + disable_mdi(regs);
  15124. + spin_unlock_irq(&lp->lock);
  15125. +
  15126. + return res;
  15127. +}
  15128. +
  15129. +/*
  15130. + * User-space ioctl interface.
  15131. + */
  15132. +static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  15133. +{
  15134. + switch(cmd) {
  15135. + case SIOCETHTOOL:
  15136. + return at91ether_ethtool_ioctl(dev, (void *) rq->ifr_data);
  15137. + default:
  15138. + return -EOPNOTSUPP;
  15139. + }
  15140. +}
  15141. +
  15142. +/* ................................ MAC ................................ */
  15143. +
  15144. +/*
  15145. + * Initialize and start the Receiver and Transmit subsystems
  15146. + */
  15147. +static void at91ether_start(struct net_device *dev)
  15148. +{
  15149. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15150. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15151. + int i;
  15152. + struct recv_desc_bufs *dlist, *dlist_phys;
  15153. +
  15154. + dlist = lp->dlist;
  15155. + dlist_phys = lp->dlist_phys;
  15156. +
  15157. + for (i = 0; i < MAX_RX_DESCR; i++) {
  15158. + dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
  15159. + dlist->descriptors[i].size = 0;
  15160. + }
  15161. +
  15162. + /* Set the Wrap bit on the last descriptor */
  15163. + dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
  15164. +
  15165. + /* Reset buffer index */
  15166. + lp->rxBuffIndex = 0;
  15167. +
  15168. + /* Program address of descriptor list in Rx Buffer Queue register */
  15169. + regs->EMAC_RBQP = (AT91_REG) dlist_phys;
  15170. +
  15171. + /* Enable Receive and Transmit */
  15172. + regs->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE);
  15173. +}
  15174. +
  15175. +/*
  15176. + * Open the ethernet interface
  15177. + */
  15178. +static int at91ether_open(struct net_device *dev)
  15179. +{
  15180. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15181. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15182. +
  15183. + if (!is_valid_ether_addr(dev->dev_addr))
  15184. + return -EADDRNOTAVAIL;
  15185. +
  15186. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Re-enable Peripheral clock */
  15187. + regs->EMAC_CTL |= AT91C_EMAC_CSR; /* Clear internal statistics */
  15188. +
  15189. + /* Enable PHY interrupt */
  15190. + enable_phyirq(dev, regs);
  15191. +
  15192. + /* Enable MAC interrupts */
  15193. + regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
  15194. + | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
  15195. + | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
  15196. +
  15197. + /* Determine current link speed */
  15198. + spin_lock_irq(&lp->lock);
  15199. + enable_mdi(regs);
  15200. + (void) update_linkspeed(dev, regs);
  15201. + disable_mdi(regs);
  15202. + spin_unlock_irq(&lp->lock);
  15203. +
  15204. + at91ether_start(dev);
  15205. + netif_start_queue(dev);
  15206. + return 0;
  15207. +}
  15208. +
  15209. +/*
  15210. + * Close the interface
  15211. + */
  15212. +static int at91ether_close(struct net_device *dev)
  15213. +{
  15214. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15215. +
  15216. + /* Disable Receiver and Transmitter */
  15217. + regs->EMAC_CTL &= ~(AT91C_EMAC_TE | AT91C_EMAC_RE);
  15218. +
  15219. + /* Disable PHY interrupt */
  15220. + disable_phyirq(dev, regs);
  15221. +
  15222. + /* Disable MAC interrupts */
  15223. + regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
  15224. + | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
  15225. + | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
  15226. +
  15227. + netif_stop_queue(dev);
  15228. +
  15229. + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
  15230. +
  15231. + return 0;
  15232. +}
  15233. +
  15234. +/*
  15235. + * Transmit packet.
  15236. + */
  15237. +static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
  15238. +{
  15239. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15240. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15241. +
  15242. + if (regs->EMAC_TSR & AT91C_EMAC_BNQ) {
  15243. + netif_stop_queue(dev);
  15244. +
  15245. + /* Store packet information (to free when Tx completed) */
  15246. + lp->skb = skb;
  15247. + lp->skb_length = skb->len;
  15248. + lp->skb_physaddr = pci_map_single(NULL, skb->data, skb->len, PCI_DMA_TODEVICE);
  15249. + lp->stats.tx_bytes += skb->len;
  15250. +
  15251. + /* Set address of the data in the Transmit Address register */
  15252. + regs->EMAC_TAR = lp->skb_physaddr;
  15253. + /* Set length of the packet in the Transmit Control register */
  15254. + regs->EMAC_TCR = skb->len;
  15255. +
  15256. + dev->trans_start = jiffies;
  15257. + } else {
  15258. + printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n");
  15259. + return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
  15260. + on this skb, he also reports -ENETDOWN and printk's, so either
  15261. + we free and return(0) or don't free and return 1 */
  15262. + }
  15263. +
  15264. + return 0;
  15265. +}
  15266. +
  15267. +/*
  15268. + * Update the current statistics from the internal statistics registers.
  15269. + */
  15270. +static struct net_device_stats *at91ether_stats(struct net_device *dev)
  15271. +{
  15272. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15273. + AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
  15274. + int ale, lenerr, seqe, lcol, ecol;
  15275. +
  15276. + if (netif_running(dev)) {
  15277. + lp->stats.rx_packets += regs->EMAC_OK; /* Good frames received */
  15278. + ale = regs->EMAC_ALE;
  15279. + lp->stats.rx_frame_errors += ale; /* Alignment errors */
  15280. + lenerr = regs->EMAC_ELR + regs->EMAC_USF;
  15281. + lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
  15282. + seqe = regs->EMAC_SEQE;
  15283. + lp->stats.rx_crc_errors += seqe; /* CRC error */
  15284. + lp->stats.rx_fifo_errors += regs->EMAC_DRFC; /* Receive buffer not available */
  15285. + lp->stats.rx_errors += (ale + lenerr + seqe + regs->EMAC_CDE + regs->EMAC_RJB);
  15286. +
  15287. + lp->stats.tx_packets += regs->EMAC_FRA; /* Frames successfully transmitted */
  15288. + lp->stats.tx_fifo_errors += regs->EMAC_TUE; /* Transmit FIFO underruns */
  15289. + lp->stats.tx_carrier_errors += regs->EMAC_CSE; /* Carrier Sense errors */
  15290. + lp->stats.tx_heartbeat_errors += regs->EMAC_SQEE; /* Heartbeat error */
  15291. +
  15292. + lcol = regs->EMAC_LCOL;
  15293. + ecol = regs->EMAC_ECOL;
  15294. + lp->stats.tx_window_errors += lcol; /* Late collisions */
  15295. + lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
  15296. +
  15297. + lp->stats.collisions += (regs->EMAC_SCOL + regs->EMAC_MCOL + lcol + ecol);
  15298. + }
  15299. + return &lp->stats;
  15300. +}
  15301. +
  15302. +/*
  15303. + * Extract received frame from buffer descriptors and sent to upper layers.
  15304. + * (Called from interrupt context)
  15305. + */
  15306. +static void at91ether_rx(struct net_device *dev)
  15307. +{
  15308. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15309. + struct recv_desc_bufs *dlist;
  15310. + unsigned char *p_recv;
  15311. + struct sk_buff *skb;
  15312. + unsigned int pktlen;
  15313. +
  15314. + dlist = lp->dlist;
  15315. + while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
  15316. + p_recv = dlist->recv_buf[lp->rxBuffIndex];
  15317. + pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
  15318. + skb = alloc_skb(pktlen + 2, GFP_ATOMIC);
  15319. + if (skb != NULL) {
  15320. + skb_reserve(skb, 2);
  15321. + memcpy(skb_put(skb, pktlen), p_recv, pktlen);
  15322. +
  15323. + skb->dev = dev;
  15324. + skb->protocol = eth_type_trans(skb, dev);
  15325. + skb->len = pktlen;
  15326. + dev->last_rx = jiffies;
  15327. + lp->stats.rx_bytes += pktlen;
  15328. + netif_rx(skb);
  15329. + }
  15330. + else {
  15331. + lp->stats.rx_dropped += 1;
  15332. + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
  15333. + }
  15334. +
  15335. + if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
  15336. + lp->stats.multicast++;
  15337. +
  15338. + dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
  15339. + if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
  15340. + lp->rxBuffIndex = 0;
  15341. + else
  15342. + lp->rxBuffIndex++;
  15343. + }
  15344. +}
  15345. +
  15346. +/*
  15347. + * MAC interrupt handler
  15348. + */
  15349. +static void at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  15350. +{
  15351. + struct net_device *dev = (struct net_device *) dev_id;
  15352. + struct at91_private *lp = (struct at91_private *) dev->priv;
  15353. + AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
  15354. + unsigned long intstatus;
  15355. +
  15356. + /* MAC Interrupt Status register indicates what interrupts are pending.
  15357. + It is automatically cleared once read. */
  15358. + intstatus = emac->EMAC_ISR;
  15359. +
  15360. + if (intstatus & AT91C_EMAC_RCOM) /* Receive complete */
  15361. + at91ether_rx(dev);
  15362. +
  15363. + if (intstatus & AT91C_EMAC_TCOM) { /* Transmit complete */
  15364. + /* The TCOM bit is set even if the transmission failed. */
  15365. + if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY))
  15366. + lp->stats.tx_errors += 1;
  15367. +
  15368. + dev_kfree_skb_irq(lp->skb);
  15369. + pci_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, PCI_DMA_TODEVICE);
  15370. + netif_wake_queue(dev);
  15371. + }
  15372. +
  15373. + if (intstatus & AT91C_EMAC_RBNA)
  15374. + printk("%s: RBNA error\n", dev->name);
  15375. + if (intstatus & AT91C_EMAC_ROVR)
  15376. + printk("%s: ROVR error\n", dev->name);
  15377. +}
  15378. +
  15379. +/*
  15380. + * Initialize the ethernet interface
  15381. + */
  15382. +static int at91ether_setup(struct net_device *dev, unsigned long phy_type)
  15383. +{
  15384. + struct at91_private *lp;
  15385. + AT91PS_EMAC regs;
  15386. + static int already_initialized = 0;
  15387. + unsigned int val;
  15388. +
  15389. + if (already_initialized)
  15390. + return 0;
  15391. +
  15392. + dev = init_etherdev(dev, sizeof(struct at91_private));
  15393. + dev->base_addr = AT91C_VA_BASE_EMAC;
  15394. + dev->irq = AT91C_ID_EMAC;
  15395. + SET_MODULE_OWNER(dev);
  15396. +
  15397. + /* Install the interrupt handler */
  15398. + if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev))
  15399. + return -EBUSY;
  15400. +
  15401. + /* Allocate memory for private data structure */
  15402. + lp = (struct at91_private *) kmalloc(sizeof(struct at91_private), GFP_KERNEL);
  15403. + if (lp == NULL) {
  15404. + free_irq(dev->irq, dev);
  15405. + return -ENOMEM;
  15406. + }
  15407. + memset(lp, 0, sizeof(struct at91_private));
  15408. + dev->priv = lp;
  15409. +
  15410. + /* Allocate memory for DMA Receive descriptors */
  15411. + lp->dlist = (struct recv_desc_bufs *) consistent_alloc(GFP_DMA | GFP_KERNEL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys);
  15412. + if (lp->dlist == NULL) {
  15413. + kfree(dev->priv);
  15414. + free_irq(dev->irq, dev);
  15415. + return -ENOMEM;
  15416. + }
  15417. +
  15418. + spin_lock_init(&lp->lock);
  15419. +
  15420. + ether_setup(dev);
  15421. + dev->open = at91ether_open;
  15422. + dev->stop = at91ether_close;
  15423. + dev->hard_start_xmit = at91ether_tx;
  15424. + dev->get_stats = at91ether_stats;
  15425. + dev->set_multicast_list = at91ether_set_rx_mode;
  15426. + dev->do_ioctl = at91ether_ioctl;
  15427. +
  15428. +#ifdef AT91_ETHER_ADDR_CONFIGURABLE
  15429. + dev->set_mac_address = set_mac_address;
  15430. +#endif
  15431. +
  15432. + get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
  15433. + update_mac_address(dev); /* Program ethernet address into MAC */
  15434. +
  15435. + regs = (AT91PS_EMAC) dev->base_addr;
  15436. + regs->EMAC_CTL = 0;
  15437. +
  15438. +#ifdef CONFIG_AT91_ETHER_RMII
  15439. + regs->EMAC_CFG = AT91C_EMAC_BIG | AT91C_EMAC_RMII;
  15440. +#else
  15441. + regs->EMAC_CFG = AT91C_EMAC_BIG;
  15442. +#endif
  15443. + if (phy_type == MII_LXT971A_ID)
  15444. + regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; /* MDIO clock = system clock/64 */
  15445. +
  15446. + if (phy_type == MII_DM9161_ID) {
  15447. + spin_lock_irq(&lp->lock);
  15448. + enable_mdi(regs);
  15449. +
  15450. + read_phy(regs, 0, MII_DSCR_REG, &val);
  15451. + if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
  15452. + lp->phy_media = PORT_FIBRE;
  15453. +
  15454. + disable_mdi(regs);
  15455. + spin_unlock_irq(&lp->lock);
  15456. + }
  15457. +
  15458. + lp->mii.dev = dev; /* Support for ethtool */
  15459. + lp->mii.mdio_read = mdio_read;
  15460. + lp->mii.mdio_write = mdio_write;
  15461. +
  15462. + lp->phy_type = phy_type; /* Type of PHY connected */
  15463. +
  15464. + /* Determine current link speed */
  15465. + spin_lock_irq(&lp->lock);
  15466. + enable_mdi(regs);
  15467. + (void) update_linkspeed(dev, regs);
  15468. + disable_mdi(regs);
  15469. + spin_unlock_irq(&lp->lock);
  15470. +
  15471. + /* Display ethernet banner */
  15472. + printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
  15473. + dev->name, (uint) dev->base_addr, dev->irq,
  15474. + regs->EMAC_CFG & AT91C_EMAC_SPD ? "100-" : "10-",
  15475. + regs->EMAC_CFG & AT91C_EMAC_FD ? "FullDuplex" : "HalfDuplex",
  15476. + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
  15477. + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
  15478. + if (phy_type == MII_DM9161_ID)
  15479. + printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
  15480. + else if (phy_type == MII_LXT971A_ID)
  15481. + printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
  15482. +
  15483. + already_initialized = 1;
  15484. + return 0;
  15485. +}
  15486. +
  15487. +/*
  15488. + * Detect MAC and PHY and perform initialization
  15489. + */
  15490. +static int at91ether_probe(struct net_device *dev)
  15491. +{
  15492. + AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC;
  15493. + unsigned int phyid1, phyid2;
  15494. + int detected = -1;
  15495. +
  15496. + /* Configure the hardware - RMII vs MII mode */
  15497. +#ifdef CONFIG_AT91_ETHER_RMII
  15498. + AT91_CfgPIO_EMAC_RMII();
  15499. +#else
  15500. + AT91_CfgPIO_EMAC_MII();
  15501. +#endif
  15502. +
  15503. + AT91_CfgPIO_EMAC_PHY(); /* Configure PHY interrupt */
  15504. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Enable Peripheral clock */
  15505. +
  15506. + /* Read the PHY ID registers */
  15507. + enable_mdi(regs);
  15508. + read_phy(regs, 0, MII_PHYSID1, &phyid1);
  15509. + read_phy(regs, 0, MII_PHYSID2, &phyid2);
  15510. + disable_mdi(regs);
  15511. +
  15512. + /* Davicom 9161: PHY_ID1 = 0x181 PHY_ID2 = B881 */
  15513. + if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_DM9161_ID) {
  15514. + detected = at91ether_setup(dev, MII_DM9161_ID);
  15515. + }
  15516. + /* Intel LXT971A: PHY_ID1 = 0x13 PHY_ID2 = 78E0 */
  15517. + else if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) {
  15518. + detected = at91ether_setup(dev, MII_LXT971A_ID);
  15519. + }
  15520. +
  15521. + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
  15522. +
  15523. + return detected;
  15524. +}
  15525. +
  15526. +static int __init at91ether_init(void)
  15527. +{
  15528. + if (!at91ether_probe(&at91_dev))
  15529. + return register_netdev(&at91_dev);
  15530. +
  15531. + return -1;
  15532. +}
  15533. +
  15534. +static void __exit at91ether_exit(void)
  15535. +{
  15536. + unregister_netdev(&at91_dev);
  15537. +}
  15538. +
  15539. +module_init(at91ether_init)
  15540. +module_exit(at91ether_exit)
  15541. +
  15542. +MODULE_LICENSE("GPL");
  15543. +MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
  15544. +MODULE_AUTHOR("Andrew Victor");
  15545. diff -urN linux-2.4.26/drivers/at91/net/at91_ether.h linux-2.4.26-vrs1/drivers/at91/net/at91_ether.h
  15546. --- linux-2.4.26/drivers/at91/net/at91_ether.h 1970-01-01 01:00:00.000000000 +0100
  15547. +++ linux-2.4.26-vrs1/drivers/at91/net/at91_ether.h 2004-03-04 22:07:29.000000000 +0000
  15548. @@ -0,0 +1,81 @@
  15549. +/*
  15550. + * Ethernet driver for the Atmel AT91RM9200 (Thunder)
  15551. + *
  15552. + * (c) SAN People (Pty) Ltd
  15553. + *
  15554. + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
  15555. + * Initial version by Rick Bronson.
  15556. + *
  15557. + * This program is free software; you can redistribute it and/or
  15558. + * modify it under the terms of the GNU General Public License
  15559. + * as published by the Free Software Foundation; either version
  15560. + * 2 of the License, or (at your option) any later version.
  15561. + */
  15562. +
  15563. +#ifndef AT91_ETHERNET
  15564. +#define AT91_ETHERNET
  15565. +
  15566. +#undef AT91_ETHER_ADDR_CONFIGURABLE /* MAC address can be changed? */
  15567. +
  15568. +
  15569. +/* Davicom 9161 PHY */
  15570. +#define MII_DM9161_ID 0x0181b880
  15571. +
  15572. +/* Davicom specific registers */
  15573. +#define MII_DSCR_REG 16
  15574. +#define MII_DSCSR_REG 17
  15575. +#define MII_DSINTR_REG 21
  15576. +
  15577. +/* Intel LXT971A PHY */
  15578. +#define MII_LXT971A_ID 0x001378E0
  15579. +
  15580. +/* Intel specific registers */
  15581. +#define MII_ISINTE_REG 18
  15582. +#define MII_ISINTS_REG 19
  15583. +
  15584. +/* ........................................................................ */
  15585. +
  15586. +#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
  15587. +#define MAX_RX_DESCR 9 /* max number of receive buffers */
  15588. +
  15589. +#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
  15590. +#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
  15591. +
  15592. +#define EMAC_BROADCAST 0x80000000 /* broadcast address */
  15593. +#define EMAC_MULTICAST 0x40000000 /* multicast address */
  15594. +#define EMAC_UNICAST 0x20000000 /* unicast address */
  15595. +
  15596. +struct rbf_t
  15597. +{
  15598. + unsigned int addr;
  15599. + unsigned long size;
  15600. +};
  15601. +
  15602. +struct recv_desc_bufs
  15603. +{
  15604. + struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
  15605. + char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
  15606. +};
  15607. +
  15608. +struct at91_private
  15609. +{
  15610. + struct net_device_stats stats;
  15611. + struct mii_if_info mii; /* ethtool support */
  15612. +
  15613. + /* PHY */
  15614. + unsigned long phy_type; /* type of PHY (PHY_ID) */
  15615. + spinlock_t lock; /* lock for MDI interface */
  15616. + short phy_media; /* media interface type */
  15617. +
  15618. + /* Transmit */
  15619. + struct sk_buff *skb; /* holds skb until xmit interrupt completes */
  15620. + dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
  15621. + int skb_length; /* saved skb length for pci_unmap_single */
  15622. +
  15623. + /* Receive */
  15624. + int rxBuffIndex; /* index into receive descriptor list */
  15625. + struct recv_desc_bufs *dlist; /* descriptor list address */
  15626. + struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
  15627. +};
  15628. +
  15629. +#endif
  15630. diff -urN linux-2.4.26/drivers/at91/rtc/Makefile linux-2.4.26-vrs1/drivers/at91/rtc/Makefile
  15631. --- linux-2.4.26/drivers/at91/rtc/Makefile 1970-01-01 01:00:00.000000000 +0100
  15632. +++ linux-2.4.26-vrs1/drivers/at91/rtc/Makefile 2004-01-14 21:32:25.000000000 +0000
  15633. @@ -0,0 +1,15 @@
  15634. +# File: drivers/at91/rtc/Makefile
  15635. +#
  15636. +# Makefile for the Atmel AT91RM9200 real time clock device drivers
  15637. +#
  15638. +
  15639. +O_TARGET := at91rtc.o
  15640. +
  15641. +obj-y :=
  15642. +obj-m :=
  15643. +obj-n :=
  15644. +obj- :=
  15645. +
  15646. +obj-$(CONFIG_AT91_RTC) += at91_rtc.o
  15647. +
  15648. +include $(TOPDIR)/Rules.make
  15649. diff -urN linux-2.4.26/drivers/at91/rtc/at91_rtc.c linux-2.4.26-vrs1/drivers/at91/rtc/at91_rtc.c
  15650. --- linux-2.4.26/drivers/at91/rtc/at91_rtc.c 1970-01-01 01:00:00.000000000 +0100
  15651. +++ linux-2.4.26-vrs1/drivers/at91/rtc/at91_rtc.c 2004-03-04 22:31:24.000000000 +0000
  15652. @@ -0,0 +1,441 @@
  15653. +/*
  15654. + * Real Time Clock interface for Linux on Atmel AT91RM9200
  15655. + *
  15656. + * Copyright (c) 2002 Rick Bronson
  15657. + *
  15658. + * Based on sa1100-rtc.c by Nils Faerber
  15659. + * Based on rtc.c by Paul Gortmaker
  15660. + * Date/time conversion routines taken from arch/arm/kernel/time.c
  15661. + * by Linus Torvalds and Russell King
  15662. + * and the GNU C Library
  15663. + * ( ... I love the GPL ... just take what you need! ;)
  15664. + *
  15665. + * This program is free software; you can redistribute it and/or
  15666. + * modify it under the terms of the GNU General Public License
  15667. + * as published by the Free Software Foundation; either version
  15668. + * 2 of the License, or (at your option) any later version.
  15669. + *
  15670. + */
  15671. +
  15672. +#include <linux/module.h>
  15673. +#include <linux/fs.h>
  15674. +#include <linux/miscdevice.h>
  15675. +#include <linux/string.h>
  15676. +#include <linux/init.h>
  15677. +#include <linux/poll.h>
  15678. +#include <linux/proc_fs.h>
  15679. +#include <asm/bitops.h>
  15680. +#include <asm/hardware.h>
  15681. +#include <asm/irq.h>
  15682. +#include <linux/rtc.h>
  15683. +
  15684. +#define AT91_RTC_FREQ 1
  15685. +#define EPOCH 1970
  15686. +
  15687. +/* Those are the bits from a classic RTC we want to mimic */
  15688. +#define AT91_RTC_IRQF 0x80 /* any of the following 3 is active */
  15689. +#define AT91_RTC_PF 0x40
  15690. +#define AT91_RTC_AF 0x20
  15691. +#define AT91_RTC_UF 0x10
  15692. +
  15693. +#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
  15694. +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
  15695. +
  15696. +static unsigned long rtc_status = 0;
  15697. +static unsigned long rtc_irq_data;
  15698. +static unsigned int at91_alarm_year = EPOCH;
  15699. +
  15700. +static struct fasync_struct *at91_rtc_async_queue;
  15701. +static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait);
  15702. +static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_update);
  15703. +static spinlock_t at91_rtc_updlock; /* some spinlocks for saving/restoring interrupt levels */
  15704. +extern spinlock_t at91_rtc_lock;
  15705. +
  15706. +static const unsigned char days_in_mo[] =
  15707. + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  15708. +
  15709. +#define is_leap(year) \
  15710. + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  15711. +
  15712. +static const unsigned short int __mon_yday[2][13] =
  15713. +{
  15714. + /* Normal years. */
  15715. + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  15716. + /* Leap years. */
  15717. + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  15718. +};
  15719. +
  15720. +/*
  15721. + * Returns day since start of the year [0-365]
  15722. + * (from drivers/char/efirtc.c)
  15723. + */
  15724. +static inline int compute_yday(int year, int month, int day)
  15725. +{
  15726. + return __mon_yday[is_leap(year)][month] + day-1;
  15727. +}
  15728. +
  15729. +/*
  15730. + * Set current time and date in RTC
  15731. + */
  15732. +static void at91_rtc_settime(struct rtc_time *tval)
  15733. +{
  15734. + unsigned long flags;
  15735. +
  15736. + /* Stop Time/Calendar from counting */
  15737. + AT91_SYS->RTC_CR |= (AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
  15738. +
  15739. + spin_lock_irqsave(&at91_rtc_updlock, flags); /* stop int's else we wakeup b4 we sleep */
  15740. + AT91_SYS->RTC_IER = AT91C_RTC_ACKUPD;
  15741. + interruptible_sleep_on(&at91_rtc_update); /* wait for ACKUPD interrupt to hit */
  15742. + spin_unlock_irqrestore(&at91_rtc_updlock, flags);
  15743. + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD;
  15744. +
  15745. + AT91_SYS->RTC_TIMR = BIN2BCD(tval->tm_sec) << 0
  15746. + | BIN2BCD(tval->tm_min) << 8
  15747. + | BIN2BCD(tval->tm_hour) << 16;
  15748. +
  15749. + AT91_SYS->RTC_CALR = BIN2BCD((tval->tm_year + 1900) / 100) /* century */
  15750. + | BIN2BCD(tval->tm_year % 100) << 8 /* year */
  15751. + | BIN2BCD(tval->tm_mon + 1) << 16 /* tm_mon starts at zero */
  15752. + | BIN2BCD(tval->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
  15753. + | BIN2BCD(tval->tm_mday) << 24;
  15754. +
  15755. + /* Restart Time/Calendar */
  15756. + AT91_SYS->RTC_CR &= ~(AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
  15757. +}
  15758. +
  15759. +/*
  15760. + * Decode time/date into rtc_time structure
  15761. + */
  15762. +static void at91_rtc_decodetime(AT91_REG *timereg, AT91_REG *calreg, struct rtc_time *tval)
  15763. +{
  15764. + unsigned int time, date;
  15765. +
  15766. + do { /* must read twice in case it changes */
  15767. + time = *timereg;
  15768. + date = *calreg;
  15769. + } while ((time != *timereg) || (date != *calreg));
  15770. +
  15771. + tval->tm_sec = BCD2BIN((time & AT91C_RTC_SEC) >> 0);
  15772. + tval->tm_min = BCD2BIN((time & AT91C_RTC_MIN) >> 8);
  15773. + tval->tm_hour = BCD2BIN((time & AT91C_RTC_HOUR) >> 16);
  15774. +
  15775. + /* The Calendar Alarm register does not have a field for
  15776. + the year - so these will return an invalid value. When an
  15777. + alarm is set, at91_alarm_year wille store the current year. */
  15778. + tval->tm_year = BCD2BIN(date & AT91C_RTC_CENT) * 100; /* century */
  15779. + tval->tm_year += BCD2BIN((date & AT91C_RTC_YEAR) >> 8); /* year */
  15780. +
  15781. + tval->tm_wday = BCD2BIN((date & AT91C_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
  15782. + tval->tm_mon = BCD2BIN(((date & AT91C_RTC_MONTH) >> 16) - 1);
  15783. + tval->tm_mday = BCD2BIN((date & AT91C_RTC_DATE) >> 24);
  15784. +}
  15785. +
  15786. +/*
  15787. + * IRQ handler for the RTC
  15788. + */
  15789. +static void at91_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  15790. +{
  15791. + unsigned int rtsr = AT91_SYS->RTC_SR & AT91_SYS->RTC_IMR;
  15792. +
  15793. + /* update irq data & counter */
  15794. + if (rtsr) { /* this interrupt is shared! Is it ours? */
  15795. + if (rtsr & AT91C_RTC_ALARM)
  15796. + rtc_irq_data |= (AT91_RTC_AF | AT91_RTC_IRQF);
  15797. + if (rtsr & AT91C_RTC_SECEV)
  15798. + rtc_irq_data |= (AT91_RTC_UF | AT91_RTC_IRQF);
  15799. + if (rtsr & AT91C_RTC_ACKUPD)
  15800. + wake_up_interruptible(&at91_rtc_update);
  15801. + rtc_irq_data += 0x100;
  15802. + AT91_SYS->RTC_SCCR = rtsr; /* clear status reg */
  15803. +
  15804. + /* wake up waiting process */
  15805. + wake_up_interruptible(&at91_rtc_wait);
  15806. + kill_fasync(&at91_rtc_async_queue, SIGIO, POLL_IN);
  15807. + }
  15808. +}
  15809. +
  15810. +static int at91_rtc_open(struct inode *inode, struct file *file)
  15811. +{
  15812. + if (test_and_set_bit(1, &rtc_status))
  15813. + return -EBUSY;
  15814. + rtc_irq_data = 0;
  15815. + return 0;
  15816. +}
  15817. +
  15818. +static int at91_rtc_release(struct inode *inode, struct file *file)
  15819. +{
  15820. + rtc_status = 0;
  15821. + return 0;
  15822. +}
  15823. +
  15824. +static int at91_rtc_fasync(int fd, struct file *filp, int on)
  15825. +{
  15826. + return fasync_helper(fd, filp, on, &at91_rtc_async_queue);
  15827. +}
  15828. +
  15829. +static unsigned int at91_rtc_poll(struct file *file, poll_table * wait)
  15830. +{
  15831. + poll_wait(file, &at91_rtc_wait, wait);
  15832. + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
  15833. +}
  15834. +
  15835. +static ssize_t at91_rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
  15836. +{
  15837. + DECLARE_WAITQUEUE(wait, current);
  15838. + unsigned long data;
  15839. + ssize_t retval;
  15840. +
  15841. + if (count < sizeof(unsigned long))
  15842. + return -EINVAL;
  15843. +
  15844. + add_wait_queue(&at91_rtc_wait, &wait);
  15845. + set_current_state(TASK_INTERRUPTIBLE);
  15846. + for (;;) {
  15847. + spin_lock_irq(&at91_rtc_lock);
  15848. + data = rtc_irq_data;
  15849. + if (data != 0) {
  15850. + rtc_irq_data = 0;
  15851. + break;
  15852. + }
  15853. + spin_unlock_irq(&at91_rtc_lock);
  15854. +
  15855. + if (file->f_flags & O_NONBLOCK) {
  15856. + retval = -EAGAIN;
  15857. + goto out;
  15858. + }
  15859. +
  15860. + if (signal_pending(current)) {
  15861. + retval = -ERESTARTSYS;
  15862. + goto out;
  15863. + }
  15864. +
  15865. + schedule();
  15866. + }
  15867. + spin_unlock_irq(&at91_rtc_lock);
  15868. +
  15869. + data -= 0x100; /* the first IRQ wasn't actually missed */
  15870. + retval = put_user(data, (unsigned long *) buf);
  15871. + if (!retval)
  15872. + retval = sizeof(unsigned long);
  15873. +
  15874. +out:
  15875. + set_current_state(TASK_RUNNING);
  15876. + remove_wait_queue(&at91_rtc_wait, &wait);
  15877. + return retval;
  15878. +}
  15879. +
  15880. +/*
  15881. + * Handle commands from user-space
  15882. + */
  15883. +static int at91_rtc_ioctl(struct inode *inode, struct file *file,
  15884. + unsigned int cmd, unsigned long arg)
  15885. +{
  15886. + struct rtc_time tm, tm2;
  15887. + int ret = 0;
  15888. +
  15889. + spin_lock_irq(&at91_rtc_lock);
  15890. + switch (cmd) {
  15891. + case RTC_AIE_OFF: /* alarm off */
  15892. + AT91_SYS->RTC_IDR = AT91C_RTC_ALARM;
  15893. + rtc_irq_data = 0;
  15894. + break;
  15895. + case RTC_AIE_ON: /* alarm on */
  15896. + AT91_SYS->RTC_IER = AT91C_RTC_ALARM;
  15897. + rtc_irq_data = 0;
  15898. + break;
  15899. + case RTC_UIE_OFF: /* update off */
  15900. + AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
  15901. + rtc_irq_data = 0;
  15902. + break;
  15903. + case RTC_UIE_ON: /* update on */
  15904. + AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
  15905. + rtc_irq_data = 0;
  15906. + break;
  15907. + case RTC_PIE_OFF: /* periodic off */
  15908. + AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
  15909. + rtc_irq_data = 0;
  15910. + break;
  15911. + case RTC_PIE_ON: /* periodic on */
  15912. + AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
  15913. + rtc_irq_data = 0;
  15914. + break;
  15915. + case RTC_ALM_READ: /* read alarm */
  15916. + memset(&tm, 0, sizeof(struct rtc_time));
  15917. + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
  15918. + tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
  15919. + tm.tm_year = at91_alarm_year - 1900;
  15920. + ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
  15921. + break;
  15922. + case RTC_ALM_SET: /* set alarm */
  15923. + if (copy_from_user(&tm2, (struct rtc_time *) arg, sizeof(tm2)))
  15924. + ret = -EFAULT;
  15925. + else {
  15926. + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
  15927. + at91_alarm_year = tm.tm_year;
  15928. + if ((unsigned) tm2.tm_hour < 24) /* do some range checking */
  15929. + tm.tm_hour = tm2.tm_hour;
  15930. + if ((unsigned) tm2.tm_min < 60)
  15931. + tm.tm_min = tm2.tm_min;
  15932. + if ((unsigned) tm2.tm_sec < 60)
  15933. + tm.tm_sec = tm2.tm_sec;
  15934. + AT91_SYS->RTC_TIMALR = BIN2BCD(tm.tm_sec) << 0
  15935. + | BIN2BCD(tm.tm_min) << 8
  15936. + | BIN2BCD(tm.tm_hour) << 16
  15937. + | AT91C_RTC_HOUREN | AT91C_RTC_MINEN
  15938. + | AT91C_RTC_SECEN;
  15939. + AT91_SYS->RTC_CALALR = BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
  15940. + | BIN2BCD(tm.tm_mday) << 24
  15941. + | AT91C_RTC_DATEEN | AT91C_RTC_MONTHEN;
  15942. + }
  15943. + break;
  15944. + case RTC_RD_TIME: /* read time */
  15945. + memset(&tm, 0, sizeof(struct rtc_time));
  15946. + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
  15947. + tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
  15948. + tm.tm_year = tm.tm_year - 1900;
  15949. + ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
  15950. + break;
  15951. + case RTC_SET_TIME: /* set time */
  15952. + if (!capable(CAP_SYS_TIME))
  15953. + ret = -EACCES;
  15954. + else {
  15955. + if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(tm)))
  15956. + ret = -EFAULT;
  15957. + else {
  15958. + int tm_year = tm.tm_year + 1900;
  15959. + if (tm_year < EPOCH
  15960. + || (unsigned) tm.tm_mon >= 12
  15961. + || tm.tm_mday < 1
  15962. + || tm.tm_mday > (days_in_mo[tm.tm_mon] + (tm.tm_mon == 1 && is_leap(tm_year)))
  15963. + || (unsigned) tm.tm_hour >= 24
  15964. + || (unsigned) tm.tm_min >= 60
  15965. + || (unsigned) tm.tm_sec >= 60)
  15966. + ret = -EINVAL;
  15967. + else
  15968. + at91_rtc_settime(&tm);
  15969. + }
  15970. + }
  15971. + break;
  15972. + case RTC_IRQP_READ: /* read periodic alarm frequency */
  15973. + ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
  15974. + break;
  15975. + case RTC_IRQP_SET: /* set periodic alarm frequency */
  15976. + if (arg != AT91_RTC_FREQ)
  15977. + ret = -EINVAL;
  15978. + break;
  15979. + case RTC_EPOCH_READ: /* read epoch */
  15980. + ret = put_user(EPOCH, (unsigned long *) arg);
  15981. + break;
  15982. + default:
  15983. + ret = -EINVAL;
  15984. + break;
  15985. + }
  15986. + spin_unlock_irq(&at91_rtc_lock);
  15987. + return ret;
  15988. +}
  15989. +
  15990. +/*
  15991. + * Provide RTC information in /proc/driver/rtc
  15992. + */
  15993. +static int at91_rtc_read_proc(char *page, char **start, off_t off,
  15994. + int count, int *eof, void *data)
  15995. +{
  15996. + char *p = page;
  15997. + int len;
  15998. + struct rtc_time tm;
  15999. +
  16000. + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
  16001. + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
  16002. + "rtc_date\t: %04d-%02d-%02d\n"
  16003. + "rtc_epoch\t: %04d\n",
  16004. + tm.tm_hour, tm.tm_min, tm.tm_sec,
  16005. + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, EPOCH);
  16006. + at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
  16007. + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
  16008. + "alrm_date\t: %04d-%02d-%02d\n",
  16009. + tm.tm_hour, tm.tm_min, tm.tm_sec,
  16010. + at91_alarm_year, tm.tm_mon + 1, tm.tm_mday);
  16011. + p += sprintf(p, "alarm_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ALARM) ? "yes" : "no");
  16012. + p += sprintf(p, "update_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ACKUPD) ? "yes" : "no");
  16013. + p += sprintf(p, "periodic_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_SECEV) ? "yes" : "no");
  16014. + p += sprintf(p, "periodic_freq\t: %ld\n", (unsigned long) AT91_RTC_FREQ);
  16015. +
  16016. + len = (p - page) - off;
  16017. + if (len < 0)
  16018. + len = 0;
  16019. +
  16020. + *eof = (len <= count) ? 1 : 0;
  16021. + *start = page + off;
  16022. +
  16023. + return len;
  16024. +}
  16025. +
  16026. +static struct file_operations at91_rtc_fops = {
  16027. + owner:THIS_MODULE,
  16028. + llseek:no_llseek,
  16029. + read:at91_rtc_read,
  16030. + poll:at91_rtc_poll,
  16031. + ioctl:at91_rtc_ioctl,
  16032. + open:at91_rtc_open,
  16033. + release:at91_rtc_release,
  16034. + fasync:at91_rtc_fasync,
  16035. +};
  16036. +
  16037. +static struct miscdevice at91_rtc_miscdev = {
  16038. + minor:RTC_MINOR,
  16039. + name:"rtc",
  16040. + fops:&at91_rtc_fops,
  16041. +};
  16042. +
  16043. +/*
  16044. + * Initialize and install RTC driver
  16045. + */
  16046. +static int __init at91_rtc_init(void)
  16047. +{
  16048. + int ret;
  16049. +
  16050. + AT91_SYS->RTC_CR = 0;
  16051. + AT91_SYS->RTC_MR = 0; /* put in 24 hour format */
  16052. + /* Disable all interrupts */
  16053. + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
  16054. +
  16055. + spin_lock_init(&at91_rtc_updlock);
  16056. + spin_lock_init(&at91_rtc_lock);
  16057. +
  16058. + misc_register(&at91_rtc_miscdev);
  16059. + create_proc_read_entry("driver/rtc", 0, 0, at91_rtc_read_proc, NULL);
  16060. + ret = request_irq(AT91C_ID_SYS, at91_rtc_interrupt, SA_SHIRQ,
  16061. + "at91_rtc", &rtc_status);
  16062. + if (ret) {
  16063. + printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91C_ID_SYS);
  16064. + remove_proc_entry("driver/rtc", NULL);
  16065. + misc_deregister(&at91_rtc_miscdev);
  16066. + return ret;
  16067. + }
  16068. +
  16069. + printk(KERN_INFO "AT91 Real Time Clock driver\n");
  16070. + return 0;
  16071. +}
  16072. +
  16073. +/*
  16074. + * Disable and remove the RTC driver
  16075. + */
  16076. +static void __exit at91_rtc_exit(void)
  16077. +{
  16078. + /* Disable all interrupts */
  16079. + AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
  16080. + free_irq(AT91C_ID_SYS, &rtc_status);
  16081. +
  16082. + rtc_status = 0;
  16083. + remove_proc_entry("driver/rtc", NULL);
  16084. + misc_deregister(&at91_rtc_miscdev);
  16085. +}
  16086. +
  16087. +module_init(at91_rtc_init);
  16088. +module_exit(at91_rtc_exit);
  16089. +
  16090. +MODULE_AUTHOR("Rick Bronson");
  16091. +MODULE_DESCRIPTION("AT91 Realtime Clock Driver (AT91_RTC)");
  16092. +MODULE_LICENSE("GPL");
  16093. +EXPORT_NO_SYMBOLS;
  16094. diff -urN linux-2.4.26/drivers/at91/serial/Makefile linux-2.4.26-vrs1/drivers/at91/serial/Makefile
  16095. --- linux-2.4.26/drivers/at91/serial/Makefile 1970-01-01 01:00:00.000000000 +0100
  16096. +++ linux-2.4.26-vrs1/drivers/at91/serial/Makefile 2004-01-14 21:32:25.000000000 +0000
  16097. @@ -0,0 +1,15 @@
  16098. +# File: drivers/at91/serial/Makefile
  16099. +#
  16100. +# Makefile for the Atmel AT91RM9200 serial and console device drivers
  16101. +#
  16102. +
  16103. +O_TARGET := at91serial.o
  16104. +
  16105. +obj-y :=
  16106. +obj-m :=
  16107. +obj-n :=
  16108. +obj- :=
  16109. +
  16110. +obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
  16111. +
  16112. +include $(TOPDIR)/Rules.make
  16113. diff -urN linux-2.4.26/drivers/at91/serial/at91_serial.c linux-2.4.26-vrs1/drivers/at91/serial/at91_serial.c
  16114. --- linux-2.4.26/drivers/at91/serial/at91_serial.c 1970-01-01 01:00:00.000000000 +0100
  16115. +++ linux-2.4.26-vrs1/drivers/at91/serial/at91_serial.c 2004-04-09 15:12:35.000000000 +0100
  16116. @@ -0,0 +1,870 @@
  16117. +/*
  16118. + * linux/drivers/char/at91_serial.c
  16119. + *
  16120. + * Driver for Atmel AT91RM9200 Serial ports
  16121. + *
  16122. + * Copyright (c) Rick Bronson
  16123. + *
  16124. + * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
  16125. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  16126. + *
  16127. + * This program is free software; you can redistribute it and/or modify
  16128. + * it under the terms of the GNU General Public License as published by
  16129. + * the Free Software Foundation; either version 2 of the License, or
  16130. + * (at your option) any later version.
  16131. + *
  16132. + * This program is distributed in the hope that it will be useful,
  16133. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16134. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16135. + * GNU General Public License for more details.
  16136. + *
  16137. + * You should have received a copy of the GNU General Public License
  16138. + * along with this program; if not, write to the Free Software
  16139. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16140. + *
  16141. + */
  16142. +#include <linux/config.h>
  16143. +#include <linux/module.h>
  16144. +#include <linux/tty.h>
  16145. +#include <linux/ioport.h>
  16146. +#include <linux/slab.h>
  16147. +#include <linux/init.h>
  16148. +#include <linux/serial.h>
  16149. +#include <linux/console.h>
  16150. +#include <linux/sysrq.h>
  16151. +
  16152. +#include <asm/arch/AT91RM9200_USART.h>
  16153. +#include <asm/mach/serial_at91rm9200.h>
  16154. +#include <asm/arch/pio.h>
  16155. +
  16156. +
  16157. +#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  16158. +#define SUPPORT_SYSRQ
  16159. +#endif
  16160. +
  16161. +#include <linux/serial_core.h>
  16162. +
  16163. +#define SERIAL_AT91_MAJOR TTY_MAJOR
  16164. +#define CALLOUT_AT91_MAJOR TTYAUX_MAJOR
  16165. +#define MINOR_START 64
  16166. +
  16167. +#define AT91C_VA_BASE_DBGU ((unsigned long) &(AT91_SYS->DBGU_CR))
  16168. +#define AT91_ISR_PASS_LIMIT 256
  16169. +
  16170. +#define UART_PUT_CR(port,v) ((AT91PS_USART)(port)->membase)->US_CR = v
  16171. +#define UART_GET_MR(port) ((AT91PS_USART)(port)->membase)->US_MR
  16172. +#define UART_PUT_MR(port,v) ((AT91PS_USART)(port)->membase)->US_MR = v
  16173. +#define UART_PUT_IER(port,v) ((AT91PS_USART)(port)->membase)->US_IER = v
  16174. +#define UART_PUT_IDR(port,v) ((AT91PS_USART)(port)->membase)->US_IDR = v
  16175. +#define UART_GET_IMR(port) ((AT91PS_USART)(port)->membase)->US_IMR
  16176. +#define UART_GET_CSR(port) ((AT91PS_USART)(port)->membase)->US_CSR
  16177. +#define UART_GET_CHAR(port) ((AT91PS_USART)(port)->membase)->US_RHR
  16178. +#define UART_PUT_CHAR(port,v) ((AT91PS_USART)(port)->membase)->US_THR = v
  16179. +#define UART_GET_BRGR(port) ((AT91PS_USART)(port)->membase)->US_BRGR
  16180. +#define UART_PUT_BRGR(port,v) ((AT91PS_USART)(port)->membase)->US_BRGR = v
  16181. +#define UART_PUT_RTOR(port,v) ((AT91PS_USART)(port)->membase)->US_RTOR = v
  16182. +
  16183. +// #define UART_GET_CR(port) ((AT91PS_USART)(port)->membase)->US_CR // is write-only
  16184. +
  16185. + /* PDC registers */
  16186. +#define UART_PUT_PTCR(port,v) ((AT91PS_USART)(port)->membase)->US_PTCR = v
  16187. +#define UART_PUT_RPR(port,v) ((AT91PS_USART)(port)->membase)->US_RPR = v
  16188. +#define UART_PUT_RCR(port,v) ((AT91PS_USART)(port)->membase)->US_RCR = v
  16189. +#define UART_GET_RCR(port) ((AT91PS_USART)(port)->membase)->US_RCR
  16190. +#define UART_PUT_RNPR(port,v) ((AT91PS_USART)(port)->membase)->US_RNPR = v
  16191. +#define UART_PUT_RNCR(port,v) ((AT91PS_USART)(port)->membase)->US_RNCR = v
  16192. +
  16193. +static struct tty_driver normal, callout;
  16194. +static struct tty_struct *at91_table[AT91C_NR_UART];
  16195. +static struct termios *at91_termios[AT91C_NR_UART], *at91_termios_locked[AT91C_NR_UART];
  16196. +
  16197. +const int at91_serialmap[AT91C_NR_UART] = AT91C_UART_MAP;
  16198. +
  16199. +static int (*at91_open)(struct uart_port *);
  16200. +static void (*at91_close)(struct uart_port *);
  16201. +
  16202. +#ifdef SUPPORT_SYSRQ
  16203. +static struct console at91_console;
  16204. +#endif
  16205. +
  16206. +/*
  16207. + * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
  16208. + */
  16209. +static u_int at91_tx_empty(struct uart_port *port)
  16210. +{
  16211. + return UART_GET_CSR(port) & AT91C_US_TXEMPTY ? TIOCSER_TEMT : 0;
  16212. +}
  16213. +
  16214. +/*
  16215. + * Set state of the modem control output lines
  16216. + */
  16217. +static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
  16218. +{
  16219. + unsigned int control = 0;
  16220. +
  16221. + if (mctrl & TIOCM_RTS)
  16222. + control |= AT91C_US_RTSEN;
  16223. + else
  16224. + control |= AT91C_US_RTSDIS;
  16225. +
  16226. + if (mctrl & TIOCM_DTR)
  16227. + control |= AT91C_US_DTREN;
  16228. + else
  16229. + control |= AT91C_US_DTRDIS;
  16230. +
  16231. + UART_PUT_CR(port,control);
  16232. +}
  16233. +
  16234. +/*
  16235. + * Get state of the modem control input lines
  16236. + */
  16237. +static u_int at91_get_mctrl(struct uart_port *port)
  16238. +{
  16239. + unsigned int status, ret = 0;
  16240. +
  16241. + status = UART_GET_CSR(port);
  16242. + if (status & AT91C_US_DCD)
  16243. + ret |= TIOCM_CD;
  16244. + if (status & AT91C_US_CTS)
  16245. + ret |= TIOCM_CTS;
  16246. + if (status & AT91C_US_DSR)
  16247. + ret |= TIOCM_DSR;
  16248. + if (status & AT91C_US_RI)
  16249. + ret |= TIOCM_RI;
  16250. +
  16251. + return ret;
  16252. +}
  16253. +
  16254. +/*
  16255. + * Stop transmitting.
  16256. + */
  16257. +static void at91_stop_tx(struct uart_port *port, u_int from_tty)
  16258. +{
  16259. + UART_PUT_IDR(port, AT91C_US_TXRDY);
  16260. + port->read_status_mask &= ~AT91C_US_TXRDY;
  16261. +}
  16262. +
  16263. +/*
  16264. + * Start transmitting.
  16265. + */
  16266. +static void at91_start_tx(struct uart_port *port, u_int from_tty)
  16267. +{
  16268. + unsigned long flags;
  16269. +
  16270. + local_irq_save(flags);
  16271. + port->read_status_mask |= AT91C_US_TXRDY;
  16272. + UART_PUT_IER(port, AT91C_US_TXRDY);
  16273. + local_irq_restore(flags);
  16274. +}
  16275. +
  16276. +/*
  16277. + * Stop receiving - port is in process of being closed.
  16278. + */
  16279. +static void at91_stop_rx(struct uart_port *port)
  16280. +{
  16281. + UART_PUT_IDR(port, AT91C_US_RXRDY);
  16282. +}
  16283. +
  16284. +/*
  16285. + * Enable modem status interrupts
  16286. + */
  16287. +static void at91_enable_ms(struct uart_port *port)
  16288. +{
  16289. + UART_PUT_IER(port, AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC);
  16290. +}
  16291. +
  16292. +/*
  16293. + * Control the transmission of a break signal
  16294. + */
  16295. +static void at91_break_ctl(struct uart_port *port, int break_state)
  16296. +{
  16297. + if (break_state != 0)
  16298. + UART_PUT_CR(port, AT91C_US_STTBRK); /* start break */
  16299. + else
  16300. + UART_PUT_CR(port, AT91C_US_STPBRK); /* stop break */
  16301. +}
  16302. +
  16303. +/*
  16304. + * Characters received (called from interrupt handler)
  16305. + */
  16306. +static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
  16307. +{
  16308. + struct uart_info *info = port->info;
  16309. + struct tty_struct *tty = info->tty;
  16310. + unsigned int status, ch, flg, ignored = 0;
  16311. +
  16312. + status = UART_GET_CSR(port);
  16313. + while (status & (AT91C_US_RXRDY)) {
  16314. + ch = UART_GET_CHAR(port);
  16315. +
  16316. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  16317. + goto ignore_char;
  16318. + port->icount.rx++;
  16319. +
  16320. + flg = TTY_NORMAL;
  16321. +
  16322. + /*
  16323. + * note that the error handling code is
  16324. + * out of the main execution path
  16325. + */
  16326. + if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
  16327. + goto handle_error;
  16328. +
  16329. + if (uart_handle_sysrq_char(port, ch, regs))
  16330. + goto ignore_char;
  16331. +
  16332. + error_return:
  16333. + *tty->flip.flag_buf_ptr++ = flg;
  16334. + *tty->flip.char_buf_ptr++ = ch;
  16335. + tty->flip.count++;
  16336. + ignore_char:
  16337. + status = UART_GET_CSR(port);
  16338. + }
  16339. +out:
  16340. + tty_flip_buffer_push(tty);
  16341. + return;
  16342. +
  16343. +handle_error:
  16344. + if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
  16345. + UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
  16346. + if (status & (AT91C_US_PARE))
  16347. + port->icount.parity++;
  16348. + else if (status & (AT91C_US_FRAME))
  16349. + port->icount.frame++;
  16350. + if (status & (AT91C_US_OVRE))
  16351. + port->icount.overrun++;
  16352. +
  16353. + if (status & port->ignore_status_mask) {
  16354. + if (++ignored > 100)
  16355. + goto out;
  16356. + goto ignore_char;
  16357. + }
  16358. +
  16359. + status &= port->read_status_mask;
  16360. +
  16361. + UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
  16362. + if (status & AT91C_US_PARE)
  16363. + flg = TTY_PARITY;
  16364. + else if (status & AT91C_US_FRAME)
  16365. + flg = TTY_FRAME;
  16366. +
  16367. + if (status & AT91C_US_OVRE) {
  16368. + /*
  16369. + * overrun does *not* affect the character
  16370. + * we read from the FIFO
  16371. + */
  16372. + *tty->flip.flag_buf_ptr++ = flg;
  16373. + *tty->flip.char_buf_ptr++ = ch;
  16374. + tty->flip.count++;
  16375. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  16376. + goto ignore_char;
  16377. + ch = 0;
  16378. + flg = TTY_OVERRUN;
  16379. + }
  16380. +#ifdef SUPPORT_SYSRQ
  16381. + port->sysrq = 0;
  16382. +#endif
  16383. + goto error_return;
  16384. +}
  16385. +
  16386. +/*
  16387. + * Transmit characters (called from interrupt handler)
  16388. + */
  16389. +static void at91_tx_chars(struct uart_port *port)
  16390. +{
  16391. + struct circ_buf *xmit = &port->info->xmit;
  16392. +
  16393. + if (port->x_char) {
  16394. + UART_PUT_CHAR(port, port->x_char);
  16395. + port->icount.tx++;
  16396. + port->x_char = 0;
  16397. + return;
  16398. + }
  16399. + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  16400. + at91_stop_tx(port, 0);
  16401. + return;
  16402. + }
  16403. +
  16404. + while (UART_GET_CSR(port) & AT91C_US_TXRDY) {
  16405. + UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
  16406. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  16407. + port->icount.tx++;
  16408. + if (uart_circ_empty(xmit))
  16409. + break;
  16410. + }
  16411. +
  16412. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  16413. + uart_write_wakeup(port);
  16414. +
  16415. + if (uart_circ_empty(xmit))
  16416. + at91_stop_tx(port, 0);
  16417. +}
  16418. +
  16419. +/*
  16420. + * Interrupt handler
  16421. + */
  16422. +static void at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  16423. +{
  16424. + struct uart_port *port = dev_id;
  16425. + unsigned int status, pending, pass_counter = 0;
  16426. +
  16427. + status = UART_GET_CSR(port);
  16428. + pending = status & port->read_status_mask;
  16429. + if (pending) {
  16430. + do {
  16431. + if (pending & AT91C_US_RXRDY)
  16432. + at91_rx_chars(port, regs);
  16433. +
  16434. + /* Clear the relevent break bits */
  16435. + if (pending & AT91C_US_RXBRK) {
  16436. + UART_PUT_CR(port, AT91C_US_RSTSTA);
  16437. + port->icount.brk++;
  16438. +#ifdef SUPPORT_SYSRQ
  16439. + if (port->line == at91_console.index && !port->sysrq) {
  16440. + port->sysrq = jiffies + HZ*5;
  16441. + }
  16442. +#endif
  16443. + }
  16444. +
  16445. + // TODO: All reads to CSR will clear these interrupts!
  16446. + if (pending & AT91C_US_RIIC) port->icount.rng++;
  16447. + if (pending & AT91C_US_DSRIC) port->icount.dsr++;
  16448. + if (pending & AT91C_US_DCDIC) {
  16449. + port->icount.dcd++;
  16450. + uart_handle_dcd_change(port, status & AT91C_US_DCD);
  16451. + }
  16452. + if (pending & AT91C_US_CTSIC) {
  16453. + port->icount.cts++;
  16454. + uart_handle_cts_change(port, status & AT91C_US_CTS);
  16455. + }
  16456. + if (pending & (AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC))
  16457. + wake_up_interruptible(&port->info->delta_msr_wait);
  16458. +
  16459. + if (pending & AT91C_US_TXRDY)
  16460. + at91_tx_chars(port);
  16461. + if (pass_counter++ > AT91_ISR_PASS_LIMIT)
  16462. + break;
  16463. +
  16464. + status = UART_GET_CSR(port);
  16465. + pending = status & port->read_status_mask;
  16466. + } while (pending);
  16467. + }
  16468. +}
  16469. +
  16470. +/*
  16471. + * Perform initialization and enable port for reception
  16472. + */
  16473. +static int at91_startup(struct uart_port *port)
  16474. +{
  16475. + int retval;
  16476. +
  16477. + /*
  16478. + * Allocate the IRQ
  16479. + */
  16480. + retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
  16481. + if (retval) {
  16482. + printk("at91_serial: at91_startup - Can't get irq\n");
  16483. + return retval;
  16484. + }
  16485. + /*
  16486. + * If there is a specific "open" function (to register
  16487. + * control line interrupts)
  16488. + */
  16489. + if (at91_open) {
  16490. + retval = at91_open(port);
  16491. + if (retval) {
  16492. + free_irq(port->irq, port);
  16493. + return retval;
  16494. + }
  16495. + }
  16496. +
  16497. + /* Enable peripheral clock if required */
  16498. + if (port->irq != AT91C_ID_SYS)
  16499. + AT91_SYS->PMC_PCER = 1 << port->irq;
  16500. +
  16501. + port->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE
  16502. + | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK;
  16503. + /*
  16504. + * Finally, clear and enable interrupts
  16505. + */
  16506. + UART_PUT_IDR(port, -1);
  16507. + UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */
  16508. + UART_PUT_IER(port, AT91C_US_RXRDY); /* do receive only */
  16509. + return 0;
  16510. +}
  16511. +
  16512. +/*
  16513. + * Disable the port
  16514. + */
  16515. +static void at91_shutdown(struct uart_port *port)
  16516. +{
  16517. + /*
  16518. + * Free the interrupt
  16519. + */
  16520. + free_irq(port->irq, port);
  16521. +
  16522. + /*
  16523. + * If there is a specific "close" function (to unregister
  16524. + * control line interrupts)
  16525. + */
  16526. + if (at91_close)
  16527. + at91_close(port);
  16528. +
  16529. + /*
  16530. + * Disable all interrupts, port and break condition.
  16531. + */
  16532. + UART_PUT_CR(port, AT91C_US_RSTSTA);
  16533. + UART_PUT_IDR(port, -1);
  16534. +
  16535. + /* Disable peripheral clock if required */
  16536. + if (port->irq != AT91C_ID_SYS)
  16537. + AT91_SYS->PMC_PCDR = 1 << port->irq;
  16538. +}
  16539. +
  16540. +static struct uart_ops at91_pops; /* forward declaration */
  16541. +
  16542. +/*
  16543. + * Change the port parameters
  16544. + */
  16545. +static void at91_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
  16546. +{
  16547. + unsigned long flags;
  16548. + unsigned int mode, imr;
  16549. +
  16550. + /* Get current mode register */
  16551. + mode = UART_GET_MR(port) & ~(AT91C_US_CHRL | AT91C_US_NBSTOP | AT91C_US_PAR);
  16552. +
  16553. + /* byte size */
  16554. + switch (cflag & CSIZE) {
  16555. + case CS5:
  16556. + mode |= AT91C_US_CHRL_5_BITS;
  16557. + break;
  16558. + case CS6:
  16559. + mode |= AT91C_US_CHRL_6_BITS;
  16560. + break;
  16561. + case CS7:
  16562. + mode |= AT91C_US_CHRL_7_BITS;
  16563. + break;
  16564. + default:
  16565. + mode |= AT91C_US_CHRL_8_BITS;
  16566. + break;
  16567. + }
  16568. +
  16569. + /* stop bits */
  16570. + if (cflag & CSTOPB)
  16571. + mode |= AT91C_US_NBSTOP_2_BIT;
  16572. +
  16573. + /* parity */
  16574. + if (cflag & PARENB) {
  16575. + if (cflag & CMSPAR) { /* Mark or Space parity */
  16576. + if (cflag & PARODD)
  16577. + mode |= AT91C_US_PAR_MARK;
  16578. + else
  16579. + mode |= AT91C_US_PAR_SPACE;
  16580. + }
  16581. + else if (cflag & PARODD)
  16582. + mode |= AT91C_US_PAR_ODD;
  16583. + else
  16584. + mode |= AT91C_US_PAR_EVEN;
  16585. + }
  16586. + else
  16587. + mode |= AT91C_US_PAR_NONE;
  16588. +
  16589. + port->read_status_mask |= AT91C_US_OVRE;
  16590. + if (iflag & INPCK)
  16591. + port->read_status_mask |= AT91C_US_FRAME | AT91C_US_PARE;
  16592. + if (iflag & (BRKINT | PARMRK))
  16593. + port->read_status_mask |= AT91C_US_RXBRK;
  16594. +
  16595. + /*
  16596. + * Characters to ignore
  16597. + */
  16598. + port->ignore_status_mask = 0;
  16599. + if (iflag & IGNPAR)
  16600. + port->ignore_status_mask |= (AT91C_US_FRAME | AT91C_US_PARE);
  16601. + if (iflag & IGNBRK) {
  16602. + port->ignore_status_mask |= AT91C_US_RXBRK;
  16603. + /*
  16604. + * If we're ignoring parity and break indicators,
  16605. + * ignore overruns too (for real raw support).
  16606. + */
  16607. + if (iflag & IGNPAR)
  16608. + port->ignore_status_mask |= AT91C_US_OVRE;
  16609. + }
  16610. +
  16611. + // TODO: Ignore all characters if CREAD is set.
  16612. +
  16613. + /* first, disable interrupts and drain transmitter */
  16614. + local_irq_save(flags);
  16615. + imr = UART_GET_IMR(port); /* get interrupt mask */
  16616. + UART_PUT_IDR(port, -1); /* disable all interrupts */
  16617. + local_irq_restore(flags);
  16618. + while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); }
  16619. +
  16620. + /* disable receiver and transmitter */
  16621. + UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS);
  16622. +
  16623. + /* set the parity, stop bits and data size */
  16624. + UART_PUT_MR(port, mode);
  16625. +
  16626. + /* set the baud rate */
  16627. + UART_PUT_BRGR(port, quot);
  16628. + UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN);
  16629. +
  16630. + /* restore interrupts */
  16631. + UART_PUT_IER(port, imr);
  16632. +
  16633. + /* CTS flow-control and modem-status interrupts */
  16634. + if (UART_ENABLE_MS(port, cflag))
  16635. + at91_pops.enable_ms(port);
  16636. +}
  16637. +
  16638. +/*
  16639. + * Return string describing the specified port
  16640. + */
  16641. +static const char *at91_type(struct uart_port *port)
  16642. +{
  16643. + return port->type == PORT_AT91RM9200 ? "AT91_SERIAL" : NULL;
  16644. +}
  16645. +
  16646. +/*
  16647. + * Release the memory region(s) being used by 'port'.
  16648. + */
  16649. +static void at91_release_port(struct uart_port *port)
  16650. +{
  16651. + release_mem_region(port->mapbase,
  16652. + port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K);
  16653. +}
  16654. +
  16655. +/*
  16656. + * Request the memory region(s) being used by 'port'.
  16657. + */
  16658. +static int at91_request_port(struct uart_port *port)
  16659. +{
  16660. + return request_mem_region(port->mapbase,
  16661. + port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K,
  16662. + "at91_serial") != NULL ? 0 : -EBUSY;
  16663. +
  16664. +}
  16665. +
  16666. +/*
  16667. + * Configure/autoconfigure the port.
  16668. + */
  16669. +static void at91_config_port(struct uart_port *port, int flags)
  16670. +{
  16671. + if (flags & UART_CONFIG_TYPE) {
  16672. + port->type = PORT_AT91RM9200;
  16673. + at91_request_port(port);
  16674. + }
  16675. +}
  16676. +
  16677. +/*
  16678. + * Verify the new serial_struct (for TIOCSSERIAL).
  16679. + */
  16680. +static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
  16681. +{
  16682. + int ret = 0;
  16683. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
  16684. + ret = -EINVAL;
  16685. + if (port->irq != ser->irq)
  16686. + ret = -EINVAL;
  16687. + if (ser->io_type != SERIAL_IO_MEM)
  16688. + ret = -EINVAL;
  16689. + if (port->uartclk / 16 != ser->baud_base)
  16690. + ret = -EINVAL;
  16691. + if ((void *)port->mapbase != ser->iomem_base)
  16692. + ret = -EINVAL;
  16693. + if (port->iobase != ser->port)
  16694. + ret = -EINVAL;
  16695. + if (ser->hub6 != 0)
  16696. + ret = -EINVAL;
  16697. + return ret;
  16698. +}
  16699. +
  16700. +static struct uart_ops at91_pops = {
  16701. + tx_empty: at91_tx_empty,
  16702. + set_mctrl: at91_set_mctrl,
  16703. + get_mctrl: at91_get_mctrl,
  16704. + stop_tx: at91_stop_tx,
  16705. + start_tx: at91_start_tx,
  16706. + stop_rx: at91_stop_rx,
  16707. + enable_ms: at91_enable_ms,
  16708. + break_ctl: at91_break_ctl,
  16709. + startup: at91_startup,
  16710. + shutdown: at91_shutdown,
  16711. + change_speed: at91_change_speed,
  16712. + type: at91_type,
  16713. + release_port: at91_release_port,
  16714. + request_port: at91_request_port,
  16715. + config_port: at91_config_port,
  16716. + verify_port: at91_verify_port,
  16717. +};
  16718. +
  16719. +static struct uart_port at91_ports[AT91C_NR_UART];
  16720. +
  16721. +void __init at91_init_ports(void)
  16722. +{
  16723. + static int first = 1;
  16724. + int i;
  16725. +
  16726. + if (!first)
  16727. + return;
  16728. + first = 0;
  16729. +
  16730. + for (i = 0; i < AT91C_NR_UART; i++) {
  16731. + at91_ports[i].iotype = SERIAL_IO_MEM;
  16732. + at91_ports[i].flags = ASYNC_BOOT_AUTOCONF;
  16733. + at91_ports[i].uartclk = AT91C_MASTER_CLOCK;
  16734. + at91_ports[i].ops = &at91_pops;
  16735. + at91_ports[i].fifosize = 1;
  16736. + at91_ports[i].line = i;
  16737. + }
  16738. +}
  16739. +
  16740. +void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
  16741. +{
  16742. + if (fns->enable_ms)
  16743. + at91_pops.enable_ms = fns->enable_ms;
  16744. + if (fns->get_mctrl)
  16745. + at91_pops.get_mctrl = fns->get_mctrl;
  16746. + if (fns->set_mctrl)
  16747. + at91_pops.set_mctrl = fns->set_mctrl;
  16748. + at91_open = fns->open;
  16749. + at91_close = fns->close;
  16750. + at91_pops.pm = fns->pm;
  16751. + at91_pops.set_wake = fns->set_wake;
  16752. +}
  16753. +
  16754. +/*
  16755. + * Setup ports.
  16756. + */
  16757. +void __init at91_register_uart(int idx, int port)
  16758. +{
  16759. + if ((idx < 0) || (idx >= AT91C_NR_UART)) {
  16760. + printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);
  16761. + return;
  16762. + }
  16763. +
  16764. + switch (port) {
  16765. + case 0:
  16766. + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0;
  16767. + at91_ports[idx].mapbase = AT91C_VA_BASE_US0;
  16768. + at91_ports[idx].irq = AT91C_ID_US0;
  16769. + AT91_CfgPIO_USART0();
  16770. + break;
  16771. + case 1:
  16772. + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1;
  16773. + at91_ports[idx].mapbase = AT91C_VA_BASE_US1;
  16774. + at91_ports[idx].irq = AT91C_ID_US1;
  16775. + AT91_CfgPIO_USART1();
  16776. + break;
  16777. + case 2:
  16778. + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2;
  16779. + at91_ports[idx].mapbase = AT91C_VA_BASE_US2;
  16780. + at91_ports[idx].irq = AT91C_ID_US2;
  16781. + AT91_CfgPIO_USART2();
  16782. + break;
  16783. + case 3:
  16784. + at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3;
  16785. + at91_ports[idx].mapbase = AT91C_VA_BASE_US3;
  16786. + at91_ports[idx].irq = AT91C_ID_US3;
  16787. + AT91_CfgPIO_USART3();
  16788. + break;
  16789. + case 4:
  16790. + at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU;
  16791. + at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU;
  16792. + at91_ports[idx].irq = AT91C_ID_SYS;
  16793. + AT91_CfgPIO_DBGU();
  16794. + break;
  16795. + default:
  16796. + printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);
  16797. + }
  16798. +}
  16799. +
  16800. +#ifdef CONFIG_SERIAL_AT91_CONSOLE
  16801. +
  16802. +/*
  16803. + * Interrupts are disabled on entering
  16804. + */
  16805. +static void at91_console_write(struct console *co, const char *s, u_int count)
  16806. +{
  16807. + struct uart_port *port = at91_ports + co->index;
  16808. + unsigned int status, i, imr;
  16809. +
  16810. + /*
  16811. + * First, save IMR and then disable interrupts
  16812. + */
  16813. + imr = UART_GET_IMR(port); /* get interrupt mask */
  16814. + UART_PUT_IDR(port, AT91C_US_RXRDY | AT91C_US_TXRDY);
  16815. +
  16816. + /*
  16817. + * Now, do each character
  16818. + */
  16819. + for (i = 0; i < count; i++) {
  16820. + do {
  16821. + status = UART_GET_CSR(port);
  16822. + } while (!(status & AT91C_US_TXRDY));
  16823. + UART_PUT_CHAR(port, s[i]);
  16824. + if (s[i] == '\n') {
  16825. + do {
  16826. + status = UART_GET_CSR(port);
  16827. + } while (!(status & AT91C_US_TXRDY));
  16828. + UART_PUT_CHAR(port, '\r');
  16829. + }
  16830. + }
  16831. +
  16832. + /*
  16833. + * Finally, wait for transmitter to become empty
  16834. + * and restore IMR
  16835. + */
  16836. + do {
  16837. + status = UART_GET_CSR(port);
  16838. + } while (status & AT91C_US_TXRDY);
  16839. + UART_PUT_IER(port, imr); /* set interrupts back the way they were */
  16840. +}
  16841. +
  16842. +static kdev_t at91_console_device(struct console *co)
  16843. +{
  16844. + return MKDEV(SERIAL_AT91_MAJOR, MINOR_START + co->index);
  16845. +}
  16846. +
  16847. +/*
  16848. + * If the port was already initialised (eg, by a boot loader), try to determine
  16849. + * the current setup.
  16850. + */
  16851. +static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  16852. +{
  16853. + unsigned int mr, quot;
  16854. +
  16855. +// TODO: CR is a write-only register
  16856. +// unsigned int cr;
  16857. +//
  16858. +// cr = UART_GET_CR(port) & (AT91C_US_RXEN | AT91C_US_TXEN);
  16859. +// if (cr == (AT91C_US_RXEN | AT91C_US_TXEN)) {
  16860. +// /* ok, the port was enabled */
  16861. +//
  16862. +// mr = UART_GET_MR(port) & AT91C_US_PAR;
  16863. +//
  16864. +// *parity = 'n';
  16865. +// if (mr == AT91C_US_PAR_EVEN)
  16866. +// *parity = 'e';
  16867. +// else if (mr == AT91C_US_PAR_ODD)
  16868. +// *parity = 'o';
  16869. +// }
  16870. +
  16871. + mr = UART_GET_MR(port) & AT91C_US_CHRL;
  16872. + if (mr == AT91C_US_CHRL_8_BITS)
  16873. + *bits = 8;
  16874. + else
  16875. + *bits = 7;
  16876. +
  16877. + quot = UART_GET_BRGR(port);
  16878. + *baud = port->uartclk / (16 * (quot));
  16879. +}
  16880. +
  16881. +static int __init at91_console_setup(struct console *co, char *options)
  16882. +{
  16883. + struct uart_port *port;
  16884. + int baud = AT91C_CONSOLE_DEFAULT_BAUDRATE;
  16885. + int bits = 8;
  16886. + int parity = 'n';
  16887. + int flow = 'n';
  16888. +
  16889. + /*
  16890. + * Check whether an invalid uart number has been specified, and
  16891. + * if so, search for the first available port that does have
  16892. + * console support.
  16893. + */
  16894. + port = uart_get_console(at91_ports, AT91C_NR_UART, co);
  16895. +
  16896. + // TODO: The console port should be initialized, and clock enabled if
  16897. + // we're not relying on the bootloader to do it.
  16898. +
  16899. + if (options)
  16900. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  16901. + else
  16902. + at91_console_get_options(port, &baud, &parity, &bits);
  16903. +
  16904. + return uart_set_options(port, co, baud, parity, bits, flow);
  16905. +}
  16906. +
  16907. +static struct console at91_console = {
  16908. + name: "ttyS",
  16909. + write: at91_console_write,
  16910. + device: at91_console_device,
  16911. + setup: at91_console_setup,
  16912. + flags: CON_PRINTBUFFER,
  16913. + index: AT91C_CONSOLE,
  16914. +};
  16915. +
  16916. +#define AT91_CONSOLE_DEVICE &at91_console
  16917. +
  16918. +void __init at91_console_init(void)
  16919. +{
  16920. + at91_init_ports();
  16921. + register_console(&at91_console);
  16922. +}
  16923. +
  16924. +#else
  16925. +#define AT91_CONSOLE_DEVICE NULL
  16926. +#endif
  16927. +
  16928. +static struct uart_driver at91_reg = {
  16929. + owner: THIS_MODULE,
  16930. + normal_major: SERIAL_AT91_MAJOR,
  16931. +#ifdef CONFIG_DEVFS_FS
  16932. + normal_name: "ttyS%d",
  16933. + callout_name: "cua%d",
  16934. +#else
  16935. + normal_name: "ttyS",
  16936. + callout_name: "cua",
  16937. +#endif
  16938. + normal_driver: &normal,
  16939. + callout_major: CALLOUT_AT91_MAJOR,
  16940. + callout_driver: &callout,
  16941. + table: at91_table,
  16942. + termios: at91_termios,
  16943. + termios_locked: at91_termios_locked,
  16944. + minor: MINOR_START,
  16945. + nr: AT91C_NR_UART,
  16946. + cons: AT91_CONSOLE_DEVICE,
  16947. +};
  16948. +
  16949. +static int __init at91_serial_init(void)
  16950. +{
  16951. + int ret, i;
  16952. +
  16953. + at91_init_ports();
  16954. +
  16955. + ret = uart_register_driver(&at91_reg);
  16956. + if (ret)
  16957. + return ret;
  16958. +
  16959. + for (i = 0; i < AT91C_NR_UART; i++) {
  16960. + if (at91_serialmap[i] >= 0)
  16961. + uart_add_one_port(&at91_reg, &at91_ports[i]);
  16962. + }
  16963. +
  16964. + return 0;
  16965. +}
  16966. +
  16967. +static void __exit at91_serial_exit(void)
  16968. +{
  16969. + int i;
  16970. +
  16971. + for (i = 0; i < AT91C_NR_UART; i++) {
  16972. + if (at91_serialmap[i] >= 0)
  16973. + uart_remove_one_port(&at91_reg, &at91_ports[i]);
  16974. + }
  16975. +
  16976. + uart_unregister_driver(&at91_reg);
  16977. +}
  16978. +
  16979. +module_init(at91_serial_init);
  16980. +module_exit(at91_serial_exit);
  16981. +
  16982. +EXPORT_NO_SYMBOLS;
  16983. +
  16984. +MODULE_AUTHOR("Rick Bronson");
  16985. +MODULE_DESCRIPTION("AT91 generic serial port driver");
  16986. +MODULE_LICENSE("GPL");
  16987. diff -urN linux-2.4.26/drivers/at91/spi/Makefile linux-2.4.26-vrs1/drivers/at91/spi/Makefile
  16988. --- linux-2.4.26/drivers/at91/spi/Makefile 1970-01-01 01:00:00.000000000 +0100
  16989. +++ linux-2.4.26-vrs1/drivers/at91/spi/Makefile 2004-01-14 21:32:25.000000000 +0000
  16990. @@ -0,0 +1,17 @@
  16991. +# File: drivers/at91/spi/Makefile
  16992. +#
  16993. +# Makefile for the Atmel AT91RM9200 SPI device drivers
  16994. +#
  16995. +
  16996. +O_TARGET := at91spi.o
  16997. +
  16998. +export-objs := at91_spi.o
  16999. +
  17000. +obj-y := at91_spi.o
  17001. +obj-m :=
  17002. +obj-n :=
  17003. +obj- :=
  17004. +
  17005. +obj-$(CONFIG_AT91_SPIDEV) += at91_spidev.o
  17006. +
  17007. +include $(TOPDIR)/Rules.make
  17008. diff -urN linux-2.4.26/drivers/at91/spi/at91_spi.c linux-2.4.26-vrs1/drivers/at91/spi/at91_spi.c
  17009. --- linux-2.4.26/drivers/at91/spi/at91_spi.c 1970-01-01 01:00:00.000000000 +0100
  17010. +++ linux-2.4.26-vrs1/drivers/at91/spi/at91_spi.c 2004-04-10 12:23:48.000000000 +0100
  17011. @@ -0,0 +1,275 @@
  17012. +/*
  17013. + * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 (Thunder)
  17014. + *
  17015. + * (c) SAN People (Pty) Ltd
  17016. + *
  17017. + * This program is free software; you can redistribute it and/or
  17018. + * modify it under the terms of the GNU General Public License
  17019. + * as published by the Free Software Foundation; either version
  17020. + * 2 of the License, or (at your option) any later version.
  17021. + */
  17022. +
  17023. +#include <linux/init.h>
  17024. +#include <linux/module.h>
  17025. +#include <asm/semaphore.h>
  17026. +#include <linux/pci.h>
  17027. +#include <linux/sched.h>
  17028. +#include <linux/completion.h>
  17029. +
  17030. +#include <asm/arch/AT91RM9200_SPI.h>
  17031. +#include <asm/arch/pio.h>
  17032. +#include "at91_spi.h"
  17033. +
  17034. +#undef DEBUG_SPI
  17035. +
  17036. +static struct spi_local spi_dev[NR_SPI_DEVICES]; /* state of the SPI devices */
  17037. +static int spi_enabled = 0;
  17038. +static struct semaphore spi_lock; /* protect access to SPI bus */
  17039. +static int current_device = -1; /* currently selected SPI device */
  17040. +
  17041. +DECLARE_COMPLETION(transfer_complete);
  17042. +
  17043. +/* SPI controller device */
  17044. +static AT91PS_SPI controller = (AT91PS_SPI) AT91C_VA_BASE_SPI;
  17045. +
  17046. +/* ......................................................................... */
  17047. +
  17048. +/*
  17049. + * Access and enable the SPI bus.
  17050. + * This MUST be called before any transfers are performed.
  17051. + */
  17052. +void spi_access_bus(short device)
  17053. +{
  17054. + /* Ensure that requested device is valid */
  17055. + if ((device < 0) || (device >= NR_SPI_DEVICES))
  17056. + panic("at91_spi: spi_access_bus called with invalid device");
  17057. +
  17058. + if (spi_enabled == 0) {
  17059. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Enable Peripheral clock */
  17060. + controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
  17061. +#ifdef DEBUG_SPI
  17062. + printk("SPI on\n");
  17063. +#endif
  17064. + }
  17065. + MOD_INC_USE_COUNT;
  17066. + spi_enabled++;
  17067. +
  17068. + /* Lock the SPI bus */
  17069. + down(&spi_lock);
  17070. + current_device = device;
  17071. +
  17072. + /* Enable PIO */
  17073. + if (!spi_dev[device].pio_enabled) {
  17074. + switch (device) {
  17075. + case 0: AT91_CfgPIO_SPI_CS0();
  17076. + case 1: AT91_CfgPIO_SPI_CS1();
  17077. + case 2: AT91_CfgPIO_SPI_CS2();
  17078. + case 3: AT91_CfgPIO_SPI_CS3();
  17079. + }
  17080. + spi_dev[device].pio_enabled = 1;
  17081. +#ifdef DEBUG_SPI
  17082. + printk("SPI CS%i enabled\n", device);
  17083. +#endif
  17084. + }
  17085. +
  17086. + /* Configure SPI bus for device */
  17087. + controller->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (spi_dev[device].pcs << 16);
  17088. +}
  17089. +
  17090. +/*
  17091. + * Relinquish control of the SPI bus.
  17092. + */
  17093. +void spi_release_bus(short device)
  17094. +{
  17095. + if (device != current_device)
  17096. + panic("at91_spi: spi_release called with invalid device");
  17097. +
  17098. + /* Release the SPI bus */
  17099. + current_device = -1;
  17100. + up(&spi_lock);
  17101. +
  17102. + spi_enabled--;
  17103. + MOD_DEC_USE_COUNT;
  17104. + if (spi_enabled == 0) {
  17105. + controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
  17106. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Disable Peripheral clock */
  17107. +#ifdef DEBUG_SPI
  17108. + printk("SPI off\n");
  17109. +#endif
  17110. + }
  17111. +}
  17112. +
  17113. +/*
  17114. + * Perform a data transfer over the SPI bus
  17115. + */
  17116. +int spi_transfer(struct spi_transfer_list* list)
  17117. +{
  17118. + struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
  17119. +
  17120. + if (!list)
  17121. + panic("at91_spi: spi_transfer called with NULL transfer list");
  17122. + if (current_device == -1)
  17123. + panic("at91_spi: spi_transfer called without acquiring bus");
  17124. +
  17125. +#ifdef DEBUG_SPI
  17126. + printk("SPI transfer start [%i]\n", list->nr_transfers);
  17127. +#endif
  17128. +
  17129. + /* Store transfer list */
  17130. + device->xfers = list;
  17131. + list->curr = 0;
  17132. +
  17133. + /* Assume there must be at least one transfer */
  17134. + device->tx = pci_map_single(NULL, list->tx[0], list->txlen[0], PCI_DMA_TODEVICE);
  17135. + device->rx = pci_map_single(NULL, list->rx[0], list->rxlen[0], PCI_DMA_FROMDEVICE);
  17136. +
  17137. + /* Program PDC registers */
  17138. + controller->SPI_TPR = device->tx;
  17139. + controller->SPI_RPR = device->rx;
  17140. + controller->SPI_TCR = list->txlen[0];
  17141. + controller->SPI_RCR = list->rxlen[0];
  17142. +
  17143. + /* Is there a second transfer? */
  17144. + if (list->nr_transfers > 1) {
  17145. + device->txnext = pci_map_single(NULL, list->tx[1], list->txlen[1], PCI_DMA_TODEVICE);
  17146. + device->rxnext = pci_map_single(NULL, list->rx[1], list->rxlen[1], PCI_DMA_FROMDEVICE);
  17147. +
  17148. + /* Program Next PDC registers */
  17149. + controller->SPI_TNPR = device->txnext;
  17150. + controller->SPI_RNPR = device->rxnext;
  17151. + controller->SPI_TNCR = list->txlen[1];
  17152. + controller->SPI_RNCR = list->rxlen[1];
  17153. + }
  17154. + else {
  17155. + device->txnext = 0;
  17156. + device->rxnext = 0;
  17157. + controller->SPI_TNCR = 0;
  17158. + controller->SPI_RNCR = 0;
  17159. + }
  17160. +
  17161. + // TODO: If we are doing consecutive transfers (at high speed, or
  17162. + // small buffers), then it might be worth modifying the 'Delay between
  17163. + // Consecutive Transfers' in the CSR registers.
  17164. + // This is an issue if we cannot chain the next buffer fast enough
  17165. + // in the interrupt handler.
  17166. +
  17167. + /* Enable transmitter and receiver */
  17168. + controller->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
  17169. +
  17170. + controller->SPI_IER = AT91C_SPI_SPENDRX; /* enable buffer complete interrupt */
  17171. + wait_for_completion(&transfer_complete);
  17172. +
  17173. +#ifdef DEBUG_SPI
  17174. + printk("SPI transfer end\n");
  17175. +#endif
  17176. +
  17177. + return 0;
  17178. +}
  17179. +
  17180. +/* ......................................................................... */
  17181. +
  17182. +/*
  17183. + * Handle interrupts from the SPI controller.
  17184. + */
  17185. +static void spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  17186. +{
  17187. + unsigned int status;
  17188. + struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
  17189. + struct spi_transfer_list *list = device->xfers;
  17190. +
  17191. +#ifdef DEBUG_SPI
  17192. + printk("SPI interrupt %i\n", current_device);
  17193. +#endif
  17194. +
  17195. + if (!list)
  17196. + panic("at91_spi: spi_interrupt with a NULL transfer list");
  17197. +
  17198. + status = controller->SPI_SR & controller->SPI_IMR; /* read status */
  17199. +
  17200. + pci_unmap_single(NULL, device->tx, list->txlen[list->curr], PCI_DMA_TODEVICE);
  17201. + pci_unmap_single(NULL, device->rx, list->rxlen[list->curr], PCI_DMA_FROMDEVICE);
  17202. +
  17203. + device->tx = device->txnext; /* move next transfer to current transfer */
  17204. + device->rx = device->rxnext;
  17205. +
  17206. + list->curr = list->curr + 1;
  17207. + if (list->curr == list->nr_transfers) { /* all transfers complete */
  17208. + controller->SPI_IDR = AT91C_SPI_SPENDRX; /* disable interrupt */
  17209. +
  17210. + /* Disable transmitter and receiver */
  17211. + controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
  17212. +
  17213. + device->xfers = NULL;
  17214. + complete(&transfer_complete);
  17215. + }
  17216. + else if (list->curr+1 == list->nr_transfers) { /* no more next transfers */
  17217. + device->txnext = 0;
  17218. + device->rxnext = 0;
  17219. + controller->SPI_TNCR = 0;
  17220. + controller->SPI_RNCR = 0;
  17221. + }
  17222. + else {
  17223. + int i = (list->curr)+1;
  17224. +
  17225. + device->txnext = pci_map_single(NULL, list->tx[i], list->txlen[i], PCI_DMA_TODEVICE);
  17226. + device->rxnext = pci_map_single(NULL, list->rx[i], list->rxlen[i], PCI_DMA_FROMDEVICE);
  17227. + controller->SPI_TNPR = device->txnext;
  17228. + controller->SPI_RNPR = device->rxnext;
  17229. + controller->SPI_TNCR = list->txlen[i];
  17230. + controller->SPI_RNCR = list->rxlen[i];
  17231. + }
  17232. +}
  17233. +
  17234. +/* ......................................................................... */
  17235. +
  17236. +/*
  17237. + * Initialize the SPI controller
  17238. + */
  17239. +static int __init at91_spi_init(void)
  17240. +{
  17241. + init_MUTEX(&spi_lock);
  17242. +
  17243. + AT91_CfgPIO_SPI();
  17244. +
  17245. + controller->SPI_CR = AT91C_SPI_SWRST; /* software reset of SPI controller */
  17246. +
  17247. + /* Set Chip Select registers to good defaults */
  17248. + controller->SPI_CSR0 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
  17249. + controller->SPI_CSR1 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
  17250. + controller->SPI_CSR2 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
  17251. + controller->SPI_CSR3 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
  17252. +
  17253. + controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
  17254. +
  17255. + memset(&spi_dev, 0, sizeof(spi_dev));
  17256. + spi_dev[0].pcs = 0xE;
  17257. + spi_dev[1].pcs = 0xD;
  17258. + spi_dev[2].pcs = 0xB;
  17259. + spi_dev[3].pcs = 0x7;
  17260. +
  17261. + if (request_irq(AT91C_ID_SPI, spi_interrupt, 0, "spi", NULL))
  17262. + return -EBUSY;
  17263. +
  17264. + controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
  17265. +
  17266. + return 0;
  17267. +}
  17268. +
  17269. +static void at91_spi_exit(void)
  17270. +{
  17271. + controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
  17272. +
  17273. + free_irq(AT91C_ID_SPI, 0);
  17274. +}
  17275. +
  17276. +
  17277. +EXPORT_SYMBOL(spi_access_bus);
  17278. +EXPORT_SYMBOL(spi_release_bus);
  17279. +EXPORT_SYMBOL(spi_transfer);
  17280. +
  17281. +module_init(at91_spi_init);
  17282. +module_exit(at91_spi_exit);
  17283. +
  17284. +MODULE_LICENSE("GPL")
  17285. +MODULE_AUTHOR("Andrew Victor")
  17286. +MODULE_DESCRIPTION("SPI driver for Atmel AT91RM9200")
  17287. diff -urN linux-2.4.26/drivers/at91/spi/at91_spi.h linux-2.4.26-vrs1/drivers/at91/spi/at91_spi.h
  17288. --- linux-2.4.26/drivers/at91/spi/at91_spi.h 1970-01-01 01:00:00.000000000 +0100
  17289. +++ linux-2.4.26-vrs1/drivers/at91/spi/at91_spi.h 2004-01-14 21:32:25.000000000 +0000
  17290. @@ -0,0 +1,56 @@
  17291. +/*
  17292. + * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200
  17293. + *
  17294. + * (c) SAN People (Pty) Ltd
  17295. + *
  17296. + * This program is free software; you can redistribute it and/or
  17297. + * modify it under the terms of the GNU General Public License
  17298. + * as published by the Free Software Foundation; either version
  17299. + * 2 of the License, or (at your option) any later version.
  17300. + */
  17301. +
  17302. +#ifndef AT91_SPI_H
  17303. +#define AT91_SPI_H
  17304. +
  17305. +/* Maximum number of buffers in a single SPI transfer.
  17306. + * DataFlash uses maximum of 2
  17307. + * spidev interface supports up to 8.
  17308. + */
  17309. +#define MAX_SPI_TRANSFERS 8
  17310. +
  17311. +#define NR_SPI_DEVICES 4 /* number of devices on SPI bus */
  17312. +
  17313. +#define DATAFLASH_CLK 6000000
  17314. +#define DEFAULT_SPI_BAUD AT91C_MASTER_CLOCK / (2 * DATAFLASH_CLK)
  17315. +
  17316. +#define SPI_MAJOR 153 /* registered device number */
  17317. +
  17318. +/*
  17319. + * Describes the buffers for a SPI transfer.
  17320. + * A transmit & receive buffer must be specified for each transfer
  17321. + */
  17322. +struct spi_transfer_list {
  17323. + void* tx[MAX_SPI_TRANSFERS]; /* transmit */
  17324. + int txlen[MAX_SPI_TRANSFERS];
  17325. + void* rx[MAX_SPI_TRANSFERS]; /* receive */
  17326. + int rxlen[MAX_SPI_TRANSFERS];
  17327. + int nr_transfers; /* number of transfers */
  17328. + int curr; /* current transfer */
  17329. +};
  17330. +
  17331. +struct spi_local {
  17332. + unsigned int pcs; /* Peripheral Chip Select value */
  17333. + short pio_enabled; /* has PIO been enabled? */
  17334. +
  17335. + struct spi_transfer_list *xfers; /* current transfer list */
  17336. + dma_addr_t tx, rx; /* DMA address for current transfer */
  17337. + dma_addr_t txnext, rxnext; /* DMA address for next transfer */
  17338. +};
  17339. +
  17340. +
  17341. +/* Exported functions */
  17342. +extern void spi_access_bus(short device);
  17343. +extern void spi_release_bus(short device);
  17344. +extern int spi_transfer(struct spi_transfer_list* list);
  17345. +
  17346. +#endif
  17347. diff -urN linux-2.4.26/drivers/at91/spi/at91_spidev.c linux-2.4.26-vrs1/drivers/at91/spi/at91_spidev.c
  17348. --- linux-2.4.26/drivers/at91/spi/at91_spidev.c 1970-01-01 01:00:00.000000000 +0100
  17349. +++ linux-2.4.26-vrs1/drivers/at91/spi/at91_spidev.c 2004-04-10 12:23:48.000000000 +0100
  17350. @@ -0,0 +1,226 @@
  17351. +/*
  17352. + * User-space interface to the SPI bus on Atmel AT91RM9200
  17353. + *
  17354. + * (c) SAN People (Pty) Ltd
  17355. + *
  17356. + * Based on SPI driver by Rick Bronson
  17357. + *
  17358. + * This program is free software; you can redistribute it and/or
  17359. + * modify it under the terms of the GNU General Public License
  17360. + * as published by the Free Software Foundation; either version
  17361. + * 2 of the License, or (at your option) any later version.
  17362. + */
  17363. +
  17364. +#include <linux/module.h>
  17365. +#include <linux/config.h>
  17366. +#include <linux/init.h>
  17367. +#include <linux/slab.h>
  17368. +#include <linux/iobuf.h>
  17369. +#include <linux/highmem.h>
  17370. +
  17371. +#ifdef CONFIG_DEVFS_FS
  17372. +#include <linux/devfs_fs_kernel.h>
  17373. +#endif
  17374. +
  17375. +#include "at91_spi.h"
  17376. +
  17377. +#undef DEBUG_SPIDEV
  17378. +
  17379. +#ifdef CONFIG_DEVFS_FS
  17380. +static devfs_handle_t devfs_handle = NULL;
  17381. +static devfs_handle_t devfs_spi[NR_SPI_DEVICES];
  17382. +#endif
  17383. +
  17384. +/* ......................................................................... */
  17385. +
  17386. +/*
  17387. + * Read or Write to SPI bus.
  17388. + */
  17389. +static ssize_t spidev_rd_wr(struct file *file, char *buf, size_t count, loff_t *offset)
  17390. +{
  17391. + unsigned int spi_device = (unsigned int) file->private_data;
  17392. + struct kiobuf *iobuf;
  17393. + unsigned int ofs, pagelen;
  17394. + int res, i;
  17395. +
  17396. + struct spi_transfer_list* list = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
  17397. + if (!list)
  17398. + return -ENOMEM;
  17399. +
  17400. + res = alloc_kiovec(1, &iobuf);
  17401. + if (res) {
  17402. + kfree(list);
  17403. + return res;
  17404. + }
  17405. +
  17406. + res = map_user_kiobuf(READ, iobuf, (unsigned long) buf, count);
  17407. + if (res) {
  17408. + free_kiovec(1, &iobuf);
  17409. + kfree(list);
  17410. + return res;
  17411. + }
  17412. +
  17413. + /* More pages than transfer slots in spi_transfer_list */
  17414. + if (iobuf->nr_pages >= MAX_SPI_TRANSFERS) {
  17415. + unmap_kiobuf(iobuf);
  17416. + free_kiovec(1, &iobuf);
  17417. + kfree(list);
  17418. + return -EFBIG;
  17419. + }
  17420. +
  17421. +#ifdef DEBUG_SPIDEV
  17422. + printk("spidev_rd_rw: %i %i\n", count, iobuf->nr_pages);
  17423. +#endif
  17424. +
  17425. + /* Set default return value = transfer length */
  17426. + res = count;
  17427. +
  17428. + /*
  17429. + * At this point, the virtual area buf[0] .. buf[count-1] will have
  17430. + * corresponding pages mapped in the physical memory and locked until
  17431. + * we unmap the kiobuf. The pages cannot be swapped out or moved
  17432. + * around.
  17433. + */
  17434. + ofs = iobuf->offset;
  17435. + pagelen = PAGE_SIZE - iobuf->offset;
  17436. + if (count < pagelen)
  17437. + pagelen = count;
  17438. +
  17439. + for (i = 0; i < iobuf->nr_pages; i++) {
  17440. + list->tx[i] = list->rx[i] = page_address(iobuf->maplist[i]) + ofs;
  17441. + list->txlen[i] = list->rxlen[i] = pagelen;
  17442. +
  17443. +#ifdef DEBUG_SPIDEV
  17444. + printk(" %i: %x (%i)\n", i, list->tx[i], list->txlen[i]);
  17445. +#endif
  17446. +
  17447. + ofs = 0; /* all subsequent transfers start at beginning of a page */
  17448. + count = count - pagelen;
  17449. + pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE;
  17450. + }
  17451. + list->nr_transfers = iobuf->nr_pages;
  17452. +
  17453. + /* Perform transfer on SPI bus */
  17454. + spi_access_bus(spi_device);
  17455. + spi_transfer(list);
  17456. + spi_release_bus(spi_device);
  17457. +
  17458. + unmap_kiobuf(iobuf);
  17459. + free_kiovec(1, &iobuf);
  17460. + kfree(list);
  17461. +
  17462. + return res;
  17463. +}
  17464. +
  17465. +static int spidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  17466. +{
  17467. + int spi_device = MINOR(inode->i_rdev);
  17468. +
  17469. + if (spi_device >= NR_SPI_DEVICES)
  17470. + return -ENODEV;
  17471. +
  17472. + // TODO: This interface can be used to configure the SPI bus.
  17473. + // Configurable options could include: Speed, Clock Polarity, Clock Phase
  17474. +
  17475. + switch(cmd) {
  17476. + default:
  17477. + return -ENOIOCTLCMD;
  17478. + }
  17479. +}
  17480. +
  17481. +/*
  17482. + * Open the SPI device
  17483. + */
  17484. +static int spidev_open(struct inode *inode, struct file *file)
  17485. +{
  17486. + unsigned int spi_device = MINOR(inode->i_rdev);
  17487. +
  17488. + if (spi_device >= NR_SPI_DEVICES)
  17489. + return -ENODEV;
  17490. +
  17491. + MOD_INC_USE_COUNT;
  17492. +
  17493. + /*
  17494. + * 'private_data' is actually a pointer, but we overload it with the
  17495. + * value we want to store.
  17496. + */
  17497. + (unsigned int) file->private_data = spi_device;
  17498. +
  17499. + return 0;
  17500. +}
  17501. +
  17502. +/*
  17503. + * Close the SPI device
  17504. + */
  17505. +static int spidev_close(struct inode *inode, struct file *file)
  17506. +{
  17507. + MOD_DEC_USE_COUNT;
  17508. + return 0;
  17509. +}
  17510. +
  17511. +/* ......................................................................... */
  17512. +
  17513. +static struct file_operations spidev_fops = {
  17514. + owner: THIS_MODULE,
  17515. + llseek: no_llseek,
  17516. + read: spidev_rd_wr,
  17517. + write: spidev_rd_wr,
  17518. + ioctl: spidev_ioctl,
  17519. + open: spidev_open,
  17520. + release: spidev_close,
  17521. +};
  17522. +
  17523. +/*
  17524. + * Install the SPI /dev interface driver
  17525. + */
  17526. +static int __init at91_spidev_init(void)
  17527. +{
  17528. + int i;
  17529. + char name[3];
  17530. +
  17531. +#ifdef CONFIG_DEVFS_FS
  17532. + if (devfs_register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
  17533. +#else
  17534. + if (register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
  17535. +#endif
  17536. + printk(KERN_ERR "at91_spidev: Unable to get major %d for SPI bus\n", SPI_MAJOR);
  17537. + return -EIO;
  17538. + }
  17539. +
  17540. +#ifdef CONFIG_DEVFS_FS
  17541. + devfs_handle = devfs_mk_dir(NULL, "spi", NULL);
  17542. +
  17543. + for (i = 0; i < NR_SPI_DEVICES; i++) {
  17544. + sprintf (name, "%d", i);
  17545. + devfs_spi[i] = devfs_register (devfs_handle, name,
  17546. + DEVFS_FL_DEFAULT, SPI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
  17547. + &spidev_fops, NULL);
  17548. + }
  17549. +#endif
  17550. + printk(KERN_INFO "AT91 SPI driver loaded\n");
  17551. +
  17552. + return 0;
  17553. +}
  17554. +
  17555. +/*
  17556. + * Remove the SPI /dev interface driver
  17557. + */
  17558. +static void __exit at91_spidev_exit(void)
  17559. +{
  17560. +#ifdef CONFIG_DEVFS_FS
  17561. + devfs_unregister(devfs_handle);
  17562. + if (devfs_unregister_chrdev(SPI_MAJOR, "spi")) {
  17563. +#else
  17564. + if (unregister_chrdev(SPI_MAJOR,"spi")) {
  17565. +#endif
  17566. + printk(KERN_ERR "at91_spidev: Unable to release major %d for SPI bus\n", SPI_MAJOR);
  17567. + return;
  17568. + }
  17569. +}
  17570. +
  17571. +module_init(at91_spidev_init);
  17572. +module_exit(at91_spidev_exit);
  17573. +
  17574. +MODULE_LICENSE("GPL")
  17575. +MODULE_AUTHOR("Andrew Victor")
  17576. +MODULE_DESCRIPTION("SPI /dev interface for Atmel AT91RM9200")
  17577. diff -urN linux-2.4.26/drivers/at91/usb/Makefile linux-2.4.26-vrs1/drivers/at91/usb/Makefile
  17578. --- linux-2.4.26/drivers/at91/usb/Makefile 1970-01-01 01:00:00.000000000 +0100
  17579. +++ linux-2.4.26-vrs1/drivers/at91/usb/Makefile 2004-01-14 21:32:25.000000000 +0000
  17580. @@ -0,0 +1,17 @@
  17581. +# File: drivers/at91/usb/Makefile
  17582. +#
  17583. +# Makefile for the Atmel AT91RM9200 USB device drivers
  17584. +#
  17585. +
  17586. +O_TARGET := at91usb.o
  17587. +
  17588. +export-objs :=
  17589. +
  17590. +obj-y :=
  17591. +obj-m :=
  17592. +obj-n :=
  17593. +obj- :=
  17594. +
  17595. +obj-$(CONFIG_USB_OHCI_AT91) += at91_usb-ohci.o
  17596. +
  17597. +include $(TOPDIR)/Rules.make
  17598. diff -urN linux-2.4.26/drivers/at91/usb/at91_usb-ohci.c linux-2.4.26-vrs1/drivers/at91/usb/at91_usb-ohci.c
  17599. --- linux-2.4.26/drivers/at91/usb/at91_usb-ohci.c 1970-01-01 01:00:00.000000000 +0100
  17600. +++ linux-2.4.26-vrs1/drivers/at91/usb/at91_usb-ohci.c 2004-04-10 12:44:07.000000000 +0100
  17601. @@ -0,0 +1,85 @@
  17602. +/*
  17603. + * linux/drivers/at91/usb/at91_usb_ohci-at91.c
  17604. + *
  17605. + * (c) Rick Bronson
  17606. + *
  17607. + * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
  17608. + * original OHCI driver modifications, and reworked into a cleaner form
  17609. + * by Russell King <rmk@arm.linux.org.uk>.
  17610. + */
  17611. +
  17612. +#include <linux/module.h>
  17613. +#include <linux/init.h>
  17614. +#include <linux/sched.h>
  17615. +#include <linux/ioport.h>
  17616. +#include <linux/interrupt.h>
  17617. +#include <linux/slab.h>
  17618. +#include <linux/usb.h>
  17619. +#include <asm/hardware.h>
  17620. +#include <asm/irq.h>
  17621. +#include <asm/io.h>
  17622. +
  17623. +#include <asm/arch/AT91RM9200_UHP.h>
  17624. +
  17625. +/*
  17626. + NOTE:
  17627. + The following is so that we don't have to include usb-ohci.h or pci.h as the
  17628. + usb-ohci.c driver needs these routines even when the architecture
  17629. + has no PCI bus...
  17630. +*/
  17631. +
  17632. +extern int __devinit hc_add_ohci(struct pci_dev *dev, int irq, void *membase,
  17633. + unsigned long flags, void *ohci, const char *name,
  17634. + const char *slot_name);
  17635. +extern void hc_remove_ohci(void *ohci);
  17636. +
  17637. +static void *at91_ohci;
  17638. +AT91PS_UHP ohci_regs;
  17639. +
  17640. +static int __init at91_ohci_init(void)
  17641. +{
  17642. + int ret;
  17643. +
  17644. + ohci_regs = ioremap(AT91_UHP_BASE, SZ_4K);
  17645. + if (!ohci_regs) {
  17646. + printk(KERN_ERR "at91_usb-ohci: ioremap failed\n");
  17647. + return -EIO;
  17648. + }
  17649. +
  17650. + /* Enable PLLB */
  17651. + AT91_SYS->CKGR_PLLBR = AT91_PLLB_INIT;
  17652. + while ((AT91_SYS->PMC_SR & 4) == 0);
  17653. +
  17654. + /* Now, enable the USB clock */
  17655. + AT91_SYS->PMC_SCER = AT91C_PMC_UHP; /* enable system clock */
  17656. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_UHP; /* enable peripheral clock */
  17657. +
  17658. + /* Take Hc out of reset */
  17659. + ohci_regs->UHP_HcControl = 2 << 6;
  17660. +
  17661. + /* Initialise the generic OHCI driver. */
  17662. + ret = hc_add_ohci((struct pci_dev *) 1, AT91C_ID_UHP,
  17663. + (void *)ohci_regs, 0, &at91_ohci,
  17664. + "usb-ohci", "at91");
  17665. + if (ret)
  17666. + iounmap(ohci_regs);
  17667. +
  17668. + return ret;
  17669. +}
  17670. +
  17671. +static void __exit at91_ohci_exit(void)
  17672. +{
  17673. + hc_remove_ohci(at91_ohci);
  17674. +
  17675. + /* Force UHP_Hc to reset */
  17676. + ohci_regs->UHP_HcControl = 0;
  17677. +
  17678. + /* Stop the USB clock. */
  17679. + AT91_SYS->PMC_SCDR = AT91C_PMC_UHP; /* disable system clock */
  17680. + AT91_SYS->PMC_PCDR = 1 << AT91C_ID_UHP; /* disable peripheral clock */
  17681. +
  17682. + iounmap(ohci_regs);
  17683. +}
  17684. +
  17685. +module_init(at91_ohci_init);
  17686. +module_exit(at91_ohci_exit);
  17687. diff -urN linux-2.4.26/drivers/at91/watchdog/Makefile linux-2.4.26-vrs1/drivers/at91/watchdog/Makefile
  17688. --- linux-2.4.26/drivers/at91/watchdog/Makefile 1970-01-01 01:00:00.000000000 +0100
  17689. +++ linux-2.4.26-vrs1/drivers/at91/watchdog/Makefile 2004-01-14 21:32:25.000000000 +0000
  17690. @@ -0,0 +1,15 @@
  17691. +# File: drivers/at91/watchdog/Makefile
  17692. +#
  17693. +# Makefile for the Atmel AT91RM9200 watchdog device driver
  17694. +#
  17695. +
  17696. +O_TARGET := at91wdt.o
  17697. +
  17698. +obj-y :=
  17699. +obj-m :=
  17700. +obj-n :=
  17701. +obj- :=
  17702. +
  17703. +obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
  17704. +
  17705. +include $(TOPDIR)/Rules.make
  17706. diff -urN linux-2.4.26/drivers/at91/watchdog/at91_wdt.c linux-2.4.26-vrs1/drivers/at91/watchdog/at91_wdt.c
  17707. --- linux-2.4.26/drivers/at91/watchdog/at91_wdt.c 1970-01-01 01:00:00.000000000 +0100
  17708. +++ linux-2.4.26-vrs1/drivers/at91/watchdog/at91_wdt.c 2004-04-10 12:23:48.000000000 +0100
  17709. @@ -0,0 +1,193 @@
  17710. +/*
  17711. + * Watchdog driver for Atmel AT91RM9200 (Thunder)
  17712. + *
  17713. + * (c) SAN People (Pty) Ltd
  17714. + *
  17715. + * This program is free software; you can redistribute it and/or
  17716. + * modify it under the terms of the GNU General Public License
  17717. + * as published by the Free Software Foundation; either version
  17718. + * 2 of the License, or (at your option) any later version.
  17719. + */
  17720. +
  17721. +#include <linux/module.h>
  17722. +#include <linux/config.h>
  17723. +#include <linux/miscdevice.h>
  17724. +#include <linux/watchdog.h>
  17725. +#include <asm/uaccess.h>
  17726. +#include <linux/init.h>
  17727. +
  17728. +#define WDT_DEFAULT_TIME 5 /* 5 seconds */
  17729. +#define WDT_MAX_TIME 256 /* 256 seconds */
  17730. +
  17731. +static int at91wdt_time = WDT_DEFAULT_TIME;
  17732. +static int at91wdt_busy;
  17733. +
  17734. +/* ......................................................................... */
  17735. +
  17736. +/*
  17737. + * Disable the watchdog.
  17738. + */
  17739. +static void at91_wdt_stop(void)
  17740. +{
  17741. + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN;
  17742. +}
  17743. +
  17744. +/*
  17745. + * Enable and reset the watchdog.
  17746. + */
  17747. +static void at91_wdt_start(void)
  17748. +{
  17749. + AT91_SYS->ST_WDMR = AT91C_ST_EXTEN | AT91C_ST_RSTEN | (((65536 * at91wdt_time) >> 8) & AT91C_ST_WDV);
  17750. + AT91_SYS->ST_CR = AT91C_ST_WDRST;
  17751. +}
  17752. +
  17753. +/* ......................................................................... */
  17754. +
  17755. +/*
  17756. + * Watchdog device is opened, and watchdog starts running.
  17757. + */
  17758. +static int at91_wdt_open(struct inode *inode, struct file *file)
  17759. +{
  17760. + if (test_and_set_bit(1, &at91wdt_busy))
  17761. + return -EBUSY;
  17762. + MOD_INC_USE_COUNT;
  17763. +
  17764. + /*
  17765. + * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
  17766. + *
  17767. + * Since WDV is a 16-bit counter, the maximum period is
  17768. + * 65536 / 0.256 = 256 seconds.
  17769. + */
  17770. +
  17771. + at91_wdt_start();
  17772. + return 0;
  17773. +}
  17774. +
  17775. +/*
  17776. + * Close the watchdog device.
  17777. + * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
  17778. + * disabled.
  17779. + */
  17780. +static int at91_wdt_close(struct inode *inode, struct file *file)
  17781. +{
  17782. +#ifndef CONFIG_WATCHDOG_NOWAYOUT
  17783. + /* Disable the watchdog when file is closed */
  17784. + at91_wdt_stop();
  17785. +#endif
  17786. +
  17787. + at91wdt_busy = 0;
  17788. + MOD_DEC_USE_COUNT;
  17789. + return 0;
  17790. +}
  17791. +
  17792. +/*
  17793. + * Handle commands from user-space.
  17794. + */
  17795. +static int at91_wdt_ioctl(struct inode *inode, struct file *file,
  17796. + unsigned int cmd, unsigned long arg)
  17797. +{
  17798. + unsigned int new_value;
  17799. + static struct watchdog_info info = {
  17800. + identity: "at91 watchdog",
  17801. + options: WDIOF_SETTIMEOUT,
  17802. + };
  17803. +
  17804. + switch(cmd) {
  17805. + case WDIOC_KEEPALIVE:
  17806. + AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
  17807. + return 0;
  17808. +
  17809. + case WDIOC_GETSUPPORT:
  17810. + return copy_to_user((struct watchdog_info *)arg, &info, sizeof(info));
  17811. +
  17812. + case WDIOC_SETTIMEOUT:
  17813. + if (get_user(new_value, (int *)arg))
  17814. + return -EFAULT;
  17815. + if ((new_value <= 0) || (new_value > WDT_MAX_TIME))
  17816. + return -EINVAL;
  17817. +
  17818. + /* Restart watchdog with new time */
  17819. + at91wdt_time = new_value;
  17820. + at91_wdt_start();
  17821. +
  17822. + /* Return current value */
  17823. + return put_user(at91wdt_time, (int *)arg);
  17824. +
  17825. + case WDIOC_GETTIMEOUT:
  17826. + return put_user(at91wdt_time, (int *)arg);
  17827. +
  17828. + case WDIOC_GETSTATUS:
  17829. + return put_user(0, (int *)arg);
  17830. +
  17831. + case WDIOC_SETOPTIONS:
  17832. + if (get_user(new_value, (int *)arg))
  17833. + return -EFAULT;
  17834. + if (new_value & WDIOS_DISABLECARD)
  17835. + at91_wdt_stop();
  17836. + if (new_value & WDIOS_ENABLECARD)
  17837. + at91_wdt_start();
  17838. + return 0;
  17839. +
  17840. + default:
  17841. + return -ENOIOCTLCMD;
  17842. + }
  17843. +}
  17844. +
  17845. +/*
  17846. + * Pat the watchdog whenever device is written to.
  17847. + */
  17848. +static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  17849. +{
  17850. + /* Can't seek (pwrite) on this device */
  17851. + if (ppos != &file->f_pos)
  17852. + return -ESPIPE;
  17853. +
  17854. + if (len) {
  17855. + AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
  17856. + return len;
  17857. + }
  17858. +
  17859. + return 0;
  17860. +}
  17861. +
  17862. +/* ......................................................................... */
  17863. +
  17864. +static struct file_operations at91wdt_fops =
  17865. +{
  17866. + .owner = THIS_MODULE,
  17867. + .ioctl = at91_wdt_ioctl,
  17868. + .open = at91_wdt_open,
  17869. + .release = at91_wdt_close,
  17870. + .write = at91_wdt_write,
  17871. +};
  17872. +
  17873. +static struct miscdevice at91wdt_miscdev =
  17874. +{
  17875. + .minor = WATCHDOG_MINOR,
  17876. + .name = "watchdog",
  17877. + .fops = &at91wdt_fops,
  17878. +};
  17879. +
  17880. +static int __init at91_wdt_init(void)
  17881. +{
  17882. + int res;
  17883. +
  17884. + res = misc_register(&at91wdt_miscdev);
  17885. + if (res)
  17886. + return res;
  17887. +
  17888. + printk("AT91 Watchdog Timer enabled (%d seconds)\n", WDT_DEFAULT_TIME);
  17889. + return 0;
  17890. +}
  17891. +
  17892. +static void __exit at91_wdt_exit(void)
  17893. +{
  17894. + misc_deregister(&at91wdt_miscdev);
  17895. +}
  17896. +
  17897. +module_init(at91_wdt_init);
  17898. +module_exit(at91_wdt_exit);
  17899. +
  17900. +MODULE_LICENSE("GPL")
  17901. +MODULE_AUTHOR("Andrew Victor")
  17902. +MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200")
  17903. diff -urN linux-2.4.26/drivers/block/Makefile linux-2.4.26-vrs1/drivers/block/Makefile
  17904. --- linux-2.4.26/drivers/block/Makefile 2003-06-13 15:51:32.000000000 +0100
  17905. +++ linux-2.4.26-vrs1/drivers/block/Makefile 2004-01-14 21:32:25.000000000 +0000
  17906. @@ -27,11 +27,17 @@
  17907. obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o
  17908. obj-$(CONFIG_BLK_DEV_XD) += xd.o
  17909. obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
  17910. -obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
  17911. +obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
  17912. obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
  17913. obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
  17914. obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
  17915. subdir-$(CONFIG_PARIDE) += paride
  17916. +ifeq ($(CONFIG_ARCH_ACORN),y)
  17917. +mod-subdirs += ../acorn/block
  17918. +subdir-y += ../acorn/block
  17919. +obj-y += ../acorn/block/acorn-block.o
  17920. +endif
  17921. +
  17922. include $(TOPDIR)/Rules.make
  17923. diff -urN linux-2.4.26/drivers/block/ll_rw_blk.c linux-2.4.26-vrs1/drivers/block/ll_rw_blk.c
  17924. --- linux-2.4.26/drivers/block/ll_rw_blk.c 2004-04-19 11:44:16.000000000 +0100
  17925. +++ linux-2.4.26-vrs1/drivers/block/ll_rw_blk.c 2004-04-18 21:47:50.000000000 +0100
  17926. @@ -32,6 +32,19 @@
  17927. #include <linux/slab.h>
  17928. #include <linux/module.h>
  17929. +/* Maybe something to cleanup in 2.3?
  17930. + * We shouldn't touch 0x3f2 on machines which don't have a PC floppy controller
  17931. + * - it may contain something else which could cause a system hang. This is
  17932. + * now selected by a configuration option, but maybe it ought to be in the
  17933. + * floppy code itself? - rmk
  17934. + */
  17935. +#if defined(__i386__) || (defined(__arm__) && defined(CONFIG_ARCH_ACORN))
  17936. +#define FLOPPY_BOOT_DISABLE
  17937. +#endif
  17938. +#ifdef CONFIG_BLK_DEV_FD
  17939. +#undef FLOPPY_BOOT_DISABLE
  17940. +#endif
  17941. +
  17942. /*
  17943. * MAC Floppy IWM hooks
  17944. */
  17945. @@ -524,7 +537,7 @@
  17946. elevator_init(&q->elevator, ELEVATOR_LINUS);
  17947. blk_init_free_list(q);
  17948. q->request_fn = rfn;
  17949. - q->back_merge_fn = ll_back_merge_fn;
  17950. + q->back_merge_fn = ll_back_merge_fn;
  17951. q->front_merge_fn = ll_front_merge_fn;
  17952. q->merge_requests_fn = ll_merge_requests_fn;
  17953. q->make_request_fn = __make_request;
  17954. @@ -1549,7 +1562,7 @@
  17955. mfm_init();
  17956. #endif
  17957. #ifdef CONFIG_PARIDE
  17958. - { extern void paride_init(void); paride_init(); };
  17959. + { extern void paride_init(void); paride_init(); }
  17960. #endif
  17961. #ifdef CONFIG_MAC_FLOPPY
  17962. swim3_init();
  17963. @@ -1563,12 +1576,14 @@
  17964. #ifdef CONFIG_ATARI_FLOPPY
  17965. atari_floppy_init();
  17966. #endif
  17967. +#ifdef CONFIG_BLK_DEV_FD1772
  17968. + fd1772_init();
  17969. +#endif
  17970. #ifdef CONFIG_BLK_DEV_FD
  17971. floppy_init();
  17972. -#else
  17973. -#if defined(__i386__) /* Do we even need this? */
  17974. - outb_p(0xc, 0x3f2);
  17975. #endif
  17976. +#ifdef FLOPPY_BOOT_DISABLE
  17977. + outb_p(0xc, 0x3f2);
  17978. #endif
  17979. #ifdef CONFIG_CDU31A
  17980. cdu31a_init();
  17981. @@ -1626,7 +1641,7 @@
  17982. jsfd_init();
  17983. #endif
  17984. return 0;
  17985. -};
  17986. +}
  17987. EXPORT_SYMBOL(io_request_lock);
  17988. EXPORT_SYMBOL(end_that_request_first);
  17989. diff -urN linux-2.4.26/drivers/cdrom/cdrom.c linux-2.4.26-vrs1/drivers/cdrom/cdrom.c
  17990. --- linux-2.4.26/drivers/cdrom/cdrom.c 2003-11-28 18:26:20.000000000 +0000
  17991. +++ linux-2.4.26-vrs1/drivers/cdrom/cdrom.c 2004-01-14 21:38:59.000000000 +0000
  17992. @@ -246,8 +246,8 @@
  17993. #define CD_DVD 0x80
  17994. /* Define this to remove _all_ the debugging messages */
  17995. -/* #define ERRLOGMASK CD_NOTHING */
  17996. -#define ERRLOGMASK (CD_WARNING)
  17997. +#define ERRLOGMASK CD_NOTHING
  17998. +/* #define ERRLOGMASK (CD_WARNING) */
  17999. /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
  18000. /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
  18001. diff -urN linux-2.4.26/drivers/char/Config.in linux-2.4.26-vrs1/drivers/char/Config.in
  18002. --- linux-2.4.26/drivers/char/Config.in 2004-02-27 20:03:25.000000000 +0000
  18003. +++ linux-2.4.26-vrs1/drivers/char/Config.in 2004-04-10 12:04:15.000000000 +0100
  18004. @@ -20,10 +20,10 @@
  18005. if [ "$CONFIG_IA64" = "y" ]; then
  18006. bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP
  18007. fi
  18008. - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
  18009. - tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
  18010. - tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
  18011. - fi
  18012. +fi
  18013. +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
  18014. + dep_tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_SERIAL
  18015. + dep_tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL $CONFIG_SERIAL
  18016. fi
  18017. dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
  18018. if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
  18019. @@ -132,18 +132,6 @@
  18020. bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL
  18021. fi
  18022. fi
  18023. -fi
  18024. -if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
  18025. - tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
  18026. -fi
  18027. -if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
  18028. - bool 'DC21285 serial port support' CONFIG_SERIAL_21285
  18029. - if [ "$CONFIG_SERIAL_21285" = "y" ]; then
  18030. - if [ "$CONFIG_OBSOLETE" = "y" ]; then
  18031. - bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD
  18032. - fi
  18033. - bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE
  18034. - fi
  18035. if [ "$CONFIG_PARISC" = "y" ]; then
  18036. bool ' PDC software console support' CONFIG_PDC_CONSOLE
  18037. fi
  18038. @@ -168,6 +156,16 @@
  18039. if [ "$CONFIG_CPU_VR41XX" = "y" ]; then
  18040. bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU
  18041. fi
  18042. +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  18043. + tristate 'AT91RM9200 SPI device interface' CONFIG_AT91_SPIDEV
  18044. +fi
  18045. +
  18046. +source drivers/serial/Config.in
  18047. +
  18048. +if [ "$CONFIG_ARCH_ANAKIN" = "y" ]; then
  18049. + tristate 'Anakin touchscreen support' CONFIG_TOUCHSCREEN_ANAKIN
  18050. +fi
  18051. +
  18052. bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
  18053. if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
  18054. int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
  18055. @@ -190,6 +188,12 @@
  18056. source drivers/i2c/Config.in
  18057. +if [ "$CONFIG_I2C" != "n" ]; then
  18058. + dep_tristate ' DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C
  18059. +fi
  18060. +
  18061. +source drivers/l3/Config.in
  18062. +
  18063. mainmenu_option next_comment
  18064. comment 'Mice'
  18065. tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
  18066. @@ -245,11 +249,13 @@
  18067. tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT
  18068. tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT
  18069. tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
  18070. - if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
  18071. - tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG
  18072. - if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
  18073. - tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG
  18074. - fi
  18075. + if [ "$CONFIG_ARM" = "y" ]; then
  18076. + dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
  18077. + dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
  18078. + dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
  18079. + dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
  18080. + dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
  18081. + dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
  18082. fi
  18083. tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
  18084. tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
  18085. @@ -326,6 +332,15 @@
  18086. if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then
  18087. tristate 'Dallas DS1742 RTC support' CONFIG_DS1742
  18088. fi
  18089. +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
  18090. + tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
  18091. +fi
  18092. +if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
  18093. + tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
  18094. +fi
  18095. +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  18096. + tristate 'AT91RM9200 Real Time Clock' CONFIG_AT91_RTC
  18097. +fi
  18098. tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
  18099. tristate 'Siemens R3964 line discipline' CONFIG_R3964
  18100. diff -urN linux-2.4.26/drivers/char/Makefile linux-2.4.26-vrs1/drivers/char/Makefile
  18101. --- linux-2.4.26/drivers/char/Makefile 2004-02-27 20:03:25.000000000 +0000
  18102. +++ linux-2.4.26-vrs1/drivers/char/Makefile 2004-04-10 12:07:34.000000000 +0100
  18103. @@ -29,7 +29,7 @@
  18104. mod-subdirs := joystick ftape drm drm-4.0 pcmcia
  18105. -list-multi :=
  18106. +list-multi :=
  18107. KEYMAP =defkeymap.o
  18108. KEYBD =pc_keyb.o
  18109. @@ -106,11 +106,39 @@
  18110. endif
  18111. ifeq ($(ARCH),arm)
  18112. - ifneq ($(CONFIG_PC_KEYMAP),y)
  18113. - KEYMAP =
  18114. + KEYMAP :=
  18115. + KEYBD :=
  18116. + ifeq ($(CONFIG_PC_KEYMAP),y)
  18117. + KEYMAP := defkeymap.o
  18118. endif
  18119. - ifneq ($(CONFIG_PC_KEYB),y)
  18120. - KEYBD =
  18121. + ifeq ($(CONFIG_PC_KEYB),y)
  18122. + KEYBD += pc_keyb.o
  18123. + endif
  18124. + ifeq ($(CONFIG_KMI_KEYB),y)
  18125. + KEYBD += amba_kmi_keyb.o
  18126. + endif
  18127. + ifeq ($(CONFIG_SA1111),y)
  18128. + KEYBD += sa1111_keyb.o
  18129. + endif
  18130. + ifeq ($(CONFIG_ARCH_EDB7211),y)
  18131. + KEYBD += edb7211_keyb.o
  18132. + endif
  18133. + ifeq ($(CONFIG_ARCH_AUTCPU12),y)
  18134. + KEYMAP := defkeymap.o
  18135. + KEYBD += clps711x_keyb.o
  18136. + endif
  18137. + ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
  18138. + KEYMAP = gckeymap.o
  18139. + KEYBD += gc_keyb.o
  18140. + endif
  18141. + ifeq ($(CONFIG_SA1100_CERF_CPLD),y)
  18142. + KEYBD += cerf_keyb.o
  18143. + endif
  18144. + ifeq ($(CONFIG_ARCH_FORTUNET),y)
  18145. + KEYMAP := defkeymap.o
  18146. + endif
  18147. + ifeq ($(CONFIG_ARCH_GUIDEA07),y)
  18148. + KEYMAP := defkeymap.o
  18149. endif
  18150. endif
  18151. @@ -172,11 +200,9 @@
  18152. obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
  18153. obj-$(CONFIG_SERIAL) += $(SERIAL)
  18154. obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
  18155. -obj-$(CONFIG_SERIAL_21285) += serial_21285.o
  18156. -obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
  18157. -obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o
  18158. obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o
  18159. obj-$(CONFIG_SERIAL_DEC) += decserial.o
  18160. +obj-$(CONFIG_TOUCHSCREEN_ANAKIN) += anakin_ts.o
  18161. ifndef CONFIG_SUN_KEYBOARD
  18162. obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
  18163. @@ -253,6 +279,8 @@
  18164. obj-$(CONFIG_SGI_DS1286) += ds1286.o
  18165. obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
  18166. obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
  18167. +obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
  18168. +obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
  18169. ifeq ($(CONFIG_PPC),)
  18170. obj-$(CONFIG_NVRAM) += nvram.o
  18171. endif
  18172. @@ -291,6 +319,7 @@
  18173. obj-$(CONFIG_NWFLASH) += nwflash.o
  18174. obj-$(CONFIG_SCx200) += scx200.o
  18175. obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
  18176. +obj-$(CONFIG_SA1100_CONSUS) += consusbutton.o
  18177. # Only one watchdog can succeed. We probe the hardware watchdog
  18178. # drivers first, then the softdog driver. This means if your hardware
  18179. @@ -319,16 +348,28 @@
  18180. obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
  18181. obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
  18182. obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
  18183. +obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
  18184. +obj-$(CONFIG_EPXA_WATCHDOG) += epxa_wdt.o
  18185. +obj-$(CONFIG_OMAHA_WATCHDOG) += omaha_wdt.o
  18186. obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
  18187. obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o
  18188. obj-$(CONFIG_INDYDOG) += indydog.o
  18189. obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
  18190. +# I2C char devices
  18191. +obj-$(CONFIG_I2C_DS1307) += ds1307.o
  18192. +
  18193. subdir-$(CONFIG_MWAVE) += mwave
  18194. ifeq ($(CONFIG_MWAVE),y)
  18195. obj-y += mwave/mwave.o
  18196. endif
  18197. +ifeq ($(CONFIG_ARCH_ACORN),y)
  18198. +mod-subdirs += ../acorn/char
  18199. +subdir-y += ../acorn/char
  18200. +obj-y += ../acorn/char/acorn-char.o
  18201. +endif
  18202. +
  18203. subdir-$(CONFIG_IPMI_HANDLER) += ipmi
  18204. ifeq ($(CONFIG_IPMI_HANDLER),y)
  18205. obj-y += ipmi/ipmi.o
  18206. diff -urN linux-2.4.26/drivers/char/amba_kmi_keyb.c linux-2.4.26-vrs1/drivers/char/amba_kmi_keyb.c
  18207. --- linux-2.4.26/drivers/char/amba_kmi_keyb.c 1970-01-01 01:00:00.000000000 +0100
  18208. +++ linux-2.4.26-vrs1/drivers/char/amba_kmi_keyb.c 2004-01-14 21:32:25.000000000 +0000
  18209. @@ -0,0 +1,999 @@
  18210. +/*
  18211. + * linux/drivers/char/amba_kmi_keyb.c
  18212. + *
  18213. + * AMBA Keyboard and Mouse Interface Driver
  18214. + *
  18215. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  18216. + *
  18217. + * This program is free software; you can redistribute it and/or modify
  18218. + * it under the terms of the GNU General Public License as published by
  18219. + * the Free Software Foundation; either version 2 of the License, or
  18220. + * (at your option) any later version.
  18221. + *
  18222. + * This program is distributed in the hope that it will be useful,
  18223. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18224. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18225. + * GNU General Public License for more details.
  18226. + *
  18227. + * You should have received a copy of the GNU General Public License
  18228. + * along with this program; if not, write to the Free Software
  18229. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18230. + *
  18231. + * This keyboard driver drives a PS/2 keyboard and mouse connected
  18232. + * to the KMI interfaces. The KMI interfaces are nothing more than
  18233. + * a uart; there is no inteligence in them to do keycode translation.
  18234. + * We leave all that up to the keyboard itself.
  18235. + *
  18236. + * FIXES:
  18237. + * dirk.uffmann@nokia.com: enabled PS/2 reconnection
  18238. + */
  18239. +#include <linux/config.h>
  18240. +#include <linux/kernel.h>
  18241. +#include <linux/sched.h>
  18242. +#include <linux/interrupt.h> /* for in_interrupt */
  18243. +#include <linux/timer.h>
  18244. +#include <linux/init.h>
  18245. +#include <linux/delay.h> /* for udelay */
  18246. +#include <linux/kbd_kern.h> /* for keyboard_tasklet */
  18247. +#include <linux/kbd_ll.h>
  18248. +
  18249. +#include <asm/io.h>
  18250. +#include <asm/hardware/amba_kmi.h>
  18251. +#include <asm/mach/amba_kmi.h>
  18252. +#include <asm/keyboard.h>
  18253. +
  18254. +//#define DEBUG(s) printk s
  18255. +#define DEBUG(s) do { } while (0)
  18256. +
  18257. +#define CONFIG_AMBA_PS2_RECONNECT
  18258. +
  18259. +#define KMI_BASE (kmi->base)
  18260. +
  18261. +#define KMI_RESET 0x00
  18262. +#define KMI_RESET_POR 0x01
  18263. +#define KMI_RESET_DONE 0x02
  18264. +
  18265. +#define KMI_NO_ACK 0xffff
  18266. +
  18267. +#define PS2_O_RESET 0xff
  18268. +#define PS2_O_RESEND 0xfe
  18269. +#define PS2_O_DISABLE 0xf5
  18270. +#define PS2_O_ENABLE 0xf4
  18271. +#define PS2_O_ECHO 0xee
  18272. +
  18273. +/*
  18274. + * Keyboard
  18275. + */
  18276. +#define PS2_O_SET_DEFAULT 0xf6
  18277. +#define PS2_O_SET_RATE_DELAY 0xf3
  18278. +#define PS2_O_SET_SCANSET 0xf0
  18279. +#define PS2_O_INDICATORS 0xed
  18280. +
  18281. +/*
  18282. + * Mouse
  18283. + */
  18284. +#define PS2_O_SET_SAMPLE 0xf3
  18285. +#define PS2_O_SET_STREAM 0xea
  18286. +#define PS2_O_SET_RES 0xe8
  18287. +#define PS2_O_SET_SCALE21 0xe7
  18288. +#define PS2_O_SET_SCALE11 0xe6
  18289. +#define PS2_O_REQ_STATUS 0xe9
  18290. +
  18291. +/*
  18292. + * Responses
  18293. + */
  18294. +#define PS2_I_RESEND 0xfe
  18295. +#define PS2_I_DIAGFAIL 0xfc
  18296. +#define PS2_I_ACK 0xfa
  18297. +#define PS2_I_BREAK 0xf0
  18298. +#define PS2_I_ECHO 0xee
  18299. +#define PS2_I_BAT_OK 0xaa
  18300. +
  18301. +static char *kmi_type[] = { "Keyboard", "Mouse" };
  18302. +
  18303. +static struct kmi_info *kmi_keyb;
  18304. +static struct kmi_info *kmi_mouse;
  18305. +
  18306. +static inline void __kmi_send(struct kmi_info *kmi, u_int val)
  18307. +{
  18308. + u_int status;
  18309. +
  18310. + do {
  18311. + status = __raw_readb(KMISTAT);
  18312. + } while (!(status & KMISTAT_TXEMPTY));
  18313. +
  18314. + kmi->resend_count += 1;
  18315. + __raw_writeb(val, KMIDATA);
  18316. +}
  18317. +
  18318. +static void kmi_send(struct kmi_info *kmi, u_int val)
  18319. +{
  18320. + kmi->last_tx = val;
  18321. + kmi->resend_count = -1;
  18322. + __kmi_send(kmi, val);
  18323. +}
  18324. +
  18325. +static u_int kmi_send_and_wait(struct kmi_info *kmi, u_int val, u_int timeo)
  18326. +{
  18327. + DECLARE_WAITQUEUE(wait, current);
  18328. +
  18329. + if (kmi->present == 0)
  18330. + return KMI_NO_ACK;
  18331. +
  18332. + kmi->res = KMI_NO_ACK;
  18333. + kmi->last_tx = val;
  18334. + kmi->resend_count = -1;
  18335. +
  18336. + if (current->pid != 0 && !in_interrupt()) {
  18337. + add_wait_queue(&kmi->wait_q, &wait);
  18338. + set_current_state(TASK_UNINTERRUPTIBLE);
  18339. + __kmi_send(kmi, val);
  18340. + schedule_timeout(timeo);
  18341. + current->state = TASK_RUNNING;
  18342. + remove_wait_queue(&kmi->wait_q, &wait);
  18343. + } else {
  18344. + int i;
  18345. +
  18346. + __kmi_send(kmi, val);
  18347. + for (i = 0; i < 1000; i++) {
  18348. + if (kmi->res != KMI_NO_ACK)
  18349. + break;
  18350. + udelay(100);
  18351. + }
  18352. + }
  18353. +
  18354. + return kmi->res;
  18355. +}
  18356. +
  18357. +/*
  18358. + * This lot should probably be separated into a separate file...
  18359. + */
  18360. +#ifdef CONFIG_KMI_MOUSE
  18361. +
  18362. +#include <linux/fs.h> /* for struct file_ops */
  18363. +#include <linux/poll.h> /* for poll_table */
  18364. +#include <linux/miscdevice.h> /* for struct miscdev */
  18365. +#include <linux/random.h> /* for add_mouse_randomness */
  18366. +#include <linux/slab.h> /* for kmalloc */
  18367. +#include <linux/smp_lock.h> /* for {un,}lock_kernel */
  18368. +#include <linux/spinlock.h>
  18369. +
  18370. +#include <asm/uaccess.h>
  18371. +
  18372. +#define BUF_SZ 2048
  18373. +
  18374. +static spinlock_t kmi_mouse_lock;
  18375. +static int kmi_mouse_count;
  18376. +static struct queue {
  18377. + u_int head;
  18378. + u_int tail;
  18379. + struct fasync_struct *fasync;
  18380. + unsigned char buf[BUF_SZ];
  18381. +} *queue;
  18382. +
  18383. +#define queue_empty() (queue->head == queue->tail)
  18384. +
  18385. +static u_char get_from_queue(void)
  18386. +{
  18387. + unsigned long flags;
  18388. + u_char res;
  18389. +
  18390. + spin_lock_irqsave(&kmi_mouse_lock, flags);
  18391. + res = queue->buf[queue->tail];
  18392. + queue->tail = (queue->tail + 1) & (BUF_SZ-1);
  18393. + spin_unlock_irqrestore(&kmi_mouse_lock, flags);
  18394. +
  18395. + return res;
  18396. +}
  18397. +
  18398. +static ssize_t
  18399. +kmi_mouse_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  18400. +{
  18401. + ssize_t i = count;
  18402. +
  18403. + if (queue_empty()) {
  18404. + int ret;
  18405. +
  18406. + if (file->f_flags & O_NONBLOCK)
  18407. + return -EAGAIN;
  18408. + ret = wait_event_interruptible(kmi_mouse->wait_q, !queue_empty());
  18409. + if (ret)
  18410. + return ret;
  18411. + }
  18412. + while (i > 0 && !queue_empty()) {
  18413. + u_char c;
  18414. + c = get_from_queue();
  18415. + put_user(c, buf++);
  18416. + i--;
  18417. + }
  18418. + if (count - i)
  18419. + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  18420. + return count - i;
  18421. +}
  18422. +
  18423. +static ssize_t
  18424. +kmi_mouse_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
  18425. +{
  18426. + ssize_t retval = 0;
  18427. +
  18428. + if (count > 32)
  18429. + count = 32;
  18430. +
  18431. + do {
  18432. + char c;
  18433. + get_user(c, buf++);
  18434. + kmi_send_and_wait(kmi_mouse, c, HZ);
  18435. + retval++;
  18436. + } while (--count);
  18437. +
  18438. + if (retval)
  18439. + file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
  18440. +
  18441. + return retval;
  18442. +}
  18443. +
  18444. +static unsigned int
  18445. +kmi_mouse_poll(struct file *file, poll_table *wait)
  18446. +{
  18447. + poll_wait(file, &kmi_mouse->wait_q, wait);
  18448. + return (!queue_empty()) ? POLLIN | POLLRDNORM : 0;
  18449. +}
  18450. +
  18451. +static int
  18452. +kmi_mouse_release(struct inode *inode, struct file *file)
  18453. +{
  18454. + lock_kernel();
  18455. + fasync_helper(-1, file, 0, &queue->fasync);
  18456. + if (--kmi_mouse_count == 0)
  18457. + kmi_send_and_wait(kmi_mouse, PS2_O_DISABLE, HZ);
  18458. + unlock_kernel();
  18459. + return 0;
  18460. +}
  18461. +
  18462. +static int
  18463. +kmi_mouse_open(struct inode *inode, struct file *file)
  18464. +{
  18465. + if (kmi_mouse_count++)
  18466. + return 0;
  18467. + queue->head = queue->tail = 0;
  18468. + kmi_send_and_wait(kmi_mouse, PS2_O_ENABLE, HZ);
  18469. + return 0;
  18470. +}
  18471. +
  18472. +static int
  18473. +kmi_mouse_fasync(int fd, struct file *filp, int on)
  18474. +{
  18475. + int retval = fasync_helper(fd, filp, on, &queue->fasync);
  18476. + if (retval > 0)
  18477. + retval = 0;
  18478. + return retval;
  18479. +}
  18480. +
  18481. +static struct file_operations ps_fops = {
  18482. + read: kmi_mouse_read,
  18483. + write: kmi_mouse_write,
  18484. + poll: kmi_mouse_poll,
  18485. + open: kmi_mouse_open,
  18486. + release: kmi_mouse_release,
  18487. + fasync: kmi_mouse_fasync,
  18488. +};
  18489. +
  18490. +static struct miscdevice ps_mouse = {
  18491. + minor: PSMOUSE_MINOR,
  18492. + name: "psaux",
  18493. + fops: &ps_fops,
  18494. +};
  18495. +
  18496. +static u_char kmi_mse_init_string[] = {
  18497. + PS2_O_DISABLE,
  18498. + PS2_O_SET_SAMPLE, 100,
  18499. + PS2_O_SET_RES, 3,
  18500. + PS2_O_SET_SCALE21
  18501. +};
  18502. +
  18503. +/*
  18504. + * The "normal" mouse scancode processing
  18505. + */
  18506. +static void kmi_mse_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
  18507. +{
  18508. + u_int head;
  18509. +
  18510. + add_mouse_randomness(val);
  18511. +
  18512. +#ifdef CONFIG_AMBA_PS2_RECONNECT
  18513. + /* Try to detect a hot-plug event on the PS/2 mouse port */
  18514. + switch (kmi->hotplug_state) {
  18515. + case 0:
  18516. + /* Maybe we lost contact... */
  18517. + if (val == PS2_I_BAT_OK) {
  18518. + kmi->hotplug_state++;
  18519. + DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
  18520. + }
  18521. + break;
  18522. +
  18523. + case 1:
  18524. + /* Again, maybe (but only maybe) we lost contact... */
  18525. + if (val == 0) {
  18526. + kmi->hotplug_state++;
  18527. + kmi_send(kmi, PS2_O_REQ_STATUS);
  18528. + DEBUG(("%s: Got 0xAA 0x00. Sent Status Request\n", kmi->name));
  18529. + } else {
  18530. + kmi->hotplug_state = 0;
  18531. + DEBUG(("%s: No 0x00 followed 0xAA. No reconnect.\n", kmi->name));
  18532. + }
  18533. + break;
  18534. +
  18535. + case 2:
  18536. + /* Eat up acknowledge */
  18537. + if (val == PS2_I_ACK)
  18538. + kmi->hotplug_state++;
  18539. + else {
  18540. + kmi->hotplug_state = 0;
  18541. + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
  18542. + }
  18543. + break;
  18544. +
  18545. + case 3:
  18546. + /* check if data reporting is still enabled, then no POR has happend */
  18547. + kmi->reconnect = !(val & 1<<5);
  18548. + DEBUG(("%s: Data reporting disabled?: (%d)\n", kmi->name, kmi->reconnect));
  18549. + kmi->hotplug_state++;
  18550. + DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
  18551. + break;
  18552. +
  18553. + case 4:
  18554. + /* Eat up one status byte */
  18555. + kmi->hotplug_state++;
  18556. + DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
  18557. + break;
  18558. +
  18559. + case 5:
  18560. + /* Eat up another status byte */
  18561. + if (kmi->reconnect) {
  18562. + kmi->config_num = 0;
  18563. + kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
  18564. + kmi->config_num++;
  18565. + kmi->hotplug_state++;
  18566. + DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
  18567. + } else {
  18568. + kmi->hotplug_state = 0;
  18569. + DEBUG(("%s: False Alarm...\n", kmi->name));
  18570. + }
  18571. + break;
  18572. +
  18573. + case 6:
  18574. + if (val == PS2_I_ACK && kmi->config_num < sizeof(kmi_mse_init_string)) {
  18575. + kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
  18576. + kmi->config_num++;
  18577. + DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
  18578. + } else {
  18579. + if (val == PS2_I_ACK) {
  18580. + DEBUG(("%s: Now enable the mouse again...\n", kmi->name));
  18581. + queue->head = queue->tail = 0;
  18582. + kmi_send(kmi, PS2_O_ENABLE);
  18583. + kmi->hotplug_state++;
  18584. + } else {
  18585. + kmi->hotplug_state = 0;
  18586. + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
  18587. + }
  18588. + }
  18589. + break;
  18590. +
  18591. + case 7:
  18592. + /* Eat up last acknowledge from enable */
  18593. + if (val == PS2_I_ACK)
  18594. + printk(KERN_ERR "%s: reconnected\n", kmi->name);
  18595. + else
  18596. + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
  18597. +
  18598. + kmi->hotplug_state = 0;
  18599. + break;
  18600. +
  18601. + } /* switch (kmi->hotplug_state) */
  18602. +
  18603. + /* while inside hotplug mechanism, don't misinterpret values */
  18604. + if (kmi->hotplug_state > 2)
  18605. + return;
  18606. +#endif
  18607. +
  18608. + /* We are waiting for the mouse to respond to a kmi_send_and_wait() */
  18609. + if (kmi->res == KMI_NO_ACK) {
  18610. + if (val == PS2_I_RESEND) {
  18611. + if (kmi->resend_count < 5)
  18612. + __kmi_send(kmi, kmi->last_tx);
  18613. + else {
  18614. + printk(KERN_ERR "%s: too many resends\n", kmi->name);
  18615. + return;
  18616. + }
  18617. + }
  18618. +
  18619. + if (val == PS2_I_ACK) {
  18620. + kmi->res = val;
  18621. + wake_up(&kmi->wait_q);
  18622. + }
  18623. + return;
  18624. + }
  18625. +
  18626. + /* The mouse autonomously send new data, so wake up mouse_read() */
  18627. + if (queue) {
  18628. + head = queue->head;
  18629. + queue->buf[head] = val;
  18630. + head = (head + 1) & (BUF_SZ - 1);
  18631. + if (head != queue->tail) {
  18632. + queue->head = head;
  18633. + kill_fasync(&queue->fasync, SIGIO, POLL_IN);
  18634. + wake_up_interruptible(&kmi->wait_q);
  18635. + }
  18636. + }
  18637. +}
  18638. +
  18639. +static int kmi_init_mouse(struct kmi_info *kmi)
  18640. +{
  18641. + u_int ret, i;
  18642. +
  18643. + if (kmi->present) {
  18644. + kmi->rx = kmi_mse_intr;
  18645. +
  18646. + for (i = 0; i < sizeof(kmi_mse_init_string); i++) {
  18647. + ret = kmi_send_and_wait(kmi, kmi_mse_init_string[i], HZ);
  18648. + if (ret != PS2_I_ACK)
  18649. + printk("%s: didn't get ack (0x%2.2x)\n",
  18650. + kmi->name, ret);
  18651. + }
  18652. + }
  18653. +
  18654. + queue = kmalloc(sizeof(*queue), GFP_KERNEL);
  18655. + if (queue) {
  18656. + memset(queue, 0, sizeof(*queue));
  18657. + misc_register(&ps_mouse);
  18658. + ret = 0;
  18659. + } else
  18660. + ret = -ENOMEM;
  18661. +
  18662. + return ret;
  18663. +}
  18664. +#endif /* CONFIG_KMI_MOUSE */
  18665. +
  18666. +/*
  18667. + * The "program" we send to the keyboard to set it up how we want it:
  18668. + * - default typematic delays
  18669. + * - scancode set 1
  18670. + */
  18671. +static u_char kmi_kbd_init_string[] = {
  18672. + PS2_O_DISABLE,
  18673. + PS2_O_SET_DEFAULT,
  18674. + PS2_O_SET_SCANSET, 0x01,
  18675. + PS2_O_ENABLE
  18676. +};
  18677. +
  18678. +static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs);
  18679. +
  18680. +static int __kmi_init_keyboard(struct kmi_info *kmi)
  18681. +{
  18682. + u_int ret, i;
  18683. +
  18684. + if (!kmi->present)
  18685. + return 0;
  18686. +
  18687. + kmi->rx = kmi_kbd_intr;
  18688. +
  18689. + for (i = 0; i < sizeof(kmi_kbd_init_string); i++) {
  18690. + ret = kmi_send_and_wait(kmi, kmi_kbd_init_string[i], HZ);
  18691. + if (ret != PS2_I_ACK)
  18692. + printk("%s: didn't ack (0x%2.2x)\n",
  18693. + kmi->name, ret);
  18694. + }
  18695. +
  18696. + return 0;
  18697. +}
  18698. +
  18699. +static void kmi_kbd_init_tasklet(unsigned long k)
  18700. +{
  18701. + struct kmi_info *kmi = (struct kmi_info *)k;
  18702. + __kmi_init_keyboard(kmi);
  18703. +}
  18704. +
  18705. +static DECLARE_TASKLET_DISABLED(kmikbd_init_tasklet, kmi_kbd_init_tasklet, 0);
  18706. +
  18707. +/*
  18708. + * The "normal" keyboard scancode processing
  18709. + */
  18710. +static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
  18711. +{
  18712. +#ifdef CONFIG_AMBA_PS2_RECONNECT
  18713. + /* Try to detect a hot-plug event on the PS/2 keyboard port */
  18714. + switch (kmi->hotplug_state) {
  18715. + case 0:
  18716. + /* Maybe we lost contact... */
  18717. + if (val == PS2_I_BAT_OK) {
  18718. + kmi_send(kmi, PS2_O_SET_SCANSET);
  18719. + kmi->hotplug_state++;
  18720. + DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
  18721. + }
  18722. + break;
  18723. +
  18724. + case 1:
  18725. + /* Eat up acknowledge */
  18726. + if (val == PS2_I_ACK) {
  18727. + /* Request scan code set: '2' if POR has happend, '1' is false alarm */
  18728. + kmi_send(kmi, 0);
  18729. + kmi->hotplug_state++;
  18730. + }
  18731. + else {
  18732. + kmi->hotplug_state = 0;
  18733. + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
  18734. + }
  18735. + break;
  18736. +
  18737. + case 2:
  18738. + /* Eat up acknowledge */
  18739. + if (val == PS2_I_ACK)
  18740. + kmi->hotplug_state++;
  18741. + else {
  18742. + kmi->hotplug_state = 0;
  18743. + DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
  18744. + }
  18745. + break;
  18746. +
  18747. + case 3:
  18748. + kmi->hotplug_state = 0;
  18749. + if (val == 2) {
  18750. + DEBUG(("%s: POR detected. Scan code is: (%d)\n", kmi->name, val));
  18751. + kmi->present = 1;
  18752. + tasklet_schedule(&kmikbd_init_tasklet);
  18753. + printk(KERN_ERR "%s: reconnected\n", kmi->name);
  18754. + return;
  18755. + }
  18756. + else
  18757. + DEBUG(("%s: False Alarm...\n", kmi->name));
  18758. + break;
  18759. +
  18760. + } /* switch (kmi->hotplug_state) */
  18761. +#endif
  18762. +
  18763. + if (val == PS2_I_DIAGFAIL) {
  18764. + printk(KERN_ERR "%s: diagnostic failed\n", kmi->name);
  18765. + return;
  18766. + }
  18767. +
  18768. + /* We are waiting for the keyboard to respond to a kmi_send_and_wait() */
  18769. + if (kmi->res == KMI_NO_ACK) {
  18770. + if (val == PS2_I_RESEND) {
  18771. + if (kmi->resend_count < 5)
  18772. + __kmi_send(kmi, kmi->last_tx);
  18773. + else {
  18774. + printk(KERN_ERR "%s: too many resends\n", kmi->name);
  18775. + return;
  18776. + }
  18777. + }
  18778. +
  18779. + if (val >= 0xee) {
  18780. + kmi->res = val;
  18781. + wake_up(&kmi->wait_q);
  18782. + }
  18783. + return;
  18784. + }
  18785. +
  18786. +#ifdef CONFIG_VT
  18787. + kbd_pt_regs = regs;
  18788. + handle_scancode(val, !(val & 0x80));
  18789. + tasklet_schedule(&keyboard_tasklet);
  18790. +#endif
  18791. +}
  18792. +
  18793. +static void kmi_intr(int nr, void *devid, struct pt_regs *regs)
  18794. +{
  18795. + struct kmi_info *kmi = devid;
  18796. + u_int status = __raw_readb(KMIIR);
  18797. +
  18798. + if (status & KMIIR_RXINTR) {
  18799. + u_int val = __raw_readb(KMIDATA);
  18800. +
  18801. + if (kmi->rx)
  18802. + kmi->rx(kmi, val, regs);
  18803. + }
  18804. +}
  18805. +
  18806. +static int kmi_init_keyboard(struct kmi_info *kmi)
  18807. +{
  18808. + kmikbd_init_tasklet.data = (unsigned long)kmi;
  18809. + tasklet_enable(&kmikbd_init_tasklet);
  18810. +
  18811. + return __kmi_init_keyboard(kmi);
  18812. +}
  18813. +
  18814. +/*
  18815. + * Reset interrupt handler
  18816. + */
  18817. +static void __init
  18818. +kmi_reset_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
  18819. +{
  18820. + if (kmi->state == KMI_RESET) {
  18821. + if (val == PS2_I_ACK)
  18822. + kmi->state = KMI_RESET_POR;
  18823. + else {
  18824. + val = KMI_NO_ACK;
  18825. + goto finished;
  18826. + }
  18827. + } else if (kmi->state == KMI_RESET_POR) {
  18828. +finished:
  18829. + kmi->res = val;
  18830. + kmi->state = KMI_RESET_DONE;
  18831. + kmi->rx = NULL;
  18832. + wake_up(&kmi->wait_q);
  18833. + }
  18834. +}
  18835. +
  18836. +/*
  18837. + * Reset the device plugged into this interface
  18838. + */
  18839. +static int __init kmi_reset(struct kmi_info *kmi)
  18840. +{
  18841. + u_int res;
  18842. + int ret = 0;
  18843. +
  18844. + kmi->state = KMI_RESET;
  18845. + kmi->rx = kmi_reset_intr;
  18846. + res = kmi_send_and_wait(kmi, PS2_O_RESET, HZ);
  18847. + kmi->rx = NULL;
  18848. +
  18849. + if (res != PS2_I_BAT_OK) {
  18850. + printk(KERN_ERR "%s: reset failed; ", kmi->name);
  18851. + if (kmi->res != KMI_NO_ACK)
  18852. + printk("code 0x%2.2x\n", kmi->res);
  18853. + else
  18854. + printk("no ack\n");
  18855. + ret = -EINVAL;
  18856. + }
  18857. + return ret;
  18858. +}
  18859. +
  18860. +static int __init kmi_init_one_interface(struct kmi_info *kmi)
  18861. +{
  18862. + u_int stat;
  18863. + int ret = -ENODEV;
  18864. +
  18865. + init_waitqueue_head(&kmi->wait_q);
  18866. +
  18867. + printk(KERN_INFO "%s at 0x%8.8x on irq %d (%s)\n", kmi->name,
  18868. + kmi->base, kmi->irq, kmi_type[kmi->type]);
  18869. +
  18870. + /*
  18871. + * Initialise the KMI interface
  18872. + */
  18873. + __raw_writeb(kmi->divisor, KMICLKDIV);
  18874. + __raw_writeb(KMICR_EN, KMICR);
  18875. +
  18876. + /*
  18877. + * Check that the data and clock lines are OK.
  18878. + */
  18879. + stat = __raw_readb(KMISTAT);
  18880. + if ((stat & (KMISTAT_IC|KMISTAT_ID)) != (KMISTAT_IC|KMISTAT_ID)) {
  18881. + printk(KERN_ERR "%s: %s%s%sline%s stuck low\n", kmi->name,
  18882. + (stat & KMISTAT_IC) ? "" : "clock ",
  18883. + (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "and ",
  18884. + (stat & KMISTAT_ID) ? "" : "data ",
  18885. + (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "s");
  18886. + goto bad;
  18887. + }
  18888. +
  18889. + /*
  18890. + * Claim the appropriate interrupts
  18891. + */
  18892. + ret = request_irq(kmi->irq, kmi_intr, 0, kmi->name, kmi);
  18893. + if (ret)
  18894. + goto bad;
  18895. +
  18896. + /*
  18897. + * Enable the receive interrupt, and reset the device.
  18898. + */
  18899. + __raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
  18900. + kmi->present = 1;
  18901. + kmi->present = kmi_reset(kmi) == 0;
  18902. +
  18903. + switch (kmi->type) {
  18904. + case KMI_KEYBOARD:
  18905. + ret = kmi_init_keyboard(kmi);
  18906. + break;
  18907. +
  18908. +#ifdef CONFIG_KMI_MOUSE
  18909. + case KMI_MOUSE:
  18910. + ret = kmi_init_mouse(kmi);
  18911. + break;
  18912. +#endif
  18913. + }
  18914. +
  18915. + return ret;
  18916. +
  18917. +bad:
  18918. + /*
  18919. + * Oh dear, the interface was bad, disable it.
  18920. + */
  18921. + __raw_writeb(0, KMICR);
  18922. + return ret;
  18923. +}
  18924. +
  18925. +#ifdef CONFIG_VT
  18926. +/*
  18927. + * The fragment between #ifdef above and #endif * CONFIG_VT *
  18928. + * is from the pc_keyb.c driver. It is not copyrighted under the
  18929. + * above notice. This code is by various authors; please see
  18930. + * drivers/char/pc_keyb.c for further information.
  18931. + */
  18932. +
  18933. +/*
  18934. + * Translation of escaped scancodes to keycodes.
  18935. + * This is now user-settable.
  18936. + * The keycodes 1-88,96-111,119 are fairly standard, and
  18937. + * should probably not be changed - changing might confuse X.
  18938. + * X also interprets scancode 0x5d (KEY_Begin).
  18939. + *
  18940. + * For 1-88 keycode equals scancode.
  18941. + */
  18942. +
  18943. +#define E0_KPENTER 96
  18944. +#define E0_RCTRL 97
  18945. +#define E0_KPSLASH 98
  18946. +#define E0_PRSCR 99
  18947. +#define E0_RALT 100
  18948. +#define E0_BREAK 101 /* (control-pause) */
  18949. +#define E0_HOME 102
  18950. +#define E0_UP 103
  18951. +#define E0_PGUP 104
  18952. +#define E0_LEFT 105
  18953. +#define E0_RIGHT 106
  18954. +#define E0_END 107
  18955. +#define E0_DOWN 108
  18956. +#define E0_PGDN 109
  18957. +#define E0_INS 110
  18958. +#define E0_DEL 111
  18959. +
  18960. +#define E1_PAUSE 119
  18961. +
  18962. +/* BTC */
  18963. +#define E0_MACRO 112
  18964. +/* LK450 */
  18965. +#define E0_F13 113
  18966. +#define E0_F14 114
  18967. +#define E0_HELP 115
  18968. +#define E0_DO 116
  18969. +#define E0_F17 117
  18970. +#define E0_KPMINPLUS 118
  18971. +/*
  18972. + * My OmniKey generates e0 4c for the "OMNI" key and the
  18973. + * right alt key does nada. [kkoller@nyx10.cs.du.edu]
  18974. + */
  18975. +#define E0_OK 124
  18976. +/*
  18977. + * New microsoft keyboard is rumoured to have
  18978. + * e0 5b (left window button), e0 5c (right window button),
  18979. + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
  18980. + * [or: Windows_L, Windows_R, TaskMan]
  18981. + */
  18982. +#define E0_MSLW 125
  18983. +#define E0_MSRW 126
  18984. +#define E0_MSTM 127
  18985. +
  18986. +static u_char e0_keys[128] = {
  18987. + 0, 0, 0, 0,
  18988. + 0, 0, 0, 0,
  18989. + 0, 0, 0, 0,
  18990. + 0, 0, 0, 0,
  18991. + 0, 0, 0, 0,
  18992. + 0, 0, 0, 0,
  18993. + 0, 0, 0, 0,
  18994. + E0_KPENTER, E0_RCTRL, 0, 0,
  18995. + 0, 0, 0, 0,
  18996. + 0, 0, 0, 0,
  18997. + 0, 0, 0, 0,
  18998. + 0, 0, 0, 0,
  18999. + 0, 0, 0, 0,
  19000. + 0, E0_KPSLASH, 0, E0_PRSCR,
  19001. + E0_RALT, 0, 0, 0,
  19002. + 0, E0_F13, E0_F14, E0_HELP,
  19003. + E0_DO, E0_F17, 0, 0,
  19004. + 0, 0, E0_BREAK, E0_HOME,
  19005. + E0_UP, E0_PGUP, 0, E0_LEFT,
  19006. + E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,
  19007. + E0_DOWN, E0_PGDN, E0_INS, E0_DEL,
  19008. + 0, 0, 0, 0,
  19009. + 0, 0, 0, E0_MSLW,
  19010. + E0_MSRW, E0_MSTM, 0, 0,
  19011. + 0, 0, 0, 0,
  19012. + 0, 0, 0, 0,
  19013. + 0, 0, 0, 0,
  19014. + 0, 0, 0, E0_MACRO,
  19015. + 0, 0, 0, 0,
  19016. + 0, 0, 0, 0,
  19017. + 0, 0, 0, 0,
  19018. + 0, 0, 0, 0
  19019. +};
  19020. +
  19021. +#ifdef CONFIG_MAGIC_SYSRQ
  19022. +u_char kmi_kbd_sysrq_xlate[128] =
  19023. + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
  19024. + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
  19025. + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
  19026. + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
  19027. + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
  19028. + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
  19029. + "\r\000/"; /* 0x60 - 0x6f */
  19030. +#endif
  19031. +
  19032. +int kmi_kbd_setkeycode(u_int scancode, u_int keycode)
  19033. +{
  19034. + if (scancode < 128 || scancode > 255 || keycode > 127)
  19035. + return -EINVAL;
  19036. + e0_keys[scancode - 128] = keycode;
  19037. + return 0;
  19038. +}
  19039. +
  19040. +int kmi_kbd_getkeycode(u_int scancode)
  19041. +{
  19042. + if (scancode < 128 || scancode > 255)
  19043. + return -EINVAL;
  19044. + return e0_keys[scancode - 128];
  19045. +}
  19046. +
  19047. +int kmi_kbd_translate(u_char scancode, u_char *keycode, char raw_mode)
  19048. +{
  19049. + static int prev_scancode = 0;
  19050. +
  19051. + /* special prefix scancodes.. */
  19052. + if (scancode == 0xe0 || scancode == 0xe1) {
  19053. + prev_scancode = scancode;
  19054. + return 0;
  19055. + }
  19056. +
  19057. + /* 0xff is sent by a few keyboards, ignore it. 0x00 is error */
  19058. + if (scancode == 0x00 || scancode == 0xff) {
  19059. + prev_scancode = 0;
  19060. + return 0;
  19061. + }
  19062. +
  19063. + scancode &= 0x7f;
  19064. +
  19065. + if (prev_scancode) {
  19066. + int old_scancode = prev_scancode;
  19067. +
  19068. + prev_scancode = 0;
  19069. + switch (old_scancode) {
  19070. + case 0xe0:
  19071. + /*
  19072. + * The keyboard maintains its own internal caps lock
  19073. + * and num lock status. In caps lock mode, E0 AA
  19074. + * precedes make code and E0 2A follows break code.
  19075. + * In numlock mode, E0 2A precedes make code, and
  19076. + * E0 AA follows break code. We do our own book-
  19077. + * keeping, so we will just ignore these.
  19078. + *
  19079. + * For my keyboard there is no caps lock mode, but
  19080. + * there are both Shift-L and Shift-R modes. The
  19081. + * former mode generates E0 2A / E0 AA pairs, the
  19082. + * latter E0 B6 / E0 36 pairs. So, we should also
  19083. + * ignore the latter. - aeb@cwi.nl
  19084. + */
  19085. + if (scancode == 0x2a || scancode == 0x36)
  19086. + return 0;
  19087. + if (e0_keys[scancode])
  19088. + *keycode = e0_keys[scancode];
  19089. + else {
  19090. + if (!raw_mode)
  19091. + printk(KERN_INFO "kbd: unknown "
  19092. + "scancode e0 %02x\n",
  19093. + scancode);
  19094. + return 0;
  19095. + }
  19096. + break;
  19097. +
  19098. + case 0xe1:
  19099. + if (scancode == 0x1d)
  19100. + prev_scancode = 0x100;
  19101. + else {
  19102. + if (!raw_mode)
  19103. + printk(KERN_INFO "kbd: unknown "
  19104. + "scancode e1 %02x\n",
  19105. + scancode);
  19106. + return 0;
  19107. + }
  19108. + break;
  19109. +
  19110. + case 0x100:
  19111. + if (scancode == 0x45)
  19112. + *keycode = E1_PAUSE;
  19113. + else {
  19114. + if (!raw_mode)
  19115. + printk(KERN_INFO "kbd: unknown "
  19116. + "scan code e1 1d %02x\n",
  19117. + scancode);
  19118. + return 0;
  19119. + }
  19120. + break;
  19121. + }
  19122. + } else
  19123. + *keycode = scancode;
  19124. + return 1;
  19125. +}
  19126. +
  19127. +char kmi_kbd_unexpected_up(u_char keycode)
  19128. +{
  19129. + return 0x80;
  19130. +}
  19131. +
  19132. +void kmi_kbd_leds(u_char leds)
  19133. +{
  19134. + struct kmi_info *kmi = kmi_keyb;
  19135. + u_int ret;
  19136. +
  19137. + if (kmi) {
  19138. + ret = kmi_send_and_wait(kmi, PS2_O_INDICATORS, HZ);
  19139. + if (ret != KMI_NO_ACK)
  19140. + ret = kmi_send_and_wait(kmi, leds, HZ);
  19141. + if (ret == KMI_NO_ACK)
  19142. + kmi->present = 0;
  19143. + }
  19144. +}
  19145. +
  19146. +int __init kmi_kbd_init(void)
  19147. +{
  19148. + int ret = -ENODEV;
  19149. +
  19150. + if (kmi_keyb) {
  19151. + strcpy(kmi_keyb->name, "kmikbd");
  19152. + ret = kmi_init_one_interface(kmi_keyb);
  19153. + }
  19154. +
  19155. + if (ret == 0) {
  19156. + k_setkeycode = kmi_kbd_setkeycode;
  19157. + k_getkeycode = kmi_kbd_getkeycode;
  19158. + k_translate = kmi_kbd_translate;
  19159. + k_unexpected_up = kmi_kbd_unexpected_up;
  19160. + k_leds = kmi_kbd_leds;
  19161. +#ifdef CONFIG_MAGIC_SYSRQ
  19162. + k_sysrq_xlate = kmi_kbd_sysrq_xlate;
  19163. + k_sysrq_key = 0x54;
  19164. +#endif
  19165. + }
  19166. +
  19167. + return ret;
  19168. +}
  19169. +
  19170. +#endif /* CONFIG_VT */
  19171. +
  19172. +int register_kmi(struct kmi_info *kmi)
  19173. +{
  19174. + struct kmi_info **kmip = NULL;
  19175. + int ret;
  19176. +
  19177. + if (kmi->type == KMI_KEYBOARD)
  19178. + kmip = &kmi_keyb;
  19179. + else if (kmi->type == KMI_MOUSE)
  19180. + kmip = &kmi_mouse;
  19181. +
  19182. + ret = -EINVAL;
  19183. + if (kmip) {
  19184. + ret = -EBUSY;
  19185. + if (!*kmip) {
  19186. + *kmip = kmi;
  19187. + ret = 0;
  19188. + }
  19189. + }
  19190. +
  19191. + return ret;
  19192. +}
  19193. +
  19194. +#ifdef CONFIG_KMI_MOUSE
  19195. +static int __init kmi_init(void)
  19196. +{
  19197. + int ret = -ENODEV;
  19198. +
  19199. + if (kmi_mouse) {
  19200. + strcpy(kmi_mouse->name, "kmimouse");
  19201. + ret = kmi_init_one_interface(kmi_mouse);
  19202. + }
  19203. +
  19204. + return ret;
  19205. +}
  19206. +
  19207. +__initcall(kmi_init);
  19208. +#endif
  19209. diff -urN linux-2.4.26/drivers/char/anakin_ts.c linux-2.4.26-vrs1/drivers/char/anakin_ts.c
  19210. --- linux-2.4.26/drivers/char/anakin_ts.c 1970-01-01 01:00:00.000000000 +0100
  19211. +++ linux-2.4.26-vrs1/drivers/char/anakin_ts.c 2004-01-14 21:32:25.000000000 +0000
  19212. @@ -0,0 +1,208 @@
  19213. +/*
  19214. + * linux/drivers/char/anakin_ts.c
  19215. + *
  19216. + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
  19217. + *
  19218. + * This program is free software; you can redistribute it and/or modify
  19219. + * it under the terms of the GNU General Public License version 2 as
  19220. + * published by the Free Software Foundation.
  19221. + *
  19222. + * Changelog:
  19223. + * 18-Apr-2001 TTC Created
  19224. + * 23-Oct-2001 dwmw2 Cleanup
  19225. + */
  19226. +
  19227. +#include <linux/module.h>
  19228. +#include <linux/types.h>
  19229. +#include <linux/wait.h>
  19230. +#include <linux/fs.h>
  19231. +#include <linux/sched.h>
  19232. +#include <linux/poll.h>
  19233. +#include <linux/miscdevice.h>
  19234. +#include <linux/init.h>
  19235. +#include <linux/compiler.h>
  19236. +#include <linux/interrupt.h>
  19237. +
  19238. +#include <asm/io.h>
  19239. +#include <asm/uaccess.h>
  19240. +#include <asm/irq.h>
  19241. +
  19242. +/*
  19243. + * TSBUF_SIZE must be a power of two
  19244. + */
  19245. +#define ANAKIN_TS_MINOR 16
  19246. +#define TSBUF_SIZE 256
  19247. +#define NEXT(index) (((index) + 1) & (TSBUF_SIZE - 1))
  19248. +
  19249. +static unsigned short buffer[TSBUF_SIZE][4];
  19250. +static int head, tail;
  19251. +static DECLARE_WAIT_QUEUE_HEAD(queue);
  19252. +static DECLARE_MUTEX(open_sem);
  19253. +static spinlock_t tailptr_lock = SPIN_LOCK_UNLOCKED;
  19254. +static struct fasync_struct *fasync;
  19255. +
  19256. +/*
  19257. + * Interrupt handler and standard file operations
  19258. + */
  19259. +static void
  19260. +anakin_ts_handler(int irq, void *dev_id, struct pt_regs *regs)
  19261. +{
  19262. + unsigned int status = __raw_readl(IO_BASE + IO_CONTROLLER + 0x24);
  19263. +
  19264. + /*
  19265. + * iPAQ format (u16 pressure, x, y, millisecs)
  19266. + */
  19267. + switch (status >> 20 & 3) {
  19268. + case 0:
  19269. + return;
  19270. + case 2:
  19271. + buffer[head][0] = 0;
  19272. + break;
  19273. + default:
  19274. + buffer[head][0] = 0x7f;
  19275. + }
  19276. +
  19277. + if (unlikely((volatile int)tail == NEXT(head))) {
  19278. + /* Run out of space in the buffer. Move the tail pointer */
  19279. + spin_lock(&tailptr_lock);
  19280. +
  19281. + if ((volatile int)tail == NEXT(head)) {
  19282. + tail = NEXT(NEXT(head));
  19283. + }
  19284. + spin_unlock(&tailptr_lock);
  19285. + }
  19286. +
  19287. + buffer[head][1] = status >> 2 & 0xff;
  19288. + buffer[head][2] = status >> 12 & 0xff;
  19289. + buffer[head][3] = jiffies;
  19290. + mb();
  19291. + head = NEXT(head);
  19292. +
  19293. + wake_up_interruptible(&queue);
  19294. + kill_fasync(&fasync, SIGIO, POLL_IN);
  19295. +
  19296. +}
  19297. +
  19298. +static ssize_t
  19299. +anakin_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
  19300. +{
  19301. + unsigned short data[4];
  19302. + ssize_t written = 0;
  19303. +
  19304. + if (head == tail) {
  19305. + if (filp->f_flags & O_NONBLOCK)
  19306. + return -EAGAIN;
  19307. + if (wait_event_interruptible(queue, (volatile int)head != (volatile int)tail))
  19308. + return -ERESTARTSYS;
  19309. + }
  19310. +
  19311. + while ((volatile int)head != (volatile int)tail && count >= sizeof data) {
  19312. + /* Copy the data out with the spinlock held, so the
  19313. + interrupt can't fill the buffer and move the tail
  19314. + pointer while we're doing it */
  19315. + spin_lock_irq(&tailptr_lock);
  19316. +
  19317. + memcpy(data, buffer[tail], sizeof data);
  19318. + tail = NEXT(tail);
  19319. +
  19320. + spin_unlock_irq(&tailptr_lock);
  19321. +
  19322. + if (copy_to_user(buf, data, sizeof data))
  19323. + return -EFAULT;
  19324. + count -= sizeof data;
  19325. + buf += sizeof data;
  19326. + written += sizeof data;
  19327. + }
  19328. + return written ? written : -EINVAL;
  19329. +}
  19330. +
  19331. +static unsigned int
  19332. +anakin_ts_poll(struct file *filp, poll_table *wait)
  19333. +{
  19334. + poll_wait(filp, &queue, wait);
  19335. + return head != tail ? POLLIN | POLLRDNORM : 0;
  19336. +}
  19337. +
  19338. +static int
  19339. +anakin_ts_ioctl(struct inode *inode, struct file *filp,
  19340. + unsigned int cmd, unsigned long arg)
  19341. +{
  19342. + /*
  19343. + * Future ioctl goes here
  19344. + */
  19345. + return 0;
  19346. +}
  19347. +
  19348. +static int
  19349. +anakin_ts_open(struct inode *inode, struct file *filp)
  19350. +{
  19351. + if (down_trylock(&open_sem))
  19352. + return -EBUSY;
  19353. + return 0;
  19354. +}
  19355. +
  19356. +static int
  19357. +anakin_ts_fasync(int fd, struct file *filp, int on)
  19358. +{
  19359. + return fasync_helper(fd, filp, on, &fasync);
  19360. +}
  19361. +
  19362. +static int
  19363. +anakin_ts_release(struct inode *inode, struct file *filp)
  19364. +{
  19365. + anakin_ts_fasync(-1, filp, 0);
  19366. + up(&open_sem);
  19367. + return 0;
  19368. +}
  19369. +
  19370. +static struct file_operations anakin_ts_fops = {
  19371. + owner: THIS_MODULE,
  19372. + read: anakin_ts_read,
  19373. + poll: anakin_ts_poll,
  19374. + ioctl: anakin_ts_ioctl,
  19375. + open: anakin_ts_open,
  19376. + release: anakin_ts_release,
  19377. + fasync: anakin_ts_fasync,
  19378. +};
  19379. +
  19380. +static struct miscdevice anakin_ts_miscdev = {
  19381. + ANAKIN_TS_MINOR,
  19382. + "anakin_ts",
  19383. + &anakin_ts_fops
  19384. +};
  19385. +
  19386. +/*
  19387. + * Initialization and exit routines
  19388. + */
  19389. +int __init
  19390. +anakin_ts_init(void)
  19391. +{
  19392. + int retval;
  19393. +
  19394. + if ((retval = request_irq(IRQ_TOUCHSCREEN, anakin_ts_handler,
  19395. + SA_INTERRUPT, "anakin_ts", 0))) {
  19396. + printk(KERN_WARNING "anakin_ts: failed to get IRQ\n");
  19397. + return retval;
  19398. + }
  19399. + __raw_writel(1, IO_BASE + IO_CONTROLLER + 8);
  19400. + misc_register(&anakin_ts_miscdev);
  19401. +
  19402. + printk(KERN_NOTICE "Anakin touchscreen driver initialised\n");
  19403. +
  19404. + return 0;
  19405. +}
  19406. +
  19407. +void __exit
  19408. +anakin_ts_exit(void)
  19409. +{
  19410. + __raw_writel(0, IO_BASE + IO_CONTROLLER + 8);
  19411. + free_irq(IRQ_TOUCHSCREEN, 0);
  19412. + misc_deregister(&anakin_ts_miscdev);
  19413. +}
  19414. +
  19415. +module_init(anakin_ts_init);
  19416. +module_exit(anakin_ts_exit);
  19417. +
  19418. +MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
  19419. +MODULE_DESCRIPTION("Anakin touchscreen driver");
  19420. +MODULE_SUPPORTED_DEVICE("touchscreen/anakin");
  19421. diff -urN linux-2.4.26/drivers/char/cerf_keyb.c linux-2.4.26-vrs1/drivers/char/cerf_keyb.c
  19422. --- linux-2.4.26/drivers/char/cerf_keyb.c 1970-01-01 01:00:00.000000000 +0100
  19423. +++ linux-2.4.26-vrs1/drivers/char/cerf_keyb.c 2004-01-14 21:32:25.000000000 +0000
  19424. @@ -0,0 +1,380 @@
  19425. +/*
  19426. + cerf_keyb.c: This is the end. Daniel is writing a device driver!!!
  19427. +*/
  19428. +#include <linux/config.h>
  19429. +
  19430. +#include <linux/spinlock.h>
  19431. +#include <linux/sched.h>
  19432. +#include <linux/interrupt.h>
  19433. +#include <linux/tty.h>
  19434. +#include <linux/mm.h>
  19435. +#include <linux/signal.h>
  19436. +#include <linux/init.h>
  19437. +#include <linux/kbd_ll.h>
  19438. +#include <linux/delay.h>
  19439. +#include <linux/random.h>
  19440. +#include <linux/poll.h>
  19441. +#include <linux/miscdevice.h>
  19442. +#include <linux/slab.h>
  19443. +#include <linux/kbd_kern.h>
  19444. +#include <linux/smp_lock.h>
  19445. +#include <linux/timer.h>
  19446. +
  19447. +#include <asm/keyboard.h>
  19448. +#include <asm/bitops.h>
  19449. +#include <asm/uaccess.h>
  19450. +#include <asm/irq.h>
  19451. +#include <asm/system.h>
  19452. +
  19453. +#include <asm/io.h>
  19454. +
  19455. +#define KBD_REPORT_UNKN
  19456. +
  19457. +#define KBD_REPORT_ERR /* Report keyboard errors */
  19458. +#define KBD_REPORT_UNKN /* Report unknown scan codes */
  19459. +#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */
  19460. +#define KBD_NO_DATA (-1) /* No data */
  19461. +#define KBD_REPEAT_START (0x20)
  19462. +#define KBD_REPEAT_CONTINUE (0x05)
  19463. +#define KBD_KEY_DOWN_MAX (0x10)
  19464. +#define UINT_LEN (20)
  19465. +#define SC_LIM (69)
  19466. +#define KBD_ROWS (5)
  19467. +#define KBD_COLUMNS (8)
  19468. +
  19469. +#define KBD_KEYUP (0x80)
  19470. +#define KBD_MODESCAN (0x7f)
  19471. +#define KBD_CAPSSCAN (0x3a)
  19472. +#define KBD_SHIFTSCAN (0x2a)
  19473. +#define KBD_NUMCURSCAN (0x7c)
  19474. +#define KBD_CTRLSCAN (0x1d)
  19475. +#define KBD_ALTSCAN (0x38)
  19476. +
  19477. +#define KBD_UP_OFF (0)
  19478. +#define KBD_UP_ON (1)
  19479. +#define KBD_DOWN (2)
  19480. +#define KBD_DOWN_HOLD (3)
  19481. +
  19482. +
  19483. +
  19484. +static unsigned char handle_kbd_event(void);
  19485. +static unsigned char kbd_read_input(void);
  19486. +static void column_set(unsigned int column);
  19487. +static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]);
  19488. +
  19489. +static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
  19490. +static struct timer_list kbd_timer;
  19491. +
  19492. +static short mode_ena = 0;
  19493. +static short numcur_ena = 0;
  19494. +static short shift_ena = 0;
  19495. +
  19496. +#define E0_KPENTER 96
  19497. +#define E0_RCTRL 97
  19498. +#define E0_KPSLASH 98
  19499. +#define E0_PRSCR 99
  19500. +#define E0_RALT 100
  19501. +#define E0_BREAK 101 /* (control-pause) */
  19502. +#define E0_HOME 102
  19503. +#define E0_UP 103
  19504. +#define E0_PGUP 104
  19505. +#define E0_LEFT 105
  19506. +#define E0_RIGHT 106
  19507. +#define E0_END 107
  19508. +#define E0_DOWN 108
  19509. +#define E0_PGDN 109
  19510. +#define E0_INS 110
  19511. +#define E0_DEL 111
  19512. +#define E1_PAUSE 119
  19513. +#define E0_MACRO 112
  19514. +#define E0_F13 113
  19515. +#define E0_F14 114
  19516. +#define E0_HELP 115
  19517. +#define E0_DO 116
  19518. +#define E0_F17 117
  19519. +#define E0_KPMINPLUS 118
  19520. +#define E0_OK 124
  19521. +#define E0_MSLW 125
  19522. +#define E0_MSRW 126
  19523. +#define E0_MSTM 127
  19524. +
  19525. +static unsigned char e0_keys[128] = {
  19526. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
  19527. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
  19528. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
  19529. + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
  19530. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
  19531. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
  19532. + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
  19533. + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
  19534. + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
  19535. + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
  19536. + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
  19537. + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
  19538. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
  19539. + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
  19540. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
  19541. + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
  19542. +};
  19543. +
  19544. +static unsigned char cerf_normal_map[KBD_ROWS][KBD_COLUMNS] = {
  19545. + {KBD_ALTSCAN, KBD_MODESCAN, 0x1e, 0x30, 0x2e, 0x20, 0x00, 0x00},
  19546. + {0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x00},
  19547. + {0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x00},
  19548. + {0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x00},
  19549. + {0x2c, KBD_SHIFTSCAN, KBD_CTRLSCAN, 0x39, KBD_NUMCURSCAN, 0x2b, 0x1c, 0x00}
  19550. +};
  19551. +
  19552. +static unsigned char cerf_mode_map[KBD_ROWS][KBD_COLUMNS] = {
  19553. + {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
  19554. + {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, //
  19555. + {0x0d, 0x0c, 0x37, 0x35, 0x0d, 0x48, 0x28, 0x00},
  19556. + {0x01, 0x33, 0x34, 0x00, 0x4b, 0x27, 0x4d, 0x00}, //
  19557. + {0x0f, 0x00, KBD_CAPSSCAN, 0x0e, 0x00, 0x50, 0x00, 0x00}
  19558. +};
  19559. +
  19560. +static unsigned char cerf_numcur_map[KBD_ROWS][KBD_COLUMNS] = {
  19561. + {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
  19562. + {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00},
  19563. + {0x0d, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00},
  19564. + {0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4d, 0x00},
  19565. + {0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00}
  19566. +};
  19567. +
  19568. +static void column_set(unsigned int column)
  19569. +{
  19570. + if (column < 0)
  19571. + {
  19572. + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
  19573. + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
  19574. + }
  19575. + else
  19576. + {
  19577. + if(column < 4)
  19578. + {
  19579. + CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_A, 1 << (column % 4), 0xFF);
  19580. + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
  19581. + }
  19582. + else
  19583. + {
  19584. + CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
  19585. + CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_B, 1 << (column % 4), 0xFF);
  19586. + }
  19587. + }
  19588. +}
  19589. +
  19590. +static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS])
  19591. +{
  19592. + int i, j;
  19593. +
  19594. + for(i = 0; i < KBD_COLUMNS; i++)
  19595. + {
  19596. + column_set(i);
  19597. + udelay(50);
  19598. + for(j = 0; j < KBD_ROWS; j++)
  19599. + {
  19600. + if(mode_ena)
  19601. + codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_mode_map[j][i]?cerf_mode_map[j][i]:cerf_normal_map[j][i]):0;
  19602. + else if(numcur_ena)
  19603. + codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_numcur_map[j][i]?cerf_numcur_map[j][i]:cerf_normal_map[j][i]):0;
  19604. + else
  19605. + codeval[j][i] = (GPLR & (1 << (20 + j)))?cerf_normal_map[j][i]:0;
  19606. + }
  19607. + }
  19608. + column_set(-1);
  19609. +
  19610. + return 0;
  19611. +}
  19612. +
  19613. +static unsigned char kbd_read_input(void)
  19614. +{
  19615. + int i, j, k, l;
  19616. + unsigned char prev;
  19617. + static unsigned char count = 0;
  19618. +
  19619. + static unsigned char oldcodes[KBD_ROWS][KBD_COLUMNS]={{0,0,0,0,0,0,0,0},
  19620. + {0,0,0,0,0,0,0,0},
  19621. + {0,0,0,0,0,0,0,0},
  19622. + {0,0,0,0,0,0,0,0},
  19623. + {0,0,0,0,0,0,0,0}};
  19624. + unsigned char inputcode[KBD_ROWS][KBD_COLUMNS];
  19625. +
  19626. + memset(inputcode, 0, sizeof(unsigned char) * (KBD_ROWS * KBD_COLUMNS));
  19627. + scancodes(inputcode);
  19628. +
  19629. + for(i = 0; i < KBD_COLUMNS; i++)
  19630. + {
  19631. + for(j = 0; j < KBD_ROWS; j++)
  19632. + {
  19633. +// if(oldcodes[j][i] == 0xe0)
  19634. +// oldcodes[j][i] =
  19635. + if(oldcodes[j][i] != inputcode[j][i])
  19636. + {
  19637. + // Value of the key before entering this function
  19638. + prev = oldcodes[j][i];
  19639. +
  19640. + // KEYUP
  19641. + if(inputcode[j][i] == 0 && oldcodes[j][i] != 0 && !(oldcodes[j][i] & KBD_KEYUP))
  19642. + {
  19643. + oldcodes[j][i] |= KBD_KEYUP;
  19644. +
  19645. + if(mode_ena == KBD_UP_ON)
  19646. + mode_ena = KBD_UP_OFF;
  19647. + if(prev == KBD_MODESCAN)
  19648. + if(mode_ena == KBD_DOWN_HOLD)
  19649. + mode_ena = KBD_UP_OFF;
  19650. + else if(mode_ena == KBD_DOWN)
  19651. + mode_ena = KBD_UP_ON;
  19652. + if(mode_ena == KBD_DOWN)
  19653. + mode_ena = KBD_DOWN_HOLD;
  19654. + }
  19655. + // RESET KEYUP
  19656. + else if(oldcodes[j][i] & KBD_KEYUP)
  19657. + oldcodes[j][i] = 0;
  19658. + // KEY DOWN
  19659. + else
  19660. + {
  19661. + oldcodes[j][i] = inputcode[j][i];
  19662. +
  19663. + // Parse out mode modifiers before the keyboard interpreter can touch them
  19664. + if(inputcode[j][i] == KBD_MODESCAN)
  19665. + {
  19666. + if(!mode_ena)
  19667. + mode_ena = KBD_DOWN;
  19668. + continue;
  19669. + }
  19670. + if(inputcode[j][i] == KBD_NUMCURSCAN)
  19671. + {
  19672. + numcur_ena = numcur_ena?0:1;
  19673. + continue;
  19674. + }
  19675. + }
  19676. + //printk("Modified: (%#x,%#x), ipv:%#x, To: (%#.2x), From: (%#.2x), Flags:%d,%d,%d\r\n", j, i, inputcode[j][i], oldcodes[j][i], prev, mode_ena, shift_ena, numcur_ena);
  19677. + return oldcodes[j][i];
  19678. + }
  19679. + }
  19680. + }
  19681. +
  19682. + return (unsigned char)(KBD_NO_DATA);
  19683. +}
  19684. +
  19685. +int cerf_kbd_translate(unsigned char scancode, unsigned char *keycode,
  19686. + char raw_mode)
  19687. +{
  19688. + static int prev_scancode;
  19689. +
  19690. + if (scancode == 0xe0 || scancode == 0xe1) {
  19691. + prev_scancode = scancode;
  19692. + return 0;
  19693. + }
  19694. +
  19695. + if (scancode == 0x00 || scancode == 0xff) {
  19696. + prev_scancode = 0;
  19697. + return 0;
  19698. + }
  19699. +
  19700. + scancode &= 0x7f;
  19701. +
  19702. + if (prev_scancode) {
  19703. + if (prev_scancode != 0xe0) {
  19704. + if (prev_scancode == 0xe1 && scancode == 0x1d) {
  19705. + prev_scancode = 0x100;
  19706. + return 0;
  19707. + } else if (prev_scancode == 0x100 && scancode == 0x45) {
  19708. + prev_scancode = 0;
  19709. + } else {
  19710. +#ifdef KBD_REPORT_UNKN
  19711. + if (!raw_mode)
  19712. + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
  19713. +#endif
  19714. + prev_scancode = 0;
  19715. + return 0;
  19716. + }
  19717. + } else {
  19718. + prev_scancode = 0;
  19719. + if (scancode == 0x2a || scancode == 0x36)
  19720. + return 0;
  19721. + else {
  19722. +#ifdef KBD_REPORT_UNKN
  19723. + if (!raw_mode)
  19724. + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
  19725. + scancode);
  19726. +#endif
  19727. + return 0;
  19728. + }
  19729. + }
  19730. + } else
  19731. + *keycode = scancode;
  19732. + return 1;
  19733. +}
  19734. +
  19735. +static inline void handle_keyboard_event(unsigned char scancode)
  19736. +{
  19737. + if(scancode != (unsigned char)(KBD_NO_DATA))
  19738. + {
  19739. +#ifdef CONFIG_VT
  19740. + handle_scancode(scancode, !(scancode & KBD_KEYUP));
  19741. +#endif
  19742. + tasklet_schedule(&keyboard_tasklet);
  19743. + }
  19744. +}
  19745. +
  19746. +static unsigned char handle_kbd_event(void)
  19747. +{
  19748. + unsigned char scancode;
  19749. +
  19750. + scancode = kbd_read_input();
  19751. + handle_keyboard_event(scancode);
  19752. +
  19753. + return 0;
  19754. +}
  19755. +
  19756. +/* Handle the automatic interrupts handled by the timer */
  19757. +static void keyboard_interrupt(unsigned long foo)
  19758. +{
  19759. + spin_lock_irq(&kbd_controller_lock);
  19760. + handle_kbd_event();
  19761. + spin_unlock_irq(&kbd_controller_lock);
  19762. +
  19763. + kbd_timer.expires = 8 + jiffies;
  19764. + kbd_timer.data = 0x00000000;
  19765. + kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
  19766. +
  19767. + add_timer(&kbd_timer);
  19768. +}
  19769. +
  19770. +void cerf_leds(unsigned char leds)
  19771. +{
  19772. +}
  19773. +char cerf_unexpected_up(unsigned char keycode)
  19774. +{
  19775. +return 0;
  19776. +}
  19777. +int cerf_getkeycode(unsigned int scancode)
  19778. +{
  19779. +return 0;
  19780. +}
  19781. +int cerf_setkeycode(unsigned int scancode, unsigned int keycode)
  19782. +{
  19783. +return 0;
  19784. +}
  19785. +
  19786. +void cerf_kbd_init_hw(void)
  19787. +{
  19788. + printk("Starting Cerf PDA Keyboard Driver... ");
  19789. +
  19790. + k_setkeycode = cerf_setkeycode;
  19791. + k_getkeycode = cerf_getkeycode;
  19792. + k_translate = cerf_kbd_translate;
  19793. + k_unexpected_up = cerf_unexpected_up;
  19794. + k_leds = cerf_leds;
  19795. +
  19796. + GPDR &= ~(GPIO_GPIO(20) | GPIO_GPIO(21) | GPIO_GPIO(22) | GPIO_GPIO(23) | GPIO_GPIO(24));
  19797. + kbd_timer.expires = 40 + jiffies;
  19798. + kbd_timer.data = 0x00000000;
  19799. + kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
  19800. +
  19801. + add_timer(&kbd_timer);
  19802. +
  19803. + printk("Done\r\n");
  19804. +}
  19805. diff -urN linux-2.4.26/drivers/char/clps711x_keyb.c linux-2.4.26-vrs1/drivers/char/clps711x_keyb.c
  19806. --- linux-2.4.26/drivers/char/clps711x_keyb.c 1970-01-01 01:00:00.000000000 +0100
  19807. +++ linux-2.4.26-vrs1/drivers/char/clps711x_keyb.c 2004-01-14 21:32:25.000000000 +0000
  19808. @@ -0,0 +1,547 @@
  19809. +/*
  19810. + * drivers/char/clps711x_keyb.c
  19811. + *
  19812. + * Copyright (C) 2001 Thomas Gleixner <gleixner@autronix.de>
  19813. + *
  19814. + * based on drivers/edb7211_keyb.c, which is copyright (C) 2000 Bluemug Inc.
  19815. + *
  19816. + * Keyboard driver for ARM Linux on EP7xxx and CS89712 processors
  19817. + *
  19818. + * This program is free software; you can redistribute it and/or modify
  19819. + * it under the terms of the GNU General Public License version 2 as
  19820. + * published by the Free Software Foundation. See the file COPYING
  19821. + * in the main directory of this archive for more details.
  19822. + *
  19823. + *
  19824. + * Hardware:
  19825. + *
  19826. + * matrix scan keyboards based on EP7209,7211,7212,7312 and CS89712
  19827. + * on chip keyboard scanner.
  19828. + * Adaption for different machines is done in init function.
  19829. + *
  19830. + * Basic Function:
  19831. + *
  19832. + * Basicly the driver is interrupt driven. It sets all column drivers
  19833. + * high. If any key is pressed, a interrupt occures. Now a separate scan of
  19834. + * each column is done. This scan is timer based, because we use a keyboard
  19835. + * interface with decoupling capacitors (neccecary if you want to survive
  19836. + * EMC compliance tests). Always one line is set high. When next timer event
  19837. + * occures the scan data on port A are valid. This makes also sure, that no
  19838. + * spurious keys are scanned. The kbd int on these CPU's is not deglitched!
  19839. + * After scanning all columns, we switch back to int mode, if no key is
  19840. + * pressed. If any is pressed we reschedule the scan within a programmable
  19841. + * delay. If we would switch back to interrupt mode as long as a key is pressed,
  19842. + * we come right back to the interrupt, because the int. is level triggered !
  19843. + * The timer based scan of the separate columns can also be done in one
  19844. + * timer event (set fastscan to 1).
  19845. + *
  19846. + * Summary:
  19847. + * The design of this keyboard controller chip is stupid at all !
  19848. + *
  19849. + * Matrix translation:
  19850. + * The matrix translation table is based on standard XT scancodes. Maybe
  19851. + * you have to adjust the KEYISPRINTABLE macro if you set other codes.
  19852. + *
  19853. + * HandyKey:
  19854. + *
  19855. + * On small matrix keyboards you don't have enough keys for operation.
  19856. + * The intention was to implement a operation mode as it's used on handys.
  19857. + * You can rotate trough four scancode levels and produce e.g. with a 4x3
  19858. + * matrix 4*3*4 = 48 different keycodes. That's basicly enough for editing
  19859. + * filenames or things like that. The HandyKey function takes care about
  19860. + * nonprintable keys like cursors, backspace, del ...
  19861. + * If a key is pressed and is a printable keycode, the code is put to the
  19862. + * main keyboard handler and a cursor left is applied. If you press the same
  19863. + * key again, the current character is deleted and the next level character
  19864. + * is applied. (e.g. 1, a, b, c, 1 ....). If you press a different key, the
  19865. + * driver applies cursor right, before processing the new key.
  19866. + * The autocomplete feature moves the cursor right, if you do not press a
  19867. + * key within a programmable time.
  19868. + * If HandyKey is off, the keyboard behaviour is that of a standard keyboard
  19869. + * HandyKey can be en/disabled from userspace with the proc/keyboard entry
  19870. + *
  19871. + * proc/keyboard:
  19872. + *
  19873. + * Read access gives back the actual state of the HandyKey function
  19874. + * h:0 Disabled
  19875. + * h:1 Enabled
  19876. + * Write access has two functions. Changing the HandyKey mode and applying
  19877. + * a different scancode translation table.
  19878. + * Syntax is: h:0 disable Handykey
  19879. + * h:1 enabled Handykey
  19880. + * t:array[256] of bytes Transfer translation table
  19881. + */
  19882. +
  19883. +#include <linux/config.h>
  19884. +#include <linux/sched.h>
  19885. +#include <linux/interrupt.h>
  19886. +#include <linux/tty.h>
  19887. +#include <linux/tty_flip.h>
  19888. +#include <linux/mm.h>
  19889. +#include <linux/slab.h>
  19890. +#include <linux/ptrace.h>
  19891. +#include <linux/signal.h>
  19892. +#include <linux/timer.h>
  19893. +#include <linux/tqueue.h>
  19894. +#include <linux/random.h>
  19895. +#include <linux/ctype.h>
  19896. +#include <linux/init.h>
  19897. +#include <linux/kbd_ll.h>
  19898. +#include <linux/kbd_kern.h>
  19899. +#include <linux/delay.h>
  19900. +#include <linux/proc_fs.h>
  19901. +
  19902. +#include <asm/bitops.h>
  19903. +#include <asm/keyboard.h>
  19904. +#include <asm/irq.h>
  19905. +#include <asm/hardware.h>
  19906. +#include <asm/uaccess.h>
  19907. +
  19908. +#include <asm/io.h>
  19909. +#include <asm/system.h>
  19910. +
  19911. +void clps711x_kbd_init_hw(void);
  19912. +
  19913. +/*
  19914. + * Values for the keyboard column scan control register.
  19915. + */
  19916. +#define KBSC_HI 0x0 /* All driven high */
  19917. +#define KBSC_LO 0x1 /* All driven low */
  19918. +#define KBSC_X 0x2 /* All high impedance */
  19919. +#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
  19920. +#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
  19921. +#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
  19922. +#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
  19923. +#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
  19924. +#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
  19925. +#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
  19926. +#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
  19927. +
  19928. +/*
  19929. +* Keycodes for cursor left/right and delete (used by HandyKey)
  19930. +*/
  19931. +#define KEYCODE_CLEFT 0x4b
  19932. +#define KEYCODE_CRIGHT 0x4d
  19933. +#define KEYCODE_DEL 0x53
  19934. +#define KEYISPRINTABLE(code) ( (code > 0x01 && code < 0x37 && code != 0x1c \
  19935. + && code != 0x0e) || code == 0x39)
  19936. +
  19937. +/* Simple translation table for the SysRq keys */
  19938. +#ifdef CONFIG_MAGIC_SYSRQ
  19939. +unsigned char clps711x_kbd_sysrq_xlate[128] =
  19940. + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
  19941. + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
  19942. + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
  19943. + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
  19944. + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
  19945. + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
  19946. + "\r\000/"; /* 0x60 - 0x6f */
  19947. +#endif
  19948. +
  19949. +/*
  19950. + * This table maps row/column keyboard matrix positions to XT scancodes.
  19951. + * It's a default table, which can be overriden by writing to proc/keyboard
  19952. + */
  19953. +#ifdef CONFIG_ARCH_AUTCPU12
  19954. +static unsigned char autcpu12_scancode[256] =
  19955. +{
  19956. +/* Column:
  19957. + Row 0 1 2 3 4 5 6 7 */
  19958. +/* A0 */ 0x08, 0x09, 0x0a, 0x0e, 0x05, 0x06, 0x00, 0x00,
  19959. +/* A1 */ 0x07, 0x53, 0x02, 0x03, 0x04, 0x0f, 0x00, 0x00,
  19960. +/* A2 */ 0x0c, 0x0b, 0x33, 0x1c, 0xff, 0x4b, 0x00, 0x00,
  19961. +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
  19962. +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19963. +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19964. +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19965. +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19966. +
  19967. +/* A0 */ 0x1e, 0x20, 0x22, 0x0e, 0x24, 0x32, 0x00, 0x00,
  19968. +/* A1 */ 0x19, 0x53, 0x1f, 0x2f, 0x15, 0x0f, 0x00, 0x00,
  19969. +/* A2 */ 0x0c, 0x39, 0x34, 0x1c, 0xff, 0x4b, 0x00, 0x00,
  19970. +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
  19971. +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19972. +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19973. +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19974. +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19975. +
  19976. +/* A0 */ 0x30, 0x12, 0x23, 0x0e, 0x25, 0x31, 0x00, 0x00,
  19977. +/* A1 */ 0x10, 0x53, 0x14, 0x11, 0x2c, 0x0f, 0x00, 0x00,
  19978. +/* A2 */ 0x0c, 0x0b, 0x27, 0x1c, 0xff, 0x4b, 0x00, 0x00,
  19979. +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
  19980. +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19981. +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19982. +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19983. +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19984. +
  19985. +/* A0 */ 0x2e, 0x21, 0x17, 0x0e, 0x26, 0x18, 0x00, 0x00,
  19986. +/* A1 */ 0x13, 0x53, 0x16, 0x2D, 0x04, 0x0f, 0x00, 0x00,
  19987. +/* A2 */ 0x0c, 0x39, 0x35, 0x1c, 0xff, 0x4b, 0x00, 0x00,
  19988. +/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
  19989. +/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19990. +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19991. +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19992. +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19993. +};
  19994. +#endif
  19995. +
  19996. +static int keys[8];
  19997. +static int new_keys[8];
  19998. +static int previous_keys[8];
  19999. +
  20000. +static int fastscan;
  20001. +static int scan_interval;
  20002. +static int scan_delay;
  20003. +static int last_column;
  20004. +static int key_is_pressed;
  20005. +
  20006. +static unsigned char *act_scancode;
  20007. +
  20008. +static struct kbd_handy_key {
  20009. + int ena;
  20010. + int code;
  20011. + int shift;
  20012. + int autocomplete;
  20013. + unsigned long expires;
  20014. + unsigned long delay;
  20015. + unsigned char left;
  20016. + unsigned char right;
  20017. + unsigned char del;
  20018. +} khandy;
  20019. +
  20020. +static struct tq_struct kbd_process_task;
  20021. +static struct timer_list clps711x_kbd_timer;
  20022. +static struct timer_list clps711x_kbdhandy_timer;
  20023. +static struct proc_dir_entry *clps711x_keyboard_proc_entry = NULL;
  20024. +
  20025. +/*
  20026. + * Translate a raw keycode to an XT keyboard scancode.
  20027. + */
  20028. +static int clps711x_translate(unsigned char scancode, unsigned char *keycode,
  20029. + char raw_mode)
  20030. +{
  20031. + *keycode = act_scancode[scancode];
  20032. + return 1;
  20033. +}
  20034. +
  20035. +/*
  20036. +* Initialize handykey structure
  20037. +* clear code, clear shift
  20038. +* scan scancode for cursor right/left and delete
  20039. +*/
  20040. +static void clps711x_handykey_init(void) {
  20041. +
  20042. + int i;
  20043. +
  20044. + khandy.ena = 0;
  20045. + khandy.code = 0;
  20046. + khandy.shift = 0;
  20047. + khandy.autocomplete = 0;
  20048. + for(i = 0; i < 64; i++) {
  20049. + switch(act_scancode[i]) {
  20050. + case KEYCODE_CLEFT: khandy.left = i; break;
  20051. + case KEYCODE_CRIGHT: khandy.right = i; break;
  20052. + case KEYCODE_DEL: khandy.del = i; break;
  20053. + }
  20054. + }
  20055. +}
  20056. +
  20057. +/*
  20058. +* Check for handy key and process it
  20059. +*/
  20060. +void inline clps711x_checkhandy(int col, int row) {
  20061. +
  20062. + int scode, down;
  20063. + unsigned char kcode;
  20064. +
  20065. + scode = (row<<3) + col;
  20066. + down = keys[col]>>row & 0x01;
  20067. + kcode = act_scancode[scode];
  20068. +
  20069. + if (!khandy.ena) {
  20070. + if (khandy.code) {
  20071. + handle_scancode(khandy.right,1);
  20072. + handle_scancode(khandy.right,0);
  20073. + }
  20074. + khandy.code = 0;
  20075. + khandy.shift = 0;
  20076. + khandy.autocomplete = 0;
  20077. + }
  20078. +
  20079. + if(!kcode)
  20080. + return;
  20081. +
  20082. + if (!down || !khandy.ena) {
  20083. + if (khandy.ena && KEYISPRINTABLE(act_scancode[scode]))
  20084. + khandy.autocomplete = 1;
  20085. + else
  20086. + handle_scancode(scode + khandy.shift, down);
  20087. + return;
  20088. + }
  20089. +
  20090. + khandy.autocomplete = 0;
  20091. + if (KEYISPRINTABLE(kcode)) {
  20092. + if (khandy.code) {
  20093. + if(khandy.code == (scode|0x100)) {
  20094. + handle_scancode(khandy.del,1);
  20095. + handle_scancode(khandy.del,0);
  20096. + khandy.shift = khandy.shift < 3*64 ? khandy.shift + 64 : 0 ;
  20097. + } else {
  20098. + handle_scancode(khandy.right,1);
  20099. + handle_scancode(khandy.right,0);
  20100. + khandy.shift = 0;
  20101. + }
  20102. + }
  20103. + handle_scancode(scode + khandy.shift, 1);
  20104. + handle_scancode(scode + khandy.shift, 0);
  20105. + khandy.code = scode | 0x100;
  20106. + handle_scancode(khandy.left,1);
  20107. + handle_scancode(khandy.left,0);
  20108. + } else {
  20109. + if (khandy.code) {
  20110. + khandy.code = 0;
  20111. + handle_scancode(khandy.right,1);
  20112. + handle_scancode(khandy.right,0);
  20113. + }
  20114. + khandy.shift = 0;
  20115. + handle_scancode(scode, down);
  20116. + }
  20117. +}
  20118. +
  20119. +
  20120. +/*
  20121. + * Process the new key data
  20122. + */
  20123. +static void clps711x_kbd_process(void* data)
  20124. +{
  20125. + int col,row,res;
  20126. +
  20127. + for (col = 0; col < 8; col++) {
  20128. + if (( res = previous_keys[col] ^ keys[col]) == 0)
  20129. + continue;
  20130. + for(row = 0; row < 8; row++) {
  20131. + if ( ((res >> row) & 0x01) != 0)
  20132. + clps711x_checkhandy(col,row);
  20133. + }
  20134. + }
  20135. + /* Update the state variables. */
  20136. + memcpy(previous_keys, keys, 8 * sizeof(int));
  20137. +
  20138. + /* reschedule, if autocomplete pending */
  20139. + if (khandy.autocomplete) {
  20140. + khandy.expires = jiffies + khandy.delay;
  20141. + mod_timer(&clps711x_kbdhandy_timer,khandy.expires);
  20142. + }
  20143. +
  20144. +}
  20145. +
  20146. +static char clps711x_unexpected_up(unsigned char scancode)
  20147. +{
  20148. + return 0200;
  20149. +}
  20150. +
  20151. +/*
  20152. +* Handle timer event, for autocomplete function
  20153. +* Reschedule keyboard process task
  20154. +*/
  20155. +static void clps711x_kbdhandy_timeout(unsigned long data)
  20156. +{
  20157. + if(khandy.autocomplete) {
  20158. + khandy.code = 0;
  20159. + khandy.shift = 0;
  20160. + khandy.autocomplete = 0;
  20161. + handle_scancode(khandy.right,1);
  20162. + handle_scancode(khandy.right,0);
  20163. + }
  20164. +}
  20165. +
  20166. +/*
  20167. +* Handle timer event, while in pollmode
  20168. +*/
  20169. +static void clps711x_kbd_timeout(unsigned long data)
  20170. +{
  20171. + int i;
  20172. + unsigned long flags;
  20173. + /*
  20174. + * read bits of actual column or all columns in fastscan-mode
  20175. + */
  20176. + for (i = 0; i < 8; i++) {
  20177. + new_keys[last_column - KBSC_COL0] = clps_readb(PADR) & 0xff;
  20178. + key_is_pressed |= new_keys[last_column - KBSC_COL0];
  20179. + last_column = last_column < KBSC_COL7 ? last_column + 1 : KBSC_COL0;
  20180. + local_irq_save(flags);
  20181. + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
  20182. + | last_column, SYSCON1);
  20183. + local_irq_restore(flags);
  20184. + /*
  20185. + * For fastscan, apply a short delay to settle scanlines
  20186. + * else break and wait for next timeout
  20187. + */
  20188. + if (fastscan)
  20189. + udelay(5);
  20190. + else
  20191. + break;
  20192. + }
  20193. +
  20194. + if (key_is_pressed)
  20195. + khandy.autocomplete = 0;
  20196. +
  20197. + /*
  20198. + * switch to interupt mode, if all columns scanned and no key pressed
  20199. + * else reschedule scan
  20200. + */
  20201. + if (last_column == KBSC_COL0) {
  20202. + if (!key_is_pressed) {
  20203. + local_irq_save(flags);
  20204. + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
  20205. + | KBSC_HI, SYSCON1);
  20206. + local_irq_restore(flags);
  20207. + clps_writel(0,KBDEOI);
  20208. + enable_irq(IRQ_KBDINT);
  20209. + } else {
  20210. + clps711x_kbd_timer.expires = jiffies + scan_interval;
  20211. + add_timer(&clps711x_kbd_timer);
  20212. + }
  20213. + key_is_pressed = 0;
  20214. + memcpy(keys, new_keys, 8 * sizeof(int));
  20215. + for (i = 0; i < 8; i++) {
  20216. + if (previous_keys[i] != keys[i]) {
  20217. + queue_task(&kbd_process_task, &tq_timer);
  20218. + return;
  20219. + }
  20220. + }
  20221. + } else {
  20222. + clps711x_kbd_timer.expires = jiffies + scan_delay;
  20223. + add_timer(&clps711x_kbd_timer);
  20224. + }
  20225. +}
  20226. +
  20227. +/*
  20228. +* Keyboard interrupt, change to scheduling mode
  20229. +*/
  20230. +static void clps711x_kbd_int(int irq, void *dev_id, struct pt_regs *regs)
  20231. +{
  20232. +
  20233. +#ifdef CONFIG_VT
  20234. + kbd_pt_regs = regs;
  20235. +#endif
  20236. + disable_irq(IRQ_KBDINT);
  20237. + khandy.autocomplete = 0;
  20238. + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
  20239. + | KBSC_COL0, SYSCON1);
  20240. + clps711x_kbd_timer.expires = jiffies + scan_delay;
  20241. + add_timer(&clps711x_kbd_timer);
  20242. +}
  20243. +
  20244. +
  20245. +static int clps711x_kbd_proc_keyboard_read(char *page, char **start, off_t off,
  20246. + int count, int *eof, void *data)
  20247. +{
  20248. + if (count < 2)
  20249. + return -EINVAL;
  20250. +
  20251. + return sprintf(page,"h:%d\n",khandy.ena);
  20252. +}
  20253. +
  20254. +static int clps711x_kbd_proc_keyboard_write(struct file *file, const char *buffer,
  20255. + unsigned long count, void *data)
  20256. +{
  20257. + unsigned char buf[260];
  20258. +
  20259. + if (count < 3|| count > 258)
  20260. + return -EINVAL;
  20261. + if (copy_from_user(buf, buffer, count))
  20262. + return -EFAULT;
  20263. + if (buf[1] != ':')
  20264. + return -EINVAL;
  20265. +
  20266. + if (buf[0] == 'h') {
  20267. + switch (buf[2]) {
  20268. + case '0':
  20269. + case '1':
  20270. + case '2': khandy.ena = buf[2]-'0'; return count;
  20271. + }
  20272. + }
  20273. +
  20274. + if (buf[0] == 't' && count == 258) {
  20275. + memcpy(act_scancode,buf+2,256);
  20276. + /* rescan cursor left/right and del */
  20277. + clps711x_handykey_init();
  20278. + return count;
  20279. + }
  20280. +
  20281. + return -EINVAL;
  20282. +}
  20283. +
  20284. +
  20285. +/*
  20286. + * Initialize the keyboard hardware.
  20287. + * Set all columns high
  20288. + * Install interrupt handler
  20289. + *
  20290. + * Machine dependent parameters:
  20291. + *
  20292. + * fastscan: 0 = timer based scan for each column
  20293. + * 1 = full scan is done in one timer event
  20294. + * scan_delay: time between column scans
  20295. + * setup even if you use fastscan (leeds to timer mode)
  20296. + * scan_interval: time between full scans
  20297. + * handy.delay: timeout before last entry get's automatically valid
  20298. + *
  20299. + */
  20300. +void __init clps711x_kbd_init_hw(void)
  20301. +{
  20302. +
  20303. + /*
  20304. + * put here machine dependent init stuff
  20305. + */
  20306. + if (machine_is_autcpu12()) {
  20307. + fastscan = 0;
  20308. + scan_interval = 50*HZ/1000;
  20309. + scan_delay = 20*HZ/1000;
  20310. + khandy.delay = 750*HZ/1000;
  20311. + act_scancode = autcpu12_scancode;
  20312. + } else {
  20313. + printk("No initialization, keyboard killed\n");
  20314. + return;
  20315. + }
  20316. +
  20317. + last_column = KBSC_COL0;
  20318. + key_is_pressed = 0;
  20319. +
  20320. + clps711x_handykey_init();
  20321. +
  20322. + /* Register the /proc entry */
  20323. + clps711x_keyboard_proc_entry = create_proc_entry("keyboard", 0444,
  20324. + &proc_root);
  20325. + if (clps711x_keyboard_proc_entry == NULL)
  20326. + printk("Couldn't create the /proc entry for the keyboard\n");
  20327. + else {
  20328. + clps711x_keyboard_proc_entry->read_proc =
  20329. + &clps711x_kbd_proc_keyboard_read;
  20330. + clps711x_keyboard_proc_entry->write_proc =
  20331. + &clps711x_kbd_proc_keyboard_write;
  20332. + }
  20333. +
  20334. + /* Initialize the matrix processing task. */
  20335. + k_translate = clps711x_translate;
  20336. + k_unexpected_up = clps711x_unexpected_up;
  20337. + kbd_process_task.routine = clps711x_kbd_process;
  20338. + kbd_process_task.data = 0;
  20339. +
  20340. + /* Setup the timer for keyboard polling, after kbd int */
  20341. + init_timer(&clps711x_kbd_timer);
  20342. + clps711x_kbd_timer.function = clps711x_kbd_timeout;
  20343. + clps711x_kbd_timer.data = 0;
  20344. + init_timer(&clps711x_kbdhandy_timer);
  20345. + clps711x_kbdhandy_timer.function = clps711x_kbdhandy_timeout;
  20346. + clps711x_kbdhandy_timer.data = 1;
  20347. +
  20348. + /* Initialise scan hardware, request int */
  20349. + clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
  20350. + | KBSC_HI, SYSCON1);
  20351. + request_irq(IRQ_KBDINT, clps711x_kbd_int, 0,"keyboard", NULL);
  20352. +
  20353. + printk("clps711x keyboard init done\n");
  20354. +
  20355. +}
  20356. diff -urN linux-2.4.26/drivers/char/console.c linux-2.4.26-vrs1/drivers/char/console.c
  20357. --- linux-2.4.26/drivers/char/console.c 2003-11-28 18:26:20.000000000 +0000
  20358. +++ linux-2.4.26-vrs1/drivers/char/console.c 2004-01-14 21:38:59.000000000 +0000
  20359. @@ -72,8 +72,14 @@
  20360. *
  20361. * Removed console_lock, enabled interrupts across all console operations
  20362. * 13 March 2001, Andrew Morton
  20363. + *
  20364. + * Split out con_write_ctrl_* functions from do_con_write & changed
  20365. + * vc_state to function pointer
  20366. + * by Russell King <rmk@arm.linux.org.uk>, July 1998
  20367. */
  20368. +#define CONSOLE_WIP
  20369. +
  20370. #include <linux/module.h>
  20371. #include <linux/sched.h>
  20372. #include <linux/tty.h>
  20373. @@ -228,7 +234,7 @@
  20374. static inline unsigned short *screenpos(int currcons, int offset, int viewed)
  20375. {
  20376. unsigned short *p;
  20377. -
  20378. +
  20379. if (!viewed)
  20380. p = (unsigned short *)(origin + offset);
  20381. else if (!sw->con_screen_pos)
  20382. @@ -729,7 +735,7 @@
  20383. else {
  20384. unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
  20385. if (!p) {
  20386. - for (i = first; i < currcons; i++)
  20387. + for (i = first; i< currcons; i++)
  20388. if (newscreens[i])
  20389. kfree(newscreens[i]);
  20390. return -ENOMEM;
  20391. @@ -847,7 +853,7 @@
  20392. /* the default colour table, for VGA+ colour systems */
  20393. int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
  20394. 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
  20395. -int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
  20396. +int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa,
  20397. 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
  20398. int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
  20399. 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
  20400. @@ -1393,6 +1399,19 @@
  20401. need_wrap = 0;
  20402. }
  20403. +static int con_write_ctrl_ESnormal(int, struct tty_struct *, unsigned int);
  20404. +static int con_write_ctrl_ESesc(int, struct tty_struct *, unsigned int);
  20405. +static int con_write_ctrl_ESnonstd(int, struct tty_struct *, unsigned int);
  20406. +static int con_write_ctrl_ESpalette(int, struct tty_struct *, unsigned int);
  20407. +static int con_write_ctrl_ESsquare(int, struct tty_struct *, unsigned int);
  20408. +static int con_write_ctrl_ESgetpars(int, struct tty_struct *, unsigned int);
  20409. +static int con_write_ctrl_ESgotpars(int, struct tty_struct *, unsigned int);
  20410. +static int con_write_ctrl_ESpercent(int, struct tty_struct *, unsigned int);
  20411. +static int con_write_ctrl_ESfunckey(int, struct tty_struct *, unsigned int);
  20412. +static int con_write_ctrl_EShash(int, struct tty_struct *, unsigned int);
  20413. +static int con_write_ctrl_ESsetG0(int, struct tty_struct *, unsigned int);
  20414. +static int con_write_ctrl_ESsetG1(int, struct tty_struct *, unsigned int);
  20415. +
  20416. enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
  20417. EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
  20418. ESpalette };
  20419. @@ -1402,7 +1421,7 @@
  20420. {
  20421. top = 0;
  20422. bottom = video_num_lines;
  20423. - vc_state = ESnormal;
  20424. + vc_state = con_write_ctrl_ESnormal;
  20425. ques = 0;
  20426. translate = set_translate(LAT1_MAP,currcons);
  20427. G0_charset = LAT1_MAP;
  20428. @@ -1500,328 +1519,426 @@
  20429. disp_ctrl = 0;
  20430. return;
  20431. case 24: case 26:
  20432. - vc_state = ESnormal;
  20433. + vc_state = con_write_ctrl_ESnormal;
  20434. return;
  20435. case 27:
  20436. - vc_state = ESesc;
  20437. + vc_state = con_write_ctrl_ESesc;
  20438. return;
  20439. case 127:
  20440. del(currcons);
  20441. return;
  20442. case 128+27:
  20443. - vc_state = ESsquare;
  20444. + vc_state = con_write_ctrl_ESsquare;
  20445. return;
  20446. }
  20447. - switch(vc_state) {
  20448. - case ESesc:
  20449. - vc_state = ESnormal;
  20450. - switch (c) {
  20451. - case '[':
  20452. - vc_state = ESsquare;
  20453. - return;
  20454. - case ']':
  20455. - vc_state = ESnonstd;
  20456. - return;
  20457. - case '%':
  20458. - vc_state = ESpercent;
  20459. - return;
  20460. - case 'E':
  20461. - cr(currcons);
  20462. - lf(currcons);
  20463. - return;
  20464. - case 'M':
  20465. - ri(currcons);
  20466. - return;
  20467. - case 'D':
  20468. - lf(currcons);
  20469. - return;
  20470. - case 'H':
  20471. - tab_stop[x >> 5] |= (1 << (x & 31));
  20472. - return;
  20473. - case 'Z':
  20474. - respond_ID(tty);
  20475. - return;
  20476. - case '7':
  20477. - save_cur(currcons);
  20478. - return;
  20479. - case '8':
  20480. - restore_cur(currcons);
  20481. - return;
  20482. - case '(':
  20483. - vc_state = ESsetG0;
  20484. - return;
  20485. - case ')':
  20486. - vc_state = ESsetG1;
  20487. - return;
  20488. - case '#':
  20489. - vc_state = EShash;
  20490. - return;
  20491. - case 'c':
  20492. - reset_terminal(currcons,1);
  20493. - return;
  20494. - case '>': /* Numeric keypad */
  20495. - clr_kbd(kbdapplic);
  20496. - return;
  20497. - case '=': /* Appl. keypad */
  20498. - set_kbd(kbdapplic);
  20499. - return;
  20500. + vc_state(currcons, tty, c);
  20501. +}
  20502. +
  20503. +static int con_write_utf(int currcons, int c)
  20504. +{
  20505. + unsigned int chr;
  20506. +
  20507. + /* Combine UTF-8 into Unicode */
  20508. + /* Incomplete characters silently ignored */
  20509. + if (c < 0x80) {
  20510. + utf_count = 0;
  20511. + return c;
  20512. + }
  20513. +
  20514. + if (utf_count > 0 && (c & 0xc0) == 0x80) {
  20515. + chr = (utf_char << 6) | (c & 0x3f);
  20516. + utf_count--;
  20517. + if (utf_count == 0)
  20518. + return chr;
  20519. + } else {
  20520. + unsigned int count;
  20521. + if ((c & 0xe0) == 0xc0) {
  20522. + count = 1;
  20523. + chr = (c & 0x1f);
  20524. + } else if ((c & 0xf0) == 0xe0) {
  20525. + count = 2;
  20526. + chr = (c & 0x0f);
  20527. + } else if ((c & 0xf8) == 0xf0) {
  20528. + count = 3;
  20529. + chr = (c & 0x07);
  20530. + } else if ((c & 0xfc) == 0xf8) {
  20531. + count = 4;
  20532. + chr = (c & 0x03);
  20533. + } else if ((c & 0xfe) == 0xfc) {
  20534. + count = 5;
  20535. + chr = (c & 0x01);
  20536. + } else {
  20537. + count = 0;
  20538. + chr = 0;
  20539. }
  20540. - return;
  20541. - case ESnonstd:
  20542. - if (c=='P') { /* palette escape sequence */
  20543. - for (npar=0; npar<NPAR; npar++)
  20544. - par[npar] = 0 ;
  20545. - npar = 0 ;
  20546. - vc_state = ESpalette;
  20547. - return;
  20548. - } else if (c=='R') { /* reset palette */
  20549. - reset_palette(currcons);
  20550. - vc_state = ESnormal;
  20551. - } else
  20552. - vc_state = ESnormal;
  20553. - return;
  20554. - case ESpalette:
  20555. - if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
  20556. - par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
  20557. - if (npar==7) {
  20558. - int i = par[0]*3, j = 1;
  20559. - palette[i] = 16*par[j++];
  20560. - palette[i++] += par[j++];
  20561. - palette[i] = 16*par[j++];
  20562. - palette[i++] += par[j++];
  20563. - palette[i] = 16*par[j++];
  20564. - palette[i] += par[j];
  20565. - set_palette(currcons);
  20566. - vc_state = ESnormal;
  20567. - }
  20568. - } else
  20569. - vc_state = ESnormal;
  20570. - return;
  20571. - case ESsquare:
  20572. - for(npar = 0 ; npar < NPAR ; npar++)
  20573. - par[npar] = 0;
  20574. - npar = 0;
  20575. - vc_state = ESgetpars;
  20576. - if (c == '[') { /* Function key */
  20577. - vc_state=ESfunckey;
  20578. - return;
  20579. + utf_count = count;
  20580. + }
  20581. +
  20582. + utf_char = chr;
  20583. + return -1;
  20584. +}
  20585. +
  20586. +static int con_write_ctrl_ESnormal(int currcons, struct tty_struct *tty, unsigned int c)
  20587. +{
  20588. + return 0;
  20589. +}
  20590. +
  20591. +static int con_write_ctrl_ESesc(int currcons, struct tty_struct *tty, unsigned int c)
  20592. +{
  20593. + vc_state = con_write_ctrl_ESnormal;
  20594. + switch (c) {
  20595. + case '[':
  20596. + vc_state = con_write_ctrl_ESsquare;
  20597. + break;
  20598. + case ']':
  20599. + vc_state = con_write_ctrl_ESnonstd;
  20600. + break;
  20601. + case '%':
  20602. + vc_state = con_write_ctrl_ESpercent;
  20603. + break;
  20604. + case 'E':
  20605. + cr(currcons);
  20606. + lf(currcons);
  20607. + break;
  20608. + case 'M':
  20609. + ri(currcons);
  20610. + break;
  20611. + case 'D':
  20612. + lf(currcons);
  20613. + break;
  20614. + case 'H':
  20615. + tab_stop[x >> 5] |= (1 << (x & 31));
  20616. + break;
  20617. + case 'Z':
  20618. + respond_ID(tty);
  20619. + break;
  20620. + case '7':
  20621. + save_cur(currcons);
  20622. + break;
  20623. + case '8':
  20624. + restore_cur(currcons);
  20625. + return 1;
  20626. + case '(':
  20627. + vc_state = con_write_ctrl_ESsetG0;
  20628. + break;
  20629. + case ')':
  20630. + vc_state = con_write_ctrl_ESsetG1;
  20631. + break;
  20632. + case '#':
  20633. + vc_state = con_write_ctrl_EShash;
  20634. + break;
  20635. + case 'c':
  20636. + reset_terminal(currcons,1);
  20637. + return 1;
  20638. + case '>': /* Numeric keypad */
  20639. + clr_kbd(kbdapplic);
  20640. + break;
  20641. + case '=': /* Appl. keypad */
  20642. + set_kbd(kbdapplic);
  20643. + break;
  20644. + }
  20645. + return 0;
  20646. +}
  20647. +
  20648. +static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c)
  20649. +{
  20650. + switch (c) {
  20651. + case 'P': /* palette escape sequence */
  20652. + for (npar=0; npar<NPAR; npar++)
  20653. + par[npar] = 0 ;
  20654. + npar = 0 ;
  20655. + vc_state = con_write_ctrl_ESpalette;
  20656. + break;
  20657. + case 'R': /* reset palette */
  20658. + reset_palette (currcons);
  20659. + default:
  20660. + vc_state = con_write_ctrl_ESnormal;
  20661. + }
  20662. + return 0;
  20663. +}
  20664. +
  20665. +static int con_write_ctrl_ESpalette(int currcons, struct tty_struct *tty, unsigned int c)
  20666. +{
  20667. + if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
  20668. + par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
  20669. + if (npar==7) {
  20670. + int i = par[0]*3, j = 1;
  20671. + palette[i] = 16*par[j++];
  20672. + palette[i++] += par[j++];
  20673. + palette[i] = 16*par[j++];
  20674. + palette[i++] += par[j++];
  20675. + palette[i] = 16*par[j++];
  20676. + palette[i] += par[j];
  20677. + set_palette(currcons);
  20678. + vc_state = con_write_ctrl_ESnormal;
  20679. }
  20680. - ques = (c=='?');
  20681. - if (ques)
  20682. - return;
  20683. - case ESgetpars:
  20684. - if (c==';' && npar<NPAR-1) {
  20685. - npar++;
  20686. - return;
  20687. - } else if (c>='0' && c<='9') {
  20688. - par[npar] *= 10;
  20689. - par[npar] += c-'0';
  20690. - return;
  20691. - } else vc_state=ESgotpars;
  20692. - case ESgotpars:
  20693. - vc_state = ESnormal;
  20694. - switch(c) {
  20695. - case 'h':
  20696. - set_mode(currcons,1);
  20697. - return;
  20698. - case 'l':
  20699. - set_mode(currcons,0);
  20700. - return;
  20701. - case 'c':
  20702. - if (ques) {
  20703. - if (par[0])
  20704. - cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
  20705. - else
  20706. - cursor_type = CUR_DEFAULT;
  20707. - return;
  20708. - }
  20709. - break;
  20710. - case 'm':
  20711. - if (ques) {
  20712. - clear_selection();
  20713. - if (par[0])
  20714. - complement_mask = par[0]<<8 | par[1];
  20715. - else
  20716. - complement_mask = s_complement_mask;
  20717. - return;
  20718. - }
  20719. - break;
  20720. - case 'n':
  20721. - if (!ques) {
  20722. - if (par[0] == 5)
  20723. - status_report(tty);
  20724. - else if (par[0] == 6)
  20725. - cursor_report(currcons,tty);
  20726. - }
  20727. - return;
  20728. + } else
  20729. + vc_state = con_write_ctrl_ESnormal;
  20730. + return 0;
  20731. +}
  20732. +
  20733. +static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c)
  20734. +{
  20735. + for(npar = 0 ; npar < NPAR ; npar++)
  20736. + par[npar] = 0;
  20737. + npar = 0;
  20738. + vc_state = con_write_ctrl_ESgetpars;
  20739. + if (c == '[') { /* Function key */
  20740. + vc_state = con_write_ctrl_ESfunckey;
  20741. + return 0;
  20742. + }
  20743. + ques = (c=='?');
  20744. + if (ques)
  20745. + return 0;
  20746. + return con_write_ctrl_ESgetpars(currcons, tty, c);
  20747. +}
  20748. +
  20749. +static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c)
  20750. +{
  20751. + if (c==';' && npar<NPAR-1) {
  20752. + npar++;
  20753. + return 0;
  20754. + } else if (c>='0' && c<='9') {
  20755. + par[npar] *= 10;
  20756. + par[npar] += c-'0';
  20757. + return 0;
  20758. + } else vc_state = con_write_ctrl_ESgotpars;
  20759. + return con_write_ctrl_ESgotpars(currcons, tty, c);
  20760. +}
  20761. +
  20762. +static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c)
  20763. +{
  20764. + vc_state = con_write_ctrl_ESnormal;
  20765. + switch(c) {
  20766. + case 'h':
  20767. + set_mode(currcons,1);
  20768. + return 0;
  20769. + case 'l':
  20770. + set_mode(currcons,0);
  20771. + return 0;
  20772. + case 'c':
  20773. + if (ques) {
  20774. + if (par[0])
  20775. + cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
  20776. + else
  20777. + cursor_type = CUR_DEFAULT;
  20778. + return 0;
  20779. }
  20780. + break;
  20781. + case 'm':
  20782. if (ques) {
  20783. - ques = 0;
  20784. - return;
  20785. + clear_selection();
  20786. + if (par[0])
  20787. + complement_mask = par[0]<<8 | par[1];
  20788. + else
  20789. + complement_mask = s_complement_mask;
  20790. + return 0;
  20791. }
  20792. - switch(c) {
  20793. - case 'G': case '`':
  20794. - if (par[0]) par[0]--;
  20795. - gotoxy(currcons,par[0],y);
  20796. - return;
  20797. - case 'A':
  20798. - if (!par[0]) par[0]++;
  20799. - gotoxy(currcons,x,y-par[0]);
  20800. - return;
  20801. - case 'B': case 'e':
  20802. - if (!par[0]) par[0]++;
  20803. - gotoxy(currcons,x,y+par[0]);
  20804. - return;
  20805. - case 'C': case 'a':
  20806. - if (!par[0]) par[0]++;
  20807. - gotoxy(currcons,x+par[0],y);
  20808. - return;
  20809. - case 'D':
  20810. - if (!par[0]) par[0]++;
  20811. - gotoxy(currcons,x-par[0],y);
  20812. - return;
  20813. - case 'E':
  20814. - if (!par[0]) par[0]++;
  20815. - gotoxy(currcons,0,y+par[0]);
  20816. - return;
  20817. - case 'F':
  20818. - if (!par[0]) par[0]++;
  20819. - gotoxy(currcons,0,y-par[0]);
  20820. - return;
  20821. - case 'd':
  20822. - if (par[0]) par[0]--;
  20823. - gotoxay(currcons,x,par[0]);
  20824. - return;
  20825. - case 'H': case 'f':
  20826. - if (par[0]) par[0]--;
  20827. - if (par[1]) par[1]--;
  20828. - gotoxay(currcons,par[1],par[0]);
  20829. - return;
  20830. - case 'J':
  20831. - csi_J(currcons,par[0]);
  20832. - return;
  20833. - case 'K':
  20834. - csi_K(currcons,par[0]);
  20835. - return;
  20836. - case 'L':
  20837. - csi_L(currcons,par[0]);
  20838. - return;
  20839. - case 'M':
  20840. - csi_M(currcons,par[0]);
  20841. - return;
  20842. - case 'P':
  20843. - csi_P(currcons,par[0]);
  20844. - return;
  20845. - case 'c':
  20846. - if (!par[0])
  20847. - respond_ID(tty);
  20848. - return;
  20849. - case 'g':
  20850. - if (!par[0])
  20851. - tab_stop[x >> 5] &= ~(1 << (x & 31));
  20852. - else if (par[0] == 3) {
  20853. - tab_stop[0] =
  20854. - tab_stop[1] =
  20855. - tab_stop[2] =
  20856. - tab_stop[3] =
  20857. - tab_stop[4] = 0;
  20858. - }
  20859. - return;
  20860. - case 'm':
  20861. - csi_m(currcons);
  20862. - return;
  20863. - case 'q': /* DECLL - but only 3 leds */
  20864. - /* map 0,1,2,3 to 0,1,2,4 */
  20865. - if (par[0] < 4)
  20866. - setledstate(kbd_table + currcons,
  20867. - (par[0] < 3) ? par[0] : 4);
  20868. - return;
  20869. - case 'r':
  20870. - if (!par[0])
  20871. - par[0]++;
  20872. - if (!par[1])
  20873. - par[1] = video_num_lines;
  20874. - /* Minimum allowed region is 2 lines */
  20875. - if (par[0] < par[1] &&
  20876. - par[1] <= video_num_lines) {
  20877. - top=par[0]-1;
  20878. - bottom=par[1];
  20879. - gotoxay(currcons,0,0);
  20880. - }
  20881. - return;
  20882. - case 's':
  20883. - save_cur(currcons);
  20884. - return;
  20885. - case 'u':
  20886. - restore_cur(currcons);
  20887. - return;
  20888. - case 'X':
  20889. - csi_X(currcons, par[0]);
  20890. - return;
  20891. - case '@':
  20892. - csi_at(currcons,par[0]);
  20893. - return;
  20894. - case ']': /* setterm functions */
  20895. - setterm_command(currcons);
  20896. - return;
  20897. + break;
  20898. + case 'n':
  20899. + if (!ques) {
  20900. + if (par[0] == 5)
  20901. + status_report(tty);
  20902. + else if (par[0] == 6)
  20903. + cursor_report(currcons,tty);
  20904. }
  20905. - return;
  20906. - case ESpercent:
  20907. - vc_state = ESnormal;
  20908. - switch (c) {
  20909. - case '@': /* defined in ISO 2022 */
  20910. - utf = 0;
  20911. - return;
  20912. - case 'G': /* prelim official escape code */
  20913. - case '8': /* retained for compatibility */
  20914. - utf = 1;
  20915. - return;
  20916. + return 0;
  20917. + }
  20918. + if (ques) {
  20919. + ques = 0;
  20920. + return 0;
  20921. + }
  20922. + switch(c) {
  20923. + case 'G': case '`':
  20924. + if (par[0]) par[0]--;
  20925. + gotoxy(currcons,par[0],y);
  20926. + break;
  20927. + case 'A':
  20928. + if (!par[0]) par[0]++;
  20929. + gotoxy(currcons,x,y-par[0]);
  20930. + break;
  20931. + case 'B': case 'e':
  20932. + if (!par[0]) par[0]++;
  20933. + gotoxy(currcons,x,y+par[0]);
  20934. + break;
  20935. + case 'C': case 'a':
  20936. + if (!par[0]) par[0]++;
  20937. + gotoxy(currcons,x+par[0],y);
  20938. + break;
  20939. + case 'D':
  20940. + if (!par[0]) par[0]++;
  20941. + gotoxy(currcons,x-par[0],y);
  20942. + break;
  20943. + case 'E':
  20944. + if (!par[0]) par[0]++;
  20945. + gotoxy(currcons,0,y+par[0]);
  20946. + break;
  20947. + case 'F':
  20948. + if (!par[0]) par[0]++;
  20949. + gotoxy(currcons,0,y-par[0]);
  20950. + break;
  20951. + case 'd':
  20952. + if (par[0]) par[0]--;
  20953. + gotoxay(currcons,x,par[0]);
  20954. + break;
  20955. + case 'H': case 'f':
  20956. + if (par[0]) par[0]--;
  20957. + if (par[1]) par[1]--;
  20958. + gotoxay(currcons,par[1],par[0]);
  20959. + break;
  20960. + case 'J':
  20961. + csi_J(currcons,par[0]);
  20962. + break;
  20963. + case 'K':
  20964. + csi_K(currcons,par[0]);
  20965. + break;
  20966. + case 'L':
  20967. + csi_L(currcons,par[0]);
  20968. + break;
  20969. + case 'M':
  20970. + csi_M(currcons,par[0]);
  20971. + break;
  20972. + case 'P':
  20973. + csi_P(currcons,par[0]);
  20974. + break;
  20975. + case 'c':
  20976. + if (!par[0])
  20977. + respond_ID(tty);
  20978. + break;
  20979. + case 'g':
  20980. + if (!par[0])
  20981. + tab_stop[x >> 5] &= ~(1 << (x & 31));
  20982. + else if (par[0] == 3) {
  20983. + tab_stop[0] =
  20984. + tab_stop[1] =
  20985. + tab_stop[2] =
  20986. + tab_stop[3] =
  20987. + tab_stop[4] = 0;
  20988. }
  20989. - return;
  20990. - case ESfunckey:
  20991. - vc_state = ESnormal;
  20992. - return;
  20993. - case EShash:
  20994. - vc_state = ESnormal;
  20995. - if (c == '8') {
  20996. - /* DEC screen alignment test. kludge :-) */
  20997. - video_erase_char =
  20998. - (video_erase_char & 0xff00) | 'E';
  20999. - csi_J(currcons, 2);
  21000. - video_erase_char =
  21001. - (video_erase_char & 0xff00) | ' ';
  21002. - do_update_region(currcons, origin, screenbuf_size/2);
  21003. + break;
  21004. + case 'm':
  21005. + csi_m(currcons);
  21006. + return 1;
  21007. + case 'q': /* DECLL - but only 3 leds */
  21008. + /* map 0,1,2,3 to 0,1,2,4 */
  21009. + if (par[0] < 4)
  21010. + setledstate(kbd_table + currcons,
  21011. + (par[0] < 3) ? par[0] : 4);
  21012. + break;
  21013. + case 'r':
  21014. + if (!par[0])
  21015. + par[0]++;
  21016. + if (!par[1])
  21017. + par[1] = video_num_lines;
  21018. + /* Minimum allowed region is 2 lines */
  21019. + if (par[0] < par[1] &&
  21020. + par[1] <= video_num_lines) {
  21021. + top=par[0]-1;
  21022. + bottom=par[1];
  21023. + gotoxay(currcons,0,0);
  21024. }
  21025. - return;
  21026. - case ESsetG0:
  21027. - if (c == '0')
  21028. - G0_charset = GRAF_MAP;
  21029. - else if (c == 'B')
  21030. - G0_charset = LAT1_MAP;
  21031. - else if (c == 'U')
  21032. - G0_charset = IBMPC_MAP;
  21033. - else if (c == 'K')
  21034. - G0_charset = USER_MAP;
  21035. - if (charset == 0)
  21036. - translate = set_translate(G0_charset,currcons);
  21037. - vc_state = ESnormal;
  21038. - return;
  21039. - case ESsetG1:
  21040. - if (c == '0')
  21041. - G1_charset = GRAF_MAP;
  21042. - else if (c == 'B')
  21043. - G1_charset = LAT1_MAP;
  21044. - else if (c == 'U')
  21045. - G1_charset = IBMPC_MAP;
  21046. - else if (c == 'K')
  21047. - G1_charset = USER_MAP;
  21048. - if (charset == 1)
  21049. - translate = set_translate(G1_charset,currcons);
  21050. - vc_state = ESnormal;
  21051. - return;
  21052. - default:
  21053. - vc_state = ESnormal;
  21054. + break;
  21055. + case 's':
  21056. + save_cur(currcons);
  21057. + break;
  21058. + case 'u':
  21059. + restore_cur(currcons);
  21060. + return 1;
  21061. + case 'X':
  21062. + csi_X(currcons, par[0]);
  21063. + break;
  21064. + case '@':
  21065. + csi_at(currcons,par[0]);
  21066. + break;
  21067. + case ']': /* setterm functions */
  21068. + setterm_command(currcons);
  21069. + break;
  21070. + }
  21071. + return 0;
  21072. +}
  21073. +
  21074. +static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c)
  21075. +{
  21076. + vc_state = con_write_ctrl_ESnormal;
  21077. + switch (c) {
  21078. + case '@': /* defined in ISO 2022 */
  21079. + utf = 0;
  21080. + break;
  21081. + case 'G': /* prelim official escape code */
  21082. + case '8': /* retained for compatibility */
  21083. + utf = 1;
  21084. + break;
  21085. + }
  21086. + return 0;
  21087. +}
  21088. +
  21089. +static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c)
  21090. +{
  21091. + vc_state = con_write_ctrl_ESnormal;
  21092. + return 0;
  21093. +}
  21094. +
  21095. +static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c)
  21096. +{
  21097. + vc_state = con_write_ctrl_ESnormal;
  21098. + if (c == '8') {
  21099. + /* DEC screen alignment test. kludge :-) */
  21100. + video_erase_char =
  21101. + (video_erase_char & 0xff00) | 'E';
  21102. + csi_J(currcons, 2);
  21103. + video_erase_char =
  21104. + (video_erase_char & 0xff00) | ' ';
  21105. + do_update_region(currcons, origin, screenbuf_size/2);
  21106. + }
  21107. + return 0;
  21108. +}
  21109. +
  21110. +static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c)
  21111. +{
  21112. + switch (c) {
  21113. + case '0':
  21114. + G0_charset = GRAF_MAP;
  21115. + break;
  21116. + case 'B':
  21117. + G0_charset = LAT1_MAP;
  21118. + break;
  21119. + case 'U':
  21120. + G0_charset = IBMPC_MAP;
  21121. + break;
  21122. + case 'K':
  21123. + G0_charset = USER_MAP;
  21124. + break;
  21125. + }
  21126. + if (charset == 0) {
  21127. + translate = set_translate(G0_charset,currcons);
  21128. + return 1;
  21129. + }
  21130. + vc_state = con_write_ctrl_ESnormal;
  21131. + return 0;
  21132. +}
  21133. +
  21134. +static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c)
  21135. +{
  21136. + switch (c) {
  21137. + case '0':
  21138. + G1_charset = GRAF_MAP;
  21139. + break;
  21140. + case 'B':
  21141. + G1_charset = LAT1_MAP;
  21142. + break;
  21143. + case 'U':
  21144. + G1_charset = IBMPC_MAP;
  21145. + break;
  21146. + case 'K':
  21147. + G1_charset = USER_MAP;
  21148. + break;
  21149. + }
  21150. + if (charset == 1) {
  21151. + translate = set_translate(G1_charset,currcons);
  21152. + return 1;
  21153. }
  21154. + vc_state = con_write_ctrl_ESnormal;
  21155. + return 0;
  21156. }
  21157. /* This is a temporary buffer used to prepare a tty console write
  21158. @@ -1855,7 +1972,7 @@
  21159. unsigned long draw_from = 0, draw_to = 0;
  21160. struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
  21161. u16 himask, charmask;
  21162. - const unsigned char *orig_buf = NULL;
  21163. + const unsigned char *orig_buf;
  21164. int orig_count;
  21165. if (in_interrupt())
  21166. @@ -1913,42 +2030,12 @@
  21167. count--;
  21168. if (utf) {
  21169. - /* Combine UTF-8 into Unicode */
  21170. - /* Incomplete characters silently ignored */
  21171. - if(c > 0x7f) {
  21172. - if (utf_count > 0 && (c & 0xc0) == 0x80) {
  21173. - utf_char = (utf_char << 6) | (c & 0x3f);
  21174. - utf_count--;
  21175. - if (utf_count == 0)
  21176. - tc = c = utf_char;
  21177. - else continue;
  21178. - } else {
  21179. - if ((c & 0xe0) == 0xc0) {
  21180. - utf_count = 1;
  21181. - utf_char = (c & 0x1f);
  21182. - } else if ((c & 0xf0) == 0xe0) {
  21183. - utf_count = 2;
  21184. - utf_char = (c & 0x0f);
  21185. - } else if ((c & 0xf8) == 0xf0) {
  21186. - utf_count = 3;
  21187. - utf_char = (c & 0x07);
  21188. - } else if ((c & 0xfc) == 0xf8) {
  21189. - utf_count = 4;
  21190. - utf_char = (c & 0x03);
  21191. - } else if ((c & 0xfe) == 0xfc) {
  21192. - utf_count = 5;
  21193. - utf_char = (c & 0x01);
  21194. - } else
  21195. - utf_count = 0;
  21196. + tc = con_write_utf(currcons, c);
  21197. + if (tc < 0)
  21198. continue;
  21199. - }
  21200. - } else {
  21201. - tc = c;
  21202. - utf_count = 0;
  21203. - }
  21204. - } else { /* no utf */
  21205. - tc = translate[toggle_meta ? (c|0x80) : c];
  21206. - }
  21207. + c = tc;
  21208. + } else /* no utf */
  21209. + tc = translate[toggle_meta ? (c|0x80) : c];
  21210. /* If the original code was a control character we
  21211. * only allow a glyph to be displayed if the code is
  21212. @@ -1966,7 +2053,7 @@
  21213. && (c != 127 || disp_ctrl)
  21214. && (c != 128+27);
  21215. - if (vc_state == ESnormal && ok) {
  21216. + if (vc_state == con_write_ctrl_ESnormal && ok) {
  21217. /* Now try to find out how to display it */
  21218. tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
  21219. if ( tc == -4 ) {
  21220. @@ -2112,7 +2199,7 @@
  21221. if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
  21222. currcons = kmsg_redirect - 1;
  21223. - /* read `x' only after setting currecons properly (otherwise
  21224. + /* read `x' only after setting currcons properly (otherwise
  21225. the `x' macro will read the x of the foreground console). */
  21226. myx = x;
  21227. @@ -2475,8 +2562,8 @@
  21228. console_driver.init_termios = tty_std_termios;
  21229. console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
  21230. /* Tell tty_register_driver() to skip consoles because they are
  21231. - * registered before kmalloc() is ready. We'll patch them in later.
  21232. - * See comments at console_init(); see also con_init_devfs().
  21233. + * registered before kmalloc() is ready. We'll patch them in later.
  21234. + * See comments at console_init(); see also con_init_devfs().
  21235. */
  21236. console_driver.flags |= TTY_DRIVER_NO_DEVFS;
  21237. console_driver.refcount = &console_refcount;
  21238. @@ -2719,7 +2806,7 @@
  21239. if (console_blank_hook && console_blank_hook(1))
  21240. return;
  21241. - if (vesa_blank_mode)
  21242. + if (vesa_blank_mode)
  21243. sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
  21244. }
  21245. @@ -2893,7 +2980,7 @@
  21246. if (!op->height) { /* Need to guess font height [compat] */
  21247. int h, i;
  21248. u8 *charmap = op->data, tmp;
  21249. -
  21250. +
  21251. /* If from KDFONTOP ioctl, don't allow things which can be done in userland,
  21252. so that we can get rid of this soon */
  21253. if (!(op->flags & KD_FONT_FLAG_OLD))
  21254. @@ -2940,18 +3027,18 @@
  21255. op->data = old_op.data;
  21256. if (!rc && !set) {
  21257. int c = (op->width+7)/8 * 32 * op->charcount;
  21258. -
  21259. +
  21260. if (op->data && op->charcount > old_op.charcount)
  21261. rc = -ENOSPC;
  21262. if (!(op->flags & KD_FONT_FLAG_OLD)) {
  21263. - if (op->width > old_op.width ||
  21264. + if (op->width > old_op.width ||
  21265. op->height > old_op.height)
  21266. rc = -ENOSPC;
  21267. } else {
  21268. if (op->width != 8)
  21269. rc = -EIO;
  21270. else if ((old_op.height && op->height > old_op.height) ||
  21271. - op->height > 32)
  21272. + op->height > 32)
  21273. rc = -ENOSPC;
  21274. }
  21275. if (!rc && op->data && copy_to_user(op->data, temp, c))
  21276. diff -urN linux-2.4.26/drivers/char/ds1307.c linux-2.4.26-vrs1/drivers/char/ds1307.c
  21277. --- linux-2.4.26/drivers/char/ds1307.c 1970-01-01 01:00:00.000000000 +0100
  21278. +++ linux-2.4.26-vrs1/drivers/char/ds1307.c 2004-01-14 21:32:25.000000000 +0000
  21279. @@ -0,0 +1,604 @@
  21280. +/*
  21281. + * ds1307.c
  21282. + *
  21283. + * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
  21284. + *
  21285. + * Copyright (C) 2002 Intrinsyc Software Inc.
  21286. + *
  21287. + * This program is free software; you can redistribute it and/or modify
  21288. + * it under the terms of the GNU General Public License version 2 as
  21289. + * published by the Free Software Foundation.
  21290. + *
  21291. + */
  21292. +
  21293. +#include <linux/config.h>
  21294. +#include <linux/module.h>
  21295. +#include <linux/version.h>
  21296. +
  21297. +#include <linux/kernel.h>
  21298. +#include <linux/poll.h>
  21299. +#include <linux/i2c.h>
  21300. +#include <linux/slab.h>
  21301. +#include <linux/init.h>
  21302. +#include <linux/rtc.h>
  21303. +#include <linux/string.h>
  21304. +#include <linux/miscdevice.h>
  21305. +#include <linux/proc_fs.h>
  21306. +
  21307. +#include "ds1307.h"
  21308. +
  21309. +#define DEBUG 0
  21310. +
  21311. +#if DEBUG
  21312. +static unsigned int rtc_debug = DEBUG;
  21313. +#else
  21314. +#define rtc_debug 0 /* gcc will remove all the debug code for us */
  21315. +#endif
  21316. +
  21317. +static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
  21318. +
  21319. +struct i2c_driver ds1307_driver;
  21320. +struct i2c_client *ds1307_i2c_client = 0;
  21321. +
  21322. +static unsigned short ignore[] = { I2C_CLIENT_END };
  21323. +static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
  21324. +
  21325. +static struct i2c_client_address_data addr_data = {
  21326. + normal_i2c: normal_addr,
  21327. + normal_i2c_range: ignore,
  21328. + probe: ignore,
  21329. + probe_range: ignore,
  21330. + ignore: ignore,
  21331. + ignore_range: ignore,
  21332. + force: ignore,
  21333. +};
  21334. +
  21335. +static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
  21336. +static int ds1307_rtc_open(struct inode *inode, struct file *file);
  21337. +static int ds1307_rtc_release(struct inode *inode, struct file *file);
  21338. +
  21339. +static struct file_operations rtc_fops = {
  21340. + owner: THIS_MODULE,
  21341. + ioctl: ds1307_rtc_ioctl,
  21342. + open: ds1307_rtc_open,
  21343. + release: ds1307_rtc_release,
  21344. +};
  21345. +
  21346. +static struct miscdevice ds1307_rtc_miscdev = {
  21347. + RTC_MINOR,
  21348. + "rtc",
  21349. + &rtc_fops
  21350. +};
  21351. +
  21352. +static int ds1307_probe(struct i2c_adapter *adap);
  21353. +static int ds1307_detach(struct i2c_client *client);
  21354. +static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
  21355. +
  21356. +struct i2c_driver ds1307_driver = {
  21357. + name: "DS1307",
  21358. + id: I2C_DRIVERID_DS1307,
  21359. + flags: I2C_DF_NOTIFY,
  21360. + attach_adapter: ds1307_probe,
  21361. + detach_client: ds1307_detach,
  21362. + command: ds1307_command
  21363. +};
  21364. +
  21365. +static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
  21366. +
  21367. +#define DAT(x) ((unsigned int)((x)->data)) /* keep the control register info */
  21368. +
  21369. +static int
  21370. +ds1307_readram( char *buf, int len)
  21371. +{
  21372. + unsigned long flags;
  21373. + unsigned char ad[1] = { 0 };
  21374. + int ret;
  21375. + struct i2c_msg msgs[2] = {
  21376. + { ds1307_i2c_client->addr , 0, 1, ad },
  21377. + { ds1307_i2c_client->addr , I2C_M_RD, len, buf } };
  21378. +
  21379. + spin_lock_irqsave(&ds1307_rtc_lock, flags);
  21380. + ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
  21381. + spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
  21382. +
  21383. + return ret;
  21384. +}
  21385. +
  21386. +static void
  21387. +ds1307_dumpram( void)
  21388. +{
  21389. + unsigned char buf[DS1307_RAM_SIZE];
  21390. + int ret;
  21391. +
  21392. + ret = ds1307_readram( buf, DS1307_RAM_SIZE);
  21393. +
  21394. + if( ret > 0)
  21395. + {
  21396. + int i;
  21397. + for( i=0; i<DS1307_RAM_SIZE; i++)
  21398. + {
  21399. + printk ("%02X ", buf[i]);
  21400. + if( (i%8) == 7) printk ("\n");
  21401. + }
  21402. + printk ("\n");
  21403. + }
  21404. +}
  21405. +
  21406. +static void
  21407. +ds1307_enable_clock( int enable)
  21408. +{
  21409. + unsigned char buf[2], ad[1] = { 0 };
  21410. + struct i2c_msg msgs[2] = {
  21411. + { ds1307_i2c_client->addr , 0, 1, ad },
  21412. + { ds1307_i2c_client->addr , I2C_M_RD, 1, buf }
  21413. + };
  21414. + unsigned char ctrl_info;
  21415. + int ret;
  21416. +
  21417. + if( enable)
  21418. + ctrl_info = SQW_ENABLE | RATE_32768HZ;
  21419. + else
  21420. + ctrl_info = SQW_DISABLE;
  21421. + ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
  21422. +
  21423. + /* read addr 0 (Clock-Halt bit and second counter */
  21424. + ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
  21425. +
  21426. + if( enable)
  21427. + buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
  21428. + else
  21429. + buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
  21430. + buf[0] = 0; /* control register address on DS1307 */
  21431. +
  21432. + ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
  21433. +}
  21434. +
  21435. +static int
  21436. +ds1307_attach(struct i2c_adapter *adap, int addr, unsigned short flags,int kind)
  21437. +{
  21438. + struct i2c_client *c;
  21439. + unsigned char buf[1], ad[1] = { 7 };
  21440. + struct i2c_msg msgs[2] = {
  21441. + { addr , 0, 1, ad },
  21442. + { addr , I2C_M_RD, 1, buf }
  21443. + };
  21444. + int ret;
  21445. +
  21446. + c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
  21447. + if (!c)
  21448. + return -ENOMEM;
  21449. +
  21450. + strcpy(c->name, "DS1307");
  21451. + c->id = ds1307_driver.id;
  21452. + c->flags = 0;
  21453. + c->addr = addr;
  21454. + c->adapter = adap;
  21455. + c->driver = &ds1307_driver;
  21456. + c->data = NULL;
  21457. +
  21458. + ret = i2c_transfer(c->adapter, msgs, 2);
  21459. +
  21460. + if ( ret == 2 )
  21461. + {
  21462. + DAT(c) = buf[0];
  21463. + }
  21464. + else
  21465. + printk ("ds1307_attach(): i2c_transfer() returned %d.\n",ret);
  21466. +
  21467. + ds1307_i2c_client = c;
  21468. + ds1307_enable_clock( 1);
  21469. +
  21470. + return i2c_attach_client(c);
  21471. +}
  21472. +
  21473. +static int
  21474. +ds1307_probe(struct i2c_adapter *adap)
  21475. +{
  21476. + return i2c_probe(adap, &addr_data, ds1307_attach);
  21477. +}
  21478. +
  21479. +static int
  21480. +ds1307_detach(struct i2c_client *client)
  21481. +{
  21482. + i2c_detach_client(client);
  21483. + ds1307_enable_clock( 0);
  21484. +
  21485. + return 0;
  21486. +}
  21487. +
  21488. +static void
  21489. +ds1307_convert_to_time( struct rtc_time *dt, char *buf)
  21490. +{
  21491. + dt->tm_sec = BCD_TO_BIN(buf[0]);
  21492. + dt->tm_min = BCD_TO_BIN(buf[1]);
  21493. +
  21494. + if ( TWELVE_HOUR_MODE(buf[2]) )
  21495. + {
  21496. + dt->tm_hour = HOURS_12(buf[2]);
  21497. + if (HOURS_AP(buf[2])) /* PM */
  21498. + {
  21499. + dt->tm_hour += 12;
  21500. + }
  21501. + }
  21502. + else /* 24-hour-mode */
  21503. + {
  21504. + dt->tm_hour = HOURS_24(buf[2]);
  21505. + }
  21506. +
  21507. + dt->tm_mday = BCD_TO_BIN(buf[4]);
  21508. + /* dt->tm_mon is zero-based */
  21509. + dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
  21510. + /* year is 1900 + dt->tm_year */
  21511. + dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
  21512. +
  21513. + if( rtc_debug > 2)
  21514. + {
  21515. + printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
  21516. + printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon);
  21517. + printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
  21518. + printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
  21519. + printk("ds1307_get_datetime: min = %d\n", dt->tm_min);
  21520. + printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec);
  21521. + }
  21522. +}
  21523. +
  21524. +static int
  21525. +ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
  21526. +{
  21527. + unsigned char buf[7], addr[1] = { 0 };
  21528. + struct i2c_msg msgs[2] = {
  21529. + { client->addr, 0, 1, addr },
  21530. + { client->addr, I2C_M_RD, 7, buf }
  21531. + };
  21532. + int ret = -EIO;
  21533. +
  21534. + memset(buf, 0, sizeof(buf));
  21535. +
  21536. + ret = i2c_transfer(client->adapter, msgs, 2);
  21537. +
  21538. + if (ret == 2) {
  21539. + ds1307_convert_to_time( dt, buf);
  21540. + ret = 0;
  21541. + }
  21542. + else
  21543. + printk("ds1307_get_datetime(), i2c_transfer() returned %d\n",ret);
  21544. +
  21545. + return ret;
  21546. +}
  21547. +
  21548. +static int
  21549. +ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
  21550. +{
  21551. + unsigned char buf[8];
  21552. + int ret, len = 4;
  21553. +
  21554. + if( rtc_debug > 2)
  21555. + {
  21556. + printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
  21557. + printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon);
  21558. + printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
  21559. + printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
  21560. + printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min);
  21561. + printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec);
  21562. + }
  21563. +
  21564. + buf[0] = 0; /* register address on DS1307 */
  21565. + buf[1] = (BIN_TO_BCD(dt->tm_sec));
  21566. + buf[2] = (BIN_TO_BCD(dt->tm_min));
  21567. + buf[3] = (BIN_TO_BCD(dt->tm_hour));
  21568. +
  21569. + if (datetoo) {
  21570. + len = 8;
  21571. + /* we skip buf[4] as we don't use day-of-week. */
  21572. + buf[5] = (BIN_TO_BCD(dt->tm_mday));
  21573. + buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
  21574. + /* The year only ranges from 0-99, we are being passed an offset from 1900,
  21575. + * and the chip calulates leap years based on 2000, thus we adjust by 100.
  21576. + */
  21577. + buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
  21578. + }
  21579. + ret = i2c_master_send(client, (char *)buf, len);
  21580. + if (ret == len)
  21581. + ret = 0;
  21582. + else
  21583. + printk("ds1307_set_datetime(), i2c_master_send() returned %d\n",ret);
  21584. +
  21585. +
  21586. + return ret;
  21587. +}
  21588. +
  21589. +static int
  21590. +ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
  21591. +{
  21592. + *ctrl = DAT(client);
  21593. +
  21594. + return 0;
  21595. +}
  21596. +
  21597. +static int
  21598. +ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
  21599. +{
  21600. + unsigned char buf[2];
  21601. + int ret;
  21602. +
  21603. +
  21604. + buf[0] = 7; /* control register address on DS1307 */
  21605. + buf[1] = *cinfo;
  21606. + /* save the control reg info in the client data field so that get_ctrl
  21607. + * function doesn't have to do an I2C transfer to get it.
  21608. + */
  21609. + DAT(client) = buf[1];
  21610. +
  21611. + ret = i2c_master_send(client, (char *)buf, 2);
  21612. +
  21613. + return ret;
  21614. +}
  21615. +
  21616. +static int
  21617. +ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
  21618. +{
  21619. + unsigned char addr[1];
  21620. + struct i2c_msg msgs[2] = {
  21621. + { client->addr, 0, 1, addr },
  21622. + { client->addr, I2C_M_RD, mem->nr, mem->data }
  21623. + };
  21624. +
  21625. + if ( (mem->loc < DS1307_RAM_ADDR_START) ||
  21626. + ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
  21627. + return -EINVAL;
  21628. +
  21629. + addr[0] = mem->loc;
  21630. +
  21631. + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
  21632. +}
  21633. +
  21634. +static int
  21635. +ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
  21636. +{
  21637. + unsigned char addr[1];
  21638. + struct i2c_msg msgs[2] = {
  21639. + { client->addr, 0, 1, addr },
  21640. + { client->addr, 0, mem->nr, mem->data }
  21641. + };
  21642. +
  21643. + if ( (mem->loc < DS1307_RAM_ADDR_START) ||
  21644. + ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
  21645. + return -EINVAL;
  21646. +
  21647. + addr[0] = mem->loc;
  21648. +
  21649. + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
  21650. +}
  21651. +
  21652. +static int
  21653. +ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
  21654. +{
  21655. + switch (cmd) {
  21656. + case DS1307_GETDATETIME:
  21657. + return ds1307_get_datetime(client, arg);
  21658. +
  21659. + case DS1307_SETTIME:
  21660. + return ds1307_set_datetime(client, arg, 0);
  21661. +
  21662. + case DS1307_SETDATETIME:
  21663. + return ds1307_set_datetime(client, arg, 1);
  21664. +
  21665. + case DS1307_GETCTRL:
  21666. + return ds1307_get_ctrl(client, arg);
  21667. +
  21668. + case DS1307_SETCTRL:
  21669. + return ds1307_set_ctrl(client, arg);
  21670. +
  21671. + case DS1307_MEM_READ:
  21672. + return ds1307_read_mem(client, arg);
  21673. +
  21674. + case DS1307_MEM_WRITE:
  21675. + return ds1307_write_mem(client, arg);
  21676. +
  21677. + default:
  21678. + return -EINVAL;
  21679. + }
  21680. +}
  21681. +
  21682. +static int
  21683. +ds1307_rtc_open(struct inode *inode, struct file *file)
  21684. +{
  21685. + return 0;
  21686. +}
  21687. +
  21688. +static int
  21689. +ds1307_rtc_release(struct inode *inode, struct file *file)
  21690. +{
  21691. + return 0;
  21692. +}
  21693. +
  21694. +static int
  21695. +ds1307_rtc_ioctl( struct inode *inode, struct file *file,
  21696. + unsigned int cmd, unsigned long arg)
  21697. +{
  21698. + unsigned long flags;
  21699. + struct rtc_time wtime;
  21700. + int status = 0;
  21701. +
  21702. + switch (cmd) {
  21703. + default:
  21704. + case RTC_UIE_ON:
  21705. + case RTC_UIE_OFF:
  21706. + case RTC_PIE_ON:
  21707. + case RTC_PIE_OFF:
  21708. + case RTC_AIE_ON:
  21709. + case RTC_AIE_OFF:
  21710. + case RTC_ALM_SET:
  21711. + case RTC_ALM_READ:
  21712. + case RTC_IRQP_READ:
  21713. + case RTC_IRQP_SET:
  21714. + case RTC_EPOCH_READ:
  21715. + case RTC_EPOCH_SET:
  21716. + case RTC_WKALM_SET:
  21717. + case RTC_WKALM_RD:
  21718. + status = -EINVAL;
  21719. + break;
  21720. +
  21721. + case RTC_RD_TIME:
  21722. + spin_lock_irqsave(&ds1307_rtc_lock, flags);
  21723. + ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
  21724. + spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
  21725. +
  21726. + if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
  21727. + status = -EFAULT;
  21728. + break;
  21729. +
  21730. + case RTC_SET_TIME:
  21731. + if (!capable(CAP_SYS_TIME))
  21732. + {
  21733. + status = -EACCES;
  21734. + break;
  21735. + }
  21736. +
  21737. + if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
  21738. + {
  21739. + status = -EFAULT;
  21740. + break;
  21741. + }
  21742. +
  21743. + spin_lock_irqsave(&ds1307_rtc_lock, flags);
  21744. + ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
  21745. + spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
  21746. + break;
  21747. + }
  21748. +
  21749. + return status;
  21750. +}
  21751. +
  21752. +static char *
  21753. +ds1307_mon2str( unsigned int mon)
  21754. +{
  21755. + char *mon2str[12] = {
  21756. + "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  21757. + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  21758. + };
  21759. + if( mon > 11) return "error";
  21760. + else return mon2str[ mon];
  21761. +}
  21762. +
  21763. +static int ds1307_rtc_proc_output( char *buf)
  21764. +{
  21765. +#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
  21766. + unsigned char ram[DS1307_RAM_SIZE];
  21767. + int ret;
  21768. +
  21769. + char *p = buf;
  21770. +
  21771. + ret = ds1307_readram( ram, DS1307_RAM_SIZE);
  21772. + if( ret > 0)
  21773. + {
  21774. + int i;
  21775. + struct rtc_time dt;
  21776. + char text[9];
  21777. +
  21778. + p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
  21779. +
  21780. + ds1307_convert_to_time( &dt, ram);
  21781. + p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n",
  21782. + dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
  21783. + dt.tm_hour, dt.tm_min, dt.tm_sec);
  21784. +
  21785. + p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80));
  21786. + p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40));
  21787. + p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
  21788. + p += sprintf(p, "Freq : ");
  21789. +
  21790. + switch( ram[7] & 0x03)
  21791. + {
  21792. + case RATE_1HZ:
  21793. + p += sprintf(p, "1Hz\n");
  21794. + break;
  21795. + case RATE_4096HZ:
  21796. + p += sprintf(p, "4.096kHz\n");
  21797. + break;
  21798. + case RATE_8192HZ:
  21799. + p += sprintf(p, "8.192kHz\n");
  21800. + break;
  21801. + case RATE_32768HZ:
  21802. + default:
  21803. + p += sprintf(p, "32.768kHz\n");
  21804. + break;
  21805. +
  21806. + }
  21807. +
  21808. + p += sprintf(p, "RAM dump:\n");
  21809. + text[8]='\0';
  21810. + for( i=0; i<DS1307_RAM_SIZE; i++)
  21811. + {
  21812. + p += sprintf(p, "%02X ", ram[i]);
  21813. +
  21814. + if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
  21815. + text[i%8] = ram[i];
  21816. + if( (i%8) == 7) p += sprintf(p, "%s\n",text);
  21817. + }
  21818. + p += sprintf(p, "\n");
  21819. + }
  21820. + else
  21821. + {
  21822. + p += sprintf(p, "Failed to read RTC memory!\n");
  21823. + }
  21824. +
  21825. + return p - buf;
  21826. +}
  21827. +
  21828. +static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
  21829. + int count, int *eof, void *data)
  21830. +{
  21831. + int len = ds1307_rtc_proc_output (page);
  21832. + if (len <= off+count) *eof = 1;
  21833. + *start = page + off;
  21834. + len -= off;
  21835. + if (len>count) len = count;
  21836. + if (len<0) len = 0;
  21837. + return len;
  21838. +}
  21839. +
  21840. +static __init int ds1307_init(void)
  21841. +{
  21842. + int retval=0;
  21843. +
  21844. + if( slave_address != 0xffff)
  21845. + {
  21846. + normal_addr[0] = slave_address;
  21847. + }
  21848. +
  21849. + if( normal_addr[0] == 0xffff)
  21850. + {
  21851. + printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
  21852. + normal_addr[0]);
  21853. + return -EINVAL;
  21854. + }
  21855. +
  21856. + retval = i2c_add_driver(&ds1307_driver);
  21857. +
  21858. + if (retval==0)
  21859. + {
  21860. + misc_register (&ds1307_rtc_miscdev);
  21861. + create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
  21862. + printk("I2C: DS1307 RTC driver successfully loaded\n");
  21863. +
  21864. + if( rtc_debug) ds1307_dumpram();
  21865. + }
  21866. + return retval;
  21867. +}
  21868. +
  21869. +static __exit void ds1307_exit(void)
  21870. +{
  21871. + remove_proc_entry (PROC_DS1307_NAME, NULL);
  21872. + misc_deregister(&ds1307_rtc_miscdev);
  21873. + i2c_del_driver(&ds1307_driver);
  21874. +}
  21875. +
  21876. +module_init(ds1307_init);
  21877. +module_exit(ds1307_exit);
  21878. +
  21879. +MODULE_PARM (slave_address, "i");
  21880. +MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
  21881. +
  21882. +MODULE_AUTHOR ("Intrinsyc Software Inc.");
  21883. +MODULE_LICENSE("GPL");
  21884. diff -urN linux-2.4.26/drivers/char/ds1307.h linux-2.4.26-vrs1/drivers/char/ds1307.h
  21885. --- linux-2.4.26/drivers/char/ds1307.h 1970-01-01 01:00:00.000000000 +0100
  21886. +++ linux-2.4.26-vrs1/drivers/char/ds1307.h 2004-03-04 22:44:33.000000000 +0000
  21887. @@ -0,0 +1,58 @@
  21888. +/*
  21889. + * ds1307.h
  21890. + *
  21891. + * Copyright (C) 2002 Intrinsyc Software Inc.
  21892. + *
  21893. + * This program is free software; you can redistribute it and/or modify
  21894. + * it under the terms of the GNU General Public License version 2 as
  21895. + * published by the Free Software Foundation.
  21896. + *
  21897. + */
  21898. +#ifndef DS1307_H
  21899. +#define DS1307_H
  21900. +
  21901. +#if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD) || defined(CONFIG_MACH_CSB337)
  21902. + #define DS1307_I2C_SLAVE_ADDR 0x68
  21903. +#else
  21904. + #define DS1307_I2C_SLAVE_ADDR 0xffff
  21905. +#endif
  21906. +
  21907. +#define DS1307_RAM_ADDR_START 0x08
  21908. +#define DS1307_RAM_ADDR_END 0x3F
  21909. +#define DS1307_RAM_SIZE 0x40
  21910. +
  21911. +#define PROC_DS1307_NAME "driver/ds1307"
  21912. +
  21913. +struct rtc_mem {
  21914. + unsigned int loc;
  21915. + unsigned int nr;
  21916. + unsigned char *data;
  21917. +};
  21918. +
  21919. +#define DS1307_GETDATETIME 0
  21920. +#define DS1307_SETTIME 1
  21921. +#define DS1307_SETDATETIME 2
  21922. +#define DS1307_GETCTRL 3
  21923. +#define DS1307_SETCTRL 4
  21924. +#define DS1307_MEM_READ 5
  21925. +#define DS1307_MEM_WRITE 6
  21926. +
  21927. +#define SQW_ENABLE 0x10 /* Square Wave Enable */
  21928. +#define SQW_DISABLE 0x00 /* Square Wave disable */
  21929. +
  21930. +#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */
  21931. +#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */
  21932. +#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */
  21933. +#define RATE_1HZ 0x00 /* Rate Select 1Hz */
  21934. +
  21935. +#define CLOCK_HALT 0x80 /* Clock Halt */
  21936. +
  21937. +#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
  21938. +#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
  21939. +
  21940. +#define TWELVE_HOUR_MODE(n) (((n)>>6)&1)
  21941. +#define HOURS_AP(n) (((n)>>5)&1)
  21942. +#define HOURS_12(n) BCD_TO_BIN((n)&0x1F)
  21943. +#define HOURS_24(n) BCD_TO_BIN((n)&0x3F)
  21944. +
  21945. +#endif
  21946. diff -urN linux-2.4.26/drivers/char/edb7211_keyb.c linux-2.4.26-vrs1/drivers/char/edb7211_keyb.c
  21947. --- linux-2.4.26/drivers/char/edb7211_keyb.c 1970-01-01 01:00:00.000000000 +0100
  21948. +++ linux-2.4.26-vrs1/drivers/char/edb7211_keyb.c 2004-01-14 21:32:25.000000000 +0000
  21949. @@ -0,0 +1,335 @@
  21950. +/*
  21951. + * drivers/char/edb7211_keyb.c
  21952. + *
  21953. + * Copyright (C) 2000 Blue Mug, Inc. All Rights Reserved.
  21954. + *
  21955. + * EDB7211 Keyboard driver for ARM Linux.
  21956. + *
  21957. + * The EP7211 keyboard hardware only supports generating interrupts for 64 keys.
  21958. + * The EBD7211's keyboard has 84 keys. Therefore we need to poll for keys,
  21959. + * instead of waiting for interrupts.
  21960. + *
  21961. + * In a real-world hardware situation, this would be a bad thing. It would
  21962. + * kill power management.
  21963. + */
  21964. +
  21965. +#include <linux/config.h>
  21966. +#include <linux/sched.h>
  21967. +#include <linux/interrupt.h>
  21968. +#include <linux/tty.h>
  21969. +#include <linux/tty_flip.h>
  21970. +#include <linux/mm.h>
  21971. +#include <linux/slab.h>
  21972. +#include <linux/ptrace.h>
  21973. +#include <linux/signal.h>
  21974. +#include <linux/timer.h>
  21975. +#include <linux/tqueue.h>
  21976. +#include <linux/random.h>
  21977. +#include <linux/ctype.h>
  21978. +#include <linux/init.h>
  21979. +#include <linux/kbd_ll.h>
  21980. +#include <linux/kbd_kern.h>
  21981. +#include <linux/delay.h>
  21982. +
  21983. +#include <asm/bitops.h>
  21984. +#include <asm/keyboard.h>
  21985. +#include <asm/irq.h>
  21986. +#include <asm/hardware.h>
  21987. +
  21988. +#include <asm/io.h>
  21989. +#include <asm/system.h>
  21990. +
  21991. +
  21992. +/*
  21993. + * The number of jiffies between keyboard scans.
  21994. + */
  21995. +#define KEYBOARD_SCAN_INTERVAL 5
  21996. +
  21997. +/*
  21998. + * Values for the keyboard column scan control register.
  21999. + */
  22000. +#define KBSC_HI 0x0 /* All driven high */
  22001. +#define KBSC_LO 0x1 /* All driven low */
  22002. +#define KBSC_X 0x2 /* All high impedance */
  22003. +#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
  22004. +#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
  22005. +#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
  22006. +#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
  22007. +#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
  22008. +#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
  22009. +#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
  22010. +#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
  22011. +
  22012. +
  22013. +/* XXX: Figure out what these values should be... */
  22014. +/* Simple translation table for the SysRq keys */
  22015. +#ifdef CONFIG_MAGIC_SYSRQ
  22016. +unsigned char edb7211_kbd_sysrq_xlate[128] =
  22017. + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
  22018. + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
  22019. + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
  22020. + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
  22021. + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
  22022. + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
  22023. + "\r\000/"; /* 0x60 - 0x6f */
  22024. +#endif
  22025. +
  22026. +/*
  22027. + * Row/column to scancode mappings.
  22028. + *
  22029. + * This table maps row/column keyboard matrix positions to XT scancodes.
  22030. + *
  22031. + * The port A rows come first, followed by the extended rows.
  22032. + */
  22033. +static unsigned char colrow_2_scancode[128] =
  22034. +{
  22035. +/* Column:
  22036. + Row 0 1 2 3 4 5 6 7 */
  22037. +/* A0 */ 0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x40, 0x41,
  22038. +/* A1 */ 0x02, 0x07, 0x06, 0x05, 0x04, 0x03, 0x08, 0x09,
  22039. +/* A2 */ 0x0f, 0x14, 0x13, 0x12, 0x11, 0x10, 0x15, 0x16,
  22040. +/* A3 */ 0x3a, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x23, 0x24,
  22041. +/* A4 */ 0x29, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x31, 0x32,
  22042. +/* A5 */ 0x39, 0x35, 0x6F, 0x52, 0x00, 0x6B, 0x34, 0x33,
  22043. +/* A6 */ 0x6A, 0x27, 0x28, 0x00, 0x1c, 0x6D, 0x26, 0x25,
  22044. +/* A7 */ 0x67, 0x19, 0x1a, 0x1b, 0x2b, 0x68, 0x18, 0x17,
  22045. +/* E0 */ 0x6C, 0x0c, 0x0d, 0x0e, 0x00, 0x66, 0x0b, 0x0a,
  22046. +/* E1 */ 0x69, 0x44, 0x45, 0x37, 0x46, 0x77, 0x43, 0x42,
  22047. +/* E2 */ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  22048. +/* E3 */ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  22049. +/* E4 */ 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  22050. +/* E5 */ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  22051. +/* E6 */ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  22052. +/* E7 */ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  22053. +};
  22054. +
  22055. +/*
  22056. + * A bitfield array which contains the state of the keyboard after the last
  22057. + * scan. A bit set in this array corresponds to a key down. Only the lower
  22058. + * 16 bits of each array element are used.
  22059. + */
  22060. +static unsigned long previous_keys[8];
  22061. +static unsigned long keys[8];
  22062. +
  22063. +
  22064. +/* This will be set to a non-zero value if a key was found to be pressed
  22065. + * in the last scan. */
  22066. +static int key_is_pressed;
  22067. +
  22068. +static struct tq_struct kbd_process_task;
  22069. +static struct timer_list edb7211_kbd_timer;
  22070. +
  22071. +/*
  22072. + * External methods.
  22073. + */
  22074. +void edb7211_kbd_init_hw(void);
  22075. +
  22076. +/*
  22077. + * Internal methods.
  22078. + */
  22079. +static int edb7211_kbd_scan_matrix(u_long* keys);
  22080. +static void edb7211_kbd_timeout(unsigned long data);
  22081. +static void edb7211_kbd_process(void* data);
  22082. +
  22083. +/*
  22084. + * Translate a raw keycode to an XT keyboard scancode.
  22085. + */
  22086. +static int
  22087. +edb7211_translate(unsigned char scancode, unsigned char *keycode,
  22088. + char raw_mode)
  22089. +{
  22090. + *keycode = colrow_2_scancode[scancode & 0x7f];
  22091. + return 1;
  22092. +}
  22093. +
  22094. +/*
  22095. + * Scan the keyboard matrix; for each key that is pressed, set the
  22096. + * corresponding bit in the bitfield array.
  22097. + *
  22098. + * The parameter is expected to be an array of 8 32-bit values. Only the lower
  22099. + * 16 bits of each value is used. Each value contains the row bits for the
  22100. + * corresponding column.
  22101. + */
  22102. +static int
  22103. +edb7211_kbd_scan_matrix(u_long* keys)
  22104. +{
  22105. + int column, row, key_pressed;
  22106. + unsigned char port_a_data, ext_port_data;
  22107. +
  22108. + key_pressed = 0;
  22109. +
  22110. + /* Drive all the columns low. */
  22111. + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_LO,
  22112. + SYSCON1);
  22113. +
  22114. + for (column = 0; column < 8; column++) {
  22115. +
  22116. + /* Drive the column high. */
  22117. + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) |
  22118. + (KBSC_COL0 + column), SYSCON1);
  22119. +
  22120. + /* Read port A and the extended port. */
  22121. + port_a_data = clps_readb(PADR) & 0xff;
  22122. + ext_port_data = __raw_readb(EP7211_VIRT_EXTKBD) & 0xff;
  22123. +
  22124. + /* Drive all columns tri-state. */
  22125. + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
  22126. + SYSCON1);
  22127. +
  22128. + /* Look at each column in port A. */
  22129. + for (row=0; row < 8; row++) {
  22130. + /* If the row's bit is set, set the bit in the bitfield.
  22131. + * Otherwise, clear it.
  22132. + */
  22133. + if (port_a_data & (1 << row)) {
  22134. + keys[column] |= (1 << row);
  22135. + key_pressed = 1;
  22136. + } else {
  22137. + keys[column] &= ~(1 << row);
  22138. + }
  22139. + }
  22140. +
  22141. + /* Look at each column in the extended port. */
  22142. + for (row=0; row < 8; row++) {
  22143. + /* If the row's bit is set, set the bit in the bitfield.
  22144. + * Otherwise, clear it.
  22145. + */
  22146. + if (ext_port_data & (1 << row)) {
  22147. + keys[column] |= (1 << (row + 8));
  22148. + key_pressed = 1;
  22149. + } else {
  22150. + keys[column] &= ~(1 << (row + 8));
  22151. + }
  22152. + }
  22153. +
  22154. + /*
  22155. + * Short delay: The example code for the EDB7211 runs an empty
  22156. + * loop 256 times. At this rate, there were some spurious keys
  22157. + * generated. I doubled the delay to let the column drives
  22158. + * settle some.
  22159. + */
  22160. + for (row=0; row < 512; row++) { }
  22161. + }
  22162. +
  22163. + /* If we could use interrupts, we would drive all columns high so
  22164. + * that interrupts will be generated on key presses. But we can't,
  22165. + * so we leave all columns floating.
  22166. + */
  22167. + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
  22168. + SYSCON1);
  22169. +
  22170. + return key_pressed;
  22171. +}
  22172. +
  22173. +/*
  22174. + * XXX: This is really ugly; this needs to be reworked to have less levels of
  22175. + * indentation.
  22176. + */
  22177. +static void
  22178. +edb7211_kbd_timeout(unsigned long data)
  22179. +{
  22180. + /* Schedule the next timer event. */
  22181. + edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
  22182. + add_timer(&edb7211_kbd_timer);
  22183. +
  22184. + if (edb7211_kbd_scan_matrix(keys) || key_is_pressed) {
  22185. + queue_task(&kbd_process_task, &tq_timer);
  22186. + } else {
  22187. + key_is_pressed = 0;
  22188. + }
  22189. +}
  22190. +
  22191. +/*
  22192. + * Process the keys that have been pressed.
  22193. + */
  22194. +static void
  22195. +edb7211_kbd_process(void* data)
  22196. +{
  22197. + int i;
  22198. +
  22199. + /* First check if any keys have been released. */
  22200. + if (key_is_pressed) {
  22201. + for (i=0; i < 8; i++) {
  22202. + if (previous_keys[i]) {
  22203. + int row;
  22204. +
  22205. + for (row=0; row < 16; row++) {
  22206. + if ((previous_keys[i] & (1 << row)) &&
  22207. + !(keys[i] & (1 << row))) {
  22208. + /* Generate the up event. */
  22209. + handle_scancode(
  22210. + (row<<3)+i, 0);
  22211. + }
  22212. + }
  22213. + }
  22214. + }
  22215. + }
  22216. +
  22217. + key_is_pressed = 0;
  22218. +
  22219. + /* Now scan the keys and send press events. */
  22220. + for (i=0; i < 8; i++) {
  22221. + if (keys[i]) {
  22222. + int row;
  22223. +
  22224. + for (row=0; row < 16; row++) {
  22225. + if (keys[i] & (1 << row)) {
  22226. + if (previous_keys[i] & (1 << row)) {
  22227. + /* Generate the hold event. */
  22228. + handle_scancode((row<<3)+i, 1);
  22229. + } else {
  22230. + /* Generate the down event. */
  22231. + handle_scancode((row<<3)+i, 1);
  22232. + }
  22233. +
  22234. + key_is_pressed = 1;
  22235. + }
  22236. + }
  22237. + }
  22238. + }
  22239. +
  22240. + /* Update the state variables. */
  22241. + memcpy(previous_keys, keys, 8 * sizeof(unsigned long));
  22242. +}
  22243. +
  22244. +static char edb7211_unexpected_up(unsigned char scancode)
  22245. +{
  22246. + return 0200;
  22247. +}
  22248. +
  22249. +static void edb7211_leds(unsigned char leds)
  22250. +{
  22251. +}
  22252. +
  22253. +/*
  22254. + * Initialize the keyboard hardware. Set the column drives low and
  22255. + * start the timer.
  22256. + */
  22257. +void __init
  22258. +edb7211_kbd_init_hw(void)
  22259. +{
  22260. + k_translate = edb7211_translate;
  22261. + k_unexpected_up = edb7211_unexpected_up;
  22262. + k_leds = edb7211_leds;
  22263. +
  22264. + /*
  22265. + * If we had the ability to use interrupts, we would want to drive all
  22266. + * columns high. But we have more keys than can generate interrupts, so
  22267. + * we leave them floating.
  22268. + */
  22269. + clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
  22270. + SYSCON1);
  22271. +
  22272. + /* Initialize the matrix processing task. */
  22273. + kbd_process_task.routine = edb7211_kbd_process;
  22274. + kbd_process_task.data = NULL;
  22275. +
  22276. + /* Setup the timer to poll the keyboard. */
  22277. + init_timer(&edb7211_kbd_timer);
  22278. + edb7211_kbd_timer.function = edb7211_kbd_timeout;
  22279. + edb7211_kbd_timer.data = (unsigned long)NULL;
  22280. + edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
  22281. + add_timer(&edb7211_kbd_timer);
  22282. +}
  22283. +
  22284. +
  22285. diff -urN linux-2.4.26/drivers/char/epxa_wdt.c linux-2.4.26-vrs1/drivers/char/epxa_wdt.c
  22286. --- linux-2.4.26/drivers/char/epxa_wdt.c 1970-01-01 01:00:00.000000000 +0100
  22287. +++ linux-2.4.26-vrs1/drivers/char/epxa_wdt.c 2004-01-14 21:32:25.000000000 +0000
  22288. @@ -0,0 +1,178 @@
  22289. +/*
  22290. + * Watchdog driver for the Altera Excalibur EPXA1DB
  22291. + *
  22292. + * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
  22293. + * Based on SA11x0 Watchdog driver by Oleg Drokin <green@crimea.edu>
  22294. + *
  22295. + * This program is free software; you can redistribute it and/or
  22296. + * modify it under the terms of the GNU General Public License
  22297. + * as published by the Free Software Foundation; either version
  22298. + * 2 of the License, or (at your option) any later version.
  22299. + *
  22300. + * This material is provided "AS-IS" and at no charge
  22301. + *
  22302. + * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
  22303. + *
  22304. + * 1/08/2003 Initial release
  22305. + */
  22306. +
  22307. +#include <linux/module.h>
  22308. +#include <linux/config.h>
  22309. +#include <linux/types.h>
  22310. +#include <linux/kernel.h>
  22311. +#include <linux/fs.h>
  22312. +#include <linux/mm.h>
  22313. +#include <linux/miscdevice.h>
  22314. +#include <linux/watchdog.h>
  22315. +#include <linux/reboot.h>
  22316. +#include <linux/smp_lock.h>
  22317. +#include <linux/init.h>
  22318. +#include <asm/uaccess.h>
  22319. +#include <asm/hardware.h>
  22320. +
  22321. +#define WATCHDOG00_TYPE (volatile unsigned int*)
  22322. +#include <asm/arch/watchdog00.h>
  22323. +#include <asm/bitops.h>
  22324. +
  22325. +#define TIMER_MARGIN 30 /* (secs) Default is 30 seconds */
  22326. +
  22327. +static int margin = TIMER_MARGIN; /* in seconds */
  22328. +static int epxa1wdt_users;
  22329. +static unsigned char last_written_byte;
  22330. +
  22331. +#ifdef CONFIG_WATCHDOG_NOWAYOUT
  22332. +static int nowayout=1;
  22333. +#else
  22334. +static int nowayout=0;
  22335. +#endif
  22336. +
  22337. +#ifdef MODULE
  22338. +MODULE_PARM(margin,"i");
  22339. +MODULE_PARM(nowayout, "i");
  22340. +#endif
  22341. +
  22342. +/*
  22343. + * Allow only one person to hold it open
  22344. + */
  22345. +
  22346. +static int epxa1dog_open(struct inode *inode, struct file *file)
  22347. +{
  22348. + if(test_and_set_bit(1,&epxa1wdt_users))
  22349. + return -EBUSY;
  22350. +
  22351. + /* Reset the Watchdog, just to be sure we don't set
  22352. + a value close to actual value of WDOG_COUNT register */
  22353. + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
  22354. + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
  22355. +
  22356. + /* Activate EPXA1DB Watchdog timer */
  22357. + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
  22358. +
  22359. + last_written_byte = 'V'; //in case user opens it only to ioctl
  22360. + return 0;
  22361. +}
  22362. +
  22363. +static int epxa1dog_release(struct inode *inode, struct file *file)
  22364. +{
  22365. + /*
  22366. + * Shut off the timer and set lock bit when no special
  22367. + * character 'V' was last written
  22368. + */
  22369. +
  22370. + if ((last_written_byte != 'V') && (nowayout)) {
  22371. + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)) |= WDOG_CR_LK_MSK;
  22372. + printk("No special character 'V' was written to Watchdog just before closing it\n");
  22373. + printk("WATCHDOG LOCKED - Reboot expected!!!\n");
  22374. + } else
  22375. + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))=0;
  22376. +
  22377. + epxa1wdt_users = 0;
  22378. +
  22379. + return 0;
  22380. +}
  22381. +
  22382. +static ssize_t epxa1dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  22383. +{
  22384. + /* Can't seek (pwrite) on this device */
  22385. + if (ppos != &file->f_pos)
  22386. + return -ESPIPE;
  22387. +
  22388. + /* Reset Watchdog timer. */
  22389. + if(len) {
  22390. + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
  22391. + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
  22392. + last_written_byte = *data;
  22393. + return 1;
  22394. + }
  22395. + return 0;
  22396. +}
  22397. +
  22398. +static int epxa1dog_ioctl(struct inode *inode, struct file *file,
  22399. + unsigned int cmd, unsigned long arg)
  22400. +{
  22401. + static struct watchdog_info ident = {
  22402. + identity: "EPXA Watchdog",
  22403. + };
  22404. +
  22405. + switch(cmd){
  22406. + default:
  22407. + return -ENOIOCTLCMD;
  22408. + case WDIOC_GETSUPPORT:
  22409. + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
  22410. +// case WDIOC_GETSTATUS: //TODO
  22411. +// return put_user(0,(int *)arg);
  22412. +// case WDIOC_GETBOOTSTATUS: //TODO
  22413. +// return 0;
  22414. + case WDIOC_KEEPALIVE:
  22415. + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
  22416. + *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
  22417. + return 0;
  22418. + case WDIOC_SETTIMEOUT:
  22419. + *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
  22420. + return 0;
  22421. + case WDIOC_GETTIMEOUT:
  22422. + return put_user( ((*WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)))/EXC_INPUT_CLK_FREQUENCY), (int*)arg);
  22423. + }
  22424. +}
  22425. +
  22426. +static struct file_operations epxa1dog_fops = {
  22427. + .owner = THIS_MODULE,
  22428. + .write = epxa1dog_write,
  22429. + .ioctl = epxa1dog_ioctl,
  22430. + .open = epxa1dog_open,
  22431. + .release = epxa1dog_release,
  22432. +};
  22433. +
  22434. +static struct miscdevice epxa1dog_miscdev=
  22435. +{
  22436. + .minor = WATCHDOG_MINOR,
  22437. + .name = "EPXA watchdog",
  22438. + .fops = &epxa1dog_fops
  22439. +};
  22440. +
  22441. +static int __init epxa1dog_init(void)
  22442. +{
  22443. + int ret;
  22444. +
  22445. + ret = misc_register(&epxa1dog_miscdev);
  22446. +
  22447. + if (ret)
  22448. + return ret;
  22449. +
  22450. + printk("EPXA Watchdog Timer: timer margin %d sec\n", margin);
  22451. + printk("EPXA Watchdog Timer: no way out is %s\n", nowayout ? "enabled" : "disabled");
  22452. +
  22453. + return 0;
  22454. +}
  22455. +
  22456. +static void __exit epxa1dog_exit(void)
  22457. +{
  22458. + misc_deregister(&epxa1dog_miscdev);
  22459. +}
  22460. +
  22461. +module_init(epxa1dog_init);
  22462. +module_exit(epxa1dog_exit);
  22463. +
  22464. +MODULE_AUTHOR("Krzysztof Marianski <kmarian@konin.lm.pl>");
  22465. +MODULE_DESCRIPTION("EPXA Watchdog Timer");
  22466. +MODULE_LICENSE("GPL");
  22467. diff -urN linux-2.4.26/drivers/char/gc_kbmap.h linux-2.4.26-vrs1/drivers/char/gc_kbmap.h
  22468. --- linux-2.4.26/drivers/char/gc_kbmap.h 1970-01-01 01:00:00.000000000 +0100
  22469. +++ linux-2.4.26-vrs1/drivers/char/gc_kbmap.h 2004-01-14 21:32:25.000000000 +0000
  22470. @@ -0,0 +1,162 @@
  22471. +
  22472. +
  22473. +#define KK_NONE 0x7f
  22474. +#define KK_ESC 0x00
  22475. +#define KK_F1 0x01
  22476. +#define KK_F2 0x02
  22477. +#define KK_F3 0x03
  22478. +#define KK_F4 0x04
  22479. +#define KK_F5 0x05
  22480. +#define KK_F6 0x06
  22481. +#define KK_F7 0x07
  22482. +#define KK_F8 0x08
  22483. +#define KK_F9 0x09
  22484. +#define KK_F10 0x0a
  22485. +#define KK_F11 0x0b
  22486. +#define KK_F12 0x0c
  22487. +#define KK_PRNT 0x0d
  22488. +#define KK_SCRL 0x0e
  22489. +#define KK_BRK 0x0f
  22490. +#define KK_AGR 0x10
  22491. +#define KK_1 0x11
  22492. +#define KK_2 0x12
  22493. +#define KK_3 0x13
  22494. +#define KK_4 0x14
  22495. +#define KK_5 0x15
  22496. +#define KK_6 0x16
  22497. +#define KK_7 0x17
  22498. +#define KK_8 0x18
  22499. +#define KK_9 0x19
  22500. +#define KK_0 0x1a
  22501. +#define KK_MINS 0x1b
  22502. +#define KK_EQLS 0x1c
  22503. +#define KK_BKSP 0x1e
  22504. +#define KK_INS 0x1f
  22505. +#define KK_HOME 0x20
  22506. +#define KK_PGUP 0x21
  22507. +#define KK_NUML 0x22
  22508. +#define KP_SLH 0x23
  22509. +#define KP_STR 0x24
  22510. +#define KP_MNS 0x3a
  22511. +#define KK_TAB 0x26
  22512. +#define KK_Q 0x27
  22513. +#define KK_W 0x28
  22514. +#define KK_E 0x29
  22515. +#define KK_R 0x2a
  22516. +#define KK_T 0x2b
  22517. +#define KK_Y 0x2c
  22518. +#define KK_U 0x2d
  22519. +#define KK_I 0x2e
  22520. +#define KK_O 0x2f
  22521. +#define KK_P 0x30
  22522. +#define KK_LSBK 0x31
  22523. +#define KK_RSBK 0x32
  22524. +#define KK_ENTR 0x47
  22525. +#define KK_DEL 0x34
  22526. +#define KK_END 0x35
  22527. +#define KK_PGDN 0x36
  22528. +#define KP_7 0x37
  22529. +#define KP_8 0x38
  22530. +#define KP_9 0x39
  22531. +#define KP_PLS 0x4b
  22532. +#define KK_CAPS 0x5d
  22533. +#define KK_A 0x3c
  22534. +#define KK_S 0x3d
  22535. +#define KK_D 0x3e
  22536. +#define KK_F 0x3f
  22537. +#define KK_G 0x40
  22538. +#define KK_H 0x41
  22539. +#define KK_J 0x42
  22540. +#define KK_K 0x43
  22541. +#define KK_L 0x44
  22542. +#define KK_SEMI 0x45
  22543. +#define KK_SQOT 0x46
  22544. +#define KK_HASH 0x1d
  22545. +#define KP_4 0x48
  22546. +#define KP_5 0x49
  22547. +#define KP_6 0x4a
  22548. +#define KK_LSFT 0x4c
  22549. +#define KK_BSLH 0x33
  22550. +#define KK_Z 0x4e
  22551. +#define KK_X 0x4f
  22552. +#define KK_C 0x50
  22553. +#define KK_V 0x51
  22554. +#define KK_B 0x52
  22555. +#define KK_N 0x53
  22556. +#define KK_M 0x54
  22557. +#define KK_COMA 0x55
  22558. +#define KK_DOT 0x56
  22559. +#define KK_FSLH 0x57
  22560. +#define KK_RSFT 0x58
  22561. +#define KK_UP 0x59
  22562. +#define KP_1 0x5a
  22563. +#define KP_2 0x5b
  22564. +#define KP_3 0x5c
  22565. +#define KP_ENT 0x67
  22566. +#define KK_LCTL 0x3b
  22567. +#define KK_LALT 0x5e
  22568. +#define KK_SPCE 0x5f
  22569. +#define KK_RALT 0x60
  22570. +#define KK_RCTL 0x61
  22571. +#define KK_LEFT 0x62
  22572. +#define KK_DOWN 0x63
  22573. +#define KK_RGHT 0x64
  22574. +#define KP_0 0x65
  22575. +#define KP_DOT 0x66
  22576. +
  22577. +static char kbmap[128] = {
  22578. +KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22579. +KK_NONE, KK_AGR, KK_BSLH, KK_TAB, KK_Z, KK_A, KK_X, KK_NONE,
  22580. +KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22581. +KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22582. +KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22583. +KK_NONE, KK_ESC, KK_DEL, KK_Q, KK_CAPS, KK_S, KK_C, KK_3,
  22584. +KK_NONE, KK_1, KK_NONE, KK_W, KK_NONE, KK_D, KK_V, KK_4,
  22585. +KK_NONE, KK_2, KK_T, KK_E, KK_NONE, KK_F, KK_B, KK_5,
  22586. +KK_NONE, KK_9, KK_Y, KK_R, KK_K, KK_G, KK_N, KK_6,
  22587. +KK_NONE, KK_0, KK_U, KK_O, KK_L, KK_H, KK_M, KK_7,
  22588. +KK_NONE, KK_MINS, KK_I, KK_P, KK_SEMI, KK_J, KK_COMA, KK_8,
  22589. +KK_NONE, KK_EQLS, KK_ENTR, KK_LSBK, KK_BSLH, KK_FSLH, KK_DOT, KK_NONE,
  22590. +KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22591. +KK_NONE, KK_BKSP, KK_DOWN, KK_RSBK, KK_UP, KK_LEFT, KK_SPCE, KK_RGHT,
  22592. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22593. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
  22594. +
  22595. +static char kbmapFN[128] = {
  22596. +KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22597. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22598. +KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22599. +KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22600. +KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22601. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F3,
  22602. +KK_NONE, KK_F1, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F4,
  22603. +KK_NONE, KK_F2, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F5,
  22604. +KK_NONE, KK_F9, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F6,
  22605. +KK_NONE, KK_F10, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F7,
  22606. +KK_NONE, KK_NUML, KK_NONE, KK_INS, KK_PRNT, KK_NONE, KK_NONE, KK_F8,
  22607. +KK_NONE, KK_BRK, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22608. +KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22609. +KK_NONE, KK_NONE, KK_PGDN, KK_SCRL, KK_PGUP, KK_HOME, KK_NONE, KK_END,
  22610. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22611. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
  22612. +
  22613. +static char kbmapNL[128] = {
  22614. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22615. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22616. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22617. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22618. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22619. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22620. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22621. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22622. +KK_NONE, KP_9, KK_NONE, KK_NONE, KP_2, KK_NONE, KK_NONE, KK_NONE,
  22623. +KK_NONE, KP_STR, KP_4, KP_6, KP_3, KK_NONE, KP_0, KP_7,
  22624. +KK_NONE, KK_NONE, KP_5, KP_MNS, KP_PLS, KP_1, KK_NONE, KP_8,
  22625. +KK_NONE, KK_NONE, KP_ENT, KK_NONE, KK_NONE, KP_SLH, KP_DOT, KK_NONE,
  22626. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22627. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22628. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
  22629. +KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
  22630. +
  22631. +
  22632. +
  22633. diff -urN linux-2.4.26/drivers/char/gc_keyb.c linux-2.4.26-vrs1/drivers/char/gc_keyb.c
  22634. --- linux-2.4.26/drivers/char/gc_keyb.c 1970-01-01 01:00:00.000000000 +0100
  22635. +++ linux-2.4.26-vrs1/drivers/char/gc_keyb.c 2004-01-14 21:32:25.000000000 +0000
  22636. @@ -0,0 +1,1145 @@
  22637. +/*
  22638. + * linux/arch/arm/drivers/char/gc_keyb.c
  22639. + *
  22640. + * Copyright 2000 Applied Data Systems
  22641. + *
  22642. + * Keyboard & Smartio driver for GraphicsClient ARM Linux.
  22643. + * Graphics Client is SA1110 based single board computer by
  22644. + * Applied Data Systems (http://www.applieddata.net)
  22645. + *
  22646. + * Change log:
  22647. + * 7-10/6/01 Thomas Thaele <tthaele@papenmeier.de>
  22648. + * - Added Keyboard Sniffer on /dev/sio12 <minor = 12>
  22649. + * - First implementation of PC- compatible Scancodes (thanks to pc_keyb.c)
  22650. + * 3/23/01 Woojung Huh
  22651. + * Power Management added
  22652. + * 12/01/00 Woojung Huh
  22653. + * Bug fixed
  22654. + * 11/16/00 Woojung Huh [whuh@applieddata.net]
  22655. + * Added smartio device driver on it
  22656. + */
  22657. +
  22658. +/*
  22659. + * Introduced setkeycode, ketkeycode for the GC+ by Thomas Thaele
  22660. + * <tthaele@papenmeier.de> GC+ now performs like a real PC on the keyboard.
  22661. + * Warning: this code is still beta! PrntScrn and Pause keys are not
  22662. + * completely tested and implemented!!! Keyboard driver can be confused
  22663. + * by hacking like crazy on the keyboard. (hardware problem on serial line?)
  22664. + */
  22665. +
  22666. +#include <linux/sched.h>
  22667. +#include <linux/interrupt.h>
  22668. +#include <linux/kbd_ll.h>
  22669. +#include <linux/init.h>
  22670. +#include <linux/delay.h>
  22671. +#include <linux/kbd_kern.h>
  22672. +
  22673. +#include <asm/irq.h>
  22674. +#include <asm/hardware.h>
  22675. +#include <asm/keyboard.h>
  22676. +#include <linux/tqueue.h>
  22677. +#include <linux/proc_fs.h>
  22678. +#include <linux/pm.h>
  22679. +
  22680. +#define ADS_AVR_IRQ 63
  22681. +
  22682. +#define SMARTIO_IOCTL_BASES 's'
  22683. +#define SMARTIO_KPD_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 0, int)
  22684. +#define SMARTIO_KPD_SETUP _IOW(SMARTIO_IOCTL_BASES, 1, short)
  22685. +#define SMARTIO_BL_CONTROL _IOW(SMARTIO_IOCTL_BASES, 2, char)
  22686. +#define SMARTIO_BL_CONTRAST _IOW(SMARTIO_IOCTL_BASES, 3, char)
  22687. +#define SMARTIO_PORT_CONFIG _IOW(SMARTIO_IOCTL_BASES, 4, char)
  22688. +#define SMARTIO_SNIFFER_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 5, long)
  22689. +
  22690. +
  22691. +/* Simple translation table for the SysRq keys */
  22692. +
  22693. +#ifdef CONFIG_MAGIC_SYSRQ
  22694. +unsigned char pckbd_sysrq_xlate[128] =
  22695. + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
  22696. + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
  22697. + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
  22698. + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
  22699. + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
  22700. + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
  22701. + "\r\000/"; /* 0x60 - 0x6f */
  22702. +#endif
  22703. +
  22704. +/*
  22705. + * Translation of escaped scancodes to keycodes.
  22706. + * This is now user-settable.
  22707. + * The keycodes 1-88,96-111,119 are fairly standard, and
  22708. + * should probably not be changed - changing might confuse X.
  22709. + * X also interprets scancode 0x5d (KEY_Begin).
  22710. + *
  22711. + * For 1-88 keycode equals scancode.
  22712. + */
  22713. +
  22714. +#define E0_KPENTER 96
  22715. +#define E0_RCTRL 97
  22716. +#define E0_KPSLASH 98
  22717. +#define E0_PRSCR 99
  22718. +#define E0_RALT 100
  22719. +#define E0_BREAK 101 /* (control-pause) */
  22720. +#define E0_HOME 102
  22721. +#define E0_UP 103
  22722. +#define E0_PGUP 104
  22723. +#define E0_LEFT 105
  22724. +#define E0_RIGHT 106
  22725. +#define E0_END 107
  22726. +#define E0_DOWN 108
  22727. +#define E0_PGDN 109
  22728. +#define E0_INS 110
  22729. +#define E0_DEL 111
  22730. +
  22731. +#define E1_PAUSE 119
  22732. +
  22733. +/*
  22734. + * The keycodes below are randomly located in 89-95,112-118,120-127.
  22735. + * They could be thrown away (and all occurrences below replaced by 0),
  22736. + * but that would force many users to use the `setkeycodes' utility, where
  22737. + * they needed not before. It does not matter that there are duplicates, as
  22738. + * long as no duplication occurs for any single keyboard.
  22739. + */
  22740. +#define SC_LIM 89
  22741. +
  22742. +#define FOCUS_PF1 85 /* actual code! */
  22743. +#define FOCUS_PF2 89
  22744. +#define FOCUS_PF3 90
  22745. +#define FOCUS_PF4 91
  22746. +#define FOCUS_PF5 92
  22747. +#define FOCUS_PF6 93
  22748. +#define FOCUS_PF7 94
  22749. +#define FOCUS_PF8 95
  22750. +#define FOCUS_PF9 120
  22751. +#define FOCUS_PF10 121
  22752. +#define FOCUS_PF11 122
  22753. +#define FOCUS_PF12 123
  22754. +
  22755. +#define JAP_86 124
  22756. +/* tfj@olivia.ping.dk:
  22757. + * The four keys are located over the numeric keypad, and are
  22758. + * labelled A1-A4. It's an rc930 keyboard, from
  22759. + * Regnecentralen/RC International, Now ICL.
  22760. + * Scancodes: 59, 5a, 5b, 5c.
  22761. + */
  22762. +#define RGN1 124
  22763. +#define RGN2 125
  22764. +#define RGN3 126
  22765. +#define RGN4 127
  22766. +
  22767. +static unsigned char high_keys[128 - SC_LIM] = {
  22768. + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
  22769. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
  22770. + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
  22771. + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
  22772. + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
  22773. + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
  22774. +};
  22775. +
  22776. +/* BTC */
  22777. +#define E0_MACRO 112
  22778. +/* LK450 */
  22779. +#define E0_F13 113
  22780. +#define E0_F14 114
  22781. +#define E0_HELP 115
  22782. +#define E0_DO 116
  22783. +#define E0_F17 117
  22784. +#define E0_KPMINPLUS 118
  22785. +/*
  22786. + * My OmniKey generates e0 4c for the "OMNI" key and the
  22787. + * right alt key does nada. [kkoller@nyx10.cs.du.edu]
  22788. + */
  22789. +#define E0_OK 124
  22790. +/*
  22791. + * New microsoft keyboard is rumoured to have
  22792. + * e0 5b (left window button), e0 5c (right window button),
  22793. + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
  22794. + * [or: Windows_L, Windows_R, TaskMan]
  22795. + */
  22796. +#define E0_MSLW 125
  22797. +#define E0_MSRW 126
  22798. +#define E0_MSTM 127
  22799. +
  22800. +static unsigned char e0_keys[128] = {
  22801. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
  22802. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
  22803. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
  22804. + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
  22805. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
  22806. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
  22807. + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
  22808. + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
  22809. + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
  22810. + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
  22811. + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
  22812. + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
  22813. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
  22814. + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
  22815. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
  22816. + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
  22817. +};
  22818. +
  22819. +int gc_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
  22820. +{
  22821. + if (scancode < SC_LIM || scancode > 255 || keycode > 127)
  22822. + return -EINVAL;
  22823. + if (scancode < 128)
  22824. + high_keys[scancode - SC_LIM] = keycode;
  22825. + else
  22826. + e0_keys[scancode - 128] = keycode;
  22827. + return 0;
  22828. +}
  22829. +
  22830. +int gc_kbd_getkeycode(unsigned int scancode)
  22831. +{
  22832. + return
  22833. + (scancode < SC_LIM || scancode > 255) ? -EINVAL :
  22834. + (scancode < 128) ? high_keys[scancode - SC_LIM] :
  22835. + e0_keys[scancode - 128];
  22836. +}
  22837. +
  22838. +int gc_kbd_translate(unsigned char scancode, unsigned char *keycode,
  22839. + char raw_mode)
  22840. +{
  22841. + static int prev_scancode;
  22842. +
  22843. + /* special prefix scancodes.. */
  22844. + if (scancode == 0xe0 || scancode == 0xe1) {
  22845. + prev_scancode = scancode;
  22846. + return 0;
  22847. + }
  22848. +
  22849. + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
  22850. + if (scancode == 0x00 || scancode == 0xff) {
  22851. + prev_scancode = 0;
  22852. + return 0;
  22853. + }
  22854. +
  22855. + scancode &= 0x7f;
  22856. +
  22857. + if (prev_scancode) {
  22858. + /*
  22859. + * usually it will be 0xe0, but a Pause key generates
  22860. + * e1 1d 45 e1 9d c5 when pressed, and nothing when released
  22861. + */
  22862. + if (prev_scancode != 0xe0) {
  22863. + if (prev_scancode == 0xe1 && scancode == 0x1d) {
  22864. + prev_scancode = 0x100;
  22865. + return 0;
  22866. + } else if (prev_scancode == 0x100 && scancode == 0x45) {
  22867. + *keycode = E1_PAUSE;
  22868. + prev_scancode = 0;
  22869. + } else {
  22870. +#ifdef KBD_REPORT_UNKN
  22871. + if (!raw_mode)
  22872. + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
  22873. +#endif
  22874. + prev_scancode = 0;
  22875. + return 0;
  22876. + }
  22877. + } else {
  22878. + prev_scancode = 0;
  22879. + /*
  22880. + * The keyboard maintains its own internal caps lock and
  22881. + * num lock statuses. In caps lock mode E0 AA precedes make
  22882. + * code and E0 2A follows break code. In num lock mode,
  22883. + * E0 2A precedes make code and E0 AA follows break code.
  22884. + * We do our own book-keeping, so we will just ignore these.
  22885. + */
  22886. + /*
  22887. + * For my keyboard there is no caps lock mode, but there are
  22888. + * both Shift-L and Shift-R modes. The former mode generates
  22889. + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
  22890. + * So, we should also ignore the latter. - aeb@cwi.nl
  22891. + */
  22892. + if (scancode == 0x2a || scancode == 0x36)
  22893. + return 0;
  22894. +
  22895. + if (e0_keys[scancode])
  22896. + *keycode = e0_keys[scancode];
  22897. + else {
  22898. +#ifdef KBD_REPORT_UNKN
  22899. + if (!raw_mode)
  22900. + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
  22901. + scancode);
  22902. +#endif
  22903. + return 0;
  22904. + }
  22905. + }
  22906. + } else if (scancode >= SC_LIM) {
  22907. + /* This happens with the FOCUS 9000 keyboard
  22908. + Its keys PF1..PF12 are reported to generate
  22909. + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
  22910. + Moreover, unless repeated, they do not generate
  22911. + key-down events, so we have to zero up_flag below */
  22912. + /* Also, Japanese 86/106 keyboards are reported to
  22913. + generate 0x73 and 0x7d for \ - and \ | respectively. */
  22914. + /* Also, some Brazilian keyboard is reported to produce
  22915. + 0x73 and 0x7e for \ ? and KP-dot, respectively. */
  22916. +
  22917. + *keycode = high_keys[scancode - SC_LIM];
  22918. +
  22919. + if (!*keycode) {
  22920. + if (!raw_mode) {
  22921. +#ifdef KBD_REPORT_UNKN
  22922. + printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
  22923. + " - ignored\n", scancode);
  22924. +#endif
  22925. + }
  22926. + return 0;
  22927. + }
  22928. + } else
  22929. + *keycode = scancode;
  22930. + return 1;
  22931. +}
  22932. +
  22933. +// this table converts the hardware dependent codes of a MF-2 Keyboard to
  22934. +// the codes normally comming out of a i8042. This table is 128 Bytes too
  22935. +// big, but for stability reasons it should be kept like it is!
  22936. +// There is no range checking in the code!
  22937. +static int mf_two_kbdmap[256] = {
  22938. + 00, 67, 65, 63, 61, 59, 60, 88, 00, 68, 66, 64, 62, 15, 41, 00,
  22939. + 00, 56, 42, 00, 29, 16, 02, 00, 00, 00, 44, 31, 30, 17, 03, 00,
  22940. + 00, 46, 45, 32, 18, 05, 04, 00, 00, 57, 47, 33, 20, 19, 06, 00,
  22941. + 00, 49, 48, 35, 34, 21, 7, 00, 00, 00, 50, 36, 22, 8, 9, 00,
  22942. + 00, 51, 37, 23, 24, 11, 10, 00, 00, 52, 53, 38, 39, 25, 12, 00,
  22943. + 00, 00, 40, 00, 26, 13, 00, 00, 58, 54, 28, 27, 00, 43, 00, 00,
  22944. + 00, 86, 00, 00, 00, 00, 14, 00, 00, 79, 00, 75, 71, 00, 00, 00,
  22945. + 82, 83, 80, 76, 77, 72, 01, 69, 87, 78, 81, 74, 55, 73, 70, 00,
  22946. + 00, 00, 00, 65, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22947. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22948. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22949. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22950. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22951. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22952. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
  22953. + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 };
  22954. +
  22955. +
  22956. +// some texts displayed by the proc_file_system
  22957. +static char *kbd_sniff[2] = { "off", "on" };
  22958. +static char *kbd_sniff_mode[2] = { "passive", "active" };
  22959. +
  22960. +#define PASSIVE 0
  22961. +#define ACTIVE 1
  22962. +
  22963. +// is the sniffer active (1) or inactive (0)
  22964. +static int SNIFFER = 0;
  22965. +// do we get a copy (SNIFFMODE = PASSIVE) or do we get the original data (SNIFFMODE = ACTIVE)
  22966. +// and have to reinsert the data
  22967. +static int SNIFFMODE = PASSIVE;
  22968. +
  22969. +// we allow only one process to sniff
  22970. +static int sniffer_in_use = 0;
  22971. +
  22972. +// timeout for the keyboard sniffer -1 = blocking, otherwise timeout in msecs
  22973. +static long sniffer_timeout = -1;
  22974. +
  22975. +// the value we sniffed from the keyboard
  22976. +static int sniffed_value;
  22977. +
  22978. +static char *smartio_version = "1.02 MF-II compatibility patch <tthaele@papenmeier.de>";
  22979. +static char *smartio_date = "Aug-27-2001";
  22980. +
  22981. +static int sio_reset_flag;
  22982. +static int kbd_press_flag;
  22983. +
  22984. +static void send_SSP_msg(unchar *pBuf, int num)
  22985. +{
  22986. + ushort tmp;
  22987. + int i;
  22988. +
  22989. + for (i=0;i<num;i++) {
  22990. + while ((Ser4SSSR & SSSR_TNF) == 0);
  22991. + tmp = pBuf[i];
  22992. + Ser4SSDR = (tmp << 8);
  22993. + }
  22994. +
  22995. + // Throw away Echo
  22996. + for (i=0;i<num;i++) {
  22997. + while ((Ser4SSSR & SSSR_RNE) == 0);
  22998. + tmp = Ser4SSDR;
  22999. + }
  23000. +}
  23001. +
  23002. +static unchar ReadSSPByte(void)
  23003. +{
  23004. + if (Ser4SSSR & SSSR_ROR) {
  23005. + printk("%s() : Overrun\n", __FUNCTION__);
  23006. + return 0;
  23007. + }
  23008. +
  23009. + Ser4SSDR = 0x00;
  23010. +
  23011. + while ((Ser4SSSR & SSSR_RNE) == 0);
  23012. +
  23013. + return ((unchar) Ser4SSDR);
  23014. +}
  23015. +
  23016. +static ulong read_SSP_response(int num)
  23017. +{
  23018. + int i;
  23019. + ulong ret;
  23020. +
  23021. + // discard leading 0x00 and command echo 0 (command group value)
  23022. + while (ReadSSPByte() == 0);
  23023. + // discard command echo 1 (command code value)
  23024. + ReadSSPByte();
  23025. +
  23026. + // data from SMARTIO
  23027. + // It assumes LSB first.
  23028. + // NOTE:Some command uses MSB first order
  23029. + ret = 0;
  23030. + for (i=0;i<num;i++) {
  23031. + ret |= ReadSSPByte() << (8*i);
  23032. + }
  23033. +
  23034. + return ret;
  23035. +}
  23036. +
  23037. +typedef struct t_SMARTIO_CMD {
  23038. + unchar Group;
  23039. + unchar Code;
  23040. + unchar Opt[2];
  23041. +} SMARTIO_CMD;
  23042. +
  23043. +static SMARTIO_CMD RD_INT_CMD = { 0x83, 0x01, { 0x00, 0x00 } };
  23044. +static SMARTIO_CMD RD_KBD_CMD = { 0x83, 0x02, { 0x00, 0x00 } };
  23045. +static SMARTIO_CMD RD_ADC_CMD = { 0x83, 0x28, { 0x00, 0x00 } };
  23046. +static SMARTIO_CMD RD_KPD_CMD = { 0x83, 0x04, { 0x00, 0x00 } };
  23047. +
  23048. +static volatile ushort adc_value;
  23049. +static volatile unchar kpd_value;
  23050. +static unsigned int kpd_timeout = 10000; // 10000 msec
  23051. +
  23052. +static ulong kbd_int, kpd_int, adc_int;
  23053. +
  23054. +static void smartio_interrupt_task(void *data);
  23055. +
  23056. +static struct tq_struct tq_smartio = {
  23057. + { NULL, NULL }, // struct list_head
  23058. + 0, // unsigned long sync
  23059. + smartio_interrupt_task, // void (*routine)(void *)
  23060. + NULL, // void *data
  23061. +};
  23062. +
  23063. +DECLARE_WAIT_QUEUE_HEAD(smartio_queue);
  23064. +DECLARE_WAIT_QUEUE_HEAD(smartio_adc_queue);
  23065. +DECLARE_WAIT_QUEUE_HEAD(smartio_kpd_queue);
  23066. +DECLARE_WAIT_QUEUE_HEAD(keyboard_done_queue);
  23067. +DECLARE_WAIT_QUEUE_HEAD(sniffer_queue);
  23068. +
  23069. +static spinlock_t smartio_busy_lock = SPIN_LOCK_UNLOCKED;
  23070. +static atomic_t smartio_busy = ATOMIC_INIT(0);
  23071. +
  23072. +static int f_five_pressed = 0;
  23073. +static int f_seven_pressed = 0;
  23074. +//static int e_null_counter = 0;
  23075. +//static int f_null_counter = 0;
  23076. +//static int keydown = 0;
  23077. +static unchar previous_code = 0;
  23078. +//static int e0 = 0;
  23079. +
  23080. +static void smartio_interrupt_task(void *arg)
  23081. +{
  23082. + unchar code;
  23083. + unsigned long flags;
  23084. + unchar dummy;
  23085. +
  23086. + spin_lock_irqsave(&smartio_busy_lock, flags);
  23087. + if (atomic_read(&smartio_busy) == 1) {
  23088. + spin_unlock_irqrestore(&smartio_busy_lock, flags);
  23089. + queue_task(&tq_smartio, &tq_timer);
  23090. + }
  23091. + else {
  23092. + atomic_set(&smartio_busy, 1);
  23093. + spin_unlock_irqrestore(&smartio_busy_lock, flags);
  23094. + }
  23095. +
  23096. + /* Read SMARTIO Interrupt Status to check which Interrupt is occurred
  23097. + * and Clear SMARTIO Interrupt */
  23098. + send_SSP_msg((unchar *) &RD_INT_CMD, 2);
  23099. + code = (unchar) (read_SSP_response(1) & 0xFF);
  23100. +
  23101. +#ifdef CONFIG_VT
  23102. + if (code & 0x04) { // Keyboard Interrupt
  23103. + kbd_int++;
  23104. + /* Read Scan code */
  23105. + send_SSP_msg((unchar *) &RD_KBD_CMD, 2);
  23106. + code = (unchar) (read_SSP_response(1) & 0xFF);
  23107. + dummy = code & 0x80;
  23108. + if ((code == 0xE0) || (code == 0xE1) || (code == 0xF0)) { // combined code
  23109. + if (code == 0xF0) {
  23110. + if (!previous_code) {
  23111. + code = 0xE0;
  23112. + previous_code = 0xF0;
  23113. + } else {
  23114. + code = mf_two_kbdmap[code & 0x7F] | dummy;
  23115. + previous_code = 0;
  23116. + }
  23117. + } else if (code == 0xE0) {
  23118. + if (previous_code != 0) {
  23119. + code = mf_two_kbdmap[code & 0x7F] | dummy;
  23120. + previous_code = 0;
  23121. + } else previous_code = code;
  23122. + } else { // 0xE1
  23123. + if (!previous_code) {
  23124. + code = mf_two_kbdmap[code &0x7F] | dummy;
  23125. + previous_code = 0;
  23126. + } else {
  23127. + previous_code = code;
  23128. + }
  23129. + }
  23130. + } else {
  23131. + if (code == 0x03) {
  23132. + f_five_pressed = 1;
  23133. + } else if (code == 0x83) {
  23134. + if (f_five_pressed != 0) {
  23135. + f_five_pressed = 0;
  23136. + code = 0x03;
  23137. + } else if (f_seven_pressed == 0) {
  23138. + f_seven_pressed = 1;
  23139. + code = 2;
  23140. + dummy = 0;
  23141. + } else {
  23142. + f_seven_pressed = 0;
  23143. + code = 2;
  23144. + }
  23145. + }
  23146. + previous_code = 0;
  23147. + code &= 0x7F;
  23148. + code = mf_two_kbdmap[code] | dummy;
  23149. + }
  23150. + sniffed_value = (ushort)code;
  23151. + if (SNIFFER) wake_up_interruptible(&sniffer_queue);
  23152. + if (SNIFFMODE == PASSIVE) {
  23153. + handle_scancode( code, (code & 0x80) ? 0 : 1 );
  23154. + if (code & 0x80) {
  23155. + wake_up_interruptible(&keyboard_done_queue);
  23156. + mdelay(10); // this makes the whole thing a bit more stable
  23157. + // keyboard handling can be corrupted when hitting
  23158. + // thousands of keys like crazy. kbd_translate might catch up
  23159. + // with irq routine? or there is simply a buffer overflow on
  23160. + // the serial device? somehow it looses some key sequences.
  23161. + // if a break code is lost or coruppted the keyboard starts
  23162. + // to autorepeat like crazy and appears to hang.
  23163. + // this needs further investigations! Thomas
  23164. + kbd_press_flag = 0;
  23165. + }
  23166. + else
  23167. + kbd_press_flag = 1;
  23168. + }
  23169. + code = 0; // prevent furthermore if ... then to react!
  23170. + }
  23171. +#endif
  23172. + // ADC resolution is 10bit (0x000 ~ 0x3FF)
  23173. + if (code & 0x02) { // ADC Complete Interrupt
  23174. + adc_int++;
  23175. + send_SSP_msg((unchar *) &RD_ADC_CMD, 2);
  23176. + adc_value = (ushort) (read_SSP_response(2) & 0x3FF);
  23177. + wake_up_interruptible(&smartio_adc_queue);
  23178. + }
  23179. +
  23180. + if (code & 0x08) { // Keypad interrupt
  23181. + kpd_int++;
  23182. + send_SSP_msg((unchar *) &RD_KPD_CMD, 2);
  23183. + kpd_value = (unchar) (read_SSP_response(1) & 0xFF);
  23184. + wake_up_interruptible(&smartio_kpd_queue);
  23185. + }
  23186. +
  23187. + spin_lock_irqsave(&smartio_busy_lock, flags);
  23188. + atomic_set(&smartio_busy, 0);
  23189. + spin_unlock_irqrestore(&smartio_busy_lock, flags);
  23190. +
  23191. + enable_irq(ADS_AVR_IRQ);
  23192. +
  23193. + wake_up_interruptible(&smartio_queue);
  23194. +}
  23195. +
  23196. +static void gc_sio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  23197. +{
  23198. +#ifdef CONFIG_VT
  23199. + kbd_pt_regs = regs;
  23200. +#endif
  23201. +
  23202. + // *NOTE*
  23203. + // ADS SMARTIO interrupt is cleared after reading interrupt status
  23204. + // from smartio.
  23205. + // disable SMARTIO IRQ here and re-enable at samrtio_bh.
  23206. + // 11/13/00 Woojung
  23207. + disable_irq(ADS_AVR_IRQ);
  23208. +
  23209. + queue_task(&tq_smartio, &tq_immediate);
  23210. + mark_bh(IMMEDIATE_BH);
  23211. +}
  23212. +
  23213. +char gc_kbd_unexpected_up(unsigned char keycode)
  23214. +{
  23215. + return 0;
  23216. +}
  23217. +
  23218. +static inline void gc_sio_init(void)
  23219. +{
  23220. + GPDR |= (GPIO_GPIO10 | GPIO_GPIO12 | GPIO_GPIO13); // Output
  23221. + GPDR &= ~GPIO_GPIO11;
  23222. +
  23223. + // Alternative Function
  23224. + GAFR |= (GPIO_GPIO10 | GPIO_GPIO11 | GPIO_GPIO12 | GPIO_GPIO13);
  23225. +
  23226. + Ser4SSCR0 = 0xA707;
  23227. + Ser4SSSR = SSSR_ROR;
  23228. + Ser4SSCR1 = 0x0010;
  23229. + Ser4SSCR0 = 0xA787;
  23230. +
  23231. + // Reset SMARTIO
  23232. + ADS_AVR_REG &= 0xFE;
  23233. + mdelay(300); // 10 mSec
  23234. + ADS_AVR_REG |= 0x01;
  23235. + mdelay(10); // 10 mSec
  23236. +
  23237. +}
  23238. +
  23239. +void __init gc_kbd_init_hw(void)
  23240. +{
  23241. + printk (KERN_INFO "Graphics Client keyboard driver v1.0\n");
  23242. +
  23243. + k_setkeycode = gc_kbd_setkeycode;
  23244. + k_getkeycode = gc_kbd_getkeycode;
  23245. + k_translate = gc_kbd_translate;
  23246. + k_unexpected_up = gc_kbd_unexpected_up;
  23247. +#ifdef CONFIG_MAGIC_SYSRQ
  23248. + k_sysrq_key = 0x54;
  23249. + /* sysrq table??? --rmk */
  23250. +#endif
  23251. +
  23252. + gc_sio_init();
  23253. +
  23254. + if (request_irq(ADS_AVR_IRQ,gc_sio_interrupt,0,"smartio", NULL) != 0)
  23255. + printk("Could not allocate SMARTIO IRQ!\n");
  23256. +
  23257. + sio_reset_flag = 1;
  23258. +}
  23259. +
  23260. +/* SMARTIO ADC Interface */
  23261. +#define SMARTIO_VERSION 0
  23262. +#define SMARTIO_PORT_A 1
  23263. +#define SMARTIO_PORT_B 2
  23264. +#define SMARTIO_PORT_C 3
  23265. +#define SMARTIO_PORT_D 4
  23266. +#define SMARTIO_SELECT_OPTION 5
  23267. +#define SMARTIO_BACKLITE 6
  23268. +#define SMARTIO_KEYPAD 7
  23269. +#define SMARTIO_ADC 8
  23270. +#define SMARTIO_VEE_PWM 9
  23271. +#define SMARTIO_SLEEP 11
  23272. +#define SMARTIO_KBD_SNIFFER 12
  23273. +
  23274. +static SMARTIO_CMD CONV_ADC_CMD = { 0x80, 0x28, { 0x00, 0x00 } };
  23275. +static SMARTIO_CMD READ_PORT_CMD = { 0x82, 0x00, { 0x00, 0x00 } };
  23276. +
  23277. +static SMARTIO_CMD READ_DEVVER_CMD = { 0x82, 0x05, { 0x00, 0x00 } };
  23278. +static SMARTIO_CMD READ_DEVTYPE_CMD = { 0x82, 0x06, { 0x00, 0x00 } };
  23279. +static SMARTIO_CMD READ_FWLEVEL_CMD = { 0x82, 0x07, { 0x00, 0x00 } };
  23280. +
  23281. +static int lock_smartio(unsigned long *flags)
  23282. +{
  23283. + spin_lock_irqsave(&smartio_busy_lock, *flags);
  23284. + if (atomic_read(&smartio_busy) == 1) {
  23285. + spin_unlock_irqrestore(&smartio_busy_lock, *flags);
  23286. + interruptible_sleep_on(&smartio_queue);
  23287. + }
  23288. + else {
  23289. + atomic_set(&smartio_busy, 1);
  23290. + spin_unlock_irqrestore(&smartio_busy_lock, *flags);
  23291. + }
  23292. +
  23293. + return 1;
  23294. +}
  23295. +
  23296. +static int unlock_smartio(unsigned long *flags)
  23297. +{
  23298. + spin_lock_irqsave(&smartio_busy_lock, *flags);
  23299. + atomic_set(&smartio_busy, 0);
  23300. + spin_unlock_irqrestore(&smartio_busy_lock, *flags);
  23301. +
  23302. + return 1;
  23303. +}
  23304. +
  23305. +static ushort read_sio_adc(int channel)
  23306. +{
  23307. + unsigned long flags;
  23308. +
  23309. + if ((channel < 0) || (channel > 7))
  23310. + return 0xFFFF;
  23311. +
  23312. + CONV_ADC_CMD.Opt[0] = (unchar) channel;
  23313. +
  23314. + lock_smartio(&flags);
  23315. + send_SSP_msg((unchar *) &CONV_ADC_CMD, 3);
  23316. + unlock_smartio(&flags);
  23317. +
  23318. + interruptible_sleep_on(&smartio_adc_queue);
  23319. +
  23320. + return adc_value & 0x3FF;
  23321. +}
  23322. +
  23323. +static ushort read_sio_port(int port)
  23324. +{
  23325. + unsigned long flags;
  23326. + ushort ret;
  23327. +
  23328. + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
  23329. + return 0xFFFF;
  23330. +
  23331. + READ_PORT_CMD.Code = (unchar) port;
  23332. +
  23333. + lock_smartio(&flags);
  23334. + send_SSP_msg((unchar *) &READ_PORT_CMD, 2);
  23335. + ret = read_SSP_response(1);
  23336. + unlock_smartio(&flags);
  23337. +
  23338. + return ret;
  23339. +}
  23340. +
  23341. +static ushort read_sio_kpd(void)
  23342. +{
  23343. + long timeout;
  23344. +
  23345. + // kpd_timeout is mSec order
  23346. + // interrupt_sleep_on_timeout is based on 10msec timer tick
  23347. + if (kpd_timeout == -1) {
  23348. + interruptible_sleep_on(&smartio_kpd_queue);
  23349. + }
  23350. + else {
  23351. + timeout = interruptible_sleep_on_timeout(&smartio_kpd_queue,
  23352. + kpd_timeout/10);
  23353. + if (timeout == 0) {
  23354. + // timeout without keypad input
  23355. + return 0xFFFF;
  23356. + }
  23357. + }
  23358. + return kpd_value;
  23359. +}
  23360. +
  23361. +static ushort read_sio_sniff(void)
  23362. +{
  23363. + long timeout;
  23364. +
  23365. + // kpd_timeout is mSec order
  23366. + // interrupt_sleep_on_timeout is based on 10msec timer tick
  23367. + if (sniffer_timeout == -1) {
  23368. + interruptible_sleep_on(&sniffer_queue);
  23369. + }
  23370. + else {
  23371. + timeout = interruptible_sleep_on_timeout(&sniffer_queue,
  23372. + sniffer_timeout/10);
  23373. + if (timeout == 0) {
  23374. + // timeout without keypad input
  23375. + return -1;
  23376. + }
  23377. + }
  23378. + return (ushort)sniffed_value;
  23379. +}
  23380. +
  23381. +static struct sio_ver {
  23382. + uint DevVer;
  23383. + uint DevType;
  23384. + uint FwLevel;
  23385. +};
  23386. +
  23387. +static ushort read_sio_version(struct sio_ver *ptr)
  23388. +{
  23389. + unsigned long flags;
  23390. + ushort ret;
  23391. +
  23392. + // Read Device Version
  23393. + lock_smartio(&flags);
  23394. + send_SSP_msg((unchar *) &READ_DEVVER_CMD, 2);
  23395. + ret = read_SSP_response(1);
  23396. + unlock_smartio(&flags);
  23397. + ptr->DevVer = (uint)ret;
  23398. + // Read Device Type
  23399. + lock_smartio(&flags);
  23400. + send_SSP_msg((unchar *) &READ_DEVTYPE_CMD, 2);
  23401. + ret = read_SSP_response(2);
  23402. + unlock_smartio(&flags);
  23403. + // swap MSB & LSB
  23404. + ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
  23405. + ptr->DevType = (uint)ret;
  23406. + // Read Firmware Level
  23407. + lock_smartio(&flags);
  23408. + send_SSP_msg((unchar *) &READ_FWLEVEL_CMD, 2);
  23409. + ret = read_SSP_response(2);
  23410. + unlock_smartio(&flags);
  23411. + // swap MSB & LSB
  23412. + ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
  23413. + ptr->FwLevel = (uint)ret;
  23414. +
  23415. + return 0;
  23416. +}
  23417. +
  23418. +static ssize_t sio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  23419. +{
  23420. + struct inode *inode = file->f_dentry->d_inode;
  23421. + unsigned int minor = MINOR(inode->i_rdev);
  23422. + ushort *ret = (ushort *)buf;
  23423. +
  23424. + switch (minor) {
  23425. + case SMARTIO_ADC:
  23426. + if ((*ret = read_sio_adc(buf[0])) != 0xFFFF)
  23427. + return sizeof(ushort); // 2 bytes
  23428. + case SMARTIO_PORT_B:
  23429. + case SMARTIO_PORT_C:
  23430. + case SMARTIO_PORT_D:
  23431. + if ((*ret = read_sio_port(minor)) != 0xFFFF)
  23432. + return sizeof(ushort);
  23433. + case SMARTIO_VERSION:
  23434. + if ((read_sio_version((struct sio_ver *)buf)) != 0xFFFF)
  23435. + return sizeof(struct sio_ver);
  23436. + case SMARTIO_KEYPAD:
  23437. + if ((*ret = read_sio_kpd()) != 0xFFFF)
  23438. + return sizeof(ushort);
  23439. + case SMARTIO_KBD_SNIFFER:
  23440. + if ((*ret = read_sio_sniff()) != (ushort)-1)
  23441. + return 1;
  23442. + default :
  23443. + return -ENXIO;
  23444. + }
  23445. +}
  23446. +
  23447. +static SMARTIO_CMD WRITE_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
  23448. +static SMARTIO_CMD SELECT_OPT_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
  23449. +static SMARTIO_CMD CONTROL_BL_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
  23450. +static SMARTIO_CMD CONTRAST_BL_CMD = { 0x80, 0x21, { 0x00, 0x00 } };
  23451. +static SMARTIO_CMD CONTROL_KPD_CMD = { 0x80, 0x27, { 0x00, 0x00 } };
  23452. +static SMARTIO_CMD CONTROL_VEE_CMD = { 0x80, 0x22, { 0x00, 0x00 } };
  23453. +
  23454. +static ushort write_sio_port(int port, unchar value)
  23455. +{
  23456. + unsigned long flags;
  23457. +
  23458. + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
  23459. + return 0xFFFF;
  23460. +
  23461. + WRITE_PORT_CMD.Code = (unchar) port;
  23462. + WRITE_PORT_CMD.Opt[0] = (unchar) value;
  23463. +
  23464. + lock_smartio(&flags);
  23465. + send_SSP_msg((unchar *) &WRITE_PORT_CMD, 3);
  23466. + unlock_smartio(&flags);
  23467. +
  23468. + return 0;
  23469. +}
  23470. +
  23471. +static ushort write_sio_select(unchar select)
  23472. +{
  23473. + unsigned long flags;
  23474. +
  23475. + if ((select < 1) || (select > 2))
  23476. + return 0xFFFF;
  23477. +
  23478. + SELECT_OPT_CMD.Code = (unchar) (select + 0x28);
  23479. +
  23480. + lock_smartio(&flags);
  23481. + send_SSP_msg((unchar *) &SELECT_OPT_CMD, 2);
  23482. + unlock_smartio(&flags);
  23483. +
  23484. + return 0;
  23485. +}
  23486. +
  23487. +static ushort control_sio_backlite(int cmd, int value)
  23488. +{
  23489. + unsigned long flags;
  23490. +
  23491. + if (cmd == SMARTIO_BL_CONTRAST) {
  23492. + value &= 0xFF;
  23493. + CONTRAST_BL_CMD.Opt[0] = (unchar) value;
  23494. +
  23495. + lock_smartio(&flags);
  23496. + send_SSP_msg((unchar *) &CONTRAST_BL_CMD, 3);
  23497. + unlock_smartio(&flags);
  23498. + }
  23499. + else if (cmd == SMARTIO_BL_CONTROL) {
  23500. + if (value == 0x00) {
  23501. + // Backlite OFF
  23502. + CONTROL_BL_CMD.Code = 0x24;
  23503. + }
  23504. + else {
  23505. + // Backlite ON
  23506. + CONTROL_BL_CMD.Code = 0x23;
  23507. + }
  23508. + lock_smartio(&flags);
  23509. + send_SSP_msg((unchar *) &CONTROL_BL_CMD, 2);
  23510. + unlock_smartio(&flags);
  23511. + }
  23512. + else
  23513. + return 0xFFFF;
  23514. +
  23515. + return 0;
  23516. +}
  23517. +
  23518. +static ushort control_sio_keypad(int x, int y)
  23519. +{
  23520. + unsigned long flags;
  23521. +
  23522. + if ( (x<1) || (x>8) || (y<1) || (y>8)) {
  23523. + return 0xFFFF;
  23524. + }
  23525. +
  23526. + CONTROL_KPD_CMD.Opt[0] = (unchar) x;
  23527. + CONTROL_KPD_CMD.Opt[1] = (unchar) y;
  23528. +
  23529. + lock_smartio(&flags);
  23530. + send_SSP_msg((unchar *) &CONTROL_KPD_CMD, 4);
  23531. + unlock_smartio(&flags);
  23532. +
  23533. + return 0;
  23534. +}
  23535. +
  23536. +static ushort control_sio_vee(int value)
  23537. +{
  23538. + unsigned long flags;
  23539. +
  23540. + value &= 0xFF;
  23541. + CONTROL_VEE_CMD.Opt[0] = (unchar) value;
  23542. +
  23543. + lock_smartio(&flags);
  23544. + send_SSP_msg((unchar *) &CONTROL_VEE_CMD, 3);
  23545. + unlock_smartio(&flags);
  23546. +
  23547. + return 0;
  23548. +}
  23549. +
  23550. +static ssize_t sio_write(struct file *file, const char *buf, size_t cont, loff_t *ppos)
  23551. +{
  23552. + struct inode *inode = file->f_dentry->d_inode;
  23553. + unsigned int minor = MINOR(inode->i_rdev);
  23554. +
  23555. + switch (minor) {
  23556. + case SMARTIO_PORT_B:
  23557. + case SMARTIO_PORT_C:
  23558. + case SMARTIO_PORT_D:
  23559. + if (write_sio_port(minor, buf[0]) != 0xFFFF)
  23560. + return 1;
  23561. + case SMARTIO_SELECT_OPTION:
  23562. + if (write_sio_select(buf[0]) != 0xFFFF)
  23563. + return 1;
  23564. + case SMARTIO_BACKLITE:
  23565. + if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF)
  23566. + return 1;
  23567. + case SMARTIO_KEYPAD:
  23568. + if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF)
  23569. + return 2;
  23570. + case SMARTIO_VEE_PWM:
  23571. + if (control_sio_vee(buf[0]) != 0xFFFF)
  23572. + return 1;
  23573. + case SMARTIO_KBD_SNIFFER:
  23574. + // here are the scancodes injected
  23575. + handle_scancode((unchar)buf[0], (buf[0] & 0x80) ? 0 : 1);
  23576. + wake_up_interruptible(&keyboard_done_queue);
  23577. + // give some time to process! File IO is a bit faster than manual typing ;-)
  23578. + udelay(10000);
  23579. + return 1;
  23580. + default:
  23581. + return -ENXIO;
  23582. + }
  23583. +}
  23584. +
  23585. +static unsigned int sio_poll(struct file *file, struct poll_table_struct *wait)
  23586. +{
  23587. + return 0;
  23588. +}
  23589. +
  23590. +static SMARTIO_CMD IOCTL_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
  23591. +
  23592. +static ushort ioctl_sio_port(int port, unchar value)
  23593. +{
  23594. + unsigned long flags;
  23595. +
  23596. + if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
  23597. + return 0xFFFF;
  23598. +
  23599. + IOCTL_PORT_CMD.Code = (unchar) port + 0x04; // 0x05 ~ 0x08
  23600. + if (port == SMARTIO_PORT_B) {
  23601. + // Port B has 4 bits only
  23602. + IOCTL_PORT_CMD.Opt[0] = (unchar) value & 0x0F;
  23603. + }
  23604. + else
  23605. + IOCTL_PORT_CMD.Opt[0] = (unchar) value;
  23606. +
  23607. + lock_smartio(&flags);
  23608. + send_SSP_msg((unchar *) &IOCTL_PORT_CMD, 3);
  23609. + unlock_smartio(&flags);
  23610. +
  23611. + return 0;
  23612. +}
  23613. +
  23614. +static int sio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  23615. +{
  23616. + unsigned int minor = MINOR(inode->i_rdev);
  23617. + unchar *buf = (unchar *)arg;
  23618. +
  23619. + switch (minor) {
  23620. + case SMARTIO_PORT_B:
  23621. + case SMARTIO_PORT_C:
  23622. + case SMARTIO_PORT_D:
  23623. + if (cmd == SMARTIO_PORT_CONFIG) {
  23624. + if (ioctl_sio_port(minor, buf[0]) != 0xFFFF)
  23625. + return 0;
  23626. + }
  23627. + return -EINVAL;
  23628. + case SMARTIO_SELECT_OPTION:
  23629. + if (write_sio_select(buf[0]) != 0xFFFF) return 0;
  23630. + return -EINVAL;
  23631. + case SMARTIO_BACKLITE:
  23632. + if (cmd == SMARTIO_BL_CONTROL) {
  23633. + if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 0;
  23634. + }
  23635. + else if (cmd == SMARTIO_BL_CONTRAST) {
  23636. + if (control_sio_backlite(SMARTIO_BL_CONTRAST, buf[0]) != 0xFFFF) return 0;
  23637. + }
  23638. + else return -EINVAL;
  23639. + case SMARTIO_KEYPAD:
  23640. + if (cmd == SMARTIO_KPD_TIMEOUT) {
  23641. + kpd_timeout = *(long*)buf;
  23642. + return 0;
  23643. + }
  23644. + else if (cmd == SMARTIO_KPD_SETUP) {
  23645. + if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 0;
  23646. + }
  23647. + return -EINVAL;
  23648. + case SMARTIO_VEE_PWM:
  23649. + if (control_sio_vee(buf[0]) != 0xFFFF) return 0;
  23650. + return -EINVAL;
  23651. + case SMARTIO_KBD_SNIFFER:
  23652. + if (cmd == SMARTIO_SNIFFER_TIMEOUT) {
  23653. + sniffer_timeout = *(long*)buf;
  23654. + if (sniffer_timeout < 0) sniffer_timeout = -1;
  23655. + // the value will be devided by 10 later on
  23656. + if (!sniffer_timeout) sniffer_timeout = 10;
  23657. + return 0;
  23658. + }
  23659. + return -EINVAL;
  23660. + default:
  23661. + return -ENXIO;
  23662. + }
  23663. +}
  23664. +
  23665. +static int sio_open(struct inode *inode, struct file *file)
  23666. +{
  23667. + unsigned int minor = MINOR(inode->i_rdev);
  23668. +
  23669. + // we open all by default. we only have a special handler for the kbd sniffer
  23670. + switch (minor) {
  23671. + case SMARTIO_KBD_SNIFFER:
  23672. + if (sniffer_in_use) return -EBUSY;
  23673. + sniffer_in_use = 1;
  23674. + SNIFFER = 1;
  23675. + // sniff in active or passive mode
  23676. + if ((file->f_flags & O_RDWR) == O_RDWR) SNIFFMODE = 1; else SNIFFMODE = 0;
  23677. + // do we have a blocking or non blocking sniffer?
  23678. + if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK) sniffer_timeout = 100; else sniffer_timeout = -1;
  23679. + break;
  23680. + default:
  23681. + break;
  23682. + }
  23683. + return 0;
  23684. +}
  23685. +
  23686. +static int sio_close(struct inode *inode, struct file *file)
  23687. +{
  23688. + unsigned int minor = MINOR(inode->i_rdev);
  23689. +
  23690. + switch (minor) {
  23691. + case SMARTIO_KBD_SNIFFER:
  23692. + SNIFFER = 0;
  23693. + SNIFFMODE = 0;
  23694. + sniffer_in_use = 0;
  23695. + break;
  23696. + default:
  23697. + break;
  23698. + }
  23699. + return 0;
  23700. +}
  23701. +
  23702. +static struct file_operations sio_fops = {
  23703. + read: sio_read,
  23704. + write: sio_write,
  23705. + poll: sio_poll,
  23706. + ioctl: sio_ioctl,
  23707. + open: sio_open,
  23708. + release: sio_close,
  23709. +};
  23710. +
  23711. +static struct proc_dir_entry *sio_dir, *parent_dir = NULL;
  23712. +
  23713. +#define SMARTIO_MAJOR 58
  23714. +#define MAJOR_NR SMARTIO_MAJOR
  23715. +
  23716. +#define PROC_NAME "sio"
  23717. +
  23718. +static int sio_read_proc(char *buf, char **start, off_t pos, int count, int *eof, void *data)
  23719. +{
  23720. + char *p = buf;
  23721. +
  23722. + p += sprintf(p, "ADS SMARTIO Status: \n");
  23723. + p += sprintf(p, "\t Keyboard Interrupt : %lu\n", kbd_int);
  23724. + p += sprintf(p, "\t Keypad Interrupt : %lu\n", kpd_int);
  23725. + p += sprintf(p, "\t ADC Interrupt : %lu\n", adc_int);
  23726. + p += sprintf(p, "\t Keyboard Sniffer : %s mode : %s\n", kbd_sniff[ SNIFFER ], kbd_sniff_mode [ SNIFFMODE ]);
  23727. +
  23728. + return (p-buf);
  23729. +}
  23730. +
  23731. +#ifdef CONFIG_PM
  23732. +static int pm_smartio_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
  23733. +{
  23734. + switch (rqst) {
  23735. + case PM_RESUME:
  23736. + gc_sio_init();
  23737. + break;
  23738. + case PM_SUSPEND:
  23739. + // 4/5/01 Woojung
  23740. + // It checks Keybard received pair of press/release code.
  23741. + // System can sleep before receiving release code
  23742. + if (kbd_press_flag) {
  23743. + interruptible_sleep_on(&keyboard_done_queue);
  23744. + }
  23745. + break;
  23746. + }
  23747. +
  23748. + return 0;
  23749. +}
  23750. +#endif
  23751. +
  23752. +void __init sio_init(void)
  23753. +{
  23754. + if (register_chrdev(MAJOR_NR, "sio", &sio_fops)) {
  23755. + printk("smartio : unable to get major %d\n", MAJOR_NR);
  23756. + return;
  23757. + }
  23758. + else {
  23759. + printk("smartio driver initialized. version %s, date:%s\n",
  23760. + smartio_version, smartio_date);
  23761. +
  23762. + if (sio_reset_flag != 1) {
  23763. + gc_sio_init();
  23764. + if (request_irq(ADS_AVR_IRQ, gc_sio_interrupt,0,"sio",NULL) != 0){
  23765. + printk("smartio : Could not allocate IRQ!\n");
  23766. + return;
  23767. + }
  23768. + }
  23769. +
  23770. + if ((sio_dir = create_proc_entry(PROC_NAME, 0, parent_dir)) == NULL) {
  23771. + printk("smartio : Unable to create /proc entry\n");
  23772. + return;
  23773. + }
  23774. + else {
  23775. + sio_dir->read_proc = sio_read_proc;
  23776. +#ifdef CONFIG_PM
  23777. + pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_smartio_callback);
  23778. +#endif
  23779. + }
  23780. + }
  23781. +}
  23782. diff -urN linux-2.4.26/drivers/char/gckeymap.c linux-2.4.26-vrs1/drivers/char/gckeymap.c
  23783. --- linux-2.4.26/drivers/char/gckeymap.c 1970-01-01 01:00:00.000000000 +0100
  23784. +++ linux-2.4.26-vrs1/drivers/char/gckeymap.c 2004-01-14 21:32:25.000000000 +0000
  23785. @@ -0,0 +1,262 @@
  23786. +/* Do not edit this file! It was automatically generated by */
  23787. +/* loadkeys --mktable defkeymap.map > defkeymap.c */
  23788. +
  23789. +#include <linux/types.h>
  23790. +#include <linux/keyboard.h>
  23791. +#include <linux/kd.h>
  23792. +
  23793. +u_short plain_map[NR_KEYS] = {
  23794. + 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
  23795. + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
  23796. + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
  23797. + 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
  23798. + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
  23799. + 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
  23800. + 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
  23801. + 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
  23802. + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
  23803. + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
  23804. + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
  23805. + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23806. + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
  23807. + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
  23808. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23809. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23810. +};
  23811. +
  23812. +u_short shift_map[NR_KEYS] = {
  23813. + 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
  23814. + 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
  23815. + 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
  23816. + 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
  23817. + 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
  23818. + 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
  23819. + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
  23820. + 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
  23821. + 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
  23822. + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
  23823. + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
  23824. + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23825. + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
  23826. + 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
  23827. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23828. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23829. +};
  23830. +
  23831. +u_short altgr_map[NR_KEYS] = {
  23832. + 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
  23833. + 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
  23834. + 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
  23835. + 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
  23836. + 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
  23837. + 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
  23838. + 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
  23839. + 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
  23840. + 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
  23841. + 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
  23842. + 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
  23843. + 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23844. + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
  23845. + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
  23846. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23847. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23848. +};
  23849. +
  23850. +u_short ctrl_map[NR_KEYS] = {
  23851. + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
  23852. + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
  23853. + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
  23854. + 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
  23855. + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
  23856. + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
  23857. + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
  23858. + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
  23859. + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
  23860. + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
  23861. + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
  23862. + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23863. + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
  23864. + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
  23865. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23866. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23867. +};
  23868. +
  23869. +u_short shift_ctrl_map[NR_KEYS] = {
  23870. + 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
  23871. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
  23872. + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
  23873. + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
  23874. + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
  23875. + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
  23876. + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
  23877. + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23878. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
  23879. + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
  23880. + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
  23881. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23882. + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
  23883. + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
  23884. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23885. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23886. +};
  23887. +
  23888. +u_short alt_map[NR_KEYS] = {
  23889. + 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
  23890. + 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
  23891. + 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
  23892. + 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
  23893. + 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
  23894. + 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
  23895. + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
  23896. + 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
  23897. + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
  23898. + 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
  23899. + 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
  23900. + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23901. + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
  23902. + 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
  23903. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23904. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23905. +};
  23906. +
  23907. +u_short ctrl_alt_map[NR_KEYS] = {
  23908. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23909. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23910. + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
  23911. + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
  23912. + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
  23913. + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
  23914. + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
  23915. + 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
  23916. + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
  23917. + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
  23918. + 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
  23919. + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23920. + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
  23921. + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
  23922. + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
  23923. + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  23924. +};
  23925. +
  23926. +ushort *key_maps[MAX_NR_KEYMAPS] = {
  23927. + plain_map, shift_map, altgr_map, 0,
  23928. + ctrl_map, shift_ctrl_map, 0, 0,
  23929. + alt_map, 0, 0, 0,
  23930. + ctrl_alt_map, 0
  23931. +};
  23932. +
  23933. +unsigned int keymap_count = 7;
  23934. +
  23935. +/*
  23936. + * Philosophy: most people do not define more strings, but they who do
  23937. + * often want quite a lot of string space. So, we statically allocate
  23938. + * the default and allocate dynamically in chunks of 512 bytes.
  23939. + */
  23940. +
  23941. +char func_buf[] = {
  23942. + '\033', '[', '[', 'A', 0,
  23943. + '\033', '[', '[', 'B', 0,
  23944. + '\033', '[', '[', 'C', 0,
  23945. + '\033', '[', '[', 'D', 0,
  23946. + '\033', '[', '[', 'E', 0,
  23947. + '\033', '[', '1', '7', '~', 0,
  23948. + '\033', '[', '1', '8', '~', 0,
  23949. + '\033', '[', '1', '9', '~', 0,
  23950. + '\033', '[', '2', '0', '~', 0,
  23951. + '\033', '[', '2', '1', '~', 0,
  23952. + '\033', '[', '2', '3', '~', 0,
  23953. + '\033', '[', '2', '4', '~', 0,
  23954. + '\033', '[', '2', '5', '~', 0,
  23955. + '\033', '[', '2', '6', '~', 0,
  23956. + '\033', '[', '2', '8', '~', 0,
  23957. + '\033', '[', '2', '9', '~', 0,
  23958. + '\033', '[', '3', '1', '~', 0,
  23959. + '\033', '[', '3', '2', '~', 0,
  23960. + '\033', '[', '3', '3', '~', 0,
  23961. + '\033', '[', '3', '4', '~', 0,
  23962. + '\033', '[', '1', '~', 0,
  23963. + '\033', '[', '2', '~', 0,
  23964. + '\033', '[', '3', '~', 0,
  23965. + '\033', '[', '4', '~', 0,
  23966. + '\033', '[', '5', '~', 0,
  23967. + '\033', '[', '6', '~', 0,
  23968. + '\033', '[', 'M', 0,
  23969. + '\033', '[', 'P', 0,
  23970. +};
  23971. +
  23972. +char *funcbufptr = func_buf;
  23973. +int funcbufsize = sizeof(func_buf);
  23974. +int funcbufleft = 0; /* space left */
  23975. +
  23976. +char *func_table[MAX_NR_FUNC] = {
  23977. + func_buf + 0,
  23978. + func_buf + 5,
  23979. + func_buf + 10,
  23980. + func_buf + 15,
  23981. + func_buf + 20,
  23982. + func_buf + 25,
  23983. + func_buf + 31,
  23984. + func_buf + 37,
  23985. + func_buf + 43,
  23986. + func_buf + 49,
  23987. + func_buf + 55,
  23988. + func_buf + 61,
  23989. + func_buf + 67,
  23990. + func_buf + 73,
  23991. + func_buf + 79,
  23992. + func_buf + 85,
  23993. + func_buf + 91,
  23994. + func_buf + 97,
  23995. + func_buf + 103,
  23996. + func_buf + 109,
  23997. + func_buf + 115,
  23998. + func_buf + 120,
  23999. + func_buf + 125,
  24000. + func_buf + 130,
  24001. + func_buf + 135,
  24002. + func_buf + 140,
  24003. + func_buf + 145,
  24004. + 0,
  24005. + 0,
  24006. + func_buf + 149,
  24007. + 0,
  24008. +};
  24009. +
  24010. +struct kbdiacr accent_table[MAX_DIACR] = {
  24011. + {'`', 'A', '\300'}, {'`', 'a', '\340'},
  24012. + {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
  24013. + {'^', 'A', '\302'}, {'^', 'a', '\342'},
  24014. + {'~', 'A', '\303'}, {'~', 'a', '\343'},
  24015. + {'"', 'A', '\304'}, {'"', 'a', '\344'},
  24016. + {'O', 'A', '\305'}, {'o', 'a', '\345'},
  24017. + {'0', 'A', '\305'}, {'0', 'a', '\345'},
  24018. + {'A', 'A', '\305'}, {'a', 'a', '\345'},
  24019. + {'A', 'E', '\306'}, {'a', 'e', '\346'},
  24020. + {',', 'C', '\307'}, {',', 'c', '\347'},
  24021. + {'`', 'E', '\310'}, {'`', 'e', '\350'},
  24022. + {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
  24023. + {'^', 'E', '\312'}, {'^', 'e', '\352'},
  24024. + {'"', 'E', '\313'}, {'"', 'e', '\353'},
  24025. + {'`', 'I', '\314'}, {'`', 'i', '\354'},
  24026. + {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
  24027. + {'^', 'I', '\316'}, {'^', 'i', '\356'},
  24028. + {'"', 'I', '\317'}, {'"', 'i', '\357'},
  24029. + {'-', 'D', '\320'}, {'-', 'd', '\360'},
  24030. + {'~', 'N', '\321'}, {'~', 'n', '\361'},
  24031. + {'`', 'O', '\322'}, {'`', 'o', '\362'},
  24032. + {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
  24033. + {'^', 'O', '\324'}, {'^', 'o', '\364'},
  24034. + {'~', 'O', '\325'}, {'~', 'o', '\365'},
  24035. + {'"', 'O', '\326'}, {'"', 'o', '\366'},
  24036. + {'/', 'O', '\330'}, {'/', 'o', '\370'},
  24037. + {'`', 'U', '\331'}, {'`', 'u', '\371'},
  24038. + {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
  24039. + {'^', 'U', '\333'}, {'^', 'u', '\373'},
  24040. + {'"', 'U', '\334'}, {'"', 'u', '\374'},
  24041. + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
  24042. + {'T', 'H', '\336'}, {'t', 'h', '\376'},
  24043. + {'s', 's', '\337'}, {'"', 'y', '\377'},
  24044. + {'s', 'z', '\337'}, {'i', 'j', '\377'},
  24045. +};
  24046. +
  24047. +unsigned int accent_table_size = 68;
  24048. diff -urN linux-2.4.26/drivers/char/gckeymap.map linux-2.4.26-vrs1/drivers/char/gckeymap.map
  24049. --- linux-2.4.26/drivers/char/gckeymap.map 1970-01-01 01:00:00.000000000 +0100
  24050. +++ linux-2.4.26-vrs1/drivers/char/gckeymap.map 2004-01-14 21:32:25.000000000 +0000
  24051. @@ -0,0 +1,357 @@
  24052. +# Default kernel keymap. This uses 7 modifier combinations.
  24053. +keymaps 0-2,4-5,8,12
  24054. +# Change the above line into
  24055. +# keymaps 0-2,4-6,8,12
  24056. +# in case you want the entries
  24057. +# altgr control keycode 83 = Boot
  24058. +# altgr control keycode 111 = Boot
  24059. +# below.
  24060. +#
  24061. +# In fact AltGr is used very little, and one more keymap can
  24062. +# be saved by mapping AltGr to Alt (and adapting a few entries):
  24063. +# keycode 100 = Alt
  24064. +#
  24065. +keycode 1 = Escape Escape
  24066. + alt keycode 1 = Meta_Escape
  24067. +keycode 2 = one exclam
  24068. + alt keycode 2 = Meta_one
  24069. +keycode 3 = two at at
  24070. + control keycode 3 = nul
  24071. + shift control keycode 3 = nul
  24072. + alt keycode 3 = Meta_two
  24073. +keycode 4 = three numbersign
  24074. + control keycode 4 = Escape
  24075. + alt keycode 4 = Meta_three
  24076. +keycode 5 = four dollar dollar
  24077. + control keycode 5 = Control_backslash
  24078. + alt keycode 5 = Meta_four
  24079. +keycode 6 = five percent
  24080. + control keycode 6 = Control_bracketright
  24081. + alt keycode 6 = Meta_five
  24082. +keycode 7 = six asciicircum
  24083. + control keycode 7 = Control_asciicircum
  24084. + alt keycode 7 = Meta_six
  24085. +keycode 8 = seven ampersand braceleft
  24086. + control keycode 8 = Control_underscore
  24087. + alt keycode 8 = Meta_seven
  24088. +keycode 9 = eight asterisk bracketleft
  24089. + control keycode 9 = Delete
  24090. + alt keycode 9 = Meta_eight
  24091. +keycode 10 = nine parenleft bracketright
  24092. + alt keycode 10 = Meta_nine
  24093. +keycode 11 = zero parenright braceright
  24094. + alt keycode 11 = Meta_zero
  24095. +keycode 12 = minus underscore backslash
  24096. + control keycode 12 = Control_underscore
  24097. + shift control keycode 12 = Control_underscore
  24098. + alt keycode 12 = Meta_minus
  24099. +keycode 13 = equal plus
  24100. + alt keycode 13 = Meta_equal
  24101. +keycode 14 = Delete Delete
  24102. + control keycode 14 = BackSpace
  24103. + alt keycode 14 = Meta_Delete
  24104. +keycode 15 = Tab Tab
  24105. + alt keycode 15 = Meta_Tab
  24106. +keycode 16 = q
  24107. +keycode 17 = w
  24108. +keycode 18 = e
  24109. + altgr keycode 18 = Hex_E
  24110. +keycode 19 = r
  24111. +keycode 20 = t
  24112. +keycode 21 = y
  24113. +keycode 22 = u
  24114. +keycode 23 = i
  24115. +keycode 24 = o
  24116. +keycode 25 = p
  24117. +keycode 26 = bracketleft braceleft
  24118. + control keycode 26 = Escape
  24119. + alt keycode 26 = Meta_bracketleft
  24120. +keycode 27 = bracketright braceright asciitilde
  24121. + control keycode 27 = Control_bracketright
  24122. + alt keycode 27 = Meta_bracketright
  24123. +keycode 28 = Return
  24124. + alt keycode 28 = Meta_Control_m
  24125. +keycode 29 = Control
  24126. +keycode 30 = a
  24127. + altgr keycode 30 = Hex_A
  24128. +keycode 31 = s
  24129. +keycode 32 = d
  24130. + altgr keycode 32 = Hex_D
  24131. +keycode 33 = f
  24132. + altgr keycode 33 = Hex_F
  24133. +keycode 34 = g
  24134. +keycode 35 = h
  24135. +keycode 36 = j
  24136. +keycode 37 = k
  24137. +keycode 38 = l
  24138. +keycode 39 = semicolon colon
  24139. + alt keycode 39 = Meta_semicolon
  24140. +keycode 40 = apostrophe quotedbl
  24141. + control keycode 40 = Control_g
  24142. + alt keycode 40 = Meta_apostrophe
  24143. +keycode 41 = grave asciitilde
  24144. + control keycode 41 = nul
  24145. + alt keycode 41 = Meta_grave
  24146. +keycode 42 = Shift
  24147. +keycode 43 = backslash bar
  24148. + control keycode 43 = Control_backslash
  24149. + alt keycode 43 = Meta_backslash
  24150. +keycode 44 = z
  24151. +keycode 45 = x
  24152. +keycode 46 = c
  24153. + altgr keycode 46 = Hex_C
  24154. +keycode 47 = v
  24155. +keycode 48 = b
  24156. + altgr keycode 48 = Hex_B
  24157. +keycode 49 = n
  24158. +keycode 50 = m
  24159. +keycode 51 = comma less
  24160. + alt keycode 51 = Meta_comma
  24161. +keycode 52 = period greater
  24162. + control keycode 52 = Compose
  24163. + alt keycode 52 = Meta_period
  24164. +keycode 53 = slash question
  24165. + control keycode 53 = Delete
  24166. + alt keycode 53 = Meta_slash
  24167. +keycode 54 = Shift
  24168. +keycode 55 = KP_Multiply
  24169. +keycode 56 = Alt
  24170. +keycode 57 = space space
  24171. + control keycode 57 = nul
  24172. + alt keycode 57 = Meta_space
  24173. +keycode 58 = Caps_Lock
  24174. +keycode 59 = F1 F11 Console_13
  24175. + control keycode 59 = F1
  24176. + alt keycode 59 = Console_1
  24177. + control alt keycode 59 = Console_1
  24178. +keycode 60 = F2 F12 Console_14
  24179. + control keycode 60 = F2
  24180. + alt keycode 60 = Console_2
  24181. + control alt keycode 60 = Console_2
  24182. +keycode 61 = F3 F13 Console_15
  24183. + control keycode 61 = F3
  24184. + alt keycode 61 = Console_3
  24185. + control alt keycode 61 = Console_3
  24186. +keycode 62 = F4 F14 Console_16
  24187. + control keycode 62 = F4
  24188. + alt keycode 62 = Console_4
  24189. + control alt keycode 62 = Console_4
  24190. +keycode 63 = F5 F15 Console_17
  24191. + control keycode 63 = F5
  24192. + alt keycode 63 = Console_5
  24193. + control alt keycode 63 = Console_5
  24194. +keycode 64 = F6 F16 Console_18
  24195. + control keycode 64 = F6
  24196. + alt keycode 64 = Console_6
  24197. + control alt keycode 64 = Console_6
  24198. +keycode 65 = F7 F17 Console_19
  24199. + control keycode 65 = F7
  24200. + alt keycode 65 = Console_7
  24201. + control alt keycode 65 = Console_7
  24202. +keycode 66 = F8 F18 Console_20
  24203. + control keycode 66 = F8
  24204. + alt keycode 66 = Console_8
  24205. + control alt keycode 66 = Console_8
  24206. +keycode 67 = F9 F19 Console_21
  24207. + control keycode 67 = F9
  24208. + alt keycode 67 = Console_9
  24209. + control alt keycode 67 = Console_9
  24210. +keycode 68 = F10 F20 Console_22
  24211. + control keycode 68 = F10
  24212. + alt keycode 68 = Console_10
  24213. + control alt keycode 68 = Console_10
  24214. +keycode 69 = Num_Lock
  24215. + shift keycode 69 = Bare_Num_Lock
  24216. +keycode 70 = Scroll_Lock Show_Memory Show_Registers
  24217. + control keycode 70 = Show_State
  24218. + alt keycode 70 = Scroll_Lock
  24219. +keycode 71 = KP_7
  24220. + alt keycode 71 = Ascii_7
  24221. + altgr keycode 71 = Hex_7
  24222. +keycode 72 = KP_8
  24223. + alt keycode 72 = Ascii_8
  24224. + altgr keycode 72 = Hex_8
  24225. +keycode 73 = KP_9
  24226. + alt keycode 73 = Ascii_9
  24227. + altgr keycode 73 = Hex_9
  24228. +keycode 74 = KP_Subtract
  24229. +keycode 75 = KP_4
  24230. + alt keycode 75 = Ascii_4
  24231. + altgr keycode 75 = Hex_4
  24232. +keycode 76 = KP_5
  24233. + alt keycode 76 = Ascii_5
  24234. + altgr keycode 76 = Hex_5
  24235. +keycode 77 = KP_6
  24236. + alt keycode 77 = Ascii_6
  24237. + altgr keycode 77 = Hex_6
  24238. +keycode 78 = KP_Add
  24239. +keycode 79 = KP_1
  24240. + alt keycode 79 = Ascii_1
  24241. + altgr keycode 79 = Hex_1
  24242. +keycode 80 = KP_2
  24243. + alt keycode 80 = Ascii_2
  24244. + altgr keycode 80 = Hex_2
  24245. +keycode 81 = KP_3
  24246. + alt keycode 81 = Ascii_3
  24247. + altgr keycode 81 = Hex_3
  24248. +keycode 82 = KP_0
  24249. + alt keycode 82 = Ascii_0
  24250. + altgr keycode 82 = Hex_0
  24251. +keycode 83 = KP_Period
  24252. +# altgr control keycode 83 = Boot
  24253. + control alt keycode 83 = Boot
  24254. +keycode 84 = Last_Console
  24255. +keycode 85 =
  24256. +keycode 86 = less greater bar
  24257. + alt keycode 86 = Meta_less
  24258. +keycode 87 = F11 F11 Console_23
  24259. + control keycode 87 = F11
  24260. + alt keycode 87 = Console_11
  24261. + control alt keycode 87 = Console_11
  24262. +keycode 88 = F12 F12 Console_24
  24263. + control keycode 88 = F12
  24264. + alt keycode 88 = Console_12
  24265. + control alt keycode 88 = Console_12
  24266. +keycode 89 =
  24267. +keycode 90 =
  24268. +keycode 91 =
  24269. +keycode 92 =
  24270. +keycode 93 =
  24271. +keycode 94 =
  24272. +keycode 95 =
  24273. +keycode 96 = KP_Enter
  24274. +keycode 97 = Control
  24275. +keycode 98 = KP_Divide
  24276. +keycode 99 = Control_backslash
  24277. + control keycode 99 = Control_backslash
  24278. + alt keycode 99 = Control_backslash
  24279. +keycode 100 = AltGr
  24280. +keycode 101 = Break
  24281. +keycode 102 = Find
  24282. +keycode 103 = Up
  24283. +keycode 104 = Prior
  24284. + shift keycode 104 = Scroll_Backward
  24285. +keycode 105 = Left
  24286. + alt keycode 105 = Decr_Console
  24287. +keycode 106 = Right
  24288. + alt keycode 106 = Incr_Console
  24289. +keycode 107 = Select
  24290. +keycode 108 = Down
  24291. +keycode 109 = Next
  24292. + shift keycode 109 = Scroll_Forward
  24293. +keycode 110 = Insert
  24294. +keycode 111 = Remove
  24295. +# altgr control keycode 111 = Boot
  24296. + control alt keycode 111 = Boot
  24297. +keycode 112 = Macro
  24298. +keycode 113 = F13
  24299. +keycode 114 = F14
  24300. +keycode 115 = Help
  24301. +keycode 116 = Do
  24302. +keycode 117 = F17
  24303. +keycode 118 = KP_MinPlus
  24304. +keycode 119 = Pause
  24305. +keycode 120 =
  24306. +keycode 121 =
  24307. +keycode 122 =
  24308. +keycode 123 =
  24309. +keycode 124 =
  24310. +keycode 125 =
  24311. +keycode 126 =
  24312. +keycode 127 =
  24313. +string F1 = "\033[[A"
  24314. +string F2 = "\033[[B"
  24315. +string F3 = "\033[[C"
  24316. +string F4 = "\033[[D"
  24317. +string F5 = "\033[[E"
  24318. +string F6 = "\033[17~"
  24319. +string F7 = "\033[18~"
  24320. +string F8 = "\033[19~"
  24321. +string F9 = "\033[20~"
  24322. +string F10 = "\033[21~"
  24323. +string F11 = "\033[23~"
  24324. +string F12 = "\033[24~"
  24325. +string F13 = "\033[25~"
  24326. +string F14 = "\033[26~"
  24327. +string F15 = "\033[28~"
  24328. +string F16 = "\033[29~"
  24329. +string F17 = "\033[31~"
  24330. +string F18 = "\033[32~"
  24331. +string F19 = "\033[33~"
  24332. +string F20 = "\033[34~"
  24333. +string Find = "\033[1~"
  24334. +string Insert = "\033[2~"
  24335. +string Remove = "\033[3~"
  24336. +string Select = "\033[4~"
  24337. +string Prior = "\033[5~"
  24338. +string Next = "\033[6~"
  24339. +string Macro = "\033[M"
  24340. +string Pause = "\033[P"
  24341. +compose '`' 'A' to 'À'
  24342. +compose '`' 'a' to 'à'
  24343. +compose '\'' 'A' to 'Á'
  24344. +compose '\'' 'a' to 'á'
  24345. +compose '^' 'A' to 'Â'
  24346. +compose '^' 'a' to 'â'
  24347. +compose '~' 'A' to 'Ã'
  24348. +compose '~' 'a' to 'ã'
  24349. +compose '"' 'A' to 'Ä'
  24350. +compose '"' 'a' to 'ä'
  24351. +compose 'O' 'A' to 'Å'
  24352. +compose 'o' 'a' to 'å'
  24353. +compose '0' 'A' to 'Å'
  24354. +compose '0' 'a' to 'å'
  24355. +compose 'A' 'A' to 'Å'
  24356. +compose 'a' 'a' to 'å'
  24357. +compose 'A' 'E' to 'Æ'
  24358. +compose 'a' 'e' to 'æ'
  24359. +compose ',' 'C' to 'Ç'
  24360. +compose ',' 'c' to 'ç'
  24361. +compose '`' 'E' to 'È'
  24362. +compose '`' 'e' to 'è'
  24363. +compose '\'' 'E' to 'É'
  24364. +compose '\'' 'e' to 'é'
  24365. +compose '^' 'E' to 'Ê'
  24366. +compose '^' 'e' to 'ê'
  24367. +compose '"' 'E' to 'Ë'
  24368. +compose '"' 'e' to 'ë'
  24369. +compose '`' 'I' to 'Ì'
  24370. +compose '`' 'i' to 'ì'
  24371. +compose '\'' 'I' to 'Í'
  24372. +compose '\'' 'i' to 'í'
  24373. +compose '^' 'I' to 'Î'
  24374. +compose '^' 'i' to 'î'
  24375. +compose '"' 'I' to 'Ï'
  24376. +compose '"' 'i' to 'ï'
  24377. +compose '-' 'D' to 'Ð'
  24378. +compose '-' 'd' to 'ð'
  24379. +compose '~' 'N' to 'Ñ'
  24380. +compose '~' 'n' to 'ñ'
  24381. +compose '`' 'O' to 'Ò'
  24382. +compose '`' 'o' to 'ò'
  24383. +compose '\'' 'O' to 'Ó'
  24384. +compose '\'' 'o' to 'ó'
  24385. +compose '^' 'O' to 'Ô'
  24386. +compose '^' 'o' to 'ô'
  24387. +compose '~' 'O' to 'Õ'
  24388. +compose '~' 'o' to 'õ'
  24389. +compose '"' 'O' to 'Ö'
  24390. +compose '"' 'o' to 'ö'
  24391. +compose '/' 'O' to 'Ø'
  24392. +compose '/' 'o' to 'ø'
  24393. +compose '`' 'U' to 'Ù'
  24394. +compose '`' 'u' to 'ù'
  24395. +compose '\'' 'U' to 'Ú'
  24396. +compose '\'' 'u' to 'ú'
  24397. +compose '^' 'U' to 'Û'
  24398. +compose '^' 'u' to 'û'
  24399. +compose '"' 'U' to 'Ü'
  24400. +compose '"' 'u' to 'ü'
  24401. +compose '\'' 'Y' to 'Ý'
  24402. +compose '\'' 'y' to 'ý'
  24403. +compose 'T' 'H' to 'Þ'
  24404. +compose 't' 'h' to 'þ'
  24405. +compose 's' 's' to 'ß'
  24406. +compose '"' 'y' to 'ÿ'
  24407. +compose 's' 'z' to 'ß'
  24408. +compose 'i' 'j' to 'ÿ'
  24409. diff -urN linux-2.4.26/drivers/char/generic_serial.c linux-2.4.26-vrs1/drivers/char/generic_serial.c
  24410. --- linux-2.4.26/drivers/char/generic_serial.c 2002-11-28 23:53:12.000000000 +0000
  24411. +++ linux-2.4.26-vrs1/drivers/char/generic_serial.c 2004-01-14 21:32:25.000000000 +0000
  24412. @@ -883,6 +883,9 @@
  24413. if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
  24414. }
  24415. + /*
  24416. + * should be using tty_get_baud_rate() here -- rmk
  24417. + */
  24418. baudrate = tiosp->c_cflag & CBAUD;
  24419. if (baudrate & CBAUDEX) {
  24420. baudrate &= ~CBAUDEX;
  24421. @@ -957,6 +960,11 @@
  24422. unsigned long flags;
  24423. unsigned long page;
  24424. + /*
  24425. + * Do we expect to allocate tmp_buf from an interrupt routine?
  24426. + * If not, then save_flags() cli() and restore_flags() are
  24427. + * redundant here and should be replaced by a semaphore. -- rmk
  24428. + */
  24429. save_flags (flags);
  24430. if (!tmp_buf) {
  24431. page = get_free_page(GFP_KERNEL);
  24432. @@ -976,6 +984,11 @@
  24433. if (port->flags & ASYNC_INITIALIZED)
  24434. return 0;
  24435. + /*
  24436. + * Do we expect to allocate xmit_buf from an interrupt routine?
  24437. + * If not, then save_flags() cli() and restore_flags() are
  24438. + * redundant here and should be replaced by a semaphore. -- rmk
  24439. + */
  24440. if (!port->xmit_buf) {
  24441. /* We may sleep in get_free_page() */
  24442. unsigned long tmp;
  24443. @@ -1016,7 +1029,7 @@
  24444. struct serial_struct sio;
  24445. if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
  24446. - return(-EFAULT);
  24447. + return -EFAULT;
  24448. if (!capable(CAP_SYS_ADMIN)) {
  24449. if ((sio.baud_base != port->baud_base) ||
  24450. diff -urN linux-2.4.26/drivers/char/keyboard.c linux-2.4.26-vrs1/drivers/char/keyboard.c
  24451. --- linux-2.4.26/drivers/char/keyboard.c 2003-11-28 18:26:20.000000000 +0000
  24452. +++ linux-2.4.26-vrs1/drivers/char/keyboard.c 2004-02-11 01:12:05.000000000 +0000
  24453. @@ -14,13 +14,17 @@
  24454. * `Sticky' modifier keys, 951006.
  24455. *
  24456. * 11-11-96: SAK should now work in the raw mode (Martin Mares)
  24457. - *
  24458. + *
  24459. * Modified to provide 'generic' keyboard support by Hamish Macdonald
  24460. * Merge with the m68k keyboard driver and split-off of the PC low-level
  24461. * parts by Geert Uytterhoeven, May 1997
  24462. *
  24463. * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
  24464. * 30-07-98: Dead keys redone, aeb@cwi.nl.
  24465. + *
  24466. + * 04-04-1998: Added keyboard autorepeat support (some keyboards don't
  24467. + * autorepeat, and some keyboard changers interfere with keyboard
  24468. + * autorepeat settings). - Russell King (rmk@arm.linux.org.uk)
  24469. */
  24470. #include <linux/config.h>
  24471. @@ -30,6 +34,7 @@
  24472. #include <linux/tty_flip.h>
  24473. #include <linux/mm.h>
  24474. #include <linux/string.h>
  24475. +#include <linux/timer.h>
  24476. #include <linux/random.h>
  24477. #include <linux/init.h>
  24478. @@ -61,6 +66,14 @@
  24479. #define KBD_DEFLOCK 0
  24480. #endif
  24481. +/*
  24482. + * Default autorepeat settings.
  24483. + * DEFAULT_REPEAT_TIMEOUT is the timeout from the keypress to the first repeat
  24484. + * DEFAULT_REPEAT_INTERVAL is the timeout between successive repeats
  24485. + */
  24486. +#define DEFAULT_REPEAT_TIMEOUT HZ*300/1000
  24487. +#define DEFAULT_REPEAT_INTERVAL HZ*30/1000
  24488. +
  24489. void (*kbd_ledfunc)(unsigned int led);
  24490. EXPORT_SYMBOL(handle_scancode);
  24491. EXPORT_SYMBOL(kbd_ledfunc);
  24492. @@ -82,21 +95,25 @@
  24493. static unsigned long key_down[256/BITS_PER_LONG];
  24494. static int dead_key_next;
  24495. -/*
  24496. +/*
  24497. * In order to retrieve the shift_state (for the mouse server), either
  24498. - * the variable must be global, or a new procedure must be created to
  24499. + * the variable must be global, or a new procedure must be created to
  24500. * return the value. I chose the former way.
  24501. */
  24502. int shift_state;
  24503. static int npadch = -1; /* -1 or number assembled on pad */
  24504. static unsigned char diacr;
  24505. static char rep; /* flag telling character repeat */
  24506. +static int kbd_repeatkeycode= -1;
  24507. +static int kbd_repeattimeout = DEFAULT_REPEAT_TIMEOUT;
  24508. +static int kbd_repeatinterval= DEFAULT_REPEAT_INTERVAL;
  24509. struct kbd_struct kbd_table[MAX_NR_CONSOLES];
  24510. static struct tty_struct **ttytab;
  24511. static struct kbd_struct * kbd = kbd_table;
  24512. static struct tty_struct * tty;
  24513. static unsigned char prev_scancode;
  24514. +static void kbd_processkeycode(unsigned char scancode, char up_flag, int autorepeat);
  24515. void compute_shiftstate(void);
  24516. typedef void (*k_hand)(unsigned char value, char up_flag);
  24517. @@ -163,7 +180,8 @@
  24518. * string, and in both cases we might assume that it is
  24519. * in utf-8 already.
  24520. */
  24521. -void to_utf8(ushort c) {
  24522. +void to_utf8(ushort c)
  24523. +{
  24524. if (c < 0x80)
  24525. put_queue(c); /* 0******* */
  24526. else if (c < 0x800) {
  24527. @@ -182,17 +200,23 @@
  24528. * Translation of escaped scancodes to keycodes.
  24529. * This is now user-settable (for machines were it makes sense).
  24530. */
  24531. -
  24532. int setkeycode(unsigned int scancode, unsigned int keycode)
  24533. {
  24534. - return kbd_setkeycode(scancode, keycode);
  24535. + return kbd_setkeycode(scancode, keycode);
  24536. }
  24537. int getkeycode(unsigned int scancode)
  24538. {
  24539. - return kbd_getkeycode(scancode);
  24540. + return kbd_getkeycode(scancode);
  24541. }
  24542. +static void key_callback(unsigned long nr);
  24543. +
  24544. +static struct timer_list key_autorepeat_timer =
  24545. +{
  24546. + function: key_callback
  24547. +};
  24548. +
  24549. void handle_scancode(unsigned char scancode, int down)
  24550. {
  24551. unsigned char keycode;
  24552. @@ -201,6 +225,7 @@
  24553. char have_keycode;
  24554. pm_access(pm_kbd);
  24555. +
  24556. add_keyboard_randomness(scancode | up_flag);
  24557. tty = ttytab? ttytab[fg_console]: NULL;
  24558. @@ -223,15 +248,15 @@
  24559. if (raw_mode) {
  24560. /*
  24561. * The following is a workaround for hardware
  24562. - * which sometimes send the key release event twice
  24563. + * which sometimes send the key release event twice
  24564. */
  24565. unsigned char next_scancode = scancode|up_flag;
  24566. if (have_keycode && up_flag && next_scancode==prev_scancode) {
  24567. /* unexpected 2nd release event */
  24568. } else {
  24569. - /*
  24570. + /*
  24571. * Only save previous scancode if it was a key-up
  24572. - * and had a single-byte scancode.
  24573. + * and had a single-byte scancode.
  24574. */
  24575. if (!have_keycode)
  24576. prev_scancode = 1;
  24577. @@ -256,12 +281,35 @@
  24578. * return the keycode if in MEDIUMRAW mode.
  24579. */
  24580. + kbd_processkeycode(keycode, up_flag, 0);
  24581. +
  24582. +out:
  24583. + do_poke_blanked_console = 1;
  24584. + schedule_console_callback();
  24585. +}
  24586. +
  24587. +static void
  24588. +kbd_processkeycode(unsigned char keycode, char up_flag, int autorepeat)
  24589. +{
  24590. + char raw_mode = (kbd->kbdmode == VC_RAW);
  24591. +
  24592. if (up_flag) {
  24593. rep = 0;
  24594. if(!test_and_clear_bit(keycode, key_down))
  24595. up_flag = kbd_unexpected_up(keycode);
  24596. - } else
  24597. + } else {
  24598. rep = test_and_set_bit(keycode, key_down);
  24599. + /* If the keyboard autorepeated for us, ignore it.
  24600. + * We do our own autorepeat processing.
  24601. + */
  24602. + if (rep && !autorepeat)
  24603. + return;
  24604. + }
  24605. +
  24606. + if (kbd_repeatkeycode == keycode || !up_flag || raw_mode) {
  24607. + kbd_repeatkeycode = -1;
  24608. + del_timer(&key_autorepeat_timer);
  24609. + }
  24610. #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
  24611. if (keycode == SYSRQ_KEY) {
  24612. @@ -275,6 +323,23 @@
  24613. }
  24614. #endif
  24615. + /*
  24616. + * Calculate the next time when we have to do some autorepeat
  24617. + * processing. Note that we do not do autorepeat processing
  24618. + * while in raw mode but we do do autorepeat processing in
  24619. + * medium raw mode.
  24620. + */
  24621. + if (!up_flag && !raw_mode) {
  24622. + kbd_repeatkeycode = keycode;
  24623. + if (vc_kbd_mode(kbd, VC_REPEAT)) {
  24624. + if (rep)
  24625. + key_autorepeat_timer.expires = jiffies + kbd_repeatinterval;
  24626. + else
  24627. + key_autorepeat_timer.expires = jiffies + kbd_repeattimeout;
  24628. + add_timer(&key_autorepeat_timer);
  24629. + }
  24630. + }
  24631. +
  24632. if (kbd->kbdmode == VC_MEDIUMRAW) {
  24633. /* soon keycodes will require more than one byte */
  24634. put_queue(keycode + up_flag);
  24635. @@ -343,9 +408,24 @@
  24636. #endif
  24637. }
  24638. }
  24639. + rep = 0;
  24640. out:
  24641. - do_poke_blanked_console = 1;
  24642. - schedule_console_callback();
  24643. +}
  24644. +
  24645. +/*
  24646. + * This clears the key down arrays when the keyboard is reset. On
  24647. + * keyboard reset, this must be called before any keycodes are
  24648. + * received.
  24649. + */
  24650. +void kbd_reset_kdown(void)
  24651. +{
  24652. + int i;
  24653. +
  24654. + for (i = 0; i < NR_SHIFT; i++)
  24655. + k_down[i] = 0;
  24656. + for (i = 0; i < SIZE(key_down); i++)
  24657. + key_down[i] = 0;
  24658. + shift_state = 0;
  24659. }
  24660. void put_queue(int ch)
  24661. @@ -453,7 +533,7 @@
  24662. static void decr_console(void)
  24663. {
  24664. int i;
  24665. -
  24666. +
  24667. for (i = fg_console-1; i != fg_console; i--) {
  24668. if (i == -1)
  24669. i = MAX_NR_CONSOLES-1;
  24670. @@ -531,7 +611,7 @@
  24671. {
  24672. }
  24673. -static void do_null()
  24674. +static void do_null(void)
  24675. {
  24676. compute_shiftstate();
  24677. }
  24678. @@ -646,8 +726,8 @@
  24679. static void do_pad(unsigned char value, char up_flag)
  24680. {
  24681. - static const char *pad_chars = "0123456789+-*/\015,.?()";
  24682. - static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
  24683. + static const char *pad_chars = "0123456789+-*/\015,.?()#";
  24684. + static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
  24685. if (up_flag)
  24686. return; /* no action, if this is a key release */
  24687. @@ -748,9 +828,10 @@
  24688. }
  24689. }
  24690. -/* called after returning from RAW mode or when changing consoles -
  24691. - recompute k_down[] and shift_state from key_down[] */
  24692. -/* maybe called when keymap is undefined, so that shiftkey release is seen */
  24693. +/* Called after returning from RAW mode or when changing consoles -
  24694. + * recompute k_down[] and shift_state from key_down[]
  24695. + * Maybe called when keymap is undefined so that shift key release is seen
  24696. + */
  24697. void compute_shiftstate(void)
  24698. {
  24699. int i, j, k, sym, val;
  24700. @@ -829,19 +910,22 @@
  24701. }
  24702. /*
  24703. - * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
  24704. - * or (ii) whatever pattern of lights people want to show using KDSETLED,
  24705. - * or (iii) specified bits of specified words in kernel memory.
  24706. + * The leds display either
  24707. + * (i) the status of NumLock, CapsLock, ScrollLock, or
  24708. + * (ii) whatever pattern of lights people want to show using KDSETLED, or
  24709. + * (iii) specified bits of specified words in kernel memory.
  24710. */
  24711. static unsigned char ledstate = 0xff; /* undefined */
  24712. static unsigned char ledioctl;
  24713. -unsigned char getledstate(void) {
  24714. +unsigned char getledstate(void)
  24715. +{
  24716. return ledstate;
  24717. }
  24718. -void setledstate(struct kbd_struct *kbd, unsigned int led) {
  24719. +void setledstate(struct kbd_struct *kbd, unsigned int led)
  24720. +{
  24721. if (!(led & ~7)) {
  24722. ledioctl = led;
  24723. kbd->ledmode = LED_SHOW_IOCTL;
  24724. @@ -857,7 +941,8 @@
  24725. } ledptrs[3];
  24726. void register_leds(int console, unsigned int led,
  24727. - unsigned int *addr, unsigned int mask) {
  24728. + unsigned int *addr, unsigned int mask)
  24729. +{
  24730. struct kbd_struct *kbd = kbd_table + console;
  24731. if (led < 3) {
  24732. ledptrs[led].addr = addr;
  24733. @@ -868,7 +953,8 @@
  24734. kbd->ledmode = LED_SHOW_FLAGS;
  24735. }
  24736. -static inline unsigned char getleds(void){
  24737. +static inline unsigned char getleds(void)
  24738. +{
  24739. struct kbd_struct *kbd = kbd_table + fg_console;
  24740. unsigned char leds;
  24741. @@ -915,6 +1001,19 @@
  24742. {
  24743. unsigned char leds = getleds();
  24744. + if (rep && kbd_repeatkeycode != -1) {
  24745. + tty = ttytab? ttytab[fg_console]: NULL;
  24746. + kbd = kbd_table + fg_console;
  24747. +
  24748. + /* This prevents the kbd_key routine from being called
  24749. + * twice, once by this BH, and once by the interrupt
  24750. + * routine.
  24751. + */
  24752. + kbd_disable_irq();
  24753. + kbd_processkeycode(kbd_repeatkeycode, 0, 1);
  24754. + kbd_enable_irq();
  24755. + }
  24756. +
  24757. if (leds != ledstate) {
  24758. ledstate = leds;
  24759. kbd_leds(leds);
  24760. @@ -937,6 +1036,12 @@
  24761. tasklet_enable(&keyboard_tasklet);
  24762. }
  24763. +static void key_callback(unsigned long nr)
  24764. +{
  24765. + rep = 1;
  24766. + tasklet_schedule(&keyboard_tasklet);
  24767. +}
  24768. +
  24769. typedef void (pm_kbd_func) (void);
  24770. pm_callback pm_kbd_request_override = NULL;
  24771. @@ -953,7 +1058,7 @@
  24772. kbd0.slockstate = 0;
  24773. kbd0.modeflags = KBD_DEFMODE;
  24774. kbd0.kbdmode = VC_XLATE;
  24775. -
  24776. +
  24777. for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
  24778. kbd_table[i] = kbd0;
  24779. @@ -963,7 +1068,7 @@
  24780. tasklet_enable(&keyboard_tasklet);
  24781. tasklet_schedule(&keyboard_tasklet);
  24782. -
  24783. +
  24784. pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override);
  24785. return 0;
  24786. diff -urN linux-2.4.26/drivers/char/mem.c linux-2.4.26-vrs1/drivers/char/mem.c
  24787. --- linux-2.4.26/drivers/char/mem.c 2003-11-28 18:26:20.000000000 +0000
  24788. +++ linux-2.4.26-vrs1/drivers/char/mem.c 2004-01-14 21:39:01.000000000 +0000
  24789. @@ -27,9 +27,6 @@
  24790. #include <asm/io.h>
  24791. #include <asm/pgalloc.h>
  24792. -#ifdef CONFIG_I2C
  24793. -extern int i2c_init_all(void);
  24794. -#endif
  24795. #ifdef CONFIG_FB
  24796. extern void fbmem_init(void);
  24797. #endif
  24798. @@ -740,9 +737,6 @@
  24799. printk("unable to get major %d for memory devs\n", MEM_MAJOR);
  24800. memory_devfs_register();
  24801. rand_initialize();
  24802. -#ifdef CONFIG_I2C
  24803. - i2c_init_all();
  24804. -#endif
  24805. #if defined (CONFIG_FB)
  24806. fbmem_init();
  24807. #endif
  24808. diff -urN linux-2.4.26/drivers/char/omaha-rtc.c linux-2.4.26-vrs1/drivers/char/omaha-rtc.c
  24809. --- linux-2.4.26/drivers/char/omaha-rtc.c 1970-01-01 01:00:00.000000000 +0100
  24810. +++ linux-2.4.26-vrs1/drivers/char/omaha-rtc.c 2004-01-14 21:32:25.000000000 +0000
  24811. @@ -0,0 +1,566 @@
  24812. +/*
  24813. + * (C) ARM Limited 2002.
  24814. + *
  24815. + * Real Time Clock interface for Linux on Omaha
  24816. + *
  24817. + * Based on sa1100-rtc.c
  24818. + *
  24819. + * Copyright (c) 2000 Nils Faerber
  24820. + *
  24821. + * Based on rtc.c by Paul Gortmaker
  24822. + * Date/time conversion routines taken from arch/arm/kernel/time.c
  24823. + * by Linus Torvalds and Russell King
  24824. + * and the GNU C Library
  24825. + * ( ... I love the GPL ... just take what you need! ;)
  24826. + *
  24827. + * This program is free software; you can redistribute it and/or
  24828. + * modify it under the terms of the GNU General Public License
  24829. + * as published by the Free Software Foundation; either version
  24830. + * 2 of the License, or (at your option) any later version.
  24831. + *
  24832. + * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
  24833. + * - added periodic timer capability using OSMR1
  24834. + * - flag compatibility with other RTC chips
  24835. + * - permission checks for ioctls
  24836. + * - major cleanup, partial rewrite
  24837. + *
  24838. + * 0.03 2001-03-07 CIH <cih@coventive.com>
  24839. + * - Modify the bug setups RTC clock.
  24840. + *
  24841. + * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
  24842. + * - removed mktime(), added alarm irq clear
  24843. + *
  24844. + * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
  24845. + * - initial release
  24846. + */
  24847. +
  24848. +#include <linux/module.h>
  24849. +#include <linux/fs.h>
  24850. +#include <linux/miscdevice.h>
  24851. +#include <linux/string.h>
  24852. +#include <linux/init.h>
  24853. +#include <linux/poll.h>
  24854. +#include <linux/proc_fs.h>
  24855. +#include <asm/bitops.h>
  24856. +#include <asm/io.h>
  24857. +#include <asm/hardware.h>
  24858. +#include <asm/irq.h>
  24859. +#include <linux/rtc.h>
  24860. +#include <linux/mc146818rtc.h>
  24861. +
  24862. +#define DRIVER_VERSION "1.00"
  24863. +
  24864. +#define epoch 1970
  24865. +
  24866. +#define TIMER_FREQ 3686400
  24867. +
  24868. +#define RTC_DEF_DIVIDER 32768 - 1
  24869. +#define RTC_DEF_TRIM 0
  24870. +
  24871. +/* Those are the bits from a classic RTC we want to mimic */
  24872. +#define RTC_IRQF 0x80 /* any of the following 3 is active */
  24873. +#define RTC_PF 0x40
  24874. +#define RTC_AF 0x20
  24875. +#define RTC_UF 0x10
  24876. +
  24877. +// bitdefs for rtc registers
  24878. +#define TICNT_ENABLE 0x80 // Enable tick interrupt
  24879. +#define TICNT_PERIOD 0x7F // Divisor required for 1Hz tick
  24880. +#define RTC_ENABLE 0x1 // Enable bit for RTC
  24881. +
  24882. +static unsigned long rtc_status;
  24883. +static unsigned long rtc_irq_data;
  24884. +static unsigned long rtc_freq = 1024;
  24885. +
  24886. +static struct fasync_struct *rtc_async_queue;
  24887. +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
  24888. +
  24889. +extern spinlock_t rtc_lock;
  24890. +
  24891. +static const unsigned char days_in_mo[] =
  24892. + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  24893. +
  24894. +#define is_leap(year) \
  24895. + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  24896. +
  24897. +// all the alarm and rtc registers
  24898. +static volatile unsigned int almsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMSEC);
  24899. +static volatile unsigned int almmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMIN);
  24900. +static volatile unsigned int almhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMHOUR);
  24901. +static volatile unsigned int almday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMDAY);
  24902. +static volatile unsigned int almmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMON);
  24903. +static volatile unsigned int almyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMYEAR);
  24904. +
  24905. +static volatile unsigned int bcdsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDSEC);
  24906. +static volatile unsigned int bcdmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMIN);
  24907. +static volatile unsigned int bcdhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDHOUR);
  24908. +static volatile unsigned int bcdday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDAY);
  24909. +static volatile unsigned int bcddate = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDATE);
  24910. +static volatile unsigned int bcdmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMON);
  24911. +static volatile unsigned int bcdyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDYEAR);
  24912. +
  24913. +/*
  24914. + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
  24915. + */
  24916. +
  24917. +static void decodetime (unsigned long t, struct rtc_time *tval)
  24918. +{
  24919. + long days, month, year, rem;
  24920. +
  24921. + days = t / 86400;
  24922. + rem = t % 86400;
  24923. + tval->tm_hour = rem / 3600;
  24924. + rem %= 3600;
  24925. + tval->tm_min = rem / 60;
  24926. + tval->tm_sec = rem % 60;
  24927. + tval->tm_wday = (4 + days) % 7;
  24928. +
  24929. +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
  24930. +
  24931. + year = epoch;
  24932. + while (days >= (365 + is_leap(year))) {
  24933. + unsigned long yg = year + days / 365;
  24934. + days -= ((yg - year) * 365
  24935. + + LEAPS_THRU_END_OF (yg - 1)
  24936. + - LEAPS_THRU_END_OF (year - 1));
  24937. + year = yg;
  24938. + }
  24939. + tval->tm_year = year - 1900;
  24940. + tval->tm_yday = days + 1;
  24941. +
  24942. + month = 0;
  24943. + if (days >= 31) {
  24944. + days -= 31;
  24945. + month++;
  24946. + if (days >= (28 + is_leap(year))) {
  24947. + days -= (28 + is_leap(year));
  24948. + month++;
  24949. + while (days >= days_in_mo[month]) {
  24950. + days -= days_in_mo[month];
  24951. + month++;
  24952. + }
  24953. + }
  24954. + }
  24955. + tval->tm_mon = month;
  24956. + tval->tm_mday = days + 1;
  24957. +}
  24958. +
  24959. +// Get alarm time in seconds
  24960. +static unsigned long get_alarm_time(void)
  24961. +{
  24962. + int sec, min,hour,date,mon,year;
  24963. +
  24964. + // Read data from h/w
  24965. + year = __raw_readb(almyear);
  24966. + mon = __raw_readb(almmon);
  24967. + date = __raw_readb(almday);
  24968. + hour = __raw_readb(almhour);
  24969. + min = __raw_readb(almmin);
  24970. + sec = __raw_readb(almsec);
  24971. +
  24972. + // convert all the data into binary
  24973. + year = BCD_TO_BIN(year);
  24974. + mon = BCD_TO_BIN(mon);
  24975. + date = BCD_TO_BIN(date);
  24976. + hour = BCD_TO_BIN(hour);
  24977. + min = BCD_TO_BIN(min);
  24978. + sec = BCD_TO_BIN(sec);
  24979. +
  24980. + // convert year to 19xx or 20xx as appropriate
  24981. + if (year > 69)
  24982. + year += 1900;
  24983. + else
  24984. + year += 2000;
  24985. +
  24986. + // Now calculate number of seconds since time began...
  24987. + return mktime(year,mon,date,hour,min,sec);
  24988. +}
  24989. +
  24990. +// Get rtc time in seconds
  24991. +static unsigned long get_rtc_time(void)
  24992. +{
  24993. + int sec,min,hour,day,date,mon,year;
  24994. +
  24995. + // Read data from h/w
  24996. + year = __raw_readb(bcdyear);
  24997. + mon = __raw_readb(bcdmon);
  24998. + date = __raw_readb(bcdday);
  24999. + day = __raw_readb(bcddate);
  25000. + hour = __raw_readb(bcdhour);
  25001. + min = __raw_readb(bcdmin);
  25002. + sec = __raw_readb(bcdsec);
  25003. +
  25004. + // convert all the data into binary
  25005. + year = BCD_TO_BIN(year);
  25006. + mon = BCD_TO_BIN(mon);
  25007. + date = BCD_TO_BIN(date);
  25008. + day = BCD_TO_BIN(day);
  25009. + hour = BCD_TO_BIN(hour);
  25010. + min = BCD_TO_BIN(min);
  25011. + sec = BCD_TO_BIN(sec);
  25012. +
  25013. + // convert year to 19xx or 20xx as appropriate
  25014. + if (year > 69)
  25015. + year += 1900;
  25016. + else
  25017. + year += 2000;
  25018. +
  25019. + // Now calculate number of seconds since time began...
  25020. + return mktime(year,mon,date,hour,min,sec);
  25021. +}
  25022. +
  25023. +/* Sets time of alarm */
  25024. +static void set_alarm_time(struct rtc_time *tval)
  25025. +{
  25026. +
  25027. + int sec,min,hour,day,mon,year;
  25028. +
  25029. + // Convert data from binary to 8-bit bcd
  25030. + sec = BIN_TO_BCD(tval->tm_sec);
  25031. + min = BIN_TO_BCD(tval->tm_min);
  25032. + hour = BIN_TO_BCD(tval->tm_hour);
  25033. + day = BIN_TO_BCD(tval->tm_mday);
  25034. + mon = BIN_TO_BCD(tval->tm_mon);
  25035. +
  25036. + // Year is special
  25037. + year = tval->tm_year;
  25038. + if(year > 1999)
  25039. + year -=2000;
  25040. + else
  25041. + year -=1900;
  25042. +
  25043. + year = BIN_TO_BCD(year);
  25044. +
  25045. + // Write all the registers
  25046. + __raw_writeb(year,almyear);
  25047. + __raw_writeb(mon,almmon);
  25048. + __raw_writeb(day,almday);
  25049. + __raw_writeb(hour,almhour);
  25050. + __raw_writeb(min,almmin);
  25051. + __raw_writeb(sec,almsec);
  25052. +}
  25053. +
  25054. +/* Sets time of alarm */
  25055. +static void set_rtc_time(struct rtc_time *tval)
  25056. +{
  25057. +
  25058. + int sec,min,hour,day,date,mon,year;
  25059. +
  25060. + // Convert data from binary to 8-bit bcd
  25061. + sec = BIN_TO_BCD(tval->tm_sec);
  25062. + min = BIN_TO_BCD(tval->tm_min);
  25063. + hour = BIN_TO_BCD(tval->tm_hour);
  25064. + day = BIN_TO_BCD(tval->tm_mday);
  25065. + date = BIN_TO_BCD(tval->tm_wday);
  25066. + mon = BIN_TO_BCD(tval->tm_mon);
  25067. +
  25068. + // Year is special
  25069. + year = tval->tm_year;
  25070. + if(year > 1999)
  25071. + year -=2000;
  25072. + else
  25073. + year -=1900;
  25074. +
  25075. + year = BIN_TO_BCD(year);
  25076. +
  25077. + // Write all the registers
  25078. + __raw_writeb(year,bcdyear);
  25079. + __raw_writeb(mon,bcdmon);
  25080. + __raw_writeb(date,bcddate);
  25081. + __raw_writeb(day,bcdday);
  25082. + __raw_writeb(hour,bcdhour);
  25083. + __raw_writeb(min,bcdmin);
  25084. + __raw_writeb(sec,bcdsec);
  25085. +}
  25086. +
  25087. +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  25088. +{
  25089. + /* update irq data & counter */
  25090. + rtc_irq_data += 0x100;
  25091. +
  25092. + /* wake up waiting process */
  25093. + wake_up_interruptible(&rtc_wait);
  25094. + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
  25095. +}
  25096. +
  25097. +static int rtc_open(struct inode *inode, struct file *file)
  25098. +{
  25099. + if (test_and_set_bit (1, &rtc_status))
  25100. + return -EBUSY;
  25101. + MOD_INC_USE_COUNT;
  25102. + rtc_irq_data = 0;
  25103. + return 0;
  25104. +}
  25105. +
  25106. +static int rtc_release(struct inode *inode, struct file *file)
  25107. +{
  25108. + rtc_status = 0;
  25109. + MOD_DEC_USE_COUNT;
  25110. + return 0;
  25111. +}
  25112. +
  25113. +static int rtc_fasync (int fd, struct file *filp, int on)
  25114. +{
  25115. + return fasync_helper (fd, filp, on, &rtc_async_queue);
  25116. +}
  25117. +
  25118. +static unsigned int rtc_poll(struct file *file, poll_table *wait)
  25119. +{
  25120. + poll_wait (file, &rtc_wait, wait);
  25121. + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
  25122. +}
  25123. +
  25124. +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
  25125. +{
  25126. + return -ESPIPE;
  25127. +}
  25128. +
  25129. +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  25130. +{
  25131. + DECLARE_WAITQUEUE(wait, current);
  25132. + unsigned long data;
  25133. + ssize_t retval;
  25134. +
  25135. + if (count < sizeof(unsigned long))
  25136. + return -EINVAL;
  25137. +
  25138. + add_wait_queue(&rtc_wait, &wait);
  25139. + set_current_state(TASK_INTERRUPTIBLE);
  25140. + for (;;) {
  25141. + spin_lock_irq (&rtc_lock);
  25142. + data = rtc_irq_data;
  25143. + if (data != 0) {
  25144. + rtc_irq_data = 0;
  25145. + break;
  25146. + }
  25147. + spin_unlock_irq (&rtc_lock);
  25148. +
  25149. + if (file->f_flags & O_NONBLOCK) {
  25150. + retval = -EAGAIN;
  25151. + goto out;
  25152. + }
  25153. +
  25154. + if (signal_pending(current)) {
  25155. + retval = -ERESTARTSYS;
  25156. + goto out;
  25157. + }
  25158. +
  25159. + schedule();
  25160. + }
  25161. +
  25162. + spin_unlock_irq (&rtc_lock);
  25163. +
  25164. + data -= 0x100; /* the first IRQ wasn't actually missed */
  25165. +
  25166. + retval = put_user(data, (unsigned long *)buf);
  25167. + if (!retval)
  25168. + retval = sizeof(unsigned long);
  25169. +
  25170. +out:
  25171. + set_current_state(TASK_RUNNING);
  25172. + remove_wait_queue(&rtc_wait, &wait);
  25173. + return retval;
  25174. +}
  25175. +
  25176. +static int rtc_ioctl(struct inode *inode, struct file *file,
  25177. + unsigned int cmd, unsigned long arg)
  25178. +{
  25179. + volatile unsigned int rtcalm = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCALM);
  25180. + volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
  25181. +
  25182. + struct rtc_time tm, tm2;
  25183. + switch (cmd) {
  25184. + case RTC_AIE_OFF:
  25185. + spin_lock_irq(&rtc_lock);
  25186. + __raw_writel(0,rtcalm);
  25187. + rtc_irq_data = 0;
  25188. + spin_unlock_irq(&rtc_lock);
  25189. + return 0;
  25190. + case RTC_AIE_ON:
  25191. + spin_lock_irq(&rtc_lock);
  25192. + __raw_writel(0x7F,rtcalm);
  25193. + rtc_irq_data = 0;
  25194. + spin_unlock_irq(&rtc_lock);
  25195. + return 0;
  25196. + case RTC_UIE_OFF:
  25197. + spin_lock_irq(&rtc_lock);
  25198. + __raw_writel(~TICNT_ENABLE,ticnt);
  25199. + rtc_irq_data = 0;
  25200. + spin_unlock_irq(&rtc_lock);
  25201. + return 0;
  25202. + case RTC_UIE_ON:
  25203. + spin_lock_irq(&rtc_lock);
  25204. + __raw_writel(TICNT_ENABLE|TICNT_PERIOD,ticnt);
  25205. + rtc_irq_data = 0;
  25206. + spin_unlock_irq(&rtc_lock);
  25207. + return 0;
  25208. + case RTC_PIE_OFF:
  25209. + spin_lock_irq(&rtc_lock);
  25210. + // Periodic int not available
  25211. + rtc_irq_data = 0;
  25212. + spin_unlock_irq(&rtc_lock);
  25213. + return 0;
  25214. + case RTC_PIE_ON:
  25215. + spin_lock_irq(&rtc_lock);
  25216. + // Periodic int not available
  25217. + rtc_irq_data = 0;
  25218. + spin_unlock_irq(&rtc_lock);
  25219. + return 0;
  25220. + case RTC_ALM_READ:
  25221. + decodetime(get_alarm_time(),&tm);
  25222. + break;
  25223. + case RTC_ALM_SET:
  25224. + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
  25225. + return -EFAULT;
  25226. + decodetime(get_rtc_time(),&tm);
  25227. + if ((unsigned)tm2.tm_hour < 24)
  25228. + tm.tm_hour = tm2.tm_hour;
  25229. + if ((unsigned)tm2.tm_min < 60)
  25230. + tm.tm_min = tm2.tm_min;
  25231. + if ((unsigned)tm2.tm_sec < 60)
  25232. + tm.tm_sec = tm2.tm_sec;
  25233. +
  25234. + // Munge (as per sa1100)
  25235. + tm.tm_year+=1900;
  25236. + tm.tm_mon+=1;
  25237. +
  25238. + // Set the alarm
  25239. + set_alarm_time(&tm);
  25240. + return 0;
  25241. + case RTC_RD_TIME:
  25242. + decodetime (get_rtc_time(), &tm);
  25243. + break;
  25244. + case RTC_SET_TIME:
  25245. + if (!capable(CAP_SYS_TIME))
  25246. + return -EACCES;
  25247. + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
  25248. + return -EFAULT;
  25249. + tm.tm_year += 1900;
  25250. + if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 ||
  25251. + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
  25252. + (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
  25253. + (unsigned)tm.tm_hour >= 24 ||
  25254. + (unsigned)tm.tm_min >= 60 ||
  25255. + (unsigned)tm.tm_sec >= 60)
  25256. + return -EINVAL;
  25257. + tm.tm_mon +=1; // wierd: same as sa1100 though (gets month wrong otherwise!)
  25258. + set_rtc_time(&tm);
  25259. + return 0;
  25260. + case RTC_IRQP_READ:
  25261. + return put_user(rtc_freq, (unsigned long *)arg);
  25262. + case RTC_IRQP_SET:
  25263. + if (arg < 1 || arg > TIMER_FREQ)
  25264. + return -EINVAL;
  25265. + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
  25266. + return -EACCES;
  25267. + rtc_freq = arg;
  25268. + return 0;
  25269. + case RTC_EPOCH_READ:
  25270. + return put_user (epoch, (unsigned long *)arg);
  25271. + default:
  25272. + return -EINVAL;
  25273. + }
  25274. + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
  25275. +}
  25276. +
  25277. +static struct file_operations rtc_fops = {
  25278. + .owner = THIS_MODULE,
  25279. + .llseek = rtc_llseek,
  25280. + .read = rtc_read,
  25281. + .poll = rtc_poll,
  25282. + .ioctl = rtc_ioctl,
  25283. + .open = rtc_open,
  25284. + .release = rtc_release,
  25285. + .fasync = rtc_fasync,
  25286. +};
  25287. +
  25288. +static struct miscdevice omahartc_miscdev = {
  25289. + .minor = RTC_MINOR,
  25290. + .name = "rtc",
  25291. + .fops = &rtc_fops,
  25292. +};
  25293. +
  25294. +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
  25295. +{
  25296. + char *p = page;
  25297. + int len;
  25298. + struct rtc_time tm;
  25299. +
  25300. + decodetime (get_rtc_time(), &tm);
  25301. + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
  25302. + "rtc_date\t: %04d-%02d-%02d\n"
  25303. + "rtc_epoch\t: %04d\n",
  25304. + tm.tm_hour, tm.tm_min, tm.tm_sec,
  25305. + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
  25306. + decodetime (get_alarm_time(), &tm);
  25307. + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
  25308. + "alrm_date\t: %04d-%02d-%02d\n",
  25309. + tm.tm_hour, tm.tm_min, tm.tm_sec,
  25310. + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
  25311. + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
  25312. +
  25313. + len = (p - page) - off;
  25314. + if (len < 0)
  25315. + len = 0;
  25316. +
  25317. + *eof = (len <= count) ? 1 : 0;
  25318. + *start = page + off;
  25319. +
  25320. + return len;
  25321. +}
  25322. +
  25323. +static int __init rtc_init(void)
  25324. +{
  25325. + volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
  25326. + volatile unsigned int rtccon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCCON);
  25327. + int ret;
  25328. +
  25329. + misc_register (&omahartc_miscdev);
  25330. + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
  25331. +
  25332. + // Enable RTC
  25333. + __raw_writel(RTC_ENABLE,rtccon);
  25334. +
  25335. + // Acquire 1Hz timer
  25336. + ret = request_irq (OMAHA_INT_TICK, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
  25337. + if (ret) {
  25338. + printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_TICK);
  25339. + goto IRQ_TICK_failed;
  25340. + }
  25341. +
  25342. + // Acquire RTC (Alarm interrupt)
  25343. + ret = request_irq (OMAHA_INT_RTC, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
  25344. + if (ret) {
  25345. + printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_RTC);
  25346. + goto IRQ_RTC_failed;
  25347. + }
  25348. +
  25349. + printk (KERN_INFO "Omaha Real Time Clock driver v" DRIVER_VERSION "\n");
  25350. +
  25351. + // Program tick interrupt divisor to generate real 1Hz clock and enable the interrupt
  25352. + __raw_writeb(TICNT_ENABLE|TICNT_PERIOD,ticnt);
  25353. +
  25354. + return 0;
  25355. +
  25356. +IRQ_TICK_failed:
  25357. + free_irq (OMAHA_INT_TICK, NULL);
  25358. +IRQ_RTC_failed:
  25359. + free_irq(OMAHA_INT_RTC, NULL);
  25360. + remove_proc_entry ("driver/rtc", NULL);
  25361. + misc_deregister (&omahartc_miscdev);
  25362. + return ret;
  25363. +}
  25364. +
  25365. +static void __exit rtc_exit(void)
  25366. +{
  25367. + free_irq (OMAHA_INT_TICK, NULL);
  25368. + remove_proc_entry ("driver/rtc", NULL);
  25369. + misc_deregister (&omahartc_miscdev);
  25370. +}
  25371. +
  25372. +module_init(rtc_init);
  25373. +module_exit(rtc_exit);
  25374. +
  25375. +MODULE_AUTHOR("ARM Limited <support@arm.com>");
  25376. +MODULE_DESCRIPTION("Omaha Realtime Clock Driver (RTC)");
  25377. +EXPORT_NO_SYMBOLS;
  25378. diff -urN linux-2.4.26/drivers/char/omaha_wdt.c linux-2.4.26-vrs1/drivers/char/omaha_wdt.c
  25379. --- linux-2.4.26/drivers/char/omaha_wdt.c 1970-01-01 01:00:00.000000000 +0100
  25380. +++ linux-2.4.26-vrs1/drivers/char/omaha_wdt.c 2004-01-14 21:32:25.000000000 +0000
  25381. @@ -0,0 +1,193 @@
  25382. +/*
  25383. + * Watchdog driver for the Omaha
  25384. + * (C) ARM Limited 2002.
  25385. + *
  25386. + * Based on sa1100_wdt.c
  25387. + *
  25388. + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
  25389. + * Based on SoftDog driver by Alan Cox <alan@redhat.com>
  25390. + *
  25391. + * This program is free software; you can redistribute it and/or
  25392. + * modify it under the terms of the GNU General Public License
  25393. + * as published by the Free Software Foundation; either version
  25394. + * 2 of the License, or (at your option) any later version.
  25395. + *
  25396. + * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
  25397. + * warranty for any of this software. This material is provided
  25398. + * "AS-IS" and at no charge.
  25399. + *
  25400. + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
  25401. + *
  25402. + * 27/11/2000 Initial release
  25403. + */
  25404. +
  25405. +#include <linux/module.h>
  25406. +#include <linux/config.h>
  25407. +#include <linux/types.h>
  25408. +#include <linux/kernel.h>
  25409. +#include <linux/fs.h>
  25410. +#include <linux/mm.h>
  25411. +#include <linux/miscdevice.h>
  25412. +#include <linux/watchdog.h>
  25413. +#include <linux/reboot.h>
  25414. +#include <linux/smp_lock.h>
  25415. +#include <linux/init.h>
  25416. +#include <asm/uaccess.h>
  25417. +#include <asm/io.h>
  25418. +#include <asm/hardware.h>
  25419. +#include <asm/bitops.h>
  25420. +
  25421. +#define TIMER_MARGIN 8 /* (secs) Default is 1 minute */
  25422. +#define WT_TPS 7812 /* Watchdog ticks per second. */
  25423. +#define WT_ENABLE 0x21 // Enable bits for watchdog
  25424. +#define WT_CLKSEL_128 0x18 // Select 1/128 divider
  25425. +
  25426. +static int omaha_margin = TIMER_MARGIN; /* in seconds */
  25427. +static int omahawdt_users;
  25428. +static int pre_margin;
  25429. +#ifdef MODULE
  25430. +MODULE_PARM(omaha_margin,"i");
  25431. +#endif
  25432. +
  25433. +/*
  25434. + * Allow only one person to hold it open
  25435. + */
  25436. +
  25437. +static int omahadog_open(struct inode *inode, struct file *file)
  25438. +{
  25439. + volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
  25440. + volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
  25441. + volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
  25442. + unsigned int tmp;
  25443. +
  25444. + if(test_and_set_bit(1,&omahawdt_users))
  25445. + return -EBUSY;
  25446. + MOD_INC_USE_COUNT;
  25447. + /* Activate omaha Watchdog timer */
  25448. +
  25449. + /* Assume that uhal has set up pre-scaler according
  25450. + * to the system clock frequency (don't change it!)
  25451. + *
  25452. + * Ie. all counting occurs at 1MHz / 128 = 7812.5Hz
  25453. + *
  25454. + * Since we have 16-bit counter, maximum period is
  25455. + * 65536/7812.5 = 8.338608 seconds!
  25456. + */
  25457. +
  25458. + pre_margin = WT_TPS * omaha_margin;
  25459. +
  25460. + // Set count to the maximum
  25461. + __raw_writel(pre_margin,wtcnt);
  25462. +
  25463. + // Set the clock division factor
  25464. + tmp = __raw_readl(wtcon);
  25465. + tmp |= WT_CLKSEL_128;
  25466. + __raw_writel(tmp,wtcon);
  25467. +
  25468. + // Program an initial count into WTDAT
  25469. + __raw_writel(0x8000,wtdat);
  25470. +
  25471. + // enable the watchdog
  25472. + tmp = __raw_readl(wtcon);
  25473. + tmp |= WT_ENABLE;
  25474. +
  25475. + __raw_writel(tmp,wtcon);
  25476. +
  25477. + return 0;
  25478. +}
  25479. +
  25480. +static int omahadog_release(struct inode *inode, struct file *file)
  25481. +{
  25482. + volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
  25483. + unsigned int tmp;
  25484. +
  25485. + /*
  25486. + * Shut off the timer.
  25487. + * Lock it in if it's a module and we defined ...NOWAYOUT
  25488. + */
  25489. +#ifndef CONFIG_WATCHDOG_NOWAYOUT
  25490. + tmp = __raw_readl(wtcon);
  25491. + tmp &= ~WT_ENABLE;
  25492. + __raw_writel(tmp,wtcon);
  25493. +#endif
  25494. + omahawdt_users = 0;
  25495. + MOD_DEC_USE_COUNT;
  25496. + return 0;
  25497. +}
  25498. +
  25499. +static ssize_t omahadog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  25500. +{
  25501. + volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
  25502. +
  25503. + /* Can't seek (pwrite) on this device */
  25504. + if (ppos != &file->f_pos)
  25505. + return -ESPIPE;
  25506. +
  25507. + /* Refresh timer. */
  25508. + if(len) {
  25509. + __raw_writel(pre_margin,wtcnt);
  25510. + return 1;
  25511. + }
  25512. + return 0;
  25513. +}
  25514. +
  25515. +static int omahadog_ioctl(struct inode *inode, struct file *file,
  25516. + unsigned int cmd, unsigned long arg)
  25517. +{
  25518. + volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
  25519. + static struct watchdog_info ident = {
  25520. + identity: "omaha Watchdog",
  25521. + };
  25522. +
  25523. + switch(cmd){
  25524. + default:
  25525. + return -ENOIOCTLCMD;
  25526. + case WDIOC_GETSUPPORT:
  25527. + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
  25528. + case WDIOC_GETSTATUS:
  25529. + return put_user(0,(int *)arg);
  25530. + case WDIOC_GETBOOTSTATUS:
  25531. + return 0;
  25532. + case WDIOC_KEEPALIVE:
  25533. + __raw_writel(pre_margin,wtdat);
  25534. + return 0;
  25535. + }
  25536. +}
  25537. +
  25538. +static struct file_operations omahadog_fops=
  25539. +{
  25540. + .owner = THIS_MODULE,
  25541. + .write = omahadog_write,
  25542. + .ioctl = omahadog_ioctl,
  25543. + .open = omahadog_open,
  25544. + .release = omahadog_release,
  25545. +};
  25546. +
  25547. +static struct miscdevice omahadog_miscdev=
  25548. +{
  25549. + .minor = WATCHDOG_MINOR,
  25550. + .name = "omaha watchdog",
  25551. + .fops = &omahadog_fops
  25552. +};
  25553. +
  25554. +static int __init omahadog_init(void)
  25555. +{
  25556. + int ret;
  25557. +
  25558. + ret = misc_register(&omahadog_miscdev);
  25559. +
  25560. + if (ret)
  25561. + return ret;
  25562. +
  25563. + printk("Omaha Watchdog Timer: timer margin %d sec\n", omaha_margin);
  25564. +
  25565. + return 0;
  25566. +}
  25567. +
  25568. +static void __exit omahadog_exit(void)
  25569. +{
  25570. + misc_deregister(&omahadog_miscdev);
  25571. +}
  25572. +
  25573. +module_init(omahadog_init);
  25574. +module_exit(omahadog_exit);
  25575. diff -urN linux-2.4.26/drivers/char/pcmcia/Config.in linux-2.4.26-vrs1/drivers/char/pcmcia/Config.in
  25576. --- linux-2.4.26/drivers/char/pcmcia/Config.in 2002-11-28 23:53:12.000000000 +0000
  25577. +++ linux-2.4.26-vrs1/drivers/char/pcmcia/Config.in 2004-01-14 21:32:25.000000000 +0000
  25578. @@ -5,7 +5,13 @@
  25579. mainmenu_option next_comment
  25580. comment 'PCMCIA character devices'
  25581. -dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_SERIAL
  25582. +if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL_8250" = "y" ]; then
  25583. + dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS y
  25584. +else
  25585. + if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_SERIAL_8250" = "m" ]; then
  25586. + dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS m
  25587. + fi
  25588. +fi
  25589. if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" ]; then
  25590. define_bool CONFIG_PCMCIA_CHRDEV y
  25591. fi
  25592. diff -urN linux-2.4.26/drivers/char/pcmcia/memory_cs.c linux-2.4.26-vrs1/drivers/char/pcmcia/memory_cs.c
  25593. --- linux-2.4.26/drivers/char/pcmcia/memory_cs.c 1970-01-01 01:00:00.000000000 +0100
  25594. +++ linux-2.4.26-vrs1/drivers/char/pcmcia/memory_cs.c 2004-01-14 21:32:25.000000000 +0000
  25595. @@ -0,0 +1,214 @@
  25596. +#include <linux/module.h>
  25597. +#include <linux/kernel.h>
  25598. +#include <linux/init.h>
  25599. +#include <linux/mtd.h>
  25600. +
  25601. +#include <pcmcia/version.h>
  25602. +#include <pcmcia/cs_types.h>
  25603. +#include <pcmcia/cs.h>
  25604. +#include <pcmcia/cistpl.h>
  25605. +#include <pcmcia/ciscode.h>
  25606. +#include <pcmcia/ds.h>
  25607. +#include <pcmcia/cisreg.h>
  25608. +
  25609. +#include <linux/mtd/map.h>
  25610. +#include <linux/mtd/mtd.h>
  25611. +
  25612. +static dev_info_t dev_info = "memory_cs";
  25613. +static dev_link_t *dev_list;
  25614. +
  25615. +struct memcs_dev {
  25616. + dev_link_t link;
  25617. + struct map_info map;
  25618. +};
  25619. +
  25620. +static __u8 mem_cs_read8(struct map_info *map, unsigned long ofs)
  25621. +{
  25622. + return readb(map->map_priv_1 + ofs);
  25623. +}
  25624. +
  25625. +static __u16 mem_cs_read16(struct map_info *map, unsigned long ofs)
  25626. +{
  25627. + return readw(map->map_priv_1 + ofs);
  25628. +}
  25629. +
  25630. +static __u32 mem_cs_read32(struct map_info *map, unsigned long ofs)
  25631. +{
  25632. + return readl(map->map_priv_1 + ofs);
  25633. +}
  25634. +
  25635. +static void mem_cs_copy_from(struct map_info *map, void *to, unsigned long ofs, ssize_t size)
  25636. +{
  25637. + memcpy_fromio(to, map->map_priv_1 + ofs, size);
  25638. +}
  25639. +
  25640. +static void mem_cs_write8(struct map_info *map, __u8 val, unsigned long ofs)
  25641. +{
  25642. + writeb(val, map->map_priv_1 + ofs);
  25643. +}
  25644. +
  25645. +static void mem_cs_write16(struct map_info *map, __u16 val, unsigned long ofs)
  25646. +{
  25647. + writew(val, map->map_priv_1 + ofs);
  25648. +}
  25649. +
  25650. +static void mem_cs_write32(struct map_info *map, __u32 val, unsigned long ofs)
  25651. +{
  25652. + writel(val, map->map_priv_1 + ofs);
  25653. +}
  25654. +
  25655. +static void mem_cs_copy_to(struct map_info *map, unsigned long ofs, const void *to, ssize_t size)
  25656. +{
  25657. + memcpy_toio(map->map_priv_1 + ofs, from, size);
  25658. +}
  25659. +
  25660. +static void mem_cs_release(u_long arg);
  25661. +
  25662. +static void mem_cs_detach(dev_link_t *link)
  25663. +{
  25664. + del_timer(&link->release);
  25665. + if (link->state & DEV_CONFIG) {
  25666. + mem_cs_release((u_long)link);
  25667. + if (link->state & DEV_STALE_CONFIG) {
  25668. + link->state |= DEV_STALE_LINK;
  25669. + return;
  25670. + }
  25671. + }
  25672. +
  25673. + if (link->handle)
  25674. + CardServices(DeregisterClient, link->handle);
  25675. +
  25676. + kfree(link);
  25677. +}
  25678. +
  25679. +static void mem_cs_release(u_long arg)
  25680. +{
  25681. + dev_link_t *link = (dev_link_t *)arg;
  25682. +
  25683. + link->dev = NULL;
  25684. + if (link->win) {
  25685. + CardServices(ReleaseWindow, link->win);
  25686. + }
  25687. + link->state &= ~DEV_CONFIG;
  25688. +
  25689. + if (link->state & DEV_STALE_LINK)
  25690. + mem_cs_detach(link);
  25691. +}
  25692. +
  25693. +static void mem_cs_config(dev_link_t *link)
  25694. +{
  25695. + struct memcs_dev *dev = link->priv;
  25696. + cs_status_t status;
  25697. + win_req_t req;
  25698. +
  25699. + link->state |= DEV_CONFIG;
  25700. +
  25701. + req.Attributes = word_width ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8;
  25702. + req.Base = 0;
  25703. + req.Size = 0;
  25704. + req.AccessSpeed = mem_speed;
  25705. +
  25706. + link->win = (window_handle_t)link->handle;
  25707. +
  25708. + CS_CHECK(RequestWindow, &link->win, &req);
  25709. +
  25710. + CS_CHECK(GetStatus, link->handle, &status);
  25711. +
  25712. + dev->map.buswidth = word_width ? 2 : 1;
  25713. + dev->map.size = req.Size;
  25714. + dev->map.map_priv_1 = ioremap(req.Base, req.Size);
  25715. +}
  25716. +
  25717. +static int
  25718. +mem_cs_event(event_t event, int priority, event_callback_args_t *args)
  25719. +{
  25720. + dev_link_t *link = args->client_data;
  25721. +
  25722. + switch (event) {
  25723. + case CS_EVENT_CARD_REMOVAL:
  25724. + link->state &= ~DEV_PRESENT;
  25725. + if (link->state & DEV_CONFIG)
  25726. + mod_timer(&link->release, jiffies + HZ/20);
  25727. + break;
  25728. +
  25729. + case CS_EVENT_CARD_INSERTION:
  25730. + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
  25731. + mem_cs_config(link);
  25732. + break;
  25733. + }
  25734. + return 0;
  25735. +}
  25736. +
  25737. +static dev_link_t *mem_cs_attach(void)
  25738. +{
  25739. + struct memcs_dev *dev;
  25740. + client_reg_t clnt;
  25741. +
  25742. + dev = kmalloc(sizeof(*dev), GFP_KERNEL);
  25743. + if (dev) {
  25744. + memset(dev, 0, sizeof(*dev));
  25745. +
  25746. + dev->map.read8 = mem_cs_read8;
  25747. + dev->map.read16 = mem_cs_read16;
  25748. + dev->map.read32 = mem_cs_read32;
  25749. + dev->map.copy_from = mem_cs_copy_from;
  25750. + dev->map.write8 = mem_cs_write8;
  25751. + dev->map.write16 = mem_cs_write16;
  25752. + dev->map.write32 = mem_cs_write32;
  25753. + dev->map.copy_to = mem_cs_copy_to;
  25754. +
  25755. + dev->link.release.function = &mem_cs_release;
  25756. + dev->link.release.data = (u_long)link;
  25757. + dev->link.priv = dev;
  25758. +
  25759. + dev->link.next = dev_list;
  25760. + dev_list = &dev->link;
  25761. +
  25762. + clnt.dev_info = &dev_info;
  25763. + clnt.Attributes = INOF_IO_CLIENT | INFO_CARD_SHARE;
  25764. + clnt.EventMask =
  25765. + CS_EVENT_WRITE_PROTECT | CS_EVENT_CARD_INSERTION |
  25766. + CS_EVENT_CARD_REMOVAL | CS_EVENT_BATTERY_DEAD |
  25767. + CS_EVENT_BATTERY_LOW;
  25768. +
  25769. + clnt.event_handler = &mem_cs_event;
  25770. + clnt.Version = 0x0210;
  25771. + clnt.event_callback_args.client_data = &dev->link;
  25772. +
  25773. + ret = CardServices(RegisterClient, &dev->link.handle, &clnt);
  25774. + if (ret != CS_SUCCESS) {
  25775. + error_info_t err = { RegisterClient, ret };
  25776. + CardServices(ReportError, dev->link.handle, &err);
  25777. + mem_cs_detach(&dev->link);
  25778. + dev = NULL;
  25779. + }
  25780. + }
  25781. +
  25782. + return &dev->link;
  25783. +}
  25784. +
  25785. +static int __init mem_cs_init(void)
  25786. +{
  25787. + servinfo_t serv;
  25788. +
  25789. + CardServices(GetCardServicesInfo, &serv);
  25790. + if (serv.Revision != CS_RELEASE_CODE) {
  25791. + printk(KERN_NOTICE "memory_cs: Card services release "
  25792. + "does not match\n");
  25793. + return -ENXIO;
  25794. + }
  25795. + register_pccard_driver(&dev_info, mem_cs_attach, mem_cs_detach);
  25796. + return 0;
  25797. +}
  25798. +
  25799. +static void __exit mem_cs_exit(void)
  25800. +{
  25801. + unregister_pccard_driver(&dev_info);
  25802. + while (dev_list != NULL)
  25803. + memory_detach(dev_list);
  25804. +}
  25805. +
  25806. +module_init(mem_cs_init);
  25807. +module_exit(mem_cs_exit);
  25808. +
  25809. +MODULE_LICENSE("GPL");
  25810. diff -urN linux-2.4.26/drivers/char/sa1100-rtc.c linux-2.4.26-vrs1/drivers/char/sa1100-rtc.c
  25811. --- linux-2.4.26/drivers/char/sa1100-rtc.c 1970-01-01 01:00:00.000000000 +0100
  25812. +++ linux-2.4.26-vrs1/drivers/char/sa1100-rtc.c 2004-01-14 21:32:25.000000000 +0000
  25813. @@ -0,0 +1,474 @@
  25814. +/*
  25815. + * Real Time Clock interface for Linux on StrongARM SA1100
  25816. + *
  25817. + * Copyright (c) 2000 Nils Faerber
  25818. + *
  25819. + * Based on rtc.c by Paul Gortmaker
  25820. + * Date/time conversion routines taken from arch/arm/kernel/time.c
  25821. + * by Linus Torvalds and Russel King
  25822. + * and the GNU C Library
  25823. + * ( ... I love the GPL ... just take what you need! ;)
  25824. + *
  25825. + * This program is free software; you can redistribute it and/or
  25826. + * modify it under the terms of the GNU General Public License
  25827. + * as published by the Free Software Foundation; either version
  25828. + * 2 of the License, or (at your option) any later version.
  25829. + *
  25830. + * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
  25831. + * - added periodic timer capability using OSMR1
  25832. + * - flag compatibility with other RTC chips
  25833. + * - permission checks for ioctls
  25834. + * - major cleanup, partial rewrite
  25835. + *
  25836. + * 0.03 2001-03-07 CIH <cih@coventive.com>
  25837. + * - Modify the bug setups RTC clock.
  25838. + *
  25839. + * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
  25840. + * - removed mktime(), added alarm irq clear
  25841. + *
  25842. + * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
  25843. + * - initial release
  25844. + */
  25845. +
  25846. +#include <linux/module.h>
  25847. +#include <linux/fs.h>
  25848. +#include <linux/miscdevice.h>
  25849. +#include <linux/string.h>
  25850. +#include <linux/init.h>
  25851. +#include <linux/poll.h>
  25852. +#include <linux/proc_fs.h>
  25853. +#include <asm/bitops.h>
  25854. +#include <asm/hardware.h>
  25855. +#include <asm/irq.h>
  25856. +#include <linux/rtc.h>
  25857. +
  25858. +#define DRIVER_VERSION "1.00"
  25859. +
  25860. +#define TIMER_FREQ 3686400
  25861. +
  25862. +#define RTC_DEF_DIVIDER 32768 - 1
  25863. +#define RTC_DEF_TRIM 0
  25864. +
  25865. +/* Those are the bits from a classic RTC we want to mimic */
  25866. +#define RTC_IRQF 0x80 /* any of the following 3 is active */
  25867. +#define RTC_PF 0x40
  25868. +#define RTC_AF 0x20
  25869. +#define RTC_UF 0x10
  25870. +
  25871. +static unsigned long rtc_status;
  25872. +static unsigned long rtc_irq_data;
  25873. +static unsigned long rtc_freq = 1024;
  25874. +
  25875. +static struct fasync_struct *rtc_async_queue;
  25876. +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
  25877. +
  25878. +extern spinlock_t rtc_lock;
  25879. +
  25880. +static const unsigned char days_in_mo[] =
  25881. + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  25882. +
  25883. +#define is_leap(year) \
  25884. + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  25885. +
  25886. +/*
  25887. + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
  25888. + */
  25889. +
  25890. +static void decodetime (unsigned long t, struct rtc_time *tval)
  25891. +{
  25892. + long days, month, year, rem;
  25893. +
  25894. + days = t / 86400;
  25895. + rem = t % 86400;
  25896. + tval->tm_hour = rem / 3600;
  25897. + rem %= 3600;
  25898. + tval->tm_min = rem / 60;
  25899. + tval->tm_sec = rem % 60;
  25900. + tval->tm_wday = (4 + days) % 7;
  25901. +
  25902. +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
  25903. +
  25904. + year = 1970 + days / 365;
  25905. + days -= ((year - 1970) * 365
  25906. + + LEAPS_THRU_END_OF (year - 1)
  25907. + - LEAPS_THRU_END_OF (1970 - 1));
  25908. + if (days < 0) {
  25909. + year -= 1;
  25910. + days += 365 + is_leap(year);
  25911. + }
  25912. + tval->tm_year = year - 1900;
  25913. + tval->tm_yday = days + 1;
  25914. +
  25915. + month = 0;
  25916. + if (days >= 31) {
  25917. + days -= 31;
  25918. + month++;
  25919. + if (days >= (28 + is_leap(year))) {
  25920. + days -= (28 + is_leap(year));
  25921. + month++;
  25922. + while (days >= days_in_mo[month]) {
  25923. + days -= days_in_mo[month];
  25924. + month++;
  25925. + }
  25926. + }
  25927. + }
  25928. + tval->tm_mon = month;
  25929. + tval->tm_mday = days + 1;
  25930. +}
  25931. +
  25932. +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  25933. +{
  25934. + unsigned int rtsr = RTSR;
  25935. +
  25936. + /* clear interrupt sources */
  25937. + RTSR = 0;
  25938. + RTSR = (RTSR_AL|RTSR_HZ);
  25939. +
  25940. + /* clear alarm interrupt if it has occurred */
  25941. + if (rtsr & RTSR_AL)
  25942. + rtsr &= ~RTSR_ALE;
  25943. + RTSR = rtsr & (RTSR_ALE|RTSR_HZE);
  25944. +
  25945. + /* update irq data & counter */
  25946. + if (rtsr & RTSR_AL)
  25947. + rtc_irq_data |= (RTC_AF|RTC_IRQF);
  25948. + if (rtsr & RTSR_HZ)
  25949. + rtc_irq_data |= (RTC_UF|RTC_IRQF);
  25950. + rtc_irq_data += 0x100;
  25951. +
  25952. + /* wake up waiting process */
  25953. + wake_up_interruptible(&rtc_wait);
  25954. + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
  25955. +}
  25956. +
  25957. +static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  25958. +{
  25959. + /*
  25960. + * If we match for the first time, the periodic interrupt flag won't
  25961. + * be set. If it is, then we did wrap around (very unlikely but
  25962. + * still possible) and compute the amount of missed periods.
  25963. + * The match reg is updated only when the data is actually retrieved
  25964. + * to avoid unnecessary interrupts.
  25965. + */
  25966. + OSSR = OSSR_M1; /* clear match on timer1 */
  25967. + if (rtc_irq_data & RTC_PF) {
  25968. + rtc_irq_data += (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))) << 8;
  25969. + } else {
  25970. + rtc_irq_data += (0x100|RTC_PF|RTC_IRQF);
  25971. + }
  25972. +
  25973. + wake_up_interruptible(&rtc_wait);
  25974. + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
  25975. +}
  25976. +
  25977. +static int rtc_open(struct inode *inode, struct file *file)
  25978. +{
  25979. + if (test_and_set_bit (1, &rtc_status))
  25980. + return -EBUSY;
  25981. + rtc_irq_data = 0;
  25982. + return 0;
  25983. +}
  25984. +
  25985. +static int rtc_release(struct inode *inode, struct file *file)
  25986. +{
  25987. + spin_lock_irq (&rtc_lock);
  25988. + RTSR = 0;
  25989. + RTSR = (RTSR_AL|RTSR_HZ);
  25990. + OIER &= ~OIER_E1;
  25991. + OSSR = OSSR_M1;
  25992. + spin_unlock_irq (&rtc_lock);
  25993. + rtc_status = 0;
  25994. + return 0;
  25995. +}
  25996. +
  25997. +static int rtc_fasync (int fd, struct file *filp, int on)
  25998. +{
  25999. + return fasync_helper (fd, filp, on, &rtc_async_queue);
  26000. +}
  26001. +
  26002. +static unsigned int rtc_poll(struct file *file, poll_table *wait)
  26003. +{
  26004. + poll_wait (file, &rtc_wait, wait);
  26005. + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
  26006. +}
  26007. +
  26008. +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
  26009. +{
  26010. + return -ESPIPE;
  26011. +}
  26012. +
  26013. +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  26014. +{
  26015. + DECLARE_WAITQUEUE(wait, current);
  26016. + unsigned long data;
  26017. + ssize_t retval;
  26018. +
  26019. + if (count < sizeof(unsigned long))
  26020. + return -EINVAL;
  26021. +
  26022. + add_wait_queue(&rtc_wait, &wait);
  26023. + set_current_state(TASK_INTERRUPTIBLE);
  26024. + for (;;) {
  26025. + spin_lock_irq (&rtc_lock);
  26026. + data = rtc_irq_data;
  26027. + if (data != 0) {
  26028. + rtc_irq_data = 0;
  26029. + break;
  26030. + }
  26031. + spin_unlock_irq (&rtc_lock);
  26032. +
  26033. + if (file->f_flags & O_NONBLOCK) {
  26034. + retval = -EAGAIN;
  26035. + goto out;
  26036. + }
  26037. +
  26038. + if (signal_pending(current)) {
  26039. + retval = -ERESTARTSYS;
  26040. + goto out;
  26041. + }
  26042. +
  26043. + schedule();
  26044. + }
  26045. +
  26046. + if (data & RTC_PF) {
  26047. + /* interpolate missed periods and set match for the next one */
  26048. + unsigned long period = TIMER_FREQ/rtc_freq;
  26049. + unsigned long oscr = OSCR;
  26050. + unsigned long osmr1 = OSMR1;
  26051. + unsigned long missed = (oscr - osmr1)/period;
  26052. + data += missed << 8;
  26053. + OSSR = OSSR_M1; /* clear match on timer 1 */
  26054. + OSMR1 = osmr1 + (missed + 1)*period;
  26055. + /* ensure we didn't miss another match in the mean time */
  26056. + while( (signed long)((osmr1 = OSMR1) - OSCR) <= 0 ) {
  26057. + data += 0x100;
  26058. + OSSR = OSSR_M1; /* clear match on timer 1 */
  26059. + OSMR1 = osmr1 + period;
  26060. + }
  26061. + }
  26062. + spin_unlock_irq (&rtc_lock);
  26063. +
  26064. + data -= 0x100; /* the first IRQ wasn't actually missed */
  26065. +
  26066. + retval = put_user(data, (unsigned long *)buf);
  26067. + if (!retval)
  26068. + retval = sizeof(unsigned long);
  26069. +
  26070. +out:
  26071. + set_current_state(TASK_RUNNING);
  26072. + remove_wait_queue(&rtc_wait, &wait);
  26073. + return retval;
  26074. +}
  26075. +
  26076. +static int rtc_ioctl(struct inode *inode, struct file *file,
  26077. + unsigned int cmd, unsigned long arg)
  26078. +{
  26079. + struct rtc_time tm, tm2;
  26080. +
  26081. + switch (cmd) {
  26082. + case RTC_AIE_OFF:
  26083. + spin_lock_irq(&rtc_lock);
  26084. + RTSR &= ~RTSR_ALE;
  26085. + rtc_irq_data = 0;
  26086. + spin_unlock_irq(&rtc_lock);
  26087. + return 0;
  26088. + case RTC_AIE_ON:
  26089. + spin_lock_irq(&rtc_lock);
  26090. + RTSR |= RTSR_ALE;
  26091. + rtc_irq_data = 0;
  26092. + spin_unlock_irq(&rtc_lock);
  26093. + return 0;
  26094. + case RTC_UIE_OFF:
  26095. + spin_lock_irq(&rtc_lock);
  26096. + RTSR &= ~RTSR_HZE;
  26097. + rtc_irq_data = 0;
  26098. + spin_unlock_irq(&rtc_lock);
  26099. + return 0;
  26100. + case RTC_UIE_ON:
  26101. + spin_lock_irq(&rtc_lock);
  26102. + RTSR |= RTSR_HZE;
  26103. + rtc_irq_data = 0;
  26104. + spin_unlock_irq(&rtc_lock);
  26105. + return 0;
  26106. + case RTC_PIE_OFF:
  26107. + spin_lock_irq(&rtc_lock);
  26108. + OIER &= ~OIER_E1;
  26109. + rtc_irq_data = 0;
  26110. + spin_unlock_irq(&rtc_lock);
  26111. + return 0;
  26112. + case RTC_PIE_ON:
  26113. + if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
  26114. + return -EACCES;
  26115. + spin_lock_irq(&rtc_lock);
  26116. + OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
  26117. + OIER |= OIER_E1;
  26118. + rtc_irq_data = 0;
  26119. + spin_unlock_irq(&rtc_lock);
  26120. + return 0;
  26121. + case RTC_ALM_READ:
  26122. + decodetime (RTAR, &tm);
  26123. + break;
  26124. + case RTC_ALM_SET:
  26125. + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
  26126. + return -EFAULT;
  26127. + decodetime (RCNR, &tm);
  26128. + if ((unsigned)tm2.tm_hour < 24)
  26129. + tm.tm_hour = tm2.tm_hour;
  26130. + if ((unsigned)tm2.tm_min < 60)
  26131. + tm.tm_min = tm2.tm_min;
  26132. + if ((unsigned)tm2.tm_sec < 60)
  26133. + tm.tm_sec = tm2.tm_sec;
  26134. + RTAR = mktime ( tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  26135. + tm.tm_hour, tm.tm_min, tm.tm_sec);
  26136. + return 0;
  26137. + case RTC_RD_TIME:
  26138. + decodetime (RCNR, &tm);
  26139. + break;
  26140. + case RTC_SET_TIME:
  26141. + if (!capable(CAP_SYS_TIME))
  26142. + return -EACCES;
  26143. + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
  26144. + return -EFAULT;
  26145. + tm.tm_year += 1900;
  26146. + if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 ||
  26147. + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
  26148. + (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
  26149. + (unsigned)tm.tm_hour >= 24 ||
  26150. + (unsigned)tm.tm_min >= 60 ||
  26151. + (unsigned)tm.tm_sec >= 60)
  26152. + return -EINVAL;
  26153. + RCNR = mktime ( tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
  26154. + tm.tm_hour, tm.tm_min, tm.tm_sec);
  26155. + return 0;
  26156. + case RTC_IRQP_READ:
  26157. + return put_user(rtc_freq, (unsigned long *)arg);
  26158. + case RTC_IRQP_SET:
  26159. + if (arg < 1 || arg > TIMER_FREQ)
  26160. + return -EINVAL;
  26161. + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
  26162. + return -EACCES;
  26163. + rtc_freq = arg;
  26164. + return 0;
  26165. + case RTC_EPOCH_READ:
  26166. + return put_user (1970, (unsigned long *)arg);
  26167. + default:
  26168. + return -EINVAL;
  26169. + }
  26170. + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
  26171. +}
  26172. +
  26173. +static struct file_operations rtc_fops = {
  26174. + owner: THIS_MODULE,
  26175. + llseek: rtc_llseek,
  26176. + read: rtc_read,
  26177. + poll: rtc_poll,
  26178. + ioctl: rtc_ioctl,
  26179. + open: rtc_open,
  26180. + release: rtc_release,
  26181. + fasync: rtc_fasync,
  26182. +};
  26183. +
  26184. +static struct miscdevice sa1100rtc_miscdev = {
  26185. + RTC_MINOR,
  26186. + "rtc",
  26187. + &rtc_fops
  26188. +};
  26189. +
  26190. +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
  26191. +{
  26192. + char *p = page;
  26193. + int len;
  26194. + struct rtc_time tm;
  26195. +
  26196. + decodetime (RCNR, &tm);
  26197. + p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
  26198. + "rtc_date\t: %04d-%02d-%02d\n"
  26199. + "rtc_epoch\t: %04d\n",
  26200. + tm.tm_hour, tm.tm_min, tm.tm_sec,
  26201. + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1970);
  26202. + decodetime (RTAR, &tm);
  26203. + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
  26204. + "alrm_date\t: %04d-%02d-%02d\n",
  26205. + tm.tm_hour, tm.tm_min, tm.tm_sec,
  26206. + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
  26207. + p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR);
  26208. + p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" );
  26209. + p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no");
  26210. + p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no");
  26211. + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
  26212. +
  26213. + len = (p - page) - off;
  26214. + if (len < 0)
  26215. + len = 0;
  26216. +
  26217. + *eof = (len <= count) ? 1 : 0;
  26218. + *start = page + off;
  26219. +
  26220. + return len;
  26221. +}
  26222. +
  26223. +static int __init rtc_init(void)
  26224. +{
  26225. + int ret;
  26226. +
  26227. + misc_register (&sa1100rtc_miscdev);
  26228. + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
  26229. + ret = request_irq (IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
  26230. + if (ret) {
  26231. + printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTC1Hz);
  26232. + goto IRQ_RTC1Hz_failed;
  26233. + }
  26234. + ret = request_irq (IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
  26235. + if (ret) {
  26236. + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTCAlrm);
  26237. + goto IRQ_RTCAlrm_failed;
  26238. + }
  26239. + ret = request_irq (IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL);
  26240. + if (ret) {
  26241. + printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_OST1);
  26242. + goto IRQ_OST1_failed;
  26243. + }
  26244. +
  26245. + printk (KERN_INFO "SA1100 Real Time Clock driver v" DRIVER_VERSION "\n");
  26246. +
  26247. + /*
  26248. + * According to the manual we should be able to let RTTR be zero
  26249. + * and then a default diviser for a 32.768KHz clock is used.
  26250. + * Apparently this doesn't work, at least for my SA1110 rev 5.
  26251. + * If the clock divider is uninitialized then reset it to the
  26252. + * default value to get the 1Hz clock.
  26253. + */
  26254. + if (RTTR == 0) {
  26255. + RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
  26256. + printk (KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
  26257. + /* The current RTC value probably doesn't make sense either */
  26258. + RCNR = 0;
  26259. + }
  26260. +
  26261. + return 0;
  26262. +
  26263. +IRQ_OST1_failed:
  26264. + free_irq (IRQ_RTCAlrm, NULL);
  26265. +IRQ_RTCAlrm_failed:
  26266. + free_irq (IRQ_RTC1Hz, NULL);
  26267. +IRQ_RTC1Hz_failed:
  26268. + remove_proc_entry ("driver/rtc", NULL);
  26269. + misc_deregister (&sa1100rtc_miscdev);
  26270. + return ret;
  26271. +}
  26272. +
  26273. +static void __exit rtc_exit(void)
  26274. +{
  26275. + free_irq (IRQ_OST1, NULL);
  26276. + free_irq (IRQ_RTCAlrm, NULL);
  26277. + free_irq (IRQ_RTC1Hz, NULL);
  26278. + remove_proc_entry ("driver/rtc", NULL);
  26279. + misc_deregister (&sa1100rtc_miscdev);
  26280. +}
  26281. +
  26282. +module_init(rtc_init);
  26283. +module_exit(rtc_exit);
  26284. +
  26285. +MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
  26286. +MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
  26287. +EXPORT_NO_SYMBOLS;
  26288. diff -urN linux-2.4.26/drivers/char/sa1100_wdt.c linux-2.4.26-vrs1/drivers/char/sa1100_wdt.c
  26289. --- linux-2.4.26/drivers/char/sa1100_wdt.c 1970-01-01 01:00:00.000000000 +0100
  26290. +++ linux-2.4.26-vrs1/drivers/char/sa1100_wdt.c 2004-04-10 12:04:15.000000000 +0100
  26291. @@ -0,0 +1,150 @@
  26292. +/*
  26293. + * Watchdog driver for the SA11x0
  26294. + *
  26295. + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
  26296. + * Based on SoftDog driver by Alan Cox <alan@redhat.com>
  26297. + *
  26298. + * This program is free software; you can redistribute it and/or
  26299. + * modify it under the terms of the GNU General Public License
  26300. + * as published by the Free Software Foundation; either version
  26301. + * 2 of the License, or (at your option) any later version.
  26302. + *
  26303. + * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
  26304. + * warranty for any of this software. This material is provided
  26305. + * "AS-IS" and at no charge.
  26306. + *
  26307. + * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
  26308. + *
  26309. + * 27/11/2000 Initial release
  26310. + */
  26311. +
  26312. +#include <linux/module.h>
  26313. +#include <linux/config.h>
  26314. +#include <linux/types.h>
  26315. +#include <linux/kernel.h>
  26316. +#include <linux/fs.h>
  26317. +#include <linux/mm.h>
  26318. +#include <linux/miscdevice.h>
  26319. +#include <linux/watchdog.h>
  26320. +#include <linux/reboot.h>
  26321. +#include <linux/smp_lock.h>
  26322. +#include <linux/init.h>
  26323. +#include <asm/uaccess.h>
  26324. +#include <asm/hardware.h>
  26325. +#include <asm/bitops.h>
  26326. +
  26327. +#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
  26328. +
  26329. +static int sa1100_margin = TIMER_MARGIN; /* in seconds */
  26330. +static int sa1100wdt_users;
  26331. +static int pre_margin;
  26332. +#ifdef MODULE
  26333. +MODULE_PARM(sa1100_margin,"i");
  26334. +#endif
  26335. +
  26336. +/*
  26337. + * Allow only one person to hold it open
  26338. + */
  26339. +
  26340. +static int sa1100dog_open(struct inode *inode, struct file *file)
  26341. +{
  26342. + if(test_and_set_bit(1,&sa1100wdt_users))
  26343. + return -EBUSY;
  26344. + MOD_INC_USE_COUNT;
  26345. + /* Activate SA1100 Watchdog timer */
  26346. + pre_margin=3686400 * sa1100_margin;
  26347. + OSMR3 = OSCR + pre_margin;
  26348. + OSSR = OSSR_M3;
  26349. + OWER = OWER_WME;
  26350. + OIER |= OIER_E3;
  26351. + return 0;
  26352. +}
  26353. +
  26354. +static int sa1100dog_release(struct inode *inode, struct file *file)
  26355. +{
  26356. + /*
  26357. + * Shut off the timer.
  26358. + * Lock it in if it's a module and we defined ...NOWAYOUT
  26359. + */
  26360. + OSMR3 = OSCR + pre_margin;
  26361. +#ifndef CONFIG_WATCHDOG_NOWAYOUT
  26362. + OIER &= ~OIER_E3;
  26363. +#endif
  26364. + sa1100wdt_users = 0;
  26365. + MOD_DEC_USE_COUNT;
  26366. + return 0;
  26367. +}
  26368. +
  26369. +static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  26370. +{
  26371. + /* Can't seek (pwrite) on this device */
  26372. + if (ppos != &file->f_pos)
  26373. + return -ESPIPE;
  26374. +
  26375. + /* Refresh OSMR3 timer. */
  26376. + if(len) {
  26377. + OSMR3 = OSCR + pre_margin;
  26378. + return 1;
  26379. + }
  26380. + return 0;
  26381. +}
  26382. +
  26383. +static int sa1100dog_ioctl(struct inode *inode, struct file *file,
  26384. + unsigned int cmd, unsigned long arg)
  26385. +{
  26386. + static struct watchdog_info ident = {
  26387. + identity: "SA1100 Watchdog",
  26388. + };
  26389. +
  26390. + switch(cmd){
  26391. + default:
  26392. + return -ENOIOCTLCMD;
  26393. + case WDIOC_GETSUPPORT:
  26394. + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
  26395. + case WDIOC_GETSTATUS:
  26396. + return put_user(0,(int *)arg);
  26397. + case WDIOC_GETBOOTSTATUS:
  26398. + return put_user((RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0, (int *)arg);
  26399. + case WDIOC_KEEPALIVE:
  26400. + OSMR3 = OSCR + pre_margin;
  26401. + return 0;
  26402. + }
  26403. +}
  26404. +
  26405. +static struct file_operations sa1100dog_fops=
  26406. +{
  26407. + owner: THIS_MODULE,
  26408. + write: sa1100dog_write,
  26409. + ioctl: sa1100dog_ioctl,
  26410. + open: sa1100dog_open,
  26411. + release: sa1100dog_release,
  26412. +};
  26413. +
  26414. +static struct miscdevice sa1100dog_miscdev=
  26415. +{
  26416. + WATCHDOG_MINOR,
  26417. + "SA1100 watchdog",
  26418. + &sa1100dog_fops
  26419. +};
  26420. +
  26421. +static int __init sa1100dog_init(void)
  26422. +{
  26423. + int ret;
  26424. +
  26425. + ret = misc_register(&sa1100dog_miscdev);
  26426. +
  26427. + if (ret)
  26428. + return ret;
  26429. +
  26430. + printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
  26431. +
  26432. + return 0;
  26433. +}
  26434. +
  26435. +static void __exit sa1100dog_exit(void)
  26436. +{
  26437. + misc_deregister(&sa1100dog_miscdev);
  26438. +}
  26439. +
  26440. +module_init(sa1100dog_init);
  26441. +module_exit(sa1100dog_exit);
  26442. diff -urN linux-2.4.26/drivers/char/sa1111_keyb.c linux-2.4.26-vrs1/drivers/char/sa1111_keyb.c
  26443. --- linux-2.4.26/drivers/char/sa1111_keyb.c 1970-01-01 01:00:00.000000000 +0100
  26444. +++ linux-2.4.26-vrs1/drivers/char/sa1111_keyb.c 2004-01-14 21:32:25.000000000 +0000
  26445. @@ -0,0 +1,1153 @@
  26446. +/*
  26447. + * SA1111 PS/2 keyboard/mouse driver
  26448. + *
  26449. + * 2000 by VASARA RESEARCH INC.
  26450. + *
  26451. + * Changelog:
  26452. + * Jun.xx,2000: Kunihiko IMAI <imai@vasara.co.jp>
  26453. + * Port to 2.4.0test1-ac19-rmk1-np1
  26454. + * Apr.17,2000: Takafumi Kawana <kawana@pro.or.jp>
  26455. + * Internal Release for XP860
  26456. + *
  26457. + *
  26458. + * This driver is based on linux/drivers/char/pc_keyb.c
  26459. + * Original declaration follows:
  26460. +
  26461. + *
  26462. + * linux/drivers/char/pc_keyb.c
  26463. + *
  26464. + * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
  26465. + * See keyboard.c for the whole history.
  26466. + *
  26467. + * Major cleanup by Martin Mares, May 1997
  26468. + *
  26469. + * Combined the keyboard and PS/2 mouse handling into one file,
  26470. + * because they share the same hardware.
  26471. + * Johan Myreen <jem@iki.fi> 1998-10-08.
  26472. + *
  26473. + * Code fixes to handle mouse ACKs properly.
  26474. + * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
  26475. + *
  26476. + */
  26477. +#include <linux/config.h>
  26478. +#include <linux/spinlock.h>
  26479. +#include <linux/sched.h>
  26480. +#include <linux/interrupt.h>
  26481. +#include <linux/tty.h>
  26482. +#include <linux/mm.h>
  26483. +#include <linux/signal.h>
  26484. +#include <linux/init.h>
  26485. +#include <linux/kbd_ll.h>
  26486. +#include <linux/delay.h>
  26487. +#include <linux/random.h>
  26488. +#include <linux/poll.h>
  26489. +#include <linux/miscdevice.h>
  26490. +#include <linux/slab.h>
  26491. +#include <linux/kbd_kern.h>
  26492. +#include <linux/ioport.h>
  26493. +
  26494. +#include <asm/hardware.h>
  26495. +#include <asm/bitops.h>
  26496. +#include <asm/uaccess.h>
  26497. +#include <asm/irq.h>
  26498. +#include <asm/system.h>
  26499. +
  26500. +#include <asm/io.h>
  26501. +
  26502. +/* Some configuration switches are present in the include file... */
  26503. +
  26504. +#include <linux/pc_keyb.h>
  26505. +#include <asm/keyboard.h>
  26506. +#include <asm/hardware/sa1111.h>
  26507. +
  26508. +#define KBD_STAT_RXB (1<<4)
  26509. +#define KBD_STAT_RXF (1<<5)
  26510. +#define KBD_STAT_TXB (1<<6)
  26511. +#define KBD_STAT_TXE (1<<7)
  26512. +#define KBD_STAT_STP (1<<8)
  26513. +
  26514. +#define MSE_STAT_RXB (1<<4)
  26515. +#define MSE_STAT_RXF (1<<5)
  26516. +#define MSE_STAT_TXB (1<<6)
  26517. +#define MSE_STAT_TXE (1<<7)
  26518. +#define MSE_STAT_STP (1<<8)
  26519. +
  26520. +/* Simple translation table for the SysRq keys */
  26521. +
  26522. +#ifdef CONFIG_MAGIC_SYSRQ
  26523. +unsigned char sa1111_sysrq_xlate[128] = "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
  26524. + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
  26525. + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
  26526. + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
  26527. + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
  26528. + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
  26529. + "\r\000/"; /* 0x60 - 0x6f */
  26530. +#endif
  26531. +
  26532. +// static void kbd_write_command_w(int data);
  26533. +static void kbd_write_output_w(int data);
  26534. +
  26535. +spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
  26536. +static void handle_kbd_event(void);
  26537. +
  26538. +/* used only by send_data - set by keyboard_interrupt */
  26539. +static volatile unsigned char reply_expected = 0;
  26540. +static volatile unsigned char acknowledge = 0;
  26541. +static volatile unsigned char resend = 0;
  26542. +
  26543. +
  26544. +#if defined CONFIG_PSMOUSE
  26545. +/*
  26546. + * PS/2 Auxiliary Device
  26547. + */
  26548. +
  26549. +static int __init psaux_init(void);
  26550. +
  26551. +static struct aux_queue *queue; /* Mouse data buffer. */
  26552. +static int aux_count = 0;
  26553. +/* used when we send commands to the mouse that expect an ACK. */
  26554. +static unsigned char mouse_reply_expected = 0;
  26555. +
  26556. +#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
  26557. +#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
  26558. +
  26559. +#define MAX_RETRIES 60 /* some aux operations take long time */
  26560. +#endif /* CONFIG_PSMOUSE */
  26561. +
  26562. +/*
  26563. + * Wait for keyboard controller input buffer to drain.
  26564. + *
  26565. + * Don't use 'jiffies' so that we don't depend on
  26566. + * interrupts..
  26567. + *
  26568. + * Quote from PS/2 System Reference Manual:
  26569. + *
  26570. + * "Address hex 0060 and address hex 0064 should be written only when
  26571. + * the input-buffer-full bit and output-buffer-full bit in the
  26572. + * Controller Status register are set 0."
  26573. + */
  26574. +
  26575. +static void kb_wait(void)
  26576. +{
  26577. + unsigned long timeout = KBC_TIMEOUT;
  26578. +
  26579. + do {
  26580. + /*
  26581. + * "handle_kbd_event()" will handle any incoming events
  26582. + * while we wait - keypresses or mouse movement.
  26583. + */
  26584. + handle_kbd_event();
  26585. + if (KBDSTAT & KBD_STAT_TXE)
  26586. + return;
  26587. + mdelay(1);
  26588. + timeout--;
  26589. + }
  26590. + while (timeout);
  26591. +#ifdef KBD_REPORT_TIMEOUTS
  26592. + printk(KERN_WARNING "Keyboard timed out[1]\n");
  26593. +#endif
  26594. +}
  26595. +
  26596. +/*
  26597. + * Translation of escaped scancodes to keycodes.
  26598. + * This is now user-settable.
  26599. + * The keycodes 1-88,96-111,119 are fairly standard, and
  26600. + * should probably not be changed - changing might confuse X.
  26601. + * X also interprets scancode 0x5d (KEY_Begin).
  26602. + *
  26603. + * For 1-88 keycode equals scancode.
  26604. + */
  26605. +
  26606. +#define E0_KPENTER 96
  26607. +#define E0_RCTRL 97
  26608. +#define E0_KPSLASH 98
  26609. +#define E0_PRSCR 99
  26610. +#define E0_RALT 100
  26611. +#define E0_BREAK 101 /* (control-pause) */
  26612. +#define E0_HOME 102
  26613. +#define E0_UP 103
  26614. +#define E0_PGUP 104
  26615. +#define E0_LEFT 105
  26616. +#define E0_RIGHT 106
  26617. +#define E0_END 107
  26618. +#define E0_DOWN 108
  26619. +#define E0_PGDN 109
  26620. +#define E0_INS 110
  26621. +#define E0_DEL 111
  26622. +
  26623. +/* for USB 106 keyboard */
  26624. +#define E0_YEN 124
  26625. +#define E0_BACKSLASH 89
  26626. +
  26627. +
  26628. +#define E1_PAUSE 119
  26629. +
  26630. +/*
  26631. + * The keycodes below are randomly located in 89-95,112-118,120-127.
  26632. + * They could be thrown away (and all occurrences below replaced by 0),
  26633. + * but that would force many users to use the `setkeycodes' utility, where
  26634. + * they needed not before. It does not matter that there are duplicates, as
  26635. + * long as no duplication occurs for any single keyboard.
  26636. + */
  26637. +#define SC_LIM 89
  26638. +
  26639. +#define FOCUS_PF1 85 /* actual code! */
  26640. +#define FOCUS_PF2 89
  26641. +#define FOCUS_PF3 90
  26642. +#define FOCUS_PF4 91
  26643. +#define FOCUS_PF5 92
  26644. +#define FOCUS_PF6 93
  26645. +#define FOCUS_PF7 94
  26646. +#define FOCUS_PF8 95
  26647. +#define FOCUS_PF9 120
  26648. +#define FOCUS_PF10 121
  26649. +#define FOCUS_PF11 122
  26650. +#define FOCUS_PF12 123
  26651. +
  26652. +#define JAP_86 124
  26653. +/* tfj@olivia.ping.dk:
  26654. + * The four keys are located over the numeric keypad, and are
  26655. + * labelled A1-A4. It's an rc930 keyboard, from
  26656. + * Regnecentralen/RC International, Now ICL.
  26657. + * Scancodes: 59, 5a, 5b, 5c.
  26658. + */
  26659. +#define RGN1 124
  26660. +#define RGN2 125
  26661. +#define RGN3 126
  26662. +#define RGN4 127
  26663. +
  26664. +static unsigned char high_keys[128 - SC_LIM] = {
  26665. + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
  26666. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
  26667. + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
  26668. + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
  26669. + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
  26670. + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
  26671. +};
  26672. +
  26673. +/* BTC */
  26674. +#define E0_MACRO 112
  26675. +/* LK450 */
  26676. +#define E0_F13 113
  26677. +#define E0_F14 114
  26678. +#define E0_HELP 115
  26679. +#define E0_DO 116
  26680. +#define E0_F17 117
  26681. +#define E0_KPMINPLUS 118
  26682. +/*
  26683. + * My OmniKey generates e0 4c for the "OMNI" key and the
  26684. + * right alt key does nada. [kkoller@nyx10.cs.du.edu]
  26685. + */
  26686. +#define E0_OK 124
  26687. +/*
  26688. + * New microsoft keyboard is rumoured to have
  26689. + * e0 5b (left window button), e0 5c (right window button),
  26690. + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
  26691. + * [or: Windows_L, Windows_R, TaskMan]
  26692. + */
  26693. +#define E0_MSLW 125
  26694. +#define E0_MSRW 126
  26695. +#define E0_MSTM 127
  26696. +
  26697. +static unsigned char e0_keys[128] = {
  26698. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
  26699. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
  26700. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
  26701. + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
  26702. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
  26703. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
  26704. + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
  26705. + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
  26706. + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
  26707. + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, /* 0x48-0x4f */
  26708. + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
  26709. + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
  26710. + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
  26711. + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
  26712. + //0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
  26713. + 0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */
  26714. + 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */
  26715. +};
  26716. +
  26717. +int sa1111_setkeycode(unsigned int scancode, unsigned int keycode)
  26718. +{
  26719. + if (scancode < SC_LIM || scancode > 255 || keycode > 127)
  26720. + return -EINVAL;
  26721. + if (scancode < 128)
  26722. + high_keys[scancode - SC_LIM] = keycode;
  26723. + else
  26724. + e0_keys[scancode - 128] = keycode;
  26725. + return 0;
  26726. +}
  26727. +
  26728. +int sa1111_getkeycode(unsigned int scancode)
  26729. +{
  26730. + return
  26731. + (scancode < SC_LIM || scancode > 255) ? -EINVAL :
  26732. + (scancode <
  26733. + 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128];
  26734. +}
  26735. +
  26736. +static int do_acknowledge(unsigned char scancode)
  26737. +{
  26738. + if (reply_expected) {
  26739. + /* Unfortunately, we must recognise these codes only if we know they
  26740. + * are known to be valid (i.e., after sending a command), because there
  26741. + * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
  26742. + * keys with such codes :(
  26743. + */
  26744. + if (scancode == KBD_REPLY_ACK) {
  26745. + acknowledge = 1;
  26746. + reply_expected = 0;
  26747. + return 0;
  26748. + } else if (scancode == KBD_REPLY_RESEND) {
  26749. + resend = 1;
  26750. + reply_expected = 0;
  26751. + return 0;
  26752. + }
  26753. + /* Should not happen... */
  26754. +#if 0
  26755. + printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
  26756. + scancode);
  26757. +#endif
  26758. + }
  26759. + return 1;
  26760. +}
  26761. +
  26762. +int
  26763. +sa1111_translate(unsigned char scancode, unsigned char *keycode,
  26764. + char raw_mode)
  26765. +{
  26766. + static int prev_scancode = 0;
  26767. +
  26768. + /* special prefix scancodes.. */
  26769. + if (scancode == 0xe0 || scancode == 0xe1) {
  26770. + prev_scancode = scancode;
  26771. + return 0;
  26772. + }
  26773. +
  26774. + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
  26775. + if (scancode == 0x00 || scancode == 0xff) {
  26776. + prev_scancode = 0;
  26777. + return 0;
  26778. + }
  26779. +
  26780. + scancode &= 0x7f;
  26781. +
  26782. + if (prev_scancode) {
  26783. + /*
  26784. + * usually it will be 0xe0, but a Pause key generates
  26785. + * e1 1d 45 e1 9d c5 when pressed, and nothing when released
  26786. + */
  26787. + if (prev_scancode != 0xe0) {
  26788. + if (prev_scancode == 0xe1 && scancode == 0x1d) {
  26789. + prev_scancode = 0x100;
  26790. + return 0;
  26791. + }
  26792. + else if (prev_scancode == 0x100
  26793. + && scancode == 0x45) {
  26794. + *keycode = E1_PAUSE;
  26795. + prev_scancode = 0;
  26796. + } else {
  26797. +#ifdef KBD_REPORT_UNKN
  26798. + if (!raw_mode)
  26799. + printk(KERN_INFO
  26800. + "keyboard: unknown e1 escape sequence\n");
  26801. +#endif
  26802. + prev_scancode = 0;
  26803. + return 0;
  26804. + }
  26805. + } else {
  26806. + prev_scancode = 0;
  26807. + /*
  26808. + * The keyboard maintains its own internal caps lock and
  26809. + * num lock statuses. In caps lock mode E0 AA precedes make
  26810. + * code and E0 2A follows break code. In num lock mode,
  26811. + * E0 2A precedes make code and E0 AA follows break code.
  26812. + * We do our own book-keeping, so we will just ignore these.
  26813. + */
  26814. + /*
  26815. + * For my keyboard there is no caps lock mode, but there are
  26816. + * both Shift-L and Shift-R modes. The former mode generates
  26817. + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
  26818. + * So, we should also ignore the latter. - aeb@cwi.nl
  26819. + */
  26820. + if (scancode == 0x2a || scancode == 0x36)
  26821. + return 0;
  26822. +
  26823. + if (e0_keys[scancode])
  26824. + *keycode = e0_keys[scancode];
  26825. + else {
  26826. +#ifdef KBD_REPORT_UNKN
  26827. + if (!raw_mode)
  26828. + printk(KERN_INFO
  26829. + "keyboard: unknown scancode e0 %02x\n",
  26830. + scancode);
  26831. +#endif
  26832. + return 0;
  26833. + }
  26834. + }
  26835. + } else if (scancode >= SC_LIM) {
  26836. + /* This happens with the FOCUS 9000 keyboard
  26837. + Its keys PF1..PF12 are reported to generate
  26838. + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
  26839. + Moreover, unless repeated, they do not generate
  26840. + key-down events, so we have to zero up_flag below */
  26841. + /* Also, Japanese 86/106 keyboards are reported to
  26842. + generate 0x73 and 0x7d for \ - and \ | respectively. */
  26843. + /* Also, some Brazilian keyboard is reported to produce
  26844. + 0x73 and 0x7e for \ ? and KP-dot, respectively. */
  26845. +
  26846. + *keycode = high_keys[scancode - SC_LIM];
  26847. +
  26848. + if (!*keycode) {
  26849. + if (!raw_mode) {
  26850. +#ifdef KBD_REPORT_UNKN
  26851. + printk(KERN_INFO
  26852. + "keyboard: unrecognized scancode (%02x)"
  26853. + " - ignored\n", scancode);
  26854. +#endif
  26855. + }
  26856. + return 0;
  26857. + }
  26858. + } else
  26859. + *keycode = scancode;
  26860. + return 1;
  26861. +}
  26862. +
  26863. +char sa1111_unexpected_up(unsigned char keycode)
  26864. +{
  26865. + /* unexpected, but this can happen: maybe this was a key release for a
  26866. + FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
  26867. + if (keycode >= SC_LIM || keycode == 85)
  26868. + return 0;
  26869. + else
  26870. + return 0200;
  26871. +}
  26872. +
  26873. +static unsigned char kbd_exists = 1;
  26874. +
  26875. +static inline void handle_keyboard_event(unsigned char scancode)
  26876. +{
  26877. +#ifdef CONFIG_VT
  26878. + kbd_exists = 1;
  26879. + if (do_acknowledge(scancode))
  26880. + handle_scancode(scancode, !(scancode & 0x80));
  26881. +#endif
  26882. + tasklet_schedule(&keyboard_tasklet);
  26883. +}
  26884. +
  26885. +/*
  26886. + * This reads the keyboard status port, and does the
  26887. + * appropriate action.
  26888. + *
  26889. + * It requires that we hold the keyboard controller
  26890. + * spinlock.
  26891. + */
  26892. +static void handle_kbd_event(void)
  26893. +{
  26894. + unsigned int status = KBDSTAT;
  26895. + unsigned int work = 10000;
  26896. + unsigned char scancode;
  26897. +
  26898. + while (status & KBD_STAT_RXF) {
  26899. + while (status & KBD_STAT_RXF) {
  26900. + scancode = KBDDATA & 0xff;
  26901. + if (!(status & KBD_STAT_STP))
  26902. + handle_keyboard_event(scancode);
  26903. + if (!--work) {
  26904. + printk(KERN_ERR
  26905. + "pc_keyb: keyboard controller jammed (0x%02X).\n",
  26906. + status);
  26907. + return;
  26908. + }
  26909. + status = KBDSTAT;
  26910. + }
  26911. + work = 10000;
  26912. + }
  26913. +
  26914. + if (status & KBD_STAT_STP)
  26915. + KBDSTAT = KBD_STAT_STP;
  26916. +}
  26917. +
  26918. +static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  26919. +{
  26920. + unsigned long flags;
  26921. +
  26922. +#ifdef CONFIG_VT
  26923. + kbd_pt_regs = regs;
  26924. +#endif
  26925. + spin_lock_irqsave(&kbd_controller_lock, flags);
  26926. + handle_kbd_event();
  26927. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  26928. +}
  26929. +
  26930. +/*
  26931. + * send_data sends a character to the keyboard and waits
  26932. + * for an acknowledge, possibly retrying if asked to. Returns
  26933. + * the success status.
  26934. + *
  26935. + * Don't use 'jiffies', so that we don't depend on interrupts
  26936. + */
  26937. +static int send_data(unsigned char data)
  26938. +{
  26939. + int retries = 3;
  26940. +
  26941. + do {
  26942. + unsigned long timeout = KBD_TIMEOUT;
  26943. +
  26944. + acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
  26945. + resend = 0;
  26946. + reply_expected = 1;
  26947. + kbd_write_output_w(data);
  26948. + for (;;) {
  26949. + if (acknowledge)
  26950. + return 1;
  26951. + if (resend)
  26952. + break;
  26953. + mdelay(1);
  26954. + if (!--timeout) {
  26955. +#ifdef KBD_REPORT_TIMEOUTS
  26956. + printk(KERN_WARNING
  26957. + "keyboard: Timeout - AT keyboard not present?\n");
  26958. +#endif
  26959. + return 0;
  26960. + }
  26961. + }
  26962. + }
  26963. + while (retries-- > 0);
  26964. +#ifdef KBD_REPORT_TIMEOUTS
  26965. + printk(KERN_WARNING
  26966. + "keyboard: Too many NACKs -- noisy kbd cable?\n");
  26967. +#endif
  26968. + return 0;
  26969. +}
  26970. +
  26971. +void sa1111_leds(unsigned char leds)
  26972. +{
  26973. + if (kbd_exists
  26974. + && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
  26975. + send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */
  26976. + kbd_exists = 0;
  26977. + }
  26978. +}
  26979. +
  26980. +#define KBD_NO_DATA (-1) /* No data */
  26981. +#define KBD_BAD_DATA (-2) /* Parity or other error */
  26982. +
  26983. +static int __init kbd_read_data(void)
  26984. +{
  26985. + int retval = KBD_NO_DATA;
  26986. + unsigned int status;
  26987. +
  26988. + status = KBDSTAT;
  26989. + if (status & KBD_STAT_RXF) {
  26990. + unsigned char data = KBDDATA;
  26991. +
  26992. + retval = data;
  26993. + if (status & KBD_STAT_STP)
  26994. + retval = KBD_BAD_DATA;
  26995. + }
  26996. + return retval;
  26997. +}
  26998. +
  26999. +static void __init kbd_clear_input(void)
  27000. +{
  27001. + int maxread = 100; /* Random number */
  27002. +
  27003. + do {
  27004. + if (kbd_read_data() == KBD_NO_DATA)
  27005. + break;
  27006. + }
  27007. + while (--maxread);
  27008. +}
  27009. +
  27010. +static int __init kbd_wait_for_input(void)
  27011. +{
  27012. + long timeout = KBD_INIT_TIMEOUT;
  27013. +
  27014. + do {
  27015. + int retval = kbd_read_data();
  27016. + if (retval >= 0)
  27017. + return retval;
  27018. + mdelay(1);
  27019. + }
  27020. + while (--timeout);
  27021. + return -1;
  27022. +}
  27023. +
  27024. +#if 0
  27025. +static void kbd_write_command_w(int data)
  27026. +{
  27027. + unsigned long flags;
  27028. +
  27029. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27030. + kb_wait();
  27031. + kbd_write_command(data);
  27032. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27033. +}
  27034. +#endif
  27035. +
  27036. +static void kbd_write_output_w(int data)
  27037. +{
  27038. + unsigned long flags;
  27039. +
  27040. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27041. + kb_wait();
  27042. + KBDDATA = data & 0xff;
  27043. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27044. +}
  27045. +
  27046. +/*
  27047. + * Test the keyboard interface. We basically check to make sure that
  27048. + * we can drive each line to the keyboard independently of each other.
  27049. + */
  27050. +static int kbdif_test(void)
  27051. +{
  27052. + int ret = 0;
  27053. +
  27054. + KBDCR = KBDCR_ENA | KBDCR_FKC;
  27055. + udelay(2);
  27056. + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBD) {
  27057. + printk("Keyboard interface test failed[1]: %02x\n",
  27058. + KBDSTAT);
  27059. + ret = -ENODEV;
  27060. + }
  27061. +
  27062. + KBDCR = KBDCR_ENA;
  27063. + udelay(2);
  27064. + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != (KBDSTAT_KBC | KBDSTAT_KBD)) {
  27065. + printk("Keyboard interface test failed[2]: %02x\n",
  27066. + KBDSTAT);
  27067. + ret = -ENODEV;
  27068. + }
  27069. +
  27070. + KBDCR = KBDCR_ENA | KBDCR_FKD;
  27071. + udelay(2);
  27072. + if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBC) {
  27073. + printk("Keyboard interface test failed[3]: %02x\n",
  27074. + KBDSTAT);
  27075. + ret = -ENODEV;
  27076. + }
  27077. +
  27078. + return ret;
  27079. +}
  27080. +
  27081. +static char *__init initialize_kbd(void)
  27082. +{
  27083. + int status;
  27084. +
  27085. + /*
  27086. + * Test the keyboard interface.
  27087. + */
  27088. + kbdif_test();
  27089. +
  27090. + /*
  27091. + * Ok, drop the force low bits, and wait a while,
  27092. + * and clear the stop bit error flag.
  27093. + */
  27094. + KBDCR = KBDCR_ENA;
  27095. + udelay(4);
  27096. + KBDSTAT = KBD_STAT_STP;
  27097. +
  27098. + /*
  27099. + * Ok, we're now ready to talk to the keyboard. Reset
  27100. + * it, just to make sure we're starting in a sane state.
  27101. + *
  27102. + * Set up to try again if the keyboard asks for RESEND.
  27103. + */
  27104. + do {
  27105. + KBDDATA = KBD_CMD_RESET;
  27106. + status = kbd_wait_for_input();
  27107. + if (status == KBD_REPLY_ACK)
  27108. + break;
  27109. + if (status != KBD_REPLY_RESEND)
  27110. + return "Keyboard reset failed, no ACK";
  27111. + } while (1);
  27112. +
  27113. + if (kbd_wait_for_input() != KBD_REPLY_POR)
  27114. + return "Keyboard reset failed, no POR";
  27115. +
  27116. + /*
  27117. + * Set keyboard controller mode. During this, the keyboard should be
  27118. + * in the disabled state.
  27119. + *
  27120. + * Set up to try again if the keyboard asks for RESEND.
  27121. + */
  27122. + do {
  27123. + kbd_write_output_w(KBD_CMD_DISABLE);
  27124. + status = kbd_wait_for_input();
  27125. + if (status == KBD_REPLY_ACK)
  27126. + break;
  27127. + if (status != KBD_REPLY_RESEND)
  27128. + return "Disable keyboard: no ACK";
  27129. + } while (1);
  27130. +
  27131. +#if 0 /*@@@ */
  27132. + kbd_write_command_w(KBD_CCMD_WRITE_MODE);
  27133. + kbd_write_output_w(KBD_MODE_KBD_INT
  27134. + | KBD_MODE_SYS | KBD_MODE_DISABLE_MOUSE |
  27135. + KBD_MODE_KCC);
  27136. +
  27137. + /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
  27138. + kbd_write_command_w(KBD_CCMD_READ_MODE);
  27139. + if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
  27140. + /*
  27141. + * If the controller does not support conversion,
  27142. + * Set the keyboard to scan-code set 1.
  27143. + */
  27144. + kbd_write_output_w(0xF0);
  27145. + kbd_wait_for_input();
  27146. + kbd_write_output_w(0x01);
  27147. + kbd_wait_for_input();
  27148. + }
  27149. +#else
  27150. + kbd_write_output_w(0xf0);
  27151. + kbd_wait_for_input();
  27152. + kbd_write_output_w(0x01);
  27153. + kbd_wait_for_input();
  27154. +#endif
  27155. +
  27156. +
  27157. + kbd_write_output_w(KBD_CMD_ENABLE);
  27158. + if (kbd_wait_for_input() != KBD_REPLY_ACK)
  27159. + return "Enable keyboard: no ACK";
  27160. +
  27161. + /*
  27162. + * Finally, set the typematic rate to maximum.
  27163. + */
  27164. + kbd_write_output_w(KBD_CMD_SET_RATE);
  27165. + if (kbd_wait_for_input() != KBD_REPLY_ACK)
  27166. + return "Set rate: no ACK";
  27167. + kbd_write_output_w(0x00);
  27168. + if (kbd_wait_for_input() != KBD_REPLY_ACK)
  27169. + return "Set rate: no ACK";
  27170. +
  27171. + return NULL;
  27172. +}
  27173. +
  27174. +int __init sa1111_kbd_init_hw(void)
  27175. +{
  27176. + char *msg;
  27177. + int ret;
  27178. +
  27179. + if (!request_mem_region(_KBDCR, 512, "keyboard"))
  27180. + return -EBUSY;
  27181. +
  27182. + SKPCR |= SKPCR_PTCLKEN;
  27183. + KBDCLKDIV = 0;
  27184. + KBDPRECNT = 127;
  27185. +
  27186. + /* Flush any pending input. */
  27187. + kbd_clear_input();
  27188. +
  27189. + msg = initialize_kbd();
  27190. + if (msg)
  27191. + printk(KERN_WARNING "initialize_kbd: %s\n", msg);
  27192. +
  27193. +#if defined CONFIG_PSMOUSE
  27194. + psaux_init();
  27195. +#endif
  27196. +
  27197. + k_setkeycode = sa1111_setkeycode;
  27198. + k_getkeycode = sa1111_getkeycode;
  27199. + k_translate = sa1111_translate;
  27200. + k_unexpected_up = sa1111_unexpected_up;
  27201. + k_leds = sa1111_leds;
  27202. +#ifdef CONFIG_MAGIC_SYSRQ
  27203. + k_sysrq_xlate = sa1111_sysrq_xlate;
  27204. + k_sysrq_key = 0x54;
  27205. +#endif
  27206. +
  27207. + /* Ok, finally allocate the IRQ, and off we go.. */
  27208. + ret = request_irq(IRQ_TPRXINT, keyboard_interrupt, 0, "keyboard", NULL);
  27209. + if (ret)
  27210. + release_mem_region(_KBDCR, 512);
  27211. +
  27212. + return ret;
  27213. +}
  27214. +
  27215. +#if defined CONFIG_PSMOUSE
  27216. +
  27217. +static inline void handle_mouse_event(unsigned char scancode)
  27218. +{
  27219. + if (mouse_reply_expected) {
  27220. + if (scancode == AUX_ACK) {
  27221. + mouse_reply_expected--;
  27222. + return;
  27223. + }
  27224. + mouse_reply_expected = 0;
  27225. + }
  27226. +
  27227. + add_mouse_randomness(scancode);
  27228. + if (aux_count) {
  27229. + int head = queue->head;
  27230. +
  27231. + queue->buf[head] = scancode;
  27232. + head = (head + 1) & (AUX_BUF_SIZE - 1);
  27233. + if (head != queue->tail) {
  27234. + queue->head = head;
  27235. + if (queue->fasync)
  27236. + kill_fasync(&queue->fasync, SIGIO,
  27237. + POLL_IN);
  27238. + wake_up_interruptible(&queue->proc_list);
  27239. + }
  27240. + }
  27241. +}
  27242. +
  27243. +static void handle_mse_event(void)
  27244. +{
  27245. + unsigned int msests = MSESTAT;
  27246. + unsigned int work = 10000;
  27247. + unsigned char scancode;
  27248. +
  27249. + while (msests & MSE_STAT_RXF) {
  27250. + while (msests & MSE_STAT_RXF) {
  27251. + scancode = MSEDATA & 0xff;
  27252. + if (!(msests & MSE_STAT_STP))
  27253. + handle_mouse_event(scancode);
  27254. + if (!--work) {
  27255. + printk(KERN_ERR
  27256. + "pc_keyb: mouse controller jammed (0x%02X).\n",
  27257. + msests);
  27258. + return;
  27259. + /*XXX*/}
  27260. + msests = MSESTAT;
  27261. + }
  27262. + work = 10000;
  27263. + }
  27264. +}
  27265. +
  27266. +static void ms_wait(void)
  27267. +{
  27268. + unsigned long timeout = KBC_TIMEOUT;
  27269. +
  27270. + do {
  27271. + /*
  27272. + * "handle_kbd_event()" will handle any incoming events
  27273. + * while we wait - keypresses or mouse movement.
  27274. + */
  27275. + handle_mse_event();
  27276. + if (MSESTAT & MSE_STAT_TXE)
  27277. + return;
  27278. + mdelay(1);
  27279. + timeout--;
  27280. + }
  27281. + while (timeout);
  27282. +#ifdef KBD_REPORT_TIMEOUTS
  27283. + printk(KERN_WARNING "Mouse timed out[1]\n");
  27284. +#endif
  27285. +}
  27286. +
  27287. +static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  27288. +{
  27289. + unsigned long flags;
  27290. +
  27291. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27292. + handle_mse_event();
  27293. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27294. +}
  27295. +
  27296. +/*
  27297. + * Check if this is a dual port controller.
  27298. + */
  27299. +static int __init detect_auxiliary_port(void)
  27300. +{
  27301. + unsigned long flags;
  27302. + int loops = 10;
  27303. + int retval = 0;
  27304. +
  27305. + /* Check if the BIOS detected a device on the auxiliary port. */
  27306. + if (aux_device_present == 0xaa)
  27307. + return 1;
  27308. +
  27309. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27310. +
  27311. + /* Put the value 0x5A in the output buffer using the "Write
  27312. + * Auxiliary Device Output Buffer" command (0xD3). Poll the
  27313. + * Status Register for a while to see if the value really
  27314. + * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
  27315. + * bit is also set to 1 in the Status Register, we assume this
  27316. + * controller has an Auxiliary Port (a.k.a. Mouse Port).
  27317. + */
  27318. + // kb_wait();
  27319. + // kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
  27320. +
  27321. + SKPCR |= SKPCR_PMCLKEN;
  27322. +
  27323. + MSECLKDIV = 0;
  27324. + MSEPRECNT = 127;
  27325. + MSECR = MSECR_ENA;
  27326. + mdelay(50);
  27327. + MSEDATA = 0xf4;
  27328. + mdelay(50);
  27329. +
  27330. + do {
  27331. + unsigned int msests = MSESTAT;
  27332. +
  27333. + if (msests & MSE_STAT_RXF) {
  27334. + do {
  27335. + msests = MSEDATA; /* dummy read */
  27336. + mdelay(50);
  27337. + msests = MSESTAT;
  27338. + }
  27339. + while (msests & MSE_STAT_RXF);
  27340. + printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
  27341. + retval = 1;
  27342. + break;
  27343. + }
  27344. + mdelay(1);
  27345. + }
  27346. + while (--loops);
  27347. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27348. +
  27349. + return retval;
  27350. +}
  27351. +
  27352. +/*
  27353. + * Send a byte to the mouse.
  27354. + */
  27355. +static void aux_write_dev(int val)
  27356. +{
  27357. + unsigned long flags;
  27358. +
  27359. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27360. + // kb_wait();
  27361. + // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
  27362. + ms_wait();
  27363. + MSEDATA = val;
  27364. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27365. +}
  27366. +
  27367. +/*
  27368. + * Send a byte to the mouse & handle returned ack
  27369. + */
  27370. +static void aux_write_ack(int val)
  27371. +{
  27372. + unsigned long flags;
  27373. +
  27374. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27375. + // kb_wait();
  27376. + // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
  27377. + ms_wait();
  27378. + MSEDATA = val;
  27379. + /* we expect an ACK in response. */
  27380. + mouse_reply_expected++;
  27381. + ms_wait();
  27382. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27383. +}
  27384. +
  27385. +static unsigned char get_from_queue(void)
  27386. +{
  27387. + unsigned char result;
  27388. + unsigned long flags;
  27389. +
  27390. + spin_lock_irqsave(&kbd_controller_lock, flags);
  27391. + result = queue->buf[queue->tail];
  27392. + queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1);
  27393. + spin_unlock_irqrestore(&kbd_controller_lock, flags);
  27394. + return result;
  27395. +}
  27396. +
  27397. +
  27398. +static inline int queue_empty(void)
  27399. +{
  27400. + return queue->head == queue->tail;
  27401. +}
  27402. +
  27403. +static int fasync_aux(int fd, struct file *filp, int on)
  27404. +{
  27405. + int retval;
  27406. +
  27407. + retval = fasync_helper(fd, filp, on, &queue->fasync);
  27408. + if (retval < 0)
  27409. + return retval;
  27410. + return 0;
  27411. +}
  27412. +
  27413. +
  27414. +/*
  27415. + * Random magic cookie for the aux device
  27416. + */
  27417. +#define AUX_DEV ((void *)queue)
  27418. +
  27419. +static int release_aux(struct inode *inode, struct file *file)
  27420. +{
  27421. + fasync_aux(-1, file, 0);
  27422. + if (--aux_count)
  27423. + return 0;
  27424. + // kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
  27425. + // kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
  27426. + aux_write_ack(AUX_DISABLE_DEV); /* Disable aux device */
  27427. + MSECR &= ~MSECR_ENA;
  27428. + free_irq(IRQ_MSRXINT, AUX_DEV);
  27429. + return 0;
  27430. +}
  27431. +
  27432. +/*
  27433. + * Install interrupt handler.
  27434. + * Enable auxiliary device.
  27435. + */
  27436. +
  27437. +static int open_aux(struct inode *inode, struct file *file)
  27438. +{
  27439. + if (aux_count++) {
  27440. + return 0;
  27441. + }
  27442. + queue->head = queue->tail = 0; /* Flush input queue */
  27443. + /* Don't enable the mouse controller until we've registered IRQ handler */
  27444. + if (request_irq(IRQ_MSRXINT, mouse_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {
  27445. + aux_count--;
  27446. + return -EBUSY;
  27447. + }
  27448. + MSECLKDIV = 0;
  27449. + MSEPRECNT = 127;
  27450. + MSECR &= ~MSECR_ENA;
  27451. + mdelay(50);
  27452. + MSECR = MSECR_ENA;
  27453. + mdelay(50);
  27454. + MSEDATA = 0xf4;
  27455. + mdelay(50);
  27456. + if (MSESTAT & 0x0100) {
  27457. + MSESTAT = 0x0100; /* clear IRQ status */
  27458. + }
  27459. +/* kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); *//* Enable the
  27460. + auxiliary port on
  27461. + controller. */
  27462. + aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
  27463. + // kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
  27464. +
  27465. + // send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
  27466. +
  27467. + return 0;
  27468. +}
  27469. +
  27470. +/*
  27471. + * Put bytes from input queue to buffer.
  27472. + */
  27473. +
  27474. +static ssize_t
  27475. +read_aux(struct file *file, char *buffer, size_t count, loff_t * ppos)
  27476. +{
  27477. + DECLARE_WAITQUEUE(wait, current);
  27478. + ssize_t i = count;
  27479. + unsigned char c;
  27480. +
  27481. + if (queue_empty()) {
  27482. + if (file->f_flags & O_NONBLOCK)
  27483. + return -EAGAIN;
  27484. + add_wait_queue(&queue->proc_list, &wait);
  27485. + repeat:
  27486. + set_current_state(TASK_INTERRUPTIBLE);
  27487. + if (queue_empty() && !signal_pending(current)) {
  27488. + schedule();
  27489. + goto repeat;
  27490. + }
  27491. + current->state = TASK_RUNNING;
  27492. + remove_wait_queue(&queue->proc_list, &wait);
  27493. + }
  27494. + while (i > 0 && !queue_empty()) {
  27495. + c = get_from_queue();
  27496. + put_user(c, buffer++);
  27497. + i--;
  27498. + }
  27499. + if (count - i) {
  27500. + file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  27501. + return count - i;
  27502. + }
  27503. + if (signal_pending(current))
  27504. + return -ERESTARTSYS;
  27505. + return 0;
  27506. +}
  27507. +
  27508. +/*
  27509. + * Write to the aux device.
  27510. + */
  27511. +
  27512. +static ssize_t
  27513. +write_aux(struct file *file, const char *buffer, size_t count,
  27514. + loff_t * ppos)
  27515. +{
  27516. + ssize_t retval = 0;
  27517. +
  27518. + if (count) {
  27519. + ssize_t written = 0;
  27520. +
  27521. + if (count > 32)
  27522. + count = 32; /* Limit to 32 bytes. */
  27523. + do {
  27524. + char c;
  27525. + get_user(c, buffer++);
  27526. + aux_write_dev(c);
  27527. + written++;
  27528. + }
  27529. + while (--count);
  27530. + retval = -EIO;
  27531. + if (written) {
  27532. + retval = written;
  27533. + file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
  27534. + }
  27535. + }
  27536. +
  27537. + return retval;
  27538. +}
  27539. +
  27540. +static unsigned int aux_poll(struct file *file, poll_table * wait)
  27541. +{
  27542. + poll_wait(file, &queue->proc_list, wait);
  27543. + if (!queue_empty())
  27544. + return POLLIN | POLLRDNORM;
  27545. + return 0;
  27546. +}
  27547. +
  27548. +struct file_operations psaux_fops = {
  27549. + read: read_aux,
  27550. + write: write_aux,
  27551. + poll: aux_poll,
  27552. + open: open_aux,
  27553. + release: release_aux,
  27554. + fasync: fasync_aux,
  27555. +};
  27556. +
  27557. +/*
  27558. + * Initialize driver.
  27559. + */
  27560. +static struct miscdevice psaux_mouse = {
  27561. + PSMOUSE_MINOR, "psaux", &psaux_fops
  27562. +};
  27563. +
  27564. +
  27565. +static int __init psaux_init(void)
  27566. +{
  27567. + int ret;
  27568. +
  27569. + if (!request_mem_region(_MSECR, 512, "psaux"))
  27570. + return -EBUSY;
  27571. +
  27572. + if (!detect_auxiliary_port()) {
  27573. + ret = -EIO;
  27574. + goto out;
  27575. + }
  27576. +
  27577. + misc_register(&psaux_mouse);
  27578. + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
  27579. + memset(queue, 0, sizeof(*queue));
  27580. + queue->head = queue->tail = 0;
  27581. + init_waitqueue_head(&queue->proc_list);
  27582. +
  27583. +#ifdef CONFIG_PSMOUSE
  27584. + aux_write_ack(AUX_SET_SAMPLE);
  27585. + aux_write_ack(100); /* 100 samples/sec */
  27586. + aux_write_ack(AUX_SET_RES);
  27587. + aux_write_ack(3); /* 8 counts per mm */
  27588. + aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
  27589. +#endif
  27590. + ret = 0;
  27591. +
  27592. + out:
  27593. + if (ret)
  27594. + release_mem_region(_MSECR, 512);
  27595. + return ret;
  27596. +}
  27597. +
  27598. +#endif /* CONFIG_PSMOUSE */
  27599. diff -urN linux-2.4.26/drivers/char/serial.c linux-2.4.26-vrs1/drivers/char/serial.c
  27600. --- linux-2.4.26/drivers/char/serial.c 2004-02-27 20:03:25.000000000 +0000
  27601. +++ linux-2.4.26-vrs1/drivers/char/serial.c 2004-02-23 13:36:30.000000000 +0000
  27602. @@ -4527,6 +4527,14 @@
  27603. }
  27604. /*
  27605. + * If there is exactly one port of 8 bytes, use it.
  27606. + */
  27607. + if (num_port == 1 && pci_resource_len(dev, first_port) == 8) {
  27608. + board->flags = first_port;
  27609. + return 0;
  27610. + }
  27611. +
  27612. + /*
  27613. * If there is 1 or 0 iomem regions, and exactly one port, use
  27614. * it.
  27615. */
  27616. diff -urN linux-2.4.26/drivers/char/serial_21285.c linux-2.4.26-vrs1/drivers/char/serial_21285.c
  27617. --- linux-2.4.26/drivers/char/serial_21285.c 2002-08-03 01:39:43.000000000 +0100
  27618. +++ linux-2.4.26-vrs1/drivers/char/serial_21285.c 1970-01-01 01:00:00.000000000 +0100
  27619. @@ -1,498 +0,0 @@
  27620. -/*
  27621. - * linux/drivers/char/serial_21285.c
  27622. - *
  27623. - * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
  27624. - *
  27625. - * Based on drivers/char/serial.c
  27626. - */
  27627. -
  27628. -#include <linux/config.h>
  27629. -#include <linux/module.h>
  27630. -#include <linux/errno.h>
  27631. -#include <linux/signal.h>
  27632. -#include <linux/sched.h>
  27633. -#include <linux/interrupt.h>
  27634. -#include <linux/tty.h>
  27635. -#include <linux/tty_flip.h>
  27636. -#include <linux/serial.h>
  27637. -#include <linux/major.h>
  27638. -#include <linux/ptrace.h>
  27639. -#include <linux/ioport.h>
  27640. -#include <linux/mm.h>
  27641. -#include <linux/slab.h>
  27642. -#include <linux/init.h>
  27643. -#include <linux/console.h>
  27644. -
  27645. -#include <asm/io.h>
  27646. -#include <asm/irq.h>
  27647. -#include <asm/uaccess.h>
  27648. -#include <asm/dec21285.h>
  27649. -#include <asm/hardware.h>
  27650. -
  27651. -#define BAUD_BASE (mem_fclk_21285/64)
  27652. -
  27653. -#define SERIAL_21285_NAME "ttyFB"
  27654. -#define SERIAL_21285_MAJOR 204
  27655. -#define SERIAL_21285_MINOR 4
  27656. -
  27657. -#define SERIAL_21285_AUXNAME "cuafb"
  27658. -#define SERIAL_21285_AUXMAJOR 205
  27659. -#define SERIAL_21285_AUXMINOR 4
  27660. -
  27661. -static struct tty_driver rs285_driver, callout_driver;
  27662. -static int rs285_refcount;
  27663. -static struct tty_struct *rs285_table[1];
  27664. -
  27665. -static struct termios *rs285_termios[1];
  27666. -static struct termios *rs285_termios_locked[1];
  27667. -
  27668. -static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
  27669. -static struct tty_struct *rs285_tty;
  27670. -static int rs285_use_count;
  27671. -
  27672. -static int rs285_write_room(struct tty_struct *tty)
  27673. -{
  27674. - return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
  27675. -}
  27676. -
  27677. -static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
  27678. -{
  27679. - if (!rs285_tty) {
  27680. - disable_irq(IRQ_CONRX);
  27681. - return;
  27682. - }
  27683. - while (!(*CSR_UARTFLG & 0x10)) {
  27684. - int ch, flag;
  27685. - ch = *CSR_UARTDR;
  27686. - flag = *CSR_RXSTAT;
  27687. - if (flag & 4)
  27688. - tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
  27689. - if (flag & 2)
  27690. - flag = TTY_PARITY;
  27691. - else if (flag & 1)
  27692. - flag = TTY_FRAME;
  27693. - tty_insert_flip_char(rs285_tty, ch, flag);
  27694. - }
  27695. - tty_flip_buffer_push(rs285_tty);
  27696. -}
  27697. -
  27698. -static void rs285_send_xchar(struct tty_struct *tty, char ch)
  27699. -{
  27700. - x_char = ch;
  27701. - enable_irq(IRQ_CONTX);
  27702. -}
  27703. -
  27704. -static void rs285_throttle(struct tty_struct *tty)
  27705. -{
  27706. - if (I_IXOFF(tty))
  27707. - rs285_send_xchar(tty, STOP_CHAR(tty));
  27708. -}
  27709. -
  27710. -static void rs285_unthrottle(struct tty_struct *tty)
  27711. -{
  27712. - if (I_IXOFF(tty)) {
  27713. - if (x_char)
  27714. - x_char = 0;
  27715. - else
  27716. - rs285_send_xchar(tty, START_CHAR(tty));
  27717. - }
  27718. -}
  27719. -
  27720. -static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
  27721. -{
  27722. - while (!(*CSR_UARTFLG & 0x20)) {
  27723. - if (x_char) {
  27724. - *CSR_UARTDR = x_char;
  27725. - x_char = 0;
  27726. - continue;
  27727. - }
  27728. - if (putp == getp) {
  27729. - disable_irq(IRQ_CONTX);
  27730. - break;
  27731. - }
  27732. - *CSR_UARTDR = *getp;
  27733. - if (++getp >= wbuf + sizeof(wbuf))
  27734. - getp = wbuf;
  27735. - }
  27736. - if (rs285_tty)
  27737. - wake_up_interruptible(&rs285_tty->write_wait);
  27738. -}
  27739. -
  27740. -static inline int rs285_xmit(int ch)
  27741. -{
  27742. - if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
  27743. - return 0;
  27744. - *putp = ch;
  27745. - if (++putp >= wbuf + sizeof(wbuf))
  27746. - putp = wbuf;
  27747. - enable_irq(IRQ_CONTX);
  27748. - return 1;
  27749. -}
  27750. -
  27751. -static int rs285_write(struct tty_struct *tty, int from_user,
  27752. - const u_char * buf, int count)
  27753. -{
  27754. - int i;
  27755. -
  27756. - if (from_user && verify_area(VERIFY_READ, buf, count))
  27757. - return -EINVAL;
  27758. -
  27759. - for (i = 0; i < count; i++) {
  27760. - char ch;
  27761. - if (from_user)
  27762. - __get_user(ch, buf + i);
  27763. - else
  27764. - ch = buf[i];
  27765. - if (!rs285_xmit(ch))
  27766. - break;
  27767. - }
  27768. - return i;
  27769. -}
  27770. -
  27771. -static void rs285_put_char(struct tty_struct *tty, u_char ch)
  27772. -{
  27773. - rs285_xmit(ch);
  27774. -}
  27775. -
  27776. -static int rs285_chars_in_buffer(struct tty_struct *tty)
  27777. -{
  27778. - return sizeof(wbuf) - rs285_write_room(tty);
  27779. -}
  27780. -
  27781. -static void rs285_flush_buffer(struct tty_struct *tty)
  27782. -{
  27783. - disable_irq(IRQ_CONTX);
  27784. - putp = getp = wbuf;
  27785. - if (x_char)
  27786. - enable_irq(IRQ_CONTX);
  27787. -}
  27788. -
  27789. -static inline void rs285_set_cflag(int cflag)
  27790. -{
  27791. - int h_lcr, baud, quot;
  27792. -
  27793. - switch (cflag & CSIZE) {
  27794. - case CS5:
  27795. - h_lcr = 0x10;
  27796. - break;
  27797. - case CS6:
  27798. - h_lcr = 0x30;
  27799. - break;
  27800. - case CS7:
  27801. - h_lcr = 0x50;
  27802. - break;
  27803. - default: /* CS8 */
  27804. - h_lcr = 0x70;
  27805. - break;
  27806. -
  27807. - }
  27808. - if (cflag & CSTOPB)
  27809. - h_lcr |= 0x08;
  27810. - if (cflag & PARENB)
  27811. - h_lcr |= 0x02;
  27812. - if (!(cflag & PARODD))
  27813. - h_lcr |= 0x04;
  27814. -
  27815. - switch (cflag & CBAUD) {
  27816. - case B200: baud = 200; break;
  27817. - case B300: baud = 300; break;
  27818. - case B1200: baud = 1200; break;
  27819. - case B1800: baud = 1800; break;
  27820. - case B2400: baud = 2400; break;
  27821. - case B4800: baud = 4800; break;
  27822. - default:
  27823. - case B9600: baud = 9600; break;
  27824. - case B19200: baud = 19200; break;
  27825. - case B38400: baud = 38400; break;
  27826. - case B57600: baud = 57600; break;
  27827. - case B115200: baud = 115200; break;
  27828. - }
  27829. -
  27830. - /*
  27831. - * The documented expression for selecting the divisor is:
  27832. - * BAUD_BASE / baud - 1
  27833. - * However, typically BAUD_BASE is not divisible by baud, so
  27834. - * we want to select the divisor that gives us the minimum
  27835. - * error. Therefore, we want:
  27836. - * int(BAUD_BASE / baud - 0.5) ->
  27837. - * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
  27838. - * int((BAUD_BASE - (baud >> 1)) / baud)
  27839. - */
  27840. - quot = (BAUD_BASE - (baud >> 1)) / baud;
  27841. -
  27842. - *CSR_UARTCON = 0;
  27843. - *CSR_L_UBRLCR = quot & 0xff;
  27844. - *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
  27845. - *CSR_H_UBRLCR = h_lcr;
  27846. - *CSR_UARTCON = 1;
  27847. -}
  27848. -
  27849. -static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
  27850. -{
  27851. - if (old && tty->termios->c_cflag == old->c_cflag)
  27852. - return;
  27853. - rs285_set_cflag(tty->termios->c_cflag);
  27854. -}
  27855. -
  27856. -
  27857. -static void rs285_stop(struct tty_struct *tty)
  27858. -{
  27859. - disable_irq(IRQ_CONTX);
  27860. -}
  27861. -
  27862. -static void rs285_start(struct tty_struct *tty)
  27863. -{
  27864. - enable_irq(IRQ_CONTX);
  27865. -}
  27866. -
  27867. -static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
  27868. -{
  27869. - int orig_jiffies = jiffies;
  27870. - while (*CSR_UARTFLG & 8) {
  27871. - current->state = TASK_INTERRUPTIBLE;
  27872. - schedule_timeout(1);
  27873. - if (signal_pending(current))
  27874. - break;
  27875. - if (timeout && time_after(jiffies, orig_jiffies + timeout))
  27876. - break;
  27877. - }
  27878. - current->state = TASK_RUNNING;
  27879. -}
  27880. -
  27881. -static int rs285_open(struct tty_struct *tty, struct file *filp)
  27882. -{
  27883. - int line;
  27884. -
  27885. - MOD_INC_USE_COUNT;
  27886. - line = MINOR(tty->device) - tty->driver.minor_start;
  27887. - if (line) {
  27888. - MOD_DEC_USE_COUNT;
  27889. - return -ENODEV;
  27890. - }
  27891. -
  27892. - tty->driver_data = NULL;
  27893. - if (!rs285_tty)
  27894. - rs285_tty = tty;
  27895. -
  27896. - enable_irq(IRQ_CONRX);
  27897. - rs285_use_count++;
  27898. - return 0;
  27899. -}
  27900. -
  27901. -static void rs285_close(struct tty_struct *tty, struct file *filp)
  27902. -{
  27903. - if (!--rs285_use_count) {
  27904. - rs285_wait_until_sent(tty, 0);
  27905. - disable_irq(IRQ_CONRX);
  27906. - disable_irq(IRQ_CONTX);
  27907. - rs285_tty = NULL;
  27908. - }
  27909. - MOD_DEC_USE_COUNT;
  27910. -}
  27911. -
  27912. -static int __init rs285_init(void)
  27913. -{
  27914. - int baud = B9600;
  27915. -
  27916. - if (machine_is_personal_server())
  27917. - baud = B57600;
  27918. -
  27919. - rs285_driver.magic = TTY_DRIVER_MAGIC;
  27920. - rs285_driver.driver_name = "serial_21285";
  27921. - rs285_driver.name = SERIAL_21285_NAME;
  27922. - rs285_driver.major = SERIAL_21285_MAJOR;
  27923. - rs285_driver.minor_start = SERIAL_21285_MINOR;
  27924. - rs285_driver.num = 1;
  27925. - rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
  27926. - rs285_driver.subtype = SERIAL_TYPE_NORMAL;
  27927. - rs285_driver.init_termios = tty_std_termios;
  27928. - rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
  27929. - rs285_driver.flags = TTY_DRIVER_REAL_RAW;
  27930. - rs285_driver.refcount = &rs285_refcount;
  27931. - rs285_driver.table = rs285_table;
  27932. - rs285_driver.termios = rs285_termios;
  27933. - rs285_driver.termios_locked = rs285_termios_locked;
  27934. -
  27935. - rs285_driver.open = rs285_open;
  27936. - rs285_driver.close = rs285_close;
  27937. - rs285_driver.write = rs285_write;
  27938. - rs285_driver.put_char = rs285_put_char;
  27939. - rs285_driver.write_room = rs285_write_room;
  27940. - rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
  27941. - rs285_driver.flush_buffer = rs285_flush_buffer;
  27942. - rs285_driver.throttle = rs285_throttle;
  27943. - rs285_driver.unthrottle = rs285_unthrottle;
  27944. - rs285_driver.send_xchar = rs285_send_xchar;
  27945. - rs285_driver.set_termios = rs285_set_termios;
  27946. - rs285_driver.stop = rs285_stop;
  27947. - rs285_driver.start = rs285_start;
  27948. - rs285_driver.wait_until_sent = rs285_wait_until_sent;
  27949. -
  27950. - callout_driver = rs285_driver;
  27951. - callout_driver.name = SERIAL_21285_AUXNAME;
  27952. - callout_driver.major = SERIAL_21285_AUXMAJOR;
  27953. - callout_driver.subtype = SERIAL_TYPE_CALLOUT;
  27954. -
  27955. - if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
  27956. - panic("Couldn't get rx irq for rs285");
  27957. -
  27958. - if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
  27959. - panic("Couldn't get tx irq for rs285");
  27960. -
  27961. - if (tty_register_driver(&rs285_driver))
  27962. - printk(KERN_ERR "Couldn't register 21285 serial driver\n");
  27963. - if (tty_register_driver(&callout_driver))
  27964. - printk(KERN_ERR "Couldn't register 21285 callout driver\n");
  27965. -
  27966. - return 0;
  27967. -}
  27968. -
  27969. -static void __exit rs285_fini(void)
  27970. -{
  27971. - unsigned long flags;
  27972. - int ret;
  27973. -
  27974. - save_flags(flags);
  27975. - cli();
  27976. - ret = tty_unregister_driver(&callout_driver);
  27977. - if (ret)
  27978. - printk(KERN_ERR "Unable to unregister 21285 callout driver "
  27979. - "(%d)\n", ret);
  27980. - ret = tty_unregister_driver(&rs285_driver);
  27981. - if (ret)
  27982. - printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
  27983. - ret);
  27984. - free_irq(IRQ_CONTX, NULL);
  27985. - free_irq(IRQ_CONRX, NULL);
  27986. - restore_flags(flags);
  27987. -}
  27988. -
  27989. -module_init(rs285_init);
  27990. -module_exit(rs285_fini);
  27991. -
  27992. -#ifdef CONFIG_SERIAL_21285_CONSOLE
  27993. -/************** console driver *****************/
  27994. -
  27995. -static void rs285_console_write(struct console *co, const char *s, u_int count)
  27996. -{
  27997. - int i;
  27998. -
  27999. - disable_irq(IRQ_CONTX);
  28000. - for (i = 0; i < count; i++) {
  28001. - while (*CSR_UARTFLG & 0x20);
  28002. - *CSR_UARTDR = s[i];
  28003. - if (s[i] == '\n') {
  28004. - while (*CSR_UARTFLG & 0x20);
  28005. - *CSR_UARTDR = '\r';
  28006. - }
  28007. - }
  28008. - enable_irq(IRQ_CONTX);
  28009. -}
  28010. -
  28011. -static kdev_t rs285_console_device(struct console *c)
  28012. -{
  28013. - return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
  28014. -}
  28015. -
  28016. -static int __init rs285_console_setup(struct console *co, char *options)
  28017. -{
  28018. - int baud = 9600;
  28019. - int bits = 8;
  28020. - int parity = 'n';
  28021. - int cflag = CREAD | HUPCL | CLOCAL;
  28022. -
  28023. - if (machine_is_personal_server())
  28024. - baud = 57600;
  28025. -
  28026. - if (options) {
  28027. - char *s = options;
  28028. - baud = simple_strtoul(options, NULL, 10);
  28029. - while (*s >= '0' && *s <= '9')
  28030. - s++;
  28031. - if (*s)
  28032. - parity = *s++;
  28033. - if (*s)
  28034. - bits = *s - '0';
  28035. - }
  28036. -
  28037. - /*
  28038. - * Now construct a cflag setting.
  28039. - */
  28040. - switch (baud) {
  28041. - case 1200:
  28042. - cflag |= B1200;
  28043. - break;
  28044. - case 2400:
  28045. - cflag |= B2400;
  28046. - break;
  28047. - case 4800:
  28048. - cflag |= B4800;
  28049. - break;
  28050. - case 9600:
  28051. - cflag |= B9600;
  28052. - break;
  28053. - case 19200:
  28054. - cflag |= B19200;
  28055. - break;
  28056. - case 38400:
  28057. - cflag |= B38400;
  28058. - break;
  28059. - case 57600:
  28060. - cflag |= B57600;
  28061. - break;
  28062. - case 115200:
  28063. - cflag |= B115200;
  28064. - break;
  28065. - default:
  28066. - cflag |= B9600;
  28067. - break;
  28068. - }
  28069. - switch (bits) {
  28070. - case 7:
  28071. - cflag |= CS7;
  28072. - break;
  28073. - default:
  28074. - cflag |= CS8;
  28075. - break;
  28076. - }
  28077. - switch (parity) {
  28078. - case 'o':
  28079. - case 'O':
  28080. - cflag |= PARODD;
  28081. - break;
  28082. - case 'e':
  28083. - case 'E':
  28084. - cflag |= PARENB;
  28085. - break;
  28086. - }
  28087. - co->cflag = cflag;
  28088. - rs285_set_cflag(cflag);
  28089. - rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
  28090. - if (options)
  28091. - rs285_console_write(NULL, options, strlen(options));
  28092. - else
  28093. - rs285_console_write(NULL, "no options", 10);
  28094. - rs285_console_write(NULL, "\n", 1);
  28095. -
  28096. - return 0;
  28097. -}
  28098. -
  28099. -static struct console rs285_cons =
  28100. -{
  28101. - name: SERIAL_21285_NAME,
  28102. - write: rs285_console_write,
  28103. - device: rs285_console_device,
  28104. - setup: rs285_console_setup,
  28105. - flags: CON_PRINTBUFFER,
  28106. - index: -1,
  28107. -};
  28108. -
  28109. -void __init rs285_console_init(void)
  28110. -{
  28111. - register_console(&rs285_cons);
  28112. -}
  28113. -
  28114. -#endif /* CONFIG_SERIAL_21285_CONSOLE */
  28115. -
  28116. -MODULE_LICENSE("GPL");
  28117. -EXPORT_NO_SYMBOLS;
  28118. diff -urN linux-2.4.26/drivers/char/serial_amba.c linux-2.4.26-vrs1/drivers/char/serial_amba.c
  28119. --- linux-2.4.26/drivers/char/serial_amba.c 2002-08-03 01:39:43.000000000 +0100
  28120. +++ linux-2.4.26-vrs1/drivers/char/serial_amba.c 1970-01-01 01:00:00.000000000 +0100
  28121. @@ -1,2015 +0,0 @@
  28122. -/*
  28123. - * linux/drivers/char/serial_amba.c
  28124. - *
  28125. - * Driver for AMBA serial ports
  28126. - *
  28127. - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  28128. - *
  28129. - * Copyright 1999 ARM Limited
  28130. - * Copyright (C) 2000 Deep Blue Solutions Ltd.
  28131. - *
  28132. - * This program is free software; you can redistribute it and/or modify
  28133. - * it under the terms of the GNU General Public License as published by
  28134. - * the Free Software Foundation; either version 2 of the License, or
  28135. - * (at your option) any later version.
  28136. - *
  28137. - * This program is distributed in the hope that it will be useful,
  28138. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28139. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28140. - * GNU General Public License for more details.
  28141. - *
  28142. - * You should have received a copy of the GNU General Public License
  28143. - * along with this program; if not, write to the Free Software
  28144. - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28145. - *
  28146. - *
  28147. - * This is a generic driver for ARM AMBA-type serial ports. They
  28148. - * have a lot of 16550-like features, but are not register compatable.
  28149. - * Note that although they do have CTS, DCD and DSR inputs, they do
  28150. - * not have an RI input, nor do they have DTR or RTS outputs. If
  28151. - * required, these have to be supplied via some other means (eg, GPIO)
  28152. - * and hooked into this driver.
  28153. - *
  28154. - * This could very easily become a generic serial driver for dumb UARTs
  28155. - * (eg, {82,16x}50, 21285, SA1100).
  28156. - */
  28157. -
  28158. -#include <linux/config.h>
  28159. -#include <linux/module.h>
  28160. -#include <linux/errno.h>
  28161. -#include <linux/signal.h>
  28162. -#include <linux/sched.h>
  28163. -#include <linux/interrupt.h>
  28164. -#include <linux/tty.h>
  28165. -#include <linux/tty_flip.h>
  28166. -#include <linux/major.h>
  28167. -#include <linux/string.h>
  28168. -#include <linux/fcntl.h>
  28169. -#include <linux/ptrace.h>
  28170. -#include <linux/ioport.h>
  28171. -#include <linux/mm.h>
  28172. -#include <linux/slab.h>
  28173. -#include <linux/init.h>
  28174. -#include <linux/circ_buf.h>
  28175. -#include <linux/serial.h>
  28176. -#include <linux/console.h>
  28177. -#include <linux/sysrq.h>
  28178. -
  28179. -#include <asm/system.h>
  28180. -#include <asm/io.h>
  28181. -#include <asm/irq.h>
  28182. -#include <asm/uaccess.h>
  28183. -#include <asm/bitops.h>
  28184. -
  28185. -#include <asm/hardware/serial_amba.h>
  28186. -
  28187. -#define SERIAL_AMBA_NAME "ttyAM"
  28188. -#define SERIAL_AMBA_MAJOR 204
  28189. -#define SERIAL_AMBA_MINOR 16
  28190. -#define SERIAL_AMBA_NR 2
  28191. -
  28192. -#define CALLOUT_AMBA_NAME "cuaam"
  28193. -#define CALLOUT_AMBA_MAJOR 205
  28194. -#define CALLOUT_AMBA_MINOR 16
  28195. -#define CALLOUT_AMBA_NR SERIAL_AMBA_NR
  28196. -
  28197. -#ifndef TRUE
  28198. -#define TRUE 1
  28199. -#endif
  28200. -#ifndef FALSE
  28201. -#define FALSE 0
  28202. -#endif
  28203. -
  28204. -#define DEBUG 0
  28205. -#define DEBUG_LEDS 0
  28206. -
  28207. -#if DEBUG_LEDS
  28208. -extern int get_leds(void);
  28209. -extern int set_leds(int);
  28210. -#endif
  28211. -
  28212. -/*
  28213. - * Access routines for the AMBA UARTs
  28214. - */
  28215. -#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR)
  28216. -#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR)
  28217. -#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR)
  28218. -#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c))
  28219. -#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR)
  28220. -#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR)
  28221. -#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c))
  28222. -#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L)
  28223. -#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c))
  28224. -#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M)
  28225. -#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c))
  28226. -#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H)
  28227. -#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c))
  28228. -#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
  28229. -#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
  28230. -#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
  28231. -
  28232. -#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE)
  28233. -#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS)
  28234. -
  28235. -/*
  28236. - * Things needed by tty driver
  28237. - */
  28238. -static struct tty_driver ambanormal_driver, ambacallout_driver;
  28239. -static int ambauart_refcount;
  28240. -static struct tty_struct *ambauart_table[SERIAL_AMBA_NR];
  28241. -static struct termios *ambauart_termios[SERIAL_AMBA_NR];
  28242. -static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR];
  28243. -
  28244. -#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  28245. -#define SUPPORT_SYSRQ
  28246. -#endif
  28247. -
  28248. -/*
  28249. - * Things needed internally to this driver
  28250. - */
  28251. -
  28252. -/*
  28253. - * tmp_buf is used as a temporary buffer by serial_write. We need to
  28254. - * lock it in case the copy_from_user blocks while swapping in a page,
  28255. - * and some other program tries to do a serial write at the same time.
  28256. - * Since the lock will only come under contention when the system is
  28257. - * swapping and available memory is low, it makes sense to share one
  28258. - * buffer across all the serial ports, since it significantly saves
  28259. - * memory if large numbers of serial ports are open.
  28260. - */
  28261. -static u_char *tmp_buf;
  28262. -static DECLARE_MUTEX(tmp_buf_sem);
  28263. -
  28264. -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
  28265. -
  28266. -/* number of characters left in xmit buffer before we ask for more */
  28267. -#define WAKEUP_CHARS 256
  28268. -#define AMBA_ISR_PASS_LIMIT 256
  28269. -
  28270. -#define EVT_WRITE_WAKEUP 0
  28271. -
  28272. -struct amba_icount {
  28273. - __u32 cts;
  28274. - __u32 dsr;
  28275. - __u32 rng;
  28276. - __u32 dcd;
  28277. - __u32 rx;
  28278. - __u32 tx;
  28279. - __u32 frame;
  28280. - __u32 overrun;
  28281. - __u32 parity;
  28282. - __u32 brk;
  28283. - __u32 buf_overrun;
  28284. -};
  28285. -
  28286. -/*
  28287. - * Static information about the port
  28288. - */
  28289. -struct amba_port {
  28290. - unsigned int uart_base;
  28291. - unsigned int irq;
  28292. - unsigned int uartclk;
  28293. - unsigned int fifosize;
  28294. - unsigned int tiocm_support;
  28295. - void (*set_mctrl)(struct amba_port *, u_int mctrl);
  28296. -};
  28297. -
  28298. -/*
  28299. - * This is the state information which is persistent across opens
  28300. - */
  28301. -struct amba_state {
  28302. - struct amba_icount icount;
  28303. - unsigned int line;
  28304. - unsigned int close_delay;
  28305. - unsigned int closing_wait;
  28306. - unsigned int custom_divisor;
  28307. - unsigned int flags;
  28308. - struct termios normal_termios;
  28309. - struct termios callout_termios;
  28310. -
  28311. - int count;
  28312. - struct amba_info *info;
  28313. -};
  28314. -
  28315. -#define AMBA_XMIT_SIZE 1024
  28316. -/*
  28317. - * This is the state information which is only valid when the port is open.
  28318. - */
  28319. -struct amba_info {
  28320. - struct amba_port *port;
  28321. - struct amba_state *state;
  28322. - struct tty_struct *tty;
  28323. - unsigned char x_char;
  28324. - unsigned char old_status;
  28325. - unsigned char read_status_mask;
  28326. - unsigned char ignore_status_mask;
  28327. - struct circ_buf xmit;
  28328. - unsigned int flags;
  28329. -#ifdef SUPPORT_SYSRQ
  28330. - unsigned long sysrq;
  28331. -#endif
  28332. -
  28333. - unsigned int event;
  28334. - unsigned int timeout;
  28335. - unsigned int lcr_h;
  28336. - unsigned int mctrl;
  28337. - int blocked_open;
  28338. - pid_t session;
  28339. - pid_t pgrp;
  28340. -
  28341. - struct tasklet_struct tlet;
  28342. -
  28343. - wait_queue_head_t open_wait;
  28344. - wait_queue_head_t close_wait;
  28345. - wait_queue_head_t delta_msr_wait;
  28346. -};
  28347. -
  28348. -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
  28349. -static struct console ambauart_cons;
  28350. -#endif
  28351. -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios);
  28352. -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout);
  28353. -
  28354. -#if 1 //def CONFIG_SERIAL_INTEGRATOR
  28355. -static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl)
  28356. -{
  28357. -}
  28358. -
  28359. -static struct amba_port amba_ports[SERIAL_AMBA_NR] = {
  28360. - {
  28361. - uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE),
  28362. - irq: IRQ_UARTINT0,
  28363. - uartclk: 14745600,
  28364. - fifosize: 8,
  28365. - set_mctrl: amba_set_mctrl_null,
  28366. - },
  28367. - {
  28368. - uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE),
  28369. - irq: IRQ_UARTINT1,
  28370. - uartclk: 14745600,
  28371. - fifosize: 8,
  28372. - set_mctrl: amba_set_mctrl_null,
  28373. - }
  28374. -};
  28375. -#endif
  28376. -
  28377. -static struct amba_state amba_state[SERIAL_AMBA_NR];
  28378. -
  28379. -static void ambauart_enable_rx_interrupt(struct amba_info *info)
  28380. -{
  28381. - unsigned int cr;
  28382. -
  28383. - cr = UART_GET_CR(info->port);
  28384. - cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE;
  28385. - UART_PUT_CR(info->port, cr);
  28386. -}
  28387. -
  28388. -static void ambauart_disable_rx_interrupt(struct amba_info *info)
  28389. -{
  28390. - unsigned int cr;
  28391. -
  28392. - cr = UART_GET_CR(info->port);
  28393. - cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
  28394. - UART_PUT_CR(info->port, cr);
  28395. -}
  28396. -
  28397. -static void ambauart_enable_tx_interrupt(struct amba_info *info)
  28398. -{
  28399. - unsigned int cr;
  28400. -
  28401. - cr = UART_GET_CR(info->port);
  28402. - cr |= AMBA_UARTCR_TIE;
  28403. - UART_PUT_CR(info->port, cr);
  28404. -}
  28405. -
  28406. -static void ambauart_disable_tx_interrupt(struct amba_info *info)
  28407. -{
  28408. - unsigned int cr;
  28409. -
  28410. - cr = UART_GET_CR(info->port);
  28411. - cr &= ~AMBA_UARTCR_TIE;
  28412. - UART_PUT_CR(info->port, cr);
  28413. -}
  28414. -
  28415. -static void ambauart_stop(struct tty_struct *tty)
  28416. -{
  28417. - struct amba_info *info = tty->driver_data;
  28418. - unsigned long flags;
  28419. -
  28420. - save_flags(flags); cli();
  28421. - ambauart_disable_tx_interrupt(info);
  28422. - restore_flags(flags);
  28423. -}
  28424. -
  28425. -static void ambauart_start(struct tty_struct *tty)
  28426. -{
  28427. - struct amba_info *info = tty->driver_data;
  28428. - unsigned long flags;
  28429. -
  28430. - save_flags(flags); cli();
  28431. - if (info->xmit.head != info->xmit.tail
  28432. - && info->xmit.buf)
  28433. - ambauart_enable_tx_interrupt(info);
  28434. - restore_flags(flags);
  28435. -}
  28436. -
  28437. -
  28438. -/*
  28439. - * This routine is used by the interrupt handler to schedule
  28440. - * processing in the software interrupt portion of the driver.
  28441. - */
  28442. -static void ambauart_event(struct amba_info *info, int event)
  28443. -{
  28444. - info->event |= 1 << event;
  28445. - tasklet_schedule(&info->tlet);
  28446. -}
  28447. -
  28448. -static void
  28449. -#ifdef SUPPORT_SYSRQ
  28450. -ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs)
  28451. -#else
  28452. -ambauart_rx_chars(struct amba_info *info)
  28453. -#endif
  28454. -{
  28455. - struct tty_struct *tty = info->tty;
  28456. - unsigned int status, ch, rsr, flg, ignored = 0;
  28457. - struct amba_icount *icount = &info->state->icount;
  28458. - struct amba_port *port = info->port;
  28459. -
  28460. - status = UART_GET_FR(port);
  28461. - while (UART_RX_DATA(status)) {
  28462. - ch = UART_GET_CHAR(port);
  28463. -
  28464. - if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  28465. - goto ignore_char;
  28466. - icount->rx++;
  28467. -
  28468. - flg = TTY_NORMAL;
  28469. -
  28470. - /*
  28471. - * Note that the error handling code is
  28472. - * out of the main execution path
  28473. - */
  28474. - rsr = UART_GET_RSR(port);
  28475. - if (rsr & AMBA_UARTRSR_ANY)
  28476. - goto handle_error;
  28477. -#ifdef SUPPORT_SYSRQ
  28478. - if (info->sysrq) {
  28479. - if (ch && time_before(jiffies, info->sysrq)) {
  28480. - handle_sysrq(ch, regs, NULL, NULL);
  28481. - info->sysrq = 0;
  28482. - goto ignore_char;
  28483. - }
  28484. - info->sysrq = 0;
  28485. - }
  28486. -#endif
  28487. - error_return:
  28488. - *tty->flip.flag_buf_ptr++ = flg;
  28489. - *tty->flip.char_buf_ptr++ = ch;
  28490. - tty->flip.count++;
  28491. - ignore_char:
  28492. - status = UART_GET_FR(port);
  28493. - }
  28494. -out:
  28495. - tty_flip_buffer_push(tty);
  28496. - return;
  28497. -
  28498. -handle_error:
  28499. - if (rsr & AMBA_UARTRSR_BE) {
  28500. - rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
  28501. - icount->brk++;
  28502. -
  28503. -#ifdef SUPPORT_SYSRQ
  28504. - if (info->state->line == ambauart_cons.index) {
  28505. - if (!info->sysrq) {
  28506. - info->sysrq = jiffies + HZ*5;
  28507. - goto ignore_char;
  28508. - }
  28509. - }
  28510. -#endif
  28511. - } else if (rsr & AMBA_UARTRSR_PE)
  28512. - icount->parity++;
  28513. - else if (rsr & AMBA_UARTRSR_FE)
  28514. - icount->frame++;
  28515. - if (rsr & AMBA_UARTRSR_OE)
  28516. - icount->overrun++;
  28517. -
  28518. - if (rsr & info->ignore_status_mask) {
  28519. - if (++ignored > 100)
  28520. - goto out;
  28521. - goto ignore_char;
  28522. - }
  28523. - rsr &= info->read_status_mask;
  28524. -
  28525. - if (rsr & AMBA_UARTRSR_BE)
  28526. - flg = TTY_BREAK;
  28527. - else if (rsr & AMBA_UARTRSR_PE)
  28528. - flg = TTY_PARITY;
  28529. - else if (rsr & AMBA_UARTRSR_FE)
  28530. - flg = TTY_FRAME;
  28531. -
  28532. - if (rsr & AMBA_UARTRSR_OE) {
  28533. - /*
  28534. - * CHECK: does overrun affect the current character?
  28535. - * ASSUMPTION: it does not.
  28536. - */
  28537. - *tty->flip.flag_buf_ptr++ = flg;
  28538. - *tty->flip.char_buf_ptr++ = ch;
  28539. - tty->flip.count++;
  28540. - if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  28541. - goto ignore_char;
  28542. - ch = 0;
  28543. - flg = TTY_OVERRUN;
  28544. - }
  28545. -#ifdef SUPPORT_SYSRQ
  28546. - info->sysrq = 0;
  28547. -#endif
  28548. - goto error_return;
  28549. -}
  28550. -
  28551. -static void ambauart_tx_chars(struct amba_info *info)
  28552. -{
  28553. - struct amba_port *port = info->port;
  28554. - int count;
  28555. -
  28556. - if (info->x_char) {
  28557. - UART_PUT_CHAR(port, info->x_char);
  28558. - info->state->icount.tx++;
  28559. - info->x_char = 0;
  28560. - return;
  28561. - }
  28562. - if (info->xmit.head == info->xmit.tail
  28563. - || info->tty->stopped
  28564. - || info->tty->hw_stopped) {
  28565. - ambauart_disable_tx_interrupt(info);
  28566. - return;
  28567. - }
  28568. -
  28569. - count = port->fifosize;
  28570. - do {
  28571. - UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
  28572. - info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1);
  28573. - info->state->icount.tx++;
  28574. - if (info->xmit.head == info->xmit.tail)
  28575. - break;
  28576. - } while (--count > 0);
  28577. -
  28578. - if (CIRC_CNT(info->xmit.head,
  28579. - info->xmit.tail,
  28580. - AMBA_XMIT_SIZE) < WAKEUP_CHARS)
  28581. - ambauart_event(info, EVT_WRITE_WAKEUP);
  28582. -
  28583. - if (info->xmit.head == info->xmit.tail) {
  28584. - ambauart_disable_tx_interrupt(info);
  28585. - }
  28586. -}
  28587. -
  28588. -static void ambauart_modem_status(struct amba_info *info)
  28589. -{
  28590. - unsigned int status, delta;
  28591. - struct amba_icount *icount = &info->state->icount;
  28592. -
  28593. - status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
  28594. -
  28595. - delta = status ^ info->old_status;
  28596. - info->old_status = status;
  28597. -
  28598. - if (!delta)
  28599. - return;
  28600. -
  28601. - if (delta & AMBA_UARTFR_DCD) {
  28602. - icount->dcd++;
  28603. -#ifdef CONFIG_HARD_PPS
  28604. - if ((info->flags & ASYNC_HARDPPS_CD) &&
  28605. - (status & AMBA_UARTFR_DCD)
  28606. - hardpps();
  28607. -#endif
  28608. - if (info->flags & ASYNC_CHECK_CD) {
  28609. - if (status & AMBA_UARTFR_DCD)
  28610. - wake_up_interruptible(&info->open_wait);
  28611. - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
  28612. - (info->flags & ASYNC_CALLOUT_NOHUP))) {
  28613. - if (info->tty)
  28614. - tty_hangup(info->tty);
  28615. - }
  28616. - }
  28617. - }
  28618. -
  28619. - if (delta & AMBA_UARTFR_DSR)
  28620. - icount->dsr++;
  28621. -
  28622. - if (delta & AMBA_UARTFR_CTS) {
  28623. - icount->cts++;
  28624. -
  28625. - if (info->flags & ASYNC_CTS_FLOW) {
  28626. - status &= AMBA_UARTFR_CTS;
  28627. -
  28628. - if (info->tty->hw_stopped) {
  28629. - if (status) {
  28630. - info->tty->hw_stopped = 0;
  28631. - ambauart_enable_tx_interrupt(info);
  28632. - ambauart_event(info, EVT_WRITE_WAKEUP);
  28633. - }
  28634. - } else {
  28635. - if (!status) {
  28636. - info->tty->hw_stopped = 1;
  28637. - ambauart_disable_tx_interrupt(info);
  28638. - }
  28639. - }
  28640. - }
  28641. - }
  28642. - wake_up_interruptible(&info->delta_msr_wait);
  28643. -
  28644. -}
  28645. -
  28646. -static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
  28647. -{
  28648. - struct amba_info *info = dev_id;
  28649. - unsigned int status, pass_counter = 0;
  28650. -
  28651. -#if DEBUG_LEDS
  28652. - // tell the world
  28653. - set_leds(get_leds() | RED_LED);
  28654. -#endif
  28655. -
  28656. - status = UART_GET_INT_STATUS(info->port);
  28657. - do {
  28658. - /*
  28659. - * FIXME: what about clearing the interrupts?
  28660. - */
  28661. -
  28662. - if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
  28663. -#ifdef SUPPORT_SYSRQ
  28664. - ambauart_rx_chars(info, regs);
  28665. -#else
  28666. - ambauart_rx_chars(info);
  28667. -#endif
  28668. - if (status & AMBA_UARTIIR_TIS)
  28669. - ambauart_tx_chars(info);
  28670. - if (status & AMBA_UARTIIR_MIS)
  28671. - ambauart_modem_status(info);
  28672. - if (pass_counter++ > AMBA_ISR_PASS_LIMIT)
  28673. - break;
  28674. -
  28675. - status = UART_GET_INT_STATUS(info->port);
  28676. - } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS));
  28677. -
  28678. -#if DEBUG_LEDS
  28679. - // tell the world
  28680. - set_leds(get_leds() & ~RED_LED);
  28681. -#endif
  28682. -}
  28683. -
  28684. -static void ambauart_tasklet_action(unsigned long data)
  28685. -{
  28686. - struct amba_info *info = (struct amba_info *)data;
  28687. - struct tty_struct *tty;
  28688. -
  28689. - tty = info->tty;
  28690. - if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
  28691. - return;
  28692. -
  28693. - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  28694. - tty->ldisc.write_wakeup)
  28695. - (tty->ldisc.write_wakeup)(tty);
  28696. - wake_up_interruptible(&tty->write_wait);
  28697. -}
  28698. -
  28699. -static int ambauart_startup(struct amba_info *info)
  28700. -{
  28701. - unsigned long flags;
  28702. - unsigned long page;
  28703. - int retval = 0;
  28704. -
  28705. - page = get_zeroed_page(GFP_KERNEL);
  28706. - if (!page)
  28707. - return -ENOMEM;
  28708. -
  28709. - save_flags(flags); cli();
  28710. -
  28711. - if (info->flags & ASYNC_INITIALIZED) {
  28712. - free_page(page);
  28713. - goto errout;
  28714. - }
  28715. -
  28716. - if (info->xmit.buf)
  28717. - free_page(page);
  28718. - else
  28719. - info->xmit.buf = (unsigned char *) page;
  28720. -
  28721. - /*
  28722. - * Allocate the IRQ
  28723. - */
  28724. - retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info);
  28725. - if (retval) {
  28726. - if (capable(CAP_SYS_ADMIN)) {
  28727. - if (info->tty)
  28728. - set_bit(TTY_IO_ERROR, &info->tty->flags);
  28729. - retval = 0;
  28730. - }
  28731. - goto errout;
  28732. - }
  28733. -
  28734. - info->mctrl = 0;
  28735. - if (info->tty->termios->c_cflag & CBAUD)
  28736. - info->mctrl = TIOCM_RTS | TIOCM_DTR;
  28737. - info->port->set_mctrl(info->port, info->mctrl);
  28738. -
  28739. - /*
  28740. - * initialise the old status of the modem signals
  28741. - */
  28742. - info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
  28743. -
  28744. - /*
  28745. - * Finally, enable interrupts
  28746. - */
  28747. - ambauart_enable_rx_interrupt(info);
  28748. -
  28749. - if (info->tty)
  28750. - clear_bit(TTY_IO_ERROR, &info->tty->flags);
  28751. - info->xmit.head = info->xmit.tail = 0;
  28752. -
  28753. - /*
  28754. - * Set up the tty->alt_speed kludge
  28755. - */
  28756. - if (info->tty) {
  28757. - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
  28758. - info->tty->alt_speed = 57600;
  28759. - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
  28760. - info->tty->alt_speed = 115200;
  28761. - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
  28762. - info->tty->alt_speed = 230400;
  28763. - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
  28764. - info->tty->alt_speed = 460800;
  28765. - }
  28766. -
  28767. - /*
  28768. - * and set the speed of the serial port
  28769. - */
  28770. - ambauart_change_speed(info, 0);
  28771. -
  28772. - info->flags |= ASYNC_INITIALIZED;
  28773. - restore_flags(flags);
  28774. - return 0;
  28775. -
  28776. -errout:
  28777. - restore_flags(flags);
  28778. - return retval;
  28779. -}
  28780. -
  28781. -/*
  28782. - * This routine will shutdown a serial port; interrupts are disabled, and
  28783. - * DTR is dropped if the hangup on close termio flag is on.
  28784. - */
  28785. -static void ambauart_shutdown(struct amba_info *info)
  28786. -{
  28787. - unsigned long flags;
  28788. -
  28789. - if (!(info->flags & ASYNC_INITIALIZED))
  28790. - return;
  28791. -
  28792. - save_flags(flags); cli(); /* Disable interrupts */
  28793. -
  28794. - /*
  28795. - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
  28796. - * here so the queue might never be woken up
  28797. - */
  28798. - wake_up_interruptible(&info->delta_msr_wait);
  28799. -
  28800. - /*
  28801. - * Free the IRQ
  28802. - */
  28803. - free_irq(info->port->irq, info);
  28804. -
  28805. - if (info->xmit.buf) {
  28806. - unsigned long pg = (unsigned long) info->xmit.buf;
  28807. - info->xmit.buf = NULL;
  28808. - free_page(pg);
  28809. - }
  28810. -
  28811. - /*
  28812. - * disable all interrupts, disable the port
  28813. - */
  28814. - UART_PUT_CR(info->port, 0);
  28815. -
  28816. - /* disable break condition and fifos */
  28817. - UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) &
  28818. - ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
  28819. -
  28820. - if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
  28821. - info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
  28822. - info->port->set_mctrl(info->port, info->mctrl);
  28823. -
  28824. - /* kill off our tasklet */
  28825. - tasklet_kill(&info->tlet);
  28826. - if (info->tty)
  28827. - set_bit(TTY_IO_ERROR, &info->tty->flags);
  28828. -
  28829. - info->flags &= ~ASYNC_INITIALIZED;
  28830. - restore_flags(flags);
  28831. -}
  28832. -
  28833. -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios)
  28834. -{
  28835. - unsigned int lcr_h, baud, quot, cflag, old_cr, bits;
  28836. - unsigned long flags;
  28837. -
  28838. - if (!info->tty || !info->tty->termios)
  28839. - return;
  28840. -
  28841. - cflag = info->tty->termios->c_cflag;
  28842. -
  28843. -#if DEBUG
  28844. - printk("ambauart_set_cflag(0x%x) called\n", cflag);
  28845. -#endif
  28846. - /* byte size and parity */
  28847. - switch (cflag & CSIZE) {
  28848. - case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break;
  28849. - case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break;
  28850. - case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break;
  28851. - default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8
  28852. - }
  28853. - if (cflag & CSTOPB) {
  28854. - lcr_h |= AMBA_UARTLCR_H_STP2;
  28855. - bits ++;
  28856. - }
  28857. - if (cflag & PARENB) {
  28858. - lcr_h |= AMBA_UARTLCR_H_PEN;
  28859. - bits++;
  28860. - if (!(cflag & PARODD))
  28861. - lcr_h |= AMBA_UARTLCR_H_EPS;
  28862. - }
  28863. - if (info->port->fifosize > 1)
  28864. - lcr_h |= AMBA_UARTLCR_H_FEN;
  28865. -
  28866. - do {
  28867. - /* Determine divisor based on baud rate */
  28868. - baud = tty_get_baud_rate(info->tty);
  28869. - if (!baud)
  28870. - baud = 9600;
  28871. -
  28872. - if (baud == 38400 &&
  28873. - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
  28874. - quot = info->state->custom_divisor;
  28875. - else
  28876. - quot = (info->port->uartclk / (16 * baud)) - 1;
  28877. -
  28878. - if (!quot && old_termios) {
  28879. - info->tty->termios->c_cflag &= ~CBAUD;
  28880. - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
  28881. - old_termios = NULL;
  28882. - }
  28883. - } while (quot == 0 && old_termios);
  28884. -
  28885. - /* As a last resort, if the quotient is zero, default to 9600 bps */
  28886. - if (!quot)
  28887. - quot = (info->port->uartclk / (16 * 9600)) - 1;
  28888. -
  28889. - info->timeout = (info->port->fifosize * HZ * bits * quot) /
  28890. - (info->port->uartclk / 16);
  28891. - info->timeout += HZ/50; /* Add .02 seconds of slop */
  28892. -
  28893. - if (cflag & CRTSCTS)
  28894. - info->flags |= ASYNC_CTS_FLOW;
  28895. - else
  28896. - info->flags &= ~ASYNC_CTS_FLOW;
  28897. - if (cflag & CLOCAL)
  28898. - info->flags &= ~ASYNC_CHECK_CD;
  28899. - else
  28900. - info->flags |= ASYNC_CHECK_CD;
  28901. -
  28902. - /*
  28903. - * Set up parity check flag
  28904. - */
  28905. -#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
  28906. -
  28907. - info->read_status_mask = AMBA_UARTRSR_OE;
  28908. - if (I_INPCK(info->tty))
  28909. - info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
  28910. - if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
  28911. - info->read_status_mask |= AMBA_UARTRSR_BE;
  28912. -
  28913. - /*
  28914. - * Characters to ignore
  28915. - */
  28916. - info->ignore_status_mask = 0;
  28917. - if (I_IGNPAR(info->tty))
  28918. - info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
  28919. - if (I_IGNBRK(info->tty)) {
  28920. - info->ignore_status_mask |= AMBA_UARTRSR_BE;
  28921. - /*
  28922. - * If we're ignoring parity and break indicators,
  28923. - * ignore overruns to (for real raw support).
  28924. - */
  28925. - if (I_IGNPAR(info->tty))
  28926. - info->ignore_status_mask |= AMBA_UARTRSR_OE;
  28927. - }
  28928. -
  28929. - /* first, disable everything */
  28930. - save_flags(flags); cli();
  28931. - old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE;
  28932. -
  28933. - if ((info->flags & ASYNC_HARDPPS_CD) ||
  28934. - (cflag & CRTSCTS) ||
  28935. - !(cflag & CLOCAL))
  28936. - old_cr |= AMBA_UARTCR_MSIE;
  28937. -
  28938. - UART_PUT_CR(info->port, 0);
  28939. - restore_flags(flags);
  28940. -
  28941. - /* Set baud rate */
  28942. - UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8));
  28943. - UART_PUT_LCRL(info->port, (quot & 0xff));
  28944. -
  28945. - /*
  28946. - * ----------v----------v----------v----------v-----
  28947. - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
  28948. - * ----------^----------^----------^----------^-----
  28949. - */
  28950. - UART_PUT_LCRH(info->port, lcr_h);
  28951. - UART_PUT_CR(info->port, old_cr);
  28952. -}
  28953. -
  28954. -static void ambauart_put_char(struct tty_struct *tty, u_char ch)
  28955. -{
  28956. - struct amba_info *info = tty->driver_data;
  28957. - unsigned long flags;
  28958. -
  28959. - if (!tty || !info->xmit.buf)
  28960. - return;
  28961. -
  28962. - save_flags(flags); cli();
  28963. - if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) {
  28964. - info->xmit.buf[info->xmit.head] = ch;
  28965. - info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1);
  28966. - }
  28967. - restore_flags(flags);
  28968. -}
  28969. -
  28970. -static void ambauart_flush_chars(struct tty_struct *tty)
  28971. -{
  28972. - struct amba_info *info = tty->driver_data;
  28973. - unsigned long flags;
  28974. -
  28975. - if (info->xmit.head == info->xmit.tail
  28976. - || tty->stopped
  28977. - || tty->hw_stopped
  28978. - || !info->xmit.buf)
  28979. - return;
  28980. -
  28981. - save_flags(flags); cli();
  28982. - ambauart_enable_tx_interrupt(info);
  28983. - restore_flags(flags);
  28984. -}
  28985. -
  28986. -static int ambauart_write(struct tty_struct *tty, int from_user,
  28987. - const u_char * buf, int count)
  28988. -{
  28989. - struct amba_info *info = tty->driver_data;
  28990. - unsigned long flags;
  28991. - int c, ret = 0;
  28992. -
  28993. - if (!tty || !info->xmit.buf || !tmp_buf)
  28994. - return 0;
  28995. -
  28996. - save_flags(flags);
  28997. - if (from_user) {
  28998. - down(&tmp_buf_sem);
  28999. - while (1) {
  29000. - int c1;
  29001. - c = CIRC_SPACE_TO_END(info->xmit.head,
  29002. - info->xmit.tail,
  29003. - AMBA_XMIT_SIZE);
  29004. - if (count < c)
  29005. - c = count;
  29006. - if (c <= 0)
  29007. - break;
  29008. -
  29009. - c -= copy_from_user(tmp_buf, buf, c);
  29010. - if (!c) {
  29011. - if (!ret)
  29012. - ret = -EFAULT;
  29013. - break;
  29014. - }
  29015. - cli();
  29016. - c1 = CIRC_SPACE_TO_END(info->xmit.head,
  29017. - info->xmit.tail,
  29018. - AMBA_XMIT_SIZE);
  29019. - if (c1 < c)
  29020. - c = c1;
  29021. - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
  29022. - info->xmit.head = (info->xmit.head + c) &
  29023. - (AMBA_XMIT_SIZE - 1);
  29024. - restore_flags(flags);
  29025. - buf += c;
  29026. - count -= c;
  29027. - ret += c;
  29028. - }
  29029. - up(&tmp_buf_sem);
  29030. - } else {
  29031. - cli();
  29032. - while (1) {
  29033. - c = CIRC_SPACE_TO_END(info->xmit.head,
  29034. - info->xmit.tail,
  29035. - AMBA_XMIT_SIZE);
  29036. - if (count < c)
  29037. - c = count;
  29038. - if (c <= 0)
  29039. - break;
  29040. - memcpy(info->xmit.buf + info->xmit.head, buf, c);
  29041. - info->xmit.head = (info->xmit.head + c) &
  29042. - (AMBA_XMIT_SIZE - 1);
  29043. - buf += c;
  29044. - count -= c;
  29045. - ret += c;
  29046. - }
  29047. - restore_flags(flags);
  29048. - }
  29049. - if (info->xmit.head != info->xmit.tail
  29050. - && !tty->stopped
  29051. - && !tty->hw_stopped)
  29052. - ambauart_enable_tx_interrupt(info);
  29053. - return ret;
  29054. -}
  29055. -
  29056. -static int ambauart_write_room(struct tty_struct *tty)
  29057. -{
  29058. - struct amba_info *info = tty->driver_data;
  29059. -
  29060. - return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
  29061. -}
  29062. -
  29063. -static int ambauart_chars_in_buffer(struct tty_struct *tty)
  29064. -{
  29065. - struct amba_info *info = tty->driver_data;
  29066. -
  29067. - return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
  29068. -}
  29069. -
  29070. -static void ambauart_flush_buffer(struct tty_struct *tty)
  29071. -{
  29072. - struct amba_info *info = tty->driver_data;
  29073. - unsigned long flags;
  29074. -
  29075. -#if DEBUG
  29076. - printk("ambauart_flush_buffer(%d) called\n",
  29077. - MINOR(tty->device) - tty->driver.minor_start);
  29078. -#endif
  29079. - save_flags(flags); cli();
  29080. - info->xmit.head = info->xmit.tail = 0;
  29081. - restore_flags(flags);
  29082. - wake_up_interruptible(&tty->write_wait);
  29083. - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  29084. - tty->ldisc.write_wakeup)
  29085. - (tty->ldisc.write_wakeup)(tty);
  29086. -}
  29087. -
  29088. -/*
  29089. - * This function is used to send a high-priority XON/XOFF character to
  29090. - * the device
  29091. - */
  29092. -static void ambauart_send_xchar(struct tty_struct *tty, char ch)
  29093. -{
  29094. - struct amba_info *info = tty->driver_data;
  29095. -
  29096. - info->x_char = ch;
  29097. - if (ch)
  29098. - ambauart_enable_tx_interrupt(info);
  29099. -}
  29100. -
  29101. -static void ambauart_throttle(struct tty_struct *tty)
  29102. -{
  29103. - struct amba_info *info = tty->driver_data;
  29104. - unsigned long flags;
  29105. -
  29106. - if (I_IXOFF(tty))
  29107. - ambauart_send_xchar(tty, STOP_CHAR(tty));
  29108. -
  29109. - if (tty->termios->c_cflag & CRTSCTS) {
  29110. - save_flags(flags); cli();
  29111. - info->mctrl &= ~TIOCM_RTS;
  29112. - info->port->set_mctrl(info->port, info->mctrl);
  29113. - restore_flags(flags);
  29114. - }
  29115. -}
  29116. -
  29117. -static void ambauart_unthrottle(struct tty_struct *tty)
  29118. -{
  29119. - struct amba_info *info = (struct amba_info *) tty->driver_data;
  29120. - unsigned long flags;
  29121. -
  29122. - if (I_IXOFF(tty)) {
  29123. - if (info->x_char)
  29124. - info->x_char = 0;
  29125. - else
  29126. - ambauart_send_xchar(tty, START_CHAR(tty));
  29127. - }
  29128. -
  29129. - if (tty->termios->c_cflag & CRTSCTS) {
  29130. - save_flags(flags); cli();
  29131. - info->mctrl |= TIOCM_RTS;
  29132. - info->port->set_mctrl(info->port, info->mctrl);
  29133. - restore_flags(flags);
  29134. - }
  29135. -}
  29136. -
  29137. -static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo)
  29138. -{
  29139. - struct amba_state *state = info->state;
  29140. - struct amba_port *port = info->port;
  29141. - struct serial_struct tmp;
  29142. -
  29143. - memset(&tmp, 0, sizeof(tmp));
  29144. - tmp.type = 0;
  29145. - tmp.line = state->line;
  29146. - tmp.port = port->uart_base;
  29147. - if (HIGH_BITS_OFFSET)
  29148. - tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
  29149. - tmp.irq = port->irq;
  29150. - tmp.flags = 0;
  29151. - tmp.xmit_fifo_size = port->fifosize;
  29152. - tmp.baud_base = port->uartclk / 16;
  29153. - tmp.close_delay = state->close_delay;
  29154. - tmp.closing_wait = state->closing_wait;
  29155. - tmp.custom_divisor = state->custom_divisor;
  29156. -
  29157. - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
  29158. - return -EFAULT;
  29159. - return 0;
  29160. -}
  29161. -
  29162. -static int set_serial_info(struct amba_info *info,
  29163. - struct serial_struct *newinfo)
  29164. -{
  29165. - struct serial_struct new_serial;
  29166. - struct amba_state *state, old_state;
  29167. - struct amba_port *port;
  29168. - unsigned long new_port;
  29169. - unsigned int i, change_irq, change_port;
  29170. - int retval = 0;
  29171. -
  29172. - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
  29173. - return -EFAULT;
  29174. -
  29175. - state = info->state;
  29176. - old_state = *state;
  29177. - port = info->port;
  29178. -
  29179. - new_port = new_serial.port;
  29180. - if (HIGH_BITS_OFFSET)
  29181. - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
  29182. -
  29183. - change_irq = new_serial.irq != port->irq;
  29184. - change_port = new_port != port->uart_base;
  29185. -
  29186. - if (!capable(CAP_SYS_ADMIN)) {
  29187. - if (change_irq || change_port ||
  29188. - (new_serial.baud_base != port->uartclk / 16) ||
  29189. - (new_serial.close_delay != state->close_delay) ||
  29190. - (new_serial.xmit_fifo_size != port->fifosize) ||
  29191. - ((new_serial.flags & ~ASYNC_USR_MASK) !=
  29192. - (state->flags & ~ASYNC_USR_MASK)))
  29193. - return -EPERM;
  29194. - state->flags = ((state->flags & ~ASYNC_USR_MASK) |
  29195. - (new_serial.flags & ASYNC_USR_MASK));
  29196. - info->flags = ((info->flags & ~ASYNC_USR_MASK) |
  29197. - (new_serial.flags & ASYNC_USR_MASK));
  29198. - state->custom_divisor = new_serial.custom_divisor;
  29199. - goto check_and_exit;
  29200. - }
  29201. -
  29202. - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
  29203. - (new_serial.baud_base < 9600))
  29204. - return -EINVAL;
  29205. -
  29206. - if (new_serial.type && change_port) {
  29207. - for (i = 0; i < SERIAL_AMBA_NR; i++)
  29208. - if ((port != amba_ports + i) &&
  29209. - amba_ports[i].uart_base != new_port)
  29210. - return -EADDRINUSE;
  29211. - }
  29212. -
  29213. - if ((change_port || change_irq) && (state->count > 1))
  29214. - return -EBUSY;
  29215. -
  29216. - /*
  29217. - * OK, past this point, all the error checking has been done.
  29218. - * At this point, we start making changes.....
  29219. - */
  29220. - port->uartclk = new_serial.baud_base * 16;
  29221. - state->flags = ((state->flags & ~ASYNC_FLAGS) |
  29222. - (new_serial.flags & ASYNC_FLAGS));
  29223. - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
  29224. - (info->flags & ASYNC_INTERNAL_FLAGS));
  29225. - state->custom_divisor = new_serial.custom_divisor;
  29226. - state->close_delay = new_serial.close_delay * HZ / 100;
  29227. - state->closing_wait = new_serial.closing_wait * HZ / 100;
  29228. - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
  29229. - port->fifosize = new_serial.xmit_fifo_size;
  29230. -
  29231. - if (change_port || change_irq) {
  29232. - /*
  29233. - * We need to shutdown the serial port at the old
  29234. - * port/irq combination.
  29235. - */
  29236. - ambauart_shutdown(info);
  29237. - port->irq = new_serial.irq;
  29238. - port->uart_base = new_port;
  29239. - }
  29240. -
  29241. -check_and_exit:
  29242. - if (!port->uart_base)
  29243. - return 0;
  29244. - if (info->flags & ASYNC_INITIALIZED) {
  29245. - if ((old_state.flags & ASYNC_SPD_MASK) !=
  29246. - (state->flags & ASYNC_SPD_MASK) ||
  29247. - (old_state.custom_divisor != state->custom_divisor)) {
  29248. - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
  29249. - info->tty->alt_speed = 57600;
  29250. - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
  29251. - info->tty->alt_speed = 115200;
  29252. - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
  29253. - info->tty->alt_speed = 230400;
  29254. - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
  29255. - info->tty->alt_speed = 460800;
  29256. - ambauart_change_speed(info, NULL);
  29257. - }
  29258. - } else
  29259. - retval = ambauart_startup(info);
  29260. - return retval;
  29261. -}
  29262. -
  29263. -
  29264. -/*
  29265. - * get_lsr_info - get line status register info
  29266. - */
  29267. -static int get_lsr_info(struct amba_info *info, unsigned int *value)
  29268. -{
  29269. - unsigned int result, status;
  29270. - unsigned long flags;
  29271. -
  29272. - save_flags(flags); cli();
  29273. - status = UART_GET_FR(info->port);
  29274. - restore_flags(flags);
  29275. - result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0;
  29276. -
  29277. - /*
  29278. - * If we're about to load something into the transmit
  29279. - * register, we'll pretend the transmitter isn't empty to
  29280. - * avoid a race condition (depending on when the transmit
  29281. - * interrupt happens).
  29282. - */
  29283. - if (info->x_char ||
  29284. - ((CIRC_CNT(info->xmit.head, info->xmit.tail,
  29285. - AMBA_XMIT_SIZE) > 0) &&
  29286. - !info->tty->stopped && !info->tty->hw_stopped))
  29287. - result &= TIOCSER_TEMT;
  29288. -
  29289. - return put_user(result, value);
  29290. -}
  29291. -
  29292. -static int get_modem_info(struct amba_info *info, unsigned int *value)
  29293. -{
  29294. - unsigned int result = info->mctrl;
  29295. - unsigned int status;
  29296. -
  29297. - status = UART_GET_FR(info->port);
  29298. - if (status & AMBA_UARTFR_DCD)
  29299. - result |= TIOCM_CAR;
  29300. - if (status & AMBA_UARTFR_DSR)
  29301. - result |= TIOCM_DSR;
  29302. - if (status & AMBA_UARTFR_CTS)
  29303. - result |= TIOCM_CTS;
  29304. -
  29305. - return put_user(result, value);
  29306. -}
  29307. -
  29308. -static int set_modem_info(struct amba_info *info, unsigned int cmd,
  29309. - unsigned int *value)
  29310. -{
  29311. - unsigned int arg, old;
  29312. - unsigned long flags;
  29313. -
  29314. - if (get_user(arg, value))
  29315. - return -EFAULT;
  29316. -
  29317. - old = info->mctrl;
  29318. - switch (cmd) {
  29319. - case TIOCMBIS:
  29320. - info->mctrl |= arg;
  29321. - break;
  29322. -
  29323. - case TIOCMBIC:
  29324. - info->mctrl &= ~arg;
  29325. - break;
  29326. -
  29327. - case TIOCMSET:
  29328. - info->mctrl = arg;
  29329. - break;
  29330. -
  29331. - default:
  29332. - return -EINVAL;
  29333. - }
  29334. - save_flags(flags); cli();
  29335. - if (old != info->mctrl)
  29336. - info->port->set_mctrl(info->port, info->mctrl);
  29337. - restore_flags(flags);
  29338. - return 0;
  29339. -}
  29340. -
  29341. -static void ambauart_break_ctl(struct tty_struct *tty, int break_state)
  29342. -{
  29343. - struct amba_info *info = tty->driver_data;
  29344. - unsigned long flags;
  29345. - unsigned int lcr_h;
  29346. -
  29347. - save_flags(flags); cli();
  29348. - lcr_h = UART_GET_LCRH(info->port);
  29349. - if (break_state == -1)
  29350. - lcr_h |= AMBA_UARTLCR_H_BRK;
  29351. - else
  29352. - lcr_h &= ~AMBA_UARTLCR_H_BRK;
  29353. - UART_PUT_LCRH(info->port, lcr_h);
  29354. - restore_flags(flags);
  29355. -}
  29356. -
  29357. -static int ambauart_ioctl(struct tty_struct *tty, struct file *file,
  29358. - unsigned int cmd, unsigned long arg)
  29359. -{
  29360. - struct amba_info *info = tty->driver_data;
  29361. - struct amba_icount cprev, cnow;
  29362. - struct serial_icounter_struct icount;
  29363. - unsigned long flags;
  29364. -
  29365. - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
  29366. - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
  29367. - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
  29368. - if (tty->flags & (1 << TTY_IO_ERROR))
  29369. - return -EIO;
  29370. - }
  29371. -
  29372. - switch (cmd) {
  29373. - case TIOCMGET:
  29374. - return get_modem_info(info, (unsigned int *)arg);
  29375. - case TIOCMBIS:
  29376. - case TIOCMBIC:
  29377. - case TIOCMSET:
  29378. - return set_modem_info(info, cmd, (unsigned int *)arg);
  29379. - case TIOCGSERIAL:
  29380. - return get_serial_info(info,
  29381. - (struct serial_struct *)arg);
  29382. - case TIOCSSERIAL:
  29383. - return set_serial_info(info,
  29384. - (struct serial_struct *)arg);
  29385. - case TIOCSERGETLSR: /* Get line status register */
  29386. - return get_lsr_info(info, (unsigned int *)arg);
  29387. - /*
  29388. - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
  29389. - * - mask passed in arg for lines of interest
  29390. - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
  29391. - * Caller should use TIOCGICOUNT to see which one it was
  29392. - */
  29393. - case TIOCMIWAIT:
  29394. - save_flags(flags); cli();
  29395. - /* note the counters on entry */
  29396. - cprev = info->state->icount;
  29397. - /* Force modem status interrupts on */
  29398. - UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE);
  29399. - restore_flags(flags);
  29400. - while (1) {
  29401. - interruptible_sleep_on(&info->delta_msr_wait);
  29402. - /* see if a signal did it */
  29403. - if (signal_pending(current))
  29404. - return -ERESTARTSYS;
  29405. - save_flags(flags); cli();
  29406. - cnow = info->state->icount; /* atomic copy */
  29407. - restore_flags(flags);
  29408. - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
  29409. - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
  29410. - return -EIO; /* no change => error */
  29411. - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
  29412. - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
  29413. - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
  29414. - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
  29415. - return 0;
  29416. - }
  29417. - cprev = cnow;
  29418. - }
  29419. - /* NOTREACHED */
  29420. -
  29421. - /*
  29422. - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
  29423. - * Return: write counters to the user passed counter struct
  29424. - * NB: both 1->0 and 0->1 transitions are counted except for
  29425. - * RI where only 0->1 is counted.
  29426. - */
  29427. - case TIOCGICOUNT:
  29428. - save_flags(flags); cli();
  29429. - cnow = info->state->icount;
  29430. - restore_flags(flags);
  29431. - icount.cts = cnow.cts;
  29432. - icount.dsr = cnow.dsr;
  29433. - icount.rng = cnow.rng;
  29434. - icount.dcd = cnow.dcd;
  29435. - icount.rx = cnow.rx;
  29436. - icount.tx = cnow.tx;
  29437. - icount.frame = cnow.frame;
  29438. - icount.overrun = cnow.overrun;
  29439. - icount.parity = cnow.parity;
  29440. - icount.brk = cnow.brk;
  29441. - icount.buf_overrun = cnow.buf_overrun;
  29442. -
  29443. - return copy_to_user((void *)arg, &icount, sizeof(icount))
  29444. - ? -EFAULT : 0;
  29445. -
  29446. - default:
  29447. - return -ENOIOCTLCMD;
  29448. - }
  29449. - return 0;
  29450. -}
  29451. -
  29452. -static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios)
  29453. -{
  29454. - struct amba_info *info = tty->driver_data;
  29455. - unsigned long flags;
  29456. - unsigned int cflag = tty->termios->c_cflag;
  29457. -
  29458. - if ((cflag ^ old_termios->c_cflag) == 0 &&
  29459. - RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
  29460. - return;
  29461. -
  29462. - ambauart_change_speed(info, old_termios);
  29463. -
  29464. - /* Handle transition to B0 status */
  29465. - if ((old_termios->c_cflag & CBAUD) &&
  29466. - !(cflag & CBAUD)) {
  29467. - save_flags(flags); cli();
  29468. - info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
  29469. - info->port->set_mctrl(info->port, info->mctrl);
  29470. - restore_flags(flags);
  29471. - }
  29472. -
  29473. - /* Handle transition away from B0 status */
  29474. - if (!(old_termios->c_cflag & CBAUD) &&
  29475. - (cflag & CBAUD)) {
  29476. - save_flags(flags); cli();
  29477. - info->mctrl |= TIOCM_DTR;
  29478. - if (!(cflag & CRTSCTS) ||
  29479. - !test_bit(TTY_THROTTLED, &tty->flags))
  29480. - info->mctrl |= TIOCM_RTS;
  29481. - info->port->set_mctrl(info->port, info->mctrl);
  29482. - restore_flags(flags);
  29483. - }
  29484. -
  29485. - /* Handle turning off CRTSCTS */
  29486. - if ((old_termios->c_cflag & CRTSCTS) &&
  29487. - !(cflag & CRTSCTS)) {
  29488. - tty->hw_stopped = 0;
  29489. - ambauart_start(tty);
  29490. - }
  29491. -
  29492. -#if 0
  29493. - /*
  29494. - * No need to wake up processes in open wait, since they
  29495. - * sample the CLOCAL flag once, and don't recheck it.
  29496. - * XXX It's not clear whether the current behavior is correct
  29497. - * or not. Hence, this may change.....
  29498. - */
  29499. - if (!(old_termios->c_cflag & CLOCAL) &&
  29500. - (tty->termios->c_cflag & CLOCAL))
  29501. - wake_up_interruptible(&info->open_wait);
  29502. -#endif
  29503. -}
  29504. -
  29505. -static void ambauart_close(struct tty_struct *tty, struct file *filp)
  29506. -{
  29507. - struct amba_info *info = tty->driver_data;
  29508. - struct amba_state *state;
  29509. - unsigned long flags;
  29510. -
  29511. - if (!info)
  29512. - return;
  29513. -
  29514. - state = info->state;
  29515. -
  29516. -#if DEBUG
  29517. - printk("ambauart_close() called\n");
  29518. -#endif
  29519. -
  29520. - save_flags(flags); cli();
  29521. -
  29522. - if (tty_hung_up_p(filp)) {
  29523. - MOD_DEC_USE_COUNT;
  29524. - restore_flags(flags);
  29525. - return;
  29526. - }
  29527. -
  29528. - if ((tty->count == 1) && (state->count != 1)) {
  29529. - /*
  29530. - * Uh, oh. tty->count is 1, which means that the tty
  29531. - * structure will be freed. state->count should always
  29532. - * be one in these conditions. If it's greater than
  29533. - * one, we've got real problems, since it means the
  29534. - * serial port won't be shutdown.
  29535. - */
  29536. - printk("ambauart_close: bad serial port count; tty->count is 1, "
  29537. - "state->count is %d\n", state->count);
  29538. - state->count = 1;
  29539. - }
  29540. - if (--state->count < 0) {
  29541. - printk("rs_close: bad serial port count for %s%d: %d\n",
  29542. - tty->driver.name, info->state->line, state->count);
  29543. - state->count = 0;
  29544. - }
  29545. - if (state->count) {
  29546. - MOD_DEC_USE_COUNT;
  29547. - restore_flags(flags);
  29548. - return;
  29549. - }
  29550. - info->flags |= ASYNC_CLOSING;
  29551. - restore_flags(flags);
  29552. - /*
  29553. - * Save the termios structure, since this port may have
  29554. - * separate termios for callout and dialin.
  29555. - */
  29556. - if (info->flags & ASYNC_NORMAL_ACTIVE)
  29557. - info->state->normal_termios = *tty->termios;
  29558. - if (info->flags & ASYNC_CALLOUT_ACTIVE)
  29559. - info->state->callout_termios = *tty->termios;
  29560. - /*
  29561. - * Now we wait for the transmit buffer to clear; and we notify
  29562. - * the line discipline to only process XON/XOFF characters.
  29563. - */
  29564. - tty->closing = 1;
  29565. - if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
  29566. - tty_wait_until_sent(tty, info->state->closing_wait);
  29567. - /*
  29568. - * At this point, we stop accepting input. To do this, we
  29569. - * disable the receive line status interrupts.
  29570. - */
  29571. - if (info->flags & ASYNC_INITIALIZED) {
  29572. - ambauart_disable_rx_interrupt(info);
  29573. - /*
  29574. - * Before we drop DTR, make sure the UART transmitter
  29575. - * has completely drained; this is especially
  29576. - * important if there is a transmit FIFO!
  29577. - */
  29578. - ambauart_wait_until_sent(tty, info->timeout);
  29579. - }
  29580. - ambauart_shutdown(info);
  29581. - if (tty->driver.flush_buffer)
  29582. - tty->driver.flush_buffer(tty);
  29583. - if (tty->ldisc.flush_buffer)
  29584. - tty->ldisc.flush_buffer(tty);
  29585. - tty->closing = 0;
  29586. - info->event = 0;
  29587. - info->tty = NULL;
  29588. - if (info->blocked_open) {
  29589. - if (info->state->close_delay) {
  29590. - set_current_state(TASK_INTERRUPTIBLE);
  29591. - schedule_timeout(info->state->close_delay);
  29592. - }
  29593. - wake_up_interruptible(&info->open_wait);
  29594. - }
  29595. - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
  29596. - ASYNC_CLOSING);
  29597. - wake_up_interruptible(&info->close_wait);
  29598. - MOD_DEC_USE_COUNT;
  29599. -}
  29600. -
  29601. -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
  29602. -{
  29603. - struct amba_info *info = (struct amba_info *) tty->driver_data;
  29604. - unsigned long char_time, expire;
  29605. - unsigned int status;
  29606. -
  29607. - if (info->port->fifosize == 0)
  29608. - return;
  29609. -
  29610. - /*
  29611. - * Set the check interval to be 1/5 of the estimated time to
  29612. - * send a single character, and make it at least 1. The check
  29613. - * interval should also be less than the timeout.
  29614. - *
  29615. - * Note: we have to use pretty tight timings here to satisfy
  29616. - * the NIST-PCTS.
  29617. - */
  29618. - char_time = (info->timeout - HZ/50) / info->port->fifosize;
  29619. - char_time = char_time / 5;
  29620. - if (char_time == 0)
  29621. - char_time = 1;
  29622. - if (timeout && timeout < char_time)
  29623. - char_time = timeout;
  29624. - /*
  29625. - * If the transmitter hasn't cleared in twice the approximate
  29626. - * amount of time to send the entire FIFO, it probably won't
  29627. - * ever clear. This assumes the UART isn't doing flow
  29628. - * control, which is currently the case. Hence, if it ever
  29629. - * takes longer than info->timeout, this is probably due to a
  29630. - * UART bug of some kind. So, we clamp the timeout parameter at
  29631. - * 2*info->timeout.
  29632. - */
  29633. - if (!timeout || timeout > 2 * info->timeout)
  29634. - timeout = 2 * info->timeout;
  29635. -
  29636. - expire = jiffies + timeout;
  29637. -#if DEBUG
  29638. - printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
  29639. - MINOR(tty->device) - tty->driver.minor_start, jiffies,
  29640. - expire);
  29641. -#endif
  29642. - while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
  29643. - set_current_state(TASK_INTERRUPTIBLE);
  29644. - schedule_timeout(char_time);
  29645. - if (signal_pending(current))
  29646. - break;
  29647. - if (timeout && time_after(jiffies, expire))
  29648. - break;
  29649. - status = UART_GET_FR(info->port);
  29650. - }
  29651. - set_current_state(TASK_RUNNING);
  29652. -}
  29653. -
  29654. -static void ambauart_hangup(struct tty_struct *tty)
  29655. -{
  29656. - struct amba_info *info = tty->driver_data;
  29657. - struct amba_state *state = info->state;
  29658. -
  29659. - ambauart_flush_buffer(tty);
  29660. - if (info->flags & ASYNC_CLOSING)
  29661. - return;
  29662. - ambauart_shutdown(info);
  29663. - info->event = 0;
  29664. - state->count = 0;
  29665. - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
  29666. - info->tty = NULL;
  29667. - wake_up_interruptible(&info->open_wait);
  29668. -}
  29669. -
  29670. -static int block_til_ready(struct tty_struct *tty, struct file *filp,
  29671. - struct amba_info *info)
  29672. -{
  29673. - DECLARE_WAITQUEUE(wait, current);
  29674. - struct amba_state *state = info->state;
  29675. - unsigned long flags;
  29676. - int do_clocal = 0, extra_count = 0, retval;
  29677. -
  29678. - /*
  29679. - * If the device is in the middle of being closed, then block
  29680. - * until it's done, and then try again.
  29681. - */
  29682. - if (tty_hung_up_p(filp) ||
  29683. - (info->flags & ASYNC_CLOSING)) {
  29684. - if (info->flags & ASYNC_CLOSING)
  29685. - interruptible_sleep_on(&info->close_wait);
  29686. - return (info->flags & ASYNC_HUP_NOTIFY) ?
  29687. - -EAGAIN : -ERESTARTSYS;
  29688. - }
  29689. -
  29690. - /*
  29691. - * If this is a callout device, then just make sure the normal
  29692. - * device isn't being used.
  29693. - */
  29694. - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
  29695. - if (info->flags & ASYNC_NORMAL_ACTIVE)
  29696. - return -EBUSY;
  29697. - if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
  29698. - (info->flags & ASYNC_SESSION_LOCKOUT) &&
  29699. - (info->session != current->session))
  29700. - return -EBUSY;
  29701. - if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
  29702. - (info->flags & ASYNC_PGRP_LOCKOUT) &&
  29703. - (info->pgrp != current->pgrp))
  29704. - return -EBUSY;
  29705. - info->flags |= ASYNC_CALLOUT_ACTIVE;
  29706. - return 0;
  29707. - }
  29708. -
  29709. - /*
  29710. - * If non-blocking mode is set, or the port is not enabled,
  29711. - * then make the check up front and then exit.
  29712. - */
  29713. - if ((filp->f_flags & O_NONBLOCK) ||
  29714. - (tty->flags & (1 << TTY_IO_ERROR))) {
  29715. - if (info->flags & ASYNC_CALLOUT_ACTIVE)
  29716. - return -EBUSY;
  29717. - info->flags |= ASYNC_NORMAL_ACTIVE;
  29718. - return 0;
  29719. - }
  29720. -
  29721. - if (info->flags & ASYNC_CALLOUT_ACTIVE) {
  29722. - if (state->normal_termios.c_cflag & CLOCAL)
  29723. - do_clocal = 1;
  29724. - } else {
  29725. - if (tty->termios->c_cflag & CLOCAL)
  29726. - do_clocal = 1;
  29727. - }
  29728. -
  29729. - /*
  29730. - * Block waiting for the carrier detect and the line to become
  29731. - * free (i.e., not in use by the callout). While we are in
  29732. - * this loop, state->count is dropped by one, so that
  29733. - * rs_close() knows when to free things. We restore it upon
  29734. - * exit, either normal or abnormal.
  29735. - */
  29736. - retval = 0;
  29737. - add_wait_queue(&info->open_wait, &wait);
  29738. - save_flags(flags); cli();
  29739. - if (!tty_hung_up_p(filp)) {
  29740. - extra_count = 1;
  29741. - state->count--;
  29742. - }
  29743. - restore_flags(flags);
  29744. - info->blocked_open++;
  29745. - while (1) {
  29746. - save_flags(flags); cli();
  29747. - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
  29748. - (tty->termios->c_cflag & CBAUD)) {
  29749. - info->mctrl = TIOCM_DTR | TIOCM_RTS;
  29750. - info->port->set_mctrl(info->port, info->mctrl);
  29751. - }
  29752. - restore_flags(flags);
  29753. - set_current_state(TASK_INTERRUPTIBLE);
  29754. - if (tty_hung_up_p(filp) ||
  29755. - !(info->flags & ASYNC_INITIALIZED)) {
  29756. - if (info->flags & ASYNC_HUP_NOTIFY)
  29757. - retval = -EAGAIN;
  29758. - else
  29759. - retval = -ERESTARTSYS;
  29760. - break;
  29761. - }
  29762. - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
  29763. - !(info->flags & ASYNC_CLOSING) &&
  29764. - (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD)))
  29765. - break;
  29766. - if (signal_pending(current)) {
  29767. - retval = -ERESTARTSYS;
  29768. - break;
  29769. - }
  29770. - schedule();
  29771. - }
  29772. - set_current_state(TASK_RUNNING);
  29773. - remove_wait_queue(&info->open_wait, &wait);
  29774. - if (extra_count)
  29775. - state->count++;
  29776. - info->blocked_open--;
  29777. - if (retval)
  29778. - return retval;
  29779. - info->flags |= ASYNC_NORMAL_ACTIVE;
  29780. - return 0;
  29781. -}
  29782. -
  29783. -static struct amba_info *ambauart_get(int line)
  29784. -{
  29785. - struct amba_info *info;
  29786. - struct amba_state *state = amba_state + line;
  29787. -
  29788. - state->count++;
  29789. - if (state->info)
  29790. - return state->info;
  29791. - info = kmalloc(sizeof(struct amba_info), GFP_KERNEL);
  29792. - if (info) {
  29793. - memset(info, 0, sizeof(struct amba_info));
  29794. - init_waitqueue_head(&info->open_wait);
  29795. - init_waitqueue_head(&info->close_wait);
  29796. - init_waitqueue_head(&info->delta_msr_wait);
  29797. - info->flags = state->flags;
  29798. - info->state = state;
  29799. - info->port = amba_ports + line;
  29800. - tasklet_init(&info->tlet, ambauart_tasklet_action,
  29801. - (unsigned long)info);
  29802. - }
  29803. - if (state->info) {
  29804. - kfree(info);
  29805. - return state->info;
  29806. - }
  29807. - state->info = info;
  29808. - return info;
  29809. -}
  29810. -
  29811. -static int ambauart_open(struct tty_struct *tty, struct file *filp)
  29812. -{
  29813. - struct amba_info *info;
  29814. - int retval, line = MINOR(tty->device) - tty->driver.minor_start;
  29815. -
  29816. -#if DEBUG
  29817. - printk("ambauart_open(%d) called\n", line);
  29818. -#endif
  29819. -
  29820. - // is this a line that we've got?
  29821. - MOD_INC_USE_COUNT;
  29822. - if (line >= SERIAL_AMBA_NR) {
  29823. - MOD_DEC_USE_COUNT;
  29824. - return -ENODEV;
  29825. - }
  29826. -
  29827. - info = ambauart_get(line);
  29828. - if (!info)
  29829. - return -ENOMEM;
  29830. -
  29831. - tty->driver_data = info;
  29832. - info->tty = tty;
  29833. - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
  29834. -
  29835. - /*
  29836. - * Make sure we have the temporary buffer allocated
  29837. - */
  29838. - if (!tmp_buf) {
  29839. - unsigned long page = get_zeroed_page(GFP_KERNEL);
  29840. - if (tmp_buf)
  29841. - free_page(page);
  29842. - else if (!page) {
  29843. - MOD_DEC_USE_COUNT;
  29844. - return -ENOMEM;
  29845. - }
  29846. - tmp_buf = (u_char *)page;
  29847. - }
  29848. -
  29849. - /*
  29850. - * If the port is in the middle of closing, bail out now.
  29851. - */
  29852. - if (tty_hung_up_p(filp) ||
  29853. - (info->flags & ASYNC_CLOSING)) {
  29854. - if (info->flags & ASYNC_CLOSING)
  29855. - interruptible_sleep_on(&info->close_wait);
  29856. - MOD_DEC_USE_COUNT;
  29857. - return -EAGAIN;
  29858. - }
  29859. -
  29860. - /*
  29861. - * Start up the serial port
  29862. - */
  29863. - retval = ambauart_startup(info);
  29864. - if (retval) {
  29865. - MOD_DEC_USE_COUNT;
  29866. - return retval;
  29867. - }
  29868. -
  29869. - retval = block_til_ready(tty, filp, info);
  29870. - if (retval) {
  29871. - MOD_DEC_USE_COUNT;
  29872. - return retval;
  29873. - }
  29874. -
  29875. - if ((info->state->count == 1) &&
  29876. - (info->flags & ASYNC_SPLIT_TERMIOS)) {
  29877. - if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
  29878. - *tty->termios = info->state->normal_termios;
  29879. - else
  29880. - *tty->termios = info->state->callout_termios;
  29881. - }
  29882. -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
  29883. - if (ambauart_cons.cflag && ambauart_cons.index == line) {
  29884. - tty->termios->c_cflag = ambauart_cons.cflag;
  29885. - ambauart_cons.cflag = 0;
  29886. - }
  29887. -#endif
  29888. - ambauart_change_speed(info, NULL);
  29889. - info->session = current->session;
  29890. - info->pgrp = current->pgrp;
  29891. - return 0;
  29892. -}
  29893. -
  29894. -int __init ambauart_init(void)
  29895. -{
  29896. - int i;
  29897. -
  29898. - ambanormal_driver.magic = TTY_DRIVER_MAGIC;
  29899. - ambanormal_driver.driver_name = "serial_amba";
  29900. - ambanormal_driver.name = SERIAL_AMBA_NAME;
  29901. - ambanormal_driver.major = SERIAL_AMBA_MAJOR;
  29902. - ambanormal_driver.minor_start = SERIAL_AMBA_MINOR;
  29903. - ambanormal_driver.num = SERIAL_AMBA_NR;
  29904. - ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
  29905. - ambanormal_driver.subtype = SERIAL_TYPE_NORMAL;
  29906. - ambanormal_driver.init_termios = tty_std_termios;
  29907. - ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
  29908. - ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
  29909. - ambanormal_driver.refcount = &ambauart_refcount;
  29910. - ambanormal_driver.table = ambauart_table;
  29911. - ambanormal_driver.termios = ambauart_termios;
  29912. - ambanormal_driver.termios_locked = ambauart_termios_locked;
  29913. -
  29914. - ambanormal_driver.open = ambauart_open;
  29915. - ambanormal_driver.close = ambauart_close;
  29916. - ambanormal_driver.write = ambauart_write;
  29917. - ambanormal_driver.put_char = ambauart_put_char;
  29918. - ambanormal_driver.flush_chars = ambauart_flush_chars;
  29919. - ambanormal_driver.write_room = ambauart_write_room;
  29920. - ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer;
  29921. - ambanormal_driver.flush_buffer = ambauart_flush_buffer;
  29922. - ambanormal_driver.ioctl = ambauart_ioctl;
  29923. - ambanormal_driver.throttle = ambauart_throttle;
  29924. - ambanormal_driver.unthrottle = ambauart_unthrottle;
  29925. - ambanormal_driver.send_xchar = ambauart_send_xchar;
  29926. - ambanormal_driver.set_termios = ambauart_set_termios;
  29927. - ambanormal_driver.stop = ambauart_stop;
  29928. - ambanormal_driver.start = ambauart_start;
  29929. - ambanormal_driver.hangup = ambauart_hangup;
  29930. - ambanormal_driver.break_ctl = ambauart_break_ctl;
  29931. - ambanormal_driver.wait_until_sent = ambauart_wait_until_sent;
  29932. - ambanormal_driver.read_proc = NULL;
  29933. -
  29934. - /*
  29935. - * The callout device is just like the normal device except for
  29936. - * the major number and the subtype code.
  29937. - */
  29938. - ambacallout_driver = ambanormal_driver;
  29939. - ambacallout_driver.name = CALLOUT_AMBA_NAME;
  29940. - ambacallout_driver.major = CALLOUT_AMBA_MAJOR;
  29941. - ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT;
  29942. - ambacallout_driver.read_proc = NULL;
  29943. - ambacallout_driver.proc_entry = NULL;
  29944. -
  29945. - if (tty_register_driver(&ambanormal_driver))
  29946. - panic("Couldn't register AMBA serial driver\n");
  29947. - if (tty_register_driver(&ambacallout_driver))
  29948. - panic("Couldn't register AMBA callout driver\n");
  29949. -
  29950. - for (i = 0; i < SERIAL_AMBA_NR; i++) {
  29951. - struct amba_state *state = amba_state + i;
  29952. - state->line = i;
  29953. - state->close_delay = 5 * HZ / 10;
  29954. - state->closing_wait = 30 * HZ;
  29955. - state->callout_termios = ambacallout_driver.init_termios;
  29956. - state->normal_termios = ambanormal_driver.init_termios;
  29957. - }
  29958. -
  29959. - return 0;
  29960. -}
  29961. -
  29962. -__initcall(ambauart_init);
  29963. -
  29964. -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
  29965. -/************** console driver *****************/
  29966. -
  29967. -/*
  29968. - * This code is currently never used; console->read is never called.
  29969. - * Therefore, although we have an implementation, we don't use it.
  29970. - * FIXME: the "const char *s" should be fixed to "char *s" some day.
  29971. - * (when the definition in include/linux/console.h is also fixed)
  29972. - */
  29973. -#ifdef used_and_not_const_char_pointer
  29974. -static int ambauart_console_read(struct console *co, const char *s, u_int count)
  29975. -{
  29976. - struct amba_port *port = &amba_ports[co->index];
  29977. - unsigned int status;
  29978. - char *w;
  29979. - int c;
  29980. -#if DEBUG
  29981. - printk("ambauart_console_read() called\n");
  29982. -#endif
  29983. -
  29984. - c = 0;
  29985. - w = s;
  29986. - while (c < count) {
  29987. - status = UART_GET_FR(port);
  29988. - if (UART_RX_DATA(status)) {
  29989. - *w++ = UART_GET_CHAR(port);
  29990. - c++;
  29991. - } else {
  29992. - // nothing more to get, return
  29993. - return c;
  29994. - }
  29995. - }
  29996. - // return the count
  29997. - return c;
  29998. -}
  29999. -#endif
  30000. -
  30001. -/*
  30002. - * Print a string to the serial port trying not to disturb
  30003. - * any possible real use of the port...
  30004. - *
  30005. - * The console must be locked when we get here.
  30006. - */
  30007. -static void ambauart_console_write(struct console *co, const char *s, u_int count)
  30008. -{
  30009. - struct amba_port *port = &amba_ports[co->index];
  30010. - unsigned int status, old_cr;
  30011. - int i;
  30012. -
  30013. - /*
  30014. - * First save the CR then disable the interrupts
  30015. - */
  30016. - old_cr = UART_GET_CR(port);
  30017. - UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
  30018. -
  30019. - /*
  30020. - * Now, do each character
  30021. - */
  30022. - for (i = 0; i < count; i++) {
  30023. - do {
  30024. - status = UART_GET_FR(port);
  30025. - } while (!UART_TX_READY(status));
  30026. - UART_PUT_CHAR(port, s[i]);
  30027. - if (s[i] == '\n') {
  30028. - do {
  30029. - status = UART_GET_FR(port);
  30030. - } while (!UART_TX_READY(status));
  30031. - UART_PUT_CHAR(port, '\r');
  30032. - }
  30033. - }
  30034. -
  30035. - /*
  30036. - * Finally, wait for transmitter to become empty
  30037. - * and restore the TCR
  30038. - */
  30039. - do {
  30040. - status = UART_GET_FR(port);
  30041. - } while (status & AMBA_UARTFR_BUSY);
  30042. - UART_PUT_CR(port, old_cr);
  30043. -}
  30044. -
  30045. -static kdev_t ambauart_console_device(struct console *c)
  30046. -{
  30047. - return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
  30048. -}
  30049. -
  30050. -static int __init ambauart_console_setup(struct console *co, char *options)
  30051. -{
  30052. - struct amba_port *port;
  30053. - int baud = 38400;
  30054. - int bits = 8;
  30055. - int parity = 'n';
  30056. - u_int cflag = CREAD | HUPCL | CLOCAL;
  30057. - u_int lcr_h, quot;
  30058. -
  30059. - if (co->index >= SERIAL_AMBA_NR)
  30060. - co->index = 0;
  30061. -
  30062. - port = &amba_ports[co->index];
  30063. -
  30064. - if (options) {
  30065. - char *s = options;
  30066. - baud = simple_strtoul(s, NULL, 10);
  30067. - while (*s >= '0' && *s <= '9')
  30068. - s++;
  30069. - if (*s) parity = *s++;
  30070. - if (*s) bits = *s - '0';
  30071. - }
  30072. -
  30073. - /*
  30074. - * Now construct a cflag setting.
  30075. - */
  30076. - switch (baud) {
  30077. - case 1200: cflag |= B1200; break;
  30078. - case 2400: cflag |= B2400; break;
  30079. - case 4800: cflag |= B4800; break;
  30080. - default: cflag |= B9600; baud = 9600; break;
  30081. - case 19200: cflag |= B19200; break;
  30082. - case 38400: cflag |= B38400; break;
  30083. - case 57600: cflag |= B57600; break;
  30084. - case 115200: cflag |= B115200; break;
  30085. - }
  30086. - switch (bits) {
  30087. - case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break;
  30088. - default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break;
  30089. - }
  30090. - switch (parity) {
  30091. - case 'o':
  30092. - case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break;
  30093. - case 'e':
  30094. - case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN |
  30095. - AMBA_UARTLCR_H_EPS; break;
  30096. - }
  30097. -
  30098. - co->cflag = cflag;
  30099. -
  30100. - if (port->fifosize > 1)
  30101. - lcr_h |= AMBA_UARTLCR_H_FEN;
  30102. -
  30103. - quot = (port->uartclk / (16 * baud)) - 1;
  30104. -
  30105. - UART_PUT_LCRL(port, (quot & 0xff));
  30106. - UART_PUT_LCRM(port, (quot >> 8));
  30107. - UART_PUT_LCRH(port, lcr_h);
  30108. -
  30109. - /* we will enable the port as we need it */
  30110. - UART_PUT_CR(port, 0);
  30111. -
  30112. - return 0;
  30113. -}
  30114. -
  30115. -static struct console ambauart_cons =
  30116. -{
  30117. - name: SERIAL_AMBA_NAME,
  30118. - write: ambauart_console_write,
  30119. -#ifdef used_and_not_const_char_pointer
  30120. - read: ambauart_console_read,
  30121. -#endif
  30122. - device: ambauart_console_device,
  30123. - setup: ambauart_console_setup,
  30124. - flags: CON_PRINTBUFFER,
  30125. - index: -1,
  30126. -};
  30127. -
  30128. -void __init ambauart_console_init(void)
  30129. -{
  30130. - register_console(&ambauart_cons);
  30131. -}
  30132. -
  30133. -#endif /* CONFIG_SERIAL_AMBA_CONSOLE */
  30134. -
  30135. -MODULE_LICENSE("GPL");
  30136. -EXPORT_NO_SYMBOLS;
  30137. diff -urN linux-2.4.26/drivers/char/tty_io.c linux-2.4.26-vrs1/drivers/char/tty_io.c
  30138. --- linux-2.4.26/drivers/char/tty_io.c 2004-04-19 11:44:16.000000000 +0100
  30139. +++ linux-2.4.26-vrs1/drivers/char/tty_io.c 2004-04-18 21:47:50.000000000 +0100
  30140. @@ -19,7 +19,7 @@
  30141. * Also restructured routines so that there is more of a separation
  30142. * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
  30143. * the low-level tty routines (serial.c, pty.c, console.c). This
  30144. - * makes for cleaner and more compact code. -TYT, 9/17/92
  30145. + * makes for cleaner and more compact code. -TYT, 9/17/92
  30146. *
  30147. * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
  30148. * which can be dynamically activated and de-activated by the line
  30149. @@ -41,7 +41,7 @@
  30150. *
  30151. * New TIOCLINUX variants added.
  30152. * -- mj@k332.feld.cvut.cz, 19-Nov-95
  30153. - *
  30154. + *
  30155. * Restrict vt switching via ioctl()
  30156. * -- grif@cs.ucr.edu, 5-Dec-95
  30157. *
  30158. @@ -151,8 +151,7 @@
  30159. extern void tty3215_init(void);
  30160. extern void tub3270_con_init(void);
  30161. extern void tub3270_init(void);
  30162. -extern void rs285_console_init(void);
  30163. -extern void sa1100_rs_console_init(void);
  30164. +extern void uart_console_init(void);
  30165. extern void sgi_serial_console_init(void);
  30166. extern void sn_sal_serial_console_init(void);
  30167. extern void sci_console_init(void);
  30168. @@ -164,6 +163,7 @@
  30169. extern void txx9_serial_console_init(void);
  30170. extern void sb1250_serial_console_init(void);
  30171. extern void arc_console_init(void);
  30172. +extern void rs285_console_init(void);
  30173. extern int hvc_console_init(void);
  30174. #ifndef MIN
  30175. @@ -201,7 +201,7 @@
  30176. else
  30177. sprintf(buf, name,
  30178. idx + tty->driver.name_base);
  30179. -
  30180. +
  30181. return buf;
  30182. }
  30183. @@ -239,7 +239,7 @@
  30184. #ifdef CHECK_TTY_COUNT
  30185. struct list_head *p;
  30186. int count = 0;
  30187. -
  30188. +
  30189. file_list_lock();
  30190. for(p = tty->tty_files.next; p != &tty->tty_files; p = p->next) {
  30191. if(list_entry(p, struct file, f_list)->private_data == tty)
  30192. @@ -255,7 +255,7 @@
  30193. "!= #fd's(%d) in %s\n",
  30194. kdevname(tty->device), tty->count, count, routine);
  30195. return count;
  30196. - }
  30197. + }
  30198. #endif
  30199. return 0;
  30200. }
  30201. @@ -264,14 +264,14 @@
  30202. {
  30203. if (disc < N_TTY || disc >= NR_LDISCS)
  30204. return -EINVAL;
  30205. -
  30206. +
  30207. if (new_ldisc) {
  30208. ldiscs[disc] = *new_ldisc;
  30209. ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
  30210. ldiscs[disc].num = disc;
  30211. } else
  30212. memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
  30213. -
  30214. +
  30215. return 0;
  30216. }
  30217. @@ -301,7 +301,7 @@
  30218. o_ldisc = tty->ldisc;
  30219. tty_wait_until_sent(tty, 0);
  30220. -
  30221. +
  30222. /* Shutdown the current discipline. */
  30223. if (tty->ldisc.close)
  30224. (tty->ldisc.close)(tty);
  30225. @@ -339,7 +339,7 @@
  30226. {
  30227. int major, minor;
  30228. struct tty_driver *p;
  30229. -
  30230. +
  30231. minor = MINOR(device);
  30232. major = MAJOR(device);
  30233. @@ -456,7 +456,7 @@
  30234. redirect = NULL;
  30235. }
  30236. spin_unlock(&redirect_lock);
  30237. -
  30238. +
  30239. check_tty_count(tty, "do_tty_hangup");
  30240. file_list_lock();
  30241. for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
  30242. @@ -473,7 +473,7 @@
  30243. filp->f_op = &hung_up_tty_fops;
  30244. }
  30245. file_list_unlock();
  30246. -
  30247. +
  30248. /* FIXME! What are the locking issues here? This may me overdoing things.. */
  30249. {
  30250. unsigned long flags;
  30251. @@ -510,7 +510,7 @@
  30252. "error %d\n", -i);
  30253. }
  30254. }
  30255. -
  30256. +
  30257. read_lock(&tasklist_lock);
  30258. for_each_task(p) {
  30259. if ((tty->session > 0) && (p->session == tty->session) &&
  30260. @@ -550,7 +550,7 @@
  30261. {
  30262. #ifdef TTY_DEBUG_HANGUP
  30263. char buf[64];
  30264. -
  30265. +
  30266. printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
  30267. #endif
  30268. schedule_task(&tty->tq_hangup);
  30269. @@ -650,7 +650,7 @@
  30270. wake_up_interruptible(&tty->write_wait);
  30271. }
  30272. -static ssize_t tty_read(struct file * file, char * buf, size_t count,
  30273. +static ssize_t tty_read(struct file * file, char * buf, size_t count,
  30274. loff_t *ppos)
  30275. {
  30276. int i;
  30277. @@ -707,7 +707,7 @@
  30278. size_t count)
  30279. {
  30280. ssize_t ret = 0, written = 0;
  30281. -
  30282. +
  30283. if (file->f_flags & O_NONBLOCK) {
  30284. if (down_trylock(&tty->atomic_write))
  30285. return -EAGAIN;
  30286. @@ -835,7 +835,7 @@
  30287. struct tty_struct *tty, *o_tty;
  30288. struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
  30289. struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
  30290. - struct tty_driver *driver;
  30291. + struct tty_driver *driver;
  30292. int retval=0;
  30293. int idx;
  30294. @@ -845,7 +845,7 @@
  30295. idx = MINOR(device) - driver->minor_start;
  30296. - /*
  30297. + /*
  30298. * Check whether we need to acquire the tty semaphore to avoid
  30299. * race conditions. For now, play it safe.
  30300. */
  30301. @@ -859,7 +859,7 @@
  30302. * First time open is complex, especially for PTY devices.
  30303. * This code guarantees that either everything succeeds and the
  30304. * TTY is ready for operation, or else the table slots are vacated
  30305. - * and the allocated memory released. (Except that the termios
  30306. + * and the allocated memory released. (Except that the termios
  30307. * and locked termios may be retained.)
  30308. */
  30309. @@ -938,13 +938,13 @@
  30310. o_tty->link = tty;
  30311. }
  30312. - /*
  30313. + /*
  30314. * All structures have been allocated, so now we install them.
  30315. - * Failures after this point use release_mem to clean up, so
  30316. + * Failures after this point use release_mem to clean up, so
  30317. * there's no need to null out the local pointers.
  30318. */
  30319. driver->table[idx] = tty;
  30320. -
  30321. +
  30322. if (!*tp_loc)
  30323. *tp_loc = tp;
  30324. if (!*ltp_loc)
  30325. @@ -954,7 +954,7 @@
  30326. (*driver->refcount)++;
  30327. tty->count++;
  30328. - /*
  30329. + /*
  30330. * Structures all installed ... call the ldisc open routines.
  30331. * If we fail here just call release_mem to clean up. No need
  30332. * to decrement the use counts, as release_mem doesn't care.
  30333. @@ -988,7 +988,7 @@
  30334. if (driver->type == TTY_DRIVER_TYPE_PTY &&
  30335. driver->subtype == PTY_TYPE_MASTER) {
  30336. /*
  30337. - * special case for PTY masters: only one open permitted,
  30338. + * special case for PTY masters: only one open permitted,
  30339. * and the slave side open count is incremented as well.
  30340. */
  30341. if (tty->count) {
  30342. @@ -1002,7 +1002,7 @@
  30343. success:
  30344. *ret_tty = tty;
  30345. -
  30346. +
  30347. /* All paths come through here to release the semaphore */
  30348. end_init:
  30349. up_tty_sem(idx);
  30350. @@ -1080,7 +1080,7 @@
  30351. int pty_master, tty_closing, o_tty_closing, do_sleep;
  30352. int idx;
  30353. char buf[64];
  30354. -
  30355. +
  30356. tty = (struct tty_struct *)filp->private_data;
  30357. if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
  30358. return;
  30359. @@ -1138,7 +1138,7 @@
  30360. idx, kdevname(tty->device));
  30361. return;
  30362. }
  30363. - if (o_tty->termios_locked !=
  30364. + if (o_tty->termios_locked !=
  30365. tty->driver.other->termios_locked[idx]) {
  30366. printk(KERN_DEBUG "release_dev: other->termios_locked["
  30367. "%d] not o_termios_locked for (%s)\n",
  30368. @@ -1204,11 +1204,11 @@
  30369. printk(KERN_WARNING "release_dev: %s: read/write wait queue "
  30370. "active!\n", tty_name(tty, buf));
  30371. schedule();
  30372. - }
  30373. + }
  30374. /*
  30375. - * The closing flags are now consistent with the open counts on
  30376. - * both sides, and we've completed the last operation that could
  30377. + * The closing flags are now consistent with the open counts on
  30378. + * both sides, and we've completed the last operation that could
  30379. * block, so it's safe to proceed with closing.
  30380. */
  30381. if (pty_master) {
  30382. @@ -1266,7 +1266,7 @@
  30383. /* check whether both sides are closing ... */
  30384. if (!tty_closing || (o_tty && !o_tty_closing))
  30385. return;
  30386. -
  30387. +
  30388. #ifdef TTY_DEBUG_HANGUP
  30389. printk(KERN_DEBUG "freeing tty structure...");
  30390. #endif
  30391. @@ -1284,14 +1284,14 @@
  30392. (o_tty->ldisc.close)(o_tty);
  30393. o_tty->ldisc = ldiscs[N_TTY];
  30394. }
  30395. -
  30396. +
  30397. /*
  30398. - * Make sure that the tty's task queue isn't activated.
  30399. + * Make sure that the tty's task queue isn't activated.
  30400. */
  30401. run_task_queue(&tq_timer);
  30402. flush_scheduled_tasks();
  30403. - /*
  30404. + /*
  30405. * The release_mem function takes care of the details of clearing
  30406. * the slots and preserving the termios structure.
  30407. */
  30408. @@ -1482,7 +1482,7 @@
  30409. tty = (struct tty_struct *)filp->private_data;
  30410. if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync"))
  30411. return 0;
  30412. -
  30413. +
  30414. retval = fasync_helper(fd, filp, on, &tty->fasync);
  30415. if (retval <= 0)
  30416. return retval;
  30417. @@ -1697,7 +1697,7 @@
  30418. static int tty_generic_brk(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
  30419. {
  30420. - if (cmd == TCSBRK && arg)
  30421. + if (cmd == TCSBRK && arg)
  30422. {
  30423. /* tcdrain case */
  30424. int retval = tty_check_change(tty);
  30425. @@ -1718,7 +1718,7 @@
  30426. {
  30427. struct tty_struct *tty, *real_tty;
  30428. int retval;
  30429. -
  30430. +
  30431. tty = (struct tty_struct *)file->private_data;
  30432. if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
  30433. return -EINVAL;
  30434. @@ -1738,7 +1738,7 @@
  30435. if (tty->driver.ioctl)
  30436. return tty->driver.ioctl(tty, file, cmd, arg);
  30437. return -EINVAL;
  30438. -
  30439. +
  30440. /* These two ioctl's always return success; even if */
  30441. /* the driver doesn't support them. */
  30442. case TCSBRK:
  30443. @@ -1761,7 +1761,7 @@
  30444. case TIOCSBRK:
  30445. case TIOCCBRK:
  30446. case TCSBRK:
  30447. - case TCSBRKP:
  30448. + case TCSBRKP:
  30449. retval = tty_check_change(tty);
  30450. if (retval)
  30451. return retval;
  30452. @@ -1824,7 +1824,7 @@
  30453. case TIOCSBRK: /* Turn break on, unconditionally */
  30454. tty->driver.break_ctl(tty, -1);
  30455. return 0;
  30456. -
  30457. +
  30458. case TIOCCBRK: /* Turn break off, unconditionally */
  30459. tty->driver.break_ctl(tty, 0);
  30460. return 0;
  30461. @@ -1837,7 +1837,7 @@
  30462. if (!arg)
  30463. return send_break(tty, HZ/4);
  30464. return 0;
  30465. - case TCSBRKP: /* support for POSIX tcsendbreak() */
  30466. + case TCSBRKP: /* support for POSIX tcsendbreak() */
  30467. return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
  30468. }
  30469. if (tty->driver.ioctl) {
  30470. @@ -1859,7 +1859,7 @@
  30471. * prevent trojan horses by killing all processes associated with this
  30472. * tty when the user hits the "Secure Attention Key". Required for
  30473. * super-paranoid applications --- see the Orange Book for more details.
  30474. - *
  30475. + *
  30476. * This code could be nicer; ideally it should send a HUP, wait a few
  30477. * seconds, then send a INT, and then a KILL signal. But you then
  30478. * have to coordinate with the init process, since all processes associated
  30479. @@ -1883,7 +1883,7 @@
  30480. int session;
  30481. int i;
  30482. struct file *filp;
  30483. -
  30484. +
  30485. if (!tty)
  30486. return;
  30487. session = tty->session;
  30488. @@ -1968,7 +1968,7 @@
  30489. count = tty->flip.count;
  30490. tty->flip.count = 0;
  30491. restore_flags(flags);
  30492. -
  30493. +
  30494. tty->ldisc.receive_buf(tty, cp, fp, count);
  30495. }
  30496. @@ -2000,7 +2000,7 @@
  30497. i = cflag & CBAUD;
  30498. if (i & CBAUDEX) {
  30499. i &= ~CBAUDEX;
  30500. - if (i < 1 || i+15 >= n_baud_table)
  30501. + if (i < 1 || i+15 >= n_baud_table)
  30502. tty->termios->c_cflag &= ~CBAUDEX;
  30503. else
  30504. i += 15;
  30505. @@ -2013,7 +2013,7 @@
  30506. }
  30507. return(tty->alt_speed);
  30508. }
  30509. -
  30510. +
  30511. return baud_table[i];
  30512. }
  30513. @@ -2079,7 +2079,7 @@
  30514. mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
  30515. break;
  30516. }
  30517. - if ( (minor < driver->minor_start) ||
  30518. + if ( (minor < driver->minor_start) ||
  30519. (minor >= driver->minor_start + driver->num) ) {
  30520. printk(KERN_ERR "Attempt to register invalid minor number "
  30521. "with devfs (%d:%d).\n", (int)driver->major,(int)minor);
  30522. @@ -2132,12 +2132,12 @@
  30523. if (!driver->put_char)
  30524. driver->put_char = tty_default_put_char;
  30525. -
  30526. +
  30527. driver->prev = 0;
  30528. driver->next = tty_drivers;
  30529. if (tty_drivers) tty_drivers->prev = driver;
  30530. tty_drivers = driver;
  30531. -
  30532. +
  30533. if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
  30534. for(i = 0; i < driver->num; i++)
  30535. tty_register_devfs(driver, 0, driver->minor_start + i);
  30536. @@ -2156,7 +2156,7 @@
  30537. int i, found = 0;
  30538. struct termios *tp;
  30539. const char *othername = NULL;
  30540. -
  30541. +
  30542. if (*driver->refcount)
  30543. return -EBUSY;
  30544. @@ -2166,7 +2166,7 @@
  30545. else if (p->major == driver->major)
  30546. othername = p->name;
  30547. }
  30548. -
  30549. +
  30550. if (!found)
  30551. return -ENOENT;
  30552. @@ -2181,7 +2181,7 @@
  30553. driver->prev->next = driver->next;
  30554. else
  30555. tty_drivers = driver->next;
  30556. -
  30557. +
  30558. if (driver->next)
  30559. driver->next->prev = driver->prev;
  30560. @@ -2221,7 +2221,7 @@
  30561. (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
  30562. /*
  30563. - * Set up the standard termios. Individual tty drivers may
  30564. + * Set up the standard termios. Individual tty drivers may
  30565. * deviate from this; this is used as a template.
  30566. */
  30567. memset(&tty_std_termios, 0, sizeof(struct termios));
  30568. @@ -2233,11 +2233,11 @@
  30569. ECHOCTL | ECHOKE | IEXTEN;
  30570. /*
  30571. - * set up the console device so that later boot sequences can
  30572. + * set up the console device so that later boot sequences can
  30573. * inform about problems etc..
  30574. */
  30575. #ifdef CONFIG_EARLY_PRINTK
  30576. - disable_early_printk();
  30577. + disable_early_printk();
  30578. #endif
  30579. #ifdef CONFIG_HVC_CONSOLE
  30580. hvc_console_init();
  30581. @@ -2288,18 +2288,12 @@
  30582. #ifdef CONFIG_STDIO_CONSOLE
  30583. stdio_console_init();
  30584. #endif
  30585. -#ifdef CONFIG_SERIAL_21285_CONSOLE
  30586. - rs285_console_init();
  30587. -#endif
  30588. -#ifdef CONFIG_SERIAL_SA1100_CONSOLE
  30589. - sa1100_rs_console_init();
  30590. +#ifdef CONFIG_SERIAL_CORE_CONSOLE
  30591. + uart_console_init();
  30592. #endif
  30593. #ifdef CONFIG_ARC_CONSOLE
  30594. arc_console_init();
  30595. #endif
  30596. -#ifdef CONFIG_SERIAL_AMBA_CONSOLE
  30597. - ambauart_console_init();
  30598. -#endif
  30599. #ifdef CONFIG_SERIAL_TX3912_CONSOLE
  30600. tx3912_console_init();
  30601. #endif
  30602. @@ -2315,6 +2309,9 @@
  30603. #ifdef CONFIG_IP22_SERIAL
  30604. sgi_serial_console_init();
  30605. #endif
  30606. +#ifdef CONFIG_SERIAL_21285_CONSOLE
  30607. + rs285_console_init();
  30608. +#endif
  30609. }
  30610. static struct tty_driver dev_tty_driver, dev_syscons_driver;
  30611. @@ -2347,7 +2344,7 @@
  30612. dev_tty_driver.num = 1;
  30613. dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
  30614. dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
  30615. -
  30616. +
  30617. if (tty_register_driver(&dev_tty_driver))
  30618. panic("Couldn't register /dev/tty driver\n");
  30619. @@ -2363,7 +2360,7 @@
  30620. panic("Couldn't register /dev/console driver\n");
  30621. /* console calls tty_register_driver() before kmalloc() works.
  30622. - * Thus, we can't devfs_register() then. Do so now, instead.
  30623. + * Thus, we can't devfs_register() then. Do so now, instead.
  30624. */
  30625. #ifdef CONFIG_VT
  30626. con_init_devfs();
  30627. @@ -2381,7 +2378,7 @@
  30628. if (tty_register_driver(&dev_ptmx_driver))
  30629. panic("Couldn't register /dev/ptmx driver\n");
  30630. #endif
  30631. -
  30632. +
  30633. #ifdef CONFIG_VT
  30634. dev_console_driver = dev_tty_driver;
  30635. dev_console_driver.driver_name = "/dev/vc/0";
  30636. @@ -2441,10 +2438,10 @@
  30637. pty_init();
  30638. #ifdef CONFIG_MOXA_SMARTIO
  30639. mxser_init();
  30640. -#endif
  30641. +#endif
  30642. #ifdef CONFIG_MOXA_INTELLIO
  30643. moxa_init();
  30644. -#endif
  30645. +#endif
  30646. #ifdef CONFIG_VT
  30647. vcs_init();
  30648. #endif
  30649. diff -urN linux-2.4.26/drivers/char/wdt285.c linux-2.4.26-vrs1/drivers/char/wdt285.c
  30650. --- linux-2.4.26/drivers/char/wdt285.c 2003-06-13 15:51:33.000000000 +0100
  30651. +++ linux-2.4.26-vrs1/drivers/char/wdt285.c 2004-01-14 21:32:25.000000000 +0000
  30652. @@ -151,7 +151,7 @@
  30653. if (get_user(new_margin, (int *)arg))
  30654. return -EFAULT;
  30655. /* Arbitrary, can't find the card's limits */
  30656. - if ((new_marg < 0) || (new_margin > 60))
  30657. + if ((new_margin < 0) || (new_margin > 60))
  30658. return -EINVAL;
  30659. soft_margin = new_margin;
  30660. watchdog_ping();
  30661. diff -urN linux-2.4.26/drivers/char/wdt977.c linux-2.4.26-vrs1/drivers/char/wdt977.c
  30662. --- linux-2.4.26/drivers/char/wdt977.c 2002-11-28 23:53:12.000000000 +0000
  30663. +++ linux-2.4.26-vrs1/drivers/char/wdt977.c 2004-01-14 21:32:25.000000000 +0000
  30664. @@ -27,6 +27,7 @@
  30665. #include <asm/io.h>
  30666. #include <asm/system.h>
  30667. #include <asm/mach-types.h>
  30668. +#include <asm/uaccess.h>
  30669. #define WATCHDOG_MINOR 130
  30670. diff -urN linux-2.4.26/drivers/cpufreq/Kconfig linux-2.4.26-vrs1/drivers/cpufreq/Kconfig
  30671. --- linux-2.4.26/drivers/cpufreq/Kconfig 1970-01-01 01:00:00.000000000 +0100
  30672. +++ linux-2.4.26-vrs1/drivers/cpufreq/Kconfig 2004-01-14 21:32:25.000000000 +0000
  30673. @@ -0,0 +1,38 @@
  30674. +config CPU_FREQ_PROC_INTF
  30675. + tristate "/proc/cpufreq interface (deprecated)"
  30676. + depends on CPU_FREQ && PROC_FS
  30677. + help
  30678. + This enables the /proc/cpufreq interface for controlling
  30679. + CPUFreq. Please note that it is recommended to use the sysfs
  30680. + interface instead (which is built automatically).
  30681. +
  30682. + For details, take a look at linux/Documentation/cpufreq.
  30683. +
  30684. + If in doubt, say N.
  30685. +
  30686. +config CPU_FREQ_GOV_USERSPACE
  30687. + tristate "'userspace' governor for userspace frequency scaling"
  30688. + depends on CPU_FREQ
  30689. + help
  30690. + Enable this cpufreq governor when you either want to set the
  30691. + CPU frequency manually or when an userspace programm shall
  30692. + be able to set the CPU dynamically, like on LART
  30693. + ( http://www.lart.tudelft.nl/ )
  30694. +
  30695. + For details, take a look at linux/Documentation/cpufreq.
  30696. +
  30697. + If in doubt, say Y.
  30698. +
  30699. +config CPU_FREQ_24_API
  30700. + bool "/proc/sys/cpu/ interface (2.4. / OLD)"
  30701. + depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
  30702. + help
  30703. + This enables the /proc/sys/cpu/ sysctl interface for controlling
  30704. + the CPUFreq,"userspace" governor. This is the same interface
  30705. + as known from the.4.-kernel patches for CPUFreq, and offers
  30706. + the same functionality as long as "userspace" is the
  30707. + selected governor for the specified CPU.
  30708. +
  30709. + For details, take a look at linux/Documentation/cpufreq.
  30710. +
  30711. + If in doubt, say N.
  30712. diff -urN linux-2.4.26/drivers/cpufreq/Makefile linux-2.4.26-vrs1/drivers/cpufreq/Makefile
  30713. --- linux-2.4.26/drivers/cpufreq/Makefile 1970-01-01 01:00:00.000000000 +0100
  30714. +++ linux-2.4.26-vrs1/drivers/cpufreq/Makefile 2004-01-14 21:32:25.000000000 +0000
  30715. @@ -0,0 +1,4 @@
  30716. +#CPUfreq governors and cross-arch helpers
  30717. +obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
  30718. +obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o
  30719. +obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o
  30720. diff -urN linux-2.4.26/drivers/cpufreq/cpufreq.c linux-2.4.26-vrs1/drivers/cpufreq/cpufreq.c
  30721. --- linux-2.4.26/drivers/cpufreq/cpufreq.c 1970-01-01 01:00:00.000000000 +0100
  30722. +++ linux-2.4.26-vrs1/drivers/cpufreq/cpufreq.c 2004-01-14 21:32:25.000000000 +0000
  30723. @@ -0,0 +1,720 @@
  30724. +/*
  30725. + * linux/kernel/cpufreq.c
  30726. + *
  30727. + * Copyright (C) 2001 Russell King
  30728. + * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
  30729. + *
  30730. + * This program is free software; you can redistribute it and/or modify
  30731. + * it under the terms of the GNU General Public License version 2 as
  30732. + * published by the Free Software Foundation.
  30733. + *
  30734. + */
  30735. +
  30736. +#include <linux/kernel.h>
  30737. +#include <linux/module.h>
  30738. +#include <linux/init.h>
  30739. +#include <linux/notifier.h>
  30740. +#include <linux/cpufreq.h>
  30741. +#include <linux/delay.h>
  30742. +#include <linux/interrupt.h>
  30743. +#include <linux/spinlock.h>
  30744. +#include <linux/slab.h>
  30745. +
  30746. +#include <asm/semaphore.h>
  30747. +/**
  30748. + * The "cpufreq driver" - the arch- or hardware-dependend low
  30749. + * level driver of CPUFreq support, and its spinlock. This lock
  30750. + * also protects the cpufreq_cpu_data array.
  30751. + */
  30752. +static struct cpufreq_driver *cpufreq_driver;
  30753. +static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
  30754. +static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED;
  30755. +
  30756. +/* internal prototype */
  30757. +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
  30758. +
  30759. +
  30760. +/**
  30761. + * Two notifier lists: the "policy" list is involved in the
  30762. + * validation process for a new CPU frequency policy; the
  30763. + * "transition" list for kernel code that needs to handle
  30764. + * changes to devices when the CPU clock speed changes.
  30765. + * The mutex locks both lists.
  30766. + */
  30767. +static struct notifier_block *cpufreq_policy_notifier_list;
  30768. +static struct notifier_block *cpufreq_transition_notifier_list;
  30769. +static DECLARE_RWSEM (cpufreq_notifier_rwsem);
  30770. +
  30771. +
  30772. +static LIST_HEAD(cpufreq_governor_list);
  30773. +static DECLARE_MUTEX (cpufreq_governor_sem);
  30774. +
  30775. +/*
  30776. + * backport info:
  30777. + * we don't have a kobj we can use for ref-counting, so use a
  30778. + * "unsigned int policy->use_count" and an "unload_sem" [idea from
  30779. + * Pat Mochel's struct driver unload_sem] for proper reference counting.
  30780. + */
  30781. +
  30782. +static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
  30783. +{
  30784. + struct cpufreq_policy *data;
  30785. + unsigned long flags;
  30786. +
  30787. + if (cpu >= NR_CPUS)
  30788. + goto err_out;
  30789. +
  30790. + /* get the cpufreq driver */
  30791. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  30792. +
  30793. + if (!cpufreq_driver)
  30794. + goto err_out_unlock;
  30795. +
  30796. + /* get the CPU */
  30797. + data = cpufreq_cpu_data[cpu];
  30798. +
  30799. + if (!data)
  30800. + goto err_out_unlock;
  30801. +
  30802. + if (!data->use_count)
  30803. + goto err_out_unlock;
  30804. +
  30805. + data->use_count += 1;
  30806. +
  30807. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30808. +
  30809. + return data;
  30810. +
  30811. + err_out_unlock:
  30812. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30813. + err_out:
  30814. + return NULL;
  30815. +}
  30816. +
  30817. +static void cpufreq_cpu_put(struct cpufreq_policy *data)
  30818. +{
  30819. + unsigned long flags;
  30820. +
  30821. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  30822. + data->use_count -= 1;
  30823. + if (!data->use_count) {
  30824. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30825. + up(&data->unload_sem);
  30826. + return;
  30827. + }
  30828. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30829. +}
  30830. +
  30831. +/*********************************************************************
  30832. + * SYSFS INTERFACE *
  30833. + *********************************************************************/
  30834. +
  30835. +/**
  30836. + * cpufreq_parse_governor - parse a governor string
  30837. + */
  30838. +int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
  30839. + struct cpufreq_governor **governor)
  30840. +{
  30841. + if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
  30842. + *policy = CPUFREQ_POLICY_PERFORMANCE;
  30843. + return 0;
  30844. + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
  30845. + *policy = CPUFREQ_POLICY_POWERSAVE;
  30846. + return 0;
  30847. + } else {
  30848. + struct cpufreq_governor *t;
  30849. + down(&cpufreq_governor_sem);
  30850. + if (!cpufreq_driver || !cpufreq_driver->target)
  30851. + goto out;
  30852. + list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
  30853. + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
  30854. + *governor = t;
  30855. + *policy = CPUFREQ_POLICY_GOVERNOR;
  30856. + up(&cpufreq_governor_sem);
  30857. + return 0;
  30858. + }
  30859. + }
  30860. + out:
  30861. + up(&cpufreq_governor_sem);
  30862. + }
  30863. + return -EINVAL;
  30864. +}
  30865. +EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
  30866. +
  30867. +
  30868. +/* backport info:
  30869. + * all the sysfs stuff is missing -- of course
  30870. + */
  30871. +
  30872. +/**
  30873. + * cpufreq_add_dev - add a CPU device
  30874. + *
  30875. + * Adds the cpufreq interface for a CPU device.
  30876. + */
  30877. +static int cpufreq_add_dev (unsigned int cpu)
  30878. +{
  30879. + int ret = 0;
  30880. + struct cpufreq_policy new_policy;
  30881. + struct cpufreq_policy *policy;
  30882. + unsigned long flags;
  30883. +
  30884. + policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
  30885. + if (!policy)
  30886. + return -ENOMEM;
  30887. + memset(policy, 0, sizeof(struct cpufreq_policy));
  30888. +
  30889. + policy->cpu = cpu;
  30890. + policy->use_count = 1;
  30891. + init_MUTEX_LOCKED(&policy->lock);
  30892. + init_MUTEX_LOCKED(&policy->unload_sem);
  30893. +
  30894. + /* call driver. From then on the cpufreq must be able
  30895. + * to accept all calls to ->verify and ->setpolicy for this CPU
  30896. + */
  30897. + ret = cpufreq_driver->init(policy);
  30898. + if (ret)
  30899. + goto err_out;
  30900. +
  30901. + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
  30902. +
  30903. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  30904. + cpufreq_cpu_data[cpu] = policy;
  30905. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30906. +
  30907. + up(&policy->lock);
  30908. +
  30909. + /* set default policy */
  30910. + ret = cpufreq_set_policy(&new_policy);
  30911. + if (ret)
  30912. + goto err_out_unregister;
  30913. +
  30914. + return 0;
  30915. +
  30916. +
  30917. + err_out_unregister:
  30918. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  30919. + cpufreq_cpu_data[cpu] = NULL;
  30920. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30921. +
  30922. + err_out:
  30923. + kfree(policy);
  30924. + return ret;
  30925. +}
  30926. +
  30927. +
  30928. +/**
  30929. + * cpufreq_remove_dev - remove a CPU device
  30930. + *
  30931. + * Removes the cpufreq interface for a CPU device.
  30932. + */
  30933. +static int cpufreq_remove_dev (unsigned int cpu)
  30934. +{
  30935. + unsigned long flags;
  30936. + struct cpufreq_policy *data;
  30937. +
  30938. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  30939. + data = cpufreq_cpu_data[cpu];
  30940. + if (!data) {
  30941. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30942. + return -EINVAL;
  30943. + }
  30944. + cpufreq_cpu_data[cpu] = NULL;
  30945. +
  30946. + data->use_count -= 1;
  30947. + if (!data->use_count) {
  30948. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30949. + up(&data->unload_sem);
  30950. + } else {
  30951. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  30952. + /* this will sleep until data->use_count gets to zero */
  30953. + down(&data->unload_sem);
  30954. + up(&data->unload_sem);
  30955. + }
  30956. +
  30957. + if (cpufreq_driver->target)
  30958. + __cpufreq_governor(data, CPUFREQ_GOV_STOP);
  30959. +
  30960. + if (cpufreq_driver->exit)
  30961. + cpufreq_driver->exit(data);
  30962. +
  30963. + kfree(data);
  30964. +
  30965. + return 0;
  30966. +}
  30967. +
  30968. +
  30969. +/*********************************************************************
  30970. + * NOTIFIER LISTS INTERFACE *
  30971. + *********************************************************************/
  30972. +
  30973. +/**
  30974. + * cpufreq_register_notifier - register a driver with cpufreq
  30975. + * @nb: notifier function to register
  30976. + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
  30977. + *
  30978. + * Add a driver to one of two lists: either a list of drivers that
  30979. + * are notified about clock rate changes (once before and once after
  30980. + * the transition), or a list of drivers that are notified about
  30981. + * changes in cpufreq policy.
  30982. + *
  30983. + * This function may sleep, and has the same return conditions as
  30984. + * notifier_chain_register.
  30985. + */
  30986. +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
  30987. +{
  30988. + int ret;
  30989. +
  30990. + down_write(&cpufreq_notifier_rwsem);
  30991. + switch (list) {
  30992. + case CPUFREQ_TRANSITION_NOTIFIER:
  30993. + ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
  30994. + break;
  30995. + case CPUFREQ_POLICY_NOTIFIER:
  30996. + ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
  30997. + break;
  30998. + default:
  30999. + ret = -EINVAL;
  31000. + }
  31001. + up_write(&cpufreq_notifier_rwsem);
  31002. +
  31003. + return ret;
  31004. +}
  31005. +EXPORT_SYMBOL(cpufreq_register_notifier);
  31006. +
  31007. +
  31008. +/**
  31009. + * cpufreq_unregister_notifier - unregister a driver with cpufreq
  31010. + * @nb: notifier block to be unregistered
  31011. + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
  31012. + *
  31013. + * Remove a driver from the CPU frequency notifier list.
  31014. + *
  31015. + * This function may sleep, and has the same return conditions as
  31016. + * notifier_chain_unregister.
  31017. + */
  31018. +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
  31019. +{
  31020. + int ret;
  31021. +
  31022. + down_write(&cpufreq_notifier_rwsem);
  31023. + switch (list) {
  31024. + case CPUFREQ_TRANSITION_NOTIFIER:
  31025. + ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
  31026. + break;
  31027. + case CPUFREQ_POLICY_NOTIFIER:
  31028. + ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
  31029. + break;
  31030. + default:
  31031. + ret = -EINVAL;
  31032. + }
  31033. + up_write(&cpufreq_notifier_rwsem);
  31034. +
  31035. + return ret;
  31036. +}
  31037. +EXPORT_SYMBOL(cpufreq_unregister_notifier);
  31038. +
  31039. +
  31040. +/*********************************************************************
  31041. + * GOVERNORS *
  31042. + *********************************************************************/
  31043. +
  31044. +
  31045. +int __cpufreq_driver_target(struct cpufreq_policy *policy,
  31046. + unsigned int target_freq,
  31047. + unsigned int relation)
  31048. +{
  31049. + return cpufreq_driver->target(policy, target_freq, relation);
  31050. +}
  31051. +EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
  31052. +
  31053. +
  31054. +int cpufreq_driver_target(struct cpufreq_policy *policy,
  31055. + unsigned int target_freq,
  31056. + unsigned int relation)
  31057. +{
  31058. + unsigned int ret;
  31059. +
  31060. + policy = cpufreq_cpu_get(policy->cpu);
  31061. + if (!policy)
  31062. + return -EINVAL;
  31063. +
  31064. + down(&policy->lock);
  31065. +
  31066. + ret = __cpufreq_driver_target(policy, target_freq, relation);
  31067. +
  31068. + up(&policy->lock);
  31069. +
  31070. + cpufreq_cpu_put(policy);
  31071. +
  31072. + return ret;
  31073. +}
  31074. +EXPORT_SYMBOL_GPL(cpufreq_driver_target);
  31075. +
  31076. +
  31077. +static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
  31078. +{
  31079. + int ret = 0;
  31080. +
  31081. + switch (policy->policy) {
  31082. + case CPUFREQ_POLICY_POWERSAVE:
  31083. + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
  31084. + ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
  31085. + }
  31086. + break;
  31087. + case CPUFREQ_POLICY_PERFORMANCE:
  31088. + if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
  31089. + ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
  31090. + }
  31091. + break;
  31092. + case CPUFREQ_POLICY_GOVERNOR:
  31093. + ret = policy->governor->governor(policy, event);
  31094. + break;
  31095. + default:
  31096. + ret = -EINVAL;
  31097. + }
  31098. +
  31099. + return ret;
  31100. +}
  31101. +
  31102. +
  31103. +int cpufreq_governor(unsigned int cpu, unsigned int event)
  31104. +{
  31105. + int ret = 0;
  31106. + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
  31107. +
  31108. + if (!policy)
  31109. + return -EINVAL;
  31110. +
  31111. + down(&policy->lock);
  31112. + ret = __cpufreq_governor(policy, event);
  31113. + up(&policy->lock);
  31114. +
  31115. + cpufreq_cpu_put(policy);
  31116. +
  31117. + return ret;
  31118. +}
  31119. +EXPORT_SYMBOL_GPL(cpufreq_governor);
  31120. +
  31121. +
  31122. +int cpufreq_register_governor(struct cpufreq_governor *governor)
  31123. +{
  31124. + struct cpufreq_governor *t;
  31125. +
  31126. + if (!governor)
  31127. + return -EINVAL;
  31128. +
  31129. + if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN))
  31130. + return -EBUSY;
  31131. + if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
  31132. + return -EBUSY;
  31133. +
  31134. + down(&cpufreq_governor_sem);
  31135. +
  31136. + list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
  31137. + if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
  31138. + up(&cpufreq_governor_sem);
  31139. + return -EBUSY;
  31140. + }
  31141. + }
  31142. + list_add(&governor->governor_list, &cpufreq_governor_list);
  31143. +
  31144. + up(&cpufreq_governor_sem);
  31145. +
  31146. + return 0;
  31147. +}
  31148. +EXPORT_SYMBOL_GPL(cpufreq_register_governor);
  31149. +
  31150. +
  31151. +void cpufreq_unregister_governor(struct cpufreq_governor *governor)
  31152. +{
  31153. + /* backport info:
  31154. + * As the module usage count isn't assured in 2.4., check for removal
  31155. + * of running cpufreq governor
  31156. + */
  31157. + unsigned int i;
  31158. +
  31159. + if (!governor)
  31160. + return;
  31161. +
  31162. + down(&cpufreq_governor_sem);
  31163. +
  31164. + for (i=0; i<NR_CPUS; i++) {
  31165. + struct cpufreq_policy *policy = cpufreq_cpu_get(i);
  31166. + if (!policy)
  31167. + goto done;
  31168. + down(&policy->lock);
  31169. +
  31170. + if (policy->policy != CPUFREQ_POLICY_GOVERNOR)
  31171. + goto unlock_done;
  31172. + if (policy->governor != governor)
  31173. + goto unlock_done;
  31174. +
  31175. + /* stop old one, start performance [always present] */
  31176. + __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
  31177. + policy->policy = CPUFREQ_POLICY_PERFORMANCE;
  31178. + __cpufreq_governor(policy, CPUFREQ_GOV_START);
  31179. +
  31180. + unlock_done:
  31181. + up(&policy->lock);
  31182. + done:
  31183. + cpufreq_cpu_put(policy);
  31184. + }
  31185. + list_del(&governor->governor_list);
  31186. + up(&cpufreq_governor_sem);
  31187. + return;
  31188. +}
  31189. +EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
  31190. +
  31191. +
  31192. +
  31193. +/*********************************************************************
  31194. + * POLICY INTERFACE *
  31195. + *********************************************************************/
  31196. +
  31197. +/**
  31198. + * cpufreq_get_policy - get the current cpufreq_policy
  31199. + * @policy: struct cpufreq_policy into which the current cpufreq_policy is written
  31200. + *
  31201. + * Reads the current cpufreq policy.
  31202. + */
  31203. +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
  31204. +{
  31205. + struct cpufreq_policy *cpu_policy;
  31206. + if (!policy)
  31207. + return -EINVAL;
  31208. +
  31209. + cpu_policy = cpufreq_cpu_get(cpu);
  31210. + if (!cpu_policy)
  31211. + return -EINVAL;
  31212. +
  31213. + down(&cpu_policy->lock);
  31214. + memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
  31215. + up(&cpu_policy->lock);
  31216. +
  31217. + cpufreq_cpu_put(cpu_policy);
  31218. +
  31219. + return 0;
  31220. +}
  31221. +EXPORT_SYMBOL(cpufreq_get_policy);
  31222. +
  31223. +
  31224. +/**
  31225. + * cpufreq_set_policy - set a new CPUFreq policy
  31226. + * @policy: policy to be set.
  31227. + *
  31228. + * Sets a new CPU frequency and voltage scaling policy.
  31229. + */
  31230. +int cpufreq_set_policy(struct cpufreq_policy *policy)
  31231. +{
  31232. + int ret = 0;
  31233. + struct cpufreq_policy *data;
  31234. +
  31235. + if (!policy)
  31236. + return -EINVAL;
  31237. +
  31238. + data = cpufreq_cpu_get(policy->cpu);
  31239. + if (!data)
  31240. + return -EINVAL;
  31241. +
  31242. + /* lock this CPU */
  31243. + down(&data->lock);
  31244. +
  31245. + memcpy(&policy->cpuinfo,
  31246. + &data->cpuinfo,
  31247. + sizeof(struct cpufreq_cpuinfo));
  31248. +
  31249. + /* verify the cpu speed can be set within this limit */
  31250. + ret = cpufreq_driver->verify(policy);
  31251. + if (ret)
  31252. + goto error_out;
  31253. +
  31254. + down_read(&cpufreq_notifier_rwsem);
  31255. +
  31256. + /* adjust if necessary - all reasons */
  31257. + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
  31258. + policy);
  31259. +
  31260. + /* adjust if necessary - hardware incompatibility*/
  31261. + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
  31262. + policy);
  31263. +
  31264. + /* verify the cpu speed can be set within this limit,
  31265. + which might be different to the first one */
  31266. + ret = cpufreq_driver->verify(policy);
  31267. + if (ret) {
  31268. + up_read(&cpufreq_notifier_rwsem);
  31269. + goto error_out;
  31270. + }
  31271. +
  31272. + /* notification of the new policy */
  31273. + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
  31274. + policy);
  31275. +
  31276. + up_read(&cpufreq_notifier_rwsem);
  31277. +
  31278. + data->min = policy->min;
  31279. + data->max = policy->max;
  31280. +
  31281. + if (cpufreq_driver->setpolicy) {
  31282. + data->policy = policy->policy;
  31283. + ret = cpufreq_driver->setpolicy(policy);
  31284. + } else {
  31285. + if ((policy->policy != data->policy) ||
  31286. + ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
  31287. + /* save old, working values */
  31288. + unsigned int old_pol = data->policy;
  31289. + struct cpufreq_governor *old_gov = data->governor;
  31290. +
  31291. + /* end old governor */
  31292. + __cpufreq_governor(data, CPUFREQ_GOV_STOP);
  31293. +
  31294. + /* start new governor */
  31295. + data->policy = policy->policy;
  31296. + data->governor = policy->governor;
  31297. + if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
  31298. + /* new governor failed, so re-start old one */
  31299. + data->policy = old_pol;
  31300. + data->governor = old_gov;
  31301. + __cpufreq_governor(data, CPUFREQ_GOV_START);
  31302. + }
  31303. + /* might be a policy change, too, so fall through */
  31304. + }
  31305. + __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
  31306. + }
  31307. +
  31308. + error_out:
  31309. + up(&data->lock);
  31310. + cpufreq_cpu_put(data);
  31311. +
  31312. + return ret;
  31313. +}
  31314. +EXPORT_SYMBOL(cpufreq_set_policy);
  31315. +
  31316. +
  31317. +
  31318. +/*********************************************************************
  31319. + * EXTERNALLY AFFECTING FREQUENCY CHANGES *
  31320. + *********************************************************************/
  31321. +
  31322. +/**
  31323. + * adjust_jiffies - adjust the system "loops_per_jiffy"
  31324. + *
  31325. + * This function alters the system "loops_per_jiffy" for the clock
  31326. + * speed change. Note that loops_per_jiffy cannot be updated on SMP
  31327. + * systems as each CPU might be scaled differently. So, use the arch
  31328. + * per-CPU loops_per_jiffy value wherever possible.
  31329. + */
  31330. +#ifndef CONFIG_SMP
  31331. +static unsigned long l_p_j_ref = 0;
  31332. +static unsigned int l_p_j_ref_freq = 0;
  31333. +
  31334. +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
  31335. +{
  31336. + if (!l_p_j_ref_freq) {
  31337. + l_p_j_ref = loops_per_jiffy;
  31338. + l_p_j_ref_freq = ci->old;
  31339. + }
  31340. + if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
  31341. + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new))
  31342. + loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
  31343. +}
  31344. +#else
  31345. +#define adjust_jiffies(x...) do {} while (0)
  31346. +#endif
  31347. +
  31348. +
  31349. +/**
  31350. + * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
  31351. + *
  31352. + * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
  31353. + * twice on all CPU frequency changes that have external effects.
  31354. + */
  31355. +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
  31356. +{
  31357. + down_read(&cpufreq_notifier_rwsem);
  31358. + switch (state) {
  31359. + case CPUFREQ_PRECHANGE:
  31360. + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
  31361. + adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
  31362. + break;
  31363. + case CPUFREQ_POSTCHANGE:
  31364. + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
  31365. + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
  31366. + cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
  31367. + break;
  31368. + }
  31369. + up_read(&cpufreq_notifier_rwsem);
  31370. +}
  31371. +EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
  31372. +
  31373. +
  31374. +
  31375. +/*********************************************************************
  31376. + * REGISTER / UNREGISTER CPUFREQ DRIVER *
  31377. + *********************************************************************/
  31378. +
  31379. +/**
  31380. + * cpufreq_register_driver - register a CPU Frequency driver
  31381. + * @driver_data: A struct cpufreq_driver containing the values#
  31382. + * submitted by the CPU Frequency driver.
  31383. + *
  31384. + * Registers a CPU Frequency driver to this core code. This code
  31385. + * returns zero on success, -EBUSY when another driver got here first
  31386. + * (and isn't unregistered in the meantime).
  31387. + *
  31388. + */
  31389. +int cpufreq_register_driver(struct cpufreq_driver *driver_data)
  31390. +{
  31391. + unsigned long flags;
  31392. + unsigned int i;
  31393. +
  31394. + if (!driver_data || !driver_data->verify || !driver_data->init ||
  31395. + ((!driver_data->setpolicy) && (!driver_data->target)))
  31396. + return -EINVAL;
  31397. +
  31398. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  31399. + if (cpufreq_driver) {
  31400. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  31401. + return -EBUSY;
  31402. + }
  31403. + cpufreq_driver = driver_data;
  31404. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  31405. +
  31406. + for (i=0; i<NR_CPUS; i++) {
  31407. + if (cpu_online(i))
  31408. + cpufreq_add_dev(i);
  31409. + }
  31410. +
  31411. + return 0;
  31412. +}
  31413. +EXPORT_SYMBOL_GPL(cpufreq_register_driver);
  31414. +
  31415. +
  31416. +/**
  31417. + * cpufreq_unregister_driver - unregister the current CPUFreq driver
  31418. + *
  31419. + * Unregister the current CPUFreq driver. Only call this if you have
  31420. + * the right to do so, i.e. if you have succeeded in initialising before!
  31421. + * Returns zero if successful, and -EINVAL if the cpufreq_driver is
  31422. + * currently not initialised.
  31423. + */
  31424. +int cpufreq_unregister_driver(struct cpufreq_driver *driver)
  31425. +{
  31426. + unsigned long flags;
  31427. + unsigned int i;
  31428. +
  31429. + if (!cpufreq_driver || (driver != cpufreq_driver))
  31430. + return -EINVAL;
  31431. +
  31432. + for (i=0; i<NR_CPUS; i++) {
  31433. + if (cpu_online(i))
  31434. + cpufreq_remove_dev(i);
  31435. + }
  31436. +
  31437. + spin_lock_irqsave(&cpufreq_driver_lock, flags);
  31438. + cpufreq_driver = NULL;
  31439. + spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  31440. +
  31441. + return 0;
  31442. +}
  31443. +EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
  31444. diff -urN linux-2.4.26/drivers/cpufreq/freq_table.c linux-2.4.26-vrs1/drivers/cpufreq/freq_table.c
  31445. --- linux-2.4.26/drivers/cpufreq/freq_table.c 1970-01-01 01:00:00.000000000 +0100
  31446. +++ linux-2.4.26-vrs1/drivers/cpufreq/freq_table.c 2004-01-14 21:32:25.000000000 +0000
  31447. @@ -0,0 +1,203 @@
  31448. +/*
  31449. + * linux/drivers/cpufreq/freq_table.c
  31450. + *
  31451. + * Copyright (C) 2002 - 2003 Dominik Brodowski
  31452. + */
  31453. +
  31454. +#include <linux/kernel.h>
  31455. +#include <linux/module.h>
  31456. +#include <linux/init.h>
  31457. +#include <linux/cpufreq.h>
  31458. +
  31459. +/*********************************************************************
  31460. + * FREQUENCY TABLE HELPERS *
  31461. + *********************************************************************/
  31462. +
  31463. +int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
  31464. + struct cpufreq_frequency_table *table)
  31465. +{
  31466. + unsigned int min_freq = ~0;
  31467. + unsigned int max_freq = 0;
  31468. + unsigned int i = 0;
  31469. +
  31470. + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  31471. + unsigned int freq = table[i].frequency;
  31472. + if (freq == CPUFREQ_ENTRY_INVALID)
  31473. + continue;
  31474. + if (freq < min_freq)
  31475. + min_freq = freq;
  31476. + if (freq > max_freq)
  31477. + max_freq = freq;
  31478. + }
  31479. +
  31480. + policy->min = policy->cpuinfo.min_freq = min_freq;
  31481. + policy->max = policy->cpuinfo.max_freq = max_freq;
  31482. +
  31483. + if (policy->min == ~0)
  31484. + return -EINVAL;
  31485. + else
  31486. + return 0;
  31487. +}
  31488. +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
  31489. +
  31490. +
  31491. +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
  31492. + struct cpufreq_frequency_table *table)
  31493. +{
  31494. + unsigned int next_larger = ~0;
  31495. + unsigned int i = 0;
  31496. + unsigned int count = 0;
  31497. +
  31498. + if (!cpu_online(policy->cpu))
  31499. + return -EINVAL;
  31500. +
  31501. + cpufreq_verify_within_limits(policy,
  31502. + policy->cpuinfo.min_freq,
  31503. + policy->cpuinfo.max_freq);
  31504. +
  31505. + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  31506. + unsigned int freq = table[i].frequency;
  31507. + if (freq == CPUFREQ_ENTRY_INVALID)
  31508. + continue;
  31509. + if ((freq >= policy->min) && (freq <= policy->max))
  31510. + count++;
  31511. + else if ((next_larger > freq) && (freq > policy->max))
  31512. + next_larger = freq;
  31513. + }
  31514. +
  31515. + if (!count)
  31516. + policy->max = next_larger;
  31517. +
  31518. + cpufreq_verify_within_limits(policy,
  31519. + policy->cpuinfo.min_freq,
  31520. + policy->cpuinfo.max_freq);
  31521. +
  31522. + return 0;
  31523. +}
  31524. +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
  31525. +
  31526. +
  31527. +int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
  31528. + struct cpufreq_frequency_table *table,
  31529. + unsigned int target_freq,
  31530. + unsigned int relation,
  31531. + unsigned int *index)
  31532. +{
  31533. + struct cpufreq_frequency_table optimal = { .index = ~0, };
  31534. + struct cpufreq_frequency_table suboptimal = { .index = ~0, };
  31535. + unsigned int i;
  31536. +
  31537. + switch (relation) {
  31538. + case CPUFREQ_RELATION_H:
  31539. + optimal.frequency = 0;
  31540. + suboptimal.frequency = ~0;
  31541. + break;
  31542. + case CPUFREQ_RELATION_L:
  31543. + optimal.frequency = ~0;
  31544. + suboptimal.frequency = 0;
  31545. + break;
  31546. + }
  31547. +
  31548. + if (!cpu_online(policy->cpu))
  31549. + return -EINVAL;
  31550. +
  31551. + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  31552. + unsigned int freq = table[i].frequency;
  31553. + if (freq == CPUFREQ_ENTRY_INVALID)
  31554. + continue;
  31555. + if ((freq < policy->min) || (freq > policy->max))
  31556. + continue;
  31557. + switch(relation) {
  31558. + case CPUFREQ_RELATION_H:
  31559. + if (freq <= target_freq) {
  31560. + if (freq >= optimal.frequency) {
  31561. + optimal.frequency = freq;
  31562. + optimal.index = i;
  31563. + }
  31564. + } else {
  31565. + if (freq <= suboptimal.frequency) {
  31566. + suboptimal.frequency = freq;
  31567. + suboptimal.index = i;
  31568. + }
  31569. + }
  31570. + break;
  31571. + case CPUFREQ_RELATION_L:
  31572. + if (freq >= target_freq) {
  31573. + if (freq <= optimal.frequency) {
  31574. + optimal.frequency = freq;
  31575. + optimal.index = i;
  31576. + }
  31577. + } else {
  31578. + if (freq >= suboptimal.frequency) {
  31579. + suboptimal.frequency = freq;
  31580. + suboptimal.index = i;
  31581. + }
  31582. + }
  31583. + break;
  31584. + }
  31585. + }
  31586. + if (optimal.index > i) {
  31587. + if (suboptimal.index > i)
  31588. + return -EINVAL;
  31589. + *index = suboptimal.index;
  31590. + } else
  31591. + *index = optimal.index;
  31592. +
  31593. + return 0;
  31594. +}
  31595. +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
  31596. +
  31597. +static struct cpufreq_frequency_table *show_table[NR_CPUS];
  31598. +/**
  31599. + * show_scaling_governor - show the current policy for the specified CPU
  31600. + */
  31601. +static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
  31602. +{
  31603. + unsigned int i = 0;
  31604. + unsigned int cpu = policy->cpu;
  31605. + ssize_t count = 0;
  31606. + struct cpufreq_frequency_table *table;
  31607. +
  31608. + if (!show_table[cpu])
  31609. + return -ENODEV;
  31610. +
  31611. + table = show_table[cpu];
  31612. +
  31613. + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  31614. + if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
  31615. + continue;
  31616. + count += sprintf(&buf[count], "%d ", table[i].frequency);
  31617. + }
  31618. + count += sprintf(&buf[count], "\n");
  31619. +
  31620. + return count;
  31621. +
  31622. +}
  31623. +
  31624. +struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
  31625. + .attr = { .name = "scaling_available_frequencies", .mode = 0444 },
  31626. + .show = show_available_freqs,
  31627. +};
  31628. +EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
  31629. +
  31630. +/*
  31631. + * if you use these, you must assure that the frequency table is valid
  31632. + * all the time between get_attr and put_attr!
  31633. + */
  31634. +void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
  31635. + unsigned int cpu)
  31636. +{
  31637. + show_table[cpu] = table;
  31638. +}
  31639. +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
  31640. +
  31641. +void cpufreq_frequency_table_put_attr(unsigned int cpu)
  31642. +{
  31643. + show_table[cpu] = NULL;
  31644. +}
  31645. +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
  31646. +
  31647. +
  31648. +MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
  31649. +MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
  31650. +MODULE_LICENSE ("GPL");
  31651. diff -urN linux-2.4.26/drivers/cpufreq/proc_intf.c linux-2.4.26-vrs1/drivers/cpufreq/proc_intf.c
  31652. --- linux-2.4.26/drivers/cpufreq/proc_intf.c 1970-01-01 01:00:00.000000000 +0100
  31653. +++ linux-2.4.26-vrs1/drivers/cpufreq/proc_intf.c 2004-01-14 21:32:25.000000000 +0000
  31654. @@ -0,0 +1,244 @@
  31655. +/*
  31656. + * linux/drivers/cpufreq/proc_intf.c
  31657. + *
  31658. + * Copyright (C) 2002 - 2003 Dominik Brodowski
  31659. + */
  31660. +
  31661. +#include <linux/kernel.h>
  31662. +#include <linux/module.h>
  31663. +#include <linux/init.h>
  31664. +#include <linux/cpufreq.h>
  31665. +#include <linux/ctype.h>
  31666. +#include <linux/proc_fs.h>
  31667. +#include <asm/uaccess.h>
  31668. +
  31669. +
  31670. +/**
  31671. + * cpufreq_parse_policy - parse a policy string
  31672. + * @input_string: the string to parse.
  31673. + * @policy: the policy written inside input_string
  31674. + *
  31675. + * This function parses a "policy string" - something the user echo'es into
  31676. + * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
  31677. + * If there are invalid/missing entries, they are replaced with current
  31678. + * cpufreq policy.
  31679. + */
  31680. +static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
  31681. +{
  31682. + unsigned int min = 0;
  31683. + unsigned int max = 0;
  31684. + unsigned int cpu = 0;
  31685. + char str_governor[16];
  31686. + struct cpufreq_policy current_policy;
  31687. + unsigned int result = -EFAULT;
  31688. +
  31689. + if (!policy)
  31690. + return -EINVAL;
  31691. +
  31692. + policy->min = 0;
  31693. + policy->max = 0;
  31694. + policy->policy = 0;
  31695. + policy->cpu = CPUFREQ_ALL_CPUS;
  31696. +
  31697. + if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4)
  31698. + {
  31699. + policy->min = min;
  31700. + policy->max = max;
  31701. + policy->cpu = cpu;
  31702. + result = 0;
  31703. + goto scan_policy;
  31704. + }
  31705. + if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
  31706. + {
  31707. + if (!cpufreq_get_policy(&current_policy, cpu)) {
  31708. + policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
  31709. + policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
  31710. + policy->cpu = cpu;
  31711. + result = 0;
  31712. + goto scan_policy;
  31713. + }
  31714. + }
  31715. +
  31716. + if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3)
  31717. + {
  31718. + policy->min = min;
  31719. + policy->max = max;
  31720. + result = 0;
  31721. + goto scan_policy;
  31722. + }
  31723. +
  31724. + if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
  31725. + {
  31726. + if (!cpufreq_get_policy(&current_policy, cpu)) {
  31727. + policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
  31728. + policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
  31729. + result = 0;
  31730. + goto scan_policy;
  31731. + }
  31732. + }
  31733. +
  31734. + return -EINVAL;
  31735. +
  31736. +scan_policy:
  31737. + result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
  31738. +
  31739. + return result;
  31740. +}
  31741. +
  31742. +/**
  31743. + * cpufreq_proc_read - read /proc/cpufreq
  31744. + *
  31745. + * This function prints out the current cpufreq policy.
  31746. + */
  31747. +static int cpufreq_proc_read (
  31748. + char *page,
  31749. + char **start,
  31750. + off_t off,
  31751. + int count,
  31752. + int *eof,
  31753. + void *data)
  31754. +{
  31755. + char *p = page;
  31756. + int len = 0;
  31757. + struct cpufreq_policy policy;
  31758. + unsigned int min_pctg = 0;
  31759. + unsigned int max_pctg = 0;
  31760. + unsigned int i = 0;
  31761. +
  31762. + if (off != 0)
  31763. + goto end;
  31764. +
  31765. + p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n");
  31766. + for (i=0;i<NR_CPUS;i++) {
  31767. + if (!cpu_online(i))
  31768. + continue;
  31769. +
  31770. + if (cpufreq_get_policy(&policy, i))
  31771. + continue;
  31772. +
  31773. + if (!policy.cpuinfo.max_freq)
  31774. + continue;
  31775. +
  31776. + min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
  31777. + max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
  31778. +
  31779. + p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
  31780. + i , policy.min, min_pctg, policy.max, max_pctg);
  31781. + switch (policy.policy) {
  31782. + case CPUFREQ_POLICY_POWERSAVE:
  31783. + p += sprintf(p, "powersave\n");
  31784. + break;
  31785. + case CPUFREQ_POLICY_PERFORMANCE:
  31786. + p += sprintf(p, "performance\n");
  31787. + break;
  31788. + case CPUFREQ_POLICY_GOVERNOR:
  31789. + p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
  31790. + break;
  31791. + default:
  31792. + p += sprintf(p, "INVALID\n");
  31793. + break;
  31794. + }
  31795. + }
  31796. +end:
  31797. + len = (p - page);
  31798. + if (len <= off+count)
  31799. + *eof = 1;
  31800. + *start = page + off;
  31801. + len -= off;
  31802. + if (len>count)
  31803. + len = count;
  31804. + if (len<0)
  31805. + len = 0;
  31806. +
  31807. + return len;
  31808. +}
  31809. +
  31810. +
  31811. +/**
  31812. + * cpufreq_proc_write - handles writing into /proc/cpufreq
  31813. + *
  31814. + * This function calls the parsing script and then sets the policy
  31815. + * accordingly.
  31816. + */
  31817. +static int cpufreq_proc_write (
  31818. + struct file *file,
  31819. + const char *buffer,
  31820. + unsigned long count,
  31821. + void *data)
  31822. +{
  31823. + int result = 0;
  31824. + char proc_string[42] = {'\0'};
  31825. + struct cpufreq_policy policy;
  31826. + unsigned int i = 0;
  31827. +
  31828. +
  31829. + if ((count > sizeof(proc_string) - 1))
  31830. + return -EINVAL;
  31831. +
  31832. + if (copy_from_user(proc_string, buffer, count))
  31833. + return -EFAULT;
  31834. +
  31835. + proc_string[count] = '\0';
  31836. +
  31837. + result = cpufreq_parse_policy(proc_string, &policy);
  31838. + if (result)
  31839. + return -EFAULT;
  31840. +
  31841. + if (policy.cpu == CPUFREQ_ALL_CPUS)
  31842. + {
  31843. + for (i=0; i<NR_CPUS; i++)
  31844. + {
  31845. + policy.cpu = i;
  31846. + if (cpu_online(i))
  31847. + cpufreq_set_policy(&policy);
  31848. + }
  31849. + }
  31850. + else
  31851. + cpufreq_set_policy(&policy);
  31852. +
  31853. + return count;
  31854. +}
  31855. +
  31856. +
  31857. +/**
  31858. + * cpufreq_proc_init - add "cpufreq" to the /proc root directory
  31859. + *
  31860. + * This function adds "cpufreq" to the /proc root directory.
  31861. + */
  31862. +static int __init cpufreq_proc_init (void)
  31863. +{
  31864. + struct proc_dir_entry *entry = NULL;
  31865. +
  31866. + /* are these acceptable values? */
  31867. + entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR,
  31868. + &proc_root);
  31869. +
  31870. + if (!entry) {
  31871. + printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
  31872. + return -EIO;
  31873. + } else {
  31874. + entry->read_proc = cpufreq_proc_read;
  31875. + entry->write_proc = cpufreq_proc_write;
  31876. + }
  31877. +
  31878. + return 0;
  31879. +}
  31880. +
  31881. +
  31882. +/**
  31883. + * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
  31884. + *
  31885. + * This function removes "cpufreq" from the /proc root directory.
  31886. + */
  31887. +static void __exit cpufreq_proc_exit (void)
  31888. +{
  31889. + remove_proc_entry("cpufreq", &proc_root);
  31890. + return;
  31891. +}
  31892. +
  31893. +MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
  31894. +MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface");
  31895. +MODULE_LICENSE ("GPL");
  31896. +
  31897. +module_init(cpufreq_proc_init);
  31898. +module_exit(cpufreq_proc_exit);
  31899. diff -urN linux-2.4.26/drivers/cpufreq/userspace.c linux-2.4.26-vrs1/drivers/cpufreq/userspace.c
  31900. --- linux-2.4.26/drivers/cpufreq/userspace.c 1970-01-01 01:00:00.000000000 +0100
  31901. +++ linux-2.4.26-vrs1/drivers/cpufreq/userspace.c 2004-01-14 21:32:25.000000000 +0000
  31902. @@ -0,0 +1,591 @@
  31903. +/*
  31904. + * drivers/cpufreq/userspace.c
  31905. + *
  31906. + * Copyright (C) 2001 Russell King
  31907. + * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
  31908. + *
  31909. + * $Id: userspace.c,v 1.4 2003/03/07 10:30:20 db Exp $
  31910. + *
  31911. + * This program is free software; you can redistribute it and/or modify
  31912. + * it under the terms of the GNU General Public License version 2 as
  31913. + * published by the Free Software Foundation.
  31914. + *
  31915. + */
  31916. +
  31917. +#include <linux/kernel.h>
  31918. +#include <linux/module.h>
  31919. +#include <linux/smp.h>
  31920. +#include <linux/init.h>
  31921. +#include <linux/spinlock.h>
  31922. +#include <linux/interrupt.h>
  31923. +#include <linux/ctype.h>
  31924. +#include <linux/cpufreq.h>
  31925. +#include <linux/sysctl.h>
  31926. +#include <linux/types.h>
  31927. +#include <linux/fs.h>
  31928. +#include <linux/sysfs.h>
  31929. +
  31930. +#include <asm/uaccess.h>
  31931. +
  31932. +#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
  31933. + .ctl_name = CPU_NR_FREQ_MAX, \
  31934. + .data = &cpu_max_freq[cpunr], \
  31935. + .procname = "speed-max", \
  31936. + .maxlen = sizeof(cpu_max_freq[cpunr]),\
  31937. + .mode = 0444, \
  31938. + .proc_handler = proc_dointvec, }
  31939. +
  31940. +#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
  31941. + .ctl_name = CPU_NR_FREQ_MIN, \
  31942. + .data = &cpu_min_freq[cpunr], \
  31943. + .procname = "speed-min", \
  31944. + .maxlen = sizeof(cpu_min_freq[cpunr]),\
  31945. + .mode = 0444, \
  31946. + .proc_handler = proc_dointvec, }
  31947. +
  31948. +#define CTL_CPU_VARS_SPEED(cpunr) { \
  31949. + .ctl_name = CPU_NR_FREQ, \
  31950. + .procname = "speed", \
  31951. + .mode = 0644, \
  31952. + .proc_handler = cpufreq_procctl, \
  31953. + .strategy = cpufreq_sysctl, \
  31954. + .extra1 = (void*) (cpunr), }
  31955. +
  31956. +#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
  31957. + CTL_CPU_VARS_SPEED_MAX(cpunr), \
  31958. + CTL_CPU_VARS_SPEED_MIN(cpunr), \
  31959. + CTL_CPU_VARS_SPEED(cpunr), \
  31960. + { .ctl_name = 0, }, }
  31961. +
  31962. +/* the ctl_table entry for each CPU */
  31963. +#define CPU_ENUM(s) { \
  31964. + .ctl_name = (CPU_NR + s), \
  31965. + .procname = #s, \
  31966. + .mode = 0555, \
  31967. + .child = ctl_cpu_vars_##s }
  31968. +
  31969. +/**
  31970. + * A few values needed by the userspace governor
  31971. + */
  31972. +static unsigned int cpu_max_freq[NR_CPUS];
  31973. +static unsigned int cpu_min_freq[NR_CPUS];
  31974. +static unsigned int cpu_cur_freq[NR_CPUS];
  31975. +static unsigned int cpu_is_managed[NR_CPUS];
  31976. +static struct cpufreq_policy current_policy[NR_CPUS];
  31977. +
  31978. +static DECLARE_MUTEX (userspace_sem);
  31979. +
  31980. +
  31981. +/* keep track of frequency transitions */
  31982. +static int
  31983. +userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
  31984. + void *data)
  31985. +{
  31986. + struct cpufreq_freqs *freq = data;
  31987. +
  31988. + cpu_cur_freq[freq->cpu] = freq->new;
  31989. +
  31990. + return 0;
  31991. +}
  31992. +
  31993. +static struct notifier_block userspace_cpufreq_notifier_block = {
  31994. + .notifier_call = userspace_cpufreq_notifier
  31995. +};
  31996. +
  31997. +
  31998. +/**
  31999. + * cpufreq_set - set the CPU frequency
  32000. + * @freq: target frequency in kHz
  32001. + * @cpu: CPU for which the frequency is to be set
  32002. + *
  32003. + * Sets the CPU frequency to freq.
  32004. + */
  32005. +int cpufreq_set(unsigned int freq, unsigned int cpu)
  32006. +{
  32007. + int ret = -EINVAL;
  32008. +
  32009. + down(&userspace_sem);
  32010. + if (!cpu_is_managed[cpu])
  32011. + goto err;
  32012. +
  32013. + if (freq < cpu_min_freq[cpu])
  32014. + freq = cpu_min_freq[cpu];
  32015. + if (freq > cpu_max_freq[cpu])
  32016. + freq = cpu_max_freq[cpu];
  32017. +
  32018. + ret = cpufreq_driver_target(&current_policy[cpu], freq,
  32019. + CPUFREQ_RELATION_L);
  32020. +
  32021. + err:
  32022. + up(&userspace_sem);
  32023. + return ret;
  32024. +}
  32025. +EXPORT_SYMBOL_GPL(cpufreq_set);
  32026. +
  32027. +
  32028. +/**
  32029. + * cpufreq_setmax - set the CPU to the maximum frequency
  32030. + * @cpu - affected cpu;
  32031. + *
  32032. + * Sets the CPU frequency to the maximum frequency supported by
  32033. + * this CPU.
  32034. + */
  32035. +int cpufreq_setmax(unsigned int cpu)
  32036. +{
  32037. + if (!cpu_is_managed[cpu] || !cpu_online(cpu))
  32038. + return -EINVAL;
  32039. + return cpufreq_set(cpu_max_freq[cpu], cpu);
  32040. +}
  32041. +EXPORT_SYMBOL_GPL(cpufreq_setmax);
  32042. +
  32043. +
  32044. +/**
  32045. + * cpufreq_get - get the current CPU frequency (in kHz)
  32046. + * @cpu: CPU number
  32047. + *
  32048. + * Get the CPU current (static) CPU frequency
  32049. + */
  32050. +unsigned int cpufreq_get(unsigned int cpu)
  32051. +{
  32052. + return cpu_cur_freq[cpu];
  32053. +}
  32054. +EXPORT_SYMBOL(cpufreq_get);
  32055. +
  32056. +
  32057. +#ifdef CONFIG_CPU_FREQ_24_API
  32058. +
  32059. +
  32060. +/*********************** cpufreq_sysctl interface ********************/
  32061. +static int
  32062. +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
  32063. + void *buffer, size_t *lenp)
  32064. +{
  32065. + char buf[16], *p;
  32066. + int cpu = (int) ctl->extra1;
  32067. + int len, left = *lenp;
  32068. +
  32069. + if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) {
  32070. + *lenp = 0;
  32071. + return 0;
  32072. + }
  32073. +
  32074. + if (write) {
  32075. + unsigned int freq;
  32076. +
  32077. + len = left;
  32078. + if (left > sizeof(buf))
  32079. + left = sizeof(buf);
  32080. + if (copy_from_user(buf, buffer, left))
  32081. + return -EFAULT;
  32082. + buf[sizeof(buf) - 1] = '\0';
  32083. +
  32084. + freq = simple_strtoul(buf, &p, 0);
  32085. + cpufreq_set(freq, cpu);
  32086. + } else {
  32087. + len = sprintf(buf, "%d\n", cpufreq_get(cpu));
  32088. + if (len > left)
  32089. + len = left;
  32090. + if (copy_to_user(buffer, buf, len))
  32091. + return -EFAULT;
  32092. + }
  32093. +
  32094. + *lenp = len;
  32095. + filp->f_pos += len;
  32096. + return 0;
  32097. +}
  32098. +
  32099. +static int
  32100. +cpufreq_sysctl(ctl_table *table, int *name, int nlen,
  32101. + void *oldval, size_t *oldlenp,
  32102. + void *newval, size_t newlen, void **context)
  32103. +{
  32104. + int cpu = (int) table->extra1;
  32105. +
  32106. + if (!cpu_online(cpu))
  32107. + return -EINVAL;
  32108. +
  32109. + if (oldval && oldlenp) {
  32110. + size_t oldlen;
  32111. +
  32112. + if (get_user(oldlen, oldlenp))
  32113. + return -EFAULT;
  32114. +
  32115. + if (oldlen != sizeof(unsigned int))
  32116. + return -EINVAL;
  32117. +
  32118. + if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
  32119. + put_user(sizeof(unsigned int), oldlenp))
  32120. + return -EFAULT;
  32121. + }
  32122. + if (newval && newlen) {
  32123. + unsigned int freq;
  32124. +
  32125. + if (newlen != sizeof(unsigned int))
  32126. + return -EINVAL;
  32127. +
  32128. + if (get_user(freq, (unsigned int *)newval))
  32129. + return -EFAULT;
  32130. +
  32131. + cpufreq_set(freq, cpu);
  32132. + }
  32133. + return 1;
  32134. +}
  32135. +
  32136. +/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */
  32137. +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
  32138. + CTL_TABLE_CPU_VARS(0);
  32139. +#if NR_CPUS > 1
  32140. + CTL_TABLE_CPU_VARS(1);
  32141. +#endif
  32142. +#if NR_CPUS > 2
  32143. + CTL_TABLE_CPU_VARS(2);
  32144. +#endif
  32145. +#if NR_CPUS > 3
  32146. + CTL_TABLE_CPU_VARS(3);
  32147. +#endif
  32148. +#if NR_CPUS > 4
  32149. + CTL_TABLE_CPU_VARS(4);
  32150. +#endif
  32151. +#if NR_CPUS > 5
  32152. + CTL_TABLE_CPU_VARS(5);
  32153. +#endif
  32154. +#if NR_CPUS > 6
  32155. + CTL_TABLE_CPU_VARS(6);
  32156. +#endif
  32157. +#if NR_CPUS > 7
  32158. + CTL_TABLE_CPU_VARS(7);
  32159. +#endif
  32160. +#if NR_CPUS > 8
  32161. + CTL_TABLE_CPU_VARS(8);
  32162. +#endif
  32163. +#if NR_CPUS > 9
  32164. + CTL_TABLE_CPU_VARS(9);
  32165. +#endif
  32166. +#if NR_CPUS > 10
  32167. + CTL_TABLE_CPU_VARS(10);
  32168. +#endif
  32169. +#if NR_CPUS > 11
  32170. + CTL_TABLE_CPU_VARS(11);
  32171. +#endif
  32172. +#if NR_CPUS > 12
  32173. + CTL_TABLE_CPU_VARS(12);
  32174. +#endif
  32175. +#if NR_CPUS > 13
  32176. + CTL_TABLE_CPU_VARS(13);
  32177. +#endif
  32178. +#if NR_CPUS > 14
  32179. + CTL_TABLE_CPU_VARS(14);
  32180. +#endif
  32181. +#if NR_CPUS > 15
  32182. + CTL_TABLE_CPU_VARS(15);
  32183. +#endif
  32184. +#if NR_CPUS > 16
  32185. + CTL_TABLE_CPU_VARS(16);
  32186. +#endif
  32187. +#if NR_CPUS > 17
  32188. + CTL_TABLE_CPU_VARS(17);
  32189. +#endif
  32190. +#if NR_CPUS > 18
  32191. + CTL_TABLE_CPU_VARS(18);
  32192. +#endif
  32193. +#if NR_CPUS > 19
  32194. + CTL_TABLE_CPU_VARS(19);
  32195. +#endif
  32196. +#if NR_CPUS > 20
  32197. + CTL_TABLE_CPU_VARS(20);
  32198. +#endif
  32199. +#if NR_CPUS > 21
  32200. + CTL_TABLE_CPU_VARS(21);
  32201. +#endif
  32202. +#if NR_CPUS > 22
  32203. + CTL_TABLE_CPU_VARS(22);
  32204. +#endif
  32205. +#if NR_CPUS > 23
  32206. + CTL_TABLE_CPU_VARS(23);
  32207. +#endif
  32208. +#if NR_CPUS > 24
  32209. + CTL_TABLE_CPU_VARS(24);
  32210. +#endif
  32211. +#if NR_CPUS > 25
  32212. + CTL_TABLE_CPU_VARS(25);
  32213. +#endif
  32214. +#if NR_CPUS > 26
  32215. + CTL_TABLE_CPU_VARS(26);
  32216. +#endif
  32217. +#if NR_CPUS > 27
  32218. + CTL_TABLE_CPU_VARS(27);
  32219. +#endif
  32220. +#if NR_CPUS > 28
  32221. + CTL_TABLE_CPU_VARS(28);
  32222. +#endif
  32223. +#if NR_CPUS > 29
  32224. + CTL_TABLE_CPU_VARS(29);
  32225. +#endif
  32226. +#if NR_CPUS > 30
  32227. + CTL_TABLE_CPU_VARS(30);
  32228. +#endif
  32229. +#if NR_CPUS > 31
  32230. + CTL_TABLE_CPU_VARS(31);
  32231. +#endif
  32232. +#if NR_CPUS > 32
  32233. +#error please extend CPU enumeration
  32234. +#endif
  32235. +
  32236. +/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
  32237. +static ctl_table ctl_cpu_table[NR_CPUS + 1] = {
  32238. + CPU_ENUM(0),
  32239. +#if NR_CPUS > 1
  32240. + CPU_ENUM(1),
  32241. +#endif
  32242. +#if NR_CPUS > 2
  32243. + CPU_ENUM(2),
  32244. +#endif
  32245. +#if NR_CPUS > 3
  32246. + CPU_ENUM(3),
  32247. +#endif
  32248. +#if NR_CPUS > 4
  32249. + CPU_ENUM(4),
  32250. +#endif
  32251. +#if NR_CPUS > 5
  32252. + CPU_ENUM(5),
  32253. +#endif
  32254. +#if NR_CPUS > 6
  32255. + CPU_ENUM(6),
  32256. +#endif
  32257. +#if NR_CPUS > 7
  32258. + CPU_ENUM(7),
  32259. +#endif
  32260. +#if NR_CPUS > 8
  32261. + CPU_ENUM(8),
  32262. +#endif
  32263. +#if NR_CPUS > 9
  32264. + CPU_ENUM(9),
  32265. +#endif
  32266. +#if NR_CPUS > 10
  32267. + CPU_ENUM(10),
  32268. +#endif
  32269. +#if NR_CPUS > 11
  32270. + CPU_ENUM(11),
  32271. +#endif
  32272. +#if NR_CPUS > 12
  32273. + CPU_ENUM(12),
  32274. +#endif
  32275. +#if NR_CPUS > 13
  32276. + CPU_ENUM(13),
  32277. +#endif
  32278. +#if NR_CPUS > 14
  32279. + CPU_ENUM(14),
  32280. +#endif
  32281. +#if NR_CPUS > 15
  32282. + CPU_ENUM(15),
  32283. +#endif
  32284. +#if NR_CPUS > 16
  32285. + CPU_ENUM(16),
  32286. +#endif
  32287. +#if NR_CPUS > 17
  32288. + CPU_ENUM(17),
  32289. +#endif
  32290. +#if NR_CPUS > 18
  32291. + CPU_ENUM(18),
  32292. +#endif
  32293. +#if NR_CPUS > 19
  32294. + CPU_ENUM(19),
  32295. +#endif
  32296. +#if NR_CPUS > 20
  32297. + CPU_ENUM(20),
  32298. +#endif
  32299. +#if NR_CPUS > 21
  32300. + CPU_ENUM(21),
  32301. +#endif
  32302. +#if NR_CPUS > 22
  32303. + CPU_ENUM(22),
  32304. +#endif
  32305. +#if NR_CPUS > 23
  32306. + CPU_ENUM(23),
  32307. +#endif
  32308. +#if NR_CPUS > 24
  32309. + CPU_ENUM(24),
  32310. +#endif
  32311. +#if NR_CPUS > 25
  32312. + CPU_ENUM(25),
  32313. +#endif
  32314. +#if NR_CPUS > 26
  32315. + CPU_ENUM(26),
  32316. +#endif
  32317. +#if NR_CPUS > 27
  32318. + CPU_ENUM(27),
  32319. +#endif
  32320. +#if NR_CPUS > 28
  32321. + CPU_ENUM(28),
  32322. +#endif
  32323. +#if NR_CPUS > 29
  32324. + CPU_ENUM(29),
  32325. +#endif
  32326. +#if NR_CPUS > 30
  32327. + CPU_ENUM(30),
  32328. +#endif
  32329. +#if NR_CPUS > 31
  32330. + CPU_ENUM(31),
  32331. +#endif
  32332. +#if NR_CPUS > 32
  32333. +#error please extend CPU enumeration
  32334. +#endif
  32335. + {
  32336. + .ctl_name = 0,
  32337. + }
  32338. +};
  32339. +
  32340. +static ctl_table ctl_cpu[2] = {
  32341. + {
  32342. + .ctl_name = CTL_CPU,
  32343. + .procname = "cpu",
  32344. + .mode = 0555,
  32345. + .child = ctl_cpu_table,
  32346. + },
  32347. + {
  32348. + .ctl_name = 0,
  32349. + }
  32350. +};
  32351. +
  32352. +struct ctl_table_header *cpufreq_sysctl_table;
  32353. +
  32354. +static inline void cpufreq_sysctl_init(void)
  32355. +{
  32356. + cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0);
  32357. +}
  32358. +
  32359. +static inline void cpufreq_sysctl_exit(void)
  32360. +{
  32361. + unregister_sysctl_table(cpufreq_sysctl_table);
  32362. +}
  32363. +
  32364. +#else
  32365. +#define cpufreq_sysctl_init() do {} while(0)
  32366. +#define cpufreq_sysctl_exit() do {} while(0)
  32367. +#endif /* CONFIG_CPU_FREQ_24API */
  32368. +
  32369. +
  32370. +/************************** sysfs interface ************************/
  32371. +static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
  32372. +{
  32373. + return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
  32374. +}
  32375. +
  32376. +static ssize_t
  32377. +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
  32378. +{
  32379. + unsigned int freq = 0;
  32380. + unsigned int ret;
  32381. +
  32382. + ret = sscanf (buf, "%u", &freq);
  32383. + if (ret != 1)
  32384. + return -EINVAL;
  32385. +
  32386. + cpufreq_set(freq, policy->cpu);
  32387. +
  32388. + return count;
  32389. +}
  32390. +
  32391. +static struct freq_attr freq_attr_scaling_setspeed = {
  32392. + .attr = { .name = "scaling_setspeed", .mode = 0644 },
  32393. + .show = show_speed,
  32394. + .store = store_speed,
  32395. +};
  32396. +
  32397. +static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
  32398. + unsigned int event)
  32399. +{
  32400. + unsigned int cpu = policy->cpu;
  32401. + switch (event) {
  32402. + case CPUFREQ_GOV_START:
  32403. + if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) ||
  32404. + !policy->cur)
  32405. + return -EINVAL;
  32406. + down(&userspace_sem);
  32407. + cpu_is_managed[cpu] = 1;
  32408. + cpu_min_freq[cpu] = policy->min;
  32409. + cpu_max_freq[cpu] = policy->max;
  32410. + cpu_cur_freq[cpu] = policy->cur;
  32411. + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
  32412. + memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
  32413. + up(&userspace_sem);
  32414. + break;
  32415. + case CPUFREQ_GOV_STOP:
  32416. + down(&userspace_sem);
  32417. + cpu_is_managed[cpu] = 0;
  32418. + cpu_min_freq[cpu] = 0;
  32419. + cpu_max_freq[cpu] = 0;
  32420. + sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
  32421. + up(&userspace_sem);
  32422. + module_put(THIS_MODULE);
  32423. + break;
  32424. + case CPUFREQ_GOV_LIMITS:
  32425. + down(&userspace_sem);
  32426. + cpu_min_freq[cpu] = policy->min;
  32427. + cpu_max_freq[cpu] = policy->max;
  32428. + if (policy->max < cpu_cur_freq[cpu])
  32429. + cpufreq_driver_target(&current_policy[cpu], policy->max,
  32430. + CPUFREQ_RELATION_H);
  32431. + else if (policy->min > cpu_cur_freq[cpu])
  32432. + cpufreq_driver_target(&current_policy[cpu], policy->min,
  32433. + CPUFREQ_RELATION_L);
  32434. + memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
  32435. + up(&userspace_sem);
  32436. + break;
  32437. + }
  32438. + return 0;
  32439. +}
  32440. +
  32441. +/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because
  32442. + * of this, cpu_cur_freq[] needs to be set early.
  32443. + */
  32444. +#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100)
  32445. +extern unsigned int sa11x0_getspeed(void);
  32446. +
  32447. +static void cpufreq_sa11x0_compat(void)
  32448. +{
  32449. + cpu_cur_freq[0] = sa11x0_getspeed();
  32450. +}
  32451. +#else
  32452. +#define cpufreq_sa11x0_compat() do {} while(0)
  32453. +#endif
  32454. +
  32455. +
  32456. +static struct cpufreq_governor cpufreq_gov_userspace = {
  32457. + .name = "userspace",
  32458. + .governor = cpufreq_governor_userspace,
  32459. + .owner = THIS_MODULE,
  32460. +};
  32461. +EXPORT_SYMBOL(cpufreq_gov_userspace);
  32462. +
  32463. +static int already_init = 0;
  32464. +
  32465. +int cpufreq_gov_userspace_init(void)
  32466. +{
  32467. + if (!already_init) {
  32468. + down(&userspace_sem);
  32469. + cpufreq_sa11x0_compat();
  32470. + cpufreq_sysctl_init();
  32471. + cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
  32472. + already_init = 1;
  32473. + up(&userspace_sem);
  32474. + }
  32475. + return cpufreq_register_governor(&cpufreq_gov_userspace);
  32476. +}
  32477. +EXPORT_SYMBOL(cpufreq_gov_userspace_init);
  32478. +
  32479. +
  32480. +static void __exit cpufreq_gov_userspace_exit(void)
  32481. +{
  32482. + cpufreq_unregister_governor(&cpufreq_gov_userspace);
  32483. + cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
  32484. + cpufreq_sysctl_exit();
  32485. +}
  32486. +
  32487. +
  32488. +MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.org.uk>");
  32489. +MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
  32490. +MODULE_LICENSE ("GPL");
  32491. +
  32492. +module_init(cpufreq_gov_userspace_init);
  32493. +module_exit(cpufreq_gov_userspace_exit);
  32494. diff -urN linux-2.4.26/drivers/i2c/Config.in linux-2.4.26-vrs1/drivers/i2c/Config.in
  32495. --- linux-2.4.26/drivers/i2c/Config.in 2004-04-19 11:44:16.000000000 +0100
  32496. +++ linux-2.4.26-vrs1/drivers/i2c/Config.in 2004-04-18 21:47:50.000000000 +0100
  32497. @@ -17,6 +17,15 @@
  32498. int ' GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12
  32499. int ' GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13
  32500. fi
  32501. +
  32502. + dep_tristate ' Guide GPIO adapter' CONFIG_I2C_GUIDE $CONFIG_I2C_ALGOBIT
  32503. + if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
  32504. + dep_tristate ' Omaha I2C interface' CONFIG_I2C_OMAHA $CONFIG_I2C
  32505. + fi
  32506. + if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
  32507. + dep_tristate ' Frodo I2C adapter' CONFIG_I2C_FRODO $CONFIG_I2C_ALGOBIT
  32508. + dep_tristate ' SA1100 I2C GPIO adapter' CONFIG_I2C_BIT_SA1100_GPIO $CONFIG_I2C_ALGOBIT
  32509. + fi
  32510. fi
  32511. dep_tristate 'NatSemi SCx200 ACCESS.bus' CONFIG_SCx200_ACB $CONFIG_I2C
  32512. @@ -49,6 +58,10 @@
  32513. dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
  32514. fi
  32515. + if [ "$CONFIG_ARCH_AT91RM9200" = "y" ] ; then
  32516. + dep_tristate 'Atmel AT91RM9200 I2C Two-Wire interface (TWI)' CONFIG_I2C_AT91 $CONFIG_I2C
  32517. + fi
  32518. +
  32519. if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
  32520. dep_tristate 'SiByte SMBus interface' CONFIG_I2C_ALGO_SIBYTE $CONFIG_I2C
  32521. dep_tristate ' MAX1617 Temperature Sensor' CONFIG_I2C_MAX1617 $CONFIG_I2C_ALGO_SIBYTE
  32522. diff -urN linux-2.4.26/drivers/i2c/Makefile linux-2.4.26-vrs1/drivers/i2c/Makefile
  32523. --- linux-2.4.26/drivers/i2c/Makefile 2004-02-27 20:03:25.000000000 +0000
  32524. +++ linux-2.4.26-vrs1/drivers/i2c/Makefile 2004-02-23 22:59:17.000000000 +0000
  32525. @@ -8,12 +8,21 @@
  32526. i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
  32527. i2c-proc.o
  32528. +# Init order: core, chardev, bit adapters, pcf adapters
  32529. +
  32530. obj-$(CONFIG_I2C) += i2c-core.o
  32531. obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
  32532. +
  32533. +# Bit adapters
  32534. obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
  32535. obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o
  32536. obj-$(CONFIG_I2C_ELV) += i2c-elv.o
  32537. obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o
  32538. +obj-$(CONFIG_I2C_GUIDE) += i2c-guide.o
  32539. +obj-$(CONFIG_I2C_FRODO) += i2c-frodo.o
  32540. +obj-$(CONFIG_I2C_OMAHA) += i2c-omaha.o
  32541. +
  32542. +# PCF adapters
  32543. obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
  32544. obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
  32545. obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o
  32546. @@ -30,4 +39,3 @@
  32547. # This is needed for automatic patch generation: sensors code ends here
  32548. include $(TOPDIR)/Rules.make
  32549. -
  32550. diff -urN linux-2.4.26/drivers/i2c/i2c-algo-bit.c linux-2.4.26-vrs1/drivers/i2c/i2c-algo-bit.c
  32551. --- linux-2.4.26/drivers/i2c/i2c-algo-bit.c 2004-02-27 20:03:25.000000000 +0000
  32552. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-algo-bit.c 2004-02-23 13:36:30.000000000 +0000
  32553. @@ -169,7 +169,14 @@
  32554. * 1 if the device acknowledged
  32555. * 0 if the device did not ack
  32556. * -ETIMEDOUT if an error occurred (while raising the scl line)
  32557. - */
  32558. +
  32559. + * tsong@iders.ca: an instruction to disable any timeconsuming interrupt
  32560. + here except the heart beat of timer2 should be added before setsda(adap, sb).
  32561. + because when interrupt occurs during
  32562. + scl is set high, the interrupt service routine is served and may take long,
  32563. + after the interrupt returns, sda could be sampled by the device(slave)
  32564. + more than once, and this cause error problem.
  32565. +*/
  32566. static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
  32567. {
  32568. int i;
  32569. @@ -582,9 +589,7 @@
  32570. printk("\n");
  32571. }
  32572. -#ifdef MODULE
  32573. MOD_INC_USE_COUNT;
  32574. -#endif
  32575. i2c_add_adapter(adap);
  32576. return 0;
  32577. @@ -600,15 +605,13 @@
  32578. DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name));
  32579. -#ifdef MODULE
  32580. MOD_DEC_USE_COUNT;
  32581. -#endif
  32582. return 0;
  32583. }
  32584. -int __init i2c_algo_bit_init (void)
  32585. +static int __init i2c_algo_bit_init (void)
  32586. {
  32587. - printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module\n");
  32588. + printk(KERN_DEBUG "i2c-algo-bit.o: i2c bit algorithm module\n");
  32589. return 0;
  32590. }
  32591. @@ -617,7 +620,6 @@
  32592. EXPORT_SYMBOL(i2c_bit_add_bus);
  32593. EXPORT_SYMBOL(i2c_bit_del_bus);
  32594. -#ifdef MODULE
  32595. MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  32596. MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
  32597. MODULE_LICENSE("GPL");
  32598. @@ -631,12 +633,4 @@
  32599. MODULE_PARM_DESC(i2c_debug,
  32600. "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
  32601. -int init_module(void)
  32602. -{
  32603. - return i2c_algo_bit_init();
  32604. -}
  32605. -
  32606. -void cleanup_module(void)
  32607. -{
  32608. -}
  32609. -#endif
  32610. +module_init(i2c_algo_bit_init);
  32611. diff -urN linux-2.4.26/drivers/i2c/i2c-algo-pcf.c linux-2.4.26-vrs1/drivers/i2c/i2c-algo-pcf.c
  32612. --- linux-2.4.26/drivers/i2c/i2c-algo-pcf.c 2004-02-27 20:03:25.000000000 +0000
  32613. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-algo-pcf.c 2004-02-23 13:36:30.000000000 +0000
  32614. @@ -475,9 +475,7 @@
  32615. return i;
  32616. }
  32617. -#ifdef MODULE
  32618. MOD_INC_USE_COUNT;
  32619. -#endif
  32620. i2c_add_adapter(adap);
  32621. @@ -515,13 +513,11 @@
  32622. return res;
  32623. DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name));
  32624. -#ifdef MODULE
  32625. MOD_DEC_USE_COUNT;
  32626. -#endif
  32627. return 0;
  32628. }
  32629. -int __init i2c_algo_pcf_init (void)
  32630. +static int __init i2c_algo_pcf_init (void)
  32631. {
  32632. printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n");
  32633. return 0;
  32634. @@ -531,7 +527,6 @@
  32635. EXPORT_SYMBOL(i2c_pcf_add_bus);
  32636. EXPORT_SYMBOL(i2c_pcf_del_bus);
  32637. -#ifdef MODULE
  32638. MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
  32639. MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
  32640. MODULE_LICENSE("GPL");
  32641. @@ -543,13 +538,4 @@
  32642. MODULE_PARM_DESC(i2c_debug,
  32643. "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
  32644. -
  32645. -int init_module(void)
  32646. -{
  32647. - return i2c_algo_pcf_init();
  32648. -}
  32649. -
  32650. -void cleanup_module(void)
  32651. -{
  32652. -}
  32653. -#endif
  32654. +module_init(i2c_algo_pcf_init);
  32655. diff -urN linux-2.4.26/drivers/i2c/i2c-core.c linux-2.4.26-vrs1/drivers/i2c/i2c-core.c
  32656. --- linux-2.4.26/drivers/i2c/i2c-core.c 2004-02-27 20:03:25.000000000 +0000
  32657. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-core.c 2004-02-27 22:54:22.000000000 +0000
  32658. @@ -41,7 +41,7 @@
  32659. /* exclusive access to the bus */
  32660. #define I2C_LOCK(adap) down(&adap->lock)
  32661. -#define I2C_UNLOCK(adap) up(&adap->lock)
  32662. +#define I2C_UNLOCK(adap) up(&adap->lock)
  32663. #define ADAP_LOCK() down(&adap_lock)
  32664. #define ADAP_UNLOCK() up(&adap_lock)
  32665. @@ -67,7 +67,7 @@
  32666. static int driver_count;
  32667. /**** debug level */
  32668. -static int i2c_debug=1;
  32669. +static int i2c_debug = 0;
  32670. /* ---------------------------------------------------
  32671. * /proc entry declarations
  32672. @@ -77,14 +77,14 @@
  32673. #ifdef CONFIG_PROC_FS
  32674. static int i2cproc_init(void);
  32675. -static int i2cproc_cleanup(void);
  32676. +static void i2cproc_cleanup(void);
  32677. -static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
  32678. +static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
  32679. loff_t *ppos);
  32680. static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
  32681. int *eof , void *private);
  32682. -/* To implement the dynamic /proc/bus/i2c-? files, we need our own
  32683. +/* To implement the dynamic /proc/bus/i2c-? files, we need our own
  32684. implementation of the read hook */
  32685. static struct file_operations i2cproc_operations = {
  32686. read: i2cproc_bus_read,
  32687. @@ -101,8 +101,8 @@
  32688. /* ---------------------------------------------------
  32689. - * registering functions
  32690. - * ---------------------------------------------------
  32691. + * registering functions
  32692. + * ---------------------------------------------------
  32693. */
  32694. /* -----
  32695. @@ -119,7 +119,7 @@
  32696. if (NULL == adapters[i])
  32697. break;
  32698. if (I2C_ADAP_MAX == i) {
  32699. - printk(KERN_WARNING
  32700. + printk(KERN_WARNING
  32701. " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
  32702. adap->name);
  32703. res = -ENOMEM;
  32704. @@ -129,7 +129,7 @@
  32705. adapters[i] = adap;
  32706. adap_count++;
  32707. ADAP_UNLOCK();
  32708. -
  32709. +
  32710. /* init data types */
  32711. init_MUTEX(&adap->lock);
  32712. @@ -157,18 +157,18 @@
  32713. #endif /* def CONFIG_PROC_FS */
  32714. /* inform drivers of new adapters */
  32715. - DRV_LOCK();
  32716. + DRV_LOCK();
  32717. for (j=0;j<I2C_DRIVER_MAX;j++)
  32718. - if (drivers[j]!=NULL &&
  32719. + if (drivers[j]!=NULL &&
  32720. (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY)))
  32721. /* We ignore the return code; if it fails, too bad */
  32722. drivers[j]->attach_adapter(adap);
  32723. DRV_UNLOCK();
  32724. -
  32725. +
  32726. DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
  32727. adap->name,i));
  32728. - return 0;
  32729. + return 0;
  32730. ERROR1:
  32731. @@ -203,13 +203,13 @@
  32732. * this or hell will break loose...
  32733. */
  32734. DRV_LOCK();
  32735. - for (j = 0; j < I2C_DRIVER_MAX; j++)
  32736. + for (j = 0; j < I2C_DRIVER_MAX; j++)
  32737. if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
  32738. if ((res = drivers[j]->attach_adapter(adap))) {
  32739. printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
  32740. "while detaching driver %s: driver not "
  32741. "detached!",adap->name,drivers[j]->name);
  32742. - goto ERROR1;
  32743. + goto ERROR1;
  32744. }
  32745. DRV_UNLOCK();
  32746. @@ -241,8 +241,8 @@
  32747. adapters[i] = NULL;
  32748. adap_count--;
  32749. -
  32750. - ADAP_UNLOCK();
  32751. +
  32752. + ADAP_UNLOCK();
  32753. DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
  32754. return 0;
  32755. @@ -269,7 +269,7 @@
  32756. if (NULL == drivers[i])
  32757. break;
  32758. if (I2C_DRIVER_MAX == i) {
  32759. - printk(KERN_WARNING
  32760. + printk(KERN_WARNING
  32761. " i2c-core.o: register_driver(%s) "
  32762. "- enlarge I2C_DRIVER_MAX.\n",
  32763. driver->name);
  32764. @@ -279,11 +279,11 @@
  32765. drivers[i] = driver;
  32766. driver_count++;
  32767. -
  32768. +
  32769. DRV_UNLOCK(); /* driver was successfully added */
  32770. -
  32771. +
  32772. DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
  32773. -
  32774. +
  32775. ADAP_LOCK();
  32776. /* now look for instances of driver on our adapters
  32777. @@ -314,11 +314,11 @@
  32778. return -ENODEV;
  32779. }
  32780. /* Have a look at each adapter, if clients of this driver are still
  32781. - * attached. If so, detach them to be able to kill the driver
  32782. + * attached. If so, detach them to be able to kill the driver
  32783. * afterwards.
  32784. */
  32785. DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n"));
  32786. - /* removing clients does not depend on the notify flag, else
  32787. + /* removing clients does not depend on the notify flag, else
  32788. * invalid operation might (will!) result, when using stale client
  32789. * pointers.
  32790. */
  32791. @@ -333,7 +333,7 @@
  32792. /* DUMMY drivers do not register their clients, so we have to
  32793. * use a trick here: we call driver->attach_adapter to
  32794. * *detach* it! Of course, each dummy driver should know about
  32795. - * this or hell will break loose...
  32796. + * this or hell will break loose...
  32797. */
  32798. if ((res = driver->attach_adapter(adap))) {
  32799. printk(KERN_WARNING "i2c-core.o: while unregistering "
  32800. @@ -345,9 +345,9 @@
  32801. return res;
  32802. }
  32803. } else {
  32804. - for (j=0;j<I2C_CLIENT_MAX;j++) {
  32805. + for (j=0;j<I2C_CLIENT_MAX;j++) {
  32806. struct i2c_client *client = adap->clients[j];
  32807. - if (client != NULL &&
  32808. + if (client != NULL &&
  32809. client->driver == driver) {
  32810. DEB2(printk(KERN_DEBUG "i2c-core.o: "
  32811. "detaching client %s:\n",
  32812. @@ -376,7 +376,7 @@
  32813. drivers[i] = NULL;
  32814. driver_count--;
  32815. DRV_UNLOCK();
  32816. -
  32817. +
  32818. DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name));
  32819. return 0;
  32820. }
  32821. @@ -384,7 +384,7 @@
  32822. int i2c_check_addr (struct i2c_adapter *adapter, int addr)
  32823. {
  32824. int i;
  32825. - for (i = 0; i < I2C_CLIENT_MAX ; i++)
  32826. + for (i = 0; i < I2C_CLIENT_MAX ; i++)
  32827. if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
  32828. return -EBUSY;
  32829. return 0;
  32830. @@ -402,7 +402,7 @@
  32831. if (NULL == adapter->clients[i])
  32832. break;
  32833. if (I2C_CLIENT_MAX == i) {
  32834. - printk(KERN_WARNING
  32835. + printk(KERN_WARNING
  32836. " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
  32837. client->name);
  32838. return -ENOMEM;
  32839. @@ -410,9 +410,9 @@
  32840. adapter->clients[i] = client;
  32841. adapter->client_count++;
  32842. -
  32843. - if (adapter->client_register)
  32844. - if (adapter->client_register(client))
  32845. +
  32846. + if (adapter->client_register)
  32847. + if (adapter->client_register(client))
  32848. printk(KERN_DEBUG "i2c-core.o: warning: client_register seems "
  32849. "to have failed for client %02x at adapter %s\n",
  32850. client->addr,adapter->name);
  32851. @@ -421,7 +421,7 @@
  32852. if(client->flags & I2C_CLIENT_ALLOW_USE)
  32853. client->usage_count = 0;
  32854. -
  32855. +
  32856. return 0;
  32857. }
  32858. @@ -440,12 +440,12 @@
  32859. client->name);
  32860. return -ENODEV;
  32861. }
  32862. -
  32863. - if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
  32864. +
  32865. + if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
  32866. (client->usage_count>0))
  32867. return -EBUSY;
  32868. -
  32869. - if (adapter->client_unregister != NULL)
  32870. +
  32871. + if (adapter->client_unregister != NULL)
  32872. if ((res = adapter->client_unregister(client))) {
  32873. printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, "
  32874. "client not detached",client->name);
  32875. @@ -471,7 +471,7 @@
  32876. void i2c_dec_use_client(struct i2c_client *client)
  32877. {
  32878. -
  32879. +
  32880. if (client->driver->dec_use != NULL)
  32881. client->driver->dec_use(client);
  32882. @@ -479,65 +479,65 @@
  32883. client->adapter->dec_use(client->adapter);
  32884. }
  32885. -struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
  32886. +struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
  32887. struct i2c_client *prev)
  32888. {
  32889. int i,j;
  32890. -
  32891. +
  32892. /* Will iterate through the list of clients in each adapter of adapters-list
  32893. - in search for a client that matches the search criteria. driver_id or
  32894. - adapter_id are ignored if set to 0. If both are ignored this returns
  32895. + in search for a client that matches the search criteria. driver_id or
  32896. + adapter_id are ignored if set to 0. If both are ignored this returns
  32897. first client found. */
  32898. -
  32899. - i = j = 0;
  32900. -
  32901. - /* set starting point */
  32902. +
  32903. + i = j = 0;
  32904. +
  32905. + /* set starting point */
  32906. if(prev)
  32907. {
  32908. if(!(prev->adapter))
  32909. return (struct i2c_client *) -EINVAL;
  32910. -
  32911. +
  32912. for(j=0; j < I2C_ADAP_MAX; j++)
  32913. if(prev->adapter == adapters[j])
  32914. break;
  32915. -
  32916. +
  32917. /* invalid starting point? */
  32918. if (I2C_ADAP_MAX == j) {
  32919. printk(KERN_WARNING " i2c-core.o: get_client adapter for client:[%s] not found\n",
  32920. prev->name);
  32921. return (struct i2c_client *) -ENODEV;
  32922. - }
  32923. -
  32924. + }
  32925. +
  32926. for(i=0; i < I2C_CLIENT_MAX; i++)
  32927. if(prev == adapters[j]->clients[i])
  32928. break;
  32929. -
  32930. +
  32931. /* invalid starting point? */
  32932. if (I2C_CLIENT_MAX == i) {
  32933. printk(KERN_WARNING " i2c-core.o: get_client client:[%s] not found\n",
  32934. prev->name);
  32935. return (struct i2c_client *) -ENODEV;
  32936. - }
  32937. -
  32938. + }
  32939. +
  32940. i++; /* start from one after prev */
  32941. }
  32942. -
  32943. +
  32944. for(; j < I2C_ADAP_MAX; j++)
  32945. {
  32946. if(!adapters[j])
  32947. continue;
  32948. -
  32949. +
  32950. if(adapter_id && (adapters[j]->id != adapter_id))
  32951. continue;
  32952. -
  32953. +
  32954. for(; i < I2C_CLIENT_MAX; i++)
  32955. {
  32956. if(!adapters[j]->clients[i])
  32957. continue;
  32958. -
  32959. +
  32960. if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id))
  32961. continue;
  32962. - if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
  32963. + if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
  32964. return adapters[j]->clients[i];
  32965. }
  32966. i = 0;
  32967. @@ -549,12 +549,12 @@
  32968. int i2c_use_client(struct i2c_client *client)
  32969. {
  32970. if(client->flags & I2C_CLIENT_ALLOW_USE) {
  32971. - if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
  32972. + if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
  32973. client->usage_count++;
  32974. else {
  32975. - if(client->usage_count > 0)
  32976. + if(client->usage_count > 0)
  32977. return -EBUSY;
  32978. - else
  32979. + else
  32980. client->usage_count++;
  32981. }
  32982. }
  32983. @@ -575,9 +575,9 @@
  32984. return -EPERM;
  32985. }
  32986. }
  32987. -
  32988. +
  32989. i2c_dec_use_client(client);
  32990. -
  32991. +
  32992. return 0;
  32993. }
  32994. @@ -589,7 +589,7 @@
  32995. #ifdef CONFIG_PROC_FS
  32996. /* This function generates the output for /proc/bus/i2c */
  32997. -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
  32998. +int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
  32999. void *private)
  33000. {
  33001. int i;
  33002. @@ -615,7 +615,7 @@
  33003. }
  33004. /* This function generates the output for /proc/bus/i2c-? */
  33005. -ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
  33006. +ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
  33007. loff_t *ppos)
  33008. {
  33009. struct inode * inode = file->f_dentry->d_inode;
  33010. @@ -626,7 +626,7 @@
  33011. int order[I2C_CLIENT_MAX];
  33012. if (count > 4000)
  33013. - return -EINVAL;
  33014. + return -EINVAL;
  33015. len_total = file->f_pos + count;
  33016. /* Too bad if this gets longer (unlikely) */
  33017. if (len_total > 4000)
  33018. @@ -641,12 +641,12 @@
  33019. sorted by address */
  33020. order_nr=0;
  33021. for (j = 0; j < I2C_CLIENT_MAX; j++) {
  33022. - if ((client = adapters[i]->clients[j]) &&
  33023. + if ((client = adapters[i]->clients[j]) &&
  33024. (client->driver->id != I2C_DRIVERID_I2CDEV)) {
  33025. - for(k = order_nr;
  33026. - (k > 0) &&
  33027. + for(k = order_nr;
  33028. + (k > 0) &&
  33029. adapters[i]->clients[order[k-1]]->
  33030. - addr > client->addr;
  33031. + addr > client->addr;
  33032. k--)
  33033. order[k] = order[k-1];
  33034. order[k] = j;
  33035. @@ -665,7 +665,7 @@
  33036. len = len - file->f_pos;
  33037. if (len > count)
  33038. len = count;
  33039. - if (len < 0)
  33040. + if (len < 0)
  33041. len = 0;
  33042. if (copy_to_user (buf,kbuf+file->f_pos, len)) {
  33043. kfree(kbuf);
  33044. @@ -689,7 +689,7 @@
  33045. printk("i2c-core.o: /proc/bus/ does not exist");
  33046. i2cproc_cleanup();
  33047. return -ENOENT;
  33048. - }
  33049. + }
  33050. proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
  33051. if (!proc_bus_i2c) {
  33052. printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
  33053. @@ -702,14 +702,13 @@
  33054. return 0;
  33055. }
  33056. -int i2cproc_cleanup(void)
  33057. +static void i2cproc_cleanup(void)
  33058. {
  33059. if (i2cproc_initialized >= 1) {
  33060. remove_proc_entry("i2c",proc_bus);
  33061. i2cproc_initialized -= 2;
  33062. }
  33063. - return 0;
  33064. }
  33065. @@ -751,10 +750,10 @@
  33066. msg.flags = client->flags & I2C_M_TEN;
  33067. msg.len = count;
  33068. (const char *)msg.buf = buf;
  33069. -
  33070. +
  33071. DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
  33072. count,client->adapter->name));
  33073. -
  33074. +
  33075. I2C_LOCK(adap);
  33076. ret = adap->algo->master_xfer(adap,&msg,1);
  33077. I2C_UNLOCK(adap);
  33078. @@ -784,14 +783,14 @@
  33079. DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
  33080. count,client->adapter->name));
  33081. -
  33082. +
  33083. I2C_LOCK(adap);
  33084. ret = adap->algo->master_xfer(adap,&msg,1);
  33085. I2C_UNLOCK(adap);
  33086. -
  33087. +
  33088. DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
  33089. ret, count, client->addr));
  33090. -
  33091. +
  33092. /* if everything went ok (i.e. 1 msg transmitted), return #bytes
  33093. * transmitted, else error code.
  33094. */
  33095. @@ -852,7 +851,7 @@
  33096. found = 0;
  33097. for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
  33098. - if (((adap_id == address_data->force[i]) ||
  33099. + if (((adap_id == address_data->force[i]) ||
  33100. (address_data->force[i] == ANY_I2C_BUS)) &&
  33101. (addr == address_data->force[i+1])) {
  33102. DEB2(printk(KERN_DEBUG "i2c-core.o: found force parameter for adapter %d, addr %04x\n",
  33103. @@ -862,7 +861,7 @@
  33104. found = 1;
  33105. }
  33106. }
  33107. - if (found)
  33108. + if (found)
  33109. continue;
  33110. /* If this address is in one of the ignores, we can forget about
  33111. @@ -870,7 +869,7 @@
  33112. for (i = 0;
  33113. !found && (address_data->ignore[i] != I2C_CLIENT_END);
  33114. i += 2) {
  33115. - if (((adap_id == address_data->ignore[i]) ||
  33116. + if (((adap_id == address_data->ignore[i]) ||
  33117. ((address_data->ignore[i] == ANY_I2C_BUS))) &&
  33118. (addr == address_data->ignore[i+1])) {
  33119. DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore parameter for adapter %d, "
  33120. @@ -890,11 +889,11 @@
  33121. found = 1;
  33122. }
  33123. }
  33124. - if (found)
  33125. + if (found)
  33126. continue;
  33127. - /* Now, we will do a detection, but only if it is in the normal or
  33128. - probe entries */
  33129. + /* Now, we will do a detection, but only if it is in the normal or
  33130. + probe entries */
  33131. for (i = 0;
  33132. !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
  33133. i += 1) {
  33134. @@ -939,7 +938,7 @@
  33135. "addr %04x\n", adap_id,addr));
  33136. }
  33137. }
  33138. - if (!found)
  33139. + if (!found)
  33140. continue;
  33141. /* OK, so we really should examine this address. First check
  33142. @@ -1087,11 +1086,11 @@
  33143. I2C_SMBUS_I2C_BLOCK_DATA,&data);
  33144. }
  33145. -/* Simulate a SMBus command using the i2c protocol
  33146. +/* Simulate a SMBus command using the i2c protocol
  33147. No checking of parameters is done! */
  33148. -static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
  33149. +static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
  33150. unsigned short flags,
  33151. - char read_write, u8 command, int size,
  33152. + char read_write, u8 command, int size,
  33153. union i2c_smbus_data * data)
  33154. {
  33155. /* So we need to generate a series of msgs. In the case of writing, we
  33156. @@ -1101,7 +1100,7 @@
  33157. unsigned char msgbuf0[34];
  33158. unsigned char msgbuf1[34];
  33159. int num = read_write == I2C_SMBUS_READ?2:1;
  33160. - struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
  33161. + struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
  33162. { addr, flags | I2C_M_RD, 0, msgbuf1 }
  33163. };
  33164. int i;
  33165. @@ -1179,7 +1178,7 @@
  33166. case I2C_SMBUS_BYTE_DATA:
  33167. data->byte = msgbuf1[0];
  33168. break;
  33169. - case I2C_SMBUS_WORD_DATA:
  33170. + case I2C_SMBUS_WORD_DATA:
  33171. case I2C_SMBUS_PROC_CALL:
  33172. data->word = msgbuf1[0] | (msgbuf1[1] << 8);
  33173. break;
  33174. @@ -1189,7 +1188,7 @@
  33175. s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
  33176. - char read_write, u8 command, int size,
  33177. + char read_write, u8 command, int size,
  33178. union i2c_smbus_data * data)
  33179. {
  33180. s32 res;
  33181. @@ -1207,7 +1206,7 @@
  33182. /* You should always define `functionality'; the 'else' is just for
  33183. - backward compatibility. */
  33184. + backward compatibility. */
  33185. u32 i2c_get_functionality (struct i2c_adapter *adap)
  33186. {
  33187. if (adap->algo->functionality)
  33188. @@ -1233,122 +1232,12 @@
  33189. init_MUTEX(&adap_lock);
  33190. init_MUTEX(&driver_lock);
  33191. -
  33192. - i2cproc_init();
  33193. -
  33194. - return 0;
  33195. -}
  33196. -#ifndef MODULE
  33197. -#ifdef CONFIG_I2C_CHARDEV
  33198. - extern int i2c_dev_init(void);
  33199. -#endif
  33200. -#ifdef CONFIG_I2C_ALGOBIT
  33201. - extern int i2c_algo_bit_init(void);
  33202. -#endif
  33203. -#ifdef CONFIG_I2C_PHILIPSPAR
  33204. - extern int i2c_bitlp_init(void);
  33205. -#endif
  33206. -#ifdef CONFIG_I2C_ELV
  33207. - extern int i2c_bitelv_init(void);
  33208. -#endif
  33209. -#ifdef CONFIG_I2C_VELLEMAN
  33210. - extern int i2c_bitvelle_init(void);
  33211. -#endif
  33212. -#ifdef CONFIG_I2C_BITVIA
  33213. - extern int i2c_bitvia_init(void);
  33214. -#endif
  33215. -
  33216. -#ifdef CONFIG_I2C_ALGOPCF
  33217. - extern int i2c_algo_pcf_init(void);
  33218. -#endif
  33219. -#ifdef CONFIG_I2C_ELEKTOR
  33220. - extern int i2c_pcfisa_init(void);
  33221. -#endif
  33222. -
  33223. -#ifdef CONFIG_I2C_ALGO8XX
  33224. - extern int i2c_algo_8xx_init(void);
  33225. -#endif
  33226. -#ifdef CONFIG_I2C_RPXLITE
  33227. - extern int i2c_rpx_init(void);
  33228. -#endif
  33229. -
  33230. -#ifdef CONFIG_I2C_ALGO_SIBYTE
  33231. - extern int i2c_algo_sibyte_init(void);
  33232. - extern int i2c_sibyte_init(void);
  33233. -#endif
  33234. -#ifdef CONFIG_I2C_MAX1617
  33235. - extern int i2c_max1617_init(void);
  33236. -#endif
  33237. -
  33238. -#ifdef CONFIG_I2C_PROC
  33239. - extern int sensors_init(void);
  33240. -#endif
  33241. -
  33242. -/* This is needed for automatic patch generation: sensors code starts here */
  33243. -/* This is needed for automatic patch generation: sensors code ends here */
  33244. -
  33245. -int __init i2c_init_all(void)
  33246. -{
  33247. - /* --------------------- global ----- */
  33248. - i2c_init();
  33249. -
  33250. -#ifdef CONFIG_I2C_CHARDEV
  33251. - i2c_dev_init();
  33252. -#endif
  33253. - /* --------------------- bit -------- */
  33254. -#ifdef CONFIG_I2C_ALGOBIT
  33255. - i2c_algo_bit_init();
  33256. -#endif
  33257. -#ifdef CONFIG_I2C_PHILIPSPAR
  33258. - i2c_bitlp_init();
  33259. -#endif
  33260. -#ifdef CONFIG_I2C_ELV
  33261. - i2c_bitelv_init();
  33262. -#endif
  33263. -#ifdef CONFIG_I2C_VELLEMAN
  33264. - i2c_bitvelle_init();
  33265. -#endif
  33266. -
  33267. - /* --------------------- pcf -------- */
  33268. -#ifdef CONFIG_I2C_ALGOPCF
  33269. - i2c_algo_pcf_init();
  33270. -#endif
  33271. -#ifdef CONFIG_I2C_ELEKTOR
  33272. - i2c_pcfisa_init();
  33273. -#endif
  33274. -
  33275. - /* --------------------- 8xx -------- */
  33276. -#ifdef CONFIG_I2C_ALGO8XX
  33277. - i2c_algo_8xx_init();
  33278. -#endif
  33279. -#ifdef CONFIG_I2C_RPXLITE
  33280. - i2c_rpx_init();
  33281. -#endif
  33282. -
  33283. - /* --------------------- SiByte -------- */
  33284. -#ifdef CONFIG_I2C_ALGO_SIBYTE
  33285. - i2c_algo_sibyte_init();
  33286. - i2c_sibyte_init();
  33287. -#endif
  33288. -#ifdef CONFIG_I2C_MAX1617
  33289. - i2c_max1617_init();
  33290. -#endif
  33291. -
  33292. - /* -------------- proc interface ---- */
  33293. -#ifdef CONFIG_I2C_PROC
  33294. - sensors_init();
  33295. -#endif
  33296. -/* This is needed for automatic patch generation: sensors code starts here */
  33297. -/* This is needed for automatic patch generation: sensors code ends here */
  33298. + i2cproc_init();
  33299. return 0;
  33300. }
  33301. -#endif
  33302. -
  33303. -
  33304. -
  33305. EXPORT_SYMBOL(i2c_add_adapter);
  33306. EXPORT_SYMBOL(i2c_del_adapter);
  33307. EXPORT_SYMBOL(i2c_add_driver);
  33308. @@ -1385,7 +1274,6 @@
  33309. EXPORT_SYMBOL(i2c_get_functionality);
  33310. EXPORT_SYMBOL(i2c_check_functionality);
  33311. -#ifdef MODULE
  33312. MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  33313. MODULE_DESCRIPTION("I2C-Bus main module");
  33314. MODULE_LICENSE("GPL");
  33315. @@ -1393,13 +1281,5 @@
  33316. MODULE_PARM(i2c_debug, "i");
  33317. MODULE_PARM_DESC(i2c_debug,"debug level");
  33318. -int init_module(void)
  33319. -{
  33320. - return i2c_init();
  33321. -}
  33322. -
  33323. -void cleanup_module(void)
  33324. -{
  33325. - i2cproc_cleanup();
  33326. -}
  33327. -#endif
  33328. +module_init(i2c_init);
  33329. +module_exit(i2cproc_cleanup);
  33330. diff -urN linux-2.4.26/drivers/i2c/i2c-dev.c linux-2.4.26-vrs1/drivers/i2c/i2c-dev.c
  33331. --- linux-2.4.26/drivers/i2c/i2c-dev.c 2004-02-27 20:03:25.000000000 +0000
  33332. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-dev.c 2004-02-27 23:54:13.000000000 +0000
  33333. @@ -1,5 +1,5 @@
  33334. /*
  33335. - i2c-dev.c - i2c-bus driver, char device interface
  33336. + i2c-dev.c - i2c-bus driver, char device interface
  33337. Copyright (C) 1995-97 Simon G. Vogl
  33338. Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
  33339. @@ -25,7 +25,7 @@
  33340. /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
  33341. -/* The devfs code is contributed by Philipp Matthias Hahn
  33342. +/* The devfs code is contributed by Philipp Matthias Hahn
  33343. <pmhahn@titan.lahn.de> */
  33344. /* $Id: i2c-dev.c,v 1.40 2001/08/25 01:28:01 mds Exp $ */
  33345. @@ -50,19 +50,14 @@
  33346. #include <linux/i2c.h>
  33347. #include <linux/i2c-dev.h>
  33348. -#ifdef MODULE
  33349. -extern int init_module(void);
  33350. -extern int cleanup_module(void);
  33351. -#endif /* def MODULE */
  33352. -
  33353. /* struct file_operations changed too often in the 2.1 series for nice code */
  33354. -static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
  33355. +static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
  33356. loff_t *offset);
  33357. -static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
  33358. +static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
  33359. loff_t *offset);
  33360. -static int i2cdev_ioctl (struct inode *inode, struct file *file,
  33361. +static int i2cdev_ioctl (struct inode *inode, struct file *file,
  33362. unsigned int cmd, unsigned long arg);
  33363. static int i2cdev_open (struct inode *inode, struct file *file);
  33364. @@ -73,13 +68,8 @@
  33365. static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
  33366. void *arg);
  33367. -#ifdef MODULE
  33368. -static
  33369. -#else
  33370. -extern
  33371. -#endif
  33372. - int __init i2c_dev_init(void);
  33373. -static int i2cdev_cleanup(void);
  33374. +static int __init i2c_dev_init(void);
  33375. +static void i2cdev_cleanup(void);
  33376. static struct file_operations i2cdev_fops = {
  33377. owner: THIS_MODULE,
  33378. @@ -185,7 +175,7 @@
  33379. return ret;
  33380. }
  33381. -int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
  33382. +int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
  33383. unsigned long arg)
  33384. {
  33385. struct i2c_client *client = (struct i2c_client *)file->private_data;
  33386. @@ -198,14 +188,14 @@
  33387. unsigned long funcs;
  33388. #ifdef DEBUG
  33389. - printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
  33390. + printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
  33391. MINOR(inode->i_rdev),cmd, arg);
  33392. #endif /* DEBUG */
  33393. switch ( cmd ) {
  33394. case I2C_SLAVE:
  33395. case I2C_SLAVE_FORCE:
  33396. - if ((arg > 0x3ff) ||
  33397. + if ((arg > 0x3ff) ||
  33398. (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
  33399. return -EINVAL;
  33400. if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
  33401. @@ -224,8 +214,8 @@
  33402. sizeof(unsigned long)))?-EFAULT:0;
  33403. case I2C_RDWR:
  33404. - if (copy_from_user(&rdwr_arg,
  33405. - (struct i2c_rdwr_ioctl_data *)arg,
  33406. + if (copy_from_user(&rdwr_arg,
  33407. + (struct i2c_rdwr_ioctl_data *)arg,
  33408. sizeof(rdwr_arg)))
  33409. return -EFAULT;
  33410. @@ -233,9 +223,9 @@
  33411. * be sent at once */
  33412. if (rdwr_arg.nmsgs > 42)
  33413. return -EINVAL;
  33414. -
  33415. +
  33416. rdwr_pa = (struct i2c_msg *)
  33417. - kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
  33418. + kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
  33419. GFP_KERNEL);
  33420. if (rdwr_pa == NULL) return -ENOMEM;
  33421. @@ -312,9 +302,9 @@
  33422. (struct i2c_smbus_ioctl_data *) arg,
  33423. sizeof(struct i2c_smbus_ioctl_data)))
  33424. return -EFAULT;
  33425. - if ((data_arg.size != I2C_SMBUS_BYTE) &&
  33426. + if ((data_arg.size != I2C_SMBUS_BYTE) &&
  33427. (data_arg.size != I2C_SMBUS_QUICK) &&
  33428. - (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
  33429. + (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
  33430. (data_arg.size != I2C_SMBUS_WORD_DATA) &&
  33431. (data_arg.size != I2C_SMBUS_PROC_CALL) &&
  33432. (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
  33433. @@ -325,9 +315,9 @@
  33434. #endif
  33435. return -EINVAL;
  33436. }
  33437. - /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
  33438. + /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
  33439. so the check is valid if size==I2C_SMBUS_QUICK too. */
  33440. - if ((data_arg.read_write != I2C_SMBUS_READ) &&
  33441. + if ((data_arg.read_write != I2C_SMBUS_READ) &&
  33442. (data_arg.read_write != I2C_SMBUS_WRITE)) {
  33443. #ifdef DEBUG
  33444. printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
  33445. @@ -339,7 +329,7 @@
  33446. /* Note that command values are always valid! */
  33447. if ((data_arg.size == I2C_SMBUS_QUICK) ||
  33448. - ((data_arg.size == I2C_SMBUS_BYTE) &&
  33449. + ((data_arg.size == I2C_SMBUS_BYTE) &&
  33450. (data_arg.read_write == I2C_SMBUS_WRITE)))
  33451. /* These are special: we do not use data */
  33452. return i2c_smbus_xfer(client->adapter, client->addr,
  33453. @@ -358,13 +348,13 @@
  33454. if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
  33455. (data_arg.size == I2C_SMBUS_BYTE))
  33456. datasize = sizeof(data_arg.data->byte);
  33457. - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
  33458. + else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
  33459. (data_arg.size == I2C_SMBUS_PROC_CALL))
  33460. datasize = sizeof(data_arg.data->word);
  33461. else /* size == I2C_SMBUS_BLOCK_DATA */
  33462. datasize = sizeof(data_arg.data->block);
  33463. - if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
  33464. + if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
  33465. (data_arg.read_write == I2C_SMBUS_WRITE)) {
  33466. if (copy_from_user(&temp, data_arg.data, datasize))
  33467. return -EFAULT;
  33468. @@ -372,7 +362,7 @@
  33469. res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
  33470. data_arg.read_write,
  33471. data_arg.command,data_arg.size,&temp);
  33472. - if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
  33473. + if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
  33474. (data_arg.read_write == I2C_SMBUS_READ))) {
  33475. if (copy_to_user(data_arg.data, &temp, datasize))
  33476. return -EFAULT;
  33477. @@ -479,7 +469,7 @@
  33478. return -1;
  33479. }
  33480. -int __init i2c_dev_init(void)
  33481. +static int __init i2c_dev_init(void)
  33482. {
  33483. int res;
  33484. @@ -509,7 +499,7 @@
  33485. return 0;
  33486. }
  33487. -int i2cdev_cleanup(void)
  33488. +static void i2cdev_cleanup(void)
  33489. {
  33490. int res;
  33491. @@ -517,9 +507,9 @@
  33492. if ((res = i2c_del_driver(&i2cdev_driver))) {
  33493. printk("i2c-dev.o: Driver deregistration failed, "
  33494. "module not removed.\n");
  33495. - return res;
  33496. + return;
  33497. }
  33498. - i2cdev_initialized --;
  33499. + i2cdev_initialized --;
  33500. }
  33501. if (i2cdev_initialized >= 1) {
  33502. @@ -531,30 +521,17 @@
  33503. #endif
  33504. printk("i2c-dev.o: unable to release major %d for i2c bus\n",
  33505. I2C_MAJOR);
  33506. - return res;
  33507. + return;
  33508. }
  33509. i2cdev_initialized --;
  33510. }
  33511. - return 0;
  33512. }
  33513. EXPORT_NO_SYMBOLS;
  33514. -#ifdef MODULE
  33515. -
  33516. MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  33517. MODULE_DESCRIPTION("I2C /dev entries driver");
  33518. MODULE_LICENSE("GPL");
  33519. -int init_module(void)
  33520. -{
  33521. - return i2c_dev_init();
  33522. -}
  33523. -
  33524. -int cleanup_module(void)
  33525. -{
  33526. - return i2cdev_cleanup();
  33527. -}
  33528. -
  33529. -#endif /* def MODULE */
  33530. -
  33531. +module_init(i2c_dev_init);
  33532. +module_exit(i2cdev_cleanup);
  33533. diff -urN linux-2.4.26/drivers/i2c/i2c-elektor.c linux-2.4.26-vrs1/drivers/i2c/i2c-elektor.c
  33534. --- linux-2.4.26/drivers/i2c/i2c-elektor.c 2004-02-27 20:03:25.000000000 +0000
  33535. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-elektor.c 2004-02-23 13:36:30.000000000 +0000
  33536. @@ -181,16 +181,12 @@
  33537. static void pcf_isa_inc_use(struct i2c_adapter *adap)
  33538. {
  33539. -#ifdef MODULE
  33540. MOD_INC_USE_COUNT;
  33541. -#endif
  33542. }
  33543. static void pcf_isa_dec_use(struct i2c_adapter *adap)
  33544. {
  33545. -#ifdef MODULE
  33546. MOD_DEC_USE_COUNT;
  33547. -#endif
  33548. }
  33549. @@ -219,7 +215,7 @@
  33550. pcf_isa_unreg,
  33551. };
  33552. -int __init i2c_pcfisa_init(void)
  33553. +static int __init i2c_pcfisa_init(void)
  33554. {
  33555. #ifdef __alpha__
  33556. /* check to see we have memory mapped PCF8584 connected to the
  33557. @@ -289,10 +285,14 @@
  33558. return 0;
  33559. }
  33560. +static void i2c_pcfisa_exit(void)
  33561. +{
  33562. + i2c_pcf_del_bus(&pcf_isa_ops);
  33563. + pcf_isa_exit();
  33564. +}
  33565. EXPORT_NO_SYMBOLS;
  33566. -#ifdef MODULE
  33567. MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
  33568. MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
  33569. MODULE_LICENSE("GPL");
  33570. @@ -304,15 +304,5 @@
  33571. MODULE_PARM(mmapped, "i");
  33572. MODULE_PARM(i2c_debug, "i");
  33573. -int init_module(void)
  33574. -{
  33575. - return i2c_pcfisa_init();
  33576. -}
  33577. -
  33578. -void cleanup_module(void)
  33579. -{
  33580. - i2c_pcf_del_bus(&pcf_isa_ops);
  33581. - pcf_isa_exit();
  33582. -}
  33583. -
  33584. -#endif
  33585. +module_init(i2c_pcfisa_init);
  33586. +module_exit(i2c_pcfisa_exit);
  33587. diff -urN linux-2.4.26/drivers/i2c/i2c-elv.c linux-2.4.26-vrs1/drivers/i2c/i2c-elv.c
  33588. --- linux-2.4.26/drivers/i2c/i2c-elv.c 2004-02-27 20:03:25.000000000 +0000
  33589. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-elv.c 2004-02-27 23:52:23.000000000 +0000
  33590. @@ -75,7 +75,7 @@
  33591. PortData |=2;
  33592. }
  33593. outb(PortData, DATA);
  33594. -}
  33595. +}
  33596. static int bit_elv_getscl(void *data)
  33597. {
  33598. @@ -90,7 +90,7 @@
  33599. static int bit_elv_init(void)
  33600. {
  33601. if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
  33602. - return -ENODEV;
  33603. + return -ENODEV;
  33604. } else {
  33605. /* test for ELV adap. */
  33606. if (inb(base+1) & 0x80) { /* BUSY should be high */
  33607. @@ -131,16 +131,12 @@
  33608. static void bit_elv_inc_use(struct i2c_adapter *adap)
  33609. {
  33610. -#ifdef MODULE
  33611. MOD_INC_USE_COUNT;
  33612. -#endif
  33613. }
  33614. static void bit_elv_dec_use(struct i2c_adapter *adap)
  33615. {
  33616. -#ifdef MODULE
  33617. MOD_DEC_USE_COUNT;
  33618. -#endif
  33619. }
  33620. /* ------------------------------------------------------------------------
  33621. @@ -164,10 +160,10 @@
  33622. bit_elv_inc_use,
  33623. bit_elv_dec_use,
  33624. bit_elv_reg,
  33625. - bit_elv_unreg,
  33626. + bit_elv_unreg,
  33627. };
  33628. -int __init i2c_bitelv_init(void)
  33629. +static int __init i2c_bitelv_init(void)
  33630. {
  33631. printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
  33632. if (base==0) {
  33633. @@ -194,24 +190,19 @@
  33634. }
  33635. +static void __exit i2c_bitelv_exit(void)
  33636. +{
  33637. + i2c_bit_del_bus(&bit_elv_ops);
  33638. + bit_elv_exit();
  33639. +}
  33640. +
  33641. EXPORT_NO_SYMBOLS;
  33642. -#ifdef MODULE
  33643. MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  33644. MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
  33645. MODULE_LICENSE("GPL");
  33646. MODULE_PARM(base, "i");
  33647. -int init_module(void)
  33648. -{
  33649. - return i2c_bitelv_init();
  33650. -}
  33651. -
  33652. -void cleanup_module(void)
  33653. -{
  33654. - i2c_bit_del_bus(&bit_elv_ops);
  33655. - bit_elv_exit();
  33656. -}
  33657. -
  33658. -#endif
  33659. +module_init(i2c_bitelv_init);
  33660. +module_exit(i2c_bitelv_exit);
  33661. diff -urN linux-2.4.26/drivers/i2c/i2c-frodo.c linux-2.4.26-vrs1/drivers/i2c/i2c-frodo.c
  33662. --- linux-2.4.26/drivers/i2c/i2c-frodo.c 1970-01-01 01:00:00.000000000 +0100
  33663. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-frodo.c 2004-01-14 21:32:25.000000000 +0000
  33664. @@ -0,0 +1,114 @@
  33665. +
  33666. +/*
  33667. + * linux/drivers/i2c/i2c-frodo.c
  33668. + *
  33669. + * Author: Abraham van der Merwe <abraham@2d3d.co.za>
  33670. + *
  33671. + * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
  33672. + * Development board (Frodo).
  33673. + *
  33674. + * This source code is free software; you can redistribute it and/or
  33675. + * modify it under the terms of the GNU General Public License
  33676. + * version 2 as published by the Free Software Foundation.
  33677. + */
  33678. +
  33679. +#include <linux/config.h>
  33680. +#include <linux/version.h>
  33681. +#include <linux/module.h>
  33682. +
  33683. +#include <linux/kernel.h>
  33684. +#include <linux/init.h>
  33685. +#include <linux/delay.h>
  33686. +
  33687. +#include <asm/hardware.h>
  33688. +
  33689. +#include <linux/i2c.h>
  33690. +#include <linux/i2c-algo-bit.h>
  33691. +
  33692. +static void frodo_setsda (void *data,int state)
  33693. +{
  33694. + if (state)
  33695. + frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
  33696. + else
  33697. + frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
  33698. +}
  33699. +
  33700. +static void frodo_setscl (void *data,int state)
  33701. +{
  33702. + if (state)
  33703. + frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
  33704. + else
  33705. + frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
  33706. +}
  33707. +
  33708. +static int frodo_getsda (void *data)
  33709. +{
  33710. + return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SDA_IN) != 0);
  33711. +}
  33712. +
  33713. +static int frodo_getscl (void *data)
  33714. +{
  33715. + return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SCL_IN) != 0);
  33716. +}
  33717. +
  33718. +static struct i2c_algo_bit_data bit_frodo_data = {
  33719. + setsda: frodo_setsda,
  33720. + setscl: frodo_setscl,
  33721. + getsda: frodo_getsda,
  33722. + getscl: frodo_getscl,
  33723. + udelay: 80,
  33724. + mdelay: 80,
  33725. + timeout: 100
  33726. +};
  33727. +
  33728. +static int frodo_client_register (struct i2c_client *client)
  33729. +{
  33730. + return (0);
  33731. +}
  33732. +
  33733. +static int frodo_client_unregister (struct i2c_client *client)
  33734. +{
  33735. + return (0);
  33736. +}
  33737. +
  33738. +static void frodo_inc_use (struct i2c_adapter *adapter)
  33739. +{
  33740. + MOD_INC_USE_COUNT;
  33741. +}
  33742. +
  33743. +static void frodo_dec_use (struct i2c_adapter *adapter)
  33744. +{
  33745. + MOD_DEC_USE_COUNT;
  33746. +}
  33747. +
  33748. +static struct i2c_adapter frodo_ops = {
  33749. + name: "Frodo adapter driver",
  33750. + id: I2C_HW_B_FRODO,
  33751. + algo: NULL,
  33752. + algo_data: &bit_frodo_data,
  33753. + inc_use: frodo_inc_use,
  33754. + dec_use: frodo_dec_use,
  33755. + client_register: frodo_client_register,
  33756. + client_unregister: frodo_client_unregister
  33757. +};
  33758. +
  33759. +static int __init i2c_frodo_init (void)
  33760. +{
  33761. + return (i2c_bit_add_bus (&frodo_ops));
  33762. +}
  33763. +
  33764. +EXPORT_NO_SYMBOLS;
  33765. +
  33766. +static void __exit i2c_frodo_exit (void)
  33767. +{
  33768. + i2c_bit_del_bus (&frodo_ops);
  33769. +}
  33770. +
  33771. +MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
  33772. +MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
  33773. +MODULE_LICENSE ("GPL");
  33774. +EXPORT_NO_SYMBOLS;
  33775. +
  33776. +module_init (i2c_frodo_init);
  33777. +module_exit (i2c_frodo_exit);
  33778. +
  33779. diff -urN linux-2.4.26/drivers/i2c/i2c-guide.c linux-2.4.26-vrs1/drivers/i2c/i2c-guide.c
  33780. --- linux-2.4.26/drivers/i2c/i2c-guide.c 1970-01-01 01:00:00.000000000 +0100
  33781. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-guide.c 2004-01-14 21:32:25.000000000 +0000
  33782. @@ -0,0 +1,199 @@
  33783. +/************************************************************************************\
  33784. +Copyright : Copyright (C) 1995-2000 Simon G. Vogl
  33785. + Copyright 2002 IDERs Incorporated
  33786. +File Name : i2c-guide.c
  33787. +Description : this i2c driver uses the GPIO port B pin 0 and pin 1 on the cs89712.
  33788. +Notes : To change the bit rate, change the structure i2c_algo_bit_data
  33789. + : to 10 10 100
  33790. +Contact : tsong@iders.ca
  33791. +License : This source code is free software; you can redistribute it and/or
  33792. + modify it under the terms of the GNU General Public License
  33793. + version 2 as published by the Free Software Foundation.
  33794. +\************************************************************************************/
  33795. +
  33796. +#include <linux/kernel.h>
  33797. +#include <linux/ioport.h>
  33798. +#include <linux/module.h>
  33799. +#include <linux/init.h>
  33800. +#include <linux/string.h> /* for 2.0 kernels to get NULL */
  33801. +#include <asm/errno.h> /* for 2.0 kernels to get ENODEV */
  33802. +#include <asm/io.h>
  33803. +
  33804. +#include <asm/hardware/cs89712.h> // io operation ep_writel()
  33805. +#include <asm/hardware/clps7111.h> // io operation clps_writel()
  33806. +#include <asm/arch-clps711x/hardware.h> // io operation clps_writel()
  33807. +
  33808. +#include <linux/i2c.h>
  33809. +#include <linux/i2c-algo-bit.h>
  33810. +
  33811. +/* ----- global defines ----------------------------------------------- */
  33812. +
  33813. +#define DEB(x) /* should be reasonable open, close &c. */
  33814. +#define DEB2(x) /* low level debugging - very slow */
  33815. +#define DEBE(x) x /* error messages */
  33816. + /* Pin Port Inverted name */
  33817. +#define I2C_SDA 0x08 /* port B ctrl pin 3 (inv) */
  33818. +#define I2C_SCL 0x04 /* port B ctrl pin 2 (inv) */
  33819. +
  33820. +#define I2C_SDAIN 0x08 /* use the same pin with output */
  33821. +#define I2C_SCLIN 0x04 /* use the same pin with output */
  33822. +
  33823. +#define I2C_DMASK 0xf7 /* inverse of I2C_SDA */
  33824. +#define I2C_CMASK 0xfb /* inverse of I2c_SCL */
  33825. +
  33826. +#define PORTB_PIN0_SDA_OUTPUT 0x08 /* pin 3 direction of port B output */
  33827. +#define PORTB_PIN0_SDA_INPUT 0xf7 /* pin 3 direction of port B input */
  33828. +
  33829. +#define PORTB_PIN1_SCL_OUTPUT 0x04 /* pin 2 direction of port B output */
  33830. +#define PORTB_PIN1_SCL_INPUT 0xfb /* pin 2 direction of port B input */
  33831. +
  33832. +int base = 0;
  33833. +#define DEFAULT_BASE PBDR
  33834. +
  33835. +/* ----- local functions --------------------------------------------------- */
  33836. +
  33837. +static void bit_guide_setscl(void* data, int state)
  33838. +{
  33839. + if (state) {
  33840. + // set port B pin2 input
  33841. + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN1_SCL_INPUT, PBDDR);
  33842. + }
  33843. + else {
  33844. + // clear
  33845. + clps_writeb((clps_readb(PBDR)) & I2C_CMASK, PBDR);
  33846. + // set port B pin2 output
  33847. + clps_writeb((clps_readb(PBDDR)) | PORTB_PIN1_SCL_OUTPUT, PBDDR);
  33848. + }
  33849. +}
  33850. +
  33851. +static void bit_guide_setsda(void* data, int state)
  33852. +{
  33853. + if (state) {
  33854. + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
  33855. + // float pin 0 (actually drive high by pull up resistor)
  33856. + // clps_writeb((clps_readb(PBDR)) | I2C_SDA, PBDR); // set Jan4 ori: eff
  33857. + // printk("set sda high, state=%i\n",state);
  33858. + }
  33859. + else {
  33860. + // clear
  33861. + clps_writeb((clps_readb(PBDR)) & I2C_DMASK, PBDR);
  33862. + // set port B pin 0 output
  33863. + clps_writeb((clps_readb(PBDDR)) | PORTB_PIN0_SDA_OUTPUT, PBDDR);
  33864. + }
  33865. +}
  33866. +
  33867. +static int bit_guide_getscl(void *data)
  33868. +{
  33869. + return ( 0 != ( (clps_readb(PBDR)) & I2C_SCLIN ) );
  33870. +}
  33871. +
  33872. +static int bit_guide_getsda(void *data)
  33873. +{
  33874. + // set port B pin 0 input Jan4 ori eff
  33875. + clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
  33876. + return ( 0 != ( (clps_readb(PBDR) ) & I2C_SDAIN ) );
  33877. +}
  33878. +
  33879. +static int bit_guide_init(void)
  33880. +{
  33881. + bit_guide_setsda((void*)base,1);
  33882. + bit_guide_setscl((void*)base,1);
  33883. + return 0;
  33884. +}
  33885. +
  33886. +static int bit_guide_reg(struct i2c_client *client)
  33887. +{
  33888. + return 0;
  33889. +}
  33890. +
  33891. +static int bit_guide_unreg(struct i2c_client *client)
  33892. +{
  33893. + return 0;
  33894. +}
  33895. +
  33896. +static void bit_guide_inc_use(struct i2c_adapter *adap)
  33897. +{
  33898. +#ifdef MODULE
  33899. + MOD_INC_USE_COUNT;
  33900. +#endif
  33901. +}
  33902. +
  33903. +static void bit_guide_dec_use(struct i2c_adapter *adap)
  33904. +{
  33905. +#ifdef MODULE
  33906. + MOD_DEC_USE_COUNT;
  33907. +#endif
  33908. +}
  33909. +
  33910. +/* ------------------------------------------------------------------------
  33911. + * Encapsulate the above functions in the correct operations structure.
  33912. + * This is only done when more than one hardware adapter is supported.
  33913. + */
  33914. +
  33915. +/* last line (us, ms, timout)
  33916. + * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps)
  33917. + * 10ms not known
  33918. + * 100ms timeout
  33919. + */
  33920. +static struct i2c_algo_bit_data bit_guide_data = {
  33921. + NULL,
  33922. + bit_guide_setsda,
  33923. + bit_guide_setscl,
  33924. + bit_guide_getsda,
  33925. + bit_guide_getscl,
  33926. + 50, 10, 100, /* orginal (non-guide) value 10, 10, 100 */
  33927. +};
  33928. +
  33929. +static struct i2c_adapter bit_guide_ops = {
  33930. + "Guide Port B: PIN2-SCL/PIN3-SDA",
  33931. + I2C_HW_B_GUIDE,
  33932. + NULL,
  33933. + &bit_guide_data,
  33934. + bit_guide_inc_use,
  33935. + bit_guide_dec_use,
  33936. + bit_guide_reg,
  33937. + bit_guide_unreg,
  33938. +};
  33939. +
  33940. +static int __init i2c_bitguide_init(void)
  33941. +{
  33942. + printk("i2c-guide.o: Guide i2c port B adapter module.\n");
  33943. + clps_writeb((clps_readb(PBDDR)) & 0xfd, PBDDR); // set service reuest pb1 as input
  33944. + if (base==0) {
  33945. + /* probe some values */
  33946. + base=DEFAULT_BASE;
  33947. + bit_guide_data.data=(void*)DEFAULT_BASE;
  33948. + if (bit_guide_init()==0) {
  33949. + if(i2c_bit_add_bus(&bit_guide_ops) < 0)
  33950. + return -ENODEV;
  33951. + } else {
  33952. + return -ENODEV;
  33953. + }
  33954. + } else {
  33955. + bit_guide_data.data=(void*)base;
  33956. + if (bit_guide_init()==0) {
  33957. + if(i2c_bit_add_bus(&bit_guide_ops) < 0)
  33958. + return -ENODEV;
  33959. + } else {
  33960. + return -ENODEV;
  33961. + }
  33962. + }
  33963. + printk("i2c-guide.o: found device at %#x.\n",base);
  33964. + return 0;
  33965. +}
  33966. +
  33967. +EXPORT_NO_SYMBOLS;
  33968. +
  33969. +MODULE_AUTHOR("T. C. Song <tsong@iders.ca>");
  33970. +MODULE_DESCRIPTION("I2C-Bus adapter routines for Guide (cs89712) GPIO port B");
  33971. +MODULE_LICENSE("GPL");
  33972. +
  33973. +MODULE_PARM(base, "i");
  33974. +
  33975. +module_init(i2c_bitguide_init);
  33976. +/* for completeness, we should have a module_exit() function, but the
  33977. + GUIDE requires this to always be loaded. If it is unloaded, the
  33978. + operation of the GUIDE is undefined.
  33979. + Nobody has written the i2c_bitguide_exit() routine yet, so it is not included.
  33980. +module_exit(i2c_bitguide_exit);
  33981. +*/
  33982. diff -urN linux-2.4.26/drivers/i2c/i2c-omaha.c linux-2.4.26-vrs1/drivers/i2c/i2c-omaha.c
  33983. --- linux-2.4.26/drivers/i2c/i2c-omaha.c 1970-01-01 01:00:00.000000000 +0100
  33984. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-omaha.c 2004-01-14 21:32:25.000000000 +0000
  33985. @@ -0,0 +1,276 @@
  33986. +/* ------------------------------------------------------------------------- *
  33987. + Copyright ARM Limited 2002. All rights reserved.
  33988. +
  33989. + i2c driver for Omaha
  33990. +
  33991. + Notes:Based on i2c-elv.c
  33992. +
  33993. + The S3C2400X01 has better support for I2C, but bit oriented operations
  33994. + are directly supported by the other I2C layers, so we use that method
  33995. + of performing I2C operations.
  33996. +
  33997. + Copyright (C) 1995-2000 Simon G. Vogl
  33998. +
  33999. + This program is free software; you can redistribute it and/or modify
  34000. + it under the terms of the GNU General Public License as published by
  34001. + the Free Software Foundation; either version 2 of the License, or
  34002. + (at your option) any later version.
  34003. +
  34004. + This program is distributed in the hope that it will be useful,
  34005. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  34006. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  34007. + GNU General Public License for more details.
  34008. +
  34009. + You should have received a copy of the GNU General Public License
  34010. + along with this program; if not, write to the Free Software
  34011. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  34012. +/* ------------------------------------------------------------------------- */
  34013. +
  34014. +#include <linux/kernel.h>
  34015. +#include <linux/module.h>
  34016. +#include <linux/delay.h>
  34017. +#include <linux/slab.h>
  34018. +#include <linux/version.h>
  34019. +#include <linux/init.h>
  34020. +#include <asm/irq.h>
  34021. +#include <asm/io.h>
  34022. +#include <asm/uaccess.h>
  34023. +#include <linux/ioport.h>
  34024. +#include <linux/errno.h>
  34025. +#include <linux/sched.h>
  34026. +
  34027. +#include <linux/i2c.h>
  34028. +#include <linux/i2c-algo-bit.h>
  34029. +
  34030. +#include <asm/io.h>
  34031. +#include <asm/hardware.h>
  34032. +
  34033. +/* ----- global defines ----------------------------------------------- */
  34034. +#define DEB(x) if (i2c_debug>=1) x;
  34035. +#define DEB2(x) if (i2c_debug>=2) x;
  34036. +#define DEB3(x) if (i2c_debug>=3) x
  34037. +#define DEBE(x) x // error messages
  34038. +#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
  34039. +#define DEBPROTO(x) if (i2c_debug>=9) { x; }
  34040. + /* debug the protocol by showing transferred bits */
  34041. +
  34042. +/* Register and bitdefs for Omaha */
  34043. +
  34044. +// Port G control registers
  34045. +static volatile unsigned int pgcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
  34046. +static volatile unsigned int pgdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGDAT);
  34047. +
  34048. +static volatile unsigned int opencr = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_OPENCR);
  34049. +
  34050. +static int base = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
  34051. +
  34052. +// Open drain control registers
  34053. +#define OPC_CMD BIT2
  34054. +#define OPC_DAT BIT3
  34055. +
  34056. +// data bits in GPIO Port G data register
  34057. +#define OMAHA_SDA BIT5
  34058. +#define OMAHA_SCL BIT6
  34059. +#define IIC_WP BIT3 // Write Protect for EEPROM
  34060. +
  34061. +// input/out select bits in GPIO G control register
  34062. +#define IIC_BITS (BIT12|BIT10|BIT6);
  34063. +
  34064. +
  34065. +/* ----- local functions ---------------------------------------------- */
  34066. +
  34067. +
  34068. +static void bit_omaha_setscl(void *data, int state)
  34069. +{
  34070. + unsigned int tmp;
  34071. +
  34072. + if (state)
  34073. + {
  34074. + tmp = __raw_readl(pgdat);
  34075. + tmp |= OMAHA_SCL;
  34076. + __raw_writel(tmp,pgdat);
  34077. + }
  34078. + else
  34079. + {
  34080. + tmp = __raw_readl(pgdat);
  34081. + tmp &= ~OMAHA_SCL;
  34082. + __raw_writel(tmp,pgdat);
  34083. + }
  34084. +}
  34085. +
  34086. +static void bit_omaha_setsda(void *data, int state)
  34087. +{
  34088. + unsigned int tmp;
  34089. +
  34090. + // ensure that sda is an output at the moment
  34091. + tmp = __raw_readl(pgcon);
  34092. + tmp = tmp | BIT10;
  34093. + __raw_writel(tmp,pgcon);
  34094. +
  34095. + if (state)
  34096. + {
  34097. + tmp = __raw_readl(pgdat);
  34098. + tmp |= OMAHA_SDA;
  34099. + __raw_writel(tmp,pgdat);
  34100. + }
  34101. + else
  34102. + {
  34103. + tmp = __raw_readl(pgdat);
  34104. + tmp &= ~OMAHA_SDA;
  34105. + __raw_writel(tmp,pgdat);
  34106. + }
  34107. +}
  34108. +
  34109. +static int bit_omaha_getscl(void *data)
  34110. +{
  34111. + if (__raw_readl(pgdat) & OMAHA_SCL)
  34112. + return 1;
  34113. + else
  34114. + return 0;
  34115. +}
  34116. +
  34117. +static int bit_omaha_getsda(void *data)
  34118. +{
  34119. + unsigned int tmp;
  34120. +
  34121. + // ensure that sda is an output at the moment
  34122. + tmp = __raw_readl(pgcon);
  34123. + tmp = tmp & ~BIT10;
  34124. + __raw_writel(tmp,pgcon);
  34125. +
  34126. + if (__raw_readl(pgdat) & OMAHA_SDA)
  34127. + return 1;
  34128. + else
  34129. + return 0;
  34130. +}
  34131. +
  34132. +static int bit_omaha_init(void)
  34133. +{
  34134. + // Have we got some mmapped space?
  34135. + if (request_region(base, 0x100, "i2c (omaha bus adapter)") < 0 )
  34136. + {
  34137. + printk("i2c-omaha.o: requested I/O region (0x%08x) is in use.\n", base);
  34138. + return -ENODEV;
  34139. + }
  34140. +
  34141. + return 0;
  34142. +}
  34143. +
  34144. +
  34145. +static int bit_omaha_reg(struct i2c_client *client)
  34146. +{
  34147. + return 0;
  34148. +}
  34149. +
  34150. +
  34151. +static int bit_omaha_unreg(struct i2c_client *client)
  34152. +{
  34153. + return 0;
  34154. +}
  34155. +
  34156. +static void bit_omaha_inc_use(struct i2c_adapter *adap)
  34157. +{
  34158. + MOD_INC_USE_COUNT;
  34159. +}
  34160. +
  34161. +static void bit_omaha_dec_use(struct i2c_adapter *adap)
  34162. +{
  34163. + MOD_DEC_USE_COUNT;
  34164. +}
  34165. +
  34166. +
  34167. +
  34168. +/* ------------------------------------------------------------------------
  34169. + * Encapsulate the above functions in the correct operations structure.
  34170. + * This is only done when more than one hardware adapter is supported.
  34171. + */
  34172. +static struct i2c_algo_bit_data bit_omaha_data = {
  34173. + NULL,
  34174. + bit_omaha_setsda,
  34175. + bit_omaha_setscl,
  34176. + bit_omaha_getsda,
  34177. + bit_omaha_getscl,
  34178. + 10, 10, 20, /* waits, timeout */
  34179. +};
  34180. +
  34181. +static struct i2c_adapter bit_omaha_ops = {
  34182. + "BIT-Type Omaha I2C adapter",
  34183. + I2C_HW_B_OMAHA,
  34184. + NULL,
  34185. + &bit_omaha_data,
  34186. + bit_omaha_inc_use,
  34187. + bit_omaha_dec_use,
  34188. + bit_omaha_reg,
  34189. + bit_omaha_unreg,
  34190. +};
  34191. +
  34192. +static int __init i2c_omaha_init (void)
  34193. +{
  34194. + unsigned int tmp;
  34195. +
  34196. + printk("i2c-omaha.o: i2c omaha adapter module\n");
  34197. +
  34198. + if (bit_omaha_init() == 0) {
  34199. + if(i2c_bit_add_bus(&bit_omaha_ops) < 0)
  34200. + {
  34201. + printk("Could not add bus!\n");
  34202. + return -ENODEV;
  34203. + }
  34204. + } else {
  34205. + printk("Could not pcf_omaha_init\n");
  34206. + return -ENODEV;
  34207. + }
  34208. +
  34209. + // Program Port G bits to output function
  34210. + tmp = __raw_readl(pgcon);
  34211. + tmp |= IIC_BITS;
  34212. + __raw_writel(tmp,pgcon);
  34213. +
  34214. + // Ensure SDA and SCL are open-drain
  34215. + tmp = __raw_readl(opencr);
  34216. + tmp = tmp | OPC_CMD | OPC_DAT;
  34217. + __raw_writel(tmp,opencr);
  34218. +
  34219. + bit_omaha_setsda((void*)base,1);
  34220. + bit_omaha_setscl((void*)base,1);
  34221. +
  34222. + // Disable WP
  34223. + tmp = __raw_readl(pgdat);
  34224. + tmp = tmp & ~IIC_WP;
  34225. + __raw_writel(tmp,pgdat);
  34226. +
  34227. + return 0;
  34228. +}
  34229. +
  34230. +static void bit_omaha_exit(void)
  34231. +{
  34232. + release_region(base , 2);
  34233. +}
  34234. +
  34235. +static void i2c_omaha_exit(void)
  34236. +{
  34237. +
  34238. + i2c_bit_del_bus(&bit_omaha_ops);
  34239. +
  34240. + bit_omaha_exit();
  34241. +
  34242. +}
  34243. +
  34244. +EXPORT_NO_SYMBOLS;
  34245. +
  34246. +MODULE_AUTHOR("ARM Limited <support@arm.com>");
  34247. +MODULE_DESCRIPTION("I2C-Bus adapter routines for Omaha");
  34248. +MODULE_LICENSE("GPL");
  34249. +
  34250. +MODULE_PARM(base, "i");
  34251. +MODULE_PARM(irq, "i");
  34252. +MODULE_PARM(clock, "i");
  34253. +MODULE_PARM(own, "i");
  34254. +MODULE_PARM(mmapped, "i");
  34255. +MODULE_PARM(i2c_debug, "i");
  34256. +
  34257. +
  34258. +module_init(i2c_omaha_init);
  34259. +module_exit(i2c_omaha_exit);
  34260. +
  34261. +
  34262. diff -urN linux-2.4.26/drivers/i2c/i2c-philips-par.c linux-2.4.26-vrs1/drivers/i2c/i2c-philips-par.c
  34263. --- linux-2.4.26/drivers/i2c/i2c-philips-par.c 2004-02-27 20:03:25.000000000 +0000
  34264. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-philips-par.c 2004-02-27 23:50:14.000000000 +0000
  34265. @@ -16,7 +16,7 @@
  34266. You should have received a copy of the GNU General Public License
  34267. along with this program; if not, write to the Free Software
  34268. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  34269. -/* ------------------------------------------------------------------------- */
  34270. +/* ------------------------------------------------------------------------- */
  34271. /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
  34272. Frodo Looijaard <frodol@dds.nl> */
  34273. @@ -72,7 +72,7 @@
  34274. static void bit_lp_setscl(void *data, int state)
  34275. {
  34276. - /*be cautious about state of the control register -
  34277. + /*be cautious about state of the control register -
  34278. touch only the one bit needed*/
  34279. if (state) {
  34280. parport_write_control((struct parport *) data,
  34281. @@ -126,7 +126,7 @@
  34282. static int bit_lp_getsda2(void *data)
  34283. {
  34284. - return (parport_read_status((struct parport *) data) &
  34285. + return (parport_read_status((struct parport *) data) &
  34286. PARPORT_STATUS_BUSY) ? 0 : 1;
  34287. }
  34288. @@ -154,7 +154,7 @@
  34289. * Encapsulate the above functions in the correct operations structure.
  34290. * This is only done when more than one hardware adapter is supported.
  34291. */
  34292. -
  34293. +
  34294. static struct i2c_algo_bit_data bit_lp_data = {
  34295. NULL,
  34296. bit_lp_setsda,
  34297. @@ -162,7 +162,7 @@
  34298. bit_lp_getsda,
  34299. bit_lp_getscl,
  34300. 80, 80, 100, /* waits, timeout */
  34301. -};
  34302. +};
  34303. static struct i2c_algo_bit_data bit_lp_data2 = {
  34304. NULL,
  34305. @@ -171,7 +171,7 @@
  34306. bit_lp_getsda2,
  34307. NULL,
  34308. 80, 80, 100, /* waits, timeout */
  34309. -};
  34310. +};
  34311. static struct i2c_adapter bit_lp_ops = {
  34312. "Philips Parallel port adapter",
  34313. @@ -197,7 +197,7 @@
  34314. printk(KERN_DEBUG "i2c-philips-par.o: attaching to %s\n", port->name);
  34315. adapter->pdev = parport_register_device(port, "i2c-philips-par",
  34316. - NULL, NULL, NULL,
  34317. + NULL, NULL, NULL,
  34318. PARPORT_FLAG_EXCL,
  34319. NULL);
  34320. if (!adapter->pdev) {
  34321. @@ -257,16 +257,16 @@
  34322. NULL
  34323. };
  34324. -int __init i2c_bitlp_init(void)
  34325. +static int __init i2c_bitlp_init(void)
  34326. {
  34327. printk(KERN_INFO "i2c-philips-par.o: i2c Philips parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
  34328. parport_register_driver(&i2c_driver);
  34329. -
  34330. +
  34331. return 0;
  34332. }
  34333. -void __exit i2c_bitlp_exit(void)
  34334. +static void __exit i2c_bitlp_exit(void)
  34335. {
  34336. parport_unregister_driver(&i2c_driver);
  34337. }
  34338. @@ -279,14 +279,5 @@
  34339. MODULE_PARM(type, "i");
  34340. -#ifdef MODULE
  34341. -int init_module(void)
  34342. -{
  34343. - return i2c_bitlp_init();
  34344. -}
  34345. -
  34346. -void cleanup_module(void)
  34347. -{
  34348. - i2c_bitlp_exit();
  34349. -}
  34350. -#endif
  34351. +module_init(i2c_bitlp_init);
  34352. +module_exit(i2c_bitlp_exit);
  34353. diff -urN linux-2.4.26/drivers/i2c/i2c-velleman.c linux-2.4.26-vrs1/drivers/i2c/i2c-velleman.c
  34354. --- linux-2.4.26/drivers/i2c/i2c-velleman.c 2004-02-27 20:03:25.000000000 +0000
  34355. +++ linux-2.4.26-vrs1/drivers/i2c/i2c-velleman.c 2004-02-27 23:46:12.000000000 +0000
  34356. @@ -65,7 +65,7 @@
  34357. } else {
  34358. outb(inb(CTRL) | I2C_SCL, CTRL);
  34359. }
  34360. -
  34361. +
  34362. }
  34363. static void bit_velle_setsda(void *data, int state)
  34364. @@ -75,8 +75,8 @@
  34365. } else {
  34366. outb(inb(CTRL) | I2C_SDA, CTRL);
  34367. }
  34368. -
  34369. -}
  34370. +
  34371. +}
  34372. static int bit_velle_getscl(void *data)
  34373. {
  34374. @@ -95,7 +95,7 @@
  34375. base));
  34376. return -ENODEV;
  34377. } else {
  34378. - request_region(base, (base == 0x3bc)? 3 : 8,
  34379. + request_region(base, (base == 0x3bc)? 3 : 8,
  34380. "i2c (Vellemann adapter)");
  34381. bit_velle_setsda((void*)base,1);
  34382. bit_velle_setscl((void*)base,1);
  34383. @@ -104,7 +104,7 @@
  34384. }
  34385. static void __exit bit_velle_exit(void)
  34386. -{
  34387. +{
  34388. release_region( base , (base == 0x3bc)? 3 : 8 );
  34389. }
  34390. @@ -121,16 +121,12 @@
  34391. static void bit_velle_inc_use(struct i2c_adapter *adap)
  34392. {
  34393. -#ifdef MODULE
  34394. MOD_INC_USE_COUNT;
  34395. -#endif
  34396. }
  34397. static void bit_velle_dec_use(struct i2c_adapter *adap)
  34398. {
  34399. -#ifdef MODULE
  34400. MOD_DEC_USE_COUNT;
  34401. -#endif
  34402. }
  34403. /* ------------------------------------------------------------------------
  34404. @@ -158,7 +154,7 @@
  34405. bit_velle_unreg,
  34406. };
  34407. -int __init i2c_bitvelle_init(void)
  34408. +static int __init i2c_bitvelle_init(void)
  34409. {
  34410. printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
  34411. if (base==0) {
  34412. @@ -184,24 +180,19 @@
  34413. return 0;
  34414. }
  34415. +static void __exit i2c_bitvelle_exit(void)
  34416. +{
  34417. + i2c_bit_del_bus(&bit_velle_ops);
  34418. + bit_velle_exit();
  34419. +}
  34420. +
  34421. EXPORT_NO_SYMBOLS;
  34422. -#ifdef MODULE
  34423. MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  34424. MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter");
  34425. MODULE_LICENSE("GPL");
  34426. MODULE_PARM(base, "i");
  34427. -int init_module(void)
  34428. -{
  34429. - return i2c_bitvelle_init();
  34430. -}
  34431. -
  34432. -void cleanup_module(void)
  34433. -{
  34434. - i2c_bit_del_bus(&bit_velle_ops);
  34435. - bit_velle_exit();
  34436. -}
  34437. -
  34438. -#endif
  34439. +module_init(i2c_bitvelle_init);
  34440. +module_exit(i2c_bitvelle_exit);
  34441. diff -urN linux-2.4.26/drivers/ide/Config.in linux-2.4.26-vrs1/drivers/ide/Config.in
  34442. --- linux-2.4.26/drivers/ide/Config.in 2004-04-19 11:44:16.000000000 +0100
  34443. +++ linux-2.4.26-vrs1/drivers/ide/Config.in 2004-04-18 21:47:50.000000000 +0100
  34444. @@ -107,6 +107,9 @@
  34445. define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS
  34446. dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN
  34447. fi
  34448. + if [ "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
  34449. + dep_bool ' RiscStation IDE' CONFIG_BLK_DEV_IDE_RISCSTATION $CONFIG_ARCH_RISCSTATION
  34450. + fi
  34451. if [ "$CONFIG_AMIGA" = "y" ]; then
  34452. dep_bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
  34453. dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
  34454. diff -urN linux-2.4.26/drivers/ide/arm/Makefile linux-2.4.26-vrs1/drivers/ide/arm/Makefile
  34455. --- linux-2.4.26/drivers/ide/arm/Makefile 2003-06-13 15:51:33.000000000 +0100
  34456. +++ linux-2.4.26-vrs1/drivers/ide/arm/Makefile 2004-01-14 21:32:25.000000000 +0000
  34457. @@ -6,6 +6,7 @@
  34458. obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
  34459. obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
  34460. +obj-$(CONFIG_BLK_DEV_IDE_RISCSTATION) += rstation-ide.o
  34461. EXTRA_CFLAGS := -I../
  34462. diff -urN linux-2.4.26/drivers/ide/arm/icside.c linux-2.4.26-vrs1/drivers/ide/arm/icside.c
  34463. --- linux-2.4.26/drivers/ide/arm/icside.c 2003-06-13 15:51:33.000000000 +0100
  34464. +++ linux-2.4.26-vrs1/drivers/ide/arm/icside.c 2004-01-14 21:32:25.000000000 +0000
  34465. @@ -1,7 +1,7 @@
  34466. /*
  34467. * linux/drivers/ide/arm/icside.c
  34468. *
  34469. - * Copyright (c) 1996,1997 Russell King.
  34470. + * Copyright (c) 1996-2003 Russell King.
  34471. *
  34472. * Changelog:
  34473. * 08-Jun-1996 RMK Created
  34474. @@ -26,24 +26,6 @@
  34475. #include <asm/ecard.h>
  34476. #include <asm/io.h>
  34477. -#include "ide-noise.h"
  34478. -
  34479. -/*
  34480. - * FIXME: We want to drop the the MACRO CRAP!
  34481. - *
  34482. - * ec->iops->in{b/w/l}
  34483. - * ec->iops->in{b/w/l}_p
  34484. - * ec->iops->out{b/w/l}
  34485. - * ec->iops->out{b/w/l}_p
  34486. - *
  34487. - * the new core supports clean MMIO calls and other goodies
  34488. - */
  34489. -
  34490. -/*
  34491. - * Maximum number of interfaces per card
  34492. - */
  34493. -#define MAX_IFS 2
  34494. -
  34495. #define ICS_IDENT_OFFSET 0x8a0
  34496. #define ICS_ARCIN_V5_INTRSTAT 0x000
  34497. @@ -86,17 +68,20 @@
  34498. ICS_ARCIN_V6_IDESTEPPING
  34499. };
  34500. -static const card_ids icside_cids[] = {
  34501. - { MANU_ICS, PROD_ICS_IDE },
  34502. - { MANU_ICS2, PROD_ICS2_IDE },
  34503. - { 0xffff, 0xffff }
  34504. +struct icside_state {
  34505. + unsigned int channel;
  34506. + unsigned int enabled;
  34507. + unsigned long irq_port;
  34508. + unsigned long slot_port;
  34509. + unsigned int type;
  34510. + ide_hwif_t *hwif[2];
  34511. };
  34512. -typedef enum {
  34513. - ics_if_unknown,
  34514. - ics_if_arcin_v5,
  34515. - ics_if_arcin_v6
  34516. -} iftype_t;
  34517. +#define ICS_TYPE_A3IN 0
  34518. +#define ICS_TYPE_A3USER 1
  34519. +#define ICS_TYPE_V6 3
  34520. +#define ICS_TYPE_V5 15
  34521. +#define ICS_TYPE_NOTYPE ((unsigned int)-1)
  34522. /* ---------------- Version 5 PCB Support Functions --------------------- */
  34523. /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
  34524. @@ -104,8 +89,10 @@
  34525. */
  34526. static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
  34527. {
  34528. - unsigned int memc_port = (unsigned int)ec->irq_data;
  34529. - outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET);
  34530. + struct icside_state *state = ec->irq_data;
  34531. + unsigned int base = state->irq_port;
  34532. +
  34533. + outb(0, base + ICS_ARCIN_V5_INTROFFSET);
  34534. }
  34535. /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
  34536. @@ -113,17 +100,15 @@
  34537. */
  34538. static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
  34539. {
  34540. - unsigned int memc_port = (unsigned int)ec->irq_data;
  34541. - inb(memc_port + ICS_ARCIN_V5_INTROFFSET);
  34542. + struct icside_state *state = ec->irq_data;
  34543. + unsigned int base = state->irq_port;
  34544. +
  34545. + inb(base + ICS_ARCIN_V5_INTROFFSET);
  34546. }
  34547. static const expansioncard_ops_t icside_ops_arcin_v5 = {
  34548. - icside_irqenable_arcin_v5,
  34549. - icside_irqdisable_arcin_v5,
  34550. - NULL,
  34551. - NULL,
  34552. - NULL,
  34553. - NULL
  34554. + .irqenable = icside_irqenable_arcin_v5,
  34555. + .irqdisable = icside_irqdisable_arcin_v5,
  34556. };
  34557. @@ -133,10 +118,21 @@
  34558. */
  34559. static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
  34560. {
  34561. - unsigned int ide_base_port = (unsigned int)ec->irq_data;
  34562. + struct icside_state *state = ec->irq_data;
  34563. + unsigned int base = state->irq_port;
  34564. +
  34565. + state->enabled = 1;
  34566. - outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
  34567. - outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
  34568. + switch (state->channel) {
  34569. + case 0:
  34570. + outb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
  34571. + inb(base + ICS_ARCIN_V6_INTROFFSET_2);
  34572. + break;
  34573. + case 1:
  34574. + outb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
  34575. + inb(base + ICS_ARCIN_V6_INTROFFSET_1);
  34576. + break;
  34577. + }
  34578. }
  34579. /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
  34580. @@ -144,10 +140,12 @@
  34581. */
  34582. static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
  34583. {
  34584. - unsigned int ide_base_port = (unsigned int)ec->irq_data;
  34585. + struct icside_state *state = ec->irq_data;
  34586. +
  34587. + state->enabled = 0;
  34588. - inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
  34589. - inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
  34590. + inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
  34591. + inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
  34592. }
  34593. /* Prototype: icside_irqprobe(struct expansion_card *ec)
  34594. @@ -155,70 +153,49 @@
  34595. */
  34596. static int icside_irqpending_arcin_v6(struct expansion_card *ec)
  34597. {
  34598. - unsigned int ide_base_port = (unsigned int)ec->irq_data;
  34599. + struct icside_state *state = ec->irq_data;
  34600. - return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
  34601. - inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
  34602. + return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
  34603. + inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
  34604. }
  34605. static const expansioncard_ops_t icside_ops_arcin_v6 = {
  34606. - icside_irqenable_arcin_v6,
  34607. - icside_irqdisable_arcin_v6,
  34608. - icside_irqpending_arcin_v6,
  34609. - NULL,
  34610. - NULL,
  34611. - NULL
  34612. + .irqenable = icside_irqenable_arcin_v6,
  34613. + .irqdisable = icside_irqdisable_arcin_v6,
  34614. + .irqpending = icside_irqpending_arcin_v6,
  34615. };
  34616. -/* Prototype: icside_identifyif (struct expansion_card *ec)
  34617. - * Purpose : identify IDE interface type
  34618. - * Notes : checks the description string
  34619. +/*
  34620. + * Handle routing of interrupts. This is called before
  34621. + * we write the command to the drive.
  34622. */
  34623. -static iftype_t __init icside_identifyif (struct expansion_card *ec)
  34624. +static void icside_maskproc(ide_drive_t *drive, int mask)
  34625. {
  34626. - unsigned int addr;
  34627. - iftype_t iftype;
  34628. - int id = 0;
  34629. -
  34630. - iftype = ics_if_unknown;
  34631. -
  34632. - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
  34633. -
  34634. - id = inb(addr) & 1;
  34635. - id |= (inb(addr + 1) & 1) << 1;
  34636. - id |= (inb(addr + 2) & 1) << 2;
  34637. - id |= (inb(addr + 3) & 1) << 3;
  34638. -
  34639. - switch (id) {
  34640. - case 0: /* A3IN */
  34641. - printk("icside: A3IN unsupported\n");
  34642. - break;
  34643. -
  34644. - case 1: /* A3USER */
  34645. - printk("icside: A3USER unsupported\n");
  34646. - break;
  34647. + ide_hwif_t *hwif = HWIF(drive);
  34648. + struct icside_state *state = hwif->hwif_data;
  34649. + unsigned long flags;
  34650. - case 3: /* ARCIN V6 */
  34651. - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no);
  34652. - iftype = ics_if_arcin_v6;
  34653. - break;
  34654. + local_irq_save(flags);
  34655. - case 15:/* ARCIN V5 (no id) */
  34656. - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no);
  34657. - iftype = ics_if_arcin_v5;
  34658. - break;
  34659. + state->channel = hwif->channel;
  34660. - default:/* we don't know - complain very loudly */
  34661. - printk("icside: ***********************************\n");
  34662. - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id);
  34663. - printk("icside: ***********************************\n");
  34664. - printk("icside: please report this to linux@arm.linux.org.uk\n");
  34665. - printk("icside: defaulting to ARCIN V5\n");
  34666. - iftype = ics_if_arcin_v5;
  34667. - break;
  34668. + if (state->enabled && !mask) {
  34669. + switch (hwif->channel) {
  34670. + case 0:
  34671. + outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
  34672. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
  34673. + break;
  34674. + case 1:
  34675. + outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
  34676. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
  34677. + break;
  34678. + }
  34679. + } else {
  34680. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
  34681. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
  34682. }
  34683. - return iftype;
  34684. + local_irq_restore(flags);
  34685. }
  34686. #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
  34687. @@ -234,125 +211,138 @@
  34688. #define NR_ENTRIES 256
  34689. #define TABLE_SIZE (NR_ENTRIES * 8)
  34690. -static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
  34691. +static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
  34692. {
  34693. - struct buffer_head *bh;
  34694. + ide_hwif_t *hwif = HWIF(drive);
  34695. struct scatterlist *sg = hwif->sg_table;
  34696. + struct buffer_head *bh;
  34697. int nents = 0;
  34698. - if (rq->cmd == READ)
  34699. - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
  34700. - else
  34701. - hwif->sg_dma_direction = PCI_DMA_TODEVICE;
  34702. - bh = rq->bh;
  34703. - do {
  34704. - unsigned char *virt_addr = bh->b_data;
  34705. - unsigned int size = bh->b_size;
  34706. -
  34707. - while ((bh = bh->b_reqnext) != NULL) {
  34708. - if ((virt_addr + size) != (unsigned char *)bh->b_data)
  34709. - break;
  34710. - size += bh->b_size;
  34711. - }
  34712. - memset(&sg[nents], 0, sizeof(*sg));
  34713. - sg[nents].address = virt_addr;
  34714. - sg[nents].length = size;
  34715. - nents++;
  34716. - } while (bh != NULL);
  34717. + BUG_ON(hwif->sg_dma_active);
  34718. - return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
  34719. -}
  34720. + if (rq->cmd == IDE_DRIVE_TASKFILE) {
  34721. + ide_task_t *args = rq->special;
  34722. -static int
  34723. -icside_build_dmatable(ide_drive_t *drive, int ddir)
  34724. -{
  34725. - return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir);
  34726. -}
  34727. + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
  34728. + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
  34729. + else
  34730. + hwif->sg_dma_direction = PCI_DMA_TODEVICE;
  34731. +
  34732. + memset(sg, 0, sizeof(*sg));
  34733. + sg->address = rq->buffer;
  34734. + sg->length = rq->nr_sectors * SECTOR_SIZE;
  34735. + nents = 1;
  34736. + } else {
  34737. + if (rq->cmd == READ)
  34738. + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
  34739. + else
  34740. + hwif->sg_dma_direction = PCI_DMA_TODEVICE;
  34741. +
  34742. + bh = rq->bh;
  34743. + do {
  34744. + unsigned long lastend;
  34745. +
  34746. + memset(sg, 0, sizeof(*sg));
  34747. + sg->page = bh->b_page;
  34748. + lastend = bh_phys(bh);
  34749. +
  34750. + do {
  34751. + lastend += bh->b_size;
  34752. + sg->length += bh->b_size;
  34753. +
  34754. + bh = bh->b_reqnext;
  34755. + if (bh == NULL)
  34756. + break;
  34757. + } while (lastend == bh_phys(bh));
  34758. +
  34759. + sg++;
  34760. + nents++;
  34761. + } while (bh != NULL);
  34762. + }
  34763. -/* Teardown mappings after DMA has completed. */
  34764. -static void icside_destroy_dmatable(ide_drive_t *drive)
  34765. -{
  34766. - struct scatterlist *sg = HWIF(drive)->sg_table;
  34767. - int nents = HWIF(drive)->sg_nents;
  34768. + nents = pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
  34769. - pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
  34770. + hwif->sg_nents = nents;
  34771. }
  34772. -static int
  34773. -icside_config_if(ide_drive_t *drive, int xfer_mode)
  34774. +
  34775. +/*
  34776. + * Configure the IOMD to give the appropriate timings for the transfer
  34777. + * mode being requested. We take the advice of the ATA standards, and
  34778. + * calculate the cycle time based on the transfer mode, and the EIDE
  34779. + * MW DMA specs that the drive provides in the IDENTIFY command.
  34780. + *
  34781. + * We have the following IOMD DMA modes to choose from:
  34782. + *
  34783. + * Type Active Recovery Cycle
  34784. + * A 250 (250) 312 (550) 562 (800)
  34785. + * B 187 250 437
  34786. + * C 125 (125) 125 (375) 250 (500)
  34787. + * D 62 125 187
  34788. + *
  34789. + * (figures in brackets are actual measured timings)
  34790. + *
  34791. + * However, we also need to take care of the read/write active and
  34792. + * recovery timings:
  34793. + *
  34794. + * Read Write
  34795. + * Mode Active -- Recovery -- Cycle IOMD type
  34796. + * MW0 215 50 215 480 A
  34797. + * MW1 80 50 50 150 C
  34798. + * MW2 70 25 25 120 C
  34799. + */
  34800. +static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode)
  34801. {
  34802. - int func = ide_dma_off;
  34803. + int on = 0, cycle_time = 0, use_dma_info = 0;
  34804. +
  34805. + /*
  34806. + * Limit the transfer speed to MW_DMA_2.
  34807. + */
  34808. + if (xfer_mode > XFER_MW_DMA_2)
  34809. + xfer_mode = XFER_MW_DMA_2;
  34810. switch (xfer_mode) {
  34811. case XFER_MW_DMA_2:
  34812. - /*
  34813. - * The cycle time is limited to 250ns by the r/w
  34814. - * pulse width (90ns), however we should still
  34815. - * have a maximum burst transfer rate of 8MB/s.
  34816. - */
  34817. - drive->drive_data = 250;
  34818. + cycle_time = 250;
  34819. + use_dma_info = 1;
  34820. break;
  34821. case XFER_MW_DMA_1:
  34822. - drive->drive_data = 250;
  34823. + cycle_time = 250;
  34824. + use_dma_info = 1;
  34825. break;
  34826. case XFER_MW_DMA_0:
  34827. - drive->drive_data = 480;
  34828. + cycle_time = 480;
  34829. break;
  34830. - default:
  34831. - drive->drive_data = 0;
  34832. + case XFER_SW_DMA_2:
  34833. + case XFER_SW_DMA_1:
  34834. + case XFER_SW_DMA_0:
  34835. + cycle_time = 480;
  34836. break;
  34837. }
  34838. - if (!drive->init_speed)
  34839. - drive->init_speed = (u8) xfer_mode;
  34840. + /*
  34841. + * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
  34842. + * take care to note the values in the ID...
  34843. + */
  34844. + if (use_dma_info && drive->id->eide_dma_time > cycle_time)
  34845. + cycle_time = drive->id->eide_dma_time;
  34846. +
  34847. + drive->drive_data = cycle_time;
  34848. - if (drive->drive_data &&
  34849. - ide_config_drive_speed(drive, (u8) xfer_mode) == 0)
  34850. - func = ide_dma_on;
  34851. + if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0)
  34852. + on = 1;
  34853. else
  34854. drive->drive_data = 480;
  34855. printk("%s: %s selected (peak %dMB/s)\n", drive->name,
  34856. ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
  34857. - drive->current_speed = (u8) xfer_mode;
  34858. -
  34859. - return func;
  34860. -}
  34861. -
  34862. -static int
  34863. -icside_set_speed(ide_drive_t *drive, u8 speed)
  34864. -{
  34865. - return icside_config_if(drive, speed);
  34866. -}
  34867. -
  34868. -/*
  34869. - * dma_intr() is the handler for disk read/write DMA interrupts
  34870. - */
  34871. -static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
  34872. -{
  34873. - u8 dma_stat = HWIF(drive)->ide_dma_end(drive);
  34874. - /* get drive status */
  34875. - u8 stat = HWIF(drive)->INB(IDE_STATUS_REG);
  34876. - int i;
  34877. + drive->current_speed = xfer_mode;
  34878. - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
  34879. - if (!dma_stat) {
  34880. - struct request *rq = HWGROUP(drive)->rq;
  34881. - rq = HWGROUP(drive)->rq;
  34882. - for (i = rq->nr_sectors; i > 0;) {
  34883. - i -= rq->current_nr_sectors;
  34884. - DRIVER(drive)->end_request(drive, 1);
  34885. - }
  34886. - return ide_stopped;
  34887. - }
  34888. - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
  34889. - drive->name, dma_stat);
  34890. - }
  34891. - return DRIVER(drive)->error(drive, "dma_intr", stat);
  34892. + return on;
  34893. }
  34894. /*
  34895. @@ -361,19 +351,19 @@
  34896. * This should be defined in one place only.
  34897. */
  34898. struct drive_list_entry {
  34899. - char * id_model;
  34900. - char * id_firmware;
  34901. + const char * id_model;
  34902. + const char * id_firmware;
  34903. };
  34904. -static struct drive_list_entry drive_whitelist [] = {
  34905. +static const struct drive_list_entry drive_whitelist [] = {
  34906. { "Micropolis 2112A", "ALL" },
  34907. { "CONNER CTMA 4000", "ALL" },
  34908. { "CONNER CTT8000-A", "ALL" },
  34909. { "ST34342A", "ALL" },
  34910. - { NULL, 0 }
  34911. + { NULL, NULL }
  34912. };
  34913. -static struct drive_list_entry drive_blacklist [] = {
  34914. +static const struct drive_list_entry drive_blacklist [] = {
  34915. { "WDC AC11000H", "ALL" },
  34916. { "WDC AC22100H", "ALL" },
  34917. { "WDC AC32500H", "ALL" },
  34918. @@ -407,10 +397,11 @@
  34919. { "PLEXTOR CD-R PX-W8432T", "ALL" },
  34920. { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
  34921. { "_NEC DV5800A", "ALL" },
  34922. - { NULL, 0 }
  34923. + { NULL, NULL }
  34924. };
  34925. -static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
  34926. +static int
  34927. +in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
  34928. {
  34929. for ( ; drive_table->id_model ; drive_table++)
  34930. if ((!strcmp(drive_table->id_model, id->model)) &&
  34931. @@ -420,41 +411,52 @@
  34932. return 0;
  34933. }
  34934. -/*
  34935. - * For both Blacklisted and Whitelisted drives.
  34936. - * This is setup to be called as an extern for future support
  34937. - * to other special driver code.
  34938. - */
  34939. -int check_drive_good_lists (ide_drive_t *drive)
  34940. +static int icside_dma_host_off(ide_drive_t *drive)
  34941. {
  34942. - struct hd_driveid *id = drive->id;
  34943. - return in_drive_list(id, drive_whitelist);
  34944. + return 0;
  34945. }
  34946. -int check_drive_bad_lists (ide_drive_t *drive)
  34947. +static int icside_dma_off_quietly(ide_drive_t *drive)
  34948. {
  34949. - struct hd_driveid *id = drive->id;
  34950. - int blacklist = in_drive_list(id, drive_blacklist);
  34951. - if (blacklist)
  34952. - printk("%s: Disabling DMA for %s\n", drive->name, id->model);
  34953. - return(blacklist);
  34954. + drive->using_dma = 0;
  34955. + return icside_dma_host_off(drive);
  34956. +}
  34957. +
  34958. +static int icside_dma_off(ide_drive_t *drive)
  34959. +{
  34960. + printk("%s: DMA disabled\n", drive->name);
  34961. + return icside_dma_off_quietly(drive);
  34962. +}
  34963. +
  34964. +static int icside_dma_host_on(ide_drive_t *drive)
  34965. +{
  34966. + return 0;
  34967. }
  34968. -int icside_dma_check(ide_drive_t *drive)
  34969. +static int icside_dma_on(ide_drive_t *drive)
  34970. +{
  34971. + drive->using_dma = 1;
  34972. + return icside_dma_host_on(drive);
  34973. +}
  34974. +
  34975. +static int icside_dma_check(ide_drive_t *drive)
  34976. {
  34977. struct hd_driveid *id = drive->id;
  34978. ide_hwif_t *hwif = HWIF(drive);
  34979. - int autodma = hwif->autodma;
  34980. int xfer_mode = XFER_PIO_2;
  34981. + int on;
  34982. - if (!id || !(id->capability & 1) || !autodma)
  34983. - return hwif->ide_dma_off_quietly(drive);
  34984. + if (!id || !(id->capability & 1) || !hwif->autodma)
  34985. + goto out;
  34986. /*
  34987. * Consult the list of known "bad" drives
  34988. */
  34989. - if (check_drive_bad_lists(drive))
  34990. - return hwif->ide_dma_off(drive);
  34991. + if (in_drive_list(id, drive_blacklist)) {
  34992. + printk("%s: Disabling DMA for %s (blacklisted)\n",
  34993. + drive->name, id->model);
  34994. + goto out;
  34995. + }
  34996. /*
  34997. * Enable DMA on any drive that has multiword DMA
  34998. @@ -473,192 +475,241 @@
  34999. /*
  35000. * Consult the list of known "good" drives
  35001. */
  35002. - if (check_drive_good_lists(drive)) {
  35003. + if (in_drive_list(id, drive_whitelist)) {
  35004. if (id->eide_dma_time > 150)
  35005. goto out;
  35006. xfer_mode = XFER_MW_DMA_1;
  35007. }
  35008. out:
  35009. - if (icside_config_if(drive, xfer_mode))
  35010. - return hwif->ide_dma_on(drive);
  35011. - return hwif->ide_dma_off(drive);
  35012. -}
  35013. + on = icside_set_speed(drive, xfer_mode);
  35014. -int icside_dma_verbose(ide_drive_t *drive)
  35015. -{
  35016. - printk(", DMA");
  35017. - return 1;
  35018. + if (on)
  35019. + return icside_dma_on(drive);
  35020. + else
  35021. + return icside_dma_off(drive);
  35022. }
  35023. -int icside_dma_test_irq(ide_drive_t *drive)
  35024. +static int icside_dma_end(ide_drive_t *drive)
  35025. {
  35026. ide_hwif_t *hwif = HWIF(drive);
  35027. - return inb((unsigned long)hwif->hw.priv) & 1;
  35028. -}
  35029. -int icside_dma_host_off(ide_drive_t *drive)
  35030. -{
  35031. - return 0;
  35032. -}
  35033. + drive->waiting_for_dma = 0;
  35034. -int icside_dma_off_quietly(ide_drive_t *drive)
  35035. -{
  35036. - drive->using_dma = 0;
  35037. - return icside_dma_host_off(drive);
  35038. -}
  35039. + disable_dma(hwif->hw.dma);
  35040. -int icside_dma_off(ide_drive_t *drive)
  35041. -{
  35042. - printk("%s: DMA disabled\n", drive->name);
  35043. - return icside_dma_off_quietly(drive);
  35044. -}
  35045. + /* Teardown mappings after DMA has completed. */
  35046. + pci_unmap_sg(NULL, hwif->sg_table, hwif->sg_nents,
  35047. + hwif->sg_dma_direction);
  35048. -int icside_dma_host_on(ide_drive_t *drive)
  35049. -{
  35050. - return 0;
  35051. -}
  35052. + hwif->sg_dma_active = 0;
  35053. -int icside_dma_on(ide_drive_t *drive)
  35054. -{
  35055. - drive->using_dma = 1;
  35056. - return icside_dma_host_on(drive);
  35057. + return get_dma_residue(hwif->hw.dma) != 0;
  35058. }
  35059. -int icside_dma_begin(ide_drive_t *drive)
  35060. +static int icside_dma_begin(ide_drive_t *drive)
  35061. {
  35062. ide_hwif_t *hwif = HWIF(drive);
  35063. + /* We can not enable DMA on both channels simultaneously. */
  35064. + BUG_ON(dma_channel_active(hwif->hw.dma));
  35065. enable_dma(hwif->hw.dma);
  35066. return 0;
  35067. }
  35068. -int icside_dma_end(ide_drive_t *drive)
  35069. +static int icside_dma_count(ide_drive_t *drive)
  35070. {
  35071. - ide_hwif_t *hwif = HWIF(drive);
  35072. -
  35073. - drive->waiting_for_dma = 0;
  35074. - disable_dma(hwif->hw.dma);
  35075. - icside_destroy_dmatable(drive);
  35076. - return get_dma_residue(hwif->hw.dma) != 0;
  35077. + return icside_dma_begin(drive);
  35078. }
  35079. -int icside_dma_count (ide_drive_t *drive)
  35080. +/*
  35081. + * dma_intr() is the handler for disk read/write DMA interrupts
  35082. + */
  35083. +static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
  35084. {
  35085. - return icside_dma_begin(drive);
  35086. + unsigned int stat;
  35087. + int dma_stat;
  35088. +
  35089. + dma_stat = icside_dma_end(drive);
  35090. + stat = HWIF(drive)->INB(IDE_STATUS_REG);
  35091. + if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
  35092. + if (!dma_stat) {
  35093. + struct request *rq = HWGROUP(drive)->rq;
  35094. + int i;
  35095. +
  35096. + for (i = rq->nr_sectors; i > 0; ) {
  35097. + i -= rq->current_nr_sectors;
  35098. + DRIVER(drive)->end_request(drive, 1);
  35099. + }
  35100. +
  35101. + return ide_stopped;
  35102. + }
  35103. + printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n",
  35104. + drive->name, dma_stat);
  35105. + }
  35106. +
  35107. + return DRIVER(drive)->error(drive, __FUNCTION__, stat);
  35108. }
  35109. -int icside_dma_read(ide_drive_t *drive)
  35110. +static int
  35111. +icside_dma_common(ide_drive_t *drive, struct request *rq,
  35112. + unsigned int dma_mode)
  35113. {
  35114. - ide_hwif_t *hwif = HWIF(drive);
  35115. -// ide_task_t *args = HWGROUP(drive)->rq->special;
  35116. - int count = 0;
  35117. - u8 lba48 = (drive->addressing == 1) ? 1 : 0;
  35118. - task_ioreg_t command = WIN_NOP;
  35119. + ide_hwif_t *hwif = HWIF(drive);
  35120. - count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE);
  35121. - if (!count)
  35122. - return 1;
  35123. - disable_dma(hwif->hw.dma);
  35124. + /*
  35125. + * We can not enable DMA on both channels.
  35126. + */
  35127. + BUG_ON(hwif->sg_dma_active);
  35128. + BUG_ON(dma_channel_active(hwif->hw.dma));
  35129. +
  35130. + ide_build_sglist(drive, rq);
  35131. - /* Route the DMA signals to
  35132. - * to the correct interface.
  35133. + /*
  35134. + * Ensure that we have the right interrupt routed.
  35135. */
  35136. - HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
  35137. + icside_maskproc(drive, 0);
  35138. - /* Select the correct timing
  35139. - * for this drive
  35140. + /*
  35141. + * Route the DMA signals to the correct interface.
  35142. + */
  35143. + outb(hwif->select_data, hwif->config_data);
  35144. +
  35145. + /*
  35146. + * Select the correct timing for this drive.
  35147. */
  35148. set_dma_speed(hwif->hw.dma, drive->drive_data);
  35149. - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
  35150. - set_dma_mode(hwif->hw.dma, DMA_MODE_READ);
  35151. + /*
  35152. + * Tell the DMA engine about the SG table and
  35153. + * data direction.
  35154. + */
  35155. + set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);
  35156. + set_dma_mode(hwif->hw.dma, dma_mode);
  35157. +
  35158. + return 0;
  35159. +}
  35160. +
  35161. +static int icside_dma_read(ide_drive_t *drive)
  35162. +{
  35163. + struct request *rq = HWGROUP(drive)->rq;
  35164. + task_ioreg_t cmd;
  35165. +
  35166. + if (icside_dma_common(drive, rq, DMA_MODE_READ))
  35167. + return 1;
  35168. drive->waiting_for_dma = 1;
  35169. +
  35170. if (drive->media != ide_disk)
  35171. return 0;
  35172. - if (HWGROUP(drive)->handler != NULL) /* paranoia check */
  35173. - BUG();
  35174. - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
  35175. /*
  35176. * FIX ME to use only ACB ide_task_t args Struct
  35177. */
  35178. #if 0
  35179. {
  35180. - ide_task_t *args = HWGROUP(drive)->rq->special;
  35181. - command = args->tfRegister[IDE_COMMAND_OFFSET];
  35182. + ide_task_t *args = rq->special;
  35183. + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
  35184. }
  35185. #else
  35186. - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
  35187. - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
  35188. - ide_task_t *args = HWGROUP(drive)->rq->special;
  35189. - command = args->tfRegister[IDE_COMMAND_OFFSET];
  35190. + if (rq->cmd == IDE_DRIVE_TASKFILE) {
  35191. + ide_task_t *args = rq->special;
  35192. + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
  35193. + } else if (drive->addressing == 1) {
  35194. + cmd = WIN_READDMA_EXT;
  35195. + } else {
  35196. + cmd = WIN_READDMA;
  35197. }
  35198. #endif
  35199. - /* issue cmd to drive */
  35200. - HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
  35201. - return icside_dma_count(drive);
  35202. + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
  35203. +
  35204. + return icside_dma_begin(drive);
  35205. }
  35206. -int icside_dma_write(ide_drive_t *drive)
  35207. +static int icside_dma_write(ide_drive_t *drive)
  35208. {
  35209. - ide_hwif_t *hwif = HWIF(drive);
  35210. -// ide_task_t *args = HWGROUP(drive)->rq->special;
  35211. - int count = 0;
  35212. - u8 lba48 = (drive->addressing == 1) ? 1 : 0;
  35213. - task_ioreg_t command = WIN_NOP;
  35214. + struct request *rq = HWGROUP(drive)->rq;
  35215. + task_ioreg_t cmd;
  35216. - count = icside_build_dmatable(drive, PCI_DMA_TODEVICE);
  35217. - if (!count)
  35218. + if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
  35219. return 1;
  35220. - disable_dma(hwif->hw.dma);
  35221. -
  35222. - /* Route the DMA signals to
  35223. - * to the correct interface.
  35224. - */
  35225. - HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
  35226. -
  35227. - /* Select the correct timing
  35228. - * for this drive
  35229. - */
  35230. - set_dma_speed(hwif->hw.dma, drive->drive_data);
  35231. -
  35232. - set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
  35233. - set_dma_mode(hwif->hw.dma, DMA_MODE_WRITE);
  35234. drive->waiting_for_dma = 1;
  35235. +
  35236. if (drive->media != ide_disk)
  35237. return 0;
  35238. - if (HWGROUP(drive)->handler != NULL)
  35239. - BUG();
  35240. - ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
  35241. /*
  35242. * FIX ME to use only ACB ide_task_t args Struct
  35243. */
  35244. #if 0
  35245. {
  35246. - ide_task_t *args = HWGROUP(drive)->rq->special;
  35247. - command = args->tfRegister[IDE_COMMAND_OFFSET];
  35248. + ide_task_t *args = rq->special;
  35249. + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
  35250. }
  35251. #else
  35252. - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
  35253. - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
  35254. - ide_task_t *args = HWGROUP(drive)->rq->special;
  35255. - command = args->tfRegister[IDE_COMMAND_OFFSET];
  35256. + if (rq->cmd == IDE_DRIVE_TASKFILE) {
  35257. + ide_task_t *args = rq->special;
  35258. + cmd = args->tfRegister[IDE_COMMAND_OFFSET];
  35259. + } else if (drive->addressing == 1) {
  35260. + cmd = WIN_WRITEDMA_EXT;
  35261. + } else {
  35262. + cmd = WIN_WRITEDMA;
  35263. }
  35264. #endif
  35265. - /* issue cmd to drive */
  35266. - HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
  35267. - return icside_dma_count(drive);
  35268. + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
  35269. +
  35270. + return icside_dma_begin(drive);
  35271. }
  35272. -static int
  35273. -icside_setup_dma(ide_hwif_t *hwif, int autodma)
  35274. +static int icside_dma_test_irq(ide_drive_t *drive)
  35275. +{
  35276. + ide_hwif_t *hwif = HWIF(drive);
  35277. + struct icside_state *state = hwif->hwif_data;
  35278. +
  35279. + return inb(state->irq_port +
  35280. + (hwif->channel ?
  35281. + ICS_ARCIN_V6_INTRSTAT_2 :
  35282. + ICS_ARCIN_V6_INTRSTAT_1)) & 1;
  35283. +}
  35284. +
  35285. +static int icside_dma_verbose(ide_drive_t *drive)
  35286. +{
  35287. + printk(", %s (peak %dMB/s)",
  35288. + ide_xfer_verbose(drive->current_speed),
  35289. + 2000 / drive->drive_data);
  35290. + return 1;
  35291. +}
  35292. +
  35293. +static int icside_dma_timeout(ide_drive_t *drive)
  35294. +{
  35295. + printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
  35296. +
  35297. + if (icside_dma_test_irq(drive))
  35298. + return 0;
  35299. +
  35300. + ide_dump_status(drive, "DMA timeout",
  35301. + HWIF(drive)->INB(IDE_STATUS_REG));
  35302. +
  35303. + return icside_dma_end(drive);
  35304. +}
  35305. +
  35306. +static int icside_dma_lostirq(ide_drive_t *drive)
  35307. +{
  35308. + printk(KERN_ERR "%s: IRQ lost\n", drive->name);
  35309. + return 1;
  35310. +}
  35311. +
  35312. +static int icside_dma_init(ide_hwif_t *hwif)
  35313. {
  35314. + int autodma = 0;
  35315. +
  35316. +#ifdef CONFIG_IDEDMA_ICS_AUTO
  35317. + autodma = 1;
  35318. +#endif
  35319. +
  35320. printk(" %s: SG-DMA", hwif->name);
  35321. hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
  35322. @@ -666,40 +717,53 @@
  35323. if (!hwif->sg_table)
  35324. goto failed;
  35325. - hwif->dmatable_cpu = NULL;
  35326. - hwif->dmatable_dma = 0;
  35327. - hwif->speedproc = icside_set_speed;
  35328. - hwif->autodma = autodma;
  35329. + hwif->atapi_dma = 1;
  35330. + hwif->mwdma_mask = 7; /* MW0..2 */
  35331. + hwif->swdma_mask = 7; /* SW0..2 */
  35332. +
  35333. + hwif->dmatable_cpu = NULL;
  35334. + hwif->dmatable_dma = 0;
  35335. + hwif->speedproc = icside_set_speed;
  35336. + hwif->autodma = autodma;
  35337. - hwif->ide_dma_check = icside_dma_check;
  35338. - hwif->ide_dma_host_off = icside_dma_host_off;
  35339. + hwif->ide_dma_check = icside_dma_check;
  35340. + hwif->ide_dma_host_off = icside_dma_host_off;
  35341. hwif->ide_dma_off_quietly = icside_dma_off_quietly;
  35342. - hwif->ide_dma_off = icside_dma_off;
  35343. - hwif->ide_dma_host_on = icside_dma_host_on;
  35344. - hwif->ide_dma_on = icside_dma_on;
  35345. - hwif->ide_dma_read = icside_dma_read;
  35346. - hwif->ide_dma_write = icside_dma_write;
  35347. - hwif->ide_dma_count = icside_dma_count;
  35348. - hwif->ide_dma_begin = icside_dma_begin;
  35349. - hwif->ide_dma_end = icside_dma_end;
  35350. - hwif->ide_dma_verbose = icside_dma_verbose;
  35351. - hwif->ide_dma_bad_drive = check_drive_bad_lists;
  35352. - hwif->ide_dma_good_drive = check_drive_good_lists;
  35353. - hwif->ide_dma_test_irq = icside_dma_test_irq;
  35354. + hwif->ide_dma_off = icside_dma_off;
  35355. + hwif->ide_dma_host_on = icside_dma_host_on;
  35356. + hwif->ide_dma_on = icside_dma_on;
  35357. + hwif->ide_dma_read = icside_dma_read;
  35358. + hwif->ide_dma_write = icside_dma_write;
  35359. + hwif->ide_dma_count = icside_dma_count;
  35360. + hwif->ide_dma_begin = icside_dma_begin;
  35361. + hwif->ide_dma_end = icside_dma_end;
  35362. + hwif->ide_dma_test_irq = icside_dma_test_irq;
  35363. + hwif->ide_dma_verbose = icside_dma_verbose;
  35364. + hwif->ide_dma_timeout = icside_dma_timeout;
  35365. + hwif->ide_dma_lostirq = icside_dma_lostirq;
  35366. - printk(" capable%s\n", autodma ?
  35367. - ", auto-enable" : "");
  35368. + printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
  35369. return 1;
  35370. failed:
  35371. - printk(" -- ERROR, unable to allocate DMA table\n");
  35372. + printk(" disabled, unable to allocate DMA table\n");
  35373. return 0;
  35374. }
  35375. +
  35376. +static void icside_dma_exit(ide_hwif_t *hwif)
  35377. +{
  35378. + if (hwif->sg_table) {
  35379. + kfree(hwif->sg_table);
  35380. + hwif->sg_table = NULL;
  35381. + }
  35382. +}
  35383. +#else
  35384. +#define icside_dma_init(hwif) (0)
  35385. +#define icside_dma_exit(hwif) do { } while (0)
  35386. #endif
  35387. -static ide_hwif_t *
  35388. -icside_find_hwif(unsigned long dataport)
  35389. +static ide_hwif_t *icside_find_hwif(unsigned long dataport)
  35390. {
  35391. ide_hwif_t *hwif;
  35392. int index;
  35393. @@ -716,13 +780,13 @@
  35394. goto found;
  35395. }
  35396. - return NULL;
  35397. + hwif = NULL;
  35398. found:
  35399. return hwif;
  35400. }
  35401. static ide_hwif_t *
  35402. -icside_setup(unsigned long base, struct cardinfo *info, int irq)
  35403. +icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec)
  35404. {
  35405. unsigned long port = base + info->dataoffset;
  35406. ide_hwif_t *hwif;
  35407. @@ -740,8 +804,8 @@
  35408. }
  35409. hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
  35410. hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
  35411. - hwif->hw.irq = irq;
  35412. - hwif->irq = irq;
  35413. + hwif->hw.irq = ec->irq;
  35414. + hwif->irq = ec->irq;
  35415. hwif->hw.dma = NO_DMA;
  35416. hwif->noprobe = 0;
  35417. hwif->chipset = ide_acorn;
  35418. @@ -750,33 +814,39 @@
  35419. return hwif;
  35420. }
  35421. -static int __init icside_register_v5(struct expansion_card *ec, int autodma)
  35422. +static int __init
  35423. +icside_register_v5(struct icside_state *state, struct expansion_card *ec)
  35424. {
  35425. unsigned long slot_port;
  35426. ide_hwif_t *hwif;
  35427. slot_port = ecard_address(ec, ECARD_MEMC, 0);
  35428. + state->irq_port = slot_port;
  35429. +
  35430. ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);
  35431. ec->irqmask = 1;
  35432. - ec->irq_data = (void *)slot_port;
  35433. - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5;
  35434. + ec->irq_data = state;
  35435. + ec->ops = &icside_ops_arcin_v5;
  35436. /*
  35437. * Be on the safe side - disable interrupts
  35438. */
  35439. inb(slot_port + ICS_ARCIN_V5_INTROFFSET);
  35440. - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq);
  35441. + hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec);
  35442. - return hwif ? 0 : -1;
  35443. + state->hwif[0] = hwif;
  35444. +
  35445. + return hwif ? 0 : -ENODEV;
  35446. }
  35447. -static int __init icside_register_v6(struct expansion_card *ec, int autodma)
  35448. +static int __init
  35449. +icside_register_v6(struct icside_state *state, struct expansion_card *ec)
  35450. {
  35451. unsigned long slot_port, port;
  35452. ide_hwif_t *hwif, *mate;
  35453. - int sel = 0;
  35454. + unsigned int sel = 0;
  35455. slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
  35456. port = ecard_address(ec, ECARD_EASI, ECARD_FAST);
  35457. @@ -788,88 +858,185 @@
  35458. outb(sel, slot_port);
  35459. - ec->irq_data = (void *)port;
  35460. - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
  35461. -
  35462. /*
  35463. * Be on the safe side - disable interrupts
  35464. */
  35465. inb(port + ICS_ARCIN_V6_INTROFFSET_1);
  35466. inb(port + ICS_ARCIN_V6_INTROFFSET_2);
  35467. - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq);
  35468. - mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq);
  35469. + /*
  35470. + * Find and register the interfaces.
  35471. + */
  35472. + hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);
  35473. + mate = icside_setup(port, &icside_cardinfo_v6_2, ec);
  35474. +
  35475. + if (!hwif || !mate)
  35476. + return -ENODEV;
  35477. -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
  35478. - if (ec->dma != NO_DMA) {
  35479. - if (request_dma(ec->dma, hwif->name))
  35480. - goto no_dma;
  35481. -
  35482. - if (hwif) {
  35483. - hwif->config_data = slot_port;
  35484. - hwif->select_data = sel;
  35485. - hwif->hw.dma = ec->dma;
  35486. - hwif->hw.priv = (void *)
  35487. - (port + ICS_ARCIN_V6_INTRSTAT_1);
  35488. - hwif->channel = 0;
  35489. - icside_setup_dma(hwif, autodma);
  35490. - hwif->drives[0].autodma = autodma;
  35491. - hwif->drives[1].autodma = autodma;
  35492. - }
  35493. - if (mate) {
  35494. - mate->config_data = slot_port;
  35495. - mate->select_data = sel | 1;
  35496. - mate->hw.dma = ec->dma;
  35497. - mate->hw.priv = (void *)
  35498. - (port + ICS_ARCIN_V6_INTRSTAT_2);
  35499. - mate->channel = 1;
  35500. - icside_setup_dma(mate, autodma);
  35501. - mate->drives[0].autodma = autodma;
  35502. - mate->drives[1].autodma = autodma;
  35503. - }
  35504. + state->irq_port = port;
  35505. + state->slot_port = slot_port;
  35506. + state->hwif[0] = hwif;
  35507. + state->hwif[1] = mate;
  35508. +
  35509. + ec->irq_data = state;
  35510. + ec->ops = &icside_ops_arcin_v6;
  35511. +
  35512. + hwif->maskproc = icside_maskproc;
  35513. + hwif->channel = 0;
  35514. + hwif->hwif_data = state;
  35515. + hwif->mate = mate;
  35516. + hwif->serialized = 1;
  35517. + hwif->config_data = slot_port;
  35518. + hwif->select_data = sel;
  35519. + hwif->hw.dma = ec->dma;
  35520. +
  35521. + mate->maskproc = icside_maskproc;
  35522. + mate->channel = 1;
  35523. + mate->hwif_data = state;
  35524. + mate->mate = hwif;
  35525. + mate->serialized = 1;
  35526. + mate->config_data = slot_port;
  35527. + mate->select_data = sel | 1;
  35528. + mate->hw.dma = ec->dma;
  35529. +
  35530. + if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
  35531. + icside_dma_init(hwif);
  35532. + icside_dma_init(mate);
  35533. }
  35534. -no_dma:
  35535. -#endif
  35536. - return hwif || mate ? 0 : -1;
  35537. + return 0;
  35538. }
  35539. -int __init icside_init(void)
  35540. +static int __init icside_probe(struct expansion_card *ec, const struct ecard_id *id)
  35541. {
  35542. - int autodma = 0;
  35543. + struct icside_state *state;
  35544. + int ret;
  35545. -#ifdef CONFIG_IDEDMA_ICS_AUTO
  35546. - autodma = 1;
  35547. -#endif
  35548. + state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);
  35549. + if (!state) {
  35550. + ret = -ENOMEM;
  35551. + goto out;
  35552. + }
  35553. - ecard_startfind ();
  35554. + memset(state, 0, sizeof(struct icside_state));
  35555. + state->type = ICS_TYPE_NOTYPE;
  35556. - do {
  35557. - struct expansion_card *ec;
  35558. - int result;
  35559. + {
  35560. + unsigned int addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
  35561. + unsigned int type;
  35562. - ec = ecard_find(0, icside_cids);
  35563. - if (ec == NULL)
  35564. - break;
  35565. + type = inb(addr) & 1;
  35566. + type |= (inb(addr + 1) & 1) << 1;
  35567. + type |= (inb(addr + 2) & 1) << 2;
  35568. + type |= (inb(addr + 3) & 1) << 3;
  35569. - ecard_claim(ec);
  35570. + state->type = type;
  35571. + }
  35572. - switch (icside_identifyif(ec)) {
  35573. - case ics_if_arcin_v5:
  35574. - result = icside_register_v5(ec, autodma);
  35575. - break;
  35576. + switch (state->type) {
  35577. + case ICS_TYPE_A3IN:
  35578. + printk(KERN_WARNING "icside: A3IN unsupported\n");
  35579. + ret = -ENODEV;
  35580. + break;
  35581. - case ics_if_arcin_v6:
  35582. - result = icside_register_v6(ec, autodma);
  35583. - break;
  35584. + case ICS_TYPE_A3USER:
  35585. + printk(KERN_WARNING "icside: A3USER unsupported\n");
  35586. + ret = -ENODEV;
  35587. + break;
  35588. - default:
  35589. - result = -1;
  35590. - break;
  35591. - }
  35592. + case ICS_TYPE_V5:
  35593. + ret = icside_register_v5(state, ec);
  35594. + break;
  35595. - if (result)
  35596. - ecard_release(ec);
  35597. - } while (1);
  35598. + case ICS_TYPE_V6:
  35599. + ret = icside_register_v6(state, ec);
  35600. + break;
  35601. - return 0;
  35602. + default:
  35603. + printk(KERN_WARNING "icside: unknown interface type\n");
  35604. + ret = -ENODEV;
  35605. + break;
  35606. + }
  35607. +
  35608. + if (ret == 0) {
  35609. + ecard_set_drvdata(ec, state);
  35610. + } else {
  35611. + kfree(state);
  35612. + }
  35613. + out:
  35614. + return ret;
  35615. +}
  35616. +
  35617. +static void __devexit icside_remove(struct expansion_card *ec)
  35618. +{
  35619. + struct icside_state *state = ecard_get_drvdata(ec);
  35620. +
  35621. + switch (state->type) {
  35622. + case ICS_TYPE_V5:
  35623. + /* FIXME: tell IDE to stop using the interface */
  35624. +
  35625. + /* Disable interrupts */
  35626. + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
  35627. + break;
  35628. +
  35629. + case ICS_TYPE_V6:
  35630. + /* FIXME: tell IDE to stop using the interface */
  35631. + icside_dma_exit(state->hwif[1]);
  35632. + icside_dma_exit(state->hwif[0]);
  35633. +
  35634. + if (ec->dma != NO_DMA)
  35635. + free_dma(ec->dma);
  35636. +
  35637. + /* Disable interrupts */
  35638. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
  35639. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
  35640. +
  35641. + /* Reset the ROM pointer/EASI selection */
  35642. + outb(0, state->slot_port);
  35643. + break;
  35644. + }
  35645. +
  35646. + ecard_set_drvdata(ec, NULL);
  35647. + ec->ops = NULL;
  35648. + ec->irq_data = NULL;
  35649. +
  35650. + kfree(state);
  35651. +}
  35652. +
  35653. +static void icside_shutdown(struct expansion_card *ec)
  35654. +{
  35655. + struct icside_state *state = ecard_get_drvdata(ec);
  35656. +
  35657. + switch (state->type) {
  35658. + case ICS_TYPE_V5:
  35659. + /* Disable interrupts */
  35660. + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
  35661. + break;
  35662. +
  35663. + case ICS_TYPE_V6:
  35664. + /* Disable interrupts */
  35665. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
  35666. + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
  35667. +
  35668. + /* Reset the ROM pointer/EASI selection */
  35669. + outb(0, state->slot_port);
  35670. + break;
  35671. + }
  35672. +}
  35673. +
  35674. +static const struct ecard_id icside_ids[] = {
  35675. + { MANU_ICS, PROD_ICS_IDE },
  35676. + { MANU_ICS2, PROD_ICS2_IDE },
  35677. + { 0xffff, 0xffff }
  35678. +};
  35679. +
  35680. +static struct ecard_driver icside_driver = {
  35681. + .probe = icside_probe,
  35682. + .remove = __devexit_p(icside_remove),
  35683. + .shutdown = icside_shutdown,
  35684. + .id_table = icside_ids,
  35685. +};
  35686. +
  35687. +int __init icside_init(void)
  35688. +{
  35689. + return ecard_register_driver(&icside_driver);
  35690. }
  35691. diff -urN linux-2.4.26/drivers/ide/arm/rstation-ide.c linux-2.4.26-vrs1/drivers/ide/arm/rstation-ide.c
  35692. --- linux-2.4.26/drivers/ide/arm/rstation-ide.c 1970-01-01 01:00:00.000000000 +0100
  35693. +++ linux-2.4.26-vrs1/drivers/ide/arm/rstation-ide.c 2004-01-14 21:32:25.000000000 +0000
  35694. @@ -0,0 +1,78 @@
  35695. +/*
  35696. + * linux/drivers/ide/rs-ide.c
  35697. + *
  35698. + * Copyright (c) 2002 Ben Dooks
  35699. + * Copyright (c) 2002 Simtec Electronics
  35700. + *
  35701. + * Simple RiscStation IDE support
  35702. +*/
  35703. +
  35704. +#include <linux/module.h>
  35705. +#include <linux/slab.h>
  35706. +#include <linux/blkdev.h>
  35707. +#include <linux/errno.h>
  35708. +#include <linux/ide.h>
  35709. +#include <linux/init.h>
  35710. +
  35711. +#include <asm/hardware/iomd.h>
  35712. +#include <asm/mach-types.h>
  35713. +#include <asm/io.h>
  35714. +
  35715. +#ifndef CONFIG_ARCH_RISCSTATION
  35716. +#error "compiling this code for non-riscstation hardware is dangerous!"
  35717. +#endif
  35718. +
  35719. +#define DRV_PREFIX "ide-rs"
  35720. +
  35721. +#define IRQ_PRI (40+3)
  35722. +#define IRQ_SEC (40+4)
  35723. +
  35724. +#define PORT_BASE ((0x2b800 - 0x10000) >> 2)
  35725. +#define SEC_OFF (0x400 >> 2)
  35726. +
  35727. +int __init rside_reg(unsigned long base, unsigned int irq);
  35728. +
  35729. +int __init rside_init(void)
  35730. +{
  35731. + int iotcr;
  35732. +
  35733. + if (!machine_is_riscstation()) {
  35734. + printk(DRV_PREFIX ": hardware is not a RiscStation!\n");
  35735. + return 0;
  35736. + }
  35737. +
  35738. + /* select correct area cycle time */
  35739. +
  35740. + iotcr = inb(IOMD_IOTCR);
  35741. + outb((iotcr & ~3) | 1, IOMD_IOTCR);
  35742. +
  35743. + /* register h/w */
  35744. +
  35745. + rside_reg(PORT_BASE, IRQ_PRI);
  35746. + rside_reg(PORT_BASE + SEC_OFF, IRQ_SEC);
  35747. +
  35748. + return 0;
  35749. +}
  35750. +
  35751. +
  35752. +int __init rside_reg(unsigned long port, unsigned int irq)
  35753. +{
  35754. + unsigned long addr, i;
  35755. + hw_regs_t hw;
  35756. +
  35757. + hw.irq = irq;
  35758. +
  35759. + addr = port;
  35760. +
  35761. + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
  35762. + hw.io_ports[i] = (ide_ioreg_t)addr;
  35763. + addr += 0x40 >> 2;
  35764. + }
  35765. +
  35766. + hw.io_ports[IDE_CONTROL_OFFSET] = port + ((0xb80 - 0x800) >> 2);
  35767. +
  35768. + printk(DRV_PREFIX ": registering channel at %08lx, %08lx, irq %d\n",
  35769. + port, hw.io_ports[IDE_CONTROL_OFFSET], irq);
  35770. +
  35771. + return ide_register_hw(&hw, NULL);
  35772. +}
  35773. diff -urN linux-2.4.26/drivers/ide/ide-probe.c linux-2.4.26-vrs1/drivers/ide/ide-probe.c
  35774. --- linux-2.4.26/drivers/ide/ide-probe.c 2004-04-19 11:44:16.000000000 +0100
  35775. +++ linux-2.4.26-vrs1/drivers/ide/ide-probe.c 2004-04-18 21:47:50.000000000 +0100
  35776. @@ -1297,11 +1297,11 @@
  35777. hwif->name, hwif->major);
  35778. return (hwif->present = 0);
  35779. }
  35780. -
  35781. +
  35782. if (init_irq(hwif)) {
  35783. int i = hwif->irq;
  35784. /*
  35785. - * It failed to initialise. Find the default IRQ for
  35786. + * It failed to initialise. Find the default IRQ for
  35787. * this port and try that.
  35788. */
  35789. if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
  35790. @@ -1319,7 +1319,7 @@
  35791. printk("%s: probed IRQ %d failed, using default.\n",
  35792. hwif->name, hwif->irq);
  35793. }
  35794. -
  35795. +
  35796. init_gendisk(hwif);
  35797. blk_dev[hwif->major].data = hwif;
  35798. blk_dev[hwif->major].queue = ide_get_queue;
  35799. diff -urN linux-2.4.26/drivers/ide/ide-proc.c linux-2.4.26-vrs1/drivers/ide/ide-proc.c
  35800. --- linux-2.4.26/drivers/ide/ide-proc.c 2004-04-19 11:44:16.000000000 +0100
  35801. +++ linux-2.4.26-vrs1/drivers/ide/ide-proc.c 2004-04-18 21:47:50.000000000 +0100
  35802. @@ -425,6 +425,7 @@
  35803. case ide_cy82c693: name = "cy82c693"; break;
  35804. case ide_4drives: name = "4drives"; break;
  35805. case ide_pmac: name = "pmac"; break;
  35806. + case ide_acorn: name = "acorn"; break;
  35807. default: name = "(unknown)"; break;
  35808. }
  35809. len = sprintf(page, "%s\n", name);
  35810. diff -urN linux-2.4.26/drivers/ide/ide.c linux-2.4.26-vrs1/drivers/ide/ide.c
  35811. --- linux-2.4.26/drivers/ide/ide.c 2004-02-27 20:03:25.000000000 +0000
  35812. +++ linux-2.4.26-vrs1/drivers/ide/ide.c 2004-02-23 13:36:30.000000000 +0000
  35813. @@ -218,23 +218,14 @@
  35814. static void init_hwif_data (unsigned int index)
  35815. {
  35816. unsigned int unit;
  35817. - hw_regs_t hw;
  35818. ide_hwif_t *hwif = &ide_hwifs[index];
  35819. /* bulk initialize hwif & drive info with zeros */
  35820. memset(hwif, 0, sizeof(ide_hwif_t));
  35821. - memset(&hw, 0, sizeof(hw_regs_t));
  35822. /* fill in any non-zero initial values */
  35823. hwif->index = index;
  35824. - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
  35825. - memcpy(&hwif->hw, &hw, sizeof(hw));
  35826. - memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
  35827. - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
  35828. -#ifdef CONFIG_BLK_DEV_HD
  35829. - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
  35830. - hwif->noprobe = 1; /* may be overridden by ide_setup() */
  35831. -#endif /* CONFIG_BLK_DEV_HD */
  35832. + hwif->noprobe = 1;
  35833. hwif->major = ide_hwif_to_major[index];
  35834. hwif->name[0] = 'i';
  35835. hwif->name[1] = 'd';
  35836. @@ -276,6 +267,28 @@
  35837. }
  35838. /*
  35839. + * Old compatability function - initialise ports using ide_default_io_base
  35840. + */
  35841. +static void ide_old_init_default_hwifs(void)
  35842. +{
  35843. + unsigned int index;
  35844. + ide_ioreg_t base;
  35845. + ide_hwif_t *hwif;
  35846. +
  35847. + for (index = 0; index < MAX_HWIFS; index++) {
  35848. + hwif = &ide_hwifs[index];
  35849. +
  35850. + base = ide_default_io_base(index);
  35851. +
  35852. + if (base) {
  35853. + ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->hw.irq);
  35854. + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
  35855. + hwif->noprobe = 0;
  35856. + }
  35857. + }
  35858. +}
  35859. +
  35860. +/*
  35861. * init_ide_data() sets reasonable default values into all fields
  35862. * of all instances of the hwifs and drives, but only on the first call.
  35863. * Subsequent calls have no effect (they don't wipe out anything).
  35864. @@ -307,6 +320,7 @@
  35865. init_hwif_data(index);
  35866. /* Add default hw interfaces */
  35867. + ide_old_init_default_hwifs();
  35868. ide_init_default_hwifs();
  35869. idebus_parameter = 0;
  35870. @@ -2530,6 +2544,12 @@
  35871. rapide_init();
  35872. }
  35873. #endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
  35874. +#ifdef CONFIG_BLK_DEV_IDE_RISCSTATION
  35875. + {
  35876. + extern void rside_init(void);
  35877. + rside_init();
  35878. + }
  35879. +#endif /* CONFIG_BLK_DEV_IDE_RISCSTATION */
  35880. #ifdef CONFIG_BLK_DEV_GAYLE
  35881. {
  35882. extern void gayle_init(void);
  35883. diff -urN linux-2.4.26/drivers/ide/pci/Makefile linux-2.4.26-vrs1/drivers/ide/pci/Makefile
  35884. --- linux-2.4.26/drivers/ide/pci/Makefile 2004-04-19 11:44:16.000000000 +0100
  35885. +++ linux-2.4.26-vrs1/drivers/ide/pci/Makefile 2004-04-18 21:47:50.000000000 +0100
  35886. @@ -16,7 +16,6 @@
  35887. obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
  35888. obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
  35889. #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o
  35890. -obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
  35891. obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
  35892. obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
  35893. obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
  35894. diff -urN linux-2.4.26/drivers/ide/pci/sl82c105.c linux-2.4.26-vrs1/drivers/ide/pci/sl82c105.c
  35895. --- linux-2.4.26/drivers/ide/pci/sl82c105.c 2003-06-13 15:51:33.000000000 +0100
  35896. +++ linux-2.4.26-vrs1/drivers/ide/pci/sl82c105.c 2004-01-14 21:32:25.000000000 +0000
  35897. @@ -37,7 +37,7 @@
  35898. #ifdef DEBUG
  35899. #define DBG(arg) printk arg
  35900. #else
  35901. -#define DBG(fmt,...)
  35902. +#define DBG(fmt...)
  35903. #endif
  35904. /*
  35905. * SL82C105 PCI config register 0x40 bits.
  35906. diff -urN linux-2.4.26/drivers/ide/pci/sl82c105.c.2419 linux-2.4.26-vrs1/drivers/ide/pci/sl82c105.c.2419
  35907. --- linux-2.4.26/drivers/ide/pci/sl82c105.c.2419 1970-01-01 01:00:00.000000000 +0100
  35908. +++ linux-2.4.26-vrs1/drivers/ide/pci/sl82c105.c.2419 2004-01-14 21:32:25.000000000 +0000
  35909. @@ -0,0 +1,380 @@
  35910. +/*
  35911. + * linux/drivers/ide/sl82c105.c
  35912. + *
  35913. + * SL82C105/Winbond 553 IDE driver
  35914. + *
  35915. + * Maintainer unknown.
  35916. + *
  35917. + * Changelog:
  35918. + *
  35919. + * 15/11/1998 RMK Drive tuning added from Rebel.com's kernel
  35920. + * sources
  35921. + * 30/03/2002 RMK Add fixes specified in W83C553F errata.
  35922. + * (with special thanks to Todd Inglett)
  35923. + */
  35924. +
  35925. +#include <linux/config.h>
  35926. +#include <linux/types.h>
  35927. +#include <linux/kernel.h>
  35928. +#include <linux/timer.h>
  35929. +#include <linux/mm.h>
  35930. +#include <linux/ioport.h>
  35931. +#include <linux/interrupt.h>
  35932. +#include <linux/blkdev.h>
  35933. +#include <linux/hdreg.h>
  35934. +#include <linux/pci.h>
  35935. +#include <linux/ide.h>
  35936. +
  35937. +#include <asm/io.h>
  35938. +#include <asm/dma.h>
  35939. +
  35940. +#include "ide_modes.h"
  35941. +
  35942. +extern char *ide_xfer_verbose (byte xfer_rate);
  35943. +
  35944. +/*
  35945. + * SL82C105 PCI config register 0x40 bits.
  35946. + */
  35947. +#define CTRL_IDE_IRQB (1 << 30)
  35948. +#define CTRL_IDE_IRQA (1 << 28)
  35949. +#define CTRL_LEGIRQ (1 << 11)
  35950. +#define CTRL_P1F16 (1 << 5)
  35951. +#define CTRL_P1EN (1 << 4)
  35952. +#define CTRL_P0F16 (1 << 1)
  35953. +#define CTRL_P0EN (1 << 0)
  35954. +
  35955. +/*
  35956. + * Convert a PIO mode and cycle time to the required on/off
  35957. + * times for the interface. This has protection against run-away
  35958. + * timings.
  35959. + */
  35960. +static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
  35961. +{
  35962. + unsigned int cmd_on;
  35963. + unsigned int cmd_off;
  35964. +
  35965. + cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
  35966. + cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
  35967. +
  35968. + if (cmd_on > 32)
  35969. + cmd_on = 32;
  35970. + if (cmd_on == 0)
  35971. + cmd_on = 1;
  35972. +
  35973. + if (cmd_off > 32)
  35974. + cmd_off = 32;
  35975. + if (cmd_off == 0)
  35976. + cmd_off = 1;
  35977. +
  35978. + return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00);
  35979. +}
  35980. +
  35981. +/*
  35982. + * Configure the drive and chipset for PIO
  35983. + */
  35984. +static void config_for_pio(ide_drive_t *drive, int pio, int report)
  35985. +{
  35986. + ide_hwif_t *hwif = HWIF(drive);
  35987. + struct pci_dev *dev = hwif->pci_dev;
  35988. + ide_pio_data_t p;
  35989. + unsigned short drv_ctrl = 0x909;
  35990. + unsigned int xfer_mode, reg;
  35991. +
  35992. + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
  35993. +
  35994. + pio = ide_get_best_pio_mode(drive, pio, 5, &p);
  35995. +
  35996. + switch (pio) {
  35997. + default:
  35998. + case 0: xfer_mode = XFER_PIO_0; break;
  35999. + case 1: xfer_mode = XFER_PIO_1; break;
  36000. + case 2: xfer_mode = XFER_PIO_2; break;
  36001. + case 3: xfer_mode = XFER_PIO_3; break;
  36002. + case 4: xfer_mode = XFER_PIO_4; break;
  36003. + }
  36004. +
  36005. + if (ide_config_drive_speed(drive, xfer_mode) == 0)
  36006. + drv_ctrl = get_timing_sl82c105(&p);
  36007. +
  36008. + if (drive->using_dma == 0) {
  36009. + /*
  36010. + * If we are actually using MW DMA, then we can not
  36011. + * reprogram the interface drive control register.
  36012. + */
  36013. + pci_write_config_word(dev, reg, drv_ctrl);
  36014. + pci_read_config_word(dev, reg, &drv_ctrl);
  36015. +
  36016. + if (report) {
  36017. + printk("%s: selected %s (%dns) (%04X)\n", drive->name,
  36018. + ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl);
  36019. + }
  36020. + }
  36021. +}
  36022. +
  36023. +/*
  36024. + * Configure the drive and the chipset for DMA
  36025. + */
  36026. +static int config_for_dma(ide_drive_t *drive)
  36027. +{
  36028. + ide_hwif_t *hwif = HWIF(drive);
  36029. + struct pci_dev *dev = hwif->pci_dev;
  36030. + unsigned short drv_ctrl = 0x909;
  36031. + unsigned int reg;
  36032. +
  36033. + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
  36034. +
  36035. + if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0)
  36036. + drv_ctrl = 0x0240;
  36037. +
  36038. + pci_write_config_word(dev, reg, drv_ctrl);
  36039. +
  36040. + return 0;
  36041. +}
  36042. +
  36043. +
  36044. +/*
  36045. + * Check to see if the drive and
  36046. + * chipset is capable of DMA mode
  36047. + */
  36048. +static int sl82c105_check_drive(ide_drive_t *drive)
  36049. +{
  36050. + ide_dma_action_t dma_func = ide_dma_off_quietly;
  36051. +
  36052. + do {
  36053. + struct hd_driveid *id = drive->id;
  36054. + ide_hwif_t *hwif = HWIF(drive);
  36055. +
  36056. + if (!hwif->autodma)
  36057. + break;
  36058. +
  36059. + if (!id || !(id->capability & 1))
  36060. + break;
  36061. +
  36062. + /* Consult the list of known "bad" drives */
  36063. + if (ide_dmaproc(ide_dma_bad_drive, drive)) {
  36064. + dma_func = ide_dma_off;
  36065. + break;
  36066. + }
  36067. +
  36068. + if (id->field_valid & 2) {
  36069. + if (id->dma_mword & 7 || id->dma_1word & 7)
  36070. + dma_func = ide_dma_on;
  36071. + break;
  36072. + }
  36073. +
  36074. + if (ide_dmaproc(ide_dma_good_drive, drive)) {
  36075. + dma_func = ide_dma_on;
  36076. + break;
  36077. + }
  36078. + } while (0);
  36079. +
  36080. + return HWIF(drive)->dmaproc(dma_func, drive);
  36081. +}
  36082. +
  36083. +/*
  36084. + * The SL82C105 holds off all IDE interrupts while in DMA mode until
  36085. + * all DMA activity is completed. Sometimes this causes problems (eg,
  36086. + * when the drive wants to report an error condition).
  36087. + *
  36088. + * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller
  36089. + * state machine. We need to kick this to work around various bugs.
  36090. + */
  36091. +static inline void sl82c105_reset_host(struct pci_dev *dev)
  36092. +{
  36093. + u16 val;
  36094. +
  36095. + pci_read_config_word(dev, 0x7e, &val);
  36096. + pci_write_config_word(dev, 0x7e, val | (1 << 2));
  36097. + pci_write_config_word(dev, 0x7e, val & ~(1 << 2));
  36098. +}
  36099. +
  36100. +/*
  36101. + * If we get an IRQ timeout, it might be that the DMA state machine
  36102. + * got confused. Fix from Todd Inglett. Details from Winbond.
  36103. + *
  36104. + * This function is called when the IDE timer expires, the drive
  36105. + * indicates that it is READY, and we were waiting for DMA to complete.
  36106. + */
  36107. +static int sl82c105_lostirq(ide_drive_t *drive)
  36108. +{
  36109. + ide_hwif_t *hwif = HWIF(drive);
  36110. + struct pci_dev *dev = hwif->pci_dev;
  36111. + u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
  36112. + unsigned long dma_base = hwif->dma_base;
  36113. +
  36114. + printk("sl82c105: lost IRQ: resetting host\n");
  36115. +
  36116. + /*
  36117. + * Check the raw interrupt from the drive.
  36118. + */
  36119. + pci_read_config_dword(dev, 0x40, &val);
  36120. + if (val & mask)
  36121. + printk("sl82c105: drive was requesting IRQ, but host lost it\n");
  36122. +
  36123. + /*
  36124. + * Was DMA enabled? If so, disable it - we're resetting the
  36125. + * host. The IDE layer will be handling the drive for us.
  36126. + */
  36127. + val = inb(dma_base);
  36128. + if (val & 1) {
  36129. + outb(val & ~1, dma_base);
  36130. + printk("sl82c105: DMA was enabled\n");
  36131. + }
  36132. +
  36133. + sl82c105_reset_host(dev);
  36134. +
  36135. + /* ide_dmaproc would return 1, so we do as well */
  36136. + return 1;
  36137. +}
  36138. +
  36139. +/*
  36140. + * ATAPI devices can cause the SL82C105 DMA state machine to go gaga.
  36141. + * Winbond recommend that the DMA state machine is reset prior to
  36142. + * setting the bus master DMA enable bit.
  36143. + *
  36144. + * The generic IDE core will have disabled the BMEN bit before this
  36145. + * function is called.
  36146. + */
  36147. +static void sl82c105_before_bm_enable(ide_drive_t *drive)
  36148. +{
  36149. + ide_hwif_t *hwif = HWIF(drive);
  36150. + struct pci_dev *dev = hwif->pci_dev;
  36151. +
  36152. + sl82c105_reset_host(dev);
  36153. +}
  36154. +
  36155. +/*
  36156. + * Our very own dmaproc. We need to intercept various calls
  36157. + * to fix up the SL82C105 specific behaviour.
  36158. + */
  36159. +static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
  36160. +{
  36161. + switch (func) {
  36162. + case ide_dma_check:
  36163. + return sl82c105_check_drive(drive);
  36164. +
  36165. + case ide_dma_on:
  36166. + if (config_for_dma(drive))
  36167. + func = ide_dma_off;
  36168. + /* fall through */
  36169. +
  36170. + case ide_dma_off_quietly:
  36171. + case ide_dma_off:
  36172. + config_for_pio(drive, 4, 0);
  36173. + break;
  36174. +
  36175. + case ide_dma_read:
  36176. + case ide_dma_write:
  36177. + case ide_dma_begin:
  36178. + case ide_dma_timeout:
  36179. + sl82c105_before_bm_enable(drive);
  36180. + break;
  36181. +
  36182. + case ide_dma_lostirq:
  36183. + return sl82c105_lostirq(drive);
  36184. +
  36185. + default:
  36186. + break;
  36187. + }
  36188. + return ide_dmaproc(func, drive);
  36189. +}
  36190. +
  36191. +/*
  36192. + * We only deal with PIO mode here - DMA mode 'using_dma' is not
  36193. + * initialised at the point that this function is called.
  36194. + */
  36195. +static void tune_sl82c105(ide_drive_t *drive, byte pio)
  36196. +{
  36197. + config_for_pio(drive, pio, 1);
  36198. +
  36199. + /*
  36200. + * We support 32-bit I/O on this interface, and it
  36201. + * doesn't have problems with interrupts.
  36202. + */
  36203. + drive->io_32bit = 1;
  36204. + drive->unmask = 1;
  36205. +}
  36206. +
  36207. +/*
  36208. + * Return the revision of the Winbond bridge
  36209. + * which this function is part of.
  36210. + */
  36211. +static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
  36212. +{
  36213. + struct pci_dev *bridge;
  36214. + unsigned char rev;
  36215. +
  36216. + /*
  36217. + * The bridge should be part of the same device, but function 0.
  36218. + */
  36219. + bridge = pci_find_slot(dev->bus->number,
  36220. + PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
  36221. + if (!bridge)
  36222. + return -1;
  36223. +
  36224. + /*
  36225. + * Make sure it is a Winbond 553 and is an ISA bridge.
  36226. + */
  36227. + if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
  36228. + bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
  36229. + bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA)
  36230. + return -1;
  36231. +
  36232. + /*
  36233. + * We need to find function 0's revision, not function 1
  36234. + */
  36235. + pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
  36236. +
  36237. + return rev;
  36238. +}
  36239. +
  36240. +/*
  36241. + * Enable the PCI device
  36242. + */
  36243. +unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg)
  36244. +{
  36245. + u32 val;
  36246. +
  36247. + pci_read_config_dword(dev, 0x40, &val);
  36248. + val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1EN | CTRL_P1F16;
  36249. + pci_write_config_dword(dev, 0x40, val);
  36250. +
  36251. + return dev->irq;
  36252. +}
  36253. +
  36254. +void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
  36255. +{
  36256. + unsigned int bridge_rev;
  36257. + byte dma_state;
  36258. +
  36259. + dma_state = inb(dma_base + 2);
  36260. + bridge_rev = sl82c105_bridge_revision(hwif->pci_dev);
  36261. + if (bridge_rev <= 5) {
  36262. + hwif->autodma = 0;
  36263. + hwif->drives[0].autotune = 1;
  36264. + hwif->drives[1].autotune = 1;
  36265. + printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
  36266. + hwif->name, bridge_rev);
  36267. + dma_state &= ~0x60;
  36268. + } else {
  36269. + dma_state |= 0x60;
  36270. + hwif->autodma = 1;
  36271. + }
  36272. + outb(dma_state, dma_base + 2);
  36273. +
  36274. + ide_setup_dma(hwif, dma_base, 8);
  36275. +
  36276. + if (bridge_rev <= 5)
  36277. + hwif->dmaproc = NULL;
  36278. + else
  36279. + hwif->dmaproc = sl82c105_dmaproc;
  36280. +}
  36281. +
  36282. +/*
  36283. + * Initialise the chip
  36284. + */
  36285. +void __init ide_init_sl82c105(ide_hwif_t *hwif)
  36286. +{
  36287. + hwif->tuneproc = tune_sl82c105;
  36288. +}
  36289. +
  36290. diff -urN linux-2.4.26/drivers/input/Config.in linux-2.4.26-vrs1/drivers/input/Config.in
  36291. --- linux-2.4.26/drivers/input/Config.in 2004-02-27 20:03:25.000000000 +0000
  36292. +++ linux-2.4.26-vrs1/drivers/input/Config.in 2004-02-23 22:53:55.000000000 +0000
  36293. @@ -15,5 +15,6 @@
  36294. dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
  36295. dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT
  36296. dep_tristate ' User level driver support' CONFIG_INPUT_UINPUT $CONFIG_INPUT
  36297. +dep_tristate ' MX1 touchscreen support' CONFIG_INPUT_MX1TS $CONFIG_INPUT_MOUSEDEV $CONFIG_ARCH_MX1ADS
  36298. endmenu
  36299. diff -urN linux-2.4.26/drivers/input/Makefile linux-2.4.26-vrs1/drivers/input/Makefile
  36300. --- linux-2.4.26/drivers/input/Makefile 2004-02-27 20:03:25.000000000 +0000
  36301. +++ linux-2.4.26-vrs1/drivers/input/Makefile 2004-02-23 22:53:03.000000000 +0000
  36302. @@ -24,6 +24,7 @@
  36303. obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
  36304. obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
  36305. obj-$(CONFIG_INPUT_EVDEV) += evdev.o
  36306. +obj-$(CONFIG_INPUT_MX1TS) += mx1ts.o
  36307. obj-$(CONFIG_INPUT_UINPUT) += uinput.o
  36308. # The global Rules.make.
  36309. diff -urN linux-2.4.26/drivers/input/mx1ts.c linux-2.4.26-vrs1/drivers/input/mx1ts.c
  36310. --- linux-2.4.26/drivers/input/mx1ts.c 1970-01-01 01:00:00.000000000 +0100
  36311. +++ linux-2.4.26-vrs1/drivers/input/mx1ts.c 2004-01-14 21:32:25.000000000 +0000
  36312. @@ -0,0 +1,508 @@
  36313. +/*
  36314. + * linux/drivers/misc/mx1ts.c
  36315. + *
  36316. + * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
  36317. + *
  36318. + * Cloned from ucb1x00_ts.c
  36319. + *
  36320. + * This program is free software; you can redistribute it and/or modify
  36321. + * it under the terms of the GNU General Public License version 2 as
  36322. + * published by the Free Software Foundation.
  36323. + *
  36324. + */
  36325. +#include <linux/config.h>
  36326. +#include <linux/module.h>
  36327. +#include <linux/init.h>
  36328. +#include <linux/smp.h>
  36329. +#include <linux/smp_lock.h>
  36330. +#include <linux/sched.h>
  36331. +#include <linux/completion.h>
  36332. +#include <linux/delay.h>
  36333. +#include <linux/string.h>
  36334. +#include <linux/pm.h>
  36335. +
  36336. +#include <asm/dma.h>
  36337. +
  36338. +#include <linux/input.h>
  36339. +
  36340. +#include "mx1ts.h"
  36341. +
  36342. +#define DEV_IRQ_ID "mx1-ts"
  36343. +
  36344. +struct mx1_ts {
  36345. + struct input_dev idev;
  36346. +#ifdef CONFIG_PM
  36347. + struct pm_dev *pmdev;
  36348. +#endif
  36349. +
  36350. + wait_queue_head_t irq_wait;
  36351. + struct completion init_exit;
  36352. + int use_count;
  36353. + u16 x_res;
  36354. + u16 y_res;
  36355. +
  36356. + int restart:1;
  36357. +};
  36358. +
  36359. +static struct mx1_ts mx1ts;
  36360. +static u8 mx1_performing_auto_calibration = 0;
  36361. +static u16 mx1_cal_auto_zero = 0;
  36362. +static u16 mx1_cal_range_x = 0;
  36363. +static u16 mx1_cal_range_y = 0;
  36364. +
  36365. +static int mx1_ts_startup(struct mx1_ts *ts);
  36366. +static void mx1_ts_shutdown(struct mx1_ts *ts);
  36367. +
  36368. +static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs);
  36369. +static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs);
  36370. +static void mx1_ts_compare_int(int irq, void *dev_id, struct pt_regs *regs);
  36371. +
  36372. +static void mx1_ts_enable_pen_touch_interrupt(void);
  36373. +static void mx1_ts_disable_pen_touch_interrupt(void);
  36374. +static void mx1_ts_enable_pen_up_interrupt(void);
  36375. +static void mx1_ts_disable_pen_up_interrupt(void);
  36376. +static void mx1_ts_enable_auto_sample(void);
  36377. +static void mx1_ts_disable_auto_sample(void);
  36378. +static void mx1_ts_start_auto_calibration(void);
  36379. +
  36380. +static inline void mx1_reg_write(unsigned int reg, unsigned int val)
  36381. +{
  36382. + *((volatile unsigned int *)reg) = val;
  36383. +}
  36384. +
  36385. +static inline unsigned int mx1_reg_read(unsigned int reg)
  36386. +{
  36387. + return *((volatile unsigned int *)reg);
  36388. +}
  36389. +
  36390. +static inline void mx1_reg_clear_bit(unsigned int reg, unsigned int bit)
  36391. +{
  36392. + *((volatile unsigned int *)reg) &= ~bit;
  36393. +}
  36394. +
  36395. +static inline void mx1_reg_set_bit(unsigned int reg, unsigned int bit)
  36396. +{
  36397. + *((volatile unsigned int *)reg) |= bit;
  36398. +}
  36399. +
  36400. +static inline void mx1_ts_evt_add(struct mx1_ts *ts, u16 pressure, u16 x, u16 y)
  36401. +{
  36402. + input_report_abs(&ts->idev, ABS_X, (int)x - 32768);
  36403. + input_report_abs(&ts->idev, ABS_Y, (int)y - 32768);
  36404. + input_report_abs(&ts->idev, ABS_PRESSURE, (int)pressure);
  36405. +}
  36406. +
  36407. +static inline void mx1_ts_flush_fifo(void)
  36408. +{
  36409. + int i;
  36410. + for (i = 0; i < 12; i++)
  36411. + if (mx1_reg_read(ASP_ISTATR) & (ASP_PFF | ASP_PDR))
  36412. + mx1_reg_read(ASP_PADFIFO);
  36413. +}
  36414. +
  36415. +static int mx1_ts_open(struct input_dev *idev)
  36416. +{
  36417. + struct mx1_ts *ts = (struct mx1_ts *)idev;
  36418. +
  36419. + mx1_performing_auto_calibration = 0;
  36420. + return mx1_ts_startup(ts);
  36421. +}
  36422. +
  36423. +static void mx1_ts_close(struct input_dev *idev)
  36424. +{
  36425. + struct mx1_ts *ts = (struct mx1_ts *)idev;
  36426. +
  36427. + mx1_ts_shutdown(ts);
  36428. +}
  36429. +
  36430. +static inline int mx1_ts_enable_irqs(void)
  36431. +{
  36432. + int result;
  36433. +
  36434. + result = request_irq(ASP_PENDATA_IRQ,
  36435. + mx1_ts_pendata_int,
  36436. + SA_INTERRUPT,
  36437. + DEV_IRQ_ID,
  36438. + DEV_IRQ_ID);
  36439. + if (result) {
  36440. + printk("Couldn't request pen data IRQ.\n");
  36441. + return result;
  36442. + }
  36443. +
  36444. + result = request_irq(ASP_TOUCH_IRQ,
  36445. + mx1_ts_touch_int,
  36446. + SA_INTERRUPT,
  36447. + DEV_IRQ_ID,
  36448. + DEV_IRQ_ID);
  36449. + if (result) {
  36450. + printk("Couldn't request pen touch IRQ.\n");
  36451. + free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
  36452. + return result;
  36453. + }
  36454. +
  36455. + return result;
  36456. +}
  36457. +
  36458. +static inline int mx1_ts_disable_irqs(void)
  36459. +{
  36460. + free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
  36461. + free_irq(ASP_TOUCH_IRQ, DEV_IRQ_ID);
  36462. +
  36463. + return 0;
  36464. +}
  36465. +
  36466. +static inline int mx1_ts_register(struct mx1_ts *ts)
  36467. +{
  36468. + ts->idev.name = "Touchscreen panel";
  36469. + ts->idev.open = mx1_ts_open;
  36470. + ts->idev.close = mx1_ts_close;
  36471. +
  36472. + __set_bit(EV_ABS, ts->idev.evbit);
  36473. + __set_bit(ABS_X, ts->idev.absbit);
  36474. + __set_bit(ABS_Y, ts->idev.absbit);
  36475. + __set_bit(ABS_PRESSURE, ts->idev.absbit);
  36476. +
  36477. + ts->idev.absmin[ABS_X] = 0;
  36478. + ts->idev.absmax[ABS_X] = (u32)0x0000FFFF;
  36479. + ts->idev.absfuzz[ABS_X] = 50;
  36480. + ts->idev.absflat[ABS_X] = 0;
  36481. +
  36482. + ts->idev.absmin[ABS_Y] = 0;
  36483. + ts->idev.absmax[ABS_Y] = (u32)0x0000FFFF;
  36484. + ts->idev.absfuzz[ABS_Y] = 50;
  36485. + ts->idev.absflat[ABS_Y] = 0;
  36486. +
  36487. + input_register_device(&ts->idev);
  36488. +
  36489. + return 0;
  36490. +}
  36491. +
  36492. +static inline void mx1_ts_deregister(struct mx1_ts *ts)
  36493. +{
  36494. + input_unregister_device(&ts->idev);
  36495. +}
  36496. +
  36497. +/*
  36498. + * Handle the touch interrupt, generated when the pen is pressed/
  36499. + * released.
  36500. + */
  36501. +static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs)
  36502. +{
  36503. + /* Clear the interrupt. */
  36504. + mx1_reg_set_bit(ASP_ISTATR, ASP_PEN);
  36505. +
  36506. + mx1_ts_disable_pen_touch_interrupt();
  36507. + mx1_ts_start_auto_calibration();
  36508. + mx1_ts_enable_pen_up_interrupt();
  36509. +}
  36510. +
  36511. +/*
  36512. + * Handle the pen data ready interrupt, generated when pen data is
  36513. + * in the FIFO.
  36514. + */
  36515. +static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs)
  36516. +{
  36517. + static unsigned int auto_zero, pen_x, pen_y, pen_u;
  36518. +
  36519. + if (mx1_reg_read(ASP_ISTATR) & 0x400) {
  36520. + mx1_reg_set_bit(ASP_ISTATR, 0x400);
  36521. +
  36522. + mx1_ts_disable_auto_sample();
  36523. + mx1_ts_disable_pen_up_interrupt();
  36524. + mx1_ts_enable_pen_touch_interrupt();
  36525. +
  36526. + mx1_ts_evt_add(&mx1ts, 0, pen_x, pen_y);
  36527. +
  36528. + mx1_ts_flush_fifo();
  36529. +
  36530. + return;
  36531. + }
  36532. +
  36533. + if (mx1_performing_auto_calibration) {
  36534. + unsigned int value;
  36535. +
  36536. + mx1_cal_auto_zero = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
  36537. + mx1_cal_range_x = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
  36538. + mx1_cal_range_y = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
  36539. +
  36540. + if ((mx1_cal_auto_zero >= mx1_cal_range_x) ||
  36541. + (mx1_cal_auto_zero >= mx1_cal_range_y)) {
  36542. + /* Invalid data. */
  36543. + mx1_ts_start_auto_calibration();
  36544. + return;
  36545. + }
  36546. +
  36547. + mx1_cal_range_x -= mx1_cal_auto_zero;
  36548. + mx1_cal_range_y -= mx1_cal_auto_zero;
  36549. +
  36550. + value = mx1_reg_read(ASP_ACNTLCR);
  36551. + value &= ~0x04000000; /* XXX Undocumented. */
  36552. + mx1_reg_write(ASP_ACNTLCR, value);
  36553. +
  36554. + mx1_performing_auto_calibration = 0;
  36555. +
  36556. + mx1_ts_enable_auto_sample();
  36557. + } else {
  36558. + /* There could be more than one sample in the FIFO, but we're
  36559. + * only going to read one per call. The interrupt will be
  36560. + * generated as long as there is data in the FIFO. */
  36561. +
  36562. + if ((mx1_reg_read(ASP_ISTATR) & ASP_PDR) != ASP_PDR) {
  36563. + return;
  36564. + }
  36565. +
  36566. + auto_zero = mx1_reg_read(ASP_PADFIFO);
  36567. + if (auto_zero > (mx1_cal_auto_zero + 0x200)) {
  36568. + return;
  36569. + }
  36570. +
  36571. + pen_x = mx1_reg_read(ASP_PADFIFO);
  36572. + pen_y = mx1_reg_read(ASP_PADFIFO);
  36573. + pen_u = mx1_reg_read(ASP_PADFIFO);
  36574. +
  36575. + pen_x = (u32)(((pen_x - mx1_cal_auto_zero) << 16) /
  36576. + mx1_cal_range_x);
  36577. + pen_y = (u32)(((pen_y - mx1_cal_auto_zero) << 16) /
  36578. + mx1_cal_range_y);
  36579. +
  36580. + mx1_ts_evt_add(&mx1ts, pen_u, pen_x, pen_y);
  36581. + }
  36582. +}
  36583. +
  36584. +static void mx1_ts_reset_asp(void)
  36585. +{
  36586. + unsigned int value;
  36587. +
  36588. + mx1_ts_flush_fifo();
  36589. +
  36590. + /* Soft reset the ASP module */
  36591. + mx1_reg_write(ASP_ACNTLCR, ASP_SWRST);
  36592. +
  36593. + /* Read back the reset value of the control register */
  36594. + value = mx1_reg_read(ASP_ACNTLCR);
  36595. +
  36596. + /* Enable the clock and wait for a short while */
  36597. + value |= ASP_CLKEN;
  36598. + mx1_reg_write(ASP_ACNTLCR, value);
  36599. + udelay(100);
  36600. +
  36601. + /* Set the value of the conrtol register. */
  36602. + value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE;
  36603. + mx1_reg_write(ASP_ACNTLCR, value);
  36604. +
  36605. + /* Set the clock divide ratio to 2. */
  36606. + mx1_reg_write(ASP_CLKDIV, 0x01);
  36607. +
  36608. + /* Set the sample rate control register. These values should yield
  36609. + * about 150 samples per second, which seems to give good smooth
  36610. + * lines. */
  36611. + value = (0x2 << ASP_DMCNT_SCALE) | /* Decimation ratio is 3 */
  36612. + (0x1 << ASP_IDLECNT_SCALE) | /* Idle count is 1 clock */
  36613. + (0x2 << ASP_DSCNT_SCALE); /* Data setup is 2 clocks */
  36614. + mx1_reg_write(ASP_PSMPLRG, value);
  36615. +
  36616. + /* Disable the compare function. */
  36617. + mx1_reg_write(ASP_CMPCNTL, 0);
  36618. +}
  36619. +
  36620. +static void mx1_ts_enable_auto_sample(void)
  36621. +{
  36622. + unsigned int value;
  36623. +
  36624. + mx1_ts_flush_fifo();
  36625. +
  36626. + value = mx1_reg_read(ASP_ACNTLCR);
  36627. +
  36628. + /* Set the mode to X then Y */
  36629. + value &= ~ASP_MODE_MASK;
  36630. + value |= ASP_MODE_ONLY_Y;
  36631. +
  36632. + /* Enable auto zero. */
  36633. + value |= ASP_AZE;
  36634. +
  36635. + /* Enable auto sample. */
  36636. + value |= ASP_AUTO;
  36637. +
  36638. + /* Enable pen A/D. */
  36639. + value |= ASP_PADE;
  36640. + mx1_reg_write(ASP_ACNTLCR, value);
  36641. +
  36642. + /* Enable pen data ready and full interrupt. */
  36643. + value = mx1_reg_read(ASP_ICNTLR);
  36644. + value |= ASP_PFFE | ASP_PDRE;
  36645. + mx1_reg_write(ASP_ICNTLR, value);
  36646. +}
  36647. +
  36648. +static void mx1_ts_disable_auto_sample(void)
  36649. +{
  36650. + unsigned int value;
  36651. +
  36652. + value = mx1_reg_read(ASP_ACNTLCR);
  36653. +
  36654. + /* Set the mode to none */
  36655. + value &= ~ASP_MODE_MASK;
  36656. +
  36657. + /* Disable auto zero. */
  36658. + value &= ~ASP_AZE;
  36659. +
  36660. + /* Disable auto sample. */
  36661. + value &= ~ASP_AUTO;
  36662. +
  36663. + /* Disable pen A/D. */
  36664. + value &= ~ASP_PADE;
  36665. + mx1_reg_write(ASP_ACNTLCR, value);
  36666. +
  36667. + /* Disable pen data ready and full interrupt. */
  36668. + value = mx1_reg_read(ASP_ICNTLR);
  36669. + value &= ~(ASP_PFFE | ASP_PDRE);
  36670. + mx1_reg_write(ASP_ICNTLR, value);
  36671. +}
  36672. +
  36673. +static void mx1_ts_enable_pen_touch_interrupt(void)
  36674. +{
  36675. + unsigned int value;
  36676. +
  36677. + /* Enable pen touch interrupt. */
  36678. + value = mx1_reg_read(ASP_ICNTLR);
  36679. + value |= ASP_EDGE | ASP_PIRQE;
  36680. + mx1_reg_write(ASP_ICNTLR, value);
  36681. +}
  36682. +
  36683. +static void mx1_ts_disable_pen_touch_interrupt(void)
  36684. +{
  36685. + unsigned int value;
  36686. +
  36687. + /* Enable pen touch interrupt. */
  36688. + value = mx1_reg_read(ASP_ICNTLR);
  36689. + value &= ~ASP_PIRQE;
  36690. + mx1_reg_write(ASP_ICNTLR, value);
  36691. +}
  36692. +
  36693. +static void mx1_ts_enable_pen_up_interrupt(void)
  36694. +{
  36695. + unsigned int value;
  36696. +
  36697. + /* Enable pen up interrupt. XXX: This feature is undocumented. */
  36698. + value = mx1_reg_read(ASP_ICNTLR);
  36699. + value |= ASP_PUPE;
  36700. + mx1_reg_write(ASP_ICNTLR, value);
  36701. +}
  36702. +
  36703. +static void mx1_ts_disable_pen_up_interrupt(void)
  36704. +{
  36705. + unsigned int value;
  36706. +
  36707. + /* Enable pen up interrupt. XXX: This feature is undocumented. */
  36708. + value = mx1_reg_read(ASP_ICNTLR);
  36709. + value &= ~ASP_PUPE;
  36710. + mx1_reg_write(ASP_ICNTLR, value);
  36711. +}
  36712. +
  36713. +static void mx1_ts_start_auto_calibration(void)
  36714. +{
  36715. + unsigned int value;
  36716. +
  36717. + mx1_performing_auto_calibration = 1;
  36718. +
  36719. + value = mx1_reg_read(ASP_ACNTLCR);
  36720. +
  36721. + /* Set the mode to X then Y */
  36722. + value &= ~ASP_MODE_MASK;
  36723. + value |= ASP_MODE_ONLY_X;
  36724. +
  36725. + /* Enable auto zero. */
  36726. + value |= ASP_AZE;
  36727. +
  36728. + /* Enable auto calibrate. XXX: Undocumented bitfield. */
  36729. + value |= 0x04000000;
  36730. +
  36731. + /* Enable auto sample. */
  36732. + value |= ASP_AUTO;
  36733. +
  36734. + /* Enable pen A/D. */
  36735. + value |= ASP_PADE;
  36736. + mx1_reg_write(ASP_ACNTLCR, value);
  36737. +
  36738. + /* Enable pen data ready and full interrupt. */
  36739. + value = mx1_reg_read(ASP_ICNTLR);
  36740. + value |= ASP_PFFE | ASP_PDRE | ASP_PUPE;
  36741. + mx1_reg_write(ASP_ICNTLR, value);
  36742. +}
  36743. +
  36744. +static int mx1_ts_startup(struct mx1_ts *ts)
  36745. +{
  36746. + int ret = 0;
  36747. +
  36748. + if (ts->use_count++ != 0)
  36749. + goto out;
  36750. +
  36751. + /*
  36752. + * Reset the ASP.
  36753. + */
  36754. + mx1_ts_reset_asp();
  36755. +
  36756. +
  36757. + /*
  36758. + * XXX: Figure out if we need this...
  36759. + * If we do this at all, we should allow the user to
  36760. + * measure and read the X and Y resistance at any time.
  36761. + */
  36762. + //ts->x_res = mx1_ts_read_xres(ts);
  36763. + //ts->y_res = mx1_ts_read_yres(ts);
  36764. +
  36765. + mx1_ts_enable_pen_touch_interrupt();
  36766. +
  36767. + out:
  36768. + if (ret)
  36769. + ts->use_count--;
  36770. + return ret;
  36771. +}
  36772. +
  36773. +/*
  36774. + * Release touchscreen resources. Disable IRQs.
  36775. + */
  36776. +static void mx1_ts_shutdown(struct mx1_ts *ts)
  36777. +{
  36778. + if (--ts->use_count == 0) {
  36779. + unsigned int value;
  36780. +
  36781. + /* Turn off the ADC and associated circuitry. */
  36782. + value = mx1_reg_read(ASP_ACNTLCR);
  36783. + value &= !(ASP_CLKEN | ASP_PADE | ASP_BGE);
  36784. + mx1_reg_write(ASP_ACNTLCR, value);
  36785. + }
  36786. +}
  36787. +
  36788. +/*
  36789. + * Initialization.
  36790. + */
  36791. +static int __init mx1_ts_init(void)
  36792. +{
  36793. + int ret = 0;
  36794. + struct mx1_ts *ts = &mx1ts;
  36795. +
  36796. + mx1_ts_reset_asp();
  36797. +
  36798. + /*
  36799. + * Enable the IRQ's
  36800. + */
  36801. + if ((ret = mx1_ts_enable_irqs()))
  36802. + return ret;
  36803. +
  36804. + return mx1_ts_register(ts);
  36805. +}
  36806. +
  36807. +static void __exit mx1_ts_exit(void)
  36808. +{
  36809. + struct mx1_ts *ts = &mx1ts;
  36810. +
  36811. + mx1_ts_disable_irqs();
  36812. + mx1_ts_deregister(ts);
  36813. +}
  36814. +
  36815. +module_init(mx1_ts_init);
  36816. +module_exit(mx1_ts_exit);
  36817. +
  36818. +MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
  36819. +MODULE_DESCRIPTION("MX1 touchscreen driver");
  36820. +MODULE_LICENSE("GPL");
  36821. diff -urN linux-2.4.26/drivers/input/mx1ts.h linux-2.4.26-vrs1/drivers/input/mx1ts.h
  36822. --- linux-2.4.26/drivers/input/mx1ts.h 1970-01-01 01:00:00.000000000 +0100
  36823. +++ linux-2.4.26-vrs1/drivers/input/mx1ts.h 2004-01-14 21:32:25.000000000 +0000
  36824. @@ -0,0 +1,108 @@
  36825. +/*
  36826. + * linux/drivers/misc/mx1ts.h
  36827. + *
  36828. + * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
  36829. + *
  36830. + * This program is free software; you can redistribute it and/or modify
  36831. + * it under the terms of the GNU General Public License version 2 as
  36832. + * published by the Free Software Foundation.
  36833. + *
  36834. + */
  36835. +
  36836. +/* Interrupt numbers */
  36837. +#define ASP_COMPARE_IRQ 5
  36838. +#define ASP_PENDATA_IRQ 33
  36839. +#define ASP_TOUCH_IRQ 46
  36840. +
  36841. +/* Analog signal processor (ASP) control registers */
  36842. +#define ASP_ACNTLCR 0xF0215010 /* Control register */
  36843. +#define ASP_PSMPLRG 0xF0215014 /* Pen A/D sampe rate control */
  36844. +#define ASP_CMPCNTL 0xF0215030 /* Compare control register */
  36845. +#define ASP_ICNTLR 0xF0215018 /* Interrupt control register */
  36846. +#define ASP_ISTATR 0xF021501C /* Interrupt status register */
  36847. +#define ASP_PADFIFO 0xF0215000 /* Pen sample FIFO */
  36848. +#define ASP_CLKDIV 0xF021502C /* Clock divide register */
  36849. +
  36850. +/* ASP control register bits */
  36851. +#define ASP_CLKEN (1 << 25) /* Clock enable */
  36852. +#define ASP_SWRST (1 << 23) /* Software reset */
  36853. +#define ASP_U_SEL (1 << 21) /* U-channel resistor select */
  36854. +#define ASP_AZ_SEL (1 << 20) /* Auto-zero position select */
  36855. +#define ASP_LVM (1 << 19) /* Low voltage output */
  36856. +#define ASP_NM (1 << 18) /* Normal voltage output */
  36857. +#define ASP_HPM (1 << 17) /* High voltage output */
  36858. +#define ASP_GLO (1 << 16) /* Low gain enable */
  36859. +#define ASP_AZE (1 << 15) /* Auto-zero enable */
  36860. +#define ASP_AUTO (1 << 14) /* Auto sampling */
  36861. +#define ASP_SW8 (1 << 11) /* Switch control 8 */
  36862. +#define ASP_SW7 (1 << 10)
  36863. +#define ASP_SW6 (1 << 9)
  36864. +#define ASP_SW5 (1 << 8)
  36865. +#define ASP_SW4 (1 << 7)
  36866. +#define ASP_SW3 (1 << 6)
  36867. +#define ASP_SW2 (1 << 5)
  36868. +#define ASP_SW1 (1 << 4) /* Switch control 1 */
  36869. +#define ASP_VDAE (1 << 3) /* Voice D/A enable */
  36870. +#define ASP_VADE (1 << 2) /* Voice A/D enable */
  36871. +#define ASP_PADE (1 << 1) /* Pen A/D enable */
  36872. +#define ASP_BGE (1 << 0) /* Bandgap enable */
  36873. +
  36874. +#define ASP_MODE_MASK 0x00003000
  36875. +#define ASP_MODE_NONE 0x00000000
  36876. +#define ASP_MODE_ONLY_X 0x00001000
  36877. +#define ASP_MODE_ONLY_Y 0x00002000
  36878. +#define ASP_MODE_ONLY_U 0x00003000
  36879. +
  36880. +/* ASP Pen A/D sample rate control register */
  36881. +#define ASP_DMCNT_MASK (0x00007000) /* Decimation ratio count */
  36882. +#define ASP_DMCNT_SCALE (12)
  36883. +#define ASP_BIT_SELECT_MASK (0x00000C00) /* Bit select */
  36884. +#define ASP_BIT_SELECT_SCALE (10)
  36885. +#define ASP_IDLECNT_MASK (0x000003F0) /* Idle count */
  36886. +#define ASP_IDLECNT_SCALE (4)
  36887. +#define ASP_DSCNT_MASK (0x0000000F) /* Data setup count */
  36888. +#define ASP_DSCNT_SCALE (0)
  36889. +
  36890. +/* ASP compare control register */
  36891. +#define ASP_INT (1 << 19) /* Interrupt status */
  36892. +#define ASP_CC (1 << 18) /* Trigger on greater than */
  36893. +#define ASP_INSEL_MASK (0x00030000)
  36894. +#define ASP_INSEL_DISABLE (0x00000000)
  36895. +#define ASP_INSEL_X (0x00010000)
  36896. +#define ASP_INSEL_Y (0x00020000)
  36897. +#define ASP_INSEL_U (0x00030000)
  36898. +#define ASP_COMPARE_VAL_MASK (0x0000FFFF)
  36899. +#define ASP_COMPARE_VAL_SCALE (0)
  36900. +
  36901. +/* ASP interrupt control register bits */
  36902. +#define ASP_PUPE (1 << 10) /* Pen up XXX undocumented */
  36903. +#define ASP_VDDMAE (1 << 8) /* VDAC FIFO empty DMA */
  36904. +#define ASP_VADMAE (1 << 7) /* VADC FIFO full DMA */
  36905. +#define ASP_POL (1 << 6) /* Pen interrupt polarity */
  36906. +#define ASP_EDGE (1 << 5) /* Edge trigger enable */
  36907. +#define ASP_PIRQE (1 << 4) /* Pen interrupt enable */
  36908. +#define ASP_VDAFEE (1 << 3) /* VDAC FIFO empty interrupt */
  36909. +#define ASP_VADFFE (1 << 2) /* VADC FIFO full interrupt */
  36910. +#define ASP_PFFE (1 << 1) /* Pen FIFO full interrupt */
  36911. +#define ASP_PDRE (1 << 0) /* Pen data ready interrupt */
  36912. +
  36913. +/* ASP interrupt/error status register bits */
  36914. +#define ASP_PUP (1 << 10) /* Pen up XXX undocumented */
  36915. +#define ASP_BGR (1 << 9) /* Bandgap ready */
  36916. +#define ASP_VOV (1 << 8) /* Voice sample data overflow */
  36917. +#define ASP_POV (1 << 7) /* Pen sample data overflow */
  36918. +#define ASP_PEN (1 << 6) /* Pen interrupt */
  36919. +#define ASP_VDAFF (1 << 5) /* VDAC FIFO full */
  36920. +#define ASP_VDAFE (1 << 4) /* VDAC FIFO empty */
  36921. +#define ASP_VADFF (1 << 3) /* VADC FIFO full */
  36922. +#define ASP_VADDR (1 << 2) /* VADC data ready */
  36923. +#define ASP_PFF (1 << 1) /* Pen sample FIFO full */
  36924. +#define ASP_PDR (1 << 0) /* Pen data ready */
  36925. +
  36926. +/* ASP Clock divide register */
  36927. +#define ASP_PADC_CLK_MASK (0x0000001F)
  36928. +#define ASP_PADC_CLK_SCALE (0)
  36929. +#define ASP_VADC_CLK_MASK (0x000003E0)
  36930. +#define ASP_VADC_CLK_SCALE (5)
  36931. +#define ASP_VDAC_CLK_MASK (0x00003C00)
  36932. +#define ASP_VDAC_CLK_SCALE (10)
  36933. diff -urN linux-2.4.26/drivers/l3/Config.in linux-2.4.26-vrs1/drivers/l3/Config.in
  36934. --- linux-2.4.26/drivers/l3/Config.in 1970-01-01 01:00:00.000000000 +0100
  36935. +++ linux-2.4.26-vrs1/drivers/l3/Config.in 2004-01-14 21:32:25.000000000 +0000
  36936. @@ -0,0 +1,21 @@
  36937. +#
  36938. +# L3 bus configuration
  36939. +#
  36940. +mainmenu_option next_comment
  36941. +comment 'L3 serial bus support'
  36942. +
  36943. +tristate 'L3 support' CONFIG_L3
  36944. +dep_bool ' L3 bit-banging interfaces' CONFIG_L3_ALGOBIT $CONFIG_L3
  36945. +dep_bool ' SA11x0 GPIO adapter' CONFIG_L3_BIT_SA1100_GPIO $CONFIG_L3_ALGOBIT $CONFIG_ARCH_SA1100
  36946. +
  36947. +comment 'Other L3 adapters'
  36948. +dep_bool ' SA1111 adapter' CONFIG_L3_SA1111 $CONFIG_L3
  36949. +endmenu
  36950. +
  36951. +# i2c must come before this
  36952. +if [ "$CONFIG_L3_BIT_SA1100_GPIO" = "y" -o \
  36953. + "$CONFIG_I2C_BIT_SA1100_GPIO" = "y" ]; then
  36954. + define_bool CONFIG_BIT_SA1100_GPIO y
  36955. +else
  36956. + define_bool CONFIG_BIT_SA1100_GPIO n
  36957. +fi
  36958. diff -urN linux-2.4.26/drivers/l3/Makefile linux-2.4.26-vrs1/drivers/l3/Makefile
  36959. --- linux-2.4.26/drivers/l3/Makefile 1970-01-01 01:00:00.000000000 +0100
  36960. +++ linux-2.4.26-vrs1/drivers/l3/Makefile 2004-01-14 21:32:25.000000000 +0000
  36961. @@ -0,0 +1,23 @@
  36962. +#
  36963. +# Makefile for the L3 bus driver.
  36964. +#
  36965. +
  36966. +O_TARGET := l3.o
  36967. +
  36968. +export-objs := l3-core.o l3-algo-bit.o
  36969. +l3-y :=
  36970. +l3-n :=
  36971. +l3-drv-y :=
  36972. +l3-drv-n :=
  36973. +
  36974. +# Link order:
  36975. +# (core, adapters, algorithms, drivers) then clients
  36976. +
  36977. +l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o
  36978. +l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o
  36979. +l3-$(CONFIG_L3_SA1111) += l3-sa1111.o
  36980. +
  36981. +obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y)
  36982. +
  36983. +include $(TOPDIR)/Rules.make
  36984. +
  36985. diff -urN linux-2.4.26/drivers/l3/l3-algo-bit.c linux-2.4.26-vrs1/drivers/l3/l3-algo-bit.c
  36986. --- linux-2.4.26/drivers/l3/l3-algo-bit.c 1970-01-01 01:00:00.000000000 +0100
  36987. +++ linux-2.4.26-vrs1/drivers/l3/l3-algo-bit.c 2004-01-14 21:32:25.000000000 +0000
  36988. @@ -0,0 +1,175 @@
  36989. +/*
  36990. + * L3 bus algorithm module.
  36991. + *
  36992. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  36993. + *
  36994. + * This program is free software; you can redistribute it and/or modify
  36995. + * it under the terms of the GNU General Public License version 2 as
  36996. + * published by the Free Software Foundation.
  36997. + *
  36998. + * Note that L3 buses can share the same pins as I2C buses, so we must
  36999. + * _not_ generate an I2C start condition. An I2C start condition is
  37000. + * defined as a high-to-low transition of the data line while the clock
  37001. + * is high. Therefore, we must only change the data line while the
  37002. + * clock is low.
  37003. + */
  37004. +#include <linux/module.h>
  37005. +#include <linux/kernel.h>
  37006. +#include <linux/delay.h>
  37007. +#include <linux/slab.h>
  37008. +#include <linux/init.h>
  37009. +#include <linux/errno.h>
  37010. +#include <linux/sched.h>
  37011. +#include <linux/l3/l3.h>
  37012. +#include <linux/l3/algo-bit.h>
  37013. +
  37014. +#define setdat(adap,val) adap->setdat(adap->data, val)
  37015. +#define setclk(adap,val) adap->setclk(adap->data, val)
  37016. +#define setmode(adap,val) adap->setmode(adap->data, val)
  37017. +#define setdatin(adap) adap->setdir(adap->data, 1)
  37018. +#define setdatout(adap) adap->setdir(adap->data, 0)
  37019. +#define getdat(adap) adap->getdat(adap->data)
  37020. +
  37021. +/*
  37022. + * Send one byte of data to the chip. Data is latched into the chip on
  37023. + * the rising edge of the clock.
  37024. + */
  37025. +static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte)
  37026. +{
  37027. + int i;
  37028. +
  37029. + for (i = 0; i < 8; i++) {
  37030. + setclk(adap, 0);
  37031. + udelay(adap->data_hold);
  37032. + setdat(adap, byte & 1);
  37033. + udelay(adap->data_setup);
  37034. + setclk(adap, 1);
  37035. + udelay(adap->clock_high);
  37036. + byte >>= 1;
  37037. + }
  37038. +}
  37039. +
  37040. +/*
  37041. + * Send a set of bytes to the chip. We need to pulse the MODE line
  37042. + * between each byte, but never at the start nor at the end of the
  37043. + * transfer.
  37044. + */
  37045. +static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len)
  37046. +{
  37047. + int i;
  37048. +
  37049. + for (i = 0; i < len; i++) {
  37050. + if (i) {
  37051. + udelay(adap->mode_hold);
  37052. + setmode(adap, 0);
  37053. + udelay(adap->mode);
  37054. + }
  37055. + setmode(adap, 1);
  37056. + udelay(adap->mode_setup);
  37057. + sendbyte(adap, buf[i]);
  37058. + }
  37059. +}
  37060. +
  37061. +/*
  37062. + * Read one byte of data from the chip. Data is latched into the chip on
  37063. + * the rising edge of the clock.
  37064. + */
  37065. +static unsigned int readbyte(struct l3_algo_bit_data *adap)
  37066. +{
  37067. + unsigned int byte = 0;
  37068. + int i;
  37069. +
  37070. + for (i = 0; i < 8; i++) {
  37071. + setclk(adap, 0);
  37072. + udelay(adap->data_hold + adap->data_setup);
  37073. + setclk(adap, 1);
  37074. + if (getdat(adap))
  37075. + byte |= 1 << i;
  37076. + udelay(adap->clock_high);
  37077. + }
  37078. +
  37079. + return byte;
  37080. +}
  37081. +
  37082. +/*
  37083. + * Read a set of bytes from the chip. We need to pulse the MODE line
  37084. + * between each byte, but never at the start nor at the end of the
  37085. + * transfer.
  37086. + */
  37087. +static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len)
  37088. +{
  37089. + int i;
  37090. +
  37091. + for (i = 0; i < len; i++) {
  37092. + if (i) {
  37093. + udelay(adap->mode_hold);
  37094. + setmode(adap, 0);
  37095. + }
  37096. + setmode(adap, 1);
  37097. + udelay(adap->mode_setup);
  37098. + buf[i] = readbyte(adap);
  37099. + }
  37100. +}
  37101. +
  37102. +static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num)
  37103. +{
  37104. + struct l3_algo_bit_data *adap = l3_adap->algo_data;
  37105. + int i;
  37106. +
  37107. + /*
  37108. + * If we share an I2C bus, ensure that it is in STOP mode
  37109. + */
  37110. + setclk(adap, 1);
  37111. + setdat(adap, 1);
  37112. + setmode(adap, 1);
  37113. + setdatout(adap);
  37114. + udelay(adap->mode);
  37115. +
  37116. + for (i = 0; i < num; i++) {
  37117. + struct l3_msg *pmsg = &msgs[i];
  37118. +
  37119. + if (!(pmsg->flags & L3_M_NOADDR)) {
  37120. + setmode(adap, 0);
  37121. + udelay(adap->mode_setup);
  37122. + sendbyte(adap, pmsg->addr);
  37123. + udelay(adap->mode_hold);
  37124. + }
  37125. +
  37126. + if (pmsg->flags & L3_M_RD) {
  37127. + setdatin(adap);
  37128. + readbytes(adap, pmsg->buf, pmsg->len);
  37129. + } else {
  37130. + setdatout(adap);
  37131. + sendbytes(adap, pmsg->buf, pmsg->len);
  37132. + }
  37133. + }
  37134. +
  37135. + /*
  37136. + * Ensure that we leave the bus in I2C stop mode.
  37137. + */
  37138. + setclk(adap, 1);
  37139. + setdat(adap, 1);
  37140. + setmode(adap, 0);
  37141. + setdatin(adap);
  37142. +
  37143. + return num;
  37144. +}
  37145. +
  37146. +static struct l3_algorithm l3_bit_algo = {
  37147. + name: "L3 bit-shift algorithm",
  37148. + xfer: l3_xfer,
  37149. +};
  37150. +
  37151. +int l3_bit_add_bus(struct l3_adapter *adap)
  37152. +{
  37153. + adap->algo = &l3_bit_algo;
  37154. + return l3_add_adapter(adap);
  37155. +}
  37156. +
  37157. +int l3_bit_del_bus(struct l3_adapter *adap)
  37158. +{
  37159. + return l3_del_adapter(adap);
  37160. +}
  37161. +
  37162. +EXPORT_SYMBOL(l3_bit_add_bus);
  37163. +EXPORT_SYMBOL(l3_bit_del_bus);
  37164. diff -urN linux-2.4.26/drivers/l3/l3-bit-sa1100.c linux-2.4.26-vrs1/drivers/l3/l3-bit-sa1100.c
  37165. --- linux-2.4.26/drivers/l3/l3-bit-sa1100.c 1970-01-01 01:00:00.000000000 +0100
  37166. +++ linux-2.4.26-vrs1/drivers/l3/l3-bit-sa1100.c 2004-01-14 21:32:25.000000000 +0000
  37167. @@ -0,0 +1,277 @@
  37168. +/*
  37169. + * linux/drivers/l3/l3-bit-sa1100.c
  37170. + *
  37171. + * Copyright (C) 2001 Russell King
  37172. + *
  37173. + * This program is free software; you can redistribute it and/or modify
  37174. + * it under the terms of the GNU General Public License version 2 as
  37175. + * published by the Free Software Foundation.
  37176. + *
  37177. + * This is a combined I2C and L3 bus driver.
  37178. + */
  37179. +#include <linux/config.h>
  37180. +#include <linux/module.h>
  37181. +#include <linux/kernel.h>
  37182. +#include <linux/ioport.h>
  37183. +#include <linux/delay.h>
  37184. +#include <linux/slab.h>
  37185. +#include <linux/init.h>
  37186. +#include <linux/i2c-algo-bit.h>
  37187. +#include <linux/l3/algo-bit.h>
  37188. +
  37189. +#include <asm/system.h>
  37190. +#include <asm/hardware.h>
  37191. +#include <asm/mach-types.h>
  37192. +#include <asm/arch/assabet.h>
  37193. +
  37194. +#define NAME "l3-bit-sa1100-gpio"
  37195. +
  37196. +struct bit_data {
  37197. + unsigned int sda;
  37198. + unsigned int scl;
  37199. + unsigned int l3_mode;
  37200. +};
  37201. +
  37202. +static int getsda(void *data)
  37203. +{
  37204. + struct bit_data *bits = data;
  37205. +
  37206. + return GPLR & bits->sda;
  37207. +}
  37208. +
  37209. +#ifdef CONFIG_I2C_BIT_SA1100_GPIO
  37210. +static void i2c_setsda(void *data, int state)
  37211. +{
  37212. + struct bit_data *bits = data;
  37213. + unsigned long flags;
  37214. +
  37215. + local_irq_save(flags);
  37216. + if (state)
  37217. + GPDR &= ~bits->sda;
  37218. + else {
  37219. + GPCR = bits->sda;
  37220. + GPDR |= bits->sda;
  37221. + }
  37222. + local_irq_restore(flags);
  37223. +}
  37224. +
  37225. +static void i2c_setscl(void *data, int state)
  37226. +{
  37227. + struct bit_data *bits = data;
  37228. + unsigned long flags;
  37229. +
  37230. + local_irq_save(flags);
  37231. + if (state)
  37232. + GPDR &= ~bits->scl;
  37233. + else {
  37234. + GPCR = bits->scl;
  37235. + GPDR |= bits->scl;
  37236. + }
  37237. + local_irq_restore(flags);
  37238. +}
  37239. +
  37240. +static int i2c_getscl(void *data)
  37241. +{
  37242. + struct bit_data *bits = data;
  37243. +
  37244. + return GPLR & bits->scl;
  37245. +}
  37246. +
  37247. +static struct i2c_algo_bit_data i2c_bit_data = {
  37248. + setsda: i2c_setsda,
  37249. + setscl: i2c_setscl,
  37250. + getsda: getsda,
  37251. + getscl: i2c_getscl,
  37252. + udelay: 10,
  37253. + mdelay: 10,
  37254. + timeout: 100,
  37255. +};
  37256. +
  37257. +static struct i2c_adapter i2c_adapter = {
  37258. + name: NAME,
  37259. + algo_data: &i2c_bit_data,
  37260. +// inc_use: i2c_inc_use,
  37261. +// dec_use: i2c_dec_use,
  37262. +};
  37263. +
  37264. +#define LOCK &i2c_adapter.lock
  37265. +
  37266. +static int __init i2c_init(struct bit_data *bits)
  37267. +{
  37268. + i2c_bit_data.data = bits;
  37269. + return i2c_bit_add_bus(&i2c_adapter);
  37270. +}
  37271. +
  37272. +static void i2c_exit(void)
  37273. +{
  37274. + i2c_bit_del_bus(&i2c_adapter);
  37275. +}
  37276. +
  37277. +#else
  37278. +static DECLARE_MUTEX(l3_lock);
  37279. +#define LOCK &l3_lock
  37280. +#define i2c_init(bits) (0)
  37281. +#define i2c_exit() do { } while (0)
  37282. +#endif
  37283. +
  37284. +#ifdef CONFIG_L3_BIT_SA1100_GPIO
  37285. +/*
  37286. + * iPAQs need the clock line driven hard high and low.
  37287. + */
  37288. +static void l3_setscl(void *data, int state)
  37289. +{
  37290. + struct bit_data *bits = data;
  37291. + unsigned long flags;
  37292. +
  37293. + local_irq_save(flags);
  37294. + if (state)
  37295. + GPSR = bits->scl;
  37296. + else
  37297. + GPCR = bits->scl;
  37298. + GPDR |= bits->scl;
  37299. + local_irq_restore(flags);
  37300. +}
  37301. +
  37302. +static void l3_setsda(void *data, int state)
  37303. +{
  37304. + struct bit_data *bits = data;
  37305. +
  37306. + if (state)
  37307. + GPSR = bits->sda;
  37308. + else
  37309. + GPCR = bits->sda;
  37310. +}
  37311. +
  37312. +static void l3_setdir(void *data, int in)
  37313. +{
  37314. + struct bit_data *bits = data;
  37315. + unsigned long flags;
  37316. +
  37317. + local_irq_save(flags);
  37318. + if (in)
  37319. + GPDR &= ~bits->sda;
  37320. + else
  37321. + GPDR |= bits->sda;
  37322. + local_irq_restore(flags);
  37323. +}
  37324. +
  37325. +static void l3_setmode(void *data, int state)
  37326. +{
  37327. + struct bit_data *bits = data;
  37328. +
  37329. + if (state)
  37330. + GPSR = bits->l3_mode;
  37331. + else
  37332. + GPCR = bits->l3_mode;
  37333. +}
  37334. +
  37335. +static struct l3_algo_bit_data l3_bit_data = {
  37336. + data: NULL,
  37337. + setdat: l3_setsda,
  37338. + setclk: l3_setscl,
  37339. + setmode: l3_setmode,
  37340. + setdir: l3_setdir,
  37341. + getdat: getsda,
  37342. + data_hold: 1,
  37343. + data_setup: 1,
  37344. + clock_high: 1,
  37345. + mode_hold: 1,
  37346. + mode_setup: 1,
  37347. +};
  37348. +
  37349. +static struct l3_adapter l3_adapter = {
  37350. + owner: THIS_MODULE,
  37351. + name: NAME,
  37352. + algo_data: &l3_bit_data,
  37353. + lock: LOCK,
  37354. +};
  37355. +
  37356. +static int __init l3_init(struct bit_data *bits)
  37357. +{
  37358. + l3_bit_data.data = bits;
  37359. + return l3_bit_add_bus(&l3_adapter);
  37360. +}
  37361. +
  37362. +static void __exit l3_exit(void)
  37363. +{
  37364. + l3_bit_del_bus(&l3_adapter);
  37365. +}
  37366. +#else
  37367. +#define l3_init(bits) (0)
  37368. +#define l3_exit() do { } while (0)
  37369. +#endif
  37370. +
  37371. +static struct bit_data bit_data;
  37372. +
  37373. +static int __init bus_init(void)
  37374. +{
  37375. + struct bit_data *bit = &bit_data;
  37376. + unsigned long flags;
  37377. + int ret;
  37378. +
  37379. + if (machine_is_assabet() || machine_is_pangolin()) {
  37380. + bit->sda = GPIO_GPIO15;
  37381. + bit->scl = GPIO_GPIO18;
  37382. + bit->l3_mode = GPIO_GPIO17;
  37383. + }
  37384. +
  37385. +#if defined(CONFIG_SA1100_H3600) || defined(CONFIG_SA1100_H3100)
  37386. + if (machine_is_h3600() || machine_is_h3100()) {
  37387. + bit->sda = GPIO_H3600_L3_DATA;
  37388. + bit->scl = GPIO_H3600_L3_CLOCK;
  37389. + bit->l3_mode = GPIO_H3600_L3_MODE;
  37390. + }
  37391. +#endif
  37392. +
  37393. +#ifdef CONFIG_SA1100_STORK
  37394. + if (machine_is_stork()) {
  37395. + bit->sda = GPIO_STORK_L3_I2C_SDA;
  37396. + bit->scl = GPIO_STORK_L3_I2C_SCL;
  37397. + bit->l3_mode = GPIO_STORK_L3_MODE;
  37398. + }
  37399. +#endif
  37400. +
  37401. + if (!bit->sda)
  37402. + return -ENODEV;
  37403. +
  37404. + /*
  37405. + * Default level for L3 mode is low.
  37406. + * We set SCL and SDA high (i2c idle state).
  37407. + */
  37408. + local_irq_save(flags);
  37409. + GPDR &= ~(bit->scl | bit->sda);
  37410. + GPCR = bit->l3_mode | bit->scl | bit->sda;
  37411. + GPDR |= bit->l3_mode;
  37412. + local_irq_restore(flags);
  37413. +
  37414. + if (machine_is_assabet()) {
  37415. + /*
  37416. + * Release reset on UCB1300, ADI7171 and UDA1341. We
  37417. + * need to do this here so that we can communicate on
  37418. + * the I2C/L3 buses.
  37419. + */
  37420. + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
  37421. + mdelay(1);
  37422. + ASSABET_BCR_clear(ASSABET_BCR_CODEC_RST);
  37423. + mdelay(1);
  37424. + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
  37425. + }
  37426. +
  37427. + ret = i2c_init(bit);
  37428. + if (ret == 0 && bit->l3_mode) {
  37429. + ret = l3_init(bit);
  37430. + if (ret)
  37431. + i2c_exit();
  37432. + }
  37433. +
  37434. + return ret;
  37435. +}
  37436. +
  37437. +static void __exit bus_exit(void)
  37438. +{
  37439. + l3_exit();
  37440. + i2c_exit();
  37441. +}
  37442. +
  37443. +module_init(bus_init);
  37444. +module_exit(bus_exit);
  37445. diff -urN linux-2.4.26/drivers/l3/l3-core.c linux-2.4.26-vrs1/drivers/l3/l3-core.c
  37446. --- linux-2.4.26/drivers/l3/l3-core.c 1970-01-01 01:00:00.000000000 +0100
  37447. +++ linux-2.4.26-vrs1/drivers/l3/l3-core.c 2004-01-14 21:32:25.000000000 +0000
  37448. @@ -0,0 +1,377 @@
  37449. +/*
  37450. + * linux/drivers/l3/l3-core.c
  37451. + *
  37452. + * Copyright (C) 2001 Russell King
  37453. + *
  37454. + * General structure taken from i2c-core.c by Simon G. Vogl
  37455. + *
  37456. + * This program is free software; you can redistribute it and/or modify
  37457. + * it under the terms of the GNU General Public License as published by
  37458. + * the Free Software Foundation; either version 2 of the License.
  37459. + *
  37460. + * See linux/Documentation/l3 for further documentation.
  37461. + */
  37462. +#include <linux/module.h>
  37463. +#include <linux/config.h>
  37464. +#include <linux/kernel.h>
  37465. +#include <linux/errno.h>
  37466. +#include <linux/slab.h>
  37467. +#include <linux/proc_fs.h>
  37468. +#include <linux/kmod.h>
  37469. +#include <linux/init.h>
  37470. +#include <linux/l3/l3.h>
  37471. +
  37472. +static DECLARE_MUTEX(adapter_lock);
  37473. +static LIST_HEAD(adapter_list);
  37474. +
  37475. +static DECLARE_MUTEX(driver_lock);
  37476. +static LIST_HEAD(driver_list);
  37477. +
  37478. +/**
  37479. + * l3_add_adapter - register a new L3 bus adapter
  37480. + * @adap: l3_adapter structure for the registering adapter
  37481. + *
  37482. + * Make the adapter available for use by clients using name adap->name.
  37483. + * The adap->adapters list is initialised by this function.
  37484. + *
  37485. + * Returns 0;
  37486. + */
  37487. +int l3_add_adapter(struct l3_adapter *adap)
  37488. +{
  37489. + INIT_LIST_HEAD(&adap->clients);
  37490. + down(&adapter_lock);
  37491. + list_add(&adap->adapters, &adapter_list);
  37492. + up(&adapter_lock);
  37493. + return 0;
  37494. +}
  37495. +
  37496. +/**
  37497. + * l3_del_adapter - unregister a L3 bus adapter
  37498. + * @adap: l3_adapter structure to unregister
  37499. + *
  37500. + * Remove an adapter from the list of available L3 Bus adapters.
  37501. + *
  37502. + * Returns 0;
  37503. + */
  37504. +int l3_del_adapter(struct l3_adapter *adap)
  37505. +{
  37506. + down(&adapter_lock);
  37507. + list_del(&adap->adapters);
  37508. + up(&adapter_lock);
  37509. + return 0;
  37510. +}
  37511. +
  37512. +static struct l3_adapter *__l3_get_adapter(const char *name)
  37513. +{
  37514. + struct list_head *l;
  37515. +
  37516. + list_for_each(l, &adapter_list) {
  37517. + struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters);
  37518. +
  37519. + if (strcmp(adap->name, name) == 0)
  37520. + return adap;
  37521. + }
  37522. +
  37523. + return NULL;
  37524. +}
  37525. +
  37526. +/**
  37527. + * l3_get_adapter - get a reference to an adapter
  37528. + * @name: driver name
  37529. + *
  37530. + * Obtain a l3_adapter structure for the specified adapter. If the adapter
  37531. + * is not currently load, then load it. The adapter will be locked in core
  37532. + * until all references are released via l3_put_adapter.
  37533. + */
  37534. +struct l3_adapter *l3_get_adapter(const char *name)
  37535. +{
  37536. + struct l3_adapter *adap;
  37537. + int try;
  37538. +
  37539. + for (try = 0; try < 2; try ++) {
  37540. + down(&adapter_lock);
  37541. + adap = __l3_get_adapter(name);
  37542. + if (adap && !try_inc_mod_count(adap->owner))
  37543. + adap = NULL;
  37544. + up(&adapter_lock);
  37545. +
  37546. + if (adap)
  37547. + break;
  37548. +
  37549. + if (try == 0)
  37550. + request_module(name);
  37551. + }
  37552. +
  37553. + return adap;
  37554. +}
  37555. +
  37556. +/**
  37557. + * l3_put_adapter - release a reference to an adapter
  37558. + * @adap: driver to release reference
  37559. + *
  37560. + * Indicate to the L3 core that you no longer require the adapter reference.
  37561. + * The adapter module may be unloaded when there are no references to its
  37562. + * data structure.
  37563. + *
  37564. + * You must not use the reference after calling this function.
  37565. + */
  37566. +void l3_put_adapter(struct l3_adapter *adap)
  37567. +{
  37568. + if (adap && adap->owner)
  37569. + __MOD_DEC_USE_COUNT(adap->owner);
  37570. +}
  37571. +
  37572. +/**
  37573. + * l3_add_driver - register a new L3 device driver
  37574. + * @driver - driver structure to make available
  37575. + *
  37576. + * Make the driver available for use by clients using name driver->name.
  37577. + * The driver->drivers list is initialised by this function.
  37578. + *
  37579. + * Returns 0;
  37580. + */
  37581. +int l3_add_driver(struct l3_driver *driver)
  37582. +{
  37583. + down(&driver_lock);
  37584. + list_add(&driver->drivers, &driver_list);
  37585. + up(&driver_lock);
  37586. + return 0;
  37587. +}
  37588. +
  37589. +/**
  37590. + * l3_del_driver - unregister a L3 device driver
  37591. + * @driver: driver to remove
  37592. + *
  37593. + * Remove an driver from the list of available L3 Bus device drivers.
  37594. + *
  37595. + * Returns 0;
  37596. + */
  37597. +int l3_del_driver(struct l3_driver *driver)
  37598. +{
  37599. + down(&driver_lock);
  37600. + list_del(&driver->drivers);
  37601. + up(&driver_lock);
  37602. + return 0;
  37603. +}
  37604. +
  37605. +static struct l3_driver *__l3_get_driver(const char *name)
  37606. +{
  37607. + struct list_head *l;
  37608. +
  37609. + list_for_each(l, &driver_list) {
  37610. + struct l3_driver *drv = list_entry(l, struct l3_driver, drivers);
  37611. +
  37612. + if (strcmp(drv->name, name) == 0)
  37613. + return drv;
  37614. + }
  37615. +
  37616. + return NULL;
  37617. +}
  37618. +
  37619. +/**
  37620. + * l3_get_driver - get a reference to a driver
  37621. + * @name: driver name
  37622. + *
  37623. + * Obtain a l3_driver structure for the specified driver. If the driver is
  37624. + * not currently load, then load it. The driver will be locked in core
  37625. + * until all references are released via l3_put_driver.
  37626. + */
  37627. +struct l3_driver *l3_get_driver(const char *name)
  37628. +{
  37629. + struct l3_driver *drv;
  37630. + int try;
  37631. +
  37632. + for (try = 0; try < 2; try ++) {
  37633. + down(&adapter_lock);
  37634. + drv = __l3_get_driver(name);
  37635. + if (drv && !try_inc_mod_count(drv->owner))
  37636. + drv = NULL;
  37637. + up(&adapter_lock);
  37638. +
  37639. + if (drv)
  37640. + break;
  37641. +
  37642. + if (try == 0)
  37643. + request_module(name);
  37644. + }
  37645. +
  37646. + return drv;
  37647. +}
  37648. +
  37649. +/**
  37650. + * l3_put_driver - release a reference to a driver
  37651. + * @drv: driver to release reference
  37652. + *
  37653. + * Indicate to the L3 core that you no longer require the driver reference.
  37654. + * The driver module may be unloaded when there are no references to its
  37655. + * data structure.
  37656. + *
  37657. + * You must not use the reference after calling this function.
  37658. + */
  37659. +void l3_put_driver(struct l3_driver *drv)
  37660. +{
  37661. + if (drv && drv->owner)
  37662. + __MOD_DEC_USE_COUNT(drv->owner);
  37663. +}
  37664. +
  37665. +/**
  37666. + * l3_attach_client - attach a client to an adapter and driver
  37667. + * @client: client structure to attach
  37668. + * @adap: adapter (module) name
  37669. + * @drv: driver (module) name
  37670. + *
  37671. + * Attempt to attach a client (a user of a device driver) to a particular
  37672. + * driver and adapter. If the specified driver or adapter aren't registered,
  37673. + * request_module is used to load the relevant modules.
  37674. + *
  37675. + * Returns 0 on success, or negative error code.
  37676. + */
  37677. +int l3_attach_client(struct l3_client *client, const char *adap, const char *drv)
  37678. +{
  37679. + struct l3_adapter *adapter = l3_get_adapter(adap);
  37680. + struct l3_driver *driver = l3_get_driver(drv);
  37681. + int ret = -ENOENT;
  37682. +
  37683. + if (!adapter)
  37684. + printk(KERN_ERR "%s: unable to get adapter: %s\n",
  37685. + __FUNCTION__, adap);
  37686. + if (!driver)
  37687. + printk(KERN_ERR "%s: unable to get driver: %s\n",
  37688. + __FUNCTION__, drv);
  37689. +
  37690. + if (adapter && driver) {
  37691. + ret = 0;
  37692. +
  37693. + client->adapter = adapter;
  37694. + client->driver = driver;
  37695. +
  37696. + list_add(&client->__adap, &adapter->clients);
  37697. +
  37698. + if (driver->attach_client)
  37699. + ret = driver->attach_client(client);
  37700. + }
  37701. +
  37702. + if (ret) {
  37703. + l3_put_driver(driver);
  37704. + l3_put_adapter(adapter);
  37705. + }
  37706. + return ret;
  37707. +}
  37708. +
  37709. +/**
  37710. + * l3_detach_client - detach a client from an adapter and driver
  37711. + * @client: client structure to detach
  37712. + *
  37713. + * Detach the client from the adapter and driver.
  37714. + */
  37715. +int l3_detach_client(struct l3_client *client)
  37716. +{
  37717. + struct l3_adapter *adapter = client->adapter;
  37718. + struct l3_driver *driver = client->driver;
  37719. +
  37720. + driver->detach_client(client);
  37721. +
  37722. + client->adapter = NULL;
  37723. + client->driver = NULL;
  37724. +
  37725. + l3_put_driver(driver);
  37726. + l3_put_adapter(adapter);
  37727. +
  37728. + list_del(&client->__adap);
  37729. +
  37730. + return 0;
  37731. +}
  37732. +
  37733. +/**
  37734. + * l3_transfer - transfer information on an L3 bus
  37735. + * @adap: adapter structure to perform transfer on
  37736. + * @msgs: array of l3_msg structures describing transfer
  37737. + * @num: number of l3_msg structures
  37738. + *
  37739. + * Transfer the specified messages to/from a device on the L3 bus.
  37740. + *
  37741. + * Returns number of messages successfully transferred, otherwise negative
  37742. + * error code.
  37743. + */
  37744. +int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
  37745. +{
  37746. + int ret = -ENOSYS;
  37747. +
  37748. + if (adap->algo->xfer) {
  37749. + down(adap->lock);
  37750. + ret = adap->algo->xfer(adap, msgs, num);
  37751. + up(adap->lock);
  37752. + }
  37753. + return ret;
  37754. +}
  37755. +
  37756. +/**
  37757. + * l3_write - send data to a device on an L3 bus
  37758. + * @client: registered client structure
  37759. + * @addr: L3 bus address
  37760. + * @buf: buffer for bytes to send
  37761. + * @len: number of bytes to send
  37762. + *
  37763. + * Send len bytes pointed to by buf to device address addr on the L3 bus
  37764. + * described by client.
  37765. + *
  37766. + * Returns the number of bytes transferred, or negative error code.
  37767. + */
  37768. +int l3_write(struct l3_client *client, int addr, const char *buf, int len)
  37769. +{
  37770. + struct l3_adapter *adap = client->adapter;
  37771. + struct l3_msg msg;
  37772. + int ret;
  37773. +
  37774. + msg.addr = addr;
  37775. + msg.flags = 0;
  37776. + msg.buf = (char *)buf;
  37777. + msg.len = len;
  37778. +
  37779. + ret = l3_transfer(adap, &msg, 1);
  37780. + return ret == 1 ? len : ret;
  37781. +}
  37782. +
  37783. +/**
  37784. + * l3_read - receive data from a device on an L3 bus
  37785. + * @client: registered client structure
  37786. + * @addr: L3 bus address
  37787. + * @buf: buffer for bytes to receive
  37788. + * @len: number of bytes to receive
  37789. + *
  37790. + * Receive len bytes from device address addr on the L3 bus described by
  37791. + * client to a buffer pointed to by buf.
  37792. + *
  37793. + * Returns the number of bytes transferred, or negative error code.
  37794. + */
  37795. +int l3_read(struct l3_client *client, int addr, char *buf, int len)
  37796. +{
  37797. + struct l3_adapter *adap = client->adapter;
  37798. + struct l3_msg msg;
  37799. + int ret;
  37800. +
  37801. + msg.addr = addr;
  37802. + msg.flags = L3_M_RD;
  37803. + msg.buf = buf;
  37804. + msg.len = len;
  37805. +
  37806. + ret = l3_transfer(adap, &msg, 1);
  37807. + return ret == 1 ? len : ret;
  37808. +}
  37809. +
  37810. +EXPORT_SYMBOL(l3_add_adapter);
  37811. +EXPORT_SYMBOL(l3_del_adapter);
  37812. +EXPORT_SYMBOL(l3_get_adapter);
  37813. +EXPORT_SYMBOL(l3_put_adapter);
  37814. +
  37815. +EXPORT_SYMBOL(l3_add_driver);
  37816. +EXPORT_SYMBOL(l3_del_driver);
  37817. +EXPORT_SYMBOL(l3_get_driver);
  37818. +EXPORT_SYMBOL(l3_put_driver);
  37819. +
  37820. +EXPORT_SYMBOL(l3_attach_client);
  37821. +EXPORT_SYMBOL(l3_detach_client);
  37822. +
  37823. +EXPORT_SYMBOL(l3_transfer);
  37824. +EXPORT_SYMBOL(l3_write);
  37825. +EXPORT_SYMBOL(l3_read);
  37826. diff -urN linux-2.4.26/drivers/l3/l3-sa1111.c linux-2.4.26-vrs1/drivers/l3/l3-sa1111.c
  37827. --- linux-2.4.26/drivers/l3/l3-sa1111.c 1970-01-01 01:00:00.000000000 +0100
  37828. +++ linux-2.4.26-vrs1/drivers/l3/l3-sa1111.c 2004-01-14 21:32:25.000000000 +0000
  37829. @@ -0,0 +1,118 @@
  37830. +/*
  37831. + * L3 SA1111 algorithm/adapter module.
  37832. + *
  37833. + * By Russell King,
  37834. + * gratuitously ripped from sa1111-uda1341.c by John Dorsey.
  37835. + *
  37836. + * This program is free software; you can redistribute it and/or modify
  37837. + * it under the terms of the GNU General Public License version 2 as
  37838. + * published by the Free Software Foundation.
  37839. + */
  37840. +#include <linux/module.h>
  37841. +#include <linux/init.h>
  37842. +#include <linux/delay.h>
  37843. +#include <linux/errno.h>
  37844. +#include <linux/l3/l3.h>
  37845. +
  37846. +#include <asm/hardware.h>
  37847. +#include <asm/semaphore.h>
  37848. +#include <asm/mach-types.h>
  37849. +#include <asm/arch/assabet.h>
  37850. +#include <asm/hardware/sa1111.h>
  37851. +
  37852. +static inline unsigned char l3_sa1111_recv_byte(unsigned char addr)
  37853. +{
  37854. + unsigned char dat;
  37855. +
  37856. + L3_CAR = addr;
  37857. + while ((SASR0 & SASR0_L3RD) == 0)
  37858. + mdelay(1);
  37859. + dat = L3_CDR;
  37860. + SASCR = SASCR_RDD;
  37861. + return dat;
  37862. +}
  37863. +
  37864. +static void l3_sa1111_recv_msg(struct l3_msg *msg)
  37865. +{
  37866. + int len = msg->len;
  37867. + char *p = msg->buf;
  37868. +
  37869. + if (len > 1) {
  37870. + SACR1 |= SACR1_L3MB;
  37871. + while ((len--) > 1)
  37872. + *p++ = l3_sa1111_recv_byte(msg->addr);
  37873. + }
  37874. + SACR1 &= ~SACR1_L3MB;
  37875. + *p = l3_sa1111_recv_byte(msg->addr);
  37876. +}
  37877. +
  37878. +static inline void l3_sa1111_send_byte(unsigned char addr, unsigned char dat)
  37879. +{
  37880. + L3_CAR = addr;
  37881. + L3_CDR = dat;
  37882. + while ((SASR0 & SASR0_L3WD) == 0)
  37883. + mdelay(1);
  37884. + SASCR = SASCR_DTS;
  37885. +}
  37886. +
  37887. +static void l3_sa1111_send_msg(struct l3_msg *msg)
  37888. +{
  37889. + int len = msg->len;
  37890. + char *p = msg->buf;
  37891. +
  37892. + if (len > 1) {
  37893. + SACR1 |= SACR1_L3MB;
  37894. + while ((len--) > 1)
  37895. + l3_sa1111_send_byte(msg->addr, *p++);
  37896. + }
  37897. + SACR1 &= ~SACR1_L3MB;
  37898. + l3_sa1111_send_byte(msg->addr, *p);
  37899. +}
  37900. +
  37901. +static int l3_sa1111_xfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
  37902. +{
  37903. + int i;
  37904. +
  37905. + for (i = 0; i < num; i++) {
  37906. + struct l3_msg *pmsg = &msgs[i];
  37907. +
  37908. + if (pmsg->flags & L3_M_RD)
  37909. + l3_sa1111_recv_msg(pmsg);
  37910. + else
  37911. + l3_sa1111_send_msg(pmsg);
  37912. + }
  37913. +
  37914. + return num;
  37915. +}
  37916. +
  37917. +static struct l3_algorithm l3_sa1111_algo = {
  37918. + name: "L3 SA1111 algorithm",
  37919. + xfer: l3_sa1111_xfer,
  37920. +};
  37921. +
  37922. +static DECLARE_MUTEX(sa1111_lock);
  37923. +
  37924. +static struct l3_adapter l3_sa1111_adapter = {
  37925. + owner: THIS_MODULE,
  37926. + name: "l3-sa1111",
  37927. + algo: &l3_sa1111_algo,
  37928. + lock: &sa1111_lock,
  37929. +};
  37930. +
  37931. +static int __init l3_sa1111_init(void)
  37932. +{
  37933. + int ret = -ENODEV;
  37934. + if ((machine_is_assabet() && machine_has_neponset()) ||
  37935. + machine_is_jornada720() || machine_is_accelent_sa() ||
  37936. + machine_is_badge4())
  37937. + ret = l3_add_adapter(&l3_sa1111_adapter);
  37938. + return ret;
  37939. +}
  37940. +
  37941. +static void __exit l3_sa1111_exit(void)
  37942. +{
  37943. + l3_del_adapter(&l3_sa1111_adapter);
  37944. +}
  37945. +
  37946. +module_init(l3_sa1111_init);
  37947. +module_exit(l3_sa1111_exit);
  37948. diff -urN linux-2.4.26/drivers/media/video/Config.in linux-2.4.26-vrs1/drivers/media/video/Config.in
  37949. --- linux-2.4.26/drivers/media/video/Config.in 2004-04-19 11:44:16.000000000 +0100
  37950. +++ linux-2.4.26-vrs1/drivers/media/video/Config.in 2004-04-19 10:36:42.000000000 +0100
  37951. @@ -52,5 +52,8 @@
  37952. if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HIGHMEM64G" != "y" ]; then
  37953. dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
  37954. fi
  37955. +# unfortunately, this depends on having CONFIG_FB_CYBER2000
  37956. +# set as well - we hook off of the VGA driver
  37957. +dep_tristate ' NetWinder Video for Linux (EXPERIMENTAL)' CONFIG_VIDEO_CYBERPRO $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL $CONFIG_ARCH_NETWINDER
  37958. endmenu
  37959. diff -urN linux-2.4.26/drivers/media/video/Makefile linux-2.4.26-vrs1/drivers/media/video/Makefile
  37960. --- linux-2.4.26/drivers/media/video/Makefile 2004-02-27 20:03:25.000000000 +0000
  37961. +++ linux-2.4.26-vrs1/drivers/media/video/Makefile 2004-02-23 22:56:20.000000000 +0000
  37962. @@ -16,7 +16,7 @@
  37963. obj-n :=
  37964. obj- :=
  37965. -SUB_DIRS :=
  37966. +SUB_DIRS :=
  37967. MOD_SUB_DIRS := $(SUB_DIRS)
  37968. ALL_SUB_DIRS := $(SUB_DIRS)
  37969. @@ -47,7 +47,8 @@
  37970. obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
  37971. obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o
  37972. obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o
  37973. -obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o
  37974. +obj-$(CONFIG_VIDEO_CYBERPRO) += cyberpro.o i2c-old.o saa7111.o
  37975. +obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
  37976. obj-$(CONFIG_VIDEO_PMS) += pms.o
  37977. obj-$(CONFIG_VIDEO_PLANB) += planb.o
  37978. obj-$(CONFIG_VIDEO_VINO) += saa7191.o indycam.o vino.o
  37979. diff -urN linux-2.4.26/drivers/media/video/cyberpro.c linux-2.4.26-vrs1/drivers/media/video/cyberpro.c
  37980. --- linux-2.4.26/drivers/media/video/cyberpro.c 1970-01-01 01:00:00.000000000 +0100
  37981. +++ linux-2.4.26-vrs1/drivers/media/video/cyberpro.c 2004-01-14 21:32:25.000000000 +0000
  37982. @@ -0,0 +1,2091 @@
  37983. +/*
  37984. + * CyberPro 2000 video capture driver for the Rebel.com NetWinder
  37985. + *
  37986. + * (C) 1999-2000 Russell King
  37987. + *
  37988. + * Re-written from Rebel.com's vidcap driver.
  37989. + *
  37990. + * Architecture
  37991. + * ------------
  37992. + * The NetWinder video capture consists of a SAA7111 video decoder chip
  37993. + * connected to the CyberPro feature bus. The video data is captured to
  37994. + * the VGA memory, where the CyberPro can overlay (by chromakeying) the
  37995. + * data onto the VGA display.
  37996. + *
  37997. + * The CyberPro also has some nifty features, including a second overlay
  37998. + * and picture in picture mode. We do not currently use these features.
  37999. + *
  38000. + * Power Saving
  38001. + * ------------
  38002. + * Please note that rev.5 NetWinders have the ability to hold the SAA7111
  38003. + * decoder chip into reset, which saves power. The only time at which
  38004. + * this is done is when the driver is unloaded, which implies that this
  38005. + * is compiled as a module.
  38006. + *
  38007. + * In this case, you will want the kernel to automatically load this
  38008. + * driver when required. Place the following line in /etc/modules.conf
  38009. + * to enable this:
  38010. + *
  38011. + * alias char-major-81-0 cyberpro
  38012. + *
  38013. + * The relevant modules will be automatically loaded by modprobe on a
  38014. + * as and when needed basis.
  38015. + *
  38016. + * Capture resolution
  38017. + * ------------------
  38018. + * The maximum useful capture resolution is:
  38019. + * 625-line UK: 716x576
  38020. + * 525-line US: ?
  38021. + *
  38022. + * Bugs
  38023. + * ----
  38024. + * 1. The CyberPro chip seems to be prone to randomly scribbling over VGA
  38025. + * memory [hopefully fixed with new capture enable/freeze stuff]
  38026. + * 2. read()ing pauses video capture, and sometimes triggers bug 1.
  38027. + * 3. mmap() is not supported (requires BM-DMA - see bug 4)
  38028. + * 4. Really, we want to do scatter BM-DMA. Is the CyberPro capable of this?
  38029. + * The Cyberpro seems to randomly scribble to various PCI addresses if you
  38030. + * transfer >16 words.
  38031. + * 5. We shouldn't ignore O_NONBLOCK when reading a frame.
  38032. + * 6. The incoming stream on the NetWinder is CCIR656, which is YUV422.
  38033. + * CyberPro docs also call the format we capture and overlay "YUV422",
  38034. + * but we actually seem to have Y, U, Y, V bytes (is this YUYV format?)
  38035. + */
  38036. +#include <linux/config.h>
  38037. +#include <linux/module.h>
  38038. +#include <linux/videodev.h>
  38039. +#include <linux/video_decoder.h>
  38040. +#include <linux/mm.h>
  38041. +#include <linux/i2c-old.h>
  38042. +#include <linux/spinlock.h>
  38043. +#include <linux/slab.h>
  38044. +#include <linux/vmalloc.h>
  38045. +#include <linux/delay.h>
  38046. +#include <linux/sched.h>
  38047. +#include <linux/kmod.h>
  38048. +#include <linux/pci.h>
  38049. +#include <linux/init.h>
  38050. +
  38051. +#include <asm/io.h>
  38052. +#include <asm/irq.h>
  38053. +#include <asm/pgtable.h>
  38054. +#include <asm/pgalloc.h>
  38055. +
  38056. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  38057. +MODULE_DESCRIPTION("CyberPro v4l video grabber");
  38058. +MODULE_LICENSE("GPL");
  38059. +
  38060. +#include "../../video/cyber2000fb.h"
  38061. +
  38062. +/*
  38063. + * These enable various experimental features. Most of these
  38064. + * are just plain broken or just don't work at the moment.
  38065. + */
  38066. +/*
  38067. + * Enable this if you want mmap() access. (see bug 4)
  38068. + */
  38069. +#undef USE_MMAP
  38070. +
  38071. +/*
  38072. + * Enable this if you want mmio access. (slow)
  38073. + */
  38074. +#define USE_MMIO
  38075. +
  38076. +/*
  38077. + * The V4L API is unclear whether VIDIOCSCAPTURE call is allowed while
  38078. + * capture is running. The default is to disallow the call.
  38079. + *
  38080. + * Define this if you do want to allow the call while capture is active.
  38081. + */
  38082. +#undef ALLOW_SCAPTURE_WHILE_CAP
  38083. +
  38084. +/*
  38085. + * We capture two frames
  38086. + */
  38087. +#define NR_FRAMES 2
  38088. +
  38089. +/*
  38090. + * One frame of video is 202 pages, assuming YUV422 format, 716x576
  38091. + */
  38092. +#define NR_PAGES 202
  38093. +
  38094. +struct src_info {
  38095. + unsigned int offset; /* offset of source data */
  38096. + unsigned int x; /* source x */
  38097. + unsigned int y; /* source y */
  38098. + unsigned int width; /* source width */
  38099. + unsigned int height; /* source height */
  38100. + unsigned int format; /* source format */
  38101. +};
  38102. +
  38103. +struct dst_info {
  38104. + unsigned int x; /* destination x */
  38105. + unsigned int y; /* destination y */
  38106. + unsigned int width; /* destination width */
  38107. + unsigned int height; /* destination height */
  38108. + unsigned int chromakey; /* chromakey */
  38109. + unsigned int flags; /* flags (eg, chromakey enable) */
  38110. +};
  38111. +
  38112. +struct cyberpro_vidinfo;
  38113. +
  38114. +struct win_info {
  38115. + void (*init)(struct cyberpro_vidinfo *dp, struct win_info *wi);
  38116. + void (*set_src)(struct cyberpro_vidinfo *dp, struct win_info *wi);
  38117. + void (*set_win)(struct cyberpro_vidinfo *dp, struct win_info *wi);
  38118. + void (*ctl)(struct cyberpro_vidinfo *dp, struct win_info *wi, int on_off);
  38119. +
  38120. + /* public */
  38121. + struct src_info src;
  38122. + struct dst_info dst;
  38123. +
  38124. + /* private */
  38125. + unsigned short vid_fifo_ctl;
  38126. + unsigned char vid_fmt;
  38127. + unsigned char vid_disp_ctl1;
  38128. + unsigned char vid_fifo_ctl1;
  38129. + unsigned char vid_misc_ctl1;
  38130. +};
  38131. +
  38132. +struct framebuf {
  38133. + unsigned int offset; /* mmap offset for this frame */
  38134. + unsigned int status;
  38135. +#define FRAME_FREE 0
  38136. +#define FRAME_DONE 1
  38137. +#define FRAME_WAITING 2
  38138. +#define FRAME_GRABBING 3
  38139. +
  38140. + /*
  38141. + * Bus-Master DMA stuff. Note that we should
  38142. + * probably use the kiovec stuff instead.
  38143. + */
  38144. + unsigned long bus_addr[NR_PAGES]; /* list of pages */
  38145. + struct page *pages[NR_PAGES];
  38146. + void *buffer;
  38147. + int dbg;
  38148. +};
  38149. +
  38150. +struct cyberpro_vidinfo {
  38151. + struct video_device *dev;
  38152. + struct i2c_bus *bus;
  38153. + struct cyberpro_info info; /* host information */
  38154. + unsigned char *regs;
  38155. + unsigned int irq; /* PCI interrupt number */
  38156. +
  38157. + /* hardware configuration */
  38158. + unsigned int stream_fmt; /* format of stream from decoder*/
  38159. +
  38160. + /* software settings */
  38161. + unsigned int decoder:1; /* decoder loaded */
  38162. + unsigned int interlace:1; /* interlace */
  38163. + unsigned int buf_set:1; /* VIDIOCSFBUF has been issued */
  38164. + unsigned int win_set:1; /* VIDIOCSWIN has been issued */
  38165. + unsigned int cap_active:1; /* capture is active */
  38166. + unsigned int ovl_active:1; /* overlay is active */
  38167. + unsigned int mmaped:1; /* buffer is mmap()d */
  38168. + unsigned int unused:25;
  38169. +
  38170. + unsigned int users; /* number of users */
  38171. + unsigned long cap_mem_offset; /* capture framebuffer offset */
  38172. + void * buffer; /* kernel capture buffer */
  38173. + unsigned int norm; /* video standard */
  38174. +
  38175. + struct video_capability cap; /* capabilities */
  38176. + struct video_picture pic; /* current picture settings */
  38177. + struct video_buffer buf; /* display parameters */
  38178. + struct video_capture capt; /* video capture params */
  38179. +
  38180. + struct win_info *ovl; /* overlay window set */
  38181. + struct win_info ext; /* "Extended" window info */
  38182. + struct win_info v2; /* "V2" window info */
  38183. + struct win_info x2; /* "X2" window info */
  38184. +
  38185. + unsigned int bm_offset; /* Cap memory bus master offset */
  38186. + unsigned int bm_index; /* Cap page index */
  38187. +
  38188. +#ifdef USE_MMAP
  38189. + unsigned int frame_idx; /* currently grabbing frame */
  38190. + unsigned int frame_size;
  38191. + struct framebuf frame[NR_FRAMES];
  38192. + wait_queue_head_t frame_wait;
  38193. +#endif
  38194. +
  38195. + wait_queue_head_t vbl_wait;
  38196. +
  38197. + /*
  38198. + * cyberpro registers
  38199. + */
  38200. + unsigned char cap_mode1;
  38201. + unsigned char cap_mode2;
  38202. + unsigned char cap_miscctl;
  38203. + unsigned char vfac1;
  38204. + unsigned char vfac3;
  38205. +};
  38206. +
  38207. +/*
  38208. + * Our access methods.
  38209. + */
  38210. +#define cyberpro_writel(val,reg,dp) writel(val, (dp)->regs + (reg))
  38211. +#define cyberpro_writew(val,reg,dp) writew(val, (dp)->regs + (reg))
  38212. +#define cyberpro_writeb(val,reg,dp) writeb(val, (dp)->regs + (reg))
  38213. +
  38214. +#define cyberpro_readb(reg,dp) readb((dp)->regs + (reg))
  38215. +
  38216. +static inline void
  38217. +cyberpro_grphw(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
  38218. +{
  38219. + cyberpro_writew((reg & 255) | val << 8, 0x3ce, dp);
  38220. +}
  38221. +
  38222. +static void cyberpro_grphw8(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
  38223. +{
  38224. + cyberpro_grphw(reg, val, dp);
  38225. +}
  38226. +
  38227. +static unsigned char cyberpro_grphr8(int reg, struct cyberpro_vidinfo *dp)
  38228. +{
  38229. + cyberpro_writeb(reg, 0x3ce, dp);
  38230. + return cyberpro_readb(0x3cf, dp);
  38231. +}
  38232. +
  38233. +static void cyberpro_grphw16(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
  38234. +{
  38235. + cyberpro_grphw(reg, val, dp);
  38236. + cyberpro_grphw(reg + 1, val >> 8, dp);
  38237. +}
  38238. +
  38239. +static void cyberpro_grphw24(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
  38240. +{
  38241. + cyberpro_grphw(reg, val, dp);
  38242. + cyberpro_grphw(reg + 1, val >> 8, dp);
  38243. + cyberpro_grphw(reg + 2, val >> 16, dp);
  38244. +}
  38245. +
  38246. +#if 0
  38247. +static void
  38248. +cyberpro_dbg_dump(void)
  38249. +{
  38250. + int i;
  38251. + unsigned char idx[] =
  38252. + { 0x30, 0x3e, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d,
  38253. + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad };
  38254. + printk(KERN_DEBUG);
  38255. + for (i = 0; i < sizeof(idx); i++)
  38256. + printk("%02x ", idx[i]);
  38257. + printk("\n" KERN_DEBUG);
  38258. + for (i = 0; i < sizeof(idx); i++)
  38259. + printk("%02x ", cyberpro_grphr8(idx[i]));
  38260. + printk("\n");
  38261. +}
  38262. +#endif
  38263. +
  38264. +/*
  38265. + * On the NetWinder, we can put the SAA7111 to sleep by holding
  38266. + * it in reset.
  38267. + *
  38268. + * Note: once we have initialised the SAA7111, we can't put it back to
  38269. + * sleep and expect it to keep its settings. Maybe a better solution
  38270. + * is to register/de-register the i2c bus in open/release?
  38271. + */
  38272. +static void
  38273. +decoder_sleep(int sleep)
  38274. +{
  38275. +#ifdef CONFIG_ARCH_NETWINDER
  38276. + extern spinlock_t gpio_lock;
  38277. +
  38278. + spin_lock_irq(&gpio_lock);
  38279. + cpld_modify(CPLD_7111_DISABLE, sleep ? CPLD_7111_DISABLE : 0);
  38280. + spin_unlock_irq(&gpio_lock);
  38281. +
  38282. + if (!sleep) {
  38283. + /*
  38284. + * wait 20ms for device to wake up
  38285. + */
  38286. + set_current_state(TASK_UNINTERRUPTIBLE);
  38287. + schedule_timeout(HZ / 50);
  38288. + }
  38289. +#endif
  38290. +}
  38291. +
  38292. +/* -------------------------------- I2C support ---------------------------- */
  38293. +
  38294. +#define I2C_DELAY 100
  38295. +
  38296. +static void
  38297. +cyberpro_i2c_setlines(struct i2c_bus *bus, int ctrl, int data)
  38298. +{
  38299. + struct cyberpro_vidinfo *dp = bus->data;
  38300. + int v;
  38301. +
  38302. + v = (ctrl ? EXT_LATCH2_I2C_CLKEN : 0x00) | (data ? EXT_LATCH2_I2C_DATEN : 0x00);
  38303. + cyberpro_grphw8(EXT_LATCH2, v, dp);
  38304. +
  38305. + udelay(I2C_DELAY);
  38306. +}
  38307. +
  38308. +static int
  38309. +cyberpro_i2c_getdataline(struct i2c_bus *bus)
  38310. +{
  38311. + struct cyberpro_vidinfo *dp = bus->data;
  38312. + unsigned long flags;
  38313. + int v;
  38314. +
  38315. + save_flags(flags);
  38316. + cli();
  38317. +
  38318. + v = cyberpro_grphr8(EXT_LATCH2, dp);
  38319. +
  38320. + restore_flags(flags);
  38321. +
  38322. + return v & EXT_LATCH2_I2C_DAT ? 1 : 0;
  38323. +}
  38324. +
  38325. +static void
  38326. +cyberpro_i2c_attach(struct i2c_bus *bus, int id)
  38327. +{
  38328. + struct cyberpro_vidinfo *dp = bus->data;
  38329. + int zero = 0;
  38330. +
  38331. + if (id == I2C_DRIVERID_VIDEODECODER) {
  38332. + __u16 norm = dp->norm;
  38333. + i2c_control_device(bus, id, DECODER_SET_NORM, &norm);
  38334. + i2c_control_device(bus, id, DECODER_SET_PICTURE, &dp->pic);
  38335. + i2c_control_device(bus, id, DECODER_ENABLE_OUTPUT, &zero);
  38336. +
  38337. + dp->decoder = 1;
  38338. + }
  38339. +}
  38340. +
  38341. +static void
  38342. +cyberpro_i2c_detach(struct i2c_bus *bus, int id)
  38343. +{
  38344. + struct cyberpro_vidinfo *dp = bus->data;
  38345. +
  38346. + if (id == I2C_DRIVERID_VIDEODECODER)
  38347. + dp->decoder = 0;
  38348. +}
  38349. +
  38350. +static struct i2c_bus cyberpro_i2c_bus = {
  38351. + name: "",
  38352. + id: I2C_BUSID_CYBER2000,
  38353. + bus_lock: SPIN_LOCK_UNLOCKED,
  38354. + attach_inform: cyberpro_i2c_attach,
  38355. + detach_inform: cyberpro_i2c_detach,
  38356. + i2c_setlines: cyberpro_i2c_setlines,
  38357. + i2c_getdataline: cyberpro_i2c_getdataline,
  38358. +};
  38359. +
  38360. +/*------------------------- Extended Overlay Window -------------------------
  38361. + * Initialise 1st overlay window (works)
  38362. + */
  38363. +static void
  38364. +cyberpro_ext_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38365. +{
  38366. + wi->vid_fifo_ctl = 0xf87c;
  38367. + wi->vid_fmt = EXT_VID_FMT_YUV422;
  38368. + wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
  38369. + EXT_VID_DISP_CTL1_NOCLIP;
  38370. + wi->vid_fifo_ctl1 = EXT_VID_FIFO_CTL1_INTERLEAVE |
  38371. + EXT_VID_FIFO_CTL1_OE_HIGH;
  38372. + wi->vid_misc_ctl1 = 0;
  38373. +
  38374. + cyberpro_grphw8 (EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
  38375. + cyberpro_grphw16(EXT_DDA_X_INIT, 0x0800, dp);
  38376. + cyberpro_grphw16(EXT_DDA_Y_INIT, 0x0800, dp);
  38377. + cyberpro_grphw16(EXT_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
  38378. + cyberpro_grphw8 (EXT_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
  38379. +}
  38380. +
  38381. +/*
  38382. + * Set the source parameters for the extended window
  38383. + */
  38384. +static void
  38385. +cyberpro_ext_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38386. +{
  38387. + unsigned int phase, pitch;
  38388. +
  38389. + pitch = (wi->src.width >> 2) & 0x0fff;
  38390. + phase = (wi->src.width + 3) >> 2;
  38391. +
  38392. + wi->vid_fmt &= ~7;
  38393. + switch (wi->src.format) {
  38394. + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
  38395. + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
  38396. + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
  38397. + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
  38398. + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
  38399. + }
  38400. +
  38401. + cyberpro_grphw24(EXT_MEM_START, wi->src.offset, dp);
  38402. + cyberpro_grphw16(EXT_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
  38403. + cyberpro_grphw8 (EXT_SRC_WIN_WIDTH, phase, dp);
  38404. + cyberpro_grphw8 (EXT_VID_FMT, wi->vid_fmt, dp);
  38405. +}
  38406. +
  38407. +/*
  38408. + * Set overlay1 window
  38409. + */
  38410. +static void
  38411. +cyberpro_ext_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38412. +{
  38413. + unsigned int xscale, yscale;
  38414. + unsigned int xoff, yoff;
  38415. +
  38416. + /*
  38417. + * Note: the offset does not appear to be influenced by
  38418. + * hardware scrolling.
  38419. + */
  38420. + xoff = yoff = 0;
  38421. +
  38422. + xoff += wi->dst.x;
  38423. + yoff += wi->dst.y;
  38424. +
  38425. + xscale = wi->src.width;
  38426. +
  38427. + if (wi->dst.width >= wi->src.width * 2) {
  38428. + wi->vid_fmt |= EXT_VID_FMT_DBL_H_PIX;
  38429. + xscale *= 2;
  38430. + } else {
  38431. + wi->vid_fmt &= ~EXT_VID_FMT_DBL_H_PIX;
  38432. + }
  38433. +
  38434. + xscale = ((xscale - /*2*/0) * 4096) / wi->dst.width;
  38435. + yscale = ((wi->src.height - /*2*/0) * 4096) / wi->dst.height;
  38436. +
  38437. + cyberpro_grphw16(EXT_X_START, xoff, dp);
  38438. + cyberpro_grphw16(EXT_X_END, xoff + wi->dst.width, dp);
  38439. + cyberpro_grphw16(EXT_Y_START, yoff, dp);
  38440. + cyberpro_grphw16(EXT_Y_END, yoff + wi->dst.height, dp);
  38441. + cyberpro_grphw24(EXT_COLOUR_COMPARE, wi->dst.chromakey, dp);
  38442. + cyberpro_grphw16(EXT_DDA_X_INC, xscale, dp);
  38443. + cyberpro_grphw16(EXT_DDA_Y_INC, yscale, dp);
  38444. + cyberpro_grphw8(EXT_VID_FMT, wi->vid_fmt, dp);
  38445. +
  38446. + if (wi->dst.flags & VIDEO_WINDOW_CHROMAKEY)
  38447. + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_IGNORE_CCOMP;
  38448. + else
  38449. + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_IGNORE_CCOMP;
  38450. +}
  38451. +
  38452. +/*
  38453. + * Enable or disable the 1st overlay window. Note that for anything
  38454. + * useful to be displayed, we must have capture enabled.
  38455. + */
  38456. +static void
  38457. +cyberpro_ext_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
  38458. +{
  38459. + if (on)
  38460. + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
  38461. + else
  38462. + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
  38463. +
  38464. + cyberpro_grphw8(EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
  38465. +}
  38466. +
  38467. +/*------------------------------- V2 Overlay Window -------------------------
  38468. + * Initialise 2nd overlay window (guesswork)
  38469. + */
  38470. +static void
  38471. +cyberpro_v2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38472. +{
  38473. + wi->vid_fifo_ctl = 0xf87c;
  38474. + wi->vid_fmt = EXT_VID_FMT_YUV422;
  38475. + wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
  38476. + EXT_VID_DISP_CTL1_NOCLIP;
  38477. + wi->vid_fifo_ctl1 = 0x06;
  38478. + wi->vid_misc_ctl1 = 0;
  38479. +
  38480. + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
  38481. + cyberpro_grphw8 (Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
  38482. + /* No DDA init values */
  38483. + cyberpro_grphw16(Y_V2_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
  38484. + cyberpro_grphw8 (Y_V2_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
  38485. +}
  38486. +
  38487. +/*
  38488. + * Set the source parameters for the v2 window
  38489. + */
  38490. +static void
  38491. +cyberpro_v2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38492. +{
  38493. + unsigned int phase, pitch;
  38494. +
  38495. + pitch = (wi->src.width >> 2) & 0x0fff;
  38496. + phase = (wi->src.width + 3) >> 2;
  38497. +
  38498. + wi->vid_fmt &= ~7;
  38499. + switch (wi->src.format) {
  38500. + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
  38501. + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
  38502. + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
  38503. + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
  38504. + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
  38505. + }
  38506. +
  38507. + cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
  38508. + cyberpro_grphw24(X_V2_VID_MEM_START, wi->src.offset, dp);
  38509. + cyberpro_grphw16(X_V2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
  38510. + cyberpro_grphw8 (X_V2_VID_SRC_WIN_WIDTH, phase, dp);
  38511. +
  38512. + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
  38513. + cyberpro_grphw8(Y_V2_VID_FMT, wi->vid_fmt, dp);
  38514. +}
  38515. +
  38516. +/*
  38517. + * Set v2 window
  38518. + */
  38519. +static void
  38520. +cyberpro_v2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38521. +{
  38522. + unsigned int xscale, yscale;
  38523. + unsigned int xoff, yoff;
  38524. +
  38525. + /*
  38526. + * Note: the offset does not appear to be influenced by
  38527. + * hardware scrolling.
  38528. + */
  38529. + xoff = yoff = 0;
  38530. +
  38531. + xoff += wi->dst.x;
  38532. + yoff += wi->dst.y;
  38533. +
  38534. + xscale = (wi->src.width * 4096) / wi->dst.width;
  38535. + yscale = (wi->src.height * 4096) / wi->dst.height;
  38536. +
  38537. + cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
  38538. + cyberpro_grphw16(X_V2_X_START, xoff, dp);
  38539. + cyberpro_grphw16(X_V2_X_END, xoff + wi->dst.width, dp);
  38540. + cyberpro_grphw16(X_V2_Y_START, yoff, dp);
  38541. + cyberpro_grphw16(X_V2_Y_END, yoff + wi->dst.height, dp);
  38542. +
  38543. + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
  38544. + cyberpro_grphw16(Y_V2_DDA_X_INC, xscale, dp);
  38545. + cyberpro_grphw16(Y_V2_DDA_Y_INC, yscale, dp);
  38546. +}
  38547. +
  38548. +/*
  38549. + * Enable or disable the 2nd overlay window. Note that for anything
  38550. + * useful to be displayed, we must have capture enabled.
  38551. + */
  38552. +static void
  38553. +cyberpro_v2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
  38554. +{
  38555. + if (on)
  38556. + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
  38557. + else
  38558. + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
  38559. +
  38560. + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
  38561. + cyberpro_grphw8(Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
  38562. +}
  38563. +
  38564. +/*--------------------------- X2 Overlay Window -----------------------------
  38565. + * Initialise 3rd overlay window (guesswork)
  38566. + */
  38567. +static void
  38568. +cyberpro_x2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38569. +{
  38570. + wi->vid_fmt = EXT_VID_FMT_YUV422;
  38571. + wi->vid_disp_ctl1 = 0x40;
  38572. + wi->vid_misc_ctl1 = 0;
  38573. +
  38574. + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
  38575. + cyberpro_grphw8 (K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
  38576. + cyberpro_grphw16(K_X2_DDA_X_INIT, 0x0800, dp);
  38577. + cyberpro_grphw16(K_X2_DDA_Y_INIT, 0x0800, dp);
  38578. +}
  38579. +
  38580. +/*
  38581. + * Set the source parameters for the x2 window
  38582. + */
  38583. +static void
  38584. +cyberpro_x2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38585. +{
  38586. + unsigned int phase, pitch;
  38587. +
  38588. + pitch = (wi->src.width >> 2) & 0x0fff;
  38589. + phase = (wi->src.width + 3) >> 2;
  38590. +
  38591. + wi->vid_fmt &= ~7;
  38592. + switch (wi->src.format) {
  38593. + case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
  38594. + case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
  38595. + case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
  38596. + case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
  38597. + case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
  38598. + }
  38599. +
  38600. + cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
  38601. + cyberpro_grphw24(J_X2_VID_MEM_START, wi->src.offset, dp);
  38602. + cyberpro_grphw16(J_X2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
  38603. + cyberpro_grphw8 (J_X2_VID_SRC_WIN_WIDTH, phase, dp);
  38604. +
  38605. + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
  38606. + cyberpro_grphw8(K_X2_VID_FMT, wi->vid_fmt, dp);
  38607. +}
  38608. +
  38609. +/*
  38610. + * Set x2 window
  38611. + */
  38612. +static void
  38613. +cyberpro_x2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
  38614. +{
  38615. + unsigned int xscale, yscale;
  38616. + unsigned int xoff, yoff;
  38617. +
  38618. + /*
  38619. + * Note: the offset does not appear to be influenced by
  38620. + * hardware scrolling.
  38621. + */
  38622. + xoff = yoff = 0;
  38623. +
  38624. + xoff += wi->dst.x;
  38625. + yoff += wi->dst.y;
  38626. +
  38627. + xscale = (wi->src.width * 4096) / wi->dst.width;
  38628. + yscale = (wi->src.height * 4096) / wi->dst.height;
  38629. +
  38630. + cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
  38631. + cyberpro_grphw16(J_X2_X_START, xoff, dp);
  38632. + cyberpro_grphw16(J_X2_X_END, xoff + wi->dst.width, dp);
  38633. + cyberpro_grphw16(J_X2_Y_START, yoff, dp);
  38634. + cyberpro_grphw16(J_X2_Y_END, yoff + wi->dst.height, dp);
  38635. +
  38636. + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
  38637. + cyberpro_grphw16(K_X2_DDA_X_INC, xscale, dp);
  38638. + cyberpro_grphw16(K_X2_DDA_Y_INC, yscale, dp);
  38639. +}
  38640. +
  38641. +/*
  38642. + * Enable or disable the 3rd overlay window. Note that for anything
  38643. + * useful to be displayed, we must have capture enabled.
  38644. + */
  38645. +static void
  38646. +cyberpro_x2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
  38647. +{
  38648. + if (on)
  38649. + wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
  38650. + else
  38651. + wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
  38652. +
  38653. + cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
  38654. + cyberpro_grphw8(K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
  38655. +}
  38656. +
  38657. +/* ------------------------------------------------------------------------- */
  38658. +
  38659. +#if 0
  38660. +static void reset_seq(struct cyberpro_vidinfo *dp)
  38661. +{
  38662. + unsigned char ext_mem_ctl = cyberpro_grphr8(0x70, dp);
  38663. +
  38664. + cyberpro_grphw8(ext_mem_ctl | 0x80, 0x70, dp);
  38665. + cyberpro_grphw8(ext_mem_ctl, 0x70, dp);
  38666. +}
  38667. +#endif
  38668. +
  38669. +#ifdef USE_MMAP
  38670. +/*
  38671. + * Buffer support
  38672. + */
  38673. +static int
  38674. +cyberpro_alloc_frame_buffer(struct cyberpro_vidinfo *dp,
  38675. + struct framebuf *frame)
  38676. +{
  38677. + unsigned long addr;
  38678. + void *buffer;
  38679. + int pgidx;
  38680. +
  38681. + if (frame->buffer)
  38682. + return 0;
  38683. +
  38684. + /*
  38685. + * Allocate frame buffer
  38686. + */
  38687. + buffer = vmalloc(NR_PAGES * PAGE_SIZE);
  38688. +
  38689. + if (frame->buffer) {
  38690. + vfree(buffer);
  38691. + return 0;
  38692. + }
  38693. +
  38694. + if (!buffer)
  38695. + return -ENOMEM;
  38696. +
  38697. + printk("Buffer allocated @ %p [", buffer);
  38698. +
  38699. + frame->buffer = buffer;
  38700. + frame->dbg = 1;
  38701. +
  38702. + /*
  38703. + * Don't leak information from the kernel.
  38704. + */
  38705. + memset(buffer, 0x5a, NR_PAGES * PAGE_SIZE);
  38706. +
  38707. + /*
  38708. + * Now, reserve all the pages, and calculate
  38709. + * each pages' bus address.
  38710. + */
  38711. + addr = (unsigned long)buffer;
  38712. + for (pgidx = 0; pgidx < NR_PAGES; pgidx++, addr += PAGE_SIZE) {
  38713. + struct page *page;
  38714. + pgd_t *pgd;
  38715. + pmd_t *pmd;
  38716. + pte_t *pte;
  38717. +
  38718. + /*
  38719. + * The page should be present. If not,
  38720. + * vmalloc has gone nuts.
  38721. + */
  38722. + pgd = pgd_offset_k(addr);
  38723. + if (pgd_none(*pgd))
  38724. + BUG();
  38725. + pmd = pmd_offset(pgd, addr);
  38726. + if (pmd_none(*pmd))
  38727. + BUG();
  38728. + pte = pte_offset(pmd, addr);
  38729. + if (!pte_present(*pte))
  38730. + BUG();
  38731. +
  38732. + page = pte_page(*pte);
  38733. +
  38734. + frame->bus_addr[pgidx] = virt_to_bus((void *)page_address(page));
  38735. + frame->pages[pgidx] = page;
  38736. + SetPageReserved(page);
  38737. +
  38738. + printk("%08lx (%08lx) ", page_address(page), frame->bus_addr[pgidx]);
  38739. + }
  38740. + printk("\n");
  38741. +
  38742. + return 0;
  38743. +}
  38744. +
  38745. +static void
  38746. +cyberpro_frames_free_one(struct cyberpro_vidinfo *dp, struct framebuf *frame)
  38747. +{
  38748. + void *buffer;
  38749. + int pgidx;
  38750. +
  38751. + frame->status = FRAME_FREE;
  38752. + buffer = frame->buffer;
  38753. + frame->buffer = NULL;
  38754. +
  38755. + if (buffer) {
  38756. + for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
  38757. + frame->bus_addr[pgidx] = 0;
  38758. + ClearPageReserved(frame->pages[pgidx]);
  38759. + frame->pages[pgidx] = NULL;
  38760. + }
  38761. + vfree(buffer);
  38762. + }
  38763. +}
  38764. +
  38765. +static void
  38766. +cyberpro_busmaster_frame(struct cyberpro_vidinfo *dp, struct framebuf *frame)
  38767. +{
  38768. + unsigned long bus_addr;
  38769. +
  38770. + bus_addr = frame->bus_addr[dp->bm_index];
  38771. +
  38772. + if (frame->dbg) {
  38773. + printk("Frame%d: %06x -> %08lx\n",
  38774. + dp->frame_idx,
  38775. + dp->bm_offset,
  38776. + bus_addr);
  38777. + }
  38778. +
  38779. + cyber2000_outw(dp->bm_offset, BM_VID_ADDR_LOW);
  38780. + cyber2000_outw(dp->bm_offset >> 16, BM_VID_ADDR_HIGH);
  38781. +
  38782. + cyber2000_outw(bus_addr, BM_ADDRESS_LOW);
  38783. + cyber2000_outw(bus_addr >> 16, BM_ADDRESS_HIGH);
  38784. +
  38785. + /*
  38786. + * One page-full only
  38787. + */
  38788. + cyber2000_outw(1023, BM_LENGTH);
  38789. +
  38790. + /*
  38791. + * Load length
  38792. + */
  38793. + cyber2000_outw(BM_CONTROL_INIT, BM_CONTROL);
  38794. +
  38795. + /*
  38796. + * Enable transfer
  38797. + */
  38798. + cyber2000_outw(BM_CONTROL_ENABLE|BM_CONTROL_IRQEN, BM_CONTROL);
  38799. +
  38800. + dp->bm_offset += 1024;
  38801. + dp->bm_index += 1;
  38802. +}
  38803. +
  38804. +static void cyberpro_busmaster_interrupt(struct cyberpro_vidinfo *dp)
  38805. +{
  38806. + struct framebuf *frame = dp->frame + dp->frame_idx;
  38807. +
  38808. + /*
  38809. + * Disable Busmaster operations
  38810. + */
  38811. + cyber2000_outw(0, BM_CONTROL);
  38812. +
  38813. + if (frame->status == FRAME_GRABBING) {
  38814. + /*
  38815. + * We are still grabbing this frame to system
  38816. + * memory. Transfer next page if there are
  38817. + * more, or else flag this frame as complete.
  38818. + */
  38819. + if (dp->bm_index < NR_PAGES)
  38820. + cyberpro_busmaster_frame(dp);
  38821. + else {
  38822. + unsigned int idx;
  38823. +
  38824. + frame->status = FRAME_DONE;
  38825. + frame->dbg = 0;
  38826. +
  38827. + idx = dp->frame_idx + 1;
  38828. + if (idx >= NR_FRAMES)
  38829. + idx = 0;
  38830. +
  38831. + dp->frame_idx = idx;
  38832. +
  38833. + wake_up(&dp->frame_wait);
  38834. + }
  38835. + }
  38836. +}
  38837. +
  38838. +static void cyberpro_frames_vbl(struct cyberpro_vidinfo *dp, unsigned int stat)
  38839. +{
  38840. + struct framebuf *frame = dp->frame + dp->frame_idx;
  38841. +
  38842. + /*
  38843. + * No point capturing frames if the grabber isn't active.
  38844. + */
  38845. + if (stat & EXT_ROM_UCB4GH_FREEZE)
  38846. + return;
  38847. +
  38848. + /*
  38849. + * If the next buffer is ready for grabbing,
  38850. + * set up the bus master registers for the
  38851. + * transfer.
  38852. + */
  38853. + if (frame->status == FRAME_WAITING) {
  38854. + frame->status = FRAME_GRABBING;
  38855. +
  38856. + dp->bm_offset = dp->cap_mem_offset;
  38857. + dp->bm_index = 0;
  38858. +
  38859. + cyberpro_busmaster_frame(dp, frame);
  38860. + }
  38861. +}
  38862. +
  38863. +static void __init cyberpro_frames_init(struct cyberpro_vidinfo *dp)
  38864. +{
  38865. + unsigned int offset, maxsize;
  38866. + int i;
  38867. +
  38868. + init_waitqueue_head(&dp->frame_wait);
  38869. +
  38870. + maxsize = 2 * dp->cap.maxwidth * dp->cap.maxheight;
  38871. + dp->frame_size = PAGE_ALIGN(maxsize);
  38872. + dp->frame_idx = 0;
  38873. +
  38874. + for (i = offset = 0; i < NR_FRAMES; i++) {
  38875. + dp->frame[i].offset = offset;
  38876. + dp->frame[i].status = FRAME_FREE;
  38877. + offset += dp->frame_size;
  38878. + }
  38879. +}
  38880. +
  38881. +static void cyberpro_frames_free(struct cyberpro_vidinfo *dp)
  38882. +{
  38883. + int i;
  38884. +
  38885. + dp->mmaped = 0;
  38886. +
  38887. + /*
  38888. + * Free all frame buffers
  38889. + */
  38890. + for (i = 0; i < NR_FRAMES; i++)
  38891. + cyberpro_frames_free_one(dp, dp->frame + i);
  38892. +}
  38893. +
  38894. +#else
  38895. +#define cyberpro_frames_vbl(dp,stat) do { } while (0)
  38896. +#define cyberpro_frames_init(dp) do { } while (0)
  38897. +#define cyberpro_frames_free(dp) do { } while (0)
  38898. +#endif
  38899. +
  38900. +/*
  38901. + * CyberPro Interrupts
  38902. + * -------------------
  38903. + *
  38904. + * We don't really know how to signal an IRQ clear to the chip. However,
  38905. + * disabling and re-enabling the capture interrupt enable seems to do what
  38906. + * we want.
  38907. + */
  38908. +static void cyberpro_interrupt(int nr, void *dev_id, struct pt_regs *regs)
  38909. +{
  38910. + struct cyberpro_vidinfo *dp = dev_id;
  38911. + unsigned char old_grphidx;
  38912. + unsigned int status;
  38913. +
  38914. + /*
  38915. + * Save old graphics index register
  38916. + */
  38917. + old_grphidx = cyberpro_readb(0x3ce, dp);
  38918. +
  38919. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  38920. +
  38921. + /*
  38922. + * Was it due to the Capture VSYNC?
  38923. + */
  38924. + if (status & EXT_ROM_UCB4GH_INTSTAT) {
  38925. + /*
  38926. + * Frob the IRQ enable bit to drop the request.
  38927. + */
  38928. + cyberpro_grphw8(VFAC_CTL3, dp->vfac3 & ~VFAC_CTL3_CAP_IRQ, dp);
  38929. + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
  38930. +
  38931. + cyberpro_frames_vbl(dp, status);
  38932. + wake_up(&dp->vbl_wait);
  38933. + }
  38934. +
  38935. + /*
  38936. + * Restore graphics controller index
  38937. + */
  38938. + cyberpro_writeb(old_grphidx, 0x3ce, dp);
  38939. +
  38940. +#ifdef USE_MMAP
  38941. + /*
  38942. + * Do Bus-Master IRQ stuff
  38943. + */
  38944. + if (cyber2000_inb(BM_CONTROL) & (1 << 7))
  38945. + cyberpro_busmaster_interrupt(dp);
  38946. +#endif
  38947. +}
  38948. +
  38949. +static void cyberpro_capture(struct cyberpro_vidinfo *dp, int on)
  38950. +{
  38951. + DECLARE_WAITQUEUE(wait, current);
  38952. + unsigned int status;
  38953. +
  38954. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  38955. +
  38956. + add_wait_queue(&dp->vbl_wait, &wait);
  38957. + set_current_state(TASK_UNINTERRUPTIBLE);
  38958. +
  38959. + if (!!on ^ !(status & EXT_ROM_UCB4GH_FREEZE)) {
  38960. + if (on) {
  38961. + schedule_timeout(40 * HZ / 1000);
  38962. + dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
  38963. + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
  38964. +
  38965. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  38966. + } else {
  38967. + dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
  38968. + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
  38969. +
  38970. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  38971. + if (!(status & EXT_ROM_UCB4GH_FREEZE))
  38972. + schedule_timeout(40 * HZ / 1000);
  38973. + }
  38974. + }
  38975. +
  38976. + current->state = TASK_RUNNING;
  38977. + remove_wait_queue(&dp->vbl_wait, &wait);
  38978. +}
  38979. +
  38980. +static void cyberpro_capture_one(struct cyberpro_vidinfo *dp)
  38981. +{
  38982. + struct task_struct *tsk = current;
  38983. + DECLARE_WAITQUEUE(wait, tsk);
  38984. + unsigned int status;
  38985. + unsigned long policy, rt_priority;
  38986. +
  38987. + policy = tsk->policy;
  38988. + rt_priority = tsk->rt_priority;
  38989. +
  38990. + tsk->policy = SCHED_FIFO;
  38991. + tsk->rt_priority = 1;
  38992. +
  38993. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  38994. +
  38995. + add_wait_queue(&dp->vbl_wait, &wait);
  38996. + set_current_state(TASK_UNINTERRUPTIBLE);
  38997. +
  38998. + schedule_timeout(40 * HZ / 1000);
  38999. + dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
  39000. + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
  39001. +
  39002. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  39003. + set_current_state(TASK_UNINTERRUPTIBLE);
  39004. + schedule_timeout(40 * HZ / 1000);
  39005. + set_current_state(TASK_UNINTERRUPTIBLE);
  39006. + schedule_timeout(40 * HZ / 1000);
  39007. +
  39008. + dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
  39009. + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
  39010. +
  39011. + set_current_state(TASK_UNINTERRUPTIBLE);
  39012. + status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
  39013. +
  39014. + current->state = TASK_RUNNING;
  39015. + remove_wait_queue(&dp->vbl_wait, &wait);
  39016. +
  39017. + tsk->policy = policy;
  39018. + tsk->rt_priority = rt_priority;
  39019. +}
  39020. +
  39021. +static void cyberpro_capture_set_win(struct cyberpro_vidinfo *dp)
  39022. +{
  39023. + unsigned int xstart, xend, ystart, yend;
  39024. +
  39025. + xstart = 4 + dp->capt.x;
  39026. + xend = xstart + dp->capt.width;
  39027. +
  39028. + if (dp->cap_mode1 & EXT_CAP_MODE1_8BIT) {
  39029. + /* 8-bit capture */
  39030. + xstart *= 2;
  39031. + xend *= 2;
  39032. + }
  39033. +
  39034. + xstart -= 1;
  39035. + xend -= 1;
  39036. +
  39037. + ystart = 18 + dp->capt.y;
  39038. + yend = ystart + dp->capt.height / 2;
  39039. +
  39040. + cyberpro_grphw16(CAP_X_START, xstart, dp);
  39041. + cyberpro_grphw16(CAP_X_END, xend + 1, dp);
  39042. + cyberpro_grphw16(CAP_Y_START, ystart, dp);
  39043. + cyberpro_grphw16(CAP_Y_END, yend + 2, dp);
  39044. +
  39045. + /*
  39046. + * This should take account of capt.decimation
  39047. + */
  39048. + cyberpro_grphw16(CAP_DDA_X_INIT, 0x0800, dp);
  39049. + cyberpro_grphw16(CAP_DDA_X_INC, 0x1000, dp);
  39050. + cyberpro_grphw16(CAP_DDA_Y_INIT, 0x0800, dp);
  39051. + cyberpro_grphw16(CAP_DDA_Y_INC, 0x1000, dp);
  39052. +
  39053. + cyberpro_grphw8(CAP_PITCH, dp->capt.width >> 2, dp);
  39054. +}
  39055. +
  39056. +static void cyberpro_set_interlace(struct cyberpro_vidinfo *dp)
  39057. +{
  39058. + /*
  39059. + * set interlace mode
  39060. + */
  39061. + if (dp->interlace) {
  39062. + dp->vfac3 |= VFAC_CTL3_CAP_INTERLACE;
  39063. + dp->cap_miscctl &= ~CAP_CTL_MISC_ODDEVEN;
  39064. + dp->ovl->src.height = dp->capt.height;
  39065. + } else {
  39066. + dp->vfac3 &= ~VFAC_CTL3_CAP_INTERLACE;
  39067. + dp->cap_miscctl |= CAP_CTL_MISC_ODDEVEN;
  39068. + dp->ovl->src.height = dp->capt.height / 2;
  39069. + }
  39070. +
  39071. + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
  39072. + cyberpro_grphw8(CAP_CTL_MISC, dp->cap_miscctl, dp);
  39073. +
  39074. + dp->ovl->set_src(dp, dp->ovl);
  39075. +
  39076. + if (dp->win_set)
  39077. + dp->ovl->set_win(dp, dp->ovl);
  39078. +}
  39079. +
  39080. +/*
  39081. + * Calculate and set the address of the capture buffer. Note we
  39082. + * also update the extended memory buffer for the overlay window.
  39083. + *
  39084. + * base: phys base address of display
  39085. + * width: pixel width of display
  39086. + * height: height of display
  39087. + * depth: depth of display (8/16/24)
  39088. + * bytesperline: number of bytes on a line
  39089. + *
  39090. + * We place the capture buffer 16K after the screen.
  39091. + */
  39092. +static int
  39093. +cyberpro_set_buffer(struct cyberpro_vidinfo *dp, struct video_buffer *b)
  39094. +{
  39095. + unsigned long screensize, maxbufsz;
  39096. +
  39097. + if (b->height <= 0 || b->width <= 0 || b->bytesperline <= 0)
  39098. + return -EINVAL;
  39099. +
  39100. + maxbufsz = dp->cap.maxwidth * dp->cap.maxheight * 2;
  39101. + screensize = b->height * b->bytesperline + 16384;
  39102. +
  39103. + if ((screensize + maxbufsz) >= dp->info.fb_size)
  39104. + return -EINVAL;
  39105. +
  39106. + dp->buf.base = b->base;
  39107. + dp->buf.width = b->width;
  39108. + dp->buf.height = b->height;
  39109. + dp->buf.depth = b->depth;
  39110. + dp->buf.bytesperline = b->bytesperline;
  39111. + dp->cap_mem_offset = screensize >> 2;
  39112. +
  39113. + cyberpro_grphw24(CAP_MEM_START, dp->cap_mem_offset, dp);
  39114. +
  39115. + /*
  39116. + * Setup the overlay source information.
  39117. + */
  39118. + dp->ovl->src.offset = dp->cap_mem_offset;
  39119. + dp->ovl->set_src(dp, dp->ovl);
  39120. +
  39121. + return 0;
  39122. +}
  39123. +
  39124. +static void cyberpro_hw_init(struct cyberpro_vidinfo *dp)
  39125. +{
  39126. + unsigned char old;
  39127. +
  39128. + /*
  39129. + * Enable access to bus-master registers
  39130. + */
  39131. + dp->info.enable_extregs(dp->info.info);
  39132. +
  39133. + dp->vfac1 = VFAC_CTL1_PHILIPS |
  39134. + VFAC_CTL1_FREEZE_CAPTURE |
  39135. + VFAC_CTL1_FREEZE_CAPTURE_SYNC;
  39136. + dp->vfac3 = VFAC_CTL3_CAP_IRQ;
  39137. +
  39138. + dp->cap_miscctl = CAP_CTL_MISC_DISPUSED |
  39139. + CAP_CTL_MISC_SYNCTZOR |
  39140. + CAP_CTL_MISC_SYNCTZHIGH;
  39141. +
  39142. + /*
  39143. + * Setup bus-master mode
  39144. + */
  39145. + cyberpro_grphw8(BM_CTRL1, 0x88, dp);
  39146. + cyberpro_grphw8(PCI_BM_CTL, PCI_BM_CTL_ENABLE, dp);
  39147. + cyberpro_grphw8(BM_CTRL0, 0x44, dp);
  39148. + cyberpro_grphw8(BM_CTRL1, 0x84, dp);
  39149. +
  39150. + cyberpro_grphw24(CAP_MEM_START, 0, dp);
  39151. +
  39152. + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
  39153. + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
  39154. + cyberpro_grphw8(VFAC_CTL2, 0, dp);
  39155. +
  39156. + cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
  39157. + cyberpro_grphw8(EXT_TV_CTL, 0x80, dp);
  39158. +
  39159. + cyberpro_grphw8(EXT_CAP_CTL1, 0x3f, dp); /* disable PIP */
  39160. + cyberpro_grphw8(EXT_CAP_CTL2, 0xc0 | EXT_CAP_CTL2_ODDFRAMEIRQ, dp);
  39161. +
  39162. + /*
  39163. + * Configure capture mode to match the
  39164. + * external video processor format
  39165. + */
  39166. + cyberpro_grphw8(EXT_CAP_MODE1, dp->cap_mode1, dp);
  39167. + cyberpro_grphw8(EXT_CAP_MODE2, dp->cap_mode2, dp);
  39168. +
  39169. + /* setup overlay */
  39170. + cyberpro_grphw16(EXT_FIFO_CTL, 0x1010, dp);
  39171. +// cyberpro_grphw16(EXT_FIFO_CTL, 0x1b0f, dp);
  39172. +
  39173. + /*
  39174. + * Always reset the capture parameters on each open.
  39175. + */
  39176. + dp->capt.x = 0;
  39177. + dp->capt.y = 0;
  39178. + dp->capt.width = dp->cap.maxwidth;
  39179. + dp->capt.height = dp->cap.maxheight;
  39180. + dp->capt.decimation = 0;
  39181. + dp->capt.flags = 0;
  39182. +
  39183. + cyberpro_capture_set_win(dp);
  39184. +
  39185. + /*
  39186. + * Enable VAFC
  39187. + */
  39188. + old = cyberpro_grphr8(EXT_LATCH1, dp);
  39189. + cyberpro_grphw8(EXT_LATCH1, old | EXT_LATCH1_VAFC_EN, dp);
  39190. +
  39191. + /*
  39192. + * Enable capture (we hope that VSYNC=1)
  39193. + */
  39194. + dp->vfac1 |= VFAC_CTL1_CAPTURE;
  39195. + cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
  39196. +
  39197. + /*
  39198. + * The overlay source format is always the
  39199. + * same as the capture stream format.
  39200. + */
  39201. + dp->ovl->src.width = dp->capt.width;
  39202. + dp->ovl->src.height = dp->capt.height;
  39203. + dp->ovl->src.format = dp->stream_fmt;
  39204. +
  39205. + /*
  39206. + * Initialise the overlay windows
  39207. + */
  39208. + dp->ext.init(dp, &dp->ext);
  39209. + dp->v2.init(dp, &dp->v2);
  39210. + dp->x2.init(dp, &dp->x2);
  39211. +}
  39212. +
  39213. +static void cyberpro_deinit(struct cyberpro_vidinfo *dp)
  39214. +{
  39215. + unsigned char old;
  39216. +
  39217. + /*
  39218. + * Stop any bus-master activity
  39219. + */
  39220. + cyberpro_writew(0, BM_CONTROL, dp);
  39221. +
  39222. + /*
  39223. + * Shut down overlay
  39224. + */
  39225. + if (dp->ovl_active)
  39226. + dp->ovl->ctl(dp, dp->ovl, 0);
  39227. + dp->ovl_active = 0;
  39228. +
  39229. + /*
  39230. + * Shut down capture
  39231. + */
  39232. + if (dp->cap_active)
  39233. + cyberpro_capture(dp, 0);
  39234. + dp->cap_active = 0;
  39235. +
  39236. + /*
  39237. + * Disable all capture
  39238. + */
  39239. + cyberpro_grphw8(VFAC_CTL1, 0, dp);
  39240. +
  39241. + /*
  39242. + * Disable VAFC
  39243. + */
  39244. + old = cyberpro_grphr8(EXT_LATCH1, dp);
  39245. + cyberpro_grphw8(EXT_LATCH1, old & ~EXT_LATCH1_VAFC_EN, dp);
  39246. +
  39247. + /*
  39248. + * Disable interrupt (this allows it to float)
  39249. + */
  39250. + dp->vfac3 &= ~VFAC_CTL3_CAP_IRQ;
  39251. + cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
  39252. +
  39253. + /*
  39254. + * Switch off bus-master mode
  39255. + */
  39256. + cyberpro_grphw8(PCI_BM_CTL, 0, dp);
  39257. +
  39258. + /*
  39259. + * Disable access to bus-master registers
  39260. + */
  39261. + dp->info.disable_extregs(dp->info.info);
  39262. +}
  39263. +
  39264. +static int cyberpro_grabber_open(struct video_device *dev, int flags)
  39265. +{
  39266. + struct cyberpro_vidinfo *dp = dev->priv;
  39267. + int ret, one = 1;
  39268. +
  39269. + MOD_INC_USE_COUNT;
  39270. +
  39271. + ret = -EBUSY;
  39272. + if (flags || dp->users)
  39273. + goto out;
  39274. +
  39275. + dp->users += 1;
  39276. +
  39277. + if (dp->users == 1) {
  39278. + ret = request_irq(dp->irq, cyberpro_interrupt, SA_SHIRQ,
  39279. + dp->info.dev_name, dp);
  39280. +
  39281. + if (ret) {
  39282. + dp->users -= 1;
  39283. + goto out;
  39284. + }
  39285. +
  39286. + /*
  39287. + * Initialise the VGA chip
  39288. + */
  39289. + cyberpro_hw_init(dp);
  39290. +
  39291. + /*
  39292. + * Enable the IRQ. This allows the IRQ to work as expected
  39293. + * even if the IRQ line is missing the pull-up resistor.
  39294. + */
  39295. + enable_irq(dp->irq);
  39296. +
  39297. + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
  39298. + DECODER_ENABLE_OUTPUT, &one);
  39299. + }
  39300. +
  39301. + ret = 0;
  39302. +out:
  39303. + if (ret)
  39304. + MOD_DEC_USE_COUNT;
  39305. + return ret;
  39306. +}
  39307. +
  39308. +static void cyberpro_grabber_close(struct video_device *dev)
  39309. +{
  39310. + struct cyberpro_vidinfo *dp = dev->priv;
  39311. +
  39312. + if (dp->users == 1) {
  39313. + int zero = 0;
  39314. +
  39315. + /*
  39316. + * Disable the IRQ. This prevents problems with missing
  39317. + * pull-up resistors on the PCI interrupt line.
  39318. + */
  39319. + disable_irq(dp->irq);
  39320. +
  39321. + cyberpro_frames_free(dp);
  39322. +
  39323. + /*
  39324. + * Turn off the SAA7111 decoder
  39325. + */
  39326. + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
  39327. + DECODER_ENABLE_OUTPUT, &zero);
  39328. +
  39329. + /*
  39330. + * Disable grabber
  39331. + */
  39332. + cyberpro_deinit(dp);
  39333. +
  39334. + free_irq(dp->irq, dp);
  39335. + }
  39336. +
  39337. + dp->users -= 1;
  39338. +
  39339. + MOD_DEC_USE_COUNT;
  39340. +}
  39341. +
  39342. +/*
  39343. + * Our general plan here is:
  39344. + * 1. Set the CyberPro to perform a BM-DMA of one frame to this memory
  39345. + * 2. Copy the frame to the userspace
  39346. + *
  39347. + * However, BM-DMA seems to be unreliable at the moment, especially on
  39348. + * rev. 4 NetWinders.
  39349. + */
  39350. +static long
  39351. +cyberpro_grabber_read(struct video_device *dev, char *buf,
  39352. + unsigned long count, int noblock)
  39353. +{
  39354. + struct cyberpro_vidinfo *dp = dev->priv;
  39355. + int ret = -EINVAL;
  39356. +
  39357. +#ifdef USE_MMIO
  39358. + unsigned long maxbufsz = dp->capt.width * dp->capt.height * 2;
  39359. + char *disp = dp->info.fb + (dp->cap_mem_offset << 2);
  39360. +
  39361. + /*
  39362. + * If the buffer is mmap()'d, we shouldn't be using read()
  39363. + */
  39364. + if (dp->mmaped)
  39365. + return -EINVAL;
  39366. +
  39367. + if (count > maxbufsz)
  39368. + count = maxbufsz;
  39369. +
  39370. + if (dp->cap_active)
  39371. + cyberpro_capture(dp, 0);
  39372. + else
  39373. + cyberpro_capture_one(dp);
  39374. +
  39375. + ret = (int)count;
  39376. + if (copy_to_user(buf, disp, count))
  39377. + ret = -EFAULT;
  39378. +
  39379. + /*
  39380. + * unfreeze capture
  39381. + */
  39382. + if (dp->cap_active)
  39383. + cyberpro_capture(dp, 1);
  39384. +#endif
  39385. +
  39386. + return ret;
  39387. +}
  39388. +
  39389. +/*
  39390. + * We don't support writing to the grabber
  39391. + * (In theory, we could allow writing to a separate region of VGA memory,
  39392. + * and display this using the second overlay window. This would allow us
  39393. + * to do video conferencing for example).
  39394. + */
  39395. +static long
  39396. +cyberpro_grabber_write(struct video_device *dev, const char *buf,
  39397. + unsigned long count, int noblock)
  39398. +{
  39399. + return -EINVAL;
  39400. +}
  39401. +
  39402. +static int
  39403. +cyberpro_grabber_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
  39404. +{
  39405. + struct cyberpro_vidinfo *dp = dev->priv;
  39406. +
  39407. + switch (cmd) {
  39408. + case VIDIOCGCAP:
  39409. + return copy_to_user(arg, &dp->cap, sizeof(dp->cap))
  39410. + ? -EFAULT : 0;
  39411. +
  39412. + case VIDIOCGCHAN:
  39413. + {
  39414. + struct video_channel chan;
  39415. +
  39416. + chan.channel = 0;
  39417. + strcpy(chan.name, "Composite");
  39418. + chan.tuners = 0;
  39419. + chan.flags = 0;
  39420. + chan.type = VIDEO_TYPE_CAMERA;
  39421. + chan.norm = dp->norm;
  39422. +
  39423. + return copy_to_user(arg, &chan, sizeof(chan)) ? -EFAULT : 0;
  39424. + }
  39425. +
  39426. + case VIDIOCGPICT:
  39427. + return copy_to_user(arg, &dp->pic, sizeof(dp->pic))
  39428. + ? -EINVAL : 0;
  39429. +
  39430. + case VIDIOCGWIN:
  39431. + {
  39432. + struct video_window win;
  39433. +
  39434. + win.x = dp->ovl->dst.x;
  39435. + win.y = dp->ovl->dst.y;
  39436. + win.width = dp->ovl->dst.width;
  39437. + win.height = dp->ovl->dst.height;
  39438. + win.chromakey = dp->ovl->dst.chromakey;
  39439. + win.flags = VIDEO_WINDOW_CHROMAKEY |
  39440. + (dp->interlace ? VIDEO_WINDOW_INTERLACE : 0);
  39441. + win.clips = NULL;
  39442. + win.clipcount = 0;
  39443. +
  39444. + return copy_to_user(arg, &win, sizeof(win))
  39445. + ? -EINVAL : 0;
  39446. + }
  39447. +
  39448. + case VIDIOCGFBUF:
  39449. + return copy_to_user(arg, &dp->buf, sizeof(dp->buf))
  39450. + ? -EINVAL : 0;
  39451. +
  39452. + case VIDIOCGUNIT:
  39453. + {
  39454. + struct video_unit unit;
  39455. +
  39456. + unit.video = dev->minor;
  39457. + unit.vbi = VIDEO_NO_UNIT;
  39458. + unit.radio = VIDEO_NO_UNIT;
  39459. + unit.audio = VIDEO_NO_UNIT;
  39460. + unit.teletext = VIDEO_NO_UNIT;
  39461. +
  39462. + return copy_to_user(arg, &unit, sizeof(unit))
  39463. + ? -EINVAL : 0;
  39464. + }
  39465. +
  39466. + case VIDIOCGCAPTURE:
  39467. + return copy_to_user(arg, &dp->capt, sizeof(dp->capt))
  39468. + ? -EFAULT : 0;
  39469. +
  39470. + case VIDIOCSCHAN:
  39471. + {
  39472. + struct video_decoder_capability vdc;
  39473. + struct video_channel v;
  39474. + int ok;
  39475. +
  39476. + if (copy_from_user(&v, arg, sizeof(v)))
  39477. + return -EFAULT;
  39478. +
  39479. + if (v.channel != 0)
  39480. + return -EINVAL;
  39481. +
  39482. + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
  39483. + DECODER_GET_CAPABILITIES, &vdc);
  39484. +
  39485. + switch (v.norm) {
  39486. + case VIDEO_MODE_PAL:
  39487. + ok = vdc.flags & VIDEO_DECODER_PAL;
  39488. + break;
  39489. + case VIDEO_MODE_NTSC:
  39490. + ok = vdc.flags & VIDEO_DECODER_NTSC;
  39491. + break;
  39492. + case VIDEO_MODE_AUTO:
  39493. + ok = vdc.flags & VIDEO_DECODER_AUTO;
  39494. + break;
  39495. + default:
  39496. + ok = 0;
  39497. + }
  39498. + if (!ok)
  39499. + return -EINVAL;
  39500. +
  39501. + dp->norm = v.norm;
  39502. +
  39503. + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
  39504. + DECODER_SET_NORM, &v.norm);
  39505. +
  39506. + return 0;
  39507. + }
  39508. +
  39509. + case VIDIOCSPICT:
  39510. + {
  39511. + struct video_picture p;
  39512. +
  39513. + if (copy_from_user(&p, arg, sizeof(p)))
  39514. + return -EFAULT;
  39515. +
  39516. + if (p.palette != dp->stream_fmt ||
  39517. + p.depth != 8)
  39518. + return -EINVAL;
  39519. +
  39520. + dp->pic = p;
  39521. +
  39522. + /* p.depth sets the capture depth */
  39523. + /* p.palette sets the capture palette */
  39524. +
  39525. + i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
  39526. + DECODER_SET_PICTURE, &p);
  39527. +
  39528. + return 0;
  39529. + }
  39530. +
  39531. + case VIDIOCSWIN: /* set the size & position of the overlay window */
  39532. + {
  39533. + struct video_window w;
  39534. + int diff;
  39535. +
  39536. + if (!dp->buf_set)
  39537. + return -EINVAL;
  39538. +
  39539. + if (copy_from_user(&w, arg, sizeof(w)))
  39540. + return -EFAULT;
  39541. +
  39542. + if (w.clipcount)
  39543. + return -EINVAL;
  39544. +
  39545. + /*
  39546. + * Bound the overlay window by the size of the screen
  39547. + */
  39548. + if (w.x < 0)
  39549. + w.x = 0;
  39550. + if (w.y < 0)
  39551. + w.y = 0;
  39552. +
  39553. + if (w.x > dp->buf.width)
  39554. + w.x = dp->buf.width;
  39555. + if (w.y > dp->buf.height)
  39556. + w.y = dp->buf.height;
  39557. +
  39558. + if (w.width < dp->capt.width)
  39559. + w.width = dp->capt.width;
  39560. + if (w.height < dp->capt.height)
  39561. + w.height = dp->capt.height;
  39562. +
  39563. + if (w.x + w.width > dp->buf.width)
  39564. + w.width = dp->buf.width - w.x;
  39565. + if (w.y + w.height > dp->buf.height)
  39566. + w.height = dp->buf.height - w.y;
  39567. +
  39568. + /*
  39569. + * We've tried to make the values fit, but
  39570. + * they just won't.
  39571. + */
  39572. + if (w.width < dp->capt.width || w.height < dp->capt.height)
  39573. + return -EINVAL;
  39574. +
  39575. + diff = dp->ovl->dst.x != w.x ||
  39576. + dp->ovl->dst.y != w.y ||
  39577. + dp->ovl->dst.width != w.width ||
  39578. + dp->ovl->dst.height != w.height ||
  39579. + dp->ovl->dst.chromakey != w.chromakey ||
  39580. + dp->ovl->dst.flags != w.flags;
  39581. +
  39582. + if (!dp->win_set || diff) {
  39583. + dp->ovl->dst.x = w.x;
  39584. + dp->ovl->dst.y = w.y;
  39585. + dp->ovl->dst.width = w.width;
  39586. + dp->ovl->dst.height = w.height;
  39587. + dp->ovl->dst.chromakey = w.chromakey;
  39588. + dp->ovl->dst.flags = w.flags;
  39589. +
  39590. + if (dp->ovl_active)
  39591. + dp->ovl->ctl(dp, dp->ovl, 0);
  39592. +
  39593. + dp->ovl->set_win(dp, dp->ovl);
  39594. +
  39595. + if (dp->ovl_active)
  39596. + dp->ovl->ctl(dp, dp->ovl, 1);
  39597. +
  39598. + diff = w.flags & VIDEO_WINDOW_INTERLACE ? 1 : 0;
  39599. + if (!dp->win_set || dp->interlace != diff) {
  39600. + dp->interlace = diff;
  39601. + cyberpro_set_interlace(dp);
  39602. + }
  39603. + }
  39604. +
  39605. + dp->win_set = 1;
  39606. +
  39607. + return 0;
  39608. + }
  39609. +
  39610. + case VIDIOCSFBUF: /* set frame buffer info */
  39611. + {
  39612. + struct video_buffer b;
  39613. + int ret;
  39614. +
  39615. + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
  39616. + return -EPERM;
  39617. +
  39618. + if (dp->cap_active)
  39619. + return -EINVAL;
  39620. +
  39621. + if (copy_from_user(&b, arg, sizeof(b)))
  39622. + return -EFAULT;
  39623. +
  39624. + ret = cyberpro_set_buffer(dp, &b);
  39625. + if (ret == 0) {
  39626. + dp->buf_set = 1;
  39627. + dp->win_set = 0;
  39628. + }
  39629. +
  39630. + return ret;
  39631. + }
  39632. +
  39633. + case VIDIOCCAPTURE:
  39634. + {
  39635. + int on;
  39636. +
  39637. + if (get_user(on, (int *)arg))
  39638. + return -EFAULT;
  39639. +
  39640. + if (( on && dp->ovl_active) ||
  39641. + (!on && !dp->ovl_active))
  39642. + return 0;
  39643. +
  39644. + if (on && (!dp->buf_set || !dp->win_set))
  39645. + return -EINVAL;
  39646. +
  39647. + cyberpro_capture(dp, on);
  39648. + dp->cap_active = on;
  39649. + dp->ovl->ctl(dp, dp->ovl, on);
  39650. + dp->ovl_active = on;
  39651. +
  39652. + return 0;
  39653. + }
  39654. +
  39655. +#ifdef USE_MMAP
  39656. + case VIDIOCSYNC:
  39657. + {
  39658. + DECLARE_WAITQUEUE(wait, current);
  39659. + int buf;
  39660. +
  39661. + /*
  39662. + * The buffer must have been mmaped
  39663. + * for this call to work.
  39664. + */
  39665. + if (!dp->mmaped)
  39666. + return -EINVAL;
  39667. +
  39668. + if (get_user(buf, (int *)arg))
  39669. + return -EFAULT;
  39670. +
  39671. + if (buf < 0 || buf >= NR_FRAMES)
  39672. + return -EINVAL;
  39673. +
  39674. + switch (dp->frame[buf].status) {
  39675. + case FRAME_FREE:
  39676. + return -EINVAL;
  39677. +
  39678. + case FRAME_WAITING:
  39679. + case FRAME_GRABBING:
  39680. + add_wait_queue(&dp->frame_wait, &wait);
  39681. + while (1) {
  39682. + set_current_state(TASK_INTERRUPTIBLE);
  39683. + if (signal_pending(current))
  39684. + break;
  39685. + if (dp->frame[buf].status == FRAME_DONE)
  39686. + break;
  39687. + schedule();
  39688. + }
  39689. + set_current_state(TASK_RUNNING);
  39690. + remove_wait_queue(&dp->frame_wait, &wait);
  39691. + if (signal_pending(current))
  39692. + return -EINTR;
  39693. + /*FALLTHROUGH*/
  39694. + case FRAME_DONE:
  39695. + dp->frame[buf].status = FRAME_FREE;
  39696. + break;
  39697. + }
  39698. + return 0;
  39699. + }
  39700. +
  39701. + case VIDIOCMCAPTURE:
  39702. + {
  39703. + struct video_mmap vmap;
  39704. +
  39705. + /*
  39706. + * The buffer must have been mmaped
  39707. + * for this call to work.
  39708. + */
  39709. + if (!dp->mmaped)
  39710. + return -EINVAL;
  39711. +
  39712. + if (copy_from_user(&vmap, arg, sizeof(vmap)))
  39713. + return -EFAULT;
  39714. +
  39715. + /*
  39716. + * We can only capture in our source format/size.
  39717. + */
  39718. + if (vmap.frame >= NR_FRAMES ||
  39719. + vmap.format != dp->stream_fmt ||
  39720. + vmap.width != dp->capt.width ||
  39721. + vmap.height != dp->capt.height)
  39722. + return -EINVAL;
  39723. +
  39724. + if (dp->frame[vmap.frame].status == FRAME_WAITING ||
  39725. + dp->frame[vmap.frame].status == FRAME_GRABBING)
  39726. + return -EBUSY;
  39727. +
  39728. + dp->frame[vmap.frame].status = FRAME_WAITING;
  39729. + return 0;
  39730. + }
  39731. +
  39732. + case VIDIOCGMBUF:
  39733. + {
  39734. + struct video_mbuf vmb;
  39735. + unsigned int i;
  39736. +
  39737. + vmb.frames = NR_FRAMES;
  39738. + vmb.size = dp->frame_size * NR_FRAMES;
  39739. +
  39740. + for (i = 0; i < NR_FRAMES; i++)
  39741. + vmb.offsets[i] = dp->frame[i].offset;
  39742. +
  39743. + return copy_to_user(arg, &vmb, sizeof(vmb)) ? -EFAULT : 0;
  39744. + }
  39745. +#endif
  39746. +
  39747. + case VIDIOCSCAPTURE:
  39748. + {
  39749. + struct video_capture capt;
  39750. +
  39751. +#ifndef ALLOW_SCAPTURE_WHILE_CAP
  39752. + if (dp->cap_active)
  39753. + return -EINVAL;
  39754. +#endif
  39755. +
  39756. + if (copy_from_user(&capt, arg, sizeof(capt)))
  39757. + return -EFAULT;
  39758. +
  39759. + if (capt.x < 0 || capt.width < 0 ||
  39760. + capt.y < 0 || capt.height < 0 ||
  39761. + capt.x + capt.width > dp->cap.maxwidth ||
  39762. + capt.y + capt.height > dp->cap.maxheight)
  39763. + return -EINVAL;
  39764. +
  39765. + /*
  39766. + * The capture width must be a multiple of 4
  39767. + */
  39768. + if (dp->capt.width & 3)
  39769. + return -EINVAL;
  39770. +
  39771. + dp->capt.x = capt.x;
  39772. + dp->capt.y = capt.y;
  39773. + dp->capt.width = capt.width;
  39774. + dp->capt.height = capt.height;
  39775. +#ifdef ALLOW_SCAPTURE_WHILE_CAP
  39776. + if (dp->ovl_active)
  39777. + dp->ovl->ctl(dp, dp->ovl, 0);
  39778. + if (dp->cap_active)
  39779. + cyberpro_capture(dp, 0);
  39780. +#endif
  39781. + cyberpro_capture_set_win(dp);
  39782. +
  39783. + /*
  39784. + * Update the overlay window information
  39785. + */
  39786. + dp->ovl->src.width = capt.width;
  39787. + dp->ovl->src.height = capt.height;
  39788. +
  39789. + dp->ovl->set_src(dp, dp->ovl);
  39790. + if (dp->win_set)
  39791. + dp->ovl->set_win(dp, dp->ovl);
  39792. +
  39793. +#ifdef ALLOW_SCAPTURE_WHILE_CAP
  39794. + if (dp->cap_active)
  39795. + cyberpro_capture(dp, 1);
  39796. + if (dp->ovl_active)
  39797. + dp->ovl->ctl(dp, dp->ovl, 1);
  39798. +#endif
  39799. + return 0;
  39800. + }
  39801. +
  39802. + case VIDIOCGTUNER: /* no tuner */
  39803. + case VIDIOCSTUNER:
  39804. + return -EINVAL;
  39805. + }
  39806. +
  39807. + return -EINVAL;
  39808. +}
  39809. +
  39810. +#ifdef USE_MMAP
  39811. +static int
  39812. +cyberpro_grabber_mmap(struct video_device *dev, const char *addr, unsigned long size)
  39813. +{
  39814. + struct cyberpro_vidinfo *dp = dev->priv;
  39815. + unsigned long vaddr = (unsigned long)addr;
  39816. + pgprot_t prot;
  39817. + int frame_idx, ret = -EINVAL;
  39818. +
  39819. +#if defined(__arm__)
  39820. + prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_USER | L_PTE_WRITE | L_PTE_DIRTY);
  39821. +#elif defined(__i386__)
  39822. + prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED);
  39823. + if (boot_cpu_data.x86 > 3)
  39824. + pgprot_val(prot) |= _PAGE_PCD;
  39825. +#else
  39826. +#error "Unsupported architecture"
  39827. +#endif
  39828. +
  39829. + /*
  39830. + * The mmap() request must have the correct size.
  39831. + */
  39832. + if (size != NR_FRAMES * dp->frame_size)
  39833. + goto out;
  39834. +
  39835. + /*
  39836. + * If it's already mapped, don't re-do
  39837. + */
  39838. + if (dp->mmaped)
  39839. + goto out;
  39840. + dp->mmaped = 1;
  39841. +
  39842. + /*
  39843. + * Map in each frame
  39844. + */
  39845. + for (frame_idx = 0; frame_idx < NR_FRAMES; frame_idx++) {
  39846. + struct framebuf *frame;
  39847. + int pgidx;
  39848. +
  39849. + frame = dp->frame + frame_idx;
  39850. +
  39851. + ret = cyberpro_alloc_frame_buffer(dp, frame);
  39852. +
  39853. + /*
  39854. + * If an error occurs, we can be lazy and leave what we've
  39855. + * been able to do. Our release function will free any
  39856. + * allocated buffers, and do_mmap_pgoff() will zap any
  39857. + * inserted mappings.
  39858. + */
  39859. + if (ret)
  39860. + goto out2;
  39861. +
  39862. + /*
  39863. + * Map in each page on a page by page basis. This is just
  39864. + * a little on the inefficient side, but it's only run once.
  39865. + */
  39866. + for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
  39867. + unsigned long virt;
  39868. +
  39869. + virt = page_address(frame->pages[pgidx]);
  39870. +
  39871. + ret = remap_page_range(vaddr, virt_to_phys((void *)virt),
  39872. + PAGE_SIZE, prot);
  39873. +
  39874. + if (ret)
  39875. + goto out2;
  39876. +
  39877. + vaddr += PAGE_SIZE;
  39878. + }
  39879. + }
  39880. +
  39881. + out2:
  39882. + if (ret)
  39883. + dp->mmaped = 0;
  39884. + out:
  39885. + return ret;
  39886. +}
  39887. +#endif
  39888. +
  39889. +static int __init cyberpro_grabber_init_done(struct video_device *dev)
  39890. +{
  39891. + struct cyberpro_vidinfo *dp;
  39892. + struct cyberpro_info *info = dev->priv;
  39893. + int ret;
  39894. +
  39895. + dp = kmalloc(sizeof(*dp), GFP_KERNEL);
  39896. + if (!dp)
  39897. + return -ENOMEM;
  39898. +
  39899. + memset(dp, 0, sizeof(*dp));
  39900. +
  39901. + dev->priv = dp;
  39902. + dp->info = *info;
  39903. + dp->dev = dev;
  39904. + dp->bus = &cyberpro_i2c_bus;
  39905. + dp->regs = info->regs;
  39906. + dp->irq = info->dev->irq;
  39907. +
  39908. + strcpy(dp->cap.name, dev->name);
  39909. + dp->cap.type = dev->type;
  39910. + dp->cap.channels = 1;
  39911. + dp->cap.audios = 0;
  39912. + dp->cap.minwidth = 32;
  39913. + dp->cap.maxwidth = 716;
  39914. + dp->cap.minheight = 32;
  39915. + dp->cap.maxheight = 576;
  39916. +
  39917. + dp->pic.brightness = 32768;
  39918. + dp->pic.hue = 32768;
  39919. + dp->pic.colour = 32768;
  39920. + dp->pic.contrast = 32768;
  39921. + dp->pic.whiteness = 0;
  39922. + dp->pic.depth = 8;
  39923. + dp->pic.palette = VIDEO_PALETTE_YUV422;
  39924. +
  39925. + /* dp->buf is setup by the user */
  39926. + /* dp->cap_mem_offset setup by dp->buf */
  39927. +
  39928. + dp->norm = VIDEO_MODE_AUTO;
  39929. +
  39930. + /*
  39931. + * The extended overlay window
  39932. + */
  39933. + dp->ext.init = cyberpro_ext_init;
  39934. + dp->ext.set_src = cyberpro_ext_set_src;
  39935. + dp->ext.set_win = cyberpro_ext_set_win;
  39936. + dp->ext.ctl = cyberpro_ext_ctl;
  39937. +
  39938. + /*
  39939. + * The V2 overlay window
  39940. + */
  39941. + dp->v2.init = cyberpro_v2_init;
  39942. + dp->v2.set_src = cyberpro_v2_set_src;
  39943. + dp->v2.set_win = cyberpro_v2_set_win;
  39944. + dp->v2.ctl = cyberpro_v2_ctl;
  39945. +
  39946. + /*
  39947. + * The X2 overlay window
  39948. + */
  39949. + dp->x2.init = cyberpro_x2_init;
  39950. + dp->x2.set_src = cyberpro_x2_set_src;
  39951. + dp->x2.set_win = cyberpro_x2_set_win;
  39952. + dp->x2.ctl = cyberpro_x2_ctl;
  39953. +
  39954. + /*
  39955. + * Set the overlay window which we shall be using
  39956. + */
  39957. + dp->ovl = &dp->ext;
  39958. +
  39959. + dp->cap_mode1 = EXT_CAP_MODE1_ALTFIFO;
  39960. +
  39961. + /*
  39962. + * Initialise hardware specific values.
  39963. + * - CCIR656 8bit mode (YUV422 data)
  39964. + * - Ignore Hgood signal
  39965. + * - Invert Odd/Even field signal
  39966. + */
  39967. + dp->cap_mode1 |= EXT_CAP_MODE1_CCIR656 | EXT_CAP_MODE1_8BIT;
  39968. + dp->cap_mode2 = EXT_CAP_MODE2_FIXSONY | EXT_CAP_MODE2_DATEND |
  39969. + EXT_CAP_MODE2_CCIRINVOE;
  39970. + dp->stream_fmt = VIDEO_PALETTE_YUV422;
  39971. +
  39972. +
  39973. + init_waitqueue_head(&dp->vbl_wait);
  39974. + cyberpro_frames_init(dp);
  39975. +
  39976. + /*
  39977. + * wake up the decoder
  39978. + */
  39979. + decoder_sleep(0);
  39980. +
  39981. + dp->bus->data = dp;
  39982. + strncpy(dp->bus->name, dev->name, sizeof(dp->bus->name));
  39983. +
  39984. + pci_set_master(dp->info.dev);
  39985. +
  39986. + ret = i2c_register_bus(dp->bus);
  39987. +
  39988. + /*
  39989. + * If we successfully registered the bus, but didn't initialise
  39990. + * the decoder (because its driver is not present), request
  39991. + * that it is loaded.
  39992. + */
  39993. + if (ret == 0 && !dp->decoder)
  39994. + request_module("saa7111");
  39995. +
  39996. + /*
  39997. + * If that didn't work, then we're out of luck.
  39998. + */
  39999. + if (ret == 0 && !dp->decoder) {
  40000. + i2c_unregister_bus(dp->bus);
  40001. + ret = -ENXIO;
  40002. + }
  40003. +
  40004. + if (ret) {
  40005. + kfree(dp);
  40006. +
  40007. + /*
  40008. + * put the decoder back to sleep
  40009. + */
  40010. + decoder_sleep(1);
  40011. + }
  40012. +
  40013. + return ret;
  40014. +}
  40015. +
  40016. +static struct video_device cyberpro_grabber = {
  40017. + name: "",
  40018. + type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
  40019. + VID_TYPE_CHROMAKEY | VID_TYPE_SCALES |
  40020. + VID_TYPE_SUBCAPTURE,
  40021. + hardware: 0,
  40022. + open: cyberpro_grabber_open,
  40023. + close: cyberpro_grabber_close,
  40024. + read: cyberpro_grabber_read,
  40025. + write: cyberpro_grabber_write,
  40026. + ioctl: cyberpro_grabber_ioctl,
  40027. +#ifdef USE_MMAP
  40028. + mmap: cyberpro_grabber_mmap,
  40029. +#endif
  40030. + initialize: cyberpro_grabber_init_done,
  40031. +};
  40032. +
  40033. +int init_cyber2000fb_viddev(void)
  40034. +{
  40035. + struct cyberpro_info info;
  40036. +
  40037. + if (!cyber2000fb_attach(&info, 0))
  40038. + return -ENXIO;
  40039. +
  40040. + strncpy(cyberpro_grabber.name, info.dev_name, sizeof(cyberpro_grabber.name));
  40041. +
  40042. + cyberpro_grabber.priv = &info;
  40043. +
  40044. + return video_register_device(&cyberpro_grabber, VFL_TYPE_GRABBER, -1);
  40045. +}
  40046. +
  40047. +/*
  40048. + * This can be cleaned up when the SAA7111 code is fixed.
  40049. + */
  40050. +#ifdef MODULE
  40051. +static int __init cyberpro_init(void)
  40052. +{
  40053. + disable_irq(35);
  40054. + return init_cyber2000fb_viddev();
  40055. +}
  40056. +
  40057. +static void __exit cyberpro_exit(void)
  40058. +{
  40059. + video_unregister_device(&cyberpro_grabber);
  40060. + kfree(cyberpro_grabber.priv);
  40061. + i2c_unregister_bus(&cyberpro_i2c_bus);
  40062. +
  40063. + /*
  40064. + * put the decoder back to sleep
  40065. + */
  40066. + decoder_sleep(1);
  40067. +
  40068. + cyber2000fb_detach(0);
  40069. +}
  40070. +
  40071. +module_init(cyberpro_init);
  40072. +module_exit(cyberpro_exit);
  40073. +#endif
  40074. diff -urN linux-2.4.26/drivers/media/video/i2c-old.c linux-2.4.26-vrs1/drivers/media/video/i2c-old.c
  40075. --- linux-2.4.26/drivers/media/video/i2c-old.c 2004-02-27 20:03:26.000000000 +0000
  40076. +++ linux-2.4.26-vrs1/drivers/media/video/i2c-old.c 2004-02-27 23:41:21.000000000 +0000
  40077. @@ -36,11 +36,20 @@
  40078. static struct i2c_driver *drivers[I2C_DRIVER_MAX];
  40079. static int bus_count = 0, driver_count = 0;
  40080. +extern int saa7111_init(void);
  40081. +extern int saa7185_init(void);
  40082. +extern int bt819_init(void);
  40083. +extern int bt856_init(void);
  40084. +
  40085. int i2c_init(void)
  40086. {
  40087. printk(KERN_INFO "i2c: initialized%s\n",
  40088. scan ? " (i2c bus scan enabled)" : "");
  40089. +#if defined(CONFIG_VIDEO_CYBERPRO)
  40090. + saa7111_init();
  40091. +#endif
  40092. +
  40093. return 0;
  40094. }
  40095. @@ -52,10 +61,10 @@
  40096. int i,j,ack=1;
  40097. unsigned char addr;
  40098. LOCK_FLAGS;
  40099. -
  40100. +
  40101. /* probe for device */
  40102. LOCK_I2C_BUS(bus);
  40103. - for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
  40104. + for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
  40105. {
  40106. i2c_start(bus);
  40107. ack = i2c_sendbyte(bus,addr,0);
  40108. @@ -87,8 +96,8 @@
  40109. device->addr = addr;
  40110. /* Attach */
  40111. -
  40112. - if (driver->attach(device)!=0)
  40113. +
  40114. + if (driver->attach(device)!=0)
  40115. {
  40116. kfree(device);
  40117. return;
  40118. @@ -114,7 +123,7 @@
  40119. for (i = 0; i < I2C_DEVICE_MAX; i++)
  40120. if (device == device->driver->devices[i])
  40121. break;
  40122. - if (I2C_DEVICE_MAX == i)
  40123. + if (I2C_DEVICE_MAX == i)
  40124. {
  40125. printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
  40126. device->name);
  40127. @@ -126,7 +135,7 @@
  40128. for (i = 0; i < I2C_DEVICE_MAX; i++)
  40129. if (device == device->bus->devices[i])
  40130. break;
  40131. - if (I2C_DEVICE_MAX == i)
  40132. + if (I2C_DEVICE_MAX == i)
  40133. {
  40134. printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
  40135. device->name);
  40136. @@ -158,19 +167,19 @@
  40137. busses[i] = bus;
  40138. bus_count++;
  40139. REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
  40140. -
  40141. +
  40142. MOD_INC_USE_COUNT;
  40143. - if (scan)
  40144. + if (scan)
  40145. {
  40146. /* scan whole i2c bus */
  40147. LOCK_I2C_BUS(bus);
  40148. - for (i = 0; i < 256; i+=2)
  40149. + for (i = 0; i < 256; i+=2)
  40150. {
  40151. i2c_start(bus);
  40152. ack = i2c_sendbyte(bus,i,0);
  40153. i2c_stop(bus);
  40154. - if (!ack)
  40155. + if (!ack)
  40156. {
  40157. printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n",
  40158. bus->name,i);
  40159. @@ -198,20 +207,20 @@
  40160. for (i = 0; i < I2C_BUS_MAX; i++)
  40161. if (bus == busses[i])
  40162. break;
  40163. - if (I2C_BUS_MAX == i)
  40164. + if (I2C_BUS_MAX == i)
  40165. {
  40166. printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
  40167. bus->name);
  40168. return -ENODEV;
  40169. }
  40170. -
  40171. +
  40172. MOD_DEC_USE_COUNT;
  40173. -
  40174. +
  40175. busses[i] = NULL;
  40176. bus_count--;
  40177. REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
  40178. - return 0;
  40179. + return 0;
  40180. }
  40181. /* ----------------------------------------------------------------------- */
  40182. @@ -231,9 +240,9 @@
  40183. drivers[i] = driver;
  40184. driver_count++;
  40185. -
  40186. +
  40187. MOD_INC_USE_COUNT;
  40188. -
  40189. +
  40190. REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
  40191. /* Probe available busses */
  40192. @@ -256,7 +265,7 @@
  40193. for (i = 0; i < I2C_DRIVER_MAX; i++)
  40194. if (driver == drivers[i])
  40195. break;
  40196. - if (I2C_DRIVER_MAX == i)
  40197. + if (I2C_DRIVER_MAX == i)
  40198. {
  40199. printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
  40200. driver->name);
  40201. @@ -264,7 +273,7 @@
  40202. }
  40203. MOD_DEC_USE_COUNT;
  40204. -
  40205. +
  40206. drivers[i] = NULL;
  40207. driver_count--;
  40208. REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
  40209. @@ -328,7 +337,7 @@
  40210. int i2c_ack(struct i2c_bus *bus)
  40211. {
  40212. int ack;
  40213. -
  40214. +
  40215. I2C_SET(bus,0,1);
  40216. I2C_SET(bus,1,1);
  40217. ack = I2C_GET(bus);
  40218. @@ -339,7 +348,7 @@
  40219. int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack)
  40220. {
  40221. int i, ack;
  40222. -
  40223. +
  40224. I2C_SET(bus,0,0);
  40225. for (i=7; i>=0; i--)
  40226. (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
  40227. @@ -354,9 +363,9 @@
  40228. {
  40229. int i;
  40230. unsigned char data=0;
  40231. -
  40232. +
  40233. I2C_SET(bus,0,1);
  40234. - for (i=7; i>=0; i--)
  40235. + for (i=7; i>=0; i--)
  40236. {
  40237. I2C_SET(bus,1,1);
  40238. if (I2C_GET(bus))
  40239. @@ -373,7 +382,7 @@
  40240. int i2c_read(struct i2c_bus *bus, unsigned char addr)
  40241. {
  40242. int ret;
  40243. -
  40244. +
  40245. if (bus->i2c_read)
  40246. return bus->i2c_read(bus, addr);
  40247. diff -urN linux-2.4.26/drivers/media/video/saa7111.c linux-2.4.26-vrs1/drivers/media/video/saa7111.c
  40248. --- linux-2.4.26/drivers/media/video/saa7111.c 2001-09-30 20:26:06.000000000 +0100
  40249. +++ linux-2.4.26-vrs1/drivers/media/video/saa7111.c 2004-01-14 21:32:25.000000000 +0000
  40250. @@ -20,9 +20,9 @@
  40251. along with this program; if not, write to the Free Software
  40252. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40253. */
  40254. -
  40255. -#include <linux/module.h>
  40256. +#include <linux/config.h>
  40257. #include <linux/init.h>
  40258. +#include <linux/module.h>
  40259. #include <linux/delay.h>
  40260. #include <linux/errno.h>
  40261. #include <linux/fs.h>
  40262. @@ -149,7 +149,11 @@
  40263. 0x0d, 0x00, /* 0d - HUE=0 */
  40264. 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
  40265. 0x0f, 0x00, /* 0f - reserved */
  40266. +#ifndef CONFIG_ARCH_NETWINDER
  40267. 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
  40268. +#else
  40269. + 0x10, 0xc8, /* 10 - OFTS=YUV-CCIR656, HDEL=0, VLRN=1, YDEL=0 */
  40270. +#endif
  40271. 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
  40272. 0x12, 0x00, /* 12 - output control 2 */
  40273. 0x13, 0x00, /* 13 - output control 3 */
  40274. diff -urN linux-2.4.26/drivers/message/i2o/i2o_core.c linux-2.4.26-vrs1/drivers/message/i2o/i2o_core.c
  40275. --- linux-2.4.26/drivers/message/i2o/i2o_core.c 2003-06-13 15:51:34.000000000 +0100
  40276. +++ linux-2.4.26-vrs1/drivers/message/i2o/i2o_core.c 2004-01-14 21:32:25.000000000 +0000
  40277. @@ -1665,14 +1665,14 @@
  40278. }
  40279. memset(status, 0, 4);
  40280. - msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
  40281. - msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
  40282. - msg[2]=core_context;
  40283. - msg[3]=0;
  40284. - msg[4]=0;
  40285. - msg[5]=0;
  40286. - msg[6]=virt_to_bus(status);
  40287. - msg[7]=0; /* 64bit host FIXME */
  40288. + writel(EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
  40289. + writel(I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
  40290. + writel(core_context, msg + 2);
  40291. + writel(0, msg + 3);
  40292. + writel(0, msg + 4);
  40293. + writel(0, msg + 5);
  40294. + writel(virt_to_bus(status), msg + 6);
  40295. + writel(0, msg + 7); /* 64bit host FIXME */
  40296. i2o_post_message(c,m);
  40297. @@ -1781,15 +1781,15 @@
  40298. return -ETIMEDOUT;
  40299. msg=(u32 *)(c->mem_offset+m);
  40300. - msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
  40301. - msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
  40302. - msg[2]=core_context;
  40303. - msg[3]=0;
  40304. - msg[4]=0;
  40305. - msg[5]=0;
  40306. - msg[6]=virt_to_bus(c->status_block);
  40307. - msg[7]=0; /* 64bit host FIXME */
  40308. - msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
  40309. + writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
  40310. + writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
  40311. + writel(core_context, msg + 2);
  40312. + writel(0, msg + 3);
  40313. + writel(0, msg + 4);
  40314. + writel(0, msg + 5);
  40315. + writel(virt_to_bus(c->status_block), msg + 6);
  40316. + writel(0, msg + 7); /* 64bit host FIXME */
  40317. + writel(sizeof(i2o_status_block), msg + 8); /* always 88 bytes */
  40318. i2o_post_message(c,m);
  40319. @@ -2193,15 +2193,15 @@
  40320. }
  40321. memset(status, 0, 4);
  40322. - msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
  40323. - msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
  40324. - msg[2]= core_context;
  40325. - msg[3]= 0x0106; /* Transaction context */
  40326. - msg[4]= 4096; /* Host page frame size */
  40327. + writel(EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6, msg + 0);
  40328. + writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, msg + 1);
  40329. + writel(core_context, msg + 2);
  40330. + writel(0x0106, msg + 3); /* Transaction context */
  40331. + writel(PAGE_SIZE, msg + 4); /* Host page frame size */
  40332. /* Frame size is in words. 256 bytes a frame for now */
  40333. - msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size in words and Initcode */
  40334. - msg[6]= 0xD0000004; /* Simple SG LE, EOB */
  40335. - msg[7]= virt_to_bus(status);
  40336. + writel(MSG_FRAME_SIZE<<16|0x80, msg + 5);/* Outbound msg frame size in words and Initcode */
  40337. + writel(0xD0000004, msg + 6); /* Simple SG LE, EOB */
  40338. + writel(virt_to_bus(status), msg + 7);
  40339. i2o_post_message(c,m);
  40340. diff -urN linux-2.4.26/drivers/message/i2o/i2o_pci.c linux-2.4.26-vrs1/drivers/message/i2o/i2o_pci.c
  40341. --- linux-2.4.26/drivers/message/i2o/i2o_pci.c 2002-11-28 23:53:13.000000000 +0000
  40342. +++ linux-2.4.26-vrs1/drivers/message/i2o/i2o_pci.c 2004-01-14 21:32:25.000000000 +0000
  40343. @@ -390,4 +390,4 @@
  40344. MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o");
  40345. module_init(i2o_pci_core_attach);
  40346. module_exit(i2o_pci_core_detach);
  40347. -
  40348. \ No newline at end of file
  40349. +
  40350. diff -urN linux-2.4.26/drivers/misc/Config.in linux-2.4.26-vrs1/drivers/misc/Config.in
  40351. --- linux-2.4.26/drivers/misc/Config.in 1999-12-25 23:04:56.000000000 +0000
  40352. +++ linux-2.4.26-vrs1/drivers/misc/Config.in 2004-01-14 21:32:25.000000000 +0000
  40353. @@ -1,7 +1,17 @@
  40354. #
  40355. -# Misc strange devices
  40356. +# MCP drivers
  40357. #
  40358. mainmenu_option next_comment
  40359. -comment 'Misc devices'
  40360. +comment 'Multimedia Capabilities Port drivers'
  40361. +
  40362. +bool 'Multimedia drivers' CONFIG_MCP
  40363. +
  40364. +# Interface drivers
  40365. +dep_bool 'Support SA1100 MCP interface' CONFIG_MCP_SA1100 $CONFIG_MCP $CONFIG_ARCH_SA1100
  40366. +
  40367. +# Chip drivers
  40368. +dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
  40369. +dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
  40370. +dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
  40371. endmenu
  40372. diff -urN linux-2.4.26/drivers/misc/Makefile linux-2.4.26-vrs1/drivers/misc/Makefile
  40373. --- linux-2.4.26/drivers/misc/Makefile 2000-12-29 22:07:22.000000000 +0000
  40374. +++ linux-2.4.26-vrs1/drivers/misc/Makefile 2004-01-14 21:32:25.000000000 +0000
  40375. @@ -11,6 +11,14 @@
  40376. O_TARGET := misc.o
  40377. +export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o
  40378. +
  40379. +obj-$(CONFIG_MCP) += mcp-core.o
  40380. +obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o
  40381. +obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
  40382. +obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
  40383. +obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
  40384. +
  40385. include $(TOPDIR)/Rules.make
  40386. fastdep:
  40387. diff -urN linux-2.4.26/drivers/misc/mcp-core.c linux-2.4.26-vrs1/drivers/misc/mcp-core.c
  40388. --- linux-2.4.26/drivers/misc/mcp-core.c 1970-01-01 01:00:00.000000000 +0100
  40389. +++ linux-2.4.26-vrs1/drivers/misc/mcp-core.c 2004-01-14 21:32:25.000000000 +0000
  40390. @@ -0,0 +1,155 @@
  40391. +/*
  40392. + * linux/drivers/misc/mcp-core.c
  40393. + *
  40394. + * Copyright (C) 2001 Russell King
  40395. + *
  40396. + * This program is free software; you can redistribute it and/or modify
  40397. + * it under the terms of the GNU General Public License as published by
  40398. + * the Free Software Foundation; either version 2 of the License.
  40399. + *
  40400. + * Generic MCP (Multimedia Communications Port) layer. All MCP locking
  40401. + * is solely held within this file.
  40402. + */
  40403. +#include <linux/module.h>
  40404. +#include <linux/init.h>
  40405. +#include <linux/errno.h>
  40406. +#include <linux/smp.h>
  40407. +
  40408. +#include <asm/dma.h>
  40409. +#include <asm/system.h>
  40410. +
  40411. +#include "mcp.h"
  40412. +
  40413. +/**
  40414. + * mcp_set_telecom_divisor - set the telecom divisor
  40415. + * @mcp: MCP interface structure
  40416. + * @div: SIB clock divisor
  40417. + *
  40418. + * Set the telecom divisor on the MCP interface. The resulting
  40419. + * sample rate is SIBCLOCK/div.
  40420. + */
  40421. +void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
  40422. +{
  40423. + spin_lock_irq(&mcp->lock);
  40424. + mcp->set_telecom_divisor(mcp, div);
  40425. + spin_unlock_irq(&mcp->lock);
  40426. +}
  40427. +
  40428. +/**
  40429. + * mcp_set_audio_divisor - set the audio divisor
  40430. + * @mcp: MCP interface structure
  40431. + * @div: SIB clock divisor
  40432. + *
  40433. + * Set the audio divisor on the MCP interface.
  40434. + */
  40435. +void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
  40436. +{
  40437. + spin_lock_irq(&mcp->lock);
  40438. + mcp->set_audio_divisor(mcp, div);
  40439. + spin_unlock_irq(&mcp->lock);
  40440. +}
  40441. +
  40442. +/**
  40443. + * mcp_reg_write - write a device register
  40444. + * @mcp: MCP interface structure
  40445. + * @reg: 4-bit register index
  40446. + * @val: 16-bit data value
  40447. + *
  40448. + * Write a device register. The MCP interface must be enabled
  40449. + * to prevent this function hanging.
  40450. + */
  40451. +void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
  40452. +{
  40453. + unsigned long flags;
  40454. +
  40455. + spin_lock_irqsave(&mcp->lock, flags);
  40456. + mcp->reg_write(mcp, reg, val);
  40457. + spin_unlock_irqrestore(&mcp->lock, flags);
  40458. +}
  40459. +
  40460. +/**
  40461. + * mcp_reg_read - read a device register
  40462. + * @mcp: MCP interface structure
  40463. + * @reg: 4-bit register index
  40464. + *
  40465. + * Read a device register and return its value. The MCP interface
  40466. + * must be enabled to prevent this function hanging.
  40467. + */
  40468. +unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
  40469. +{
  40470. + unsigned long flags;
  40471. + unsigned int val;
  40472. +
  40473. + spin_lock_irqsave(&mcp->lock, flags);
  40474. + val = mcp->reg_read(mcp, reg);
  40475. + spin_unlock_irqrestore(&mcp->lock, flags);
  40476. +
  40477. + return val;
  40478. +}
  40479. +
  40480. +/**
  40481. + * mcp_enable - enable the MCP interface
  40482. + * @mcp: MCP interface to enable
  40483. + *
  40484. + * Enable the MCP interface. Each call to mcp_enable will need
  40485. + * a corresponding call to mcp_disable to disable the interface.
  40486. + */
  40487. +void mcp_enable(struct mcp *mcp)
  40488. +{
  40489. + spin_lock_irq(&mcp->lock);
  40490. + if (mcp->use_count++ == 0)
  40491. + mcp->enable(mcp);
  40492. + spin_unlock_irq(&mcp->lock);
  40493. +}
  40494. +
  40495. +/**
  40496. + * mcp_disable - disable the MCP interface
  40497. + * @mcp: MCP interface to disable
  40498. + *
  40499. + * Disable the MCP interface. The MCP interface will only be
  40500. + * disabled once the number of calls to mcp_enable matches the
  40501. + * number of calls to mcp_disable.
  40502. + */
  40503. +void mcp_disable(struct mcp *mcp)
  40504. +{
  40505. + unsigned long flags;
  40506. +
  40507. + spin_lock_irqsave(&mcp->lock, flags);
  40508. + if (--mcp->use_count == 0)
  40509. + mcp->disable(mcp);
  40510. + spin_unlock_irqrestore(&mcp->lock, flags);
  40511. +}
  40512. +
  40513. +
  40514. +/*
  40515. + * This needs re-working
  40516. + */
  40517. +static struct mcp *mcp_if;
  40518. +
  40519. +struct mcp *mcp_get(void)
  40520. +{
  40521. + return mcp_if;
  40522. +}
  40523. +
  40524. +int mcp_register(struct mcp *mcp)
  40525. +{
  40526. + if (mcp_if)
  40527. + return -EBUSY;
  40528. + if (mcp->owner)
  40529. + __MOD_INC_USE_COUNT(mcp->owner);
  40530. + mcp_if = mcp;
  40531. + return 0;
  40532. +}
  40533. +
  40534. +EXPORT_SYMBOL(mcp_set_telecom_divisor);
  40535. +EXPORT_SYMBOL(mcp_set_audio_divisor);
  40536. +EXPORT_SYMBOL(mcp_reg_write);
  40537. +EXPORT_SYMBOL(mcp_reg_read);
  40538. +EXPORT_SYMBOL(mcp_enable);
  40539. +EXPORT_SYMBOL(mcp_disable);
  40540. +EXPORT_SYMBOL(mcp_get);
  40541. +EXPORT_SYMBOL(mcp_register);
  40542. +
  40543. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  40544. +MODULE_DESCRIPTION("Core multimedia communications port driver");
  40545. +MODULE_LICENSE("GPL");
  40546. diff -urN linux-2.4.26/drivers/misc/mcp-sa1100.c linux-2.4.26-vrs1/drivers/misc/mcp-sa1100.c
  40547. --- linux-2.4.26/drivers/misc/mcp-sa1100.c 1970-01-01 01:00:00.000000000 +0100
  40548. +++ linux-2.4.26-vrs1/drivers/misc/mcp-sa1100.c 2004-01-14 21:32:25.000000000 +0000
  40549. @@ -0,0 +1,180 @@
  40550. +/*
  40551. + * linux/drivers/misc/mcp-sa1100.c
  40552. + *
  40553. + * Copyright (C) 2001 Russell King
  40554. + *
  40555. + * This program is free software; you can redistribute it and/or modify
  40556. + * it under the terms of the GNU General Public License as published by
  40557. + * the Free Software Foundation; either version 2 of the License.
  40558. + *
  40559. + * SA1100 MCP (Multimedia Communications Port) driver.
  40560. + *
  40561. + * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
  40562. + */
  40563. +#include <linux/module.h>
  40564. +#include <linux/init.h>
  40565. +#include <linux/errno.h>
  40566. +#include <linux/kernel.h>
  40567. +#include <linux/delay.h>
  40568. +#include <linux/spinlock.h>
  40569. +
  40570. +#include <asm/dma.h>
  40571. +#include <asm/hardware.h>
  40572. +#include <asm/system.h>
  40573. +
  40574. +#include "mcp.h"
  40575. +
  40576. +static void
  40577. +mcp_sa1100_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
  40578. +{
  40579. + unsigned int mccr0;
  40580. +
  40581. + divisor /= 32;
  40582. +
  40583. + mccr0 = Ser4MCCR0 & ~0x00007f00;
  40584. + mccr0 |= divisor << 8;
  40585. + Ser4MCCR0 = mccr0;
  40586. +}
  40587. +
  40588. +static void
  40589. +mcp_sa1100_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
  40590. +{
  40591. + unsigned int mccr0;
  40592. +
  40593. + divisor /= 32;
  40594. +
  40595. + mccr0 = Ser4MCCR0 & ~0x0000007f;
  40596. + mccr0 |= divisor;
  40597. + Ser4MCCR0 = mccr0;
  40598. +}
  40599. +
  40600. +/*
  40601. + * Write data to the device. The bit should be set after 3 subframe
  40602. + * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
  40603. + * We really should try doing something more productive while we
  40604. + * wait.
  40605. + */
  40606. +static void
  40607. +mcp_sa1100_write(struct mcp *mcp, unsigned int reg, unsigned int val)
  40608. +{
  40609. + int ret = -ETIME;
  40610. + int i;
  40611. +
  40612. + Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
  40613. +
  40614. + for (i = 0; i < 2; i++) {
  40615. + udelay(mcp->rw_timeout);
  40616. + if (Ser4MCSR & MCSR_CWC) {
  40617. + ret = 0;
  40618. + break;
  40619. + }
  40620. + }
  40621. +
  40622. + if (ret < 0)
  40623. + printk(KERN_WARNING "mcp: write timed out\n");
  40624. +}
  40625. +
  40626. +/*
  40627. + * Read data from the device. The bit should be set after 3 subframe
  40628. + * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
  40629. + * We really should try doing something more productive while we
  40630. + * wait.
  40631. + */
  40632. +static unsigned int
  40633. +mcp_sa1100_read(struct mcp *mcp, unsigned int reg)
  40634. +{
  40635. + int ret = -ETIME;
  40636. + int i;
  40637. +
  40638. + Ser4MCDR2 = reg << 17 | MCDR2_Rd;
  40639. +
  40640. + for (i = 0; i < 2; i++) {
  40641. + udelay(mcp->rw_timeout);
  40642. + if (Ser4MCSR & MCSR_CRC) {
  40643. + ret = Ser4MCDR2 & 0xffff;
  40644. + break;
  40645. + }
  40646. + }
  40647. +
  40648. + if (ret < 0)
  40649. + printk(KERN_WARNING "mcp: read timed out\n");
  40650. +
  40651. + return ret;
  40652. +}
  40653. +
  40654. +static void mcp_sa1100_enable(struct mcp *mcp)
  40655. +{
  40656. + Ser4MCSR = -1;
  40657. + Ser4MCCR0 |= MCCR0_MCE;
  40658. +}
  40659. +
  40660. +static void mcp_sa1100_disable(struct mcp *mcp)
  40661. +{
  40662. + Ser4MCCR0 &= ~MCCR0_MCE;
  40663. +}
  40664. +
  40665. +struct mcp mcp_sa1100 = {
  40666. + owner: THIS_MODULE,
  40667. + lock: SPIN_LOCK_UNLOCKED,
  40668. + sclk_rate: 11981000,
  40669. + dma_audio_rd: DMA_Ser4MCP0Rd,
  40670. + dma_audio_wr: DMA_Ser4MCP0Wr,
  40671. + dma_telco_rd: DMA_Ser4MCP1Rd,
  40672. + dma_telco_wr: DMA_Ser4MCP1Wr,
  40673. + set_telecom_divisor: mcp_sa1100_set_telecom_divisor,
  40674. + set_audio_divisor: mcp_sa1100_set_audio_divisor,
  40675. + reg_write: mcp_sa1100_write,
  40676. + reg_read: mcp_sa1100_read,
  40677. + enable: mcp_sa1100_enable,
  40678. + disable: mcp_sa1100_disable,
  40679. +};
  40680. +
  40681. +/*
  40682. + * This needs re-working
  40683. + */
  40684. +static int mcp_sa1100_init(void)
  40685. +{
  40686. + struct mcp *mcp = &mcp_sa1100;
  40687. + int ret = -ENODEV;
  40688. +
  40689. + if (machine_is_accelent_sa() ||
  40690. + machine_is_adsbitsy() || machine_is_assabet() ||
  40691. + machine_is_cerf() || machine_is_flexanet() ||
  40692. + machine_is_freebird() || machine_is_graphicsclient() ||
  40693. + machine_is_graphicsmaster() || machine_is_lart() ||
  40694. + machine_is_omnimeter() || machine_is_pfs168() ||
  40695. + machine_is_shannon() || machine_is_simpad() ||
  40696. + machine_is_simputer() || machine_is_yopy()) {
  40697. + /*
  40698. + * Setup the PPC unit correctly.
  40699. + */
  40700. + PPDR &= ~PPC_RXD4;
  40701. + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
  40702. + PSDR |= PPC_RXD4;
  40703. + PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
  40704. + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
  40705. +
  40706. + Ser4MCSR = -1;
  40707. + Ser4MCCR1 = 0;
  40708. + Ser4MCCR0 = 0x00007f7f | MCCR0_ADM;
  40709. +
  40710. + /*
  40711. + * Calculate the read/write timeout (us) from the bit clock
  40712. + * rate. This is the period for 3 64-bit frames. Always
  40713. + * round this time up.
  40714. + */
  40715. + mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
  40716. + mcp->sclk_rate;
  40717. +
  40718. + ret = mcp_register(mcp);
  40719. + }
  40720. +
  40721. + return ret;
  40722. +}
  40723. +
  40724. +module_init(mcp_sa1100_init);
  40725. +EXPORT_SYMBOL(mcp_sa1100_init);
  40726. +
  40727. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  40728. +MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
  40729. +MODULE_LICENSE("GPL");
  40730. diff -urN linux-2.4.26/drivers/misc/mcp.h linux-2.4.26-vrs1/drivers/misc/mcp.h
  40731. --- linux-2.4.26/drivers/misc/mcp.h 1970-01-01 01:00:00.000000000 +0100
  40732. +++ linux-2.4.26-vrs1/drivers/misc/mcp.h 2004-01-14 21:32:25.000000000 +0000
  40733. @@ -0,0 +1,44 @@
  40734. +/*
  40735. + * linux/drivers/misc/mcp.h
  40736. + *
  40737. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  40738. + *
  40739. + * This program is free software; you can redistribute it and/or modify
  40740. + * it under the terms of the GNU General Public License as published by
  40741. + * the Free Software Foundation; either version 2 of the License.
  40742. + */
  40743. +#ifndef MCP_H
  40744. +#define MCP_H
  40745. +
  40746. +struct mcp {
  40747. + struct module *owner;
  40748. + spinlock_t lock;
  40749. + int use_count;
  40750. + unsigned int sclk_rate;
  40751. + unsigned int rw_timeout;
  40752. + dma_device_t dma_audio_rd;
  40753. + dma_device_t dma_audio_wr;
  40754. + dma_device_t dma_telco_rd;
  40755. + dma_device_t dma_telco_wr;
  40756. + void (*set_telecom_divisor)(struct mcp *, unsigned int);
  40757. + void (*set_audio_divisor)(struct mcp *, unsigned int);
  40758. + void (*reg_write)(struct mcp *, unsigned int, unsigned int);
  40759. + unsigned int (*reg_read)(struct mcp *, unsigned int);
  40760. + void (*enable)(struct mcp *);
  40761. + void (*disable)(struct mcp *);
  40762. +};
  40763. +
  40764. +void mcp_set_telecom_divisor(struct mcp *, unsigned int);
  40765. +void mcp_set_audio_divisor(struct mcp *, unsigned int);
  40766. +void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
  40767. +unsigned int mcp_reg_read(struct mcp *, unsigned int);
  40768. +void mcp_enable(struct mcp *);
  40769. +void mcp_disable(struct mcp *);
  40770. +
  40771. +/* noddy implementation alert! */
  40772. +struct mcp *mcp_get(void);
  40773. +int mcp_register(struct mcp *);
  40774. +
  40775. +#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
  40776. +
  40777. +#endif
  40778. diff -urN linux-2.4.26/drivers/misc/ucb1x00-audio.c linux-2.4.26-vrs1/drivers/misc/ucb1x00-audio.c
  40779. --- linux-2.4.26/drivers/misc/ucb1x00-audio.c 1970-01-01 01:00:00.000000000 +0100
  40780. +++ linux-2.4.26-vrs1/drivers/misc/ucb1x00-audio.c 2004-01-14 21:32:25.000000000 +0000
  40781. @@ -0,0 +1,378 @@
  40782. +/*
  40783. + * linux/drivers/misc/ucb1x00-audio.c
  40784. + *
  40785. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  40786. + *
  40787. + * This program is free software; you can redistribute it and/or modify
  40788. + * it under the terms of the GNU General Public License version 2 as
  40789. + * published by the Free Software Foundation.
  40790. + */
  40791. +#include <linux/module.h>
  40792. +#include <linux/init.h>
  40793. +#include <linux/fs.h>
  40794. +#include <linux/errno.h>
  40795. +#include <linux/slab.h>
  40796. +#include <linux/sound.h>
  40797. +#include <linux/soundcard.h>
  40798. +#include <linux/list.h>
  40799. +
  40800. +#include <asm/dma.h>
  40801. +#include <asm/hardware.h>
  40802. +#include <asm/semaphore.h>
  40803. +#include <asm/uaccess.h>
  40804. +
  40805. +#include "ucb1x00.h"
  40806. +
  40807. +#include "../drivers/sound/sa1100-audio.h"
  40808. +
  40809. +#define MAGIC 0x41544154
  40810. +
  40811. +struct ucb1x00_audio {
  40812. + struct file_operations fops;
  40813. + struct file_operations mops;
  40814. + struct ucb1x00 *ucb;
  40815. + audio_stream_t output_stream;
  40816. + audio_stream_t input_stream;
  40817. + audio_state_t state;
  40818. + unsigned int rate;
  40819. + int dev_id;
  40820. + int mix_id;
  40821. + unsigned int daa_oh_bit;
  40822. + unsigned int telecom;
  40823. + unsigned int magic;
  40824. + unsigned int ctrl_a;
  40825. + unsigned int ctrl_b;
  40826. +
  40827. + /* mixer info */
  40828. + unsigned int mod_cnt;
  40829. + unsigned short output_level;
  40830. + unsigned short input_level;
  40831. +};
  40832. +
  40833. +#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC)
  40834. +#define DEV_MASK REC_MASK
  40835. +
  40836. +static int
  40837. +ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg)
  40838. +{
  40839. + struct ucb1x00_audio *ucba;
  40840. + unsigned int val, gain;
  40841. + int ret = 0;
  40842. +
  40843. + ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops);
  40844. +
  40845. + if (_IOC_TYPE(cmd) != 'M')
  40846. + return -EINVAL;
  40847. +
  40848. + if (cmd == SOUND_MIXER_INFO) {
  40849. + struct mixer_info mi;
  40850. +
  40851. + strncpy(mi.id, "UCB1x00", sizeof(mi.id));
  40852. + strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name));
  40853. + mi.modify_counter = ucba->mod_cnt;
  40854. + return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0;
  40855. + }
  40856. +
  40857. + if (_IOC_DIR(cmd) & _IOC_WRITE) {
  40858. + unsigned int left, right;
  40859. +
  40860. + ret = get_user(val, (unsigned int *)arg);
  40861. + if (ret)
  40862. + goto out;
  40863. +
  40864. + left = val & 255;
  40865. + right = val >> 8;
  40866. +
  40867. + if (left > 100)
  40868. + left = 100;
  40869. + if (right > 100)
  40870. + right = 100;
  40871. +
  40872. + gain = (left + right) / 2;
  40873. +
  40874. + ret = -EINVAL;
  40875. + if (!ucba->telecom) {
  40876. + switch(_IOC_NR(cmd)) {
  40877. + case SOUND_MIXER_VOLUME:
  40878. + ucba->output_level = gain | gain << 8;
  40879. + ucba->mod_cnt++;
  40880. + ucba->ctrl_b = (ucba->ctrl_b & 0xff00) |
  40881. + ((gain * 31) / 100);
  40882. + ucb1x00_reg_write(ucba->ucb, UCB_AC_B,
  40883. + ucba->ctrl_b);
  40884. + ret = 0;
  40885. + break;
  40886. +
  40887. + case SOUND_MIXER_MIC:
  40888. + ucba->input_level = gain | gain << 8;
  40889. + ucba->mod_cnt++;
  40890. + ucba->ctrl_a = (ucba->ctrl_a & 0x7f) |
  40891. + (((gain * 31) / 100) << 7);
  40892. + ucb1x00_reg_write(ucba->ucb, UCB_AC_A,
  40893. + ucba->ctrl_a);
  40894. + ret = 0;
  40895. + break;
  40896. + }
  40897. + }
  40898. + }
  40899. +
  40900. + if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
  40901. + switch (_IOC_NR(cmd)) {
  40902. + case SOUND_MIXER_VOLUME:
  40903. + val = ucba->output_level;
  40904. + break;
  40905. +
  40906. + case SOUND_MIXER_MIC:
  40907. + val = ucba->input_level;
  40908. + break;
  40909. +
  40910. + case SOUND_MIXER_RECSRC:
  40911. + case SOUND_MIXER_RECMASK:
  40912. + val = ucba->telecom ? 0 : REC_MASK;
  40913. + break;
  40914. +
  40915. + case SOUND_MIXER_DEVMASK:
  40916. + val = ucba->telecom ? 0 : DEV_MASK;
  40917. + break;
  40918. +
  40919. + case SOUND_MIXER_CAPS:
  40920. + case SOUND_MIXER_STEREODEVS:
  40921. + val = 0;
  40922. + break;
  40923. +
  40924. + default:
  40925. + val = 0;
  40926. + ret = -EINVAL;
  40927. + break;
  40928. + }
  40929. +
  40930. + if (ret == 0)
  40931. + ret = put_user(val, (int *)arg);
  40932. + }
  40933. + out:
  40934. + return ret;
  40935. +}
  40936. +
  40937. +static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate)
  40938. +{
  40939. + unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32;
  40940. + unsigned int div;
  40941. +
  40942. + div = (div_rate + (rate / 2)) / rate;
  40943. + if (div < 6)
  40944. + div = 6;
  40945. + if (div > 127)
  40946. + div = 127;
  40947. +
  40948. + ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div;
  40949. +
  40950. + if (ucba->telecom) {
  40951. + ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0);
  40952. + ucb1x00_set_telecom_divisor(ucba->ucb, div * 32);
  40953. + ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a);
  40954. + ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b);
  40955. + } else {
  40956. + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0);
  40957. + ucb1x00_set_audio_divisor(ucba->ucb, div * 32);
  40958. + ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a);
  40959. + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b);
  40960. + }
  40961. +
  40962. + ucba->rate = div_rate / div;
  40963. +
  40964. + return ucba->rate;
  40965. +}
  40966. +
  40967. +static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba)
  40968. +{
  40969. + return ucba->rate;
  40970. +}
  40971. +
  40972. +static void ucb1x00_audio_startup(void *data)
  40973. +{
  40974. + struct ucb1x00_audio *ucba = data;
  40975. +
  40976. + ucb1x00_enable(ucba->ucb);
  40977. + ucb1x00_audio_setrate(ucba, ucba->rate);
  40978. +
  40979. + ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA);
  40980. +
  40981. + /*
  40982. + * Take off-hook
  40983. + */
  40984. + if (ucba->daa_oh_bit)
  40985. + ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit);
  40986. +}
  40987. +
  40988. +static void ucb1x00_audio_shutdown(void *data)
  40989. +{
  40990. + struct ucb1x00_audio *ucba = data;
  40991. +
  40992. + /*
  40993. + * Place on-hook
  40994. + */
  40995. + if (ucba->daa_oh_bit)
  40996. + ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0);
  40997. +
  40998. + ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0);
  40999. + ucb1x00_disable(ucba->ucb);
  41000. +}
  41001. +
  41002. +static int
  41003. +ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  41004. +{
  41005. + struct ucb1x00_audio *ucba;
  41006. + int val, ret = 0;
  41007. +
  41008. + ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
  41009. +
  41010. + /*
  41011. + * Make sure we have our magic number
  41012. + */
  41013. + if (ucba->magic != MAGIC)
  41014. + return -ENODEV;
  41015. +
  41016. + switch (cmd) {
  41017. + case SNDCTL_DSP_STEREO:
  41018. + ret = get_user(val, (int *)arg);
  41019. + if (ret)
  41020. + return ret;
  41021. + if (val != 0)
  41022. + return -EINVAL;
  41023. + val = 0;
  41024. + break;
  41025. +
  41026. + case SNDCTL_DSP_CHANNELS:
  41027. + case SOUND_PCM_READ_CHANNELS:
  41028. + val = 1;
  41029. + break;
  41030. +
  41031. + case SNDCTL_DSP_SPEED:
  41032. + ret = get_user(val, (int *)arg);
  41033. + if (ret)
  41034. + return ret;
  41035. + val = ucb1x00_audio_setrate(ucba, val);
  41036. + break;
  41037. +
  41038. + case SOUND_PCM_READ_RATE:
  41039. + val = ucb1x00_audio_getrate(ucba);
  41040. + break;
  41041. +
  41042. + case SNDCTL_DSP_SETFMT:
  41043. + case SNDCTL_DSP_GETFMTS:
  41044. + val = AFMT_S16_LE;
  41045. + break;
  41046. +
  41047. + default:
  41048. + return ucb1x00_mixer_ioctl(inode, file, cmd, arg);
  41049. + }
  41050. +
  41051. + return put_user(val, (int *)arg);
  41052. +}
  41053. +
  41054. +static int ucb1x00_audio_open(struct inode *inode, struct file *file)
  41055. +{
  41056. + struct ucb1x00_audio *ucba;
  41057. +
  41058. + ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
  41059. +
  41060. + return sa1100_audio_attach(inode, file, &ucba->state);
  41061. +}
  41062. +
  41063. +static struct ucb1x00_audio *ucb1x00_audio_alloc(struct ucb1x00 *ucb)
  41064. +{
  41065. + struct ucb1x00_audio *ucba;
  41066. +
  41067. + ucba = kmalloc(sizeof(*ucba), GFP_KERNEL);
  41068. + if (ucba) {
  41069. + memset(ucba, 0, sizeof(*ucba));
  41070. +
  41071. + ucba->magic = MAGIC;
  41072. + ucba->ucb = ucb;
  41073. + ucba->fops.owner = THIS_MODULE;
  41074. + ucba->fops.open = ucb1x00_audio_open;
  41075. + ucba->mops.owner = THIS_MODULE;
  41076. + ucba->mops.ioctl = ucb1x00_mixer_ioctl;
  41077. + ucba->state.output_stream = &ucba->output_stream;
  41078. + ucba->state.input_stream = &ucba->input_stream;
  41079. + ucba->state.data = ucba;
  41080. + ucba->state.hw_init = ucb1x00_audio_startup;
  41081. + ucba->state.hw_shutdown = ucb1x00_audio_shutdown;
  41082. + ucba->state.client_ioctl = ucb1x00_audio_ioctl;
  41083. +
  41084. + /* There is a bug in the StrongARM causes corrupt MCP data to be sent to
  41085. + * the codec when the FIFOs are empty and writes are made to the OS timer
  41086. + * match register 0. To avoid this we must make sure that data is always
  41087. + * sent to the codec.
  41088. + */
  41089. + ucba->state.need_tx_for_rx = 1;
  41090. +
  41091. + init_MUTEX(&ucba->state.sem);
  41092. + ucba->rate = 8000;
  41093. + }
  41094. + return ucba;
  41095. +}
  41096. +
  41097. +static struct ucb1x00_audio *audio, *telecom;
  41098. +
  41099. +static int __init ucb1x00_audio_init(void)
  41100. +{
  41101. + struct ucb1x00 *ucb = ucb1x00_get();
  41102. + struct ucb1x00_audio *a;
  41103. +
  41104. + if (!ucb)
  41105. + return -ENODEV;
  41106. +
  41107. + a = ucb1x00_audio_alloc(ucb);
  41108. + if (a) {
  41109. + a->state.input_dma = ucb->mcp->dma_audio_rd;
  41110. + a->state.input_id = "UCB1x00 audio in";
  41111. + a->state.output_dma = ucb->mcp->dma_audio_wr;
  41112. + a->state.output_id = "UCB1x00 audio out";
  41113. + a->dev_id = register_sound_dsp(&a->fops, -1);
  41114. + a->mix_id = register_sound_mixer(&a->mops, -1);
  41115. + a->ctrl_a = 0;
  41116. + a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA;
  41117. + audio = a;
  41118. + }
  41119. +
  41120. + a = ucb1x00_audio_alloc(ucb);
  41121. + if (a) {
  41122. +#if 0
  41123. + a->daa_oh_bit = UCB_IO_8;
  41124. +
  41125. + ucb1x00_enable(ucb);
  41126. + ucb1x00_io_write(ucb, a->daa_oh_bit, 0);
  41127. + ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit);
  41128. + ucb1x00_disable(ucb);
  41129. +#endif
  41130. +
  41131. + a->telecom = 1;
  41132. + a->state.input_dma = ucb->mcp->dma_telco_rd;
  41133. + a->state.input_id = "UCB1x00 telco in";
  41134. + a->state.output_dma = ucb->mcp->dma_telco_wr;
  41135. + a->state.output_id = "UCB1x00 telco out";
  41136. + a->dev_id = register_sound_dsp(&a->fops, -1);
  41137. + a->mix_id = register_sound_mixer(&a->mops, -1);
  41138. + a->ctrl_a = 0;
  41139. + a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA;
  41140. + telecom = a;
  41141. + }
  41142. +
  41143. + return 0;
  41144. +}
  41145. +
  41146. +static void __exit ucb1x00_audio_exit(void)
  41147. +{
  41148. + unregister_sound_dsp(telecom->dev_id);
  41149. + unregister_sound_dsp(audio->dev_id);
  41150. + unregister_sound_mixer(telecom->mix_id);
  41151. + unregister_sound_mixer(audio->mix_id);
  41152. +}
  41153. +
  41154. +module_init(ucb1x00_audio_init);
  41155. +module_exit(ucb1x00_audio_exit);
  41156. +
  41157. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  41158. +MODULE_DESCRIPTION("UCB1x00 telecom/audio driver");
  41159. +MODULE_LICENSE("GPL");
  41160. diff -urN linux-2.4.26/drivers/misc/ucb1x00-core.c linux-2.4.26-vrs1/drivers/misc/ucb1x00-core.c
  41161. --- linux-2.4.26/drivers/misc/ucb1x00-core.c 1970-01-01 01:00:00.000000000 +0100
  41162. +++ linux-2.4.26-vrs1/drivers/misc/ucb1x00-core.c 2004-01-14 21:32:25.000000000 +0000
  41163. @@ -0,0 +1,651 @@
  41164. +/*
  41165. + * linux/drivers/misc/ucb1x00-core.c
  41166. + *
  41167. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  41168. + *
  41169. + * This program is free software; you can redistribute it and/or modify
  41170. + * it under the terms of the GNU General Public License as published by
  41171. + * the Free Software Foundation; either version 2 of the License.
  41172. + *
  41173. + * The UCB1x00 core driver provides basic services for handling IO,
  41174. + * the ADC, interrupts, and accessing registers. It is designed
  41175. + * such that everything goes through this layer, thereby providing
  41176. + * a consistent locking methodology, as well as allowing the drivers
  41177. + * to be used on other non-MCP-enabled hardware platforms.
  41178. + *
  41179. + * Note that all locks are private to this file. Nothing else may
  41180. + * touch them.
  41181. + */
  41182. +#include <linux/module.h>
  41183. +#include <linux/kernel.h>
  41184. +#include <linux/slab.h>
  41185. +#include <linux/init.h>
  41186. +#include <linux/errno.h>
  41187. +#include <linux/interrupt.h>
  41188. +#include <linux/pm.h>
  41189. +
  41190. +#include <asm/dma.h>
  41191. +#include <asm/hardware.h>
  41192. +#include <asm/irq.h>
  41193. +#include <asm/mach-types.h>
  41194. +#include <asm/arch/shannon.h>
  41195. +
  41196. +#include "ucb1x00.h"
  41197. +
  41198. +/**
  41199. + * ucb1x00_io_set_dir - set IO direction
  41200. + * @ucb: UCB1x00 structure describing chip
  41201. + * @in: bitfield of IO pins to be set as inputs
  41202. + * @out: bitfield of IO pins to be set as outputs
  41203. + *
  41204. + * Set the IO direction of the ten general purpose IO pins on
  41205. + * the UCB1x00 chip. The @in bitfield has priority over the
  41206. + * @out bitfield, in that if you specify a pin as both input
  41207. + * and output, it will end up as an input.
  41208. + *
  41209. + * ucb1x00_enable must have been called to enable the comms
  41210. + * before using this function.
  41211. + *
  41212. + * This function takes a spinlock, disabling interrupts.
  41213. + */
  41214. +void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
  41215. +{
  41216. + unsigned long flags;
  41217. +
  41218. + spin_lock_irqsave(&ucb->io_lock, flags);
  41219. + ucb->io_dir |= out;
  41220. + ucb->io_dir &= ~in;
  41221. +
  41222. + ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
  41223. + spin_unlock_irqrestore(&ucb->io_lock, flags);
  41224. +}
  41225. +
  41226. +/**
  41227. + * ucb1x00_io_write - set or clear IO outputs
  41228. + * @ucb: UCB1x00 structure describing chip
  41229. + * @set: bitfield of IO pins to set to logic '1'
  41230. + * @clear: bitfield of IO pins to set to logic '0'
  41231. + *
  41232. + * Set the IO output state of the specified IO pins. The value
  41233. + * is retained if the pins are subsequently configured as inputs.
  41234. + * The @clear bitfield has priority over the @set bitfield -
  41235. + * outputs will be cleared.
  41236. + *
  41237. + * ucb1x00_enable must have been called to enable the comms
  41238. + * before using this function.
  41239. + *
  41240. + * This function takes a spinlock, disabling interrupts.
  41241. + */
  41242. +void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
  41243. +{
  41244. + unsigned long flags;
  41245. +
  41246. + spin_lock_irqsave(&ucb->io_lock, flags);
  41247. + ucb->io_out |= set;
  41248. + ucb->io_out &= ~clear;
  41249. +
  41250. + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
  41251. + spin_unlock_irqrestore(&ucb->io_lock, flags);
  41252. +}
  41253. +
  41254. +/**
  41255. + * ucb1x00_io_read - read the current state of the IO pins
  41256. + * @ucb: UCB1x00 structure describing chip
  41257. + *
  41258. + * Return a bitfield describing the logic state of the ten
  41259. + * general purpose IO pins.
  41260. + *
  41261. + * ucb1x00_enable must have been called to enable the comms
  41262. + * before using this function.
  41263. + *
  41264. + * This function does not take any semaphores or spinlocks.
  41265. + */
  41266. +unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
  41267. +{
  41268. + return ucb1x00_reg_read(ucb, UCB_IO_DATA);
  41269. +}
  41270. +
  41271. +/*
  41272. + * UCB1300 data sheet says we must:
  41273. + * 1. enable ADC => 5us (including reference startup time)
  41274. + * 2. select input => 51*tsibclk => 4.3us
  41275. + * 3. start conversion => 102*tsibclk => 8.5us
  41276. + * (tsibclk = 1/11981000)
  41277. + * Period between SIB 128-bit frames = 10.7us
  41278. + */
  41279. +
  41280. +/**
  41281. + * ucb1x00_adc_enable - enable the ADC converter
  41282. + * @ucb: UCB1x00 structure describing chip
  41283. + *
  41284. + * Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
  41285. + * Any code wishing to use the ADC converter must call this
  41286. + * function prior to using it.
  41287. + *
  41288. + * This function takes the ADC semaphore to prevent two or more
  41289. + * concurrent uses, and therefore may sleep. As a result, it
  41290. + * can only be called from process context, not interrupt
  41291. + * context.
  41292. + *
  41293. + * You should release the ADC as soon as possible using
  41294. + * ucb1x00_adc_disable.
  41295. + */
  41296. +void ucb1x00_adc_enable(struct ucb1x00 *ucb)
  41297. +{
  41298. + down(&ucb->adc_sem);
  41299. +
  41300. + ucb->adc_cr |= UCB_ADC_ENA;
  41301. +
  41302. + ucb1x00_enable(ucb);
  41303. + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
  41304. +}
  41305. +
  41306. +/**
  41307. + * ucb1x00_adc_read - read the specified ADC channel
  41308. + * @ucb: UCB1x00 structure describing chip
  41309. + * @adc_channel: ADC channel mask
  41310. + * @sync: wait for syncronisation pulse.
  41311. + *
  41312. + * Start an ADC conversion and wait for the result. Note that
  41313. + * synchronised ADC conversions (via the ADCSYNC pin) must wait
  41314. + * until the trigger is asserted and the conversion is finished.
  41315. + *
  41316. + * This function currently spins waiting for the conversion to
  41317. + * complete (2 frames max without sync).
  41318. + *
  41319. + * If called for a synchronised ADC conversion, it may sleep
  41320. + * with the ADC semaphore held.
  41321. + */
  41322. +unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
  41323. +{
  41324. + unsigned int val;
  41325. +
  41326. + if (sync)
  41327. + adc_channel |= UCB_ADC_SYNC_ENA;
  41328. +
  41329. + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
  41330. + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
  41331. +
  41332. + for (;;) {
  41333. + val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
  41334. + if (val & UCB_ADC_DAT_VAL)
  41335. + break;
  41336. + /* yield to other processes */
  41337. + set_current_state(TASK_INTERRUPTIBLE);
  41338. + schedule_timeout(1);
  41339. + }
  41340. +
  41341. + return UCB_ADC_DAT(val);
  41342. +}
  41343. +
  41344. +/**
  41345. + * ucb1x00_adc_disable - disable the ADC converter
  41346. + * @ucb: UCB1x00 structure describing chip
  41347. + *
  41348. + * Disable the ADC converter and release the ADC semaphore.
  41349. + */
  41350. +void ucb1x00_adc_disable(struct ucb1x00 *ucb)
  41351. +{
  41352. + ucb->adc_cr &= ~UCB_ADC_ENA;
  41353. + ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
  41354. + ucb1x00_disable(ucb);
  41355. +
  41356. + up(&ucb->adc_sem);
  41357. +}
  41358. +
  41359. +#ifdef CONFIG_PM
  41360. +static int ucb1x00_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
  41361. +{
  41362. + struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data;
  41363. + unsigned int isr;
  41364. +
  41365. + if (rqst == PM_RESUME) {
  41366. + ucb1x00_enable(ucb);
  41367. + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
  41368. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
  41369. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
  41370. + ucb1x00_disable(ucb);
  41371. + }
  41372. +
  41373. + return 0;
  41374. +}
  41375. +#endif
  41376. +
  41377. +/*
  41378. + * UCB1x00 Interrupt handling.
  41379. + *
  41380. + * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
  41381. + * Since we need to read an internal register, we must re-enable
  41382. + * SIBCLK to talk to the chip. We leave the clock running until
  41383. + * we have finished processing all interrupts from the chip.
  41384. + */
  41385. +static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
  41386. +{
  41387. + struct ucb1x00 *ucb = devid;
  41388. + struct ucb1x00_irq *irq;
  41389. + unsigned int isr, i;
  41390. +
  41391. + ucb1x00_enable(ucb);
  41392. + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
  41393. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
  41394. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
  41395. +
  41396. + for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
  41397. + if (isr & 1 && irq->fn)
  41398. + irq->fn(i, irq->devid);
  41399. + ucb1x00_disable(ucb);
  41400. +}
  41401. +
  41402. +/**
  41403. + * ucb1x00_hook_irq - hook a UCB1x00 interrupt
  41404. + * @ucb: UCB1x00 structure describing chip
  41405. + * @idx: interrupt index
  41406. + * @fn: function to call when interrupt is triggered
  41407. + * @devid: device id to pass to interrupt handler
  41408. + *
  41409. + * Hook the specified interrupt. You can only register one handler
  41410. + * for each interrupt source. The interrupt source is not enabled
  41411. + * by this function; use ucb1x00_enable_irq instead.
  41412. + *
  41413. + * Interrupt handlers will be called with other interrupts enabled.
  41414. + *
  41415. + * Returns zero on success, or one of the following errors:
  41416. + * -EINVAL if the interrupt index is invalid
  41417. + * -EBUSY if the interrupt has already been hooked
  41418. + */
  41419. +int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
  41420. +{
  41421. + struct ucb1x00_irq *irq;
  41422. + int ret = -EINVAL;
  41423. +
  41424. + if (idx < 16) {
  41425. + irq = ucb->irq_handler + idx;
  41426. + ret = -EBUSY;
  41427. +
  41428. + spin_lock_irq(&ucb->lock);
  41429. + if (irq->fn == NULL) {
  41430. + irq->devid = devid;
  41431. + irq->fn = fn;
  41432. + ret = 0;
  41433. + }
  41434. + spin_unlock_irq(&ucb->lock);
  41435. + }
  41436. + return ret;
  41437. +}
  41438. +
  41439. +/**
  41440. + * ucb1x00_enable_irq - enable an UCB1x00 interrupt source
  41441. + * @ucb: UCB1x00 structure describing chip
  41442. + * @idx: interrupt index
  41443. + * @edges: interrupt edges to enable
  41444. + *
  41445. + * Enable the specified interrupt to trigger on %UCB_RISING,
  41446. + * %UCB_FALLING or both edges. The interrupt should have been
  41447. + * hooked by ucb1x00_hook_irq.
  41448. + */
  41449. +void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
  41450. +{
  41451. + unsigned long flags;
  41452. +
  41453. + if (idx < 16) {
  41454. + spin_lock_irqsave(&ucb->lock, flags);
  41455. +
  41456. + ucb1x00_enable(ucb);
  41457. + if (edges & UCB_RISING) {
  41458. + ucb->irq_ris_enbl |= 1 << idx;
  41459. + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
  41460. + }
  41461. + if (edges & UCB_FALLING) {
  41462. + ucb->irq_fal_enbl |= 1 << idx;
  41463. + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
  41464. + }
  41465. + ucb1x00_disable(ucb);
  41466. + spin_unlock_irqrestore(&ucb->lock, flags);
  41467. + }
  41468. +}
  41469. +
  41470. +/**
  41471. + * ucb1x00_disable_irq - disable an UCB1x00 interrupt source
  41472. + * @ucb: UCB1x00 structure describing chip
  41473. + * @edges: interrupt edges to disable
  41474. + *
  41475. + * Disable the specified interrupt triggering on the specified
  41476. + * (%UCB_RISING, %UCB_FALLING or both) edges.
  41477. + */
  41478. +void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
  41479. +{
  41480. + unsigned long flags;
  41481. +
  41482. + if (idx < 16) {
  41483. + spin_lock_irqsave(&ucb->lock, flags);
  41484. +
  41485. + ucb1x00_enable(ucb);
  41486. + if (edges & UCB_RISING) {
  41487. + ucb->irq_ris_enbl &= ~(1 << idx);
  41488. + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
  41489. + }
  41490. + if (edges & UCB_FALLING) {
  41491. + ucb->irq_fal_enbl &= ~(1 << idx);
  41492. + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
  41493. + }
  41494. + ucb1x00_disable(ucb);
  41495. + spin_unlock_irqrestore(&ucb->lock, flags);
  41496. + }
  41497. +}
  41498. +
  41499. +/**
  41500. + * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
  41501. + * @ucb: UCB1x00 structure describing chip
  41502. + * @idx: interrupt index
  41503. + * @devid: device id.
  41504. + *
  41505. + * Disable the interrupt source and remove the handler. devid must
  41506. + * match the devid passed when hooking the interrupt.
  41507. + *
  41508. + * Returns zero on success, or one of the following errors:
  41509. + * -EINVAL if the interrupt index is invalid
  41510. + * -ENOENT if devid does not match
  41511. + */
  41512. +int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
  41513. +{
  41514. + struct ucb1x00_irq *irq;
  41515. + int ret;
  41516. +
  41517. + if (idx >= 16)
  41518. + goto bad;
  41519. +
  41520. + irq = ucb->irq_handler + idx;
  41521. + ret = -ENOENT;
  41522. +
  41523. + spin_lock_irq(&ucb->lock);
  41524. + if (irq->devid == devid) {
  41525. + ucb->irq_ris_enbl &= ~(1 << idx);
  41526. + ucb->irq_fal_enbl &= ~(1 << idx);
  41527. +
  41528. + ucb1x00_enable(ucb);
  41529. + ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
  41530. + ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
  41531. + ucb1x00_disable(ucb);
  41532. +
  41533. + irq->fn = NULL;
  41534. + irq->devid = NULL;
  41535. + ret = 0;
  41536. + }
  41537. + spin_unlock_irq(&ucb->lock);
  41538. + return ret;
  41539. +
  41540. +bad:
  41541. + printk(KERN_ERR "%s: freeing bad irq %d\n", __FUNCTION__, idx);
  41542. + return -EINVAL;
  41543. +}
  41544. +
  41545. +/*
  41546. + * Try to probe our interrupt, rather than relying on lots of
  41547. + * hard-coded machine dependencies. For reference, the expected
  41548. + * IRQ mappings are:
  41549. + *
  41550. + * Machine Default IRQ
  41551. + * adsbitsy IRQ_GPCIN4
  41552. + * cerf IRQ_GPIO_UCB1200_IRQ
  41553. + * flexanet IRQ_GPIO_GUI
  41554. + * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ
  41555. + * graphicsclient IRQ_GRAPHICSCLIENT_UCB1200
  41556. + * graphicsmaster IRQ_GRAPHICSMASTER_UCB1200
  41557. + * lart LART_IRQ_UCB1200
  41558. + * omnimeter IRQ_GPIO23
  41559. + * pfs168 IRQ_GPIO_UCB1300_IRQ
  41560. + * simpad IRQ_GPIO_UCB1300_IRQ
  41561. + * shannon SHANNON_IRQ_GPIO_IRQ_CODEC
  41562. + * yopy IRQ_GPIO_UCB1200_IRQ
  41563. + */
  41564. +static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb)
  41565. +{
  41566. + unsigned long mask;
  41567. +
  41568. + mask = probe_irq_on();
  41569. + if (!mask)
  41570. + return NO_IRQ;
  41571. +
  41572. + /*
  41573. + * Enable the ADC interrupt.
  41574. + */
  41575. + ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
  41576. + ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
  41577. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
  41578. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
  41579. +
  41580. + /*
  41581. + * Cause an ADC interrupt.
  41582. + */
  41583. + ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
  41584. + ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
  41585. +
  41586. + /*
  41587. + * Wait for the conversion to complete.
  41588. + */
  41589. + while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
  41590. + ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
  41591. +
  41592. + /*
  41593. + * Disable and clear interrupt.
  41594. + */
  41595. + ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
  41596. + ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
  41597. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
  41598. + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
  41599. +
  41600. + /*
  41601. + * Read triggered interrupt.
  41602. + */
  41603. + return probe_irq_off(mask);
  41604. +}
  41605. +
  41606. +/*
  41607. + * This configures the UCB1x00 layer depending on the machine type
  41608. + * we're running on. The UCB1x00 drivers should not contain any
  41609. + * machine dependencies.
  41610. + *
  41611. + * We can get rid of some of these dependencies by using existing
  41612. + * facilities provided by the kernel - namely IRQ probing. The
  41613. + * machine specific files are expected to setup the IRQ levels on
  41614. + * initialisation. With any luck, we'll get rid of all the
  41615. + * machine dependencies here.
  41616. + */
  41617. +static int __init ucb1x00_configure(struct ucb1x00 *ucb)
  41618. +{
  41619. + unsigned int irq_gpio_pin = 0;
  41620. + int irq, default_irq = NO_IRQ;
  41621. +
  41622. + if (machine_is_adsbitsy())
  41623. + default_irq = IRQ_GPCIN4;
  41624. +
  41625. +// if (machine_is_assabet())
  41626. +// default_irq = IRQ_GPIO23;
  41627. +
  41628. +#ifdef CONFIG_SA1100_CERF
  41629. + if (machine_is_cerf())
  41630. + default_irq = IRQ_GPIO_UCB1200_IRQ;
  41631. +#endif
  41632. +#ifdef CONFIG_SA1100_FREEBIRD
  41633. + if (machine_is_freebird())
  41634. + default_irq = IRQ_GPIO_FREEBIRD_UCB1300_IRQ;
  41635. +#endif
  41636. +#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
  41637. +// if (machine_is_graphicsclient())
  41638. +// default_irq = IRQ_GRAPHICSCLIENT_UCB1200;
  41639. +#endif
  41640. +#if defined(CONFIG_SA1100_GRAPICSMASTER)
  41641. + if (machine_is_graphicsmaster())
  41642. + default_irq = IRQ_GRAPHICSMASTER_UCB1200;
  41643. +#endif
  41644. +#ifdef CONFIG_SA1100_LART
  41645. + if (machine_is_lart()) {
  41646. + default_irq = LART_IRQ_UCB1200;
  41647. + irq_gpio_pin = LART_GPIO_UCB1200;
  41648. + }
  41649. +#endif
  41650. + if (machine_is_omnimeter())
  41651. + default_irq = IRQ_GPIO23;
  41652. +
  41653. +#ifdef CONFIG_SA1100_PFS168
  41654. + if (machine_is_pfs168())
  41655. + default_irq = IRQ_GPIO_UCB1300_IRQ;
  41656. +#endif
  41657. +#ifdef CONFIG_SA1100_SIMPAD
  41658. + if (machine_is_simpad())
  41659. + default_irq = IRQ_GPIO_UCB1300_IRQ;
  41660. +#endif
  41661. +#ifdef CONFIG_SA1100_SIMPUTER
  41662. + if (machine_is_simputer()) {
  41663. + default_irq = IRQ_GPIO_UCB1300_IRQ;
  41664. + irq_gpio_pin = GPIO_UCB1300_IRQ;
  41665. + }
  41666. +#endif
  41667. + if (machine_is_shannon())
  41668. + default_irq = SHANNON_IRQ_GPIO_IRQ_CODEC;
  41669. +#ifdef CONFIG_SA1100_YOPY
  41670. + if (machine_is_yopy())
  41671. + default_irq = IRQ_GPIO_UCB1200_IRQ;
  41672. +#endif
  41673. +#ifdef CONFIG_SA1100_ACCELENT
  41674. + if (machine_is_accelent_sa()) {
  41675. + ucb->irq = IRQ_GPIO_UCB1200_IRQ;
  41676. + irq_gpio_pin = GPIO_UCB1200_IRQ;
  41677. + }
  41678. +#endif
  41679. +
  41680. + /*
  41681. + * Eventually, this will disappear.
  41682. + */
  41683. + if (irq_gpio_pin)
  41684. + set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
  41685. +
  41686. + irq = ucb1x00_detect_irq(ucb);
  41687. + if (irq != NO_IRQ) {
  41688. + if (default_irq != NO_IRQ && irq != default_irq)
  41689. + printk(KERN_ERR "UCB1x00: probed IRQ%d != default IRQ%d\n",
  41690. + irq, default_irq);
  41691. + if (irq == default_irq)
  41692. + printk(KERN_ERR "UCB1x00: probed IRQ%d correctly. "
  41693. + "Please remove machine dependencies from "
  41694. + "ucb1x00-core.c\n", irq);
  41695. + ucb->irq = irq;
  41696. + } else {
  41697. + printk(KERN_ERR "UCB1x00: IRQ probe failed, using IRQ%d\n",
  41698. + default_irq);
  41699. + ucb->irq = default_irq;
  41700. + }
  41701. +
  41702. + return ucb->irq == NO_IRQ ? -ENODEV : 0;
  41703. +}
  41704. +
  41705. +struct ucb1x00 *my_ucb;
  41706. +
  41707. +/**
  41708. + * ucb1x00_get - get the UCB1x00 structure describing a chip
  41709. + * @ucb: UCB1x00 structure describing chip
  41710. + *
  41711. + * Return the UCB1x00 structure describing a chip.
  41712. + *
  41713. + * FIXME: Currently very noddy indeed, which currently doesn't
  41714. + * matter since we only support one chip.
  41715. + */
  41716. +struct ucb1x00 *ucb1x00_get(void)
  41717. +{
  41718. + return my_ucb;
  41719. +}
  41720. +
  41721. +static int __init ucb1x00_init(void)
  41722. +{
  41723. + struct mcp *mcp;
  41724. + unsigned int id;
  41725. + int ret = -ENODEV;
  41726. +
  41727. + mcp = mcp_get();
  41728. + if (!mcp)
  41729. + goto no_mcp;
  41730. +
  41731. + mcp_enable(mcp);
  41732. + id = mcp_reg_read(mcp, UCB_ID);
  41733. +
  41734. + if (id != UCB_ID_1200 && id != UCB_ID_1300) {
  41735. + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
  41736. + goto out;
  41737. + }
  41738. +
  41739. + my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
  41740. + ret = -ENOMEM;
  41741. + if (!my_ucb)
  41742. + goto out;
  41743. +
  41744. + if (machine_is_shannon()) {
  41745. + /* reset the codec */
  41746. + GPDR |= SHANNON_GPIO_CODEC_RESET;
  41747. + GPCR = SHANNON_GPIO_CODEC_RESET;
  41748. + GPSR = SHANNON_GPIO_CODEC_RESET;
  41749. +
  41750. + }
  41751. +
  41752. + memset(my_ucb, 0, sizeof(struct ucb1x00));
  41753. +
  41754. + spin_lock_init(&my_ucb->lock);
  41755. + spin_lock_init(&my_ucb->io_lock);
  41756. + sema_init(&my_ucb->adc_sem, 1);
  41757. +
  41758. + my_ucb->id = id;
  41759. + my_ucb->mcp = mcp;
  41760. +
  41761. + ret = ucb1x00_configure(my_ucb);
  41762. + if (ret)
  41763. + goto out;
  41764. +
  41765. + ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
  41766. + if (ret) {
  41767. + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
  41768. + my_ucb->irq, ret);
  41769. + kfree(my_ucb);
  41770. + my_ucb = NULL;
  41771. + goto out;
  41772. + }
  41773. +
  41774. +#ifdef CONFIG_PM
  41775. + my_ucb->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_pm);
  41776. + if (my_ucb->pmdev == NULL)
  41777. + printk("ucb1x00: unable to register in PM.\n");
  41778. + else
  41779. + my_ucb->pmdev->data = my_ucb;
  41780. +#endif
  41781. +
  41782. +out:
  41783. + mcp_disable(mcp);
  41784. +no_mcp:
  41785. + return ret;
  41786. +}
  41787. +
  41788. +static void __exit ucb1x00_exit(void)
  41789. +{
  41790. + free_irq(my_ucb->irq, my_ucb);
  41791. + kfree(my_ucb);
  41792. +}
  41793. +
  41794. +module_init(ucb1x00_init);
  41795. +module_exit(ucb1x00_exit);
  41796. +
  41797. +EXPORT_SYMBOL(ucb1x00_get);
  41798. +
  41799. +EXPORT_SYMBOL(ucb1x00_io_set_dir);
  41800. +EXPORT_SYMBOL(ucb1x00_io_write);
  41801. +EXPORT_SYMBOL(ucb1x00_io_read);
  41802. +
  41803. +EXPORT_SYMBOL(ucb1x00_adc_enable);
  41804. +EXPORT_SYMBOL(ucb1x00_adc_read);
  41805. +EXPORT_SYMBOL(ucb1x00_adc_disable);
  41806. +
  41807. +EXPORT_SYMBOL(ucb1x00_hook_irq);
  41808. +EXPORT_SYMBOL(ucb1x00_free_irq);
  41809. +EXPORT_SYMBOL(ucb1x00_enable_irq);
  41810. +EXPORT_SYMBOL(ucb1x00_disable_irq);
  41811. +
  41812. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  41813. +MODULE_DESCRIPTION("UCB1x00 core driver");
  41814. +MODULE_LICENSE("GPL");
  41815. diff -urN linux-2.4.26/drivers/misc/ucb1x00-ts.c linux-2.4.26-vrs1/drivers/misc/ucb1x00-ts.c
  41816. --- linux-2.4.26/drivers/misc/ucb1x00-ts.c 1970-01-01 01:00:00.000000000 +0100
  41817. +++ linux-2.4.26-vrs1/drivers/misc/ucb1x00-ts.c 2004-01-14 21:32:25.000000000 +0000
  41818. @@ -0,0 +1,664 @@
  41819. +/*
  41820. + * linux/drivers/misc/ucb1x00-ts.c
  41821. + *
  41822. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  41823. + *
  41824. + * This program is free software; you can redistribute it and/or modify
  41825. + * it under the terms of the GNU General Public License version 2 as
  41826. + * published by the Free Software Foundation.
  41827. + *
  41828. + * 21-Jan-2002 <jco@ict.es> :
  41829. + *
  41830. + * Added support for synchronous A/D mode. This mode is useful to
  41831. + * avoid noise induced in the touchpanel by the LCD, provided that
  41832. + * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
  41833. + * It is important to note that the signal connected to the ADCSYNC
  41834. + * pin should provide pulses even when the LCD is blanked, otherwise
  41835. + * a pen touch needed to unblank the LCD will never be read.
  41836. + */
  41837. +#include <linux/config.h>
  41838. +#include <linux/module.h>
  41839. +#include <linux/init.h>
  41840. +#include <linux/smp.h>
  41841. +#include <linux/smp_lock.h>
  41842. +#include <linux/sched.h>
  41843. +#include <linux/completion.h>
  41844. +#include <linux/delay.h>
  41845. +#include <linux/string.h>
  41846. +#include <linux/pm.h>
  41847. +
  41848. +#include <asm/dma.h>
  41849. +#include <asm/semaphore.h>
  41850. +
  41851. +#include "ucb1x00.h"
  41852. +
  41853. +/*
  41854. + * Define this if you want the UCB1x00 stuff to talk to the input layer
  41855. + */
  41856. +#undef USE_INPUT
  41857. +
  41858. +#ifndef USE_INPUT
  41859. +
  41860. +#include <linux/fs.h>
  41861. +#include <linux/miscdevice.h>
  41862. +#include <linux/poll.h>
  41863. +
  41864. +/*
  41865. + * This structure is nonsense - millisecs is not very useful
  41866. + * since the field size is too small. Also, we SHOULD NOT
  41867. + * be exposing jiffies to user space directly.
  41868. + */
  41869. +struct ts_event {
  41870. + u16 pressure;
  41871. + u16 x;
  41872. + u16 y;
  41873. + u16 pad;
  41874. + struct timeval stamp;
  41875. +};
  41876. +
  41877. +#define NR_EVENTS 16
  41878. +
  41879. +#else
  41880. +
  41881. +#include <linux/input.h>
  41882. +
  41883. +#endif
  41884. +
  41885. +struct ucb1x00_ts {
  41886. +#ifdef USE_INPUT
  41887. + struct input_dev idev;
  41888. +#endif
  41889. + struct ucb1x00 *ucb;
  41890. +#ifdef CONFIG_PM
  41891. + struct pm_dev *pmdev;
  41892. +#endif
  41893. +
  41894. + wait_queue_head_t irq_wait;
  41895. + struct semaphore sem;
  41896. + struct completion init_exit;
  41897. + struct task_struct *rtask;
  41898. + int use_count;
  41899. + u16 x_res;
  41900. + u16 y_res;
  41901. +
  41902. +#ifndef USE_INPUT
  41903. + struct fasync_struct *fasync;
  41904. + wait_queue_head_t read_wait;
  41905. + u8 evt_head;
  41906. + u8 evt_tail;
  41907. + struct ts_event events[NR_EVENTS];
  41908. +#endif
  41909. + int restart:1;
  41910. + int adcsync:1;
  41911. +};
  41912. +
  41913. +static struct ucb1x00_ts ucbts;
  41914. +static int adcsync = UCB_NOSYNC;
  41915. +
  41916. +static int ucb1x00_ts_startup(struct ucb1x00_ts *ts);
  41917. +static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts);
  41918. +
  41919. +#ifndef USE_INPUT
  41920. +
  41921. +#define ucb1x00_ts_evt_pending(ts) ((volatile u8)(ts)->evt_head != (ts)->evt_tail)
  41922. +#define ucb1x00_ts_evt_get(ts) ((ts)->events + (ts)->evt_tail)
  41923. +#define ucb1x00_ts_evt_pull(ts) ((ts)->evt_tail = ((ts)->evt_tail + 1) & (NR_EVENTS - 1))
  41924. +#define ucb1x00_ts_evt_clear(ts) ((ts)->evt_head = (ts)->evt_tail = 0)
  41925. +
  41926. +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
  41927. +{
  41928. + int next_head;
  41929. +
  41930. + next_head = (ts->evt_head + 1) & (NR_EVENTS - 1);
  41931. + if (next_head != ts->evt_tail) {
  41932. + ts->events[ts->evt_head].pressure = pressure;
  41933. + ts->events[ts->evt_head].x = x;
  41934. + ts->events[ts->evt_head].y = y;
  41935. + do_gettimeofday(&ts->events[ts->evt_head].stamp);
  41936. + ts->evt_head = next_head;
  41937. +
  41938. + if (ts->fasync)
  41939. + kill_fasync(&ts->fasync, SIGIO, POLL_IN);
  41940. + wake_up_interruptible(&ts->read_wait);
  41941. + }
  41942. +}
  41943. +
  41944. +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
  41945. +{
  41946. + ucb1x00_ts_evt_add(ts, 0, 0, 0);
  41947. +}
  41948. +
  41949. +/*
  41950. + * User space driver interface.
  41951. + */
  41952. +static ssize_t
  41953. +ucb1x00_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
  41954. +{
  41955. + DECLARE_WAITQUEUE(wait, current);
  41956. + struct ucb1x00_ts *ts = filp->private_data;
  41957. + char *ptr = buffer;
  41958. + int err = 0;
  41959. +
  41960. + add_wait_queue(&ts->read_wait, &wait);
  41961. + while (count >= sizeof(struct ts_event)) {
  41962. + err = -ERESTARTSYS;
  41963. + if (signal_pending(current))
  41964. + break;
  41965. +
  41966. + if (ucb1x00_ts_evt_pending(ts)) {
  41967. + struct ts_event *evt = ucb1x00_ts_evt_get(ts);
  41968. +
  41969. + err = copy_to_user(ptr, evt, sizeof(struct ts_event));
  41970. + ucb1x00_ts_evt_pull(ts);
  41971. +
  41972. + if (err)
  41973. + break;
  41974. +
  41975. + ptr += sizeof(struct ts_event);
  41976. + count -= sizeof(struct ts_event);
  41977. + continue;
  41978. + }
  41979. +
  41980. + set_current_state(TASK_INTERRUPTIBLE);
  41981. + err = -EAGAIN;
  41982. + if (filp->f_flags & O_NONBLOCK)
  41983. + break;
  41984. + schedule();
  41985. + }
  41986. + current->state = TASK_RUNNING;
  41987. + remove_wait_queue(&ts->read_wait, &wait);
  41988. +
  41989. + return ptr == buffer ? err : ptr - buffer;
  41990. +}
  41991. +
  41992. +static unsigned int ucb1x00_ts_poll(struct file *filp, poll_table *wait)
  41993. +{
  41994. + struct ucb1x00_ts *ts = filp->private_data;
  41995. + int ret = 0;
  41996. +
  41997. + poll_wait(filp, &ts->read_wait, wait);
  41998. + if (ucb1x00_ts_evt_pending(ts))
  41999. + ret = POLLIN | POLLRDNORM;
  42000. +
  42001. + return ret;
  42002. +}
  42003. +
  42004. +static int ucb1x00_ts_fasync(int fd, struct file *filp, int on)
  42005. +{
  42006. + struct ucb1x00_ts *ts = filp->private_data;
  42007. +
  42008. + return fasync_helper(fd, filp, on, &ts->fasync);
  42009. +}
  42010. +
  42011. +static int ucb1x00_ts_open(struct inode *inode, struct file *filp)
  42012. +{
  42013. + struct ucb1x00_ts *ts = &ucbts;
  42014. + int ret = 0;
  42015. +
  42016. + ret = ucb1x00_ts_startup(ts);
  42017. + if (ret == 0)
  42018. + filp->private_data = ts;
  42019. +
  42020. + return ret;
  42021. +}
  42022. +
  42023. +/*
  42024. + * Release touchscreen resources. Disable IRQs.
  42025. + */
  42026. +static int ucb1x00_ts_release(struct inode *inode, struct file *filp)
  42027. +{
  42028. + struct ucb1x00_ts *ts = filp->private_data;
  42029. +
  42030. + down(&ts->sem);
  42031. + ucb1x00_ts_fasync(-1, filp, 0);
  42032. + ucb1x00_ts_shutdown(ts);
  42033. + up(&ts->sem);
  42034. +
  42035. + return 0;
  42036. +}
  42037. +
  42038. +static struct file_operations ucb1x00_fops = {
  42039. + owner: THIS_MODULE,
  42040. + read: ucb1x00_ts_read,
  42041. + poll: ucb1x00_ts_poll,
  42042. + open: ucb1x00_ts_open,
  42043. + release: ucb1x00_ts_release,
  42044. + fasync: ucb1x00_ts_fasync,
  42045. +};
  42046. +
  42047. +/*
  42048. + * The official UCB1x00 touchscreen is a miscdevice:
  42049. + * 10 char Non-serial mice, misc features
  42050. + * 14 = /dev/touchscreen/ucb1x00 UCB 1x00 touchscreen
  42051. + */
  42052. +static struct miscdevice ucb1x00_ts_dev = {
  42053. + minor: 14,
  42054. + name: "touchscreen/ucb1x00",
  42055. + fops: &ucb1x00_fops,
  42056. +};
  42057. +
  42058. +static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
  42059. +{
  42060. + init_waitqueue_head(&ts->read_wait);
  42061. + return misc_register(&ucb1x00_ts_dev);
  42062. +}
  42063. +
  42064. +static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
  42065. +{
  42066. + misc_deregister(&ucb1x00_ts_dev);
  42067. +}
  42068. +
  42069. +#else
  42070. +
  42071. +#define ucb1x00_ts_evt_clear(ts) do { } while (0)
  42072. +
  42073. +static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
  42074. +{
  42075. + input_report_abs(&ts->idev, ABS_X, x);
  42076. + input_report_abs(&ts->idev, ABS_Y, y);
  42077. + input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
  42078. +}
  42079. +
  42080. +static int ucb1x00_ts_open(struct input_dev *idev)
  42081. +{
  42082. + struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
  42083. +
  42084. + return ucb1x00_ts_startup(ts);
  42085. +}
  42086. +
  42087. +static void ucb1x00_ts_close(struct input_dev *idev)
  42088. +{
  42089. + struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
  42090. +
  42091. + down(&ts->sem);
  42092. + ucb1x00_ts_shutdown(ts);
  42093. + up(&ts->sem);
  42094. +}
  42095. +
  42096. +static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
  42097. +{
  42098. + ts->idev.name = "Touchscreen panel";
  42099. + ts->idev.idproduct = ts->ucb->id;
  42100. + ts->idev.open = ucb1x00_ts_open;
  42101. + ts->idev.close = ucb1x00_ts_close;
  42102. +
  42103. + __set_bit(EV_ABS, ts->idev.evbit);
  42104. + __set_bit(ABS_X, ts->idev.absbit);
  42105. + __set_bit(ABS_Y, ts->idev.absbit);
  42106. + __set_bit(ABS_PRESSURE, ts->idev.absbit);
  42107. +
  42108. + input_register_device(&ts->idev);
  42109. +
  42110. + return 0;
  42111. +}
  42112. +
  42113. +static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
  42114. +{
  42115. + input_unregister_device(&ts->idev);
  42116. +}
  42117. +
  42118. +#endif
  42119. +
  42120. +/*
  42121. + * Switch to interrupt mode.
  42122. + */
  42123. +static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
  42124. +{
  42125. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42126. + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
  42127. + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
  42128. + UCB_TS_CR_MODE_INT);
  42129. +}
  42130. +
  42131. +/*
  42132. + * Switch to pressure mode, and read pressure. We don't need to wait
  42133. + * here, since both plates are being driven.
  42134. + */
  42135. +static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
  42136. +{
  42137. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42138. + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
  42139. + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
  42140. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42141. +
  42142. + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
  42143. +}
  42144. +
  42145. +/*
  42146. + * Switch to X position mode and measure Y plate. We switch the plate
  42147. + * configuration in pressure mode, then switch to position mode. This
  42148. + * gives a faster response time. Even so, we need to wait about 55us
  42149. + * for things to stabilise.
  42150. + */
  42151. +static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
  42152. +{
  42153. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42154. + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
  42155. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42156. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42157. + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
  42158. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42159. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42160. + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
  42161. + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
  42162. +
  42163. + udelay(55);
  42164. +
  42165. + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
  42166. +}
  42167. +
  42168. +/*
  42169. + * Switch to Y position mode and measure X plate. We switch the plate
  42170. + * configuration in pressure mode, then switch to position mode. This
  42171. + * gives a faster response time. Even so, we need to wait about 55us
  42172. + * for things to stabilise.
  42173. + */
  42174. +static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
  42175. +{
  42176. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42177. + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
  42178. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42179. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42180. + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
  42181. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42182. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42183. + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
  42184. + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
  42185. +
  42186. + udelay(55);
  42187. +
  42188. + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
  42189. +}
  42190. +
  42191. +/*
  42192. + * Switch to X plate resistance mode. Set MX to ground, PX to
  42193. + * supply. Measure current.
  42194. + */
  42195. +static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
  42196. +{
  42197. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42198. + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
  42199. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42200. + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
  42201. +}
  42202. +
  42203. +/*
  42204. + * Switch to Y plate resistance mode. Set MY to ground, PY to
  42205. + * supply. Measure current.
  42206. + */
  42207. +static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
  42208. +{
  42209. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
  42210. + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
  42211. + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
  42212. + return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
  42213. +}
  42214. +
  42215. +/*
  42216. + * This is a RT kernel thread that handles the ADC accesses
  42217. + * (mainly so we can use semaphores in the UCB1200 core code
  42218. + * to serialise accesses to the ADC).
  42219. + */
  42220. +static int ucb1x00_thread(void *_ts)
  42221. +{
  42222. + struct ucb1x00_ts *ts = _ts;
  42223. + struct task_struct *tsk = current;
  42224. + DECLARE_WAITQUEUE(wait, tsk);
  42225. + int valid;
  42226. +
  42227. + ts->rtask = tsk;
  42228. +
  42229. + daemonize();
  42230. + reparent_to_init();
  42231. + strcpy(tsk->comm, "ktsd");
  42232. + tsk->tty = NULL;
  42233. + /*
  42234. + * We could run as a real-time thread. However, thus far
  42235. + * this doesn't seem to be necessary.
  42236. + */
  42237. +// tsk->policy = SCHED_FIFO;
  42238. +// tsk->rt_priority = 1;
  42239. +
  42240. + /* only want to receive SIGKILL */
  42241. + spin_lock_irq(&tsk->sigmask_lock);
  42242. + siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
  42243. + recalc_sigpending(tsk);
  42244. + spin_unlock_irq(&tsk->sigmask_lock);
  42245. +
  42246. + complete(&ts->init_exit);
  42247. +
  42248. + valid = 0;
  42249. +
  42250. + add_wait_queue(&ts->irq_wait, &wait);
  42251. + for (;;) {
  42252. + unsigned int x, y, p, val;
  42253. + signed long timeout;
  42254. +
  42255. + ts->restart = 0;
  42256. +
  42257. + ucb1x00_adc_enable(ts->ucb);
  42258. +
  42259. + x = ucb1x00_ts_read_xpos(ts);
  42260. + y = ucb1x00_ts_read_ypos(ts);
  42261. + p = ucb1x00_ts_read_pressure(ts);
  42262. +
  42263. + /*
  42264. + * Switch back to interrupt mode.
  42265. + */
  42266. + ucb1x00_ts_mode_int(ts);
  42267. + ucb1x00_adc_disable(ts->ucb);
  42268. +
  42269. + set_task_state(tsk, TASK_UNINTERRUPTIBLE);
  42270. + schedule_timeout(HZ / 100);
  42271. + if (signal_pending(tsk))
  42272. + break;
  42273. +
  42274. + ucb1x00_enable(ts->ucb);
  42275. + val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
  42276. +
  42277. + if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
  42278. + set_task_state(tsk, TASK_INTERRUPTIBLE);
  42279. +
  42280. + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
  42281. + ucb1x00_disable(ts->ucb);
  42282. +
  42283. + /*
  42284. + * If we spat out a valid sample set last time,
  42285. + * spit out a "pen off" sample here.
  42286. + */
  42287. + if (valid) {
  42288. + ucb1x00_ts_event_release(ts);
  42289. + valid = 0;
  42290. + }
  42291. +
  42292. + timeout = MAX_SCHEDULE_TIMEOUT;
  42293. + } else {
  42294. + ucb1x00_disable(ts->ucb);
  42295. +
  42296. + /*
  42297. + * Filtering is policy. Policy belongs in user
  42298. + * space. We therefore leave it to user space
  42299. + * to do any filtering they please.
  42300. + */
  42301. + if (!ts->restart) {
  42302. + ucb1x00_ts_evt_add(ts, p, x, y);
  42303. + valid = 1;
  42304. + }
  42305. +
  42306. + set_task_state(tsk, TASK_INTERRUPTIBLE);
  42307. + timeout = HZ / 100;
  42308. + }
  42309. +
  42310. + schedule_timeout(timeout);
  42311. + if (signal_pending(tsk))
  42312. + break;
  42313. + }
  42314. +
  42315. + remove_wait_queue(&ts->irq_wait, &wait);
  42316. +
  42317. + ts->rtask = NULL;
  42318. + ucb1x00_ts_evt_clear(ts);
  42319. + complete_and_exit(&ts->init_exit, 0);
  42320. +}
  42321. +
  42322. +/*
  42323. + * We only detect touch screen _touches_ with this interrupt
  42324. + * handler, and even then we just schedule our task.
  42325. + */
  42326. +static void ucb1x00_ts_irq(int idx, void *id)
  42327. +{
  42328. + struct ucb1x00_ts *ts = id;
  42329. + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
  42330. + wake_up(&ts->irq_wait);
  42331. +}
  42332. +
  42333. +static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
  42334. +{
  42335. + int ret = 0;
  42336. +
  42337. + if (down_interruptible(&ts->sem))
  42338. + return -EINTR;
  42339. +
  42340. + if (ts->use_count++ != 0)
  42341. + goto out;
  42342. +
  42343. + if (ts->rtask)
  42344. + panic("ucb1x00: rtask running?");
  42345. +
  42346. + init_waitqueue_head(&ts->irq_wait);
  42347. + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
  42348. + if (ret < 0)
  42349. + goto out;
  42350. +
  42351. + /*
  42352. + * If we do this at all, we should allow the user to
  42353. + * measure and read the X and Y resistance at any time.
  42354. + */
  42355. + ucb1x00_adc_enable(ts->ucb);
  42356. + ts->x_res = ucb1x00_ts_read_xres(ts);
  42357. + ts->y_res = ucb1x00_ts_read_yres(ts);
  42358. + ucb1x00_adc_disable(ts->ucb);
  42359. +
  42360. + init_completion(&ts->init_exit);
  42361. + ret = kernel_thread(ucb1x00_thread, ts, 0);
  42362. + if (ret >= 0) {
  42363. + wait_for_completion(&ts->init_exit);
  42364. + ret = 0;
  42365. + } else {
  42366. + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
  42367. + }
  42368. +
  42369. + out:
  42370. + if (ret)
  42371. + ts->use_count--;
  42372. + up(&ts->sem);
  42373. + return ret;
  42374. +}
  42375. +
  42376. +/*
  42377. + * Release touchscreen resources. Disable IRQs.
  42378. + */
  42379. +static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts)
  42380. +{
  42381. + if (--ts->use_count == 0) {
  42382. + if (ts->rtask) {
  42383. + send_sig(SIGKILL, ts->rtask, 1);
  42384. + wait_for_completion(&ts->init_exit);
  42385. + }
  42386. +
  42387. + ucb1x00_enable(ts->ucb);
  42388. + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
  42389. + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
  42390. + ucb1x00_disable(ts->ucb);
  42391. + }
  42392. +}
  42393. +
  42394. +#ifdef CONFIG_PM
  42395. +static int ucb1x00_ts_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
  42396. +{
  42397. + struct ucb1x00_ts *ts = (struct ucb1x00_ts *) (dev->data);
  42398. +
  42399. + if (rqst == PM_RESUME && ts->rtask != NULL) {
  42400. + /*
  42401. + * Restart the TS thread to ensure the
  42402. + * TS interrupt mode is set up again
  42403. + * after sleep.
  42404. + */
  42405. + ts->restart = 1;
  42406. + wake_up(&ts->irq_wait);
  42407. + }
  42408. + return 0;
  42409. +}
  42410. +#endif
  42411. +
  42412. +
  42413. +/*
  42414. + * Initialisation.
  42415. + */
  42416. +static int __init ucb1x00_ts_init(void)
  42417. +{
  42418. + struct ucb1x00_ts *ts = &ucbts;
  42419. +
  42420. + ts->ucb = ucb1x00_get();
  42421. + if (!ts->ucb)
  42422. + return -ENODEV;
  42423. +
  42424. + ts->adcsync = adcsync;
  42425. + init_MUTEX(&ts->sem);
  42426. +
  42427. +#ifdef CONFIG_PM
  42428. + ts->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_ts_pm);
  42429. + if (ts->pmdev == NULL)
  42430. + printk("ucb1x00_ts: unable to register in PM.\n");
  42431. + else
  42432. + ts->pmdev->data = ts;
  42433. +#endif
  42434. + return ucb1x00_ts_register(ts);
  42435. +}
  42436. +
  42437. +static void __exit ucb1x00_ts_exit(void)
  42438. +{
  42439. + struct ucb1x00_ts *ts = &ucbts;
  42440. +
  42441. + ucb1x00_ts_deregister(ts);
  42442. +
  42443. +#ifdef CONFIG_PM
  42444. + if (ts->pmdev)
  42445. + pm_unregister(ts->pmdev);
  42446. +#endif
  42447. +}
  42448. +
  42449. +#ifndef MODULE
  42450. +
  42451. +/*
  42452. + * Parse kernel command-line options.
  42453. + *
  42454. + * syntax : ucbts=[sync|nosync],...
  42455. + */
  42456. +static int __init ucb1x00_ts_setup(char *str)
  42457. +{
  42458. + char *p;
  42459. +
  42460. + while ((p = strsep(&str, ",")) != NULL) {
  42461. + if (strcmp(p, "sync") == 0)
  42462. + adcsync = UCB_SYNC;
  42463. + }
  42464. +
  42465. + return 1;
  42466. +}
  42467. +
  42468. +__setup("ucbts=", ucb1x00_ts_setup);
  42469. +
  42470. +#else
  42471. +
  42472. +MODULE_PARM(adcsync, "i");
  42473. +MODULE_PARM_DESC(adcsync, "Enable use of ADCSYNC signal");
  42474. +
  42475. +#endif
  42476. +
  42477. +module_init(ucb1x00_ts_init);
  42478. +module_exit(ucb1x00_ts_exit);
  42479. +
  42480. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  42481. +MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
  42482. +MODULE_LICENSE("GPL");
  42483. diff -urN linux-2.4.26/drivers/misc/ucb1x00.h linux-2.4.26-vrs1/drivers/misc/ucb1x00.h
  42484. --- linux-2.4.26/drivers/misc/ucb1x00.h 1970-01-01 01:00:00.000000000 +0100
  42485. +++ linux-2.4.26-vrs1/drivers/misc/ucb1x00.h 2004-01-14 21:32:25.000000000 +0000
  42486. @@ -0,0 +1,232 @@
  42487. +/*
  42488. + * linux/drivers/misc/ucb1x00.h
  42489. + *
  42490. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  42491. + *
  42492. + * This program is free software; you can redistribute it and/or modify
  42493. + * it under the terms of the GNU General Public License as published by
  42494. + * the Free Software Foundation; either version 2 of the License.
  42495. + */
  42496. +#ifndef UCB1200_H
  42497. +#define UCB1200_H
  42498. +
  42499. +#define UCB_IO_DATA 0x00
  42500. +#define UCB_IO_DIR 0x01
  42501. +
  42502. +#define UCB_IO_0 (1 << 0)
  42503. +#define UCB_IO_1 (1 << 1)
  42504. +#define UCB_IO_2 (1 << 2)
  42505. +#define UCB_IO_3 (1 << 3)
  42506. +#define UCB_IO_4 (1 << 4)
  42507. +#define UCB_IO_5 (1 << 5)
  42508. +#define UCB_IO_6 (1 << 6)
  42509. +#define UCB_IO_7 (1 << 7)
  42510. +#define UCB_IO_8 (1 << 8)
  42511. +#define UCB_IO_9 (1 << 9)
  42512. +
  42513. +#define UCB_IE_RIS 0x02
  42514. +#define UCB_IE_FAL 0x03
  42515. +#define UCB_IE_STATUS 0x04
  42516. +#define UCB_IE_CLEAR 0x04
  42517. +#define UCB_IE_ADC (1 << 11)
  42518. +#define UCB_IE_TSPX (1 << 12)
  42519. +#define UCB_IE_TSMX (1 << 13)
  42520. +#define UCB_IE_TCLIP (1 << 14)
  42521. +#define UCB_IE_ACLIP (1 << 15)
  42522. +
  42523. +#define UCB_IRQ_TSPX 12
  42524. +
  42525. +#define UCB_TC_A 0x05
  42526. +#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
  42527. +#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
  42528. +
  42529. +#define UCB_TC_B 0x06
  42530. +#define UCB_TC_B_VOICE_ENA (1 << 3)
  42531. +#define UCB_TC_B_CLIP (1 << 4)
  42532. +#define UCB_TC_B_ATT (1 << 6)
  42533. +#define UCB_TC_B_SIDE_ENA (1 << 11)
  42534. +#define UCB_TC_B_MUTE (1 << 13)
  42535. +#define UCB_TC_B_IN_ENA (1 << 14)
  42536. +#define UCB_TC_B_OUT_ENA (1 << 15)
  42537. +
  42538. +#define UCB_AC_A 0x07
  42539. +#define UCB_AC_B 0x08
  42540. +#define UCB_AC_B_LOOP (1 << 8)
  42541. +#define UCB_AC_B_MUTE (1 << 13)
  42542. +#define UCB_AC_B_IN_ENA (1 << 14)
  42543. +#define UCB_AC_B_OUT_ENA (1 << 15)
  42544. +
  42545. +#define UCB_TS_CR 0x09
  42546. +#define UCB_TS_CR_TSMX_POW (1 << 0)
  42547. +#define UCB_TS_CR_TSPX_POW (1 << 1)
  42548. +#define UCB_TS_CR_TSMY_POW (1 << 2)
  42549. +#define UCB_TS_CR_TSPY_POW (1 << 3)
  42550. +#define UCB_TS_CR_TSMX_GND (1 << 4)
  42551. +#define UCB_TS_CR_TSPX_GND (1 << 5)
  42552. +#define UCB_TS_CR_TSMY_GND (1 << 6)
  42553. +#define UCB_TS_CR_TSPY_GND (1 << 7)
  42554. +#define UCB_TS_CR_MODE_INT (0 << 8)
  42555. +#define UCB_TS_CR_MODE_PRES (1 << 8)
  42556. +#define UCB_TS_CR_MODE_POS (2 << 8)
  42557. +#define UCB_TS_CR_BIAS_ENA (1 << 11)
  42558. +#define UCB_TS_CR_TSPX_LOW (1 << 12)
  42559. +#define UCB_TS_CR_TSMX_LOW (1 << 13)
  42560. +
  42561. +#define UCB_ADC_CR 0x0a
  42562. +#define UCB_ADC_SYNC_ENA (1 << 0)
  42563. +#define UCB_ADC_VREFBYP_CON (1 << 1)
  42564. +#define UCB_ADC_INP_TSPX (0 << 2)
  42565. +#define UCB_ADC_INP_TSMX (1 << 2)
  42566. +#define UCB_ADC_INP_TSPY (2 << 2)
  42567. +#define UCB_ADC_INP_TSMY (3 << 2)
  42568. +#define UCB_ADC_INP_AD0 (4 << 2)
  42569. +#define UCB_ADC_INP_AD1 (5 << 2)
  42570. +#define UCB_ADC_INP_AD2 (6 << 2)
  42571. +#define UCB_ADC_INP_AD3 (7 << 2)
  42572. +#define UCB_ADC_EXT_REF (1 << 5)
  42573. +#define UCB_ADC_START (1 << 7)
  42574. +#define UCB_ADC_ENA (1 << 15)
  42575. +
  42576. +#define UCB_ADC_DATA 0x0b
  42577. +#define UCB_ADC_DAT_VAL (1 << 15)
  42578. +#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
  42579. +
  42580. +#define UCB_ID 0x0c
  42581. +#define UCB_ID_1200 0x1004
  42582. +#define UCB_ID_1300 0x1005
  42583. +
  42584. +#define UCB_MODE 0x0d
  42585. +#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
  42586. +#define UCB_MODE_AUD_OFF_CAN (1 << 13)
  42587. +
  42588. +#include "mcp.h"
  42589. +
  42590. +struct ucb1x00;
  42591. +
  42592. +struct ucb1x00_irq {
  42593. + void *devid;
  42594. + void (*fn)(int, void *);
  42595. +};
  42596. +
  42597. +struct ucb1x00 {
  42598. + spinlock_t lock;
  42599. + struct mcp *mcp;
  42600. + struct pm_dev *pmdev;
  42601. + unsigned int irq;
  42602. + struct semaphore adc_sem;
  42603. + spinlock_t io_lock;
  42604. + u16 id;
  42605. + u16 io_dir;
  42606. + u16 io_out;
  42607. + u16 adc_cr;
  42608. + u16 irq_fal_enbl;
  42609. + u16 irq_ris_enbl;
  42610. + struct ucb1x00_irq irq_handler[16];
  42611. +};
  42612. +
  42613. +/**
  42614. + * ucb1x00_clkrate - return the UCB1x00 SIB clock rate
  42615. + * @ucb: UCB1x00 structure describing chip
  42616. + *
  42617. + * Return the SIB clock rate in Hz.
  42618. + */
  42619. +static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
  42620. +{
  42621. + return mcp_get_sclk_rate(ucb->mcp);
  42622. +}
  42623. +
  42624. +/**
  42625. + * ucb1x00_enable - enable the UCB1x00 SIB clock
  42626. + * @ucb: UCB1x00 structure describing chip
  42627. + *
  42628. + * Enable the SIB clock. This can be called multiple times.
  42629. + */
  42630. +static inline void ucb1x00_enable(struct ucb1x00 *ucb)
  42631. +{
  42632. + mcp_enable(ucb->mcp);
  42633. +}
  42634. +
  42635. +/**
  42636. + * ucb1x00_disable - disable the UCB1x00 SIB clock
  42637. + * @ucb: UCB1x00 structure describing chip
  42638. + *
  42639. + * Disable the SIB clock. The SIB clock will only be disabled
  42640. + * when the number of ucb1x00_enable calls match the number of
  42641. + * ucb1x00_disable calls.
  42642. + */
  42643. +static inline void ucb1x00_disable(struct ucb1x00 *ucb)
  42644. +{
  42645. + mcp_disable(ucb->mcp);
  42646. +}
  42647. +
  42648. +/**
  42649. + * ucb1x00_reg_write - write a UCB1x00 register
  42650. + * @ucb: UCB1x00 structure describing chip
  42651. + * @reg: UCB1x00 4-bit register index to write
  42652. + * @val: UCB1x00 16-bit value to write
  42653. + *
  42654. + * Write the UCB1x00 register @reg with value @val. The SIB
  42655. + * clock must be running for this function to return.
  42656. + */
  42657. +static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
  42658. +{
  42659. + mcp_reg_write(ucb->mcp, reg, val);
  42660. +}
  42661. +
  42662. +/**
  42663. + * ucb1x00_reg_read - read a UCB1x00 register
  42664. + * @ucb: UCB1x00 structure describing chip
  42665. + * @reg: UCB1x00 4-bit register index to write
  42666. + *
  42667. + * Read the UCB1x00 register @reg and return its value. The SIB
  42668. + * clock must be running for this function to return.
  42669. + */
  42670. +static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
  42671. +{
  42672. + return mcp_reg_read(ucb->mcp, reg);
  42673. +}
  42674. +/**
  42675. + * ucb1x00_set_audio_divisor -
  42676. + * @ucb: UCB1x00 structure describing chip
  42677. + * @div: SIB clock divisor
  42678. + */
  42679. +static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
  42680. +{
  42681. + mcp_set_audio_divisor(ucb->mcp, div);
  42682. +}
  42683. +
  42684. +/**
  42685. + * ucb1x00_set_telecom_divisor -
  42686. + * @ucb: UCB1x00 structure describing chip
  42687. + * @div: SIB clock divisor
  42688. + */
  42689. +static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
  42690. +{
  42691. + mcp_set_telecom_divisor(ucb->mcp, div);
  42692. +}
  42693. +
  42694. +struct ucb1x00 *ucb1x00_get(void);
  42695. +
  42696. +void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
  42697. +void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
  42698. +unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
  42699. +
  42700. +#define UCB_NOSYNC (0)
  42701. +#define UCB_SYNC (1)
  42702. +
  42703. +unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
  42704. +void ucb1x00_adc_enable(struct ucb1x00 *ucb);
  42705. +void ucb1x00_adc_disable(struct ucb1x00 *ucb);
  42706. +
  42707. +/*
  42708. + * Which edges of the IRQ do you want to control today?
  42709. + */
  42710. +#define UCB_RISING (1 << 0)
  42711. +#define UCB_FALLING (1 << 1)
  42712. +
  42713. +int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
  42714. +void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
  42715. +void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
  42716. +int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
  42717. +
  42718. +#endif
  42719. diff -urN linux-2.4.26/drivers/mtd/chips/cfi_probe.c linux-2.4.26-vrs1/drivers/mtd/chips/cfi_probe.c
  42720. --- linux-2.4.26/drivers/mtd/chips/cfi_probe.c 2003-06-13 15:51:34.000000000 +0100
  42721. +++ linux-2.4.26-vrs1/drivers/mtd/chips/cfi_probe.c 2004-01-14 21:32:25.000000000 +0000
  42722. @@ -65,6 +65,10 @@
  42723. return 0;
  42724. }
  42725. cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  42726. +
  42727. + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
  42728. + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  42729. +
  42730. cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
  42731. if (!qry_present(map,base,cfi))
  42732. @@ -84,6 +88,8 @@
  42733. /* Eep. This chip also had the QRY marker.
  42734. * Is it an alias for the new one? */
  42735. cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
  42736. + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
  42737. + cfi_send_gen_cmd(0xFF, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
  42738. /* If the QRY marker goes away, it's an alias */
  42739. if (!qry_present(map, chips[i].start, cfi)) {
  42740. @@ -96,7 +102,8 @@
  42741. * too and if it's the same, assume it's an alias. */
  42742. /* FIXME: Use other modes to do a proper check */
  42743. cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  42744. -
  42745. + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
  42746. + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  42747. if (qry_present(map, base, cfi)) {
  42748. printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
  42749. map->name, base, chips[i].start);
  42750. @@ -119,6 +126,10 @@
  42751. /* Put it back into Read Mode */
  42752. cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  42753. + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
  42754. + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  42755. +
  42756. +
  42757. printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
  42758. map->name, cfi->interleave, cfi->device_type*8, base,
  42759. map->buswidth*8);
  42760. @@ -165,6 +176,20 @@
  42761. cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
  42762. cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
  42763. + /*
  42764. + * ST screwed up the CFI interface for buffer writes on their parts,
  42765. + * so this needs to be fixed up by hand here.
  42766. + *
  42767. + * A possible enhancment is that instead of just reverting back
  42768. + * to word write (as this does), we could use the ST specific double
  42769. + * word write instead.
  42770. + */
  42771. +
  42772. + if (cfi_read_query(map,base) == 0x20){
  42773. + cfi->cfiq->BufWriteTimeoutTyp = 0;
  42774. + cfi->cfiq->BufWriteTimeoutMax = 0;
  42775. + }
  42776. +
  42777. #ifdef DEBUG_CFI
  42778. /* Dump the information therein */
  42779. print_cfi_ident(cfi->cfiq);
  42780. @@ -182,6 +207,9 @@
  42781. /* Put it back into Read Mode */
  42782. cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  42783. + /* some devices don't respond to 0xF0, so send 0xFF to be sure */
  42784. + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
  42785. +
  42786. return 1;
  42787. }
  42788. diff -urN linux-2.4.26/drivers/mtd/chips/jedec_probe.c linux-2.4.26-vrs1/drivers/mtd/chips/jedec_probe.c
  42789. --- linux-2.4.26/drivers/mtd/chips/jedec_probe.c 2003-06-13 15:51:34.000000000 +0100
  42790. +++ linux-2.4.26-vrs1/drivers/mtd/chips/jedec_probe.c 2004-04-18 21:33:04.000000000 +0100
  42791. @@ -100,6 +100,8 @@
  42792. #define M29W040B 0x00E3
  42793. /* SST */
  42794. +#define SST29EE020 0x0010
  42795. +#define SST29LE020 0x0012
  42796. #define SST29EE512 0x005d
  42797. #define SST29LE512 0x003d
  42798. #define SST39LF800 0x2781
  42799. @@ -839,6 +841,24 @@
  42800. }
  42801. }, {
  42802. mfr_id: MANUFACTURER_SST,
  42803. + dev_id: SST29EE020,
  42804. + name: "SST 29EE020",
  42805. + DevSize: SIZE_256KiB,
  42806. + CmdSet: P_ID_SST_PAGE,
  42807. + NumEraseRegions: 1,
  42808. + regions: {ERASEINFO(0x01000,64),
  42809. + }
  42810. + }, {
  42811. + mfr_id: MANUFACTURER_SST,
  42812. + dev_id: SST29LE020,
  42813. + name: "SST 29LE020",
  42814. + DevSize: SIZE_256KiB,
  42815. + CmdSet: P_ID_SST_PAGE,
  42816. + NumEraseRegions: 1,
  42817. + regions: {ERASEINFO(0x01000,64),
  42818. + }
  42819. + }, {
  42820. + mfr_id: MANUFACTURER_SST,
  42821. dev_id: SST39LF020,
  42822. name: "SST 39LF020",
  42823. DevSize: SIZE_256KiB,
  42824. @@ -937,7 +957,20 @@
  42825. struct cfi_private *cfi)
  42826. {
  42827. /* Reset */
  42828. - cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
  42829. +
  42830. + /* after checking the datasheets for SST, MACRONIX and ATMEL
  42831. + * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
  42832. + * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
  42833. + * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
  42834. + * as they will ignore the writes and dont care what address
  42835. + * the F0 is written to */
  42836. + if(cfi->addr_unlock1) {
  42837. + /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/
  42838. + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
  42839. + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
  42840. + }
  42841. +
  42842. + cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
  42843. /* Some misdesigned intel chips do not respond for 0xF0 for a reset,
  42844. * so ensure we're in read mode. Send both the Intel and the AMD command
  42845. * for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so
  42846. diff -urN linux-2.4.26/drivers/mtd/devices/Config.in linux-2.4.26-vrs1/drivers/mtd/devices/Config.in
  42847. --- linux-2.4.26/drivers/mtd/devices/Config.in 2003-06-13 15:51:34.000000000 +0100
  42848. +++ linux-2.4.26-vrs1/drivers/mtd/devices/Config.in 2004-01-14 21:32:25.000000000 +0000
  42849. @@ -17,6 +17,15 @@
  42850. if [ "$CONFIG_SA1100_LART" = "y" ]; then
  42851. dep_tristate ' 28F160xx flash driver for LART' CONFIG_MTD_LART $CONFIG_MTD
  42852. fi
  42853. +if [ "$CONFIG_ARCH_MX1ADS" = "y" ]; then
  42854. + dep_tristate ' SyncFlash driver for MX1ADS' CONFIG_MTD_SYNCFLASH $CONFIG_MTD
  42855. +fi
  42856. +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  42857. + dep_tristate ' AT91RM9200 DataFlash support' CONFIG_MTD_AT91_DATAFLASH $CONFIG_MTD
  42858. + if [ "$CONFIG_MTD_AT91_DATAFLASH" = "y" -o "$CONFIG_MTD_AT91_DATAFLASH" = "m" ]; then
  42859. + bool ' Enable DataFlash card? ' CONFIG_MTD_AT91_DATAFLASH_CARD
  42860. + fi
  42861. +fi
  42862. dep_tristate ' Test driver using RAM' CONFIG_MTD_MTDRAM $CONFIG_MTD
  42863. if [ "$CONFIG_MTD_MTDRAM" = "y" -o "$CONFIG_MTD_MTDRAM" = "m" ]; then
  42864. int 'MTDRAM device size in KiB' CONFIG_MTDRAM_TOTAL_SIZE 4096
  42865. diff -urN linux-2.4.26/drivers/mtd/devices/Makefile linux-2.4.26-vrs1/drivers/mtd/devices/Makefile
  42866. --- linux-2.4.26/drivers/mtd/devices/Makefile 2002-11-28 23:53:13.000000000 +0000
  42867. +++ linux-2.4.26-vrs1/drivers/mtd/devices/Makefile 2004-01-14 21:32:25.000000000 +0000
  42868. @@ -21,6 +21,7 @@
  42869. obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
  42870. obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
  42871. obj-$(CONFIG_MTD_LART) += lart.o
  42872. +obj-$(CONFIG_MTD_SYNCFLASH) += syncflash.o
  42873. obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
  42874. include $(TOPDIR)/Rules.make
  42875. diff -urN linux-2.4.26/drivers/mtd/devices/syncflash.c linux-2.4.26-vrs1/drivers/mtd/devices/syncflash.c
  42876. --- linux-2.4.26/drivers/mtd/devices/syncflash.c 1970-01-01 01:00:00.000000000 +0100
  42877. +++ linux-2.4.26-vrs1/drivers/mtd/devices/syncflash.c 2004-01-14 21:32:26.000000000 +0000
  42878. @@ -0,0 +1,615 @@
  42879. +/*
  42880. + * MTD driver for Micron SyncFlash flash memory.
  42881. + *
  42882. + * Author: Jon McClintock <jonm@bluemug.com>
  42883. + *
  42884. + * Based loosely upon the LART flash driver, authored by Abraham vd Merwe
  42885. + * <abraham@2d3d.co.za>.
  42886. + *
  42887. + * Copyright 2003, Blue Mug, Inc. for Motorola, Inc.
  42888. + *
  42889. + * This code is free software; you can redistribute it and/or modify
  42890. + * it under the terms of the GNU General Public License version 2 as
  42891. + * published by the Free Software Foundation.
  42892. + *
  42893. + * References:
  42894. + *
  42895. + * [1] Micron SyncFlash homepage
  42896. + * - http://www.syncflash.com/
  42897. + *
  42898. + * [2] MT28S4M16LC -- 4Mx16 SyncFlash memory datasheet
  42899. + * - http://syncflash.com/pdfs/datasheets/mt28s4m16lc_6.pdf
  42900. + *
  42901. + * [3] MTD internal API documentation
  42902. + * - http://www.linux-mtd.infradead.org/tech/
  42903. + *
  42904. + * Limitations:
  42905. + *
  42906. + * Even though this driver is written for Micron SyncFlash, it is quite
  42907. + * specific to the Motorola MX1 ADS development board.
  42908. + */
  42909. +
  42910. +#include <linux/kernel.h>
  42911. +#include <linux/module.h>
  42912. +#include <linux/types.h>
  42913. +#include <linux/version.h>
  42914. +#include <linux/errno.h>
  42915. +#include <linux/mtd/mtd.h>
  42916. +#include <asm/io.h>
  42917. +
  42918. +/* partition support */
  42919. +#define HAVE_PARTITIONS
  42920. +#ifdef HAVE_PARTITIONS
  42921. +#include <linux/mtd/partitions.h>
  42922. +#endif
  42923. +
  42924. +#ifndef CONFIG_ARCH_MX1ADS
  42925. +#error The SyncFlash driver currently only supports the MX1 ADS platform.
  42926. +#endif
  42927. +
  42928. +/*
  42929. + * General flash configuration parameters.
  42930. + */
  42931. +#define BUSWIDTH 4
  42932. +#define FLASH_BLOCKSIZE (256 * 1024 * BUSWIDTH)
  42933. +#define FLASH_NUMBLOCKS 16
  42934. +
  42935. +#define BUSWIDTH 4
  42936. +#define FLASH_ADDRESS IO_ADDRESS(MX1ADS_FLASH_BASE)
  42937. +
  42938. +#define FLASH_MANUFACTURER 0x002C002C
  42939. +#define FLASH_DEVICE_ID 0x00D300D3
  42940. +
  42941. +/*
  42942. + * The size and extent of the bootloader in flash.
  42943. + */
  42944. +#define NUM_BOOTLOADER_BLOCKS 1
  42945. +#define BOOTLOADER_START 0x00000000
  42946. +#define BOOTLOADER_LEN (NUM_BOOTLOADER_BLOCKS * FLASH_BLOCKSIZE)
  42947. +
  42948. +/*
  42949. + * The size and extent of the kernel in flash.
  42950. + */
  42951. +#define NUM_KERNEL_BLOCKS 1
  42952. +#define KERNEL_START (BOOTLOADER_START + BOOTLOADER_LEN)
  42953. +#define KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE)
  42954. +
  42955. +/* File system */
  42956. +#define NUM_FILESYSTEM_BLOCKS 14
  42957. +#define FILESYSTEM_START (KERNEL_START + KERNEL_LEN)
  42958. +#define FILESYSTEM_LEN (NUM_FILESYSTEM_BLOCKS * FLASH_BLOCKSIZE)
  42959. +
  42960. +
  42961. +/*
  42962. + * SDRAM controller register location and values. These are very specific
  42963. + * to the MX1.
  42964. + */
  42965. +#define SDRAMC_REGISTER IO_ADDRESS(0x00221004)
  42966. +
  42967. +/*
  42968. + * This the mask we use to get the start of a block from a given address.
  42969. + */
  42970. +#define BLOCK_MASK (0xFFF00000)
  42971. +
  42972. +/*
  42973. + * This is the A10 address line of the SyncFlash; it's used to initiate
  42974. + * a precharge command.
  42975. + */
  42976. +#define SYNCFLASH_A10 (0x00100000)
  42977. +
  42978. +/*
  42979. + * SDRAM controller MODE settings.
  42980. + */
  42981. +#define CMD_NORMAL (0x81020300) /* Normal Mode */
  42982. +#define CMD_PREC (CMD_NORMAL + 0x10000000) /* Precharge command */
  42983. +#define CMD_AUTO (CMD_NORMAL + 0x20000000) /* Auto refresh */
  42984. +#define CMD_LMR (CMD_NORMAL + 0x30000000) /* Load Mode Register */
  42985. +#define CMD_LCR (CMD_NORMAL + 0x60000000) /* LCR Command */
  42986. +#define CMD_PROGRAM (CMD_NORMAL + 0x70000000) /* SyncFlash Program */
  42987. +
  42988. +/*
  42989. + * SyncFlash LCR Commands adjusted for the DBMX1 AHB internal address bus .
  42990. + */
  42991. +#define LCR_READ_STATUS (0x0001C000) /* 0x70 */
  42992. +#define LCR_READ_CONFIG (0x00024000) /* 0x90 */
  42993. +#define LCR_ERASE_CONFIRM (0x00008000) /* 0x20 */
  42994. +#define LCR_ERASE_NVMODE (0x0000C000) /* 0x30 */
  42995. +#define LCR_PROG_NVMODE (0x00028000) /* 0xA0 */
  42996. +#define LCR_SR_CLEAR (0x00014000) /* 0x50 */
  42997. +
  42998. +/*
  42999. + * Status register bits
  43000. + */
  43001. +#define SR_VPS_ERROR (1 << 8) /* Power-Up status error */
  43002. +#define SR_ISM_READY (1 << 7) /* State machine isn't busy */
  43003. +#define SR_ERASE_ERROR (1 << 5) /* Erase/Unprotect error */
  43004. +#define SR_PROGRAM_ERROR (1 << 4) /* Program/Protect error */
  43005. +#define SR_DEVICE_PROTECTED (1 << 3) /* Device is protected */
  43006. +#define SR_ISM_STATUS_H (1 << 2) /* Bank ISM status, high bit */
  43007. +#define SR_ISM_STATUS_L (1 << 1) /* Bank ISM status, low bit */
  43008. +#define SR_DEVICE_ISM_STATUS (1 << 0) /* ISM is device-level */
  43009. +
  43010. +#define SR_ERROR (SR_VPS_ERROR|SR_ERASE_ERROR|SR_PROGRAM_ERROR|SR_DEVICE_PROTECTED)
  43011. +
  43012. +#define STATUS_VALUE(a) ((a) | ((a) << 16))
  43013. +
  43014. +/*
  43015. + * Device configuration register offsets
  43016. + */
  43017. +#define DC_MANUFACTURER (0 * BUSWIDTH)
  43018. +#define DC_DEVICE_ID (1 * BUSWIDTH)
  43019. +#define DC_BLOCK_PROTECT (2 * BUSWIDTH)
  43020. +#define DC_DEVICE_PROTECT (3 * BUSWIDTH)
  43021. +
  43022. +#define FL_WORD(addr) (*(volatile unsigned long*)(addr))
  43023. +
  43024. +static char module_name[] = "syncflash";
  43025. +
  43026. +inline __u8 read8 (__u32 offset)
  43027. +{
  43028. + return *(volatile __u8 *) (FLASH_ADDRESS + offset);
  43029. +}
  43030. +
  43031. +inline __u32 read32 (__u32 offset)
  43032. +{
  43033. + return *(volatile __u32 *) (FLASH_ADDRESS + offset);
  43034. +}
  43035. +
  43036. +inline void write32 (__u32 x,__u32 offset)
  43037. +{
  43038. + *(volatile __u32 *) (FLASH_ADDRESS + offset) = x;
  43039. +}
  43040. +
  43041. +static __u32 read_device_configuration_register(__u32 reg_number)
  43042. +{
  43043. + __u32 tmp;
  43044. +
  43045. + /* Setup the SDRAM controller to issue an LCR command. */
  43046. + FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
  43047. +
  43048. + /* Perform a read to issue the Read Device Configuration Command. */
  43049. + tmp = read32(LCR_READ_CONFIG);
  43050. +
  43051. + /* Return the SDRAM controller to normal mode. */
  43052. + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
  43053. +
  43054. + /* Return the value of the specified register. */
  43055. + tmp = read32(reg_number);
  43056. +
  43057. + return tmp;
  43058. +}
  43059. +
  43060. +/*
  43061. + * Get the status of the flash devices.
  43062. + */
  43063. +static __u32 flash_read_status()
  43064. +{
  43065. + __u32 status, tmp;
  43066. +
  43067. + /* Enter the SyncFlash Program READ/WRITE mode. */
  43068. + FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
  43069. +
  43070. + /* Read the status register. */
  43071. + status = read32(LCR_READ_STATUS);
  43072. +
  43073. + /* Clear the status register. */
  43074. + FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
  43075. + tmp = read32(LCR_SR_CLEAR);
  43076. +
  43077. + /* Return to Normal mode. */
  43078. + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
  43079. +
  43080. + return status;
  43081. +}
  43082. +
  43083. +/*
  43084. + * Loop until both write state machines are ready.
  43085. + */
  43086. +static __u32 flash_status_wait()
  43087. +{
  43088. + __u32 status;
  43089. + do {
  43090. + status = flash_read_status();
  43091. + } while ((status & STATUS_VALUE(SR_ISM_READY)) !=
  43092. + STATUS_VALUE(SR_ISM_READY));
  43093. + return status;
  43094. +}
  43095. +
  43096. +/*
  43097. + * Loop until the Write State machine is ready, then do a full error
  43098. + * check. Clear status and leave the flash in Read Array mode; return
  43099. + * 0 for no error, -1 for error.
  43100. + */
  43101. +static int flash_status_full_check()
  43102. +{
  43103. + __u32 status;
  43104. +
  43105. + status = flash_status_wait() & STATUS_VALUE(SR_ERROR);
  43106. + return status ? -EIO : 0;
  43107. +}
  43108. +
  43109. +/*
  43110. + * Return the flash to the normal mode.
  43111. + */
  43112. +static void flash_normal_mode()
  43113. +{
  43114. + __u32 tmp;
  43115. +
  43116. + /* First issue a precharge all command. */
  43117. + FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
  43118. + tmp = read32(SYNCFLASH_A10);
  43119. +
  43120. + /* Now place the SDRAM controller in Normal mode. */
  43121. + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
  43122. +}
  43123. +
  43124. +/*
  43125. + * Probe for SyncFlash memory on MX1ADS board.
  43126. + *
  43127. + * Returns 1 if we found SyncFlash memory, 0 otherwise.
  43128. + */
  43129. +static int flash_probe (void)
  43130. +{
  43131. + __u32 manufacturer, device_id;
  43132. +
  43133. + /* For some reason, the first read doesn't work, so we do it
  43134. + * twice. */
  43135. + manufacturer = read_device_configuration_register(DC_MANUFACTURER);
  43136. + manufacturer = read_device_configuration_register(DC_MANUFACTURER);
  43137. + device_id = read_device_configuration_register(DC_DEVICE_ID);
  43138. +
  43139. + printk("SyncFlash probe: manufacturer 0x%08lx, device_id 0x%08lx\n",
  43140. + manufacturer, device_id);
  43141. + return (manufacturer == FLASH_MANUFACTURER &&
  43142. + device_id == FLASH_DEVICE_ID);
  43143. +}
  43144. +
  43145. +/*
  43146. + * Erase one block of flash memory at offset ``offset'' which is any
  43147. + * address within the block which should be erased.
  43148. + *
  43149. + * Returns 0 if successful, -1 otherwise.
  43150. + */
  43151. +static inline int erase_block (__u32 offset)
  43152. +{
  43153. + __u32 tmp;
  43154. +
  43155. + /* Mask off the lower bits of the address to get the first address
  43156. + * in the flash block. */
  43157. + offset &= (__u32)BLOCK_MASK;
  43158. +
  43159. + /* Perform a read and precharge of the bank before the LCR|ACT|WRIT
  43160. + * sequence to avoid the inadvertent precharge command occurring
  43161. + * during the LCR_ACT_WRIT sequence. */
  43162. + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
  43163. + tmp = read32(offset);
  43164. + FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
  43165. + tmp = read32(offset);
  43166. +
  43167. + /* Now start the actual erase. */
  43168. +
  43169. + /* LCR|ACT|WRIT sequence */
  43170. + FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
  43171. + write32(0, offset + LCR_ERASE_CONFIRM);
  43172. +
  43173. + /* Return to normal mode to issue the erase confirm. */
  43174. + FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
  43175. + write32(0xD0D0D0D0, offset);
  43176. +
  43177. + if (flash_status_full_check()) {
  43178. + printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",
  43179. + module_name, offset);
  43180. + return (-1);
  43181. + }
  43182. +
  43183. + flash_normal_mode();
  43184. +
  43185. + return 0;
  43186. +}
  43187. +
  43188. +static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
  43189. +{
  43190. + __u32 addr,len;
  43191. + int i,first;
  43192. +
  43193. + /* sanity checks */
  43194. + if (instr->addr + instr->len > mtd->size) return (-EINVAL);
  43195. +
  43196. + /*
  43197. + * check that both start and end of the requested erase are
  43198. + * aligned with the erasesize at the appropriate addresses.
  43199. + *
  43200. + * skip all erase regions which are ended before the start of
  43201. + * the requested erase. Actually, to save on the calculations,
  43202. + * we skip to the first erase region which starts after the
  43203. + * start of the requested erase, and then go back one.
  43204. + */
  43205. + for (i = 0; (i < mtd->numeraseregions) &&
  43206. + (instr->addr >= mtd->eraseregions[i].offset); i++) ;
  43207. + i--;
  43208. +
  43209. + /*
  43210. + * ok, now i is pointing at the erase region in which this
  43211. + * erase request starts. Check the start of the requested
  43212. + * erase range is aligned with the erase size which is in
  43213. + * effect here.
  43214. + */
  43215. + if (instr->addr & (mtd->eraseregions[i].erasesize - 1))
  43216. + return (-EINVAL);
  43217. +
  43218. + /* Remember the erase region we start on */
  43219. + first = i;
  43220. +
  43221. + /*
  43222. + * next, check that the end of the requested erase is aligned
  43223. + * with the erase region at that address.
  43224. + *
  43225. + * as before, drop back one to point at the region in which
  43226. + * the address actually falls
  43227. + */
  43228. + for (;
  43229. + (i < mtd->numeraseregions) &&
  43230. + ((instr->addr + instr->len) >= mtd->eraseregions[i].offset) ;
  43231. + i++) ;
  43232. + i--;
  43233. +
  43234. + /* is the end aligned on a block boundary? */
  43235. + if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1))
  43236. + return (-EINVAL);
  43237. +
  43238. + addr = instr->addr;
  43239. + len = instr->len;
  43240. +
  43241. + i = first;
  43242. +
  43243. + /* now erase those blocks */
  43244. + while (len)
  43245. + {
  43246. + if (erase_block (addr))
  43247. + {
  43248. + instr->state = MTD_ERASE_FAILED;
  43249. + return (-EIO);
  43250. + }
  43251. +
  43252. + addr += mtd->eraseregions[i].erasesize;
  43253. + len -= mtd->eraseregions[i].erasesize;
  43254. +
  43255. + if (addr == (mtd->eraseregions[i].offset +
  43256. + (mtd->eraseregions[i].erasesize *
  43257. + mtd->eraseregions[i].numblocks)))
  43258. + i++;
  43259. + }
  43260. +
  43261. + instr->state = MTD_ERASE_DONE;
  43262. + if (instr->callback) instr->callback (instr);
  43263. +
  43264. + return (0);
  43265. +}
  43266. +
  43267. +static int flash_read (struct mtd_info *mtd, loff_t from,
  43268. + size_t len, size_t *retlen, u_char *buf)
  43269. +{
  43270. + /* Sanity checks. */
  43271. + if (!len) return (0);
  43272. + if (from + len > mtd->size) return (-EINVAL);
  43273. +
  43274. + /* Ensure that we are in normal mode. */
  43275. + flash_normal_mode();
  43276. +
  43277. + /* We always read len bytes. */
  43278. + *retlen = len;
  43279. +
  43280. + /* first, we read bytes until we reach a dword boundary */
  43281. + if (from & (BUSWIDTH - 1))
  43282. + {
  43283. + int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
  43284. + while (len && gap--) *buf++ = read8(from++), len--;
  43285. + }
  43286. +
  43287. + /* now we read dwords until we reach a non-dword boundary */
  43288. + while (len >= BUSWIDTH)
  43289. + {
  43290. + *((__u32 *) buf) = read32(from);
  43291. +
  43292. + buf += BUSWIDTH;
  43293. + from += BUSWIDTH;
  43294. + len -= BUSWIDTH;
  43295. + }
  43296. +
  43297. + /* top up the last unaligned bytes */
  43298. + if (len & (BUSWIDTH - 1))
  43299. + while (len--) *buf++ = read8(from++);
  43300. +
  43301. + return (0);
  43302. +}
  43303. +
  43304. +/*
  43305. + * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
  43306. + * must be 32 bits, i.e. it must be on a dword boundary.
  43307. + *
  43308. + * Returns 0 if successful, -1 otherwise.
  43309. + */
  43310. +static int flash_write_dword(__u32 offset, __u32 x)
  43311. +{
  43312. + __u32 tmp;
  43313. +
  43314. + /* First issue a precharge all command. */
  43315. + FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
  43316. + tmp = read32(SYNCFLASH_A10);
  43317. +
  43318. + /* Enter the SyncFlash programming mode. */
  43319. + FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
  43320. + write32(x, offset);
  43321. +
  43322. + /* Wait for the write to complete. */
  43323. + flash_status_wait();
  43324. +
  43325. + /* Return to normal mode. */
  43326. + flash_normal_mode();
  43327. +
  43328. + return 0;
  43329. +}
  43330. +
  43331. +static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
  43332. +{
  43333. + __u8 tmp[4];
  43334. + int i,n;
  43335. +
  43336. + *retlen = 0;
  43337. +
  43338. + /* Sanity checks */
  43339. + if (!len) return (0);
  43340. + if (to + len > mtd->size) return (-EINVAL);
  43341. +
  43342. + /* First, we write a 0xFF.... padded byte until we reach a
  43343. + * dword boundary. */
  43344. + if (to & (BUSWIDTH - 1))
  43345. + {
  43346. + __u32 aligned = to & ~(BUSWIDTH - 1);
  43347. + int gap = to - aligned;
  43348. +
  43349. + i = n = 0;
  43350. +
  43351. + while (gap--) tmp[i++] = 0xFF;
  43352. + while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
  43353. + while (i < BUSWIDTH) tmp[i++] = 0xFF;
  43354. +
  43355. + if (flash_write_dword(aligned, *((__u32 *) tmp)))
  43356. + return (-EIO);
  43357. +
  43358. + to += n;
  43359. + buf += n;
  43360. + *retlen += n;
  43361. + }
  43362. +
  43363. + /* Now we write dwords until we reach a non-dword boundary. */
  43364. + while (len >= BUSWIDTH)
  43365. + {
  43366. + if (flash_write_dword (to,*((__u32 *) buf))) return (-EIO);
  43367. +
  43368. + to += BUSWIDTH;
  43369. + buf += BUSWIDTH;
  43370. + *retlen += BUSWIDTH;
  43371. + len -= BUSWIDTH;
  43372. + }
  43373. +
  43374. + /* Top up the last unaligned bytes, padded with 0xFF.... */
  43375. + if (len & (BUSWIDTH - 1))
  43376. + {
  43377. + i = n = 0;
  43378. +
  43379. + while (len--) tmp[i++] = buf[n++];
  43380. + while (i < BUSWIDTH) tmp[i++] = 0xFF;
  43381. +
  43382. + if (flash_write_dword (to,*((__u32 *) tmp))) return (-EIO);
  43383. +
  43384. + *retlen += n;
  43385. + }
  43386. +
  43387. + return flash_status_full_check();
  43388. +}
  43389. +
  43390. +
  43391. +
  43392. +#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
  43393. +
  43394. +static struct mtd_info mtd;
  43395. +
  43396. +static struct mtd_erase_region_info erase_regions[] =
  43397. +{
  43398. + /* flash blocks */
  43399. + {
  43400. + offset: 0x00000000,
  43401. + erasesize: FLASH_BLOCKSIZE,
  43402. + numblocks: FLASH_NUMBLOCKS
  43403. + },
  43404. +};
  43405. +
  43406. +#ifdef HAVE_PARTITIONS
  43407. +static struct mtd_partition syncflash_partitions[] =
  43408. +{
  43409. + /* bootloader */
  43410. + {
  43411. + name: "bootloader",
  43412. + offset: BOOTLOADER_START,
  43413. + size: BOOTLOADER_LEN,
  43414. + mask_flags: 0
  43415. + },
  43416. + /* Kernel */
  43417. + {
  43418. + name: "kernel",
  43419. + offset: KERNEL_START, /* MTDPART_OFS_APPEND */
  43420. + size: KERNEL_LEN,
  43421. + mask_flags: 0
  43422. + },
  43423. + /* file system */
  43424. + {
  43425. + name: "file system",
  43426. + offset: FILESYSTEM_START, /* MTDPART_OFS_APPEND */
  43427. + size: FILESYSTEM_LEN, /* MTDPART_SIZ_FULL */
  43428. + mask_flags: 0
  43429. + }
  43430. +};
  43431. +#endif
  43432. +
  43433. +int __init syncflash_init (void)
  43434. +{
  43435. + int result;
  43436. +
  43437. + memset (&mtd,0,sizeof (mtd));
  43438. +
  43439. + printk ("MTD driver for Micron SyncFlash.\n");
  43440. + printk ("%s: Probing for SyncFlash on MX1ADS...\n",module_name);
  43441. +
  43442. + if (!flash_probe ())
  43443. + {
  43444. + printk (KERN_WARNING "%s: Found no SyncFlash devices\n",
  43445. + module_name);
  43446. + return (-ENXIO);
  43447. + }
  43448. +
  43449. + printk ("%s: Found a SyncFlash device.\n",module_name);
  43450. +
  43451. + mtd.name = module_name;
  43452. + mtd.type = MTD_NORFLASH;
  43453. + mtd.flags = MTD_CAP_NORFLASH;
  43454. + mtd.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS;
  43455. +
  43456. + mtd.erasesize = FLASH_BLOCKSIZE;
  43457. + mtd.numeraseregions = NB_OF(erase_regions);
  43458. + mtd.eraseregions = erase_regions;
  43459. +
  43460. + mtd.module = THIS_MODULE;
  43461. +
  43462. + mtd.erase = flash_erase;
  43463. + mtd.read = flash_read;
  43464. + mtd.write = flash_write;
  43465. +
  43466. +#ifndef HAVE_PARTITIONS
  43467. + result = add_mtd_device(&mtd);
  43468. +#else
  43469. + result = add_mtd_partitions(&mtd,
  43470. + syncflash_partitions,
  43471. + NB_OF(syncflash_partitions));
  43472. +#endif
  43473. +
  43474. + return (result);
  43475. +}
  43476. +
  43477. +void __exit syncflash_exit (void)
  43478. +{
  43479. +#ifndef HAVE_PARTITIONS
  43480. + del_mtd_device (&mtd);
  43481. +#else
  43482. + del_mtd_partitions (&mtd);
  43483. +#endif
  43484. +}
  43485. +
  43486. +module_init (syncflash_init);
  43487. +module_exit (syncflash_exit);
  43488. +
  43489. +MODULE_LICENSE("GPL");
  43490. +MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
  43491. +MODULE_DESCRIPTION("MTD driver for Micron MT28S4M16LC SyncFlash on MX1ADS board");
  43492. +
  43493. +
  43494. diff -urN linux-2.4.26/drivers/mtd/maps/Config.in linux-2.4.26-vrs1/drivers/mtd/maps/Config.in
  43495. --- linux-2.4.26/drivers/mtd/maps/Config.in 2003-06-13 15:51:34.000000000 +0100
  43496. +++ linux-2.4.26-vrs1/drivers/mtd/maps/Config.in 2004-01-14 21:32:26.000000000 +0000
  43497. @@ -81,10 +81,10 @@
  43498. dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS
  43499. dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE
  43500. dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310
  43501. - dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
  43502. - dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET
  43503. + dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_FORTUNET
  43504. + dep_tristate ' CFI Flash device mapped on Epxa' CONFIG_MTD_EPXA $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
  43505. dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12
  43506. - dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI
  43507. + dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_ARCH_EDB7212 $CONFIG_MTD_CFI
  43508. dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE
  43509. dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA
  43510. fi
  43511. diff -urN linux-2.4.26/drivers/mtd/maps/Makefile linux-2.4.26-vrs1/drivers/mtd/maps/Makefile
  43512. --- linux-2.4.26/drivers/mtd/maps/Makefile 2003-06-13 15:51:34.000000000 +0100
  43513. +++ linux-2.4.26-vrs1/drivers/mtd/maps/Makefile 2004-01-14 21:32:26.000000000 +0000
  43514. @@ -3,11 +3,7 @@
  43515. #
  43516. # $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $
  43517. -BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/)
  43518. -
  43519. -ifeq ($(BELOW25),y)
  43520. O_TARGET := mapslink.o
  43521. -endif
  43522. # Chip mappings
  43523. obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
  43524. @@ -17,7 +13,7 @@
  43525. obj-$(CONFIG_MTD_DC21285) += dc21285.o
  43526. obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
  43527. obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
  43528. -obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
  43529. +obj-$(CONFIG_MTD_EPXA) += epxa-flash.o
  43530. obj-$(CONFIG_MTD_IQ80310) += iq80310.o
  43531. obj-$(CONFIG_MTD_L440GX) += l440gx.o
  43532. obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
  43533. @@ -29,9 +25,9 @@
  43534. obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
  43535. ifneq ($(CONFIG_MTD_PHYSMAP),n)
  43536. ifeq ($(CONFIG_MTD_PHYSMAP_BUSWIDTH),8)
  43537. - obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
  43538. + obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
  43539. else
  43540. - obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
  43541. + obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
  43542. endif
  43543. endif
  43544. obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
  43545. @@ -39,6 +35,9 @@
  43546. obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
  43547. obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
  43548. obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
  43549. +ifeq ($(CONFIG_ASSABET_NEPONSET),y)
  43550. + obj-$(CONFIG_MTD_SA1100) += neponset-flash.o
  43551. +endif
  43552. obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
  43553. obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
  43554. obj-$(CONFIG_MTD_NETSC520) += netsc520.o
  43555. diff -urN linux-2.4.26/drivers/mtd/maps/dc21285.c linux-2.4.26-vrs1/drivers/mtd/maps/dc21285.c
  43556. --- linux-2.4.26/drivers/mtd/maps/dc21285.c 2003-06-13 15:51:34.000000000 +0100
  43557. +++ linux-2.4.26-vrs1/drivers/mtd/maps/dc21285.c 2004-04-18 21:33:22.000000000 +0100
  43558. @@ -11,6 +11,7 @@
  43559. #include <linux/module.h>
  43560. #include <linux/types.h>
  43561. #include <linux/kernel.h>
  43562. +#include <linux/delay.h>
  43563. #include <linux/mtd/mtd.h>
  43564. #include <linux/mtd/map.h>
  43565. @@ -18,9 +19,9 @@
  43566. #include <asm/io.h>
  43567. #include <asm/hardware/dec21285.h>
  43568. +#include <asm/mach-types.h>
  43569. -
  43570. -static struct mtd_info *mymtd;
  43571. +static struct mtd_info *dc21285_mtd;
  43572. __u8 dc21285_read8(struct map_info *map, unsigned long ofs)
  43573. {
  43574. @@ -44,6 +45,9 @@
  43575. void dc21285_write8(struct map_info *map, __u8 d, unsigned long adr)
  43576. {
  43577. + if(machine_is_netwinder()) {
  43578. + nw_en_write();
  43579. + }
  43580. *CSR_ROMWRITEREG = adr & 3;
  43581. adr &= ~3;
  43582. *(__u8*)(map->map_priv_1 + adr) = d;
  43583. @@ -51,6 +55,9 @@
  43584. void dc21285_write16(struct map_info *map, __u16 d, unsigned long adr)
  43585. {
  43586. + if(machine_is_netwinder()) {
  43587. + nw_en_write();
  43588. + }
  43589. *CSR_ROMWRITEREG = adr & 3;
  43590. adr &= ~3;
  43591. *(__u16*)(map->map_priv_1 + adr) = d;
  43592. @@ -58,6 +65,9 @@
  43593. void dc21285_write32(struct map_info *map, __u32 d, unsigned long adr)
  43594. {
  43595. + if(machine_is_netwinder()) {
  43596. + nw_en_write();
  43597. + }
  43598. *(__u32*)(map->map_priv_1 + adr) = d;
  43599. }
  43600. @@ -105,6 +115,27 @@
  43601. };
  43602. +static void
  43603. +nw_en_write(void) {
  43604. +#ifdef CONFIG_ARCH_NETWINDER
  43605. + extern spinlock_t gpio_lock;
  43606. + unsigned long flags;
  43607. +
  43608. + /*
  43609. + * we want to write a bit pattern XXX1 to Xilinx to enable
  43610. + * the write gate, which will be open for about the next 2ms.
  43611. + */
  43612. + spin_lock_irqsave(&gpio_lock, flags);
  43613. + cpld_modify(1, 1);
  43614. + spin_unlock_irqrestore(&gpio_lock, flags);
  43615. +
  43616. + /*
  43617. + * let the ISA bus to catch on...
  43618. + */
  43619. + udelay(25);
  43620. +#endif
  43621. +}
  43622. +
  43623. /* Partition stuff */
  43624. static struct mtd_partition *dc21285_parts;
  43625. @@ -112,6 +143,9 @@
  43626. int __init init_dc21285(void)
  43627. {
  43628. + int nr_parts = 0;
  43629. + char *part_type = "none";
  43630. +
  43631. /* Determine buswidth */
  43632. switch (*CSR_SA110_CNTL & (3<<14)) {
  43633. case SA110_CNTL_ROMWIDTH_8:
  43634. @@ -137,24 +171,64 @@
  43635. return -EIO;
  43636. }
  43637. - mymtd = do_map_probe("cfi_probe", &dc21285_map);
  43638. - if (mymtd) {
  43639. - int nrparts = 0;
  43640. + if(machine_is_ebsa285()) {
  43641. + dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
  43642. + } else {
  43643. + dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
  43644. + }
  43645. - mymtd->module = THIS_MODULE;
  43646. + if (!dc21285_mtd) {
  43647. + /* no recognised device so unmap and exit */
  43648. + iounmap((void *)dc21285_map.map_priv_1);
  43649. + return -ENXIO;
  43650. + }
  43651. - /* partition fixup */
  43652. + dc21285_mtd->module = THIS_MODULE;
  43653. + /*
  43654. + * Dynamic partition selection stuff (might override the static ones)
  43655. + */
  43656. #ifdef CONFIG_MTD_REDBOOT_PARTS
  43657. - nrparts = parse_redboot_partitions(mymtd, &dc21285_parts);
  43658. + if (nr_parts == 0) {
  43659. + int ret = parse_redboot_partitions(dc21285_mtd, &dc21285_parts);
  43660. +
  43661. + if (ret > 0) {
  43662. + part_type = "RedBoot";
  43663. + nr_parts = ret;
  43664. + }
  43665. + else
  43666. + {
  43667. + dc21285_parts=NULL; /* ensure partition table remains clear */
  43668. + }
  43669. + }
  43670. #endif
  43671. - if (nrparts > 0) {
  43672. - add_mtd_partitions(mymtd, dc21285_parts, nrparts);
  43673. - } else if (nrparts == 0) {
  43674. - printk(KERN_NOTICE "RedBoot partition table failed\n");
  43675. - add_mtd_device(mymtd);
  43676. +#ifdef CONFIG_MTD_CMDLINE_PARTS
  43677. + if (nr_parts == 0) {
  43678. + int ret = parse_cmdline_partitions(dc21285_mtd, &dc21285_parts, "sa1100");
  43679. + if (ret > 0) {
  43680. + part_type = "Command Line";
  43681. + nr_parts = ret;
  43682. }
  43683. + else
  43684. + {
  43685. + dc21285_parts=NULL; /* ensure partition table remains clear */
  43686. + }
  43687. + }
  43688. +#endif
  43689. + if (nr_parts == 0) {
  43690. + printk(KERN_NOTICE "DC21285 Flash: no partition info available, registering whole flash at once\n");
  43691. + add_mtd_device(dc21285_mtd);
  43692. + }
  43693. +#ifdef CONFIG_MTD_PARTITIONS
  43694. + else
  43695. + {
  43696. + printk(KERN_NOTICE "DC21285 Flash: Using %s partition definition\n", part_type);
  43697. + add_mtd_partitions(dc21285_mtd, &dc21285_parts, nr_parts);
  43698. + }
  43699. +#endif
  43700. +
  43701. + if(machine_is_ebsa285()) {
  43702. /*
  43703. * Flash timing is determined with bits 19-16 of the
  43704. * CSR_SA110_CNTL. The value is the number of wait cycles, or
  43705. @@ -167,20 +241,15 @@
  43706. *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
  43707. /* tristate time */
  43708. *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
  43709. -
  43710. - return 0;
  43711. }
  43712. -
  43713. - iounmap((void *)dc21285_map.map_priv_1);
  43714. - return -ENXIO;
  43715. }
  43716. static void __exit cleanup_dc21285(void)
  43717. {
  43718. - if (mymtd) {
  43719. - del_mtd_device(mymtd);
  43720. - map_destroy(mymtd);
  43721. - mymtd = NULL;
  43722. + if (dc21285_mtd) {
  43723. + del_mtd_device(dc21285_mtd);
  43724. + map_destroy(dc21285_mtd);
  43725. + dc21285_mtd = NULL;
  43726. }
  43727. if (dc21285_map.map_priv_1) {
  43728. iounmap((void *)dc21285_map.map_priv_1);
  43729. diff -urN linux-2.4.26/drivers/mtd/maps/epxa-flash.c linux-2.4.26-vrs1/drivers/mtd/maps/epxa-flash.c
  43730. --- linux-2.4.26/drivers/mtd/maps/epxa-flash.c 1970-01-01 01:00:00.000000000 +0100
  43731. +++ linux-2.4.26-vrs1/drivers/mtd/maps/epxa-flash.c 2004-01-14 21:32:26.000000000 +0000
  43732. @@ -0,0 +1,234 @@
  43733. +/*
  43734. + * Flash memory access on EPXA based devices
  43735. + *
  43736. + * (C) 2000 Nicolas Pitre <nico@cam.org>
  43737. + * Copyright (C) 2001 Altera Corporation
  43738. + * Copyright (C) 2001 Red Hat, Inc.
  43739. + *
  43740. + * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
  43741. + *
  43742. + * This program is free software; you can redistribute it and/or modify
  43743. + * it under the terms of the GNU General Public License as published by
  43744. + * the Free Software Foundation; either version 2 of the License, or
  43745. + * (at your option) any later version.
  43746. + *
  43747. + * This program is distributed in the hope that it will be useful,
  43748. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  43749. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  43750. + * GNU General Public License for more details.
  43751. + *
  43752. + * You should have received a copy of the GNU General Public License
  43753. + * along with this program; if not, write to the Free Software
  43754. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  43755. + */
  43756. +
  43757. +#include <linux/config.h>
  43758. +#include <linux/module.h>
  43759. +#include <linux/types.h>
  43760. +#include <linux/kernel.h>
  43761. +#include <asm/io.h>
  43762. +#include <linux/mtd/mtd.h>
  43763. +#include <linux/mtd/map.h>
  43764. +#include <linux/mtd/partitions.h>
  43765. +
  43766. +#include <asm/hardware.h>
  43767. +#ifdef CONFIG_EPXA10DB
  43768. +#define BOARD_NAME "EPXA10DB"
  43769. +#else
  43770. +#define BOARD_NAME "EPXA1DB"
  43771. +#endif
  43772. +
  43773. +static int nr_parts = 0;
  43774. +static struct mtd_partition *parts;
  43775. +
  43776. +static struct mtd_info *mymtd;
  43777. +
  43778. +extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
  43779. +static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
  43780. +
  43781. +static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
  43782. +{
  43783. + return __raw_readb(map->map_priv_1 + ofs);
  43784. +}
  43785. +
  43786. +static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
  43787. +{
  43788. + return __raw_readw(map->map_priv_1 + ofs);
  43789. +}
  43790. +
  43791. +static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
  43792. +{
  43793. + return __raw_readl(map->map_priv_1 + ofs);
  43794. +}
  43795. +
  43796. +static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  43797. +{
  43798. + memcpy_fromio(to, map->map_priv_1 + from, len);
  43799. +}
  43800. +
  43801. +static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
  43802. +{
  43803. + __raw_writeb(d, map->map_priv_1 + adr);
  43804. + mb();
  43805. +}
  43806. +
  43807. +static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
  43808. +{
  43809. + __raw_writew(d, map->map_priv_1 + adr);
  43810. + mb();
  43811. +}
  43812. +
  43813. +static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
  43814. +{
  43815. + __raw_writel(d, map->map_priv_1 + adr);
  43816. + mb();
  43817. +}
  43818. +
  43819. +static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  43820. +{
  43821. + memcpy_toio(map->map_priv_1 + to, from, len);
  43822. +}
  43823. +
  43824. +static struct map_info epxa_map = {
  43825. + .name = "EPXA flash",
  43826. + .size = FLASH_SIZE,
  43827. + .buswidth = 2,
  43828. + .read8 = epxa_read8,
  43829. + .read16 = epxa_read16,
  43830. + .read32 = epxa_read32,
  43831. + .copy_from = epxa_copy_from,
  43832. + .write8 = epxa_write8,
  43833. + .write16 = epxa_write16,
  43834. + .write32 = epxa_write32,
  43835. + .copy_to = epxa_copy_to
  43836. +};
  43837. +
  43838. +static int __init epxa_mtd_init(void)
  43839. +{
  43840. + int i;
  43841. +
  43842. + printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
  43843. + epxa_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_START, FLASH_SIZE);
  43844. + if (!epxa_map.map_priv_1) {
  43845. + printk("Failed to ioremap %s flash\n",BOARD_NAME);
  43846. + return -EIO;
  43847. + }
  43848. +
  43849. + mymtd = do_map_probe("cfi_probe", &epxa_map);
  43850. + if (!mymtd) {
  43851. + iounmap((void *)epxa_map.map_priv_1);
  43852. + return -ENXIO;
  43853. + }
  43854. +
  43855. + mymtd->module = THIS_MODULE;
  43856. +
  43857. + /* Unlock the flash device. */
  43858. + if(mymtd->unlock){
  43859. + for (i=0; i<mymtd->numeraseregions;i++){
  43860. + int j;
  43861. + for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
  43862. + mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
  43863. + }
  43864. + }
  43865. + }
  43866. +
  43867. +#ifdef CONFIG_MTD_REDBOOT_PARTS
  43868. + nr_parts = parse_redboot_partitions(mymtd, &parts);
  43869. +
  43870. + if (nr_parts > 0) {
  43871. + add_mtd_partitions(mymtd, parts, nr_parts);
  43872. + return 0;
  43873. + }
  43874. +#endif
  43875. +#ifdef CONFIG_MTD_AFS_PARTS
  43876. + nr_parts = parse_afs_partitions(mymtd, &parts);
  43877. +
  43878. + if (nr_parts > 0) {
  43879. + add_mtd_partitions(mymtd, parts, nr_parts);
  43880. + return 0;
  43881. + }
  43882. +#endif
  43883. +
  43884. + /* No recognised partitioning schemes found - use defaults */
  43885. + nr_parts = epxa_default_partitions(mymtd, &parts);
  43886. + if (nr_parts > 0) {
  43887. + add_mtd_partitions(mymtd, parts, nr_parts);
  43888. + return 0;
  43889. + }
  43890. +
  43891. + /* If all else fails... */
  43892. + add_mtd_device(mymtd);
  43893. + return 0;
  43894. +}
  43895. +
  43896. +static void __exit epxa_mtd_cleanup(void)
  43897. +{
  43898. + if (mymtd) {
  43899. + if (nr_parts)
  43900. + del_mtd_partitions(mymtd);
  43901. + else
  43902. + del_mtd_device(mymtd);
  43903. + map_destroy(mymtd);
  43904. + }
  43905. + if (epxa_map.map_priv_1) {
  43906. + iounmap((void *)epxa_map.map_priv_1);
  43907. + epxa_map.map_priv_1 = 0;
  43908. + }
  43909. +}
  43910. +
  43911. +
  43912. +/*
  43913. + * This will do for now, once we decide which bootldr we're finally
  43914. + * going to use then we'll remove this function and do it properly
  43915. + *
  43916. + * Partions are currently (as offsets from base of flash):
  43917. + * 0x00000000 - 0x003FFFFF - bootloader (!)
  43918. + * 0x00400000 - 0x00FFFFFF - Flashdisk
  43919. + */
  43920. +
  43921. +static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
  43922. +{
  43923. + struct mtd_partition *parts;
  43924. + int ret;
  43925. + int npartitions = 0;
  43926. + char *names;
  43927. + const char *name = "jffs";
  43928. +
  43929. + printk("Using default partitions for %s\n",BOARD_NAME);
  43930. + npartitions=1;
  43931. + parts = kmalloc(npartitions*sizeof(*parts)+strlen(name)+1, GFP_KERNEL);
  43932. + if (!parts) {
  43933. + ret = -ENOMEM;
  43934. + goto out;
  43935. + }
  43936. + memzero(parts,npartitions*sizeof(*parts)+strlen(name));
  43937. +
  43938. + names = (char *)&parts[npartitions];
  43939. + parts[0].name = names;
  43940. + names += strlen(name) + 1;
  43941. + strcpy(parts[0].name, name);
  43942. +
  43943. +#ifdef CONFIG_EPXA10DB_R2
  43944. + parts[0].size = FLASH_SIZE-0x00400000;
  43945. + parts[0].offset = 0x00400000;
  43946. +#elif defined CONFIG_EPXA10DB_R3
  43947. + parts[0].size = 0x00800000;
  43948. + parts[0].offset = 0x00800000;
  43949. +#else
  43950. + parts[0].size = FLASH_SIZE-0x00180000;
  43951. + parts[0].offset = 0x00180000;
  43952. +#endif
  43953. + ret = npartitions;
  43954. +
  43955. + out:
  43956. + *pparts = parts;
  43957. + return ret;
  43958. +}
  43959. +
  43960. +
  43961. +module_init(epxa_mtd_init);
  43962. +module_exit(epxa_mtd_cleanup);
  43963. +
  43964. +MODULE_AUTHOR("Clive Davies");
  43965. +MODULE_DESCRIPTION("Altera epxa mtd flash map");
  43966. +MODULE_LICENSE("GPL");
  43967. diff -urN linux-2.4.26/drivers/mtd/maps/epxa10db-flash.c linux-2.4.26-vrs1/drivers/mtd/maps/epxa10db-flash.c
  43968. --- linux-2.4.26/drivers/mtd/maps/epxa10db-flash.c 2003-06-13 15:51:34.000000000 +0100
  43969. +++ linux-2.4.26-vrs1/drivers/mtd/maps/epxa10db-flash.c 1970-01-01 01:00:00.000000000 +0100
  43970. @@ -1,233 +0,0 @@
  43971. -/*
  43972. - * Flash memory access on EPXA based devices
  43973. - *
  43974. - * (C) 2000 Nicolas Pitre <nico@cam.org>
  43975. - * Copyright (C) 2001 Altera Corporation
  43976. - * Copyright (C) 2001 Red Hat, Inc.
  43977. - *
  43978. - * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
  43979. - *
  43980. - * This program is free software; you can redistribute it and/or modify
  43981. - * it under the terms of the GNU General Public License as published by
  43982. - * the Free Software Foundation; either version 2 of the License, or
  43983. - * (at your option) any later version.
  43984. - *
  43985. - * This program is distributed in the hope that it will be useful,
  43986. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  43987. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  43988. - * GNU General Public License for more details.
  43989. - *
  43990. - * You should have received a copy of the GNU General Public License
  43991. - * along with this program; if not, write to the Free Software
  43992. - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  43993. - */
  43994. -
  43995. -#include <linux/config.h>
  43996. -#include <linux/module.h>
  43997. -#include <linux/types.h>
  43998. -#include <linux/kernel.h>
  43999. -#include <asm/io.h>
  44000. -#include <linux/mtd/mtd.h>
  44001. -#include <linux/mtd/map.h>
  44002. -#include <linux/mtd/partitions.h>
  44003. -
  44004. -#include <asm/hardware.h>
  44005. -#ifdef CONFIG_EPXA10DB
  44006. -#define BOARD_NAME "EPXA10DB"
  44007. -#else
  44008. -#define BOARD_NAME "EPXA1DB"
  44009. -#endif
  44010. -
  44011. -static int nr_parts = 0;
  44012. -static struct mtd_partition *parts;
  44013. -
  44014. -static struct mtd_info *mymtd;
  44015. -
  44016. -extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
  44017. -static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
  44018. -
  44019. -static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
  44020. -{
  44021. - return __raw_readb(map->map_priv_1 + ofs);
  44022. -}
  44023. -
  44024. -static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
  44025. -{
  44026. - return __raw_readw(map->map_priv_1 + ofs);
  44027. -}
  44028. -
  44029. -static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
  44030. -{
  44031. - return __raw_readl(map->map_priv_1 + ofs);
  44032. -}
  44033. -
  44034. -static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  44035. -{
  44036. - memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
  44037. -}
  44038. -
  44039. -static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
  44040. -{
  44041. - __raw_writeb(d, map->map_priv_1 + adr);
  44042. - mb();
  44043. -}
  44044. -
  44045. -static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
  44046. -{
  44047. - __raw_writew(d, map->map_priv_1 + adr);
  44048. - mb();
  44049. -}
  44050. -
  44051. -static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
  44052. -{
  44053. - __raw_writel(d, map->map_priv_1 + adr);
  44054. - mb();
  44055. -}
  44056. -
  44057. -static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  44058. -{
  44059. - memcpy_toio((void *)(map->map_priv_1 + to), from, len);
  44060. -}
  44061. -
  44062. -
  44063. -
  44064. -static struct map_info epxa_map = {
  44065. - name: "EPXA flash",
  44066. - size: FLASH_SIZE,
  44067. - buswidth: 2,
  44068. - read8: epxa_read8,
  44069. - read16: epxa_read16,
  44070. - read32: epxa_read32,
  44071. - copy_from: epxa_copy_from,
  44072. - write8: epxa_write8,
  44073. - write16: epxa_write16,
  44074. - write32: epxa_write32,
  44075. - copy_to: epxa_copy_to
  44076. -};
  44077. -
  44078. -
  44079. -static int __init epxa_mtd_init(void)
  44080. -{
  44081. - int i;
  44082. -
  44083. - printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
  44084. - epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
  44085. - if (!epxa_map.map_priv_1) {
  44086. - printk("Failed to ioremap %s flash\n",BOARD_NAME);
  44087. - return -EIO;
  44088. - }
  44089. -
  44090. - mymtd = do_map_probe("cfi_probe", &epxa_map);
  44091. - if (!mymtd) {
  44092. - iounmap((void *)epxa_map.map_priv_1);
  44093. - return -ENXIO;
  44094. - }
  44095. -
  44096. - mymtd->module = THIS_MODULE;
  44097. -
  44098. - /* Unlock the flash device. */
  44099. - if(mymtd->unlock){
  44100. - for (i=0; i<mymtd->numeraseregions;i++){
  44101. - int j;
  44102. - for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
  44103. - mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
  44104. - }
  44105. - }
  44106. - }
  44107. -
  44108. -#ifdef CONFIG_MTD_REDBOOT_PARTS
  44109. - nr_parts = parse_redboot_partitions(mymtd, &parts);
  44110. -
  44111. - if (nr_parts > 0) {
  44112. - add_mtd_partitions(mymtd, parts, nr_parts);
  44113. - return 0;
  44114. - }
  44115. -#endif
  44116. -#ifdef CONFIG_MTD_AFS_PARTS
  44117. - nr_parts = parse_afs_partitions(mymtd, &parts);
  44118. -
  44119. - if (nr_parts > 0) {
  44120. - add_mtd_partitions(mymtd, parts, nr_parts);
  44121. - return 0;
  44122. - }
  44123. -#endif
  44124. -
  44125. - /* No recognised partitioning schemes found - use defaults */
  44126. - nr_parts = epxa_default_partitions(mymtd, &parts);
  44127. - if (nr_parts > 0) {
  44128. - add_mtd_partitions(mymtd, parts, nr_parts);
  44129. - return 0;
  44130. - }
  44131. -
  44132. - /* If all else fails... */
  44133. - add_mtd_device(mymtd);
  44134. - return 0;
  44135. -}
  44136. -
  44137. -static void __exit epxa_mtd_cleanup(void)
  44138. -{
  44139. - if (mymtd) {
  44140. - if (nr_parts)
  44141. - del_mtd_partitions(mymtd);
  44142. - else
  44143. - del_mtd_device(mymtd);
  44144. - map_destroy(mymtd);
  44145. - }
  44146. - if (epxa_map.map_priv_1) {
  44147. - iounmap((void *)epxa_map.map_priv_1);
  44148. - epxa_map.map_priv_1 = 0;
  44149. - }
  44150. -}
  44151. -
  44152. -
  44153. -/*
  44154. - * This will do for now, once we decide which bootldr we're finally
  44155. - * going to use then we'll remove this function and do it properly
  44156. - *
  44157. - * Partions are currently (as offsets from base of flash):
  44158. - * 0x00000000 - 0x003FFFFF - bootloader (!)
  44159. - * 0x00400000 - 0x00FFFFFF - Flashdisk
  44160. - */
  44161. -
  44162. -static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
  44163. -{
  44164. - struct mtd_partition *parts;
  44165. - int ret, i;
  44166. - int npartitions = 0;
  44167. - char *names;
  44168. - const char *name = "jffs";
  44169. -
  44170. - printk("Using default partitions for %s\n",BOARD_NAME);
  44171. - npartitions=1;
  44172. - parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
  44173. - memzero(parts,npartitions*sizeof(*parts)+strlen(name));
  44174. - if (!parts) {
  44175. - ret = -ENOMEM;
  44176. - goto out;
  44177. - }
  44178. - i=0;
  44179. - names = (char *)&parts[npartitions];
  44180. - parts[i].name = names;
  44181. - names += strlen(name) + 1;
  44182. - strcpy(parts[i].name, name);
  44183. -
  44184. -#ifdef CONFIG_EPXA10DB
  44185. - parts[i].size = FLASH_SIZE-0x00400000;
  44186. - parts[i].offset = 0x00400000;
  44187. -#else
  44188. - parts[i].size = FLASH_SIZE-0x00180000;
  44189. - parts[i].offset = 0x00180000;
  44190. -#endif
  44191. -
  44192. - out:
  44193. - *pparts = parts;
  44194. - return npartitions;
  44195. -}
  44196. -
  44197. -
  44198. -module_init(epxa_mtd_init);
  44199. -module_exit(epxa_mtd_cleanup);
  44200. -
  44201. -MODULE_AUTHOR("Clive Davies");
  44202. -MODULE_DESCRIPTION("Altera epxa mtd flash map");
  44203. -MODULE_LICENSE("GPL");
  44204. diff -urN linux-2.4.26/drivers/mtd/maps/neponset-flash.c linux-2.4.26-vrs1/drivers/mtd/maps/neponset-flash.c
  44205. --- linux-2.4.26/drivers/mtd/maps/neponset-flash.c 1970-01-01 01:00:00.000000000 +0100
  44206. +++ linux-2.4.26-vrs1/drivers/mtd/maps/neponset-flash.c 2004-01-14 21:32:26.000000000 +0000
  44207. @@ -0,0 +1,109 @@
  44208. +/*
  44209. + * Flash memory access on SA11x0 based devices
  44210. + *
  44211. + * (C) 2000 Nicolas Pitre <nico@cam.org>
  44212. + *
  44213. + * $Id: neponset-flash.c,v 1.18 2001/07/14 00:59:17 thockin Exp $
  44214. + */
  44215. +
  44216. +#include <linux/config.h>
  44217. +#include <linux/module.h>
  44218. +#include <linux/types.h>
  44219. +#include <linux/kernel.h>
  44220. +
  44221. +#include <linux/mtd/mtd.h>
  44222. +#include <linux/mtd/map.h>
  44223. +#include <linux/mtd/partitions.h>
  44224. +
  44225. +#include <asm/hardware.h>
  44226. +#include <asm/io.h>
  44227. +#include <asm/arch/assabet.h>
  44228. +
  44229. +static __u8 read8(struct map_info *map, unsigned long ofs)
  44230. +{
  44231. + return readb(map->map_priv_1 + ofs);
  44232. +}
  44233. +
  44234. +static __u16 read16(struct map_info *map, unsigned long ofs)
  44235. +{
  44236. + return readw(map->map_priv_1 + ofs);
  44237. +}
  44238. +
  44239. +static __u32 read32(struct map_info *map, unsigned long ofs)
  44240. +{
  44241. + return readl(map->map_priv_1 + ofs);
  44242. +}
  44243. +
  44244. +static void copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  44245. +{
  44246. + memcpy_fromio(to, map->map_priv_1 + from, len);
  44247. +}
  44248. +
  44249. +static void write8(struct map_info *map, __u8 d, unsigned long adr)
  44250. +{
  44251. + writeb(d, map->map_priv_1 + adr);
  44252. +}
  44253. +
  44254. +static void write16(struct map_info *map, __u16 d, unsigned long adr)
  44255. +{
  44256. + writew(d, map->map_priv_1 + adr);
  44257. +}
  44258. +
  44259. +static void write32(struct map_info *map, __u32 d, unsigned long adr)
  44260. +{
  44261. + writel(d, map->map_priv_1 + adr);
  44262. +}
  44263. +
  44264. +static void copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  44265. +{
  44266. + memcpy_toio(map->map_priv_1 + to, from, len);
  44267. +}
  44268. +
  44269. +#define MAX_SZ (32 * 1024 * 1024)
  44270. +
  44271. +static struct map_info neponset_map = {
  44272. + name: "Neponset",
  44273. + size: MAX_SZ,
  44274. + buswidth: 4,
  44275. + read8: read8,
  44276. + read16: read16,
  44277. + read32: read32,
  44278. + copy_from: copy_from,
  44279. + write8: write8,
  44280. + write16: write16,
  44281. + write32: write32,
  44282. + copy_to: copy_to,
  44283. +};
  44284. +
  44285. +extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
  44286. +extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
  44287. +
  44288. +static struct mtd_info *neponset_mtd;
  44289. +
  44290. +int __init neponset_mtd_init(void)
  44291. +{
  44292. + if (!machine_is_assabet() || !machine_has_neponset())
  44293. + return -ENODEV;
  44294. +
  44295. + neponset_map.map_priv_1 = (unsigned int)ioremap(0x08000000, MAX_SZ);
  44296. + if (!neponset_map.map_priv_1)
  44297. + return -ENOMEM;
  44298. +
  44299. + neponset_mtd = do_map_probe("cfi_probe", &neponset_map);
  44300. + if (!neponset_mtd)
  44301. + return -ENXIO;
  44302. + neponset_mtd->module = THIS_MODULE;
  44303. + add_mtd_device(neponset_mtd);
  44304. + return 0;
  44305. +}
  44306. +
  44307. +static void __exit neponset_mtd_cleanup(void)
  44308. +{
  44309. + if (neponset_mtd)
  44310. + map_destroy(neponset_mtd);
  44311. + if (neponset_map.map_priv_1)
  44312. + iounmap((void *)neponset_map.map_priv_1);
  44313. +}
  44314. +
  44315. +module_init(neponset_mtd_init);
  44316. +module_exit(neponset_mtd_cleanup);
  44317. diff -urN linux-2.4.26/drivers/mtd/maps/sa1100-flash.c linux-2.4.26-vrs1/drivers/mtd/maps/sa1100-flash.c
  44318. --- linux-2.4.26/drivers/mtd/maps/sa1100-flash.c 2003-06-13 15:51:34.000000000 +0100
  44319. +++ linux-2.4.26-vrs1/drivers/mtd/maps/sa1100-flash.c 2004-01-14 21:32:26.000000000 +0000
  44320. @@ -97,6 +97,32 @@
  44321. * entries. Thanks.
  44322. */
  44323. +#ifdef CONFIG_SA1100_ADSAGC
  44324. +#define ADSAGC_FLASH_SIZE 0x02000000
  44325. +static struct mtd_partition adsagc_partitions[] = {
  44326. + {
  44327. + name: "bootROM",
  44328. + size: 0x80000,
  44329. + offset: 0,
  44330. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44331. + }, {
  44332. + name: "zImage",
  44333. + size: 0x100000,
  44334. + offset: MTDPART_OFS_APPEND,
  44335. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44336. + }, {
  44337. + name: "ramdisk.gz",
  44338. + size: 0x300000,
  44339. + offset: MTDPART_OFS_APPEND,
  44340. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44341. + }, {
  44342. + name: "User FS",
  44343. + size: MTDPART_SIZ_FULL,
  44344. + offset: MTDPART_OFS_APPEND,
  44345. + }
  44346. +};
  44347. +#endif
  44348. +
  44349. #ifdef CONFIG_SA1100_ADSBITSY
  44350. #define ADSBITSY_FLASH_SIZE 0x02000000
  44351. static struct mtd_partition adsbitsy_partitions[] = {
  44352. @@ -123,6 +149,32 @@
  44353. };
  44354. #endif
  44355. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  44356. +#define ADSBITSYPLUS_FLASH_SIZE 0x02000000
  44357. +static struct mtd_partition adsbitsyplus_partitions[] = {
  44358. + {
  44359. + name: "bootROM",
  44360. + size: 0x80000,
  44361. + offset: 0,
  44362. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44363. + }, {
  44364. + name: "zImage",
  44365. + size: 0x100000,
  44366. + offset: MTDPART_OFS_APPEND,
  44367. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44368. + }, {
  44369. + name: "ramdisk.gz",
  44370. + size: 0x300000,
  44371. + offset: MTDPART_OFS_APPEND,
  44372. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44373. + }, {
  44374. + name: "User FS",
  44375. + size: MTDPART_SIZ_FULL,
  44376. + offset: MTDPART_OFS_APPEND,
  44377. + }
  44378. +};
  44379. +#endif
  44380. +
  44381. #ifdef CONFIG_SA1100_ASSABET
  44382. /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
  44383. #define ASSABET4_FLASH_SIZE 0x00400000
  44384. @@ -438,7 +490,7 @@
  44385. #endif
  44386. #ifdef CONFIG_SA1100_GRAPHICSMASTER
  44387. -#define GRAPHICSMASTER_FLASH_SIZE 0x01000000
  44388. +#define GRAPHICSMASTER_FLASH_SIZE 0x02000000
  44389. static struct mtd_partition graphicsmaster_partitions[] = {
  44390. {
  44391. name: "zImage",
  44392. @@ -507,6 +559,38 @@
  44393. }
  44394. #endif
  44395. +#ifdef CONFIG_SA1100_HACKKIT
  44396. +#define HACKKIT_FLASH_SIZE 0x01000000
  44397. +static struct mtd_partition hackkit_partitions[] = {
  44398. + {
  44399. + name: "BLOB",
  44400. + size: 0x00040000,
  44401. + offset: 0x00000000,
  44402. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44403. + }, {
  44404. + name: "config",
  44405. + size: 0x00040000,
  44406. + offset: MTDPART_OFS_APPEND,
  44407. + }, {
  44408. + name: "kernel",
  44409. + size: 0x00100000,
  44410. + offset: MTDPART_OFS_APPEND,
  44411. + }, {
  44412. + name: "initrd",
  44413. + size: 0x00180000,
  44414. + offset: MTDPART_OFS_APPEND,
  44415. + }, {
  44416. + name: "rootfs",
  44417. + size: 0x700000,
  44418. + offset: MTDPART_OFS_APPEND,
  44419. + }, {
  44420. + name: "data",
  44421. + size: MTDPART_SIZ_FULL,
  44422. + offset: MTDPART_OFS_APPEND,
  44423. + }
  44424. +};
  44425. +#endif
  44426. +
  44427. #ifdef CONFIG_SA1100_HUW_WEBPANEL
  44428. #define HUW_WEBPANEL_FLASH_SIZE 0x01000000
  44429. static struct mtd_partition huw_webpanel_partitions[] = {
  44430. @@ -555,12 +639,12 @@
  44431. offset: 0x00540000,
  44432. }, {
  44433. name: "JORNADA720 usr local",
  44434. - size: 0 /* will expand to the end of the flash */
  44435. + size: 0, /* will expand to the end of the flash */
  44436. offset: 0x00d00000,
  44437. }
  44438. };
  44439. -static void jornada720_set_vpp(int vpp)
  44440. +static void jornada720_set_vpp(struct map_info *map, int vpp)
  44441. {
  44442. if (vpp)
  44443. PPSR |= 0x80;
  44444. @@ -571,6 +655,27 @@
  44445. #endif
  44446. +#ifdef CONFIG_SA1100_NANOENGINE
  44447. +/* nanoEngine has one 28F320B3B Flash part in bank 0: */
  44448. +#define NANOENGINE_FLASH_SIZE 0x00400000
  44449. +static struct mtd_partition nanoengine_partitions[] = {
  44450. + {
  44451. + name: "nanoEngine boot firmware and parameter table",
  44452. + size: 0x00010000, /* 32K */
  44453. + offset: 0x00000000,
  44454. + mask_flags: MTD_WRITEABLE, /* force read-only */
  44455. + },{
  44456. + name: "kernel/initrd reserved",
  44457. + size: 0x002f0000,
  44458. + offset: 0x00010000,
  44459. + },{
  44460. + name: "experimental filesystem allocation",
  44461. + size: 0x00100000,
  44462. + offset: 0x00300000,
  44463. + }
  44464. +};
  44465. +#endif
  44466. +
  44467. #ifdef CONFIG_SA1100_PANGOLIN
  44468. #define PANGOLIN_FLASH_SIZE 0x04000000
  44469. static struct mtd_partition pangolin_partitions[] = {
  44470. @@ -699,6 +804,32 @@
  44471. };
  44472. #endif /* CONFIG_SA1100_SIMPAD */
  44473. +#ifdef CONFIG_SA1100_SIMPUTER
  44474. +#define SIMPUTER_FLASH_SIZE 0x02000000
  44475. +static struct mtd_partition simputer_partitions[] = {
  44476. + {
  44477. + name: "blob+logo",
  44478. + offset: 0,
  44479. + size: 0x00040000
  44480. + },
  44481. + {
  44482. + name: "kernel",
  44483. + offset: MTDPART_OFS_APPEND,
  44484. + size: 0x000C0000
  44485. + },
  44486. + {
  44487. + name: "/(cramfs)",
  44488. + offset: MTDPART_OFS_APPEND,
  44489. + size: 0x00200000
  44490. + },
  44491. + {
  44492. + name: "/usr/local(jffs2)",
  44493. + offset: MTDPART_OFS_APPEND,
  44494. + size: MTDPART_SIZ_FULL /* expand till the end */
  44495. + }
  44496. +};
  44497. +#endif
  44498. +
  44499. #ifdef CONFIG_SA1100_STORK
  44500. #define STORK_FLASH_SIZE 0x02000000
  44501. static struct mtd_partition stork_partitions[] = {
  44502. @@ -766,7 +897,7 @@
  44503. #endif
  44504. extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
  44505. -extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
  44506. +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
  44507. static struct mtd_partition *parsed_parts;
  44508. static struct mtd_info *mymtd;
  44509. @@ -787,6 +918,14 @@
  44510. */
  44511. part_type = "static";
  44512. +#ifdef CONFIG_SA1100_ADSAGC
  44513. + if (machine_is_adsagc()) {
  44514. + parts = adsagc_partitions;
  44515. + nb_parts = ARRAY_SIZE(adsagc_partitions);
  44516. + sa1100_map.size = ADSAGC_FLASH_SIZE;
  44517. + sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
  44518. + }
  44519. +#endif
  44520. #ifdef CONFIG_SA1100_ADSBITSY
  44521. if (machine_is_adsbitsy()) {
  44522. parts = adsbitsy_partitions;
  44523. @@ -795,6 +934,14 @@
  44524. sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
  44525. }
  44526. #endif
  44527. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  44528. + if (machine_is_adsbitsyplus()) {
  44529. + parts = adsbitsyplus_partitions;
  44530. + nb_parts = ARRAY_SIZE(adsbitsyplus_partitions);
  44531. + sa1100_map.size = ADSBITSYPLUS_FLASH_SIZE;
  44532. + sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
  44533. + }
  44534. +#endif
  44535. #ifdef CONFIG_SA1100_ASSABET
  44536. if (machine_is_assabet()) {
  44537. parts = assabet_partitions;
  44538. @@ -869,6 +1016,13 @@
  44539. sa1100_map.set_vpp = h3600_set_vpp;
  44540. }
  44541. #endif
  44542. +#ifdef CONFIG_SA1100_HACKKIT
  44543. + if (machine_is_hackkit()) {
  44544. + parts = hackkit_partitions;
  44545. + nb_parts = ARRAY_SIZE(hackkit_partitions);
  44546. + sa1100_map.size = HACKKIT_FLASH_SIZE;
  44547. + }
  44548. +#endif
  44549. #ifdef CONFIG_SA1100_HUW_WEBPANEL
  44550. if (machine_is_huw_webpanel()) {
  44551. parts = huw_webpanel_partitions;
  44552. @@ -884,6 +1038,13 @@
  44553. sa1100_map.set_vpp = jornada720_set_vpp;
  44554. }
  44555. #endif
  44556. +#ifdef CONFIG_SA1100_NANOENGINE
  44557. + if (machine_is_nanoengine()) {
  44558. + parts = nanoengine_partitions;
  44559. + nb_parts = ARRAY_SIZE(nanoengine_partitions);
  44560. + sa1100_map.size = NANOENGINE_FLASH_SIZE;
  44561. + }
  44562. +#endif
  44563. #ifdef CONFIG_SA1100_PANGOLIN
  44564. if (machine_is_pangolin()) {
  44565. parts = pangolin_partitions;
  44566. @@ -919,6 +1080,13 @@
  44567. sa1100_map.size = SIMPAD_FLASH_SIZE;
  44568. }
  44569. #endif
  44570. +#ifdef CONFIG_SA1100_SIMPUTER
  44571. + if (machine_is_simputer()) {
  44572. + parts = simputer_partitions;
  44573. + nb_parts = ARRAY_SIZE(simputer_partitions);
  44574. + sa1100_map.size = SIMPUTER_FLASH_SIZE;
  44575. + }
  44576. +#endif
  44577. #ifdef CONFIG_SA1100_STORK
  44578. if (machine_is_stork()) {
  44579. parts = stork_partitions;
  44580. @@ -953,7 +1121,9 @@
  44581. * specific machine settings might have been set above.
  44582. */
  44583. printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8);
  44584. - mymtd = do_map_probe("cfi_probe", &sa1100_map);
  44585. + mymtd = do_map_probe("jedec_probe", &sa1100_map);
  44586. + if (!mymtd)
  44587. + mymtd = do_map_probe("cfi_probe", &sa1100_map);
  44588. ret = -ENXIO;
  44589. if (!mymtd)
  44590. goto out_err;
  44591. diff -urN linux-2.4.26/drivers/mtd/nand/Config.in linux-2.4.26-vrs1/drivers/mtd/nand/Config.in
  44592. --- linux-2.4.26/drivers/mtd/nand/Config.in 2003-06-13 15:51:34.000000000 +0100
  44593. +++ linux-2.4.26-vrs1/drivers/mtd/nand/Config.in 2004-04-10 12:50:22.000000000 +0100
  44594. @@ -33,4 +33,8 @@
  44595. fi
  44596. fi
  44597. +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  44598. + dep_tristate ' SmartMedia Card on Atmel AT91RM9200' CONFIG_MTD_AT91_SMARTMEDIA $CONFIG_MTD_NAND
  44599. +fi
  44600. +
  44601. endmenu
  44602. diff -urN linux-2.4.26/drivers/net/Config.in linux-2.4.26-vrs1/drivers/net/Config.in
  44603. --- linux-2.4.26/drivers/net/Config.in 2004-04-19 11:44:16.000000000 +0100
  44604. +++ linux-2.4.26-vrs1/drivers/net/Config.in 2004-04-18 21:47:50.000000000 +0100
  44605. @@ -30,9 +30,15 @@
  44606. if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
  44607. source drivers/acorn/net/Config.in
  44608. fi
  44609. + if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  44610. + tristate ' AT91RM9200 Ethernet support' CONFIG_AT91_ETHER
  44611. + if [ "$CONFIG_AT91_ETHER" = "y" -o "$CONFIG_AT91_ETHER" = "m" ]; then
  44612. + bool ' RMII interface? ' CONFIG_AT91_ETHER_RMII
  44613. + fi
  44614. + fi
  44615. fi
  44616. if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
  44617. - tristate ' Altera Ether00 support' CONFIG_ETHER00
  44618. + tristate ' Altera Ether00 support' CONFIG_ETHER00
  44619. fi
  44620. if [ "$CONFIG_PPC" = "y" ]; then
  44621. dep_tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE $CONFIG_ALL_PPC
  44622. diff -urN linux-2.4.26/drivers/net/Makefile linux-2.4.26-vrs1/drivers/net/Makefile
  44623. --- linux-2.4.26/drivers/net/Makefile 2004-04-19 11:44:16.000000000 +0100
  44624. +++ linux-2.4.26-vrs1/drivers/net/Makefile 2004-04-18 21:47:50.000000000 +0100
  44625. @@ -244,6 +244,7 @@
  44626. # non-drivers/net drivers who want mii lib
  44627. obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
  44628. obj-$(CONFIG_USB_USBNET) += mii.o
  44629. +obj-$(CONFIG_AT91_ETHER) += mii.o
  44630. ifeq ($(CONFIG_ARCH_ACORN),y)
  44631. mod-subdirs += ../acorn/net
  44632. @@ -268,4 +269,3 @@
  44633. rcpci.o: $(rcpci-objs)
  44634. $(LD) -r -o $@ $(rcpci-objs)
  44635. -
  44636. diff -urN linux-2.4.26/drivers/net/am79c961a.c linux-2.4.26-vrs1/drivers/net/am79c961a.c
  44637. --- linux-2.4.26/drivers/net/am79c961a.c 2003-06-13 15:51:34.000000000 +0100
  44638. +++ linux-2.4.26-vrs1/drivers/net/am79c961a.c 2004-01-14 21:32:26.000000000 +0000
  44639. @@ -54,25 +54,36 @@
  44640. #ifdef __arm__
  44641. static void write_rreg(u_long base, u_int reg, u_int val)
  44642. {
  44643. - __asm__("str%?h %1, [%2] @ NET_RAP
  44644. - str%?h %0, [%2, #-4] @ NET_RDP
  44645. - " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44646. + __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
  44647. + "str%?h %0, [%2, #-4] @ NET_RDP"
  44648. + : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44649. }
  44650. static inline unsigned short read_rreg(u_long base_addr, u_int reg)
  44651. {
  44652. unsigned short v;
  44653. - __asm__("str%?h %1, [%2] @ NET_RAP
  44654. - ldr%?h %0, [%2, #-4] @ NET_RDP
  44655. - " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44656. + __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
  44657. + "ldr%?h %0, [%2, #-4] @ NET_RDP"
  44658. + : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44659. return v;
  44660. }
  44661. static inline void write_ireg(u_long base, u_int reg, u_int val)
  44662. {
  44663. - __asm__("str%?h %1, [%2] @ NET_RAP
  44664. - str%?h %0, [%2, #8] @ NET_IDP
  44665. - " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44666. + __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
  44667. + "str%?h %0, [%2, #8] @ NET_IDP"
  44668. + : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44669. +}
  44670. +
  44671. +static inline unsigned short read_ireg(u_long base_addr, u_int reg)
  44672. +{
  44673. + u_short v;
  44674. + __asm__(
  44675. + "str%?h %1, [%2] @ NAT_RAP\n\t"
  44676. + "str%?h %0, [%2, #8] @ NET_IDP\n\t"
  44677. + : "=r" (v)
  44678. + : "r" (reg), "r" (ISAIO_BASE + 0x0464));
  44679. + return v;
  44680. }
  44681. #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
  44682. @@ -91,16 +102,16 @@
  44683. }
  44684. while (length > 8) {
  44685. unsigned int tmp, tmp2;
  44686. - __asm__ __volatile__("
  44687. - ldm%?ia %1!, {%2, %3}
  44688. - str%?h %2, [%0], #4
  44689. - mov%? %2, %2, lsr #16
  44690. - str%?h %2, [%0], #4
  44691. - str%?h %3, [%0], #4
  44692. - mov%? %3, %3, lsr #16
  44693. - str%?h %3, [%0], #4
  44694. - " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
  44695. - : "0" (offset), "1" (buf));
  44696. + __asm__ __volatile__(
  44697. + "ldm%?ia %1!, {%2, %3}\n\t"
  44698. + "str%?h %2, [%0], #4\n\t"
  44699. + "mov%? %2, %2, lsr #16\n\t"
  44700. + "str%?h %2, [%0], #4\n\t"
  44701. + "str%?h %3, [%0], #4\n\t"
  44702. + "mov%? %3, %3, lsr #16\n\t"
  44703. + "str%?h %3, [%0], #4"
  44704. + : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
  44705. + : "0" (offset), "1" (buf));
  44706. length -= 8;
  44707. }
  44708. while (length > 0) {
  44709. @@ -118,36 +129,36 @@
  44710. length = (length + 1) & ~1;
  44711. if ((int)buf & 2) {
  44712. unsigned int tmp;
  44713. - __asm__ __volatile__("
  44714. - ldr%?h %2, [%0], #4
  44715. - str%?b %2, [%1], #1
  44716. - mov%? %2, %2, lsr #8
  44717. - str%?b %2, [%1], #1
  44718. - " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
  44719. + __asm__ __volatile__(
  44720. + "ldr%?h %2, [%0], #4\n\t"
  44721. + "str%?b %2, [%1], #1\n\t"
  44722. + "mov%? %2, %2, lsr #8\n\t"
  44723. + "str%?b %2, [%1], #1"
  44724. + : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
  44725. length -= 2;
  44726. }
  44727. while (length > 8) {
  44728. unsigned int tmp, tmp2, tmp3;
  44729. - __asm__ __volatile__("
  44730. - ldr%?h %2, [%0], #4
  44731. - ldr%?h %3, [%0], #4
  44732. - orr%? %2, %2, %3, lsl #16
  44733. - ldr%?h %3, [%0], #4
  44734. - ldr%?h %4, [%0], #4
  44735. - orr%? %3, %3, %4, lsl #16
  44736. - stm%?ia %1!, {%2, %3}
  44737. - " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
  44738. - : "0" (offset), "1" (buf));
  44739. + __asm__ __volatile__(
  44740. + "ldr%?h %2, [%0], #4\n\t"
  44741. + "ldr%?h %3, [%0], #4\n\t"
  44742. + "orr%? %2, %2, %3, lsl #16\n\t"
  44743. + "ldr%?h %3, [%0], #4\n\t"
  44744. + "ldr%?h %4, [%0], #4\n\t"
  44745. + "orr%? %3, %3, %4, lsl #16\n\t"
  44746. + "stm%?ia %1!, {%2, %3}"
  44747. + : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
  44748. + : "0" (offset), "1" (buf));
  44749. length -= 8;
  44750. }
  44751. while (length > 0) {
  44752. unsigned int tmp;
  44753. - __asm__ __volatile__("
  44754. - ldr%?h %2, [%0], #4
  44755. - str%?b %2, [%1], #1
  44756. - mov%? %2, %2, lsr #8
  44757. - str%?b %2, [%1], #1
  44758. - " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
  44759. + __asm__ __volatile__(
  44760. + "ldr%?h %2, [%0], #4\n\t"
  44761. + "str%?b %2, [%1], #1\n\t"
  44762. + "mov%? %2, %2, lsr #8\n\t"
  44763. + "str%?b %2, [%1], #1"
  44764. + : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
  44765. length -= 2;
  44766. }
  44767. }
  44768. @@ -254,9 +265,27 @@
  44769. write_rreg (dev->base_addr, BASERXH, 0);
  44770. write_rreg (dev->base_addr, CSR0, CSR0_STOP);
  44771. write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
  44772. + write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
  44773. write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
  44774. }
  44775. +static void am79c961_timer(unsigned long data)
  44776. +{
  44777. + struct net_device *dev = (struct net_device *)data;
  44778. + struct dev_priv *priv = (struct dev_priv *)dev->priv;
  44779. + unsigned int lnkstat, carrier;
  44780. +
  44781. + lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
  44782. + carrier = netif_carrier_ok(dev);
  44783. +
  44784. + if (lnkstat && !carrier)
  44785. + netif_carrier_on(dev);
  44786. + else if (!lnkstat && carrier)
  44787. + netif_carrier_off(dev);
  44788. +
  44789. + mod_timer(&priv->timer, jiffies + 5*HZ);
  44790. +}
  44791. +
  44792. /*
  44793. * Open/initialize the board.
  44794. */
  44795. @@ -274,6 +303,11 @@
  44796. am79c961_init_for_open(dev);
  44797. + netif_carrier_off(dev);
  44798. +
  44799. + priv->timer.expires = jiffies;
  44800. + add_timer(&priv->timer);
  44801. +
  44802. netif_start_queue(dev);
  44803. return 0;
  44804. @@ -288,7 +322,10 @@
  44805. struct dev_priv *priv = (struct dev_priv *)dev->priv;
  44806. unsigned long flags;
  44807. + del_timer_sync(&priv->timer);
  44808. +
  44809. netif_stop_queue(dev);
  44810. + netif_carrier_off(dev);
  44811. spin_lock_irqsave(priv->chip_lock, flags);
  44812. write_rreg (dev->base_addr, CSR0, CSR0_STOP);
  44813. @@ -413,15 +450,6 @@
  44814. unsigned int hdraddr, bufaddr;
  44815. unsigned int head;
  44816. unsigned long flags;
  44817. -
  44818. - /* FIXME: I thought the 79c961 could do padding - RMK ??? */
  44819. - if(length < ETH_ZLEN)
  44820. - {
  44821. - skb = skb_padto(skb, ETH_ZLEN);
  44822. - if(skb == NULL)
  44823. - return 0;
  44824. - length = ETH_ZLEN;
  44825. - }
  44826. head = priv->txhead;
  44827. hdraddr = priv->txhdr + (head << 3);
  44828. @@ -431,7 +459,7 @@
  44829. head = 0;
  44830. am_writebuffer (dev, bufaddr, skb->data, length);
  44831. - am_writeword (dev, hdraddr + 4, -length);
  44832. + am_writeword (dev, hdraddr + 4, -skb->len);
  44833. am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
  44834. priv->txhead = head;
  44835. @@ -448,6 +476,8 @@
  44836. if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
  44837. netif_stop_queue(dev);
  44838. + priv->stats.tx_bytes += skb->len;
  44839. +
  44840. dev_kfree_skb(skb);
  44841. return 0;
  44842. @@ -520,6 +550,7 @@
  44843. am79c961_tx(struct net_device *dev, struct dev_priv *priv)
  44844. {
  44845. do {
  44846. + signed short len;
  44847. u_int hdraddr;
  44848. u_int status;
  44849. @@ -555,6 +586,8 @@
  44850. continue;
  44851. }
  44852. priv->stats.tx_packets ++;
  44853. + len = am_readword (dev, hdraddr + 4);
  44854. + priv->stats.tx_bytes += -len;
  44855. } while (priv->txtail != priv->txhead);
  44856. netif_wake_queue(dev);
  44857. @@ -565,17 +598,23 @@
  44858. {
  44859. struct net_device *dev = (struct net_device *)dev_id;
  44860. struct dev_priv *priv = (struct dev_priv *)dev->priv;
  44861. - u_int status;
  44862. + u_int status, n = 100;
  44863. - status = read_rreg(dev->base_addr, CSR0);
  44864. - write_rreg(dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
  44865. -
  44866. - if (status & CSR0_RINT)
  44867. - am79c961_rx(dev, priv);
  44868. - if (status & CSR0_TINT)
  44869. - am79c961_tx(dev, priv);
  44870. - if (status & CSR0_MISS)
  44871. - priv->stats.rx_dropped ++;
  44872. + do {
  44873. + status = read_rreg(dev->base_addr, CSR0);
  44874. + write_rreg(dev->base_addr, CSR0, status &
  44875. + (CSR0_IENA|CSR0_TINT|CSR0_RINT|
  44876. + CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
  44877. +
  44878. + if (status & CSR0_RINT)
  44879. + am79c961_rx(dev, priv);
  44880. + if (status & CSR0_TINT)
  44881. + am79c961_tx(dev, priv);
  44882. + if (status & CSR0_MISS)
  44883. + priv->stats.rx_dropped ++;
  44884. + if (status & CSR0_CERR)
  44885. + mod_timer(&priv->timer, jiffies);
  44886. + } while (--n && status & (CSR0_RINT | CSR0_TINT));
  44887. }
  44888. /*
  44889. @@ -587,10 +626,10 @@
  44890. {
  44891. struct dev_priv *priv = (struct dev_priv *)dev->priv;
  44892. - spin_lock_irq(priv->chip_lock);
  44893. + spin_lock_irq(&priv->chip_lock);
  44894. write_rreg (dev->base_addr, CSR0, CSR0_STOP);
  44895. write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
  44896. - spin_unlock_irq(priv->chip_lock);
  44897. + spin_unlock_irq(&priv->chip_lock);
  44898. am79c961_ramtest(dev, 0x66);
  44899. am79c961_ramtest(dev, 0x99);
  44900. @@ -655,6 +694,11 @@
  44901. printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
  44902. }
  44903. + spin_lock_init(&priv->chip_lock);
  44904. + init_timer(&priv->timer);
  44905. + priv->timer.data = (unsigned long)dev;
  44906. + priv->timer.function = am79c961_timer;
  44907. +
  44908. if (am79c961_hw_init(dev))
  44909. goto release;
  44910. diff -urN linux-2.4.26/drivers/net/am79c961a.h linux-2.4.26-vrs1/drivers/net/am79c961a.h
  44911. --- linux-2.4.26/drivers/net/am79c961a.h 2000-09-18 23:15:22.000000000 +0100
  44912. +++ linux-2.4.26-vrs1/drivers/net/am79c961a.h 2004-01-14 21:32:26.000000000 +0000
  44913. @@ -58,6 +58,18 @@
  44914. #define CSR3_BABLM 0x4000
  44915. #define CSR3_MASKALL 0x5F00
  44916. +#define CSR4 4
  44917. +#define CSR4_JABM 0x0001
  44918. +#define CSR4_JAB 0x0002
  44919. +#define CSR4_TXSTRTM 0x0004
  44920. +#define CSR4_TXSTRT 0x0008
  44921. +#define CSR4_RCVCCOM 0x0010
  44922. +#define CSR4_RCVCCO 0x0020
  44923. +#define CSR4_MFCOM 0x0100
  44924. +#define CSR4_MFCO 0x0200
  44925. +#define CSR4_ASTRP_RCV 0x0400
  44926. +#define CSR4_APAD_XMIT 0x0800
  44927. +
  44928. #define CTRL1 5
  44929. #define CTRL1_SPND 0x0001
  44930. @@ -93,6 +105,8 @@
  44931. #define SIZERXR 76
  44932. #define SIZETXR 78
  44933. +#define CSR_MFC 112
  44934. +
  44935. #define RMD_ENP 0x0100
  44936. #define RMD_STP 0x0200
  44937. #define RMD_CRC 0x0800
  44938. @@ -112,6 +126,9 @@
  44939. #define TST_UFLO 0x4000
  44940. #define TST_BUFF 0x8000
  44941. +#define ISALED0 0x0004
  44942. +#define ISALED0_LNKST 0x8000
  44943. +
  44944. struct dev_priv {
  44945. struct net_device_stats stats;
  44946. unsigned long rxbuffer[RX_BUFFERS];
  44947. @@ -123,6 +140,7 @@
  44948. unsigned long rxhdr;
  44949. unsigned long txhdr;
  44950. spinlock_t chip_lock;
  44951. + struct timer_list timer;
  44952. };
  44953. extern int am79c961_probe (struct net_device *dev);
  44954. diff -urN linux-2.4.26/drivers/net/cirrus.c linux-2.4.26-vrs1/drivers/net/cirrus.c
  44955. --- linux-2.4.26/drivers/net/cirrus.c 2003-06-13 15:51:34.000000000 +0100
  44956. +++ linux-2.4.26-vrs1/drivers/net/cirrus.c 2004-01-14 21:32:26.000000000 +0000
  44957. @@ -75,6 +75,7 @@
  44958. typedef struct {
  44959. struct net_device_stats stats;
  44960. u16 txlen;
  44961. + u16 txafter; /* Default is After5 (0) */
  44962. } cirrus_t;
  44963. typedef struct {
  44964. @@ -230,13 +231,19 @@
  44965. cirrus_t *priv = (cirrus_t *) dev->priv;
  44966. u16 status;
  44967. + /* Tx start must be done with irq disabled
  44968. + * else status can be wrong */
  44969. + disable_irq (dev->irq);
  44970. +
  44971. netif_stop_queue (dev);
  44972. - cirrus_write (dev,PP_TxCMD,TxStart (After5));
  44973. + cirrus_write (dev,PP_TxCMD,TxStart (priv->txafter));
  44974. cirrus_write (dev,PP_TxLength,skb->len);
  44975. status = cirrus_read (dev,PP_BusST);
  44976. + enable_irq (dev->irq);
  44977. +
  44978. if ((status & TxBidErr)) {
  44979. printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);
  44980. priv->stats.tx_errors++;
  44981. @@ -249,7 +256,6 @@
  44982. printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);
  44983. priv->stats.tx_errors++;
  44984. priv->txlen = 0;
  44985. - /* FIXME: store skb and send it in interrupt handler */
  44986. return (1);
  44987. }
  44988. @@ -310,11 +316,18 @@
  44989. }
  44990. if ((RegContent (status) & TxUnderrun)) {
  44991. priv->stats.tx_errors++;
  44992. - priv->stats.tx_fifo_errors++;
  44993. + /* Shift start tx, if underruns come too often */
  44994. + switch (priv->stats.tx_fifo_errors++) {
  44995. + case 3: priv->txafter = After381; break;
  44996. + case 6: priv->txafter = After1021; break;
  44997. + case 9: priv->txafter = AfterAll; break;
  44998. + }
  44999. + }
  45000. + /* Wakeup only for tx events ! */
  45001. + if ((RegContent (status) & (TxUnderrun | Rdy4Tx))) {
  45002. + priv->txlen = 0;
  45003. + netif_wake_queue (dev);
  45004. }
  45005. - /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */
  45006. - priv->txlen = 0;
  45007. - netif_wake_queue (dev);
  45008. break;
  45009. case TxCOL:
  45010. @@ -428,7 +441,7 @@
  45011. else
  45012. cirrus_clear (dev,PP_RxCTL,PromiscuousA);
  45013. - if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)
  45014. + if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
  45015. cirrus_set (dev,PP_RxCTL,MulticastA);
  45016. else
  45017. cirrus_clear (dev,PP_RxCTL,MulticastA);
  45018. diff -urN linux-2.4.26/drivers/net/cs89x0.c linux-2.4.26-vrs1/drivers/net/cs89x0.c
  45019. --- linux-2.4.26/drivers/net/cs89x0.c 2003-08-25 12:44:42.000000000 +0100
  45020. +++ linux-2.4.26-vrs1/drivers/net/cs89x0.c 2004-01-14 21:39:05.000000000 +0000
  45021. @@ -115,6 +115,7 @@
  45022. */
  45023. +#include <linux/config.h>
  45024. #include <linux/kernel.h>
  45025. #include <linux/sched.h>
  45026. #include <linux/types.h>
  45027. @@ -427,18 +428,18 @@
  45028. /* if they give us an odd I/O address, then do ONE write to
  45029. the address port, to get it back to address zero, where we
  45030. expect to find the EISA signature word. An IO with a base of 0x3
  45031. - will skip the test for the ADD_PORT. */
  45032. + will skip the test for the ADD_PORT. */
  45033. if (ioaddr & 1) {
  45034. if (net_debug > 1)
  45035. printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
  45036. - if ((ioaddr & 2) != 2)
  45037. + if ((ioaddr & 2) != 2)
  45038. if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
  45039. printk(KERN_ERR "%s: bad signature 0x%x\n",
  45040. dev->name, inw((ioaddr & ~3)+ ADD_PORT));
  45041. retval = -ENODEV;
  45042. goto out2;
  45043. }
  45044. - ioaddr &= ~3;
  45045. + ioaddr &= ~3;
  45046. outw(PP_ChipID, ioaddr + ADD_PORT);
  45047. }
  45048. printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
  45049. @@ -446,7 +447,7 @@
  45050. if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
  45051. printk(KERN_ERR "%s: incorrect signature 0x%x\n",
  45052. dev->name, inw(ioaddr + DATA_PORT));
  45053. - retval = -ENODEV;
  45054. + retval = -ENODEV;
  45055. goto out2;
  45056. }
  45057. @@ -477,7 +478,7 @@
  45058. dev->base_addr);
  45059. reset_chip(dev);
  45060. -
  45061. +
  45062. /* Here we read the current configuration of the chip. If there
  45063. is no Extended EEPROM then the idea is to not disturb the chip
  45064. configuration, it should have been correctly setup by automatic
  45065. diff -urN linux-2.4.26/drivers/net/ether00.c linux-2.4.26-vrs1/drivers/net/ether00.c
  45066. --- linux-2.4.26/drivers/net/ether00.c 2003-06-13 15:51:34.000000000 +0100
  45067. +++ linux-2.4.26-vrs1/drivers/net/ether00.c 2004-01-14 21:32:26.000000000 +0000
  45068. @@ -38,6 +38,7 @@
  45069. #include <asm/arch/ether00.h>
  45070. #include <asm/arch/tdkphy.h>
  45071. +static int ether00_get_ethernet_address(struct net_device* dev);
  45072. MODULE_AUTHOR("Clive Davies");
  45073. MODULE_DESCRIPTION("Altera Ether00 IP core driver");
  45074. @@ -734,8 +735,11 @@
  45075. int result,tmp;
  45076. struct net_priv* priv;
  45077. - if (!is_valid_ether_addr(dev->dev_addr))
  45078. - return -EINVAL;
  45079. + if (!ether00_get_ethernet_address(dev)){
  45080. + printk("%s: Invalid ethernet MAC address. Please set using "
  45081. + "ifconfig\n", dev->name);
  45082. + return -EINVAL;
  45083. + }
  45084. dev->base_addr=(unsigned int)ioremap_nocache(base,SZ_4K);
  45085. @@ -906,10 +910,9 @@
  45086. }
  45087. -static void ether00_get_ethernet_address(struct net_device* dev)
  45088. +static int ether00_get_ethernet_address(struct net_device* dev)
  45089. {
  45090. struct mtd_info *mymtd=NULL;
  45091. - int i;
  45092. size_t retlen;
  45093. /*
  45094. @@ -926,11 +929,7 @@
  45095. #ifdef CONFIG_ARCH_CAMELOT
  45096. #ifdef CONFIG_MTD
  45097. /* get the mtd_info structure for the first mtd device*/
  45098. - for(i=0;i<MAX_MTD_DEVICES;i++){
  45099. - mymtd=get_mtd_device(NULL,i);
  45100. - if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))
  45101. - break;
  45102. - }
  45103. + mymtd=get_mtd_device(NULL,0);
  45104. if(!mymtd || !mymtd->read_user_prot_reg){
  45105. printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);
  45106. @@ -947,9 +946,7 @@
  45107. #endif
  45108. #endif
  45109. - if (!is_valid_ether_addr(dev->dev_addr))
  45110. - printk("%s: Invalid ethernet MAC address. Please set using "
  45111. - "ifconfig\n", dev->name);
  45112. + return (is_valid_ether_addr(dev->dev_addr));
  45113. }
  45114. @@ -966,8 +963,6 @@
  45115. dev->tx_timeout=ether00_tx_timeout;
  45116. dev->watchdog_timeo=TX_TIMEOUT;
  45117. - ether00_get_ethernet_address(dev);
  45118. -
  45119. SET_MODULE_OWNER(dev);
  45120. return 0;
  45121. }
  45122. diff -urN linux-2.4.26/drivers/net/irda/Config.in linux-2.4.26-vrs1/drivers/net/irda/Config.in
  45123. --- linux-2.4.26/drivers/net/irda/Config.in 2004-02-27 20:03:26.000000000 +0000
  45124. +++ linux-2.4.26-vrs1/drivers/net/irda/Config.in 2004-02-23 23:21:17.000000000 +0000
  45125. @@ -40,7 +40,7 @@
  45126. dep_tristate 'VIA IrCC (Experimental)' CONFIG_VIA_IRCC_FIR $CONFIG_IRDA
  45127. fi
  45128. if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
  45129. - dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA
  45130. + dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
  45131. fi
  45132. endmenu
  45133. diff -urN linux-2.4.26/drivers/net/irda/sa1100_ir.c linux-2.4.26-vrs1/drivers/net/irda/sa1100_ir.c
  45134. --- linux-2.4.26/drivers/net/irda/sa1100_ir.c 2002-08-03 01:39:44.000000000 +0100
  45135. +++ linux-2.4.26-vrs1/drivers/net/irda/sa1100_ir.c 2004-01-14 21:32:26.000000000 +0000
  45136. @@ -38,11 +38,7 @@
  45137. #include <asm/arch/assabet.h>
  45138. -#ifndef CONFIG_SA1100_H3600
  45139. -#define clr_h3600_egpio(x) do { } while (0)
  45140. -#define set_h3600_egpio(x) do { } while (0)
  45141. -#endif
  45142. -
  45143. +/* Yopy wants fixing */
  45144. #ifndef GPIO_IRDA_FIR
  45145. #define GPIO_IRDA_FIR (0)
  45146. #endif
  45147. @@ -174,8 +170,8 @@
  45148. if (machine_is_assabet())
  45149. ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
  45150. - if (machine_is_h3600())
  45151. - clr_h3600_egpio(EGPIO_H3600_IR_FSEL);
  45152. + if (machine_is_h3xxx())
  45153. + clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
  45154. if (machine_is_yopy())
  45155. PPSR &= ~GPIO_IRDA_FIR;
  45156. @@ -199,8 +195,8 @@
  45157. if (machine_is_assabet())
  45158. ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
  45159. - if (machine_is_h3600())
  45160. - set_h3600_egpio(EGPIO_H3600_IR_FSEL);
  45161. + if (machine_is_h3xxx())
  45162. + set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
  45163. if (machine_is_yopy())
  45164. PPSR |= GPIO_IRDA_FIR;
  45165. @@ -246,10 +242,7 @@
  45166. static inline int
  45167. sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state)
  45168. {
  45169. - if (state)
  45170. - set_h3600_egpio(EGPIO_H3600_IR_ON);
  45171. - else
  45172. - clr_h3600_egpio(EGPIO_H3600_IR_ON);
  45173. + assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state );
  45174. return 0;
  45175. }
  45176. @@ -283,7 +276,7 @@
  45177. if (machine_is_assabet())
  45178. ret = sa1100_irda_set_power_assabet(si, state);
  45179. - if (machine_is_h3600())
  45180. + if (machine_is_h3xxx())
  45181. ret = sa1100_irda_set_power_h3600(si, state);
  45182. if (machine_is_yopy())
  45183. ret = sa1100_irda_set_power_yopy(si, state);
  45184. @@ -727,11 +720,6 @@
  45185. netif_wake_queue(dev);
  45186. }
  45187. -/*
  45188. - * Note that we will never build up a backlog of frames; the protocol is a
  45189. - * half duplex protocol which basically means we transmit a frame, we
  45190. - * receive a frame, we transmit the next frame etc.
  45191. - */
  45192. static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
  45193. {
  45194. struct sa1100_irda *si = dev->priv;
  45195. @@ -758,6 +746,8 @@
  45196. }
  45197. if (!IS_FIR(si)) {
  45198. + netif_stop_queue(dev);
  45199. +
  45200. si->tx_buff.data = si->tx_buff.head;
  45201. si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
  45202. si->tx_buff.truesize);
  45203. diff -urN linux-2.4.26/drivers/net/irda/w83977af_ir.c linux-2.4.26-vrs1/drivers/net/irda/w83977af_ir.c
  45204. --- linux-2.4.26/drivers/net/irda/w83977af_ir.c 2002-11-28 23:53:13.000000000 +0000
  45205. +++ linux-2.4.26-vrs1/drivers/net/irda/w83977af_ir.c 2004-01-14 21:32:26.000000000 +0000
  45206. @@ -205,7 +205,7 @@
  45207. /* FIXME: The HP HDLS-1100 does not support 1152000! */
  45208. self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
  45209. - IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
  45210. + IR_115200/*|IR_576000|IR_1152000|(IR_4000000 << 8)*/;
  45211. /* The HP HDLS-1100 needs 1 ms according to the specs */
  45212. self->qos.min_turn_time.bits = qos_mtt_bits;
  45213. @@ -1341,7 +1341,7 @@
  45214. case SIOCSBANDWIDTH: /* Set bandwidth */
  45215. if (!capable(CAP_NET_ADMIN)) {
  45216. ret = -EPERM;
  45217. - goto out;
  45218. + break;
  45219. }
  45220. w83977af_change_speed(self, irq->ifr_baudrate);
  45221. break;
  45222. diff -urN linux-2.4.26/drivers/net/smc9194.c linux-2.4.26-vrs1/drivers/net/smc9194.c
  45223. --- linux-2.4.26/drivers/net/smc9194.c 2003-06-13 15:51:35.000000000 +0100
  45224. +++ linux-2.4.26-vrs1/drivers/net/smc9194.c 2004-01-14 21:32:26.000000000 +0000
  45225. @@ -12,8 +12,8 @@
  45226. . AUI/TP selection ( mine has 10Base2/10BaseT select )
  45227. .
  45228. . Arguments:
  45229. - . io = for the base address
  45230. - . irq = for the IRQ
  45231. + . io = for the base address
  45232. + . irq = for the IRQ
  45233. . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 )
  45234. .
  45235. . author:
  45236. @@ -51,12 +51,21 @@
  45237. . allocation
  45238. . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
  45239. . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
  45240. + . 06/23/01 Russell King Separate out IO functions for different bus
  45241. + . types.
  45242. + . Use dev->name instead of CARDNAME for printk
  45243. + . Add ethtool support, full duplex support
  45244. + . Add LAN91C96 support.
  45245. . 11/08/01 Matt Domsch Use common crc32 function
  45246. ----------------------------------------------------------------------------*/
  45247. +#define DRV_NAME "smc9194"
  45248. +#define DRV_VERSION "0.15"
  45249. +
  45250. static const char version[] =
  45251. - "smc9194.c:v0.14 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
  45252. + DRV_NAME ".c:v" DRV_VERSION " 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
  45253. +#include <linux/config.h>
  45254. #include <linux/module.h>
  45255. #include <linux/version.h>
  45256. #include <linux/kernel.h>
  45257. @@ -69,16 +78,26 @@
  45258. #include <linux/in.h>
  45259. #include <linux/slab.h>
  45260. #include <linux/string.h>
  45261. +#include <linux/delay.h>
  45262. #include <linux/init.h>
  45263. #include <linux/crc32.h>
  45264. -#include <asm/bitops.h>
  45265. -#include <asm/io.h>
  45266. #include <linux/errno.h>
  45267. +#include <linux/ethtool.h>
  45268. #include <linux/netdevice.h>
  45269. #include <linux/etherdevice.h>
  45270. #include <linux/skbuff.h>
  45271. +#include <asm/bitops.h>
  45272. +#include <asm/irq.h>
  45273. +#include <asm/io.h>
  45274. +#include <asm/uaccess.h>
  45275. +
  45276. +#ifdef CONFIG_ARCH_SA1100
  45277. +#include <asm/hardware.h>
  45278. +#include <asm/arch/assabet.h>
  45279. +#endif
  45280. +
  45281. #include "smc9194.h"
  45282. /*------------------------------------------------------------------------
  45283. .
  45284. @@ -152,29 +171,27 @@
  45285. -------------------------------------------------------------------------*/
  45286. #define CARDNAME "SMC9194"
  45287. +static const char *chip_ids[15] = {
  45288. + NULL,
  45289. + NULL,
  45290. + NULL,
  45291. + "SMC91C90/91C92", /* 3 */
  45292. + "SMC91C94/91C96", /* 4 */
  45293. + "SMC91C95", /* 5 */
  45294. + NULL,
  45295. + "SMC91C100", /* 7 */
  45296. + "SMC91C100FD", /* 8 */
  45297. + NULL,
  45298. + NULL,
  45299. + NULL,
  45300. + NULL,
  45301. + NULL,
  45302. + NULL
  45303. +};
  45304. -/* store this information for the driver.. */
  45305. -struct smc_local {
  45306. - /*
  45307. - these are things that the kernel wants me to keep, so users
  45308. - can find out semi-useless statistics of how well the card is
  45309. - performing
  45310. - */
  45311. - struct net_device_stats stats;
  45312. -
  45313. - /*
  45314. - If I have to wait until memory is available to send
  45315. - a packet, I will store the skbuff here, until I get the
  45316. - desired memory. Then, I'll send it out and free it.
  45317. - */
  45318. - struct sk_buff * saved_skb;
  45319. -
  45320. - /*
  45321. - . This keeps track of how many packets that I have
  45322. - . sent out. When an TX_EMPTY interrupt comes, I know
  45323. - . that all of these have been sent.
  45324. - */
  45325. - int packets_waiting;
  45326. +static const char * interfaces[2] = {
  45327. + "TP",
  45328. + "AUI"
  45329. };
  45330. @@ -202,6 +219,11 @@
  45331. static int smc_open(struct net_device *dev);
  45332. /*
  45333. + . This handles the ethtool interface
  45334. +*/
  45335. +static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
  45336. +
  45337. +/*
  45338. . Our watchdog timed out. Called by the networking layer
  45339. */
  45340. static void smc_timeout(struct net_device *dev);
  45341. @@ -217,11 +239,11 @@
  45342. . This routine allows the proc file system to query the driver's
  45343. . statistics.
  45344. */
  45345. -static struct net_device_stats * smc_query_statistics( struct net_device *dev);
  45346. +static struct net_device_stats * smc_query_statistics(struct net_device *dev);
  45347. /*
  45348. - . Finally, a call to set promiscuous mode ( for TCPDUMP and related
  45349. - . programs ) and multicast modes.
  45350. + . Finally, a call to set promiscuous mode (for TCPDUMP and related
  45351. + . programs) and multicast modes.
  45352. */
  45353. static void smc_set_multicast_list(struct net_device *dev);
  45354. @@ -240,12 +262,12 @@
  45355. . This is a separate procedure to handle the receipt of a packet, to
  45356. . leave the interrupt code looking slightly cleaner
  45357. */
  45358. -static inline void smc_rcv( struct net_device *dev );
  45359. +static inline void smc_rcv(struct net_device *dev);
  45360. /*
  45361. . This handles a TX interrupt, which is only called when an error
  45362. . relating to a packet is sent.
  45363. */
  45364. -static inline void smc_tx( struct net_device * dev );
  45365. +static inline void smc_tx(struct net_device * dev);
  45366. /*
  45367. ------------------------------------------------------------
  45368. @@ -261,39 +283,287 @@
  45369. */
  45370. static int smc_probe(struct net_device *dev, int ioaddr);
  45371. -/*
  45372. - . A rather simple routine to print out a packet for debugging purposes.
  45373. -*/
  45374. -#if SMC_DEBUG > 2
  45375. -static void print_packet( byte *, int );
  45376. -#endif
  45377. -
  45378. -#define tx_done(dev) 1
  45379. -
  45380. /* this is called to actually send the packet to the chip */
  45381. -static void smc_hardware_send_packet( struct net_device * dev );
  45382. +static void smc_hardware_send_packet(struct net_device * dev);
  45383. /* Since I am not sure if I will have enough room in the chip's ram
  45384. . to store the packet, I call this routine, which either sends it
  45385. . now, or generates an interrupt when the card is ready for the
  45386. . packet */
  45387. -static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev );
  45388. +static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *dev);
  45389. /* this does a soft reset on the device */
  45390. -static void smc_reset( int ioaddr );
  45391. +static void smc_reset(struct net_device *dev);
  45392. /* Enable Interrupts, Receive, and Transmit */
  45393. -static void smc_enable( int ioaddr );
  45394. +static void smc_enable(struct net_device *dev);
  45395. /* this puts the device in an inactive state */
  45396. -static void smc_shutdown( int ioaddr );
  45397. +static void smc_shutdown(struct net_device *dev);
  45398. /* This routine will find the IRQ of the driver if one is not
  45399. . specified in the input to the device. */
  45400. -static int smc_findirq( int ioaddr );
  45401. +static int smc_findirq(struct net_device *dev);
  45402. +
  45403. +#ifndef CONFIG_ASSABET_NEPONSET
  45404. +/*
  45405. + * These functions allow us to handle IO addressing as we wish - this
  45406. + * ethernet controller can be connected to a variety of busses. Some
  45407. + * busses do not support 16 bit or 32 bit transfers. --rmk
  45408. + */
  45409. +static inline u8 smc_inb(u_int base, u_int reg)
  45410. +{
  45411. + return inb(base + reg);
  45412. +}
  45413. +
  45414. +static inline u16 smc_inw(u_int base, u_int reg)
  45415. +{
  45416. + return inw(base + reg);
  45417. +}
  45418. +
  45419. +static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
  45420. +{
  45421. + u_int port = base + reg;
  45422. +#ifdef USE_32_BIT
  45423. + /* QUESTION: Like in the TX routine, do I want
  45424. + to send the DWORDs or the bytes first, or some
  45425. + mixture. A mixture might improve already slow PIO
  45426. + performance */
  45427. + PRINTK3((" Reading %d dwords (and %d bytes) \n",
  45428. + len >> 2, len & 3));
  45429. + insl(port, data, len >> 2);
  45430. + /* read the left over bytes */
  45431. + insb(port, data + (len & ~3), len & 3);
  45432. +#else
  45433. + PRINTK3((" Reading %d words and %d byte(s) \n",
  45434. + len >> 1, len & 1));
  45435. + insw(port, data, len >> 1);
  45436. + if (len & 1) {
  45437. + data += len & ~1;
  45438. + *data = inb(port);
  45439. + }
  45440. +#endif
  45441. +}
  45442. +
  45443. +static inline void smc_outb(u8 val, u_int base, u_int reg)
  45444. +{
  45445. + outb(val, base + reg);
  45446. +}
  45447. +
  45448. +static inline void smc_outw(u16 val, u_int base, u_int reg)
  45449. +{
  45450. + outw(val, base + reg);
  45451. +}
  45452. +
  45453. +static inline void smc_outl(u32 val, u_int base, u_int reg)
  45454. +{
  45455. + u_int port = base + reg;
  45456. +#ifdef USE_32_BIT
  45457. + outl(val, port);
  45458. +#else
  45459. + outw(val, port);
  45460. + outw(val >> 16, port);
  45461. +#endif
  45462. +}
  45463. +
  45464. +static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
  45465. +{
  45466. + u_int port = base + reg;
  45467. +#ifdef USE_32_BIT
  45468. + if (len & 2) {
  45469. + outsl(port, data, len >> 2);
  45470. + outw(*((word *)(data + (len & ~3))), port);
  45471. + }
  45472. + else
  45473. + outsl(port, data, len >> 2);
  45474. +#else
  45475. + outsw(port, data, len >> 1);
  45476. +#endif
  45477. +}
  45478. +
  45479. +
  45480. +/*-------------------------------------------------------------------------
  45481. + . I define some macros to make it easier to do somewhat common
  45482. + . or slightly complicated, repeated tasks.
  45483. + --------------------------------------------------------------------------*/
  45484. +
  45485. +/* select a register bank, 0 to 3 */
  45486. +
  45487. +#define SMC_SELECT_BANK(x) \
  45488. + { \
  45489. + smc_outw(x, ioaddr, BANK_SELECT); \
  45490. + }
  45491. +
  45492. +/* define a small delay for the reset */
  45493. +#define SMC_DELAY() \
  45494. + { \
  45495. + smc_inw(ioaddr, RCR); \
  45496. + smc_inw(ioaddr, RCR); \
  45497. + smc_inw(ioaddr, RCR); \
  45498. + }
  45499. +
  45500. +/* this enables an interrupt in the interrupt mask register */
  45501. +#define SMC_ENABLE_INT(x) \
  45502. + { \
  45503. + byte mask; \
  45504. + mask = smc_inb(ioaddr, INT_MASK); \
  45505. + mask |= (x); \
  45506. + smc_outb(mask, ioaddr, INT_MASK); \
  45507. + }
  45508. +
  45509. +/* this sets the absolutel interrupt mask */
  45510. +#define SMC_SET_INT(x) \
  45511. + { \
  45512. + smc_outw((x), INT_MASK); \
  45513. + }
  45514. +
  45515. +#else
  45516. +
  45517. +#undef SMC_IO_EXTENT
  45518. +#define SMC_IO_EXTENT (16 << 2)
  45519. +
  45520. +/*
  45521. + * These functions allow us to handle IO addressing as we wish - this
  45522. + * ethernet controller can be connected to a variety of busses. Some
  45523. + * busses do not support 16 bit or 32 bit transfers. --rmk
  45524. + */
  45525. +static inline u8 smc_inb(u_int base, u_int reg)
  45526. +{
  45527. + u_int port = base + reg * 4;
  45528. +
  45529. + return readb(port);
  45530. +}
  45531. +
  45532. +static inline u16 smc_inw(u_int base, u_int reg)
  45533. +{
  45534. + u_int port = base + reg * 4;
  45535. +
  45536. + return readb(port) | readb(port + 4) << 8;
  45537. +}
  45538. +
  45539. +static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
  45540. +{
  45541. + u_int port = base + reg * 4;
  45542. +
  45543. + insb(port, data, len);
  45544. +}
  45545. +
  45546. +static inline void smc_outb(u8 val, u_int base, u_int reg)
  45547. +{
  45548. + u_int port = base + reg * 4;
  45549. +
  45550. + writeb(val, port);
  45551. +}
  45552. +
  45553. +static inline void smc_outw(u16 val, u_int base, u_int reg)
  45554. +{
  45555. + u_int port = base + reg * 4;
  45556. +
  45557. + writeb(val, port);
  45558. + writeb(val >> 8, port + 4);
  45559. +}
  45560. +
  45561. +static inline void smc_outl(u32 val, u_int base, u_int reg)
  45562. +{
  45563. + u_int port = base + reg * 4;
  45564. +
  45565. + writeb(val, port);
  45566. + writeb(val >> 8, port + 4);
  45567. + writeb(val >> 16, port + 8);
  45568. + writeb(val >> 24, port + 12);
  45569. +}
  45570. +
  45571. +static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
  45572. +{
  45573. + u_int port = base + reg * 4;
  45574. +
  45575. + outsb(port, data, len & ~1);
  45576. +}
  45577. +
  45578. +/*-------------------------------------------------------------------------
  45579. + . I define some macros to make it easier to do somewhat common
  45580. + . or slightly complicated, repeated tasks.
  45581. + --------------------------------------------------------------------------*/
  45582. +
  45583. +/* select a register bank, 0 to 3 */
  45584. +
  45585. +#define SMC_SELECT_BANK(x) \
  45586. + { \
  45587. + smc_outb(x, ioaddr, BANK_SELECT); \
  45588. + }
  45589. +
  45590. +/* define a small delay for the reset */
  45591. +#define SMC_DELAY() \
  45592. + { \
  45593. + smc_inb(ioaddr, RCR); \
  45594. + smc_inb(ioaddr, RCR); \
  45595. + smc_inb(ioaddr, RCR); \
  45596. + }
  45597. +
  45598. +/* this enables an interrupt in the interrupt mask register */
  45599. +#define SMC_ENABLE_INT(x) \
  45600. + { \
  45601. + byte mask; \
  45602. + mask = smc_inb(ioaddr, INT_MASK); \
  45603. + mask |= (x); \
  45604. + smc_outb(mask, ioaddr, INT_MASK); \
  45605. + }
  45606. +
  45607. +/* this sets the absolutel interrupt mask */
  45608. +#define SMC_SET_INT(x) \
  45609. + { \
  45610. + smc_outb((x), ioaddr, INT_MASK); \
  45611. + }
  45612. +
  45613. +#endif
  45614. /*
  45615. - . Function: smc_reset( int ioaddr )
  45616. + . A rather simple routine to print out a packet for debugging purposes.
  45617. +*/
  45618. +#if SMC_DEBUG > 2
  45619. +static void print_packet(byte * buf, int length)
  45620. +{
  45621. + int i;
  45622. + int remainder;
  45623. + int lines;
  45624. +
  45625. + printk("Packet of length %d \n", length);
  45626. + lines = length / 16;
  45627. + remainder = length % 16;
  45628. +
  45629. + for (i = 0; i < lines ; i ++) {
  45630. + int cur;
  45631. +
  45632. + for (cur = 0; cur < 8; cur ++) {
  45633. + byte a, b;
  45634. +
  45635. + a = *(buf ++);
  45636. + b = *(buf ++);
  45637. + printk("%02x%02x ", a, b);
  45638. + }
  45639. + printk("\n");
  45640. + }
  45641. + for (i = 0; i < remainder/2 ; i++) {
  45642. + byte a, b;
  45643. +
  45644. + a = *(buf ++);
  45645. + b = *(buf ++);
  45646. + printk("%02x%02x ", a, b);
  45647. + }
  45648. + if (remainder & 1) {
  45649. + byte a;
  45650. +
  45651. + a = *buf++;
  45652. + printk("%02x", a);
  45653. + }
  45654. + printk("\n");
  45655. +}
  45656. +#else
  45657. +#define print_packet(buf,len) do { } while (0)
  45658. +#endif
  45659. +
  45660. +/*
  45661. + . Function: smc_reset(struct net_device *dev)
  45662. . Purpose:
  45663. . This sets the SMC91xx chip to its normal state, hopefully from whatever
  45664. . mess that any other DOS driver has put it in.
  45665. @@ -309,36 +579,37 @@
  45666. . 5. clear all interrupts
  45667. .
  45668. */
  45669. -static void smc_reset( int ioaddr )
  45670. +static void smc_reset(struct net_device *dev)
  45671. {
  45672. + u_int ioaddr = dev->base_addr;
  45673. +
  45674. /* This resets the registers mostly to defaults, but doesn't
  45675. affect EEPROM. That seems unnecessary */
  45676. - SMC_SELECT_BANK( 0 );
  45677. - outw( RCR_SOFTRESET, ioaddr + RCR );
  45678. + SMC_SELECT_BANK(0);
  45679. + smc_outw(RCR_SOFTRESET, ioaddr, RCR);
  45680. /* this should pause enough for the chip to be happy */
  45681. - SMC_DELAY( );
  45682. + SMC_DELAY();
  45683. /* Set the transmit and receive configuration registers to
  45684. default values */
  45685. - outw( RCR_CLEAR, ioaddr + RCR );
  45686. - outw( TCR_CLEAR, ioaddr + TCR );
  45687. + smc_outw(RCR_CLEAR, ioaddr, RCR);
  45688. + smc_outw(TCR_CLEAR, ioaddr, TCR);
  45689. /* set the control register to automatically
  45690. release successfully transmitted packets, to make the best
  45691. use out of our limited memory */
  45692. - SMC_SELECT_BANK( 1 );
  45693. - outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL );
  45694. + SMC_SELECT_BANK(1);
  45695. + smc_outw(smc_inw(ioaddr, CONTROL) | CTL_AUTO_RELEASE, ioaddr, CONTROL);
  45696. /* Reset the MMU */
  45697. - SMC_SELECT_BANK( 2 );
  45698. - outw( MC_RESET, ioaddr + MMU_CMD );
  45699. + SMC_SELECT_BANK(2);
  45700. + smc_outw(MC_RESET, ioaddr, MMU_CMD);
  45701. /* Note: It doesn't seem that waiting for the MMU busy is needed here,
  45702. but this is a place where future chipsets _COULD_ break. Be wary
  45703. of issuing another MMU command right after this */
  45704. -
  45705. - outb( 0, ioaddr + INT_MASK );
  45706. + SMC_SET_INT(0);
  45707. }
  45708. /*
  45709. @@ -349,20 +620,21 @@
  45710. . 2. Enable the receiver
  45711. . 3. Enable interrupts
  45712. */
  45713. -static void smc_enable( int ioaddr )
  45714. +static void smc_enable(struct net_device *dev)
  45715. {
  45716. - SMC_SELECT_BANK( 0 );
  45717. + u_int ioaddr = dev->base_addr;
  45718. + SMC_SELECT_BANK(0);
  45719. /* see the header file for options in TCR/RCR NORMAL*/
  45720. - outw( TCR_NORMAL, ioaddr + TCR );
  45721. - outw( RCR_NORMAL, ioaddr + RCR );
  45722. + smc_outw(TCR_NORMAL, ioaddr, TCR);
  45723. + smc_outw(RCR_NORMAL, ioaddr, RCR);
  45724. /* now, enable interrupts */
  45725. - SMC_SELECT_BANK( 2 );
  45726. - outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK );
  45727. + SMC_SELECT_BANK(2);
  45728. + SMC_SET_INT(SMC_INTERRUPT_MASK);
  45729. }
  45730. /*
  45731. - . Function: smc_shutdown
  45732. + . Function: smc_shutdown(struct net_device *dev)
  45733. . Purpose: closes down the SMC91xxx chip.
  45734. . Method:
  45735. . 1. zero the interrupt mask
  45736. @@ -375,26 +647,28 @@
  45737. . the manual says that it will wake up in response to any I/O requests
  45738. . in the register space. Empirical results do not show this working.
  45739. */
  45740. -static void smc_shutdown( int ioaddr )
  45741. +static void smc_shutdown(struct net_device *dev)
  45742. {
  45743. + u_int ioaddr = dev->base_addr;
  45744. +
  45745. /* no more interrupts for me */
  45746. - SMC_SELECT_BANK( 2 );
  45747. - outb( 0, ioaddr + INT_MASK );
  45748. + SMC_SELECT_BANK(2);
  45749. + SMC_SET_INT(0);
  45750. /* and tell the card to stay away from that nasty outside world */
  45751. - SMC_SELECT_BANK( 0 );
  45752. - outb( RCR_CLEAR, ioaddr + RCR );
  45753. - outb( TCR_CLEAR, ioaddr + TCR );
  45754. + SMC_SELECT_BANK(0);
  45755. + smc_outb(RCR_CLEAR, ioaddr, RCR);
  45756. + smc_outb(TCR_CLEAR, ioaddr, TCR);
  45757. #if 0
  45758. /* finally, shut the chip down */
  45759. - SMC_SELECT_BANK( 1 );
  45760. - outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL );
  45761. + SMC_SELECT_BANK(1);
  45762. + smc_outw(smc_inw(ioaddr, CONTROL), CTL_POWERDOWN, ioaddr, CONTROL);
  45763. #endif
  45764. }
  45765. /*
  45766. - . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
  45767. + . Function: smc_setmulticast(int ioaddr, int count, dev_mc_list * adds)
  45768. . Purpose:
  45769. . This sets the internal hardware table to filter out unwanted multicast
  45770. . packets before they take up memory.
  45771. @@ -411,26 +685,28 @@
  45772. */
  45773. -static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) {
  45774. +static void smc_setmulticast(struct net_device *dev, int count, struct dev_mc_list * addrs)
  45775. +{
  45776. + u_int ioaddr = dev->base_addr;
  45777. int i;
  45778. - unsigned char multicast_table[ 8 ];
  45779. + unsigned char multicast_table[8];
  45780. struct dev_mc_list * cur_addr;
  45781. /* table for flipping the order of 3 bits */
  45782. unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
  45783. /* start with a table of all zeros: reject all */
  45784. - memset( multicast_table, 0, sizeof( multicast_table ) );
  45785. + memset(multicast_table, 0, sizeof(multicast_table));
  45786. cur_addr = addrs;
  45787. - for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) {
  45788. + for (i = 0; i < count ; i ++, cur_addr = cur_addr->next) {
  45789. int position;
  45790. /* do we have a pointer here? */
  45791. - if ( !cur_addr )
  45792. + if (!cur_addr)
  45793. break;
  45794. /* make sure this is a multicast address - shouldn't this
  45795. be a given if we have it here ? */
  45796. - if ( !( *cur_addr->dmi_addr & 1 ) )
  45797. + if (!(*cur_addr->dmi_addr & 1))
  45798. continue;
  45799. /* only use the low order bits */
  45800. @@ -442,15 +718,15 @@
  45801. }
  45802. /* now, the table can be loaded into the chipset */
  45803. - SMC_SELECT_BANK( 3 );
  45804. + SMC_SELECT_BANK(3);
  45805. - for ( i = 0; i < 8 ; i++ ) {
  45806. - outb( multicast_table[i], ioaddr + MULTICAST1 + i );
  45807. + for (i = 0; i < 8 ; i++) {
  45808. + smc_outb(multicast_table[i], ioaddr, MULTICAST1 + i);
  45809. }
  45810. }
  45811. /*
  45812. - . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
  45813. + . Function: smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *)
  45814. . Purpose:
  45815. . Attempt to allocate memory for a packet, if chip-memory is not
  45816. . available, then tell the card to generate an interrupt when it
  45817. @@ -465,10 +741,10 @@
  45818. . o (NO): Enable interrupts and let the interrupt handler deal with it.
  45819. . o (YES):Send it now.
  45820. */
  45821. -static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
  45822. +static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev)
  45823. {
  45824. struct smc_local *lp = (struct smc_local *)dev->priv;
  45825. - unsigned short ioaddr = dev->base_addr;
  45826. + u_int ioaddr = dev->base_addr;
  45827. word length;
  45828. unsigned short numPages;
  45829. word time_out;
  45830. @@ -477,15 +753,16 @@
  45831. /* Well, I want to send the packet.. but I don't know
  45832. if I can send it right now... */
  45833. - if ( lp->saved_skb) {
  45834. + if (lp->saved_skb) {
  45835. /* THIS SHOULD NEVER HAPPEN. */
  45836. lp->stats.tx_aborted_errors++;
  45837. - printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );
  45838. + printk("%s: Bad Craziness - sent packet while busy.\n",
  45839. + dev->name);
  45840. return 1;
  45841. }
  45842. length = skb->len;
  45843. -
  45844. +
  45845. if(length < ETH_ZLEN)
  45846. {
  45847. skb = skb_padto(skb, ETH_ZLEN);
  45848. @@ -497,18 +774,18 @@
  45849. length = ETH_ZLEN;
  45850. }
  45851. lp->saved_skb = skb;
  45852. -
  45853. +
  45854. /*
  45855. ** The MMU wants the number of pages to be the number of 256 bytes
  45856. - ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
  45857. + ** 'pages', minus 1 (since a packet can't ever have 0 pages :))
  45858. **
  45859. ** Pkt size for allocating is data length +6 (for additional status words,
  45860. ** length and ctl!) If odd size last byte is included in this header.
  45861. */
  45862. - numPages = ((length & 0xfffe) + 6) / 256;
  45863. + numPages = ((length & 0xfffe) + 6) / 256;
  45864. - if (numPages > 7 ) {
  45865. - printk(CARDNAME": Far too big packet error. \n");
  45866. + if (numPages > 7) {
  45867. + printk("%s: Far too big packet error.\n", dev->name);
  45868. /* freeing the packet is a good thing here... but should
  45869. . any packets of this size get down here? */
  45870. dev_kfree_skb (skb);
  45871. @@ -517,12 +794,13 @@
  45872. netif_wake_queue(dev);
  45873. return 0;
  45874. }
  45875. +
  45876. /* either way, a packet is waiting now */
  45877. lp->packets_waiting++;
  45878. /* now, try to allocate the memory */
  45879. - SMC_SELECT_BANK( 2 );
  45880. - outw( MC_ALLOC | numPages, ioaddr + MMU_CMD );
  45881. + SMC_SELECT_BANK(2);
  45882. + smc_outw(MC_ALLOC | numPages, ioaddr, MMU_CMD);
  45883. /*
  45884. . Performance Hack
  45885. .
  45886. @@ -539,21 +817,21 @@
  45887. do {
  45888. word status;
  45889. - status = inb( ioaddr + INTERRUPT );
  45890. - if ( status & IM_ALLOC_INT ) {
  45891. + status = smc_inb(ioaddr, INTERRUPT);
  45892. + if (status & IM_ALLOC_INT) {
  45893. /* acknowledge the interrupt */
  45894. - outb( IM_ALLOC_INT, ioaddr + INTERRUPT );
  45895. - break;
  45896. + smc_outb(IM_ALLOC_INT, ioaddr, INTERRUPT);
  45897. + break;
  45898. }
  45899. - } while ( -- time_out );
  45900. + } while (-- time_out);
  45901. - if ( !time_out ) {
  45902. + if (!time_out) {
  45903. /* oh well, wait until the chip finds memory later */
  45904. - SMC_ENABLE_INT( IM_ALLOC_INT );
  45905. - PRINTK2((CARDNAME": memory allocation deferred. \n"));
  45906. + SMC_ENABLE_INT(IM_ALLOC_INT);
  45907. + PRINTK2(("%s: memory allocation deferred.\n", dev->name));
  45908. /* it's deferred, but I'll handle it later */
  45909. - return 0;
  45910. - }
  45911. + return 0;
  45912. + }
  45913. /* or YES! I can send the packet now.. */
  45914. smc_hardware_send_packet(dev);
  45915. netif_wake_queue(dev);
  45916. @@ -561,46 +839,46 @@
  45917. }
  45918. /*
  45919. - . Function: smc_hardware_send_packet(struct net_device * )
  45920. + . Function: smc_hardware_send_packet(struct net_device *)
  45921. . Purpose:
  45922. . This sends the actual packet to the SMC9xxx chip.
  45923. .
  45924. . Algorithm:
  45925. . First, see if a saved_skb is available.
  45926. - . ( this should NOT be called if there is no 'saved_skb'
  45927. + . (this should NOT be called if there is no 'saved_skb'
  45928. . Now, find the packet number that the chip allocated
  45929. . Point the data pointers at it in memory
  45930. . Set the length word in the chip's memory
  45931. . Dump the packet to chip memory
  45932. - . Check if a last byte is needed ( odd length packet )
  45933. + . Check if a last byte is needed (odd length packet)
  45934. . if so, set the control flag right
  45935. . Tell the card to send it
  45936. . Enable the transmit interrupt, so I know if it failed
  45937. . Free the kernel data if I actually sent it.
  45938. */
  45939. -static void smc_hardware_send_packet( struct net_device * dev )
  45940. +static void smc_hardware_send_packet(struct net_device *dev)
  45941. {
  45942. struct smc_local *lp = (struct smc_local *)dev->priv;
  45943. - byte packet_no;
  45944. - struct sk_buff * skb = lp->saved_skb;
  45945. - word length;
  45946. - unsigned short ioaddr;
  45947. - byte * buf;
  45948. -
  45949. - ioaddr = dev->base_addr;
  45950. + struct sk_buff *skb = lp->saved_skb;
  45951. + word length, lastword;
  45952. + u_int ioaddr = dev->base_addr;
  45953. + byte packet_no;
  45954. + byte *buf;
  45955. - if ( !skb ) {
  45956. - PRINTK((CARDNAME": In XMIT with no packet to send \n"));
  45957. + if (!skb) {
  45958. + PRINTK(("%s: In XMIT with no packet to send\n", dev->name));
  45959. return;
  45960. }
  45961. +
  45962. length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
  45963. buf = skb->data;
  45964. /* If I get here, I _know_ there is a packet slot waiting for me */
  45965. - packet_no = inb( ioaddr + PNR_ARR + 1 );
  45966. - if ( packet_no & 0x80 ) {
  45967. + packet_no = smc_inb(ioaddr, PNR_ARR + 1);
  45968. + if (packet_no & 0x80) {
  45969. /* or isn't there? BAD CHIP! */
  45970. - printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");
  45971. + printk(KERN_DEBUG "%s: Memory allocation failed.\n",
  45972. + dev->name);
  45973. dev_kfree_skb_any(skb);
  45974. lp->saved_skb = NULL;
  45975. netif_wake_queue(dev);
  45976. @@ -608,26 +886,19 @@
  45977. }
  45978. /* we have a packet address, so tell the card to use it */
  45979. - outb( packet_no, ioaddr + PNR_ARR );
  45980. + smc_outb(packet_no, ioaddr, PNR_ARR);
  45981. /* point to the beginning of the packet */
  45982. - outw( PTR_AUTOINC , ioaddr + POINTER );
  45983. + smc_outw(PTR_AUTOINC, ioaddr, POINTER);
  45984. - PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length ));
  45985. -#if SMC_DEBUG > 2
  45986. - print_packet( buf, length );
  45987. -#endif
  45988. + PRINTK3(("%s: Trying to xmit packet of length %x\n",
  45989. + dev->name, length));
  45990. - /* send the packet length ( +6 for status, length and ctl byte )
  45991. - and the status word ( set to zeros ) */
  45992. -#ifdef USE_32_BIT
  45993. - outl( (length +6 ) << 16 , ioaddr + DATA_1 );
  45994. -#else
  45995. - outw( 0, ioaddr + DATA_1 );
  45996. - /* send the packet length ( +6 for status words, length, and ctl*/
  45997. - outb( (length+6) & 0xFF,ioaddr + DATA_1 );
  45998. - outb( (length+6) >> 8 , ioaddr + DATA_1 );
  45999. -#endif
  46000. + print_packet(buf, length);
  46001. +
  46002. + /* send the packet length (+6 for status, length and ctl byte)
  46003. + and the status word (set to zeros) */
  46004. + smc_outl((length + 6) << 16, ioaddr, DATA_1);
  46005. /* send the actual data
  46006. . I _think_ it's faster to send the longs first, and then
  46007. @@ -636,32 +907,22 @@
  46008. . a good idea to check which is optimal? But that could take
  46009. . almost as much time as is saved?
  46010. */
  46011. -#ifdef USE_32_BIT
  46012. - if ( length & 0x2 ) {
  46013. - outsl(ioaddr + DATA_1, buf, length >> 2 );
  46014. - outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
  46015. - }
  46016. - else
  46017. - outsl(ioaddr + DATA_1, buf, length >> 2 );
  46018. -#else
  46019. - outsw(ioaddr + DATA_1 , buf, (length ) >> 1);
  46020. -#endif
  46021. - /* Send the last byte, if there is one. */
  46022. + smc_outs(ioaddr, DATA_1, buf, length);
  46023. - if ( (length & 1) == 0 ) {
  46024. - outw( 0, ioaddr + DATA_1 );
  46025. - } else {
  46026. - outb( buf[length -1 ], ioaddr + DATA_1 );
  46027. - outb( 0x20, ioaddr + DATA_1);
  46028. - }
  46029. + /* Send the last byte, if there is one. */
  46030. + if ((length & 1) == 0)
  46031. + lastword = 0;
  46032. + else
  46033. + lastword = 0x2000 | buf[length - 1];
  46034. + smc_outw(lastword, ioaddr, DATA_1);
  46035. /* enable the interrupts */
  46036. - SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) );
  46037. + SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
  46038. /* and let the chipset deal with it */
  46039. - outw( MC_ENQUEUE , ioaddr + MMU_CMD );
  46040. + smc_outw(MC_ENQUEUE, ioaddr, MMU_CMD);
  46041. - PRINTK2((CARDNAME": Sent packet of length %d \n",length));
  46042. + PRINTK2(("%s: Sent packet of length %d\n", dev->name, length));
  46043. lp->saved_skb = NULL;
  46044. dev_kfree_skb_any (skb);
  46045. @@ -676,7 +937,7 @@
  46046. /*-------------------------------------------------------------------------
  46047. |
  46048. - | smc_init( struct net_device * dev )
  46049. + | smc_init(struct net_device * dev)
  46050. | Input parameters:
  46051. | dev->base_addr == 0, try to find all possible locations
  46052. | dev->base_addr == 1, return failure code
  46053. @@ -691,6 +952,65 @@
  46054. */
  46055. int __init smc_init(struct net_device *dev)
  46056. {
  46057. + int ret = -ENODEV;
  46058. +#if defined(CONFIG_ASSABET_NEPONSET)
  46059. + if (machine_is_assabet() && machine_has_neponset()) {
  46060. + unsigned int *addr;
  46061. + unsigned char ecor;
  46062. + unsigned long flags;
  46063. +
  46064. + NCR_0 |= NCR_ENET_OSC_EN;
  46065. + dev->irq = IRQ_NEPONSET_SMC9196;
  46066. +
  46067. + /*
  46068. + * Map the attribute space. This is overkill, but clean.
  46069. + */
  46070. + addr = ioremap(0x18000000 + (1 << 25), 64 * 1024 * 4);
  46071. + if (!addr)
  46072. + return -ENOMEM;
  46073. +
  46074. + /*
  46075. + * Reset the device. We must disable IRQs around this.
  46076. + */
  46077. + local_irq_save(flags);
  46078. + ecor = readl(addr + ECOR) & ~ECOR_RESET;
  46079. + writel(ecor | ECOR_RESET, addr + ECOR);
  46080. + udelay(100);
  46081. +
  46082. + /*
  46083. + * The device will ignore all writes to the enable bit while
  46084. + * reset is asserted, even if the reset bit is cleared in the
  46085. + * same write. Must clear reset first, then enable the device.
  46086. + */
  46087. + writel(ecor, addr + ECOR);
  46088. + writel(ecor | ECOR_ENABLE, addr + ECOR);
  46089. +
  46090. + /*
  46091. + * Force byte mode.
  46092. + */
  46093. + writel(readl(addr + ECSR) | ECSR_IOIS8, addr + ECSR);
  46094. + local_irq_restore(flags);
  46095. +
  46096. + iounmap(addr);
  46097. +
  46098. + /*
  46099. + * Wait for the chip to wake up.
  46100. + */
  46101. + mdelay(1);
  46102. +
  46103. + /*
  46104. + * Map the real registers.
  46105. + */
  46106. + addr = ioremap(0x18000000, 8 * 1024);
  46107. + if (!addr)
  46108. + return -ENOMEM;
  46109. +
  46110. + ret = smc_probe(dev, (int)addr);
  46111. + if (ret)
  46112. + iounmap(addr);
  46113. + }
  46114. +
  46115. +#elif defined(CONFIG_ISA)
  46116. int i;
  46117. int base_addr = dev->base_addr;
  46118. @@ -708,7 +1028,8 @@
  46119. return 0;
  46120. /* couldn't find anything */
  46121. - return -ENODEV;
  46122. +#endif
  46123. + return ret;
  46124. }
  46125. /*----------------------------------------------------------------------
  46126. @@ -718,10 +1039,11 @@
  46127. . interrupt, so an auto-detect routine can detect it, and find the IRQ,
  46128. ------------------------------------------------------------------------
  46129. */
  46130. -int __init smc_findirq( int ioaddr )
  46131. +int __init smc_findirq(struct net_device *dev)
  46132. {
  46133. int timeout = 20;
  46134. unsigned long cookie;
  46135. + u_int ioaddr = dev->base_addr;
  46136. /* I have to do a STI() here, because this is called from
  46137. @@ -737,26 +1059,25 @@
  46138. * when done.
  46139. */
  46140. -
  46141. + /* enable ALLOCation interrupts ONLY. */
  46142. SMC_SELECT_BANK(2);
  46143. - /* enable ALLOCation interrupts ONLY */
  46144. - outb( IM_ALLOC_INT, ioaddr + INT_MASK );
  46145. + SMC_SET_INT(IM_ALLOC_INT);
  46146. /*
  46147. . Allocate 512 bytes of memory. Note that the chip was just
  46148. . reset so all the memory is available
  46149. */
  46150. - outw( MC_ALLOC | 1, ioaddr + MMU_CMD );
  46151. + smc_outw(MC_ALLOC | 1, ioaddr, MMU_CMD);
  46152. /*
  46153. . Wait until positive that the interrupt has been generated
  46154. */
  46155. - while ( timeout ) {
  46156. + while (timeout) {
  46157. byte int_status;
  46158. - int_status = inb( ioaddr + INTERRUPT );
  46159. + int_status = smc_inb(ioaddr, INTERRUPT);
  46160. - if ( int_status & IM_ALLOC_INT )
  46161. + if (int_status & IM_ALLOC_INT)
  46162. break; /* got the interrupt */
  46163. timeout--;
  46164. }
  46165. @@ -775,7 +1096,7 @@
  46166. SMC_DELAY();
  46167. /* and disable all interrupts again */
  46168. - outb( 0, ioaddr + INT_MASK );
  46169. + SMC_SET_INT(0);
  46170. /* clear hardware interrupts again, because that's how it
  46171. was when I was called... */
  46172. @@ -785,8 +1106,87 @@
  46173. return probe_irq_off(cookie);
  46174. }
  46175. +static int __init smc_probe_chip(struct net_device *dev, int ioaddr)
  46176. +{
  46177. + unsigned int temp;
  46178. +
  46179. + /* First, see if the high byte is 0x33 */
  46180. + temp = smc_inw(ioaddr, BANK_SELECT);
  46181. + if ((temp & 0xFF00) != 0x3300)
  46182. + return -ENODEV;
  46183. +
  46184. + /* The above MIGHT indicate a device, but I need to write to further
  46185. + test this. */
  46186. + smc_outw(0, ioaddr, BANK_SELECT);
  46187. + temp = smc_inw(ioaddr, BANK_SELECT);
  46188. + if ((temp & 0xFF00) != 0x3300)
  46189. + return -ENODEV;
  46190. +
  46191. +#ifndef CONFIG_ASSABET_NEPONSET
  46192. + /* well, we've already written once, so hopefully another time won't
  46193. + hurt. This time, I need to switch the bank register to bank 1,
  46194. + so I can access the base address register */
  46195. + SMC_SELECT_BANK(1);
  46196. + temp = smc_inw(ioaddr, BASE);
  46197. + if (ioaddr != (temp >> 3 & 0x3E0)) {
  46198. + printk("%s: IOADDR %x doesn't match configuration (%x)."
  46199. + "Probably not a SMC chip\n", dev->name,
  46200. + ioaddr, (base_address_register >> 3) & 0x3E0);
  46201. + /* well, the base address register didn't match. Must not have
  46202. + been a SMC chip after all. */
  46203. + return -ENODEV;
  46204. + }
  46205. +#endif
  46206. +
  46207. + return 0;
  46208. +}
  46209. +
  46210. +/*
  46211. + . If dev->irq is 0, then the device has to be banged on to see
  46212. + . what the IRQ is.
  46213. + .
  46214. + . This banging doesn't always detect the IRQ, for unknown reasons.
  46215. + . a workaround is to reset the chip and try again.
  46216. + .
  46217. + . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
  46218. + . be what is requested on the command line. I don't do that, mostly
  46219. + . because the card that I have uses a non-standard method of accessing
  46220. + . the IRQs, and because this _should_ work in most configurations.
  46221. + .
  46222. + . Specifying an IRQ is done with the assumption that the user knows
  46223. + . what (s)he is doing. No checking is done!!!!
  46224. + .
  46225. +*/
  46226. +static int __init smc_probe_irq(struct net_device *dev)
  46227. +{
  46228. + if (dev->irq < 2) {
  46229. + int trials;
  46230. +
  46231. + trials = 3;
  46232. + while (trials--) {
  46233. + dev->irq = smc_findirq(dev);
  46234. + if (dev->irq)
  46235. + break;
  46236. + /* kick the card and try again */
  46237. + smc_reset(dev);
  46238. + }
  46239. + }
  46240. + if (dev->irq == 0) {
  46241. + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
  46242. + dev->name);
  46243. + return -ENODEV;
  46244. + }
  46245. +
  46246. + /*
  46247. + * Some machines (eg, PCs) need to cannonicalize their IRQs.
  46248. + */
  46249. + dev->irq = irq_cannonicalize(dev->irq);
  46250. +
  46251. + return 0;
  46252. +}
  46253. +
  46254. /*----------------------------------------------------------------------
  46255. - . Function: smc_probe( int ioaddr )
  46256. + . Function: smc_probe(struct net_device *dev, int ioaddr)
  46257. .
  46258. . Purpose:
  46259. . Tests to see if a given ioaddr points to an SMC9xxx chip.
  46260. @@ -816,16 +1216,14 @@
  46261. */
  46262. static int __init smc_probe(struct net_device *dev, int ioaddr)
  46263. {
  46264. + struct smc_local *smc;
  46265. int i, memory, retval;
  46266. static unsigned version_printed;
  46267. - unsigned int bank;
  46268. const char *version_string;
  46269. - const char *if_string;
  46270. /* registers */
  46271. word revision_register;
  46272. - word base_address_register;
  46273. word configuration_register;
  46274. word memory_info_register;
  46275. word memory_cfg_register;
  46276. @@ -834,44 +1232,24 @@
  46277. if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
  46278. return -EBUSY;
  46279. - /* First, see if the high byte is 0x33 */
  46280. - bank = inw( ioaddr + BANK_SELECT );
  46281. - if ( (bank & 0xFF00) != 0x3300 ) {
  46282. - retval = -ENODEV;
  46283. - goto err_out;
  46284. - }
  46285. - /* The above MIGHT indicate a device, but I need to write to further
  46286. - test this. */
  46287. - outw( 0x0, ioaddr + BANK_SELECT );
  46288. - bank = inw( ioaddr + BANK_SELECT );
  46289. - if ( (bank & 0xFF00 ) != 0x3300 ) {
  46290. - retval = -ENODEV;
  46291. - goto err_out;
  46292. - }
  46293. - /* well, we've already written once, so hopefully another time won't
  46294. - hurt. This time, I need to switch the bank register to bank 1,
  46295. - so I can access the base address register */
  46296. - SMC_SELECT_BANK(1);
  46297. - base_address_register = inw( ioaddr + BASE );
  46298. - if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) {
  46299. - printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)."
  46300. - "Probably not a SMC chip\n",
  46301. - ioaddr, base_address_register >> 3 & 0x3E0 );
  46302. - /* well, the base address register didn't match. Must not have
  46303. - been a SMC chip after all. */
  46304. - retval = -ENODEV;
  46305. + /*
  46306. + * Do the basic probes.
  46307. + */
  46308. + retval = smc_probe_chip(dev, ioaddr);
  46309. + if (retval)
  46310. goto err_out;
  46311. - }
  46312. /* check if the revision register is something that I recognize.
  46313. These might need to be added to later, as future revisions
  46314. could be added. */
  46315. SMC_SELECT_BANK(3);
  46316. - revision_register = inw( ioaddr + REVISION );
  46317. - if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) {
  46318. + revision_register = smc_inw(ioaddr, REVISION);
  46319. + version_string = chip_ids[(revision_register >> 4) & 15];
  46320. + if (!version_string) {
  46321. /* I don't recognize this chip, so... */
  46322. - printk(CARDNAME ": IO %x: Unrecognized revision register:"
  46323. - " %x, Contact author. \n", ioaddr, revision_register );
  46324. + printk("%s: IO %x: unrecognized revision register: %x, "
  46325. + "contact author.\n", dev->name, ioaddr,
  46326. + revision_register);
  46327. retval = -ENODEV;
  46328. goto err_out;
  46329. @@ -882,138 +1260,122 @@
  46330. against the hardware address, or do some other tests. */
  46331. if (version_printed++ == 0)
  46332. - printk("%s", version);
  46333. + printk(KERN_INFO "%s", version);
  46334. /* fill in some of the fields */
  46335. dev->base_addr = ioaddr;
  46336. /*
  46337. - . Get the MAC address ( bank 1, regs 4 - 9 )
  46338. + . Get the MAC address (bank 1, regs 4 - 9)
  46339. */
  46340. - SMC_SELECT_BANK( 1 );
  46341. - for ( i = 0; i < 6; i += 2 ) {
  46342. + SMC_SELECT_BANK(1);
  46343. + for (i = 0; i < 6; i += 2) {
  46344. word address;
  46345. - address = inw( ioaddr + ADDR0 + i );
  46346. - dev->dev_addr[ i + 1] = address >> 8;
  46347. - dev->dev_addr[ i ] = address & 0xFF;
  46348. + address = smc_inw(ioaddr, ADDR0 + i);
  46349. + dev->dev_addr[i + 1] = address >> 8;
  46350. + dev->dev_addr[i] = address & 0xFF;
  46351. }
  46352. + if (!is_valid_ether_addr(dev->dev_addr))
  46353. + printk("%s: Invalid ethernet MAC address. Please set using "
  46354. + "ifconfig\n", dev->name);
  46355. +
  46356. /* get the memory information */
  46357. - SMC_SELECT_BANK( 0 );
  46358. - memory_info_register = inw( ioaddr + MIR );
  46359. - memory_cfg_register = inw( ioaddr + MCR );
  46360. - memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */
  46361. - memory *= 256 * ( memory_info_register & 0xFF );
  46362. + SMC_SELECT_BANK(0);
  46363. + memory_info_register = smc_inw(ioaddr, MIR);
  46364. + memory_cfg_register = smc_inw(ioaddr, MCR);
  46365. + memory = (memory_cfg_register >> 9) & 0x7; /* multiplier */
  46366. + memory *= 256 * (memory_info_register & 0xFF);
  46367. +
  46368. + /* now, reset the chip, and put it into a known state */
  46369. + smc_reset(dev);
  46370. /*
  46371. - Now, I want to find out more about the chip. This is sort of
  46372. - redundant, but it's cleaner to have it in both, rather than having
  46373. - one VERY long probe procedure.
  46374. - */
  46375. - SMC_SELECT_BANK(3);
  46376. - revision_register = inw( ioaddr + REVISION );
  46377. - version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ];
  46378. - if ( !version_string ) {
  46379. - /* I shouldn't get here because this call was done before.... */
  46380. - retval = -ENODEV;
  46381. + * Ok, now that we have everything in a
  46382. + * sane state, probe for the interrupt.
  46383. + */
  46384. + retval = smc_probe_irq(dev);
  46385. + if (retval)
  46386. goto err_out;
  46387. - }
  46388. - /* is it using AUI or 10BaseT ? */
  46389. - if ( dev->if_port == 0 ) {
  46390. - SMC_SELECT_BANK(1);
  46391. - configuration_register = inw( ioaddr + CONFIG );
  46392. - if ( configuration_register & CFG_AUI_SELECT )
  46393. - dev->if_port = 2;
  46394. - else
  46395. - dev->if_port = 1;
  46396. + /* Initialize the private structure. */
  46397. + if (dev->priv == NULL) {
  46398. + dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
  46399. + if (dev->priv == NULL) {
  46400. + retval = -ENOMEM;
  46401. + goto err_out;
  46402. + }
  46403. }
  46404. - if_string = interfaces[ dev->if_port - 1 ];
  46405. - /* now, reset the chip, and put it into a known state */
  46406. - smc_reset( ioaddr );
  46407. + smc = dev->priv;
  46408. +
  46409. + /* set the private data to zero by default */
  46410. + memset(smc, 0, sizeof(struct smc_local));
  46411. /*
  46412. - . If dev->irq is 0, then the device has to be banged on to see
  46413. - . what the IRQ is.
  46414. - .
  46415. - . This banging doesn't always detect the IRQ, for unknown reasons.
  46416. - . a workaround is to reset the chip and try again.
  46417. - .
  46418. - . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
  46419. - . be what is requested on the command line. I don't do that, mostly
  46420. - . because the card that I have uses a non-standard method of accessing
  46421. - . the IRQs, and because this _should_ work in most configurations.
  46422. - .
  46423. - . Specifying an IRQ is done with the assumption that the user knows
  46424. - . what (s)he is doing. No checking is done!!!!
  46425. - .
  46426. - */
  46427. - if ( dev->irq < 2 ) {
  46428. - int trials;
  46429. + * Get the interface characteristics.
  46430. + * is it using AUI or 10BaseT ?
  46431. + */
  46432. + switch (dev->if_port) {
  46433. + case IF_PORT_10BASET:
  46434. + smc->port = PORT_TP;
  46435. + break;
  46436. +
  46437. + case IF_PORT_AUI:
  46438. + smc->port = PORT_AUI;
  46439. + break;
  46440. - trials = 3;
  46441. - while ( trials-- ) {
  46442. - dev->irq = smc_findirq( ioaddr );
  46443. - if ( dev->irq )
  46444. - break;
  46445. - /* kick the card and try again */
  46446. - smc_reset( ioaddr );
  46447. + default:
  46448. + SMC_SELECT_BANK(1);
  46449. + configuration_register = smc_inw(ioaddr, CONFIG);
  46450. + if (configuration_register & CFG_AUI_SELECT) {
  46451. + dev->if_port = IF_PORT_AUI;
  46452. + smc->port = PORT_AUI;
  46453. + } else {
  46454. + dev->if_port = IF_PORT_10BASET;
  46455. + smc->port = PORT_TP;
  46456. }
  46457. - }
  46458. - if (dev->irq == 0 ) {
  46459. - printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
  46460. - retval = -ENODEV;
  46461. - goto err_out;
  46462. + break;
  46463. }
  46464. - /* now, print out the card info, in a short format.. */
  46465. + /* all interfaces are half-duplex by default */
  46466. + smc->duplex = DUPLEX_HALF;
  46467. - printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
  46468. - version_string, revision_register & 0xF, ioaddr, dev->irq,
  46469. - if_string, memory );
  46470. + /* now, print out the card info, in a short format.. */
  46471. + printk("%s: %s (rev %d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
  46472. + version_string, revision_register & 15, ioaddr, dev->irq,
  46473. + interfaces[smc->port], memory);
  46474. /*
  46475. . Print the Ethernet address
  46476. */
  46477. printk("ADDR: ");
  46478. for (i = 0; i < 5; i++)
  46479. - printk("%2.2x:", dev->dev_addr[i] );
  46480. - printk("%2.2x \n", dev->dev_addr[5] );
  46481. -
  46482. -
  46483. - /* Initialize the private structure. */
  46484. - if (dev->priv == NULL) {
  46485. - dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
  46486. - if (dev->priv == NULL) {
  46487. - retval = -ENOMEM;
  46488. - goto err_out;
  46489. - }
  46490. - }
  46491. - /* set the private data to zero by default */
  46492. - memset(dev->priv, 0, sizeof(struct smc_local));
  46493. + printk("%2.2x:", dev->dev_addr[i]);
  46494. + printk("%2.2x\n", dev->dev_addr[5]);
  46495. /* Fill in the fields of the device structure with ethernet values. */
  46496. ether_setup(dev);
  46497. /* Grab the IRQ */
  46498. - retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
  46499. - if (retval) {
  46500. + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
  46501. + if (retval) {
  46502. printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
  46503. dev->irq, retval);
  46504. kfree(dev->priv);
  46505. dev->priv = NULL;
  46506. - goto err_out;
  46507. - }
  46508. + goto err_out;
  46509. + }
  46510. - dev->open = smc_open;
  46511. - dev->stop = smc_close;
  46512. - dev->hard_start_xmit = smc_wait_to_send_packet;
  46513. - dev->tx_timeout = smc_timeout;
  46514. - dev->watchdog_timeo = HZ/20;
  46515. - dev->get_stats = smc_query_statistics;
  46516. - dev->set_multicast_list = smc_set_multicast_list;
  46517. + dev->open = smc_open;
  46518. + dev->stop = smc_close;
  46519. + dev->hard_start_xmit = smc_wait_to_send_packet;
  46520. + dev->tx_timeout = smc_timeout;
  46521. + dev->watchdog_timeo = HZ/20;
  46522. + dev->get_stats = smc_query_statistics;
  46523. + dev->set_multicast_list = smc_set_multicast_list;
  46524. + dev->do_ioctl = smc_ioctl;
  46525. return 0;
  46526. @@ -1022,42 +1384,43 @@
  46527. return retval;
  46528. }
  46529. -#if SMC_DEBUG > 2
  46530. -static void print_packet( byte * buf, int length )
  46531. +/*
  46532. + * This is responsible for setting the chip appropriately
  46533. + * for the interface type. This should only be called while
  46534. + * the interface is up and running.
  46535. + */
  46536. +static void smc_set_port(struct net_device *dev)
  46537. {
  46538. -#if 0
  46539. - int i;
  46540. - int remainder;
  46541. - int lines;
  46542. -
  46543. - printk("Packet of length %d \n", length );
  46544. - lines = length / 16;
  46545. - remainder = length % 16;
  46546. + struct smc_local *smc = dev->priv;
  46547. + u_int ioaddr = dev->base_addr;
  46548. + u_int val;
  46549. - for ( i = 0; i < lines ; i ++ ) {
  46550. - int cur;
  46551. -
  46552. - for ( cur = 0; cur < 8; cur ++ ) {
  46553. - byte a, b;
  46554. -
  46555. - a = *(buf ++ );
  46556. - b = *(buf ++ );
  46557. - printk("%02x%02x ", a, b );
  46558. - }
  46559. - printk("\n");
  46560. + SMC_SELECT_BANK(1);
  46561. + val = smc_inw(ioaddr, CONFIG);
  46562. + switch (smc->port) {
  46563. + case PORT_TP:
  46564. + val &= ~CFG_AUI_SELECT;
  46565. + break;
  46566. +
  46567. + case PORT_AUI:
  46568. + val |= CFG_AUI_SELECT;
  46569. + break;
  46570. }
  46571. - for ( i = 0; i < remainder/2 ; i++ ) {
  46572. - byte a, b;
  46573. + smc_outw(val, ioaddr, CONFIG);
  46574. - a = *(buf ++ );
  46575. - b = *(buf ++ );
  46576. - printk("%02x%02x ", a, b );
  46577. + SMC_SELECT_BANK(0);
  46578. + val = smc_inw(ioaddr, TCR);
  46579. + switch (smc->duplex) {
  46580. + case DUPLEX_HALF:
  46581. + val &= ~TCR_FDSE;
  46582. + break;
  46583. +
  46584. + case DUPLEX_FULL:
  46585. + val |= TCR_FDSE;
  46586. + break;
  46587. }
  46588. - printk("\n");
  46589. -#endif
  46590. + smc_outw(val, ioaddr, TCR);
  46591. }
  46592. -#endif
  46593. -
  46594. /*
  46595. * Open and Initialize the board
  46596. @@ -1067,48 +1430,141 @@
  46597. */
  46598. static int smc_open(struct net_device *dev)
  46599. {
  46600. - int ioaddr = dev->base_addr;
  46601. + struct smc_local *smc = dev->priv;
  46602. + u_int ioaddr = dev->base_addr;
  46603. + int i;
  46604. - int i; /* used to set hw ethernet address */
  46605. + /*
  46606. + * Check that the address is valid. If its not, refuse
  46607. + * to bring the device up. The user must specify an
  46608. + * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
  46609. + */
  46610. + if (!is_valid_ether_addr(dev->dev_addr))
  46611. + return -EINVAL;
  46612. /* clear out all the junk that was put here before... */
  46613. - memset(dev->priv, 0, sizeof(struct smc_local));
  46614. + smc->saved_skb = NULL;
  46615. + smc->packets_waiting = 0;
  46616. /* reset the hardware */
  46617. -
  46618. - smc_reset( ioaddr );
  46619. - smc_enable( ioaddr );
  46620. + smc_reset(dev);
  46621. + smc_enable(dev);
  46622. /* Select which interface to use */
  46623. -
  46624. - SMC_SELECT_BANK( 1 );
  46625. - if ( dev->if_port == 1 ) {
  46626. - outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT,
  46627. - ioaddr + CONFIG );
  46628. - }
  46629. - else if ( dev->if_port == 2 ) {
  46630. - outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT,
  46631. - ioaddr + CONFIG );
  46632. - }
  46633. + smc_set_port(dev);
  46634. /*
  46635. - According to Becker, I have to set the hardware address
  46636. + According to Becker, I have to set the hardware address
  46637. at this point, because the (l)user can set it with an
  46638. ioctl. Easily done...
  46639. */
  46640. - SMC_SELECT_BANK( 1 );
  46641. - for ( i = 0; i < 6; i += 2 ) {
  46642. + SMC_SELECT_BANK(1);
  46643. + for (i = 0; i < 6; i += 2) {
  46644. word address;
  46645. - address = dev->dev_addr[ i + 1 ] << 8 ;
  46646. - address |= dev->dev_addr[ i ];
  46647. - outw( address, ioaddr + ADDR0 + i );
  46648. + address = dev->dev_addr[i + 1] << 8 ;
  46649. + address |= dev->dev_addr[i];
  46650. + smc_outw(address, ioaddr, ADDR0 + i);
  46651. }
  46652. netif_start_queue(dev);
  46653. return 0;
  46654. }
  46655. +/*
  46656. + * This is our template. Fill the rest in at run-time
  46657. + */
  46658. +static const struct ethtool_cmd ecmd_template = {
  46659. + supported: SUPPORTED_10baseT_Half |
  46660. + SUPPORTED_10baseT_Full |
  46661. + SUPPORTED_TP |
  46662. + SUPPORTED_AUI,
  46663. + speed: SPEED_10,
  46664. + autoneg: AUTONEG_DISABLE,
  46665. + maxtxpkt: 1,
  46666. + maxrxpkt: 1,
  46667. + transceiver: XCVR_INTERNAL,
  46668. +};
  46669. +
  46670. +static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  46671. +{
  46672. + struct smc_local *smc = dev->priv;
  46673. + u32 etcmd;
  46674. + int ret = -EINVAL;
  46675. +
  46676. + if (cmd != SIOCETHTOOL)
  46677. + return -EOPNOTSUPP;
  46678. +
  46679. + if (get_user(etcmd, (u32 *)rq->ifr_data))
  46680. + return -EFAULT;
  46681. +
  46682. + switch (etcmd) {
  46683. + case ETHTOOL_GSET: {
  46684. + struct ethtool_cmd ecmd = ecmd_template;
  46685. +
  46686. + ecmd.cmd = etcmd;
  46687. + ecmd.port = smc->port;
  46688. + ecmd.duplex = smc->duplex;
  46689. +
  46690. + ret = copy_to_user(rq->ifr_data, &ecmd, sizeof(ecmd))
  46691. + ? -EFAULT : 0;
  46692. + break;
  46693. + }
  46694. +
  46695. + case ETHTOOL_SSET: {
  46696. + struct ethtool_cmd ecmd;
  46697. +
  46698. + ret = -EPERM;
  46699. + if (!capable(CAP_NET_ADMIN))
  46700. + break;
  46701. +
  46702. + ret = -EFAULT;
  46703. + if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
  46704. + break;
  46705. +
  46706. + /*
  46707. + * Sanity-check the arguments.
  46708. + */
  46709. + ret = -EINVAL;
  46710. + if (ecmd.autoneg != AUTONEG_DISABLE)
  46711. + break;
  46712. + if (ecmd.speed != SPEED_10)
  46713. + break;
  46714. + if (ecmd.duplex != DUPLEX_HALF && ecmd.duplex != DUPLEX_FULL)
  46715. + break;
  46716. + if (ecmd.port != PORT_TP && ecmd.port != PORT_AUI)
  46717. + break;
  46718. +
  46719. + smc->port = ecmd.port;
  46720. + smc->duplex = ecmd.duplex;
  46721. +
  46722. + if (netif_running(dev))
  46723. + smc_set_port(dev);
  46724. +
  46725. + ret = 0;
  46726. + break;
  46727. + }
  46728. +
  46729. + case ETHTOOL_GDRVINFO: {
  46730. + struct ethtool_drvinfo edrv;
  46731. +
  46732. + memset(&edrv, 0, sizeof(edrv));
  46733. +
  46734. + edrv.cmd = etcmd;
  46735. + strcpy(edrv.driver, DRV_NAME);
  46736. + strcpy(edrv.version, DRV_VERSION);
  46737. + sprintf(edrv.bus_info, "ISA:%8.8lx:%d",
  46738. + dev->base_addr, dev->irq);
  46739. +
  46740. + ret = copy_to_user(rq->ifr_data, &edrv, sizeof(edrv))
  46741. + ? -EFAULT : 0;
  46742. + break;
  46743. + }
  46744. + }
  46745. +
  46746. + return ret;
  46747. +}
  46748. +
  46749. /*--------------------------------------------------------
  46750. . Called by the kernel to send a packet out into the void
  46751. . of the net. This routine is largely based on
  46752. @@ -1120,12 +1576,10 @@
  46753. {
  46754. /* If we get here, some higher level has decided we are broken.
  46755. There should really be a "kick me" function call instead. */
  46756. - printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
  46757. - tx_done(dev) ? "IRQ conflict" :
  46758. - "network cable problem");
  46759. + printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
  46760. /* "kick" the adaptor */
  46761. - smc_reset( dev->base_addr );
  46762. - smc_enable( dev->base_addr );
  46763. + smc_reset(dev);
  46764. + smc_enable(dev);
  46765. dev->trans_start = jiffies;
  46766. /* clear anything saved */
  46767. ((struct smc_local *)dev->priv)->saved_skb = NULL;
  46768. @@ -1145,10 +1599,10 @@
  46769. .
  46770. ---------------------------------------------------------------------*/
  46771. -static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
  46772. +static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
  46773. {
  46774. struct net_device *dev = dev_id;
  46775. - int ioaddr = dev->base_addr;
  46776. + u_int ioaddr = dev->base_addr;
  46777. struct smc_local *lp = (struct smc_local *)dev->priv;
  46778. byte status;
  46779. @@ -1161,45 +1615,45 @@
  46780. - PRINTK3((CARDNAME": SMC interrupt started \n"));
  46781. + PRINTK3(("%s: SMC interrupt started\n", dev->name));
  46782. - saved_bank = inw( ioaddr + BANK_SELECT );
  46783. + saved_bank = smc_inw(ioaddr, BANK_SELECT);
  46784. SMC_SELECT_BANK(2);
  46785. - saved_pointer = inw( ioaddr + POINTER );
  46786. + saved_pointer = smc_inw(ioaddr, POINTER);
  46787. - mask = inb( ioaddr + INT_MASK );
  46788. + mask = smc_inb(ioaddr, INT_MASK);
  46789. /* clear all interrupts */
  46790. - outb( 0, ioaddr + INT_MASK );
  46791. + SMC_SET_INT(0);
  46792. /* set a timeout value, so I don't stay here forever */
  46793. timeout = 4;
  46794. - PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
  46795. + PRINTK2((KERN_WARNING "%s: MASK IS %x\n", dev->name, mask));
  46796. do {
  46797. /* read the status flag, and mask it */
  46798. - status = inb( ioaddr + INTERRUPT ) & mask;
  46799. - if (!status )
  46800. + status = smc_inb(ioaddr, INTERRUPT) & mask;
  46801. + if (!status)
  46802. break;
  46803. - PRINTK3((KERN_WARNING CARDNAME
  46804. - ": Handling interrupt status %x \n", status ));
  46805. + PRINTK3((KERN_WARNING "%s: handling interrupt status %x\n",
  46806. + dev->name, status));
  46807. if (status & IM_RCV_INT) {
  46808. /* Got a packet(s). */
  46809. - PRINTK2((KERN_WARNING CARDNAME
  46810. - ": Receive Interrupt\n"));
  46811. + PRINTK2((KERN_WARNING "%s: receive interrupt\n",
  46812. + dev->name));
  46813. smc_rcv(dev);
  46814. - } else if (status & IM_TX_INT ) {
  46815. - PRINTK2((KERN_WARNING CARDNAME
  46816. - ": TX ERROR handled\n"));
  46817. + } else if (status & IM_TX_INT) {
  46818. + PRINTK2((KERN_WARNING "%s: TX ERROR handled\n",
  46819. + dev->name));
  46820. smc_tx(dev);
  46821. - outb(IM_TX_INT, ioaddr + INTERRUPT );
  46822. - } else if (status & IM_TX_EMPTY_INT ) {
  46823. + smc_outb(IM_TX_INT, ioaddr, INTERRUPT);
  46824. + } else if (status & IM_TX_EMPTY_INT) {
  46825. /* update stats */
  46826. - SMC_SELECT_BANK( 0 );
  46827. - card_stats = inw( ioaddr + COUNTER );
  46828. + SMC_SELECT_BANK(0);
  46829. + card_stats = smc_inw(ioaddr, COUNTER);
  46830. /* single collisions */
  46831. lp->stats.collisions += card_stats & 0xF;
  46832. card_stats >>= 4;
  46833. @@ -1208,60 +1662,63 @@
  46834. /* these are for when linux supports these statistics */
  46835. - SMC_SELECT_BANK( 2 );
  46836. - PRINTK2((KERN_WARNING CARDNAME
  46837. - ": TX_BUFFER_EMPTY handled\n"));
  46838. - outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
  46839. + SMC_SELECT_BANK(2);
  46840. + PRINTK2((KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n",
  46841. + dev->name));
  46842. + smc_outb(IM_TX_EMPTY_INT, ioaddr, INTERRUPT);
  46843. mask &= ~IM_TX_EMPTY_INT;
  46844. lp->stats.tx_packets += lp->packets_waiting;
  46845. lp->packets_waiting = 0;
  46846. - } else if (status & IM_ALLOC_INT ) {
  46847. - PRINTK2((KERN_DEBUG CARDNAME
  46848. - ": Allocation interrupt \n"));
  46849. + } else if (status & IM_ALLOC_INT) {
  46850. + PRINTK2((KERN_DEBUG "%s: Allocation interrupt\n",
  46851. + dev->name));
  46852. /* clear this interrupt so it doesn't happen again */
  46853. mask &= ~IM_ALLOC_INT;
  46854. - smc_hardware_send_packet( dev );
  46855. + smc_hardware_send_packet(dev);
  46856. /* enable xmit interrupts based on this */
  46857. - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
  46858. + mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
  46859. /* and let the card send more packets to me */
  46860. netif_wake_queue(dev);
  46861. - PRINTK2((CARDNAME": Handoff done successfully.\n"));
  46862. - } else if (status & IM_RX_OVRN_INT ) {
  46863. + PRINTK2(("%s: Handoff done successfully.\n",
  46864. + dev->name));
  46865. + } else if (status & IM_RX_OVRN_INT) {
  46866. lp->stats.rx_errors++;
  46867. lp->stats.rx_fifo_errors++;
  46868. - outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
  46869. - } else if (status & IM_EPH_INT ) {
  46870. - PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
  46871. - } else if (status & IM_ERCV_INT ) {
  46872. - PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
  46873. - outb( IM_ERCV_INT, ioaddr + INTERRUPT );
  46874. + smc_outb(IM_RX_OVRN_INT, ioaddr, INTERRUPT);
  46875. + } else if (status & IM_EPH_INT) {
  46876. + PRINTK(("%s: UNSUPPORTED: EPH INTERRUPT\n",
  46877. + dev->name));
  46878. + } else if (status & IM_ERCV_INT) {
  46879. + PRINTK(("%s: UNSUPPORTED: ERCV INTERRUPT\n",
  46880. + dev->name));
  46881. + smc_outb(IM_ERCV_INT, ioaddr, INTERRUPT);
  46882. }
  46883. - } while ( timeout -- );
  46884. + } while (timeout --);
  46885. /* restore state register */
  46886. - SMC_SELECT_BANK( 2 );
  46887. - outb( mask, ioaddr + INT_MASK );
  46888. + SMC_SELECT_BANK(2);
  46889. + SMC_SET_INT(mask);
  46890. - PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
  46891. - outw( saved_pointer, ioaddr + POINTER );
  46892. + PRINTK3((KERN_WARNING "%s: MASK is now %x\n", dev->name, mask));
  46893. + smc_outw(saved_pointer, ioaddr, POINTER);
  46894. - SMC_SELECT_BANK( saved_bank );
  46895. + SMC_SELECT_BANK(saved_bank);
  46896. - PRINTK3((CARDNAME ": Interrupt done\n"));
  46897. + PRINTK3(("%s: Interrupt done\n", dev->name));
  46898. return;
  46899. }
  46900. /*-------------------------------------------------------------
  46901. .
  46902. - . smc_rcv - receive a packet from the card
  46903. + . smc_rcv - receive a packet from the card
  46904. .
  46905. - . There is ( at least ) a packet waiting to be read from
  46906. + . There is (at least) a packet waiting to be read from
  46907. . chip-memory.
  46908. .
  46909. . o Read the status
  46910. @@ -1272,55 +1729,57 @@
  46911. static void smc_rcv(struct net_device *dev)
  46912. {
  46913. struct smc_local *lp = (struct smc_local *)dev->priv;
  46914. - int ioaddr = dev->base_addr;
  46915. + u_int ioaddr = dev->base_addr;
  46916. int packet_number;
  46917. word status;
  46918. word packet_length;
  46919. /* assume bank 2 */
  46920. - packet_number = inw( ioaddr + FIFO_PORTS );
  46921. + packet_number = smc_inw(ioaddr, FIFO_PORTS);
  46922. - if ( packet_number & FP_RXEMPTY ) {
  46923. + if (packet_number & FP_RXEMPTY) {
  46924. /* we got called , but nothing was on the FIFO */
  46925. - PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n"));
  46926. + PRINTK(("%s: WARNING: smc_rcv with nothing on FIFO.\n",
  46927. + dev->name));
  46928. /* don't need to restore anything */
  46929. return;
  46930. }
  46931. /* start reading from the start of the packet */
  46932. - outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER );
  46933. + smc_outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr, POINTER);
  46934. /* First two words are status and packet_length */
  46935. - status = inw( ioaddr + DATA_1 );
  46936. - packet_length = inw( ioaddr + DATA_1 );
  46937. + status = smc_inw(ioaddr, DATA_1);
  46938. + packet_length = smc_inw(ioaddr, DATA_1);
  46939. packet_length &= 0x07ff; /* mask off top bits */
  46940. - PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ));
  46941. + PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length));
  46942. /*
  46943. . the packet length contains 3 extra words :
  46944. . status, length, and an extra word with an odd byte .
  46945. */
  46946. packet_length -= 6;
  46947. - if ( !(status & RS_ERRORS ) ){
  46948. + if (!(status & RS_ERRORS)){
  46949. /* do stuff to make a new packet */
  46950. struct sk_buff * skb;
  46951. byte * data;
  46952. /* read one extra byte */
  46953. - if ( status & RS_ODDFRAME )
  46954. + if (status & RS_ODDFRAME)
  46955. packet_length++;
  46956. /* set multicast stats */
  46957. - if ( status & RS_MULTICAST )
  46958. + if (status & RS_MULTICAST)
  46959. lp->stats.multicast++;
  46960. - skb = dev_alloc_skb( packet_length + 5);
  46961. + skb = dev_alloc_skb(packet_length + 5);
  46962. - if ( skb == NULL ) {
  46963. - printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n");
  46964. + if (skb == NULL) {
  46965. + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
  46966. + dev->name);
  46967. lp->stats.rx_dropped++;
  46968. goto done;
  46969. }
  46970. @@ -1330,36 +1789,15 @@
  46971. ! in the worse case
  46972. */
  46973. - skb_reserve( skb, 2 ); /* 16 bit alignment */
  46974. + skb_reserve(skb, 2); /* 16 bit alignment */
  46975. skb->dev = dev;
  46976. - data = skb_put( skb, packet_length);
  46977. + data = skb_put(skb, packet_length);
  46978. -#ifdef USE_32_BIT
  46979. - /* QUESTION: Like in the TX routine, do I want
  46980. - to send the DWORDs or the bytes first, or some
  46981. - mixture. A mixture might improve already slow PIO
  46982. - performance */
  46983. - PRINTK3((" Reading %d dwords (and %d bytes) \n",
  46984. - packet_length >> 2, packet_length & 3 ));
  46985. - insl(ioaddr + DATA_1 , data, packet_length >> 2 );
  46986. - /* read the left over bytes */
  46987. - insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC),
  46988. - packet_length & 0x3 );
  46989. -#else
  46990. - PRINTK3((" Reading %d words and %d byte(s) \n",
  46991. - (packet_length >> 1 ), packet_length & 1 ));
  46992. - insw(ioaddr + DATA_1 , data, packet_length >> 1);
  46993. - if ( packet_length & 1 ) {
  46994. - data += packet_length & ~1;
  46995. - *(data++) = inb( ioaddr + DATA_1 );
  46996. - }
  46997. -#endif
  46998. -#if SMC_DEBUG > 2
  46999. - print_packet( data, packet_length );
  47000. -#endif
  47001. + smc_ins(ioaddr, DATA_1, data, packet_length);
  47002. + print_packet(data, packet_length);
  47003. - skb->protocol = eth_type_trans(skb, dev );
  47004. + skb->protocol = eth_type_trans(skb, dev);
  47005. netif_rx(skb);
  47006. dev->last_rx = jiffies;
  47007. lp->stats.rx_packets++;
  47008. @@ -1368,15 +1806,17 @@
  47009. /* error ... */
  47010. lp->stats.rx_errors++;
  47011. - if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++;
  47012. - if ( status & (RS_TOOSHORT | RS_TOOLONG ) )
  47013. + if (status & RS_ALGNERR)
  47014. + lp->stats.rx_frame_errors++;
  47015. + if (status & (RS_TOOSHORT | RS_TOOLONG))
  47016. lp->stats.rx_length_errors++;
  47017. - if ( status & RS_BADCRC) lp->stats.rx_crc_errors++;
  47018. + if (status & RS_BADCRC)
  47019. + lp->stats.rx_crc_errors++;
  47020. }
  47021. done:
  47022. /* error or good, tell the card to get rid of this packet */
  47023. - outw( MC_RELEASE, ioaddr + MMU_CMD );
  47024. + smc_outw(MC_RELEASE, ioaddr, MMU_CMD);
  47025. }
  47026. @@ -1389,62 +1829,64 @@
  47027. . Algorithm:
  47028. . Save pointer and packet no
  47029. . Get the packet no from the top of the queue
  47030. - . check if it's valid ( if not, is this an error??? )
  47031. + . check if it's valid (if not, is this an error???)
  47032. . read the status word
  47033. . record the error
  47034. - . ( resend? Not really, since we don't want old packets around )
  47035. + . (resend? Not really, since we don't want old packets around)
  47036. . Restore saved values
  47037. ************************************************************************/
  47038. -static void smc_tx( struct net_device * dev )
  47039. +static void smc_tx(struct net_device * dev)
  47040. {
  47041. - int ioaddr = dev->base_addr;
  47042. + u_int ioaddr = dev->base_addr;
  47043. struct smc_local *lp = (struct smc_local *)dev->priv;
  47044. byte saved_packet;
  47045. byte packet_no;
  47046. word tx_status;
  47047. - /* assume bank 2 */
  47048. + /* assume bank 2 */
  47049. - saved_packet = inb( ioaddr + PNR_ARR );
  47050. - packet_no = inw( ioaddr + FIFO_PORTS );
  47051. + saved_packet = smc_inb(ioaddr, PNR_ARR);
  47052. + packet_no = smc_inw(ioaddr, FIFO_PORTS);
  47053. packet_no &= 0x7F;
  47054. /* select this as the packet to read from */
  47055. - outb( packet_no, ioaddr + PNR_ARR );
  47056. + smc_outb(packet_no, ioaddr, PNR_ARR);
  47057. /* read the first word from this packet */
  47058. - outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER );
  47059. + smc_outw(PTR_AUTOINC | PTR_READ, ioaddr, POINTER);
  47060. - tx_status = inw( ioaddr + DATA_1 );
  47061. - PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status ));
  47062. + tx_status = smc_inw(ioaddr, DATA_1);
  47063. + PRINTK3(("%s: TX DONE STATUS: %4x\n", dev->name, tx_status));
  47064. lp->stats.tx_errors++;
  47065. - if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++;
  47066. - if ( tx_status & TS_LATCOL ) {
  47067. - printk(KERN_DEBUG CARDNAME
  47068. - ": Late collision occurred on last xmit.\n");
  47069. + if (tx_status & TS_LOSTCAR)
  47070. + lp->stats.tx_carrier_errors++;
  47071. + if (tx_status & TS_LATCOL) {
  47072. + printk(KERN_DEBUG "%s: Late collision occurred on "
  47073. + "last xmit.\n", dev->name);
  47074. lp->stats.tx_window_errors++;
  47075. }
  47076. #if 0
  47077. - if ( tx_status & TS_16COL ) { ... }
  47078. + if (tx_status & TS_16COL) { ... }
  47079. #endif
  47080. - if ( tx_status & TS_SUCCESS ) {
  47081. - printk(CARDNAME": Successful packet caused interrupt \n");
  47082. + if (tx_status & TS_SUCCESS) {
  47083. + printk("%s: Successful packet caused interrupt\n",
  47084. + dev->name);
  47085. }
  47086. /* re-enable transmit */
  47087. - SMC_SELECT_BANK( 0 );
  47088. - outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR );
  47089. + SMC_SELECT_BANK(0);
  47090. + smc_outw(smc_inw(ioaddr, TCR) | TCR_ENABLE, ioaddr, TCR);
  47091. /* kill the packet */
  47092. - SMC_SELECT_BANK( 2 );
  47093. - outw( MC_FREEPKT, ioaddr + MMU_CMD );
  47094. + SMC_SELECT_BANK(2);
  47095. + smc_outw(MC_FREEPKT, ioaddr, MMU_CMD);
  47096. /* one less packet waiting for me */
  47097. lp->packets_waiting--;
  47098. - outb( saved_packet, ioaddr + PNR_ARR );
  47099. + smc_outb(saved_packet, ioaddr, PNR_ARR);
  47100. return;
  47101. }
  47102. @@ -1460,7 +1902,7 @@
  47103. {
  47104. netif_stop_queue(dev);
  47105. /* clear everything */
  47106. - smc_shutdown( dev->base_addr );
  47107. + smc_shutdown(dev);
  47108. /* Update the statistics here. */
  47109. return 0;
  47110. @@ -1481,16 +1923,16 @@
  47111. .
  47112. . This routine will, depending on the values passed to it,
  47113. . either make it accept multicast packets, go into
  47114. - . promiscuous mode ( for TCPDUMP and cousins ) or accept
  47115. + . promiscuous mode (for TCPDUMP and cousins) or accept
  47116. . a select set of multicast packets
  47117. */
  47118. static void smc_set_multicast_list(struct net_device *dev)
  47119. {
  47120. - short ioaddr = dev->base_addr;
  47121. + u_int ioaddr = dev->base_addr;
  47122. SMC_SELECT_BANK(0);
  47123. - if ( dev->flags & IFF_PROMISC )
  47124. - outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR );
  47125. + if (dev->flags & IFF_PROMISC)
  47126. + smc_outw(smc_inw(ioaddr, RCR) | RCR_PROMISC, ioaddr, RCR);
  47127. /* BUG? I never disable promiscuous mode if multicasting was turned on.
  47128. Now, I turn off promiscuous mode, but I don't do anything to multicasting
  47129. @@ -1502,34 +1944,34 @@
  47130. checked before the table is
  47131. */
  47132. else if (dev->flags & IFF_ALLMULTI)
  47133. - outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR );
  47134. + smc_outw(smc_inw(ioaddr, RCR) | RCR_ALMUL, ioaddr, RCR);
  47135. /* We just get all multicast packets even if we only want them
  47136. . from one source. This will be changed at some future
  47137. . point. */
  47138. - else if (dev->mc_count ) {
  47139. + else if (dev->mc_count) {
  47140. /* support hardware multicasting */
  47141. /* be sure I get rid of flags I might have set */
  47142. - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
  47143. - ioaddr + RCR );
  47144. + smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
  47145. + ioaddr, RCR);
  47146. /* NOTE: this has to set the bank, so make sure it is the
  47147. last thing called. The bank is set to zero at the top */
  47148. - smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
  47149. + smc_setmulticast(dev, dev->mc_count, dev->mc_list);
  47150. }
  47151. - else {
  47152. - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
  47153. - ioaddr + RCR );
  47154. + else {
  47155. + smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
  47156. + ioaddr, RCR);
  47157. /*
  47158. since I'm disabling all multicast entirely, I need to
  47159. clear the multicast list
  47160. */
  47161. - SMC_SELECT_BANK( 3 );
  47162. - outw( 0, ioaddr + MULTICAST1 );
  47163. - outw( 0, ioaddr + MULTICAST2 );
  47164. - outw( 0, ioaddr + MULTICAST3 );
  47165. - outw( 0, ioaddr + MULTICAST4 );
  47166. + SMC_SELECT_BANK(3);
  47167. + smc_outw(0, ioaddr, MULTICAST1);
  47168. + smc_outw(0, ioaddr, MULTICAST2);
  47169. + smc_outw(0, ioaddr, MULTICAST3);
  47170. + smc_outw(0, ioaddr, MULTICAST4);
  47171. }
  47172. }
  47173. @@ -1550,21 +1992,26 @@
  47174. int init_module(void)
  47175. {
  47176. - int result;
  47177. -
  47178. if (io == 0)
  47179. - printk(KERN_WARNING
  47180. - CARDNAME": You shouldn't use auto-probing with insmod!\n" );
  47181. + printk(KERN_WARNING CARDNAME
  47182. + ": You shouldn't use auto-probing with insmod!\n");
  47183. +
  47184. + /*
  47185. + * Note: dev->if_port has changed to be 2.4 compliant.
  47186. + * We keep the ifport insmod parameter the same though.
  47187. + */
  47188. + switch (ifport) {
  47189. + case 1: devSMC9194.if_port = IF_PORT_10BASET; break;
  47190. + case 2: devSMC9194.if_port = IF_PORT_AUI; break;
  47191. + default: devSMC9194.if_port = 0; break;
  47192. + }
  47193. /* copy the parameters from insmod into the device structure */
  47194. devSMC9194.base_addr = io;
  47195. devSMC9194.irq = irq;
  47196. - devSMC9194.if_port = ifport;
  47197. - devSMC9194.init = smc_init;
  47198. - if ((result = register_netdev(&devSMC9194)) != 0)
  47199. - return result;
  47200. + devSMC9194.init = smc_init;
  47201. - return 0;
  47202. + return register_netdev(&devSMC9194);
  47203. }
  47204. void cleanup_module(void)
  47205. diff -urN linux-2.4.26/drivers/net/smc9194.h linux-2.4.26-vrs1/drivers/net/smc9194.h
  47206. --- linux-2.4.26/drivers/net/smc9194.h 2001-09-08 20:13:55.000000000 +0100
  47207. +++ linux-2.4.26-vrs1/drivers/net/smc9194.h 2004-01-14 21:32:26.000000000 +0000
  47208. @@ -63,10 +63,11 @@
  47209. #define TCR 0 /* transmit control register */
  47210. #define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
  47211. +#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
  47212. +#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
  47213. #define TCR_FDUPLX 0x0800 /* receive packets sent out */
  47214. #define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
  47215. -#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
  47216. -#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
  47217. +#define TCR_FDSE 0x8000 /* full duplex, switched ethernet */
  47218. #define TCR_CLEAR 0 /* do NOTHING */
  47219. /* the normal settings for the TCR register : */
  47220. @@ -107,7 +108,10 @@
  47221. #define CTL_CR_ENABLE 0x40
  47222. #define CTL_TE_ENABLE 0x0020
  47223. #define CTL_AUTO_RELEASE 0x0800
  47224. -#define CTL_EPROM_ACCESS 0x0003 /* high if Eprom is being read */
  47225. +#define CTL_EPROM_SELECT 0x0004
  47226. +#define CTL_EPROM_RELOAD 0x0002
  47227. +#define CTL_EPROM_STORE 0x0001
  47228. +#define CTL_EPROM_ACCESS (CTL_EPROM_RELOAD | CTL_EPROM_STORE) /* high if Eprom is being read */
  47229. /* BANK 2 */
  47230. #define MMU_CMD 0
  47231. @@ -130,7 +134,6 @@
  47232. #define PTR_READ 0x2000
  47233. #define PTR_RCV 0x8000
  47234. #define PTR_AUTOINC 0x4000
  47235. -#define PTR_AUTO_INC 0x0040
  47236. #define DATA_1 8
  47237. #define DATA_2 10
  47238. @@ -162,17 +165,6 @@
  47239. #define CHIP_9195 5
  47240. #define CHIP_91100 7
  47241. -static const char * chip_ids[ 15 ] = {
  47242. - NULL, NULL, NULL,
  47243. - /* 3 */ "SMC91C90/91C92",
  47244. - /* 4 */ "SMC91C94",
  47245. - /* 5 */ "SMC91C95",
  47246. - NULL,
  47247. - /* 7 */ "SMC91C100",
  47248. - /* 8 */ "SMC91C100FD",
  47249. - NULL, NULL, NULL,
  47250. - NULL, NULL, NULL};
  47251. -
  47252. /*
  47253. . Transmit status bits
  47254. */
  47255. @@ -192,40 +184,20 @@
  47256. #define RS_MULTICAST 0x0001
  47257. #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
  47258. -static const char * interfaces[ 2 ] = { "TP", "AUI" };
  47259. -
  47260. -/*-------------------------------------------------------------------------
  47261. - . I define some macros to make it easier to do somewhat common
  47262. - . or slightly complicated, repeated tasks.
  47263. - --------------------------------------------------------------------------*/
  47264. -
  47265. -/* select a register bank, 0 to 3 */
  47266. -
  47267. -#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT ); }
  47268. -
  47269. -/* define a small delay for the reset */
  47270. -#define SMC_DELAY() { inw( ioaddr + RCR );\
  47271. - inw( ioaddr + RCR );\
  47272. - inw( ioaddr + RCR ); }
  47273. -
  47274. -/* this enables an interrupt in the interrupt mask register */
  47275. -#define SMC_ENABLE_INT(x) {\
  47276. - unsigned char mask;\
  47277. - SMC_SELECT_BANK(2);\
  47278. - mask = inb( ioaddr + INT_MASK );\
  47279. - mask |= (x);\
  47280. - outb( mask, ioaddr + INT_MASK ); \
  47281. -}
  47282. -
  47283. -/* this disables an interrupt from the interrupt mask register */
  47284. -
  47285. -#define SMC_DISABLE_INT(x) {\
  47286. - unsigned char mask;\
  47287. - SMC_SELECT_BANK(2);\
  47288. - mask = inb( ioaddr + INT_MASK );\
  47289. - mask &= ~(x);\
  47290. - outb( mask, ioaddr + INT_MASK ); \
  47291. -}
  47292. +/*
  47293. + * SMC91C96 ethernet config and status registers.
  47294. + * These are in the "attribute" space.
  47295. + */
  47296. +#define ECOR 0x8000
  47297. +#define ECOR_RESET 0x80
  47298. +#define ECOR_LEVEL_IRQ 0x40
  47299. +#define ECOR_WR_ATTRIB 0x04
  47300. +#define ECOR_ENABLE 0x01
  47301. +
  47302. +#define ECSR 0x8002
  47303. +#define ECSR_IOIS8 0x20
  47304. +#define ECSR_PWRDWN 0x04
  47305. +#define ECSR_INT 0x02
  47306. /*----------------------------------------------------------------------
  47307. . Define the interrupts that I want to receive from the card
  47308. @@ -237,5 +209,36 @@
  47309. --------------------------------------------------------------------------*/
  47310. #define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT)
  47311. +/* store this information for the driver.. */
  47312. +struct smc_local {
  47313. + /*
  47314. + these are things that the kernel wants me to keep, so users
  47315. + can find out semi-useless statistics of how well the card is
  47316. + performing
  47317. + */
  47318. + struct net_device_stats stats;
  47319. +
  47320. + /*
  47321. + If I have to wait until memory is available to send
  47322. + a packet, I will store the skbuff here, until I get the
  47323. + desired memory. Then, I'll send it out and free it.
  47324. + */
  47325. + struct sk_buff * saved_skb;
  47326. +
  47327. + /*
  47328. + . This keeps track of how many packets that I have
  47329. + . sent out. When an TX_EMPTY interrupt comes, I know
  47330. + . that all of these have been sent.
  47331. + */
  47332. + int packets_waiting;
  47333. +
  47334. + /*
  47335. + . Interface status. These correspond to the parameters
  47336. + . in the ethtool_cmd structure.
  47337. + */
  47338. + u8 duplex;
  47339. + u8 port;
  47340. +};
  47341. +
  47342. #endif /* _SMC_9194_H_ */
  47343. diff -urN linux-2.4.26/drivers/parport/Config.in linux-2.4.26-vrs1/drivers/parport/Config.in
  47344. --- linux-2.4.26/drivers/parport/Config.in 2004-02-27 20:03:27.000000000 +0000
  47345. +++ linux-2.4.26-vrs1/drivers/parport/Config.in 2004-02-23 23:33:11.000000000 +0000
  47346. @@ -27,7 +27,8 @@
  47347. dep_tristate ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA $CONFIG_PCMCIA $CONFIG_PARPORT_PC $CONFIG_HOTPLUG
  47348. fi
  47349. if [ "$CONFIG_ARM" = "y" ]; then
  47350. - dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
  47351. + dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT $CONFIG_ARCH_ARC
  47352. + dep_tristate ' Accelent SA1110 IDP' CONFIG_PARPORT_IDP $CONFIG_PARPORT $CONFIG_SA1100_ACCELENT
  47353. fi
  47354. if [ "$CONFIG_AMIGA" = "y" ]; then
  47355. dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
  47356. diff -urN linux-2.4.26/drivers/parport/Makefile linux-2.4.26-vrs1/drivers/parport/Makefile
  47357. --- linux-2.4.26/drivers/parport/Makefile 2004-02-27 20:03:27.000000000 +0000
  47358. +++ linux-2.4.26-vrs1/drivers/parport/Makefile 2004-02-23 23:17:13.000000000 +0000
  47359. @@ -29,6 +29,7 @@
  47360. obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
  47361. obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
  47362. obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
  47363. +obj-$(CONFIG_PARPORT_IDP) += parport_idp.o
  47364. obj-$(CONFIG_PARPORT_IP22) += parport_ip22.o
  47365. include $(TOPDIR)/Rules.make
  47366. diff -urN linux-2.4.26/drivers/parport/init.c linux-2.4.26-vrs1/drivers/parport/init.c
  47367. --- linux-2.4.26/drivers/parport/init.c 2002-11-28 23:53:14.000000000 +0000
  47368. +++ linux-2.4.26-vrs1/drivers/parport/init.c 2004-01-14 21:32:26.000000000 +0000
  47369. @@ -164,6 +164,9 @@
  47370. #ifdef CONFIG_PARPORT_SUNBPP
  47371. parport_sunbpp_init();
  47372. #endif
  47373. +#ifdef CONFIG_PARPORT_IDP
  47374. + parport_idp_init();
  47375. +#endif
  47376. return 0;
  47377. }
  47378. diff -urN linux-2.4.26/drivers/parport/parport_idp.c linux-2.4.26-vrs1/drivers/parport/parport_idp.c
  47379. --- linux-2.4.26/drivers/parport/parport_idp.c 1970-01-01 01:00:00.000000000 +0100
  47380. +++ linux-2.4.26-vrs1/drivers/parport/parport_idp.c 2004-01-14 21:32:26.000000000 +0000
  47381. @@ -0,0 +1,247 @@
  47382. +/* Low-level polled-mode parallel port routines for the Accelent IDP
  47383. + *
  47384. + * Author: Rich Dulabahn <rich@accelent.com>
  47385. + *
  47386. + * Inspiration taken from parport_amiga.c and parport_atari.c.
  47387. + *
  47388. + * To use, under menuconfig:
  47389. + * 1) Turn on <*> Accelent IDP under Parallel port setup
  47390. + * 2) Turn on <*> Parallel printer support under Character devices
  47391. + *
  47392. + * This will give you parport0 configured as /dev/lp0
  47393. + *
  47394. + * To make the correct /dev/lp* entries, enter /dev and type this:
  47395. + *
  47396. + * mknod lp0 c 6 0
  47397. + * mknod lp1 c 6 1
  47398. + * mknod lp2 c 6 2
  47399. + *
  47400. + */
  47401. +
  47402. +#include <linux/module.h>
  47403. +#include <linux/init.h>
  47404. +#include <linux/parport.h>
  47405. +#include <asm/hardware.h>
  47406. +
  47407. +/*
  47408. + * Parallel data port is port H, data
  47409. + * Parallel data direction is port H, direction
  47410. + * Control port is port I, data, lowest 4 bits
  47411. + * Status port is port G, data, upper 5 bits
  47412. + */
  47413. +
  47414. +#define INPUTPOWERHANDLER 0
  47415. +/* masks */
  47416. +#define CONTROL_MASK 0x0f
  47417. +#define STATUS_MASK 0xf8
  47418. +
  47419. +#undef DEBUG
  47420. +
  47421. +#ifdef DEBUG
  47422. +#define DPRINTK printk
  47423. +#else
  47424. +#define DPRINTK(stuff...)
  47425. +#endif
  47426. +
  47427. +static struct parport *this_port = NULL;
  47428. +
  47429. +static unsigned char
  47430. +parport_idp_read_data(struct parport *p)
  47431. +{
  47432. + unsigned char c;
  47433. +
  47434. + c = IDP_FPGA_PORTH_DATA;
  47435. + DPRINTK("read_data:0x%x\n",c);
  47436. + return c;
  47437. +}
  47438. +
  47439. +static void
  47440. +parport_idp_write_data(struct parport *p, unsigned char data)
  47441. +{
  47442. + IDP_FPGA_PORTH_DATA = data;
  47443. + DPRINTK("write_data:0x%x\n",data);
  47444. +}
  47445. +
  47446. +static unsigned char
  47447. +parport_idp_read_control(struct parport *p)
  47448. +{
  47449. + unsigned char c;
  47450. +
  47451. + c = IDP_FPGA_PORTI_DATA & CONTROL_MASK;
  47452. + DPRINTK("read_control:0x%x\n",c);
  47453. + return c;
  47454. +}
  47455. +
  47456. +static void
  47457. +parport_idp_write_control(struct parport *p, unsigned char control)
  47458. +{
  47459. + unsigned int temp;
  47460. +
  47461. + temp = IDP_FPGA_PORTH_DATA;
  47462. + temp &= ~CONTROL_MASK;
  47463. + IDP_FPGA_PORTI_DATA = (temp | (control & CONTROL_MASK));
  47464. +DPRINTK("write_control:0x%x\n",control);
  47465. +}
  47466. +
  47467. +static unsigned char
  47468. +parport_idp_frob_control(struct parport *p, unsigned char mask,
  47469. + unsigned char val)
  47470. +{
  47471. + unsigned char c;
  47472. +
  47473. +/* From the parport-lowlevel.txt file...*/
  47474. +/* This is equivalent to reading from the control register, masking out
  47475. +the bits in mask, exclusive-or'ing with the bits in val, and writing
  47476. +the result to the control register. */
  47477. +
  47478. +/* Easy enough, right? */
  47479. +
  47480. + c = parport_idp_read_control(p);
  47481. + parport_idp_write_control(p, (c & ~mask) ^ val);
  47482. + DPRINTK("frob_control:0x%x\n",c);
  47483. + return c;
  47484. +}
  47485. +
  47486. +static unsigned char
  47487. +parport_idp_read_status(struct parport *p)
  47488. +{
  47489. + unsigned char c;
  47490. +
  47491. + c = IDP_FPGA_PORTG_DATA & STATUS_MASK;
  47492. + c ^= 0x80; /* toggle S7 bit, active low */
  47493. + DPRINTK("read_status:0x%x\n",c);
  47494. + return c;
  47495. +}
  47496. +
  47497. +static void
  47498. +parport_idp_init_state(struct pardevice *d, struct parport_state *s)
  47499. +{
  47500. +}
  47501. +
  47502. +static void
  47503. +parport_idp_save_state(struct parport *p, struct parport_state *s)
  47504. +{
  47505. +}
  47506. +
  47507. +static void
  47508. +parport_idp_restore_state(struct parport *p, struct parport_state *s)
  47509. +{
  47510. +}
  47511. +
  47512. +static void
  47513. +parport_idp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  47514. +{
  47515. +}
  47516. +
  47517. +static void
  47518. +parport_idp_enable_irq(struct parport *p)
  47519. +{
  47520. +}
  47521. +
  47522. +static void
  47523. +parport_idp_disable_irq(struct parport *p)
  47524. +{
  47525. +}
  47526. +
  47527. +static void
  47528. +parport_idp_data_forward(struct parport *p)
  47529. +{
  47530. + IDP_FPGA_PORTH_DIR = 0x00; /* 0 sets to output */
  47531. + DPRINTK("data_forward:0x%x\n",0);
  47532. +}
  47533. +
  47534. +static void
  47535. +parport_idp_data_reverse(struct parport *p)
  47536. +{
  47537. + IDP_FPGA_PORTH_DIR = 0xff; /* and 1 sets to input */
  47538. + DPRINTK("data_reverse:0x%x\n",0xff);
  47539. +}
  47540. +
  47541. +static void
  47542. +parport_idp_inc_use_count(void)
  47543. +{
  47544. + MOD_INC_USE_COUNT;
  47545. +}
  47546. +
  47547. +static void
  47548. +parport_idp_dec_use_count(void)
  47549. +{
  47550. + MOD_DEC_USE_COUNT;
  47551. +}
  47552. +
  47553. +static struct parport_operations parport_idp_ops = {
  47554. + parport_idp_write_data,
  47555. + parport_idp_read_data,
  47556. +
  47557. + parport_idp_write_control,
  47558. + parport_idp_read_control,
  47559. + parport_idp_frob_control,
  47560. +
  47561. + parport_idp_read_status,
  47562. +
  47563. + parport_idp_enable_irq,
  47564. + parport_idp_disable_irq,
  47565. +
  47566. + parport_idp_data_forward,
  47567. + parport_idp_data_reverse,
  47568. +
  47569. + parport_idp_init_state,
  47570. + parport_idp_save_state,
  47571. + parport_idp_restore_state,
  47572. +
  47573. + parport_idp_inc_use_count,
  47574. + parport_idp_dec_use_count,
  47575. +
  47576. + parport_ieee1284_epp_write_data,
  47577. + parport_ieee1284_epp_read_data,
  47578. + parport_ieee1284_epp_write_addr,
  47579. + parport_ieee1284_epp_read_addr,
  47580. +
  47581. + parport_ieee1284_ecp_write_data,
  47582. + parport_ieee1284_ecp_read_data,
  47583. + parport_ieee1284_ecp_write_addr,
  47584. +
  47585. + parport_ieee1284_write_compat,
  47586. + parport_ieee1284_read_nibble,
  47587. + parport_ieee1284_read_byte,
  47588. +};
  47589. +
  47590. +
  47591. +int __init
  47592. +parport_idp_init(void)
  47593. +{
  47594. + struct parport *p;
  47595. +
  47596. + p = parport_register_port((unsigned long)0,PARPORT_IRQ_NONE,PARPORT_DMA_NONE,&parport_idp_ops);
  47597. +
  47598. + if (!p) return 0; /* return 0 on failure */
  47599. +
  47600. + this_port=p;
  47601. + printk("%s: Accelent IDP parallel port registered.\n", p->name);
  47602. + parport_proc_register(p);
  47603. + parport_announce_port(p);
  47604. +
  47605. + return 1;
  47606. +}
  47607. +
  47608. +#ifdef MODULE
  47609. +
  47610. +MODULE_AUTHOR("Rich Dulabahn");
  47611. +MODULE_DESCRIPTION("Parport Driver for Accelent IDP");
  47612. +MODULE_SUPPORTED_DEVICE("Accelent IDP builtin Parallel Port");
  47613. +MODULE_LICENSE("GPL");
  47614. +
  47615. +int
  47616. +init_module(void)
  47617. +{
  47618. + return parport_idp_init() ? 0 : -ENODEV;
  47619. +}
  47620. +
  47621. +void
  47622. +cleanup_module(void)
  47623. +{
  47624. + parport_proc_unregister(this_port);
  47625. + parport_unregister_port(this_port);
  47626. +}
  47627. +#endif
  47628. +
  47629. diff -urN linux-2.4.26/drivers/pci/Makefile linux-2.4.26-vrs1/drivers/pci/Makefile
  47630. --- linux-2.4.26/drivers/pci/Makefile 2003-08-25 12:44:42.000000000 +0100
  47631. +++ linux-2.4.26-vrs1/drivers/pci/Makefile 2004-01-14 21:39:07.000000000 +0000
  47632. @@ -13,7 +13,7 @@
  47633. export-objs := pci.o
  47634. -obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
  47635. +obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o bridge.o
  47636. obj-$(CONFIG_PROC_FS) += proc.o
  47637. ifndef CONFIG_SPARC64
  47638. diff -urN linux-2.4.26/drivers/pci/bridge.c linux-2.4.26-vrs1/drivers/pci/bridge.c
  47639. --- linux-2.4.26/drivers/pci/bridge.c 1970-01-01 01:00:00.000000000 +0100
  47640. +++ linux-2.4.26-vrs1/drivers/pci/bridge.c 2004-01-14 21:32:26.000000000 +0000
  47641. @@ -0,0 +1,149 @@
  47642. +
  47643. +/*
  47644. + * Copyright (c) 2001 Red Hat, Inc. All rights reserved.
  47645. + *
  47646. + * This software may be freely redistributed under the terms
  47647. + * of the GNU public license.
  47648. + *
  47649. + * You should have received a copy of the GNU General Public License
  47650. + * along with this program; if not, write to the Free Software
  47651. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  47652. + *
  47653. + * Author: Arjan van de Ven <arjanv@redhat.com>
  47654. + *
  47655. + */
  47656. +
  47657. +
  47658. +/*
  47659. + * Generic PCI driver for PCI bridges for powermanagement purposes
  47660. + *
  47661. + */
  47662. +
  47663. +#include <linux/config.h>
  47664. +#include <linux/module.h>
  47665. +#include <linux/kernel.h>
  47666. +#include <linux/pci.h>
  47667. +#include <linux/init.h>
  47668. +
  47669. +static struct pci_device_id bridge_pci_table[] __devinitdata = {
  47670. + {/* handle all PCI bridges */
  47671. + class: ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
  47672. + class_mask: ~0,
  47673. + vendor: PCI_ANY_ID,
  47674. + device: PCI_ANY_ID,
  47675. + subvendor: PCI_ANY_ID,
  47676. + subdevice: PCI_ANY_ID,
  47677. + },
  47678. + {0,},
  47679. +};
  47680. +
  47681. +static int bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id);
  47682. +static int pci_bridge_save_state_bus(struct pci_bus *bus, int force);
  47683. +int pci_generic_resume_compare(struct pci_dev *pdev);
  47684. +
  47685. +int pci_bridge_force_restore = 0;
  47686. +
  47687. +
  47688. +
  47689. +
  47690. +static int __init bridge_setup(char *str)
  47691. +{
  47692. + if (!strcmp(str,"force"))
  47693. + pci_bridge_force_restore = 1;
  47694. + else if (!strcmp(str,"noforce"))
  47695. + pci_bridge_force_restore = 0;
  47696. + return 0;
  47697. +}
  47698. +
  47699. +__setup("resume=",bridge_setup);
  47700. +
  47701. +
  47702. +static int pci_bridge_save_state_bus(struct pci_bus *bus, int force)
  47703. +{
  47704. + struct list_head *list;
  47705. + int error = 0;
  47706. +
  47707. + list_for_each(list, &bus->children) {
  47708. + error = pci_bridge_save_state_bus(pci_bus_b(list),force);
  47709. + if (error) return error;
  47710. + }
  47711. + list_for_each(list, &bus->devices) {
  47712. + pci_generic_suspend_save(pci_dev_b(list),0);
  47713. + }
  47714. + return 0;
  47715. +}
  47716. +
  47717. +
  47718. +static int pci_bridge_restore_state_bus(struct pci_bus *bus, int force)
  47719. +{
  47720. + struct list_head *list;
  47721. + int error = 0;
  47722. + static int printed_warning=0;
  47723. +
  47724. + list_for_each(list, &bus->children) {
  47725. + error = pci_bridge_restore_state_bus(pci_bus_b(list),force);
  47726. + if (error) return error;
  47727. + }
  47728. + list_for_each(list, &bus->devices) {
  47729. + if (force)
  47730. + pci_generic_resume_restore(pci_dev_b(list));
  47731. + else {
  47732. + error = pci_generic_resume_compare(pci_dev_b(list));
  47733. + if (error && !printed_warning++) {
  47734. + printk(KERN_WARNING "resume warning: bios doesn't restore PCI state properly\n");
  47735. + printk(KERN_WARNING "resume warning: if resume failed, try booting with resume=force\n");
  47736. + }
  47737. + if (error)
  47738. + return error;
  47739. + }
  47740. + }
  47741. + return 0;
  47742. +}
  47743. +
  47744. +static int bridge_suspend(struct pci_dev *dev, u32 force)
  47745. +{
  47746. + pci_generic_suspend_save(dev,force);
  47747. + if (dev->subordinate)
  47748. + pci_bridge_save_state_bus(dev->subordinate,force);
  47749. + return 0;
  47750. +}
  47751. +
  47752. +static int bridge_resume(struct pci_dev *dev)
  47753. +{
  47754. +
  47755. + pci_generic_resume_restore(dev);
  47756. + if (dev->subordinate)
  47757. + pci_bridge_restore_state_bus(dev->subordinate,pci_bridge_force_restore);
  47758. + return 0;
  47759. +}
  47760. +
  47761. +
  47762. +MODULE_DEVICE_TABLE(pci, bridge_pci_table);
  47763. +static struct pci_driver bridge_ops = {
  47764. + name: "PCI Bridge",
  47765. + id_table: bridge_pci_table,
  47766. + probe: bridge_probe,
  47767. + suspend: bridge_suspend,
  47768. + resume: bridge_resume
  47769. +};
  47770. +
  47771. +static int __devinit bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  47772. +{
  47773. + return 0;
  47774. +}
  47775. +
  47776. +static int __init bridge_init(void)
  47777. +{
  47778. + pci_register_driver(&bridge_ops);
  47779. + return 0;
  47780. +}
  47781. +
  47782. +static void __exit bridge_exit(void)
  47783. +{
  47784. + pci_unregister_driver(&bridge_ops);
  47785. +}
  47786. +
  47787. +
  47788. +module_init(bridge_init)
  47789. +module_exit(bridge_exit)
  47790. +
  47791. diff -urN linux-2.4.26/drivers/pci/pci.c linux-2.4.26-vrs1/drivers/pci/pci.c
  47792. --- linux-2.4.26/drivers/pci/pci.c 2003-11-28 18:26:20.000000000 +0000
  47793. +++ linux-2.4.26-vrs1/drivers/pci/pci.c 2004-01-14 21:39:08.000000000 +0000
  47794. @@ -359,6 +359,48 @@
  47795. return 0;
  47796. }
  47797. +int
  47798. +pci_compare_state(struct pci_dev *dev, u32 *buffer)
  47799. +{
  47800. + int i;
  47801. + unsigned int temp;
  47802. +
  47803. + if (buffer) {
  47804. + for (i = 0; i < 16; i++) {
  47805. + pci_read_config_dword(dev,i*4,&temp);
  47806. + if (temp!=buffer[i])
  47807. + return 1;
  47808. + }
  47809. + }
  47810. + return 0;
  47811. +}
  47812. +
  47813. +int pci_generic_suspend_save(struct pci_dev *pdev, u32 state)
  47814. +{
  47815. + if (pdev)
  47816. + pci_save_state(pdev,pdev->saved_state);
  47817. + return 0;
  47818. +}
  47819. +
  47820. +int pci_generic_resume_restore(struct pci_dev *pdev)
  47821. +{
  47822. + if (pdev)
  47823. + pci_restore_state(pdev,pdev->saved_state);
  47824. + return 0;
  47825. +}
  47826. +
  47827. +int pci_generic_resume_compare(struct pci_dev *pdev)
  47828. +{
  47829. + int retval=0;
  47830. + if (pdev)
  47831. + retval = pci_compare_state(pdev,pdev->saved_state);
  47832. + return retval;
  47833. +}
  47834. +
  47835. +EXPORT_SYMBOL(pci_generic_suspend_save);
  47836. +EXPORT_SYMBOL(pci_generic_resume_restore);
  47837. +EXPORT_SYMBOL(pci_generic_resume_compare);
  47838. +
  47839. /**
  47840. * pci_enable_device_bars - Initialize some of a device for use
  47841. * @dev: PCI device to be initialized
  47842. diff -urN linux-2.4.26/drivers/pci/setup-bus.c linux-2.4.26-vrs1/drivers/pci/setup-bus.c
  47843. --- linux-2.4.26/drivers/pci/setup-bus.c 2003-06-13 15:51:35.000000000 +0100
  47844. +++ linux-2.4.26-vrs1/drivers/pci/setup-bus.c 2004-01-14 21:32:26.000000000 +0000
  47845. @@ -12,6 +12,8 @@
  47846. /*
  47847. * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
  47848. * PCI-PCI bridges cleanup, sorted resource allocation.
  47849. + * May 2001, Russell King <rmk@arm.linux.org.uk>
  47850. + * Allocate prefetchable memory regions where available.
  47851. * Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
  47852. * Converted to allocation in 3 passes, which gives
  47853. * tighter packing. Prefetchable range support.
  47854. @@ -160,8 +162,10 @@
  47855. pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
  47856. /* Check if we have VGA behind the bridge.
  47857. - Enable ISA in either case (FIXME!). */
  47858. - l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
  47859. + Enable ISA in either case. */
  47860. + l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ?
  47861. + PCI_BRIDGE_CTL_VGA | PCI_BRIDGE_CTL_NO_ISA :
  47862. + PCI_BRIDGE_CTL_NO_ISA;
  47863. pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
  47864. }
  47865. diff -urN linux-2.4.26/drivers/pcmcia/Config.in linux-2.4.26-vrs1/drivers/pcmcia/Config.in
  47866. --- linux-2.4.26/drivers/pcmcia/Config.in 2004-02-27 20:03:27.000000000 +0000
  47867. +++ linux-2.4.26-vrs1/drivers/pcmcia/Config.in 2004-02-23 23:29:38.000000000 +0000
  47868. @@ -14,21 +14,19 @@
  47869. tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA
  47870. if [ "$CONFIG_PCMCIA" != "n" ]; then
  47871. + # yes, I really mean the following...
  47872. + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then
  47873. + define_bool CONFIG_PCMCIA_PROBE y
  47874. + fi
  47875. if [ "$CONFIG_PCI" != "n" ]; then
  47876. bool ' CardBus support' CONFIG_CARDBUS
  47877. fi
  47878. + dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
  47879. + bool ' i82365 compatible bridge support' CONFIG_I82365
  47880. bool ' Databook TCIC host bridge support' CONFIG_TCIC
  47881. if [ "$CONFIG_HD64465" = "y" ]; then
  47882. dep_tristate ' HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
  47883. fi
  47884. - dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
  47885. - bool ' i82365 compatible bridge support' CONFIG_I82365
  47886. - if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
  47887. - dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_PCMCIA
  47888. - fi
  47889. - if [ "$CONFIG_8xx" = "y" ]; then
  47890. - dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA
  47891. - fi
  47892. if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
  47893. dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA
  47894. if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then
  47895. @@ -44,5 +42,9 @@
  47896. dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA
  47897. fi
  47898. fi
  47899. +if [ "$CONFIG_ARM" = "y" ]; then
  47900. + dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
  47901. + dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
  47902. +fi
  47903. endmenu
  47904. diff -urN linux-2.4.26/drivers/pcmcia/Makefile linux-2.4.26-vrs1/drivers/pcmcia/Makefile
  47905. --- linux-2.4.26/drivers/pcmcia/Makefile 2004-02-27 20:03:27.000000000 +0000
  47906. +++ linux-2.4.26-vrs1/drivers/pcmcia/Makefile 2004-02-23 23:19:09.000000000 +0000
  47907. @@ -65,15 +65,18 @@
  47908. au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o
  47909. au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o
  47910. +obj-$(CONFIG_PCMCIA_CLPS6700) += clps6700.o
  47911. obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
  47912. -obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
  47913. obj-$(CONFIG_PCMCIA_SIBYTE) += sibyte_generic.o
  47914. sa1100_cs-objs-y := sa1100_generic.o
  47915. +sa1100_cs-objs-$(CONFIG_SA1100_ADSAGC) += sa1100_graphicsmaster.o sa1111_generic.o
  47916. sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
  47917. +sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSYPLUS) += sa1100_adsbitsyplus.o sa1111_generic.o
  47918. sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
  47919. sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
  47920. sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
  47921. +sa1100_cs-objs-$(CONFIG_SA1100_CONSUS) += sa1100_neponset.o sa1111_generic.o
  47922. sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
  47923. sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
  47924. sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
  47925. diff -urN linux-2.4.26/drivers/pcmcia/cistpl.c linux-2.4.26-vrs1/drivers/pcmcia/cistpl.c
  47926. --- linux-2.4.26/drivers/pcmcia/cistpl.c 2004-02-27 20:03:27.000000000 +0000
  47927. +++ linux-2.4.26-vrs1/drivers/pcmcia/cistpl.c 2004-02-23 13:36:32.000000000 +0000
  47928. @@ -286,7 +286,7 @@
  47929. s->cis_mem.flags &= ~MAP_ACTIVE;
  47930. s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
  47931. if (!(s->cap.features & SS_CAP_STATIC_MAP))
  47932. - release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
  47933. + release_mem_resource(s->cis_mem.sys_start, s->cap.map_size);
  47934. bus_iounmap(s->cap.bus, s->cis_virt);
  47935. s->cis_mem.sys_start = 0;
  47936. s->cis_virt = NULL;
  47937. diff -urN linux-2.4.26/drivers/pcmcia/clps6700.c linux-2.4.26-vrs1/drivers/pcmcia/clps6700.c
  47938. --- linux-2.4.26/drivers/pcmcia/clps6700.c 1970-01-01 01:00:00.000000000 +0100
  47939. +++ linux-2.4.26-vrs1/drivers/pcmcia/clps6700.c 2004-01-14 21:32:26.000000000 +0000
  47940. @@ -0,0 +1,498 @@
  47941. +/*
  47942. + * linux/drivers/pcmcia/clps6700.c
  47943. + *
  47944. + * Copyright (C) 2000 Deep Blue Solutions Ltd
  47945. + *
  47946. + * This program is free software; you can redistribute it and/or modify
  47947. + * it under the terms of the GNU General Public License as published by
  47948. + * the Free Software Foundation; either version 2 of the License, or
  47949. + * (at your option) any later version.
  47950. + *
  47951. + * This program is distributed in the hope that it will be useful,
  47952. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  47953. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  47954. + * GNU General Public License for more details.
  47955. + *
  47956. + * You should have received a copy of the GNU General Public License
  47957. + * along with this program; if not, write to the Free Software
  47958. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  47959. + */
  47960. +#include <linux/module.h>
  47961. +#include <linux/kernel.h>
  47962. +#include <linux/slab.h>
  47963. +#include <linux/errno.h>
  47964. +#include <linux/sched.h>
  47965. +#include <linux/proc_fs.h>
  47966. +#include <linux/spinlock.h>
  47967. +#include <linux/init.h>
  47968. +
  47969. +#include <asm/io.h>
  47970. +#include <asm/irq.h>
  47971. +#include <asm/hardware.h>
  47972. +#include <asm/page.h>
  47973. +
  47974. +#include <asm/arch/syspld.h>
  47975. +#include <asm/hardware/clps7111.h>
  47976. +
  47977. +#include <pcmcia/version.h>
  47978. +#include <pcmcia/cs_types.h>
  47979. +#include <pcmcia/ss.h>
  47980. +
  47981. +#include "clps6700.h"
  47982. +
  47983. +#define DEBUG
  47984. +
  47985. +MODULE_AUTHOR("Russell King");
  47986. +MODULE_DESCRIPTION("CL-PS6700 PCMCIA socket driver");
  47987. +
  47988. +#define NR_CLPS6700 2
  47989. +
  47990. +struct clps6700_skt {
  47991. + u_int nr;
  47992. + u_int physbase;
  47993. + u_int regbase;
  47994. + u_int pmr;
  47995. + u_int cpcr;
  47996. + u_int cpcr_3v3;
  47997. + u_int cpcr_5v0;
  47998. + u_int cur_pmr;
  47999. + u_int cur_cicr;
  48000. + u_int cur_pcimr;
  48001. + u_int cur_cpcr;
  48002. + void (*handler)(void *, u_int);
  48003. + void *handler_info;
  48004. +
  48005. + u_int ev_pending;
  48006. + spinlock_t ev_lock;
  48007. +};
  48008. +
  48009. +static struct clps6700_skt *skts[NR_CLPS6700];
  48010. +
  48011. +static int clps6700_sock_init(u_int sock)
  48012. +{
  48013. + struct clps6700_skt *skt = skts[sock];
  48014. +
  48015. + skt->cur_cicr = 0;
  48016. + skt->cur_pmr = skt->pmr;
  48017. + skt->cur_pcimr = 0;
  48018. + skt->cur_cpcr = skt->cpcr;
  48019. +
  48020. +#ifdef DEBUG
  48021. + printk("skt%d: sock_init()\n", sock);
  48022. +#endif
  48023. +
  48024. + __raw_writel(skt->cur_pmr, skt->regbase + PMR);
  48025. + __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
  48026. + __raw_writel(0x01f8, skt->regbase + SICR);
  48027. + __raw_writel(0x0000, skt->regbase + DMACR);
  48028. + __raw_writel(skt->cur_cicr, skt->regbase + CICR);
  48029. + __raw_writel(0x1f00, skt->regbase + CITR0A);
  48030. + __raw_writel(0x0000, skt->regbase + CITR0B);
  48031. + __raw_writel(0x1f00, skt->regbase + CITR1A);
  48032. + __raw_writel(0x0000, skt->regbase + CITR1B);
  48033. + __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
  48034. +
  48035. + /*
  48036. + * Enable Auto Idle Mode in PM register
  48037. + */
  48038. + __raw_writel(-1, skt->regbase + PCIRR1);
  48039. + __raw_writel(-1, skt->regbase + PCIRR2);
  48040. + __raw_writel(-1, skt->regbase + PCIRR3);
  48041. +
  48042. + return 0;
  48043. +}
  48044. +
  48045. +static int clps6700_suspend(u_int sock)
  48046. +{
  48047. + return 0;
  48048. +}
  48049. +
  48050. +static int clps6700_register_callback(u_int sock, void (*handler)(void *, u_int), void *info)
  48051. +{
  48052. + struct clps6700_skt *skt = skts[sock];
  48053. +
  48054. +#ifdef DEBUG
  48055. + printk("skt%d: register_callback: %p (%p)\n", sock, handler, info);
  48056. +#endif
  48057. +
  48058. + skt->handler_info = info;
  48059. + skt->handler = handler;
  48060. +
  48061. + return 0;
  48062. +}
  48063. +
  48064. +static int clps6700_inquire_socket(u_int sock, socket_cap_t *cap)
  48065. +{
  48066. + cap->features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_MEM_ALIGN;
  48067. + cap->irq_mask = 0; /* available IRQs for this socket */
  48068. + cap->map_size = PAGE_SIZE; /* minimum mapping size */
  48069. + cap->pci_irq = 0; /* PCI interrupt number */
  48070. + cap->cb_dev = NULL;
  48071. + cap->bus = NULL;
  48072. + return 0;
  48073. +}
  48074. +
  48075. +static int __clps6700_get_status(struct clps6700_skt *skt)
  48076. +{
  48077. + unsigned int v, val;
  48078. +
  48079. + v = __raw_readl(skt->regbase + PCIILR);
  48080. + val = 0;
  48081. + if ((v & (PCM_CD1 | PCM_CD2)) == 0)
  48082. + val |= SS_DETECT;
  48083. + if ((v & (PCM_BVD2 | PCM_BVD1)) == PCM_BVD1)
  48084. + val |= SS_BATWARN;
  48085. + if ((v & PCM_BVD2) == 0)
  48086. + val |= SS_BATDEAD;
  48087. +
  48088. + if (v & PCM_RDYL)
  48089. + val |= SS_READY;
  48090. + if (v & PCM_VS1)
  48091. + val |= SS_3VCARD;
  48092. + if (v & PCM_VS2)
  48093. + val |= SS_XVCARD;
  48094. +
  48095. +#ifdef DEBUG
  48096. + printk("skt%d: PCIILR: %08x -> (%s %s %s %s %s %s)\n",
  48097. + skt->nr, v,
  48098. + val & SS_READY ? "rdy" : "---",
  48099. + val & SS_DETECT ? "det" : "---",
  48100. + val & SS_BATWARN ? "bw" : "--",
  48101. + val & SS_BATDEAD ? "bd" : "--",
  48102. + val & SS_3VCARD ? "3v" : "--",
  48103. + val & SS_XVCARD ? "xv" : "--");
  48104. +#endif
  48105. + return val;
  48106. +}
  48107. +
  48108. +static int clps6700_get_status(u_int sock, u_int *valp)
  48109. +{
  48110. + struct clps6700_skt *skt = skts[sock];
  48111. +
  48112. + *valp = __clps6700_get_status(skt);
  48113. +
  48114. + return 0; /* not used! */
  48115. +}
  48116. +
  48117. +static int clps6700_get_socket(u_int sock, socket_state_t *state)
  48118. +{
  48119. + return -EINVAL;
  48120. +}
  48121. +
  48122. +static int clps6700_set_socket(u_int sock, socket_state_t *state)
  48123. +{
  48124. + struct clps6700_skt *skt = skts[sock];
  48125. + unsigned long flags;
  48126. + u_int cpcr = skt->cur_cpcr, pmr = skt->cur_pmr, cicr = skt->cur_cicr;
  48127. + u_int pcimr = 0;
  48128. +
  48129. + cicr &= ~(CICR_ENABLE | CICR_RESET | CICR_IOMODE);
  48130. +
  48131. + if (state->flags & SS_PWR_AUTO)
  48132. + pmr |= PMR_DCAR | PMR_PDCR;
  48133. +
  48134. + /*
  48135. + * Note! We must NOT assert the Card Enable bit until reset has
  48136. + * been de-asserted. Some cards indicate not ready, which then
  48137. + * hangs our next access. (Bug in CLPS6700?)
  48138. + */
  48139. + if (state->flags & SS_RESET)
  48140. + cicr |= CICR_RESET | CICR_RESETOE;
  48141. + else if (state->flags & SS_OUTPUT_ENA)
  48142. + cicr |= CICR_ENABLE;
  48143. +
  48144. + if (state->flags & SS_IOCARD) {
  48145. + cicr |= CICR_IOMODE;
  48146. +
  48147. +/* if (state->csc_mask & SS_STSCHG)*/
  48148. + } else {
  48149. + if (state->csc_mask & SS_BATDEAD)
  48150. + pcimr |= PCM_BVD2;
  48151. + if (state->csc_mask & SS_BATWARN)
  48152. + pcimr |= PCM_BVD1;
  48153. + if (state->csc_mask & SS_READY)
  48154. + pcimr |= PCM_RDYL;
  48155. + }
  48156. +
  48157. + if (state->csc_mask & SS_DETECT)
  48158. + pcimr |= PCM_CD1 | PCM_CD2;
  48159. +
  48160. + switch (state->Vcc) {
  48161. + case 0: break;
  48162. + case 33: cpcr |= skt->cpcr_3v3; pmr |= PMR_CPE; break;
  48163. + case 50: cpcr |= skt->cpcr_5v0; pmr |= PMR_CPE; break;
  48164. + default: return -EINVAL;
  48165. + }
  48166. +
  48167. +#ifdef DEBUG
  48168. + printk("skt%d: PMR: %04x, CPCR: %04x, CICR: %04x PCIMR: %04x "
  48169. + "(Vcc = %d, flags = %c%c%c%c, csc = %c%c%c%c%c)\n",
  48170. + sock, pmr, cpcr, cicr, pcimr, state->Vcc,
  48171. + state->flags & SS_RESET ? 'r' : '-',
  48172. + state->flags & SS_PWR_AUTO ? 'p' : '-',
  48173. + state->flags & SS_IOCARD ? 'i' : '-',
  48174. + state->flags & SS_OUTPUT_ENA ? 'o' : '-',
  48175. + state->csc_mask & SS_STSCHG ? 's' : '-',
  48176. + state->csc_mask & SS_BATDEAD ? 'd' : '-',
  48177. + state->csc_mask & SS_BATWARN ? 'w' : '-',
  48178. + state->csc_mask & SS_READY ? 'r' : '-',
  48179. + state->csc_mask & SS_DETECT ? 'c' : '-');
  48180. +#endif
  48181. +
  48182. + save_flags_cli(flags);
  48183. +
  48184. + if (skt->cur_cpcr != cpcr) {
  48185. + skt->cur_cpcr = cpcr;
  48186. + __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
  48187. + }
  48188. +
  48189. + if (skt->cur_pmr != pmr) {
  48190. + skt->cur_pmr = pmr;
  48191. + __raw_writel(skt->cur_pmr, skt->regbase + PMR);
  48192. + }
  48193. + if (skt->cur_pcimr != pcimr) {
  48194. + skt->cur_pcimr = pcimr;
  48195. + __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
  48196. + }
  48197. + if (skt->cur_cicr != cicr) {
  48198. + skt->cur_cicr = cicr;
  48199. + __raw_writel(skt->cur_cicr, skt->regbase + CICR);
  48200. + }
  48201. +
  48202. + restore_flags(flags);
  48203. +
  48204. + return 0;
  48205. +}
  48206. +
  48207. +static int clps6700_get_io_map(u_int sock, struct pccard_io_map *io)
  48208. +{
  48209. + return -EINVAL;
  48210. +}
  48211. +
  48212. +static int clps6700_set_io_map(u_int sock, struct pccard_io_map *io)
  48213. +{
  48214. + printk("skt%d: iomap: %d: speed %d, flags %X start %X stop %X\n",
  48215. + sock, io->map, io->speed, io->flags, io->start, io->stop);
  48216. + return 0;
  48217. +}
  48218. +
  48219. +static int clps6700_get_mem_map(u_int sock, struct pccard_mem_map *mem)
  48220. +{
  48221. + return -EINVAL;
  48222. +}
  48223. +
  48224. +/*
  48225. + * Set the memory map attributes for this socket. (ie, mem->speed)
  48226. + * Note that since we have SS_CAP_STATIC_MAP set, we don't need to do
  48227. + * any mapping here at all; we just need to return the address (suitable
  48228. + * for ioremap) to map the requested space in mem->sys_start.
  48229. + *
  48230. + * flags & MAP_ATTRIB indicates whether we want attribute space.
  48231. + */
  48232. +static int clps6700_set_mem_map(u_int sock, struct pccard_mem_map *mem)
  48233. +{
  48234. + struct clps6700_skt *skt = skts[sock];
  48235. + u_int off;
  48236. +
  48237. + printk("skt%d: memmap: %d: speed %d, flags %X start %lX stop %lX card %X\n",
  48238. + sock, mem->map, mem->speed, mem->flags, mem->sys_start,
  48239. + mem->sys_stop, mem->card_start);
  48240. +
  48241. + if (mem->flags & MAP_ATTRIB)
  48242. + off = CLPS6700_ATTRIB_BASE;
  48243. + else
  48244. + off = CLPS6700_MEM_BASE;
  48245. +
  48246. + mem->sys_start = skt->physbase + off;
  48247. + mem->sys_start += mem->card_start;
  48248. +
  48249. + return 0;
  48250. +}
  48251. +
  48252. +static void clps6700_proc_setup(u_int sock, struct proc_dir_entry *base)
  48253. +{
  48254. +}
  48255. +
  48256. +static struct pccard_operations clps6700_operations = {
  48257. + init: clps6700_sock_init,
  48258. + suspend: clps6700_suspend,
  48259. + register_callback: clps6700_register_callback,
  48260. + inquire_socket: clps6700_inquire_socket,
  48261. + get_status: clps6700_get_status,
  48262. + get_socket: clps6700_get_socket,
  48263. + set_socket: clps6700_set_socket,
  48264. + get_io_map: clps6700_get_io_map,
  48265. + set_io_map: clps6700_set_io_map,
  48266. + get_mem_map: clps6700_get_mem_map,
  48267. + set_mem_map: clps6700_set_mem_map,
  48268. + proc_setup: clps6700_proc_setup
  48269. +};
  48270. +
  48271. +static void clps6700_bh(void *dummy)
  48272. +{
  48273. + int i;
  48274. +
  48275. + for (i = 0; i < NR_CLPS6700; i++) {
  48276. + struct clps6700_skt *skt = skts[i];
  48277. + unsigned long flags;
  48278. + u_int events;
  48279. +
  48280. + if (!skt)
  48281. + continue;
  48282. +
  48283. + /*
  48284. + * Note! We must read the pending event state
  48285. + * with interrupts disabled, otherwise we race
  48286. + * with our own interrupt routine!
  48287. + */
  48288. + spin_lock_irqsave(&skt->ev_lock, flags);
  48289. + events = skt->ev_pending;
  48290. + skt->ev_pending = 0;
  48291. + spin_unlock_irqrestore(&skt->ev_lock, flags);
  48292. +
  48293. + if (skt->handler && events)
  48294. + skt->handler(skt->handler_info, events);
  48295. + }
  48296. +}
  48297. +
  48298. +static struct tq_struct clps6700_task = {
  48299. + routine: clps6700_bh
  48300. +};
  48301. +
  48302. +static void clps6700_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  48303. +{
  48304. + struct clps6700_skt *skt = dev_id;
  48305. + u_int val, events;
  48306. +
  48307. + val = __raw_readl(skt->regbase + PCISR);
  48308. + if (!val)
  48309. + return;
  48310. +
  48311. + __raw_writel(val, skt->regbase + PCICR);
  48312. +
  48313. + events = 0;
  48314. + if (val & (PCM_CD1 | PCM_CD2))
  48315. + events |= SS_DETECT;
  48316. + if (val & PCM_BVD1)
  48317. + events |= SS_BATWARN;
  48318. + if (val & PCM_BVD2)
  48319. + events |= SS_BATDEAD;
  48320. + if (val & PCM_RDYL)
  48321. + events |= SS_READY;
  48322. +
  48323. + spin_lock(&skt->ev_lock);
  48324. + skt->ev_pending |= events;
  48325. + spin_unlock(&skt->ev_lock);
  48326. + schedule_task(&clps6700_task);
  48327. +}
  48328. +
  48329. +static int __init clps6700_init_skt(int nr)
  48330. +{
  48331. + struct clps6700_skt *skt;
  48332. + int ret;
  48333. +
  48334. + skt = kmalloc(sizeof(struct clps6700_skt), GFP_KERNEL);
  48335. + if (!skt)
  48336. + return -ENOMEM;
  48337. +
  48338. + memset(skt, 0, sizeof(struct clps6700_skt));
  48339. +
  48340. + spin_lock_init(&skt->ev_lock);
  48341. +
  48342. + skt->nr = nr;
  48343. + skt->physbase = nr ? CS5_PHYS_BASE : CS4_PHYS_BASE;
  48344. + skt->pmr = PMR_AUTOIDLE | PMR_MCPE | PMR_CDWEAK;
  48345. + skt->cpcr = CPCR_PDIR(PCTL1|PCTL0);
  48346. + skt->cpcr_3v3 = CPCR_PON(PCTL0);
  48347. + skt->cpcr_5v0 = CPCR_PON(PCTL0); /* we only do 3v3 */
  48348. +
  48349. + skt->cur_pmr = skt->pmr;
  48350. +
  48351. + skt->regbase = (u_int)ioremap(skt->physbase + CLPS6700_REG_BASE,
  48352. + CLPS6700_REG_SIZE);
  48353. + ret = -ENOMEM;
  48354. + if (!skt->regbase)
  48355. + goto err_free;
  48356. +
  48357. + skts[nr] = skt;
  48358. +
  48359. + ret = request_irq(IRQ_EINT3, clps6700_interrupt,
  48360. + SA_SHIRQ, "pcmcia", skt);
  48361. +
  48362. + if (ret) {
  48363. + printk(KERN_ERR "clps6700: unable to grab irq%d (%d)\n",
  48364. + IRQ_EINT3, ret);
  48365. + goto err_unmap;
  48366. + }
  48367. + return 0;
  48368. +
  48369. +err_unmap:
  48370. + iounmap((void *)skt->regbase);
  48371. +err_free:
  48372. + kfree(skt);
  48373. + skts[nr] = NULL;
  48374. + return ret;
  48375. +}
  48376. +
  48377. +static void clps6700_free_resources(void)
  48378. +{
  48379. + int i;
  48380. +
  48381. + for (i = NR_CLPS6700; i >= 0; i--) {
  48382. + struct clps6700_skt *skt = skts[i];
  48383. +
  48384. + skts[i] = NULL;
  48385. + if (skt == NULL)
  48386. + continue;
  48387. +
  48388. + free_irq(IRQ_EINT3, skt);
  48389. + if (skt->regbase) {
  48390. + __raw_writel(skt->pmr, skt->regbase + PMR);
  48391. + __raw_writel(skt->cpcr, skt->regbase + CPCR);
  48392. + __raw_writel(0, skt->regbase + CICR);
  48393. + __raw_writel(0, skt->regbase + PCIMR);
  48394. + }
  48395. + iounmap((void *)skt->regbase);
  48396. + kfree(skt);
  48397. + }
  48398. +}
  48399. +
  48400. +static int __init clps6700_init(void)
  48401. +{
  48402. + unsigned int v;
  48403. + int err, nr;
  48404. +
  48405. + PLD_CF = 0;
  48406. + v = clps_readl(SYSCON2) | SYSCON2_PCCARD1 | SYSCON2_PCCARD2;
  48407. + clps_writel(v, SYSCON2);
  48408. + v = clps_readl(SYSCON1) | SYSCON1_EXCKEN;
  48409. + clps_writel(v, SYSCON1);
  48410. +
  48411. + for (nr = 0; nr < NR_CLPS6700; nr++) {
  48412. + err = clps6700_init_skt(nr);
  48413. + if (err)
  48414. + goto free;
  48415. + }
  48416. +
  48417. + err = register_ss_entry(nr, &clps6700_operations);
  48418. + if (err)
  48419. + goto free;
  48420. +
  48421. + return 0;
  48422. +
  48423. +free:
  48424. + clps6700_free_resources();
  48425. + /*
  48426. + * An error occurred. Unmap and free all CLPS6700
  48427. + */
  48428. + return err;
  48429. +}
  48430. +
  48431. +static void __exit clps6700_exit(void)
  48432. +{
  48433. + unregister_ss_entry(&clps6700_operations);
  48434. + clps6700_free_resources();
  48435. +}
  48436. +
  48437. +module_init(clps6700_init);
  48438. +module_exit(clps6700_exit);
  48439. diff -urN linux-2.4.26/drivers/pcmcia/clps6700.h linux-2.4.26-vrs1/drivers/pcmcia/clps6700.h
  48440. --- linux-2.4.26/drivers/pcmcia/clps6700.h 1970-01-01 01:00:00.000000000 +0100
  48441. +++ linux-2.4.26-vrs1/drivers/pcmcia/clps6700.h 2004-01-14 21:32:26.000000000 +0000
  48442. @@ -0,0 +1,85 @@
  48443. +#define PCISR 0x0000 /* PC Card Interrupt Status Register */
  48444. +#define PCIMR 0x0400 /* PC Card Interrupt Mask Register */
  48445. +#define PCICR 0x0800 /* PC Card Interrupt Clear Register */
  48446. +#define PCIOSR 0x0c00 /* PC Card Interrupt Output Select Regsiter */
  48447. +#define PCIRR1 0x1000 /* PC Card Interrupt Reserved Register 1 */
  48448. +#define PCIRR2 0x1400 /* PC Card Interrupt Reserved Register 2 */
  48449. +#define PCIRR3 0x1800 /* PC Card Interrupt Reserved Register 3 */
  48450. +#define PCIILR 0x1c00 /* PC Card Interrupt Input Level Register */
  48451. +#define SICR 0x2000 /* System Interface Configuration Register */
  48452. +#define CICR 0x2400 /* Card Interface Configuration Register */
  48453. +#define PMR 0x2800 /* Power Management Register */
  48454. +#define CPCR 0x2c00 /* Card Power Control Register */
  48455. +#define CITR0A 0x3000 /* Card Interface Timing Register 0A */
  48456. +#define CITR0B 0x3400 /* Card Interface Timing Register 0B */
  48457. +#define CITR1A 0x3800 /* Card Interface Timing Register 1A */
  48458. +#define CITR1B 0x3c00 /* Card Interface Timing Register 1B */
  48459. +#define DMACR 0x4000 /* DMA Control Register */
  48460. +#define DIR 0x4400 /* Device Information Register */
  48461. +
  48462. +#define CLPS6700_ATTRIB_BASE 0x00000000
  48463. +#define CLPS6700_IO_BASE 0x04000000
  48464. +#define CLPS6700_MEM_BASE 0x08000000
  48465. +#define CLPS6700_REG_BASE 0x0c000000
  48466. +#define CLPS6700_REG_SIZE 0x00005000
  48467. +
  48468. +
  48469. +#define PMR_AUTOIDLE (1 << 0) /* auto idle mode */
  48470. +#define PMR_FORCEIDLE (1 << 1) /* force idle mode */
  48471. +#define PMR_PDCS (1 << 2) /* Power down card on standby */
  48472. +#define PMR_PDCR (1 << 3) /* Power down card on removal */
  48473. +#define PMR_DCAR (1 << 4) /* Disable card access on removal */
  48474. +#define PMR_CPE (1 << 5) /* Card power enable */
  48475. +#define PMR_MCPE (1 << 6) /* Monitor card power enable */
  48476. +#define PMR_PDREQLSEL (1 << 7) /* If set, PDREQL is a GPIO pin */
  48477. +#define PMR_DISSTBY (1 << 8) /* Disable standby */
  48478. +#define PMR_ACCSTBY (1 << 9) /* Complete card accesses before standby*/
  48479. +#define PMR_CDUNPROT (0 << 10) /* Card detect inputs unprotected */
  48480. +#define PMR_CDPROT (1 << 10) /* Card detect inputs protected */
  48481. +#define PMR_CDWEAK (2 << 10) /* Weak pullup except in standby */
  48482. +#define PMR_CDWEAKAL (3 << 10) /* Weak pullup */
  48483. +
  48484. +#define CPCR_PON(x) ((x)&7) /* PCTL[2:0] value when PMR_CPE = 1 */
  48485. +#define CPCR_POFF(x) (((x)&7)<<3) /* PCTL[2:0] value when PMR_CPE = 0 */
  48486. +#define CPCR_PDIR(x) (((x)&7)<<6) /* PCTL[2:0] direction */
  48487. +#define CPCR_CON(x) (((x)&1)<<9) /* GPIO value when PMR_CPE = 1 */
  48488. +#define CPCR_COFF(x) (((x)&1)<<10) /* GPIO value when PMR_CPE = 0 */
  48489. +#define CPCR_CDIR(x) (((x)&1)<<11) /* GPIO direction (PMR_PDREQLSEL = 1) */
  48490. +#define CPCR_VS(x) (((x)&3)<<12) /* VS[2:1] output value */
  48491. +#define CPCR_VSDIR(x) (((x)&3)<<14) /* VS[2:1] direction */
  48492. +
  48493. +#define PCTL0 (1 << 0)
  48494. +#define PCTL1 (1 << 1)
  48495. +#define PCTL2 (1 << 2)
  48496. +
  48497. +#define CICR_ASRTMR1 (1 << 0) /* Timer 1 select for attribute read */
  48498. +#define CICR_ASWTMR1 (1 << 1) /* Timer 1 select for attribute write */
  48499. +#define CICR_IOSRTMR1 (1 << 2) /* Timer 1 select for IO read */
  48500. +#define CICR_IOSWTMR1 (1 << 3) /* Timer 1 select for IO write */
  48501. +#define CICR_MEMSRTMR1 (1 << 4) /* Timer 1 select for memory read */
  48502. +#define CICR_MEMSWTMR1 (1 << 5) /* Timer 1 select for memory write */
  48503. +#define CICR_AUTOIOSZ (1 << 6) /* Auto size I/O accesses */
  48504. +#define CICR_CAW (1 << 7) /* Card access width */
  48505. +#define CICR_IOMODE (1 << 8) /* IO mode select */
  48506. +#define CICR_ENABLE (1 << 10) /* Card enable */
  48507. +#define CICR_RESETOE (1 << 11) /* Card reset output enable */
  48508. +#define CICR_RESET (1 << 12) /* Card reset */
  48509. +
  48510. +
  48511. +#define RD_FAIL (1 << 14)
  48512. +#define WR_FAIL (1 << 13)
  48513. +#define IDLE (1 << 12)
  48514. +
  48515. +#define FFOTHLD (1 << 11)
  48516. +#define PCM_RDYL (1 << 10)
  48517. +#define PCM_WP (1 << 9)
  48518. +#define PCTL (1 << 8)
  48519. +
  48520. +#define PDREQ_L (1 << 6)
  48521. +#define PCM_VS2 (1 << 5)
  48522. +#define PCM_VS1 (1 << 4)
  48523. +
  48524. +#define PCM_CD2 (1 << 3)
  48525. +#define PCM_CD1 (1 << 2)
  48526. +#define PCM_BVD2 (1 << 1)
  48527. +#define PCM_BVD1 (1 << 0)
  48528. diff -urN linux-2.4.26/drivers/pcmcia/cs.c linux-2.4.26-vrs1/drivers/pcmcia/cs.c
  48529. --- linux-2.4.26/drivers/pcmcia/cs.c 2004-02-27 20:03:27.000000000 +0000
  48530. +++ linux-2.4.26-vrs1/drivers/pcmcia/cs.c 2004-02-27 23:44:12.000000000 +0000
  48531. @@ -3,7 +3,7 @@
  48532. Kernel Card Services -- core services
  48533. cs.c 1.271 2000/10/02 20:27:49
  48534. -
  48535. +
  48536. The contents of this file are subject to the Mozilla Public
  48537. License Version 1.1 (the "License"); you may not use this file
  48538. except in compliance with the License. You may obtain a copy of
  48539. @@ -28,7 +28,7 @@
  48540. and other provisions required by the GPL. If you do not delete
  48541. the provisions above, a recipient may use your version of this
  48542. file under either the MPL or the GPL.
  48543. -
  48544. +
  48545. ======================================================================*/
  48546. #include <linux/module.h>
  48547. @@ -92,7 +92,7 @@
  48548. MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  48549. MODULE_DESCRIPTION("Linux Kernel Card Services " CS_RELEASE
  48550. "\n options:" OPTIONS);
  48551. -MODULE_LICENSE("Dual MPL/GPL");
  48552. +MODULE_LICENSE("Dual MPL/GPL");
  48553. #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
  48554. @@ -123,7 +123,7 @@
  48555. static const char *version =
  48556. "cs.c 1.279 2001/10/13 00:08:28 (David Hinds)";
  48557. #endif
  48558. -
  48559. +
  48560. /*====================================================================*/
  48561. socket_state_t dead_socket = {
  48562. @@ -299,7 +299,7 @@
  48563. Low-level PC Card interface drivers need to register with Card
  48564. Services using these calls.
  48565. -
  48566. +
  48567. ======================================================================*/
  48568. static int setup_socket(socket_info_t *);
  48569. @@ -331,7 +331,7 @@
  48570. s->use_bus_pm = use_bus_pm;
  48571. s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
  48572. spin_lock_init(&s->lock);
  48573. -
  48574. +
  48575. for (i = 0; i < sockets; i++)
  48576. if (socket_table[i] == NULL) break;
  48577. socket_table[i] = s;
  48578. @@ -365,7 +365,7 @@
  48579. for (ns = 0; ns < nsock; ns++) {
  48580. pcmcia_register_socket (ns, ss_entry, 0);
  48581. }
  48582. -
  48583. +
  48584. return 0;
  48585. } /* register_ss_entry */
  48586. @@ -457,7 +457,7 @@
  48587. static void shutdown_socket(socket_info_t *s)
  48588. {
  48589. client_t **c;
  48590. -
  48591. +
  48592. DEBUG(1, "cs: shutdown_socket(%p)\n", s);
  48593. /* Blank out the socket state */
  48594. @@ -561,7 +561,7 @@
  48595. have several causes: card insertion, a call to reset_socket, or
  48596. recovery from a suspend/resume cycle. Unreset_socket() sends
  48597. a CS event that matches the cause of the reset.
  48598. -
  48599. +
  48600. ======================================================================*/
  48601. static void reset_socket(socket_info_t *s)
  48602. @@ -616,7 +616,7 @@
  48603. s->state &= ~SOCKET_SETUP_PENDING;
  48604. } else {
  48605. send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
  48606. - if (s->reset_handle) {
  48607. + if (s->reset_handle) {
  48608. s->reset_handle->event_callback_args.info = NULL;
  48609. EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
  48610. CS_EVENT_PRI_LOW);
  48611. @@ -631,7 +631,7 @@
  48612. valid clients. Parse_events() interprets the event bits from
  48613. a card status change report. Do_shutdown() handles the high
  48614. priority stuff associated with a card removal.
  48615. -
  48616. +
  48617. ======================================================================*/
  48618. static int send_event(socket_info_t *s, event_t event, int priority)
  48619. @@ -641,7 +641,7 @@
  48620. DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",
  48621. s->sock, event, priority);
  48622. ret = 0;
  48623. - for (; client; client = client->next) {
  48624. + for (; client; client = client->next) {
  48625. if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
  48626. continue;
  48627. if (client->EventMask & event) {
  48628. @@ -675,10 +675,17 @@
  48629. static void parse_events(void *info, u_int events)
  48630. {
  48631. socket_info_t *s = info;
  48632. +
  48633. if (events & SS_DETECT) {
  48634. int status;
  48635. get_socket_status(s, &status);
  48636. +
  48637. + /*
  48638. + * If our socket state indicates that a card is present and
  48639. + * either the socket has not been suspended (for some reason)
  48640. + * or the card has been removed, shut down the socket first.
  48641. + */
  48642. if ((s->state & SOCKET_PRESENT) &&
  48643. (!(s->state & SOCKET_SUSPEND) ||
  48644. !(status & SS_DETECT)))
  48645. @@ -716,7 +723,7 @@
  48646. This does not comply with the latest PC Card spec for handling
  48647. power management events.
  48648. -
  48649. +
  48650. ======================================================================*/
  48651. void pcmcia_suspend_socket (socket_info_t *s)
  48652. @@ -773,7 +780,7 @@
  48653. /*======================================================================
  48654. Special stuff for managing IO windows, because they are scarce.
  48655. -
  48656. +
  48657. ======================================================================*/
  48658. static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
  48659. @@ -862,7 +869,7 @@
  48660. Access_configuration_register() reads and writes configuration
  48661. registers in attribute memory. Memory window 0 is reserved for
  48662. this and the tuple reading services.
  48663. -
  48664. +
  48665. ======================================================================*/
  48666. int pcmcia_access_configuration_register(client_handle_t handle,
  48667. @@ -872,7 +879,7 @@
  48668. config_t *c;
  48669. int addr;
  48670. u_char val;
  48671. -
  48672. +
  48673. if (CHECK_HANDLE(handle))
  48674. return CS_BAD_HANDLE;
  48675. s = SOCKET(handle);
  48676. @@ -890,7 +897,7 @@
  48677. return CS_CONFIGURATION_LOCKED;
  48678. addr = (c->ConfigBase + reg->Offset) >> 1;
  48679. -
  48680. +
  48681. switch (reg->Action) {
  48682. case CS_READ:
  48683. read_cis_mem(s, 1, addr, 1, &val);
  48684. @@ -913,7 +920,7 @@
  48685. It is normally called by Driver Services after it has identified
  48686. a newly inserted card. An instance of that driver will then be
  48687. eligible to register as a client of this socket.
  48688. -
  48689. +
  48690. ======================================================================*/
  48691. int pcmcia_bind_device(bind_req_t *req)
  48692. @@ -949,23 +956,23 @@
  48693. region. It is normally called by Driver Services after it has
  48694. identified a memory device type. An instance of the corresponding
  48695. driver will then be able to register to control this region.
  48696. -
  48697. +
  48698. ======================================================================*/
  48699. int pcmcia_bind_mtd(mtd_bind_t *req)
  48700. {
  48701. socket_info_t *s;
  48702. memory_handle_t region;
  48703. -
  48704. +
  48705. if (CHECK_SOCKET(req->Socket))
  48706. return CS_BAD_SOCKET;
  48707. s = SOCKET(req);
  48708. -
  48709. +
  48710. if (req->Attributes & REGION_TYPE_AM)
  48711. region = s->a_region;
  48712. else
  48713. region = s->c_region;
  48714. -
  48715. +
  48716. while (region) {
  48717. if (region->info.CardOffset == req->CardOffset) break;
  48718. region = region->info.next;
  48719. @@ -973,7 +980,7 @@
  48720. if (!region || (region->mtd != NULL))
  48721. return CS_BAD_OFFSET;
  48722. strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
  48723. -
  48724. +
  48725. DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
  48726. req->Attributes, req->CardOffset, (char *)req->dev_info);
  48727. return CS_SUCCESS;
  48728. @@ -988,7 +995,7 @@
  48729. memory_handle_t region;
  48730. u_long flags;
  48731. int i, sn;
  48732. -
  48733. +
  48734. DEBUG(1, "cs: deregister_client(%p)\n", handle);
  48735. if (CHECK_HANDLE(handle))
  48736. return CS_BAD_HANDLE;
  48737. @@ -1007,7 +1014,7 @@
  48738. for (region = s->c_region; region; region = region->info.next)
  48739. if (region->mtd == handle) region->mtd = NULL;
  48740. }
  48741. -
  48742. +
  48743. sn = handle->Socket; s = socket_table[sn];
  48744. if ((handle->state & CLIENT_STALE) ||
  48745. @@ -1032,7 +1039,7 @@
  48746. if (--s->real_clients == 0)
  48747. register_callback(s, NULL, NULL);
  48748. -
  48749. +
  48750. return CS_SUCCESS;
  48751. } /* deregister_client */
  48752. @@ -1043,7 +1050,7 @@
  48753. {
  48754. socket_info_t *s;
  48755. config_t *c;
  48756. -
  48757. +
  48758. if (CHECK_HANDLE(handle))
  48759. return CS_BAD_HANDLE;
  48760. s = SOCKET(handle);
  48761. @@ -1055,7 +1062,7 @@
  48762. return CS_BAD_ARGS;
  48763. } else
  48764. config->Function = handle->Function;
  48765. -
  48766. +
  48767. #ifdef CONFIG_CARDBUS
  48768. if (s->state & SOCKET_CARDBUS) {
  48769. u_char fn = config->Function;
  48770. @@ -1076,16 +1083,16 @@
  48771. return CS_SUCCESS;
  48772. }
  48773. #endif
  48774. -
  48775. +
  48776. c = (s->config != NULL) ? &s->config[config->Function] : NULL;
  48777. -
  48778. +
  48779. if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
  48780. config->Attributes = 0;
  48781. config->Vcc = s->socket.Vcc;
  48782. config->Vpp1 = config->Vpp2 = s->socket.Vpp;
  48783. return CS_SUCCESS;
  48784. }
  48785. -
  48786. +
  48787. /* !!! This is a hack !!! */
  48788. memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
  48789. config->Attributes |= CONF_VALID_CLIENT;
  48790. @@ -1099,14 +1106,14 @@
  48791. config->NumPorts2 = c->io.NumPorts2;
  48792. config->Attributes2 = c->io.Attributes2;
  48793. config->IOAddrLines = c->io.IOAddrLines;
  48794. -
  48795. +
  48796. return CS_SUCCESS;
  48797. } /* get_configuration_info */
  48798. /*======================================================================
  48799. Return information about this version of Card Services.
  48800. -
  48801. +
  48802. ======================================================================*/
  48803. int pcmcia_get_card_services_info(servinfo_t *info)
  48804. @@ -1124,7 +1131,7 @@
  48805. Note that get_first_client() *does* recognize the Socket field
  48806. in the request structure.
  48807. -
  48808. +
  48809. ======================================================================*/
  48810. int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
  48811. @@ -1239,7 +1246,7 @@
  48812. Get the current socket state bits. We don't support the latched
  48813. SocketState yet: I haven't seen any point for it.
  48814. -
  48815. +
  48816. ======================================================================*/
  48817. int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
  48818. @@ -1247,7 +1254,7 @@
  48819. socket_info_t *s;
  48820. config_t *c;
  48821. int val;
  48822. -
  48823. +
  48824. if (CHECK_HANDLE(handle))
  48825. return CS_BAD_HANDLE;
  48826. s = SOCKET(handle);
  48827. @@ -1263,7 +1270,7 @@
  48828. return CS_NO_CARD;
  48829. if (s->state & SOCKET_SETUP_PENDING)
  48830. status->CardState |= CS_EVENT_CARD_INSERTION;
  48831. -
  48832. +
  48833. /* Get info from the PRR, if necessary */
  48834. if (handle->Function == BIND_FN_ALL) {
  48835. if (status->Function && (status->Function >= s->functions))
  48836. @@ -1309,7 +1316,7 @@
  48837. /*======================================================================
  48838. Change the card address of an already open memory window.
  48839. -
  48840. +
  48841. ======================================================================*/
  48842. int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
  48843. @@ -1338,7 +1345,7 @@
  48844. /*======================================================================
  48845. Modify a locked socket configuration
  48846. -
  48847. +
  48848. ======================================================================*/
  48849. int pcmcia_modify_configuration(client_handle_t handle,
  48850. @@ -1346,7 +1353,7 @@
  48851. {
  48852. socket_info_t *s;
  48853. config_t *c;
  48854. -
  48855. +
  48856. if (CHECK_HANDLE(handle))
  48857. return CS_BAD_HANDLE;
  48858. s = SOCKET(handle); c = CONFIG(handle);
  48859. @@ -1354,7 +1361,7 @@
  48860. return CS_NO_CARD;
  48861. if (!(c->state & CONFIG_LOCKED))
  48862. return CS_CONFIGURATION_LOCKED;
  48863. -
  48864. +
  48865. if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
  48866. if (mod->Attributes & CONF_ENABLE_IRQ) {
  48867. c->Attributes |= CONF_ENABLE_IRQ;
  48868. @@ -1406,7 +1413,7 @@
  48869. win->ctl.flags |= MAP_USE_WAIT;
  48870. win->ctl.speed = req->AccessSpeed;
  48871. set_mem_map(win->sock, &win->ctl);
  48872. -
  48873. +
  48874. return CS_SUCCESS;
  48875. } /* modify_window */
  48876. @@ -1416,7 +1423,7 @@
  48877. caller with a socket. The driver must have already been bound
  48878. to a socket with bind_device() -- in fact, bind_device()
  48879. allocates the client structure that will be used.
  48880. -
  48881. +
  48882. ======================================================================*/
  48883. int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
  48884. @@ -1424,7 +1431,7 @@
  48885. client_t *client;
  48886. socket_info_t *s;
  48887. socket_t ns;
  48888. -
  48889. +
  48890. /* Look for unbound client with matching dev_info */
  48891. client = NULL;
  48892. for (ns = 0; ns < sockets; ns++) {
  48893. @@ -1464,7 +1471,7 @@
  48894. if (s->state & SOCKET_CARDBUS)
  48895. client->state |= CLIENT_CARDBUS;
  48896. -
  48897. +
  48898. if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
  48899. (client->Function != BIND_FN_ALL)) {
  48900. cistpl_longlink_mfc_t mfc;
  48901. @@ -1479,7 +1486,7 @@
  48902. return CS_OUT_OF_RESOURCE;
  48903. memset(s->config, 0, sizeof(config_t) * s->functions);
  48904. }
  48905. -
  48906. +
  48907. DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n",
  48908. client, client->Socket, client->dev_info);
  48909. if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
  48910. @@ -1501,13 +1508,13 @@
  48911. pccard_io_map io = { 0, 0, 0, 0, 1 };
  48912. socket_info_t *s;
  48913. int i;
  48914. -
  48915. +
  48916. if (CHECK_HANDLE(handle) ||
  48917. !(handle->state & CLIENT_CONFIG_LOCKED))
  48918. return CS_BAD_HANDLE;
  48919. handle->state &= ~CLIENT_CONFIG_LOCKED;
  48920. s = SOCKET(handle);
  48921. -
  48922. +
  48923. #ifdef CONFIG_CARDBUS
  48924. if (handle->state & CLIENT_CARDBUS) {
  48925. cb_disable(s);
  48926. @@ -1515,7 +1522,7 @@
  48927. return CS_SUCCESS;
  48928. }
  48929. #endif
  48930. -
  48931. +
  48932. if (!(handle->state & CLIENT_STALE)) {
  48933. config_t *c = CONFIG(handle);
  48934. if (--(s->lock_count) == 0) {
  48935. @@ -1536,7 +1543,7 @@
  48936. }
  48937. c->state &= ~CONFIG_LOCKED;
  48938. }
  48939. -
  48940. +
  48941. return CS_SUCCESS;
  48942. } /* release_configuration */
  48943. @@ -1547,25 +1554,25 @@
  48944. the actual socket configuration, so if the client is "stale", we
  48945. don't bother checking the port ranges against the current socket
  48946. values.
  48947. -
  48948. +
  48949. ======================================================================*/
  48950. int pcmcia_release_io(client_handle_t handle, io_req_t *req)
  48951. {
  48952. socket_info_t *s;
  48953. -
  48954. +
  48955. if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
  48956. return CS_BAD_HANDLE;
  48957. handle->state &= ~CLIENT_IO_REQ;
  48958. s = SOCKET(handle);
  48959. -
  48960. +
  48961. #ifdef CONFIG_CARDBUS
  48962. if (handle->state & CLIENT_CARDBUS) {
  48963. cb_release(s);
  48964. return CS_SUCCESS;
  48965. }
  48966. #endif
  48967. -
  48968. +
  48969. if (!(handle->state & CLIENT_STALE)) {
  48970. config_t *c = CONFIG(handle);
  48971. if (c->state & CONFIG_LOCKED)
  48972. @@ -1581,7 +1588,7 @@
  48973. release_io_space(s, req->BasePort1, req->NumPorts1);
  48974. if (req->NumPorts2)
  48975. release_io_space(s, req->BasePort2, req->NumPorts2);
  48976. -
  48977. +
  48978. return CS_SUCCESS;
  48979. } /* release_io */
  48980. @@ -1594,7 +1601,7 @@
  48981. return CS_BAD_HANDLE;
  48982. handle->state &= ~CLIENT_IRQ_REQ;
  48983. s = SOCKET(handle);
  48984. -
  48985. +
  48986. if (!(handle->state & CLIENT_STALE)) {
  48987. config_t *c = CONFIG(handle);
  48988. if (c->state & CONFIG_LOCKED)
  48989. @@ -1608,16 +1615,16 @@
  48990. s->irq.AssignedIRQ = 0;
  48991. }
  48992. }
  48993. -
  48994. +
  48995. if (req->Attributes & IRQ_HANDLE_PRESENT) {
  48996. bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance);
  48997. }
  48998. -#ifdef CONFIG_ISA
  48999. +#ifdef CONFIG_PCMCIA_PROBE
  49000. if (req->AssignedIRQ != s->cap.pci_irq)
  49001. undo_irq(req->Attributes, req->AssignedIRQ);
  49002. #endif
  49003. -
  49004. +
  49005. return CS_SUCCESS;
  49006. } /* cs_release_irq */
  49007. @@ -1626,7 +1633,7 @@
  49008. int pcmcia_release_window(window_handle_t win)
  49009. {
  49010. socket_info_t *s;
  49011. -
  49012. +
  49013. if ((win == NULL) || (win->magic != WINDOW_MAGIC))
  49014. return CS_BAD_HANDLE;
  49015. s = win->sock;
  49016. @@ -1640,11 +1647,11 @@
  49017. /* Release system memory */
  49018. if(!(s->cap.features & SS_CAP_STATIC_MAP))
  49019. - release_mem_region(win->base, win->size);
  49020. + release_mem_resource(win->base, win->size);
  49021. win->handle->state &= ~CLIENT_WIN_REQ(win->index);
  49022. win->magic = 0;
  49023. -
  49024. +
  49025. return CS_SUCCESS;
  49026. } /* release_window */
  49027. @@ -1658,13 +1665,13 @@
  49028. socket_info_t *s;
  49029. config_t *c;
  49030. pccard_io_map iomap;
  49031. -
  49032. +
  49033. if (CHECK_HANDLE(handle))
  49034. return CS_BAD_HANDLE;
  49035. i = handle->Socket; s = socket_table[i];
  49036. if (!(s->state & SOCKET_PRESENT))
  49037. return CS_NO_CARD;
  49038. -
  49039. +
  49040. #ifdef CONFIG_CARDBUS
  49041. if (handle->state & CLIENT_CARDBUS) {
  49042. if (!(req->IntType & INT_CARDBUS))
  49043. @@ -1677,7 +1684,7 @@
  49044. return CS_SUCCESS;
  49045. }
  49046. #endif
  49047. -
  49048. +
  49049. if (req->IntType & INT_CARDBUS)
  49050. return CS_UNSUPPORTED_MODE;
  49051. c = CONFIG(handle);
  49052. @@ -1692,9 +1699,9 @@
  49053. s->socket.Vpp = req->Vpp1;
  49054. if (set_socket(s, &s->socket))
  49055. return CS_BAD_VPP;
  49056. -
  49057. +
  49058. c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
  49059. -
  49060. +
  49061. /* Pick memory or I/O card, DMA mode, interrupt */
  49062. c->IntType = req->IntType;
  49063. c->Attributes = req->Attributes;
  49064. @@ -1712,7 +1719,7 @@
  49065. s->socket.io_irq = 0;
  49066. set_socket(s, &s->socket);
  49067. s->lock_count++;
  49068. -
  49069. +
  49070. /* Set up CIS configuration registers */
  49071. base = c->ConfigBase = req->ConfigBase;
  49072. c->Present = c->CardValues = req->Present;
  49073. @@ -1757,7 +1764,7 @@
  49074. u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
  49075. write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
  49076. }
  49077. -
  49078. +
  49079. /* Configure I/O windows */
  49080. if (c->state & CONFIG_IO_REQ) {
  49081. iomap.speed = io_speed;
  49082. @@ -1779,24 +1786,24 @@
  49083. s->io[i].Config++;
  49084. }
  49085. }
  49086. -
  49087. +
  49088. c->state |= CONFIG_LOCKED;
  49089. handle->state |= CLIENT_CONFIG_LOCKED;
  49090. return CS_SUCCESS;
  49091. } /* request_configuration */
  49092. /*======================================================================
  49093. -
  49094. +
  49095. Request_io() reserves ranges of port addresses for a socket.
  49096. I have not implemented range sharing or alias addressing.
  49097. -
  49098. +
  49099. ======================================================================*/
  49100. int pcmcia_request_io(client_handle_t handle, io_req_t *req)
  49101. {
  49102. socket_info_t *s;
  49103. config_t *c;
  49104. -
  49105. +
  49106. if (CHECK_HANDLE(handle))
  49107. return CS_BAD_HANDLE;
  49108. s = SOCKET(handle);
  49109. @@ -1855,7 +1862,7 @@
  49110. hooked, we don't guarantee that an irq will still be available
  49111. when the configuration is locked. Now that I think about it,
  49112. there might be a way to fix this using a dummy handler.
  49113. -
  49114. +
  49115. ======================================================================*/
  49116. int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
  49117. @@ -1863,7 +1870,7 @@
  49118. socket_info_t *s;
  49119. config_t *c;
  49120. int ret = CS_IN_USE, irq = 0;
  49121. -
  49122. +
  49123. if (CHECK_HANDLE(handle))
  49124. return CS_BAD_HANDLE;
  49125. s = SOCKET(handle);
  49126. @@ -1875,7 +1882,7 @@
  49127. if (c->state & CONFIG_IRQ_REQ)
  49128. return CS_IN_USE;
  49129. -#ifdef CONFIG_ISA
  49130. +#ifdef CONFIG_PCMCIA_PROBE
  49131. if (s->irq.AssignedIRQ != 0) {
  49132. /* If the interrupt is already assigned, it must match */
  49133. irq = s->irq.AssignedIRQ;
  49134. @@ -1909,7 +1916,7 @@
  49135. if (req->Attributes & IRQ_HANDLE_PRESENT) {
  49136. if (bus_request_irq(s->cap.bus, irq, req->Handler,
  49137. - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
  49138. + ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
  49139. (s->functions > 1) ||
  49140. (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,
  49141. handle->dev_info, req->Instance))
  49142. @@ -1919,7 +1926,7 @@
  49143. c->irq.Attributes = req->Attributes;
  49144. s->irq.AssignedIRQ = req->AssignedIRQ = irq;
  49145. s->irq.Config++;
  49146. -
  49147. +
  49148. c->state |= CONFIG_IRQ_REQ;
  49149. handle->state |= CLIENT_IRQ_REQ;
  49150. return CS_SUCCESS;
  49151. @@ -1938,7 +1945,7 @@
  49152. window_t *win;
  49153. u_long align;
  49154. int w;
  49155. -
  49156. +
  49157. if (CHECK_HANDLE(*handle))
  49158. return CS_BAD_HANDLE;
  49159. s = SOCKET(*handle);
  49160. @@ -2005,7 +2012,7 @@
  49161. /* Return window handle */
  49162. req->Base = win->ctl.sys_start;
  49163. *wh = win;
  49164. -
  49165. +
  49166. return CS_SUCCESS;
  49167. } /* request_window */
  49168. @@ -2014,14 +2021,14 @@
  49169. I'm not sure which "reset" function this is supposed to use,
  49170. but for now, it uses the low-level interface's reset, not the
  49171. CIS register.
  49172. -
  49173. +
  49174. ======================================================================*/
  49175. int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
  49176. {
  49177. int i, ret;
  49178. socket_info_t *s;
  49179. -
  49180. +
  49181. if (CHECK_HANDLE(handle))
  49182. return CS_BAD_HANDLE;
  49183. i = handle->Socket; s = socket_table[i];
  49184. @@ -2049,14 +2056,14 @@
  49185. These shut down or wake up a socket. They are sort of user
  49186. initiated versions of the APM suspend and resume actions.
  49187. -
  49188. +
  49189. ======================================================================*/
  49190. int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
  49191. {
  49192. int i;
  49193. socket_info_t *s;
  49194. -
  49195. +
  49196. if (CHECK_HANDLE(handle))
  49197. return CS_BAD_HANDLE;
  49198. i = handle->Socket; s = socket_table[i];
  49199. @@ -2077,7 +2084,7 @@
  49200. {
  49201. int i;
  49202. socket_info_t *s;
  49203. -
  49204. +
  49205. if (CHECK_HANDLE(handle))
  49206. return CS_BAD_HANDLE;
  49207. i = handle->Socket; s = socket_table[i];
  49208. @@ -2095,7 +2102,7 @@
  49209. /*======================================================================
  49210. These handle user requests to eject or insert a card.
  49211. -
  49212. +
  49213. ======================================================================*/
  49214. int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
  49215. @@ -2103,7 +2110,7 @@
  49216. int i, ret;
  49217. socket_info_t *s;
  49218. u_long flags;
  49219. -
  49220. +
  49221. if (CHECK_HANDLE(handle))
  49222. return CS_BAD_HANDLE;
  49223. i = handle->Socket; s = socket_table[i];
  49224. @@ -2119,9 +2126,9 @@
  49225. spin_lock_irqsave(&s->lock, flags);
  49226. do_shutdown(s);
  49227. spin_unlock_irqrestore(&s->lock, flags);
  49228. -
  49229. +
  49230. return CS_SUCCESS;
  49231. -
  49232. +
  49233. } /* eject_card */
  49234. int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
  49235. @@ -2129,7 +2136,7 @@
  49236. int i, status;
  49237. socket_info_t *s;
  49238. u_long flags;
  49239. -
  49240. +
  49241. if (CHECK_HANDLE(handle))
  49242. return CS_BAD_HANDLE;
  49243. i = handle->Socket; s = socket_table[i];
  49244. @@ -2157,7 +2164,7 @@
  49245. Maybe this should send a CS_EVENT_CARD_INSERTION event if we
  49246. haven't sent one to this client yet?
  49247. -
  49248. +
  49249. ======================================================================*/
  49250. int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
  49251. @@ -2189,7 +2196,7 @@
  49252. printk(KERN_NOTICE);
  49253. else
  49254. printk(KERN_NOTICE "%s: ", handle->dev_info);
  49255. -
  49256. +
  49257. for (i = 0; i < SERVICE_COUNT; i++)
  49258. if (service_table[i].key == err->func) break;
  49259. if (i < SERVICE_COUNT)
  49260. @@ -2347,13 +2354,13 @@
  49261. default:
  49262. return CS_UNSUPPORTED_FUNCTION; break;
  49263. }
  49264. -
  49265. +
  49266. } /* CardServices */
  49267. /*======================================================================
  49268. OS-specific module glue goes here
  49269. -
  49270. +
  49271. ======================================================================*/
  49272. /* in alpha order */
  49273. EXPORT_SYMBOL(pcmcia_access_configuration_register);
  49274. @@ -2450,4 +2457,3 @@
  49275. module_exit(exit_pcmcia_cs);
  49276. /*====================================================================*/
  49277. -
  49278. diff -urN linux-2.4.26/drivers/pcmcia/ds.c linux-2.4.26-vrs1/drivers/pcmcia/ds.c
  49279. --- linux-2.4.26/drivers/pcmcia/ds.c 2001-11-12 17:39:01.000000000 +0000
  49280. +++ linux-2.4.26-vrs1/drivers/pcmcia/ds.c 2004-01-14 21:32:26.000000000 +0000
  49281. @@ -55,6 +55,7 @@
  49282. #include <pcmcia/bulkmem.h>
  49283. #include <pcmcia/cistpl.h>
  49284. #include <pcmcia/ds.h>
  49285. +#include <linux/devfs_fs_kernel.h>
  49286. /*====================================================================*/
  49287. @@ -880,6 +881,8 @@
  49288. EXPORT_SYMBOL(register_pccard_driver);
  49289. EXPORT_SYMBOL(unregister_pccard_driver);
  49290. +static devfs_handle_t devfs_handle;
  49291. +
  49292. /*====================================================================*/
  49293. int __init init_pcmcia_ds(void)
  49294. @@ -957,8 +960,13 @@
  49295. if (i == -EBUSY)
  49296. printk(KERN_NOTICE "unable to find a free device # for "
  49297. "Driver Services\n");
  49298. - else
  49299. + else {
  49300. major_dev = i;
  49301. + devfs_handle = devfs_register(NULL, "pcmcia", DEVFS_FL_DEFAULT,
  49302. + major_dev, 0,
  49303. + S_IFCHR | S_IRUSR | S_IWUSR,
  49304. + &ds_fops, NULL);
  49305. + }
  49306. #ifdef CONFIG_PROC_FS
  49307. if (proc_pccard)
  49308. @@ -983,7 +991,9 @@
  49309. remove_proc_entry("drivers", proc_pccard);
  49310. #endif
  49311. if (major_dev != -1)
  49312. - unregister_chrdev(major_dev, "pcmcia");
  49313. + devfs_unregister_chrdev(major_dev, "pcmcia");
  49314. + devfs_unregister(devfs_handle);
  49315. +
  49316. for (i = 0; i < sockets; i++)
  49317. pcmcia_deregister_client(socket_table[i].handle);
  49318. sockets = 0;
  49319. diff -urN linux-2.4.26/drivers/pcmcia/i82365.c linux-2.4.26-vrs1/drivers/pcmcia/i82365.c
  49320. --- linux-2.4.26/drivers/pcmcia/i82365.c 2003-11-28 18:26:20.000000000 +0000
  49321. +++ linux-2.4.26-vrs1/drivers/pcmcia/i82365.c 2004-02-22 14:44:10.000000000 +0000
  49322. @@ -28,7 +28,7 @@
  49323. and other provisions required by the GPL. If you do not delete
  49324. the provisions above, a recipient may use your version of this
  49325. file under either the MPL or the GPL.
  49326. -
  49327. +
  49328. ======================================================================*/
  49329. #include <linux/module.h>
  49330. @@ -65,6 +65,15 @@
  49331. #include "ricoh.h"
  49332. #include "o2micro.h"
  49333. +#ifdef CONFIG_ARCH_EBSA110
  49334. +#define I365_MASK (1 << 6)
  49335. +#define SOCKIRQ2REG(sock,irq) ((irq) ? ((sock) ? 3 : 4) : 0)
  49336. +#define REG2SOCKIRQ(sock,reg) (6)
  49337. +#else
  49338. +#define SOCKIRQ2REG(sock,irq) (irq)
  49339. +#define REG2SOCKIRQ(sock,reg) (reg)
  49340. +#endif
  49341. +
  49342. #ifdef PCMCIA_DEBUG
  49343. static int pc_debug = PCMCIA_DEBUG;
  49344. MODULE_PARM(pc_debug, "i");
  49345. @@ -173,13 +182,15 @@
  49346. } socket_info_t;
  49347. /* Where we keep track of our sockets... */
  49348. -static int sockets = 0;
  49349. -static socket_info_t socket[8] = {
  49350. - { 0, }, /* ... */
  49351. -};
  49352. +static int sockets /* = 0 */;
  49353. +static socket_info_t socket[8] /* = {
  49354. + { 0, },
  49355. +} */;
  49356. /* Default ISA interrupt mask */
  49357. +#ifndef I365_MASK
  49358. #define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
  49359. +#endif
  49360. static int grab_irq;
  49361. static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
  49362. @@ -303,7 +314,7 @@
  49363. The VIA controllers also use these routines, as they are mostly
  49364. Cirrus lookalikes, without the timing registers.
  49365. -
  49366. +
  49367. ======================================================================*/
  49368. #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
  49369. @@ -389,7 +400,7 @@
  49370. Code to save and restore global state information for Vadem VG468
  49371. and VG469 controllers, and to set and report global configuration
  49372. options.
  49373. -
  49374. +
  49375. ======================================================================*/
  49376. static void vg46x_get_state(u_short s)
  49377. @@ -411,7 +422,7 @@
  49378. static u_int __init vg46x_set_opts(u_short s, char *buf)
  49379. {
  49380. vg46x_state_t *p = &socket[s].state.vg46x;
  49381. -
  49382. +
  49383. flip(p->ctl, VG468_CTL_ASYNC, async_clock);
  49384. flip(p->ema, VG469_MODE_CABLE, cable_mode);
  49385. if (p->ctl & VG468_CTL_ASYNC)
  49386. @@ -436,7 +447,7 @@
  49387. /*======================================================================
  49388. Generic routines to get and set controller options
  49389. -
  49390. +
  49391. ======================================================================*/
  49392. static void get_bridge_state(u_short s)
  49393. @@ -489,7 +500,7 @@
  49394. /*======================================================================
  49395. Interrupt testing code, for ISA and PCI interrupts
  49396. -
  49397. +
  49398. ======================================================================*/
  49399. static volatile u_int irq_hits;
  49400. @@ -517,7 +528,7 @@
  49401. }
  49402. /* Generate one interrupt */
  49403. - i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
  49404. + i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (SOCKIRQ2REG(sock, irq) << 4));
  49405. i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
  49406. udelay(1000);
  49407. @@ -526,7 +537,7 @@
  49408. /* mask all interrupts */
  49409. i365_set(sock, I365_CSCINT, 0);
  49410. DEBUG(2, " hits = %d\n", irq_hits);
  49411. -
  49412. +
  49413. return (irq_hits != 1);
  49414. }
  49415. @@ -540,7 +551,7 @@
  49416. /* Don't probe level-triggered interrupts -- reserved for PCI */
  49417. mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
  49418. #endif
  49419. -
  49420. +
  49421. if (do_scan) {
  49422. set_bridge_state(sock);
  49423. i365_set(sock, I365_CSCINT, 0);
  49424. @@ -551,7 +562,7 @@
  49425. if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
  49426. mask1 ^= (1 << i);
  49427. }
  49428. -
  49429. +
  49430. printk(KERN_INFO " ISA irqs (");
  49431. if (mask1) {
  49432. printk("scanned");
  49433. @@ -565,12 +576,12 @@
  49434. if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
  49435. }
  49436. printk(") = ");
  49437. -
  49438. +
  49439. for (i = 0; i < 16; i++)
  49440. if (mask1 & (1<<i))
  49441. printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
  49442. if (mask1 == 0) printk("none!");
  49443. -
  49444. +
  49445. return mask1;
  49446. }
  49447. @@ -598,14 +609,14 @@
  49448. /* Use the next free entry in the socket table */
  49449. socket[sockets].ioaddr = port;
  49450. socket[sockets].psock = sock;
  49451. -
  49452. +
  49453. /* Wake up a sleepy Cirrus controller */
  49454. if (wakeup) {
  49455. i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
  49456. /* Pause at least 50 ms */
  49457. mdelay(50);
  49458. }
  49459. -
  49460. +
  49461. if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
  49462. return -1;
  49463. switch (val) {
  49464. @@ -618,7 +629,7 @@
  49465. case 0x88: case 0x89: case 0x8a:
  49466. type = IS_IBM; break;
  49467. }
  49468. -
  49469. +
  49470. /* Check for Vadem VG-468 chips */
  49471. outb(0x0e, port);
  49472. outb(0x37, port);
  49473. @@ -633,7 +644,7 @@
  49474. val = i365_get(sockets, RF5C_CHIP_ID);
  49475. if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
  49476. type = IS_RF5Cx96;
  49477. -
  49478. +
  49479. /* Check for Cirrus CL-PD67xx chips */
  49480. i365_set(sockets, PD67_CHIP_INFO, 0);
  49481. val = i365_get(sockets, PD67_CHIP_INFO);
  49482. @@ -655,14 +666,14 @@
  49483. bound to a (non PC Card) Linux driver. We leave these alone.
  49484. We make an exception for cards that seem to be serial devices.
  49485. -
  49486. +
  49487. ======================================================================*/
  49488. static int __init is_alive(u_short sock)
  49489. {
  49490. u_char stat;
  49491. u_short start, stop;
  49492. -
  49493. +
  49494. stat = i365_get(sock, I365_STATUS);
  49495. start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
  49496. stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
  49497. @@ -697,7 +708,7 @@
  49498. base = sockets-ns;
  49499. if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
  49500. -
  49501. +
  49502. if (base == 0) printk("\n");
  49503. printk(KERN_INFO " %s", pcic[type].name);
  49504. printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
  49505. @@ -713,7 +724,7 @@
  49506. mask &= I365_MASK & set_bridge_opts(base, ns);
  49507. /* Scan for ISA interrupts */
  49508. mask = isa_scan(base, mask);
  49509. -
  49510. +
  49511. /* Poll if only two interrupts available */
  49512. if (!poll_interval) {
  49513. u_int tmp = (mask & 0xff20);
  49514. @@ -735,15 +746,15 @@
  49515. printk(" status change on irq %d\n", cs_irq);
  49516. }
  49517. }
  49518. -
  49519. +
  49520. if (!isa_irq) {
  49521. if (poll_interval == 0)
  49522. poll_interval = HZ;
  49523. printk(" polling interval = %d ms\n",
  49524. poll_interval * 1000 / HZ);
  49525. -
  49526. +
  49527. }
  49528. -
  49529. +
  49530. /* Update socket interrupt information, capabilities */
  49531. for (i = 0; i < ns; i++) {
  49532. t[i].cap.features |= SS_CAP_PCCARD;
  49533. @@ -866,12 +877,12 @@
  49534. events = pending_events[i];
  49535. pending_events[i] = 0;
  49536. spin_unlock_irq(&pending_event_lock);
  49537. - /*
  49538. - SS_DETECT events need a small delay here. The reason for this is that
  49539. + /*
  49540. + SS_DETECT events need a small delay here. The reason for this is that
  49541. the "is there a card" electronics need time to see the card after the
  49542. - "we have a card coming in" electronics have seen it.
  49543. + "we have a card coming in" electronics have seen it.
  49544. */
  49545. - if (events & SS_DETECT)
  49546. + if (events & SS_DETECT)
  49547. mdelay(4);
  49548. if (socket[i].handler)
  49549. socket[i].handler(socket[i].info, events);
  49550. @@ -890,7 +901,7 @@
  49551. int i, j, csc;
  49552. u_int events, active;
  49553. u_long flags = 0;
  49554. -
  49555. +
  49556. DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
  49557. for (j = 0; j < 20; j++) {
  49558. @@ -906,20 +917,20 @@
  49559. continue;
  49560. }
  49561. events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
  49562. -
  49563. -
  49564. +
  49565. +
  49566. /* Several sockets will send multiple "new card detected"
  49567. - events in rapid succession. However, the rest of the pcmcia expects
  49568. + events in rapid succession. However, the rest of the pcmcia expects
  49569. only one such event. We just ignore these events by having a
  49570. timeout */
  49571. if (events) {
  49572. - if ((jiffies - last_detect_jiffies)<(HZ/20))
  49573. + if ((jiffies - last_detect_jiffies)<(HZ/20))
  49574. events = 0;
  49575. last_detect_jiffies = jiffies;
  49576. -
  49577. +
  49578. }
  49579. -
  49580. +
  49581. if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
  49582. events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
  49583. else {
  49584. @@ -980,11 +991,11 @@
  49585. static int i365_get_status(u_short sock, u_int *value)
  49586. {
  49587. u_int status;
  49588. -
  49589. +
  49590. status = i365_get(sock, I365_STATUS);
  49591. *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
  49592. ? SS_DETECT : 0;
  49593. -
  49594. +
  49595. if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
  49596. *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
  49597. else {
  49598. @@ -1005,7 +1016,7 @@
  49599. *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
  49600. }
  49601. }
  49602. -
  49603. +
  49604. DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
  49605. return 0;
  49606. } /* i365_get_status */
  49607. @@ -1016,7 +1027,7 @@
  49608. {
  49609. socket_info_t *t = &socket[sock];
  49610. u_char reg, vcc, vpp;
  49611. -
  49612. +
  49613. reg = i365_get(sock, I365_POWER);
  49614. state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
  49615. state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
  49616. @@ -1057,14 +1068,14 @@
  49617. reg = i365_get(sock, I365_INTCTL);
  49618. state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
  49619. if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
  49620. - state->io_irq = reg & I365_IRQ_MASK;
  49621. -
  49622. + state->io_irq = REG2SOCKIRQ(sock, reg & I365_IRQ_MASK);
  49623. +
  49624. /* speaker control */
  49625. if (t->flags & IS_CIRRUS) {
  49626. if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
  49627. state->flags |= SS_SPKR_ENA;
  49628. }
  49629. -
  49630. +
  49631. /* Card status change mask */
  49632. reg = i365_get(sock, I365_CSCINT);
  49633. state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
  49634. @@ -1075,7 +1086,7 @@
  49635. state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
  49636. state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
  49637. }
  49638. -
  49639. +
  49640. DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
  49641. "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
  49642. state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
  49643. @@ -1088,21 +1099,21 @@
  49644. {
  49645. socket_info_t *t = &socket[sock];
  49646. u_char reg;
  49647. -
  49648. +
  49649. DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
  49650. "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
  49651. state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
  49652. -
  49653. +
  49654. /* First set global controller options */
  49655. set_bridge_state(sock);
  49656. -
  49657. +
  49658. /* IO card, RESET flag, IO interrupt */
  49659. reg = t->intr;
  49660. - reg |= state->io_irq;
  49661. + reg |= SOCKIRQ2REG(sock, state->io_irq);
  49662. reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
  49663. reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
  49664. i365_set(sock, I365_INTCTL, reg);
  49665. -
  49666. +
  49667. reg = I365_PWR_NORESET;
  49668. if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
  49669. if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
  49670. @@ -1165,7 +1176,7 @@
  49671. default: return -EINVAL;
  49672. }
  49673. }
  49674. -
  49675. +
  49676. if (reg != i365_get(sock, I365_POWER))
  49677. i365_set(sock, I365_POWER, reg);
  49678. @@ -1175,9 +1186,9 @@
  49679. i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
  49680. state->flags & SS_SPKR_ENA);
  49681. }
  49682. -
  49683. +
  49684. /* Card status change interrupt mask */
  49685. - reg = t->cs_irq << 4;
  49686. + reg = SOCKIRQ2REG(sock, t->cs_irq) << 4;
  49687. if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
  49688. if (state->flags & SS_IOCARD) {
  49689. if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
  49690. @@ -1188,7 +1199,7 @@
  49691. }
  49692. i365_set(sock, I365_CSCINT, reg);
  49693. i365_get(sock, I365_CSC);
  49694. -
  49695. +
  49696. return 0;
  49697. } /* i365_set_socket */
  49698. @@ -1197,7 +1208,7 @@
  49699. static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
  49700. {
  49701. u_char map, ioctl, addr;
  49702. -
  49703. +
  49704. map = io->map;
  49705. if (map > 1) return -EINVAL;
  49706. io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
  49707. @@ -1220,7 +1231,7 @@
  49708. static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
  49709. {
  49710. u_char map, ioctl;
  49711. -
  49712. +
  49713. DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
  49714. "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
  49715. io->speed, io->start, io->stop);
  49716. @@ -1250,30 +1261,30 @@
  49717. {
  49718. u_short base, i;
  49719. u_char map, addr;
  49720. -
  49721. +
  49722. map = mem->map;
  49723. if (map > 4) return -EINVAL;
  49724. addr = i365_get(sock, I365_ADDRWIN);
  49725. mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
  49726. base = I365_MEM(map);
  49727. -
  49728. +
  49729. i = i365_get_pair(sock, base+I365_W_START);
  49730. mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
  49731. mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
  49732. mem->sys_start = ((u_long)(i & 0x0fff) << 12);
  49733. -
  49734. +
  49735. i = i365_get_pair(sock, base+I365_W_STOP);
  49736. mem->speed = (i & I365_MEM_WS0) ? 1 : 0;
  49737. mem->speed += (i & I365_MEM_WS1) ? 2 : 0;
  49738. mem->speed = to_ns(mem->speed);
  49739. mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff;
  49740. -
  49741. +
  49742. i = i365_get_pair(sock, base+I365_W_OFF);
  49743. mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
  49744. mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
  49745. mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
  49746. mem->card_start &= 0x3ffffff;
  49747. -
  49748. +
  49749. DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
  49750. "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
  49751. mem->sys_start, mem->sys_stop, mem->card_start);
  49752. @@ -1281,12 +1292,12 @@
  49753. } /* i365_get_mem_map */
  49754. /*====================================================================*/
  49755. -
  49756. +
  49757. static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
  49758. {
  49759. u_short base, i;
  49760. u_char map;
  49761. -
  49762. +
  49763. DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
  49764. "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
  49765. mem->sys_start, mem->sys_stop, mem->card_start);
  49766. @@ -1297,17 +1308,17 @@
  49767. return -EINVAL;
  49768. if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
  49769. return -EINVAL;
  49770. -
  49771. +
  49772. /* Turn off the window before changing anything */
  49773. if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
  49774. i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
  49775. -
  49776. +
  49777. base = I365_MEM(map);
  49778. i = (mem->sys_start >> 12) & 0x0fff;
  49779. if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
  49780. if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
  49781. i365_set_pair(sock, base+I365_W_START, i);
  49782. -
  49783. +
  49784. i = (mem->sys_stop >> 12) & 0x0fff;
  49785. switch (to_cycles(mem->speed)) {
  49786. case 0: break;
  49787. @@ -1316,12 +1327,12 @@
  49788. default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
  49789. }
  49790. i365_set_pair(sock, base+I365_W_STOP, i);
  49791. -
  49792. +
  49793. i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
  49794. if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
  49795. if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
  49796. i365_set_pair(sock, base+I365_W_OFF, i);
  49797. -
  49798. +
  49799. /* Turn on the window if necessary */
  49800. if (mem->flags & MAP_ACTIVE)
  49801. i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
  49802. @@ -1332,7 +1343,7 @@
  49803. Routines for accessing socket information and register dumps via
  49804. /proc/bus/pccard/...
  49805. -
  49806. +
  49807. ======================================================================*/
  49808. #ifdef CONFIG_PROC_FS
  49809. @@ -1353,7 +1364,7 @@
  49810. u_short sock = (socket_info_t *)data - socket;
  49811. char *p = buf;
  49812. int i, top;
  49813. -
  49814. +
  49815. u_long flags = 0;
  49816. ISA_LOCK(sock, flags);
  49817. top = 0x40;
  49818. @@ -1399,7 +1410,7 @@
  49819. /*====================================================================*/
  49820. -/* this is horribly ugly... proper locking needs to be done here at
  49821. +/* this is horribly ugly... proper locking needs to be done here at
  49822. * some time... */
  49823. #define LOCKED(x) do { \
  49824. int retval; \
  49825. @@ -1532,7 +1543,7 @@
  49826. /* Set up interrupt handler(s) */
  49827. if (grab_irq != 0)
  49828. request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
  49829. -
  49830. +
  49831. if (register_ss_entry(sockets, &pcic_operations) != 0)
  49832. printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
  49833. @@ -1544,9 +1555,9 @@
  49834. poll_timer.expires = jiffies + poll_interval;
  49835. add_timer(&poll_timer);
  49836. }
  49837. -
  49838. +
  49839. return 0;
  49840. -
  49841. +
  49842. } /* init_i82365 */
  49843. static void __exit exit_i82365(void)
  49844. diff -urN linux-2.4.26/drivers/pcmcia/rsrc_mgr.c linux-2.4.26-vrs1/drivers/pcmcia/rsrc_mgr.c
  49845. --- linux-2.4.26/drivers/pcmcia/rsrc_mgr.c 2004-02-27 20:03:27.000000000 +0000
  49846. +++ linux-2.4.26-vrs1/drivers/pcmcia/rsrc_mgr.c 2004-02-23 13:36:32.000000000 +0000
  49847. @@ -28,7 +28,7 @@
  49848. and other provisions required by the GPL. If you do not delete
  49849. the provisions above, a recipient may use your version of this
  49850. file under either the MPL or the GPL.
  49851. -
  49852. +
  49853. ======================================================================*/
  49854. #define __NO_VERSION__
  49855. @@ -55,6 +55,10 @@
  49856. #include <pcmcia/cistpl.h>
  49857. #include "cs_internal.h"
  49858. +#ifndef ISAMEM_PHYS
  49859. +#define ISAMEM_PHYS 0
  49860. +#endif
  49861. +
  49862. /*====================================================================*/
  49863. /* Parameters that can be set with 'insmod' */
  49864. @@ -62,7 +66,7 @@
  49865. #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
  49866. INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
  49867. -#ifdef CONFIG_ISA
  49868. +#ifdef CONFIG_PCMCIA_PROBE
  49869. INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
  49870. INT_MODULE_PARM(mem_limit, 0x10000);
  49871. #endif
  49872. @@ -85,7 +89,7 @@
  49873. /* IO port resource database */
  49874. static resource_map_t io_db = { 0, 0, &io_db };
  49875. -#ifdef CONFIG_ISA
  49876. +#ifdef CONFIG_PCMCIA_PROBE
  49877. typedef struct irq_info_t {
  49878. u_int Attributes;
  49879. @@ -133,6 +137,7 @@
  49880. static inline int check_mem_resource(unsigned long b, unsigned long n,
  49881. struct pci_dev *dev)
  49882. {
  49883. + b += ISAMEM_PHYS;
  49884. return check_resource(resource_parent(b, n, IORESOURCE_MEM, dev), b, n);
  49885. }
  49886. @@ -169,10 +174,15 @@
  49887. static int request_mem_resource(unsigned long b, unsigned long n,
  49888. char *name, struct pci_dev *dev)
  49889. {
  49890. - struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
  49891. - struct resource *pr = resource_parent(b, n, IORESOURCE_MEM, dev);
  49892. + struct resource *res;
  49893. + struct resource *pr;
  49894. int err = -ENOMEM;
  49895. + b += ISAMEM_PHYS;
  49896. +
  49897. + res = make_resource(b, n, IORESOURCE_MEM, name);
  49898. + pr = resource_parent(b, n, IORESOURCE_MEM, dev);
  49899. +
  49900. if (res) {
  49901. err = request_resource(pr, res);
  49902. if (err)
  49903. @@ -181,10 +191,16 @@
  49904. return err;
  49905. }
  49906. +void release_mem_resource(unsigned long b, unsigned long n)
  49907. +{
  49908. + b += ISAMEM_PHYS;
  49909. + release_mem_region(b, n);
  49910. +}
  49911. +
  49912. /*======================================================================
  49913. These manage the internal databases of available resources.
  49914. -
  49915. +
  49916. ======================================================================*/
  49917. static int add_interval(resource_map_t *map, u_long base, u_long num)
  49918. @@ -248,25 +264,25 @@
  49919. These routines examine a region of IO or memory addresses to
  49920. determine what ranges might be genuinely available.
  49921. -
  49922. +
  49923. ======================================================================*/
  49924. -#ifdef CONFIG_ISA
  49925. +#ifdef CONFIG_PCMCIA_PROBE
  49926. static void do_io_probe(ioaddr_t base, ioaddr_t num)
  49927. {
  49928. -
  49929. +
  49930. ioaddr_t i, j, bad, any;
  49931. u_char *b, hole, most;
  49932. -
  49933. +
  49934. printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
  49935. base, base+num-1);
  49936. -
  49937. +
  49938. /* First, what does a floating port look like? */
  49939. b = kmalloc(256, GFP_KERNEL);
  49940. if (!b) {
  49941. printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
  49942. return;
  49943. - }
  49944. + }
  49945. memset(b, 0, 256);
  49946. for (i = base, most = 0; i < base+num; i += 8) {
  49947. if (check_io_resource(i, 8, NULL))
  49948. @@ -308,7 +324,7 @@
  49949. printk(" %#04x-%#04x", bad, i-1);
  49950. }
  49951. }
  49952. -
  49953. +
  49954. printk(any ? "\n" : " clean.\n");
  49955. }
  49956. #endif
  49957. @@ -318,7 +334,7 @@
  49958. The memory probe. If the memory list includes a 64K-aligned block
  49959. below 1MB, we probe in 64K chunks, and as soon as we accumulate at
  49960. least mem_limit free space, we quit.
  49961. -
  49962. +
  49963. ======================================================================*/
  49964. static int do_mem_probe(u_long base, u_long num,
  49965. @@ -332,7 +348,7 @@
  49966. bad = fail = 0;
  49967. step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
  49968. for (i = j = base; i < base+num; i = j + step) {
  49969. - if (!fail) {
  49970. + if (!fail) {
  49971. for (j = i; j < base+num; j += step)
  49972. if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
  49973. is_valid(j))
  49974. @@ -356,7 +372,7 @@
  49975. return (num - bad);
  49976. }
  49977. -#ifdef CONFIG_ISA
  49978. +#ifdef CONFIG_PCMCIA_PROBE
  49979. static u_long inv_probe(int (*is_valid)(u_long),
  49980. int (*do_cksum)(u_long),
  49981. @@ -383,7 +399,7 @@
  49982. static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
  49983. static int hi = 0, lo = 0;
  49984. u_long b, i, ok = 0;
  49985. -
  49986. +
  49987. if (!probe_mem) return;
  49988. /* We do up to four passes through the list */
  49989. if (!force_low) {
  49990. @@ -414,14 +430,14 @@
  49991. }
  49992. }
  49993. -#else /* CONFIG_ISA */
  49994. +#else /* CONFIG_PCMCIA_PROBE */
  49995. void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
  49996. int force_low, socket_info_t *s)
  49997. {
  49998. resource_map_t *m, *n;
  49999. static int done = 0;
  50000. -
  50001. +
  50002. if (!probe_mem || done++)
  50003. return;
  50004. @@ -432,7 +448,7 @@
  50005. }
  50006. }
  50007. -#endif /* CONFIG_ISA */
  50008. +#endif /* CONFIG_PCMCIA_PROBE */
  50009. /*======================================================================
  50010. @@ -444,7 +460,7 @@
  50011. should be a power of two, greater than or equal to 'num'. A value
  50012. of 0 means that all bits of *base are significant. *base should
  50013. also be strictly less than 'align'.
  50014. -
  50015. +
  50016. ======================================================================*/
  50017. int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
  50018. @@ -452,7 +468,7 @@
  50019. {
  50020. ioaddr_t try;
  50021. resource_map_t *m;
  50022. -
  50023. +
  50024. for (m = io_db.next; m != &io_db; m = m->next) {
  50025. try = (m->base & ~(align-1)) + *base;
  50026. for (try = (try >= m->base) ? try : try+align;
  50027. @@ -500,10 +516,10 @@
  50028. This checks to see if an interrupt is available, with support
  50029. for interrupt sharing. We don't support reserving interrupts
  50030. yet. If the interrupt is available, we allocate it.
  50031. -
  50032. +
  50033. ======================================================================*/
  50034. -#ifdef CONFIG_ISA
  50035. +#ifdef CONFIG_PCMCIA_PROBE
  50036. static void fake_irq(int i, void *d, struct pt_regs *r) { }
  50037. static inline int check_irq(int irq)
  50038. @@ -570,7 +586,7 @@
  50039. /*====================================================================*/
  50040. -#ifdef CONFIG_ISA
  50041. +#ifdef CONFIG_PCMCIA_PROBE
  50042. void undo_irq(u_int Attributes, int irq)
  50043. {
  50044. @@ -600,7 +616,7 @@
  50045. The various adjust_* calls form the external interface to the
  50046. resource database.
  50047. -
  50048. +
  50049. ======================================================================*/
  50050. static int adjust_memory(adjust_t *adj)
  50051. @@ -632,7 +648,7 @@
  50052. default:
  50053. ret = CS_UNSUPPORTED_FUNCTION;
  50054. }
  50055. -
  50056. +
  50057. return ret;
  50058. }
  50059. @@ -641,7 +657,7 @@
  50060. static int adjust_io(adjust_t *adj)
  50061. {
  50062. int base, num;
  50063. -
  50064. +
  50065. base = adj->resource.io.BasePort;
  50066. num = adj->resource.io.NumPorts;
  50067. if ((base < 0) || (base > 0xffff))
  50068. @@ -653,7 +669,7 @@
  50069. case ADD_MANAGED_RESOURCE:
  50070. if (add_interval(&io_db, base, num) != 0)
  50071. return CS_IN_USE;
  50072. -#ifdef CONFIG_ISA
  50073. +#ifdef CONFIG_PCMCIA_PROBE
  50074. if (probe_io)
  50075. do_io_probe(base, num);
  50076. #endif
  50077. @@ -673,15 +689,15 @@
  50078. static int adjust_irq(adjust_t *adj)
  50079. {
  50080. -#ifdef CONFIG_ISA
  50081. +#ifdef CONFIG_PCMCIA_PROBE
  50082. int irq;
  50083. irq_info_t *info;
  50084. -
  50085. +
  50086. irq = adj->resource.irq.IRQ;
  50087. if ((irq < 0) || (irq > 15))
  50088. return CS_BAD_IRQ;
  50089. info = &irq_table[irq];
  50090. -
  50091. +
  50092. switch (adj->Action) {
  50093. case ADD_MANAGED_RESOURCE:
  50094. if (info->Attributes & RES_REMOVED)
  50095. @@ -716,7 +732,7 @@
  50096. {
  50097. if (CHECK_HANDLE(handle))
  50098. return CS_BAD_HANDLE;
  50099. -
  50100. +
  50101. switch (adj->Resource) {
  50102. case RES_MEMORY_RANGE:
  50103. return adjust_memory(adj);
  50104. @@ -736,7 +752,7 @@
  50105. void release_resource_db(void)
  50106. {
  50107. resource_map_t *p, *q;
  50108. -
  50109. +
  50110. for (p = mem_db.next; p != &mem_db; p = q) {
  50111. q = p->next;
  50112. kfree(p);
  50113. diff -urN linux-2.4.26/drivers/pcmcia/sa1100.h linux-2.4.26-vrs1/drivers/pcmcia/sa1100.h
  50114. --- linux-2.4.26/drivers/pcmcia/sa1100.h 2002-08-03 01:39:44.000000000 +0100
  50115. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100.h 2004-01-14 21:32:26.000000000 +0000
  50116. @@ -204,7 +204,9 @@
  50117. extern struct pcmcia_low_level flexanet_pcmcia_ops;
  50118. extern struct pcmcia_low_level simpad_pcmcia_ops;
  50119. extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
  50120. +extern struct pcmcia_low_level adsagc_pcmcia_ops;
  50121. extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
  50122. +extern struct pcmcia_low_level adsbitsyplus_pcmcia_ops;
  50123. extern struct pcmcia_low_level stork_pcmcia_ops;
  50124. extern struct pcmcia_low_level badge4_pcmcia_ops;
  50125. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_adsbitsy.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_adsbitsy.c
  50126. --- linux-2.4.26/drivers/pcmcia/sa1100_adsbitsy.c 2002-08-03 01:39:44.000000000 +0100
  50127. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_adsbitsy.c 2004-01-14 21:32:26.000000000 +0000
  50128. @@ -11,28 +11,156 @@
  50129. */
  50130. #include <linux/kernel.h>
  50131. #include <linux/sched.h>
  50132. +#include <linux/ioport.h>
  50133. #include <asm/hardware.h>
  50134. +#include <asm/hardware/sa1111.h>
  50135. +#include <asm/irq.h>
  50136. #include "sa1100_generic.h"
  50137. #include "sa1111_generic.h"
  50138. +int adsbitsy_smc91111_present(void);
  50139. +
  50140. +#ifndef CONFIG_SMC91111
  50141. +#define adsbitsy_smc91111_present() 0
  50142. +#endif
  50143. +
  50144. +static struct irqs {
  50145. + int irq;
  50146. + const char *str;
  50147. +} irqs[] = {
  50148. + { S0_CD_VALID, "SA1111 PCMCIA card detect" },
  50149. + { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
  50150. + { S1_CD_VALID, "SA1111 CF card detect" },
  50151. + { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
  50152. +};
  50153. +
  50154. static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
  50155. {
  50156. - /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
  50157. - PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
  50158. + int ret=0;
  50159. + int nirq = 0;
  50160. + int slots = 0;
  50161. + int i;
  50162. +
  50163. + /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
  50164. + PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
  50165. +
  50166. + /* Disable Power 3.3V/5V for PCMCIA */
  50167. + PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
  50168. +
  50169. + if (!request_mem_region(_PCCR, 512, "PCMCIA"))
  50170. + return -1;
  50171. +
  50172. +
  50173. + INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
  50174. + SA1111_IRQMASK_HI(S0_CD_VALID) |
  50175. + SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
  50176. - /* Disable Power 3.3V/5V for PCMCIA/CF */
  50177. - PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
  50178. + nirq = 2;
  50179. + slots = 1;
  50180. +
  50181. + if (!adsbitsy_smc91111_present()) {
  50182. + /* If the SMC91111 is used CF cannot be used */
  50183. + /* Set GPIO_A<3:2> to be outputs for CF power controller: */
  50184. + PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
  50185. +
  50186. + /* Disable Power 3.3V/5V for CF */
  50187. + PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
  50188. +
  50189. + INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
  50190. + SA1111_IRQMASK_HI(S1_CD_VALID) |
  50191. + SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
  50192. +
  50193. + nirq = 4;
  50194. + slots = 2;
  50195. + }
  50196. +
  50197. + for (i = ret = 0; i < nirq; i++) {
  50198. + ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
  50199. + irqs[i].str, NULL);
  50200. + if (ret)
  50201. + break;
  50202. + }
  50203. - /* Why? */
  50204. - MECR = 0x09430943;
  50205. + if (i < nirq) {
  50206. + printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
  50207. + irqs[i].irq, ret);
  50208. + while (i--)
  50209. + free_irq(irqs[i].irq, NULL);
  50210. - return sa1111_pcmcia_init(init);
  50211. + release_mem_region(_PCCR, 16);
  50212. + }
  50213. +
  50214. + return ret ? -1 : slots;
  50215. +}
  50216. +
  50217. +static int adsbitsy_pcmcia_shutdown(void)
  50218. +{
  50219. +
  50220. + free_irq(S0_CD_VALID, NULL);
  50221. + free_irq(S0_BVD1_STSCHG, NULL);
  50222. + INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
  50223. +
  50224. + if (!adsbitsy_smc91111_present()) {
  50225. + free_irq(S1_CD_VALID, NULL);
  50226. + free_irq(S1_BVD1_STSCHG, NULL);
  50227. + INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
  50228. + }
  50229. +
  50230. + return 0;
  50231. }
  50232. -static int
  50233. -adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
  50234. +
  50235. +static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state)
  50236. +{
  50237. + unsigned long status;
  50238. +
  50239. + if (adsbitsy_smc91111_present()) {
  50240. + if(state->size<1) return -1;
  50241. + }
  50242. + else
  50243. + if(state->size<2) return -1;
  50244. +
  50245. + memset(state->state, 0,
  50246. + (state->size)*sizeof(struct pcmcia_state));
  50247. +
  50248. + status = PCSR;
  50249. +
  50250. + state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
  50251. + state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
  50252. + state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
  50253. + state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
  50254. + state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
  50255. + state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
  50256. + state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
  50257. +
  50258. + if (state->size > 1) {
  50259. + if (adsbitsy_smc91111_present()) {
  50260. + // If there is SMC91111 on ADS Bitsy connector board
  50261. + // it returns not detect/ready/...
  50262. + state->state[1].detect = 0;
  50263. + state->state[1].ready = 0;
  50264. + state->state[1].bvd1 = 0;
  50265. + state->state[1].bvd2 = 0;
  50266. + state->state[1].wrprot = 0;
  50267. + state->state[1].vs_3v = 0;
  50268. + state->state[1].vs_Xv = 0;
  50269. + }
  50270. + else {
  50271. + state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
  50272. + state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
  50273. + state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
  50274. + state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
  50275. + state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
  50276. + state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
  50277. + state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
  50278. + }
  50279. + }
  50280. + return 1;
  50281. +}
  50282. +
  50283. +static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
  50284. {
  50285. unsigned int pa_dwr_mask, pa_dwr_set;
  50286. int ret;
  50287. @@ -54,10 +182,11 @@
  50288. switch (conf->vcc) {
  50289. default:
  50290. - case 0: pa_dwr_set = 0; break;
  50291. + case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
  50292. case 33: pa_dwr_set = GPIO_GPIO2; break;
  50293. case 50: pa_dwr_set = GPIO_GPIO3; break;
  50294. }
  50295. + break;
  50296. default:
  50297. return -1;
  50298. @@ -83,8 +212,8 @@
  50299. struct pcmcia_low_level adsbitsy_pcmcia_ops = {
  50300. init: adsbitsy_pcmcia_init,
  50301. - shutdown: sa1111_pcmcia_shutdown,
  50302. - socket_state: sa1111_pcmcia_socket_state,
  50303. + shutdown: adsbitsy_pcmcia_shutdown,
  50304. + socket_state: adsbitsy_pcmcia_socket_state,
  50305. get_irq_info: sa1111_pcmcia_get_irq_info,
  50306. configure_socket: adsbitsy_pcmcia_configure_socket,
  50307. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_adsbitsyplus.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_adsbitsyplus.c
  50308. --- linux-2.4.26/drivers/pcmcia/sa1100_adsbitsyplus.c 1970-01-01 01:00:00.000000000 +0100
  50309. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_adsbitsyplus.c 2004-01-14 21:32:26.000000000 +0000
  50310. @@ -0,0 +1,236 @@
  50311. +/*
  50312. + * drivers/pcmcia/sa1100_adsbitsyplus.c
  50313. + *
  50314. + * PCMCIA implementation routines for ADS Bitsy Plus
  50315. + *
  50316. + * Created Feb 7, 2003 by Robert Whaley <rwhaley@applieddata.net>
  50317. + *
  50318. + * This file comes from sa1100_adsbitsy.c of Woojung Huh <whuh@applieddata.net>
  50319. + *
  50320. + */
  50321. +#include <linux/kernel.h>
  50322. +#include <linux/sched.h>
  50323. +#include <linux/ioport.h>
  50324. +
  50325. +#include <asm/hardware.h>
  50326. +#include <asm/hardware/sa1111.h>
  50327. +#include <asm/irq.h>
  50328. +
  50329. +#include "sa1100_generic.h"
  50330. +#include "sa1111_generic.h"
  50331. +
  50332. +int adsbitsy_smc91111_present(void);
  50333. +
  50334. +#ifndef CONFIG_SMC91111
  50335. +#define adsbitsy_smc91111_present() 0
  50336. +#endif
  50337. +
  50338. +static struct irqs {
  50339. + int irq;
  50340. + const char *str;
  50341. +} irqs[] = {
  50342. + { S0_CD_VALID, "SA1111 PCMCIA card detect" },
  50343. + { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
  50344. + { S1_CD_VALID, "SA1111 CF card detect" },
  50345. + { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
  50346. +};
  50347. +
  50348. +#define sock0_3_3_reverse_logic() ((ADS_CPLD_IO2 & ADS_IO2_CPLD_REV_MASK) >= ADS_IO2_CPLD_REV_5_MAGIC)
  50349. +
  50350. +static int adsbitsyplus_pcmcia_init(struct pcmcia_init *init)
  50351. +{
  50352. + int ret=0;
  50353. + int nirq = 0;
  50354. + int slots = 0;
  50355. + int i;
  50356. +
  50357. + /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
  50358. + PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
  50359. +
  50360. + /* Disable Power 3.3V/5V for PCMCIA */
  50361. + if (sock0_3_3_reverse_logic())
  50362. + PA_DWR = (PA_DWR & ~GPIO_GPIO0) | GPIO_GPIO1;
  50363. + else
  50364. + PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
  50365. +
  50366. + if (!request_mem_region(_PCCR, 512, "PCMCIA"))
  50367. + return -1;
  50368. +
  50369. +
  50370. + INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
  50371. + SA1111_IRQMASK_HI(S0_CD_VALID) |
  50372. + SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
  50373. +
  50374. + nirq = 2;
  50375. + slots = 1;
  50376. +
  50377. + if (!adsbitsy_smc91111_present()) {
  50378. + /* If the SMC91111 is used CF cannot be used */
  50379. + /* Set GPIO_A<3:2> to be outputs for CF power controller: */
  50380. + PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
  50381. +
  50382. + /* Disable Power 3.3V/5V for CF */
  50383. + PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
  50384. +
  50385. + INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
  50386. + SA1111_IRQMASK_HI(S1_CD_VALID) |
  50387. + SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
  50388. +
  50389. + nirq = 4;
  50390. + slots = 2;
  50391. + }
  50392. +
  50393. + for (i = ret = 0; i < nirq; i++) {
  50394. + ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
  50395. + irqs[i].str, NULL);
  50396. + if (ret)
  50397. + break;
  50398. + }
  50399. +
  50400. + if (i < nirq) {
  50401. + printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
  50402. + irqs[i].irq, ret);
  50403. + while (i--)
  50404. + free_irq(irqs[i].irq, NULL);
  50405. +
  50406. + release_mem_region(_PCCR, 16);
  50407. + }
  50408. +
  50409. + return ret ? -1 : slots;
  50410. +}
  50411. +
  50412. +static int adsbitsyplus_pcmcia_shutdown(void)
  50413. +{
  50414. +
  50415. + free_irq(S0_CD_VALID, NULL);
  50416. + free_irq(S0_BVD1_STSCHG, NULL);
  50417. + INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
  50418. +
  50419. + if (!adsbitsy_smc91111_present()) {
  50420. + free_irq(S1_CD_VALID, NULL);
  50421. + free_irq(S1_BVD1_STSCHG, NULL);
  50422. + INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
  50423. + }
  50424. +
  50425. + return 0;
  50426. +}
  50427. +
  50428. +
  50429. +static int adsbitsyplus_pcmcia_socket_state(struct pcmcia_state_array *state)
  50430. +{
  50431. + unsigned long status;
  50432. +
  50433. + if (adsbitsy_smc91111_present()) {
  50434. + if(state->size<1) return -1;
  50435. + }
  50436. + else
  50437. + if(state->size<2) return -1;
  50438. +
  50439. + memset(state->state, 0,
  50440. + (state->size)*sizeof(struct pcmcia_state));
  50441. +
  50442. + status = PCSR;
  50443. +
  50444. + state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
  50445. + state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
  50446. + state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
  50447. + state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
  50448. + state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
  50449. + state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
  50450. + state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
  50451. +
  50452. + if (state->size > 1) {
  50453. + if (adsbitsy_smc91111_present()) {
  50454. + // If there is SMC91111 on ADS Bitsy connector board
  50455. + // it returns not detect/ready/...
  50456. + state->state[1].detect = 0;
  50457. + state->state[1].ready = 0;
  50458. + state->state[1].bvd1 = 0;
  50459. + state->state[1].bvd2 = 0;
  50460. + state->state[1].wrprot = 0;
  50461. + state->state[1].vs_3v = 0;
  50462. + state->state[1].vs_Xv = 0;
  50463. + }
  50464. + else {
  50465. + state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
  50466. + state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
  50467. + state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
  50468. + state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
  50469. + state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
  50470. + state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
  50471. + state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
  50472. + }
  50473. + }
  50474. + return 1;
  50475. +}
  50476. +
  50477. +static int adsbitsyplus_pcmcia_configure_socket(const struct pcmcia_configure *conf)
  50478. +{
  50479. + unsigned int pa_dwr_mask, pa_dwr_set;
  50480. + int ret;
  50481. +
  50482. + switch (conf->sock) {
  50483. + case 0:
  50484. + pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
  50485. +
  50486. + if (sock0_3_3_reverse_logic()) {
  50487. + switch (conf->vcc) {
  50488. + default:
  50489. + case 0: pa_dwr_set = GPIO_GPIO1; break;
  50490. + case 33: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
  50491. + case 50: pa_dwr_set = 0; break;
  50492. + }
  50493. + } else {
  50494. + switch (conf->vcc) {
  50495. + default:
  50496. + case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
  50497. + case 33: pa_dwr_set = GPIO_GPIO1; break;
  50498. + case 50: pa_dwr_set = GPIO_GPIO0; break;
  50499. + }
  50500. + }
  50501. + break;
  50502. +
  50503. + case 1:
  50504. + pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
  50505. +
  50506. + switch (conf->vcc) {
  50507. + default:
  50508. + case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
  50509. + case 33: pa_dwr_set = GPIO_GPIO2; break;
  50510. + case 50: pa_dwr_set = GPIO_GPIO3; break;
  50511. + }
  50512. + break;
  50513. +
  50514. + default:
  50515. + return -1;
  50516. + }
  50517. +
  50518. + if (conf->vpp != conf->vcc && conf->vpp != 0) {
  50519. + printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
  50520. + __FUNCTION__, conf->vpp);
  50521. + return -1;
  50522. + }
  50523. +
  50524. + ret = sa1111_pcmcia_configure_socket(conf);
  50525. + if (ret == 0) {
  50526. + unsigned long flags;
  50527. +
  50528. + local_irq_save(flags);
  50529. + PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
  50530. + local_irq_restore(flags);
  50531. + }
  50532. +
  50533. + return ret;
  50534. +}
  50535. +
  50536. +struct pcmcia_low_level adsbitsyplus_pcmcia_ops = {
  50537. + init: adsbitsyplus_pcmcia_init,
  50538. + shutdown: adsbitsyplus_pcmcia_shutdown,
  50539. + socket_state: adsbitsyplus_pcmcia_socket_state,
  50540. + get_irq_info: sa1111_pcmcia_get_irq_info,
  50541. + configure_socket: adsbitsyplus_pcmcia_configure_socket,
  50542. +
  50543. + socket_init: sa1111_pcmcia_socket_init,
  50544. + socket_suspend: sa1111_pcmcia_socket_suspend,
  50545. +};
  50546. +
  50547. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_freebird.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_freebird.c
  50548. --- linux-2.4.26/drivers/pcmcia/sa1100_freebird.c 2002-08-03 01:39:44.000000000 +0100
  50549. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_freebird.c 2004-01-14 21:32:26.000000000 +0000
  50550. @@ -67,9 +67,6 @@
  50551. if(state_array->size<2) return -1;
  50552. - memset(state_array->state, 0,
  50553. - (state_array->size)*sizeof(struct pcmcia_state));
  50554. -
  50555. levels = LINKUP_PRS;
  50556. //printk("LINKUP_PRS=%x \n",levels);
  50557. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_generic.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_generic.c
  50558. --- linux-2.4.26/drivers/pcmcia/sa1100_generic.c 2003-06-13 15:51:35.000000000 +0100
  50559. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_generic.c 2004-01-14 21:32:26.000000000 +0000
  50560. @@ -992,10 +992,18 @@
  50561. if(machine_is_graphicsmaster())
  50562. pcmcia_low_level = &graphicsmaster_pcmcia_ops;
  50563. #endif
  50564. +#ifdef CONFIG_SA1100_ADSAGC
  50565. + if(machine_is_adsagc())
  50566. + pcmcia_low_level = &graphicsmaster_pcmcia_ops;
  50567. +#endif
  50568. #ifdef CONFIG_SA1100_ADSBITSY
  50569. if(machine_is_adsbitsy())
  50570. pcmcia_low_level = &adsbitsy_pcmcia_ops;
  50571. #endif
  50572. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  50573. + if(machine_is_adsbitsyplus())
  50574. + pcmcia_low_level = &adsbitsyplus_pcmcia_ops;
  50575. +#endif
  50576. #ifdef CONFIG_SA1100_STORK
  50577. if(machine_is_stork())
  50578. pcmcia_low_level = &stork_pcmcia_ops;
  50579. @@ -1067,7 +1075,7 @@
  50580. * We initialize the MECR to default values here, because we are
  50581. * not guaranteed to see a SetIOMap operation at runtime.
  50582. */
  50583. - mecr = 0;
  50584. + mecr = MECR;
  50585. clock = cpufreq_get(0);
  50586. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_graphicsclient.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_graphicsclient.c
  50587. --- linux-2.4.26/drivers/pcmcia/sa1100_graphicsclient.c 2002-08-03 01:39:44.000000000 +0100
  50588. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_graphicsclient.c 2004-01-14 21:32:26.000000000 +0000
  50589. @@ -3,6 +3,8 @@
  50590. *
  50591. * PCMCIA implementation routines for Graphics Client Plus
  50592. *
  50593. + * Nov/14/01 Woojung
  50594. + * Set MECR at initializing time
  50595. * 9/12/01 Woojung
  50596. * Turn power OFF at startup
  50597. * 1/31/2001 Woojung Huh
  50598. @@ -19,11 +21,6 @@
  50599. #include <asm/irq.h>
  50600. #include "sa1100_generic.h"
  50601. -#error This is broken!
  50602. -
  50603. -#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
  50604. -#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
  50605. -
  50606. static volatile unsigned long *PCMCIA_Status =
  50607. ((volatile unsigned long *) ADS_p2v(_ADS_CS_STATUS));
  50608. @@ -46,20 +43,23 @@
  50609. *PCMCIA_Power &= ~0x03;
  50610. /* Register interrupts */
  50611. - irq = S0_CD_IRQ;
  50612. + irq = IRQ_GRAPHICSCLIENT_S0_CD;
  50613. res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
  50614. if (res < 0) {
  50615. - printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
  50616. + printk(KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq);
  50617. return -1;
  50618. }
  50619. + // Nov/14/01 WH
  50620. + MECR = 0x00000943;
  50621. +
  50622. return 1; // 1 PCMCIA Slot
  50623. }
  50624. static int gcplus_pcmcia_shutdown(void)
  50625. {
  50626. /* disable IRQs */
  50627. - free_irq( S0_CD_IRQ, NULL);
  50628. + free_irq( IRQ_GRAPHICSCLIENT_S0_CD, NULL);
  50629. /* Shutdown PCMCIA power */
  50630. mdelay(2); // 2msec
  50631. @@ -74,9 +74,6 @@
  50632. if(state_array->size<1) return -1;
  50633. - memset(state_array->state, 0,
  50634. - (state_array->size)*sizeof(struct pcmcia_state));
  50635. -
  50636. levels=*PCMCIA_Status;
  50637. state_array->state[0].detect=(levels & ADS_CS_ST_A_CD)?1:0;
  50638. @@ -96,7 +93,7 @@
  50639. return -1;
  50640. if (info->sock == 0)
  50641. - info->irq = S0_STS_IRQ;
  50642. + info->irq = IRQ_GRAPHICSCLIENT_S0_STS;
  50643. return 0;
  50644. }
  50645. @@ -143,6 +140,11 @@
  50646. restore_flags(flags);
  50647. + if (configure->irq)
  50648. + enable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
  50649. + else
  50650. + disable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
  50651. +
  50652. return 0;
  50653. }
  50654. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_graphicsmaster.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_graphicsmaster.c
  50655. --- linux-2.4.26/drivers/pcmcia/sa1100_graphicsmaster.c 2002-08-03 01:39:44.000000000 +0100
  50656. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_graphicsmaster.c 2004-01-14 21:32:26.000000000 +0000
  50657. @@ -12,13 +12,13 @@
  50658. #include <linux/sched.h>
  50659. #include <asm/hardware.h>
  50660. +#include <asm/hardware/sa1111.h>
  50661. #include "sa1100_generic.h"
  50662. #include "sa1111_generic.h"
  50663. static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
  50664. {
  50665. - int return_val=0;
  50666. /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
  50667. PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
  50668. @@ -26,9 +26,6 @@
  50669. /* Disable Power 3.3V/5V for PCMCIA/CF */
  50670. PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
  50671. - /* why? */
  50672. - MECR = 0x09430943;
  50673. -
  50674. return sa1111_pcmcia_init(init);
  50675. }
  50676. @@ -59,6 +56,10 @@
  50677. case 33: pa_dwr_set = GPIO_GPIO3; break;
  50678. case 50: pa_dwr_set = GPIO_GPIO2; break;
  50679. }
  50680. + break;
  50681. +
  50682. + default:
  50683. + return -1;
  50684. }
  50685. if (conf->vpp != conf->vcc && conf->vpp != 0) {
  50686. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_h3600.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_h3600.c
  50687. --- linux-2.4.26/drivers/pcmcia/sa1100_h3600.c 2002-08-03 01:39:44.000000000 +0100
  50688. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_h3600.c 2004-01-14 21:32:26.000000000 +0000
  50689. @@ -29,6 +29,9 @@
  50690. set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_IRQ0 | GPIO_H3600_PCMCIA_IRQ1,
  50691. GPIO_FALLING_EDGE);
  50692. + set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1,
  50693. + GPIO_NO_EDGES);
  50694. +
  50695. /*
  50696. * Register interrupts
  50697. */
  50698. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_jornada720.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_jornada720.c
  50699. --- linux-2.4.26/drivers/pcmcia/sa1100_jornada720.c 2002-08-03 01:39:44.000000000 +0100
  50700. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_jornada720.c 2004-01-14 21:32:26.000000000 +0000
  50701. @@ -8,6 +8,7 @@
  50702. #include <linux/sched.h>
  50703. #include <asm/hardware.h>
  50704. +#include <asm/hardware/sa1111.h>
  50705. #include "sa1100_generic.h"
  50706. #include "sa1111_generic.h"
  50707. @@ -88,7 +89,7 @@
  50708. local_irq_save(flags);
  50709. PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
  50710. - locla_irq_restore(flags);
  50711. + local_irq_restore(flags);
  50712. }
  50713. return ret;
  50714. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_pangolin.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_pangolin.c
  50715. --- linux-2.4.26/drivers/pcmcia/sa1100_pangolin.c 2002-08-03 01:39:44.000000000 +0100
  50716. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_pangolin.c 2004-01-14 21:32:26.000000000 +0000
  50717. @@ -53,9 +53,6 @@
  50718. if(state_array->size<2) return -1;
  50719. - memset(state_array->state, 0,
  50720. - (state_array->size)*sizeof(struct pcmcia_state));
  50721. -
  50722. levels=GPLR;
  50723. #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
  50724. state_array->state[1].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
  50725. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_shannon.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_shannon.c
  50726. --- linux-2.4.26/drivers/pcmcia/sa1100_shannon.c 2002-08-03 01:39:44.000000000 +0100
  50727. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_shannon.c 2004-01-14 21:32:26.000000000 +0000
  50728. @@ -53,9 +53,6 @@
  50729. {
  50730. unsigned long levels;
  50731. - memset(state_array->state, 0,
  50732. - state_array->size * sizeof(struct pcmcia_state));
  50733. -
  50734. levels = GPLR;
  50735. state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
  50736. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_simpad.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_simpad.c
  50737. --- linux-2.4.26/drivers/pcmcia/sa1100_simpad.c 2002-08-03 01:39:44.000000000 +0100
  50738. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_simpad.c 2004-01-14 21:32:26.000000000 +0000
  50739. @@ -63,9 +63,6 @@
  50740. if(state_array->size<2) return -1;
  50741. - memset(state_array->state, 0,
  50742. - (state_array->size)*sizeof(struct pcmcia_state));
  50743. -
  50744. levels=GPLR;
  50745. state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
  50746. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_stork.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_stork.c
  50747. --- linux-2.4.26/drivers/pcmcia/sa1100_stork.c 2004-02-27 20:03:27.000000000 +0000
  50748. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_stork.c 2004-02-23 13:36:32.000000000 +0000
  50749. @@ -79,9 +79,6 @@
  50750. if(state_array->size<2) return -1;
  50751. - memset(state_array->state, 0,
  50752. - (state_array->size)*sizeof(struct pcmcia_state));
  50753. -
  50754. levels=GPLR;
  50755. if (debug > 1)
  50756. diff -urN linux-2.4.26/drivers/pcmcia/sa1100_yopy.c linux-2.4.26-vrs1/drivers/pcmcia/sa1100_yopy.c
  50757. --- linux-2.4.26/drivers/pcmcia/sa1100_yopy.c 2002-08-03 01:39:44.000000000 +0100
  50758. +++ linux-2.4.26-vrs1/drivers/pcmcia/sa1100_yopy.c 2004-01-14 21:32:26.000000000 +0000
  50759. @@ -73,9 +73,6 @@
  50760. if (state_array->size != 1)
  50761. return -1;
  50762. - memset(state_array->state, 0,
  50763. - state_array->size * sizeof(struct pcmcia_state));
  50764. -
  50765. levels = GPLR;
  50766. state_array->state[0].detect = (levels & GPIO_CF_CD) ? 0 : 1;
  50767. diff -urN linux-2.4.26/drivers/pld/Makefile linux-2.4.26-vrs1/drivers/pld/Makefile
  50768. --- linux-2.4.26/drivers/pld/Makefile 1970-01-01 01:00:00.000000000 +0100
  50769. +++ linux-2.4.26-vrs1/drivers/pld/Makefile 2004-01-14 21:32:26.000000000 +0000
  50770. @@ -0,0 +1,28 @@
  50771. +#
  50772. +# Makefile for the kernel pld device drivers.
  50773. +#
  50774. +# Note! Dependencies are done automagically by 'make dep', which also
  50775. +# removes any old dependencies. DON'T put your own dependencies here
  50776. +# unless it's something special (ie not a .c file).
  50777. +#
  50778. +# Note 2! The CFLAGS definitions are now inherited from the
  50779. +# parent makes..
  50780. +#
  50781. +# $Id: $
  50782. +#
  50783. +
  50784. +O_TARGET := pld.o
  50785. +
  50786. +export-objs := pld_hotswap.o
  50787. +obj-y :=
  50788. +obj-m :=
  50789. +obj-n :=
  50790. +obj- :=
  50791. +
  50792. +obj-$(CONFIG_PLD) += pld_epxa.o
  50793. +obj-$(CONFIG_PLD_HOTSWAP) += pld_hotswap.o
  50794. +
  50795. +include $(TOPDIR)/Rules.make
  50796. +
  50797. +fastdep:
  50798. +
  50799. diff -urN linux-2.4.26/drivers/pld/pld_epxa.c linux-2.4.26-vrs1/drivers/pld/pld_epxa.c
  50800. --- linux-2.4.26/drivers/pld/pld_epxa.c 1970-01-01 01:00:00.000000000 +0100
  50801. +++ linux-2.4.26-vrs1/drivers/pld/pld_epxa.c 2004-01-14 21:32:26.000000000 +0000
  50802. @@ -0,0 +1,375 @@
  50803. +
  50804. +/*
  50805. + * drivers/char/epxapld.c
  50806. + *
  50807. + * Copyright (C) 2001 Altera Corporation
  50808. + *
  50809. + * This program is free software; you can redistribute it and/or modify
  50810. + * it under the terms of the GNU General Public License as published by
  50811. + * the Free Software Foundation; either version 2 of the License, or
  50812. + * (at your option) any later version.
  50813. + *
  50814. + * This program is distributed in the hope that it will be useful,
  50815. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  50816. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  50817. + * GNU General Public License for more details.
  50818. + *
  50819. + * You should have received a copy of the GNU General Public License
  50820. + * along with this program; if not, write to the Free Software
  50821. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  50822. + */
  50823. +
  50824. +#include <linux/config.h>
  50825. +#include <linux/errno.h>
  50826. +#include <linux/fs.h>
  50827. +#include <linux/slab.h>
  50828. +#include <linux/ioport.h>
  50829. +#include <linux/init.h>
  50830. +#include <linux/errno.h>
  50831. +#include <linux/module.h>
  50832. +#include <asm/io.h>
  50833. +#include <asm/uaccess.h>
  50834. +#include <asm/arch/excalibur.h>
  50835. +#include <asm/arch/hardware.h>
  50836. +#define PLD_CONF00_TYPE (volatile unsigned int *)
  50837. +#define MODE_CTRL00_TYPE (volatile unsigned int *)
  50838. +//#define DEBUG(x) x
  50839. +#define DEBUG(x)
  50840. +
  50841. +#include <asm/arch/mode_ctrl00.h>
  50842. +#include <asm/arch/pld_conf00.h>
  50843. +#ifdef CONFIG_PLD_HOTSWAP
  50844. +#include <linux/pld/pld_hotswap.h>
  50845. +#endif
  50846. +#include <linux/pld/pld_epxa.h>
  50847. +
  50848. +/*
  50849. + * Macros
  50850. + */
  50851. +
  50852. +
  50853. +#define PLD_BASE (IO_ADDRESS(EXC_PLD_CONFIG00_BASE))
  50854. +#define CLOCK_DIV_RATIO ((1 + EXC_AHB2_CLK_FREQUENCY/32000000) & CONFIG_CONTROL_CLOCK_RATIO_MSK)
  50855. +/*
  50856. + * STRUCTURES
  50857. + */
  50858. +
  50859. +
  50860. +struct pld_sbihdr{
  50861. + unsigned int fpos;
  50862. + unsigned int temp;
  50863. +};
  50864. +
  50865. +static DECLARE_MUTEX(pld_sem);
  50866. +
  50867. +
  50868. +static void lock_pld (void)
  50869. +{
  50870. + /* Lock the pld i/f */
  50871. + unsigned int tmp;
  50872. +
  50873. + tmp = readl(CONFIG_CONTROL(PLD_BASE));
  50874. + tmp |= CONFIG_CONTROL_LK_MSK;
  50875. +
  50876. + writel(tmp,CONFIG_CONTROL(PLD_BASE));
  50877. +}
  50878. +
  50879. +static void unlock_excalibur_pld (void)
  50880. +{
  50881. + /* Unlock the pld i/f */
  50882. +
  50883. + if (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK ){
  50884. + writel(CONFIG_UNLOCK_MAGIC, CONFIG_UNLOCK(PLD_BASE));
  50885. + while (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK);
  50886. + }
  50887. +}
  50888. +
  50889. +
  50890. +static int place_pld_into_configure_mode (void)
  50891. +{
  50892. + unsigned int tmp;
  50893. +
  50894. +
  50895. + if( readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK ){
  50896. + /*
  50897. + * Already being configured!!!
  50898. + */
  50899. + printk(KERN_WARNING "pld0: Device already being configured!\n");
  50900. + return -EBUSY;
  50901. + }
  50902. +
  50903. + /* Set up the config clock */
  50904. +
  50905. + writel(CLOCK_DIV_RATIO,CONFIG_CONTROL_CLOCK(PLD_BASE));
  50906. + while(readl(CONFIG_CONTROL_CLOCK(PLD_BASE))
  50907. + !=CLOCK_DIV_RATIO);
  50908. + /* Tell the device we wish to configure it */
  50909. + tmp = readl(CONFIG_CONTROL(PLD_BASE));
  50910. + tmp |= CONFIG_CONTROL_CO_MSK;
  50911. + writel(tmp,CONFIG_CONTROL(PLD_BASE));
  50912. +
  50913. +
  50914. + /*
  50915. + * Wait for the busy bit to clear then check for errors.
  50916. + */
  50917. +
  50918. + while((tmp=readl(CONFIG_CONTROL(PLD_BASE))&CONFIG_CONTROL_B_MSK ));
  50919. +
  50920. + if ( tmp & CONFIG_CONTROL_E_MSK ){
  50921. + if ( tmp & CONFIG_CONTROL_ES_0_MSK ){
  50922. + /* Already being programmed via JTAG */
  50923. + printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
  50924. + return -EBUSY;
  50925. +
  50926. + }
  50927. + if ( tmp & CONFIG_CONTROL_ES_1_MSK ){
  50928. + /* No config clock configured */
  50929. + printk(KERN_ERR "pld0:No config clock!\n");
  50930. + BUG();
  50931. + return -EBUSY;
  50932. + }
  50933. + if ( tmp & CONFIG_CONTROL_ES_2_MSK ){
  50934. + /* Already being programmed via External device */
  50935. + printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
  50936. + return -EBUSY;
  50937. + }
  50938. + }
  50939. +
  50940. + return 0;
  50941. +}
  50942. +
  50943. +
  50944. +static int write_pld_data_word(unsigned int config_data)
  50945. +{
  50946. + unsigned int tmp;
  50947. +
  50948. + do{
  50949. + tmp = readl(CONFIG_CONTROL(PLD_BASE));
  50950. + }
  50951. + while ( ( tmp & CONFIG_CONTROL_B_MSK ) &&
  50952. + !( tmp & CONFIG_CONTROL_E_MSK ));
  50953. +
  50954. + if ( tmp & CONFIG_CONTROL_E_MSK ){
  50955. + printk("pld0: Error writing pld data, CONFIG_CONTROL=%#x\n",tmp);
  50956. +
  50957. + return -EILSEQ;
  50958. + }
  50959. +
  50960. + writel(config_data,CONFIG_CONTROL_DATA(PLD_BASE));
  50961. + return 0;
  50962. +
  50963. +}
  50964. +
  50965. +
  50966. +static int wait_for_device_to_configure (void)
  50967. +{
  50968. + int i=0x10000;
  50969. +
  50970. + while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
  50971. +
  50972. + /*
  50973. + * Wait for the config bit (CO) to go low, indicating that everything
  50974. + * is Ok. If it doesn't, assume that is screwed up somehow and
  50975. + * clear the CO bit to abort the configuration.
  50976. + */
  50977. +
  50978. + while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
  50979. +
  50980. + while (i&&(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK)){
  50981. + i--;
  50982. + }
  50983. +
  50984. + if (!i){
  50985. + writel(0,CONFIG_CONTROL(PLD_BASE));
  50986. + printk(KERN_WARNING "pld0: Invalid PLD config data\n");
  50987. + return -EILSEQ;
  50988. + }
  50989. +
  50990. + return 0;
  50991. +}
  50992. +
  50993. +
  50994. +
  50995. +static int pld_open(struct inode* inode, struct file *filep)
  50996. +{
  50997. +
  50998. + struct pld_sbihdr* sbihdr;
  50999. +
  51000. + /* Check the device minor number */
  51001. + if(minor(inode->i_rdev)){
  51002. + DEBUG(printk("pld0: minor=%d",minor(inode->i_rdev));)
  51003. + return -ENODEV;
  51004. + }
  51005. +
  51006. + /* Create our private data and link it to the file structure */
  51007. + sbihdr=kmalloc(sizeof(struct pld_sbihdr),GFP_KERNEL);
  51008. +
  51009. + if(!sbihdr)
  51010. + return -ENOMEM;
  51011. +
  51012. + filep->private_data=sbihdr;
  51013. +
  51014. + sbihdr->fpos=0;
  51015. + sbihdr->temp=0;
  51016. + return 0;
  51017. +}
  51018. +
  51019. +static int pld_release(struct inode* inode, struct file *filep){
  51020. + int ret_code;
  51021. +
  51022. + kfree(filep->private_data);
  51023. + ret_code=wait_for_device_to_configure();
  51024. + lock_pld();
  51025. + return ret_code;
  51026. +}
  51027. +
  51028. +static ssize_t pld_write(struct file* filep, const char* data, size_t count, loff_t* ppos){
  51029. +
  51030. + struct pld_sbihdr* sbihdr=filep->private_data;
  51031. + int bytes_left=count;
  51032. + int result;
  51033. + DEBUG(int i=0);
  51034. +
  51035. +
  51036. + /* Can't seek (pwrite) on pld. */
  51037. + if (ppos != &filep->f_pos)
  51038. + return -ESPIPE;
  51039. +
  51040. +
  51041. + /* Check access to the whole are in one go */
  51042. + if(!access_ok(VERIFY_READ,(const void*)data, count)){
  51043. + return -EFAULT;
  51044. + }
  51045. +
  51046. + /*
  51047. + * We now lock against writes.
  51048. + */
  51049. + if (down_interruptible(&pld_sem))
  51050. + return -ERESTARTSYS;
  51051. +
  51052. + if(!sbihdr->fpos){
  51053. + /*
  51054. + * unlock the pld and place in configure mode
  51055. + */
  51056. + unlock_excalibur_pld();
  51057. + result=place_pld_into_configure_mode();
  51058. + if(result)
  51059. + return result;
  51060. + }
  51061. + DEBUG(printk("data= %#x count=%#x 0ffset=%#x\n",*data, count, *ppos));
  51062. +
  51063. + while(bytes_left){
  51064. + char tmp;
  51065. + __get_user(tmp,data);
  51066. + /* read our header ! */
  51067. + sbihdr->temp|=tmp << (8*(sbihdr->fpos&3));
  51068. + if((sbihdr->fpos&3)==3){
  51069. + if(write_pld_data_word(sbihdr->temp))
  51070. + {
  51071. + DEBUG(printk("pos=%d\n",sbihdr->fpos);)
  51072. + return -EILSEQ;
  51073. + }
  51074. + DEBUG(if(i<10){)
  51075. + DEBUG(printk("fpos2 :%#x data=%#x\n",sbihdr->fpos,sbihdr->temp));
  51076. + DEBUG(i++);
  51077. + DEBUG(});
  51078. + sbihdr->temp=0;
  51079. + DEBUG(words_written++);
  51080. + }
  51081. + sbihdr->fpos++;
  51082. + data++;
  51083. + bytes_left--;
  51084. + }
  51085. +
  51086. + up(&pld_sem);
  51087. + return (count);
  51088. +}
  51089. +
  51090. +int pld_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
  51091. +{
  51092. +
  51093. + switch(cmd){
  51094. +
  51095. +#ifdef CONFIG_PLD_HOTSWAP
  51096. + case PLD_IOC_ADD_PLD_DEV:
  51097. + {
  51098. + struct pldhs_dev_desc desc;
  51099. + struct pldhs_dev_info info;
  51100. + char *name;
  51101. + void *data;
  51102. + int result=0;
  51103. +
  51104. + result=copy_from_user(&desc,(const void*)arg,sizeof(struct pldhs_dev_desc));
  51105. + if(result)
  51106. + return -EFAULT;
  51107. + result=copy_from_user(&info,(const void*)desc.info,sizeof(struct pldhs_dev_info));
  51108. + if(result)
  51109. + return -EFAULT;
  51110. + name=kmalloc(info.nsize,GFP_KERNEL);
  51111. + if(!name)
  51112. + return -ENOMEM;
  51113. +
  51114. + result=copy_from_user(name,(const void*)desc.name,info.nsize);
  51115. + if(result){
  51116. + result=-EFAULT;
  51117. + goto ioctl_out;
  51118. + }
  51119. +
  51120. + data=kmalloc(info.pssize,GFP_KERNEL);
  51121. + if(!data){
  51122. + result=-ENOMEM;
  51123. + goto ioctl_out;
  51124. + }
  51125. +
  51126. + result=copy_from_user(data,(const void*)desc.data,info.pssize);
  51127. + if(result){
  51128. + result=-EFAULT;
  51129. + goto ioctl_out1;
  51130. + }
  51131. + result=pldhs_add_device(&info,name,data);
  51132. +
  51133. + ioctl_out1:
  51134. + kfree(data);
  51135. + ioctl_out:
  51136. + kfree(name);
  51137. + return result;
  51138. +
  51139. + }
  51140. +
  51141. + case PLD_IOC_REMOVE_PLD_DEVS:
  51142. + pldhs_remove_devices();
  51143. + return 0;
  51144. +
  51145. + case PLD_IOC_SET_INT_MODE:
  51146. + if(cmd==3){
  51147. + printk(KERN_INFO "Interrupt mode set to 3 (Six individual interrupts)\n");
  51148. + return 0;
  51149. + }else{
  51150. + printk(KERN_INFO "There is no interrupt handler available for this mode (%d). You will need to add one\n to implement whatever scheme you require\n");
  51151. + return -EACCES;
  51152. + }
  51153. +#endif
  51154. + default:
  51155. + return -ENOTTY;
  51156. + }
  51157. +}
  51158. +
  51159. +
  51160. +static struct file_operations pld_fops={
  51161. + write: pld_write,
  51162. + ioctl: pld_ioctl,
  51163. + open: pld_open,
  51164. + release: pld_release
  51165. +};
  51166. +
  51167. +static int __init pld_init(void){
  51168. + int major;
  51169. + major=register_chrdev(0,"pld",&pld_fops);
  51170. + printk(KERN_INFO "Using PLD major num=%d\n",major);
  51171. + if (major<0){
  51172. + return major;
  51173. + }
  51174. + return 0;
  51175. +}
  51176. +
  51177. +__initcall(pld_init);
  51178. diff -urN linux-2.4.26/drivers/pld/pld_hotswap.c linux-2.4.26-vrs1/drivers/pld/pld_hotswap.c
  51179. --- linux-2.4.26/drivers/pld/pld_hotswap.c 1970-01-01 01:00:00.000000000 +0100
  51180. +++ linux-2.4.26-vrs1/drivers/pld/pld_hotswap.c 2004-01-14 21:32:26.000000000 +0000
  51181. @@ -0,0 +1,188 @@
  51182. +/*
  51183. + * linux/drivers/pld/pld_hotswap.c
  51184. + *
  51185. + * Pld driver for Altera EPXA Excalibur devices
  51186. + *
  51187. + *
  51188. + * Copyright 2001 Altera Corporation (cdavies@altera.com)
  51189. + *
  51190. + * This program is free software; you can redistribute it and/or modify
  51191. + * it under the terms of the GNU General Public License as published by
  51192. + * the Free Software Foundation; either version 2 of the License, or
  51193. + * (at your option) any later version.
  51194. + *
  51195. + * This program is distributed in the hope that it will be useful,
  51196. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  51197. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  51198. + * GNU General Public License for more details.
  51199. + *
  51200. + * You should have received a copy of the GNU General Public License
  51201. + * along with this program; if not, write to the Free Software
  51202. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  51203. + *
  51204. + * $Id: $
  51205. + *
  51206. + */
  51207. +
  51208. +/*
  51209. + * pld_hotswap ops contains the basic operation required for adding
  51210. + * and removing devices from the system.
  51211. + */
  51212. +
  51213. +#include <linux/config.h>
  51214. +#include <linux/module.h>
  51215. +#include <linux/kernel.h>
  51216. +#include <linux/types.h>
  51217. +#include <linux/pagemap.h>
  51218. +#include <linux/slab.h>
  51219. +#include <linux/smp_lock.h>
  51220. +#include <linux/init.h>
  51221. +#include <linux/kmod.h>
  51222. +#include <linux/proc_fs.h>
  51223. +#include <linux/list.h>
  51224. +#include <asm/uaccess.h>
  51225. +#include <linux/pld/pld_hotswap.h>
  51226. +
  51227. +
  51228. +static struct pld_hotswap_ops pldhs_driver_list={
  51229. + list: LIST_HEAD_INIT(pldhs_driver_list.list),
  51230. + name: "",
  51231. +};
  51232. +
  51233. +static spinlock_t list_lock=SPIN_LOCK_UNLOCKED;
  51234. +
  51235. +
  51236. +
  51237. +static struct pld_hotswap_ops * pldhs_find_driver(char* name)
  51238. +{
  51239. + struct pld_hotswap_ops * ptr;
  51240. + struct list_head *list_pos;
  51241. +
  51242. + spin_lock(&list_lock);
  51243. + list_for_each(list_pos,&pldhs_driver_list.list){
  51244. + ptr=(struct pld_hotswap_ops *)list_pos;
  51245. + if(!strcmp(name, ptr->name)){
  51246. + spin_unlock(&list_lock);
  51247. + return ptr;
  51248. +
  51249. + }
  51250. + }
  51251. + spin_unlock(&list_lock);
  51252. + return 0;
  51253. +}
  51254. +
  51255. +
  51256. +
  51257. +int pldhs_register_driver(struct pld_hotswap_ops *drv)
  51258. +{
  51259. +
  51260. + /* Check that the device is not already on the list
  51261. + * if so, do nothing */
  51262. + if(pldhs_find_driver(drv->name)){
  51263. + return 0;
  51264. + }
  51265. +
  51266. + printk(KERN_INFO "PLD: Registering hotswap driver %s\n",drv->name);
  51267. + /* Add this at the start of the list */
  51268. + spin_lock(&list_lock);
  51269. + list_add((struct list_head*)drv,&pldhs_driver_list.list);
  51270. + spin_unlock(&list_lock);
  51271. +
  51272. + return 0;
  51273. +}
  51274. +
  51275. +int pldhs_unregister_driver(char *name)
  51276. +{
  51277. + struct pld_hotswap_ops *ptr;
  51278. +
  51279. + ptr=pldhs_find_driver(name);
  51280. + if(!ptr){
  51281. + return -ENODEV;
  51282. + }
  51283. +
  51284. + printk(KERN_INFO "PLD: Unregistering hotswap driver%s\n",name);
  51285. + spin_lock(&list_lock);
  51286. + list_del((struct list_head*)ptr);
  51287. + spin_unlock(&list_lock);
  51288. +
  51289. + return 0;
  51290. +}
  51291. +
  51292. +int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data)
  51293. +{
  51294. + struct pld_hotswap_ops * ptr;
  51295. +
  51296. + ptr=pldhs_find_driver(drv_name);
  51297. +
  51298. + if(!ptr){
  51299. + /* try requesting this module*/
  51300. + request_module(drv_name);
  51301. + /* is the driver there now? */
  51302. + ptr=pldhs_find_driver(drv_name);
  51303. + if(!ptr){
  51304. + printk("pld hotswap: Failed to load a driver for %s\n",drv_name);
  51305. + return -ENODEV;
  51306. + }
  51307. + }
  51308. +
  51309. + if(!ptr->add_device){
  51310. + printk(KERN_WARNING "pldhs: no add_device() function for driver %s\n",drv_name);
  51311. + return 0;
  51312. + }
  51313. +
  51314. + return ptr->add_device(dev_info,dev_ps_data);
  51315. +}
  51316. +
  51317. +int pldhs_remove_devices(void)
  51318. +{
  51319. + struct list_head *list_pos;
  51320. + struct pld_hotswap_ops * ptr;
  51321. +
  51322. +
  51323. + spin_lock(&list_lock);
  51324. + list_for_each(list_pos,&pldhs_driver_list.list){
  51325. + ptr=(struct pld_hotswap_ops *)list_pos;
  51326. + if(ptr->remove_devices)
  51327. + ptr->remove_devices();
  51328. +
  51329. + }
  51330. + spin_unlock(&list_lock);
  51331. +
  51332. + return 0;
  51333. +}
  51334. +
  51335. +#ifdef CONFIG_PROC_FS
  51336. +int pldhs_read_proc(char* buf,char** start,off_t offset,int count,int *eof,void *data){
  51337. +
  51338. +
  51339. + struct list_head *list_pos;
  51340. + struct pld_hotswap_ops * ptr;
  51341. + int i,len=0;
  51342. +
  51343. + *start=buf;
  51344. + spin_lock(&list_lock);
  51345. + list_for_each(list_pos,&pldhs_driver_list.list){
  51346. + ptr=(struct pld_hotswap_ops *)list_pos;
  51347. + if(ptr->proc_read){
  51348. + i=ptr->proc_read(buf,start,offset,count,eof,data);
  51349. + count-=i;
  51350. + len+=i;
  51351. + *start+=i;
  51352. + }
  51353. + }
  51354. + spin_unlock(&list_lock);
  51355. +
  51356. + *start=NULL;
  51357. + *eof=1;
  51358. + return len;
  51359. +}
  51360. +
  51361. +void __init pldhs_init(void){
  51362. + create_proc_read_entry("pld",0,NULL,pldhs_read_proc,NULL);
  51363. +}
  51364. +
  51365. +__initcall(pldhs_init);
  51366. +#endif
  51367. +
  51368. +EXPORT_SYMBOL(pldhs_register_driver);
  51369. +EXPORT_SYMBOL(pldhs_unregister_driver);
  51370. diff -urN linux-2.4.26/drivers/scsi/Makefile linux-2.4.26-vrs1/drivers/scsi/Makefile
  51371. --- linux-2.4.26/drivers/scsi/Makefile 2004-02-27 20:03:27.000000000 +0000
  51372. +++ linux-2.4.26-vrs1/drivers/scsi/Makefile 2004-02-23 13:36:33.000000000 +0000
  51373. @@ -21,7 +21,7 @@
  51374. O_TARGET := scsidrv.o
  51375. -export-objs := scsi_syms.o 53c700.o
  51376. +export-objs := scsi_syms.o 53c700.o scsi_error.o
  51377. mod-subdirs := pcmcia ../acorn/scsi
  51378. diff -urN linux-2.4.26/drivers/scsi/scsi.c linux-2.4.26-vrs1/drivers/scsi/scsi.c
  51379. --- linux-2.4.26/drivers/scsi/scsi.c 2003-08-25 12:44:42.000000000 +0100
  51380. +++ linux-2.4.26-vrs1/drivers/scsi/scsi.c 2004-01-14 21:39:12.000000000 +0000
  51381. @@ -1334,14 +1334,10 @@
  51382. */
  51383. int scsi_retry_command(Scsi_Cmnd * SCpnt)
  51384. {
  51385. - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
  51386. - sizeof(SCpnt->data_cmnd));
  51387. - SCpnt->request_buffer = SCpnt->buffer;
  51388. - SCpnt->request_bufflen = SCpnt->bufflen;
  51389. - SCpnt->use_sg = SCpnt->old_use_sg;
  51390. - SCpnt->cmd_len = SCpnt->old_cmd_len;
  51391. - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
  51392. - SCpnt->underflow = SCpnt->old_underflow;
  51393. + /*
  51394. + * Restore the SCSI command state.
  51395. + */
  51396. + scsi_setup_cmd_retry(SCpnt);
  51397. /*
  51398. * Zero the sense information from the last time we tried
  51399. diff -urN linux-2.4.26/drivers/scsi/scsi.h linux-2.4.26-vrs1/drivers/scsi/scsi.h
  51400. --- linux-2.4.26/drivers/scsi/scsi.h 2003-08-25 12:44:42.000000000 +0100
  51401. +++ linux-2.4.26-vrs1/drivers/scsi/scsi.h 2004-04-19 18:46:03.000000000 +0100
  51402. @@ -465,6 +465,7 @@
  51403. int sectors);
  51404. extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
  51405. extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt);
  51406. +extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt);
  51407. extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
  51408. extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
  51409. int block_sectors);
  51410. @@ -588,6 +589,7 @@
  51411. unsigned changed:1; /* Data invalid due to media change */
  51412. unsigned busy:1; /* Used to prevent races */
  51413. unsigned lockable:1; /* Able to prevent media removal */
  51414. + unsigned locked:1; /* Media removal disabled */
  51415. unsigned borken:1; /* Tell the Seagate driver to be
  51416. * painfully slow on this device */
  51417. unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */
  51418. diff -urN linux-2.4.26/drivers/scsi/scsi_dma.c linux-2.4.26-vrs1/drivers/scsi/scsi_dma.c
  51419. --- linux-2.4.26/drivers/scsi/scsi_dma.c 2002-02-25 19:38:04.000000000 +0000
  51420. +++ linux-2.4.26-vrs1/drivers/scsi/scsi_dma.c 2004-01-14 21:32:26.000000000 +0000
  51421. @@ -30,6 +30,15 @@
  51422. typedef unsigned char FreeSectorBitmap;
  51423. #elif SECTORS_PER_PAGE <= 32
  51424. typedef unsigned int FreeSectorBitmap;
  51425. +#elif SECTORS_PER_PAGE <= 64
  51426. +#if 0
  51427. +typedef unsigned long long FreeSectorBitmap;
  51428. +#else
  51429. +typedef struct {
  51430. + unsigned long l,h;
  51431. +} FreeSectorBitmap;
  51432. +#define LARGE_MALLOC
  51433. +#endif
  51434. #else
  51435. #error You lose.
  51436. #endif
  51437. @@ -69,6 +78,7 @@
  51438. * to allocate more memory in order to be able to write the
  51439. * data to disk, you would wedge the system.
  51440. */
  51441. +#ifndef LARGE_MALLOC
  51442. void *scsi_malloc(unsigned int len)
  51443. {
  51444. unsigned int nbits, mask;
  51445. @@ -167,6 +177,97 @@
  51446. panic("scsi_free:Bad offset");
  51447. }
  51448. +#else
  51449. +
  51450. +void *scsi_malloc(unsigned int len)
  51451. +{
  51452. + unsigned int nbits;
  51453. + unsigned long maskl, maskh, flags;
  51454. + FreeSectorBitmap *fsb;
  51455. + int i;
  51456. +
  51457. + if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
  51458. + return NULL;
  51459. +
  51460. + save_flags_cli (flags);
  51461. + nbits = len >> 9;
  51462. + if (nbits < 32) {
  51463. + maskl = (1 << nbits) - 1;
  51464. + maskh = 0;
  51465. + } else {
  51466. + maskl = (unsigned long)-1;
  51467. + maskh = (1 << (nbits - 32)) - 1;
  51468. + }
  51469. +
  51470. + fsb = dma_malloc_freelist;
  51471. +
  51472. + for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) {
  51473. + unsigned long mml, mmh;
  51474. + int j;
  51475. + mml = maskl;
  51476. + mmh = maskh;
  51477. + j = 0;
  51478. + do {
  51479. + if ((fsb->l & mml) == 0 && (fsb->h & mmh) == 0) {
  51480. + fsb->h |= mmh;
  51481. + fsb->l |= mml;
  51482. + restore_flags (flags);
  51483. + scsi_dma_free_sectors -= nbits;
  51484. +#ifdef DEBUG
  51485. + printk("SMalloc: %d %p\n",len, dma_malloc_pages[i] + (j << 9));
  51486. +#endif
  51487. + return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
  51488. + }
  51489. + mmh = (mmh << 1) | (mml >> 31);
  51490. + mml <<= 1;
  51491. + j++;
  51492. + } while (!(mmh & (1 << 31)));
  51493. + fsb ++;
  51494. + }
  51495. + return NULL; /* Nope. No more */
  51496. +}
  51497. +
  51498. +int scsi_free(void *obj, unsigned int len)
  51499. +{
  51500. + unsigned int page, sector, nbits;
  51501. + unsigned long maskl, maskh, flags;
  51502. +
  51503. +#ifdef DEBUG
  51504. + printk("scsi_free %p %d\n",obj, len);
  51505. +#endif
  51506. +
  51507. + for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
  51508. + unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
  51509. + if ((unsigned long) obj >= page_addr &&
  51510. + (unsigned long) obj < page_addr + PAGE_SIZE) {
  51511. + sector = (((unsigned long) obj) - page_addr) >> 9;
  51512. + nbits = len >> 9;
  51513. + if (nbits < 32) {
  51514. + maskl = (1 << nbits) - 1;
  51515. + maskh = 0;
  51516. + } else {
  51517. + maskl = (unsigned long)-1;
  51518. + maskh = (1 << (nbits - 32)) - 1;
  51519. + }
  51520. + if ((sector + nbits) > SECTORS_PER_PAGE)
  51521. + panic ("scsi_free:Bad memory alignment");
  51522. + maskh = (maskh << sector) | (maskl >> (32 - sector));
  51523. + maskl = maskl << sector;
  51524. + save_flags_cli(flags);
  51525. + if (((dma_malloc_freelist[page].l & maskl) != maskl) ||
  51526. + ((dma_malloc_freelist[page].h & maskh) != maskh))
  51527. + panic("scsi_free:Trying to free unused memory");
  51528. + scsi_dma_free_sectors += nbits;
  51529. + dma_malloc_freelist[page].l &= ~maskl;
  51530. + dma_malloc_freelist[page].h &= ~maskh;
  51531. + restore_flags(flags);
  51532. + return 0;
  51533. + }
  51534. + }
  51535. + panic("scsi_free:Bad offset");
  51536. +}
  51537. +#endif
  51538. +
  51539. /*
  51540. * Function: scsi_resize_dma_pool
  51541. diff -urN linux-2.4.26/drivers/scsi/scsi_error.c linux-2.4.26-vrs1/drivers/scsi/scsi_error.c
  51542. --- linux-2.4.26/drivers/scsi/scsi_error.c 2004-04-19 11:44:16.000000000 +0100
  51543. +++ linux-2.4.26-vrs1/drivers/scsi/scsi_error.c 2004-04-18 21:47:51.000000000 +0100
  51544. @@ -35,6 +35,8 @@
  51545. #include "hosts.h"
  51546. #include "constants.h"
  51547. +#include <scsi/scsi_ioctl.h> /* grr */
  51548. +
  51549. /*
  51550. * We must always allow SHUTDOWN_SIGS. Even if we are not a module,
  51551. * the host drivers that we are using may be loaded as modules, and
  51552. @@ -49,6 +51,13 @@
  51553. */
  51554. #define SHUTDOWN_SIGS (sigmask(SIGHUP))
  51555. +/*
  51556. + * The number of times we retry a REQUEST SENSE and TEST UNIT READY
  51557. + * respectively. This is arbitary.
  51558. + */
  51559. +#define SENSE_RETRIES 5
  51560. +#define TUR_RETRIES 5
  51561. +
  51562. #ifdef DEBUG
  51563. #define SENSE_TIMEOUT SCSI_TIMEOUT
  51564. #define ABORT_TIMEOUT SCSI_TIMEOUT
  51565. @@ -373,16 +382,12 @@
  51566. */
  51567. STATIC int scsi_eh_retry_command(Scsi_Cmnd * SCpnt)
  51568. {
  51569. - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
  51570. - sizeof(SCpnt->data_cmnd));
  51571. - SCpnt->request_buffer = SCpnt->buffer;
  51572. - SCpnt->request_bufflen = SCpnt->bufflen;
  51573. - SCpnt->use_sg = SCpnt->old_use_sg;
  51574. - SCpnt->cmd_len = SCpnt->old_cmd_len;
  51575. - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
  51576. - SCpnt->underflow = SCpnt->old_underflow;
  51577. + int tries = 0;
  51578. - scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
  51579. + do {
  51580. + scsi_setup_cmd_retry(SCpnt);
  51581. + scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
  51582. + } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SCpnt->allowed);
  51583. /*
  51584. * Hey, we are done. Let's look to see what happened.
  51585. @@ -409,16 +414,10 @@
  51586. static unsigned char generic_sense[6] =
  51587. {REQUEST_SENSE, 0, 0, 0, 255, 0};
  51588. unsigned char scsi_result0[256], *scsi_result = NULL;
  51589. - int saved_result;
  51590. + int saved_result, tries;
  51591. ASSERT_LOCK(&io_request_lock, 0);
  51592. - memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
  51593. - sizeof(generic_sense));
  51594. -
  51595. - if (SCpnt->device->scsi_level <= SCSI_2)
  51596. - SCpnt->cmnd[1] = SCpnt->lun << 5;
  51597. -
  51598. scsi_result = (!SCpnt->host->hostt->unchecked_isa_dma)
  51599. ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
  51600. @@ -426,24 +425,41 @@
  51601. printk("cannot allocate scsi_result in scsi_request_sense.\n");
  51602. return FAILED;
  51603. }
  51604. - /*
  51605. - * Zero the sense buffer. Some host adapters automatically always request
  51606. - * sense, so it is not a good idea that SCpnt->request_buffer and
  51607. - * SCpnt->sense_buffer point to the same address (DB).
  51608. - * 0 is not a valid sense code.
  51609. - */
  51610. - memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
  51611. - memset((void *) scsi_result, 0, 256);
  51612. saved_result = SCpnt->result;
  51613. - SCpnt->request_buffer = scsi_result;
  51614. - SCpnt->request_bufflen = 256;
  51615. - SCpnt->use_sg = 0;
  51616. - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
  51617. - SCpnt->sc_data_direction = SCSI_DATA_READ;
  51618. - SCpnt->underflow = 0;
  51619. - scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
  51620. + tries = 0;
  51621. + do {
  51622. + memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
  51623. + sizeof(generic_sense));
  51624. +
  51625. + if (SCpnt->device->scsi_level <= SCSI_2)
  51626. + SCpnt->cmnd[1] = SCpnt->lun << 5;
  51627. +
  51628. + /*
  51629. + * Zero the sense buffer. Some host adapters automatically
  51630. + * always request sense, so it is not a good idea that
  51631. + * SCpnt->request_buffer and SCpnt->sense_buffer point to
  51632. + * the same address (DB). 0 is not a valid sense code.
  51633. + */
  51634. + memset((void *) SCpnt->sense_buffer, 0,
  51635. + sizeof(SCpnt->sense_buffer));
  51636. + memset((void *) scsi_result, 0, 256);
  51637. +
  51638. + SCpnt->request_buffer = scsi_result;
  51639. + SCpnt->request_bufflen = 256;
  51640. + SCpnt->use_sg = 0;
  51641. + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
  51642. + SCpnt->sc_data_direction = SCSI_DATA_READ;
  51643. + SCpnt->underflow = 0;
  51644. +
  51645. + scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
  51646. + /*
  51647. + * If the SCSI device responded with "logical unit
  51648. + * is in process of becoming ready", we need to
  51649. + * retry this command.
  51650. + */
  51651. + } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SENSE_RETRIES);
  51652. /* Last chance to have valid sense data */
  51653. if (!scsi_sense_valid(SCpnt))
  51654. @@ -458,15 +474,8 @@
  51655. * When we eventually call scsi_finish, we really wish to complete
  51656. * the original request, so let's restore the original data. (DB)
  51657. */
  51658. - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
  51659. - sizeof(SCpnt->data_cmnd));
  51660. SCpnt->result = saved_result;
  51661. - SCpnt->request_buffer = SCpnt->buffer;
  51662. - SCpnt->request_bufflen = SCpnt->bufflen;
  51663. - SCpnt->use_sg = SCpnt->old_use_sg;
  51664. - SCpnt->cmd_len = SCpnt->old_cmd_len;
  51665. - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
  51666. - SCpnt->underflow = SCpnt->old_underflow;
  51667. + scsi_setup_cmd_retry(SCpnt);
  51668. /*
  51669. * Hey, we are done. Let's look to see what happened.
  51670. @@ -484,40 +493,42 @@
  51671. {
  51672. static unsigned char tur_command[6] =
  51673. {TEST_UNIT_READY, 0, 0, 0, 0, 0};
  51674. + int tries = 0;
  51675. - memcpy((void *) SCpnt->cmnd, (void *) tur_command,
  51676. - sizeof(tur_command));
  51677. + do {
  51678. + memcpy((void *) SCpnt->cmnd, (void *) tur_command,
  51679. + sizeof(tur_command));
  51680. - if (SCpnt->device->scsi_level <= SCSI_2)
  51681. - SCpnt->cmnd[1] = SCpnt->lun << 5;
  51682. + if (SCpnt->device->scsi_level <= SCSI_2)
  51683. + SCpnt->cmnd[1] = SCpnt->lun << 5;
  51684. - /*
  51685. - * Zero the sense buffer. The SCSI spec mandates that any
  51686. - * untransferred sense data should be interpreted as being zero.
  51687. - */
  51688. - memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
  51689. + /*
  51690. + * Zero the sense buffer. The SCSI spec mandates that any
  51691. + * untransferred sense data should be interpreted as being zero.
  51692. + */
  51693. + memset((void *) SCpnt->sense_buffer, 0,
  51694. + sizeof(SCpnt->sense_buffer));
  51695. - SCpnt->request_buffer = NULL;
  51696. - SCpnt->request_bufflen = 0;
  51697. - SCpnt->use_sg = 0;
  51698. - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
  51699. - SCpnt->underflow = 0;
  51700. - SCpnt->sc_data_direction = SCSI_DATA_NONE;
  51701. + SCpnt->request_buffer = NULL;
  51702. + SCpnt->request_bufflen = 0;
  51703. + SCpnt->use_sg = 0;
  51704. + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
  51705. + SCpnt->underflow = 0;
  51706. + SCpnt->sc_data_direction = SCSI_DATA_NONE;
  51707. - scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
  51708. + scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
  51709. + /*
  51710. + * If the SCSI device responded with "logical unit
  51711. + * is in process of becoming ready", we need to
  51712. + * retry this command.
  51713. + */
  51714. + } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < TUR_RETRIES);
  51715. /*
  51716. * When we eventually call scsi_finish, we really wish to complete
  51717. * the original request, so let's restore the original data. (DB)
  51718. */
  51719. - memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
  51720. - sizeof(SCpnt->data_cmnd));
  51721. - SCpnt->request_buffer = SCpnt->buffer;
  51722. - SCpnt->request_bufflen = SCpnt->bufflen;
  51723. - SCpnt->use_sg = SCpnt->old_use_sg;
  51724. - SCpnt->cmd_len = SCpnt->old_cmd_len;
  51725. - SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
  51726. - SCpnt->underflow = SCpnt->old_underflow;
  51727. + scsi_setup_cmd_retry(SCpnt);
  51728. /*
  51729. * Hey, we are done. Let's look to see what happened.
  51730. @@ -577,7 +588,6 @@
  51731. host = SCpnt->host;
  51732. - retry:
  51733. /*
  51734. * We will use a queued command if possible, otherwise we will emulate the
  51735. * queuing and calling of completion function ourselves.
  51736. @@ -660,14 +670,13 @@
  51737. SCSI_LOG_ERROR_RECOVERY(3,
  51738. printk("scsi_send_eh_cmnd: scsi_eh_completed_normally %x\n", ret));
  51739. switch (ret) {
  51740. - case SUCCESS:
  51741. - SCpnt->eh_state = SUCCESS;
  51742. - break;
  51743. - case NEEDS_RETRY:
  51744. - goto retry;
  51745. - case FAILED:
  51746. default:
  51747. - SCpnt->eh_state = FAILED;
  51748. + ret = FAILED;
  51749. + /*FALLTHROUGH*/
  51750. + case FAILED:
  51751. + case NEEDS_RETRY:
  51752. + case SUCCESS:
  51753. + SCpnt->eh_state = ret;
  51754. break;
  51755. }
  51756. } else {
  51757. @@ -1208,6 +1217,82 @@
  51758. /*
  51759. + * Function: scsi_eh_lock_done
  51760. + *
  51761. + * Purpose: free the command and request structures associated
  51762. + * with the error handlers door lock request
  51763. + *
  51764. + * Arguments: SCpnt - the SCSI command block for the door lock request.
  51765. + *
  51766. + * Returns: Nothing
  51767. + *
  51768. + * Notes: We completed the asynchronous door lock request, and
  51769. + * it has either locked the door or failed. We must free
  51770. + * the command structures associated with this request.
  51771. + */
  51772. +static void scsi_eh_lock_done(struct scsi_cmnd *SCpnt)
  51773. +{
  51774. + struct scsi_request *SRpnt = SCpnt->sc_request;
  51775. +
  51776. + SCpnt->sc_request = NULL;
  51777. + SRpnt->sr_command = NULL;
  51778. +
  51779. + scsi_release_command(SCpnt);
  51780. + scsi_release_request(SRpnt);
  51781. +}
  51782. +
  51783. +
  51784. +/*
  51785. + * Function: scsi_eh_lock_door
  51786. + *
  51787. + * Purpose: Prevent medium removal for the specified device
  51788. + *
  51789. + * Arguments: dev - SCSI device to prevent medium removal
  51790. + *
  51791. + * Locking: We must be called from process context;
  51792. + * scsi_allocate_request() may sleep.
  51793. + *
  51794. + * Returns: Nothing
  51795. + *
  51796. + * Notes: We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request
  51797. + * on the head of the devices request queue, and continue.
  51798. + *
  51799. + * Bugs: scsi_allocate_request() may sleep waiting for existing
  51800. + * requests to be processed. However, since we haven't
  51801. + * kicked off any request processing for this host, this
  51802. + * may deadlock.
  51803. + *
  51804. + * If scsi_allocate_request() fails for what ever reason,
  51805. + * we completely forget to lock the door.
  51806. + */
  51807. +STATIC void scsi_eh_lock_door(struct scsi_device *dev)
  51808. +{
  51809. + struct scsi_request *SRpnt = scsi_allocate_request(dev);
  51810. +
  51811. + if (SRpnt == NULL) {
  51812. + /* what now? */
  51813. + return;
  51814. + }
  51815. +
  51816. + SRpnt->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
  51817. + SRpnt->sr_cmnd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
  51818. + SRpnt->sr_cmnd[2] = 0;
  51819. + SRpnt->sr_cmnd[3] = 0;
  51820. + SRpnt->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
  51821. + SRpnt->sr_cmnd[5] = 0;
  51822. + SRpnt->sr_data_direction = SCSI_DATA_NONE;
  51823. + SRpnt->sr_bufflen = 0;
  51824. + SRpnt->sr_buffer = NULL;
  51825. + SRpnt->sr_allowed = 5;
  51826. + SRpnt->sr_done = scsi_eh_lock_done;
  51827. + SRpnt->sr_timeout_per_command = 10 * HZ;
  51828. + SRpnt->sr_cmd_len = COMMAND_SIZE(SRpnt->sr_cmnd[0]);
  51829. +
  51830. + scsi_insert_special_req(SRpnt, 1);
  51831. +}
  51832. +
  51833. +
  51834. +/*
  51835. * Function: scsi_restart_operations
  51836. *
  51837. * Purpose: Restart IO operations to the specified host.
  51838. @@ -1229,6 +1314,15 @@
  51839. ASSERT_LOCK(&io_request_lock, 0);
  51840. /*
  51841. + * If the door was locked, we need to insert a door lock request
  51842. + * onto the head of the SCSI request queue for the device. There
  51843. + * is no point trying to lock the door of an off-line device.
  51844. + */
  51845. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
  51846. + if (SDpnt->online && SDpnt->locked)
  51847. + scsi_eh_lock_door(SDpnt);
  51848. +
  51849. + /*
  51850. * Next free up anything directly waiting upon the host. This will be
  51851. * requests for character device operations, and also for ioctls to queued
  51852. * block devices.
  51853. @@ -1248,8 +1342,7 @@
  51854. request_queue_t *q;
  51855. if ((host->can_queue > 0 && (host->host_busy >= host->can_queue))
  51856. || (host->host_blocked)
  51857. - || (host->host_self_blocked)
  51858. - || (SDpnt->device_blocked)) {
  51859. + || (host->host_self_blocked)) {
  51860. break;
  51861. }
  51862. q = &SDpnt->request_queue;
  51863. @@ -1259,136 +1352,202 @@
  51864. }
  51865. /*
  51866. - * Function: scsi_unjam_host
  51867. + * Function: scsi_eh_find_failed_command
  51868. *
  51869. - * Purpose: Attempt to fix a host which has a command that failed for
  51870. - * some reason.
  51871. + * Purpose: Find a failed Scsi_Cmnd structure on a device.
  51872. *
  51873. - * Arguments: host - host that needs unjamming.
  51874. - *
  51875. - * Returns: Nothing
  51876. + * Arguments: SDpnt - Scsi_Device structure
  51877. *
  51878. - * Notes: When we come in here, we *know* that all commands on the
  51879. - * bus have either completed, failed or timed out. We also
  51880. - * know that no further commands are being sent to the host,
  51881. - * so things are relatively quiet and we have freedom to
  51882. - * fiddle with things as we wish.
  51883. + * Returns: Pointer to Scsi_Cmnd structure, or NULL on failure
  51884. + */
  51885. +STATIC Scsi_Cmnd *scsi_eh_find_failed_command(Scsi_Device *SDpnt)
  51886. +{
  51887. + Scsi_Cmnd *SCpnt;
  51888. +
  51889. + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
  51890. + if (SCpnt->state == SCSI_STATE_FAILED ||
  51891. + SCpnt->state == SCSI_STATE_TIMEOUT)
  51892. + return SCpnt;
  51893. +
  51894. + return NULL;
  51895. +}
  51896. +
  51897. +
  51898. +/*
  51899. + * Function: scsi_eh_test_and_retry
  51900. *
  51901. - * Additional note: This is only the *default* implementation. It is possible
  51902. - * for individual drivers to supply their own version of this
  51903. - * function, and if the maintainer wishes to do this, it is
  51904. - * strongly suggested that this function be taken as a template
  51905. - * and modified. This function was designed to correctly handle
  51906. - * problems for about 95% of the different cases out there, and
  51907. - * it should always provide at least a reasonable amount of error
  51908. - * recovery.
  51909. + * Purpose: Try to retry a failed command.
  51910. *
  51911. - * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
  51912. - * have scsi_finish_command() called for it. We do all of
  51913. - * the retry stuff here, so when we restart the host after we
  51914. - * return it should have an empty queue.
  51915. + * Arguments: SCpnt - scsi command structure
  51916. + * done - list of commands that have been successfully
  51917. + * completed.
  51918. + *
  51919. + * Returns: SUCCESS or FAILED
  51920. + *
  51921. + * Note: If the TEST UNIT READY command successfully executes,
  51922. + * but returns some form of "device not ready", we wait
  51923. + * a while, and retry 3 times. The device could be still
  51924. + * re-initialising.
  51925. */
  51926. -STATIC int scsi_unjam_host(struct Scsi_Host *host)
  51927. +STATIC int scsi_eh_test_and_retry(Scsi_Cmnd *SCpnt, Scsi_Cmnd **done)
  51928. {
  51929. - int devices_failed;
  51930. - int numfailed;
  51931. - int ourrtn;
  51932. - int rtn = FALSE;
  51933. - int result;
  51934. - Scsi_Cmnd *SCloop;
  51935. - Scsi_Cmnd *SCpnt;
  51936. - Scsi_Device *SDpnt;
  51937. - Scsi_Device *SDloop;
  51938. - Scsi_Cmnd *SCdone;
  51939. - int timed_out;
  51940. + int rtn, tries = 3;
  51941. - ASSERT_LOCK(&io_request_lock, 0);
  51942. + do {
  51943. + rtn = scsi_test_unit_ready(SCpnt);
  51944. + if (rtn != SUCCESS)
  51945. + return rtn;
  51946. - SCdone = NULL;
  51947. + if (scsi_unit_is_ready(SCpnt))
  51948. + break;
  51949. +
  51950. + if (tries-- == 0)
  51951. + return FAILED;
  51952. +
  51953. + scsi_sleep(5 * HZ);
  51954. + } while (1);
  51955. +
  51956. + rtn = scsi_eh_retry_command(SCpnt);
  51957. + if (rtn == SUCCESS) {
  51958. + SCpnt->host->host_failed--;
  51959. + scsi_eh_finish_command(done, SCpnt);
  51960. + }
  51961. +
  51962. + return rtn;
  51963. +}
  51964. - /*
  51965. - * First, protect against any sort of race condition. If any of the outstanding
  51966. - * commands are in states that indicate that we are not yet blocked (i.e. we are
  51967. - * not in a quiet state) then we got woken up in error. If we ever end up here,
  51968. - * we need to re-examine some of the assumptions.
  51969. - */
  51970. - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  51971. - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  51972. - if (SCpnt->state == SCSI_STATE_FAILED
  51973. - || SCpnt->state == SCSI_STATE_TIMEOUT
  51974. - || SCpnt->state == SCSI_STATE_INITIALIZING
  51975. - || SCpnt->state == SCSI_STATE_UNUSED) {
  51976. - continue;
  51977. - }
  51978. - /*
  51979. - * Rats. Something is still floating around out there. This could
  51980. - * be the result of the fact that the upper level drivers are still frobbing
  51981. - * commands that might have succeeded. There are two outcomes. One is that
  51982. - * the command block will eventually be freed, and the other one is that
  51983. - * the command will be queued and will be finished along the way.
  51984. - */
  51985. - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
  51986. /*
  51987. - * panic("SCSI Error handler woken too early\n");
  51988. + * Function: scsi_eh_restart_device
  51989. *
  51990. - * This is no longer a problem, since now the code cares only about
  51991. - * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
  51992. - * Other states are useful only to release active commands when devices are
  51993. - * set offline. If (host->host_active == host->host_busy) we can safely assume
  51994. - * that there are no commands in state other then TIMEOUT od FAILED. (DB)
  51995. + * Purpose: Retry all failed or timed out commands for a device
  51996. *
  51997. - * FIXME:
  51998. - * It is not easy to release correctly commands according to their state when
  51999. - * devices are set offline, when the state is neither TIMEOUT nor FAILED.
  52000. - * When a device is set offline, we can have some command with
  52001. - * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
  52002. - * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
  52003. - * (DB, 17 May 1998)
  52004. + * Arguments: SDpnt - SCSI device to retry
  52005. + * done - list of commands that have been successfully
  52006. + * completed.
  52007. + *
  52008. + * Returns: SUCCESS or failure code
  52009. + */
  52010. +STATIC int scsi_eh_restart_device(Scsi_Device *SDpnt, Scsi_Cmnd **done)
  52011. +{
  52012. + Scsi_Cmnd *SCpnt, *SCnext;
  52013. + int rtn = SUCCESS;
  52014. +
  52015. + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
  52016. + SCnext = SCpnt->next;
  52017. +
  52018. + if (SCpnt->state == SCSI_STATE_FAILED ||
  52019. + SCpnt->state == SCSI_STATE_TIMEOUT) {
  52020. + rtn = scsi_eh_test_and_retry(SCpnt, done);
  52021. + if (rtn != SUCCESS)
  52022. + break;
  52023. + }
  52024. + }
  52025. +
  52026. + return rtn;
  52027. +}
  52028. +
  52029. +/*
  52030. + * Function: scsi_eh_set_device_offline
  52031. + *
  52032. + * Purpose: set a device off line
  52033. + *
  52034. + * Arguments: SDpnt - SCSI device to take off line
  52035. + * done - list of commands that have been successfully
  52036. + * completed.
  52037. + * reason - text string describing why the device is off-line
  52038. + *
  52039. + * Returns: Nothing
  52040. + *
  52041. + * Notes: In addition, we complete each failed or timed out command
  52042. + * attached to this device.
  52043. */
  52044. +STATIC void scsi_eh_set_device_offline(Scsi_Device *SDpnt, Scsi_Cmnd **done,
  52045. + const char *reason)
  52046. +{
  52047. + Scsi_Cmnd *SCpnt, *SCnext;
  52048. +
  52049. + printk(KERN_ERR "scsi: device set offline - %s: "
  52050. + "host %d channel %d id %d lun %d\n",
  52051. + reason, SDpnt->host->host_no, SDpnt->channel,
  52052. + SDpnt->id, SDpnt->lun);
  52053. +
  52054. + SDpnt->online = FALSE;
  52055. +
  52056. + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
  52057. + SCnext = SCpnt->next;
  52058. +
  52059. + switch (SCpnt->state) {
  52060. + case SCSI_STATE_TIMEOUT:
  52061. + SCpnt->result |= DRIVER_TIMEOUT;
  52062. + /*FALLTHROUGH*/
  52063. +
  52064. + case SCSI_STATE_FAILED:
  52065. + SCSI_LOG_ERROR_RECOVERY(3,
  52066. + printk("Finishing command for device %d %x\n",
  52067. + SDpnt->id, SCpnt->result));
  52068. +
  52069. + SDpnt->host->host_failed--;
  52070. + scsi_eh_finish_command(done, SCpnt);
  52071. + break;
  52072. +
  52073. + default:
  52074. + break;
  52075. }
  52076. }
  52077. +}
  52078. +
  52079. +static void scsi_unjam_request_sense(struct Scsi_Host *host, Scsi_Cmnd **done)
  52080. +{
  52081. + int rtn;
  52082. + int result;
  52083. + Scsi_Cmnd *SCpnt;
  52084. + Scsi_Device *SDpnt;
  52085. /*
  52086. * Next, see if we need to request sense information. if so,
  52087. * then get it now, so we have a better idea of what to do.
  52088. - * FIXME(eric) this has the unfortunate side effect that if a host
  52089. - * adapter does not automatically request sense information, that we end
  52090. - * up shutting it down before we request it. All hosts should be doing this
  52091. - * anyways, so for now all I have to say is tough noogies if you end up in here.
  52092. - * On second thought, this is probably a good idea. We *really* want to give
  52093. - * authors an incentive to automatically request this.
  52094. + * FIXME(eric) this has the unfortunate side effect that if a
  52095. + * host adapter does not automatically request sense information,
  52096. + * that we end up shutting it down before we request it. All
  52097. + * hosts should be doing this anyways, so for now all I have
  52098. + * to say is tough noogies if you end up in here. On second
  52099. + * thought, this is probably a good idea. We *really* want
  52100. + * to give authors an incentive to automatically request this.
  52101. */
  52102. - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
  52103. + SCSI_LOG_ERROR_RECOVERY(3,
  52104. + printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
  52105. for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52106. for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  52107. - if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt)) {
  52108. + if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt))
  52109. continue;
  52110. - }
  52111. - SCSI_LOG_ERROR_RECOVERY(2, printk("scsi_unjam_host: Requesting sense for %d\n",
  52112. - SCpnt->target));
  52113. +
  52114. + SCSI_LOG_ERROR_RECOVERY(2,
  52115. + printk("scsi_unjam_host: Requesting sense for %d\n",
  52116. + SCpnt->target));
  52117. rtn = scsi_request_sense(SCpnt);
  52118. - if (rtn != SUCCESS) {
  52119. + if (rtn != SUCCESS)
  52120. continue;
  52121. - }
  52122. - SCSI_LOG_ERROR_RECOVERY(3, printk("Sense requested for %p - result %x\n",
  52123. - SCpnt, SCpnt->result));
  52124. +
  52125. + SCSI_LOG_ERROR_RECOVERY(3,
  52126. + printk("Sense requested for %p - result %x\n",
  52127. + SCpnt, SCpnt->result));
  52128. SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", SCpnt));
  52129. result = scsi_decide_disposition(SCpnt);
  52130. /*
  52131. - * If the result was normal, then just pass it along to the
  52132. - * upper level.
  52133. + * If the result was normal, then just pass
  52134. + * it along to the upper level.
  52135. */
  52136. if (result == SUCCESS) {
  52137. SCpnt->host->host_failed--;
  52138. - scsi_eh_finish_command(&SCdone, SCpnt);
  52139. + scsi_eh_finish_command(done, SCpnt);
  52140. }
  52141. - if (result != NEEDS_RETRY) {
  52142. + if (result != NEEDS_RETRY)
  52143. continue;
  52144. - }
  52145. +
  52146. /*
  52147. * We only come in here if we want to retry a
  52148. * command. The test to see whether the command
  52149. @@ -1398,20 +1557,29 @@
  52150. */
  52151. SCpnt->state = NEEDS_RETRY;
  52152. rtn = scsi_eh_retry_command(SCpnt);
  52153. - if (rtn != SUCCESS) {
  52154. + if (rtn != SUCCESS)
  52155. continue;
  52156. - }
  52157. +
  52158. /*
  52159. * We eventually hand this one back to the top level.
  52160. */
  52161. SCpnt->host->host_failed--;
  52162. - scsi_eh_finish_command(&SCdone, SCpnt);
  52163. + scsi_eh_finish_command(done, SCpnt);
  52164. }
  52165. }
  52166. +}
  52167. +
  52168. +static void scsi_unjam_count(struct Scsi_Host *host, Scsi_Cmnd **done)
  52169. +{
  52170. + Scsi_Device *SDpnt;
  52171. + Scsi_Cmnd *SCpnt;
  52172. + int devices_failed;
  52173. + int numfailed;
  52174. + int timed_out;
  52175. /*
  52176. - * Go through the list of commands and figure out where we stand and how bad things
  52177. - * really are.
  52178. + * Go through the list of commands and figure out where we
  52179. + * stand and how bad things really are.
  52180. */
  52181. numfailed = 0;
  52182. timed_out = 0;
  52183. @@ -1421,359 +1589,478 @@
  52184. for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  52185. if (SCpnt->state == SCSI_STATE_FAILED) {
  52186. - SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d failed\n",
  52187. - SCpnt->target));
  52188. + SCSI_LOG_ERROR_RECOVERY(5,
  52189. + printk("Command to ID %d failed\n",
  52190. + SCpnt->target));
  52191. numfailed++;
  52192. device_error++;
  52193. }
  52194. if (SCpnt->state == SCSI_STATE_TIMEOUT) {
  52195. - SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d timedout\n",
  52196. - SCpnt->target));
  52197. + SCSI_LOG_ERROR_RECOVERY(5,
  52198. + printk("Command to ID %d timedout\n",
  52199. + SCpnt->target));
  52200. timed_out++;
  52201. device_error++;
  52202. }
  52203. }
  52204. - if (device_error > 0) {
  52205. + if (device_error > 0)
  52206. devices_failed++;
  52207. - }
  52208. }
  52209. - SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d+%d commands on %d devices require eh work\n",
  52210. - numfailed, timed_out, devices_failed));
  52211. + SCSI_LOG_ERROR_RECOVERY(2,
  52212. + printk("Total of %d+%d commands on %d devices require eh work\n",
  52213. + numfailed, timed_out, devices_failed));
  52214. +}
  52215. +
  52216. +static void scsi_unjam_abort(struct Scsi_Host *host, Scsi_Cmnd **done)
  52217. +{
  52218. + Scsi_Device *SDpnt;
  52219. + Scsi_Cmnd *SCpnt;
  52220. + int rtn;
  52221. - if (host->host_failed == 0) {
  52222. - ourrtn = TRUE;
  52223. - goto leave;
  52224. - }
  52225. /*
  52226. - * Next, try and see whether or not it makes sense to try and abort
  52227. - * the running command. This only works out to be the case if we have
  52228. - * one command that has timed out. If the command simply failed, it
  52229. - * makes no sense to try and abort the command, since as far as the
  52230. - * host adapter is concerned, it isn't running.
  52231. + * Next, try and see whether or not it makes sense to try and
  52232. + * abort the running command. This only works out to be the
  52233. + * case if we have one command that has timed out. If the
  52234. + * command simply failed, it makes no sense to try and abort
  52235. + * the command, since as far as the host adapter is concerned,
  52236. + * it isn't running.
  52237. */
  52238. - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
  52239. + SCSI_LOG_ERROR_RECOVERY(3,
  52240. + printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
  52241. for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52242. - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
  52243. - if (SCloop->state != SCSI_STATE_TIMEOUT) {
  52244. + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  52245. + if (SCpnt->state != SCSI_STATE_TIMEOUT)
  52246. continue;
  52247. - }
  52248. - rtn = scsi_try_to_abort_command(SCloop, ABORT_TIMEOUT);
  52249. - if (rtn == SUCCESS) {
  52250. - rtn = scsi_test_unit_ready(SCloop);
  52251. -
  52252. - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
  52253. - rtn = scsi_eh_retry_command(SCloop);
  52254. -
  52255. - if (rtn == SUCCESS) {
  52256. - SCloop->host->host_failed--;
  52257. - scsi_eh_finish_command(&SCdone, SCloop);
  52258. - }
  52259. - }
  52260. - }
  52261. +
  52262. + rtn = scsi_try_to_abort_command(SCpnt, ABORT_TIMEOUT);
  52263. + if (rtn == SUCCESS)
  52264. + scsi_eh_test_and_retry(SCpnt, done);
  52265. }
  52266. }
  52267. +}
  52268. +
  52269. +static void scsi_unjam_device_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
  52270. +{
  52271. + Scsi_Device *SDpnt;
  52272. + Scsi_Cmnd *SCpnt;
  52273. + int rtn;
  52274. - /*
  52275. - * If we have corrected all of the problems, then we are done.
  52276. - */
  52277. - if (host->host_failed == 0) {
  52278. - ourrtn = TRUE;
  52279. - goto leave;
  52280. - }
  52281. /*
  52282. * Either the abort wasn't appropriate, or it didn't succeed.
  52283. - * Now try a bus device reset. Still, look to see whether we have
  52284. - * multiple devices that are jammed or not - if we have multiple devices,
  52285. - * it makes no sense to try BUS_DEVICE_RESET - we really would need
  52286. - * to try a BUS_RESET instead.
  52287. + * Now try a bus device reset. Still, look to see whether we
  52288. + * have multiple devices that are jammed or not - if we have
  52289. + * multiple devices, it makes no sense to try BUS_DEVICE_RESET
  52290. + * - we really would need to try a BUS_RESET instead.
  52291. *
  52292. - * Does this make sense - should we try BDR on each device individually?
  52293. - * Yes, definitely.
  52294. + * Does this make sense - should we try BDR on each device
  52295. + * individually? Yes, definitely.
  52296. */
  52297. - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
  52298. + SCSI_LOG_ERROR_RECOVERY(3,
  52299. + printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
  52300. for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52301. - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
  52302. - if (SCloop->state == SCSI_STATE_FAILED
  52303. - || SCloop->state == SCSI_STATE_TIMEOUT) {
  52304. - break;
  52305. - }
  52306. - }
  52307. -
  52308. - if (SCloop == NULL) {
  52309. + SCpnt = scsi_eh_find_failed_command(SDpnt);
  52310. + if (SCpnt == NULL)
  52311. continue;
  52312. - }
  52313. +
  52314. /*
  52315. - * OK, we have a device that is having problems. Try and send
  52316. - * a bus device reset to it.
  52317. + * OK, we have a device that is having problems.
  52318. + * Try and send a bus device reset to it.
  52319. + */
  52320. + rtn = scsi_try_bus_device_reset(SCpnt, RESET_TIMEOUT);
  52321. +
  52322. + /*
  52323. + * A successful bus device reset causes all commands
  52324. + * currently executing on the device to terminate.
  52325. + * We expect the HBA driver to "forget" all commands
  52326. + * associated with this device.
  52327. *
  52328. - * FIXME(eric) - make sure we handle the case where multiple
  52329. - * commands to the same device have failed. They all must
  52330. - * get properly restarted.
  52331. - */
  52332. - rtn = scsi_try_bus_device_reset(SCloop, RESET_TIMEOUT);
  52333. -
  52334. - if (rtn == SUCCESS) {
  52335. - rtn = scsi_test_unit_ready(SCloop);
  52336. -
  52337. - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
  52338. - rtn = scsi_eh_retry_command(SCloop);
  52339. -
  52340. - if (rtn == SUCCESS) {
  52341. - SCloop->host->host_failed--;
  52342. - scsi_eh_finish_command(&SCdone, SCloop);
  52343. - }
  52344. - }
  52345. - }
  52346. + * Retry each failed or timed out command currently
  52347. + * outstanding for this device.
  52348. + *
  52349. + * If any command fails, bail out. We will try a
  52350. + * bus reset instead.
  52351. + */
  52352. + if (rtn == SUCCESS)
  52353. + scsi_eh_restart_device(SDpnt, done);
  52354. }
  52355. +}
  52356. +
  52357. +static void scsi_unjam_bus_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
  52358. +{
  52359. + Scsi_Device *SDpnt;
  52360. + Scsi_Cmnd *SCpnt;
  52361. + int rtn, channel, max_channel = 0;
  52362. - if (host->host_failed == 0) {
  52363. - ourrtn = TRUE;
  52364. - goto leave;
  52365. - }
  52366. /*
  52367. - * If we ended up here, we have serious problems. The only thing left
  52368. - * to try is a full bus reset. If someone has grabbed the bus and isn't
  52369. - * letting go, then perhaps this will help.
  52370. + * If we ended up here, we have serious problems. The only thing
  52371. + * left to try is a full bus reset. If someone has grabbed the
  52372. + * bus and isn't letting go, then perhaps this will help.
  52373. */
  52374. - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard bus reset\n"));
  52375. + SCSI_LOG_ERROR_RECOVERY(3,
  52376. + printk("scsi_unjam_host: Try hard bus reset\n"));
  52377. - /*
  52378. - * We really want to loop over the various channels, and do this on
  52379. - * a channel by channel basis. We should also check to see if any
  52380. - * of the failed commands are on soft_reset devices, and if so, skip
  52381. - * the reset.
  52382. + /*
  52383. + * Find the maximum channel number for this host.
  52384. */
  52385. - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52386. - next_device:
  52387. - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  52388. - if (SCpnt->state != SCSI_STATE_FAILED
  52389. - && SCpnt->state != SCSI_STATE_TIMEOUT) {
  52390. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
  52391. + if (SDpnt->channel > max_channel)
  52392. + max_channel = SDpnt->channel;
  52393. +
  52394. + /*
  52395. + * Loop over each channel, and see if it any device on
  52396. + * each channel has failed.
  52397. + */
  52398. + for (channel = 0; channel <= max_channel; channel++) {
  52399. + Scsi_Cmnd *failed_command;
  52400. + int soft_reset;
  52401. +
  52402. + try_again:
  52403. + failed_command = NULL;
  52404. + soft_reset = 0;
  52405. +
  52406. + /*
  52407. + * Loop over each device on this channel locating any
  52408. + * failed command. We need a Scsi_Cmnd structure to
  52409. + * call the bus reset function.
  52410. + *
  52411. + * We also need to check if any of the failed commands
  52412. + * are on soft_reset devices, and if so, skip the reset.
  52413. + */
  52414. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52415. + if (SDpnt->channel != channel)
  52416. continue;
  52417. - }
  52418. - /*
  52419. - * We have a failed command. Make sure there are no other failed
  52420. - * commands on the same channel that are timed out and implement a
  52421. - * soft reset.
  52422. - */
  52423. - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
  52424. - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
  52425. - if (SCloop->channel != SCpnt->channel) {
  52426. - continue;
  52427. - }
  52428. - if (SCloop->state != SCSI_STATE_FAILED
  52429. - && SCloop->state != SCSI_STATE_TIMEOUT) {
  52430. - continue;
  52431. - }
  52432. - if (SDloop->soft_reset && SCloop->state == SCSI_STATE_TIMEOUT) {
  52433. - /*
  52434. - * If this device uses the soft reset option, and this
  52435. - * is one of the devices acting up, then our only
  52436. - * option is to wait a bit, since the command is
  52437. - * supposedly still running.
  52438. - *
  52439. - * FIXME(eric) - right now we will just end up falling
  52440. - * through to the 'take device offline' case.
  52441. - *
  52442. - * FIXME(eric) - It is possible that the command completed
  52443. - * *after* the error recovery procedure started, and if this
  52444. - * is the case, we are worrying about nothing here.
  52445. - */
  52446. -
  52447. - scsi_sleep(1 * HZ);
  52448. - goto next_device;
  52449. - }
  52450. - }
  52451. - }
  52452. +
  52453. + SCpnt = scsi_eh_find_failed_command(SDpnt);
  52454. + if (SCpnt)
  52455. + failed_command = SCpnt;
  52456. /*
  52457. - * We now know that we are able to perform a reset for the
  52458. - * bus that SCpnt points to. There are no soft-reset devices
  52459. - * with outstanding timed out commands.
  52460. + * If this device has timed out or failed commands,
  52461. + * and uses the soft_reset option.
  52462. */
  52463. - rtn = scsi_try_bus_reset(SCpnt);
  52464. - if (rtn == SUCCESS) {
  52465. - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
  52466. - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
  52467. - if (SCloop->channel != SCpnt->channel) {
  52468. - continue;
  52469. - }
  52470. - if (SCloop->state != SCSI_STATE_FAILED
  52471. - && SCloop->state != SCSI_STATE_TIMEOUT) {
  52472. - continue;
  52473. - }
  52474. - rtn = scsi_test_unit_ready(SCloop);
  52475. -
  52476. - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
  52477. - rtn = scsi_eh_retry_command(SCloop);
  52478. -
  52479. - if (rtn == SUCCESS) {
  52480. - SCpnt->host->host_failed--;
  52481. - scsi_eh_finish_command(&SCdone, SCloop);
  52482. - }
  52483. - }
  52484. - /*
  52485. - * If the bus reset worked, but we are still unable to
  52486. - * talk to the device, take it offline.
  52487. - * FIXME(eric) - is this really the correct thing to do?
  52488. - */
  52489. - if (rtn != SUCCESS) {
  52490. - printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after bus reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
  52491. -
  52492. - SDloop->online = FALSE;
  52493. - SDloop->host->host_failed--;
  52494. - scsi_eh_finish_command(&SCdone, SCloop);
  52495. - }
  52496. - }
  52497. - }
  52498. + if (SCpnt && SDpnt->soft_reset)
  52499. + soft_reset = 1;
  52500. + }
  52501. +
  52502. + /*
  52503. + * If this channel hasn't failed, we
  52504. + * don't need to reset it.
  52505. + */
  52506. + if (!failed_command)
  52507. + continue;
  52508. +
  52509. + /*
  52510. + * If this device uses the soft reset option, and this
  52511. + * is one of the devices acting up, then our only
  52512. + * option is to wait a bit, since the command is
  52513. + * supposedly still running.
  52514. + *
  52515. + * FIXME(eric) - right now we will just end up falling
  52516. + * through to the 'take device offline' case.
  52517. + *
  52518. + * FIXME(eric) - It is possible that the command completed
  52519. + * *after* the error recovery procedure started, and if
  52520. + * this is the case, we are worrying about nothing here.
  52521. + *
  52522. + * FIXME(rmk) - This should be bounded; we shouldn't wait
  52523. + * for an infinite amount of time for any device.
  52524. + */
  52525. + if (soft_reset) {
  52526. + SCSI_LOG_ERROR_RECOVERY(3,
  52527. + printk("scsi_unjam_host: unable to try bus "
  52528. + "reset for host %d channel %d\n",
  52529. + host->host_no, channel));
  52530. + scsi_sleep(1 * HZ);
  52531. + goto try_again;
  52532. + }
  52533. +
  52534. + /*
  52535. + * We now know that we are able to perform a reset for the
  52536. + * bus that SCpnt points to. There are no soft-reset devices
  52537. + * with outstanding timed out commands.
  52538. + */
  52539. + rtn = scsi_try_bus_reset(failed_command);
  52540. +
  52541. + /*
  52542. + * If we failed to reset the bus, move on to the next bus.
  52543. + */
  52544. + if (rtn != SUCCESS)
  52545. + continue;
  52546. +
  52547. + /*
  52548. + * We succeeded. Retry each failed command.
  52549. + */
  52550. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52551. + if (SDpnt->channel != channel)
  52552. + continue;
  52553. +
  52554. + rtn = scsi_eh_restart_device(SDpnt, done);
  52555. +
  52556. + if (rtn != SUCCESS) {
  52557. + SCpnt = scsi_eh_find_failed_command(SDpnt);
  52558. +
  52559. + /*
  52560. + * This device failed again. Since a bus
  52561. + * reset freed it up, chances are we've
  52562. + * hit the same problem, so try the same
  52563. + * solution. We also need to ensure that
  52564. + * the SCSI bus is in the BUS FREE state
  52565. + * so we can try to talk to other devices.
  52566. + */
  52567. + scsi_try_bus_reset(SCpnt);
  52568. + scsi_eh_set_device_offline(SDpnt, done,
  52569. + "not ready or command retry "
  52570. + "failed after bus reset");
  52571. }
  52572. }
  52573. }
  52574. +}
  52575. +
  52576. +static void scsi_unjam_host_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
  52577. +{
  52578. + Scsi_Device *SDpnt;
  52579. + Scsi_Cmnd *SCpnt;
  52580. + Scsi_Cmnd *failed_command = NULL;
  52581. + int rtn, soft_reset;
  52582. - if (host->host_failed == 0) {
  52583. - ourrtn = TRUE;
  52584. - goto leave;
  52585. - }
  52586. /*
  52587. - * If we ended up here, we have serious problems. The only thing left
  52588. - * to try is a full host reset - perhaps the firmware on the device
  52589. - * crashed, or something like that.
  52590. + * If we ended up here, we have serious problems. The only thing
  52591. + * left to try is a full host reset - perhaps the firmware on the
  52592. + * device crashed, or something like that.
  52593. *
  52594. - * It is assumed that a succesful host reset will cause *all* information
  52595. - * about the command to be flushed from both the host adapter *and* the
  52596. - * device.
  52597. + * It is assumed that a succesful host reset will cause *all*
  52598. + * information about the command to be flushed from both the host
  52599. + * adapter *and* the device.
  52600. *
  52601. - * FIXME(eric) - it isn't clear that devices that implement the soft reset
  52602. - * option can ever be cleared except via cycling the power. The problem is
  52603. - * that sending the host reset command will cause the host to forget
  52604. - * about the pending command, but the device won't forget. For now, we
  52605. - * skip the host reset option if any of the failed devices are configured
  52606. - * to use the soft reset option.
  52607. + * FIXME(eric) - it isn't clear that devices that implement the
  52608. + * soft reset option can ever be cleared except via cycling the
  52609. + * power. The problem is that sending the host reset command will
  52610. + * cause the host to forget about the pending command, but the
  52611. + * device won't forget. For now, we skip the host reset option
  52612. + * if any of the failed devices are configured to use the soft
  52613. + * reset option.
  52614. */
  52615. + SCSI_LOG_ERROR_RECOVERY(3,
  52616. + printk("scsi_unjam_host: Try host reset\n"));
  52617. +
  52618. + try_again:
  52619. + failed_command = NULL;
  52620. + soft_reset = 0;
  52621. +
  52622. for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52623. - next_device2:
  52624. - for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  52625. - if (SCpnt->state != SCSI_STATE_FAILED
  52626. - && SCpnt->state != SCSI_STATE_TIMEOUT) {
  52627. - continue;
  52628. - }
  52629. - if (SDpnt->soft_reset && SCpnt->state == SCSI_STATE_TIMEOUT) {
  52630. - /*
  52631. - * If this device uses the soft reset option, and this
  52632. - * is one of the devices acting up, then our only
  52633. - * option is to wait a bit, since the command is
  52634. - * supposedly still running.
  52635. - *
  52636. - * FIXME(eric) - right now we will just end up falling
  52637. - * through to the 'take device offline' case.
  52638. - */
  52639. - SCSI_LOG_ERROR_RECOVERY(3,
  52640. - printk("scsi_unjam_host: Unable to try hard host reset\n"));
  52641. + /*
  52642. + * Locate any failed commands for this device.
  52643. + */
  52644. + SCpnt = scsi_eh_find_failed_command(SDpnt);
  52645. + if (SCpnt)
  52646. + failed_command = SCpnt;
  52647. - /*
  52648. - * Due to the spinlock, we will never get out of this
  52649. - * loop without a proper wait. (DB)
  52650. - */
  52651. - scsi_sleep(1 * HZ);
  52652. + /*
  52653. + * If this device has timed out or failed commands,
  52654. + * and uses the soft_reset option.
  52655. + */
  52656. + if (SCpnt && SDpnt->soft_reset)
  52657. + soft_reset = 1;
  52658. + }
  52659. - goto next_device2;
  52660. - }
  52661. - SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard host reset\n"));
  52662. + /*
  52663. + * If this device uses the soft reset option, and this
  52664. + * is one of the devices acting up, then our only
  52665. + * option is to wait a bit, since the command is
  52666. + * supposedly still running.
  52667. + *
  52668. + * FIXME(eric) - right now we will just end up falling
  52669. + * through to the 'take device offline' case.
  52670. + *
  52671. + * FIXME(rmk) - This should be bounded; we shouldn't wait
  52672. + * for an infinite amount of time for any device.
  52673. + */
  52674. + if (soft_reset) {
  52675. + SCSI_LOG_ERROR_RECOVERY(3,
  52676. + printk("scsi_unjam_host: unable to try "
  52677. + "hard host reset\n"));
  52678. /*
  52679. - * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
  52680. + * Due to the spinlock, we will never get out of this
  52681. + * loop without a proper wait. (DB)
  52682. */
  52683. - rtn = scsi_try_host_reset(SCpnt);
  52684. - if (rtn == SUCCESS) {
  52685. - /*
  52686. - * FIXME(eric) we assume that all commands are flushed from the
  52687. - * controller. We should get a DID_RESET for all of the commands
  52688. - * that were pending. We should ignore these so that we can
  52689. - * guarantee that we are in a consistent state.
  52690. - *
  52691. - * I believe this to be the case right now, but this needs to be
  52692. - * tested.
  52693. - */
  52694. - for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
  52695. - for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
  52696. - if (SCloop->state != SCSI_STATE_FAILED
  52697. - && SCloop->state != SCSI_STATE_TIMEOUT) {
  52698. - continue;
  52699. - }
  52700. - rtn = scsi_test_unit_ready(SCloop);
  52701. -
  52702. - if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
  52703. - rtn = scsi_eh_retry_command(SCloop);
  52704. -
  52705. - if (rtn == SUCCESS) {
  52706. - SCpnt->host->host_failed--;
  52707. - scsi_eh_finish_command(&SCdone, SCloop);
  52708. - }
  52709. - }
  52710. - if (rtn != SUCCESS) {
  52711. - printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after host reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
  52712. - SDloop->online = FALSE;
  52713. - SDloop->host->host_failed--;
  52714. - scsi_eh_finish_command(&SCdone, SCloop);
  52715. - }
  52716. - }
  52717. - }
  52718. - }
  52719. - }
  52720. - }
  52721. + scsi_sleep(1 * HZ);
  52722. - /*
  52723. - * If we solved all of the problems, then let's rev up the engines again.
  52724. - */
  52725. - if (host->host_failed == 0) {
  52726. - ourrtn = TRUE;
  52727. - goto leave;
  52728. + goto try_again;
  52729. }
  52730. +
  52731. + SCSI_LOG_ERROR_RECOVERY(3,
  52732. + printk("scsi_unjam_host: Try hard host reset\n"));
  52733. +
  52734. /*
  52735. - * If the HOST RESET failed, then for now we assume that the entire host
  52736. - * adapter is too hosed to be of any use. For our purposes, however, it is
  52737. - * easier to simply take the devices offline that correspond to commands
  52738. - * that failed.
  52739. + * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
  52740. */
  52741. - SCSI_LOG_ERROR_RECOVERY(1, printk("scsi_unjam_host: Take device offline\n"));
  52742. + rtn = scsi_try_host_reset(failed_command);
  52743. + if (rtn == SUCCESS) {
  52744. + /*
  52745. + * FIXME(eric) we assume that all commands are flushed from
  52746. + * the controller. We should get a DID_RESET for all of the
  52747. + * commands that were pending. We should ignore these so
  52748. + * that we can guarantee that we are in a consistent state.
  52749. + *
  52750. + * I believe this to be the case right now, but this needs
  52751. + * to be tested.
  52752. + */
  52753. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52754. + rtn = scsi_eh_restart_device(SDpnt, done);
  52755. - for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52756. - for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
  52757. - if (SCloop->state == SCSI_STATE_FAILED || SCloop->state == SCSI_STATE_TIMEOUT) {
  52758. - SDloop = SCloop->device;
  52759. - if (SDloop->online == TRUE) {
  52760. - printk(KERN_INFO "scsi: device set offline - command error recover failed: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
  52761. - SDloop->online = FALSE;
  52762. - }
  52763. + if (rtn != SUCCESS) {
  52764. + SCpnt = scsi_eh_find_failed_command(SDpnt);
  52765. /*
  52766. - * This should pass the failure up to the top level driver, and
  52767. - * it will have to try and do something intelligent with it.
  52768. + * This device failed again. Since a host
  52769. + * reset freed it up, chances are we've
  52770. + * hit the same problem, so try the same
  52771. + * solution. We also need to ensure that
  52772. + * the SCSI bus is in the BUS FREE state
  52773. + * so we can try to talk to other devices.
  52774. */
  52775. - SCloop->host->host_failed--;
  52776. -
  52777. - if (SCloop->state == SCSI_STATE_TIMEOUT) {
  52778. - SCloop->result |= (DRIVER_TIMEOUT << 24);
  52779. - }
  52780. - SCSI_LOG_ERROR_RECOVERY(3, printk("Finishing command for device %d %x\n",
  52781. - SDloop->id, SCloop->result));
  52782. -
  52783. - scsi_eh_finish_command(&SCdone, SCloop);
  52784. + scsi_try_host_reset(SCpnt);
  52785. + scsi_eh_set_device_offline(SDpnt, done,
  52786. + "not ready or command retry "
  52787. + "failed after host reset");
  52788. }
  52789. }
  52790. }
  52791. +}
  52792. +
  52793. +static void scsi_unjam_failure(struct Scsi_Host *host, Scsi_Cmnd **done)
  52794. +{
  52795. + Scsi_Device *SDpnt;
  52796. - if (host->host_failed != 0) {
  52797. + /*
  52798. + * If the HOST RESET failed, then for now we assume that the
  52799. + * entire host adapter is too hosed to be of any use. For our
  52800. + * purposes, however, it is easier to simply take the devices
  52801. + * offline that correspond to commands that failed.
  52802. + */
  52803. + SCSI_LOG_ERROR_RECOVERY(1,
  52804. + printk("scsi_unjam_host: Take device offline\n"));
  52805. +
  52806. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
  52807. + scsi_eh_set_device_offline(SDpnt, done,
  52808. + "command error recover failed");
  52809. +
  52810. + if (host->host_failed != 0)
  52811. panic("scsi_unjam_host: Miscount of number of failed commands.\n");
  52812. - }
  52813. +
  52814. SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Returning\n"));
  52815. +}
  52816. +
  52817. +static void (*unjam_method[])(struct Scsi_Host *, Scsi_Cmnd **) = {
  52818. + scsi_unjam_request_sense,
  52819. + scsi_unjam_count,
  52820. + scsi_unjam_abort,
  52821. + scsi_unjam_device_reset,
  52822. + scsi_unjam_bus_reset,
  52823. + scsi_unjam_host_reset,
  52824. + scsi_unjam_failure,
  52825. +};
  52826. +
  52827. +/*
  52828. + * Function: scsi_unjam_host
  52829. + *
  52830. + * Purpose: Attempt to fix a host which has a command that failed for
  52831. + * some reason.
  52832. + *
  52833. + * Arguments: host - host that needs unjamming.
  52834. + *
  52835. + * Returns: Nothing
  52836. + *
  52837. + * Notes: When we come in here, we *know* that all commands on the
  52838. + * bus have either completed, failed or timed out. We also
  52839. + * know that no further commands are being sent to the host,
  52840. + * so things are relatively quiet and we have freedom to
  52841. + * fiddle with things as we wish.
  52842. + *
  52843. + * Additional note: This is only the *default* implementation. It is possible
  52844. + * for individual drivers to supply their own version of this
  52845. + * function, and if the maintainer wishes to do this, it is
  52846. + * strongly suggested that this function be taken as a template
  52847. + * and modified. This function was designed to correctly handle
  52848. + * problems for about 95% of the different cases out there, and
  52849. + * it should always provide at least a reasonable amount of error
  52850. + * recovery.
  52851. + *
  52852. + * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
  52853. + * have scsi_finish_command() called for it. We do all of
  52854. + * the retry stuff here, so when we restart the host after we
  52855. + * return it should have an empty queue.
  52856. + */
  52857. +STATIC int scsi_unjam_host(struct Scsi_Host *host)
  52858. +{
  52859. + Scsi_Cmnd *SCdone = NULL;
  52860. + Scsi_Cmnd *SCpnt;
  52861. + Scsi_Device *SDpnt;
  52862. + int ourrtn = FALSE;
  52863. + int i;
  52864. - ourrtn = FALSE;
  52865. + ASSERT_LOCK(&io_request_lock, 0);
  52866. - leave:
  52867. + /*
  52868. + * First, protect against any sort of race condition. If any of the outstanding
  52869. + * commands are in states that indicate that we are not yet blocked (i.e. we are
  52870. + * not in a quiet state) then we got woken up in error. If we ever end up here,
  52871. + * we need to re-examine some of the assumptions.
  52872. + */
  52873. + for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
  52874. + for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
  52875. + if (SCpnt->state == SCSI_STATE_FAILED
  52876. + || SCpnt->state == SCSI_STATE_TIMEOUT
  52877. + || SCpnt->state == SCSI_STATE_INITIALIZING
  52878. + || SCpnt->state == SCSI_STATE_UNUSED) {
  52879. + continue;
  52880. + }
  52881. + /*
  52882. + * Rats. Something is still floating around out there. This could
  52883. + * be the result of the fact that the upper level drivers are still frobbing
  52884. + * commands that might have succeeded. There are two outcomes. One is that
  52885. + * the command block will eventually be freed, and the other one is that
  52886. + * the command will be queued and will be finished along the way.
  52887. + */
  52888. + SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
  52889. +
  52890. +/*
  52891. + * panic("SCSI Error handler woken too early\n");
  52892. + *
  52893. + * This is no longer a problem, since now the code cares only about
  52894. + * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
  52895. + * Other states are useful only to release active commands when devices are
  52896. + * set offline. If (host->host_active == host->host_busy) we can safely assume
  52897. + * that there are no commands in state other then TIMEOUT od FAILED. (DB)
  52898. + *
  52899. + * FIXME:
  52900. + * It is not easy to release correctly commands according to their state when
  52901. + * devices are set offline, when the state is neither TIMEOUT nor FAILED.
  52902. + * When a device is set offline, we can have some command with
  52903. + * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
  52904. + * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
  52905. + * (DB, 17 May 1998)
  52906. + */
  52907. + }
  52908. + }
  52909. +
  52910. + for (i = 0; i < ARRAY_SIZE(unjam_method); i++) {
  52911. + unjam_method[i](host, &SCdone);
  52912. +
  52913. + /*
  52914. + * If we solved all of the problems, then
  52915. + * let's rev up the engines again.
  52916. + */
  52917. + if (host->host_failed == 0) {
  52918. + ourrtn = TRUE;
  52919. + break;
  52920. + }
  52921. + }
  52922. /*
  52923. * We should have a list of commands that we 'finished' during the course of
  52924. @@ -2013,3 +2300,17 @@
  52925. * tab-width: 8
  52926. * End:
  52927. */
  52928. +
  52929. +EXPORT_SYMBOL(scsi_eh_times_out);
  52930. +EXPORT_SYMBOL(scsi_eh_retry_command);
  52931. +EXPORT_SYMBOL(scsi_request_sense);
  52932. +EXPORT_SYMBOL(scsi_test_unit_ready);
  52933. +EXPORT_SYMBOL(scsi_unit_is_ready);
  52934. +EXPORT_SYMBOL(scsi_eh_finish_command);
  52935. +EXPORT_SYMBOL(scsi_try_to_abort_command);
  52936. +EXPORT_SYMBOL(scsi_try_bus_device_reset);
  52937. +EXPORT_SYMBOL(scsi_try_bus_reset);
  52938. +EXPORT_SYMBOL(scsi_try_host_reset);
  52939. +EXPORT_SYMBOL(scsi_sense_valid);
  52940. +EXPORT_SYMBOL(scsi_done);
  52941. +EXPORT_SYMBOL(scsi_decide_disposition);
  52942. diff -urN linux-2.4.26/drivers/scsi/scsi_ioctl.c linux-2.4.26-vrs1/drivers/scsi/scsi_ioctl.c
  52943. --- linux-2.4.26/drivers/scsi/scsi_ioctl.c 2003-08-25 12:44:42.000000000 +0100
  52944. +++ linux-2.4.26-vrs1/drivers/scsi/scsi_ioctl.c 2004-01-14 21:39:12.000000000 +0000
  52945. @@ -153,6 +153,29 @@
  52946. return result;
  52947. }
  52948. +int scsi_set_medium_removal(Scsi_Device *dev, char state)
  52949. +{
  52950. + char scsi_cmd[MAX_COMMAND_SIZE];
  52951. + int ret;
  52952. +
  52953. + if (!dev->removable || !dev->lockable)
  52954. + return 0;
  52955. +
  52956. + scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
  52957. + scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
  52958. + scsi_cmd[2] = 0;
  52959. + scsi_cmd[3] = 0;
  52960. + scsi_cmd[4] = state;
  52961. + scsi_cmd[5] = 0;
  52962. +
  52963. + ret = ioctl_internal_command(dev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
  52964. +
  52965. + if (ret == 0)
  52966. + dev->locked = state == SCSI_REMOVAL_PREVENT;
  52967. +
  52968. + return ret;
  52969. +}
  52970. +
  52971. /*
  52972. * This interface is depreciated - users should use the scsi generic (sg)
  52973. * interface instead, as this is a more flexible approach to performing
  52974. @@ -450,24 +473,9 @@
  52975. return scsi_ioctl_send_command((Scsi_Device *) dev,
  52976. (Scsi_Ioctl_Command *) arg);
  52977. case SCSI_IOCTL_DOORLOCK:
  52978. - if (!dev->removable || !dev->lockable)
  52979. - return 0;
  52980. - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
  52981. - scsi_cmd[1] = cmd_byte1;
  52982. - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
  52983. - scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
  52984. - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
  52985. - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
  52986. - break;
  52987. + return scsi_set_medium_removal(dev, SCSI_REMOVAL_PREVENT);
  52988. case SCSI_IOCTL_DOORUNLOCK:
  52989. - if (!dev->removable || !dev->lockable)
  52990. - return 0;
  52991. - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
  52992. - scsi_cmd[1] = cmd_byte1;
  52993. - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
  52994. - scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
  52995. - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
  52996. - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
  52997. + return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
  52998. case SCSI_IOCTL_TEST_UNIT_READY:
  52999. scsi_cmd[0] = TEST_UNIT_READY;
  53000. scsi_cmd[1] = cmd_byte1;
  53001. diff -urN linux-2.4.26/drivers/scsi/scsi_lib.c linux-2.4.26-vrs1/drivers/scsi/scsi_lib.c
  53002. --- linux-2.4.26/drivers/scsi/scsi_lib.c 2004-04-19 11:44:16.000000000 +0100
  53003. +++ linux-2.4.26-vrs1/drivers/scsi/scsi_lib.c 2004-04-18 21:47:51.000000000 +0100
  53004. @@ -208,6 +208,30 @@
  53005. }
  53006. /*
  53007. + * Function: scsi_setup_cmd_retry()
  53008. + *
  53009. + * Purpose: Restore the command state for a retry
  53010. + *
  53011. + * Arguments: SCpnt - command to be restored
  53012. + *
  53013. + * Returns: Nothing
  53014. + *
  53015. + * Notes: Immediately prior to retrying a command, we need
  53016. + * to restore certain fields that we saved above.
  53017. + */
  53018. +void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt)
  53019. +{
  53020. + memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
  53021. + sizeof(SCpnt->data_cmnd));
  53022. + SCpnt->request_buffer = SCpnt->buffer;
  53023. + SCpnt->request_bufflen = SCpnt->bufflen;
  53024. + SCpnt->use_sg = SCpnt->old_use_sg;
  53025. + SCpnt->cmd_len = SCpnt->old_cmd_len;
  53026. + SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
  53027. + SCpnt->underflow = SCpnt->old_underflow;
  53028. +}
  53029. +
  53030. +/*
  53031. * Function: scsi_queue_next_request()
  53032. *
  53033. * Purpose: Handle post-processing of completed commands.
  53034. @@ -731,7 +755,7 @@
  53035. printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",
  53036. SCpnt->host->host_no, (int) SCpnt->channel,
  53037. (int) SCpnt->target, (int) SCpnt->lun);
  53038. - print_command(SCpnt->cmnd);
  53039. + print_command(SCpnt->data_cmnd);
  53040. print_sense("sd", SCpnt);
  53041. SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
  53042. return;
  53043. @@ -906,8 +930,17 @@
  53044. * space. Technically the error handling thread should be
  53045. * doing this crap, but the error handler isn't used by
  53046. * most hosts.
  53047. + *
  53048. + * (rmk)
  53049. + * Trying to lock the door can cause deadlocks. We therefore
  53050. + * only use this for old hosts; our door locking is now done
  53051. + * by the error handler in scsi_restart_operations for new
  53052. + * eh hosts.
  53053. + *
  53054. + * Note that we don't clear was_reset here; this is used by
  53055. + * st.c, and either one or other has to die.
  53056. */
  53057. - if (SDpnt->was_reset) {
  53058. + if (SHpnt->hostt->use_new_eh_code == 0 && SDpnt->was_reset) {
  53059. /*
  53060. * We need to relock the door, but we might
  53061. * be in an interrupt handler. Only do this
  53062. @@ -918,7 +951,7 @@
  53063. * this work.
  53064. */
  53065. SDpnt->was_reset = 0;
  53066. - if (SDpnt->removable && !in_interrupt()) {
  53067. + if (SDpnt->removable && SDpnt->locked && !in_interrupt()) {
  53068. spin_unlock_irq(&io_request_lock);
  53069. scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
  53070. spin_lock_irq(&io_request_lock);
  53071. diff -urN linux-2.4.26/drivers/scsi/scsi_syms.c linux-2.4.26-vrs1/drivers/scsi/scsi_syms.c
  53072. --- linux-2.4.26/drivers/scsi/scsi_syms.c 2004-04-19 11:44:16.000000000 +0100
  53073. +++ linux-2.4.26-vrs1/drivers/scsi/scsi_syms.c 2004-04-18 21:47:51.000000000 +0100
  53074. @@ -104,3 +104,6 @@
  53075. extern int scsi_delete_timer(Scsi_Cmnd *);
  53076. EXPORT_SYMBOL(scsi_add_timer);
  53077. EXPORT_SYMBOL(scsi_delete_timer);
  53078. +
  53079. +extern int scsi_set_medium_removal(Scsi_Device *dev, char state);
  53080. +EXPORT_SYMBOL(scsi_set_medium_removal);
  53081. diff -urN linux-2.4.26/drivers/scsi/sd.c linux-2.4.26-vrs1/drivers/scsi/sd.c
  53082. --- linux-2.4.26/drivers/scsi/sd.c 2003-08-25 12:44:42.000000000 +0100
  53083. +++ linux-2.4.26-vrs1/drivers/scsi/sd.c 2004-01-14 21:39:12.000000000 +0000
  53084. @@ -399,6 +399,7 @@
  53085. this_count = 0xffff;
  53086. SCpnt->cmnd[0] += READ_10 - READ_6;
  53087. + SCpnt->cmnd[1] |= 1 << 3; /* Set FUA --rmk */
  53088. SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
  53089. SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
  53090. SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
  53091. @@ -524,7 +525,7 @@
  53092. if (SDev->removable)
  53093. if (SDev->access_count==1)
  53094. if (scsi_block_when_processing_errors(SDev))
  53095. - scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);
  53096. + scsi_set_medium_removal(SDev, SCSI_REMOVAL_PREVENT);
  53097. return 0;
  53098. @@ -553,7 +554,7 @@
  53099. if (SDev->removable) {
  53100. if (!SDev->access_count)
  53101. if (scsi_block_when_processing_errors(SDev))
  53102. - scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL);
  53103. + scsi_set_medium_removal(SDev, SCSI_REMOVAL_ALLOW);
  53104. }
  53105. if (SDev->host->hostt->module)
  53106. __MOD_DEC_USE_COUNT(SDev->host->hostt->module);
  53107. diff -urN linux-2.4.26/drivers/scsi/sr_ioctl.c linux-2.4.26-vrs1/drivers/scsi/sr_ioctl.c
  53108. --- linux-2.4.26/drivers/scsi/sr_ioctl.c 2002-11-28 23:53:14.000000000 +0000
  53109. +++ linux-2.4.26-vrs1/drivers/scsi/sr_ioctl.c 2004-01-14 21:32:26.000000000 +0000
  53110. @@ -214,9 +214,8 @@
  53111. int sr_lock_door(struct cdrom_device_info *cdi, int lock)
  53112. {
  53113. - return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
  53114. - lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
  53115. - 0);
  53116. + return scsi_set_medium_removal(scsi_CDs[MINOR(cdi->dev)].device,
  53117. + lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
  53118. }
  53119. int sr_drive_status(struct cdrom_device_info *cdi, int slot)
  53120. diff -urN linux-2.4.26/drivers/serial/21285.c linux-2.4.26-vrs1/drivers/serial/21285.c
  53121. --- linux-2.4.26/drivers/serial/21285.c 1970-01-01 01:00:00.000000000 +0100
  53122. +++ linux-2.4.26-vrs1/drivers/serial/21285.c 2004-04-04 23:11:12.000000000 +0100
  53123. @@ -0,0 +1,599 @@
  53124. +/*
  53125. + * linux/drivers/char/serial_21285.c
  53126. + *
  53127. + * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
  53128. + *
  53129. + * Based on drivers/char/serial.c
  53130. + *
  53131. + * $Id: 21285.c,v 1.4.2.1 2002/10/24 09:53:23 rmk Exp $
  53132. + */
  53133. +#include <linux/config.h>
  53134. +#include <linux/module.h>
  53135. +#include <linux/errno.h>
  53136. +#include <linux/signal.h>
  53137. +#include <linux/sched.h>
  53138. +#include <linux/interrupt.h>
  53139. +#include <linux/tty.h>
  53140. +#include <linux/tty_flip.h>
  53141. +#include <linux/serial.h>
  53142. +#include <linux/major.h>
  53143. +#include <linux/ptrace.h>
  53144. +#include <linux/ioport.h>
  53145. +#include <linux/mm.h>
  53146. +#include <linux/slab.h>
  53147. +#include <linux/init.h>
  53148. +#include <linux/console.h>
  53149. +
  53150. +#include <asm/io.h>
  53151. +#include <asm/irq.h>
  53152. +#include <asm/uaccess.h>
  53153. +#include <asm/hardware/dec21285.h>
  53154. +#include <asm/hardware.h>
  53155. +
  53156. +#define BAUD_BASE (mem_fclk_21285/64)
  53157. +
  53158. +#ifdef CONFIG_DEVFS_FS
  53159. +#define SERIAL_21285_NAME "tts/FB%d"
  53160. +#define SERIAL_21285_AUXNAME "cua/FB%d"
  53161. +#else
  53162. +#define SERIAL_21285_NAME "ttyFB"
  53163. +#define SERIAL_21285_AUXNAME "cuafb"
  53164. +#endif
  53165. +
  53166. +#define SERIAL_21285_MAJOR 204
  53167. +#define SERIAL_21285_MINOR 4
  53168. +
  53169. +#define SERIAL_21285_AUXMAJOR 205
  53170. +#define SERIAL_21285_AUXMINOR 4
  53171. +
  53172. +#ifdef CONFIG_SERIAL_21285_OLD
  53173. +#include <asm/mach-types.h>
  53174. +/*
  53175. + * Compatability with a mistake made a long time ago.
  53176. + * Note - the use of "ttyI", "/dev/ttyS0" and major/minor 5,64
  53177. + * is HIGHLY DEPRECIATED, and will be removed in the 2.5
  53178. + * kernel series.
  53179. + * -- rmk 15/04/2000
  53180. + */
  53181. +#define SERIAL_21285_OLD_NAME "ttyI"
  53182. +#define SERIAL_21285_OLD_MAJOR TTY_MAJOR
  53183. +#define SERIAL_21285_OLD_MINOR 64
  53184. +
  53185. +static struct tty_driver rs285_old_driver;
  53186. +#endif
  53187. +
  53188. +static struct tty_driver rs285_driver, callout_driver;
  53189. +static int rs285_refcount;
  53190. +static struct tty_struct *rs285_table[1];
  53191. +
  53192. +static struct termios *rs285_termios[1];
  53193. +static struct termios *rs285_termios_locked[1];
  53194. +
  53195. +static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
  53196. +static struct tty_struct *rs285_tty;
  53197. +static DECLARE_MUTEX(rs285_sem);
  53198. +static int rs285_use_count;
  53199. +static unsigned long rs285_irq_enabled;
  53200. +
  53201. +#define TX_IRQ_BIT (0)
  53202. +#define RX_IRQ_BIT (1)
  53203. +
  53204. +static void rs285_stop_tx(void)
  53205. +{
  53206. + if (test_and_clear_bit(TX_IRQ_BIT, &rs285_irq_enabled))
  53207. + disable_irq(IRQ_CONTX);
  53208. +}
  53209. +
  53210. +static void rs285_start_tx(void)
  53211. +{
  53212. + if (!test_and_set_bit(TX_IRQ_BIT, &rs285_irq_enabled))
  53213. + enable_irq(IRQ_CONTX);
  53214. +}
  53215. +
  53216. +static void rs285_stop_rx(void)
  53217. +{
  53218. + if (test_and_clear_bit(RX_IRQ_BIT, &rs285_irq_enabled))
  53219. + disable_irq(IRQ_CONRX);
  53220. +}
  53221. +
  53222. +static void rs285_start_rx(void)
  53223. +{
  53224. + if (!test_and_set_bit(RX_IRQ_BIT, &rs285_irq_enabled))
  53225. + enable_irq(IRQ_CONRX);
  53226. +}
  53227. +
  53228. +static int rs285_write_room(struct tty_struct *tty)
  53229. +{
  53230. + return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
  53231. +}
  53232. +
  53233. +static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
  53234. +{
  53235. + if (!rs285_tty) {
  53236. + rs285_stop_rx();
  53237. + return;
  53238. + }
  53239. + while (!(*CSR_UARTFLG & 0x10)) {
  53240. + int ch, flag;
  53241. + ch = *CSR_UARTDR;
  53242. + flag = *CSR_RXSTAT;
  53243. + if (flag & 4)
  53244. + tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
  53245. + if (flag & 2)
  53246. + flag = TTY_PARITY;
  53247. + else if (flag & 1)
  53248. + flag = TTY_FRAME;
  53249. + tty_insert_flip_char(rs285_tty, ch, flag);
  53250. + }
  53251. + tty_flip_buffer_push(rs285_tty);
  53252. +}
  53253. +
  53254. +static void rs285_send_xchar(struct tty_struct *tty, char ch)
  53255. +{
  53256. + x_char = ch;
  53257. + rs285_start_tx();
  53258. +}
  53259. +
  53260. +static void rs285_throttle(struct tty_struct *tty)
  53261. +{
  53262. + if (I_IXOFF(tty))
  53263. + rs285_send_xchar(tty, STOP_CHAR(tty));
  53264. +}
  53265. +
  53266. +static void rs285_unthrottle(struct tty_struct *tty)
  53267. +{
  53268. + if (I_IXOFF(tty)) {
  53269. + if (x_char)
  53270. + x_char = 0;
  53271. + else
  53272. + rs285_send_xchar(tty, START_CHAR(tty));
  53273. + }
  53274. +}
  53275. +
  53276. +static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
  53277. +{
  53278. + while (!(*CSR_UARTFLG & 0x20)) {
  53279. + if (x_char) {
  53280. + *CSR_UARTDR = x_char;
  53281. + x_char = 0;
  53282. + continue;
  53283. + }
  53284. + if (putp == getp) {
  53285. + rs285_stop_tx();
  53286. + break;
  53287. + }
  53288. + *CSR_UARTDR = *getp;
  53289. + if (++getp >= wbuf + sizeof(wbuf))
  53290. + getp = wbuf;
  53291. + }
  53292. + if (rs285_tty)
  53293. + wake_up_interruptible(&rs285_tty->write_wait);
  53294. +}
  53295. +
  53296. +static inline int rs285_xmit(int ch)
  53297. +{
  53298. + if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
  53299. + return 0;
  53300. + *putp = ch;
  53301. + if (++putp >= wbuf + sizeof(wbuf))
  53302. + putp = wbuf;
  53303. + rs285_start_tx();
  53304. + return 1;
  53305. +}
  53306. +
  53307. +static int rs285_write(struct tty_struct *tty, int from_user,
  53308. + const u_char * buf, int count)
  53309. +{
  53310. + int i;
  53311. +
  53312. + if (from_user && verify_area(VERIFY_READ, buf, count))
  53313. + return -EINVAL;
  53314. +
  53315. + for (i = 0; i < count; i++) {
  53316. + char ch;
  53317. + if (from_user)
  53318. + __get_user(ch, buf + i);
  53319. + else
  53320. + ch = buf[i];
  53321. + if (!rs285_xmit(ch))
  53322. + break;
  53323. + }
  53324. + return i;
  53325. +}
  53326. +
  53327. +static void rs285_put_char(struct tty_struct *tty, u_char ch)
  53328. +{
  53329. + rs285_xmit(ch);
  53330. +}
  53331. +
  53332. +static int rs285_chars_in_buffer(struct tty_struct *tty)
  53333. +{
  53334. + return sizeof(wbuf) - rs285_write_room(tty);
  53335. +}
  53336. +
  53337. +static void rs285_flush_buffer(struct tty_struct *tty)
  53338. +{
  53339. + rs285_stop_tx();
  53340. + putp = getp = wbuf;
  53341. + if (x_char)
  53342. + rs285_start_tx();
  53343. +}
  53344. +
  53345. +static inline void rs285_set_cflag(int cflag)
  53346. +{
  53347. + int h_lcr, baud, quot;
  53348. +
  53349. + switch (cflag & CSIZE) {
  53350. + case CS5:
  53351. + h_lcr = 0x10;
  53352. + break;
  53353. + case CS6:
  53354. + h_lcr = 0x30;
  53355. + break;
  53356. + case CS7:
  53357. + h_lcr = 0x50;
  53358. + break;
  53359. + default: /* CS8 */
  53360. + h_lcr = 0x70;
  53361. + break;
  53362. +
  53363. + }
  53364. + if (cflag & CSTOPB)
  53365. + h_lcr |= 0x08;
  53366. + if (cflag & PARENB)
  53367. + h_lcr |= 0x02;
  53368. + if (!(cflag & PARODD))
  53369. + h_lcr |= 0x04;
  53370. +
  53371. + switch (cflag & CBAUD) {
  53372. + case B200: baud = 200; break;
  53373. + case B300: baud = 300; break;
  53374. + case B1200: baud = 1200; break;
  53375. + case B1800: baud = 1800; break;
  53376. + case B2400: baud = 2400; break;
  53377. + case B4800: baud = 4800; break;
  53378. + default:
  53379. + case B9600: baud = 9600; break;
  53380. + case B19200: baud = 19200; break;
  53381. + case B38400: baud = 38400; break;
  53382. + case B57600: baud = 57600; break;
  53383. + case B115200: baud = 115200; break;
  53384. + }
  53385. +
  53386. + /*
  53387. + * The documented expression for selecting the divisor is:
  53388. + * BAUD_BASE / baud - 1
  53389. + * However, typically BAUD_BASE is not divisible by baud, so
  53390. + * we want to select the divisor that gives us the minimum
  53391. + * error. Therefore, we want:
  53392. + * int(BAUD_BASE / baud - 0.5) ->
  53393. + * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
  53394. + * int((BAUD_BASE - (baud >> 1)) / baud)
  53395. + */
  53396. + quot = (BAUD_BASE - (baud >> 1)) / baud;
  53397. +
  53398. + *CSR_UARTCON = 0;
  53399. + *CSR_L_UBRLCR = quot & 0xff;
  53400. + *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
  53401. + *CSR_H_UBRLCR = h_lcr;
  53402. + *CSR_UARTCON = 1;
  53403. +}
  53404. +
  53405. +static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
  53406. +{
  53407. + if (old && tty->termios->c_cflag == old->c_cflag)
  53408. + return;
  53409. + rs285_set_cflag(tty->termios->c_cflag);
  53410. +}
  53411. +
  53412. +
  53413. +static void rs285_stop(struct tty_struct *tty)
  53414. +{
  53415. + rs285_stop_tx();
  53416. +}
  53417. +
  53418. +static void rs285_start(struct tty_struct *tty)
  53419. +{
  53420. + rs285_start_tx();
  53421. +}
  53422. +
  53423. +static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
  53424. +{
  53425. + int orig_jiffies = jiffies;
  53426. + while (*CSR_UARTFLG & 8) {
  53427. + set_current_state(TASK_INTERRUPTIBLE);
  53428. + schedule_timeout(1);
  53429. + if (signal_pending(current))
  53430. + break;
  53431. + if (timeout && time_after(jiffies, orig_jiffies + timeout))
  53432. + break;
  53433. + }
  53434. + set_current_state(TASK_RUNNING);
  53435. +}
  53436. +
  53437. +static int rs285_open(struct tty_struct *tty, struct file *filp)
  53438. +{
  53439. + int line, ret;
  53440. +
  53441. + MOD_INC_USE_COUNT;
  53442. +
  53443. + line = MINOR(tty->device) - tty->driver.minor_start;
  53444. + if (line)
  53445. + return -ENODEV;
  53446. +
  53447. + ret = down_interruptible(&rs285_sem);
  53448. + if (ret)
  53449. + return ret;
  53450. +
  53451. + tty->driver_data = NULL;
  53452. + rs285_tty = tty;
  53453. +
  53454. + if (rs285_use_count == 0) {
  53455. + rs285_irq_enabled = 3;
  53456. + ret = request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL);
  53457. + if (ret == 0) {
  53458. + ret = request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285",
  53459. + NULL);
  53460. + if (ret)
  53461. + free_irq(IRQ_CONRX, NULL);
  53462. + }
  53463. + }
  53464. +
  53465. + if (ret == 0)
  53466. + rs285_use_count++;
  53467. +
  53468. + up(&rs285_sem);
  53469. +
  53470. + return ret;
  53471. +}
  53472. +
  53473. +static void rs285_close(struct tty_struct *tty, struct file *filp)
  53474. +{
  53475. + down(&rs285_sem);
  53476. + if (!--rs285_use_count) {
  53477. + rs285_wait_until_sent(tty, 0);
  53478. + rs285_stop_rx();
  53479. + rs285_stop_tx();
  53480. + rs285_tty = NULL;
  53481. + free_irq(IRQ_CONTX, NULL);
  53482. + free_irq(IRQ_CONRX, NULL);
  53483. + }
  53484. + up(&rs285_sem);
  53485. + MOD_DEC_USE_COUNT;
  53486. +}
  53487. +
  53488. +static int __init rs285_init(void)
  53489. +{
  53490. + int baud = B9600;
  53491. +
  53492. + if (machine_is_personal_server())
  53493. + baud = B57600;
  53494. +
  53495. + rs285_driver.magic = TTY_DRIVER_MAGIC;
  53496. + rs285_driver.driver_name = "serial_21285";
  53497. + rs285_driver.name = SERIAL_21285_NAME;
  53498. + rs285_driver.major = SERIAL_21285_MAJOR;
  53499. + rs285_driver.minor_start = SERIAL_21285_MINOR;
  53500. + rs285_driver.num = 1;
  53501. + rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
  53502. + rs285_driver.subtype = SERIAL_TYPE_NORMAL;
  53503. + rs285_driver.init_termios = tty_std_termios;
  53504. + rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
  53505. + rs285_driver.flags = TTY_DRIVER_REAL_RAW;
  53506. + rs285_driver.refcount = &rs285_refcount;
  53507. + rs285_driver.table = rs285_table;
  53508. + rs285_driver.termios = rs285_termios;
  53509. + rs285_driver.termios_locked = rs285_termios_locked;
  53510. +
  53511. + rs285_driver.open = rs285_open;
  53512. + rs285_driver.close = rs285_close;
  53513. + rs285_driver.write = rs285_write;
  53514. + rs285_driver.put_char = rs285_put_char;
  53515. + rs285_driver.write_room = rs285_write_room;
  53516. + rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
  53517. + rs285_driver.flush_buffer = rs285_flush_buffer;
  53518. + rs285_driver.throttle = rs285_throttle;
  53519. + rs285_driver.unthrottle = rs285_unthrottle;
  53520. + rs285_driver.send_xchar = rs285_send_xchar;
  53521. + rs285_driver.set_termios = rs285_set_termios;
  53522. + rs285_driver.stop = rs285_stop;
  53523. + rs285_driver.start = rs285_start;
  53524. + rs285_driver.wait_until_sent = rs285_wait_until_sent;
  53525. +
  53526. + callout_driver = rs285_driver;
  53527. + callout_driver.name = SERIAL_21285_AUXNAME;
  53528. + callout_driver.major = SERIAL_21285_AUXMAJOR;
  53529. + callout_driver.subtype = SERIAL_TYPE_CALLOUT;
  53530. +
  53531. +#ifdef CONFIG_SERIAL_21285_OLD
  53532. + if (!machine_is_ebsa285() && !machine_is_netwinder()) {
  53533. + rs285_old_driver = rs285_driver;
  53534. + rs285_old_driver.name = SERIAL_21285_OLD_NAME;
  53535. + rs285_old_driver.major = SERIAL_21285_OLD_MAJOR;
  53536. + rs285_old_driver.minor_start = SERIAL_21285_OLD_MINOR;
  53537. +
  53538. + if (tty_register_driver(&rs285_old_driver))
  53539. + printk(KERN_ERR "Couldn't register old 21285 serial driver\n");
  53540. + }
  53541. +#endif
  53542. +
  53543. + if (tty_register_driver(&rs285_driver))
  53544. + printk(KERN_ERR "Couldn't register 21285 serial driver\n");
  53545. + if (tty_register_driver(&callout_driver))
  53546. + printk(KERN_ERR "Couldn't register 21285 callout driver\n");
  53547. +
  53548. + return 0;
  53549. +}
  53550. +
  53551. +static void __exit rs285_fini(void)
  53552. +{
  53553. + unsigned long flags;
  53554. + int ret;
  53555. +
  53556. + save_flags(flags);
  53557. + cli();
  53558. + ret = tty_unregister_driver(&callout_driver);
  53559. + if (ret)
  53560. + printk(KERN_ERR "Unable to unregister 21285 callout driver "
  53561. + "(%d)\n", ret);
  53562. + ret = tty_unregister_driver(&rs285_driver);
  53563. + if (ret)
  53564. + printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
  53565. + ret);
  53566. +#ifdef CONFIG_SERIAL_21285_OLD
  53567. + if (!machine_is_ebsa285() && !machine_is_netwinder()) {
  53568. + ret = tty_unregister_driver(&rs285_old_driver);
  53569. + if (ret)
  53570. + printk(KERN_ERR "Unable to unregister old 21285 "
  53571. + "driver (%d)\n", ret);
  53572. + }
  53573. +#endif
  53574. + free_irq(IRQ_CONTX, NULL);
  53575. + free_irq(IRQ_CONRX, NULL);
  53576. + restore_flags(flags);
  53577. +}
  53578. +
  53579. +module_init(rs285_init);
  53580. +module_exit(rs285_fini);
  53581. +
  53582. +#ifdef CONFIG_SERIAL_21285_CONSOLE
  53583. +/************** console driver *****************/
  53584. +
  53585. +static void rs285_console_write(struct console *co, const char *s, u_int count)
  53586. +{
  53587. + int i;
  53588. +
  53589. + rs285_stop_tx();
  53590. + for (i = 0; i < count; i++) {
  53591. + while (*CSR_UARTFLG & 0x20);
  53592. + *CSR_UARTDR = s[i];
  53593. + if (s[i] == '\n') {
  53594. + while (*CSR_UARTFLG & 0x20);
  53595. + *CSR_UARTDR = '\r';
  53596. + }
  53597. + }
  53598. + rs285_start_tx();
  53599. +}
  53600. +
  53601. +static kdev_t rs285_console_device(struct console *c)
  53602. +{
  53603. + return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
  53604. +}
  53605. +
  53606. +static int __init rs285_console_setup(struct console *co, char *options)
  53607. +{
  53608. + int baud = 9600;
  53609. + int bits = 8;
  53610. + int parity = 'n';
  53611. + int flow;
  53612. + int cflag = CREAD | HUPCL | CLOCAL;
  53613. +
  53614. + if (machine_is_personal_server())
  53615. + baud = 57600;
  53616. +
  53617. + if (options)
  53618. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  53619. +
  53620. + /*
  53621. + * Now construct a cflag setting.
  53622. + */
  53623. + switch (baud) {
  53624. + case 1200:
  53625. + cflag |= B1200;
  53626. + break;
  53627. + case 2400:
  53628. + cflag |= B2400;
  53629. + break;
  53630. + case 4800:
  53631. + cflag |= B4800;
  53632. + break;
  53633. + case 9600:
  53634. + cflag |= B9600;
  53635. + break;
  53636. + case 19200:
  53637. + cflag |= B19200;
  53638. + break;
  53639. + case 38400:
  53640. + cflag |= B38400;
  53641. + break;
  53642. + case 57600:
  53643. + cflag |= B57600;
  53644. + break;
  53645. + case 115200:
  53646. + cflag |= B115200;
  53647. + break;
  53648. + default:
  53649. + cflag |= B9600;
  53650. + break;
  53651. + }
  53652. + switch (bits) {
  53653. + case 7:
  53654. + cflag |= CS7;
  53655. + break;
  53656. + default:
  53657. + cflag |= CS8;
  53658. + break;
  53659. + }
  53660. + switch (parity) {
  53661. + case 'o':
  53662. + case 'O':
  53663. + cflag |= PARODD;
  53664. + break;
  53665. + case 'e':
  53666. + case 'E':
  53667. + cflag |= PARENB;
  53668. + break;
  53669. + }
  53670. + co->cflag = cflag;
  53671. + rs285_set_cflag(cflag);
  53672. + rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
  53673. + if (options)
  53674. + rs285_console_write(NULL, options, strlen(options));
  53675. + else
  53676. + rs285_console_write(NULL, "no options", 10);
  53677. + rs285_console_write(NULL, "\n", 1);
  53678. +
  53679. + return 0;
  53680. +}
  53681. +
  53682. +#ifdef CONFIG_SERIAL_21285_OLD
  53683. +static struct console rs285_old_cons =
  53684. +{
  53685. + SERIAL_21285_OLD_NAME,
  53686. + rs285_console_write,
  53687. + NULL,
  53688. + rs285_console_device,
  53689. + NULL,
  53690. + rs285_console_setup,
  53691. + CON_PRINTBUFFER,
  53692. + -1,
  53693. + 0,
  53694. + NULL
  53695. +};
  53696. +#endif
  53697. +
  53698. +static struct console rs285_cons =
  53699. +{
  53700. + name: SERIAL_21285_NAME,
  53701. + write: rs285_console_write,
  53702. + device: rs285_console_device,
  53703. + setup: rs285_console_setup,
  53704. + flags: CON_PRINTBUFFER,
  53705. + index: -1,
  53706. +};
  53707. +
  53708. +void __init rs285_console_init(void)
  53709. +{
  53710. +#ifdef CONFIG_SERIAL_21285_OLD
  53711. + if (!machine_is_ebsa285() && !machine_is_netwinder())
  53712. + register_console(&rs285_old_cons);
  53713. +#endif
  53714. + register_console(&rs285_cons);
  53715. +}
  53716. +
  53717. +#endif /* CONFIG_SERIAL_21285_CONSOLE */
  53718. +
  53719. +EXPORT_NO_SYMBOLS;
  53720. +
  53721. +MODULE_LICENSE("GPL");
  53722. +MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
  53723. diff -urN linux-2.4.26/drivers/serial/8250.c linux-2.4.26-vrs1/drivers/serial/8250.c
  53724. --- linux-2.4.26/drivers/serial/8250.c 1970-01-01 01:00:00.000000000 +0100
  53725. +++ linux-2.4.26-vrs1/drivers/serial/8250.c 2004-01-14 21:32:26.000000000 +0000
  53726. @@ -0,0 +1,2170 @@
  53727. +/*
  53728. + * linux/drivers/serial/8250.c
  53729. + *
  53730. + * Driver for 8250/16550-type serial ports
  53731. + *
  53732. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  53733. + *
  53734. + * Copyright (C) 2001 Russell King.
  53735. + *
  53736. + * This program is free software; you can redistribute it and/or modify
  53737. + * it under the terms of the GNU General Public License as published by
  53738. + * the Free Software Foundation; either version 2 of the License, or
  53739. + * (at your option) any later version.
  53740. + *
  53741. + * $Id: 8250.c,v 1.14.2.8 2002/10/24 14:31:31 rmk Exp $
  53742. + *
  53743. + * A note about mapbase / membase
  53744. + *
  53745. + * mapbase is the physical address of the IO port. Currently, we don't
  53746. + * support this very well, and it may well be dropped from this driver
  53747. + * in future. As such, mapbase should be NULL.
  53748. + *
  53749. + * membase is an 'ioremapped' cookie. This is compatible with the old
  53750. + * serial.c driver, and is currently the preferred form.
  53751. + */
  53752. +#include <linux/config.h>
  53753. +#include <linux/module.h>
  53754. +#include <linux/errno.h>
  53755. +#include <linux/sched.h>
  53756. +#include <linux/tty.h>
  53757. +#include <linux/tty_flip.h>
  53758. +#include <linux/major.h>
  53759. +#include <linux/ptrace.h>
  53760. +#include <linux/ioport.h>
  53761. +#include <linux/init.h>
  53762. +#include <linux/serial.h>
  53763. +#include <linux/console.h>
  53764. +#include <linux/sysrq.h>
  53765. +#include <linux/serial_reg.h>
  53766. +#include <linux/serialP.h>
  53767. +#include <linux/delay.h>
  53768. +#include <linux/serial_core.h>
  53769. +#include <linux/kmod.h>
  53770. +
  53771. +#include <asm/system.h>
  53772. +#include <asm/io.h>
  53773. +#include <asm/irq.h>
  53774. +#include <asm/uaccess.h>
  53775. +#include <asm/bitops.h>
  53776. +
  53777. +#include "8250.h"
  53778. +
  53779. +/*
  53780. + * Configuration:
  53781. + * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option
  53782. + * is unsafe when used on edge-triggered interrupts.
  53783. + */
  53784. +unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
  53785. +
  53786. +/*
  53787. + * Debugging.
  53788. + */
  53789. +#if 0
  53790. +#define DEBUG_AUTOCONF(fmt...) printk(fmt)
  53791. +#else
  53792. +#define DEBUG_AUTOCONF(fmt...) do { } while (0)
  53793. +#endif
  53794. +
  53795. +#if 0
  53796. +#define DEBUG_INTR(fmt...) printk(fmt)
  53797. +#else
  53798. +#define DEBUG_INTR(fmt...) do { } while (0)
  53799. +#endif
  53800. +
  53801. +#define PASS_LIMIT 256
  53802. +
  53803. +/*
  53804. + * We default to IRQ0 for the "no irq" hack. Some
  53805. + * machine types want others as well - they're free
  53806. + * to redefine this in their header file.
  53807. + */
  53808. +#define is_real_interrupt(irq) ((irq) != 0)
  53809. +
  53810. +/*
  53811. + * This converts from our new CONFIG_ symbols to the symbols
  53812. + * that asm/serial.h expects. You _NEED_ to comment out the
  53813. + * linux/config.h include contained inside asm/serial.h for
  53814. + * this to work.
  53815. + */
  53816. +#undef CONFIG_SERIAL_MANY_PORTS
  53817. +#undef CONFIG_SERIAL_DETECT_IRQ
  53818. +#undef CONFIG_SERIAL_MULTIPORT
  53819. +#undef CONFIG_HUB6
  53820. +
  53821. +#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
  53822. +#define CONFIG_SERIAL_DETECT_IRQ 1
  53823. +#endif
  53824. +#ifdef CONFIG_SERIAL_8250_MULTIPORT
  53825. +#define CONFIG_SERIAL_MULTIPORT 1
  53826. +#endif
  53827. +#ifdef CONFIG_SERIAL_8250_HUB6
  53828. +#define CONFIG_HUB6 1
  53829. +#endif
  53830. +#ifdef CONFIG_SERIAL_8250_MANY_PORTS
  53831. +#define CONFIG_SERIAL_MANY_PORTS 1
  53832. +#endif
  53833. +
  53834. +#include <asm/serial.h>
  53835. +
  53836. +static struct old_serial_port old_serial_port[] = {
  53837. + SERIAL_PORT_DFNS /* defined in asm/serial.h */
  53838. +};
  53839. +
  53840. +#define UART_NR ARRAY_SIZE(old_serial_port)
  53841. +
  53842. +static struct tty_driver normal, callout;
  53843. +static struct tty_struct *serial8250_table[UART_NR];
  53844. +static struct termios *serial8250_termios[UART_NR], *serial8250_termios_locked[UART_NR];
  53845. +
  53846. +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
  53847. +
  53848. +#define PORT_RSA_MAX 4
  53849. +static int probe_rsa[PORT_RSA_MAX];
  53850. +static int force_rsa[PORT_RSA_MAX];
  53851. +#endif /* CONFIG_SERIAL_8250_RSA */
  53852. +
  53853. +struct uart_8250_port {
  53854. + struct uart_port port;
  53855. + struct timer_list timer; /* "no irq" timer */
  53856. + struct list_head list; /* ports on this IRQ */
  53857. + unsigned int capabilities; /* port capabilities */
  53858. + unsigned char acr;
  53859. + unsigned char ier;
  53860. + unsigned short rev;
  53861. + unsigned char lcr;
  53862. + unsigned char mcr;
  53863. + unsigned char mcr_mask; /* mask of user bits */
  53864. + unsigned char mcr_force; /* mask of forced bits */
  53865. + unsigned char efr;
  53866. + unsigned int lsr_break_flag;
  53867. +
  53868. + /*
  53869. + * We provide a per-port pm hook.
  53870. + */
  53871. + void (*pm)(struct uart_port *port,
  53872. + unsigned int state, unsigned int old);
  53873. +};
  53874. +
  53875. +struct irq_info {
  53876. + spinlock_t lock;
  53877. + struct list_head *head;
  53878. +};
  53879. +
  53880. +static struct irq_info irq_lists[NR_IRQS];
  53881. +
  53882. +/*
  53883. + * Here we define the default xmit fifo size used for each type of UART.
  53884. + */
  53885. +static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
  53886. + { "unknown", 1, 0 },
  53887. + { "8250", 1, 0 },
  53888. + { "16450", 1, 0 },
  53889. + { "16550", 1, 0 },
  53890. + { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
  53891. + { "Cirrus", 1, 0 },
  53892. + { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
  53893. + { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
  53894. + { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
  53895. + { "Startech", 1, 0 },
  53896. + { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
  53897. + { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
  53898. + { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
  53899. + { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
  53900. +};
  53901. +
  53902. +static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
  53903. +{
  53904. + offset <<= up->port.regshift;
  53905. +
  53906. + switch (up->port.iotype) {
  53907. +#ifdef CONFIG_SERIAL_8250_HUB6
  53908. + case SERIAL_IO_HUB6:
  53909. + outb(up->port.hub6 - 1 + offset, up->port.iobase);
  53910. + return inb(up->port.iobase + 1);
  53911. +#endif
  53912. +
  53913. + case SERIAL_IO_MEM:
  53914. + return readb(up->port.membase + offset);
  53915. +
  53916. + default:
  53917. + return inb(up->port.iobase + offset);
  53918. + }
  53919. +}
  53920. +
  53921. +static _INLINE_ void
  53922. +serial_out(struct uart_8250_port *up, int offset, int value)
  53923. +{
  53924. + offset <<= up->port.regshift;
  53925. +
  53926. + switch (up->port.iotype) {
  53927. +#ifdef CONFIG_SERIAL_8250_HUB6
  53928. + case SERIAL_IO_HUB6:
  53929. + outb(up->port.hub6 - 1 + offset, up->port.iobase);
  53930. + outb(value, up->port.iobase + 1);
  53931. + break;
  53932. +#endif
  53933. +
  53934. + case SERIAL_IO_MEM:
  53935. + writeb(value, up->port.membase + offset);
  53936. + break;
  53937. +
  53938. + default:
  53939. + outb(value, up->port.iobase + offset);
  53940. + }
  53941. +}
  53942. +
  53943. +/*
  53944. + * We used to support using pause I/O for certain machines. We
  53945. + * haven't supported this for a while, but just in case it's badly
  53946. + * needed for certain old 386 machines, I've left these #define's
  53947. + * in....
  53948. + */
  53949. +#define serial_inp(up, offset) serial_in(up, offset)
  53950. +#define serial_outp(up, offset, value) serial_out(up, offset, value)
  53951. +
  53952. +
  53953. +/*
  53954. + * For the 16C950
  53955. + */
  53956. +static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
  53957. +{
  53958. + serial_out(up, UART_SCR, offset);
  53959. + serial_out(up, UART_ICR, value);
  53960. +}
  53961. +
  53962. +static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
  53963. +{
  53964. + unsigned int value;
  53965. +
  53966. + serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
  53967. + serial_out(up, UART_SCR, offset);
  53968. + value = serial_in(up, UART_ICR);
  53969. + serial_icr_write(up, UART_ACR, up->acr);
  53970. +
  53971. + return value;
  53972. +}
  53973. +
  53974. +#ifdef CONFIG_SERIAL_8250_RSA
  53975. +/*
  53976. + * Attempts to turn on the RSA FIFO. Returns zero on failure.
  53977. + * We set the port uart clock rate if we succeed.
  53978. + */
  53979. +static int __enable_rsa(struct uart_8250_port *up)
  53980. +{
  53981. + unsigned char mode;
  53982. + int result;
  53983. +
  53984. + mode = serial_inp(up, UART_RSA_MSR);
  53985. + result = mode & UART_RSA_MSR_FIFO;
  53986. +
  53987. + if (!result) {
  53988. + serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
  53989. + mode = serial_inp(up, UART_RSA_MSR);
  53990. + result = mode & UART_RSA_MSR_FIFO;
  53991. + }
  53992. +
  53993. + if (result)
  53994. + up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
  53995. +
  53996. + return result;
  53997. +}
  53998. +
  53999. +static void enable_rsa(struct uart_8250_port *up)
  54000. +{
  54001. + if (up->port.type == PORT_RSA) {
  54002. + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
  54003. + spin_lock_irq(&up->port.lock);
  54004. + __enable_rsa(up);
  54005. + spin_unlock_irq(&up->port.lock);
  54006. + }
  54007. + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
  54008. + serial_outp(up, UART_RSA_FRR, 0);
  54009. + }
  54010. +}
  54011. +
  54012. +/*
  54013. + * Attempts to turn off the RSA FIFO. Returns zero on failure.
  54014. + * It is unknown why interrupts were disabled in here. However,
  54015. + * the caller is expected to preserve this behaviour by grabbing
  54016. + * the spinlock before calling this function.
  54017. + */
  54018. +static void disable_rsa(struct uart_8250_port *up)
  54019. +{
  54020. + unsigned char mode;
  54021. + int result;
  54022. +
  54023. + if (up->port.type == PORT_RSA &&
  54024. + up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
  54025. + spin_lock_irq(&up->port.lock);
  54026. +
  54027. + mode = serial_inp(up, UART_RSA_MSR);
  54028. + result = !(mode & UART_RSA_MSR_FIFO);
  54029. +
  54030. + if (!result) {
  54031. + serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
  54032. + mode = serial_inp(up, UART_RSA_MSR);
  54033. + result = !(mode & UART_RSA_MSR_FIFO);
  54034. + }
  54035. +
  54036. + if (result)
  54037. + up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
  54038. + spin_unlock_irq(&up->port.lock);
  54039. + }
  54040. +}
  54041. +#endif /* CONFIG_SERIAL_8250_RSA */
  54042. +
  54043. +/*
  54044. + * This is a quickie test to see how big the FIFO is.
  54045. + * It doesn't work at all the time, more's the pity.
  54046. + */
  54047. +static int size_fifo(struct uart_8250_port *up)
  54048. +{
  54049. + unsigned char old_fcr, old_mcr, old_dll, old_dlm;
  54050. + int count;
  54051. +
  54052. + old_fcr = serial_inp(up, UART_FCR);
  54053. + old_mcr = serial_inp(up, UART_MCR);
  54054. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
  54055. + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
  54056. + serial_outp(up, UART_MCR, UART_MCR_LOOP);
  54057. + serial_outp(up, UART_LCR, UART_LCR_DLAB);
  54058. + old_dll = serial_inp(up, UART_DLL);
  54059. + old_dlm = serial_inp(up, UART_DLM);
  54060. + serial_outp(up, UART_DLL, 0x01);
  54061. + serial_outp(up, UART_DLM, 0x00);
  54062. + serial_outp(up, UART_LCR, 0x03);
  54063. + for (count = 0; count < 256; count++)
  54064. + serial_outp(up, UART_TX, count);
  54065. + mdelay(20);/* FIXME - schedule_timeout */
  54066. + for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
  54067. + (count < 256); count++)
  54068. + serial_inp(up, UART_RX);
  54069. + serial_outp(up, UART_FCR, old_fcr);
  54070. + serial_outp(up, UART_MCR, old_mcr);
  54071. + serial_outp(up, UART_LCR, UART_LCR_DLAB);
  54072. + serial_outp(up, UART_DLL, old_dll);
  54073. + serial_outp(up, UART_DLM, old_dlm);
  54074. +
  54075. + return count;
  54076. +}
  54077. +
  54078. +/*
  54079. + * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
  54080. + * When this function is called we know it is at least a StarTech
  54081. + * 16650 V2, but it might be one of several StarTech UARTs, or one of
  54082. + * its clones. (We treat the broken original StarTech 16650 V1 as a
  54083. + * 16550, and why not? Startech doesn't seem to even acknowledge its
  54084. + * existence.)
  54085. + *
  54086. + * What evil have men's minds wrought...
  54087. + */
  54088. +static void autoconfig_has_efr(struct uart_8250_port *up)
  54089. +{
  54090. + unsigned char id1, id2, id3, rev, saved_dll, saved_dlm;
  54091. +
  54092. + /*
  54093. + * First we check to see if it's an Oxford Semiconductor UART.
  54094. + *
  54095. + * If we have to do this here because some non-National
  54096. + * Semiconductor clone chips lock up if you try writing to the
  54097. + * LSR register (which serial_icr_read does)
  54098. + */
  54099. +
  54100. + /*
  54101. + * Check for Oxford Semiconductor 16C950.
  54102. + *
  54103. + * EFR [4] must be set else this test fails.
  54104. + *
  54105. + * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
  54106. + * claims that it's needed for 952 dual UART's (which are not
  54107. + * recommended for new designs).
  54108. + */
  54109. + up->acr = 0;
  54110. + serial_out(up, UART_LCR, 0xBF);
  54111. + serial_out(up, UART_EFR, 0x10);
  54112. + serial_out(up, UART_LCR, 0x00);
  54113. + id1 = serial_icr_read(up, UART_ID1);
  54114. + id2 = serial_icr_read(up, UART_ID2);
  54115. + id3 = serial_icr_read(up, UART_ID3);
  54116. + rev = serial_icr_read(up, UART_REV);
  54117. +
  54118. + DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
  54119. +
  54120. + if (id1 == 0x16 && id2 == 0xC9 &&
  54121. + (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
  54122. + up->port.type = PORT_16C950;
  54123. + up->rev = rev | (id3 << 8);
  54124. + return;
  54125. + }
  54126. +
  54127. + /*
  54128. + * We check for a XR16C850 by setting DLL and DLM to 0, and then
  54129. + * reading back DLL and DLM. The chip type depends on the DLM
  54130. + * value read back:
  54131. + * 0x10 - XR16C850 and the DLL contains the chip revision.
  54132. + * 0x12 - XR16C2850.
  54133. + * 0x14 - XR16C854.
  54134. + */
  54135. + serial_outp(up, UART_LCR, UART_LCR_DLAB);
  54136. + saved_dll = serial_inp(up, UART_DLL);
  54137. + saved_dlm = serial_inp(up, UART_DLM);
  54138. + serial_outp(up, UART_DLL, 0);
  54139. + serial_outp(up, UART_DLM, 0);
  54140. + id2 = serial_inp(up, UART_DLL);
  54141. + id1 = serial_inp(up, UART_DLM);
  54142. + serial_outp(up, UART_DLL, saved_dll);
  54143. + serial_outp(up, UART_DLM, saved_dlm);
  54144. +
  54145. + DEBUG_AUTOCONF("850id=%02x:%02x ", id1, id2);
  54146. +
  54147. + if (id1 == 0x10 || id1 == 0x12 || id1 == 0x14) {
  54148. + if (id1 == 0x10)
  54149. + up->rev = id2;
  54150. + up->port.type = PORT_16850;
  54151. + return;
  54152. + }
  54153. +
  54154. + /*
  54155. + * It wasn't an XR16C850.
  54156. + *
  54157. + * We distinguish between the '654 and the '650 by counting
  54158. + * how many bytes are in the FIFO. I'm using this for now,
  54159. + * since that's the technique that was sent to me in the
  54160. + * serial driver update, but I'm not convinced this works.
  54161. + * I've had problems doing this in the past. -TYT
  54162. + */
  54163. + if (size_fifo(up) == 64)
  54164. + up->port.type = PORT_16654;
  54165. + else
  54166. + up->port.type = PORT_16650V2;
  54167. +}
  54168. +
  54169. +/*
  54170. + * We detected a chip without a FIFO. Only two fall into
  54171. + * this category - the original 8250 and the 16450. The
  54172. + * 16450 has a scratch register (accessible with LCR=0)
  54173. + */
  54174. +static void autoconfig_8250(struct uart_8250_port *up)
  54175. +{
  54176. + unsigned char scratch, status1, status2;
  54177. +
  54178. + up->port.type = PORT_8250;
  54179. +
  54180. + scratch = serial_in(up, UART_SCR);
  54181. + serial_outp(up, UART_SCR, 0xa5);
  54182. + status1 = serial_in(up, UART_SCR);
  54183. + serial_outp(up, UART_SCR, 0x5a);
  54184. + status2 = serial_in(up, UART_SCR);
  54185. + serial_outp(up, UART_SCR, scratch);
  54186. +
  54187. + if (status1 == 0xa5 && status2 == 0x5a)
  54188. + up->port.type = PORT_16450;
  54189. +}
  54190. +
  54191. +/*
  54192. + * We know that the chip has FIFOs. Does it have an EFR? The
  54193. + * EFR is located in the same register position as the IIR and
  54194. + * we know the top two bits of the IIR are currently set. The
  54195. + * EFR should contain zero. Try to read the EFR.
  54196. + */
  54197. +static void autoconfig_16550a(struct uart_8250_port *up)
  54198. +{
  54199. + unsigned char status1, status2;
  54200. +
  54201. + up->port.type = PORT_16550A;
  54202. +
  54203. + /*
  54204. + * Check for presence of the EFR when DLAB is set.
  54205. + * Only ST16C650V1 UARTs pass this test.
  54206. + */
  54207. + serial_outp(up, UART_LCR, UART_LCR_DLAB);
  54208. + if (serial_in(up, UART_EFR) == 0) {
  54209. + DEBUG_AUTOCONF("EFRv1 ");
  54210. + up->port.type = PORT_16650;
  54211. + return;
  54212. + }
  54213. +
  54214. + /*
  54215. + * Maybe it requires 0xbf to be written to the LCR.
  54216. + * (other ST16C650V2 UARTs, TI16C752A, etc)
  54217. + */
  54218. + serial_outp(up, UART_LCR, 0xBF);
  54219. + if (serial_in(up, UART_EFR) == 0) {
  54220. + DEBUG_AUTOCONF("EFRv2 ");
  54221. + autoconfig_has_efr(up);
  54222. + return;
  54223. + }
  54224. +
  54225. + /*
  54226. + * Check for a National Semiconductor SuperIO chip.
  54227. + * Attempt to switch to bank 2, read the value of the LOOP bit
  54228. + * from EXCR1. Switch back to bank 0, change it in MCR. Then
  54229. + * switch back to bank 2, read it from EXCR1 again and check
  54230. + * it's changed. If so, set baud_base in EXCR2 to 921600.
  54231. + */
  54232. + serial_outp(up, UART_LCR, 0);
  54233. + status1 = serial_in(up, UART_MCR);
  54234. + serial_outp(up, UART_LCR, 0xE0);
  54235. + status2 = serial_in(up, 0x02); /* EXCR1 */
  54236. +
  54237. + if (!((status2 ^ status1) & UART_MCR_LOOP)) {
  54238. + serial_outp(up, UART_LCR, 0);
  54239. + serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
  54240. + serial_outp(up, UART_LCR, 0xE0);
  54241. + status2 = serial_in(up, 0x02); /* EXCR1 */
  54242. + serial_outp(up, UART_LCR, 0);
  54243. + serial_outp(up, UART_MCR, status1);
  54244. +
  54245. + if ((status2 ^ status1) & UART_MCR_LOOP) {
  54246. + serial_outp(up, UART_LCR, 0xE0);
  54247. + status1 = serial_in(up, 0x04); /* EXCR1 */
  54248. + status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
  54249. + status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
  54250. + serial_outp(up, 0x04, status1);
  54251. + serial_outp(up, UART_LCR, 0);
  54252. +
  54253. + up->port.type = PORT_NS16550A;
  54254. + up->port.uartclk = 921600*16;
  54255. + return;
  54256. + }
  54257. + }
  54258. +
  54259. + /*
  54260. + * No EFR. Try to detect a TI16750, which only sets bit 5 of
  54261. + * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
  54262. + * Try setting it with and without DLAB set. Cheap clones
  54263. + * set bit 5 without DLAB set.
  54264. + */
  54265. + serial_outp(up, UART_LCR, 0);
  54266. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
  54267. + status1 = serial_in(up, UART_IIR) >> 5;
  54268. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
  54269. + serial_outp(up, UART_LCR, UART_LCR_DLAB);
  54270. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
  54271. + status2 = serial_in(up, UART_IIR) >> 5;
  54272. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
  54273. +
  54274. + DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
  54275. +
  54276. + if (status1 == 6 && status2 == 7) {
  54277. + up->port.type = PORT_16750;
  54278. + return;
  54279. + }
  54280. +}
  54281. +
  54282. +/*
  54283. + * This routine is called by rs_init() to initialize a specific serial
  54284. + * port. It determines what type of UART chip this serial port is
  54285. + * using: 8250, 16450, 16550, 16550A. The important question is
  54286. + * whether or not this UART is a 16550A or not, since this will
  54287. + * determine whether or not we can use its FIFO features or not.
  54288. + */
  54289. +static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
  54290. +{
  54291. + unsigned char status1, scratch, scratch2, scratch3;
  54292. + unsigned char save_lcr, save_mcr;
  54293. + unsigned long flags;
  54294. +
  54295. + if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
  54296. + return;
  54297. +
  54298. + DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
  54299. + up->port.line, up->port.iobase, up->port.membase);
  54300. +
  54301. + /*
  54302. + * We really do need global IRQs disabled here - we're going to
  54303. + * be frobbing the chips IRQ enable register to see if it exists.
  54304. + */
  54305. + spin_lock_irqsave(&up->port.lock, flags);
  54306. +
  54307. + if (!(up->port.flags & UPF_BUGGY_UART)) {
  54308. + /*
  54309. + * Do a simple existence test first; if we fail this,
  54310. + * there's no point trying anything else.
  54311. + *
  54312. + * 0x80 is used as a nonsense port to prevent against
  54313. + * false positives due to ISA bus float. The
  54314. + * assumption is that 0x80 is a non-existent port;
  54315. + * which should be safe since include/asm/io.h also
  54316. + * makes this assumption.
  54317. + *
  54318. + * Note: this is safe as long as MCR bit 4 is clear
  54319. + * and the device is in "PC" mode.
  54320. + */
  54321. + scratch = serial_inp(up, UART_IER);
  54322. + serial_outp(up, UART_IER, 0);
  54323. +#ifdef __i386__
  54324. + outb(0xff, 0x080);
  54325. +#endif
  54326. + scratch2 = serial_inp(up, UART_IER);
  54327. + serial_outp(up, UART_IER, 0x0F);
  54328. +#ifdef __i386__
  54329. + outb(0, 0x080);
  54330. +#endif
  54331. + scratch3 = serial_inp(up, UART_IER);
  54332. + serial_outp(up, UART_IER, scratch);
  54333. + if (scratch2 != 0 || scratch3 != 0x0F) {
  54334. + /*
  54335. + * We failed; there's nothing here
  54336. + */
  54337. + DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
  54338. + scratch2, scratch3);
  54339. + goto out;
  54340. + }
  54341. + }
  54342. +
  54343. + save_mcr = serial_in(up, UART_MCR);
  54344. + save_lcr = serial_in(up, UART_LCR);
  54345. +
  54346. + /*
  54347. + * Check to see if a UART is really there. Certain broken
  54348. + * internal modems based on the Rockwell chipset fail this
  54349. + * test, because they apparently don't implement the loopback
  54350. + * test mode. So this test is skipped on the COM 1 through
  54351. + * COM 4 ports. This *should* be safe, since no board
  54352. + * manufacturer would be stupid enough to design a board
  54353. + * that conflicts with COM 1-4 --- we hope!
  54354. + */
  54355. + if (!(up->port.flags & UPF_SKIP_TEST)) {
  54356. + serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
  54357. + status1 = serial_inp(up, UART_MSR) & 0xF0;
  54358. + serial_outp(up, UART_MCR, save_mcr);
  54359. + if (status1 != 0x90) {
  54360. + DEBUG_AUTOCONF("LOOP test failed (%02x) ",
  54361. + status1);
  54362. + goto out;
  54363. + }
  54364. + }
  54365. +
  54366. + /*
  54367. + * We're pretty sure there's a port here. Lets find out what
  54368. + * type of port it is. The IIR top two bits allows us to find
  54369. + * out if its 8250 or 16450, 16550, 16550A or later. This
  54370. + * determines what we test for next.
  54371. + *
  54372. + * We also initialise the EFR (if any) to zero for later. The
  54373. + * EFR occupies the same register location as the FCR and IIR.
  54374. + */
  54375. + serial_outp(up, UART_LCR, 0xBF);
  54376. + serial_outp(up, UART_EFR, 0);
  54377. + serial_outp(up, UART_LCR, 0);
  54378. +
  54379. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
  54380. + scratch = serial_in(up, UART_IIR) >> 6;
  54381. +
  54382. + DEBUG_AUTOCONF("iir=%d ", scratch);
  54383. +
  54384. + switch (scratch) {
  54385. + case 0:
  54386. + autoconfig_8250(up);
  54387. + break;
  54388. + case 1:
  54389. + up->port.type = PORT_UNKNOWN;
  54390. + break;
  54391. + case 2:
  54392. + up->port.type = PORT_16550;
  54393. + break;
  54394. + case 3:
  54395. + autoconfig_16550a(up);
  54396. + break;
  54397. + }
  54398. +
  54399. +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
  54400. + /*
  54401. + * Only probe for RSA ports if we got the region.
  54402. + */
  54403. + if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
  54404. + int i;
  54405. +
  54406. + for (i = 0 ; i < PORT_RSA_MAX ; ++i) {
  54407. + if (!probe_rsa[i] && !force_rsa[i])
  54408. + break;
  54409. + if (((probe_rsa[i] != up->port.iobase) ||
  54410. + check_region(up->port.iobase + UART_RSA_BASE, 16)) &&
  54411. + (force_rsa[i] != up->port.iobase))
  54412. + continue;
  54413. + if (__enable_rsa(up)) {
  54414. + up->port.type = PORT_RSA;
  54415. + break;
  54416. + }
  54417. + }
  54418. + }
  54419. +#endif
  54420. + serial_outp(up, UART_LCR, save_lcr);
  54421. +
  54422. + up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
  54423. + up->capabilities = uart_config[up->port.type].flags;
  54424. +
  54425. + if (up->port.type == PORT_UNKNOWN)
  54426. + goto out;
  54427. +
  54428. + /*
  54429. + * Reset the UART.
  54430. + */
  54431. +#ifdef CONFIG_SERIAL_8250_RSA
  54432. + if (up->port.type == PORT_RSA)
  54433. + serial_outp(up, UART_RSA_FRR, 0);
  54434. +#endif
  54435. + serial_outp(up, UART_MCR, save_mcr);
  54436. + serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
  54437. + UART_FCR_CLEAR_RCVR |
  54438. + UART_FCR_CLEAR_XMIT));
  54439. + serial_outp(up, UART_FCR, 0);
  54440. + (void)serial_in(up, UART_RX);
  54441. + serial_outp(up, UART_IER, 0);
  54442. +
  54443. + out:
  54444. + spin_unlock_irqrestore(&up->port.lock, flags);
  54445. +
  54446. +#ifdef CONFIG_SERIAL_8250_RSA
  54447. + if (up->port.iobase && up->port.type == PORT_RSA) {
  54448. + release_region(up->port.iobase, 8);
  54449. + request_region(up->port.iobase + UART_RSA_BASE, 16,
  54450. + "serial_rsa");
  54451. + }
  54452. +#endif
  54453. + DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
  54454. +}
  54455. +
  54456. +static void autoconfig_irq(struct uart_8250_port *up)
  54457. +{
  54458. + unsigned char save_mcr, save_ier;
  54459. + unsigned char save_ICP = 0;
  54460. + unsigned int ICP = 0;
  54461. + unsigned long irqs;
  54462. + int irq;
  54463. +
  54464. + if (up->port.flags & UPF_FOURPORT) {
  54465. + ICP = (up->port.iobase & 0xfe0) | 0x1f;
  54466. + save_ICP = inb_p(ICP);
  54467. + outb_p(0x80, ICP);
  54468. + (void) inb_p(ICP);
  54469. + }
  54470. +
  54471. + /* forget possible initially masked and pending IRQ */
  54472. + probe_irq_off(probe_irq_on());
  54473. + save_mcr = serial_inp(up, UART_MCR);
  54474. + save_ier = serial_inp(up, UART_IER);
  54475. + serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
  54476. +
  54477. + irqs = probe_irq_on();
  54478. + serial_outp(up, UART_MCR, 0);
  54479. + udelay (10);
  54480. + if (up->port.flags & UPF_FOURPORT) {
  54481. + serial_outp(up, UART_MCR,
  54482. + UART_MCR_DTR | UART_MCR_RTS);
  54483. + } else {
  54484. + serial_outp(up, UART_MCR,
  54485. + UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
  54486. + }
  54487. + serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
  54488. + (void)serial_inp(up, UART_LSR);
  54489. + (void)serial_inp(up, UART_RX);
  54490. + (void)serial_inp(up, UART_IIR);
  54491. + (void)serial_inp(up, UART_MSR);
  54492. + serial_outp(up, UART_TX, 0xFF);
  54493. + udelay (20);
  54494. + irq = probe_irq_off(irqs);
  54495. +
  54496. + serial_outp(up, UART_MCR, save_mcr);
  54497. + serial_outp(up, UART_IER, save_ier);
  54498. +
  54499. + if (up->port.flags & UPF_FOURPORT)
  54500. + outb_p(save_ICP, ICP);
  54501. +
  54502. + up->port.irq = (irq > 0) ? irq : 0;
  54503. +}
  54504. +
  54505. +static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
  54506. +{
  54507. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54508. +
  54509. + if (up->ier & UART_IER_THRI) {
  54510. + up->ier &= ~UART_IER_THRI;
  54511. + serial_out(up, UART_IER, up->ier);
  54512. + }
  54513. + if (up->port.type == PORT_16C950 && tty_stop) {
  54514. + up->acr |= UART_ACR_TXDIS;
  54515. + serial_icr_write(up, UART_ACR, up->acr);
  54516. + }
  54517. +}
  54518. +
  54519. +static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
  54520. +{
  54521. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54522. +
  54523. + if (!(up->ier & UART_IER_THRI)) {
  54524. + up->ier |= UART_IER_THRI;
  54525. + serial_out(up, UART_IER, up->ier);
  54526. + }
  54527. + /*
  54528. + * We only do this from uart_start
  54529. + */
  54530. + if (tty_start && up->port.type == PORT_16C950) {
  54531. + up->acr &= ~UART_ACR_TXDIS;
  54532. + serial_icr_write(up, UART_ACR, up->acr);
  54533. + }
  54534. +}
  54535. +
  54536. +static void serial8250_stop_rx(struct uart_port *port)
  54537. +{
  54538. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54539. +
  54540. + up->ier &= ~UART_IER_RLSI;
  54541. + up->port.read_status_mask &= ~UART_LSR_DR;
  54542. + serial_out(up, UART_IER, up->ier);
  54543. +}
  54544. +
  54545. +static void serial8250_enable_ms(struct uart_port *port)
  54546. +{
  54547. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54548. +
  54549. + up->ier |= UART_IER_MSI;
  54550. + serial_out(up, UART_IER, up->ier);
  54551. +}
  54552. +
  54553. +static _INLINE_ void
  54554. +receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
  54555. +{
  54556. + struct tty_struct *tty = up->port.info->tty;
  54557. + unsigned char ch;
  54558. + int max_count = 256;
  54559. +
  54560. + do {
  54561. + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
  54562. + /*
  54563. + * FIXME: Deadlock can happen here if we're a
  54564. + * low-latency port. We're holding the per-port
  54565. + * spinlock, and we call flush_to_ldisc->
  54566. + * n_tty_receive_buf->n_tty_receive_char->
  54567. + * opost->uart_put_char.
  54568. + */
  54569. + tty->flip.tqueue.routine((void *)tty);
  54570. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  54571. + return; // if TTY_DONT_FLIP is set
  54572. + }
  54573. + ch = serial_inp(up, UART_RX);
  54574. + *tty->flip.char_buf_ptr = ch;
  54575. + *tty->flip.flag_buf_ptr = TTY_NORMAL;
  54576. + up->port.icount.rx++;
  54577. +
  54578. + if (*status & (UART_LSR_BI | UART_LSR_PE |
  54579. + UART_LSR_FE | UART_LSR_OE)) {
  54580. + /*
  54581. + * For statistics only
  54582. + */
  54583. + if (*status & UART_LSR_BI) {
  54584. + *status &= ~(UART_LSR_FE | UART_LSR_PE);
  54585. + up->port.icount.brk++;
  54586. + /*
  54587. + * We do the SysRQ and SAK checking
  54588. + * here because otherwise the break
  54589. + * may get masked by ignore_status_mask
  54590. + * or read_status_mask.
  54591. + */
  54592. + if (uart_handle_break(&up->port))
  54593. + goto ignore_char;
  54594. + } else if (*status & UART_LSR_PE)
  54595. + up->port.icount.parity++;
  54596. + else if (*status & UART_LSR_FE)
  54597. + up->port.icount.frame++;
  54598. + if (*status & UART_LSR_OE)
  54599. + up->port.icount.overrun++;
  54600. +
  54601. + /*
  54602. + * Mask off conditions which should be ingored.
  54603. + */
  54604. + *status &= up->port.read_status_mask;
  54605. +
  54606. +#ifdef CONFIG_SERIAL_8250_CONSOLE
  54607. + if (up->port.line == up->port.cons->index) {
  54608. + /* Recover the break flag from console xmit */
  54609. + *status |= up->lsr_break_flag;
  54610. + up->lsr_break_flag = 0;
  54611. + }
  54612. +#endif
  54613. + if (*status & UART_LSR_BI) {
  54614. + DEBUG_INTR("handling break....");
  54615. + *tty->flip.flag_buf_ptr = TTY_BREAK;
  54616. + } else if (*status & UART_LSR_PE)
  54617. + *tty->flip.flag_buf_ptr = TTY_PARITY;
  54618. + else if (*status & UART_LSR_FE)
  54619. + *tty->flip.flag_buf_ptr = TTY_FRAME;
  54620. + }
  54621. + if (uart_handle_sysrq_char(&up->port, ch, regs))
  54622. + goto ignore_char;
  54623. + if ((*status & up->port.ignore_status_mask) == 0) {
  54624. + tty->flip.flag_buf_ptr++;
  54625. + tty->flip.char_buf_ptr++;
  54626. + tty->flip.count++;
  54627. + }
  54628. + if ((*status & UART_LSR_OE) &&
  54629. + tty->flip.count < TTY_FLIPBUF_SIZE) {
  54630. + /*
  54631. + * Overrun is special, since it's reported
  54632. + * immediately, and doesn't affect the current
  54633. + * character.
  54634. + */
  54635. + *tty->flip.flag_buf_ptr = TTY_OVERRUN;
  54636. + tty->flip.flag_buf_ptr++;
  54637. + tty->flip.char_buf_ptr++;
  54638. + tty->flip.count++;
  54639. + }
  54640. + ignore_char:
  54641. + *status = serial_inp(up, UART_LSR);
  54642. + } while ((*status & UART_LSR_DR) && (max_count-- > 0));
  54643. + tty_flip_buffer_push(tty);
  54644. +}
  54645. +
  54646. +static _INLINE_ void transmit_chars(struct uart_8250_port *up)
  54647. +{
  54648. + struct circ_buf *xmit = &up->port.info->xmit;
  54649. + int count;
  54650. +
  54651. + if (up->port.x_char) {
  54652. + serial_outp(up, UART_TX, up->port.x_char);
  54653. + up->port.icount.tx++;
  54654. + up->port.x_char = 0;
  54655. + return;
  54656. + }
  54657. + if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
  54658. + serial8250_stop_tx(&up->port, 0);
  54659. + return;
  54660. + }
  54661. +
  54662. + count = up->port.fifosize;
  54663. + do {
  54664. + serial_out(up, UART_TX, xmit->buf[xmit->tail]);
  54665. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  54666. + up->port.icount.tx++;
  54667. + if (uart_circ_empty(xmit))
  54668. + break;
  54669. + } while (--count > 0);
  54670. +
  54671. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  54672. + uart_write_wakeup(&up->port);
  54673. +
  54674. + DEBUG_INTR("THRE...");
  54675. +
  54676. + if (uart_circ_empty(xmit))
  54677. + serial8250_stop_tx(&up->port, 0);
  54678. +}
  54679. +
  54680. +static _INLINE_ void check_modem_status(struct uart_8250_port *up)
  54681. +{
  54682. + int status;
  54683. +
  54684. + status = serial_in(up, UART_MSR);
  54685. +
  54686. + if ((status & UART_MSR_ANY_DELTA) == 0)
  54687. + return;
  54688. +
  54689. + if (status & UART_MSR_TERI)
  54690. + up->port.icount.rng++;
  54691. + if (status & UART_MSR_DDSR)
  54692. + up->port.icount.dsr++;
  54693. + if (status & UART_MSR_DDCD)
  54694. + uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
  54695. + if (status & UART_MSR_DCTS)
  54696. + uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
  54697. +
  54698. + wake_up_interruptible(&up->port.info->delta_msr_wait);
  54699. +}
  54700. +
  54701. +/*
  54702. + * This handles the interrupt from one port.
  54703. + */
  54704. +static inline void
  54705. +serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
  54706. +{
  54707. + unsigned int status = serial_inp(up, UART_LSR);
  54708. +
  54709. + DEBUG_INTR("status = %x...", status);
  54710. +
  54711. + if (status & UART_LSR_DR)
  54712. + receive_chars(up, &status, regs);
  54713. + check_modem_status(up);
  54714. + if (status & UART_LSR_THRE)
  54715. + transmit_chars(up);
  54716. +}
  54717. +
  54718. +/*
  54719. + * This is the serial driver's interrupt routine.
  54720. + *
  54721. + * Arjan thinks the old way was overly complex, so it got simplified.
  54722. + * Alan disagrees, saying that need the complexity to handle the weird
  54723. + * nature of ISA shared interrupts. (This is a special exception.)
  54724. + *
  54725. + * In order to handle ISA shared interrupts properly, we need to check
  54726. + * that all ports have been serviced, and therefore the ISA interrupt
  54727. + * line has been de-asserted.
  54728. + *
  54729. + * This means we need to loop through all ports. checking that they
  54730. + * don't have an interrupt pending.
  54731. + */
  54732. +static void serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  54733. +{
  54734. + struct irq_info *i = dev_id;
  54735. + struct list_head *l, *end = NULL;
  54736. + int pass_counter = 0;
  54737. +
  54738. + DEBUG_INTR("serial8250_interrupt(%d)...", irq);
  54739. +
  54740. + spin_lock(&i->lock);
  54741. +
  54742. + l = i->head;
  54743. + do {
  54744. + struct uart_8250_port *up;
  54745. + unsigned int iir;
  54746. +
  54747. + up = list_entry(l, struct uart_8250_port, list);
  54748. +
  54749. + iir = serial_in(up, UART_IIR);
  54750. + if (!(iir & UART_IIR_NO_INT)) {
  54751. + spin_lock(&up->port.lock);
  54752. + serial8250_handle_port(up, regs);
  54753. + spin_unlock(&up->port.lock);
  54754. +
  54755. + end = NULL;
  54756. + } else if (end == NULL)
  54757. + end = l;
  54758. +
  54759. + l = l->next;
  54760. +
  54761. + if (l == i->head && pass_counter++ > PASS_LIMIT) {
  54762. + /* If we hit this, we're dead. */
  54763. + printk(KERN_ERR "serial8250: too much work for "
  54764. + "irq%d\n", irq);
  54765. + break;
  54766. + }
  54767. + } while (l != end);
  54768. +
  54769. + spin_unlock(&i->lock);
  54770. +
  54771. + DEBUG_INTR("end.\n");
  54772. +}
  54773. +
  54774. +/*
  54775. + * To support ISA shared interrupts, we need to have one interrupt
  54776. + * handler that ensures that the IRQ line has been deasserted
  54777. + * before returning. Failing to do this will result in the IRQ
  54778. + * line being stuck active, and, since ISA irqs are edge triggered,
  54779. + * no more IRQs will be seen.
  54780. + */
  54781. +static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
  54782. +{
  54783. + spin_lock_irq(&i->lock);
  54784. +
  54785. + if (!list_empty(i->head)) {
  54786. + if (i->head == &up->list)
  54787. + i->head = i->head->next;
  54788. + list_del(&up->list);
  54789. + } else {
  54790. + BUG_ON(i->head != &up->list);
  54791. + i->head = NULL;
  54792. + }
  54793. +
  54794. + spin_unlock_irq(&i->lock);
  54795. +}
  54796. +
  54797. +static int serial_link_irq_chain(struct uart_8250_port *up)
  54798. +{
  54799. + struct irq_info *i = irq_lists + up->port.irq;
  54800. + int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
  54801. +
  54802. + spin_lock_irq(&i->lock);
  54803. +
  54804. + if (i->head) {
  54805. + list_add(&up->list, i->head);
  54806. + spin_unlock_irq(&i->lock);
  54807. +
  54808. + ret = 0;
  54809. + } else {
  54810. + INIT_LIST_HEAD(&up->list);
  54811. + i->head = &up->list;
  54812. + spin_unlock_irq(&i->lock);
  54813. +
  54814. + ret = request_irq(up->port.irq, serial8250_interrupt,
  54815. + irq_flags, "serial", i);
  54816. + if (ret < 0)
  54817. + serial_do_unlink(i, up);
  54818. + }
  54819. +
  54820. + return ret;
  54821. +}
  54822. +
  54823. +static void serial_unlink_irq_chain(struct uart_8250_port *up)
  54824. +{
  54825. + struct irq_info *i = irq_lists + up->port.irq;
  54826. +
  54827. + BUG_ON(i->head == NULL);
  54828. +
  54829. + if (list_empty(i->head))
  54830. + free_irq(up->port.irq, i);
  54831. +
  54832. + serial_do_unlink(i, up);
  54833. +}
  54834. +
  54835. +/*
  54836. + * This function is used to handle ports that do not have an
  54837. + * interrupt. This doesn't work very well for 16450's, but gives
  54838. + * barely passable results for a 16550A. (Although at the expense
  54839. + * of much CPU overhead).
  54840. + */
  54841. +static void serial8250_timeout(unsigned long data)
  54842. +{
  54843. + struct uart_8250_port *up = (struct uart_8250_port *)data;
  54844. + unsigned int timeout;
  54845. + unsigned int iir;
  54846. +
  54847. + iir = serial_in(up, UART_IIR);
  54848. + if (!(iir & UART_IIR_NO_INT)) {
  54849. + spin_lock(&up->port.lock);
  54850. + serial8250_handle_port(up, NULL);
  54851. + spin_unlock(&up->port.lock);
  54852. + }
  54853. +
  54854. + timeout = up->port.timeout;
  54855. + timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
  54856. + mod_timer(&up->timer, jiffies + timeout);
  54857. +}
  54858. +
  54859. +static unsigned int serial8250_tx_empty(struct uart_port *port)
  54860. +{
  54861. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54862. + unsigned long flags;
  54863. + unsigned int ret;
  54864. +
  54865. + spin_lock_irqsave(&up->port.lock, flags);
  54866. + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
  54867. + spin_unlock_irqrestore(&up->port.lock, flags);
  54868. +
  54869. + return ret;
  54870. +}
  54871. +
  54872. +static unsigned int serial8250_get_mctrl(struct uart_port *port)
  54873. +{
  54874. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54875. + unsigned long flags;
  54876. + unsigned char status;
  54877. + unsigned int ret;
  54878. +
  54879. + spin_lock_irqsave(&up->port.lock, flags);
  54880. + status = serial_in(up, UART_MSR);
  54881. + spin_unlock_irqrestore(&up->port.lock, flags);
  54882. +
  54883. + ret = 0;
  54884. + if (status & UART_MSR_DCD)
  54885. + ret |= TIOCM_CAR;
  54886. + if (status & UART_MSR_RI)
  54887. + ret |= TIOCM_RNG;
  54888. + if (status & UART_MSR_DSR)
  54889. + ret |= TIOCM_DSR;
  54890. + if (status & UART_MSR_CTS)
  54891. + ret |= TIOCM_CTS;
  54892. + return ret;
  54893. +}
  54894. +
  54895. +static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
  54896. +{
  54897. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54898. + unsigned char mcr = 0;
  54899. +
  54900. + if (mctrl & TIOCM_RTS)
  54901. + mcr |= UART_MCR_RTS;
  54902. + if (mctrl & TIOCM_DTR)
  54903. + mcr |= UART_MCR_DTR;
  54904. + if (mctrl & TIOCM_OUT1)
  54905. + mcr |= UART_MCR_OUT1;
  54906. + if (mctrl & TIOCM_OUT2)
  54907. + mcr |= UART_MCR_OUT2;
  54908. + if (mctrl & TIOCM_LOOP)
  54909. + mcr |= UART_MCR_LOOP;
  54910. +
  54911. + mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
  54912. +
  54913. + serial_out(up, UART_MCR, mcr);
  54914. +}
  54915. +
  54916. +static void serial8250_break_ctl(struct uart_port *port, int break_state)
  54917. +{
  54918. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54919. + unsigned long flags;
  54920. +
  54921. + spin_lock_irqsave(&up->port.lock, flags);
  54922. + if (break_state == -1)
  54923. + up->lcr |= UART_LCR_SBC;
  54924. + else
  54925. + up->lcr &= ~UART_LCR_SBC;
  54926. + serial_out(up, UART_LCR, up->lcr);
  54927. + spin_unlock_irqrestore(&up->port.lock, flags);
  54928. +}
  54929. +
  54930. +static int serial8250_startup(struct uart_port *port)
  54931. +{
  54932. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  54933. + unsigned long flags;
  54934. + unsigned char lsr, iir;
  54935. + int retval;
  54936. +
  54937. + up->capabilities = uart_config[up->port.type].flags;
  54938. + up->mcr = 0;
  54939. + up->efr = 0;
  54940. + up->ier = 0;
  54941. +
  54942. + if (up->port.type == PORT_16C950) {
  54943. + /* Wake up and initialize UART */
  54944. + up->acr = 0;
  54945. + serial_outp(up, UART_LCR, 0xBF);
  54946. + serial_outp(up, UART_EFR, UART_EFR_ECB);
  54947. + serial_outp(up, UART_IER, 0);
  54948. + serial_outp(up, UART_LCR, 0);
  54949. + serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
  54950. + serial_outp(up, UART_LCR, 0xBF);
  54951. + serial_outp(up, UART_EFR, UART_EFR_ECB);
  54952. + serial_outp(up, UART_LCR, 0);
  54953. + }
  54954. +
  54955. +#ifdef CONFIG_SERIAL_8250_RSA
  54956. + /*
  54957. + * If this is an RSA port, see if we can kick it up to the
  54958. + * higher speed clock.
  54959. + */
  54960. + enable_rsa(up);
  54961. +#endif
  54962. +
  54963. + /*
  54964. + * Clear the FIFO buffers and disable them.
  54965. + * (they will be reeanbled in change_speed())
  54966. + */
  54967. + if (up->capabilities & UART_CLEAR_FIFO) {
  54968. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
  54969. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
  54970. + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
  54971. + serial_outp(up, UART_FCR, 0);
  54972. + }
  54973. +
  54974. + /*
  54975. + * Clear the interrupt registers.
  54976. + */
  54977. + (void) serial_inp(up, UART_LSR);
  54978. + (void) serial_inp(up, UART_RX);
  54979. + (void) serial_inp(up, UART_IIR);
  54980. + (void) serial_inp(up, UART_MSR);
  54981. +
  54982. + /*
  54983. + * At this point, there's no way the LSR could still be 0xff;
  54984. + * if it is, then bail out, because there's likely no UART
  54985. + * here.
  54986. + */
  54987. + if (!(up->port.flags & UPF_BUGGY_UART) &&
  54988. + (serial_inp(up, UART_LSR) == 0xff)) {
  54989. + printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
  54990. + return -ENODEV;
  54991. + }
  54992. +
  54993. + /*
  54994. + * If the "interrupt" for this port doesn't correspond with any
  54995. + * hardware interrupt, we use a timer-based system. The original
  54996. + * driver used to do this with IRQ0.
  54997. + */
  54998. + if (!is_real_interrupt(up->port.irq)) {
  54999. + unsigned int timeout = up->port.timeout;
  55000. +
  55001. + timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
  55002. +
  55003. + up->timer.data = (unsigned long)up;
  55004. + mod_timer(&up->timer, jiffies + timeout);
  55005. + } else {
  55006. + retval = serial_link_irq_chain(up);
  55007. + if (retval)
  55008. + return retval;
  55009. + }
  55010. +
  55011. + /*
  55012. + * Now, initialize the UART
  55013. + */
  55014. + serial_outp(up, UART_LCR, UART_LCR_WLEN8);
  55015. +
  55016. + spin_lock_irqsave(&up->port.lock, flags);
  55017. + if (up->port.flags & UPF_FOURPORT) {
  55018. + if (!is_real_interrupt(up->port.irq))
  55019. + up->port.mctrl |= TIOCM_OUT1;
  55020. + } else
  55021. + /*
  55022. + * Most PC uarts need OUT2 raised to enable interrupts.
  55023. + */
  55024. + if (is_real_interrupt(up->port.irq))
  55025. + up->port.mctrl |= TIOCM_OUT2;
  55026. +
  55027. + serial8250_set_mctrl(&up->port, up->port.mctrl);
  55028. +
  55029. + /*
  55030. + * Do a quick test to see if we receive an
  55031. + * interrupt when we enable the TX irq.
  55032. + */
  55033. + serial_outp(up, UART_IER, UART_IER_THRI);
  55034. + lsr = serial_in(up, UART_LSR);
  55035. + iir = serial_in(up, UART_IIR);
  55036. + serial_outp(up, UART_IER, 0);
  55037. +
  55038. + if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
  55039. + up->capabilities |= UART_BAD_TX_ENABLE;
  55040. + printk("ttyS%d - enabling bad tx status workarounds\n",
  55041. + port->line);
  55042. + }
  55043. +
  55044. + spin_unlock_irqrestore(&up->port.lock, flags);
  55045. +
  55046. + /*
  55047. + * Finally, enable interrupts. Note: Modem status interrupts
  55048. + * are set via change_speed(), which will be occuring imminently
  55049. + * anyway, so we don't enable them here.
  55050. + */
  55051. + up->ier = UART_IER_RLSI | UART_IER_RDI;
  55052. + serial_outp(up, UART_IER, up->ier);
  55053. +
  55054. + if (up->port.flags & UPF_FOURPORT) {
  55055. + unsigned int icp;
  55056. + /*
  55057. + * Enable interrupts on the AST Fourport board
  55058. + */
  55059. + icp = (up->port.iobase & 0xfe0) | 0x01f;
  55060. + outb_p(0x80, icp);
  55061. + (void) inb_p(icp);
  55062. + }
  55063. +
  55064. + /*
  55065. + * And clear the interrupt registers again for luck.
  55066. + */
  55067. + (void) serial_inp(up, UART_LSR);
  55068. + (void) serial_inp(up, UART_RX);
  55069. + (void) serial_inp(up, UART_IIR);
  55070. + (void) serial_inp(up, UART_MSR);
  55071. +
  55072. + return 0;
  55073. +}
  55074. +
  55075. +static void serial8250_shutdown(struct uart_port *port)
  55076. +{
  55077. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  55078. + unsigned long flags;
  55079. +
  55080. + /*
  55081. + * Disable interrupts from this port
  55082. + */
  55083. + up->ier = 0;
  55084. + serial_outp(up, UART_IER, 0);
  55085. +
  55086. + spin_lock_irqsave(&up->port.lock, flags);
  55087. + if (up->port.flags & UPF_FOURPORT) {
  55088. + /* reset interrupts on the AST Fourport board */
  55089. + inb((up->port.iobase & 0xfe0) | 0x1f);
  55090. + up->port.mctrl |= TIOCM_OUT1;
  55091. + } else
  55092. + up->port.mctrl &= ~TIOCM_OUT2;
  55093. +
  55094. + serial8250_set_mctrl(&up->port, up->port.mctrl);
  55095. + spin_unlock_irqrestore(&up->port.lock, flags);
  55096. +
  55097. + /*
  55098. + * Disable break condition and FIFOs
  55099. + */
  55100. + serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
  55101. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
  55102. + UART_FCR_CLEAR_RCVR |
  55103. + UART_FCR_CLEAR_XMIT);
  55104. + serial_outp(up, UART_FCR, 0);
  55105. +
  55106. +#ifdef CONFIG_SERIAL_8250_RSA
  55107. + /*
  55108. + * Reset the RSA board back to 115kbps compat mode.
  55109. + */
  55110. + disable_rsa(up);
  55111. +#endif
  55112. +
  55113. + /*
  55114. + * Read data port to reset things, and then unlink from
  55115. + * the IRQ chain.
  55116. + */
  55117. + (void) serial_in(up, UART_RX);
  55118. +
  55119. + if (!is_real_interrupt(up->port.irq))
  55120. + del_timer_sync(&up->timer);
  55121. + else
  55122. + serial_unlink_irq_chain(up);
  55123. +}
  55124. +
  55125. +static void serial8250_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
  55126. +{
  55127. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  55128. + unsigned char cval, fcr = 0;
  55129. + unsigned long flags;
  55130. +
  55131. + switch (cflag & CSIZE) {
  55132. + case CS5:
  55133. + cval = 0x00;
  55134. + break;
  55135. + case CS6:
  55136. + cval = 0x01;
  55137. + break;
  55138. + case CS7:
  55139. + cval = 0x02;
  55140. + break;
  55141. + default:
  55142. + case CS8:
  55143. + cval = 0x03;
  55144. + break;
  55145. + }
  55146. +
  55147. + if (cflag & CSTOPB)
  55148. + cval |= 0x04;
  55149. + if (cflag & PARENB)
  55150. + cval |= UART_LCR_PARITY;
  55151. + if (!(cflag & PARODD))
  55152. + cval |= UART_LCR_EPAR;
  55153. +#ifdef CMSPAR
  55154. + if (cflag & CMSPAR)
  55155. + cval |= UART_LCR_SPAR;
  55156. +#endif
  55157. +
  55158. + /*
  55159. + * Work around a bug in the Oxford Semiconductor 952 rev B
  55160. + * chip which causes it to seriously miscalculate baud rates
  55161. + * when DLL is 0.
  55162. + */
  55163. + if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
  55164. + up->rev == 0x5201)
  55165. + quot ++;
  55166. +
  55167. + if (up->capabilities & UART_USE_FIFO) {
  55168. + if ((up->port.uartclk / quot) < (2400 * 16))
  55169. + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
  55170. +#ifdef CONFIG_SERIAL_8250_RSA
  55171. + else if (up->port.type == PORT_RSA)
  55172. + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
  55173. +#endif
  55174. + else
  55175. + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
  55176. + }
  55177. + if (up->port.type == PORT_16750)
  55178. + fcr |= UART_FCR7_64BYTE;
  55179. +
  55180. + /*
  55181. + * Ok, we're now changing the port state. Do it with
  55182. + * interrupts disabled.
  55183. + */
  55184. + spin_lock_irqsave(&up->port.lock, flags);
  55185. +
  55186. + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
  55187. + if (iflag & IGNPAR)
  55188. + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
  55189. + if (iflag & (BRKINT | PARMRK))
  55190. + up->port.read_status_mask |= UART_LSR_BI;
  55191. +
  55192. + /*
  55193. + * Characteres to ignore
  55194. + */
  55195. + up->port.ignore_status_mask = 0;
  55196. + if (iflag & IGNPAR)
  55197. + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
  55198. + if (iflag & IGNBRK) {
  55199. + up->port.ignore_status_mask |= UART_LSR_BI;
  55200. + /*
  55201. + * If we're ignoring parity and break indicators,
  55202. + * ignore overruns too (for real raw support).
  55203. + */
  55204. + if (iflag & IGNPAR)
  55205. + up->port.ignore_status_mask |= UART_LSR_OE;
  55206. + }
  55207. +
  55208. + /*
  55209. + * ignore all characters if CREAD is not set
  55210. + */
  55211. + if ((cflag & CREAD) == 0)
  55212. + up->port.ignore_status_mask |= UART_LSR_DR;
  55213. +
  55214. + /*
  55215. + * CTS flow control flag and modem status interrupts
  55216. + */
  55217. + up->ier &= ~UART_IER_MSI;
  55218. + if (UART_ENABLE_MS(&up->port, cflag))
  55219. + up->ier |= UART_IER_MSI;
  55220. +
  55221. + serial_out(up, UART_IER, up->ier);
  55222. +
  55223. + if (up->capabilities & UART_MCRAFE) {
  55224. + /*
  55225. + * TI16C750 hardware flow control
  55226. + */
  55227. + up->mcr &= ~UART_MCR_AFE;
  55228. + if (cflag & CRTSCTS)
  55229. + up->mcr |= UART_MCR_AFE;
  55230. + }
  55231. + if (up->capabilities & UART_EFRAFE) {
  55232. + /*
  55233. + * TI16C752/Startech hardware flow control
  55234. + * FIXME:
  55235. + * - TI16C752 requires control thresholds
  55236. + * to be set for auto-RTS.
  55237. + * - We only enable auto-CTS here.
  55238. + * Note: ST16C654 does not allow MCR bit 1
  55239. + * to override RTS when UART_EFR_RTS is set.
  55240. + */
  55241. + up->efr &= ~UART_EFR_CTS;
  55242. + if (cflag & CRTSCTS)
  55243. + up->efr |= UART_EFR_CTS;
  55244. + serial_outp(up, UART_LCR, 0xBF);
  55245. + serial_outp(up, UART_EFR, up->efr);
  55246. + }
  55247. +
  55248. + if (up->capabilities & UART_NATSEMI) {
  55249. + /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
  55250. + serial_outp(up, UART_LCR, 0xe0);
  55251. + } else {
  55252. + serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
  55253. + }
  55254. + serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */
  55255. + serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
  55256. + if (up->port.type == PORT_16750)
  55257. + serial_outp(up, UART_FCR, fcr); /* set fcr */
  55258. + serial_outp(up, UART_LCR, cval); /* reset DLAB */
  55259. + up->lcr = cval; /* Save LCR */
  55260. + if (up->port.type != PORT_16750) {
  55261. + if (fcr & UART_FCR_ENABLE_FIFO) {
  55262. + /* emulated UARTs (Lucent Venus 167x) need two steps */
  55263. + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
  55264. + }
  55265. + serial_outp(up, UART_FCR, fcr); /* set fcr */
  55266. + }
  55267. + serial8250_set_mctrl(&up->port, up->port.mctrl);
  55268. + spin_unlock_irqrestore(&up->port.lock, flags);
  55269. +}
  55270. +
  55271. +static void
  55272. +serial8250_pm(struct uart_port *port, unsigned int state,
  55273. + unsigned int oldstate)
  55274. +{
  55275. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  55276. + if (state) {
  55277. + /* sleep */
  55278. + if (up->capabilities & UART_STARTECH) {
  55279. + /* Arrange to enter sleep mode */
  55280. + serial_outp(up, UART_LCR, 0xBF);
  55281. + serial_outp(up, UART_EFR, UART_EFR_ECB);
  55282. + serial_outp(up, UART_LCR, 0);
  55283. + serial_outp(up, UART_IER, UART_IERX_SLEEP);
  55284. + serial_outp(up, UART_LCR, 0xBF);
  55285. + serial_outp(up, UART_EFR, 0);
  55286. + serial_outp(up, UART_LCR, 0);
  55287. + }
  55288. + if (up->port.type == PORT_16750) {
  55289. + /* Arrange to enter sleep mode */
  55290. + serial_outp(up, UART_IER, UART_IERX_SLEEP);
  55291. + }
  55292. + } else {
  55293. + /* wake */
  55294. + if (up->capabilities & UART_STARTECH) {
  55295. + /* Wake up UART */
  55296. + serial_outp(up, UART_LCR, 0xBF);
  55297. + serial_outp(up, UART_EFR, UART_EFR_ECB);
  55298. + /*
  55299. + * Turn off LCR == 0xBF so we actually set the IER
  55300. + * register on the XR16C850
  55301. + */
  55302. + serial_outp(up, UART_LCR, 0);
  55303. + serial_outp(up, UART_IER, 0);
  55304. + /*
  55305. + * Now reset LCR so we can turn off the ECB bit
  55306. + */
  55307. + serial_outp(up, UART_LCR, 0xBF);
  55308. + serial_outp(up, UART_EFR, 0);
  55309. + /*
  55310. + * For a XR16C850, we need to set the trigger levels
  55311. + */
  55312. + if (up->port.type == PORT_16850) {
  55313. + unsigned char fctr;
  55314. +
  55315. + fctr = serial_inp(up, UART_FCTR) &
  55316. + ~(UART_FCTR_RX | UART_FCTR_TX);
  55317. + serial_outp(up, UART_FCTR, fctr |
  55318. + UART_FCTR_TRGD |
  55319. + UART_FCTR_RX);
  55320. + serial_outp(up, UART_TRG, UART_TRG_96);
  55321. + serial_outp(up, UART_FCTR, fctr |
  55322. + UART_FCTR_TRGD |
  55323. + UART_FCTR_TX);
  55324. + serial_outp(up, UART_TRG, UART_TRG_96);
  55325. + }
  55326. + serial_outp(up, UART_LCR, 0);
  55327. + }
  55328. +
  55329. + if (up->port.type == PORT_16750) {
  55330. + /* Wake up UART */
  55331. + serial_outp(up, UART_IER, 0);
  55332. + }
  55333. + }
  55334. +}
  55335. +
  55336. +/*
  55337. + * Resource handling. This is complicated by the fact that resources
  55338. + * depend on the port type. Maybe we should be claiming the standard
  55339. + * 8250 ports, and then trying to get other resources as necessary?
  55340. + */
  55341. +static int
  55342. +serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
  55343. +{
  55344. + unsigned int size = 8 << up->port.regshift;
  55345. + int ret = 0;
  55346. +
  55347. + switch (up->port.iotype) {
  55348. + case SERIAL_IO_MEM:
  55349. + if (up->port.mapbase) {
  55350. + *res = request_mem_region(up->port.mapbase, size, "serial");
  55351. + if (!*res)
  55352. + ret = -EBUSY;
  55353. + }
  55354. + break;
  55355. +
  55356. + case SERIAL_IO_HUB6:
  55357. + case SERIAL_IO_PORT:
  55358. + *res = request_region(up->port.iobase, size, "serial");
  55359. + if (!*res)
  55360. + ret = -EBUSY;
  55361. + break;
  55362. + }
  55363. + return ret;
  55364. +}
  55365. +
  55366. +static int
  55367. +serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res)
  55368. +{
  55369. + unsigned int size = 8 << up->port.regshift;
  55370. + unsigned long start;
  55371. + int ret = 0;
  55372. +
  55373. + switch (up->port.iotype) {
  55374. + case SERIAL_IO_MEM:
  55375. + if (up->port.mapbase) {
  55376. + start = up->port.mapbase;
  55377. + start += UART_RSA_BASE << up->port.regshift;
  55378. + *res = request_mem_region(start, size, "serial-rsa");
  55379. + if (!*res)
  55380. + ret = -EBUSY;
  55381. + }
  55382. + break;
  55383. +
  55384. + case SERIAL_IO_HUB6:
  55385. + case SERIAL_IO_PORT:
  55386. + start = up->port.iobase;
  55387. + start += UART_RSA_BASE << up->port.regshift;
  55388. + *res = request_region(start, size, "serial-rsa");
  55389. + if (!*res)
  55390. + ret = -EBUSY;
  55391. + break;
  55392. + }
  55393. +
  55394. + return ret;
  55395. +}
  55396. +
  55397. +static void serial8250_release_port(struct uart_port *port)
  55398. +{
  55399. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  55400. + unsigned long start, offset = 0, size = 0;
  55401. +
  55402. + if (up->port.type == PORT_RSA) {
  55403. + offset = UART_RSA_BASE << up->port.regshift;
  55404. + size = 8;
  55405. + }
  55406. +
  55407. + size <<= up->port.regshift;
  55408. +
  55409. + switch (up->port.iotype) {
  55410. + case SERIAL_IO_MEM:
  55411. + if (up->port.mapbase) {
  55412. + /*
  55413. + * Unmap the area.
  55414. + */
  55415. + if (up->port.flags & UPF_IOREMAP) {
  55416. + iounmap(up->port.membase);
  55417. + up->port.membase = NULL;
  55418. + }
  55419. +
  55420. + start = up->port.mapbase;
  55421. +
  55422. + if (size)
  55423. + release_mem_region(start + offset, size);
  55424. + release_mem_region(start, 8 << up->port.regshift);
  55425. + }
  55426. + break;
  55427. +
  55428. + case SERIAL_IO_HUB6:
  55429. + case SERIAL_IO_PORT:
  55430. + start = up->port.iobase;
  55431. +
  55432. + if (size)
  55433. + release_region(start + offset, size);
  55434. + release_region(start + offset, 8 << up->port.regshift);
  55435. + break;
  55436. +
  55437. + default:
  55438. + break;
  55439. + }
  55440. +}
  55441. +
  55442. +static int serial8250_request_port(struct uart_port *port)
  55443. +{
  55444. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  55445. + struct resource *res = NULL, *res_rsa = NULL;
  55446. + int ret = 0;
  55447. +
  55448. + if (up->port.flags & UPF_RESOURCES) {
  55449. + if (up->port.type == PORT_RSA) {
  55450. + ret = serial8250_request_rsa_resource(up, &res_rsa);
  55451. + if (ret < 0)
  55452. + return ret;
  55453. + }
  55454. +
  55455. + ret = serial8250_request_std_resource(up, &res);
  55456. + }
  55457. +
  55458. + /*
  55459. + * If we have a mapbase, then request that as well.
  55460. + */
  55461. + if (ret == 0 && up->port.flags & UPF_IOREMAP) {
  55462. + int size = res->end - res->start + 1;
  55463. +
  55464. + up->port.membase = ioremap(up->port.mapbase, size);
  55465. + if (!up->port.membase)
  55466. + ret = -ENOMEM;
  55467. + }
  55468. +
  55469. + if (ret < 0) {
  55470. + if (res_rsa)
  55471. + release_resource(res_rsa);
  55472. + if (res)
  55473. + release_resource(res);
  55474. + }
  55475. + return ret;
  55476. +}
  55477. +
  55478. +static void serial8250_config_port(struct uart_port *port, int flags)
  55479. +{
  55480. + struct uart_8250_port *up = (struct uart_8250_port *)port;
  55481. + struct resource *res_std = NULL, *res_rsa = NULL;
  55482. + int probeflags = PROBE_ANY;
  55483. + int ret;
  55484. +
  55485. +#ifdef CONFIG_MCA
  55486. + /*
  55487. + * Don't probe for MCA ports on non-MCA machines.
  55488. + */
  55489. + if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
  55490. + return;
  55491. +#endif
  55492. +
  55493. + /*
  55494. + * Find the region that we can probe for. This in turn
  55495. + * tells us whether we can probe for the type of port.
  55496. + */
  55497. + if (up->port.flags & UPF_RESOURCES) {
  55498. + ret = serial8250_request_std_resource(up, &res_std);
  55499. + if (ret < 0)
  55500. + return;
  55501. +
  55502. + ret = serial8250_request_rsa_resource(up, &res_rsa);
  55503. + if (ret < 0)
  55504. + probeflags &= ~PROBE_RSA;
  55505. + } else {
  55506. + probeflags &= ~PROBE_RSA;
  55507. + }
  55508. +
  55509. + if (flags & UART_CONFIG_TYPE)
  55510. + autoconfig(up, probeflags);
  55511. + if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
  55512. + autoconfig_irq(up);
  55513. +
  55514. + /*
  55515. + * If the port wasn't an RSA port, release the resource.
  55516. + */
  55517. + if (up->port.type != PORT_RSA && res_rsa)
  55518. + release_resource(res_rsa);
  55519. +
  55520. + if (up->port.type == PORT_UNKNOWN && res_std)
  55521. + release_resource(res_std);
  55522. +}
  55523. +
  55524. +static int
  55525. +serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
  55526. +{
  55527. + if (ser->irq >= NR_IRQS || ser->irq < 0 ||
  55528. + ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
  55529. + ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
  55530. + ser->type == PORT_STARTECH)
  55531. + return -EINVAL;
  55532. + return 0;
  55533. +}
  55534. +
  55535. +static const char *
  55536. +serial8250_type(struct uart_port *port)
  55537. +{
  55538. + int type = port->type;
  55539. +
  55540. + if (type >= ARRAY_SIZE(uart_config))
  55541. + type = 0;
  55542. + return uart_config[type].name;
  55543. +}
  55544. +
  55545. +static struct uart_ops serial8250_pops = {
  55546. + .tx_empty = serial8250_tx_empty,
  55547. + .set_mctrl = serial8250_set_mctrl,
  55548. + .get_mctrl = serial8250_get_mctrl,
  55549. + .stop_tx = serial8250_stop_tx,
  55550. + .start_tx = serial8250_start_tx,
  55551. + .stop_rx = serial8250_stop_rx,
  55552. + .enable_ms = serial8250_enable_ms,
  55553. + .break_ctl = serial8250_break_ctl,
  55554. + .startup = serial8250_startup,
  55555. + .shutdown = serial8250_shutdown,
  55556. + .change_speed = serial8250_change_speed,
  55557. + .pm = serial8250_pm,
  55558. + .type = serial8250_type,
  55559. + .release_port = serial8250_release_port,
  55560. + .request_port = serial8250_request_port,
  55561. + .config_port = serial8250_config_port,
  55562. + .verify_port = serial8250_verify_port,
  55563. +};
  55564. +
  55565. +static struct uart_8250_port serial8250_ports[UART_NR];
  55566. +
  55567. +static void __init serial8250_isa_init_ports(void)
  55568. +{
  55569. + struct uart_8250_port *up;
  55570. + static int first = 1;
  55571. + int i;
  55572. +
  55573. + if (!first)
  55574. + return;
  55575. + first = 0;
  55576. +
  55577. + for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
  55578. + i++, up++) {
  55579. + up->port.iobase = old_serial_port[i].port;
  55580. + up->port.irq = irq_cannonicalize(old_serial_port[i].irq);
  55581. + up->port.uartclk = old_serial_port[i].baud_base * 16;
  55582. + up->port.flags = old_serial_port[i].flags |
  55583. + UPF_RESOURCES;
  55584. + up->port.hub6 = old_serial_port[i].hub6;
  55585. + up->port.membase = old_serial_port[i].iomem_base;
  55586. + up->port.iotype = old_serial_port[i].io_type;
  55587. + up->port.regshift = old_serial_port[i].iomem_reg_shift;
  55588. + up->port.ops = &serial8250_pops;
  55589. +
  55590. + if (up->port.iotype == UPIO_MEM && up->port.mapbase)
  55591. + up->port.flags |= UPF_IOREMAP;
  55592. +
  55593. + if (share_irqs)
  55594. + up->port.flags |= UPF_SHARE_IRQ;
  55595. + }
  55596. +}
  55597. +
  55598. +static void __init serial8250_register_ports(struct uart_driver *drv)
  55599. +{
  55600. + int i;
  55601. +
  55602. + serial8250_isa_init_ports();
  55603. +
  55604. + for (i = 0; i < UART_NR; i++) {
  55605. + struct uart_8250_port *up = &serial8250_ports[i];
  55606. +
  55607. + up->port.line = i;
  55608. + up->port.ops = &serial8250_pops;
  55609. + init_timer(&up->timer);
  55610. + up->timer.function = serial8250_timeout;
  55611. +
  55612. + /*
  55613. + * ALPHA_KLUDGE_MCR needs to be killed.
  55614. + */
  55615. + up->mcr_mask = ~ALPHA_KLUDGE_MCR;
  55616. + up->mcr_force = ALPHA_KLUDGE_MCR;
  55617. +
  55618. + uart_add_one_port(drv, &up->port);
  55619. + }
  55620. +}
  55621. +
  55622. +#ifdef CONFIG_SERIAL_8250_CONSOLE
  55623. +
  55624. +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
  55625. +
  55626. +/*
  55627. + * Wait for transmitter & holding register to empty
  55628. + */
  55629. +static inline void wait_for_xmitr(struct uart_8250_port *up)
  55630. +{
  55631. + unsigned int status, tmout = 10000;
  55632. +
  55633. + /* Wait up to 10ms for the character(s) to be sent. */
  55634. + do {
  55635. + status = serial_in(up, UART_LSR);
  55636. +
  55637. + if (status & UART_LSR_BI)
  55638. + up->lsr_break_flag = UART_LSR_BI;
  55639. +
  55640. + if (--tmout == 0)
  55641. + break;
  55642. + udelay(1);
  55643. + } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
  55644. +
  55645. + /* Wait up to 1s for flow control if necessary */
  55646. + if (up->port.flags & UPF_CONS_FLOW) {
  55647. + tmout = 1000000;
  55648. + while (--tmout &&
  55649. + ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
  55650. + udelay(1);
  55651. + }
  55652. +}
  55653. +
  55654. +/*
  55655. + * Print a string to the serial port trying not to disturb
  55656. + * any possible real use of the port...
  55657. + *
  55658. + * The console_lock must be held when we get here.
  55659. + */
  55660. +static void
  55661. +serial8250_console_write(struct console *co, const char *s, unsigned int count)
  55662. +{
  55663. + struct uart_8250_port *up = &serial8250_ports[co->index];
  55664. + unsigned int ier;
  55665. + int i;
  55666. +
  55667. + /*
  55668. + * First save the UER then disable the interrupts
  55669. + */
  55670. + ier = serial_in(up, UART_IER);
  55671. + serial_out(up, UART_IER, 0);
  55672. +
  55673. + /*
  55674. + * Now, do each character
  55675. + */
  55676. + for (i = 0; i < count; i++, s++) {
  55677. + wait_for_xmitr(up);
  55678. +
  55679. + /*
  55680. + * Send the character out.
  55681. + * If a LF, also do CR...
  55682. + */
  55683. + serial_out(up, UART_TX, *s);
  55684. + if (*s == 10) {
  55685. + wait_for_xmitr(up);
  55686. + serial_out(up, UART_TX, 13);
  55687. + }
  55688. + }
  55689. +
  55690. + /*
  55691. + * Finally, wait for transmitter to become empty
  55692. + * and restore the IER
  55693. + */
  55694. + wait_for_xmitr(up);
  55695. + serial_out(up, UART_IER, ier);
  55696. +}
  55697. +
  55698. +static kdev_t serial8250_console_device(struct console *co)
  55699. +{
  55700. + return MKDEV(TTY_MAJOR, 64 + co->index);
  55701. +}
  55702. +
  55703. +static int __init serial8250_console_setup(struct console *co, char *options)
  55704. +{
  55705. + struct uart_port *port;
  55706. + int baud = 9600;
  55707. + int bits = 8;
  55708. + int parity = 'n';
  55709. + int flow = 'n';
  55710. +
  55711. + /*
  55712. + * Check whether an invalid uart number has been specified, and
  55713. + * if so, search for the first available port that does have
  55714. + * console support.
  55715. + */
  55716. + if (co->index >= UART_NR)
  55717. + co->index = 0;
  55718. + port = &serial8250_ports[co->index].port;
  55719. +
  55720. + /*
  55721. + * Temporary fix.
  55722. + */
  55723. + spin_lock_init(&port->lock);
  55724. +
  55725. + if (options)
  55726. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  55727. +
  55728. + return uart_set_options(port, co, baud, parity, bits, flow);
  55729. +}
  55730. +
  55731. +static struct console serial8250_console = {
  55732. + .name = "ttyS",
  55733. + .write = serial8250_console_write,
  55734. + .device = serial8250_console_device,
  55735. + .setup = serial8250_console_setup,
  55736. + .flags = CON_PRINTBUFFER,
  55737. + .index = -1,
  55738. +};
  55739. +
  55740. +void __init serial8250_console_init(void)
  55741. +{
  55742. + serial8250_isa_init_ports();
  55743. + register_console(&serial8250_console);
  55744. +}
  55745. +
  55746. +#define SERIAL8250_CONSOLE &serial8250_console
  55747. +#else
  55748. +#define SERIAL8250_CONSOLE NULL
  55749. +#endif
  55750. +
  55751. +static struct uart_driver serial8250_reg = {
  55752. + .owner = THIS_MODULE,
  55753. +#ifdef CONFIG_DEVFS_FS
  55754. + .normal_name = "tts/%d",
  55755. + .callout_name = "cua/%d",
  55756. +#else
  55757. + .normal_name = "ttyS",
  55758. + .callout_name = "cua",
  55759. +#endif
  55760. + .normal_major = TTY_MAJOR,
  55761. + .callout_major = TTYAUX_MAJOR,
  55762. + .normal_driver = &normal,
  55763. + .callout_driver = &callout,
  55764. + .table = serial8250_table,
  55765. + .termios = serial8250_termios,
  55766. + .termios_locked = serial8250_termios_locked,
  55767. + .minor = 64,
  55768. + .nr = UART_NR,
  55769. + .cons = SERIAL8250_CONSOLE,
  55770. +};
  55771. +
  55772. +/*
  55773. + * register_serial and unregister_serial allows for 16x50 serial ports to be
  55774. + * configured at run-time, to support PCMCIA modems.
  55775. + */
  55776. +
  55777. +static int __register_serial(struct serial_struct *req, int line)
  55778. +{
  55779. + struct uart_port port;
  55780. +
  55781. + port.iobase = req->port;
  55782. + port.membase = req->iomem_base;
  55783. + port.irq = req->irq;
  55784. + port.uartclk = req->baud_base * 16;
  55785. + port.fifosize = req->xmit_fifo_size;
  55786. + port.regshift = req->iomem_reg_shift;
  55787. + port.iotype = req->io_type;
  55788. + port.flags = req->flags | UPF_BOOT_AUTOCONF;
  55789. + port.mapbase = req->iomap_base;
  55790. + port.line = line;
  55791. +
  55792. + if (share_irqs)
  55793. + port.flags |= UPF_SHARE_IRQ;
  55794. +
  55795. + if (HIGH_BITS_OFFSET)
  55796. + port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
  55797. +
  55798. + /*
  55799. + * If a clock rate wasn't specified by the low level
  55800. + * driver, then default to the standard clock rate.
  55801. + */
  55802. + if (port.uartclk == 0)
  55803. + port.uartclk = BASE_BAUD * 16;
  55804. +
  55805. + return uart_register_port(&serial8250_reg, &port);
  55806. +}
  55807. +
  55808. +/**
  55809. + * register_serial - configure a 16x50 serial port at runtime
  55810. + * @req: request structure
  55811. + *
  55812. + * Configure the serial port specified by the request. If the
  55813. + * port exists and is in use an error is returned. If the port
  55814. + * is not currently in the table it is added.
  55815. + *
  55816. + * The port is then probed and if necessary the IRQ is autodetected
  55817. + * If this fails an error is returned.
  55818. + *
  55819. + * On success the port is ready to use and the line number is returned.
  55820. + */
  55821. +int register_serial(struct serial_struct *req)
  55822. +{
  55823. + return __register_serial(req, -1);
  55824. +}
  55825. +
  55826. +/**
  55827. + * unregister_serial - remove a 16x50 serial port at runtime
  55828. + * @line: serial line number
  55829. + *
  55830. + * Remove one serial port. This may be called from interrupt
  55831. + * context.
  55832. + */
  55833. +void unregister_serial(int line)
  55834. +{
  55835. + uart_unregister_port(&serial8250_reg, line);
  55836. +}
  55837. +
  55838. +/*
  55839. + * This is for ISAPNP only.
  55840. + */
  55841. +void serial8250_get_irq_map(unsigned int *map)
  55842. +{
  55843. + int i;
  55844. +
  55845. + for (i = 0; i < UART_NR; i++) {
  55846. + if (serial8250_ports[i].port.type != PORT_UNKNOWN &&
  55847. + serial8250_ports[i].port.irq < 16)
  55848. + *map |= 1 << serial8250_ports[i].port.irq;
  55849. + }
  55850. +}
  55851. +
  55852. +static int __init serial8250_init(void)
  55853. +{
  55854. + int ret, i;
  55855. +
  55856. + for (i = 0; i < NR_IRQS; i++)
  55857. + spin_lock_init(&irq_lists[i].lock);
  55858. +
  55859. + ret = uart_register_driver(&serial8250_reg);
  55860. + if (ret >= 0)
  55861. + serial8250_register_ports(&serial8250_reg);
  55862. +
  55863. + return ret;
  55864. +}
  55865. +
  55866. +static void __exit serial8250_exit(void)
  55867. +{
  55868. + int i;
  55869. +
  55870. + for (i = 0; i < UART_NR; i++)
  55871. + uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
  55872. +
  55873. + uart_unregister_driver(&serial8250_reg);
  55874. +}
  55875. +
  55876. +module_init(serial8250_init);
  55877. +module_exit(serial8250_exit);
  55878. +
  55879. +EXPORT_SYMBOL(register_serial);
  55880. +EXPORT_SYMBOL(unregister_serial);
  55881. +EXPORT_SYMBOL(serial8250_get_irq_map);
  55882. +
  55883. +MODULE_LICENSE("GPL");
  55884. +MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
  55885. +
  55886. +MODULE_PARM(share_irqs, "i");
  55887. +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
  55888. + " (unsafe)");
  55889. +
  55890. +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
  55891. +MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
  55892. +MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
  55893. +MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
  55894. +MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
  55895. +#endif /* CONFIG_SERIAL_8250_RSA */
  55896. +
  55897. diff -urN linux-2.4.26/drivers/serial/8250.h linux-2.4.26-vrs1/drivers/serial/8250.h
  55898. --- linux-2.4.26/drivers/serial/8250.h 1970-01-01 01:00:00.000000000 +0100
  55899. +++ linux-2.4.26-vrs1/drivers/serial/8250.h 2004-04-19 16:49:20.000000000 +0100
  55900. @@ -0,0 +1,88 @@
  55901. +/*
  55902. + * linux/drivers/serial/8250.h
  55903. + *
  55904. + * Driver for 8250/16550-type serial ports
  55905. + *
  55906. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  55907. + *
  55908. + * Copyright (C) 2001 Russell King.
  55909. + *
  55910. + * This program is free software; you can redistribute it and/or modify
  55911. + * it under the terms of the GNU General Public License as published by
  55912. + * the Free Software Foundation; either version 2 of the License, or
  55913. + * (at your option) any later version.
  55914. + *
  55915. + * $Id: 8250.h,v 1.1.1.1.2.1 2002/10/24 09:53:24 rmk Exp $
  55916. + */
  55917. +
  55918. +#include <linux/config.h>
  55919. +
  55920. +struct serial8250_probe {
  55921. + struct module *owner;
  55922. + int (*pci_init_one)(struct pci_dev *dev);
  55923. + void (*pci_remove_one)(struct pci_dev *dev);
  55924. + void (*pnp_init)(void);
  55925. +};
  55926. +
  55927. +int serial8250_register_probe(struct serial8250_probe *probe);
  55928. +void serial8250_unregister_probe(struct serial8250_probe *probe);
  55929. +void serial8250_get_irq_map(unsigned int *map);
  55930. +
  55931. +struct old_serial_port {
  55932. + unsigned int uart;
  55933. + unsigned int baud_base;
  55934. + unsigned int port;
  55935. + unsigned int irq;
  55936. + unsigned int flags;
  55937. + unsigned char hub6;
  55938. + unsigned char io_type;
  55939. + unsigned char *iomem_base;
  55940. + unsigned short iomem_reg_shift;
  55941. +};
  55942. +
  55943. +struct serial8250_config {
  55944. + const char *name;
  55945. + unsigned int dfl_xmit_fifo_size;
  55946. + unsigned int flags;
  55947. +};
  55948. +
  55949. +#define UART_CLEAR_FIFO 0x01
  55950. +#define UART_USE_FIFO 0x02
  55951. +#define UART_STARTECH 0x04
  55952. +#define UART_NATSEMI 0x08
  55953. +#define UART_MCRAFE 0x10 /* TI16C750-style auto-flow */
  55954. +#define UART_EFRAFE 0x20 /* TI16C752/startech auto-flow */
  55955. +
  55956. +#define UART_BAD_TX_ENABLE 0x80000000
  55957. +
  55958. +#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
  55959. +#define SERIAL_INLINE
  55960. +#endif
  55961. +
  55962. +#ifdef SERIAL_INLINE
  55963. +#define _INLINE_ inline
  55964. +#else
  55965. +#define _INLINE_
  55966. +#endif
  55967. +
  55968. +#define PROBE_RSA (1 << 0)
  55969. +#define PROBE_ANY (~0)
  55970. +
  55971. +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
  55972. +
  55973. +#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
  55974. +#define SERIAL8250_SHARE_IRQS 1
  55975. +#else
  55976. +#define SERIAL8250_SHARE_IRQS 0
  55977. +#endif
  55978. +
  55979. +#if defined(__alpha__) && !defined(CONFIG_PCI)
  55980. +/*
  55981. + * Digital did something really horribly wrong with the OUT1 and OUT2
  55982. + * lines on at least some ALPHA's. The failure mode is that if either
  55983. + * is cleared, the machine locks up with endless interrupts.
  55984. + */
  55985. +#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
  55986. +#else
  55987. +#define ALPHA_KLUDGE_MCR 0
  55988. +#endif
  55989. diff -urN linux-2.4.26/drivers/serial/8250_pci.c linux-2.4.26-vrs1/drivers/serial/8250_pci.c
  55990. --- linux-2.4.26/drivers/serial/8250_pci.c 1970-01-01 01:00:00.000000000 +0100
  55991. +++ linux-2.4.26-vrs1/drivers/serial/8250_pci.c 2004-01-14 21:32:26.000000000 +0000
  55992. @@ -0,0 +1,1080 @@
  55993. +/*
  55994. + * linux/drivers/char/serial_8250_pci.c
  55995. + *
  55996. + * Probe module for 8250/16550-type PCI serial ports.
  55997. + *
  55998. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  55999. + *
  56000. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  56001. + *
  56002. + * This program is free software; you can redistribute it and/or modify
  56003. + * it under the terms of the GNU General Public License as published by
  56004. + * the Free Software Foundation; either version 2 of the License.
  56005. + *
  56006. + * $Id: 8250_pci.c,v 1.8.2.1 2002/10/24 09:53:24 rmk Exp $
  56007. + */
  56008. +#include <linux/config.h>
  56009. +#include <linux/module.h>
  56010. +#include <linux/init.h>
  56011. +#include <linux/pci.h>
  56012. +#include <linux/sched.h>
  56013. +#include <linux/string.h>
  56014. +#include <linux/kernel.h>
  56015. +#include <linux/slab.h>
  56016. +#include <linux/serial.h>
  56017. +
  56018. +/* 2.4.6 compatibility cruft ;( */
  56019. +#define pci_board __pci_board
  56020. +#include <linux/serialP.h>
  56021. +#undef pci_board
  56022. +
  56023. +#include <asm/bitops.h>
  56024. +#include <asm/byteorder.h>
  56025. +#include <asm/serial.h>
  56026. +
  56027. +#include "8250.h"
  56028. +
  56029. +#ifndef IS_PCI_REGION_IOPORT
  56030. +#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
  56031. + IORESOURCE_IO)
  56032. +#endif
  56033. +#ifndef IS_PCI_REGION_IOMEM
  56034. +#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
  56035. + IORESOURCE_MEM)
  56036. +#endif
  56037. +#ifndef PCI_IRQ_RESOURCE
  56038. +#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
  56039. +#endif
  56040. +
  56041. +#ifndef pci_get_subvendor
  56042. +#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
  56043. +#define pci_get_subdevice(dev) ((dev)->subsystem_device)
  56044. +#endif
  56045. +
  56046. +struct serial_private {
  56047. + unsigned int nr;
  56048. + struct pci_board *board;
  56049. + int line[0];
  56050. +};
  56051. +
  56052. +struct pci_board {
  56053. + int flags;
  56054. + int num_ports;
  56055. + int base_baud;
  56056. + int uart_offset;
  56057. + int reg_shift;
  56058. + int (*init_fn)(struct pci_dev *dev, struct pci_board *board,
  56059. + int enable);
  56060. + int first_uart_offset;
  56061. +};
  56062. +
  56063. +static int
  56064. +get_pci_port(struct pci_dev *dev, struct pci_board *board,
  56065. + struct serial_struct *req, int idx)
  56066. +{
  56067. + unsigned long port;
  56068. + int base_idx;
  56069. + int max_port;
  56070. + int offset;
  56071. +
  56072. + base_idx = SPCI_FL_GET_BASE(board->flags);
  56073. + if (board->flags & SPCI_FL_BASE_TABLE)
  56074. + base_idx += idx;
  56075. +
  56076. + if (board->flags & SPCI_FL_REGION_SZ_CAP) {
  56077. + max_port = pci_resource_len(dev, base_idx) / 8;
  56078. + if (idx >= max_port)
  56079. + return 1;
  56080. + }
  56081. +
  56082. + offset = board->first_uart_offset;
  56083. +
  56084. + /* Timedia/SUNIX uses a mixture of BARs and offsets */
  56085. + /* Ugh, this is ugly as all hell --- TYT */
  56086. + if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
  56087. + switch(idx) {
  56088. + case 0: base_idx=0;
  56089. + break;
  56090. + case 1: base_idx=0; offset=8;
  56091. + break;
  56092. + case 2: base_idx=1;
  56093. + break;
  56094. + case 3: base_idx=1; offset=8;
  56095. + break;
  56096. + case 4: /* BAR 2*/
  56097. + case 5: /* BAR 3 */
  56098. + case 6: /* BAR 4*/
  56099. + case 7: base_idx=idx-2; /* BAR 5*/
  56100. + }
  56101. +
  56102. + /* Some Titan cards are also a little weird */
  56103. + if (dev->vendor == PCI_VENDOR_ID_TITAN &&
  56104. + (dev->device == PCI_DEVICE_ID_TITAN_400L ||
  56105. + dev->device == PCI_DEVICE_ID_TITAN_800L)) {
  56106. + switch (idx) {
  56107. + case 0: base_idx = 1;
  56108. + break;
  56109. + case 1: base_idx = 2;
  56110. + break;
  56111. + default:
  56112. + base_idx = 4;
  56113. + offset = 8 * (idx - 2);
  56114. + }
  56115. + }
  56116. +
  56117. + port = pci_resource_start(dev, base_idx) + offset;
  56118. +
  56119. + if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
  56120. + port += idx * (board->uart_offset ? board->uart_offset : 8);
  56121. +
  56122. + if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
  56123. + req->port = port;
  56124. + if (HIGH_BITS_OFFSET)
  56125. + req->port_high = port >> HIGH_BITS_OFFSET;
  56126. + else
  56127. + req->port_high = 0;
  56128. + return 0;
  56129. + }
  56130. + req->io_type = SERIAL_IO_MEM;
  56131. + req->iomem_base = ioremap(port, board->uart_offset);
  56132. + req->iomem_reg_shift = board->reg_shift;
  56133. + req->port = 0;
  56134. + return 0;
  56135. +}
  56136. +
  56137. +static _INLINE_ int get_pci_irq(struct pci_dev *dev,
  56138. + struct pci_board *board,
  56139. + int idx)
  56140. +{
  56141. + int base_idx;
  56142. +
  56143. + if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
  56144. + return dev->irq;
  56145. +
  56146. + base_idx = SPCI_FL_GET_IRQBASE(board->flags);
  56147. + if (board->flags & SPCI_FL_IRQ_TABLE)
  56148. + base_idx += idx;
  56149. +
  56150. + return PCI_IRQ_RESOURCE(dev, base_idx);
  56151. +}
  56152. +
  56153. +/*
  56154. + * Some PCI serial cards using the PLX 9050 PCI interface chip require
  56155. + * that the card interrupt be explicitly enabled or disabled. This
  56156. + * seems to be mainly needed on card using the PLX which also use I/O
  56157. + * mapped memory.
  56158. + */
  56159. +static int __devinit
  56160. +pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
  56161. +{
  56162. + u8 data, *p, irq_config;
  56163. + int pci_config;
  56164. +
  56165. + irq_config = 0x41;
  56166. + pci_config = PCI_COMMAND_MEMORY;
  56167. + if (dev->vendor == PCI_VENDOR_ID_PANACOM)
  56168. + irq_config = 0x43;
  56169. + if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
  56170. + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
  56171. + /*
  56172. + * As the megawolf cards have the int pins active
  56173. + * high, and have 2 UART chips, both ints must be
  56174. + * enabled on the 9050. Also, the UARTS are set in
  56175. + * 16450 mode by default, so we have to enable the
  56176. + * 16C950 'enhanced' mode so that we can use the deep
  56177. + * FIFOs
  56178. + */
  56179. + irq_config = 0x5b;
  56180. + pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
  56181. + }
  56182. +
  56183. + pci_read_config_byte(dev, PCI_COMMAND, &data);
  56184. +
  56185. + if (enable)
  56186. + pci_write_config_byte(dev, PCI_COMMAND,
  56187. + data | pci_config);
  56188. +
  56189. + /* enable/disable interrupts */
  56190. + p = ioremap(pci_resource_start(dev, 0), 0x80);
  56191. + writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c);
  56192. + iounmap(p);
  56193. +
  56194. + if (!enable)
  56195. + pci_write_config_byte(dev, PCI_COMMAND,
  56196. + data & ~pci_config);
  56197. + return 0;
  56198. +}
  56199. +
  56200. +
  56201. +/*
  56202. + * SIIG serial cards have an PCI interface chip which also controls
  56203. + * the UART clocking frequency. Each UART can be clocked independently
  56204. + * (except cards equiped with 4 UARTs) and initial clocking settings
  56205. + * are stored in the EEPROM chip. It can cause problems because this
  56206. + * version of serial driver doesn't support differently clocked UART's
  56207. + * on single PCI card. To prevent this, initialization functions set
  56208. + * high frequency clocking for all UART's on given card. It is safe (I
  56209. + * hope) because it doesn't touch EEPROM settings to prevent conflicts
  56210. + * with other OSes (like M$ DOS).
  56211. + *
  56212. + * SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
  56213. + *
  56214. + * There is two family of SIIG serial cards with different PCI
  56215. + * interface chip and different configuration methods:
  56216. + * - 10x cards have control registers in IO and/or memory space;
  56217. + * - 20x cards have control registers in standard PCI configuration space.
  56218. + */
  56219. +
  56220. +#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
  56221. +#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
  56222. +
  56223. +static int __devinit
  56224. +pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
  56225. +{
  56226. + u16 data, *p;
  56227. +
  56228. + if (!enable) return 0;
  56229. +
  56230. + p = ioremap(pci_resource_start(dev, 0), 0x80);
  56231. +
  56232. + switch (dev->device & 0xfff8) {
  56233. + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
  56234. + data = 0xffdf;
  56235. + break;
  56236. + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
  56237. + data = 0xf7ff;
  56238. + break;
  56239. + default: /* 1S1P, 4S */
  56240. + data = 0xfffb;
  56241. + break;
  56242. + }
  56243. +
  56244. + writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
  56245. + iounmap(p);
  56246. + return 0;
  56247. +}
  56248. +
  56249. +#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
  56250. +#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
  56251. +
  56252. +static int __devinit
  56253. +pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
  56254. +{
  56255. + u8 data;
  56256. +
  56257. + if (!enable) return 0;
  56258. +
  56259. + /* Change clock frequency for the first UART. */
  56260. + pci_read_config_byte(dev, 0x6f, &data);
  56261. + pci_write_config_byte(dev, 0x6f, data & 0xef);
  56262. +
  56263. + /* If this card has 2 UART, we have to do the same with second UART. */
  56264. + if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
  56265. + ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
  56266. + pci_read_config_byte(dev, 0x73, &data);
  56267. + pci_write_config_byte(dev, 0x73, data & 0xef);
  56268. + }
  56269. + return 0;
  56270. +}
  56271. +
  56272. +/* Added for EKF Intel i960 serial boards */
  56273. +static int __devinit
  56274. +pci_inteli960ni_fn(struct pci_dev *dev,
  56275. + struct pci_board *board,
  56276. + int enable)
  56277. +{
  56278. + unsigned long oldval;
  56279. +
  56280. + if (!(pci_get_subdevice(dev) & 0x1000))
  56281. + return(-1);
  56282. +
  56283. + if (!enable) /* is there something to deinit? */
  56284. + return(0);
  56285. +
  56286. + /* is firmware started? */
  56287. + pci_read_config_dword(dev, 0x44, (void*) &oldval);
  56288. + if (oldval == 0x00001000L) { /* RESET value */
  56289. + printk(KERN_DEBUG "Local i960 firmware missing");
  56290. + return(-1);
  56291. + }
  56292. + return(0);
  56293. +}
  56294. +
  56295. +/*
  56296. + * Timedia has an explosion of boards, and to avoid the PCI table from
  56297. + * growing *huge*, we use this function to collapse some 70 entries
  56298. + * in the PCI table into one, for sanity's and compactness's sake.
  56299. + */
  56300. +static unsigned short timedia_single_port[] = {
  56301. + 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 };
  56302. +static unsigned short timedia_dual_port[] = {
  56303. + 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
  56304. + 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
  56305. + 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
  56306. + 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
  56307. + 0xD079, 0 };
  56308. +static unsigned short timedia_quad_port[] = {
  56309. + 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
  56310. + 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
  56311. + 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
  56312. + 0xB157, 0 };
  56313. +static unsigned short timedia_eight_port[] = {
  56314. + 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
  56315. + 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 };
  56316. +static struct timedia_struct {
  56317. + int num;
  56318. + unsigned short *ids;
  56319. +} timedia_data[] = {
  56320. + { 1, timedia_single_port },
  56321. + { 2, timedia_dual_port },
  56322. + { 4, timedia_quad_port },
  56323. + { 8, timedia_eight_port },
  56324. + { 0, 0 }
  56325. +};
  56326. +
  56327. +static int __devinit
  56328. +pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
  56329. +{
  56330. + int i, j;
  56331. + unsigned short *ids;
  56332. +
  56333. + if (!enable)
  56334. + return 0;
  56335. +
  56336. + for (i=0; timedia_data[i].num; i++) {
  56337. + ids = timedia_data[i].ids;
  56338. + for (j=0; ids[j]; j++) {
  56339. + if (pci_get_subdevice(dev) == ids[j]) {
  56340. + board->num_ports = timedia_data[i].num;
  56341. + return 0;
  56342. + }
  56343. + }
  56344. + }
  56345. + return 0;
  56346. +}
  56347. +
  56348. +static int __devinit
  56349. +pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
  56350. +{
  56351. + __set_current_state(TASK_UNINTERRUPTIBLE);
  56352. + schedule_timeout(HZ/10);
  56353. + return 0;
  56354. +}
  56355. +
  56356. +/*
  56357. + * This is the configuration table for all of the PCI serial boards
  56358. + * which we support. It is directly indexed by the pci_board_num_t enum
  56359. + * value, which is encoded in the pci_device_id PCI probe table's
  56360. + * driver_data member.
  56361. + */
  56362. +enum pci_board_num_t {
  56363. + pbn_b0_1_115200,
  56364. + pbn_default = 0,
  56365. +
  56366. + pbn_b0_2_115200,
  56367. + pbn_b0_4_115200,
  56368. +
  56369. + pbn_b0_1_921600,
  56370. + pbn_b0_2_921600,
  56371. + pbn_b0_4_921600,
  56372. +
  56373. + pbn_b0_bt_1_115200,
  56374. + pbn_b0_bt_2_115200,
  56375. + pbn_b0_bt_1_460800,
  56376. + pbn_b0_bt_2_460800,
  56377. +
  56378. + pbn_b1_1_115200,
  56379. + pbn_b1_2_115200,
  56380. + pbn_b1_4_115200,
  56381. + pbn_b1_8_115200,
  56382. +
  56383. + pbn_b1_2_921600,
  56384. + pbn_b1_4_921600,
  56385. + pbn_b1_8_921600,
  56386. +
  56387. + pbn_b1_2_1382400,
  56388. + pbn_b1_4_1382400,
  56389. + pbn_b1_8_1382400,
  56390. +
  56391. + pbn_b2_8_115200,
  56392. + pbn_b2_4_460800,
  56393. + pbn_b2_8_460800,
  56394. + pbn_b2_16_460800,
  56395. + pbn_b2_4_921600,
  56396. + pbn_b2_8_921600,
  56397. +
  56398. + pbn_b2_bt_1_115200,
  56399. + pbn_b2_bt_2_115200,
  56400. + pbn_b2_bt_4_115200,
  56401. + pbn_b2_bt_2_921600,
  56402. +
  56403. + pbn_panacom,
  56404. + pbn_panacom2,
  56405. + pbn_panacom4,
  56406. + pbn_plx_romulus,
  56407. + pbn_oxsemi,
  56408. + pbn_timedia,
  56409. + pbn_intel_i960,
  56410. + pbn_sgi_ioc3,
  56411. +#ifdef CONFIG_DDB5074
  56412. + pbn_nec_nile4,
  56413. +#endif
  56414. +#if 0
  56415. + pbn_dci_pccom8,
  56416. +#endif
  56417. + pbn_xircom_combo,
  56418. +
  56419. + pbn_siig10x_0,
  56420. + pbn_siig10x_1,
  56421. + pbn_siig10x_2,
  56422. + pbn_siig10x_4,
  56423. + pbn_siig20x_0,
  56424. + pbn_siig20x_2,
  56425. + pbn_siig20x_4,
  56426. +
  56427. + pbn_computone_4,
  56428. + pbn_computone_6,
  56429. + pbn_computone_8,
  56430. +};
  56431. +
  56432. +static struct pci_board pci_boards[] __devinitdata = {
  56433. + /*
  56434. + * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
  56435. + * Offset to get to next UART's registers,
  56436. + * Register shift to use for memory-mapped I/O,
  56437. + * Initialization function, first UART offset
  56438. + */
  56439. +
  56440. + /* Generic serial board, pbn_b0_1_115200, pbn_default */
  56441. + { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200,
  56442. + pbn_default */
  56443. +
  56444. + { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */
  56445. + { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */
  56446. +
  56447. + { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */
  56448. + { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */
  56449. + { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */
  56450. +
  56451. + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
  56452. + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
  56453. + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
  56454. + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
  56455. +
  56456. + { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */
  56457. + { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */
  56458. + { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */
  56459. + { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */
  56460. +
  56461. + { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */
  56462. + { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */
  56463. + { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */
  56464. +
  56465. + { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */
  56466. + { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */
  56467. + { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */
  56468. +
  56469. + { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */
  56470. + { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */
  56471. + { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */
  56472. + { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */
  56473. + { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */
  56474. + { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */
  56475. +
  56476. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
  56477. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
  56478. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
  56479. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
  56480. +
  56481. + { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */
  56482. + 0x400, 7, pci_plx9050_fn },
  56483. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */
  56484. + 0x400, 7, pci_plx9050_fn },
  56485. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */
  56486. + 0x400, 7, pci_plx9050_fn },
  56487. + { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */
  56488. + 0x20, 2, pci_plx9050_fn, 0x03 },
  56489. + /* This board uses the size of PCI Base region 0 to
  56490. + * signal now many ports are available */
  56491. + { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
  56492. + { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */
  56493. + 0, 0, pci_timedia_fn },
  56494. + /* EKF addition for i960 Boards form EKF with serial port */
  56495. + { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */
  56496. + 8<<2, 2, pci_inteli960ni_fn, 0x10000},
  56497. + { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */
  56498. + 1, 458333, 0, 0, 0, 0x20178 },
  56499. +#ifdef CONFIG_DDB5074
  56500. + /*
  56501. + * NEC Vrc-5074 (Nile 4) builtin UART.
  56502. + * Conditionally compiled in since this is a motherboard device.
  56503. + */
  56504. + { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */
  56505. + 64, 3, NULL, 0x300 },
  56506. +#endif
  56507. +#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ /* pbn_dci_pccom8 */
  56508. + { SPCI_FL_BASE3, 8, 115200, 8 },
  56509. +#endif
  56510. + { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */
  56511. + 0, 0, pci_xircom_fn },
  56512. +
  56513. + { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */
  56514. + 0, 0, pci_siig10x_fn },
  56515. + { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */
  56516. + 0, 0, pci_siig10x_fn },
  56517. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */
  56518. + 0, 0, pci_siig10x_fn },
  56519. + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */
  56520. + 0, 0, pci_siig10x_fn },
  56521. + { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */
  56522. + 0, 0, pci_siig20x_fn },
  56523. + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */
  56524. + 0, 0, pci_siig20x_fn },
  56525. + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */
  56526. + 0, 0, pci_siig20x_fn },
  56527. +
  56528. + { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */
  56529. + 0x40, 2, NULL, 0x200 },
  56530. + { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */
  56531. + 0x40, 2, NULL, 0x200 },
  56532. + { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */
  56533. + 0x40, 2, NULL, 0x200 },
  56534. +};
  56535. +
  56536. +/*
  56537. + * Given a complete unknown PCI device, try to use some heuristics to
  56538. + * guess what the configuration might be, based on the pitiful PCI
  56539. + * serial specs. Returns 0 on success, 1 on failure.
  56540. + */
  56541. +static int __devinit serial_pci_guess_board(struct pci_dev *dev,
  56542. + struct pci_board *board)
  56543. +{
  56544. + int num_iomem = 0, num_port = 0, first_port = -1;
  56545. + int i;
  56546. +
  56547. + /*
  56548. + * If it is not a communications device or the programming
  56549. + * interface is greater than 6, give up.
  56550. + *
  56551. + * (Should we try to make guesses for multiport serial devices
  56552. + * later?)
  56553. + */
  56554. + if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
  56555. + ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
  56556. + (dev->class & 0xff) > 6)
  56557. + return 1;
  56558. +
  56559. + for (i=0; i < 6; i++) {
  56560. + if (IS_PCI_REGION_IOPORT(dev, i)) {
  56561. + num_port++;
  56562. + if (first_port == -1)
  56563. + first_port = i;
  56564. + }
  56565. + if (IS_PCI_REGION_IOMEM(dev, i))
  56566. + num_iomem++;
  56567. + }
  56568. +
  56569. + /*
  56570. + * If there is 1 or 0 iomem regions, and exactly one port, use
  56571. + * it.
  56572. + */
  56573. + if (num_iomem <= 1 && num_port == 1) {
  56574. + board->flags = first_port;
  56575. + return 0;
  56576. + }
  56577. + return 1;
  56578. +}
  56579. +
  56580. +/*
  56581. + * return -1 to refuse
  56582. + */
  56583. +static int pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
  56584. +{
  56585. + struct serial_private *priv;
  56586. + struct pci_board *board, tmp;
  56587. + struct serial_struct serial_req;
  56588. + int base_baud, rc, k;
  56589. +
  56590. + board = &pci_boards[ent->driver_data];
  56591. +
  56592. + rc = pci_enable_device(dev);
  56593. + if (rc)
  56594. + return rc;
  56595. +
  56596. + if (ent->driver_data == pbn_default &&
  56597. + serial_pci_guess_board(dev, board))
  56598. + return -ENODEV;
  56599. + else if (serial_pci_guess_board(dev, &tmp) == 0) {
  56600. + printk(KERN_INFO "Redundant entry in serial pci_table. "
  56601. + "Please send the output of\n"
  56602. + "lspci -vv, this message (%d,%d,%d,%d)\n"
  56603. + "and the manufacturer and name of "
  56604. + "serial board or modem board\n"
  56605. + "to serial-pci-info@lists.sourceforge.net.\n",
  56606. + dev->vendor, dev->device,
  56607. + pci_get_subvendor(dev), pci_get_subdevice(dev));
  56608. + }
  56609. +
  56610. +
  56611. + priv = kmalloc(sizeof(struct serial_private) +
  56612. + sizeof(unsigned int) * board->num_ports,
  56613. + GFP_KERNEL);
  56614. + if (!priv)
  56615. + return -ENOMEM;
  56616. +
  56617. + /*
  56618. + * Run the initialization function, if any
  56619. + */
  56620. + if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) {
  56621. + kfree(priv);
  56622. + return -ENODEV;
  56623. + }
  56624. +
  56625. + base_baud = board->base_baud;
  56626. + if (!base_baud)
  56627. + base_baud = BASE_BAUD;
  56628. + memset(&serial_req, 0, sizeof(serial_req));
  56629. + for (k=0; k < board->num_ports; k++) {
  56630. + serial_req.irq = get_pci_irq(dev, board, k);
  56631. + if (get_pci_port(dev, board, &serial_req, k))
  56632. + break;
  56633. +#ifdef SERIAL_DEBUG_PCI
  56634. + printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
  56635. + serial_req.port, serial_req.irq, serial_req.io_type);
  56636. +#endif
  56637. + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
  56638. + serial_req.baud_base = base_baud;
  56639. + priv->line[k] = register_serial(&serial_req);
  56640. + if (priv->line[k] < 0)
  56641. + break;
  56642. + }
  56643. +
  56644. + priv->board = board;
  56645. + priv->nr = k;
  56646. +
  56647. + pci_set_drvdata(dev, priv);
  56648. +
  56649. + return 0;
  56650. +}
  56651. +
  56652. +static void pci_remove_one(struct pci_dev *dev)
  56653. +{
  56654. + struct serial_private *priv = pci_get_drvdata(dev);
  56655. + int i;
  56656. +
  56657. + pci_set_drvdata(dev, NULL);
  56658. +
  56659. + for (i = 0; i < priv->nr; i++)
  56660. + unregister_serial(priv->line[i]);
  56661. +
  56662. + priv->board->init_fn(dev, priv->board, 0);
  56663. +
  56664. + kfree(priv);
  56665. +}
  56666. +
  56667. +static struct pci_device_id serial_pci_tbl[] __devinitdata = {
  56668. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
  56669. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56670. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
  56671. + pbn_b1_8_1382400 },
  56672. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
  56673. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56674. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
  56675. + pbn_b1_4_1382400 },
  56676. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
  56677. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56678. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
  56679. + pbn_b1_2_1382400 },
  56680. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56681. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56682. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
  56683. + pbn_b1_8_1382400 },
  56684. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56685. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56686. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
  56687. + pbn_b1_4_1382400 },
  56688. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56689. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56690. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
  56691. + pbn_b1_2_1382400 },
  56692. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56693. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56694. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
  56695. + pbn_b1_8_921600 },
  56696. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56697. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56698. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
  56699. + pbn_b1_8_921600 },
  56700. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56701. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56702. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
  56703. + pbn_b1_4_921600 },
  56704. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56705. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56706. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
  56707. + pbn_b1_4_921600 },
  56708. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56709. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56710. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
  56711. + pbn_b1_2_921600 },
  56712. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56713. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56714. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
  56715. + pbn_b1_8_921600 },
  56716. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56717. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56718. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
  56719. + pbn_b1_8_921600 },
  56720. + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
  56721. + PCI_SUBVENDOR_ID_CONNECT_TECH,
  56722. + PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
  56723. + pbn_b1_4_921600 },
  56724. +
  56725. + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
  56726. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56727. + pbn_b2_bt_1_115200 },
  56728. + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
  56729. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56730. + pbn_b2_bt_2_115200 },
  56731. + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
  56732. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56733. + pbn_b2_bt_4_115200 },
  56734. + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
  56735. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56736. + pbn_b2_bt_2_115200 },
  56737. + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
  56738. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56739. + pbn_b2_bt_4_115200 },
  56740. + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
  56741. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56742. + pbn_b2_8_115200 },
  56743. +
  56744. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
  56745. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56746. + pbn_b2_bt_2_115200 },
  56747. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
  56748. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56749. + pbn_b2_bt_2_921600 },
  56750. + /* VScom SPCOM800, from sl@s.pl */
  56751. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
  56752. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56753. + pbn_b2_8_921600 },
  56754. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
  56755. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56756. + pbn_b2_4_921600 },
  56757. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56758. + PCI_SUBVENDOR_ID_KEYSPAN,
  56759. + PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
  56760. + pbn_panacom },
  56761. + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
  56762. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56763. + pbn_panacom4 },
  56764. + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
  56765. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56766. + pbn_panacom2 },
  56767. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56768. + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
  56769. + PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
  56770. + pbn_b2_4_460800 },
  56771. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56772. + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
  56773. + PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
  56774. + pbn_b2_8_460800 },
  56775. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56776. + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
  56777. + PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
  56778. + pbn_b2_16_460800 },
  56779. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56780. + PCI_SUBVENDOR_ID_CHASE_PCIFAST,
  56781. + PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
  56782. + pbn_b2_16_460800 },
  56783. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56784. + PCI_SUBVENDOR_ID_CHASE_PCIRAS,
  56785. + PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
  56786. + pbn_b2_4_460800 },
  56787. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
  56788. + PCI_SUBVENDOR_ID_CHASE_PCIRAS,
  56789. + PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
  56790. + pbn_b2_8_460800 },
  56791. + /* Megawolf Romulus PCI Serial Card, from Mike Hudson */
  56792. + /* (Exoray@isys.ca) */
  56793. + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
  56794. + 0x10b5, 0x106a, 0, 0,
  56795. + pbn_plx_romulus },
  56796. + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
  56797. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56798. + pbn_b1_4_115200 },
  56799. + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
  56800. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56801. + pbn_b1_2_115200 },
  56802. + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
  56803. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56804. + pbn_b1_8_115200 },
  56805. + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
  56806. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56807. + pbn_b1_8_115200 },
  56808. + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
  56809. + PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0,
  56810. + pbn_b0_4_921600 },
  56811. + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
  56812. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56813. + pbn_b0_4_115200 },
  56814. + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
  56815. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56816. + pbn_b0_2_115200 },
  56817. +
  56818. + /* Digitan DS560-558, from jimd@esoft.com */
  56819. + { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
  56820. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56821. + pbn_b1_1_115200 },
  56822. +
  56823. + /* 3Com US Robotics 56k Voice Internal PCI model 5610 */
  56824. + { PCI_VENDOR_ID_USR, 0x1008,
  56825. + PCI_ANY_ID, PCI_ANY_ID, },
  56826. +
  56827. + /* Titan Electronic cards */
  56828. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
  56829. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56830. + pbn_b0_1_921600 },
  56831. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
  56832. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56833. + pbn_b0_2_921600 },
  56834. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
  56835. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56836. + pbn_b0_4_921600 },
  56837. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
  56838. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56839. + pbn_b0_4_921600 },
  56840. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
  56841. + PCI_ANY_ID, PCI_ANY_ID,
  56842. + SPCI_FL_BASE1, 1, 921600 },
  56843. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
  56844. + PCI_ANY_ID, PCI_ANY_ID,
  56845. + SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
  56846. + /* The 400L and 800L have a custom hack in get_pci_port */
  56847. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
  56848. + PCI_ANY_ID, PCI_ANY_ID,
  56849. + SPCI_FL_BASE_TABLE, 4, 921600 },
  56850. + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
  56851. + PCI_ANY_ID, PCI_ANY_ID,
  56852. + SPCI_FL_BASE_TABLE, 8, 921600 },
  56853. +
  56854. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
  56855. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56856. + pbn_siig10x_0 },
  56857. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
  56858. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56859. + pbn_siig10x_0 },
  56860. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
  56861. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56862. + pbn_siig10x_0 },
  56863. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
  56864. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56865. + pbn_siig10x_1 },
  56866. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
  56867. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56868. + pbn_siig10x_1 },
  56869. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
  56870. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56871. + pbn_siig10x_1 },
  56872. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
  56873. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56874. + pbn_siig10x_2 },
  56875. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
  56876. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56877. + pbn_siig10x_2 },
  56878. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
  56879. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56880. + pbn_siig10x_2 },
  56881. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
  56882. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56883. + pbn_siig10x_2 },
  56884. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
  56885. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56886. + pbn_siig10x_2 },
  56887. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
  56888. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56889. + pbn_siig10x_2 },
  56890. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
  56891. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56892. + pbn_siig10x_4 },
  56893. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
  56894. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56895. + pbn_siig10x_4 },
  56896. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
  56897. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56898. + pbn_siig10x_4 },
  56899. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
  56900. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56901. + pbn_siig20x_0 },
  56902. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
  56903. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56904. + pbn_siig20x_0 },
  56905. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
  56906. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56907. + pbn_siig20x_0 },
  56908. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
  56909. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56910. + pbn_siig20x_0 },
  56911. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
  56912. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56913. + pbn_siig20x_0 },
  56914. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
  56915. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56916. + pbn_siig20x_0 },
  56917. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
  56918. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56919. + pbn_siig20x_0 },
  56920. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
  56921. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56922. + pbn_siig20x_0 },
  56923. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
  56924. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56925. + pbn_siig20x_0 },
  56926. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
  56927. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56928. + pbn_siig20x_2 },
  56929. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
  56930. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56931. + pbn_siig20x_2 },
  56932. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
  56933. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56934. + pbn_siig20x_2 },
  56935. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
  56936. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56937. + pbn_siig20x_2 },
  56938. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
  56939. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56940. + pbn_siig20x_2 },
  56941. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
  56942. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56943. + pbn_siig20x_2 },
  56944. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
  56945. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56946. + pbn_siig20x_4 },
  56947. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
  56948. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56949. + pbn_siig20x_4 },
  56950. + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
  56951. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56952. + pbn_siig20x_4 },
  56953. +
  56954. + /* Computone devices submitted by Doug McNash dmcnash@computone.com */
  56955. + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
  56956. + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
  56957. + 0, 0, pbn_computone_4 },
  56958. + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
  56959. + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
  56960. + 0, 0, pbn_computone_8 },
  56961. + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
  56962. + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
  56963. + 0, 0, pbn_computone_6 },
  56964. +
  56965. + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
  56966. + PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
  56967. + { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
  56968. + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
  56969. +
  56970. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
  56971. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56972. + pbn_b0_bt_2_115200 },
  56973. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
  56974. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56975. + pbn_b0_bt_2_115200 },
  56976. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
  56977. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56978. + pbn_b0_bt_2_115200 },
  56979. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
  56980. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56981. + pbn_b0_bt_2_460800 },
  56982. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
  56983. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56984. + pbn_b0_bt_2_460800 },
  56985. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
  56986. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56987. + pbn_b0_bt_2_460800 },
  56988. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
  56989. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56990. + pbn_b0_bt_1_115200 },
  56991. + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
  56992. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56993. + pbn_b0_bt_1_460800 },
  56994. +
  56995. + /* RAStel 2 port modem, gerg@moreton.com.au */
  56996. + { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
  56997. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  56998. + pbn_b2_bt_2_115200 },
  56999. +
  57000. + /* EKF addition for i960 Boards form EKF with serial port */
  57001. + { PCI_VENDOR_ID_INTEL, 0x1960,
  57002. + 0xE4BF, PCI_ANY_ID, 0, 0,
  57003. + pbn_intel_i960 },
  57004. +
  57005. + /* Xircom Cardbus/Ethernet combos */
  57006. + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
  57007. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  57008. + pbn_xircom_combo },
  57009. +
  57010. + /*
  57011. + * Untested PCI modems, sent in from various folks...
  57012. + */
  57013. +
  57014. + /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
  57015. + { PCI_VENDOR_ID_ROCKWELL, 0x1004,
  57016. + 0x1048, 0x1500, 0, 0,
  57017. + pbn_b1_1_115200 },
  57018. +
  57019. + { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
  57020. + 0xFF00, 0, 0, 0,
  57021. + pbn_sgi_ioc3 },
  57022. +
  57023. +#ifdef CONFIG_DDB5074
  57024. + /*
  57025. + * NEC Vrc-5074 (Nile 4) builtin UART.
  57026. + * Conditionally compiled in since this is a motherboard device.
  57027. + */
  57028. + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
  57029. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  57030. + pbn_nec_nile4 },
  57031. +#endif
  57032. +
  57033. +#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */
  57034. + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
  57035. + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  57036. + pbn_dci_pccom8 },
  57037. +#endif
  57038. +
  57039. + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
  57040. + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, },
  57041. + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
  57042. + PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, },
  57043. + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
  57044. + PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, },
  57045. + { 0, }
  57046. +};
  57047. +
  57048. +static struct pci_driver serial_pci_driver = {
  57049. + name: "serial",
  57050. + probe: pci_init_one,
  57051. + remove: pci_remove_one,
  57052. + id_table: serial_pci_tbl,
  57053. +};
  57054. +
  57055. +static int __init serial8250_pci_init(void)
  57056. +{
  57057. + return pci_module_init(&serial_pci_driver);
  57058. +}
  57059. +
  57060. +static void __exit serial8250_pci_exit(void)
  57061. +{
  57062. + pci_unregister_driver(&serial_pci_driver);
  57063. +}
  57064. +
  57065. +module_init(serial8250_pci_init);
  57066. +module_exit(serial8250_pci_exit);
  57067. +
  57068. +EXPORT_NO_SYMBOLS;
  57069. +
  57070. +MODULE_LICENSE("GPL");
  57071. +MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
  57072. +MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
  57073. diff -urN linux-2.4.26/drivers/serial/8250_pnp.c linux-2.4.26-vrs1/drivers/serial/8250_pnp.c
  57074. --- linux-2.4.26/drivers/serial/8250_pnp.c 1970-01-01 01:00:00.000000000 +0100
  57075. +++ linux-2.4.26-vrs1/drivers/serial/8250_pnp.c 2004-01-14 21:32:26.000000000 +0000
  57076. @@ -0,0 +1,553 @@
  57077. +/*
  57078. + * linux/drivers/char/serial_8250_pnp.c
  57079. + *
  57080. + * Probe module for 8250/16550-type ISAPNP serial ports.
  57081. + *
  57082. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  57083. + *
  57084. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  57085. + *
  57086. + * This program is free software; you can redistribute it and/or modify
  57087. + * it under the terms of the GNU General Public License as published by
  57088. + * the Free Software Foundation; either version 2 of the License.
  57089. + *
  57090. + * $Id: 8250_pnp.c,v 1.3.2.1 2002/10/24 09:53:25 rmk Exp $
  57091. + */
  57092. +#include <linux/config.h>
  57093. +#include <linux/module.h>
  57094. +#include <linux/init.h>
  57095. +#include <linux/pci.h>
  57096. +#include <linux/isapnp.h>
  57097. +#include <linux/string.h>
  57098. +#include <linux/kernel.h>
  57099. +#include <linux/serial.h>
  57100. +#include <linux/serialP.h>
  57101. +
  57102. +#include <asm/bitops.h>
  57103. +#include <asm/byteorder.h>
  57104. +#include <asm/serial.h>
  57105. +
  57106. +#include "8250.h"
  57107. +
  57108. +static struct serial_state rs_table[] = { };
  57109. +#define NR_PORTS 0
  57110. +
  57111. +struct pnpbios_device_id
  57112. +{
  57113. + char id[8];
  57114. + unsigned long driver_data;
  57115. +};
  57116. +
  57117. +static const struct pnpbios_device_id pnp_dev_table[] = {
  57118. + /* Archtek America Corp. */
  57119. + /* Archtek SmartLink Modem 3334BT Plug & Play */
  57120. + { "AAC000F", 0 },
  57121. + /* Anchor Datacomm BV */
  57122. + /* SXPro 144 External Data Fax Modem Plug & Play */
  57123. + { "ADC0001", 0 },
  57124. + /* SXPro 288 External Data Fax Modem Plug & Play */
  57125. + { "ADC0002", 0 },
  57126. + /* Rockwell 56K ACF II Fax+Data+Voice Modem */
  57127. + { "AKY1021", SPCI_FL_NO_SHIRQ },
  57128. + /* AZT3005 PnP SOUND DEVICE */
  57129. + { "AZT4001", 0 },
  57130. + /* Best Data Products Inc. Smart One 336F PnP Modem */
  57131. + { "BDP3336", 0 },
  57132. + /* Boca Research */
  57133. + /* Boca Complete Ofc Communicator 14.4 Data-FAX */
  57134. + { "BRI0A49", 0 },
  57135. + /* Boca Research 33,600 ACF Modem */
  57136. + { "BRI1400", 0 },
  57137. + /* Boca 33.6 Kbps Internal FD34FSVD */
  57138. + { "BRI3400", 0 },
  57139. + /* Boca 33.6 Kbps Internal FD34FSVD */
  57140. + { "BRI0A49", 0 },
  57141. + /* Best Data Products Inc. Smart One 336F PnP Modem */
  57142. + { "BDP3336", 0 },
  57143. + /* Computer Peripherals Inc */
  57144. + /* EuroViVa CommCenter-33.6 SP PnP */
  57145. + { "CPI4050", 0 },
  57146. + /* Creative Labs */
  57147. + /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
  57148. + { "CTL3001", 0 },
  57149. + /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
  57150. + { "CTL3011", 0 },
  57151. + /* Creative */
  57152. + /* Creative Modem Blaster Flash56 DI5601-1 */
  57153. + { "DMB1032", 0 },
  57154. + /* Creative Modem Blaster V.90 DI5660 */
  57155. + { "DMB2001", 0 },
  57156. + /* FUJITSU */
  57157. + /* Fujitsu 33600 PnP-I2 R Plug & Play */
  57158. + { "FUJ0202", 0 },
  57159. + /* Fujitsu FMV-FX431 Plug & Play */
  57160. + { "FUJ0205", 0 },
  57161. + /* Fujitsu 33600 PnP-I4 R Plug & Play */
  57162. + { "FUJ0206", 0 },
  57163. + /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
  57164. + { "FUJ0209", 0 },
  57165. + /* Archtek America Corp. */
  57166. + /* Archtek SmartLink Modem 3334BT Plug & Play */
  57167. + { "GVC000F", 0 },
  57168. + /* Hayes */
  57169. + /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
  57170. + { "HAY0001", 0 },
  57171. + /* Hayes Optima 336 V.34 + FAX + Voice PnP */
  57172. + { "HAY000C", 0 },
  57173. + /* Hayes Optima 336B V.34 + FAX + Voice PnP */
  57174. + { "HAY000D", 0 },
  57175. + /* Hayes Accura 56K Ext Fax Modem PnP */
  57176. + { "HAY5670", 0 },
  57177. + /* Hayes Accura 56K Ext Fax Modem PnP */
  57178. + { "HAY5674", 0 },
  57179. + /* Hayes Accura 56K Fax Modem PnP */
  57180. + { "HAY5675", 0 },
  57181. + /* Hayes 288, V.34 + FAX */
  57182. + { "HAYF000", 0 },
  57183. + /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
  57184. + { "HAYF001", 0 },
  57185. + /* IBM */
  57186. + /* IBM Thinkpad 701 Internal Modem Voice */
  57187. + { "IBM0033", 0 },
  57188. + /* Intertex */
  57189. + /* Intertex 28k8 33k6 Voice EXT PnP */
  57190. + { "IXDC801", 0 },
  57191. + /* Intertex 33k6 56k Voice EXT PnP */
  57192. + { "IXDC901", 0 },
  57193. + /* Intertex 28k8 33k6 Voice SP EXT PnP */
  57194. + { "IXDD801", 0 },
  57195. + /* Intertex 33k6 56k Voice SP EXT PnP */
  57196. + { "IXDD901", 0 },
  57197. + /* Intertex 28k8 33k6 Voice SP INT PnP */
  57198. + { "IXDF401", 0 },
  57199. + /* Intertex 28k8 33k6 Voice SP EXT PnP */
  57200. + { "IXDF801", 0 },
  57201. + /* Intertex 33k6 56k Voice SP EXT PnP */
  57202. + { "IXDF901", 0 },
  57203. + /* Kortex International */
  57204. + /* KORTEX 28800 Externe PnP */
  57205. + { "KOR4522", 0 },
  57206. + /* KXPro 33.6 Vocal ASVD PnP */
  57207. + { "KORF661", 0 },
  57208. + /* Lasat */
  57209. + /* LASAT Internet 33600 PnP */
  57210. + { "LAS4040", 0 },
  57211. + /* Lasat Safire 560 PnP */
  57212. + { "LAS4540", 0 },
  57213. + /* Lasat Safire 336 PnP */
  57214. + { "LAS5440", 0 },
  57215. + /* Microcom, Inc. */
  57216. + /* Microcom TravelPorte FAST V.34 Plug & Play */
  57217. + { "MNP0281", 0 },
  57218. + /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
  57219. + { "MNP0336", 0 },
  57220. + /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
  57221. + { "MNP0339", 0 },
  57222. + /* Microcom DeskPorte 28.8P Plug & Play */
  57223. + { "MNP0342", 0 },
  57224. + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
  57225. + { "MNP0500", 0 },
  57226. + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
  57227. + { "MNP0501", 0 },
  57228. + /* Microcom DeskPorte 28.8S Internal Plug & Play */
  57229. + { "MNP0502", 0 },
  57230. + /* Motorola */
  57231. + /* Motorola BitSURFR Plug & Play */
  57232. + { "MOT1105", 0 },
  57233. + /* Motorola TA210 Plug & Play */
  57234. + { "MOT1111", 0 },
  57235. + /* Motorola HMTA 200 (ISDN) Plug & Play */
  57236. + { "MOT1114", 0 },
  57237. + /* Motorola BitSURFR Plug & Play */
  57238. + { "MOT1115", 0 },
  57239. + /* Motorola Lifestyle 28.8 Internal */
  57240. + { "MOT1190", 0 },
  57241. + /* Motorola V.3400 Plug & Play */
  57242. + { "MOT1501", 0 },
  57243. + /* Motorola Lifestyle 28.8 V.34 Plug & Play */
  57244. + { "MOT1502", 0 },
  57245. + /* Motorola Power 28.8 V.34 Plug & Play */
  57246. + { "MOT1505", 0 },
  57247. + /* Motorola ModemSURFR External 28.8 Plug & Play */
  57248. + { "MOT1509", 0 },
  57249. + /* Motorola Premier 33.6 Desktop Plug & Play */
  57250. + { "MOT150A", 0 },
  57251. + /* Motorola VoiceSURFR 56K External PnP */
  57252. + { "MOT150F", 0 },
  57253. + /* Motorola ModemSURFR 56K External PnP */
  57254. + { "MOT1510", 0 },
  57255. + /* Motorola ModemSURFR 56K Internal PnP */
  57256. + { "MOT1550", 0 },
  57257. + /* Motorola ModemSURFR Internal 28.8 Plug & Play */
  57258. + { "MOT1560", 0 },
  57259. + /* Motorola Premier 33.6 Internal Plug & Play */
  57260. + { "MOT1580", 0 },
  57261. + /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
  57262. + { "MOT15B0", 0 },
  57263. + /* Motorola VoiceSURFR 56K Internal PnP */
  57264. + { "MOT15F0", 0 },
  57265. + /* Com 1 */
  57266. + /* Deskline K56 Phone System PnP */
  57267. + { "MVX00A1", 0 },
  57268. + /* PC Rider K56 Phone System PnP */
  57269. + { "MVX00F2", 0 },
  57270. + /* Pace 56 Voice Internal Plug & Play Modem */
  57271. + { "PMC2430", 0 },
  57272. + /* Generic */
  57273. + /* Generic standard PC COM port */
  57274. + { "PNP0500", 0 },
  57275. + /* Generic 16550A-compatible COM port */
  57276. + { "PNP0501", 0 },
  57277. + /* Compaq 14400 Modem */
  57278. + { "PNPC000", 0 },
  57279. + /* Compaq 2400/9600 Modem */
  57280. + { "PNPC001", 0 },
  57281. + /* Dial-Up Networking Serial Cable between 2 PCs */
  57282. + { "PNPC031", 0 },
  57283. + /* Dial-Up Networking Parallel Cable between 2 PCs */
  57284. + { "PNPC032", 0 },
  57285. + /* Standard 9600 bps Modem */
  57286. + { "PNPC100", 0 },
  57287. + /* Standard 14400 bps Modem */
  57288. + { "PNPC101", 0 },
  57289. + /* Standard 28800 bps Modem*/
  57290. + { "PNPC102", 0 },
  57291. + /* Standard Modem*/
  57292. + { "PNPC103", 0 },
  57293. + /* Standard 9600 bps Modem*/
  57294. + { "PNPC104", 0 },
  57295. + /* Standard 14400 bps Modem*/
  57296. + { "PNPC105", 0 },
  57297. + /* Standard 28800 bps Modem*/
  57298. + { "PNPC106", 0 },
  57299. + /* Standard Modem */
  57300. + { "PNPC107", 0 },
  57301. + /* Standard 9600 bps Modem */
  57302. + { "PNPC108", 0 },
  57303. + /* Standard 14400 bps Modem */
  57304. + { "PNPC109", 0 },
  57305. + /* Standard 28800 bps Modem */
  57306. + { "PNPC10A", 0 },
  57307. + /* Standard Modem */
  57308. + { "PNPC10B", 0 },
  57309. + /* Standard 9600 bps Modem */
  57310. + { "PNPC10C", 0 },
  57311. + /* Standard 14400 bps Modem */
  57312. + { "PNPC10D", 0 },
  57313. + /* Standard 28800 bps Modem */
  57314. + { "PNPC10E", 0 },
  57315. + /* Standard Modem */
  57316. + { "PNPC10F", 0 },
  57317. + /* Standard PCMCIA Card Modem */
  57318. + { "PNP2000", 0 },
  57319. + /* Rockwell */
  57320. + /* Modular Technology */
  57321. + /* Rockwell 33.6 DPF Internal PnP */
  57322. + /* Modular Technology 33.6 Internal PnP */
  57323. + { "ROK0030", 0 },
  57324. + /* Kortex International */
  57325. + /* KORTEX 14400 Externe PnP */
  57326. + { "ROK0100", 0 },
  57327. + /* Viking Components, Inc */
  57328. + /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
  57329. + { "ROK4920", 0 },
  57330. + /* Rockwell */
  57331. + /* British Telecom */
  57332. + /* Modular Technology */
  57333. + /* Rockwell 33.6 DPF External PnP */
  57334. + /* BT Prologue 33.6 External PnP */
  57335. + /* Modular Technology 33.6 External PnP */
  57336. + { "RSS00A0", 0 },
  57337. + /* Viking 56K FAX INT */
  57338. + { "RSS0262", 0 },
  57339. + /* SupraExpress 28.8 Data/Fax PnP modem */
  57340. + { "SUP1310", 0 },
  57341. + /* SupraExpress 33.6 Data/Fax PnP modem */
  57342. + { "SUP1421", 0 },
  57343. + /* SupraExpress 33.6 Data/Fax PnP modem */
  57344. + { "SUP1590", 0 },
  57345. + /* SupraExpress 33.6 Data/Fax PnP modem */
  57346. + { "SUP1760", 0 },
  57347. + /* Phoebe Micro */
  57348. + /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
  57349. + { "TEX0011", 0 },
  57350. + /* Archtek America Corp. */
  57351. + /* Archtek SmartLink Modem 3334BT Plug & Play */
  57352. + { "UAC000F", 0 },
  57353. + /* 3Com Corp. */
  57354. + /* Gateway Telepath IIvi 33.6 */
  57355. + { "USR0000", 0 },
  57356. + /* Sportster Vi 14.4 PnP FAX Voicemail */
  57357. + { "USR0004", 0 },
  57358. + /* U.S. Robotics 33.6K Voice INT PnP */
  57359. + { "USR0006", 0 },
  57360. + /* U.S. Robotics 33.6K Voice EXT PnP */
  57361. + { "USR0007", 0 },
  57362. + /* U.S. Robotics 33.6K Voice INT PnP */
  57363. + { "USR2002", 0 },
  57364. + /* U.S. Robotics 56K Voice INT PnP */
  57365. + { "USR2070", 0 },
  57366. + /* U.S. Robotics 56K Voice EXT PnP */
  57367. + { "USR2080", 0 },
  57368. + /* U.S. Robotics 56K FAX INT */
  57369. + { "USR3031", 0 },
  57370. + /* U.S. Robotics 56K Voice INT PnP */
  57371. + { "USR3070", 0 },
  57372. + /* U.S. Robotics 56K Voice EXT PnP */
  57373. + { "USR3080", 0 },
  57374. + /* U.S. Robotics 56K Voice INT PnP */
  57375. + { "USR3090", 0 },
  57376. + /* U.S. Robotics 56K Message */
  57377. + { "USR9100", 0 },
  57378. + /* U.S. Robotics 56K FAX EXT PnP*/
  57379. + { "USR9160", 0 },
  57380. + /* U.S. Robotics 56K FAX INT PnP*/
  57381. + { "USR9170", 0 },
  57382. + /* U.S. Robotics 56K Voice EXT PnP*/
  57383. + { "USR9180", 0 },
  57384. + /* U.S. Robotics 56K Voice INT PnP*/
  57385. + { "USR9190", 0 },
  57386. + { "", 0 }
  57387. +};
  57388. +
  57389. +static void inline avoid_irq_share(struct pci_dev *dev)
  57390. +{
  57391. + int i, map = 0x1FF8;
  57392. + struct serial_state *state = rs_table;
  57393. + struct isapnp_irq *irq;
  57394. + struct isapnp_resources *res = dev->sysdata;
  57395. +
  57396. + for (i = 0; i < NR_PORTS; i++) {
  57397. + if (state->type != PORT_UNKNOWN)
  57398. + clear_bit(state->irq, &map);
  57399. + state++;
  57400. + }
  57401. +
  57402. + for ( ; res; res = res->alt)
  57403. + for(irq = res->irq; irq; irq = irq->next)
  57404. + irq->map = map;
  57405. +}
  57406. +
  57407. +static char *modem_names[] __devinitdata = {
  57408. + "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
  57409. + "56K", "56k", "K56", "33.6", "28.8", "14.4",
  57410. + "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
  57411. + "33600", "28800", "14400", "V.90", "V.34", "V.32", 0
  57412. +};
  57413. +
  57414. +static int __devinit check_name(char *name)
  57415. +{
  57416. + char **tmp;
  57417. +
  57418. + for (tmp = modem_names; *tmp; tmp++)
  57419. + if (strstr(name, *tmp))
  57420. + return 1;
  57421. +
  57422. + return 0;
  57423. +}
  57424. +
  57425. +static int inline check_compatible_id(struct pci_dev *dev)
  57426. +{
  57427. + int i;
  57428. + for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
  57429. + if ((dev->vendor_compatible[i] ==
  57430. + ISAPNP_VENDOR('P', 'N', 'P')) &&
  57431. + (swab16(dev->device_compatible[i]) >= 0xc000) &&
  57432. + (swab16(dev->device_compatible[i]) <= 0xdfff))
  57433. + return 0;
  57434. + return 1;
  57435. +}
  57436. +
  57437. +/*
  57438. + * Given a complete unknown ISA PnP device, try to use some heuristics to
  57439. + * detect modems. Currently use such heuristic set:
  57440. + * - dev->name or dev->bus->name must contain "modem" substring;
  57441. + * - device must have only one IO region (8 byte long) with base adress
  57442. + * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
  57443. + *
  57444. + * Such detection looks very ugly, but can detect at least some of numerous
  57445. + * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
  57446. + * table.
  57447. + */
  57448. +static int serial_pnp_guess_board(struct pci_dev *dev, int *flags)
  57449. +{
  57450. + struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
  57451. + struct isapnp_resources *resa;
  57452. +
  57453. + if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
  57454. + !(check_compatible_id(dev)))
  57455. + return -ENODEV;
  57456. +
  57457. + if (!res || res->next)
  57458. + return -ENODEV;
  57459. +
  57460. + for (resa = res->alt; resa; resa = resa->alt) {
  57461. + struct isapnp_port *port;
  57462. + for (port = res->port; port; port = port->next)
  57463. + if ((port->size == 8) &&
  57464. + ((port->min == 0x2f8) ||
  57465. + (port->min == 0x3f8) ||
  57466. + (port->min == 0x2e8) ||
  57467. + (port->min == 0x3e8)))
  57468. + return 0;
  57469. + }
  57470. +
  57471. + return -ENODEV;
  57472. +}
  57473. +
  57474. +static int
  57475. +pnp_init_one(struct pci_dev *dev, const struct pnpbios_device_id *ent,
  57476. + char *slot_name)
  57477. +{
  57478. + struct serial_struct serial_req;
  57479. + int ret, line, flags = ent ? ent->driver_data : 0;
  57480. +
  57481. + if (!ent) {
  57482. + ret = serial_pnp_guess_board(dev, &flags);
  57483. + if (ret)
  57484. + return ret;
  57485. + }
  57486. +
  57487. + if (dev->prepare(dev) < 0) {
  57488. + printk("serial: PNP device '%s' prepare failed\n",
  57489. + slot_name);
  57490. + return -ENODEV;
  57491. + }
  57492. +
  57493. + if (dev->active)
  57494. + return -ENODEV;
  57495. +
  57496. + if (flags & SPCI_FL_NO_SHIRQ)
  57497. + avoid_irq_share(dev);
  57498. +
  57499. + if (dev->activate(dev) < 0) {
  57500. + printk("serial: PNP device '%s' activate failed\n",
  57501. + slot_name);
  57502. + return -ENODEV;
  57503. + }
  57504. +
  57505. + memset(&serial_req, 0, sizeof(serial_req));
  57506. + serial_req.irq = dev->irq_resource[0].start;
  57507. + serial_req.port = pci_resource_start(dev, 0);
  57508. + if (HIGH_BITS_OFFSET)
  57509. + serial_req.port = pci_resource_start(dev, 0) >> HIGH_BITS_OFFSET;
  57510. +
  57511. +#ifdef SERIAL_DEBUG_PCI
  57512. + printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
  57513. + serial_req.port, serial_req.irq, serial_req.io_type);
  57514. +#endif
  57515. +
  57516. + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
  57517. + serial_req.baud_base = 115200;
  57518. + line = register_serial(&serial_req);
  57519. +
  57520. + if (line >= 0) {
  57521. + pci_set_drvdata(dev, (void *)(line + 1));
  57522. +
  57523. + /*
  57524. + * Public health warning: remove this once the 2.5
  57525. + * pnpbios_module_init() stuff is incorporated.
  57526. + */
  57527. + dev->driver = (void *)pnp_dev_table;
  57528. + } else
  57529. + dev->deactivate(dev);
  57530. +
  57531. + return line >= 0 ? 0 : -ENODEV;
  57532. +}
  57533. +
  57534. +static void pnp_remove_one(struct pci_dev *dev)
  57535. +{
  57536. + int line = (int)pci_get_drvdata(dev);
  57537. +
  57538. + if (line) {
  57539. + pci_set_drvdata(dev, NULL);
  57540. +
  57541. + unregister_serial(line - 1);
  57542. +
  57543. + dev->deactivate(dev);
  57544. + }
  57545. +}
  57546. +
  57547. +static char hex[] = "0123456789ABCDEF";
  57548. +
  57549. +/*
  57550. + * This function should vanish when 2.5 comes around and
  57551. + * we have pnpbios_module_init()
  57552. + */
  57553. +static void pnp_init(void)
  57554. +{
  57555. + const struct pnpbios_device_id *id;
  57556. + struct pci_dev *dev = NULL;
  57557. +
  57558. +#ifdef SERIAL_DEBUG_PNP
  57559. + printk("Entered probe_serial_pnp()\n");
  57560. +#endif
  57561. +
  57562. + isapnp_for_each_dev(dev) {
  57563. + char slot_name[8];
  57564. + u32 pnpid;
  57565. +
  57566. + if (dev->active)
  57567. + continue;
  57568. +
  57569. + pnpid = dev->vendor << 16 | dev->device;
  57570. + pnpid = cpu_to_le32(pnpid);
  57571. +
  57572. +#define HEX(id,a) hex[((id)>>a) & 15]
  57573. +#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
  57574. + slot_name[0] = CHAR(pnpid, 26);
  57575. + slot_name[1] = CHAR(pnpid, 21);
  57576. + slot_name[2] = CHAR(pnpid, 16);
  57577. + slot_name[3] = HEX(pnpid, 12);
  57578. + slot_name[4] = HEX(pnpid, 8);
  57579. + slot_name[5] = HEX(pnpid, 4);
  57580. + slot_name[6] = HEX(pnpid, 0);
  57581. + slot_name[7] = '\0';
  57582. +
  57583. + for (id = pnp_dev_table; id->id[0]; id++)
  57584. + if (memcmp(id->id, slot_name, 7) == 0)
  57585. + break;
  57586. +
  57587. + if (id->id[0])
  57588. + pnp_init_one(dev, id, slot_name);
  57589. + else
  57590. + pnp_init_one(dev, NULL, slot_name);
  57591. + }
  57592. +
  57593. +#ifdef SERIAL_DEBUG_PNP
  57594. + printk("Leaving probe_serial_pnp() (probe finished)\n");
  57595. +#endif
  57596. +}
  57597. +
  57598. +static int __init serial8250_pnp_init(void)
  57599. +{
  57600. + if (!isapnp_present()) {
  57601. +#ifdef SERIAL_DEBUG_PNP
  57602. + printk("Leaving probe_serial_pnp() (no isapnp)\n");
  57603. +#endif
  57604. + return -ENODEV;
  57605. + }
  57606. + pnp_init();
  57607. + return 0;
  57608. +}
  57609. +
  57610. +static void __exit serial8250_pnp_exit(void)
  57611. +{
  57612. + struct pci_dev *dev = NULL;
  57613. +
  57614. + isapnp_for_each_dev(dev) {
  57615. + if (dev->driver != (void *)pnp_dev_table)
  57616. + continue;
  57617. + pnp_remove_one(dev);
  57618. + }
  57619. +}
  57620. +
  57621. +module_init(serial8250_pnp_init);
  57622. +module_exit(serial8250_pnp_exit);
  57623. +
  57624. +EXPORT_NO_SYMBOLS;
  57625. +
  57626. +MODULE_LICENSE("GPL");
  57627. +MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
  57628. +MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
  57629. +
  57630. diff -urN linux-2.4.26/drivers/serial/Config.in linux-2.4.26-vrs1/drivers/serial/Config.in
  57631. --- linux-2.4.26/drivers/serial/Config.in 1970-01-01 01:00:00.000000000 +0100
  57632. +++ linux-2.4.26-vrs1/drivers/serial/Config.in 2004-01-14 21:32:26.000000000 +0000
  57633. @@ -0,0 +1,91 @@
  57634. +#
  57635. +# Serial device configuration
  57636. +#
  57637. +# $Id: Config.in,v 1.4 2001/10/12 15:46:58 rmk Exp $
  57638. +#
  57639. +mainmenu_option next_comment
  57640. +comment 'Serial drivers'
  57641. +
  57642. +if [ "$CONFIG_ARM" = "y" ]; then
  57643. + # I don't have this in my tree yet.
  57644. + dep_bool 'Anakin serial port support' CONFIG_SERIAL_ANAKIN $CONFIG_ARCH_ANAKIN
  57645. + dep_bool ' Console on Anakin serial port' CONFIG_SERIAL_ANAKIN_CONSOLE $CONFIG_SERIAL_ANAKIN
  57646. + if [ "$CONFIG_SERIAL_ANAKIN" = "y" ]; then
  57647. + int ' Default Anakin serial baudrate' CONFIG_ANAKIN_DEFAULT_BAUDRATE 9600
  57648. + fi
  57649. +
  57650. + dep_tristate 'ARM AMBA serial port support' CONFIG_SERIAL_AMBA $CONFIG_ARCH_INTEGRATOR
  57651. + dep_bool ' Support for console on AMBA serial port' CONFIG_SERIAL_AMBA_CONSOLE $CONFIG_SERIAL_AMBA
  57652. + if [ "$CONFIG_SERIAL_AMBA" = "y" ]; then
  57653. + define_bool CONFIG_SERIAL_INTEGRATOR y
  57654. + fi
  57655. +
  57656. + dep_tristate 'CLPS711X serial port support' CONFIG_SERIAL_CLPS711X $CONFIG_ARCH_CLPS711X
  57657. + dep_bool ' Support for console on CLPS711X serial port' CONFIG_SERIAL_CLPS711X_CONSOLE $CONFIG_SERIAL_CLPS711X
  57658. +
  57659. + dep_bool 'DC21285 serial port support' CONFIG_SERIAL_21285 $CONFIG_FOOTBRIDGE
  57660. + dep_bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD $CONFIG_SERIAL_21285 $CONFIG_OBSOLETE
  57661. + dep_bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE $CONFIG_SERIAL_21285
  57662. +
  57663. + dep_bool 'Excalibur serial port (uart00) support' CONFIG_SERIAL_UART00 $CONFIG_ARCH_CAMELOT
  57664. + dep_bool ' Support for console on Excalibur serial port' CONFIG_SERIAL_UART00_CONSOLE $CONFIG_SERIAL_UART00
  57665. +
  57666. +
  57667. + dep_bool 'SA1100 serial port support' CONFIG_SERIAL_SA1100 $CONFIG_ARCH_SA1100
  57668. + dep_bool ' Console on SA1100 serial port' CONFIG_SERIAL_SA1100_CONSOLE $CONFIG_SERIAL_SA1100
  57669. + if [ "$CONFIG_SERIAL_SA1100" = "y" ]; then
  57670. + int ' Default SA1100 serial baudrate' CONFIG_SA1100_DEFAULT_BAUDRATE 9600
  57671. + fi
  57672. +
  57673. + dep_tristate 'ARM Omaha serial port support' CONFIG_SERIAL_OMAHA $CONFIG_ARCH_OMAHA
  57674. + dep_bool ' Support for console on Omaha serial port' CONFIG_SERIAL_OMAHA_CONSOLE $CONFIG_SERIAL_OMAHA
  57675. +
  57676. + dep_tristate 'AT91RM9200 serial port support' CONFIG_SERIAL_AT91 $CONFIG_ARCH_AT91RM9200
  57677. + dep_bool ' Console on AT91RM9200 serial port' CONFIG_SERIAL_AT91_CONSOLE $CONFIG_SERIAL_AT91
  57678. +
  57679. +fi
  57680. +#
  57681. +# The new 8250/16550 serial drivers
  57682. +dep_tristate '8250/16550 and compatible serial support (EXPERIMENTAL)' CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
  57683. +dep_bool ' Console on 8250/16550 and compatible serial port (EXPERIMENTAL)' CONFIG_SERIAL_8250_CONSOLE $CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
  57684. +
  57685. +dep_mbool 'Extended 8250/16550 serial driver options' CONFIG_SERIAL_8250_EXTENDED $CONFIG_SERIAL_8250
  57686. +dep_bool ' Support more than 4 serial ports' CONFIG_SERIAL_8250_MANY_PORTS $CONFIG_SERIAL_8250_EXTENDED
  57687. +dep_bool ' Support for sharing serial interrupts' CONFIG_SERIAL_8250_SHARE_IRQ $CONFIG_SERIAL_8250_EXTENDED
  57688. +dep_bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_8250_DETECT_IRQ $CONFIG_SERIAL_8250_EXTENDED
  57689. +dep_bool ' Support special multiport boards' CONFIG_SERIAL_8250_MULTIPORT $CONFIG_SERIAL_8250_EXTENDED
  57690. +dep_bool ' Support Bell Technologies HUB6 card' CONFIG_SERIAL_8250_HUB6 $CONFIG_SERIAL_8250_EXTENDED
  57691. +
  57692. +if [ "$CONFIG_SERIAL_AMBA" = "y" -o \
  57693. + "$CONFIG_SERIAL_CLPS711X" = "y" -o \
  57694. + "$CONFIG_SERIAL_SA1100" = "y" -o \
  57695. + "$CONFIG_SERIAL_ANAKIN" = "y" -o \
  57696. + "$CONFIG_SERIAL_UART00" = "y" -o \
  57697. + "$CONFIG_SERIAL_8250" = "y" -o \
  57698. + "$CONFIG_SERIAL_OMAHA" = "y" -o \
  57699. + "$CONFIG_SERIAL_AT91" = "y" ]; then
  57700. + define_bool CONFIG_SERIAL_CORE y
  57701. +else
  57702. + if [ "$CONFIG_SERIAL_AMBA" = "m" -o \
  57703. + "$CONFIG_SERIAL_CLPS711X" = "m" -o \
  57704. + "$CONFIG_SERIAL_SA1100" = "m" -o \
  57705. + "$CONFIG_SERIAL_ANAKIN" = "m" -o \
  57706. + "$CONFIG_SERIAL_UART00" = "m" -o \
  57707. + "$CONFIG_SERIAL_8250" = "m" -o \
  57708. + "$CONFIG_SERIAL_OMAHA" = "m" -o \
  57709. + "$CONFIG_SERIAL_AT91" = "m" ]; then
  57710. + define_bool CONFIG_SERIAL_CORE m
  57711. + fi
  57712. +fi
  57713. +if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \
  57714. + "$CONFIG_SERIAL_CLPS711X_CONSOLE" = "y" -o \
  57715. + "$CONFIG_SERIAL_SA1100_CONSOLE" = "y" -o \
  57716. + "$CONFIG_SERIAL_ANAKIN_CONSOLE" = "y" -o \
  57717. + "$CONFIG_SERIAL_UART00_CONSOLE" = "y" -o \
  57718. + "$CONFIG_SERIAL_8250_CONSOLE" = "y" -o \
  57719. + "$CONFIG_SERIAL_OMAHA" = "y" -o \
  57720. + "$CONFIG_SERIAL_AT91_CONSOLE" = "y" ]; then
  57721. + define_bool CONFIG_SERIAL_CORE_CONSOLE y
  57722. +fi
  57723. +
  57724. +endmenu
  57725. diff -urN linux-2.4.26/drivers/serial/Makefile linux-2.4.26-vrs1/drivers/serial/Makefile
  57726. --- linux-2.4.26/drivers/serial/Makefile 1970-01-01 01:00:00.000000000 +0100
  57727. +++ linux-2.4.26-vrs1/drivers/serial/Makefile 2004-01-14 21:32:26.000000000 +0000
  57728. @@ -0,0 +1,39 @@
  57729. +#
  57730. +# Makefile for the kernel serial device drivers.
  57731. +#
  57732. +# Note! Dependencies are done automagically by 'make dep', which also
  57733. +# removes any old dependencies. DON'T put your own dependencies here
  57734. +# unless it's something special (ie not a .c file).
  57735. +#
  57736. +# Note 2! The CFLAGS definitions are now inherited from the
  57737. +# parent makes..
  57738. +#
  57739. +# $Id: Makefile,v 1.2 2001/10/12 15:46:58 rmk Exp $
  57740. +#
  57741. +
  57742. +O_TARGET := serial.o
  57743. +
  57744. +export-objs := core.o 8250.o
  57745. +obj-y :=
  57746. +obj-m :=
  57747. +obj-n :=
  57748. +obj- :=
  57749. +
  57750. +serial-8250-y :=
  57751. +serial-8250-$(CONFIG_PCI) += 8250_pci.o
  57752. +serial-8250-$(CONFIG_ISAPNP) += 8250_pnp.o
  57753. +obj-$(CONFIG_SERIAL_CORE) += core.o
  57754. +obj-$(CONFIG_SERIAL_21285) += 21285.o
  57755. +obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
  57756. +obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
  57757. +obj-$(CONFIG_SERIAL_AMBA) += amba.o
  57758. +obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
  57759. +obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
  57760. +obj-$(CONFIG_SERIAL_UART00) += uart00.o
  57761. +obj-$(CONFIG_SERIAL_OMAHA) += omaha.o
  57762. +obj-$(CONFIG_SERIAL_AT91US3) += at91us3.o
  57763. +
  57764. +include $(TOPDIR)/Rules.make
  57765. +
  57766. +fastdep:
  57767. +
  57768. diff -urN linux-2.4.26/drivers/serial/amba.c linux-2.4.26-vrs1/drivers/serial/amba.c
  57769. --- linux-2.4.26/drivers/serial/amba.c 1970-01-01 01:00:00.000000000 +0100
  57770. +++ linux-2.4.26-vrs1/drivers/serial/amba.c 2004-01-14 21:32:26.000000000 +0000
  57771. @@ -0,0 +1,770 @@
  57772. +/*
  57773. + * linux/drivers/char/serial_amba.c
  57774. + *
  57775. + * Driver for AMBA serial ports
  57776. + *
  57777. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  57778. + *
  57779. + * Copyright 1999 ARM Limited
  57780. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  57781. + *
  57782. + * This program is free software; you can redistribute it and/or modify
  57783. + * it under the terms of the GNU General Public License as published by
  57784. + * the Free Software Foundation; either version 2 of the License, or
  57785. + * (at your option) any later version.
  57786. + *
  57787. + * This program is distributed in the hope that it will be useful,
  57788. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  57789. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  57790. + * GNU General Public License for more details.
  57791. + *
  57792. + * You should have received a copy of the GNU General Public License
  57793. + * along with this program; if not, write to the Free Software
  57794. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  57795. + *
  57796. + * $Id: amba.c,v 1.9.2.2 2002/10/24 09:53:25 rmk Exp $
  57797. + *
  57798. + * This is a generic driver for ARM AMBA-type serial ports. They
  57799. + * have a lot of 16550-like features, but are not register compatable.
  57800. + * Note that although they do have CTS, DCD and DSR inputs, they do
  57801. + * not have an RI input, nor do they have DTR or RTS outputs. If
  57802. + * required, these have to be supplied via some other means (eg, GPIO)
  57803. + * and hooked into this driver.
  57804. + */
  57805. +#include <linux/config.h>
  57806. +#include <linux/module.h>
  57807. +#include <linux/tty.h>
  57808. +#include <linux/ioport.h>
  57809. +#include <linux/init.h>
  57810. +#include <linux/sched.h>
  57811. +#include <linux/serial.h>
  57812. +#include <linux/console.h>
  57813. +#include <linux/sysrq.h>
  57814. +
  57815. +#include <asm/io.h>
  57816. +#include <asm/irq.h>
  57817. +
  57818. +#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  57819. +#define SUPPORT_SYSRQ
  57820. +#endif
  57821. +
  57822. +#include <linux/serial_core.h>
  57823. +
  57824. +#include <asm/hardware/serial_amba.h>
  57825. +
  57826. +#define UART_NR 2
  57827. +
  57828. +#define SERIAL_AMBA_MAJOR 204
  57829. +#define SERIAL_AMBA_MINOR 16
  57830. +#define SERIAL_AMBA_NR UART_NR
  57831. +
  57832. +#define CALLOUT_AMBA_NAME "cuaam"
  57833. +#define CALLOUT_AMBA_MAJOR 205
  57834. +#define CALLOUT_AMBA_MINOR 16
  57835. +#define CALLOUT_AMBA_NR UART_NR
  57836. +
  57837. +static struct tty_driver normal, callout;
  57838. +static struct tty_struct *amba_table[UART_NR];
  57839. +static struct termios *amba_termios[UART_NR], *amba_termios_locked[UART_NR];
  57840. +#ifdef SUPPORT_SYSRQ
  57841. +static struct console amba_console;
  57842. +#endif
  57843. +
  57844. +#define AMBA_ISR_PASS_LIMIT 256
  57845. +
  57846. +/*
  57847. + * Access macros for the AMBA UARTs
  57848. + */
  57849. +#define UART_GET_INT_STATUS(p) readb((p)->membase + AMBA_UARTIIR)
  57850. +#define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR)
  57851. +#define UART_GET_FR(p) readb((p)->membase + AMBA_UARTFR)
  57852. +#define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR)
  57853. +#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR)
  57854. +#define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR)
  57855. +#define UART_GET_CR(p) readb((p)->membase + AMBA_UARTCR)
  57856. +#define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR)
  57857. +#define UART_GET_LCRL(p) readb((p)->membase + AMBA_UARTLCR_L)
  57858. +#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + AMBA_UARTLCR_L)
  57859. +#define UART_GET_LCRM(p) readb((p)->membase + AMBA_UARTLCR_M)
  57860. +#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + AMBA_UARTLCR_M)
  57861. +#define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H)
  57862. +#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H)
  57863. +#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
  57864. +#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
  57865. +#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
  57866. +
  57867. +#define UART_DUMMY_RSR_RX 256
  57868. +#define UART_PORT_SIZE 64
  57869. +
  57870. +/*
  57871. + * On the Integrator platform, the port RTS and DTR are provided by
  57872. + * bits in the following SC_CTRLS register bits:
  57873. + * RTS DTR
  57874. + * UART0 7 6
  57875. + * UART1 5 4
  57876. + */
  57877. +#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
  57878. +#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
  57879. +
  57880. +/*
  57881. + * We wrap our port structure around the generic uart_port.
  57882. + */
  57883. +struct uart_amba_port {
  57884. + struct uart_port port;
  57885. + unsigned int dtr_mask;
  57886. + unsigned int rts_mask;
  57887. + unsigned int old_status;
  57888. +};
  57889. +
  57890. +static void ambauart_stop_tx(struct uart_port *port, unsigned int tty_stop)
  57891. +{
  57892. + unsigned int cr;
  57893. +
  57894. + cr = UART_GET_CR(port);
  57895. + cr &= ~AMBA_UARTCR_TIE;
  57896. + UART_PUT_CR(port, cr);
  57897. +}
  57898. +
  57899. +static void ambauart_start_tx(struct uart_port *port, unsigned int tty_start)
  57900. +{
  57901. + unsigned int cr;
  57902. +
  57903. + cr = UART_GET_CR(port);
  57904. + cr |= AMBA_UARTCR_TIE;
  57905. + UART_PUT_CR(port, cr);
  57906. +}
  57907. +
  57908. +static void ambauart_stop_rx(struct uart_port *port)
  57909. +{
  57910. + unsigned int cr;
  57911. +
  57912. + cr = UART_GET_CR(port);
  57913. + cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
  57914. + UART_PUT_CR(port, cr);
  57915. +}
  57916. +
  57917. +static void ambauart_enable_ms(struct uart_port *port)
  57918. +{
  57919. + unsigned int cr;
  57920. +
  57921. + cr = UART_GET_CR(port);
  57922. + cr |= AMBA_UARTCR_MSIE;
  57923. + UART_PUT_CR(port, cr);
  57924. +}
  57925. +
  57926. +static void
  57927. +#ifdef SUPPORT_SYSRQ
  57928. +ambauart_rx_chars(struct uart_port *port, struct pt_regs *regs)
  57929. +#else
  57930. +ambauart_rx_chars(struct uart_port *port)
  57931. +#endif
  57932. +{
  57933. + struct tty_struct *tty = port->info->tty;
  57934. + unsigned int status, ch, rsr, max_count = 256;
  57935. +
  57936. + status = UART_GET_FR(port);
  57937. + while (UART_RX_DATA(status) && max_count--) {
  57938. + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
  57939. + tty->flip.tqueue.routine((void *)tty);
  57940. + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
  57941. + printk(KERN_WARNING "TTY_DONT_FLIP set\n");
  57942. + return;
  57943. + }
  57944. + }
  57945. +
  57946. + ch = UART_GET_CHAR(port);
  57947. +
  57948. + *tty->flip.char_buf_ptr = ch;
  57949. + *tty->flip.flag_buf_ptr = TTY_NORMAL;
  57950. + port->icount.rx++;
  57951. +
  57952. + /*
  57953. + * Note that the error handling code is
  57954. + * out of the main execution path
  57955. + */
  57956. + rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
  57957. + if (rsr & AMBA_UARTRSR_ANY) {
  57958. + if (rsr & AMBA_UARTRSR_BE) {
  57959. + rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
  57960. + port->icount.brk++;
  57961. + if (uart_handle_break(port))
  57962. + goto ignore_char;
  57963. + } else if (rsr & AMBA_UARTRSR_PE)
  57964. + port->icount.parity++;
  57965. + else if (rsr & AMBA_UARTRSR_FE)
  57966. + port->icount.frame++;
  57967. + if (rsr & AMBA_UARTRSR_OE)
  57968. + port->icount.overrun++;
  57969. +
  57970. + rsr &= port->read_status_mask;
  57971. +
  57972. + if (rsr & AMBA_UARTRSR_BE)
  57973. + *tty->flip.flag_buf_ptr = TTY_BREAK;
  57974. + else if (rsr & AMBA_UARTRSR_PE)
  57975. + *tty->flip.flag_buf_ptr = TTY_PARITY;
  57976. + else if (rsr & AMBA_UARTRSR_FE)
  57977. + *tty->flip.flag_buf_ptr = TTY_FRAME;
  57978. + }
  57979. +
  57980. + if (uart_handle_sysrq_char(port, ch, regs))
  57981. + goto ignore_char;
  57982. +
  57983. + if ((rsr & port->ignore_status_mask) == 0) {
  57984. + tty->flip.flag_buf_ptr++;
  57985. + tty->flip.char_buf_ptr++;
  57986. + tty->flip.count++;
  57987. + }
  57988. + if ((rsr & AMBA_UARTRSR_OE) &&
  57989. + tty->flip.count < TTY_FLIPBUF_SIZE) {
  57990. + /*
  57991. + * Overrun is special, since it's reported
  57992. + * immediately, and doesn't affect the current
  57993. + * character
  57994. + */
  57995. + *tty->flip.char_buf_ptr++ = 0;
  57996. + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
  57997. + tty->flip.count++;
  57998. + }
  57999. + ignore_char:
  58000. + status = UART_GET_FR(port);
  58001. + }
  58002. + tty_flip_buffer_push(tty);
  58003. + return;
  58004. +}
  58005. +
  58006. +static void ambauart_tx_chars(struct uart_port *port)
  58007. +{
  58008. + struct circ_buf *xmit = &port->info->xmit;
  58009. + int count;
  58010. +
  58011. + if (port->x_char) {
  58012. + UART_PUT_CHAR(port, port->x_char);
  58013. + port->icount.tx++;
  58014. + port->x_char = 0;
  58015. + return;
  58016. + }
  58017. + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  58018. + ambauart_stop_tx(port, 0);
  58019. + return;
  58020. + }
  58021. +
  58022. + count = port->fifosize >> 1;
  58023. + do {
  58024. + UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
  58025. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  58026. + port->icount.tx++;
  58027. + if (uart_circ_empty(xmit))
  58028. + break;
  58029. + } while (--count > 0);
  58030. +
  58031. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  58032. + uart_write_wakeup(port);
  58033. +
  58034. + if (uart_circ_empty(xmit))
  58035. + ambauart_stop_tx(port, 0);
  58036. +}
  58037. +
  58038. +static void ambauart_modem_status(struct uart_port *port)
  58039. +{
  58040. + struct uart_amba_port *uap = (struct uart_amba_port *)port;
  58041. + unsigned int status, delta;
  58042. +
  58043. + UART_PUT_ICR(&uap->port, 0);
  58044. +
  58045. + status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY;
  58046. +
  58047. + delta = status ^ uap->old_status;
  58048. + uap->old_status = status;
  58049. +
  58050. + if (!delta)
  58051. + return;
  58052. +
  58053. + if (delta & AMBA_UARTFR_DCD)
  58054. + uart_handle_dcd_change(&uap->port, status & AMBA_UARTFR_DCD);
  58055. +
  58056. + if (delta & AMBA_UARTFR_DSR)
  58057. + uap->port.icount.dsr++;
  58058. +
  58059. + if (delta & AMBA_UARTFR_CTS)
  58060. + uart_handle_cts_change(&uap->port, status & AMBA_UARTFR_CTS);
  58061. +
  58062. + wake_up_interruptible(&uap->port.info->delta_msr_wait);
  58063. +}
  58064. +
  58065. +static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
  58066. +{
  58067. + struct uart_port *port = dev_id;
  58068. + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
  58069. +
  58070. + status = UART_GET_INT_STATUS(port);
  58071. + do {
  58072. + if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
  58073. +#ifdef SUPPORT_SYSRQ
  58074. + ambauart_rx_chars(port, regs);
  58075. +#else
  58076. + ambauart_rx_chars(port);
  58077. +#endif
  58078. + if (status & AMBA_UARTIIR_TIS)
  58079. + ambauart_tx_chars(port);
  58080. + if (status & AMBA_UARTIIR_MIS)
  58081. + ambauart_modem_status(port);
  58082. +
  58083. + if (pass_counter-- == 0)
  58084. + break;
  58085. +
  58086. + status = UART_GET_INT_STATUS(port);
  58087. + } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
  58088. + AMBA_UARTIIR_TIS));
  58089. +}
  58090. +
  58091. +static unsigned int ambauart_tx_empty(struct uart_port *port)
  58092. +{
  58093. + return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT;
  58094. +}
  58095. +
  58096. +static unsigned int ambauart_get_mctrl(struct uart_port *port)
  58097. +{
  58098. + unsigned int result = 0;
  58099. + unsigned int status;
  58100. +
  58101. + status = UART_GET_FR(port);
  58102. + if (status & AMBA_UARTFR_DCD)
  58103. + result |= TIOCM_CAR;
  58104. + if (status & AMBA_UARTFR_DSR)
  58105. + result |= TIOCM_DSR;
  58106. + if (status & AMBA_UARTFR_CTS)
  58107. + result |= TIOCM_CTS;
  58108. +
  58109. + return result;
  58110. +}
  58111. +
  58112. +static void ambauart_set_mctrl(struct uart_port *port, unsigned int mctrl)
  58113. +{
  58114. + struct uart_amba_port *uap = (struct uart_amba_port *)port;
  58115. + unsigned int ctrls = 0, ctrlc = 0;
  58116. +
  58117. + if (mctrl & TIOCM_RTS)
  58118. + ctrlc |= uap->rts_mask;
  58119. + else
  58120. + ctrls |= uap->rts_mask;
  58121. +
  58122. + if (mctrl & TIOCM_DTR)
  58123. + ctrlc |= uap->dtr_mask;
  58124. + else
  58125. + ctrls |= uap->dtr_mask;
  58126. +
  58127. + __raw_writel(ctrls, SC_CTRLS);
  58128. + __raw_writel(ctrlc, SC_CTRLC);
  58129. +}
  58130. +
  58131. +static void ambauart_break_ctl(struct uart_port *port, int break_state)
  58132. +{
  58133. + unsigned long flags;
  58134. + unsigned int lcr_h;
  58135. +
  58136. + spin_lock_irqsave(&port->lock, flags);
  58137. + lcr_h = UART_GET_LCRH(port);
  58138. + if (break_state == -1)
  58139. + lcr_h |= AMBA_UARTLCR_H_BRK;
  58140. + else
  58141. + lcr_h &= ~AMBA_UARTLCR_H_BRK;
  58142. + UART_PUT_LCRH(port, lcr_h);
  58143. + spin_unlock_irqrestore(&port->lock, flags);
  58144. +}
  58145. +
  58146. +static int ambauart_startup(struct uart_port *port)
  58147. +{
  58148. + struct uart_amba_port *uap = (struct uart_amba_port *)port;
  58149. + int retval;
  58150. +
  58151. + /*
  58152. + * Allocate the IRQ
  58153. + */
  58154. + retval = request_irq(port->irq, ambauart_int, 0, "amba", port);
  58155. + if (retval)
  58156. + return retval;
  58157. +
  58158. + /*
  58159. + * initialise the old status of the modem signals
  58160. + */
  58161. + uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
  58162. +
  58163. + /*
  58164. + * Finally, enable interrupts
  58165. + */
  58166. + UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE |
  58167. + AMBA_UARTCR_RTIE);
  58168. +
  58169. + return 0;
  58170. +}
  58171. +
  58172. +static void ambauart_shutdown(struct uart_port *port)
  58173. +{
  58174. + /*
  58175. + * Free the interrupt
  58176. + */
  58177. + free_irq(port->irq, port);
  58178. +
  58179. + /*
  58180. + * disable all interrupts, disable the port
  58181. + */
  58182. + UART_PUT_CR(port, 0);
  58183. +
  58184. + /* disable break condition and fifos */
  58185. + UART_PUT_LCRH(port, UART_GET_LCRH(port) &
  58186. + ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
  58187. +}
  58188. +
  58189. +static void ambauart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
  58190. +{
  58191. + unsigned int lcr_h, old_cr;
  58192. + unsigned long flags;
  58193. +
  58194. +#if DEBUG
  58195. + printk("ambauart_set_cflag(0x%x) called\n", cflag);
  58196. +#endif
  58197. + /* byte size and parity */
  58198. + switch (cflag & CSIZE) {
  58199. + case CS5:
  58200. + lcr_h = AMBA_UARTLCR_H_WLEN_5;
  58201. + break;
  58202. + case CS6:
  58203. + lcr_h = AMBA_UARTLCR_H_WLEN_6;
  58204. + break;
  58205. + case CS7:
  58206. + lcr_h = AMBA_UARTLCR_H_WLEN_7;
  58207. + break;
  58208. + default: // CS8
  58209. + lcr_h = AMBA_UARTLCR_H_WLEN_8;
  58210. + break;
  58211. + }
  58212. + if (cflag & CSTOPB)
  58213. + lcr_h |= AMBA_UARTLCR_H_STP2;
  58214. + if (cflag & PARENB) {
  58215. + lcr_h |= AMBA_UARTLCR_H_PEN;
  58216. + if (!(cflag & PARODD))
  58217. + lcr_h |= AMBA_UARTLCR_H_EPS;
  58218. + }
  58219. + if (port->fifosize > 1)
  58220. + lcr_h |= AMBA_UARTLCR_H_FEN;
  58221. +
  58222. + spin_lock_irqsave(&port->lock, flags);
  58223. +
  58224. + port->read_status_mask = AMBA_UARTRSR_OE;
  58225. + if (iflag & INPCK)
  58226. + port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
  58227. + if (iflag & (BRKINT | PARMRK))
  58228. + port->read_status_mask |= AMBA_UARTRSR_BE;
  58229. +
  58230. + /*
  58231. + * Characters to ignore
  58232. + */
  58233. + port->ignore_status_mask = 0;
  58234. + if (iflag & IGNPAR)
  58235. + port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
  58236. + if (iflag & IGNBRK) {
  58237. + port->ignore_status_mask |= AMBA_UARTRSR_BE;
  58238. + /*
  58239. + * If we're ignoring parity and break indicators,
  58240. + * ignore overruns too (for real raw support).
  58241. + */
  58242. + if (iflag & IGNPAR)
  58243. + port->ignore_status_mask |= AMBA_UARTRSR_OE;
  58244. + }
  58245. +
  58246. + /*
  58247. + * Ignore all characters if CREAD is not set.
  58248. + */
  58249. + if ((cflag & CREAD) == 0)
  58250. + port->ignore_status_mask |= UART_DUMMY_RSR_RX;
  58251. +
  58252. + old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE;
  58253. +
  58254. + if (UART_ENABLE_MS(port, cflag))
  58255. + old_cr |= AMBA_UARTCR_MSIE;
  58256. +
  58257. + UART_PUT_CR(port, 0);
  58258. +
  58259. + /* Set baud rate */
  58260. + quot -= 1;
  58261. + UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
  58262. + UART_PUT_LCRL(port, (quot & 0xff));
  58263. +
  58264. + /*
  58265. + * ----------v----------v----------v----------v-----
  58266. + * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
  58267. + * ----------^----------^----------^----------^-----
  58268. + */
  58269. + UART_PUT_LCRH(port, lcr_h);
  58270. + UART_PUT_CR(port, old_cr);
  58271. +
  58272. + spin_unlock_irqrestore(&port->lock, flags);
  58273. +}
  58274. +
  58275. +static const char *ambauart_type(struct uart_port *port)
  58276. +{
  58277. + return port->type == PORT_AMBA ? "AMBA" : NULL;
  58278. +}
  58279. +
  58280. +/*
  58281. + * Release the memory region(s) being used by 'port'
  58282. + */
  58283. +static void ambauart_release_port(struct uart_port *port)
  58284. +{
  58285. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  58286. +}
  58287. +
  58288. +/*
  58289. + * Request the memory region(s) being used by 'port'
  58290. + */
  58291. +static int ambauart_request_port(struct uart_port *port)
  58292. +{
  58293. + return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba")
  58294. + != NULL ? 0 : -EBUSY;
  58295. +}
  58296. +
  58297. +/*
  58298. + * Configure/autoconfigure the port.
  58299. + */
  58300. +static void ambauart_config_port(struct uart_port *port, int flags)
  58301. +{
  58302. + if (flags & UART_CONFIG_TYPE) {
  58303. + port->type = PORT_AMBA;
  58304. + ambauart_request_port(port);
  58305. + }
  58306. +}
  58307. +
  58308. +/*
  58309. + * verify the new serial_struct (for TIOCSSERIAL).
  58310. + */
  58311. +static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser)
  58312. +{
  58313. + int ret = 0;
  58314. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
  58315. + ret = -EINVAL;
  58316. + if (ser->irq < 0 || ser->irq >= NR_IRQS)
  58317. + ret = -EINVAL;
  58318. + if (ser->baud_base < 9600)
  58319. + ret = -EINVAL;
  58320. + return ret;
  58321. +}
  58322. +
  58323. +static struct uart_ops amba_pops = {
  58324. + .tx_empty = ambauart_tx_empty,
  58325. + .set_mctrl = ambauart_set_mctrl,
  58326. + .get_mctrl = ambauart_get_mctrl,
  58327. + .stop_tx = ambauart_stop_tx,
  58328. + .start_tx = ambauart_start_tx,
  58329. + .stop_rx = ambauart_stop_rx,
  58330. + .enable_ms = ambauart_enable_ms,
  58331. + .break_ctl = ambauart_break_ctl,
  58332. + .startup = ambauart_startup,
  58333. + .shutdown = ambauart_shutdown,
  58334. + .change_speed = ambauart_change_speed,
  58335. + .type = ambauart_type,
  58336. + .release_port = ambauart_release_port,
  58337. + .request_port = ambauart_request_port,
  58338. + .config_port = ambauart_config_port,
  58339. + .verify_port = ambauart_verify_port,
  58340. +};
  58341. +
  58342. +static struct uart_amba_port amba_ports[UART_NR] = {
  58343. + {
  58344. + .port = {
  58345. + .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
  58346. + .mapbase = INTEGRATOR_UART0_BASE,
  58347. + .iotype = SERIAL_IO_MEM,
  58348. + .irq = IRQ_UARTINT0,
  58349. + .uartclk = 14745600,
  58350. + .fifosize = 16,
  58351. + .ops = &amba_pops,
  58352. + .flags = ASYNC_BOOT_AUTOCONF,
  58353. + .line = 0,
  58354. + },
  58355. + .dtr_mask = 1 << 5,
  58356. + .rts_mask = 1 << 4,
  58357. + },
  58358. + {
  58359. + .port = {
  58360. + .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
  58361. + .mapbase = INTEGRATOR_UART1_BASE,
  58362. + .iotype = SERIAL_IO_MEM,
  58363. + .irq = IRQ_UARTINT1,
  58364. + .uartclk = 14745600,
  58365. + .fifosize = 16,
  58366. + .ops = &amba_pops,
  58367. + .flags = ASYNC_BOOT_AUTOCONF,
  58368. + .line = 1,
  58369. + },
  58370. + .dtr_mask = 1 << 7,
  58371. + .rts_mask = 1 << 6,
  58372. + }
  58373. +};
  58374. +
  58375. +#ifdef CONFIG_SERIAL_AMBA_CONSOLE
  58376. +
  58377. +static void ambauart_console_write(struct console *co, const char *s, unsigned int count)
  58378. +{
  58379. + struct uart_port *port = &amba_ports[co->index].port;
  58380. + unsigned int status, old_cr;
  58381. + int i;
  58382. +
  58383. + /*
  58384. + * First save the CR then disable the interrupts
  58385. + */
  58386. + old_cr = UART_GET_CR(port);
  58387. + UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
  58388. +
  58389. + /*
  58390. + * Now, do each character
  58391. + */
  58392. + for (i = 0; i < count; i++) {
  58393. + do {
  58394. + status = UART_GET_FR(port);
  58395. + } while (!UART_TX_READY(status));
  58396. + UART_PUT_CHAR(port, s[i]);
  58397. + if (s[i] == '\n') {
  58398. + do {
  58399. + status = UART_GET_FR(port);
  58400. + } while (!UART_TX_READY(status));
  58401. + UART_PUT_CHAR(port, '\r');
  58402. + }
  58403. + }
  58404. +
  58405. + /*
  58406. + * Finally, wait for transmitter to become empty
  58407. + * and restore the TCR
  58408. + */
  58409. + do {
  58410. + status = UART_GET_FR(port);
  58411. + } while (status & AMBA_UARTFR_BUSY);
  58412. + UART_PUT_CR(port, old_cr);
  58413. +}
  58414. +
  58415. +static kdev_t ambauart_console_device(struct console *co)
  58416. +{
  58417. + return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index);
  58418. +}
  58419. +
  58420. +static void __init
  58421. +ambauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  58422. +{
  58423. + if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) {
  58424. + unsigned int lcr_h, quot;
  58425. + lcr_h = UART_GET_LCRH(port);
  58426. +
  58427. + *parity = 'n';
  58428. + if (lcr_h & AMBA_UARTLCR_H_PEN) {
  58429. + if (lcr_h & AMBA_UARTLCR_H_EPS)
  58430. + *parity = 'e';
  58431. + else
  58432. + *parity = 'o';
  58433. + }
  58434. +
  58435. + if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7)
  58436. + *bits = 7;
  58437. + else
  58438. + *bits = 8;
  58439. +
  58440. + quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
  58441. + *baud = port->uartclk / (16 * (quot + 1));
  58442. + }
  58443. +}
  58444. +
  58445. +static int __init ambauart_console_setup(struct console *co, char *options)
  58446. +{
  58447. + struct uart_port *port;
  58448. + int baud = 38400;
  58449. + int bits = 8;
  58450. + int parity = 'n';
  58451. + int flow = 'n';
  58452. +
  58453. + /*
  58454. + * Check whether an invalid uart number has been specified, and
  58455. + * if so, search for the first available port that does have
  58456. + * console support.
  58457. + */
  58458. + if (co->index >= UART_NR)
  58459. + co->index = 0;
  58460. + port = &amba_ports[co->index].port;
  58461. +
  58462. + if (options)
  58463. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  58464. + else
  58465. + ambauart_console_get_options(port, &baud, &parity, &bits);
  58466. +
  58467. + return uart_set_options(port, co, baud, parity, bits, flow);
  58468. +}
  58469. +
  58470. +static struct console amba_console = {
  58471. + .name = "ttyAM",
  58472. + .write = ambauart_console_write,
  58473. + .device = ambauart_console_device,
  58474. + .setup = ambauart_console_setup,
  58475. + .flags = CON_PRINTBUFFER,
  58476. + .index = -1,
  58477. +};
  58478. +
  58479. +void __init ambauart_console_init(void)
  58480. +{
  58481. + register_console(&amba_console);
  58482. +}
  58483. +
  58484. +#define AMBA_CONSOLE &amba_console
  58485. +#else
  58486. +#define AMBA_CONSOLE NULL
  58487. +#endif
  58488. +
  58489. +static struct uart_driver amba_reg = {
  58490. + .owner = THIS_MODULE,
  58491. + .normal_major = SERIAL_AMBA_MAJOR,
  58492. +#ifdef CONFIG_DEVFS_FS
  58493. + .normal_name = "ttyAM%d",
  58494. + .callout_name = "cuaam%d",
  58495. +#else
  58496. + .normal_name = "ttyAM",
  58497. + .callout_name = "cuaam",
  58498. +#endif
  58499. + .normal_driver = &normal,
  58500. + .callout_major = CALLOUT_AMBA_MAJOR,
  58501. + .callout_driver = &callout,
  58502. + .table = amba_table,
  58503. + .termios = amba_termios,
  58504. + .termios_locked = amba_termios_locked,
  58505. + .minor = SERIAL_AMBA_MINOR,
  58506. + .nr = UART_NR,
  58507. + .cons = AMBA_CONSOLE,
  58508. +};
  58509. +
  58510. +static int __init ambauart_init(void)
  58511. +{
  58512. + int ret;
  58513. +
  58514. + ret = uart_register_driver(&amba_reg);
  58515. + if (ret == 0) {
  58516. + int i;
  58517. +
  58518. + for (i = 0; i < UART_NR; i++)
  58519. + uart_add_one_port(&amba_reg, &amba_ports[i].port);
  58520. + }
  58521. + return ret;
  58522. +}
  58523. +
  58524. +static void __exit ambauart_exit(void)
  58525. +{
  58526. + int i;
  58527. +
  58528. + for (i = 0; i < UART_NR; i++)
  58529. + uart_remove_one_port(&amba_reg, &amba_ports[i].port);
  58530. +
  58531. + uart_unregister_driver(&amba_reg);
  58532. +}
  58533. +
  58534. +module_init(ambauart_init);
  58535. +module_exit(ambauart_exit);
  58536. +
  58537. +EXPORT_NO_SYMBOLS;
  58538. +
  58539. +MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
  58540. +MODULE_DESCRIPTION("ARM AMBA serial port driver");
  58541. +MODULE_LICENSE("GPL");
  58542. diff -urN linux-2.4.26/drivers/serial/anakin.c linux-2.4.26-vrs1/drivers/serial/anakin.c
  58543. --- linux-2.4.26/drivers/serial/anakin.c 1970-01-01 01:00:00.000000000 +0100
  58544. +++ linux-2.4.26-vrs1/drivers/serial/anakin.c 2004-01-14 21:32:26.000000000 +0000
  58545. @@ -0,0 +1,545 @@
  58546. +/*
  58547. + * linux/drivers/char/serial_anakin.c
  58548. + *
  58549. + * Based on driver for AMBA serial ports, by ARM Limited,
  58550. + * Deep Blue Solutions Ltd., Linus Torvalds and Theodore Ts'o.
  58551. + *
  58552. + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
  58553. + *
  58554. + * Copyright (C) 2001 Blue Mug, Inc. for Acunia N.V.
  58555. + *
  58556. + * This program is free software; you can redistribute it and/or modify
  58557. + * it under the terms of the GNU General Public License version 2 as
  58558. + * published by the Free Software Foundation.
  58559. + *
  58560. + * Changelog:
  58561. + * 20-Apr-2001 TTC Created
  58562. + * 05-May-2001 W/TTC Updated for serial_core.c
  58563. + * 27-Jun-2001 jonm Minor changes; add mctrl support, switch to
  58564. + * SA_INTERRUPT. Works reliably now. No longer requires
  58565. + * changes to the serial_core API.
  58566. + *
  58567. + * $Id: anakin.c,v 1.5.2.2 2002/10/24 09:53:25 rmk Exp $
  58568. + */
  58569. +
  58570. +#include <linux/config.h>
  58571. +#include <linux/module.h>
  58572. +#include <linux/errno.h>
  58573. +#include <linux/signal.h>
  58574. +#include <linux/sched.h>
  58575. +#include <linux/interrupt.h>
  58576. +#include <linux/tty.h>
  58577. +#include <linux/tty_flip.h>
  58578. +#include <linux/major.h>
  58579. +#include <linux/string.h>
  58580. +#include <linux/fcntl.h>
  58581. +#include <linux/ptrace.h>
  58582. +#include <linux/ioport.h>
  58583. +#include <linux/mm.h>
  58584. +#include <linux/slab.h>
  58585. +#include <linux/init.h>
  58586. +#include <linux/circ_buf.h>
  58587. +#include <linux/serial.h>
  58588. +#include <linux/console.h>
  58589. +#include <linux/sysrq.h>
  58590. +
  58591. +#include <asm/system.h>
  58592. +#include <asm/io.h>
  58593. +#include <asm/irq.h>
  58594. +#include <asm/uaccess.h>
  58595. +#include <asm/bitops.h>
  58596. +
  58597. +#include <linux/serial_core.h>
  58598. +
  58599. +#include <asm/arch/serial_reg.h>
  58600. +
  58601. +#define UART_NR 5
  58602. +
  58603. +#define SERIAL_ANAKIN_NAME "ttyAN"
  58604. +#define SERIAL_ANAKIN_MAJOR 204
  58605. +#define SERIAL_ANAKIN_MINOR 32
  58606. +
  58607. +#define CALLOUT_ANAKIN_NAME "cuaan"
  58608. +#define CALLOUT_ANAKIN_MAJOR 205
  58609. +#define CALLOUT_ANAKIN_MINOR 32
  58610. +
  58611. +static struct tty_driver normal, callout;
  58612. +static struct tty_struct *anakin_table[UART_NR];
  58613. +static struct termios *anakin_termios[UART_NR], *anakin_termios_locked[UART_NR];
  58614. +static struct uart_state anakin_state[UART_NR];
  58615. +static u_int txenable[NR_IRQS]; /* Software interrupt register */
  58616. +
  58617. +static inline unsigned int
  58618. +anakin_in(struct uart_port *port, u_int offset)
  58619. +{
  58620. + return __raw_readl(port->base + offset);
  58621. +}
  58622. +
  58623. +static inline void
  58624. +anakin_out(struct uart_port *port, u_int offset, unsigned int value)
  58625. +{
  58626. + __raw_writel(value, port->base + offset);
  58627. +}
  58628. +
  58629. +static void
  58630. +anakin_stop_tx(struct uart_port *port, u_int from_tty)
  58631. +{
  58632. + txenable[port->irq] = 0;
  58633. +}
  58634. +
  58635. +static inline void
  58636. +anakin_transmit_buffer(struct uart_info *info)
  58637. +{
  58638. + struct uart_port *port = info->port;
  58639. +
  58640. + while (!(anakin_in(port, 0x10) & TXEMPTY));
  58641. + anakin_out(port, 0x14, info->xmit.buf[info->xmit.tail]);
  58642. + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
  58643. + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE-1);
  58644. + info->state->icount.tx++;
  58645. +
  58646. + if (info->xmit.head == info->xmit.tail)
  58647. + anakin_stop_tx(port, 0);
  58648. +}
  58649. +
  58650. +static inline void
  58651. +anakin_transmit_x_char(struct uart_info *info)
  58652. +{
  58653. + struct uart_port *port = info->port;
  58654. +
  58655. + anakin_out(port, 0x14, info->x_char);
  58656. + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
  58657. + info->state->icount.tx++;
  58658. + info->x_char = 0;
  58659. +}
  58660. +
  58661. +static void
  58662. +anakin_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
  58663. +{
  58664. + unsigned int flags;
  58665. +
  58666. + save_flags_cli(flags);
  58667. +
  58668. + // is it this... or below: if (nonempty
  58669. + if (!txenable[port->irq]) {
  58670. + txenable[port->irq] = TXENABLE;
  58671. +
  58672. + if ((anakin_in(port, 0x10) & TXEMPTY) && nonempty) {
  58673. + anakin_transmit_buffer((struct uart_info*)port->unused);
  58674. + }
  58675. + }
  58676. +
  58677. + restore_flags(flags);
  58678. +}
  58679. +
  58680. +static void
  58681. +anakin_stop_rx(struct uart_port *port)
  58682. +{
  58683. + unsigned long flags;
  58684. +
  58685. + save_flags_cli(flags);
  58686. + while (anakin_in(port, 0x10) & RXRELEASE)
  58687. + anakin_in(port, 0x14);
  58688. + anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX);
  58689. + restore_flags(flags);
  58690. +}
  58691. +
  58692. +static void
  58693. +anakin_enable_ms(struct uart_port *port)
  58694. +{
  58695. +}
  58696. +
  58697. +static inline void
  58698. +anakin_rx_chars(struct uart_info *info)
  58699. +{
  58700. + unsigned int ch;
  58701. + struct tty_struct *tty = info->tty;
  58702. +
  58703. + if (!(anakin_in(info->port, 0x10) & RXRELEASE))
  58704. + return;
  58705. +
  58706. + ch = anakin_in(info->port, 0x14) & 0xff;
  58707. +
  58708. + if (tty->flip.count < TTY_FLIPBUF_SIZE) {
  58709. + *tty->flip.char_buf_ptr++ = ch;
  58710. + *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
  58711. + info->state->icount.rx++;
  58712. + tty->flip.count++;
  58713. + }
  58714. + tty_flip_buffer_push(tty);
  58715. +}
  58716. +
  58717. +static inline void
  58718. +anakin_overrun_chars(struct uart_info *info)
  58719. +{
  58720. + unsigned int ch;
  58721. +
  58722. + ch = anakin_in(info->port, 0x14);
  58723. + info->state->icount.overrun++;
  58724. +}
  58725. +
  58726. +static inline void
  58727. +anakin_tx_chars(struct uart_info *info)
  58728. +{
  58729. + if (info->x_char) {
  58730. + anakin_transmit_x_char(info);
  58731. + return;
  58732. + }
  58733. +
  58734. + if (info->xmit.head == info->xmit.tail
  58735. + || info->tty->stopped
  58736. + || info->tty->hw_stopped) {
  58737. + anakin_stop_tx(info->port, 0);
  58738. + return;
  58739. + }
  58740. +
  58741. + anakin_transmit_buffer(info);
  58742. +
  58743. + if (CIRC_CNT(info->xmit.head,
  58744. + info->xmit.tail,
  58745. + UART_XMIT_SIZE) < WAKEUP_CHARS)
  58746. + uart_event(info, EVT_WRITE_WAKEUP);
  58747. +}
  58748. +
  58749. +static void
  58750. +anakin_int(int irq, void *dev_id, struct pt_regs *regs)
  58751. +{
  58752. + unsigned int status;
  58753. + struct uart_info *info = dev_id;
  58754. +
  58755. + status = anakin_in(info->port, 0x1c);
  58756. +
  58757. + if (status & RX)
  58758. + anakin_rx_chars(info);
  58759. +
  58760. + if (status & OVERRUN)
  58761. + anakin_overrun_chars(info);
  58762. +
  58763. + if (txenable[info->port->irq] && (status & TX))
  58764. + anakin_tx_chars(info);
  58765. +}
  58766. +
  58767. +static u_int
  58768. +anakin_tx_empty(struct uart_port *port)
  58769. +{
  58770. + return anakin_in(port, 0x10) & TXEMPTY ? TIOCSER_TEMT : 0;
  58771. +}
  58772. +
  58773. +static u_int
  58774. +anakin_get_mctrl(struct uart_port *port)
  58775. +{
  58776. + unsigned int status = 0;
  58777. +
  58778. + status |= (anakin_in(port, 0x10) & CTS ? TIOCM_CTS : 0);
  58779. + status |= (anakin_in(port, 0x18) & DCD ? TIOCM_CAR : 0);
  58780. + status |= (anakin_in(port, 0x18) & DTR ? TIOCM_DTR : 0);
  58781. + status |= (anakin_in(port, 0x18) & RTS ? TIOCM_RTS : 0);
  58782. +
  58783. + return status;
  58784. +}
  58785. +
  58786. +static void
  58787. +anakin_set_mctrl(struct uart_port *port, u_int mctrl)
  58788. +{
  58789. + unsigned int status;
  58790. +
  58791. + status = anakin_in(port, 0x18);
  58792. +
  58793. + if (mctrl & TIOCM_RTS)
  58794. + status |= RTS;
  58795. + else
  58796. + status &= ~RTS;
  58797. +
  58798. + if (mctrl & TIOCM_CAR)
  58799. + status |= DCD;
  58800. + else
  58801. + status &= ~DCD;
  58802. +
  58803. + anakin_out(port, 0x18, status);
  58804. +}
  58805. +
  58806. +static void
  58807. +anakin_break_ctl(struct uart_port *port, int break_state)
  58808. +{
  58809. + unsigned int status;
  58810. +
  58811. + status = anakin_in(port, 0x20);
  58812. +
  58813. + if (break_state == -1)
  58814. + status |= SETBREAK;
  58815. + else
  58816. + status &= ~SETBREAK;
  58817. +
  58818. + anakin_out(port, 0x20, status);
  58819. +}
  58820. +
  58821. +static int
  58822. +anakin_startup(struct uart_port *port, struct uart_info *info)
  58823. +{
  58824. + int retval;
  58825. + unsigned int read,write;
  58826. +
  58827. + /*
  58828. + * Allocate the IRQ
  58829. + */
  58830. + retval = request_irq(port->irq, anakin_int, SA_INTERRUPT, "serial_anakin", info);
  58831. + if (retval)
  58832. + return retval;
  58833. +
  58834. + port->ops->set_mctrl(port, info->mctrl);
  58835. +
  58836. + /*
  58837. + * initialise the old status of the modem signals
  58838. + */
  58839. + port->old_status = 0;
  58840. +
  58841. + /*
  58842. + * Finally, disable IRQ and softIRQs for first byte)
  58843. + */
  58844. + txenable[port->irq] = 0;
  58845. + read = anakin_in(port, 0x18);
  58846. + write = (read & ~(RTS | DTR | BLOCKRX)) | IRQENABLE;
  58847. + anakin_out(port, 0x18, write);
  58848. +
  58849. + /* Store the uart_info pointer so we can reference it in
  58850. + * anakin_start_tx() */
  58851. + port->unused = (u_int)info;
  58852. +
  58853. + return 0;
  58854. +}
  58855. +
  58856. +static void
  58857. +anakin_shutdown(struct uart_port *port, struct uart_info *info)
  58858. +{
  58859. + /*
  58860. + * Free the interrupt
  58861. + */
  58862. + free_irq(port->irq, info);
  58863. +
  58864. + /*
  58865. + * disable all interrupts, disable the port
  58866. + */
  58867. + anakin_out(port, 0x18, anakin_in(port, 0x18) & ~IRQENABLE);
  58868. +}
  58869. +
  58870. +static void
  58871. +anakin_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
  58872. +{
  58873. + unsigned int flags;
  58874. +
  58875. + save_flags_cli(flags);
  58876. + while (!(anakin_in(port, 0x10) & TXEMPTY));
  58877. + anakin_out(port, 0x10, (anakin_in(port, 0x10) & ~PRESCALER)
  58878. + | (quot << 3));
  58879. +
  58880. + //parity always set to none
  58881. + anakin_out(port, 0x18, anakin_in(port, 0x18) & ~PARITY);
  58882. + restore_flags(flags);
  58883. +}
  58884. +
  58885. +static const char *anakin_type(struct port *port)
  58886. +{
  58887. + return port->type == PORT_ANAKIN ? "ANAKIN" : NULL;
  58888. +}
  58889. +
  58890. +static struct uart_ops anakin_pops = {
  58891. + tx_empty: anakin_tx_empty,
  58892. + set_mctrl: anakin_set_mctrl,
  58893. + get_mctrl: anakin_get_mctrl,
  58894. + stop_tx: anakin_stop_tx,
  58895. + start_tx: anakin_start_tx,
  58896. + stop_rx: anakin_stop_rx,
  58897. + enable_ms: anakin_enable_ms,
  58898. + break_ctl: anakin_break_ctl,
  58899. + startup: anakin_startup,
  58900. + shutdown: anakin_shutdown,
  58901. + change_speed: anakin_change_speed,
  58902. + type: anakin_type,
  58903. +};
  58904. +
  58905. +static struct uart_port anakin_ports[UART_NR] = {
  58906. + {
  58907. + base: IO_BASE + UART0,
  58908. + irq: IRQ_UART0,
  58909. + uartclk: 3686400,
  58910. + fifosize: 0,
  58911. + ops: &anakin_pops,
  58912. + },
  58913. + {
  58914. + base: IO_BASE + UART1,
  58915. + irq: IRQ_UART1,
  58916. + uartclk: 3686400,
  58917. + fifosize: 0,
  58918. + ops: &anakin_pops,
  58919. + },
  58920. + {
  58921. + base: IO_BASE + UART2,
  58922. + irq: IRQ_UART2,
  58923. + uartclk: 3686400,
  58924. + fifosize: 0,
  58925. + ops: &anakin_pops,
  58926. + },
  58927. + {
  58928. + base: IO_BASE + UART3,
  58929. + irq: IRQ_UART3,
  58930. + uartclk: 3686400,
  58931. + fifosize: 0,
  58932. + ops: &anakin_pops,
  58933. + },
  58934. + {
  58935. + base: IO_BASE + UART4,
  58936. + irq: IRQ_UART4,
  58937. + uartclk: 3686400,
  58938. + fifosize: 0,
  58939. + ops: &anakin_pops,
  58940. + },
  58941. +};
  58942. +
  58943. +
  58944. +#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
  58945. +
  58946. +static void
  58947. +anakin_console_write(struct console *co, const char *s, u_int count)
  58948. +{
  58949. + struct uart_port *port = anakin_ports + co->index;
  58950. + unsigned int flags, status, i;
  58951. +
  58952. + /*
  58953. + * First save the status then disable the interrupts
  58954. + */
  58955. + save_flags_cli(flags);
  58956. + status = anakin_in(port, 0x18);
  58957. + anakin_out(port, 0x18, status & ~IRQENABLE);
  58958. + restore_flags(flags);
  58959. +
  58960. + /*
  58961. + * Now, do each character
  58962. + */
  58963. + for (i = 0; i < count; i++, s++) {
  58964. + while (!(anakin_in(port, 0x10) & TXEMPTY));
  58965. +
  58966. + /*
  58967. + * Send the character out.
  58968. + * If a LF, also do CR...
  58969. + */
  58970. + anakin_out(port, 0x14, *s);
  58971. + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
  58972. +
  58973. + if (*s == 10) {
  58974. + while (!(anakin_in(port, 0x10) & TXEMPTY));
  58975. + anakin_out(port, 0x14, 13);
  58976. + anakin_out(port, 0x18, anakin_in(port, 0x18)
  58977. + | SENDREQUEST);
  58978. + }
  58979. + }
  58980. +
  58981. + /*
  58982. + * Finally, wait for transmitter to become empty
  58983. + * and restore the interrupts
  58984. + */
  58985. + while (!(anakin_in(port, 0x10) & TXEMPTY));
  58986. +
  58987. + if (status & IRQENABLE)
  58988. + save_flags_cli(flags);
  58989. + anakin_out(port, 0x18, anakin_in(port, 0x18) | IRQENABLE);
  58990. + restore_flags(flags);
  58991. +}
  58992. +
  58993. +static kdev_t
  58994. +anakin_console_device(struct console *co)
  58995. +{
  58996. + return MKDEV(SERIAL_ANAKIN_MAJOR, SERIAL_ANAKIN_MINOR + co->index);
  58997. +}
  58998. +
  58999. +/*
  59000. + * Read the current UART setup.
  59001. + */
  59002. +static void __init
  59003. +anakin_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  59004. +{
  59005. + int paritycode;
  59006. +
  59007. + *baud = GETBAUD (anakin_in(port, 0x10) & PRESCALER);
  59008. + paritycode = GETPARITY(anakin_in(port, 0x18) & PARITY);
  59009. + switch (paritycode) {
  59010. + case NONEPARITY: *parity = 'n'; break;
  59011. + case ODDPARITY: *parity = 'o'; break;
  59012. + case EVENPARITY: *parity = 'e'; break;
  59013. + }
  59014. + *bits = 8;
  59015. +}
  59016. +
  59017. +static int __init
  59018. +anakin_console_setup(struct console *co, char *options)
  59019. +{
  59020. + struct uart_port *port;
  59021. + int baud = CONFIG_ANAKIN_DEFAULT_BAUDRATE;
  59022. + int bits = 8;
  59023. + int parity = 'n';
  59024. +
  59025. + /*
  59026. + * Check whether an invalid uart number has been specified, and
  59027. + * if so, search for the first available port that does have
  59028. + * console support.
  59029. + */
  59030. + port = uart_get_console(anakin_ports, UART_NR, co);
  59031. +
  59032. + if (options)
  59033. + uart_parse_options(options, &baud, &parity, &bits);
  59034. + else
  59035. + anakin_console_get_options(port, &baud, &parity, &bits);
  59036. +
  59037. + return uart_set_options(port, co, baud, parity, bits);
  59038. +}
  59039. +
  59040. +static struct console anakin_console = {
  59041. + name: SERIAL_ANAKIN_NAME,
  59042. + write: anakin_console_write,
  59043. + device: anakin_console_device,
  59044. + setup: anakin_console_setup,
  59045. + flags: CON_PRINTBUFFER,
  59046. + index: -1,
  59047. +};
  59048. +
  59049. +void __init
  59050. +anakin_console_init(void)
  59051. +{
  59052. + register_console(&anakin_console);
  59053. +}
  59054. +
  59055. +#define ANAKIN_CONSOLE &anakin_console
  59056. +#else
  59057. +#define ANAKIN_CONSOLE NULL
  59058. +#endif
  59059. +
  59060. +static struct uart_register anakin_reg = {
  59061. + normal_major: SERIAL_ANAKIN_MAJOR,
  59062. + normal_name: SERIAL_ANAKIN_NAME,
  59063. + normal_driver: &normal,
  59064. + callout_major: CALLOUT_ANAKIN_MAJOR,
  59065. + callout_name: CALLOUT_ANAKIN_NAME,
  59066. + callout_driver: &callout,
  59067. + table: anakin_table,
  59068. + termios: anakin_termios,
  59069. + termios_locked: anakin_termios_locked,
  59070. + minor: SERIAL_ANAKIN_MINOR,
  59071. + nr: UART_NR,
  59072. + state: anakin_state,
  59073. + port: anakin_ports,
  59074. + cons: ANAKIN_CONSOLE,
  59075. +};
  59076. +
  59077. +static int __init
  59078. +anakin_init(void)
  59079. +{
  59080. + return uart_register_port(&anakin_reg);
  59081. +}
  59082. +
  59083. +__initcall(anakin_init);
  59084. +
  59085. +MODULE_DESCRIPTION("Anakin serial driver");
  59086. +MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
  59087. +MODULE_SUPPORTED_DEVICE("ttyAN");
  59088. +MODULE_LICENSE("GPL");
  59089. +
  59090. +EXPORT_NO_SYMBOLS;
  59091. diff -urN linux-2.4.26/drivers/serial/clps711x.c linux-2.4.26-vrs1/drivers/serial/clps711x.c
  59092. --- linux-2.4.26/drivers/serial/clps711x.c 1970-01-01 01:00:00.000000000 +0100
  59093. +++ linux-2.4.26-vrs1/drivers/serial/clps711x.c 2004-01-14 21:32:26.000000000 +0000
  59094. @@ -0,0 +1,635 @@
  59095. +/*
  59096. + * linux/drivers/char/serial_clps711x.c
  59097. + *
  59098. + * Driver for CLPS711x serial ports
  59099. + *
  59100. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  59101. + *
  59102. + * Copyright 1999 ARM Limited
  59103. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  59104. + *
  59105. + * This program is free software; you can redistribute it and/or modify
  59106. + * it under the terms of the GNU General Public License as published by
  59107. + * the Free Software Foundation; either version 2 of the License, or
  59108. + * (at your option) any later version.
  59109. + *
  59110. + * This program is distributed in the hope that it will be useful,
  59111. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  59112. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  59113. + * GNU General Public License for more details.
  59114. + *
  59115. + * You should have received a copy of the GNU General Public License
  59116. + * along with this program; if not, write to the Free Software
  59117. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  59118. + *
  59119. + * $Id: clps711x.c,v 1.12.2.2 2002/10/24 09:53:25 rmk Exp $
  59120. + *
  59121. + */
  59122. +#include <linux/config.h>
  59123. +#include <linux/module.h>
  59124. +#include <linux/errno.h>
  59125. +#include <linux/signal.h>
  59126. +#include <linux/sched.h>
  59127. +#include <linux/interrupt.h>
  59128. +#include <linux/tty.h>
  59129. +#include <linux/tty_flip.h>
  59130. +#include <linux/major.h>
  59131. +#include <linux/string.h>
  59132. +#include <linux/fcntl.h>
  59133. +#include <linux/ptrace.h>
  59134. +#include <linux/ioport.h>
  59135. +#include <linux/mm.h>
  59136. +#include <linux/slab.h>
  59137. +#include <linux/init.h>
  59138. +#include <linux/circ_buf.h>
  59139. +#include <linux/serial.h>
  59140. +#include <linux/console.h>
  59141. +#include <linux/sysrq.h>
  59142. +
  59143. +#include <asm/bitops.h>
  59144. +#include <asm/hardware.h>
  59145. +#include <asm/io.h>
  59146. +#include <asm/irq.h>
  59147. +#include <asm/system.h>
  59148. +#include <asm/uaccess.h>
  59149. +
  59150. +#include <linux/serial_core.h>
  59151. +
  59152. +#include <asm/hardware/clps7111.h>
  59153. +
  59154. +#define UART_NR 2
  59155. +
  59156. +#define SERIAL_CLPS711X_NAME "ttyAM"
  59157. +#define SERIAL_CLPS711X_MAJOR 204
  59158. +#define SERIAL_CLPS711X_MINOR 16
  59159. +#define SERIAL_CLPS711X_NR UART_NR
  59160. +
  59161. +#define CALLOUT_CLPS711X_NAME "cuaam"
  59162. +#define CALLOUT_CLPS711X_MAJOR 205
  59163. +#define CALLOUT_CLPS711X_MINOR 16
  59164. +#define CALLOUT_CLPS711X_NR UART_NR
  59165. +
  59166. +static struct tty_driver normal, callout;
  59167. +static struct tty_struct *clps711x_table[UART_NR];
  59168. +static struct termios *clps711x_termios[UART_NR], *clps711x_termios_locked[UART_NR];
  59169. +
  59170. +/*
  59171. + * We use the relevant SYSCON register as a base address for these ports.
  59172. + */
  59173. +#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
  59174. +#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
  59175. +#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
  59176. +#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
  59177. +
  59178. +#define TX_IRQ(port) ((port)->irq)
  59179. +#define RX_IRQ(port) ((port)->irq + 1)
  59180. +
  59181. +#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
  59182. +
  59183. +#define tx_enabled(port) ((port)->unused[0])
  59184. +
  59185. +static void
  59186. +clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
  59187. +{
  59188. + if (tx_enabled(port)) {
  59189. + disable_irq(TX_IRQ(port));
  59190. + tx_enabled(port) = 0;
  59191. + }
  59192. +}
  59193. +
  59194. +static void
  59195. +clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
  59196. +{
  59197. + if (!tx_enabled(port)) {
  59198. + enable_irq(TX_IRQ(port));
  59199. + tx_enabled(port) = 1;
  59200. + }
  59201. +}
  59202. +
  59203. +static void clps711xuart_stop_rx(struct uart_port *port)
  59204. +{
  59205. + disable_irq(RX_IRQ(port));
  59206. +}
  59207. +
  59208. +static void clps711xuart_enable_ms(struct uart_port *port)
  59209. +{
  59210. +}
  59211. +
  59212. +static void clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
  59213. +{
  59214. + struct uart_port *port = dev_id;
  59215. + struct tty_struct *tty = port->info->tty;
  59216. + unsigned int status, ch, flg, ignored = 0;
  59217. +
  59218. + status = clps_readl(SYSFLG(port));
  59219. + while (!(status & SYSFLG_URXFE)) {
  59220. + ch = clps_readl(UARTDR(port));
  59221. +
  59222. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  59223. + goto ignore_char;
  59224. + port->icount.rx++;
  59225. +
  59226. + flg = TTY_NORMAL;
  59227. +
  59228. + /*
  59229. + * Note that the error handling code is
  59230. + * out of the main execution path
  59231. + */
  59232. + if (ch & UART_ANY_ERR)
  59233. + goto handle_error;
  59234. +
  59235. + if (uart_handle_sysrq_char(port, ch, regs))
  59236. + goto ignore_char;
  59237. +
  59238. + error_return:
  59239. + *tty->flip.flag_buf_ptr++ = flg;
  59240. + *tty->flip.char_buf_ptr++ = ch;
  59241. + tty->flip.count++;
  59242. + ignore_char:
  59243. + status = clps_readl(SYSFLG(port));
  59244. + }
  59245. + out:
  59246. + tty_flip_buffer_push(tty);
  59247. + return;
  59248. +
  59249. + handle_error:
  59250. + if (ch & UARTDR_PARERR)
  59251. + port->icount.parity++;
  59252. + else if (ch & UARTDR_FRMERR)
  59253. + port->icount.frame++;
  59254. + if (ch & UARTDR_OVERR)
  59255. + port->icount.overrun++;
  59256. +
  59257. + if (ch & port->ignore_status_mask) {
  59258. + if (++ignored > 100)
  59259. + goto out;
  59260. + goto ignore_char;
  59261. + }
  59262. + ch &= port->read_status_mask;
  59263. +
  59264. + if (ch & UARTDR_PARERR)
  59265. + flg = TTY_PARITY;
  59266. + else if (ch & UARTDR_FRMERR)
  59267. + flg = TTY_FRAME;
  59268. +
  59269. + if (ch & UARTDR_OVERR) {
  59270. + /*
  59271. + * CHECK: does overrun affect the current character?
  59272. + * ASSUMPTION: it does not.
  59273. + */
  59274. + *tty->flip.flag_buf_ptr++ = flg;
  59275. + *tty->flip.char_buf_ptr++ = ch;
  59276. + tty->flip.count++;
  59277. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  59278. + goto ignore_char;
  59279. + ch = 0;
  59280. + flg = TTY_OVERRUN;
  59281. + }
  59282. +#ifdef SUPPORT_SYSRQ
  59283. + port->sysrq = 0;
  59284. +#endif
  59285. + goto error_return;
  59286. +}
  59287. +
  59288. +static void clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
  59289. +{
  59290. + struct uart_port *port = dev_id;
  59291. + struct circ_buf *xmit = &port->info->xmit;
  59292. + int count;
  59293. +
  59294. + if (port->x_char) {
  59295. + clps_writel(port->x_char, UARTDR(port));
  59296. + port->icount.tx++;
  59297. + port->x_char = 0;
  59298. + return;
  59299. + }
  59300. + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  59301. + clps711xuart_stop_tx(port, 0);
  59302. + return;
  59303. + }
  59304. +
  59305. + count = port->fifosize >> 1;
  59306. + do {
  59307. + clps_writel(xmit->buf[xmit->tail], UARTDR(port));
  59308. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  59309. + port->icount.tx++;
  59310. + if (uart_circ_empty(xmit))
  59311. + break;
  59312. + } while (--count > 0);
  59313. +
  59314. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  59315. + uart_write_wakeup(port);
  59316. +
  59317. + if (uart_circ_empty(xmit))
  59318. + clps711xuart_stop_tx(port, 0);
  59319. +}
  59320. +
  59321. +static unsigned int clps711xuart_tx_empty(struct uart_port *port)
  59322. +{
  59323. + unsigned int status = clps_readl(SYSFLG(port));
  59324. + return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
  59325. +}
  59326. +
  59327. +static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
  59328. +{
  59329. + unsigned int port_addr;
  59330. + unsigned int result = 0;
  59331. + unsigned int status;
  59332. +
  59333. + port_addr = SYSFLG(port);
  59334. + if (port_addr == SYSFLG1) {
  59335. + status = clps_readl(SYSFLG1);
  59336. + if (status & SYSFLG1_DCD)
  59337. + result |= TIOCM_CAR;
  59338. + if (status & SYSFLG1_DSR)
  59339. + result |= TIOCM_DSR;
  59340. + if (status & SYSFLG1_CTS)
  59341. + result |= TIOCM_CTS;
  59342. + }
  59343. +
  59344. + return result;
  59345. +}
  59346. +
  59347. +static void
  59348. +clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
  59349. +{
  59350. +}
  59351. +
  59352. +static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
  59353. +{
  59354. + unsigned long flags;
  59355. + unsigned int ubrlcr;
  59356. +
  59357. + spin_lock_irqsave(&port->lock, flags);
  59358. + ubrlcr = clps_readl(UBRLCR(port));
  59359. + if (break_state == -1)
  59360. + ubrlcr |= UBRLCR_BREAK;
  59361. + else
  59362. + ubrlcr &= ~UBRLCR_BREAK;
  59363. + clps_writel(ubrlcr, UBRLCR(port));
  59364. + spin_unlock_irqrestore(&port->lock, flags);
  59365. +}
  59366. +
  59367. +static int clps711xuart_startup(struct uart_port *port)
  59368. +{
  59369. + unsigned int syscon;
  59370. + int retval;
  59371. +
  59372. + tx_enabled(port) = 1;
  59373. +
  59374. + /*
  59375. + * Allocate the IRQs
  59376. + */
  59377. + retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
  59378. + "clps711xuart_tx", port);
  59379. + if (retval)
  59380. + return retval;
  59381. +
  59382. + retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
  59383. + "clps711xuart_rx", port);
  59384. + if (retval) {
  59385. + free_irq(TX_IRQ(port), port);
  59386. + return retval;
  59387. + }
  59388. +
  59389. + /*
  59390. + * enable the port
  59391. + */
  59392. + syscon = clps_readl(SYSCON(port));
  59393. + syscon |= SYSCON_UARTEN;
  59394. + clps_writel(syscon, SYSCON(port));
  59395. +
  59396. + return 0;
  59397. +}
  59398. +
  59399. +static void clps711xuart_shutdown(struct uart_port *port)
  59400. +{
  59401. + unsigned int ubrlcr, syscon;
  59402. +
  59403. + /*
  59404. + * Free the interrupt
  59405. + */
  59406. + free_irq(TX_IRQ(port), port); /* TX interrupt */
  59407. + free_irq(RX_IRQ(port), port); /* RX interrupt */
  59408. +
  59409. + /*
  59410. + * disable the port
  59411. + */
  59412. + syscon = clps_readl(SYSCON(port));
  59413. + syscon &= ~SYSCON_UARTEN;
  59414. + clps_writel(syscon, SYSCON(port));
  59415. +
  59416. + /*
  59417. + * disable break condition and fifos
  59418. + */
  59419. + ubrlcr = clps_readl(UBRLCR(port));
  59420. + ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
  59421. + clps_writel(ubrlcr, UBRLCR(port));
  59422. +}
  59423. +
  59424. +static void clps711xuart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
  59425. +{
  59426. + unsigned int ubrlcr;
  59427. + unsigned long flags;
  59428. +
  59429. +#if DEBUG
  59430. + printk("clps711xuart_change_speed(cflag=0x%x, iflag=0x%x, quot=%d) called\n",
  59431. + cflag, iflag, quot);
  59432. +#endif
  59433. + /* byte size and parity */
  59434. + switch (cflag & CSIZE) {
  59435. + case CS5:
  59436. + ubrlcr = UBRLCR_WRDLEN5;
  59437. + break;
  59438. + case CS6:
  59439. + ubrlcr = UBRLCR_WRDLEN6;
  59440. + break;
  59441. + case CS7:
  59442. + ubrlcr = UBRLCR_WRDLEN7;
  59443. + break;
  59444. + default: // CS8
  59445. + ubrlcr = UBRLCR_WRDLEN8;
  59446. + break;
  59447. + }
  59448. + if (cflag & CSTOPB)
  59449. + ubrlcr |= UBRLCR_XSTOP;
  59450. + if (cflag & PARENB) {
  59451. + ubrlcr |= UBRLCR_PRTEN;
  59452. + if (!(cflag & PARODD))
  59453. + ubrlcr |= UBRLCR_EVENPRT;
  59454. + }
  59455. + if (port->fifosize > 1)
  59456. + ubrlcr |= UBRLCR_FIFOEN;
  59457. +
  59458. + spin_lock_irqsave(&port->lock, flags);
  59459. +
  59460. + port->read_status_mask = UARTDR_OVERR;
  59461. + if (iflag & INPCK)
  59462. + port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
  59463. +
  59464. + /*
  59465. + * Characters to ignore
  59466. + */
  59467. + port->ignore_status_mask = 0;
  59468. + if (iflag & IGNPAR)
  59469. + port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
  59470. + if (iflag & IGNBRK) {
  59471. + /*
  59472. + * If we're ignoring parity and break indicators,
  59473. + * ignore overruns to (for real raw support).
  59474. + */
  59475. + if (iflag & IGNPAR)
  59476. + port->ignore_status_mask |= UARTDR_OVERR;
  59477. + }
  59478. +
  59479. + quot -= 1;
  59480. +
  59481. + clps_writel(ubrlcr | quot, UBRLCR(port));
  59482. +
  59483. + spin_unlock_irqrestore(&port->lock, flags);
  59484. +}
  59485. +
  59486. +static const char *clps711xuart_type(struct uart_port *port)
  59487. +{
  59488. + return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
  59489. +}
  59490. +
  59491. +/*
  59492. + * Configure/autoconfigure the port.
  59493. + */
  59494. +static void clps711xuart_config_port(struct uart_port *port, int flags)
  59495. +{
  59496. + if (flags & UART_CONFIG_TYPE)
  59497. + port->type = PORT_CLPS711X;
  59498. +}
  59499. +
  59500. +static void clps711xuart_release_port(struct uart_port *port)
  59501. +{
  59502. +}
  59503. +
  59504. +static int clps711xuart_request_port(struct uart_port *port)
  59505. +{
  59506. + return 0;
  59507. +}
  59508. +
  59509. +static struct uart_ops clps711x_pops = {
  59510. + .tx_empty = clps711xuart_tx_empty,
  59511. + .set_mctrl = clps711xuart_set_mctrl_null,
  59512. + .get_mctrl = clps711xuart_get_mctrl,
  59513. + .stop_tx = clps711xuart_stop_tx,
  59514. + .start_tx = clps711xuart_start_tx,
  59515. + .stop_rx = clps711xuart_stop_rx,
  59516. + .enable_ms = clps711xuart_enable_ms,
  59517. + .break_ctl = clps711xuart_break_ctl,
  59518. + .startup = clps711xuart_startup,
  59519. + .shutdown = clps711xuart_shutdown,
  59520. + .change_speed = clps711xuart_change_speed,
  59521. + .type = clps711xuart_type,
  59522. + .config_port = clps711xuart_config_port,
  59523. + .release_port = clps711xuart_release_port,
  59524. + .request_port = clps711xuart_request_port,
  59525. +};
  59526. +
  59527. +static struct uart_port clps711x_ports[UART_NR] = {
  59528. + {
  59529. + .iobase = SYSCON1,
  59530. + .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
  59531. + .uartclk = 3686400,
  59532. + .fifosize = 16,
  59533. + .ops = &clps711x_pops,
  59534. + .line = 0,
  59535. + .flags = ASYNC_BOOT_AUTOCONF,
  59536. + },
  59537. + {
  59538. + .iobase = SYSCON2,
  59539. + .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
  59540. + .uartclk = 3686400,
  59541. + .fifosize = 16,
  59542. + .ops = &clps711x_pops,
  59543. + .line = 1,
  59544. + .flags = ASYNC_BOOT_AUTOCONF,
  59545. + }
  59546. +};
  59547. +
  59548. +#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
  59549. +/*
  59550. + * Print a string to the serial port trying not to disturb
  59551. + * any possible real use of the port...
  59552. + *
  59553. + * The console_lock must be held when we get here.
  59554. + *
  59555. + * Note that this is called with interrupts already disabled
  59556. + */
  59557. +static void
  59558. +clps711xuart_console_write(struct console *co, const char *s,
  59559. + unsigned int count)
  59560. +{
  59561. + struct uart_port *port = clps711x_ports + co->index;
  59562. + unsigned int status, syscon;
  59563. + int i;
  59564. +
  59565. + /*
  59566. + * Ensure that the port is enabled.
  59567. + */
  59568. + syscon = clps_readl(SYSCON(port));
  59569. + clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
  59570. +
  59571. + /*
  59572. + * Now, do each character
  59573. + */
  59574. + for (i = 0; i < count; i++) {
  59575. + do {
  59576. + status = clps_readl(SYSFLG(port));
  59577. + } while (status & SYSFLG_UTXFF);
  59578. + clps_writel(s[i], UARTDR(port));
  59579. + if (s[i] == '\n') {
  59580. + do {
  59581. + status = clps_readl(SYSFLG(port));
  59582. + } while (status & SYSFLG_UTXFF);
  59583. + clps_writel('\r', UARTDR(port));
  59584. + }
  59585. + }
  59586. +
  59587. + /*
  59588. + * Finally, wait for transmitter to become empty
  59589. + * and restore the uart state.
  59590. + */
  59591. + do {
  59592. + status = clps_readl(SYSFLG(port));
  59593. + } while (status & SYSFLG_UBUSY);
  59594. +
  59595. + clps_writel(syscon, SYSCON(port));
  59596. +}
  59597. +
  59598. +static kdev_t clps711xuart_console_device(struct console *co)
  59599. +{
  59600. + return MKDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR + co->index);
  59601. +}
  59602. +
  59603. +static void __init
  59604. +clps711xuart_console_get_options(struct uart_port *port, int *baud,
  59605. + int *parity, int *bits)
  59606. +{
  59607. + if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
  59608. + unsigned int ubrlcr, quot;
  59609. +
  59610. + ubrlcr = clps_readl(UBRLCR(port));
  59611. +
  59612. + *parity = 'n';
  59613. + if (ubrlcr & UBRLCR_PRTEN) {
  59614. + if (ubrlcr & UBRLCR_EVENPRT)
  59615. + *parity = 'e';
  59616. + else
  59617. + *parity = 'o';
  59618. + }
  59619. +
  59620. + if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
  59621. + *bits = 7;
  59622. + else
  59623. + *bits = 8;
  59624. +
  59625. + quot = ubrlcr & UBRLCR_BAUD_MASK;
  59626. + *baud = port->uartclk / (16 * (quot + 1));
  59627. + }
  59628. +}
  59629. +
  59630. +static int __init clps711xuart_console_setup(struct console *co, char *options)
  59631. +{
  59632. + struct uart_port *port;
  59633. + int baud = 38400;
  59634. + int bits = 8;
  59635. + int parity = 'n';
  59636. + int flow = 'n';
  59637. +
  59638. + /*
  59639. + * Check whether an invalid uart number has been specified, and
  59640. + * if so, search for the first available port that does have
  59641. + * console support.
  59642. + */
  59643. + port = uart_get_console(clps711x_ports, UART_NR, co);
  59644. +
  59645. + if (options)
  59646. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  59647. + else
  59648. + clps711xuart_console_get_options(port, &baud, &parity, &bits);
  59649. +
  59650. + return uart_set_options(port, co, baud, parity, bits, flow);
  59651. +}
  59652. +
  59653. +static struct console clps711x_console = {
  59654. + .name = SERIAL_CLPS711X_NAME,
  59655. + .write = clps711xuart_console_write,
  59656. + .device = clps711xuart_console_device,
  59657. + .setup = clps711xuart_console_setup,
  59658. + .flags = CON_PRINTBUFFER,
  59659. + .index = -1,
  59660. +};
  59661. +
  59662. +void __init clps711xuart_console_init(void)
  59663. +{
  59664. + register_console(&clps711x_console);
  59665. +}
  59666. +
  59667. +#define CLPS711X_CONSOLE &clps711x_console
  59668. +#else
  59669. +#define CLPS711X_CONSOLE NULL
  59670. +#endif
  59671. +
  59672. +static struct uart_driver clps711x_reg = {
  59673. +#ifdef CONFIG_DEVFS_FS
  59674. + .normal_name = SERIAL_CLPS711X_NAME,
  59675. + .callout_name = CALLOUT_CLPS711X_NAME,
  59676. +#else
  59677. + .normal_name = SERIAL_CLPS711X_NAME,
  59678. + .callout_name = CALLOUT_CLPS711X_NAME,
  59679. +#endif
  59680. +
  59681. + .normal_major = SERIAL_CLPS711X_MAJOR,
  59682. + .normal_driver = &normal,
  59683. + .callout_major = CALLOUT_CLPS711X_MAJOR,
  59684. + .callout_driver = &callout,
  59685. +
  59686. + .table = clps711x_table,
  59687. + .termios = clps711x_termios,
  59688. + .termios_locked = clps711x_termios_locked,
  59689. +
  59690. + .minor = SERIAL_CLPS711X_MINOR,
  59691. + .nr = UART_NR,
  59692. +
  59693. + .cons = CLPS711X_CONSOLE,
  59694. +};
  59695. +
  59696. +static int __init clps711xuart_init(void)
  59697. +{
  59698. + int ret, i;
  59699. +
  59700. + printk(KERN_INFO "Serial: CLPS711x driver\n");
  59701. +
  59702. + ret = uart_register_driver(&clps711x_reg);
  59703. + if (ret)
  59704. + return ret;
  59705. +
  59706. + for (i = 0; i < UART_NR; i++)
  59707. + uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
  59708. +
  59709. + return 0;
  59710. +}
  59711. +
  59712. +static void __exit clps711xuart_exit(void)
  59713. +{
  59714. + int i;
  59715. +
  59716. + for (i = 0; i < UART_NR; i++)
  59717. + uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
  59718. +
  59719. + uart_unregister_driver(&clps711x_reg);
  59720. +}
  59721. +
  59722. +module_init(clps711xuart_init);
  59723. +module_exit(clps711xuart_exit);
  59724. +
  59725. +EXPORT_NO_SYMBOLS;
  59726. +
  59727. +MODULE_AUTHOR("Deep Blue Solutions Ltd");
  59728. +MODULE_DESCRIPTION("CLPS-711x generic serial driver");
  59729. +MODULE_LICENSE("GPL");
  59730. diff -urN linux-2.4.26/drivers/serial/core.c linux-2.4.26-vrs1/drivers/serial/core.c
  59731. --- linux-2.4.26/drivers/serial/core.c 1970-01-01 01:00:00.000000000 +0100
  59732. +++ linux-2.4.26-vrs1/drivers/serial/core.c 2004-01-14 21:32:26.000000000 +0000
  59733. @@ -0,0 +1,2584 @@
  59734. +/*
  59735. + * linux/drivers/serial/core.c
  59736. + *
  59737. + * Driver core for serial ports
  59738. + *
  59739. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  59740. + *
  59741. + * Copyright 1999 ARM Limited
  59742. + * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
  59743. + *
  59744. + * This program is free software; you can redistribute it and/or modify
  59745. + * it under the terms of the GNU General Public License as published by
  59746. + * the Free Software Foundation; either version 2 of the License, or
  59747. + * (at your option) any later version.
  59748. + *
  59749. + * This program is distributed in the hope that it will be useful,
  59750. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  59751. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  59752. + * GNU General Public License for more details.
  59753. + *
  59754. + * You should have received a copy of the GNU General Public License
  59755. + * along with this program; if not, write to the Free Software
  59756. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  59757. + *
  59758. + * $Id: core.c,v 1.20.2.5 2002/03/13 15:22:26 rmk Exp $
  59759. + *
  59760. + */
  59761. +#include <linux/config.h>
  59762. +#include <linux/module.h>
  59763. +#include <linux/errno.h>
  59764. +#include <linux/tty.h>
  59765. +#include <linux/string.h>
  59766. +#include <linux/fcntl.h>
  59767. +#include <linux/ptrace.h>
  59768. +#include <linux/ioport.h>
  59769. +#include <linux/mm.h>
  59770. +#include <linux/slab.h>
  59771. +#include <linux/init.h>
  59772. +#include <linux/console.h>
  59773. +#include <linux/sysrq.h>
  59774. +#include <linux/pm.h>
  59775. +#include <linux/serial_core.h>
  59776. +#include <linux/smp_lock.h>
  59777. +
  59778. +#include <asm/irq.h>
  59779. +#include <asm/uaccess.h>
  59780. +
  59781. +#undef DEBUG
  59782. +#ifdef DEBUG
  59783. +#define DPRINTK(x...) printk(x)
  59784. +#else
  59785. +#define DPRINTK(x...) do { } while (0)
  59786. +#endif
  59787. +
  59788. +#ifndef CONFIG_PM
  59789. +#define pm_access(pm) do { } while (0)
  59790. +#define pm_unregister(pm) do { } while (0)
  59791. +#endif
  59792. +
  59793. +/*
  59794. + * This is used to lock changes in serial line configuration.
  59795. + */
  59796. +static DECLARE_MUTEX(port_sem);
  59797. +
  59798. +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
  59799. +
  59800. +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
  59801. +
  59802. +#ifdef CONFIG_SERIAL_CORE_CONSOLE
  59803. +#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
  59804. +#else
  59805. +#define uart_console(port) (0)
  59806. +#endif
  59807. +
  59808. +static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
  59809. +static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
  59810. +static void uart_change_pm(struct uart_state *state, int pm_state);
  59811. +
  59812. +/*
  59813. + * This routine is used by the interrupt handler to schedule processing in
  59814. + * the software interrupt portion of the driver.
  59815. + */
  59816. +void uart_write_wakeup(struct uart_port *port)
  59817. +{
  59818. + struct uart_info *info = port->info;
  59819. + tasklet_schedule(&info->tlet);
  59820. +}
  59821. +
  59822. +static void uart_stop(struct tty_struct *tty)
  59823. +{
  59824. + struct uart_state *state = tty->driver_data;
  59825. + struct uart_port *port = state->port;
  59826. + unsigned long flags;
  59827. +
  59828. + spin_lock_irqsave(&port->lock, flags);
  59829. + port->ops->stop_tx(port, 1);
  59830. + spin_unlock_irqrestore(&port->lock, flags);
  59831. +}
  59832. +
  59833. +static void __uart_start(struct tty_struct *tty)
  59834. +{
  59835. + struct uart_state *state = tty->driver_data;
  59836. + struct uart_port *port = state->port;
  59837. +
  59838. + if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
  59839. + !tty->stopped && !tty->hw_stopped)
  59840. + port->ops->start_tx(port, 1);
  59841. +}
  59842. +
  59843. +static void uart_start(struct tty_struct *tty)
  59844. +{
  59845. + struct uart_state *state = tty->driver_data;
  59846. + struct uart_port *port = state->port;
  59847. + unsigned long flags;
  59848. +
  59849. + pm_access(state->pm);
  59850. +
  59851. + spin_lock_irqsave(&port->lock, flags);
  59852. + __uart_start(tty);
  59853. + spin_unlock_irqrestore(&port->lock, flags);
  59854. +}
  59855. +
  59856. +static void uart_tasklet_action(unsigned long data)
  59857. +{
  59858. + struct uart_state *state = (struct uart_state *)data;
  59859. + struct tty_struct *tty;
  59860. +
  59861. + tty = state->info->tty;
  59862. + if (tty) {
  59863. + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  59864. + tty->ldisc.write_wakeup)
  59865. + tty->ldisc.write_wakeup(tty);
  59866. + wake_up_interruptible(&tty->write_wait);
  59867. + }
  59868. +}
  59869. +
  59870. +static inline void
  59871. +uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
  59872. +{
  59873. + unsigned long flags;
  59874. + unsigned int old;
  59875. +
  59876. + spin_lock_irqsave(&port->lock, flags);
  59877. + old = port->mctrl;
  59878. + port->mctrl = (old & ~clear) | set;
  59879. + if (old != port->mctrl)
  59880. + port->ops->set_mctrl(port, port->mctrl);
  59881. + spin_unlock_irqrestore(&port->lock, flags);
  59882. +}
  59883. +
  59884. +#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0)
  59885. +#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear)
  59886. +
  59887. +static inline unsigned int uart_get_altspeed(struct uart_port *port)
  59888. +{
  59889. + unsigned int flags = port->flags & UPF_SPD_MASK;
  59890. + unsigned int altbaud = 0;
  59891. +
  59892. + if (flags == ASYNC_SPD_HI)
  59893. + altbaud = 57600;
  59894. + if (flags == ASYNC_SPD_VHI)
  59895. + altbaud = 115200;
  59896. + if (flags == ASYNC_SPD_SHI)
  59897. + altbaud = 230400;
  59898. + if (flags == ASYNC_SPD_WARP)
  59899. + altbaud = 460800;
  59900. +
  59901. + return altbaud;
  59902. +}
  59903. +
  59904. +/*
  59905. + * Startup the port. This will be called once per open. All calls
  59906. + * will be serialised by the per-port semaphore.
  59907. + */
  59908. +static int uart_startup(struct uart_state *state, int init_hw)
  59909. +{
  59910. + struct uart_info *info = state->info;
  59911. + struct uart_port *port = state->port;
  59912. + unsigned long page;
  59913. + int retval = 0;
  59914. +
  59915. + if (info->flags & UIF_INITIALIZED)
  59916. + return 0;
  59917. +
  59918. + /*
  59919. + * Set the TTY IO error marker - we will only clear this
  59920. + * once we have successfully opened the port. Also set
  59921. + * up the tty->alt_speed kludge
  59922. + */
  59923. + if (info->tty)
  59924. + set_bit(TTY_IO_ERROR, &info->tty->flags);
  59925. +
  59926. + if (port->type == PORT_UNKNOWN)
  59927. + return 0;
  59928. +
  59929. + /*
  59930. + * Initialise and allocate the transmit and temporary
  59931. + * buffer.
  59932. + */
  59933. + if (!info->xmit.buf) {
  59934. + page = get_zeroed_page(GFP_KERNEL);
  59935. + if (!page)
  59936. + return -ENOMEM;
  59937. +
  59938. + info->xmit.buf = (unsigned char *) page;
  59939. + info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE;
  59940. + init_MUTEX(&info->tmpbuf_sem);
  59941. + uart_circ_clear(&info->xmit);
  59942. + }
  59943. +
  59944. + port->mctrl = 0;
  59945. +
  59946. + retval = port->ops->startup(port);
  59947. + if (retval == 0) {
  59948. + if (init_hw) {
  59949. + /*
  59950. + * Initialise the hardware port settings.
  59951. + */
  59952. + uart_change_speed(state, NULL);
  59953. +
  59954. + /*
  59955. + * Setup the RTS and DTR signals once the
  59956. + * port is open and ready to respond.
  59957. + */
  59958. + if (info->tty->termios->c_cflag & CBAUD)
  59959. + uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
  59960. + }
  59961. +
  59962. + info->flags |= UIF_INITIALIZED;
  59963. +
  59964. + clear_bit(TTY_IO_ERROR, &info->tty->flags);
  59965. + }
  59966. +
  59967. + if (retval && capable(CAP_SYS_ADMIN))
  59968. + retval = 0;
  59969. +
  59970. + return retval;
  59971. +}
  59972. +
  59973. +/*
  59974. + * This routine will shutdown a serial port; interrupts are disabled, and
  59975. + * DTR is dropped if the hangup on close termio flag is on. Calls to
  59976. + * uart_shutdown are serialised by the per-port semaphore.
  59977. + */
  59978. +static void uart_shutdown(struct uart_state *state)
  59979. +{
  59980. + struct uart_info *info = state->info;
  59981. + struct uart_port *port = state->port;
  59982. +
  59983. + if (!(info->flags & UIF_INITIALIZED))
  59984. + return;
  59985. +
  59986. + /*
  59987. + * Turn off DTR and RTS early.
  59988. + */
  59989. + if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
  59990. + uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
  59991. +
  59992. + /*
  59993. + * clear delta_msr_wait queue to avoid mem leaks: we may free
  59994. + * the irq here so the queue might never be woken up. Note
  59995. + * that we won't end up waiting on delta_msr_wait again since
  59996. + * any outstanding file descriptors should be pointing at
  59997. + * hung_up_tty_fops now.
  59998. + */
  59999. + wake_up_interruptible(&info->delta_msr_wait);
  60000. +
  60001. + /*
  60002. + * Free the IRQ and disable the port.
  60003. + */
  60004. + port->ops->shutdown(port);
  60005. +
  60006. + /*
  60007. + * Free the transmit buffer page.
  60008. + */
  60009. + if (info->xmit.buf) {
  60010. + free_page((unsigned long)info->xmit.buf);
  60011. + info->xmit.buf = NULL;
  60012. + info->tmpbuf = NULL;
  60013. + }
  60014. +
  60015. + /*
  60016. + * kill off our tasklet
  60017. + */
  60018. + tasklet_kill(&info->tlet);
  60019. + if (info->tty)
  60020. + set_bit(TTY_IO_ERROR, &info->tty->flags);
  60021. +
  60022. + info->flags &= ~UIF_INITIALIZED;
  60023. +}
  60024. +
  60025. +/**
  60026. + * uart_update_timeout - update per-port FIFO timeout.
  60027. + * @port: uart_port structure describing the port.
  60028. + * @cflag: termios cflag value
  60029. + * @quot: uart clock divisor quotient
  60030. + *
  60031. + * Set the port FIFO timeout value. The @cflag value should
  60032. + * reflect the actual hardware settings.
  60033. + */
  60034. +void
  60035. +uart_update_timeout(struct uart_port *port, unsigned int cflag,
  60036. + unsigned int baud)
  60037. +{
  60038. + unsigned int bits;
  60039. +
  60040. + /* byte size and parity */
  60041. + switch (cflag & CSIZE) {
  60042. + case CS5:
  60043. + bits = 7;
  60044. + break;
  60045. + case CS6:
  60046. + bits = 8;
  60047. + break;
  60048. + case CS7:
  60049. + bits = 9;
  60050. + break;
  60051. + default:
  60052. + bits = 10;
  60053. + break; // CS8
  60054. + }
  60055. +
  60056. + if (cflag & CSTOPB)
  60057. + bits++;
  60058. + if (cflag & PARENB)
  60059. + bits++;
  60060. +
  60061. + /*
  60062. + * The total number of bits to be transmitted in the fifo.
  60063. + */
  60064. + bits = bits * port->fifosize;
  60065. +
  60066. + /*
  60067. + * Figure the timeout to send the above number of bits.
  60068. + * Add .02 seconds of slop
  60069. + */
  60070. + port->timeout = (HZ * bits) / baud + HZ/50;
  60071. +}
  60072. +
  60073. +EXPORT_SYMBOL(uart_update_timeout);
  60074. +
  60075. +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
  60076. +{
  60077. + u_int quot;
  60078. +
  60079. + /* Special case: B0 rate */
  60080. + if (!baud)
  60081. + baud = 9600;
  60082. +
  60083. + /* Old HI/VHI/custom speed handling */
  60084. + if (baud == 38400 &&
  60085. + ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
  60086. + quot = port->custom_divisor;
  60087. + else
  60088. + quot = port->uartclk / (16 * baud);
  60089. +
  60090. + return quot;
  60091. +}
  60092. +
  60093. +static void
  60094. +uart_change_speed(struct uart_state *state, struct termios *old_termios)
  60095. +{
  60096. + struct tty_struct *tty = state->info->tty;
  60097. + struct uart_port *port = state->port;
  60098. + struct termios *termios;
  60099. + unsigned int quot, baud, cflag, try;
  60100. +
  60101. + /*
  60102. + * If we have no tty, termios, or the port does not exist,
  60103. + * then we can't set the parameters for this port.
  60104. + */
  60105. + if (!tty || !tty->termios || port->type == PORT_UNKNOWN)
  60106. + return;
  60107. +
  60108. + termios = tty->termios;
  60109. +
  60110. + cflag = termios->c_cflag;
  60111. +
  60112. + for (try = 0; try < 2; try ++) {
  60113. + /* Determine divisor based on baud rate */
  60114. + baud = tty_get_baud_rate(tty);
  60115. + quot = uart_calculate_quot(port, baud);
  60116. + if (quot)
  60117. + break;
  60118. +
  60119. + /*
  60120. + * Oops, the quotient was zero. Try again with
  60121. + * the old baud rate if possible.
  60122. + */
  60123. + termios->c_cflag &= ~CBAUD;
  60124. + if (old_termios) {
  60125. + termios->c_cflag |=
  60126. + (old_termios->c_cflag & CBAUD);
  60127. + old_termios = NULL;
  60128. + continue;
  60129. + }
  60130. +
  60131. + /*
  60132. + * As a last resort, if the quotient is zero,
  60133. + * default to 9600 bps
  60134. + */
  60135. + termios->c_cflag |= B9600;
  60136. + }
  60137. +
  60138. + uart_update_timeout(port, cflag, port->uartclk / (16 * quot));
  60139. +
  60140. + if (termios->c_cflag & CRTSCTS)
  60141. + state->info->flags |= UIF_CTS_FLOW;
  60142. + else
  60143. + state->info->flags &= ~UIF_CTS_FLOW;
  60144. + if (termios->c_cflag & CLOCAL)
  60145. + state->info->flags &= ~UIF_CHECK_CD;
  60146. + else
  60147. + state->info->flags |= UIF_CHECK_CD;
  60148. +
  60149. + /*
  60150. + * Set up parity check flag
  60151. + */
  60152. + pm_access(state->pm);
  60153. +
  60154. + port->ops->change_speed(port, cflag, termios->c_iflag, quot);
  60155. +}
  60156. +
  60157. +static inline void
  60158. +__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
  60159. +{
  60160. + unsigned long flags;
  60161. +
  60162. + if (!circ->buf)
  60163. + return;
  60164. +
  60165. + spin_lock_irqsave(&port->lock, flags);
  60166. + if (uart_circ_chars_free(circ) != 0) {
  60167. + circ->buf[circ->head] = c;
  60168. + circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
  60169. + }
  60170. + spin_unlock_irqrestore(&port->lock, flags);
  60171. +}
  60172. +
  60173. +static inline int
  60174. +__uart_user_write(struct uart_port *port, struct circ_buf *circ,
  60175. + const unsigned char *buf, int count)
  60176. +{
  60177. + unsigned long flags;
  60178. + int c, ret = 0;
  60179. +
  60180. + if (down_interruptible(&port->info->tmpbuf_sem))
  60181. + return -EINTR;
  60182. +
  60183. + while (1) {
  60184. + int c1;
  60185. + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
  60186. + if (count < c)
  60187. + c = count;
  60188. + if (c <= 0)
  60189. + break;
  60190. +
  60191. + c -= copy_from_user(port->info->tmpbuf, buf, c);
  60192. + if (!c) {
  60193. + if (!ret)
  60194. + ret = -EFAULT;
  60195. + break;
  60196. + }
  60197. + spin_lock_irqsave(&port->lock, flags);
  60198. + c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
  60199. + if (c1 < c)
  60200. + c = c1;
  60201. + memcpy(circ->buf + circ->head, port->info->tmpbuf, c);
  60202. + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
  60203. + spin_unlock_irqrestore(&port->lock, flags);
  60204. + buf += c;
  60205. + count -= c;
  60206. + ret += c;
  60207. + }
  60208. + up(&port->info->tmpbuf_sem);
  60209. +
  60210. + return ret;
  60211. +}
  60212. +
  60213. +static inline int
  60214. +__uart_kern_write(struct uart_port *port, struct circ_buf *circ,
  60215. + const unsigned char *buf, int count)
  60216. +{
  60217. + unsigned long flags;
  60218. + int c, ret = 0;
  60219. +
  60220. + spin_lock_irqsave(&port->lock, flags);
  60221. + while (1) {
  60222. + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
  60223. + if (count < c)
  60224. + c = count;
  60225. + if (c <= 0)
  60226. + break;
  60227. + memcpy(circ->buf + circ->head, buf, c);
  60228. + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
  60229. + buf += c;
  60230. + count -= c;
  60231. + ret += c;
  60232. + }
  60233. + spin_unlock_irqrestore(&port->lock, flags);
  60234. +
  60235. + return ret;
  60236. +}
  60237. +
  60238. +static void uart_put_char(struct tty_struct *tty, unsigned char ch)
  60239. +{
  60240. + struct uart_state *state = tty->driver_data;
  60241. +
  60242. + __uart_put_char(state->port, &state->info->xmit, ch);
  60243. +}
  60244. +
  60245. +static void uart_flush_chars(struct tty_struct *tty)
  60246. +{
  60247. + uart_start(tty);
  60248. +}
  60249. +
  60250. +static int
  60251. +uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf,
  60252. + int count)
  60253. +{
  60254. + struct uart_state *state = tty->driver_data;
  60255. + int ret;
  60256. +
  60257. + if (!state->info->xmit.buf)
  60258. + return 0;
  60259. +
  60260. + if (from_user)
  60261. + ret = __uart_user_write(state->port, &state->info->xmit, buf, count);
  60262. + else
  60263. + ret = __uart_kern_write(state->port, &state->info->xmit, buf, count);
  60264. +
  60265. + uart_start(tty);
  60266. + return ret;
  60267. +}
  60268. +
  60269. +static int uart_write_room(struct tty_struct *tty)
  60270. +{
  60271. + struct uart_state *state = tty->driver_data;
  60272. +
  60273. + return uart_circ_chars_free(&state->info->xmit);
  60274. +}
  60275. +
  60276. +static int uart_chars_in_buffer(struct tty_struct *tty)
  60277. +{
  60278. + struct uart_state *state = tty->driver_data;
  60279. +
  60280. + return uart_circ_chars_pending(&state->info->xmit);
  60281. +}
  60282. +
  60283. +static void uart_flush_buffer(struct tty_struct *tty)
  60284. +{
  60285. + struct uart_state *state = tty->driver_data;
  60286. + struct uart_port *port = state->port;
  60287. + unsigned long flags;
  60288. +
  60289. + DPRINTK("uart_flush_buffer(%d) called\n",
  60290. + MINOR(tty->device) - tty->driver.minor_start);
  60291. +
  60292. + spin_lock_irqsave(&port->lock, flags);
  60293. + uart_circ_clear(&state->info->xmit);
  60294. + spin_unlock_irqrestore(&port->lock, flags);
  60295. + wake_up_interruptible(&tty->write_wait);
  60296. + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  60297. + tty->ldisc.write_wakeup)
  60298. + (tty->ldisc.write_wakeup)(tty);
  60299. +}
  60300. +
  60301. +/*
  60302. + * This function is used to send a high-priority XON/XOFF character to
  60303. + * the device
  60304. + */
  60305. +static void uart_send_xchar(struct tty_struct *tty, char ch)
  60306. +{
  60307. + struct uart_state *state = tty->driver_data;
  60308. + struct uart_port *port = state->port;
  60309. + unsigned long flags;
  60310. +
  60311. + if (port->ops->send_xchar)
  60312. + port->ops->send_xchar(port, ch);
  60313. + else {
  60314. + port->x_char = ch;
  60315. + if (ch) {
  60316. + spin_lock_irqsave(&port->lock, flags);
  60317. + port->ops->start_tx(port, 0);
  60318. + spin_unlock_irqrestore(&port->lock, flags);
  60319. + }
  60320. + }
  60321. +}
  60322. +
  60323. +static void uart_throttle(struct tty_struct *tty)
  60324. +{
  60325. + struct uart_state *state = tty->driver_data;
  60326. +
  60327. + if (I_IXOFF(tty))
  60328. + uart_send_xchar(tty, STOP_CHAR(tty));
  60329. +
  60330. + if (tty->termios->c_cflag & CRTSCTS)
  60331. + uart_clear_mctrl(state->port, TIOCM_RTS);
  60332. +}
  60333. +
  60334. +static void uart_unthrottle(struct tty_struct *tty)
  60335. +{
  60336. + struct uart_state *state = tty->driver_data;
  60337. + struct uart_port *port = state->port;
  60338. +
  60339. + if (I_IXOFF(tty)) {
  60340. + if (port->x_char)
  60341. + port->x_char = 0;
  60342. + else
  60343. + uart_send_xchar(tty, START_CHAR(tty));
  60344. + }
  60345. +
  60346. + if (tty->termios->c_cflag & CRTSCTS)
  60347. + uart_set_mctrl(port, TIOCM_RTS);
  60348. +}
  60349. +
  60350. +static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo)
  60351. +{
  60352. + struct uart_port *port = state->port;
  60353. + struct serial_struct tmp;
  60354. +
  60355. + memset(&tmp, 0, sizeof(tmp));
  60356. + tmp.type = port->type;
  60357. + tmp.line = port->line;
  60358. + tmp.port = port->iobase;
  60359. + if (HIGH_BITS_OFFSET)
  60360. + tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
  60361. + tmp.irq = port->irq;
  60362. + tmp.flags = port->flags;
  60363. + tmp.xmit_fifo_size = port->fifosize;
  60364. + tmp.baud_base = port->uartclk / 16;
  60365. + tmp.close_delay = state->close_delay;
  60366. + tmp.closing_wait = state->closing_wait;
  60367. + tmp.custom_divisor = port->custom_divisor;
  60368. + tmp.hub6 = port->hub6;
  60369. + tmp.io_type = port->iotype;
  60370. + tmp.iomem_reg_shift = port->regshift;
  60371. + tmp.iomem_base = (void *)port->mapbase;
  60372. +
  60373. + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
  60374. + return -EFAULT;
  60375. + return 0;
  60376. +}
  60377. +
  60378. +static int
  60379. +uart_set_info(struct uart_state *state, struct serial_struct *newinfo)
  60380. +{
  60381. + struct serial_struct new_serial;
  60382. + struct uart_port *port = state->port;
  60383. + unsigned long new_port;
  60384. + unsigned int change_irq, change_port, old_flags;
  60385. + unsigned int old_custom_divisor;
  60386. + int retval = 0;
  60387. +
  60388. + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
  60389. + return -EFAULT;
  60390. +
  60391. + new_port = new_serial.port;
  60392. + if (HIGH_BITS_OFFSET)
  60393. + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
  60394. +
  60395. + new_serial.irq = irq_cannonicalize(new_serial.irq);
  60396. +
  60397. + /*
  60398. + * This semaphore protects state->count. It is also
  60399. + * very useful to prevent opens. Also, take the
  60400. + * port configuration semaphore to make sure that a
  60401. + * module insertion/removal doesn't change anything
  60402. + * under us.
  60403. + */
  60404. + down(&state->sem);
  60405. +
  60406. + change_irq = new_serial.irq != port->irq;
  60407. +
  60408. + /*
  60409. + * Since changing the 'type' of the port changes its resource
  60410. + * allocations, we should treat type changes the same as
  60411. + * IO port changes.
  60412. + */
  60413. + change_port = new_port != port->iobase ||
  60414. + (unsigned long)new_serial.iomem_base != port->mapbase ||
  60415. + new_serial.hub6 != port->hub6 ||
  60416. + new_serial.io_type != port->iotype ||
  60417. + new_serial.iomem_reg_shift != port->regshift ||
  60418. + new_serial.type != port->type;
  60419. +
  60420. + old_flags = port->flags;
  60421. + old_custom_divisor = port->custom_divisor;
  60422. +
  60423. + if (!capable(CAP_SYS_ADMIN)) {
  60424. + retval = -EPERM;
  60425. + if (change_irq || change_port ||
  60426. + (new_serial.baud_base != port->uartclk / 16) ||
  60427. + (new_serial.close_delay != state->close_delay) ||
  60428. + (new_serial.closing_wait != state->closing_wait) ||
  60429. + (new_serial.xmit_fifo_size != port->fifosize) ||
  60430. + (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0))
  60431. + goto exit;
  60432. + port->flags = ((port->flags & ~UPF_USR_MASK) |
  60433. + (new_serial.flags & UPF_USR_MASK));
  60434. + port->custom_divisor = new_serial.custom_divisor;
  60435. + goto check_and_exit;
  60436. + }
  60437. +
  60438. + /*
  60439. + * Ask the low level driver to verify the settings.
  60440. + */
  60441. + if (port->ops->verify_port)
  60442. + retval = port->ops->verify_port(port, &new_serial);
  60443. +
  60444. + if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
  60445. + (new_serial.baud_base < 9600))
  60446. + retval = -EINVAL;
  60447. +
  60448. + if (retval)
  60449. + goto exit;
  60450. +
  60451. + if (change_port || change_irq) {
  60452. + retval = -EBUSY;
  60453. +
  60454. + /*
  60455. + * Make sure that we are the sole user of this port.
  60456. + */
  60457. + if (uart_users(state) > 1)
  60458. + goto exit;
  60459. +
  60460. + /*
  60461. + * We need to shutdown the serial port at the old
  60462. + * port/type/irq combination.
  60463. + */
  60464. + uart_shutdown(state);
  60465. + }
  60466. +
  60467. + if (change_port) {
  60468. + unsigned long old_iobase, old_mapbase;
  60469. + unsigned int old_type, old_iotype, old_hub6, old_shift;
  60470. +
  60471. + old_iobase = port->iobase;
  60472. + old_mapbase = port->mapbase;
  60473. + old_type = port->type;
  60474. + old_hub6 = port->hub6;
  60475. + old_iotype = port->iotype;
  60476. + old_shift = port->regshift;
  60477. +
  60478. + /*
  60479. + * Free and release old regions
  60480. + */
  60481. + if (old_type != PORT_UNKNOWN)
  60482. + port->ops->release_port(port);
  60483. +
  60484. + port->iobase = new_port;
  60485. + port->type = new_serial.type;
  60486. + port->hub6 = new_serial.hub6;
  60487. + port->iotype = new_serial.io_type;
  60488. + port->regshift = new_serial.iomem_reg_shift;
  60489. + port->mapbase = (unsigned long)new_serial.iomem_base;
  60490. +
  60491. + /*
  60492. + * Claim and map the new regions
  60493. + */
  60494. + if (port->type != PORT_UNKNOWN) {
  60495. + retval = port->ops->request_port(port);
  60496. + } else {
  60497. + /* Always success - Jean II */
  60498. + retval = 0;
  60499. + }
  60500. +
  60501. + /*
  60502. + * If we fail to request resources for the
  60503. + * new port, try to restore the old settings.
  60504. + */
  60505. + if (retval && old_type != PORT_UNKNOWN) {
  60506. + port->iobase = old_iobase;
  60507. + port->type = old_type;
  60508. + port->hub6 = old_hub6;
  60509. + port->iotype = old_iotype;
  60510. + port->regshift = old_shift;
  60511. + port->mapbase = old_mapbase;
  60512. + retval = port->ops->request_port(port);
  60513. + /*
  60514. + * If we failed to restore the old settings,
  60515. + * we fail like this.
  60516. + */
  60517. + if (retval)
  60518. + port->type = PORT_UNKNOWN;
  60519. +
  60520. + /*
  60521. + * We failed anyway.
  60522. + */
  60523. + retval = -EBUSY;
  60524. + }
  60525. + }
  60526. +
  60527. + port->irq = new_serial.irq;
  60528. + port->uartclk = new_serial.baud_base * 16;
  60529. + port->flags = (port->flags & ~UPF_CHANGE_MASK) |
  60530. + (new_serial.flags & UPF_CHANGE_MASK);
  60531. + port->custom_divisor = new_serial.custom_divisor;
  60532. + state->close_delay = new_serial.close_delay * HZ / 100;
  60533. + state->closing_wait = new_serial.closing_wait * HZ / 100;
  60534. + port->fifosize = new_serial.xmit_fifo_size;
  60535. + if (state->info->tty)
  60536. + state->info->tty->low_latency =
  60537. + (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
  60538. +
  60539. + check_and_exit:
  60540. + retval = 0;
  60541. + if (port->type == PORT_UNKNOWN)
  60542. + goto exit;
  60543. + if (state->info->flags & UIF_INITIALIZED) {
  60544. + if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
  60545. + old_custom_divisor != port->custom_divisor) {
  60546. + state->info->tty->alt_speed = uart_get_altspeed(port);
  60547. + uart_change_speed(state, NULL);
  60548. + }
  60549. + } else
  60550. + retval = uart_startup(state, 1);
  60551. + exit:
  60552. + up(&state->sem);
  60553. + return retval;
  60554. +}
  60555. +
  60556. +
  60557. +/*
  60558. + * uart_get_lsr_info - get line status register info.
  60559. + * Note: uart_ioctl protects us against hangups.
  60560. + */
  60561. +static int uart_get_lsr_info(struct uart_state *state, unsigned int *value)
  60562. +{
  60563. + struct uart_port *port = state->port;
  60564. + unsigned int result;
  60565. +
  60566. + result = port->ops->tx_empty(port);
  60567. +
  60568. + /*
  60569. + * If we're about to load something into the transmit
  60570. + * register, we'll pretend the transmitter isn't empty to
  60571. + * avoid a race condition (depending on when the transmit
  60572. + * interrupt happens).
  60573. + */
  60574. + if (port->x_char ||
  60575. + ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
  60576. + !state->info->tty->stopped && !state->info->tty->hw_stopped))
  60577. + result &= ~TIOCSER_TEMT;
  60578. +
  60579. + return put_user(result, value);
  60580. +}
  60581. +
  60582. +static int uart_tiocmget(struct tty_struct *tty, struct file *file)
  60583. +{
  60584. + struct uart_state *state = tty->driver_data;
  60585. + struct uart_port *port = state->port;
  60586. + int result = -EIO;
  60587. +
  60588. + down(&state->sem);
  60589. + if ((!file || !tty_hung_up_p(file)) &&
  60590. + !(tty->flags & (1 << TTY_IO_ERROR))) {
  60591. + result = port->mctrl;
  60592. + result |= port->ops->get_mctrl(port);
  60593. + }
  60594. + up(&state->sem);
  60595. +
  60596. + return result;
  60597. +}
  60598. +
  60599. +static int
  60600. +uart_tiocmset(struct tty_struct *tty, struct file *file,
  60601. + unsigned int set, unsigned int clear)
  60602. +{
  60603. + struct uart_state *state = tty->driver_data;
  60604. + struct uart_port *port = state->port;
  60605. + int ret = -EIO;
  60606. +
  60607. + down(&state->sem);
  60608. + if ((!file || !tty_hung_up_p(file)) &&
  60609. + !(tty->flags & (1 << TTY_IO_ERROR))) {
  60610. + uart_update_mctrl(port, set, clear);
  60611. + ret = 0;
  60612. + }
  60613. + up(&state->sem);
  60614. + return ret;
  60615. +}
  60616. +
  60617. +static void uart_break_ctl(struct tty_struct *tty, int break_state)
  60618. +{
  60619. + struct uart_state *state = tty->driver_data;
  60620. + struct uart_port *port = state->port;
  60621. +
  60622. + BUG_ON(!kernel_locked());
  60623. +
  60624. + down(&state->sem);
  60625. +
  60626. + if (port->type != PORT_UNKNOWN)
  60627. + port->ops->break_ctl(port, break_state);
  60628. +
  60629. + up(&state->sem);
  60630. +}
  60631. +
  60632. +static int uart_do_autoconfig(struct uart_state *state)
  60633. +{
  60634. + struct uart_port *port = state->port;
  60635. + int flags, ret;
  60636. +
  60637. + if (!capable(CAP_SYS_ADMIN))
  60638. + return -EPERM;
  60639. +
  60640. + /*
  60641. + * Take the per-port semaphore. This prevents count from
  60642. + * changing, and hence any extra opens of the port while
  60643. + * we're auto-configuring.
  60644. + */
  60645. + if (down_interruptible(&state->sem))
  60646. + return -ERESTARTSYS;
  60647. +
  60648. + ret = -EBUSY;
  60649. + if (uart_users(state) == 1) {
  60650. + uart_shutdown(state);
  60651. +
  60652. + /*
  60653. + * If we already have a port type configured,
  60654. + * we must release its resources.
  60655. + */
  60656. + if (port->type != PORT_UNKNOWN)
  60657. + port->ops->release_port(port);
  60658. +
  60659. + flags = UART_CONFIG_TYPE;
  60660. + if (port->flags & UPF_AUTO_IRQ)
  60661. + flags |= UART_CONFIG_IRQ;
  60662. +
  60663. + /*
  60664. + * This will claim the ports resources if
  60665. + * a port is found.
  60666. + */
  60667. + port->ops->config_port(port, flags);
  60668. +
  60669. + ret = uart_startup(state, 1);
  60670. + }
  60671. + up(&state->sem);
  60672. + return ret;
  60673. +}
  60674. +
  60675. +/*
  60676. + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
  60677. + * - mask passed in arg for lines of interest
  60678. + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
  60679. + * Caller should use TIOCGICOUNT to see which one it was
  60680. + */
  60681. +static int
  60682. +uart_wait_modem_status(struct uart_state *state, unsigned long arg)
  60683. +{
  60684. + struct uart_port *port = state->port;
  60685. + DECLARE_WAITQUEUE(wait, current);
  60686. + struct uart_icount cprev, cnow;
  60687. + int ret;
  60688. +
  60689. + /*
  60690. + * note the counters on entry
  60691. + */
  60692. + spin_lock_irq(&port->lock);
  60693. + memcpy(&cprev, &port->icount, sizeof(struct uart_icount));
  60694. +
  60695. + /*
  60696. + * Force modem status interrupts on
  60697. + */
  60698. + port->ops->enable_ms(port);
  60699. + spin_unlock_irq(&port->lock);
  60700. +
  60701. + add_wait_queue(&state->info->delta_msr_wait, &wait);
  60702. + for (;;) {
  60703. + spin_lock_irq(&port->lock);
  60704. + memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
  60705. + spin_unlock_irq(&port->lock);
  60706. +
  60707. + set_current_state(TASK_INTERRUPTIBLE);
  60708. +
  60709. + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
  60710. + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
  60711. + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
  60712. + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
  60713. + ret = 0;
  60714. + break;
  60715. + }
  60716. +
  60717. + schedule();
  60718. +
  60719. + /* see if a signal did it */
  60720. + if (signal_pending(current)) {
  60721. + ret = -ERESTARTSYS;
  60722. + break;
  60723. + }
  60724. +
  60725. + cprev = cnow;
  60726. + }
  60727. +
  60728. + current->state = TASK_RUNNING;
  60729. + remove_wait_queue(&state->info->delta_msr_wait, &wait);
  60730. +
  60731. + return ret;
  60732. +}
  60733. +
  60734. +/*
  60735. + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
  60736. + * Return: write counters to the user passed counter struct
  60737. + * NB: both 1->0 and 0->1 transitions are counted except for
  60738. + * RI where only 0->1 is counted.
  60739. + */
  60740. +static int
  60741. +uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt)
  60742. +{
  60743. + struct serial_icounter_struct icount;
  60744. + struct uart_icount cnow;
  60745. + struct uart_port *port = state->port;
  60746. +
  60747. + spin_lock_irq(&port->lock);
  60748. + memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
  60749. + spin_unlock_irq(&port->lock);
  60750. +
  60751. + icount.cts = cnow.cts;
  60752. + icount.dsr = cnow.dsr;
  60753. + icount.rng = cnow.rng;
  60754. + icount.dcd = cnow.dcd;
  60755. + icount.rx = cnow.rx;
  60756. + icount.tx = cnow.tx;
  60757. + icount.frame = cnow.frame;
  60758. + icount.overrun = cnow.overrun;
  60759. + icount.parity = cnow.parity;
  60760. + icount.brk = cnow.brk;
  60761. + icount.buf_overrun = cnow.buf_overrun;
  60762. +
  60763. + return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
  60764. +}
  60765. +
  60766. +/*
  60767. + * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here.
  60768. + */
  60769. +static int
  60770. +uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
  60771. + unsigned long arg)
  60772. +{
  60773. + struct uart_state *state = tty->driver_data;
  60774. + int ret = -ENOIOCTLCMD;
  60775. +
  60776. + BUG_ON(!kernel_locked());
  60777. +
  60778. + /*
  60779. + * These ioctls don't rely on the hardware to be present.
  60780. + */
  60781. + switch (cmd) {
  60782. + case TIOCGSERIAL:
  60783. + ret = uart_get_info(state, (struct serial_struct *)arg);
  60784. + break;
  60785. +
  60786. + case TIOCSSERIAL:
  60787. + ret = uart_set_info(state, (struct serial_struct *)arg);
  60788. + break;
  60789. +
  60790. + case TIOCSERCONFIG:
  60791. + ret = uart_do_autoconfig(state);
  60792. + break;
  60793. +
  60794. + case TIOCSERGWILD: /* obsolete */
  60795. + case TIOCSERSWILD: /* obsolete */
  60796. + ret = 0;
  60797. + break;
  60798. + }
  60799. +
  60800. + if (ret != -ENOIOCTLCMD)
  60801. + goto out;
  60802. +
  60803. + if (tty->flags & (1 << TTY_IO_ERROR)) {
  60804. + ret = -EIO;
  60805. + goto out;
  60806. + }
  60807. +
  60808. + /*
  60809. + * The following should only be used when hardware is present.
  60810. + */
  60811. + switch (cmd) {
  60812. + case TIOCMIWAIT:
  60813. + ret = uart_wait_modem_status(state, arg);
  60814. + break;
  60815. +
  60816. + case TIOCGICOUNT:
  60817. + ret = uart_get_count(state, (struct serial_icounter_struct *)arg);
  60818. + break;
  60819. +
  60820. + case TIOCMGET:
  60821. + {
  60822. + int val;
  60823. + val = uart_tiocmget(tty, filp);
  60824. + if (val >= 0) {
  60825. + ret = put_user(val, (int *)arg);
  60826. + } else {
  60827. + ret = val;
  60828. + }
  60829. + }
  60830. + break;
  60831. +
  60832. + case TIOCMBIS:
  60833. + case TIOCMBIC:
  60834. + case TIOCMSET:
  60835. + {
  60836. + int val, set = 0, clear = 0;
  60837. + ret = get_user(val, (int *)arg);
  60838. + if (ret)
  60839. + break;
  60840. +
  60841. + switch (cmd) {
  60842. + case TIOCMBIS:
  60843. + set = val;
  60844. + break;
  60845. + case TIOCMBIC:
  60846. + clear = val;
  60847. + break;
  60848. + case TIOCMSET:
  60849. + set = val;
  60850. + clear = ~val;
  60851. + break;
  60852. + }
  60853. +
  60854. + set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
  60855. + clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
  60856. +
  60857. + ret = uart_tiocmset(tty, filp, set, clear);
  60858. + }
  60859. + break;
  60860. + }
  60861. +
  60862. + if (ret != -ENOIOCTLCMD)
  60863. + goto out;
  60864. +
  60865. + down(&state->sem);
  60866. +
  60867. + if (tty_hung_up_p(filp)) {
  60868. + ret = -EIO;
  60869. + goto out_up;
  60870. + }
  60871. +
  60872. + /*
  60873. + * All these rely on hardware being present and need to be
  60874. + * protected against the tty being hung up.
  60875. + */
  60876. + switch (cmd) {
  60877. + case TIOCSERGETLSR: /* Get line status register */
  60878. + ret = uart_get_lsr_info(state, (unsigned int *)arg);
  60879. + break;
  60880. +
  60881. + default: {
  60882. + struct uart_port *port = state->port;
  60883. + if (port->ops->ioctl)
  60884. + ret = port->ops->ioctl(port, cmd, arg);
  60885. + break;
  60886. + }
  60887. + }
  60888. + out_up:
  60889. + up(&state->sem);
  60890. + out:
  60891. + return ret;
  60892. +}
  60893. +
  60894. +static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
  60895. +{
  60896. + struct uart_state *state = tty->driver_data;
  60897. + unsigned long flags;
  60898. + unsigned int cflag = tty->termios->c_cflag;
  60899. +
  60900. + BUG_ON(!kernel_locked());
  60901. +
  60902. + /*
  60903. + * These are the bits that are used to setup various
  60904. + * flags in the low level driver.
  60905. + */
  60906. +#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
  60907. +
  60908. + if ((cflag ^ old_termios->c_cflag) == 0 &&
  60909. + RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
  60910. + return;
  60911. +
  60912. + uart_change_speed(state, old_termios);
  60913. +
  60914. + /* Handle transition to B0 status */
  60915. + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
  60916. + uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
  60917. +
  60918. + /* Handle transition away from B0 status */
  60919. + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
  60920. + unsigned int mask = TIOCM_DTR;
  60921. + if (!(cflag & CRTSCTS) ||
  60922. + !test_bit(TTY_THROTTLED, &tty->flags))
  60923. + mask |= TIOCM_RTS;
  60924. + uart_set_mctrl(state->port, mask);
  60925. + }
  60926. +
  60927. + /* Handle turning off CRTSCTS */
  60928. + if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
  60929. + spin_lock_irqsave(&state->port->lock, flags);
  60930. + tty->hw_stopped = 0;
  60931. + __uart_start(tty);
  60932. + spin_unlock_irqrestore(&state->port->lock, flags);
  60933. + }
  60934. +
  60935. +#if 0
  60936. + /*
  60937. + * No need to wake up processes in open wait, since they
  60938. + * sample the CLOCAL flag once, and don't recheck it.
  60939. + * XXX It's not clear whether the current behavior is correct
  60940. + * or not. Hence, this may change.....
  60941. + */
  60942. + if (!(old_termios->c_cflag & CLOCAL) &&
  60943. + (tty->termios->c_cflag & CLOCAL))
  60944. + wake_up_interruptible(&state->info->open_wait);
  60945. +#endif
  60946. +}
  60947. +
  60948. +/*
  60949. + * In 2.4.5, calls to this will be serialized via the BKL in
  60950. + * linux/drivers/char/tty_io.c:tty_release()
  60951. + * linux/drivers/char/tty_io.c:do_tty_handup()
  60952. + */
  60953. +static void uart_close(struct tty_struct *tty, struct file *filp)
  60954. +{
  60955. + struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
  60956. + struct uart_state *state = tty->driver_data;
  60957. + struct uart_port *port;
  60958. +
  60959. + BUG_ON(!kernel_locked());
  60960. +
  60961. + if (!state || !state->port)
  60962. + return;
  60963. +
  60964. + port = state->port;
  60965. +
  60966. + DPRINTK("uart_close(%d) called\n", port->line);
  60967. +
  60968. + down(&state->sem);
  60969. +
  60970. + if (tty_hung_up_p(filp))
  60971. + goto done;
  60972. +
  60973. + if ((tty->count == 1) && (state->count != 1)) {
  60974. + /*
  60975. + * Uh, oh. tty->count is 1, which means that the tty
  60976. + * structure will be freed. state->count should always
  60977. + * be one in these conditions. If it's greater than
  60978. + * one, we've got real problems, since it means the
  60979. + * serial port won't be shutdown.
  60980. + */
  60981. + printk("uart_close: bad serial port count; tty->count is 1, "
  60982. + "state->count is %d\n", state->count);
  60983. + state->count = 1;
  60984. + }
  60985. + if (--state->count < 0) {
  60986. + printk("rs_close: bad serial port count for %s%d: %d\n",
  60987. + tty->driver.name, port->line, state->count);
  60988. + state->count = 0;
  60989. + }
  60990. + if (state->count)
  60991. + goto done;
  60992. +
  60993. + /*
  60994. + * Save the termios structure, since this port may have
  60995. + * separate termios for callout and dialin.
  60996. + */
  60997. + if (state->info->flags & UIF_NORMAL_ACTIVE)
  60998. + state->normal_termios = *tty->termios;
  60999. + if (state->info->flags & UIF_CALLOUT_ACTIVE)
  61000. + state->callout_termios = *tty->termios;
  61001. +
  61002. + /*
  61003. + * Now we wait for the transmit buffer to clear; and we notify
  61004. + * the line discipline to only process XON/XOFF characters by
  61005. + * setting tty->closing.
  61006. + */
  61007. + tty->closing = 1;
  61008. +
  61009. + if (state->closing_wait != USF_CLOSING_WAIT_NONE)
  61010. + tty_wait_until_sent(tty, state->closing_wait);
  61011. +
  61012. + /*
  61013. + * At this point, we stop accepting input. To do this, we
  61014. + * disable the receive line status interrupts.
  61015. + */
  61016. + if (state->info->flags & UIF_INITIALIZED) {
  61017. + unsigned long flags;
  61018. + spin_lock_irqsave(&port->lock, flags);
  61019. + port->ops->stop_rx(port);
  61020. + spin_unlock_irqrestore(&port->lock, flags);
  61021. + /*
  61022. + * Before we drop DTR, make sure the UART transmitter
  61023. + * has completely drained; this is especially
  61024. + * important if there is a transmit FIFO!
  61025. + */
  61026. + uart_wait_until_sent(tty, port->timeout);
  61027. + }
  61028. +
  61029. + uart_shutdown(state);
  61030. + uart_flush_buffer(tty);
  61031. + if (tty->ldisc.flush_buffer)
  61032. + tty->ldisc.flush_buffer(tty);
  61033. + tty->closing = 0;
  61034. + state->info->tty = NULL;
  61035. +
  61036. + if (state->info->blocked_open) {
  61037. + if (state->close_delay) {
  61038. + set_current_state(TASK_INTERRUPTIBLE);
  61039. + schedule_timeout(state->close_delay);
  61040. + set_current_state(TASK_RUNNING);
  61041. + }
  61042. + } else if (!uart_console(port)) {
  61043. + uart_change_pm(state, 3);
  61044. + }
  61045. +
  61046. + /*
  61047. + * Wake up anyone trying to open this port.
  61048. + */
  61049. + state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
  61050. + wake_up_interruptible(&state->info->open_wait);
  61051. +
  61052. + done:
  61053. + up(&state->sem);
  61054. + if (drv->owner)
  61055. + __MOD_DEC_USE_COUNT(drv->owner);
  61056. +}
  61057. +
  61058. +static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
  61059. +{
  61060. + struct uart_state *state = tty->driver_data;
  61061. + struct uart_port *port = state->port;
  61062. + unsigned long char_time, expire;
  61063. +
  61064. + BUG_ON(!kernel_locked());
  61065. +
  61066. + if (port->type == PORT_UNKNOWN || port->fifosize == 0)
  61067. + return;
  61068. +
  61069. + /*
  61070. + * Set the check interval to be 1/5 of the estimated time to
  61071. + * send a single character, and make it at least 1. The check
  61072. + * interval should also be less than the timeout.
  61073. + *
  61074. + * Note: we have to use pretty tight timings here to satisfy
  61075. + * the NIST-PCTS.
  61076. + */
  61077. + char_time = (port->timeout - HZ/50) / port->fifosize;
  61078. + char_time = char_time / 5;
  61079. + if (char_time == 0)
  61080. + char_time = 1;
  61081. + if (timeout && timeout < char_time)
  61082. + char_time = timeout;
  61083. +
  61084. + /*
  61085. + * If the transmitter hasn't cleared in twice the approximate
  61086. + * amount of time to send the entire FIFO, it probably won't
  61087. + * ever clear. This assumes the UART isn't doing flow
  61088. + * control, which is currently the case. Hence, if it ever
  61089. + * takes longer than port->timeout, this is probably due to a
  61090. + * UART bug of some kind. So, we clamp the timeout parameter at
  61091. + * 2*port->timeout.
  61092. + */
  61093. + if (timeout == 0 || timeout > 2 * port->timeout)
  61094. + timeout = 2 * port->timeout;
  61095. +
  61096. + expire = jiffies + timeout;
  61097. +
  61098. + DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
  61099. + port->line, jiffies, expire);
  61100. +
  61101. + /*
  61102. + * Check whether the transmitter is empty every 'char_time'.
  61103. + * 'timeout' / 'expire' give us the maximum amount of time
  61104. + * we wait.
  61105. + */
  61106. + while (!port->ops->tx_empty(port)) {
  61107. + set_current_state(TASK_INTERRUPTIBLE);
  61108. + schedule_timeout(char_time);
  61109. + if (signal_pending(current))
  61110. + break;
  61111. + if (time_after(jiffies, expire))
  61112. + break;
  61113. + }
  61114. + set_current_state(TASK_RUNNING); /* might not be needed */
  61115. +}
  61116. +
  61117. +/*
  61118. + * This is called with the BKL held in
  61119. + * linux/drivers/char/tty_io.c:do_tty_hangup()
  61120. + * We're called from the eventd thread, so we can sleep for
  61121. + * a _short_ time only.
  61122. + */
  61123. +static void uart_hangup(struct tty_struct *tty)
  61124. +{
  61125. + struct uart_state *state = tty->driver_data;
  61126. +
  61127. + BUG_ON(!kernel_locked());
  61128. + DPRINTK("uart_hangup(%d)\n", state->port->line);
  61129. +
  61130. + down(&state->sem);
  61131. + if (state->info && state->info->flags & (UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE)) {
  61132. + uart_flush_buffer(tty);
  61133. + uart_shutdown(state);
  61134. + state->count = 0;
  61135. + state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
  61136. + state->info->tty = NULL;
  61137. + wake_up_interruptible(&state->info->open_wait);
  61138. + wake_up_interruptible(&state->info->delta_msr_wait);
  61139. + }
  61140. + up(&state->sem);
  61141. +}
  61142. +
  61143. +/*
  61144. + * Copy across the serial console cflag setting into the termios settings
  61145. + * for the initial open of the port. This allows continuity between the
  61146. + * kernel settings, and the settings init adopts when it opens the port
  61147. + * for the first time.
  61148. + */
  61149. +static void uart_update_termios(struct uart_state *state)
  61150. +{
  61151. + struct tty_struct *tty = state->info->tty;
  61152. + struct uart_port *port = state->port;
  61153. +
  61154. + if (uart_console(port) && port->cons->cflag) {
  61155. + tty->termios->c_cflag = port->cons->cflag;
  61156. + port->cons->cflag = 0;
  61157. + }
  61158. +
  61159. + /*
  61160. + * If the device failed to grab its irq resources,
  61161. + * or some other error occurred, don't try to talk
  61162. + * to the port hardware.
  61163. + */
  61164. + if (!(tty->flags & (1 << TTY_IO_ERROR))) {
  61165. + /*
  61166. + * Make termios settings take effect.
  61167. + */
  61168. + uart_change_speed(state, NULL);
  61169. +
  61170. + /*
  61171. + * And finally enable the RTS and DTR signals.
  61172. + */
  61173. + if (tty->termios->c_cflag & CBAUD)
  61174. + uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
  61175. + }
  61176. +}
  61177. +
  61178. +/*
  61179. + * Block the open until the port is ready. We must be called with
  61180. + * the per-port semaphore held.
  61181. + */
  61182. +static int
  61183. +uart_block_til_ready(struct file *filp, struct uart_state *state)
  61184. +{
  61185. + DECLARE_WAITQUEUE(wait, current);
  61186. + struct uart_info *info = state->info;
  61187. + struct uart_port *port = state->port;
  61188. + struct termios *termios;
  61189. +
  61190. + /*
  61191. + * If this is a callout device, then just make sure the normal
  61192. + * device isn't being used.
  61193. + */
  61194. + if (info->tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
  61195. + if (info->flags & UIF_NORMAL_ACTIVE)
  61196. + return -EBUSY;
  61197. + if ((info->flags & UIF_CALLOUT_ACTIVE) &&
  61198. + (info->flags & ASYNC_SESSION_LOCKOUT) &&
  61199. + (info->session != current->session))
  61200. + return -EBUSY;
  61201. + if ((info->flags & UIF_CALLOUT_ACTIVE) &&
  61202. + (info->flags & ASYNC_PGRP_LOCKOUT) &&
  61203. + (info->pgrp != current->pgrp))
  61204. + return -EBUSY;
  61205. + info->flags |= UIF_CALLOUT_ACTIVE;
  61206. + return 0;
  61207. + }
  61208. +
  61209. + if (info->flags & UIF_CALLOUT_ACTIVE) {
  61210. + termios = &state->normal_termios;
  61211. + } else {
  61212. + termios = state->info->tty->termios;
  61213. + }
  61214. +
  61215. + info->blocked_open++;
  61216. + state->count--;
  61217. +
  61218. + add_wait_queue(&info->open_wait, &wait);
  61219. + while (1) {
  61220. + set_current_state(TASK_INTERRUPTIBLE);
  61221. +
  61222. + /*
  61223. + * If we have been hung up, tell userspace/restart open.
  61224. + */
  61225. + if (tty_hung_up_p(filp) || info->tty == NULL)
  61226. + break;
  61227. +
  61228. + /*
  61229. + * If the port has been closed, tell userspace/restart open.
  61230. + */
  61231. + if (!(info->flags & UIF_INITIALIZED))
  61232. + break;
  61233. +
  61234. + /*
  61235. + * If non-blocking mode is set, or CLOCAL mode is set,
  61236. + * we don't want to wait for the modem status lines to
  61237. + * indicate that the port is ready.
  61238. + *
  61239. + * Also, if the port is not enabled/configured, we want
  61240. + * to allow the open to succeed here. Note that we will
  61241. + * have set TTY_IO_ERROR for a non-existant port.
  61242. + */
  61243. + if ((filp->f_flags & O_NONBLOCK) ||
  61244. + (termios->c_cflag & CLOCAL) ||
  61245. + (info->tty->flags & (1 << TTY_IO_ERROR))) {
  61246. + break;
  61247. + }
  61248. +
  61249. + if (!(info->flags & UIF_CALLOUT_ACTIVE)) {
  61250. + /*
  61251. + * Set DTR to allow modem to know we're waiting. Do
  61252. + * not set RTS here - we want to make sure we catch
  61253. + * the data from the modem.
  61254. + */
  61255. + if (info->tty->termios->c_cflag & CBAUD)
  61256. + uart_set_mctrl(port, TIOCM_DTR);
  61257. +
  61258. + /*
  61259. + * and wait for the carrier to indicate that the
  61260. + * modem is ready for us.
  61261. + */
  61262. + if (port->ops->get_mctrl(port) & TIOCM_CAR)
  61263. + break;
  61264. + }
  61265. +
  61266. + up(&state->sem);
  61267. + schedule();
  61268. + down(&state->sem);
  61269. +
  61270. + if (signal_pending(current))
  61271. + break;
  61272. + }
  61273. + set_current_state(TASK_RUNNING);
  61274. + remove_wait_queue(&info->open_wait, &wait);
  61275. +
  61276. + state->count++;
  61277. + info->blocked_open--;
  61278. +
  61279. + info->flags |= UIF_NORMAL_ACTIVE;
  61280. +
  61281. + if (signal_pending(current))
  61282. + return -ERESTARTSYS;
  61283. +
  61284. + if (!info->tty || tty_hung_up_p(filp))
  61285. + return -EAGAIN;
  61286. +
  61287. + return 0;
  61288. +}
  61289. +
  61290. +static struct uart_state *uart_get(struct uart_driver *drv, int line)
  61291. +{
  61292. + struct uart_state *state;
  61293. +
  61294. + down(&port_sem);
  61295. + state = drv->state + line;
  61296. + if (down_interruptible(&state->sem)) {
  61297. + state = ERR_PTR(-ERESTARTSYS);
  61298. + goto out;
  61299. + }
  61300. +
  61301. + state->count++;
  61302. + if (!state->port) {
  61303. + state->count--;
  61304. + up(&state->sem);
  61305. + state = ERR_PTR(-ENXIO);
  61306. + goto out;
  61307. + }
  61308. +
  61309. + if (!state->info) {
  61310. + state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
  61311. + if (state->info) {
  61312. + memset(state->info, 0, sizeof(struct uart_info));
  61313. + init_waitqueue_head(&state->info->open_wait);
  61314. + init_waitqueue_head(&state->info->delta_msr_wait);
  61315. +
  61316. + /*
  61317. + * Link the info into the other structures.
  61318. + */
  61319. + state->port->info = state->info;
  61320. +
  61321. + tasklet_init(&state->info->tlet, uart_tasklet_action,
  61322. + (unsigned long)state);
  61323. + } else {
  61324. + state->count--;
  61325. + up(&state->sem);
  61326. + state = ERR_PTR(-ENOMEM);
  61327. + }
  61328. + }
  61329. +
  61330. + out:
  61331. + up(&port_sem);
  61332. + return state;
  61333. +}
  61334. +
  61335. +/*
  61336. + * In 2.4.5, calls to uart_open are serialised by the BKL in
  61337. + * linux/fs/devices.c:chrdev_open()
  61338. + * Note that if this fails, then uart_close() _will_ be called.
  61339. + */
  61340. +static int uart_open(struct tty_struct *tty, struct file *filp)
  61341. +{
  61342. + struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
  61343. + struct uart_state *state;
  61344. + int retval, line = MINOR(tty->device) - tty->driver.minor_start;
  61345. +
  61346. + BUG_ON(!kernel_locked());
  61347. + DPRINTK("uart_open(%d) called\n", line);
  61348. +
  61349. + /*
  61350. + * tty->driver->num won't change, so we won't fail here with
  61351. + * tty->driver_data set to something non-NULL (and therefore
  61352. + * we won't get caught by uart_close()).
  61353. + */
  61354. + retval = -ENODEV;
  61355. + if (line >= tty->driver.num)
  61356. + goto fail;
  61357. +
  61358. + if (!try_inc_mod_count(drv->owner))
  61359. + goto fail;
  61360. +
  61361. + /*
  61362. + * We take the semaphore inside uart_get to guarantee that we won't
  61363. + * be re-entered while allocating the info structure, or while we
  61364. + * request any IRQs that the driver may need. This also has the nice
  61365. + * side-effect that it delays the action of uart_hangup, so we can
  61366. + * guarantee that info->tty will always contain something reasonable.
  61367. + */
  61368. + state = uart_get(drv, line);
  61369. + if (IS_ERR(state)) {
  61370. + retval = PTR_ERR(state);
  61371. + if (!tty->driver_data)
  61372. + goto out;
  61373. + else
  61374. + goto fail;
  61375. + }
  61376. +
  61377. + /*
  61378. + * Once we set tty->driver_data here, we are guaranteed that
  61379. + * uart_close() will decrement the driver module use count.
  61380. + * Any failures from here onwards should not touch the count.
  61381. + */
  61382. + tty->driver_data = state;
  61383. + tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
  61384. + tty->alt_speed = uart_get_altspeed(state->port);
  61385. + state->info->tty = tty;
  61386. +
  61387. + /*
  61388. + * If the port is in the middle of closing, bail out now.
  61389. + */
  61390. + if (tty_hung_up_p(filp)) {
  61391. + retval = -EAGAIN;
  61392. + state->count--;
  61393. + up(&state->sem);
  61394. + goto fail;
  61395. + }
  61396. +
  61397. + /*
  61398. + * Make sure the device is in D0 state.
  61399. + */
  61400. + if (state->count == 1)
  61401. + uart_change_pm(state, 0);
  61402. +
  61403. + /*
  61404. + * Start up the serial port.
  61405. + */
  61406. + retval = uart_startup(state, 0);
  61407. +
  61408. + /*
  61409. + * If we succeeded, wait until the port is ready.
  61410. + */
  61411. + if (retval == 0)
  61412. + retval = uart_block_til_ready(filp, state);
  61413. +
  61414. + /*
  61415. + * If this is the first open to succeed, adjust things to suit.
  61416. + */
  61417. + if (retval == 0 && state->count == 1) {
  61418. + if (state->port->flags & UPF_SPLIT_TERMIOS) {
  61419. + if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
  61420. + *tty->termios = state->normal_termios;
  61421. + else
  61422. + *tty->termios = state->callout_termios;
  61423. + }
  61424. +
  61425. + uart_update_termios(state);
  61426. +
  61427. + state->info->session = current->session;
  61428. + state->info->pgrp = current->pgrp;
  61429. + }
  61430. + up(&state->sem);
  61431. +
  61432. + return 0;
  61433. +
  61434. + out:
  61435. + if (drv->owner)
  61436. + __MOD_DEC_USE_COUNT(drv->owner);
  61437. + fail:
  61438. + return retval;
  61439. +}
  61440. +
  61441. +static const char *uart_type(struct uart_port *port)
  61442. +{
  61443. + const char *str = NULL;
  61444. +
  61445. + if (port->ops->type)
  61446. + str = port->ops->type(port);
  61447. +
  61448. + if (!str)
  61449. + str = "unknown";
  61450. +
  61451. + return str;
  61452. +}
  61453. +
  61454. +#ifdef CONFIG_PROC_FS
  61455. +
  61456. +static int uart_line_info(char *buf, struct uart_driver *drv, int i)
  61457. +{
  61458. + struct uart_state *state = drv->state + i;
  61459. + struct uart_port *port = state->port;
  61460. + char stat_buf[32];
  61461. + unsigned int status;
  61462. + int ret;
  61463. +
  61464. + if (!port)
  61465. + return 0;
  61466. +
  61467. + ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d",
  61468. + port->line, uart_type(port),
  61469. + port->iobase, port->irq);
  61470. +
  61471. + if (port->type == PORT_UNKNOWN) {
  61472. + strcat(buf, "\n");
  61473. + return ret + 1;
  61474. + }
  61475. +
  61476. + status = port->ops->get_mctrl(port);
  61477. +
  61478. + ret += sprintf(buf + ret, " tx:%d rx:%d",
  61479. + port->icount.tx, port->icount.rx);
  61480. + if (port->icount.frame)
  61481. + ret += sprintf(buf + ret, " fe:%d",
  61482. + port->icount.frame);
  61483. + if (port->icount.parity)
  61484. + ret += sprintf(buf + ret, " pe:%d",
  61485. + port->icount.parity);
  61486. + if (port->icount.brk)
  61487. + ret += sprintf(buf + ret, " brk:%d",
  61488. + port->icount.brk);
  61489. + if (port->icount.overrun)
  61490. + ret += sprintf(buf + ret, " oe:%d",
  61491. + port->icount.overrun);
  61492. +
  61493. +#define INFOBIT(bit,str) \
  61494. + if (port->mctrl & (bit)) \
  61495. + strcat(stat_buf, (str))
  61496. +#define STATBIT(bit,str) \
  61497. + if (status & (bit)) \
  61498. + strcat(stat_buf, (str))
  61499. +
  61500. + stat_buf[0] = '\0';
  61501. + stat_buf[1] = '\0';
  61502. + INFOBIT(TIOCM_RTS, "|RTS");
  61503. + STATBIT(TIOCM_CTS, "|CTS");
  61504. + INFOBIT(TIOCM_DTR, "|DTR");
  61505. + STATBIT(TIOCM_DSR, "|DSR");
  61506. + STATBIT(TIOCM_CAR, "|CD");
  61507. + STATBIT(TIOCM_RNG, "|RI");
  61508. + if (stat_buf[0])
  61509. + stat_buf[0] = ' ';
  61510. + strcat(stat_buf, "\n");
  61511. +
  61512. + ret += sprintf(buf + ret, stat_buf);
  61513. + return ret;
  61514. +}
  61515. +
  61516. +static int uart_read_proc(char *page, char **start, off_t off,
  61517. + int count, int *eof, void *data)
  61518. +{
  61519. + struct tty_driver *ttydrv = data;
  61520. + struct uart_driver *drv = ttydrv->driver_state;
  61521. + int i, len = 0, l;
  61522. + off_t begin = 0;
  61523. +
  61524. + len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",
  61525. + "", "", "");
  61526. + for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) {
  61527. + l = uart_line_info(page + len, drv, i);
  61528. + len += l;
  61529. + if (len + begin > off + count)
  61530. + goto done;
  61531. + if (len + begin < off) {
  61532. + begin += len;
  61533. + len = 0;
  61534. + }
  61535. + }
  61536. + *eof = 1;
  61537. + done:
  61538. + if (off >= len + begin)
  61539. + return 0;
  61540. + *start = page + (off - begin);
  61541. + return (count < begin + len - off) ? count : (begin + len - off);
  61542. +}
  61543. +#endif
  61544. +
  61545. +#ifdef CONFIG_SERIAL_CORE_CONSOLE
  61546. +/*
  61547. + * Check whether an invalid uart number has been specified, and
  61548. + * if so, search for the first available port that does have
  61549. + * console support.
  61550. + */
  61551. +struct uart_port * __init
  61552. +uart_get_console(struct uart_port *ports, int nr, struct console *co)
  61553. +{
  61554. + int idx = co->index;
  61555. +
  61556. + if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
  61557. + ports[idx].membase == NULL))
  61558. + for (idx = 0; idx < nr; idx++)
  61559. + if (ports[idx].iobase != 0 ||
  61560. + ports[idx].membase != NULL)
  61561. + break;
  61562. +
  61563. + co->index = idx;
  61564. +
  61565. + return ports + idx;
  61566. +}
  61567. +
  61568. +/**
  61569. + * uart_parse_options - Parse serial port baud/parity/bits/flow contro.
  61570. + * @options: pointer to option string
  61571. + * @baud: pointer to an 'int' variable for the baud rate.
  61572. + * @parity: pointer to an 'int' variable for the parity.
  61573. + * @bits: pointer to an 'int' variable for the number of data bits.
  61574. + * @flow: pointer to an 'int' variable for the flow control character.
  61575. + *
  61576. + * uart_parse_options decodes a string containing the serial console
  61577. + * options. The format of the string is <baud><parity><bits><flow>,
  61578. + * eg: 115200n8r
  61579. + */
  61580. +void __init
  61581. +uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
  61582. +{
  61583. + char *s = options;
  61584. +
  61585. + *baud = simple_strtoul(s, NULL, 10);
  61586. + while (*s >= '0' && *s <= '9')
  61587. + s++;
  61588. + if (*s)
  61589. + *parity = *s++;
  61590. + if (*s)
  61591. + *bits = *s++ - '0';
  61592. + if (*s)
  61593. + *flow = *s;
  61594. +}
  61595. +
  61596. +struct baud_rates {
  61597. + unsigned int rate;
  61598. + unsigned int cflag;
  61599. +};
  61600. +
  61601. +static struct baud_rates baud_rates[] = {
  61602. + { 921600, B921600 },
  61603. + { 460800, B460800 },
  61604. + { 230400, B230400 },
  61605. + { 115200, B115200 },
  61606. + { 57600, B57600 },
  61607. + { 38400, B38400 },
  61608. + { 19200, B19200 },
  61609. + { 9600, B9600 },
  61610. + { 4800, B4800 },
  61611. + { 2400, B2400 },
  61612. + { 1200, B1200 },
  61613. + { 0, B38400 }
  61614. +};
  61615. +
  61616. +/**
  61617. + * uart_set_options - setup the serial console parameters
  61618. + * @port: pointer to the serial ports uart_port structure
  61619. + * @co: console pointer
  61620. + * @baud: baud rate
  61621. + * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
  61622. + * @bits: number of data bits
  61623. + * @flow: flow control character - 'r' (rts)
  61624. + */
  61625. +int __init
  61626. +uart_set_options(struct uart_port *port, struct console *co,
  61627. + int baud, int parity, int bits, int flow)
  61628. +{
  61629. + struct termios termios;
  61630. + unsigned int quot;
  61631. + int i;
  61632. +
  61633. + memset(&termios, 0, sizeof(struct termios));
  61634. +
  61635. + termios.c_cflag = CREAD | HUPCL | CLOCAL;
  61636. +
  61637. + /*
  61638. + * Construct a cflag setting.
  61639. + */
  61640. + for (i = 0; baud_rates[i].rate; i++)
  61641. + if (baud_rates[i].rate <= baud)
  61642. + break;
  61643. +
  61644. + termios.c_cflag |= baud_rates[i].cflag;
  61645. + baud = baud_rates[i].rate;
  61646. + if (baud == 0)
  61647. + baud = 38400;
  61648. +
  61649. + if (bits == 7)
  61650. + termios.c_cflag |= CS7;
  61651. + else
  61652. + termios.c_cflag |= CS8;
  61653. +
  61654. + switch (parity) {
  61655. + case 'o': case 'O':
  61656. + termios.c_cflag |= PARODD;
  61657. + /*fall through*/
  61658. + case 'e': case 'E':
  61659. + termios.c_cflag |= PARENB;
  61660. + break;
  61661. + }
  61662. +
  61663. + if (flow == 'r')
  61664. + termios.c_cflag |= CRTSCTS;
  61665. +
  61666. + quot = (port->uartclk / (16 * baud));
  61667. + port->ops->change_speed(port, termios.c_cflag, 0, quot);
  61668. + co->cflag = termios.c_cflag;
  61669. +
  61670. + return 0;
  61671. +}
  61672. +
  61673. +extern void ambauart_console_init(void);
  61674. +extern void anakin_console_init(void);
  61675. +extern void clps711xuart_console_init(void);
  61676. +extern void sa1100_rs_console_init(void);
  61677. +extern void serial8250_console_init(void);
  61678. +extern void at91_console_init(void);
  61679. +
  61680. +/*
  61681. + * Central "initialise all serial consoles" container. Needs to be killed.
  61682. + */
  61683. +void __init uart_console_init(void)
  61684. +{
  61685. +#ifdef CONFIG_SERIAL_AMBA_CONSOLE
  61686. + ambauart_console_init();
  61687. +#endif
  61688. +#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
  61689. + anakin_console_init();
  61690. +#endif
  61691. +#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
  61692. + clps711xuart_console_init();
  61693. +#endif
  61694. +#ifdef CONFIG_SERIAL_SA1100_CONSOLE
  61695. + sa1100_rs_console_init();
  61696. +#endif
  61697. +#ifdef CONFIG_SERIAL_AT91_CONSOLE
  61698. + at91_console_init();
  61699. +#endif
  61700. +#ifdef CONFIG_SERIAL_8250_CONSOLE
  61701. + serial8250_console_init();
  61702. +#endif
  61703. +#ifdef CONFIG_SERIAL_UART00_CONSOLE
  61704. + uart00_console_init();
  61705. +#endif
  61706. +}
  61707. +#endif /* CONFIG_SERIAL_CORE_CONSOLE */
  61708. +
  61709. +static void uart_change_pm(struct uart_state *state, int pm_state)
  61710. +{
  61711. + struct uart_port *port = state->port;
  61712. + if (port->ops->pm)
  61713. + port->ops->pm(port, pm_state, 0);
  61714. +}
  61715. +
  61716. +#ifdef CONFIG_PM
  61717. +int uart_suspend_port(struct uart_state *state)
  61718. +{
  61719. + struct uart_port *port = state->port;
  61720. +
  61721. + down(&state->sem);
  61722. + if (port) {
  61723. + /*
  61724. + * Disable the console device before suspending.
  61725. + */
  61726. + if (uart_console(port))
  61727. + port->cons->flags &= ~CON_ENABLED;
  61728. +
  61729. + if (state->info && state->info->flags & UIF_INITIALIZED) {
  61730. + struct uart_ops *ops = port->ops;
  61731. +
  61732. + spin_lock_irq(&port->lock);
  61733. + ops->stop_tx(port, 0);
  61734. + ops->set_mctrl(port, 0);
  61735. + ops->stop_rx(port);
  61736. + spin_unlock_irq(&port->lock);
  61737. +
  61738. + /*
  61739. + * Wait for the transmitter to empty.
  61740. + */
  61741. + while (!ops->tx_empty(port)) {
  61742. + set_current_state(TASK_UNINTERRUPTIBLE);
  61743. + schedule_timeout(10*HZ/1000);
  61744. + }
  61745. + set_current_state(TASK_RUNNING);
  61746. +
  61747. + ops->shutdown(port);
  61748. + }
  61749. +
  61750. + uart_change_pm(state, 3);
  61751. + }
  61752. +
  61753. + up(&state->sem);
  61754. +
  61755. + return 0;
  61756. +}
  61757. +
  61758. +int uart_resume_port(struct uart_state *state)
  61759. +{
  61760. + struct uart_port *port = state->port;
  61761. +
  61762. + down(&state->sem);
  61763. + if (port) {
  61764. + uart_change_pm(state, 0);
  61765. +
  61766. + /*
  61767. + * Re-enable the console device after suspending.
  61768. + */
  61769. + if (uart_console(port)) {
  61770. + uart_change_speed(state, NULL);
  61771. + port->cons->flags |= CON_ENABLED;
  61772. + }
  61773. +
  61774. + if (state->info && state->info->flags & UIF_INITIALIZED) {
  61775. + struct uart_ops *ops = port->ops;
  61776. +
  61777. + ops->set_mctrl(port, 0);
  61778. + ops->startup(port);
  61779. + uart_change_speed(state, NULL);
  61780. + spin_lock_irq(&port->lock);
  61781. + ops->set_mctrl(port, port->mctrl);
  61782. + ops->start_tx(port, 0);
  61783. + spin_unlock_irq(&port->lock);
  61784. + }
  61785. + }
  61786. +
  61787. + up(&state->sem);
  61788. +
  61789. + return 0;
  61790. +}
  61791. +
  61792. +/*
  61793. + * Wakeup support.
  61794. + */
  61795. +static int uart_pm_set_wakeup(struct uart_state *state, int data)
  61796. +{
  61797. + int err = 0;
  61798. +
  61799. + if (state->port->ops->set_wake)
  61800. + err = state->port->ops->set_wake(state->port, data);
  61801. +
  61802. + return err;
  61803. +}
  61804. +
  61805. +static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
  61806. +{
  61807. + struct uart_state *state = dev->data;
  61808. + int err = 0;
  61809. +
  61810. + if (state->port && state->port->type == PORT_UNKNOWN)
  61811. + return 0;
  61812. +
  61813. + switch (rqst) {
  61814. + case PM_SUSPEND:
  61815. + err = uart_suspend_port(state);
  61816. + break;
  61817. +
  61818. + case PM_RESUME:
  61819. + err = uart_resume_port(state);
  61820. + break;
  61821. +
  61822. + case PM_SET_WAKEUP:
  61823. + err = uart_pm_set_wakeup(state, (int)data);
  61824. + break;
  61825. + }
  61826. + return err;
  61827. +}
  61828. +#endif
  61829. +
  61830. +static inline void
  61831. +uart_report_port(struct uart_driver *drv, struct uart_port *port)
  61832. +{
  61833. + printk("%s%d at ", drv->normal_name, port->line);
  61834. + switch (port->iotype) {
  61835. + case UPIO_PORT:
  61836. + printk("I/O 0x%x", port->iobase);
  61837. + break;
  61838. + case UPIO_HUB6:
  61839. + printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
  61840. + break;
  61841. + case UPIO_MEM:
  61842. + printk("MMIO 0x%lx", port->mapbase);
  61843. + break;
  61844. + }
  61845. + printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
  61846. +}
  61847. +
  61848. +static void
  61849. +uart_configure_port(struct uart_driver *drv, struct uart_state *state,
  61850. + struct uart_port *port)
  61851. +{
  61852. + unsigned int flags;
  61853. +
  61854. + /*
  61855. + * If there isn't a port here, don't do anything further.
  61856. + */
  61857. + if (!port->iobase && !port->mapbase && !port->membase)
  61858. + return;
  61859. +
  61860. + /*
  61861. + * Now do the auto configuration stuff. Note that config_port
  61862. + * is expected to claim the resources and map the port for us.
  61863. + */
  61864. + flags = UART_CONFIG_TYPE;
  61865. + if (port->flags & UPF_AUTO_IRQ)
  61866. + flags |= UART_CONFIG_IRQ;
  61867. + if (port->flags & UPF_BOOT_AUTOCONF) {
  61868. + port->type = PORT_UNKNOWN;
  61869. + port->ops->config_port(port, flags);
  61870. + }
  61871. +
  61872. + if (port->type != PORT_UNKNOWN) {
  61873. + unsigned long flags;
  61874. +
  61875. + uart_report_port(drv, port);
  61876. +
  61877. + /*
  61878. + * Ensure that the modem control lines are de-activated.
  61879. + * We probably don't need a spinlock around this, but
  61880. + */
  61881. + spin_lock_irqsave(&port->lock, flags);
  61882. + port->ops->set_mctrl(port, 0);
  61883. + spin_unlock_irqrestore(&port->lock, flags);
  61884. +
  61885. + /*
  61886. + * Power down all ports by default, except the
  61887. + * console if we have one.
  61888. + */
  61889. + if (!uart_console(port))
  61890. + uart_change_pm(state, 3);
  61891. + }
  61892. +}
  61893. +
  61894. +/*
  61895. + * This reverses the effects of uart_configure_port, hanging up the
  61896. + * port before removal.
  61897. + */
  61898. +static void
  61899. +uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
  61900. +{
  61901. + struct uart_port *port = state->port;
  61902. + struct uart_info *info = state->info;
  61903. +
  61904. + if (info && info->tty)
  61905. + tty_vhangup(info->tty);
  61906. +
  61907. + down(&state->sem);
  61908. +
  61909. + state->info = NULL;
  61910. +
  61911. + /*
  61912. + * Free the port IO and memory resources, if any.
  61913. + */
  61914. + if (port->type != PORT_UNKNOWN)
  61915. + port->ops->release_port(port);
  61916. +
  61917. + /*
  61918. + * Indicate that there isn't a port here anymore.
  61919. + */
  61920. + port->type = PORT_UNKNOWN;
  61921. +
  61922. + /*
  61923. + * Kill the tasklet, and free resources.
  61924. + */
  61925. + if (info) {
  61926. + tasklet_kill(&info->tlet);
  61927. + kfree(info);
  61928. + }
  61929. +
  61930. + up(&state->sem);
  61931. +}
  61932. +
  61933. +/**
  61934. + * uart_register_driver - register a driver with the uart core layer
  61935. + * @drv: low level driver structure
  61936. + *
  61937. + * Register a uart driver with the core driver. We in turn register
  61938. + * with the tty layer, and initialise the core driver per-port state.
  61939. + *
  61940. + * We have a proc file in /proc/tty/driver which is named after the
  61941. + * normal driver.
  61942. + *
  61943. + * drv->port should be NULL, and the per-port structures should be
  61944. + * registered using uart_add_one_port after this call has succeeded.
  61945. + */
  61946. +int uart_register_driver(struct uart_driver *drv)
  61947. +{
  61948. + struct tty_driver *normal, *callout;
  61949. + int i, retval;
  61950. +
  61951. + BUG_ON(drv->state);
  61952. +
  61953. + /*
  61954. + * Maybe we should be using a slab cache for this, especially if
  61955. + * we have a large number of ports to handle. Note that we also
  61956. + * allocate space for an integer for reference counting.
  61957. + */
  61958. + drv->state = kmalloc(sizeof(struct uart_state) * drv->nr +
  61959. + sizeof(int), GFP_KERNEL);
  61960. + retval = -ENOMEM;
  61961. + if (!drv->state)
  61962. + goto out;
  61963. +
  61964. + memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +
  61965. + sizeof(int));
  61966. +
  61967. + normal = drv->normal_driver;
  61968. + callout = drv->callout_driver;
  61969. +
  61970. + normal->magic = TTY_DRIVER_MAGIC;
  61971. + normal->driver_name = drv->normal_name;
  61972. + normal->name = drv->normal_name;
  61973. + normal->major = drv->normal_major;
  61974. + normal->minor_start = drv->minor;
  61975. + normal->num = drv->nr;
  61976. + normal->type = TTY_DRIVER_TYPE_SERIAL;
  61977. + normal->subtype = SERIAL_TYPE_NORMAL;
  61978. + normal->init_termios = tty_std_termios;
  61979. + normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  61980. + normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
  61981. + normal->refcount = (int *)(drv->state + drv->nr);
  61982. + normal->table = drv->table;
  61983. + normal->termios = drv->termios;
  61984. + normal->termios_locked = drv->termios_locked;
  61985. + normal->driver_state = drv;
  61986. +
  61987. + normal->open = uart_open;
  61988. + normal->close = uart_close;
  61989. + normal->write = uart_write;
  61990. + normal->put_char = uart_put_char;
  61991. + normal->flush_chars = uart_flush_chars;
  61992. + normal->write_room = uart_write_room;
  61993. + normal->chars_in_buffer = uart_chars_in_buffer;
  61994. + normal->flush_buffer = uart_flush_buffer;
  61995. + normal->ioctl = uart_ioctl;
  61996. + normal->throttle = uart_throttle;
  61997. + normal->unthrottle = uart_unthrottle;
  61998. + normal->send_xchar = uart_send_xchar;
  61999. + normal->set_termios = uart_set_termios;
  62000. + normal->stop = uart_stop;
  62001. + normal->start = uart_start;
  62002. + normal->hangup = uart_hangup;
  62003. + normal->break_ctl = uart_break_ctl;
  62004. + normal->wait_until_sent = uart_wait_until_sent;
  62005. +#ifdef CONFIG_PROC_FS
  62006. + normal->read_proc = uart_read_proc;
  62007. +#endif
  62008. +
  62009. + /*
  62010. + * The callout device is just like the normal device except for
  62011. + * the major number and the subtype code.
  62012. + */
  62013. + *callout = *normal;
  62014. + callout->name = drv->callout_name;
  62015. + callout->major = drv->callout_major;
  62016. + callout->subtype = SERIAL_TYPE_CALLOUT;
  62017. + callout->read_proc = NULL;
  62018. + callout->proc_entry = NULL;
  62019. +
  62020. + /*
  62021. + * Initialise the UART state(s).
  62022. + */
  62023. + for (i = 0; i < drv->nr; i++) {
  62024. + struct uart_state *state = drv->state + i;
  62025. +
  62026. + state->callout_termios = callout->init_termios;
  62027. + state->normal_termios = normal->init_termios;
  62028. + state->close_delay = 5 * HZ / 10;
  62029. + state->closing_wait = 30 * HZ;
  62030. +
  62031. + init_MUTEX(&state->sem);
  62032. + }
  62033. +
  62034. + retval = tty_register_driver(normal);
  62035. + if (retval)
  62036. + goto out;
  62037. +
  62038. + retval = tty_register_driver(callout);
  62039. + if (retval)
  62040. + tty_unregister_driver(normal);
  62041. +
  62042. + out:
  62043. + if (retval < 0) {
  62044. + kfree(drv->state);
  62045. + }
  62046. + return retval;
  62047. +}
  62048. +
  62049. +/**
  62050. + * uart_unregister_driver - remove a driver from the uart core layer
  62051. + * @drv: low level driver structure
  62052. + *
  62053. + * Remove all references to a driver from the core driver. The low
  62054. + * level driver must have removed all its ports via the
  62055. + * uart_remove_one_port() if it registered them with uart_add_one_port().
  62056. + * (ie, drv->port == NULL)
  62057. + */
  62058. +void uart_unregister_driver(struct uart_driver *drv)
  62059. +{
  62060. + tty_unregister_driver(drv->normal_driver);
  62061. + tty_unregister_driver(drv->callout_driver);
  62062. +
  62063. + kfree(drv->state);
  62064. + drv->state = NULL;
  62065. +}
  62066. +
  62067. +/**
  62068. + * uart_add_one_port - attach a driver-defined port structure
  62069. + * @drv: pointer to the uart low level driver structure for this port
  62070. + * @port: uart port structure to use for this port.
  62071. + *
  62072. + * This allows the driver to register its own uart_port structure
  62073. + * with the core driver. The main purpose is to allow the low
  62074. + * level uart drivers to expand uart_port, rather than having yet
  62075. + * more levels of structures.
  62076. + */
  62077. +int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
  62078. +{
  62079. + struct uart_state *state;
  62080. + int ret = 0;
  62081. +
  62082. + BUG_ON(in_interrupt());
  62083. +
  62084. + if (port->line >= drv->nr)
  62085. + return -EINVAL;
  62086. +
  62087. + state = drv->state + port->line;
  62088. +
  62089. + down(&port_sem);
  62090. + if (state->port) {
  62091. + ret = -EINVAL;
  62092. + goto out;
  62093. + }
  62094. +
  62095. + state->port = port;
  62096. +
  62097. + spin_lock_init(&port->lock);
  62098. + port->cons = drv->cons;
  62099. + port->info = state->info;
  62100. +
  62101. + uart_configure_port(drv, state, port);
  62102. +
  62103. + /*
  62104. + * Register the port whether it's detected or not. This allows
  62105. + * setserial to be used to alter this ports parameters.
  62106. + */
  62107. + tty_register_devfs(drv->normal_driver, 0, drv->minor + port->line);
  62108. + tty_register_devfs(drv->callout_driver, 0, drv->minor + port->line);
  62109. +
  62110. +#ifdef CONFIG_PM
  62111. + port->cons = drv->cons;
  62112. + state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
  62113. + if (state->pm)
  62114. + state->pm->data = state;
  62115. +#endif
  62116. +
  62117. + out:
  62118. + up(&port_sem);
  62119. +
  62120. + return ret;
  62121. +}
  62122. +
  62123. +/**
  62124. + * uart_remove_one_port - detach a driver defined port structure
  62125. + * @drv: pointer to the uart low level driver structure for this port
  62126. + * @port: uart port structure for this port
  62127. + *
  62128. + * This unhooks (and hangs up) the specified port structure from the
  62129. + * core driver. No further calls will be made to the low-level code
  62130. + * for this port.
  62131. + */
  62132. +int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
  62133. +{
  62134. + struct uart_state *state = drv->state + port->line;
  62135. +
  62136. + BUG_ON(in_interrupt());
  62137. +
  62138. + if (state->port != port)
  62139. + printk(KERN_ALERT "Removing wrong port: %p != %p\n",
  62140. + state->port, port);
  62141. +
  62142. + down(&port_sem);
  62143. +
  62144. + pm_unregister(state->pm);
  62145. +
  62146. + /*
  62147. + * Remove the devices from devfs
  62148. + */
  62149. + tty_unregister_devfs(drv->normal_driver, drv->minor + port->line);
  62150. + tty_unregister_devfs(drv->callout_driver, drv->minor + port->line);
  62151. +
  62152. + uart_unconfigure_port(drv, state);
  62153. + state->port = NULL;
  62154. + up(&port_sem);
  62155. +
  62156. + return 0;
  62157. +}
  62158. +
  62159. +/*
  62160. + * Are the two ports equivalent?
  62161. + */
  62162. +static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
  62163. +{
  62164. + if (port1->iotype != port2->iotype)
  62165. + return 0;
  62166. +
  62167. + switch (port1->iotype) {
  62168. + case UPIO_PORT:
  62169. + return (port1->iobase == port2->iobase);
  62170. + case UPIO_HUB6:
  62171. + return (port1->iobase == port2->iobase) &&
  62172. + (port1->hub6 == port2->hub6);
  62173. + case UPIO_MEM:
  62174. + return (port1->membase == port2->membase);
  62175. + }
  62176. + return 0;
  62177. +}
  62178. +
  62179. +/*
  62180. + * Try to find an unused uart_state slot for a port.
  62181. + */
  62182. +static struct uart_state *
  62183. +uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port)
  62184. +{
  62185. + int i;
  62186. +
  62187. + /*
  62188. + * First, find a port entry which matches. Note: if we do
  62189. + * find a matching entry, and it has a non-zero use count,
  62190. + * then we can't register the port.
  62191. + */
  62192. + for (i = 0; i < drv->nr; i++)
  62193. + if (uart_match_port(drv->state[i].port, port))
  62194. + return &drv->state[i];
  62195. +
  62196. + /*
  62197. + * We didn't find a matching entry, so look for the first
  62198. + * free entry. We look for one which hasn't been previously
  62199. + * used (indicated by zero iobase).
  62200. + */
  62201. + for (i = 0; i < drv->nr; i++)
  62202. + if (drv->state[i].port->type == PORT_UNKNOWN &&
  62203. + drv->state[i].port->iobase == 0 &&
  62204. + drv->state[i].count == 0)
  62205. + return &drv->state[i];
  62206. +
  62207. + /*
  62208. + * That also failed. Last resort is to find any currently
  62209. + * entry which doesn't have a real port associated with it.
  62210. + */
  62211. + for (i = 0; i < drv->nr; i++)
  62212. + if (drv->state[i].port->type == PORT_UNKNOWN &&
  62213. + drv->state[i].count == 0)
  62214. + return &drv->state[i];
  62215. +
  62216. + return NULL;
  62217. +}
  62218. +
  62219. +/**
  62220. + * uart_register_port: register uart settings with a port
  62221. + * @drv: pointer to the uart low level driver structure for this port
  62222. + * @port: uart port structure describing the port
  62223. + *
  62224. + * Register UART settings with the specified low level driver. Detect
  62225. + * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the
  62226. + * IRQ if UPF_AUTO_IRQ is set.
  62227. + *
  62228. + * We try to pick the same port for the same IO base address, so that
  62229. + * when a modem is plugged in, unplugged and plugged back in, it gets
  62230. + * allocated the same port.
  62231. + *
  62232. + * Returns negative error, or positive line number.
  62233. + */
  62234. +int uart_register_port(struct uart_driver *drv, struct uart_port *port)
  62235. +{
  62236. + struct uart_state *state;
  62237. + int ret;
  62238. +
  62239. + down(&port_sem);
  62240. +
  62241. + state = uart_find_match_or_unused(drv, port);
  62242. +
  62243. + if (state) {
  62244. + /*
  62245. + * Ok, we've found a line that we can use.
  62246. + *
  62247. + * If we find a port that matches this one, and it appears
  62248. + * to be in-use (even if it doesn't have a type) we shouldn't
  62249. + * alter it underneath itself - the port may be open and
  62250. + * trying to do useful work.
  62251. + */
  62252. + if (uart_users(state) != 0) {
  62253. + ret = -EBUSY;
  62254. + goto out;
  62255. + }
  62256. +
  62257. + /*
  62258. + * If the port is already initialised, don't touch it.
  62259. + */
  62260. + if (state->port->type == PORT_UNKNOWN) {
  62261. + state->port->iobase = port->iobase;
  62262. + state->port->membase = port->membase;
  62263. + state->port->irq = port->irq;
  62264. + state->port->uartclk = port->uartclk;
  62265. + state->port->fifosize = port->fifosize;
  62266. + state->port->regshift = port->regshift;
  62267. + state->port->iotype = port->iotype;
  62268. + state->port->flags = port->flags;
  62269. + state->port->line = state - drv->state;
  62270. + state->port->mapbase = port->mapbase;
  62271. +
  62272. + uart_configure_port(drv, state, state->port);
  62273. + }
  62274. +
  62275. + ret = state->port->line;
  62276. + } else
  62277. + ret = -ENOSPC;
  62278. + out:
  62279. + up(&port_sem);
  62280. + return ret;
  62281. +}
  62282. +
  62283. +/**
  62284. + * uart_unregister_port - de-allocate a port
  62285. + * @drv: pointer to the uart low level driver structure for this port
  62286. + * @line: line index previously returned from uart_register_port()
  62287. + *
  62288. + * Hang up the specified line associated with the low level driver,
  62289. + * and mark the port as unused.
  62290. + */
  62291. +void uart_unregister_port(struct uart_driver *drv, int line)
  62292. +{
  62293. + struct uart_state *state;
  62294. +
  62295. + if (line < 0 || line >= drv->nr) {
  62296. + printk(KERN_ERR "Attempt to unregister %s%d\n",
  62297. + drv->normal_name, line);
  62298. + return;
  62299. + }
  62300. +
  62301. + state = drv->state + line;
  62302. +
  62303. + down(&port_sem);
  62304. + uart_unconfigure_port(drv, state);
  62305. + up(&port_sem);
  62306. +}
  62307. +
  62308. +EXPORT_SYMBOL(uart_write_wakeup);
  62309. +EXPORT_SYMBOL(uart_register_driver);
  62310. +EXPORT_SYMBOL(uart_unregister_driver);
  62311. +EXPORT_SYMBOL(uart_register_port);
  62312. +EXPORT_SYMBOL(uart_unregister_port);
  62313. +EXPORT_SYMBOL(uart_add_one_port);
  62314. +EXPORT_SYMBOL(uart_remove_one_port);
  62315. +
  62316. +MODULE_DESCRIPTION("Serial driver core");
  62317. +MODULE_LICENSE("GPL");
  62318. diff -urN linux-2.4.26/drivers/serial/omaha.c linux-2.4.26-vrs1/drivers/serial/omaha.c
  62319. --- linux-2.4.26/drivers/serial/omaha.c 1970-01-01 01:00:00.000000000 +0100
  62320. +++ linux-2.4.26-vrs1/drivers/serial/omaha.c 2004-01-14 21:32:26.000000000 +0000
  62321. @@ -0,0 +1,584 @@
  62322. +/*
  62323. + * linux/drivers/char/omaha.c
  62324. + *
  62325. + * Driver for Omaha serial port
  62326. + *
  62327. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  62328. + *
  62329. + * Copyright 1999-2002 ARM Limited
  62330. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  62331. + *
  62332. + * This program is free software; you can redistribute it and/or modify
  62333. + * it under the terms of the GNU General Public License as published by
  62334. + * the Free Software Foundation; either version 2 of the License, or
  62335. + * (at your option) any later version.
  62336. + *
  62337. + * This program is distributed in the hope that it will be useful,
  62338. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  62339. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  62340. + * GNU General Public License for more details.
  62341. + *
  62342. + * You should have received a copy of the GNU General Public License
  62343. + * along with this program; if not, write to the Free Software
  62344. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  62345. + *
  62346. + * $Id: serial_amba.c,v 1.4 2001/07/17 20:34:27 rmk Exp $
  62347. + *
  62348. + * This is a generic driver for ARM AMBA-type serial ports. They
  62349. + * have a lot of 16550-like features, but are not register compatable.
  62350. + * Note that although they do have CTS, DCD and DSR inputs, they do
  62351. + * not have an RI input, nor do they have DTR or RTS outputs. If
  62352. + * required, these have to be supplied via some other means (eg, GPIO)
  62353. + * and hooked into this driver.
  62354. + */
  62355. +
  62356. +#include <linux/config.h>
  62357. +#include <linux/module.h>
  62358. +#include <linux/errno.h>
  62359. +#include <linux/signal.h>
  62360. +#include <linux/sched.h>
  62361. +#include <linux/interrupt.h>
  62362. +#include <linux/tty.h>
  62363. +#include <linux/tty_flip.h>
  62364. +#include <linux/major.h>
  62365. +#include <linux/string.h>
  62366. +#include <linux/fcntl.h>
  62367. +#include <linux/ptrace.h>
  62368. +#include <linux/ioport.h>
  62369. +#include <linux/mm.h>
  62370. +#include <linux/slab.h>
  62371. +#include <linux/init.h>
  62372. +#include <linux/circ_buf.h>
  62373. +#include <linux/serial.h>
  62374. +#include <linux/console.h>
  62375. +#include <linux/sysrq.h>
  62376. +
  62377. +#include <asm/system.h>
  62378. +#include <asm/io.h>
  62379. +#include <asm/irq.h>
  62380. +#include <asm/uaccess.h>
  62381. +#include <asm/bitops.h>
  62382. +
  62383. +#if defined(CONFIG_SERIAL_OMAHA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  62384. +#define SUPPORT_SYSRQ
  62385. +#endif
  62386. +
  62387. +#include <linux/serial_core.h>
  62388. +
  62389. +#include <asm/hardware/serial_omaha.h>
  62390. +
  62391. +#define UART_NR 1
  62392. +
  62393. +#define SERIAL_OMAHA_MAJOR 204
  62394. +#define SERIAL_OMAHA_MINOR 32
  62395. +#define SERIAL_OMAHA_NR UART_NR
  62396. +
  62397. +#define CALLOUT_OMAHA_NAME "cuaom"
  62398. +#define CALLOUT_OMAHA_MAJOR 205
  62399. +#define CALLOUT_OMAHA_MINOR 32
  62400. +#define CALLOUT_OMAHA_NR UART_NR
  62401. +
  62402. +static struct tty_driver normal, callout;
  62403. +static struct tty_struct *omaha_table[UART_NR];
  62404. +static struct termios *omaha_termios[UART_NR], *omaha_termios_locked[UART_NR];
  62405. +#ifdef SUPPORT_SYSRQ
  62406. +static struct console omaha_console;
  62407. +#endif
  62408. +
  62409. +#define OMAHA_ISR_PASS_LIMIT 256
  62410. +
  62411. +/*
  62412. + * Access macros for the Omaha UARTs
  62413. + */
  62414. +
  62415. +#define UART_GET_FR(p) readb((p)->membase + OMAHA_UTRSTAT)
  62416. +#define UART_GET_CHAR(p) readb((p)->membase + OMAHA_URXH)
  62417. +#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + OMAHA_UTXH)
  62418. +#define UART_GET_RSR(p) readb((p)->membase + OMAHA_UERSTAT)
  62419. +#define UART_FIFO_STATUS(p) (readl((p)->membase + OMAHA_UFSTAT))
  62420. +#define UART_RX_DATA(s) (((s) & OMAHA_RXFF_CNT) != 0)
  62421. +#define UART_TX_DATA(s) (!((s) & OMAHA_TXFF))
  62422. +#define UART_TX_READY(s) (((s) & OMAHA_UTX_EMPTY))
  62423. +#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & OMAHA_UTXEMPTY) != 0)
  62424. +
  62425. +#define UART_DUMMY_RSR_RX 256
  62426. +#define UART_PORT_SIZE 64
  62427. +
  62428. +#define RX_IRQ(port) ((port)->irq)
  62429. +#define TX_IRQ(port) ((port)->irq + 5)
  62430. +
  62431. +/*
  62432. + * Our private driver data mappings.
  62433. + */
  62434. +#define drv_old_status driver_priv
  62435. +
  62436. +static void omahauart_stop_tx(struct uart_port *port, u_int from_tty)
  62437. +{
  62438. + disable_irq(TX_IRQ(port));
  62439. +}
  62440. +
  62441. +static void omahauart_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
  62442. +{
  62443. + if (nonempty)
  62444. + enable_irq(TX_IRQ(port));
  62445. +}
  62446. +
  62447. +static void omahauart_stop_rx(struct uart_port *port)
  62448. +{
  62449. + disable_irq(RX_IRQ(port));
  62450. +}
  62451. +
  62452. +static void omahauart_enable_ms(struct uart_port *port)
  62453. +{
  62454. + // Do nothing...
  62455. +}
  62456. +
  62457. +static void
  62458. +#ifdef SUPPORT_SYSRQ
  62459. +omahauart_rx_chars(struct uart_info *info, struct pt_regs *regs)
  62460. +#else
  62461. +omahauart_rx_chars(struct uart_info *info)
  62462. +#endif
  62463. +{
  62464. + struct tty_struct *tty = info->tty;
  62465. + volatile unsigned int status, data, ch, rsr, max_count = 256;
  62466. + struct uart_port *port = info->port;
  62467. +
  62468. + status = UART_FIFO_STATUS(port);
  62469. + while (UART_RX_DATA(status) && max_count--) {
  62470. + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
  62471. + tty->flip.tqueue.routine((void *)tty);
  62472. + if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
  62473. + printk(KERN_WARNING "TTY_DONT_FLIP set\n");
  62474. + return;
  62475. + }
  62476. + }
  62477. +
  62478. + ch = UART_GET_CHAR(port);
  62479. +
  62480. + *tty->flip.char_buf_ptr = ch;
  62481. + *tty->flip.flag_buf_ptr = TTY_NORMAL;
  62482. + port->icount.rx++;
  62483. +
  62484. + /*
  62485. + * Note that the error handling code is
  62486. + * out of the main execution path
  62487. + */
  62488. + rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
  62489. + if (rsr & 0xf) {
  62490. + if (rsr & OMAHA_UART_BREAK) {
  62491. + rsr &= ~(OMAHA_UART_FRAME | OMAHA_UART_PARITY);
  62492. + port->icount.brk++;
  62493. + if (uart_handle_break(info, &omaha_console))
  62494. + goto ignore_char;
  62495. + } else if (rsr & OMAHA_UART_PARITY)
  62496. + port->icount.parity++;
  62497. + else if (rsr & OMAHA_UART_FRAME)
  62498. + port->icount.frame++;
  62499. + if (rsr & OMAHA_UART_OVERRUN)
  62500. + port->icount.overrun++;
  62501. +
  62502. + rsr &= port->read_status_mask;
  62503. +
  62504. + if (rsr & OMAHA_UART_BREAK)
  62505. + *tty->flip.flag_buf_ptr = TTY_BREAK;
  62506. + else if (rsr & OMAHA_UART_PARITY)
  62507. + *tty->flip.flag_buf_ptr = TTY_PARITY;
  62508. + else if (rsr & OMAHA_UART_FRAME)
  62509. + *tty->flip.flag_buf_ptr = TTY_FRAME;
  62510. + }
  62511. +
  62512. + if (uart_handle_sysrq_char(info, ch, regs))
  62513. + goto ignore_char;
  62514. +
  62515. + if ((rsr & port->ignore_status_mask) == 0) {
  62516. + tty->flip.flag_buf_ptr++;
  62517. + tty->flip.char_buf_ptr++;
  62518. + tty->flip.count++;
  62519. + }
  62520. + if ((rsr & OMAHA_UART_OVERRUN) &&
  62521. + tty->flip.count < TTY_FLIPBUF_SIZE) {
  62522. + /*
  62523. + * Overrun is special, since it's reported
  62524. + * immediately, and doesn't affect the current
  62525. + * character
  62526. + */
  62527. + *tty->flip.char_buf_ptr++ = 0;
  62528. + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
  62529. + tty->flip.count++;
  62530. + }
  62531. + ignore_char:
  62532. + status = UART_FIFO_STATUS(port);
  62533. + }
  62534. + tty_flip_buffer_push(tty);
  62535. + return;
  62536. +}
  62537. +
  62538. +static void omahauart_tx_chars(struct uart_info *info)
  62539. +{
  62540. + struct uart_port *port = info->port;
  62541. + volatile unsigned int status;
  62542. +
  62543. + if (port->x_char) {
  62544. + UART_PUT_CHAR(port, port->x_char);
  62545. + port->icount.tx++;
  62546. + port->x_char = 0;
  62547. + return;
  62548. + }
  62549. + if (info->xmit.head == info->xmit.tail
  62550. + || info->tty->stopped
  62551. + || info->tty->hw_stopped) {
  62552. + omahauart_stop_tx(port, 0);
  62553. + return;
  62554. + }
  62555. +
  62556. + status = UART_FIFO_STATUS(info->port);
  62557. +
  62558. + // FIll FIFO as far as possible
  62559. + while(UART_TX_DATA(UART_FIFO_STATUS(info->port)))
  62560. + {
  62561. + UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
  62562. + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
  62563. + port->icount.tx++;
  62564. + if (info->xmit.head == info->xmit.tail)
  62565. + break;
  62566. + }
  62567. +
  62568. + if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) <
  62569. + WAKEUP_CHARS)
  62570. + uart_event(info, EVT_WRITE_WAKEUP);
  62571. +
  62572. + if (info->xmit.head == info->xmit.tail)
  62573. + omahauart_stop_tx(info->port, 0);
  62574. +}
  62575. +
  62576. +static void omahauart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
  62577. +{
  62578. + struct uart_info *info = dev_id;
  62579. + volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
  62580. +
  62581. + status = UART_FIFO_STATUS(info->port);
  62582. + do {
  62583. + // TX if FIFO not full
  62584. + if (UART_TX_DATA(status))
  62585. + omahauart_tx_chars(info);
  62586. +
  62587. + if (pass_counter-- == 0)
  62588. + break;
  62589. +
  62590. + status = UART_FIFO_STATUS(info->port);
  62591. + } while (UART_TX_DATA(status));
  62592. +}
  62593. +
  62594. +static void omahauart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
  62595. +{
  62596. + struct uart_info *info = dev_id;
  62597. + volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
  62598. +
  62599. + status = UART_FIFO_STATUS(info->port);
  62600. + do {
  62601. + if (UART_RX_DATA(status))
  62602. +#ifdef SUPPORT_SYSRQ
  62603. + omahauart_rx_chars(info, regs);
  62604. +#else
  62605. + omahauart_rx_chars(info);
  62606. +#endif
  62607. +
  62608. + if (pass_counter-- == 0)
  62609. + break;
  62610. +
  62611. + status = UART_FIFO_STATUS(info->port);
  62612. + } while (UART_RX_DATA(status));
  62613. +}
  62614. +
  62615. +static u_int omahauart_tx_empty(struct uart_port *port)
  62616. +{
  62617. + return UART_FIFO_STATUS(port) ? 0 : TIOCSER_TEMT;
  62618. +}
  62619. +
  62620. +static int omahauart_get_mctrl(struct uart_port *port)
  62621. +{
  62622. + // Report no errors.
  62623. +
  62624. + return 0;
  62625. +}
  62626. +
  62627. +static void omahauart_set_mctrl(struct uart_port *port, u_int mctrl)
  62628. +{
  62629. + // Do nothing.
  62630. +}
  62631. +
  62632. +static void omahauart_break_ctl(struct uart_port *port, int break_state)
  62633. +{
  62634. + // Do nothing.
  62635. +}
  62636. +
  62637. +static int omahauart_startup(struct uart_port *port, struct uart_info *info)
  62638. +{
  62639. + unsigned int tmp;
  62640. + int retval;
  62641. +
  62642. + /*
  62643. + * Allocate the IRQs
  62644. + */
  62645. + retval = request_irq(TX_IRQ(port), omahauart_int_tx, 0, "omaha_uart_tx", info);
  62646. + if (retval)
  62647. + return retval;
  62648. +
  62649. + retval = request_irq(RX_IRQ(port), omahauart_int_rx, 0, "omaha_uart_rx", info);
  62650. +
  62651. + if (retval)
  62652. + {
  62653. + free_irq(TX_IRQ(port), info);
  62654. + return retval;
  62655. + }
  62656. +
  62657. + /*
  62658. + * initialise the old status of the modem signals
  62659. + */
  62660. + info->drv_old_status = 0;
  62661. +
  62662. + // Clear all errors
  62663. + writel(0, port->membase + OMAHA_UERSTAT);
  62664. +
  62665. + // Enable FIFO, 16-byte watermark, also do reset (auto-clearing)
  62666. + writel(0xF7, port->membase + OMAHA_UFCON);
  62667. +
  62668. + // Level driven TX/RX ints, with rx timeout enabled
  62669. + tmp = readl(port->membase + OMAHA_UCON);
  62670. + tmp |= 0x280; // rx is pulse driven...
  62671. + writel(tmp, port->membase + OMAHA_UCON);
  62672. +
  62673. + return 0;
  62674. +}
  62675. +
  62676. +static void omahauart_shutdown(struct uart_port *port, struct uart_info *info)
  62677. +{
  62678. + /*
  62679. + * Free the interrupt
  62680. + */
  62681. + free_irq(TX_IRQ(port), info); /* TX interrupt */
  62682. + free_irq(RX_IRQ(port), info); /* RX interrupt */
  62683. +
  62684. +}
  62685. +
  62686. +static void omahauart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
  62687. +{
  62688. + // Do nothing.
  62689. +}
  62690. +
  62691. +static const char *omahauart_type(struct uart_port *port)
  62692. +{
  62693. + return port->type == PORT_OMAHA ? "OMAHA" : NULL;
  62694. +}
  62695. +
  62696. +/*
  62697. + * Release the memory region(s) being used by 'port'
  62698. + */
  62699. +static void omahauart_release_port(struct uart_port *port)
  62700. +{
  62701. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  62702. +}
  62703. +
  62704. +/*
  62705. + * Request the memory region(s) being used by 'port'
  62706. + */
  62707. +static int omahauart_request_port(struct uart_port *port)
  62708. +{
  62709. + return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_omaha")
  62710. + != NULL ? 0 : -EBUSY;
  62711. +}
  62712. +
  62713. +/*
  62714. + * Configure/autoconfigure the port.
  62715. + */
  62716. +static void omahauart_config_port(struct uart_port *port, int flags)
  62717. +{
  62718. + if (flags & UART_CONFIG_TYPE) {
  62719. + port->type = PORT_OMAHA;
  62720. + omahauart_request_port(port);
  62721. + }
  62722. +}
  62723. +
  62724. +/*
  62725. + * verify the new serial_struct (for TIOCSSERIAL).
  62726. + */
  62727. +static int omahauart_verify_port(struct uart_port *port, struct serial_struct *ser)
  62728. +{
  62729. + int ret = 0;
  62730. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_OMAHA)
  62731. + ret = -EINVAL;
  62732. + if (ser->irq < 0 || ser->irq >= NR_IRQS)
  62733. + ret = -EINVAL;
  62734. + if (ser->baud_base < 9600)
  62735. + ret = -EINVAL;
  62736. + return ret;
  62737. +}
  62738. +
  62739. +static struct uart_ops omaha_pops = {
  62740. + .tx_empty = omahauart_tx_empty,
  62741. + .set_mctrl = omahauart_set_mctrl,
  62742. + .get_mctrl = omahauart_get_mctrl,
  62743. + .stop_tx = omahauart_stop_tx,
  62744. + .start_tx = omahauart_start_tx,
  62745. + .stop_rx = omahauart_stop_rx,
  62746. + .enable_ms = omahauart_enable_ms,
  62747. + .break_ctl = omahauart_break_ctl,
  62748. + .startup = omahauart_startup,
  62749. + .shutdown = omahauart_shutdown,
  62750. + .change_speed = omahauart_change_speed,
  62751. + .type = omahauart_type,
  62752. + .release_port = omahauart_release_port,
  62753. + .request_port = omahauart_request_port,
  62754. + .config_port = omahauart_config_port,
  62755. + .verify_port = omahauart_verify_port,
  62756. +};
  62757. +
  62758. +static struct uart_port omaha_ports[UART_NR] = {
  62759. + {
  62760. + .membase = (void *)IO_ADDRESS(OMAHA_UART0_BASE),
  62761. + .mapbase = OMAHA_UART0_BASE,
  62762. + .iotype = SERIAL_IO_MEM,
  62763. + .irq = OMAHA_INT_URXD0,
  62764. + .uartclk = 10000000,
  62765. + .fifosize = 8,
  62766. + .unused = { 4, 5 }, /*Udriver_priv: PORT_CTRLS(5, 4), */
  62767. + .ops = &omaha_pops,
  62768. + .flags = ASYNC_BOOT_AUTOCONF,
  62769. + }
  62770. +};
  62771. +
  62772. +#ifdef CONFIG_SERIAL_OMAHA_CONSOLE
  62773. +static void omahauart_console_write(struct console *co, const char *s, u_int count)
  62774. +{
  62775. + struct uart_port *port = omaha_ports + co->index;
  62776. + unsigned int status;
  62777. + int i;
  62778. +
  62779. + /*
  62780. + * First save the CR then disable the interrupts
  62781. + */
  62782. +
  62783. + /*
  62784. + * Now, do each character
  62785. + */
  62786. + for (i = 0; i < count; i++) {
  62787. + do {
  62788. + status = UART_GET_FR(port);
  62789. + } while ((status & OMAHA_UTX_EMPTY) == 0);
  62790. + UART_PUT_CHAR(port, s[i]);
  62791. + if (s[i] == '\n') {
  62792. + do {
  62793. + status = UART_GET_FR(port);
  62794. + } while ((status & OMAHA_UTX_EMPTY) == 0);
  62795. + UART_PUT_CHAR(port, '\r');
  62796. + }
  62797. + }
  62798. +
  62799. + /*
  62800. + * Finally, wait for transmitter to become empty
  62801. + * and restore the TCR
  62802. + */
  62803. + do {
  62804. + status = UART_GET_FR(port);
  62805. + } while ((status & OMAHA_UTX_EMPTY) == 0);
  62806. +}
  62807. +
  62808. +static kdev_t omahauart_console_device(struct console *co)
  62809. +{
  62810. + return MKDEV(SERIAL_OMAHA_MAJOR, SERIAL_OMAHA_MINOR + co->index);
  62811. +}
  62812. +
  62813. +static int omahauart_console_wait_key(struct console *co)
  62814. +{
  62815. + struct uart_port *port = omaha_ports + co->index;
  62816. + unsigned int status;
  62817. +
  62818. + do {
  62819. + status = UART_FIFO_STATUS(port);
  62820. + } while (!UART_RX_DATA(status));
  62821. + return UART_GET_CHAR(port);
  62822. +}
  62823. +
  62824. +static void __init
  62825. +omahauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  62826. +{
  62827. + // Do nothing.
  62828. +}
  62829. +
  62830. +static int __init omahauart_console_setup(struct console *co, char *options)
  62831. +{
  62832. + struct uart_port *port;
  62833. + int baud = 38400;
  62834. + int bits = 8;
  62835. + int parity = 'n';
  62836. + int flow = 'n';
  62837. +
  62838. + /*
  62839. + * Check whether an invalid uart number has been specified, and
  62840. + * if so, search for the first available port that does have
  62841. + * console support.
  62842. + */
  62843. + port = uart_get_console(omaha_ports, UART_NR, co);
  62844. +
  62845. + if (options)
  62846. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  62847. + else
  62848. + omahauart_console_get_options(port, &baud, &parity, &bits);
  62849. +
  62850. + return uart_set_options(port, co, baud, parity, bits, flow);
  62851. +}
  62852. +
  62853. +static struct console omaha_console = {
  62854. + .write = omahauart_console_write,
  62855. + .device = omahauart_console_device,
  62856. + .wait_key = omahauart_console_wait_key,
  62857. + .setup = omahauart_console_setup,
  62858. + .flags = CON_PRINTBUFFER,
  62859. + .index = -1,
  62860. +};
  62861. +
  62862. +void __init omahauart_console_init(void)
  62863. +{
  62864. + register_console(&omaha_console);
  62865. +}
  62866. +
  62867. +#define OMAHA_CONSOLE &omaha_console
  62868. +#else
  62869. +#define OMAHA_CONSOLE NULL
  62870. +#endif
  62871. +
  62872. +static struct uart_driver omaha_reg = {
  62873. + .owner = THIS_MODULE,
  62874. + .normal_major = SERIAL_OMAHA_MAJOR,
  62875. +#ifdef CONFIG_DEVFS_FS
  62876. + .normal_name = "ttyOM%d",
  62877. + .callout_name = "cuaom%d",
  62878. +#else
  62879. + .normal_name = "ttyOM",
  62880. + .callout_name = "cuaom",
  62881. +#endif
  62882. + .normal_driver = &normal,
  62883. + .callout_major = CALLOUT_OMAHA_MAJOR,
  62884. + .callout_driver = &callout,
  62885. + .table = omaha_table,
  62886. + .termios = omaha_termios,
  62887. + .termios_locked = omaha_termios_locked,
  62888. + .minor = SERIAL_OMAHA_MINOR,
  62889. + .nr = UART_NR,
  62890. + .port = omaha_ports,
  62891. + .cons = OMAHA_CONSOLE,
  62892. +};
  62893. +
  62894. +static int __init omahauart_init(void)
  62895. +{
  62896. + return uart_register_driver(&omaha_reg);
  62897. +}
  62898. +
  62899. +static void __exit omahauart_exit(void)
  62900. +{
  62901. + uart_unregister_driver(&omaha_reg);
  62902. +}
  62903. +
  62904. +module_init(omahauart_init);
  62905. +module_exit(omahauart_exit);
  62906. diff -urN linux-2.4.26/drivers/serial/sa1100.c linux-2.4.26-vrs1/drivers/serial/sa1100.c
  62907. --- linux-2.4.26/drivers/serial/sa1100.c 1970-01-01 01:00:00.000000000 +0100
  62908. +++ linux-2.4.26-vrs1/drivers/serial/sa1100.c 2004-01-14 21:32:26.000000000 +0000
  62909. @@ -0,0 +1,904 @@
  62910. +/*
  62911. + * linux/drivers/char/serial_sa1100.c
  62912. + *
  62913. + * Driver for SA11x0 serial ports
  62914. + *
  62915. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  62916. + *
  62917. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  62918. + *
  62919. + * This program is free software; you can redistribute it and/or modify
  62920. + * it under the terms of the GNU General Public License as published by
  62921. + * the Free Software Foundation; either version 2 of the License, or
  62922. + * (at your option) any later version.
  62923. + *
  62924. + * This program is distributed in the hope that it will be useful,
  62925. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  62926. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  62927. + * GNU General Public License for more details.
  62928. + *
  62929. + * You should have received a copy of the GNU General Public License
  62930. + * along with this program; if not, write to the Free Software
  62931. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  62932. + *
  62933. + * $Id: sa1100.c,v 1.14.2.4 2002/10/24 09:53:25 rmk Exp $
  62934. + *
  62935. + */
  62936. +#include <linux/config.h>
  62937. +#include <linux/module.h>
  62938. +#include <linux/tty.h>
  62939. +#include <linux/ioport.h>
  62940. +#include <linux/init.h>
  62941. +#include <linux/sched.h>
  62942. +#include <linux/serial.h>
  62943. +#include <linux/console.h>
  62944. +#include <linux/sysrq.h>
  62945. +
  62946. +#include <asm/io.h>
  62947. +#include <asm/irq.h>
  62948. +#include <asm/hardware.h>
  62949. +#include <asm/mach/serial_sa1100.h>
  62950. +
  62951. +#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  62952. +#define SUPPORT_SYSRQ
  62953. +#endif
  62954. +
  62955. +#include <linux/serial_core.h>
  62956. +
  62957. +/* We've been assigned a range on the "Low-density serial ports" major */
  62958. +#define SERIAL_SA1100_MAJOR 204
  62959. +#define CALLOUT_SA1100_MAJOR 205
  62960. +#define MINOR_START 5
  62961. +
  62962. +#define NR_PORTS 3
  62963. +
  62964. +#define SA1100_ISR_PASS_LIMIT 256
  62965. +
  62966. +/*
  62967. + * Convert from ignore_status_mask or read_status_mask to UTSR[01]
  62968. + */
  62969. +#define SM_TO_UTSR0(x) ((x) & 0xff)
  62970. +#define SM_TO_UTSR1(x) ((x) >> 8)
  62971. +#define UTSR0_TO_SM(x) ((x))
  62972. +#define UTSR1_TO_SM(x) ((x) << 8)
  62973. +
  62974. +#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0)
  62975. +#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1)
  62976. +#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2)
  62977. +#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3)
  62978. +#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0)
  62979. +#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1)
  62980. +#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR)
  62981. +
  62982. +#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0)
  62983. +#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1)
  62984. +#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2)
  62985. +#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3)
  62986. +#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0)
  62987. +#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1)
  62988. +#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR)
  62989. +
  62990. +/*
  62991. + * This is the size of our serial port register set.
  62992. + */
  62993. +#define UART_PORT_SIZE 0x24
  62994. +
  62995. +static struct tty_driver normal, callout;
  62996. +static struct tty_struct *sa1100_table[NR_PORTS];
  62997. +static struct termios *sa1100_termios[NR_PORTS], *sa1100_termios_locked[NR_PORTS];
  62998. +static int (*sa1100_open)(struct uart_port *);
  62999. +static void (*sa1100_close)(struct uart_port *);
  63000. +#ifdef SUPPORT_SYSRQ
  63001. +static struct console sa1100_console;
  63002. +#endif
  63003. +
  63004. +/*
  63005. + * This determines how often we check the modem status signals
  63006. + * for any change. They generally aren't connected to an IRQ
  63007. + * so we have to poll them. We also check immediately before
  63008. + * filling the TX fifo incase CTS has been dropped.
  63009. + */
  63010. +#define MCTRL_TIMEOUT (250*HZ/1000)
  63011. +
  63012. +struct sa1100_port {
  63013. + struct uart_port port;
  63014. + struct timer_list timer;
  63015. + unsigned int old_status;
  63016. +};
  63017. +
  63018. +/*
  63019. + * Handle any change of modem status signal since we were last called.
  63020. + */
  63021. +static void sa1100_mctrl_check(struct sa1100_port *sport)
  63022. +{
  63023. + unsigned int status, changed;
  63024. +
  63025. + status = sport->port.ops->get_mctrl(&sport->port);
  63026. + changed = status ^ sport->old_status;
  63027. +
  63028. + if (changed == 0)
  63029. + return;
  63030. +
  63031. + sport->old_status = status;
  63032. +
  63033. + if (changed & TIOCM_RI)
  63034. + sport->port.icount.rng++;
  63035. + if (changed & TIOCM_DSR)
  63036. + sport->port.icount.dsr++;
  63037. + if (changed & TIOCM_CAR)
  63038. + uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
  63039. + if (changed & TIOCM_CTS)
  63040. + uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
  63041. +
  63042. + wake_up_interruptible(&sport->port.info->delta_msr_wait);
  63043. +}
  63044. +
  63045. +/*
  63046. + * This is our per-port timeout handler, for checking the
  63047. + * modem status signals.
  63048. + */
  63049. +static void sa1100_timeout(unsigned long data)
  63050. +{
  63051. + struct sa1100_port *sport = (struct sa1100_port *)data;
  63052. + unsigned long flags;
  63053. +
  63054. + if (sport->port.info) {
  63055. + spin_lock_irqsave(&sport->port.lock, flags);
  63056. + sa1100_mctrl_check(sport);
  63057. + spin_unlock_irqrestore(&sport->port.lock, flags);
  63058. +
  63059. + mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
  63060. + }
  63061. +}
  63062. +
  63063. +/*
  63064. + * interrupts disabled on entry
  63065. + */
  63066. +static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
  63067. +{
  63068. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63069. + u32 utcr3;
  63070. +
  63071. + utcr3 = UART_GET_UTCR3(sport);
  63072. + UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
  63073. + sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
  63074. +}
  63075. +
  63076. +/*
  63077. + * interrupts may not be disabled on entry
  63078. + */
  63079. +static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
  63080. +{
  63081. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63082. + unsigned long flags;
  63083. + u32 utcr3;
  63084. +
  63085. + spin_lock_irqsave(&sport->port.lock, flags);
  63086. + utcr3 = UART_GET_UTCR3(sport);
  63087. + sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
  63088. + UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
  63089. + spin_unlock_irqrestore(&sport->port.lock, flags);
  63090. +}
  63091. +
  63092. +/*
  63093. + * Interrupts enabled
  63094. + */
  63095. +static void sa1100_stop_rx(struct uart_port *port)
  63096. +{
  63097. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63098. + u32 utcr3;
  63099. +
  63100. + utcr3 = UART_GET_UTCR3(sport);
  63101. + UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
  63102. +}
  63103. +
  63104. +/*
  63105. + * Set the modem control timer to fire immediately.
  63106. + */
  63107. +static void sa1100_enable_ms(struct uart_port *port)
  63108. +{
  63109. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63110. +
  63111. + mod_timer(&sport->timer, jiffies);
  63112. +}
  63113. +
  63114. +static void
  63115. +sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
  63116. +{
  63117. + struct tty_struct *tty = sport->port.info->tty;
  63118. + unsigned int status, ch, flg, ignored = 0;
  63119. +
  63120. + status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
  63121. + UTSR0_TO_SM(UART_GET_UTSR0(sport));
  63122. + while (status & UTSR1_TO_SM(UTSR1_RNE)) {
  63123. + ch = UART_GET_CHAR(sport);
  63124. +
  63125. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  63126. + goto ignore_char;
  63127. + sport->port.icount.rx++;
  63128. +
  63129. + flg = TTY_NORMAL;
  63130. +
  63131. + /*
  63132. + * note that the error handling code is
  63133. + * out of the main execution path
  63134. + */
  63135. + if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
  63136. + goto handle_error;
  63137. +
  63138. + if (uart_handle_sysrq_char(&sport->port, ch, regs))
  63139. + goto ignore_char;
  63140. +
  63141. + error_return:
  63142. + *tty->flip.flag_buf_ptr++ = flg;
  63143. + *tty->flip.char_buf_ptr++ = ch;
  63144. + tty->flip.count++;
  63145. + ignore_char:
  63146. + status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
  63147. + UTSR0_TO_SM(UART_GET_UTSR0(sport));
  63148. + }
  63149. + out:
  63150. + tty_flip_buffer_push(tty);
  63151. + return;
  63152. +
  63153. + handle_error:
  63154. + if (status & UTSR1_TO_SM(UTSR1_PRE))
  63155. + sport->port.icount.parity++;
  63156. + else if (status & UTSR1_TO_SM(UTSR1_FRE))
  63157. + sport->port.icount.frame++;
  63158. + if (status & UTSR1_TO_SM(UTSR1_ROR))
  63159. + sport->port.icount.overrun++;
  63160. +
  63161. + if (status & sport->port.ignore_status_mask) {
  63162. + if (++ignored > 100)
  63163. + goto out;
  63164. + goto ignore_char;
  63165. + }
  63166. +
  63167. + status &= sport->port.read_status_mask;
  63168. +
  63169. + if (status & UTSR1_TO_SM(UTSR1_PRE))
  63170. + flg = TTY_PARITY;
  63171. + else if (status & UTSR1_TO_SM(UTSR1_FRE))
  63172. + flg = TTY_FRAME;
  63173. +
  63174. + if (status & UTSR1_TO_SM(UTSR1_ROR)) {
  63175. + /*
  63176. + * overrun does *not* affect the character
  63177. + * we read from the FIFO
  63178. + */
  63179. + *tty->flip.flag_buf_ptr++ = flg;
  63180. + *tty->flip.char_buf_ptr++ = ch;
  63181. + tty->flip.count++;
  63182. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  63183. + goto ignore_char;
  63184. + ch = 0;
  63185. + flg = TTY_OVERRUN;
  63186. + }
  63187. +#ifdef SUPPORT_SYSRQ
  63188. + sport->port.sysrq = 0;
  63189. +#endif
  63190. + goto error_return;
  63191. +}
  63192. +
  63193. +static void sa1100_tx_chars(struct sa1100_port *sport)
  63194. +{
  63195. + struct circ_buf *xmit = &sport->port.info->xmit;
  63196. +
  63197. + if (sport->port.x_char) {
  63198. + UART_PUT_CHAR(sport, sport->port.x_char);
  63199. + sport->port.icount.tx++;
  63200. + sport->port.x_char = 0;
  63201. + return;
  63202. + }
  63203. +
  63204. + /*
  63205. + * Check the modem control lines before
  63206. + * transmitting anything.
  63207. + */
  63208. + sa1100_mctrl_check(sport);
  63209. +
  63210. + if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
  63211. + sa1100_stop_tx(&sport->port, 0);
  63212. + return;
  63213. + }
  63214. +
  63215. + /*
  63216. + * Tried using FIFO (not checking TNF) for fifo fill:
  63217. + * still had the '4 bytes repeated' problem.
  63218. + */
  63219. + while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
  63220. + UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
  63221. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  63222. + sport->port.icount.tx++;
  63223. + if (uart_circ_empty(xmit))
  63224. + break;
  63225. + }
  63226. +
  63227. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  63228. + uart_write_wakeup(&sport->port);
  63229. +
  63230. + if (uart_circ_empty(xmit))
  63231. + sa1100_stop_tx(&sport->port, 0);
  63232. +}
  63233. +
  63234. +static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
  63235. +{
  63236. + struct sa1100_port *sport = dev_id;
  63237. + unsigned int status, pass_counter = 0;
  63238. +
  63239. + spin_lock(&sport->port.lock);
  63240. + status = UART_GET_UTSR0(sport);
  63241. + status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
  63242. + do {
  63243. + if (status & (UTSR0_RFS | UTSR0_RID)) {
  63244. + /* Clear the receiver idle bit, if set */
  63245. + if (status & UTSR0_RID)
  63246. + UART_PUT_UTSR0(sport, UTSR0_RID);
  63247. + sa1100_rx_chars(sport, regs);
  63248. + }
  63249. +
  63250. + /* Clear the relevant break bits */
  63251. + if (status & (UTSR0_RBB | UTSR0_REB))
  63252. + UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
  63253. +
  63254. + if (status & UTSR0_RBB)
  63255. + sport->port.icount.brk++;
  63256. +
  63257. + if (status & UTSR0_REB)
  63258. + uart_handle_break(&sport->port);
  63259. +
  63260. + if (status & UTSR0_TFS)
  63261. + sa1100_tx_chars(sport);
  63262. + if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
  63263. + break;
  63264. + status = UART_GET_UTSR0(sport);
  63265. + status &= SM_TO_UTSR0(sport->port.read_status_mask) |
  63266. + ~UTSR0_TFS;
  63267. + } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
  63268. + spin_unlock(&sport->port.lock);
  63269. +}
  63270. +
  63271. +/*
  63272. + * Return TIOCSER_TEMT when transmitter is not busy.
  63273. + */
  63274. +static unsigned int sa1100_tx_empty(struct uart_port *port)
  63275. +{
  63276. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63277. +
  63278. + return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT;
  63279. +}
  63280. +
  63281. +static unsigned int sa1100_get_mctrl(struct uart_port *port)
  63282. +{
  63283. + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
  63284. +}
  63285. +
  63286. +static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
  63287. +{
  63288. +}
  63289. +
  63290. +/*
  63291. + * Interrupts always disabled.
  63292. + */
  63293. +static void sa1100_break_ctl(struct uart_port *port, int break_state)
  63294. +{
  63295. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63296. + unsigned long flags;
  63297. + unsigned int utcr3;
  63298. +
  63299. + spin_lock_irqsave(&sport->port.lock, flags);
  63300. + utcr3 = UART_GET_UTCR3(sport);
  63301. + if (break_state == -1)
  63302. + utcr3 |= UTCR3_BRK;
  63303. + else
  63304. + utcr3 &= ~UTCR3_BRK;
  63305. + UART_PUT_UTCR3(sport, utcr3);
  63306. + spin_unlock_irqrestore(&sport->port.lock, flags);
  63307. +}
  63308. +
  63309. +static int sa1100_startup(struct uart_port *port)
  63310. +{
  63311. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63312. + int retval;
  63313. +
  63314. + /*
  63315. + * Allocate the IRQ
  63316. + */
  63317. + retval = request_irq(sport->port.irq, sa1100_int, 0,
  63318. + "sa11x0-uart", sport);
  63319. + if (retval)
  63320. + return retval;
  63321. +
  63322. + /*
  63323. + * If there is a specific "open" function
  63324. + * (to register control line interrupts)
  63325. + */
  63326. + if (sa1100_open) {
  63327. + retval = sa1100_open(port);
  63328. + if (retval) {
  63329. + free_irq(sport->port.irq, sport);
  63330. + return retval;
  63331. + }
  63332. + }
  63333. +
  63334. + /*
  63335. + * Finally, clear and enable interrupts
  63336. + */
  63337. + UART_PUT_UTSR0(sport, -1);
  63338. + UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);
  63339. +
  63340. + return 0;
  63341. +}
  63342. +
  63343. +static void sa1100_shutdown(struct uart_port *port)
  63344. +{
  63345. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63346. +
  63347. + /*
  63348. + * Stop our timer.
  63349. + */
  63350. + del_timer_sync(&sport->timer);
  63351. +
  63352. + /*
  63353. + * Free the interrupt
  63354. + */
  63355. + free_irq(sport->port.irq, sport);
  63356. +
  63357. + /*
  63358. + * If there is a specific "close" function (to unregister
  63359. + * control line interrupts)
  63360. + */
  63361. + if (sa1100_close)
  63362. + sa1100_close(port);
  63363. +
  63364. + /*
  63365. + * Disable all interrupts, port and break condition.
  63366. + */
  63367. + UART_PUT_UTCR3(sport, 0);
  63368. +}
  63369. +
  63370. +static void sa1100_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
  63371. +{
  63372. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63373. + unsigned long flags;
  63374. + unsigned int utcr0, old_utcr3;
  63375. +
  63376. + if ((cflag & CSIZE) == CS8)
  63377. + utcr0 = UTCR0_DSS;
  63378. + else
  63379. + utcr0 = 0;
  63380. +
  63381. + if (cflag & CSTOPB)
  63382. + utcr0 |= UTCR0_SBS;
  63383. + if (cflag & PARENB) {
  63384. + utcr0 |= UTCR0_PE;
  63385. + if (!(cflag & PARODD))
  63386. + utcr0 |= UTCR0_OES;
  63387. + }
  63388. +
  63389. + spin_lock_irqsave(&sport->port.lock, flags);
  63390. +
  63391. + sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
  63392. + sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
  63393. + if (iflag & INPCK)
  63394. + sport->port.read_status_mask |=
  63395. + UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
  63396. + if (iflag & (BRKINT | PARMRK))
  63397. + sport->port.read_status_mask |=
  63398. + UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
  63399. +
  63400. + /*
  63401. + * Characters to ignore
  63402. + */
  63403. + sport->port.ignore_status_mask = 0;
  63404. + if (iflag & IGNPAR)
  63405. + sport->port.ignore_status_mask |=
  63406. + UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
  63407. + if (iflag & IGNBRK) {
  63408. + sport->port.ignore_status_mask |=
  63409. + UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
  63410. + /*
  63411. + * If we're ignoring parity and break indicators,
  63412. + * ignore overruns too (for real raw support).
  63413. + */
  63414. + if (iflag & IGNPAR)
  63415. + sport->port.ignore_status_mask |=
  63416. + UTSR1_TO_SM(UTSR1_ROR);
  63417. + }
  63418. +
  63419. + del_timer_sync(&sport->timer);
  63420. +
  63421. + /*
  63422. + * disable interrupts and drain transmitter
  63423. + */
  63424. + old_utcr3 = UART_GET_UTCR3(sport);
  63425. + UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
  63426. +
  63427. + while (UART_GET_UTSR1(sport) & UTSR1_TBY)
  63428. + barrier();
  63429. +
  63430. + /* then, disable everything */
  63431. + UART_PUT_UTCR3(sport, 0);
  63432. +
  63433. + /* set the parity, stop bits and data size */
  63434. + UART_PUT_UTCR0(sport, utcr0);
  63435. +
  63436. + /* set the baud rate */
  63437. + quot -= 1;
  63438. + UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
  63439. + UART_PUT_UTCR2(sport, (quot & 0xff));
  63440. +
  63441. + UART_PUT_UTSR0(sport, -1);
  63442. +
  63443. + UART_PUT_UTCR3(sport, old_utcr3);
  63444. +
  63445. + if (UART_ENABLE_MS(&sport->port, cflag))
  63446. + sa1100_enable_ms(&sport->port);
  63447. +
  63448. + spin_unlock_irqrestore(&sport->port.lock, flags);
  63449. +}
  63450. +
  63451. +static const char *sa1100_type(struct uart_port *port)
  63452. +{
  63453. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63454. +
  63455. + return sport->port.type == PORT_SA1100 ? "SA1100" : NULL;
  63456. +}
  63457. +
  63458. +/*
  63459. + * Release the memory region(s) being used by 'port'.
  63460. + */
  63461. +static void sa1100_release_port(struct uart_port *port)
  63462. +{
  63463. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63464. +
  63465. + release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
  63466. +}
  63467. +
  63468. +/*
  63469. + * Request the memory region(s) being used by 'port'.
  63470. + */
  63471. +static int sa1100_request_port(struct uart_port *port)
  63472. +{
  63473. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63474. +
  63475. + return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
  63476. + "sa11x0-uart") != NULL ? 0 : -EBUSY;
  63477. +}
  63478. +
  63479. +/*
  63480. + * Configure/autoconfigure the port.
  63481. + */
  63482. +static void sa1100_config_port(struct uart_port *port, int flags)
  63483. +{
  63484. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63485. +
  63486. + if (flags & UART_CONFIG_TYPE &&
  63487. + sa1100_request_port(&sport->port) == 0)
  63488. + sport->port.type = PORT_SA1100;
  63489. +}
  63490. +
  63491. +/*
  63492. + * Verify the new serial_struct (for TIOCSSERIAL).
  63493. + * The only change we allow are to the flags and type, and
  63494. + * even then only between PORT_SA1100 and PORT_UNKNOWN
  63495. + */
  63496. +static int sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
  63497. +{
  63498. + struct sa1100_port *sport = (struct sa1100_port *)port;
  63499. + int ret = 0;
  63500. +
  63501. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100)
  63502. + ret = -EINVAL;
  63503. + if (sport->port.irq != ser->irq)
  63504. + ret = -EINVAL;
  63505. + if (ser->io_type != SERIAL_IO_MEM)
  63506. + ret = -EINVAL;
  63507. + if (sport->port.uartclk / 16 != ser->baud_base)
  63508. + ret = -EINVAL;
  63509. + if ((void *)sport->port.mapbase != ser->iomem_base)
  63510. + ret = -EINVAL;
  63511. + if (sport->port.iobase != ser->port)
  63512. + ret = -EINVAL;
  63513. + if (ser->hub6 != 0)
  63514. + ret = -EINVAL;
  63515. + return ret;
  63516. +}
  63517. +
  63518. +static struct uart_ops sa1100_pops = {
  63519. + .tx_empty = sa1100_tx_empty,
  63520. + .set_mctrl = sa1100_set_mctrl,
  63521. + .get_mctrl = sa1100_get_mctrl,
  63522. + .stop_tx = sa1100_stop_tx,
  63523. + .start_tx = sa1100_start_tx,
  63524. + .stop_rx = sa1100_stop_rx,
  63525. + .enable_ms = sa1100_enable_ms,
  63526. + .break_ctl = sa1100_break_ctl,
  63527. + .startup = sa1100_startup,
  63528. + .shutdown = sa1100_shutdown,
  63529. + .change_speed = sa1100_change_speed,
  63530. + .type = sa1100_type,
  63531. + .release_port = sa1100_release_port,
  63532. + .request_port = sa1100_request_port,
  63533. + .config_port = sa1100_config_port,
  63534. + .verify_port = sa1100_verify_port,
  63535. +};
  63536. +
  63537. +static struct sa1100_port sa1100_ports[NR_PORTS];
  63538. +
  63539. +/*
  63540. + * Setup the SA1100 serial ports. Note that we don't include the IrDA
  63541. + * port here since we have our own SIR/FIR driver (see drivers/net/irda)
  63542. + *
  63543. + * Note also that we support "console=ttySAx" where "x" is either 0 or 1.
  63544. + * Which serial port this ends up being depends on the machine you're
  63545. + * running this kernel on. I'm not convinced that this is a good idea,
  63546. + * but that's the way it traditionally works.
  63547. + *
  63548. + * Note that NanoEngine UART3 becomes UART2, and UART2 is no longer
  63549. + * used here.
  63550. + */
  63551. +static void __init sa1100_init_ports(void)
  63552. +{
  63553. + static int first = 1;
  63554. + int i;
  63555. +
  63556. + if (!first)
  63557. + return;
  63558. + first = 0;
  63559. +
  63560. + for (i = 0; i < NR_PORTS; i++) {
  63561. + sa1100_ports[i].port.uartclk = 3686400;
  63562. + sa1100_ports[i].port.ops = &sa1100_pops;
  63563. + sa1100_ports[i].port.fifosize = 8;
  63564. + sa1100_ports[i].port.line = i;
  63565. + sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
  63566. + init_timer(&sa1100_ports[i].timer);
  63567. + sa1100_ports[i].timer.function = sa1100_timeout;
  63568. + sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
  63569. + }
  63570. +
  63571. + /*
  63572. + * make transmit lines outputs, so that when the port
  63573. + * is closed, the output is in the MARK state.
  63574. + */
  63575. + PPDR |= PPC_TXD1 | PPC_TXD3;
  63576. + PPSR |= PPC_TXD1 | PPC_TXD3;
  63577. +}
  63578. +
  63579. +void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
  63580. +{
  63581. + if (fns->enable_ms)
  63582. + sa1100_pops.enable_ms = fns->enable_ms;
  63583. + if (fns->get_mctrl)
  63584. + sa1100_pops.get_mctrl = fns->get_mctrl;
  63585. + if (fns->set_mctrl)
  63586. + sa1100_pops.set_mctrl = fns->set_mctrl;
  63587. + sa1100_open = fns->open;
  63588. + sa1100_close = fns->close;
  63589. + sa1100_pops.pm = fns->pm;
  63590. + sa1100_pops.set_wake = fns->set_wake;
  63591. +}
  63592. +
  63593. +void __init sa1100_register_uart(int idx, int port)
  63594. +{
  63595. + if (idx >= NR_PORTS) {
  63596. + printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
  63597. + return;
  63598. + }
  63599. +
  63600. + switch (port) {
  63601. + case 1:
  63602. + sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0;
  63603. + sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
  63604. + sa1100_ports[idx].port.irq = IRQ_Ser1UART;
  63605. + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
  63606. + break;
  63607. +
  63608. + case 2:
  63609. + sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0;
  63610. + sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
  63611. + sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
  63612. + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
  63613. + break;
  63614. +
  63615. + case 3:
  63616. + sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0;
  63617. + sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
  63618. + sa1100_ports[idx].port.irq = IRQ_Ser3UART;
  63619. + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
  63620. + break;
  63621. +
  63622. + default:
  63623. + printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
  63624. + }
  63625. +}
  63626. +
  63627. +
  63628. +#ifdef CONFIG_SERIAL_SA1100_CONSOLE
  63629. +
  63630. +/*
  63631. + * Interrupts are disabled on entering
  63632. + */
  63633. +static void
  63634. +sa1100_console_write(struct console *co, const char *s, unsigned int count)
  63635. +{
  63636. + struct sa1100_port *sport = &sa1100_ports[co->index];
  63637. + unsigned int old_utcr3, status, i;
  63638. +
  63639. + /*
  63640. + * First, save UTCR3 and then disable interrupts
  63641. + */
  63642. + old_utcr3 = UART_GET_UTCR3(sport);
  63643. + UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
  63644. + UTCR3_TXE);
  63645. +
  63646. + /*
  63647. + * Now, do each character
  63648. + */
  63649. + for (i = 0; i < count; i++) {
  63650. + do {
  63651. + status = UART_GET_UTSR1(sport);
  63652. + } while (!(status & UTSR1_TNF));
  63653. + UART_PUT_CHAR(sport, s[i]);
  63654. + if (s[i] == '\n') {
  63655. + do {
  63656. + status = UART_GET_UTSR1(sport);
  63657. + } while (!(status & UTSR1_TNF));
  63658. + UART_PUT_CHAR(sport, '\r');
  63659. + }
  63660. + }
  63661. +
  63662. + /*
  63663. + * Finally, wait for transmitter to become empty
  63664. + * and restore UTCR3
  63665. + */
  63666. + do {
  63667. + status = UART_GET_UTSR1(sport);
  63668. + } while (status & UTSR1_TBY);
  63669. + UART_PUT_UTCR3(sport, old_utcr3);
  63670. +}
  63671. +
  63672. +static kdev_t sa1100_console_device(struct console *co)
  63673. +{
  63674. + return MKDEV(SERIAL_SA1100_MAJOR, MINOR_START + co->index);
  63675. +}
  63676. +
  63677. +/*
  63678. + * If the port was already initialised (eg, by a boot loader), try to determine
  63679. + * the current setup.
  63680. + */
  63681. +static void __init
  63682. +sa1100_console_get_options(struct sa1100_port *sport, int *baud,
  63683. + int *parity, int *bits)
  63684. +{
  63685. + unsigned int utcr3;
  63686. +
  63687. + utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE);
  63688. + if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) {
  63689. + /* ok, the port was enabled */
  63690. + unsigned int utcr0, quot;
  63691. +
  63692. + utcr0 = UART_GET_UTCR0(sport);
  63693. +
  63694. + *parity = 'n';
  63695. + if (utcr0 & UTCR0_PE) {
  63696. + if (utcr0 & UTCR0_OES)
  63697. + *parity = 'e';
  63698. + else
  63699. + *parity = 'o';
  63700. + }
  63701. +
  63702. + if (utcr0 & UTCR0_DSS)
  63703. + *bits = 8;
  63704. + else
  63705. + *bits = 7;
  63706. +
  63707. + quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8;
  63708. + quot &= 0xfff;
  63709. + *baud = sport->port.uartclk / (16 * (quot + 1));
  63710. + }
  63711. +}
  63712. +
  63713. +static int __init
  63714. +sa1100_console_setup(struct console *co, char *options)
  63715. +{
  63716. + struct sa1100_port *sport;
  63717. + int baud = CONFIG_SA1100_DEFAULT_BAUDRATE;
  63718. + int bits = 8;
  63719. + int parity = 'n';
  63720. + int flow = 'n';
  63721. +
  63722. + /*
  63723. + * Check whether an invalid uart number has been specified, and
  63724. + * if so, search for the first available port that does have
  63725. + * console support.
  63726. + */
  63727. + if (co->index == -1 || co->index >= NR_PORTS)
  63728. + co->index = 0;
  63729. + sport = &sa1100_ports[co->index];
  63730. +
  63731. + if (options)
  63732. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  63733. + else
  63734. + sa1100_console_get_options(sport, &baud, &parity, &bits);
  63735. +
  63736. + return uart_set_options(&sport->port, co, baud, parity, bits, flow);
  63737. +}
  63738. +
  63739. +static struct console sa1100_console = {
  63740. + .name = "ttySA",
  63741. + .write = sa1100_console_write,
  63742. + .device = sa1100_console_device,
  63743. + .setup = sa1100_console_setup,
  63744. + .flags = CON_PRINTBUFFER,
  63745. + .index = -1,
  63746. +};
  63747. +
  63748. +void __init sa1100_rs_console_init(void)
  63749. +{
  63750. + sa1100_init_ports();
  63751. + register_console(&sa1100_console);
  63752. +}
  63753. +
  63754. +#define SA1100_CONSOLE &sa1100_console
  63755. +#else
  63756. +#define SA1100_CONSOLE NULL
  63757. +#endif
  63758. +
  63759. +static struct uart_driver sa1100_reg = {
  63760. + .owner = THIS_MODULE,
  63761. + .normal_major = SERIAL_SA1100_MAJOR,
  63762. +#ifdef CONFIG_DEVFS_FS
  63763. + .normal_name = "ttySA%d",
  63764. + .callout_name = "cusa%d",
  63765. +#else
  63766. + .normal_name = "ttySA",
  63767. + .callout_name = "cusa",
  63768. +#endif
  63769. + .normal_driver = &normal,
  63770. + .callout_major = CALLOUT_SA1100_MAJOR,
  63771. + .callout_driver = &callout,
  63772. + .table = sa1100_table,
  63773. + .termios = sa1100_termios,
  63774. + .termios_locked = sa1100_termios_locked,
  63775. + .minor = MINOR_START,
  63776. + .nr = NR_PORTS,
  63777. + .cons = SA1100_CONSOLE,
  63778. +};
  63779. +
  63780. +static int __init sa1100_serial_init(void)
  63781. +{
  63782. + int i, ret;
  63783. +
  63784. + sa1100_init_ports();
  63785. +
  63786. + ret = uart_register_driver(&sa1100_reg);
  63787. + if (ret)
  63788. + return ret;
  63789. +
  63790. + for (i = 0; i < NR_PORTS; i++)
  63791. + uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
  63792. +
  63793. + return 0;
  63794. +}
  63795. +
  63796. +static void __exit sa1100_serial_exit(void)
  63797. +{
  63798. + int i;
  63799. +
  63800. + for (i = 0; i < NR_PORTS; i++)
  63801. + uart_remove_one_port(&sa1100_reg, &sa1100_ports[i].port);
  63802. +
  63803. + uart_unregister_driver(&sa1100_reg);
  63804. +}
  63805. +
  63806. +module_init(sa1100_serial_init);
  63807. +module_exit(sa1100_serial_exit);
  63808. +
  63809. +EXPORT_NO_SYMBOLS;
  63810. +
  63811. +MODULE_AUTHOR("Deep Blue Solutions Ltd");
  63812. +MODULE_DESCRIPTION("SA1100 generic serial port driver");
  63813. +MODULE_LICENSE("GPL");
  63814. diff -urN linux-2.4.26/drivers/serial/uart00.c linux-2.4.26-vrs1/drivers/serial/uart00.c
  63815. --- linux-2.4.26/drivers/serial/uart00.c 1970-01-01 01:00:00.000000000 +0100
  63816. +++ linux-2.4.26-vrs1/drivers/serial/uart00.c 2004-01-14 21:32:26.000000000 +0000
  63817. @@ -0,0 +1,903 @@
  63818. +/*
  63819. + * linux/drivers/serial/uart00.c
  63820. + *
  63821. + * Driver for UART00 serial ports
  63822. + *
  63823. + * Based on drivers/char/serial_amba.c, by ARM Limited &
  63824. + * Deep Blue Solutions Ltd.
  63825. + * Copyright 2001 Altera Corporation
  63826. + *
  63827. + * This program is free software; you can redistribute it and/or modify
  63828. + * it under the terms of the GNU General Public License as published by
  63829. + * the Free Software Foundation; either version 2 of the License, or
  63830. + * (at your option) any later version.
  63831. + *
  63832. + * This program is distributed in the hope that it will be useful,
  63833. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  63834. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  63835. + * GNU General Public License for more details.
  63836. + *
  63837. + * You should have received a copy of the GNU General Public License
  63838. + * along with this program; if not, write to the Free Software
  63839. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  63840. + *
  63841. + * $Id: uart00.c,v 1.3.2.5 2002/10/24 09:53:26 rmk Exp $
  63842. + *
  63843. + */
  63844. +#include <linux/config.h>
  63845. +#include <linux/module.h>
  63846. +
  63847. +#include <linux/errno.h>
  63848. +#include <linux/signal.h>
  63849. +#include <linux/sched.h>
  63850. +#include <linux/interrupt.h>
  63851. +#include <linux/tty.h>
  63852. +#include <linux/tty_flip.h>
  63853. +#include <linux/major.h>
  63854. +#include <linux/string.h>
  63855. +#include <linux/fcntl.h>
  63856. +#include <linux/ptrace.h>
  63857. +#include <linux/ioport.h>
  63858. +#include <linux/mm.h>
  63859. +#include <linux/slab.h>
  63860. +#include <linux/init.h>
  63861. +#include <linux/circ_buf.h>
  63862. +#include <linux/serial.h>
  63863. +#include <linux/console.h>
  63864. +#include <linux/sysrq.h>
  63865. +#include <linux/pld/pld_hotswap.h>
  63866. +#include <linux/proc_fs.h>
  63867. +
  63868. +#include <asm/system.h>
  63869. +#include <asm/io.h>
  63870. +#include <asm/irq.h>
  63871. +#include <asm/uaccess.h>
  63872. +#include <asm/bitops.h>
  63873. +#include <asm/sizes.h>
  63874. +
  63875. +#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  63876. +#define SUPPORT_SYSRQ
  63877. +#endif
  63878. +
  63879. +#include <linux/serial_core.h>
  63880. +#include <asm/arch/excalibur.h>
  63881. +#define UART00_TYPE (volatile unsigned int*)
  63882. +#include <asm/arch/uart00.h>
  63883. +#include <asm/arch/int_ctrl00.h>
  63884. +
  63885. +#undef DEBUG
  63886. +#define UART_NR 2
  63887. +
  63888. +#define SERIAL_UART00_NAME "ttyUA"
  63889. +#define SERIAL_UART00_MAJOR 204
  63890. +#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
  63891. +#define SERIAL_UART00_NR UART_NR
  63892. +#define UART_PORT_SIZE 0x50
  63893. +
  63894. +#define CALLOUT_UART00_NAME "cuaua"
  63895. +#define CALLOUT_UART00_MAJOR 205
  63896. +#define CALLOUT_UART00_MINOR 16 /* Temporary - will change in future */
  63897. +#define CALLOUT_UART00_NR UART_NR
  63898. +
  63899. +static struct tty_driver normal, callout;
  63900. +static struct tty_struct *uart00_table[UART_NR];
  63901. +static struct termios *uart00_termios[UART_NR], *uart00_termios_locked[UART_NR];
  63902. +static struct console uart00_console;
  63903. +static struct uart_driver uart00_reg;
  63904. +
  63905. +
  63906. +#define UART00_ISR_PASS_LIMIT 256
  63907. +
  63908. +/*
  63909. + * Access macros for the UART00 UARTs
  63910. + */
  63911. +#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
  63912. +#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
  63913. +#define UART_GET_IES(p) inl(UART_IES((p)->membase))
  63914. +#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
  63915. +#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
  63916. +#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
  63917. +#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
  63918. +#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
  63919. +#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
  63920. +#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
  63921. +#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
  63922. +#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
  63923. +#define UART_GET_MC(p) inl(UART_MC((p)->membase))
  63924. +#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
  63925. +#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
  63926. +#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
  63927. +#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
  63928. +#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
  63929. +#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
  63930. +#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
  63931. +#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
  63932. +//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
  63933. +
  63934. +static void uart00_stop_tx(struct uart_port *port, u_int from_tty)
  63935. +{
  63936. +
  63937. + UART_PUT_IEC(port, UART_IEC_TIE_MSK);
  63938. +}
  63939. +
  63940. +static void uart00_stop_rx(struct uart_port *port)
  63941. +{
  63942. +
  63943. + UART_PUT_IEC(port, UART_IEC_RE_MSK);
  63944. +}
  63945. +
  63946. +static void uart00_enable_ms(struct uart_port *port)
  63947. +{
  63948. +
  63949. + UART_PUT_IES(port, UART_IES_ME_MSK);
  63950. +}
  63951. +
  63952. +static void
  63953. +uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
  63954. +{
  63955. + struct uart_info *info = port->info;
  63956. + struct tty_struct *tty = info->tty;
  63957. + unsigned int status, ch, rds, flg, ignored = 0;
  63958. +
  63959. +
  63960. + status = UART_GET_RSR(port);
  63961. + while (UART_RX_DATA(status)) {
  63962. +
  63963. + /*
  63964. + * We need to read rds before reading the
  63965. + * character from the fifo
  63966. + */
  63967. + rds = UART_GET_RDS(port);
  63968. + ch = UART_GET_CHAR(port);
  63969. + port->icount.rx++;
  63970. +
  63971. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  63972. + goto ignore_char;
  63973. +
  63974. + flg = TTY_NORMAL;
  63975. +
  63976. + /*
  63977. + * Note that the error handling code is
  63978. + * out of the main execution path
  63979. + */
  63980. + if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|UART_RDS_PE_MSK))
  63981. + goto handle_error;
  63982. + if (uart_handle_sysrq_char(port, ch, regs))
  63983. + goto ignore_char;
  63984. +
  63985. + error_return:
  63986. + *tty->flip.flag_buf_ptr++ = flg;
  63987. + *tty->flip.char_buf_ptr++ = ch;
  63988. + tty->flip.count++;
  63989. + ignore_char:
  63990. + status = UART_GET_RSR(port);
  63991. + }
  63992. +out:
  63993. + tty_flip_buffer_push(tty);
  63994. + return;
  63995. +
  63996. +handle_error:
  63997. + if (rds & UART_RDS_BI_MSK) {
  63998. + status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
  63999. + port->icount.brk++;
  64000. +
  64001. +#ifdef SUPPORT_SYSRQ
  64002. + if (uart_handle_break(port))
  64003. + goto ignore_char;
  64004. +#endif
  64005. + } else if (rds & UART_RDS_PE_MSK)
  64006. + port->icount.parity++;
  64007. + else if (rds & UART_RDS_FE_MSK)
  64008. + port->icount.frame++;
  64009. + if (rds & UART_RDS_OE_MSK)
  64010. + port->icount.overrun++;
  64011. +
  64012. + if (rds & port->ignore_status_mask) {
  64013. + if (++ignored > 100)
  64014. + goto out;
  64015. + goto ignore_char;
  64016. + }
  64017. + rds &= port->read_status_mask;
  64018. +
  64019. + if (rds & UART_RDS_BI_MSK)
  64020. + flg = TTY_BREAK;
  64021. + else if (rds & UART_RDS_PE_MSK)
  64022. + flg = TTY_PARITY;
  64023. + else if (rds & UART_RDS_FE_MSK)
  64024. + flg = TTY_FRAME;
  64025. +
  64026. + if (rds & UART_RDS_OE_MSK) {
  64027. + /*
  64028. + * CHECK: does overrun affect the current character?
  64029. + * ASSUMPTION: it does not.
  64030. + */
  64031. + *tty->flip.flag_buf_ptr++ = flg;
  64032. + *tty->flip.char_buf_ptr++ = ch;
  64033. + tty->flip.count++;
  64034. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  64035. + goto ignore_char;
  64036. + ch = 0;
  64037. + flg = TTY_OVERRUN;
  64038. + }
  64039. +#ifdef SUPPORT_SYSRQ
  64040. + port->sysrq = 0;
  64041. +#endif
  64042. + goto error_return;
  64043. +}
  64044. +
  64045. +static void uart00_tx_chars(struct uart_port *port)
  64046. +{
  64047. + int count;
  64048. + struct uart_info *info = port->info;
  64049. +
  64050. + if (port->x_char) {
  64051. + while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
  64052. + UART_PUT_CHAR(port, port->x_char);
  64053. + port->icount.tx++;
  64054. + port->x_char = 0;
  64055. +
  64056. + return;
  64057. + }
  64058. + if (info->xmit.head == info->xmit.tail
  64059. + || info->tty->stopped
  64060. + || info->tty->hw_stopped) {
  64061. + uart00_stop_tx(port, 0);
  64062. + return;
  64063. + }
  64064. +
  64065. + count = port->fifosize >> 1;
  64066. + do {
  64067. + while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
  64068. + UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
  64069. + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
  64070. + port->icount.tx++;
  64071. + if (info->xmit.head == info->xmit.tail)
  64072. + break;
  64073. + } while (--count > 0);
  64074. +
  64075. + if (CIRC_CNT(info->xmit.head,
  64076. + info->xmit.tail,
  64077. + UART_XMIT_SIZE) < WAKEUP_CHARS)
  64078. + uart_write_wakeup(port);
  64079. +
  64080. + if (info->xmit.head == info->xmit.tail)
  64081. + uart00_stop_tx(port, 0);
  64082. +}
  64083. +
  64084. +static void uart00_start_tx(struct uart_port *port, u_int from_tty)
  64085. +{
  64086. + UART_PUT_IES(port,UART_IES_TIE_MSK );
  64087. + uart00_tx_chars(port);
  64088. +}
  64089. +
  64090. +static void uart00_modem_status(struct uart_port *port)
  64091. +{
  64092. + unsigned int status;
  64093. + struct uart_icount *icount = &port->icount;
  64094. + struct uart_info *info = port->info;
  64095. +
  64096. + status = UART_GET_MSR(port);
  64097. +
  64098. + if (!status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
  64099. + UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK))
  64100. + return;
  64101. +
  64102. + if (status & UART_MSR_DDCD_MSK) {
  64103. + icount->dcd++;
  64104. +#ifdef CONFIG_HARD_PPS
  64105. + if ((port->flags & ASYNC_HARDPPS_CD) &&
  64106. + (status & UART_MSR_DCD_MSK))
  64107. + hardpps();
  64108. +#endif
  64109. + if (info->flags & ASYNC_CHECK_CD) {
  64110. + if (status & UART_MSR_DCD_MSK)
  64111. + wake_up_interruptible(&info->open_wait);
  64112. + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
  64113. + (port->flags & ASYNC_CALLOUT_NOHUP))) {
  64114. + if (info->tty)
  64115. + tty_hangup(info->tty);
  64116. + }
  64117. + }
  64118. + }
  64119. +
  64120. + if (status & UART_MSR_DDSR_MSK)
  64121. + icount->dsr++;
  64122. +
  64123. + if (status & UART_MSR_DCTS_MSK) {
  64124. + icount->cts++;
  64125. +
  64126. + if (info->flags & ASYNC_CTS_FLOW) {
  64127. + status &= UART_MSR_CTS_MSK;
  64128. +
  64129. + if (info->tty->hw_stopped) {
  64130. + if (status) {
  64131. + info->tty->hw_stopped = 0;
  64132. + port->ops->start_tx(port, 0);
  64133. + uart_write_wakeup(port);
  64134. + }
  64135. + } else {
  64136. + if (!status) {
  64137. + info->tty->hw_stopped = 1;
  64138. + port->ops->stop_tx(port, 0);
  64139. + }
  64140. + }
  64141. + }
  64142. + }
  64143. + wake_up_interruptible(&info->delta_msr_wait);
  64144. +
  64145. +}
  64146. +
  64147. +static void uart00_int(int irq, void *dev_id, struct pt_regs *regs)
  64148. +{
  64149. + struct uart_port *port = dev_id;
  64150. + unsigned int status, pass_counter = 0;
  64151. +
  64152. + status = UART_GET_INT_STATUS(port);
  64153. + do {
  64154. +
  64155. + if (status & UART_ISR_RI_MSK)
  64156. + uart00_rx_chars(port, regs);
  64157. + if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
  64158. + uart00_tx_chars(port);
  64159. + if (status & UART_ISR_MI_MSK)
  64160. + uart00_modem_status(port);
  64161. + if (pass_counter++ > UART00_ISR_PASS_LIMIT)
  64162. + break;
  64163. +
  64164. + status = UART_GET_INT_STATUS(port);
  64165. + } while (status);
  64166. +}
  64167. +
  64168. +static u_int uart00_tx_empty(struct uart_port *port)
  64169. +{
  64170. + return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
  64171. +}
  64172. +
  64173. +static u_int uart00_get_mctrl(struct uart_port *port)
  64174. +{
  64175. + unsigned int result = 0;
  64176. + unsigned int status;
  64177. +
  64178. + status = UART_GET_MSR(port);
  64179. + if (status & UART_MSR_DCD_MSK)
  64180. + result |= TIOCM_CAR;
  64181. + if (status & UART_MSR_DSR_MSK)
  64182. + result |= TIOCM_DSR;
  64183. + if (status & UART_MSR_CTS_MSK)
  64184. + result |= TIOCM_CTS;
  64185. + if (status & UART_MCR_RI_MSK)
  64186. + result |= TIOCM_RNG;
  64187. +
  64188. + return result;
  64189. +}
  64190. +
  64191. +static void uart00_set_mctrl(struct uart_port *port, u_int mctrl)
  64192. +{
  64193. + unsigned char mcr = 0;
  64194. +
  64195. + if (mctrl & TIOCM_RTS)
  64196. + mcr |= UART_MCR_RTS_MSK;
  64197. + if (mctrl & TIOCM_DTR)
  64198. + mcr |= UART_MCR_DTR_MSK;
  64199. + if (mctrl & TIOCM_LOOP)
  64200. + mcr |= UART_MCR_LB_MSK;
  64201. +
  64202. + UART_PUT_MCR(port, mcr);
  64203. +}
  64204. +
  64205. +static void uart00_break_ctl(struct uart_port *port, int break_state)
  64206. +{
  64207. + unsigned int mcr;
  64208. +
  64209. + mcr = UART_GET_MCR(port);
  64210. + if (break_state == -1)
  64211. + mcr |= UART_MCR_BR_MSK;
  64212. + else
  64213. + mcr &= ~UART_MCR_BR_MSK;
  64214. + UART_PUT_MCR(port, mcr);
  64215. +}
  64216. +
  64217. +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
  64218. +{
  64219. + u_int quot;
  64220. +
  64221. + /* Special case: B0 rate */
  64222. + if (!baud)
  64223. + baud = 9600;
  64224. +
  64225. + quot = (port->uartclk / (16 * baud)-1) ;
  64226. +
  64227. + return quot;
  64228. +}
  64229. +static void uart00_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
  64230. +{
  64231. + u_int uart_mc=0, old_ies;
  64232. + unsigned long flags;
  64233. +
  64234. +#ifdef DEBUG
  64235. + printk("uart00_set_cflag(0x%x) called\n", cflag);
  64236. +#endif
  64237. + /* byte size and parity */
  64238. + switch (cflag & CSIZE) {
  64239. + case CS5: uart_mc = UART_MC_CLS_CHARLEN_5; break;
  64240. + case CS6: uart_mc = UART_MC_CLS_CHARLEN_6; break;
  64241. + case CS7: uart_mc = UART_MC_CLS_CHARLEN_7; break;
  64242. + default: uart_mc = UART_MC_CLS_CHARLEN_8; break; // CS8
  64243. + }
  64244. + if (cflag & CSTOPB)
  64245. + uart_mc|= UART_MC_ST_TWO;
  64246. + if (cflag & PARENB) {
  64247. + uart_mc |= UART_MC_PE_MSK;
  64248. + if (!(cflag & PARODD))
  64249. + uart_mc |= UART_MC_EP_MSK;
  64250. + }
  64251. +
  64252. + port->read_status_mask = UART_RDS_OE_MSK;
  64253. + if (iflag & INPCK)
  64254. + port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
  64255. + if (iflag & (BRKINT | PARMRK))
  64256. + port->read_status_mask |= UART_RDS_BI_MSK;
  64257. +
  64258. + /*
  64259. + * Characters to ignore
  64260. + */
  64261. + port->ignore_status_mask = 0;
  64262. + if (iflag & IGNPAR)
  64263. + port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
  64264. + if (iflag & IGNBRK) {
  64265. + port->ignore_status_mask |= UART_RDS_BI_MSK;
  64266. + /*
  64267. + * If we're ignoring parity and break indicators,
  64268. + * ignore overruns to (for real raw support).
  64269. + */
  64270. + if (iflag & IGNPAR)
  64271. + port->ignore_status_mask |= UART_RDS_OE_MSK;
  64272. + }
  64273. +
  64274. + /* first, disable everything */
  64275. + save_flags(flags); cli();
  64276. + old_ies = UART_GET_IES(port);
  64277. +
  64278. + if ((port->flags & ASYNC_HARDPPS_CD) ||
  64279. + (cflag & CRTSCTS) || !(cflag & CLOCAL))
  64280. + old_ies |= UART_IES_ME_MSK;
  64281. +
  64282. +
  64283. + /* Set baud rate */
  64284. + UART_PUT_DIV_LO(port, (quot & 0xff));
  64285. + UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
  64286. +
  64287. +
  64288. + UART_PUT_MC(port, uart_mc);
  64289. + UART_PUT_IES(port, old_ies);
  64290. +
  64291. + restore_flags(flags);
  64292. +}
  64293. +
  64294. +static int uart00_startup(struct uart_port *port)
  64295. +{
  64296. + int retval;
  64297. +
  64298. + /*
  64299. + * Allocate the IRQ
  64300. + */
  64301. + retval = request_irq(port->irq, uart00_int, 0, "uart00", port);
  64302. + if (retval)
  64303. + return retval;
  64304. +
  64305. + /*
  64306. + * Finally, enable interrupts. Use the TII interrupt to minimise
  64307. + * the number of interrupts generated. If higher performance is
  64308. + * needed, consider using the TI interrupt with a suitable FIFO
  64309. + * threshold
  64310. + */
  64311. + UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
  64312. +
  64313. + return 0;
  64314. +}
  64315. +
  64316. +static void uart00_shutdown(struct uart_port *port)
  64317. +{
  64318. + /*
  64319. + * disable all interrupts, disable the port
  64320. + */
  64321. + UART_PUT_IEC(port, 0xff);
  64322. +
  64323. + /* disable break condition and fifos */
  64324. + UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
  64325. +
  64326. + /*
  64327. + * Free the interrupt
  64328. + */
  64329. + free_irq(port->irq, port);
  64330. +}
  64331. +
  64332. +static const char *uart00_type(struct uart_port *port)
  64333. +{
  64334. + return port->type == PORT_UART00 ? "Altera UART00" : NULL;
  64335. +}
  64336. +
  64337. +/*
  64338. + * Release the memory region(s) being used by 'port'
  64339. + */
  64340. +static void uart00_release_port(struct uart_port *port)
  64341. +{
  64342. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  64343. +
  64344. +#ifdef CONFIG_ARCH_CAMELOT
  64345. + if(port->membase!=(void*)IO_ADDRESS(EXC_UART00_BASE)){
  64346. + iounmap(port->membase);
  64347. + }
  64348. +#endif
  64349. +}
  64350. +
  64351. +/*
  64352. + * Request the memory region(s) being used by 'port'
  64353. + */
  64354. +static int uart00_request_port(struct uart_port *port)
  64355. +{
  64356. + int result;
  64357. +
  64358. + result = request_mem_region(port->mapbase, UART_PORT_SIZE,
  64359. + "serial_uart00") != NULL ? 0 : -EBUSY;
  64360. + if (result)
  64361. + return result;
  64362. +
  64363. + port->membase = ioremap(port->mapbase, SZ_4K);
  64364. + if (!port->membase) {
  64365. + printk(KERN_ERR "serial00: cannot map io memory\n");
  64366. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  64367. + }
  64368. +
  64369. + return port->membase ? 0 : -ENOMEM;
  64370. +}
  64371. +
  64372. +/*
  64373. + * Configure/autoconfigure the port.
  64374. + */
  64375. +static void uart00_config_port(struct uart_port *port, int flags)
  64376. +{
  64377. + if (flags & UART_CONFIG_TYPE) {
  64378. + if (uart00_request_port(port) == 0)
  64379. + port->type = PORT_UART00;
  64380. + }
  64381. +}
  64382. +
  64383. +/*
  64384. + * verify the new serial_struct (for TIOCSSERIAL).
  64385. + */
  64386. +static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
  64387. +{
  64388. + int ret = 0;
  64389. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
  64390. + ret = -EINVAL;
  64391. + if (ser->irq < 0 || ser->irq >= NR_IRQS)
  64392. + ret = -EINVAL;
  64393. + if (ser->baud_base < 9600)
  64394. + ret = -EINVAL;
  64395. + return ret;
  64396. +}
  64397. +
  64398. +static struct uart_ops uart00_pops = {
  64399. + tx_empty: uart00_tx_empty,
  64400. + set_mctrl: uart00_set_mctrl,
  64401. + get_mctrl: uart00_get_mctrl,
  64402. + stop_tx: uart00_stop_tx,
  64403. + start_tx: uart00_start_tx,
  64404. + stop_rx: uart00_stop_rx,
  64405. + enable_ms: uart00_enable_ms,
  64406. + break_ctl: uart00_break_ctl,
  64407. + startup: uart00_startup,
  64408. + shutdown: uart00_shutdown,
  64409. + change_speed: uart00_change_speed,
  64410. + type: uart00_type,
  64411. + release_port: uart00_release_port,
  64412. + request_port: uart00_request_port,
  64413. + config_port: uart00_config_port,
  64414. + verify_port: uart00_verify_port,
  64415. +};
  64416. +
  64417. +static struct uart_port uart00_ports[UART_NR] = {
  64418. +
  64419. +#ifdef CONFIG_ARCH_CAMELOT
  64420. +{
  64421. + .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
  64422. + .mapbase = EXC_UART00_BASE,
  64423. + .iotype = SERIAL_IO_MEM,
  64424. + .irq = IRQ_UART,
  64425. + .uartclk = EXC_AHB2_CLK_FREQUENCY,
  64426. + .fifosize = 16,
  64427. + .ops = &uart00_pops,
  64428. + .flags = ASYNC_BOOT_AUTOCONF,
  64429. +}
  64430. +#endif
  64431. +};
  64432. +
  64433. +#ifdef CONFIG_SERIAL_UART00_CONSOLE
  64434. +static void uart00_console_write(struct console *co, const char *s, unsigned count)
  64435. +{
  64436. +#ifdef CONFIG_ARCH_CAMELOT
  64437. + struct uart_port *port = &uart00_ports[0];
  64438. + unsigned int status, old_ies;
  64439. + int i;
  64440. +
  64441. + /*
  64442. + * First save the CR then disable the interrupts
  64443. + */
  64444. + old_ies = UART_GET_IES(port);
  64445. + UART_PUT_IEC(port,0xff);
  64446. +
  64447. + /*
  64448. + * Now, do each character
  64449. + */
  64450. + for (i = 0; i < count; i++) {
  64451. + do {
  64452. + status = UART_GET_TSR(port);
  64453. + } while (!UART_TX_READY(status));
  64454. + UART_PUT_CHAR(port, s[i]);
  64455. + if (s[i] == '\n') {
  64456. + do {
  64457. + status = UART_GET_TSR(port);
  64458. + } while (!UART_TX_READY(status));
  64459. + UART_PUT_CHAR(port, '\r');
  64460. + }
  64461. + }
  64462. +
  64463. + /*
  64464. + * Finally, wait for transmitter to become empty
  64465. + * and restore the IES
  64466. + */
  64467. + do {
  64468. + status = UART_GET_TSR(port);
  64469. + } while (status & UART_TSR_TX_LEVEL_MSK);
  64470. + UART_PUT_IES(port, old_ies);
  64471. +#endif
  64472. +}
  64473. +
  64474. +static kdev_t uart00_console_device(struct console *co)
  64475. +{
  64476. + return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);
  64477. +}
  64478. +
  64479. +static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  64480. +{
  64481. + u_int uart_mc, quot;
  64482. + uart_mc= UART_GET_MC(port);
  64483. +
  64484. + *parity = 'n';
  64485. + if (uart_mc & UART_MC_PE_MSK) {
  64486. + if (uart_mc & UART_MC_EP_MSK)
  64487. + *parity = 'e';
  64488. + else
  64489. + *parity = 'o';
  64490. + }
  64491. +
  64492. + switch (uart_mc & UART_MC_CLS_MSK){
  64493. +
  64494. + case UART_MC_CLS_CHARLEN_5:
  64495. + *bits = 5;
  64496. + break;
  64497. + case UART_MC_CLS_CHARLEN_6:
  64498. + *bits = 6;
  64499. + break;
  64500. + case UART_MC_CLS_CHARLEN_7:
  64501. + *bits = 7;
  64502. + break;
  64503. + case UART_MC_CLS_CHARLEN_8:
  64504. + *bits = 8;
  64505. + break;
  64506. + }
  64507. + quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
  64508. + *baud = port->uartclk / (16 *quot );
  64509. +}
  64510. +
  64511. +static int __init uart00_console_setup(struct console *co, char *options)
  64512. +{
  64513. + struct uart_port *port;
  64514. + int baud = 38400;
  64515. + int bits = 8;
  64516. + int parity = 'n';
  64517. + int flow= 'n';
  64518. +
  64519. +#ifdef CONFIG_ARCH_CAMELOT
  64520. + /*
  64521. + * Check whether an invalid uart number has been specified, and
  64522. + * if so, search for the first available port that does have
  64523. + * console support.
  64524. + */
  64525. + port = &uart00_ports[0];
  64526. + co->index = 0;
  64527. +#else
  64528. + return -ENODEV;
  64529. +#endif
  64530. +
  64531. + if (options)
  64532. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  64533. + else
  64534. + uart00_console_get_options(port, &baud, &parity, &bits);
  64535. +
  64536. + return uart_set_options(port, co, baud, parity, bits, flow);
  64537. +}
  64538. +
  64539. +static struct console uart00_console = {
  64540. + .name = SERIAL_UART00_NAME,
  64541. + .write = uart00_console_write,
  64542. + .device = uart00_console_device,
  64543. + .setup = uart00_console_setup,
  64544. + .flags = CON_PRINTBUFFER,
  64545. + .index = 0,
  64546. +};
  64547. +
  64548. +void __init uart00_console_init(void)
  64549. +{
  64550. + register_console(&uart00_console);
  64551. +}
  64552. +
  64553. +#define UART00_CONSOLE &uart00_console
  64554. +#else
  64555. +#define UART00_CONSOLE NULL
  64556. +#endif
  64557. +
  64558. +static struct uart_driver uart00_reg = {
  64559. + .owner = NULL,
  64560. + .normal_major = SERIAL_UART00_MAJOR,
  64561. + .normal_name = SERIAL_UART00_NAME,
  64562. + .normal_driver = &normal,
  64563. + .callout_major = CALLOUT_UART00_MAJOR,
  64564. + .callout_name = CALLOUT_UART00_NAME,
  64565. + .callout_driver = &callout,
  64566. + .table = uart00_table,
  64567. + .termios = uart00_termios,
  64568. + .termios_locked = uart00_termios_locked,
  64569. + .minor = SERIAL_UART00_MINOR,
  64570. + .nr = UART_NR,
  64571. + .state = NULL,
  64572. + .cons = UART00_CONSOLE,
  64573. +};
  64574. +
  64575. +struct dev_port_entry{
  64576. + struct uart_port *port;
  64577. +};
  64578. +
  64579. +static struct dev_port_entry dev_port_map[UART_NR];
  64580. +
  64581. +#ifdef CONFIG_PLD_HOTSWAP
  64582. +/*
  64583. + * Keep a mapping of dev_info addresses -> port lines to use when
  64584. + * removing ports dev==NULL indicates unused entry
  64585. + */
  64586. +
  64587. +struct uart00_ps_data{
  64588. + unsigned int clk;
  64589. + unsigned int fifosize;
  64590. +};
  64591. +
  64592. +int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
  64593. +{
  64594. + struct uart00_ps_data* dev_ps=dev_ps_data;
  64595. + struct uart_port * port;
  64596. + int i,result;
  64597. +
  64598. + i=0;
  64599. + while(dev_port_map[i].port)
  64600. + i++;
  64601. +
  64602. + if(i==UART_NR){
  64603. + printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
  64604. + return 0;
  64605. + }
  64606. +
  64607. + port=&uart00_ports[i];
  64608. +
  64609. + printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
  64610. + port->membase=0;
  64611. + port->mapbase=dev_info->base_addr;
  64612. + port->iotype=SERIAL_IO_MEM;
  64613. + port->irq=dev_info->irq;
  64614. + port->uartclk=dev_ps->clk;
  64615. + port->fifosize=dev_ps->fifosize;
  64616. + port->ops=&uart00_pops;
  64617. + port->line=i;
  64618. + port->flags=ASYNC_BOOT_AUTOCONF;
  64619. +
  64620. + result=uart_register_port(&uart00_reg, port);
  64621. + if(result<0){
  64622. + printk("uart_register_port returned %d\n",result);
  64623. + return result;
  64624. + }
  64625. + dev_port_map[i].port=port;
  64626. + printk("uart00: added device at %lx as ttyUA%d\n",dev_port_map[i].port->mapbase,i);
  64627. + return 0;
  64628. +
  64629. +}
  64630. +
  64631. +int uart00_remove_devices(void)
  64632. +{
  64633. + int i,result;
  64634. +
  64635. +
  64636. + result=0;
  64637. + for(i=1;i<UART_NR;i++){
  64638. + if(dev_port_map[i].port){
  64639. + uart_unregister_port(&uart00_reg,i);
  64640. + dev_port_map[i].port=NULL;
  64641. + }
  64642. + }
  64643. + return 0;
  64644. +
  64645. +}
  64646. +
  64647. +#ifdef CONFIG_PROC_FS
  64648. +
  64649. +
  64650. +int uart00_proc_read(char* buf,char** start,off_t offset,int count,int *eof,void *data){
  64651. +
  64652. + int i,len=0;
  64653. + struct uart_port *port;
  64654. + int limit = count - 80;
  64655. + char ps_data[80];
  64656. + if(*start)
  64657. + buf=*start;
  64658. + for(i=0;(i<UART_NR)&&(len<limit);i++){
  64659. + if(dev_port_map[i].port){
  64660. + port=dev_port_map[i].port;
  64661. + sprintf(ps_data,"clk, %dHz, fifo size, %dbytes",
  64662. + port->uartclk,port->fifosize);
  64663. + len+=PLDHS_READ_PROC_DATA(buf+len,"uart00",i,
  64664. + port->mapbase,port->irq,ps_data);
  64665. +
  64666. + }
  64667. + }
  64668. + *eof=1;
  64669. + return len;
  64670. +}
  64671. +
  64672. +
  64673. +
  64674. +#endif
  64675. +struct pld_hotswap_ops uart00_pldhs_ops={
  64676. + .name = "uart00",
  64677. + .add_device = uart00_add_device,
  64678. + .remove_devices = uart00_remove_devices,
  64679. + .proc_read = uart00_proc_read
  64680. +};
  64681. +
  64682. +#endif
  64683. +
  64684. +static int __init uart00_init(void)
  64685. +{
  64686. + int ret;
  64687. + int i;
  64688. +
  64689. + ret = uart_register_driver(&uart00_reg);
  64690. + if (ret) {
  64691. + printk(KERN_ERR "uart00: Couldn't register driver\n");
  64692. + return ret;
  64693. + }
  64694. +
  64695. + unregister_console(&uart00_console);
  64696. +
  64697. + for(i=0;i<UART_NR;i++){
  64698. + uart00_ports[i].ops=&uart00_pops;
  64699. + }
  64700. +
  64701. + printk(KERN_WARNING "uart00:Using temporary major/minor pairs - these WILL change in the future\n");
  64702. +
  64703. +#ifdef CONFIG_PLD_HOTSWAP
  64704. + pldhs_register_driver(&uart00_pldhs_ops);
  64705. +#endif
  64706. + for (i=0; i<UART_NR; i++)
  64707. + uart_add_one_port(&uart00_reg,&uart00_ports[i]);
  64708. +
  64709. + uart00_console.flags = 0;
  64710. + register_console(&uart00_console);
  64711. +#ifdef CONFIG_ARCH_CAMELOT
  64712. + dev_port_map[0].port=uart00_ports;
  64713. +#endif
  64714. + return ret;
  64715. +}
  64716. +
  64717. +
  64718. +__initcall(uart00_init);
  64719. +
  64720. +
  64721. diff -urN linux-2.4.26/drivers/sound/.version linux-2.4.26-vrs1/drivers/sound/.version
  64722. --- linux-2.4.26/drivers/sound/.version 1997-11-10 07:01:54.000000000 +0000
  64723. +++ linux-2.4.26-vrs1/drivers/sound/.version 1970-01-01 01:00:00.000000000 +0100
  64724. @@ -1,2 +0,0 @@
  64725. -3.8s
  64726. -0x030804
  64727. diff -urN linux-2.4.26/drivers/sound/Config.in linux-2.4.26-vrs1/drivers/sound/Config.in
  64728. --- linux-2.4.26/drivers/sound/Config.in 2003-11-28 18:26:20.000000000 +0000
  64729. +++ linux-2.4.26-vrs1/drivers/sound/Config.in 2004-01-14 21:39:13.000000000 +0000
  64730. @@ -131,6 +131,17 @@
  64731. dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI
  64732. dep_mbool ' VIA 82C686 MIDI' CONFIG_MIDI_VIA82CXXX $CONFIG_SOUND_VIA82CXXX
  64733. +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
  64734. + dep_tristate ' StrongARM-11x0 Sound Drivers' CONFIG_SOUND_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_SOUND
  64735. + dep_tristate ' UDA1341 Stereo Codec' CONFIG_SOUND_UDA1341 $CONFIG_L3 $CONFIG_SOUND_SA1100 $CONFIG_SOUND
  64736. + dep_tristate ' Assabet audio support' CONFIG_SOUND_ASSABET_UDA1341 $CONFIG_SA1100_ASSABET $CONFIG_SOUND_UDA1341
  64737. + dep_tristate ' Compaq iPAQ audio support' CONFIG_SOUND_H3600_UDA1341 $CONFIG_SA1100_H3600 $CONFIG_SOUND_UDA1341
  64738. + dep_tristate ' Pangolin audio support' CONFIG_SOUND_PANGOLIN_UDA1341 $CONFIG_SA1100_PANGOLIN $CONFIG_SOUND_UDA1341
  64739. + dep_tristate ' SA1111 audio support' CONFIG_SOUND_SA1111_UDA1341 $CONFIG_SA1111 $CONFIG_SOUND_UDA1341
  64740. + dep_tristate ' SA1111 AC97 Sound' CONFIG_SOUND_SA1111_AC97 $CONFIG_SA1111 $CONFIG_SOUND_SA1100
  64741. + dep_tristate ' Generic DAC on the SA11x0 SSP port' CONFIG_SOUND_SA1100SSP $CONFIG_SOUND_SA1100
  64742. +fi
  64743. +
  64744. dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
  64745. if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
  64746. @@ -220,14 +231,14 @@
  64747. bool ' Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
  64748. fi
  64749. fi
  64750. +
  64751. +fi
  64752. - if [ "$CONFIG_ARM" = "y" ]; then
  64753. - if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
  64754. - dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
  64755. - fi
  64756. - dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
  64757. +if [ "$CONFIG_ARM" = "y" ]; then
  64758. + if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" -o "$CONFIG_ARCH_RISCSTATION" ]; then
  64759. + dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
  64760. fi
  64761. -
  64762. + dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
  64763. fi
  64764. dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
  64765. diff -urN linux-2.4.26/drivers/sound/Makefile linux-2.4.26-vrs1/drivers/sound/Makefile
  64766. --- linux-2.4.26/drivers/sound/Makefile 2003-11-28 18:26:20.000000000 +0000
  64767. +++ linux-2.4.26-vrs1/drivers/sound/Makefile 2004-01-14 21:39:13.000000000 +0000
  64768. @@ -10,7 +10,8 @@
  64769. export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
  64770. msnd.o opl3.o sb_common.o sequencer_syms.o \
  64771. sound_core.o sound_syms.o uart401.o \
  64772. - nm256_audio.o ac97.o ac97_codec.o aci.o
  64773. + nm256_audio.o ac97.o ac97_codec.o aci.o \
  64774. + sa1100-audio.o
  64775. # Each configuration option enables a list of files.
  64776. @@ -76,6 +77,14 @@
  64777. obj-$(CONFIG_SOUND_FORTE) += forte.o ac97_codec.o
  64778. obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
  64779. obj-$(CONFIG_SOUND_HARMONY) += harmony.o
  64780. +obj-$(CONFIG_SOUND_SA1100) += sa1100-audio.o
  64781. +obj-$(CONFIG_SOUND_UDA1341) += uda1341.o
  64782. +obj-$(CONFIG_SOUND_ASSABET_UDA1341) += assabet-uda1341.o
  64783. +obj-$(CONFIG_SOUND_PANGOLIN_UDA1341) += pangolin-uda1341.o
  64784. +obj-$(CONFIG_SOUND_H3600_UDA1341) += h3600-uda1341.o
  64785. +obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
  64786. +obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o
  64787. +obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o
  64788. obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
  64789. obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
  64790. obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
  64791. @@ -105,7 +114,6 @@
  64792. obj-y += dmasound/dmasound.o
  64793. endif
  64794. -
  64795. # Declare multi-part drivers.
  64796. list-multi := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
  64797. diff -urN linux-2.4.26/drivers/sound/assabet-uda1341.c linux-2.4.26-vrs1/drivers/sound/assabet-uda1341.c
  64798. --- linux-2.4.26/drivers/sound/assabet-uda1341.c 1970-01-01 01:00:00.000000000 +0100
  64799. +++ linux-2.4.26-vrs1/drivers/sound/assabet-uda1341.c 2004-01-14 21:32:26.000000000 +0000
  64800. @@ -0,0 +1,404 @@
  64801. +/*
  64802. + * Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.
  64803. + *
  64804. + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
  64805. + *
  64806. + * This program is free software; you can redistribute it and/or
  64807. + * modify it under the terms of the GNU General Public License.
  64808. + *
  64809. + * This is the machine specific part of the Assabet/UDA1341 support.
  64810. + * This driver makes use of the UDA1341 and the sa1100-audio modules.
  64811. + *
  64812. + * History:
  64813. + *
  64814. + * 2000-05-21 Nicolas Pitre Initial release.
  64815. + *
  64816. + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
  64817. + * the former sa1100-uda1341.c driver.
  64818. + *
  64819. + * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
  64820. + *
  64821. + * 2001-08-03 Russell King Fix left/right channel swap.
  64822. + * Attempt to reduce power consumption when idle.
  64823. + *
  64824. + * 2001-09-23 Russell King Remove old L3 bus driver.
  64825. + *
  64826. + * Please note that fiddling too much with MDREFR results in oopses, so we don't
  64827. + * touch MDREFR unnecessarily, which means we don't touch it on close.
  64828. + */
  64829. +
  64830. +#include <linux/module.h>
  64831. +#include <linux/init.h>
  64832. +#include <linux/types.h>
  64833. +#include <linux/fs.h>
  64834. +#include <linux/delay.h>
  64835. +#include <linux/pm.h>
  64836. +#include <linux/errno.h>
  64837. +#include <linux/sound.h>
  64838. +#include <linux/soundcard.h>
  64839. +#include <linux/cpufreq.h>
  64840. +#include <linux/l3/l3.h>
  64841. +#include <linux/l3/uda1341.h>
  64842. +
  64843. +#include <asm/semaphore.h>
  64844. +#include <asm/uaccess.h>
  64845. +#include <asm/hardware.h>
  64846. +#include <asm/dma.h>
  64847. +#include <asm/arch/assabet.h>
  64848. +
  64849. +#include "sa1100-audio.h"
  64850. +
  64851. +/*
  64852. + * Define this to fix the power drain on early Assabets
  64853. + */
  64854. +#define FIX_POWER_DRAIN
  64855. +
  64856. +/*
  64857. + * Debugging?
  64858. + */
  64859. +#undef DEBUG
  64860. +
  64861. +
  64862. +#ifdef DEBUG
  64863. +#define DPRINTK( x... ) printk( ##x )
  64864. +#else
  64865. +#define DPRINTK( x... )
  64866. +#endif
  64867. +
  64868. +
  64869. +#define AUDIO_RATE_DEFAULT 44100
  64870. +
  64871. +/*
  64872. + * Mixer (UDA1341) interface
  64873. + */
  64874. +
  64875. +static struct l3_client uda1341;
  64876. +
  64877. +static int
  64878. +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  64879. +{
  64880. + /*
  64881. + * We only accept mixer (type 'M') ioctls.
  64882. + */
  64883. + if (_IOC_TYPE(cmd) != 'M')
  64884. + return -EINVAL;
  64885. +
  64886. + return l3_command(&uda1341, cmd, (void *)arg);
  64887. +}
  64888. +
  64889. +static struct file_operations assabet_mixer_fops = {
  64890. + ioctl: mixer_ioctl,
  64891. + owner: THIS_MODULE
  64892. +};
  64893. +
  64894. +
  64895. +/*
  64896. + * Audio interface
  64897. + */
  64898. +static long audio_samplerate = AUDIO_RATE_DEFAULT;
  64899. +
  64900. +/*
  64901. + * FIXME: what about SFRM going high when SSP is disabled?
  64902. + */
  64903. +static void assabet_set_samplerate(long val)
  64904. +{
  64905. + struct uda1341_cfg cfg;
  64906. + u_int clk_ref, clk_div;
  64907. +
  64908. + /* We don't want to mess with clocks when frames are in flight */
  64909. + Ser4SSCR0 &= ~SSCR0_SSE;
  64910. + /* wait for any frame to complete */
  64911. + udelay(125);
  64912. +
  64913. + /*
  64914. + * Our clock source is derived from the CPLD on which we don't have
  64915. + * much control unfortunately. This was intended for a fixed 48000 Hz
  64916. + * samplerate assuming a core clock of 221.2 MHz. The CPLD appears
  64917. + * to divide the memory clock so there is a ratio of 4608 between
  64918. + * the core clock and the resulting samplerate (obtained by
  64919. + * measurements, the CPLD equations should confirm that).
  64920. + *
  64921. + * Still we can play with the SA1110's clock divisor for the SSP port
  64922. + * to get half the samplerate as well.
  64923. + *
  64924. + * Apparently the clock sent to the SA1110 for the SSP port is further
  64925. + * more divided from the clock sent to the UDA1341 (some people tried
  64926. + * to be too clever in their design, or simply failed to read the
  64927. + * SA1110 manual). If it was the same clock we would have been able
  64928. + * to support a third samplerate with the UDA1341's 384FS mode.
  64929. + *
  64930. + * At least it would have been a minimum acceptable solution to be
  64931. + * able to set the CPLD divisor by software. The iPAQ design is
  64932. + * certainly a better example to follow for a new design.
  64933. + */
  64934. + clk_ref = cpufreq_get(0) * 1000 / 4608;
  64935. + if (val > clk_ref*4/7) {
  64936. + audio_samplerate = clk_ref;
  64937. + cfg.fs = 256;
  64938. + clk_div = SSCR0_SerClkDiv(2);
  64939. + } else {
  64940. + audio_samplerate = clk_ref/2;
  64941. + cfg.fs = 512;
  64942. + clk_div = SSCR0_SerClkDiv(4);
  64943. + }
  64944. +
  64945. + cfg.format = FMT_LSB16;
  64946. + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
  64947. +
  64948. + Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
  64949. +}
  64950. +
  64951. +/*
  64952. + * Initialise the Assabet audio driver.
  64953. + *
  64954. + * Note that we have to be careful with the order that we do things here;
  64955. + * there is a D-type flip flop which is clocked from the SFRM line which
  64956. + * indicates whether the same is for the left or right channel to the
  64957. + * UDA1341.
  64958. + *
  64959. + * When you disable the SSP (by clearing SSCR0_SSE) it appears that the
  64960. + * SFRM signal can float high. When you re-enable the SSP, you clock the
  64961. + * flip flop once, and end up swapping the left and right channels.
  64962. + *
  64963. + * The ASSABET_BCR_CODEC_RST line will force this flip flop into a known
  64964. + * state, but this line resets other devices as well!
  64965. + *
  64966. + * In addition to the above, it appears that powering down the UDA1341 on
  64967. + * early Assabets leaves the UDA_WS actively driving a logic '1' into the
  64968. + * chip, wasting power! (you can tell this by D11 being half-on). We
  64969. + * attempt to correct this by kicking the flip flop on init/open/close.
  64970. + * We should probably do this on PM resume as well.
  64971. + *
  64972. + * (Note the ordering of ASSABET_BCR_AUDIO_ON, SFRM and ASSABET_BCR_CODEC_RST
  64973. + * is important).
  64974. + */
  64975. +static void assabet_audio_init(void *dummy)
  64976. +{
  64977. + unsigned long flags;
  64978. + unsigned int mdrefr;
  64979. +
  64980. + local_irq_save(flags);
  64981. +
  64982. + /*
  64983. + * Enable the power for the UDA1341 before driving any signals.
  64984. + * We leave the audio amp (LM4880) disabled for now.
  64985. + */
  64986. + ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON);
  64987. +
  64988. +#ifdef FIX_POWER_DRAIN
  64989. + GPSR = GPIO_SSP_SFRM;
  64990. + GPCR = GPIO_SSP_SFRM;
  64991. +#endif
  64992. +
  64993. + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
  64994. + ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB);
  64995. +
  64996. + /*
  64997. + * Setup the SSP uart.
  64998. + */
  64999. + PPAR |= PPAR_SPR;
  65000. + Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
  65001. + Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
  65002. + GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK;
  65003. + GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
  65004. + GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
  65005. + Ser4SSCR0 |= SSCR0_SSE;
  65006. +
  65007. + /*
  65008. + * Only give SFRM to the SSP after it has been enabled.
  65009. + */
  65010. + GAFR |= GPIO_SSP_SFRM;
  65011. +
  65012. + /*
  65013. + * The assabet board uses the SDRAM clock as the source clock for
  65014. + * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
  65015. + * At 206MHz we need to run the audio clock (SDRAM bank 2)
  65016. + * at half speed. This clock will scale with core frequency so
  65017. + * the audio sample rate will also scale. The CPLD on Assabet
  65018. + * will need to be programmed to match the core frequency.
  65019. + */
  65020. + mdrefr = MDREFR;
  65021. + if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
  65022. + MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
  65023. + mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
  65024. + mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
  65025. + MDREFR = mdrefr;
  65026. + (void) MDREFR;
  65027. + }
  65028. + local_irq_restore(flags);
  65029. +
  65030. + /* Wait for the UDA1341 to wake up */
  65031. + mdelay(1);
  65032. +
  65033. + l3_open(&uda1341);
  65034. +
  65035. + assabet_set_samplerate(audio_samplerate);
  65036. +
  65037. + /* Enable the audio power */
  65038. + ASSABET_BCR_clear(ASSABET_BCR_QMUTE | ASSABET_BCR_SPK_OFF);
  65039. +}
  65040. +
  65041. +/*
  65042. + * Shutdown the Assabet audio driver.
  65043. + *
  65044. + * We have to be careful about the SFRM line here for the same reasons
  65045. + * described in the initialisation comments above. This basically means
  65046. + * that we must hand the SSP pins back to the GPIO module before disabling
  65047. + * the SSP.
  65048. + *
  65049. + * In addition, to reduce power drain, we toggle the SFRM line once so
  65050. + * that the UDA_WS line is at logic 0.
  65051. + *
  65052. + * We can't clear ASSABET_BCR_CODEC_RST without knowing if the UCB1300 or
  65053. + * ADV7171 driver is still active. If it is, then we still need to play
  65054. + * games, so we might as well leave ASSABET_BCR_CODEC_RST set.
  65055. + */
  65056. +static void assabet_audio_shutdown(void *dummy)
  65057. +{
  65058. + ASSABET_BCR_set(ASSABET_BCR_STEREO_LB | ASSABET_BCR_QMUTE |
  65059. + ASSABET_BCR_SPK_OFF);
  65060. +
  65061. + l3_close(&uda1341);
  65062. +
  65063. + GAFR &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
  65064. + Ser4SSCR0 = 0;
  65065. +
  65066. +#ifdef FIX_POWER_DRAIN
  65067. + GPSR = GPIO_SSP_SFRM;
  65068. + GPCR = GPIO_SSP_SFRM;
  65069. +#endif
  65070. +
  65071. + /* disable the audio power */
  65072. + ASSABET_BCR_clear(ASSABET_BCR_AUDIO_ON);
  65073. +}
  65074. +
  65075. +static int assabet_audio_ioctl( struct inode *inode, struct file *file,
  65076. + uint cmd, ulong arg)
  65077. +{
  65078. + long val;
  65079. + int ret = 0;
  65080. +
  65081. + /*
  65082. + * These are platform dependent ioctls which are not handled by the
  65083. + * generic sa1100-audio module.
  65084. + */
  65085. + switch (cmd) {
  65086. + case SNDCTL_DSP_STEREO:
  65087. + ret = get_user(val, (int *) arg);
  65088. + if (ret)
  65089. + return ret;
  65090. + /* the UDA1341 is stereo only */
  65091. + ret = (val == 0) ? -EINVAL : 1;
  65092. + return put_user(ret, (int *) arg);
  65093. +
  65094. + case SNDCTL_DSP_CHANNELS:
  65095. + case SOUND_PCM_READ_CHANNELS:
  65096. + /* the UDA1341 is stereo only */
  65097. + return put_user(2, (long *) arg);
  65098. +
  65099. + case SNDCTL_DSP_SPEED:
  65100. + ret = get_user(val, (long *) arg);
  65101. + if (ret) break;
  65102. + assabet_set_samplerate(val);
  65103. + /* fall through */
  65104. +
  65105. + case SOUND_PCM_READ_RATE:
  65106. + return put_user(audio_samplerate, (long *) arg);
  65107. +
  65108. + case SNDCTL_DSP_SETFMT:
  65109. + case SNDCTL_DSP_GETFMTS:
  65110. + /* we can do signed 16-bit only */
  65111. + return put_user(AFMT_S16_LE, (long *) arg);
  65112. +
  65113. + default:
  65114. + /* Maybe this is meant for the mixer (As per OSS Docs) */
  65115. + return mixer_ioctl(inode, file, cmd, arg);
  65116. + }
  65117. +
  65118. + return ret;
  65119. +}
  65120. +
  65121. +static audio_stream_t output_stream, input_stream;
  65122. +
  65123. +static audio_state_t audio_state = {
  65124. + output_stream: &output_stream,
  65125. + output_dma: DMA_Ser4SSPWr,
  65126. + output_id: "Assabet UDA1341 out",
  65127. + input_stream: &input_stream,
  65128. + input_dma: DMA_Ser4SSPRd,
  65129. + input_id: "Assabet UDA1341 in",
  65130. + need_tx_for_rx: 1,
  65131. + hw_init: assabet_audio_init,
  65132. + hw_shutdown: assabet_audio_shutdown,
  65133. + client_ioctl: assabet_audio_ioctl,
  65134. + sem: __MUTEX_INITIALIZER(audio_state.sem),
  65135. +};
  65136. +
  65137. +static int assabet_audio_open(struct inode *inode, struct file *file)
  65138. +{
  65139. + return sa1100_audio_attach(inode, file, &audio_state);
  65140. +}
  65141. +
  65142. +/*
  65143. + * Missing fields of this structure will be patched with the call
  65144. + * to sa1100_audio_attach().
  65145. + */
  65146. +static struct file_operations assabet_audio_fops = {
  65147. + open: assabet_audio_open,
  65148. + owner: THIS_MODULE
  65149. +};
  65150. +
  65151. +
  65152. +static int audio_dev_id, mixer_dev_id;
  65153. +
  65154. +static int __init assabet_uda1341_init(void)
  65155. +{
  65156. + int ret;
  65157. +
  65158. + if (!machine_is_assabet())
  65159. + return -ENODEV;
  65160. +
  65161. + ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
  65162. + if (ret)
  65163. + goto out;
  65164. +
  65165. + /* register devices */
  65166. + audio_dev_id = register_sound_dsp(&assabet_audio_fops, -1);
  65167. + mixer_dev_id = register_sound_mixer(&assabet_mixer_fops, -1);
  65168. +
  65169. +#ifdef FIX_POWER_DRAIN
  65170. + {
  65171. + unsigned long flags;
  65172. + local_irq_save(flags);
  65173. + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
  65174. + GPSR = GPIO_SSP_SFRM;
  65175. + GPDR |= GPIO_SSP_SFRM;
  65176. + GPCR = GPIO_SSP_SFRM;
  65177. + local_irq_restore(flags);
  65178. + }
  65179. +#endif
  65180. +
  65181. + printk(KERN_INFO "Sound: Assabet UDA1341: dsp id %d mixer id %d\n",
  65182. + audio_dev_id, mixer_dev_id);
  65183. + return 0;
  65184. +
  65185. +release_l3:
  65186. + l3_detach_client(&uda1341);
  65187. +out:
  65188. + return ret;
  65189. +}
  65190. +
  65191. +static void __exit assabet_uda1341_exit(void)
  65192. +{
  65193. + unregister_sound_dsp(audio_dev_id);
  65194. + unregister_sound_mixer(mixer_dev_id);
  65195. + l3_detach_client(&uda1341);
  65196. +}
  65197. +
  65198. +module_init(assabet_uda1341_init);
  65199. +module_exit(assabet_uda1341_exit);
  65200. +
  65201. +MODULE_AUTHOR("Nicolas Pitre");
  65202. +MODULE_DESCRIPTION("Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.");
  65203. +
  65204. +EXPORT_NO_SYMBOLS;
  65205. diff -urN linux-2.4.26/drivers/sound/h3600-uda1341.c linux-2.4.26-vrs1/drivers/sound/h3600-uda1341.c
  65206. --- linux-2.4.26/drivers/sound/h3600-uda1341.c 1970-01-01 01:00:00.000000000 +0100
  65207. +++ linux-2.4.26-vrs1/drivers/sound/h3600-uda1341.c 2004-01-14 21:32:26.000000000 +0000
  65208. @@ -0,0 +1,352 @@
  65209. +/*
  65210. + * Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.
  65211. + *
  65212. + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
  65213. + *
  65214. + * This program is free software; you can redistribute it and/or
  65215. + * modify it under the terms of the GNU General Public License.
  65216. + *
  65217. + * This is the machine specific part of the Compaq iPAQ (aka Bitsy) support.
  65218. + * This driver makes use of the UDA1341 and the sa1100-audio modules.
  65219. + *
  65220. + * History:
  65221. + *
  65222. + * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release.
  65223. + *
  65224. + * 2000-07-?? George France Bitsy support.
  65225. + *
  65226. + * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/h3600
  65227. + *
  65228. + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
  65229. + * the former sa1100-uda1341.c driver.
  65230. + *
  65231. + * 2001-07-13 Nicolas Pitre Fixes for all supported samplerates.
  65232. + *
  65233. + */
  65234. +
  65235. +#include <linux/module.h>
  65236. +#include <linux/init.h>
  65237. +#include <linux/types.h>
  65238. +#include <linux/fs.h>
  65239. +#include <linux/delay.h>
  65240. +#include <linux/pm.h>
  65241. +#include <linux/errno.h>
  65242. +#include <linux/sound.h>
  65243. +#include <linux/soundcard.h>
  65244. +#include <linux/l3/l3.h>
  65245. +#include <linux/l3/uda1341.h>
  65246. +
  65247. +#include <asm/semaphore.h>
  65248. +#include <asm/uaccess.h>
  65249. +#include <asm/hardware.h>
  65250. +#include <asm/dma.h>
  65251. +//#include <asm/arch/h3600_hal.h>
  65252. +
  65253. +#include "sa1100-audio.h"
  65254. +
  65255. +
  65256. +#undef DEBUG
  65257. +#ifdef DEBUG
  65258. +#define DPRINTK( x... ) printk( ##x )
  65259. +#else
  65260. +#define DPRINTK( x... )
  65261. +#endif
  65262. +
  65263. +
  65264. +#define AUDIO_NAME "Bitsy_UDA1341"
  65265. +
  65266. +#define AUDIO_RATE_DEFAULT 44100
  65267. +
  65268. +
  65269. +static struct l3_client uda1341;
  65270. +
  65271. +static int
  65272. +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  65273. +{
  65274. + /*
  65275. + * We only accept mixer (type 'M') ioctls.
  65276. + */
  65277. + if (_IOC_TYPE(cmd) != 'M')
  65278. + return -EINVAL;
  65279. +
  65280. + return l3_command(&uda1341, cmd, (void *)arg);
  65281. +}
  65282. +
  65283. +static struct file_operations h3600_mixer_fops = {
  65284. + ioctl: mixer_ioctl,
  65285. + owner: THIS_MODULE
  65286. +};
  65287. +
  65288. +
  65289. +/*
  65290. + * Audio interface
  65291. + */
  65292. +
  65293. +static long audio_samplerate = AUDIO_RATE_DEFAULT;
  65294. +
  65295. +/*
  65296. + * Stop-gap solution until rest of hh.org HAL stuff is merged.
  65297. + */
  65298. +#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
  65299. +#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
  65300. +static void h3600_set_audio_clock(long val)
  65301. +{
  65302. + switch (val) {
  65303. + case 24000: case 32000: case 48000: /* 00: 12.288 MHz */
  65304. + GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
  65305. + break;
  65306. +
  65307. + case 22050: case 29400: case 44100: /* 01: 11.2896 MHz */
  65308. + GPSR = GPIO_H3600_CLK_SET0;
  65309. + GPCR = GPIO_H3600_CLK_SET1;
  65310. + break;
  65311. +
  65312. + case 8000: case 10666: case 16000: /* 10: 4.096 MHz */
  65313. + GPCR = GPIO_H3600_CLK_SET0;
  65314. + GPSR = GPIO_H3600_CLK_SET1;
  65315. + break;
  65316. +
  65317. + case 10985: case 14647: case 21970: /* 11: 5.6245 MHz */
  65318. + GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
  65319. + break;
  65320. + }
  65321. +}
  65322. +
  65323. +static void h3600_set_samplerate(long val)
  65324. +{
  65325. + struct uda1341_cfg cfg;
  65326. + int clk_div = 0;
  65327. +
  65328. + /* We don't want to mess with clocks when frames are in flight */
  65329. + Ser4SSCR0 &= ~SSCR0_SSE;
  65330. + /* wait for any frame to complete */
  65331. + udelay(125);
  65332. +
  65333. + /*
  65334. + * We have the following clock sources:
  65335. + * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz
  65336. + * Those can be divided either by 256, 384 or 512.
  65337. + * This makes up 12 combinations for the following samplerates...
  65338. + */
  65339. + if (val >= 48000)
  65340. + val = 48000;
  65341. + else if (val >= 44100)
  65342. + val = 44100;
  65343. + else if (val >= 32000)
  65344. + val = 32000;
  65345. + else if (val >= 29400)
  65346. + val = 29400;
  65347. + else if (val >= 24000)
  65348. + val = 24000;
  65349. + else if (val >= 22050)
  65350. + val = 22050;
  65351. + else if (val >= 21970)
  65352. + val = 21970;
  65353. + else if (val >= 16000)
  65354. + val = 16000;
  65355. + else if (val >= 14647)
  65356. + val = 14647;
  65357. + else if (val >= 10985)
  65358. + val = 10985;
  65359. + else if (val >= 10666)
  65360. + val = 10666;
  65361. + else
  65362. + val = 8000;
  65363. +
  65364. + /* Set the external clock generator */
  65365. + h3600_set_audio_clock(val);
  65366. +
  65367. + /* Select the clock divisor */
  65368. + switch (val) {
  65369. + case 8000:
  65370. + case 10985:
  65371. + case 22050:
  65372. + case 24000:
  65373. + cfg.fs = 512;
  65374. + clk_div = SSCR0_SerClkDiv(16);
  65375. + break;
  65376. + case 16000:
  65377. + case 21970:
  65378. + case 44100:
  65379. + case 48000:
  65380. + cfg.fs = 256;
  65381. + clk_div = SSCR0_SerClkDiv(8);
  65382. + break;
  65383. + case 10666:
  65384. + case 14647:
  65385. + case 29400:
  65386. + case 32000:
  65387. + cfg.fs = 384;
  65388. + clk_div = SSCR0_SerClkDiv(12);
  65389. + break;
  65390. + }
  65391. +
  65392. + cfg.format = FMT_LSB16;
  65393. + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
  65394. + Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
  65395. + audio_samplerate = val;
  65396. +}
  65397. +
  65398. +static void h3600_audio_init(void *dummy)
  65399. +{
  65400. + unsigned long flags;
  65401. +
  65402. + /* Setup the uarts */
  65403. + local_irq_save(flags);
  65404. + GAFR |= (GPIO_SSP_CLK);
  65405. + GPDR &= ~(GPIO_SSP_CLK);
  65406. + Ser4SSCR0 = 0;
  65407. + Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);
  65408. + Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
  65409. + Ser4SSCR0 |= SSCR0_SSE;
  65410. +
  65411. + /* Enable the audio power */
  65412. +
  65413. + clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
  65414. + set_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
  65415. + set_h3600_egpio(IPAQ_EGPIO_QMUTE);
  65416. + local_irq_restore(flags);
  65417. +
  65418. + /* external clock configuration */
  65419. + h3600_set_samplerate(audio_samplerate);
  65420. +
  65421. + /* Wait for the UDA1341 to wake up */
  65422. + set_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
  65423. + mdelay(1);
  65424. +
  65425. + /* make the left and right channels unswapped (flip the WS latch ) */
  65426. + Ser4SSDR = 0;
  65427. +
  65428. + /* Initialize the UDA1341 internal state */
  65429. + l3_open(&uda1341);
  65430. +
  65431. + clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
  65432. +}
  65433. +
  65434. +static void h3600_audio_shutdown(void *dummy)
  65435. +{
  65436. + /* disable the audio power and all signals leading to the audio chip */
  65437. + l3_close(&uda1341);
  65438. + Ser4SSCR0 = 0;
  65439. + clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
  65440. + clr_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
  65441. + clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
  65442. +}
  65443. +
  65444. +static int h3600_audio_ioctl(struct inode *inode, struct file *file,
  65445. + uint cmd, ulong arg)
  65446. +{
  65447. + long val;
  65448. + int ret = 0;
  65449. +
  65450. + /*
  65451. + * These are platform dependent ioctls which are not handled by the
  65452. + * generic sa1100-audio module.
  65453. + */
  65454. + switch (cmd) {
  65455. + case SNDCTL_DSP_STEREO:
  65456. + ret = get_user(val, (int *) arg);
  65457. + if (ret)
  65458. + return ret;
  65459. + /* the UDA1341 is stereo only */
  65460. + ret = (val == 0) ? -EINVAL : 1;
  65461. + return put_user(ret, (int *) arg);
  65462. +
  65463. + case SNDCTL_DSP_CHANNELS:
  65464. + case SOUND_PCM_READ_CHANNELS:
  65465. + /* the UDA1341 is stereo only */
  65466. + return put_user(2, (long *) arg);
  65467. +
  65468. + case SNDCTL_DSP_SPEED:
  65469. + ret = get_user(val, (long *) arg);
  65470. + if (ret) break;
  65471. + h3600_set_samplerate(val);
  65472. + /* fall through */
  65473. +
  65474. + case SOUND_PCM_READ_RATE:
  65475. + return put_user(audio_samplerate, (long *) arg);
  65476. +
  65477. + case SNDCTL_DSP_SETFMT:
  65478. + case SNDCTL_DSP_GETFMTS:
  65479. + /* we can do 16-bit only */
  65480. + return put_user(AFMT_S16_LE, (long *) arg);
  65481. +
  65482. + default:
  65483. + /* Maybe this is meant for the mixer (As per OSS Docs) */
  65484. + return mixer_ioctl(inode, file, cmd, arg);
  65485. + }
  65486. +
  65487. + return ret;
  65488. +}
  65489. +
  65490. +static audio_stream_t output_stream, input_stream;
  65491. +
  65492. +static audio_state_t audio_state = {
  65493. + output_stream: &output_stream,
  65494. + output_dma: DMA_Ser4SSPWr,
  65495. + output_id: "UDA1341 out",
  65496. + input_stream: &input_stream,
  65497. + input_dma: DMA_Ser4SSPRd,
  65498. + input_id: "UDA1341 in",
  65499. + need_tx_for_rx: 1,
  65500. + hw_init: h3600_audio_init,
  65501. + hw_shutdown: h3600_audio_shutdown,
  65502. + client_ioctl: h3600_audio_ioctl,
  65503. + sem: __MUTEX_INITIALIZER(audio_state.sem),
  65504. +};
  65505. +
  65506. +static int h3600_audio_open(struct inode *inode, struct file *file)
  65507. +{
  65508. + return sa1100_audio_attach(inode, file, &audio_state);
  65509. +}
  65510. +
  65511. +/*
  65512. + * Missing fields of this structure will be patched with the call
  65513. + * to sa1100_audio_attach().
  65514. + */
  65515. +static struct file_operations h3600_audio_fops = {
  65516. + open: h3600_audio_open,
  65517. + owner: THIS_MODULE
  65518. +};
  65519. +
  65520. +
  65521. +static int audio_dev_id, mixer_dev_id;
  65522. +
  65523. +static int __init h3600_uda1341_init(void)
  65524. +{
  65525. + int ret;
  65526. +
  65527. + if (!machine_is_h3xxx())
  65528. + return -ENODEV;
  65529. +
  65530. + ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
  65531. + if (ret)
  65532. + goto out;
  65533. +
  65534. + /* register devices */
  65535. + audio_dev_id = register_sound_dsp(&h3600_audio_fops, -1);
  65536. + mixer_dev_id = register_sound_mixer(&h3600_mixer_fops, -1);
  65537. +
  65538. + printk( KERN_INFO "iPAQ audio support initialized\n" );
  65539. + return 0;
  65540. +
  65541. +release_l3:
  65542. + l3_detach_client(&uda1341);
  65543. +out:
  65544. + return ret;
  65545. +}
  65546. +
  65547. +static void __exit h3600_uda1341_exit(void)
  65548. +{
  65549. + unregister_sound_dsp(audio_dev_id);
  65550. + unregister_sound_mixer(mixer_dev_id);
  65551. + l3_detach_client(&uda1341);
  65552. +}
  65553. +
  65554. +module_init(h3600_uda1341_init);
  65555. +module_exit(h3600_uda1341_exit);
  65556. +
  65557. +MODULE_AUTHOR("Nicolas Pitre, George France");
  65558. +MODULE_DESCRIPTION("Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.");
  65559. +
  65560. +EXPORT_NO_SYMBOLS;
  65561. diff -urN linux-2.4.26/drivers/sound/pangolin-uda1341.c linux-2.4.26-vrs1/drivers/sound/pangolin-uda1341.c
  65562. --- linux-2.4.26/drivers/sound/pangolin-uda1341.c 1970-01-01 01:00:00.000000000 +0100
  65563. +++ linux-2.4.26-vrs1/drivers/sound/pangolin-uda1341.c 2004-01-14 21:32:26.000000000 +0000
  65564. @@ -0,0 +1,322 @@
  65565. +/*
  65566. + * Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.
  65567. + *
  65568. + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
  65569. + *
  65570. + * This program is free software; you can redistribute it and/or
  65571. + * modify it under the terms of the GNU General Public License.
  65572. + *
  65573. + * This is the machine specific part of the Pangolin/UDA1341 support.
  65574. + * This driver makes use of the UDA1341 and the sa1100-audio modules.
  65575. + *
  65576. + * History:
  65577. + *
  65578. + * 2000-05-21 Nicolas Pitre Initial release.
  65579. + *
  65580. + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
  65581. + * the former sa1100-uda1341.c driver.
  65582. + *
  65583. + * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
  65584. + *
  65585. + * 2001-08-06 Richard Fan Pangolin Support
  65586. + *
  65587. + * 2001-09-23 Russell King Update inline with Assabet driver
  65588. + * Remove old L3 bus driver
  65589. + *
  65590. + * Note: this should probably be merged with the Assabet audio driver,
  65591. + * and become the "SDRAM-clock driven" SA1100 audio driver.
  65592. + */
  65593. +
  65594. +#include <linux/module.h>
  65595. +#include <linux/init.h>
  65596. +#include <linux/types.h>
  65597. +#include <linux/fs.h>
  65598. +#include <linux/delay.h>
  65599. +#include <linux/pm.h>
  65600. +#include <linux/errno.h>
  65601. +#include <linux/sound.h>
  65602. +#include <linux/soundcard.h>
  65603. +#include <linux/l3/l3.h>
  65604. +#include <linux/l3/uda1341.h>
  65605. +
  65606. +#include <asm/semaphore.h>
  65607. +#include <asm/uaccess.h>
  65608. +#include <asm/hardware.h>
  65609. +#include <asm/dma.h>
  65610. +
  65611. +#include "sa1100-audio.h"
  65612. +
  65613. +/*
  65614. + * Debugging?
  65615. + */
  65616. +#undef DEBUG
  65617. +
  65618. +
  65619. +#ifdef DEBUG
  65620. +#define DPRINTK( x... ) printk( ##x )
  65621. +#else
  65622. +#define DPRINTK( x... )
  65623. +#endif
  65624. +
  65625. +
  65626. +#define AUDIO_RATE_DEFAULT 44100
  65627. +
  65628. +#define QmutePin GPIO_GPIO(4)
  65629. +#define SpeakerOffPin GPIO_GPIO(5)
  65630. +
  65631. +/*
  65632. + * Mixer (UDA1341) interface
  65633. + */
  65634. +
  65635. +static struct l3_client uda1341;
  65636. +
  65637. +static int
  65638. +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  65639. +{
  65640. + /*
  65641. + * We only accept mixer (type 'M') ioctls.
  65642. + */
  65643. + if (_IOC_TYPE(cmd) != 'M')
  65644. + return -EINVAL;
  65645. +
  65646. + return l3_command(&uda1341, cmd, (void *)arg);
  65647. +}
  65648. +
  65649. +static struct file_operations pangolin_mixer_fops = {
  65650. + ioctl: mixer_ioctl,
  65651. + owner: THIS_MODULE
  65652. +};
  65653. +
  65654. +
  65655. +/*
  65656. + * Audio interface
  65657. + */
  65658. +static long audio_samplerate = AUDIO_RATE_DEFAULT;
  65659. +
  65660. +static void pangolin_set_samplerate(long val)
  65661. +{
  65662. + struct uda1341_cfg cfg;
  65663. + int clk_div;
  65664. +
  65665. + /* We don't want to mess with clocks when frames are in flight */
  65666. + Ser4SSCR0 &= ~SSCR0_SSE;
  65667. + /* wait for any frame to complete */
  65668. + udelay(125);
  65669. +
  65670. + /*
  65671. + * Our clock source is derived from the CPLD on which we don't have
  65672. + * much control unfortunately. This was intended for a fixed 44100Hz
  65673. + * samplerate assuming a core clock of 206 MHz. Still we can play
  65674. + * with the SA1110's clock divisor for the SSP port to get a 22050Hz
  65675. + * samplerate.
  65676. + *
  65677. + * Apparently the clock sent to the SA1110 for the SSP port is
  65678. + * divided from the clock sent to the UDA1341 (some people tried to
  65679. + * be too clever in their design, or simply failed to read the SA1110
  65680. + * manual). If it was the same source we would have been able to
  65681. + * support a third samplerate.
  65682. + *
  65683. + * At least it would have been a minimum acceptable solution to be
  65684. + * able to set the CPLD divisor by software. The iPAQ design is
  65685. + * certainly a better example to follow for a new design.
  65686. + */
  65687. + if (val >= 44100) {
  65688. + audio_samplerate = 44100;
  65689. + cfg.fs = 256;
  65690. + clk_div = SSCR0_SerClkDiv(2);
  65691. + } else {
  65692. + audio_samplerate = 22050;
  65693. + cfg.fs = 512;
  65694. + clk_div = SSCR0_SerClkDiv(4);
  65695. + }
  65696. +
  65697. + cfg.format = FMT_LSB16;
  65698. + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
  65699. +
  65700. + Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
  65701. +}
  65702. +
  65703. +static void pangolin_audio_init(void *dummy)
  65704. +{
  65705. + unsigned long flags;
  65706. + unsigned int mdrefr;
  65707. +
  65708. + local_irq_save(flags);
  65709. +
  65710. + /*
  65711. + * Setup the SSP uart.
  65712. + */
  65713. + PPAR |= PPAR_SPR;
  65714. + Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
  65715. + Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
  65716. + GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK |
  65717. + GPIO_SSP_SFRM;
  65718. + GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
  65719. + GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
  65720. + Ser4SSCR0 |= SSCR0_SSE;
  65721. +
  65722. + GAFR &= ~(SpeakerOffPin | QmutePin);
  65723. + GPDR |= (SpeakerOffPin | QmutePin);
  65724. + GPCR = SpeakerOffPin;
  65725. +
  65726. + /*
  65727. + * The assabet board uses the SDRAM clock as the source clock for
  65728. + * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
  65729. + * At 206MHz we need to run the audio clock (SDRAM bank 2)
  65730. + * at half speed. This clock will scale with core frequency so
  65731. + * the audio sample rate will also scale. The CPLD on Assabet
  65732. + * will need to be programmed to match the core frequency.
  65733. + */
  65734. + mdrefr = MDREFR;
  65735. + if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
  65736. + MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
  65737. + mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
  65738. + mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
  65739. + MDREFR = mdrefr;
  65740. + (void) MDREFR;
  65741. + }
  65742. + local_irq_restore(flags);
  65743. +
  65744. + /* Wait for the UDA1341 to wake up */
  65745. + mdelay(100);
  65746. +
  65747. + l3_open(&uda1341);
  65748. +
  65749. + pangolin_set_samplerate(audio_samplerate);
  65750. +
  65751. + GPCR = QmutePin;
  65752. +}
  65753. +
  65754. +static void pangolin_audio_shutdown(void *dummy)
  65755. +{
  65756. + GPSR = QmutePin;
  65757. +
  65758. + l3_close(&uda1341);
  65759. +
  65760. + Ser4SSCR0 = 0;
  65761. + MDREFR &= ~(MDREFR_K2DB2 | MDREFR_K2RUN);
  65762. +}
  65763. +
  65764. +static int pangolin_audio_ioctl( struct inode *inode, struct file *file,
  65765. + uint cmd, ulong arg)
  65766. +{
  65767. + long val;
  65768. + int ret = 0;
  65769. +
  65770. + /*
  65771. + * These are platform dependent ioctls which are not handled by the
  65772. + * generic sa1100-audio module.
  65773. + */
  65774. + switch (cmd) {
  65775. + case SNDCTL_DSP_STEREO:
  65776. + ret = get_user(val, (int *) arg);
  65777. + if (ret)
  65778. + return ret;
  65779. + /* the UDA1341 is stereo only */
  65780. + ret = (val == 0) ? -EINVAL : 1;
  65781. + return put_user(ret, (int *) arg);
  65782. +
  65783. + case SNDCTL_DSP_CHANNELS:
  65784. + case SOUND_PCM_READ_CHANNELS:
  65785. + /* the UDA1341 is stereo only */
  65786. + return put_user(2, (long *) arg);
  65787. +
  65788. + case SNDCTL_DSP_SPEED:
  65789. + ret = get_user(val, (long *) arg);
  65790. + if (ret) break;
  65791. + pangolin_set_samplerate(val);
  65792. + /* fall through */
  65793. +
  65794. + case SOUND_PCM_READ_RATE:
  65795. + return put_user(audio_samplerate, (long *) arg);
  65796. +
  65797. + case SNDCTL_DSP_SETFMT:
  65798. + case SNDCTL_DSP_GETFMTS:
  65799. + /* we can do signed 16-bit only */
  65800. + return put_user(AFMT_S16_LE, (long *) arg);
  65801. +
  65802. + default:
  65803. + /* Maybe this is meant for the mixer (As per OSS Docs) */
  65804. + return mixer_ioctl(inode, file, cmd, arg);
  65805. + }
  65806. +
  65807. + return ret;
  65808. +}
  65809. +
  65810. +static audio_stream_t output_stream, input_stream;
  65811. +
  65812. +static audio_state_t audio_state = {
  65813. + output_stream: &output_stream,
  65814. + output_dma: DMA_Ser4SSPWr,
  65815. + output_id: "Pangolin UDA1341 out",
  65816. + input_stream: &input_stream,
  65817. + input_dma: DMA_Ser4SSPRd,
  65818. + input_id: "Pangolin UDA1341 in",
  65819. + need_tx_for_rx: 1,
  65820. + hw_init: pangolin_audio_init,
  65821. + hw_shutdown: pangolin_audio_shutdown,
  65822. + client_ioctl: pangolin_audio_ioctl,
  65823. + sem: __MUTEX_INITIALIZER(audio_state.sem),
  65824. +};
  65825. +
  65826. +static int pangolin_audio_open(struct inode *inode, struct file *file)
  65827. +{
  65828. + return sa1100_audio_attach(inode, file, &audio_state);
  65829. +}
  65830. +
  65831. +/*
  65832. + * Missing fields of this structure will be patched with the call
  65833. + * to sa1100_audio_attach().
  65834. + */
  65835. +static struct file_operations pangolin_audio_fops = {
  65836. + open: pangolin_audio_open,
  65837. + owner: THIS_MODULE
  65838. +};
  65839. +
  65840. +
  65841. +static int audio_dev_id, mixer_dev_id;
  65842. +
  65843. +static int __init pangolin_uda1341_init(void)
  65844. +{
  65845. + unsigned long flags;
  65846. + int ret;
  65847. +
  65848. + if (!machine_is_pangolin())
  65849. + return -ENODEV;
  65850. +
  65851. + ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
  65852. + if (ret)
  65853. + goto out;
  65854. +
  65855. + /* register devices */
  65856. + audio_dev_id = register_sound_dsp(&pangolin_audio_fops, -1);
  65857. + mixer_dev_id = register_sound_mixer(&pangolin_mixer_fops, -1);
  65858. +
  65859. + local_irq_save(flags);
  65860. + GAFR &= ~(SpeakerOffPin | QmutePin);
  65861. + GPDR |= (SpeakerOffPin | QmutePin);
  65862. + local_irq_restore(flags);
  65863. +
  65864. + printk(KERN_INFO "Pangolin UDA1341 audio driver initialized\n");
  65865. + return 0;
  65866. +
  65867. +release_l3:
  65868. + l3_detach_client(&uda1341);
  65869. +out:
  65870. + return ret;
  65871. +}
  65872. +
  65873. +static void __exit pangolin_uda1341_exit(void)
  65874. +{
  65875. + unregister_sound_dsp(audio_dev_id);
  65876. + unregister_sound_mixer(mixer_dev_id);
  65877. + l3_detach_client(&uda1341);
  65878. +}
  65879. +
  65880. +module_init(pangolin_uda1341_init);
  65881. +module_exit(pangolin_uda1341_exit);
  65882. +
  65883. +MODULE_AUTHOR("Nicolas Pitre");
  65884. +MODULE_DESCRIPTION("Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.");
  65885. +
  65886. +EXPORT_NO_SYMBOLS;
  65887. diff -urN linux-2.4.26/drivers/sound/sa1100-audio.c linux-2.4.26-vrs1/drivers/sound/sa1100-audio.c
  65888. --- linux-2.4.26/drivers/sound/sa1100-audio.c 1970-01-01 01:00:00.000000000 +0100
  65889. +++ linux-2.4.26-vrs1/drivers/sound/sa1100-audio.c 2004-01-14 21:32:26.000000000 +0000
  65890. @@ -0,0 +1,976 @@
  65891. +/*
  65892. + * Common audio handling for the SA11x0 processor
  65893. + *
  65894. + * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
  65895. + *
  65896. + * This program is free software; you can redistribute it and/or
  65897. + * modify it under the terms of the GNU General Public License.
  65898. + *
  65899. + *
  65900. + * This module handles the generic buffering/DMA/mmap audio interface for
  65901. + * codecs connected to the SA1100 chip. All features depending on specific
  65902. + * hardware implementations like supported audio formats or samplerates are
  65903. + * relegated to separate specific modules.
  65904. + *
  65905. + *
  65906. + * History:
  65907. + *
  65908. + * 2000-05-21 Nicolas Pitre Initial release.
  65909. + *
  65910. + * 2000-06-10 Erik Bunce Add initial poll support.
  65911. + *
  65912. + * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the
  65913. + * generic SA1100 DMA interface.
  65914. + *
  65915. + * 2000-11-30 Nicolas Pitre - Validation of opened instances;
  65916. + * - Power handling at open/release time instead
  65917. + * of driver load/unload;
  65918. + *
  65919. + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
  65920. + * the former sa1100-uda1341.c driver.
  65921. + *
  65922. + * 2001-07-22 Nicolas Pitre - added mmap() and realtime support
  65923. + * - corrected many details to better comply
  65924. + * with the OSS API
  65925. + *
  65926. + * 2001-10-19 Nicolas Pitre - brought DMA registration processing
  65927. + * into this module for better ressource
  65928. + * management. This also fixes a bug
  65929. + * with the suspend/resume logic.
  65930. + */
  65931. +
  65932. +#include <linux/module.h>
  65933. +#include <linux/init.h>
  65934. +#include <linux/types.h>
  65935. +#include <linux/fs.h>
  65936. +#include <linux/mm.h>
  65937. +#include <linux/slab.h>
  65938. +#include <linux/sched.h>
  65939. +#include <linux/poll.h>
  65940. +#include <linux/pm.h>
  65941. +#include <linux/errno.h>
  65942. +#include <linux/sound.h>
  65943. +#include <linux/soundcard.h>
  65944. +#include <linux/sysrq.h>
  65945. +
  65946. +#include <asm/uaccess.h>
  65947. +#include <asm/io.h>
  65948. +#include <asm/hardware.h>
  65949. +#include <asm/semaphore.h>
  65950. +#include <asm/dma.h>
  65951. +
  65952. +#include "sa1100-audio.h"
  65953. +
  65954. +
  65955. +#undef DEBUG
  65956. +/* #define DEBUG 1 */
  65957. +#ifdef DEBUG
  65958. +#define DPRINTK( x... ) printk( ##x )
  65959. +#else
  65960. +#define DPRINTK( x... )
  65961. +#endif
  65962. +
  65963. +
  65964. +#define AUDIO_NAME "sa1100-audio"
  65965. +#define AUDIO_NBFRAGS_DEFAULT 8
  65966. +#define AUDIO_FRAGSIZE_DEFAULT 8192
  65967. +
  65968. +#define NEXT_BUF(_s_,_b_) { \
  65969. + (_s_)->_b_##_idx++; \
  65970. + (_s_)->_b_##_idx %= (_s_)->nbfrags; \
  65971. + (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; }
  65972. +
  65973. +#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref)
  65974. +
  65975. +/*
  65976. + * This function frees all buffers
  65977. + */
  65978. +
  65979. +static void audio_clear_buf(audio_stream_t * s)
  65980. +{
  65981. + DPRINTK("audio_clear_buf\n");
  65982. +
  65983. + /* ensure DMA won't run anymore */
  65984. + s->active = 0;
  65985. + s->stopped = 0;
  65986. + sa1100_dma_flush_all(s->dma_ch);
  65987. +
  65988. + if (s->buffers) {
  65989. + int frag;
  65990. + for (frag = 0; frag < s->nbfrags; frag++) {
  65991. + if (!s->buffers[frag].master)
  65992. + continue;
  65993. + consistent_free(s->buffers[frag].start,
  65994. + s->buffers[frag].master,
  65995. + s->buffers[frag].dma_addr);
  65996. + }
  65997. + kfree(s->buffers);
  65998. + s->buffers = NULL;
  65999. + }
  66000. +
  66001. + s->buf_idx = 0;
  66002. + s->buf = NULL;
  66003. +}
  66004. +
  66005. +
  66006. +/*
  66007. + * This function allocates the buffer structure array and buffer data space
  66008. + * according to the current number of fragments and fragment size.
  66009. + */
  66010. +
  66011. +static int audio_setup_buf(audio_stream_t * s)
  66012. +{
  66013. + int frag;
  66014. + int dmasize = 0;
  66015. + char *dmabuf = NULL;
  66016. + dma_addr_t dmaphys = 0;
  66017. +
  66018. + if (s->buffers)
  66019. + return -EBUSY;
  66020. +
  66021. + s->buffers = (audio_buf_t *)
  66022. + kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
  66023. + if (!s->buffers)
  66024. + goto err;
  66025. + memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
  66026. +
  66027. + for (frag = 0; frag < s->nbfrags; frag++) {
  66028. + audio_buf_t *b = &s->buffers[frag];
  66029. +
  66030. + /*
  66031. + * Let's allocate non-cached memory for DMA buffers.
  66032. + * We try to allocate all memory at once.
  66033. + * If this fails (a common reason is memory fragmentation),
  66034. + * then we allocate more smaller buffers.
  66035. + */
  66036. + if (!dmasize) {
  66037. + dmasize = (s->nbfrags - frag) * s->fragsize;
  66038. + do {
  66039. + dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
  66040. + dmasize,
  66041. + &dmaphys);
  66042. + if (!dmabuf)
  66043. + dmasize -= s->fragsize;
  66044. + } while (!dmabuf && dmasize);
  66045. + if (!dmabuf)
  66046. + goto err;
  66047. + b->master = dmasize;
  66048. + memzero(dmabuf, dmasize);
  66049. + }
  66050. +
  66051. + b->start = dmabuf;
  66052. + b->dma_addr = dmaphys;
  66053. + b->stream = s;
  66054. + sema_init(&b->sem, 1);
  66055. + DPRINTK("buf %d: start %p dma %p\n", frag, b->start,
  66056. + b->dma_addr);
  66057. +
  66058. + dmabuf += s->fragsize;
  66059. + dmaphys += s->fragsize;
  66060. + dmasize -= s->fragsize;
  66061. + }
  66062. +
  66063. + s->buf_idx = 0;
  66064. + s->buf = &s->buffers[0];
  66065. + s->bytecount = 0;
  66066. + s->getptrCount = 0;
  66067. + s->fragcount = 0;
  66068. +
  66069. + return 0;
  66070. +
  66071. +err:
  66072. + printk(AUDIO_NAME ": unable to allocate audio memory\n ");
  66073. + audio_clear_buf(s);
  66074. + return -ENOMEM;
  66075. +}
  66076. +
  66077. +
  66078. +/*
  66079. + * This function yanks all buffers from the DMA code's control and
  66080. + * resets them ready to be used again.
  66081. + */
  66082. +
  66083. +static void audio_reset_buf(audio_stream_t * s)
  66084. +{
  66085. + int frag;
  66086. +
  66087. + s->active = 0;
  66088. + s->stopped = 0;
  66089. + sa1100_dma_flush_all(s->dma_ch);
  66090. + if (s->buffers) {
  66091. + for (frag = 0; frag < s->nbfrags; frag++) {
  66092. + audio_buf_t *b = &s->buffers[frag];
  66093. + b->size = 0;
  66094. + sema_init(&b->sem, 1);
  66095. + }
  66096. + }
  66097. + s->bytecount = 0;
  66098. + s->getptrCount = 0;
  66099. + s->fragcount = 0;
  66100. +}
  66101. +
  66102. +
  66103. +/*
  66104. + * DMA callback functions
  66105. + */
  66106. +
  66107. +static void audio_dmaout_done_callback(void *buf_id, int size)
  66108. +{
  66109. + audio_buf_t *b = (audio_buf_t *) buf_id;
  66110. + audio_stream_t *s = b->stream;
  66111. +
  66112. + /* Accounting */
  66113. + s->bytecount += size;
  66114. + s->fragcount++;
  66115. +
  66116. + /* Recycle buffer */
  66117. + if (s->mapped)
  66118. + sa1100_dma_queue_buffer(s->dma_ch, buf_id,
  66119. + b->dma_addr, s->fragsize);
  66120. + else
  66121. + up(&b->sem);
  66122. +
  66123. + /* And any process polling on write. */
  66124. + wake_up(&s->wq);
  66125. +}
  66126. +
  66127. +static void audio_dmain_done_callback(void *buf_id, int size)
  66128. +{
  66129. + audio_buf_t *b = (audio_buf_t *) buf_id;
  66130. + audio_stream_t *s = b->stream;
  66131. +
  66132. + /* Accounting */
  66133. + s->bytecount += size;
  66134. + s->fragcount++;
  66135. +
  66136. + /* Recycle buffer */
  66137. + if (s->mapped) {
  66138. + sa1100_dma_queue_buffer(s->dma_ch, buf_id,
  66139. + b->dma_addr, s->fragsize);
  66140. + } else {
  66141. + b->size = size;
  66142. + up(&b->sem);
  66143. + }
  66144. +
  66145. + /* And any process polling on write. */
  66146. + wake_up(&s->wq);
  66147. +}
  66148. +
  66149. +static int audio_sync(struct file *file)
  66150. +{
  66151. + audio_state_t *state = (audio_state_t *)file->private_data;
  66152. + audio_stream_t *s = state->output_stream;
  66153. + audio_buf_t *b;
  66154. +
  66155. + DPRINTK("audio_sync\n");
  66156. +
  66157. + if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
  66158. + return 0;
  66159. +
  66160. + /*
  66161. + * Send current buffer if it contains data. Be sure to send
  66162. + * a full sample count.
  66163. + */
  66164. + b = s->buf;
  66165. + if (b->size &= ~3) {
  66166. + down(&b->sem);
  66167. + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
  66168. + b->dma_addr, b->size);
  66169. + b->size = 0;
  66170. + NEXT_BUF(s, buf);
  66171. + }
  66172. +
  66173. + /*
  66174. + * Let's wait for the last buffer we sent i.e. the one before the
  66175. + * current buf_idx. When we acquire the semaphore, this means either:
  66176. + * - DMA on the buffer completed or
  66177. + * - the buffer was already free thus nothing else to sync.
  66178. + */
  66179. + b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags);
  66180. + if (down_interruptible(&b->sem))
  66181. + return -EINTR;
  66182. + up(&b->sem);
  66183. + return 0;
  66184. +}
  66185. +
  66186. +
  66187. +static int audio_write(struct file *file, const char *buffer,
  66188. + size_t count, loff_t * ppos)
  66189. +{
  66190. + const char *buffer0 = buffer;
  66191. + audio_state_t *state = (audio_state_t *)file->private_data;
  66192. + audio_stream_t *s = state->output_stream;
  66193. + int chunksize, ret = 0;
  66194. +
  66195. + DPRINTK("audio_write: count=%d\n", count);
  66196. +
  66197. + if (ppos != &file->f_pos)
  66198. + return -ESPIPE;
  66199. + if (s->mapped)
  66200. + return -ENXIO;
  66201. + if (!s->buffers && audio_setup_buf(s))
  66202. + return -ENOMEM;
  66203. +
  66204. + while (count > 0) {
  66205. + audio_buf_t *b = s->buf;
  66206. +
  66207. + /* Wait for a buffer to become free */
  66208. + if (file->f_flags & O_NONBLOCK) {
  66209. + ret = -EAGAIN;
  66210. + if (down_trylock(&b->sem))
  66211. + break;
  66212. + } else {
  66213. + ret = -ERESTARTSYS;
  66214. + if (down_interruptible(&b->sem))
  66215. + break;
  66216. + }
  66217. +
  66218. + /* Feed the current buffer */
  66219. + chunksize = s->fragsize - b->size;
  66220. + if (chunksize > count)
  66221. + chunksize = count;
  66222. + DPRINTK("write %d to %d\n", chunksize, s->buf_idx);
  66223. + if (copy_from_user(b->start + b->size, buffer, chunksize)) {
  66224. + up(&b->sem);
  66225. + return -EFAULT;
  66226. + }
  66227. + b->size += chunksize;
  66228. + buffer += chunksize;
  66229. + count -= chunksize;
  66230. + if (b->size < s->fragsize) {
  66231. + up(&b->sem);
  66232. + break;
  66233. + }
  66234. +
  66235. + /* Send current buffer to dma */
  66236. + s->active = 1;
  66237. + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
  66238. + b->dma_addr, b->size);
  66239. + b->size = 0; /* indicate that the buffer has been sent */
  66240. + NEXT_BUF(s, buf);
  66241. + }
  66242. +
  66243. + if ((buffer - buffer0))
  66244. + ret = buffer - buffer0;
  66245. + DPRINTK("audio_write: return=%d\n", ret);
  66246. + return ret;
  66247. +}
  66248. +
  66249. +
  66250. +static inline void audio_check_tx_spin(audio_state_t *state)
  66251. +{
  66252. + /*
  66253. + * With some codecs like the Philips UDA1341 we must ensure
  66254. + * there is an output stream at any time while recording since
  66255. + * this is how the UDA1341 gets its clock from the SA1100.
  66256. + * So while there is no playback data to send, the output DMA
  66257. + * will spin with all zeroes. We use the cache flush special
  66258. + * area for that.
  66259. + */
  66260. + if (state->need_tx_for_rx && !state->tx_spinning) {
  66261. + sa1100_dma_set_spin(state->output_stream->dma_ch,
  66262. + (dma_addr_t)FLUSH_BASE_PHYS, 2048);
  66263. + state->tx_spinning = 1;
  66264. + }
  66265. +}
  66266. +
  66267. +
  66268. +static void audio_prime_dma(audio_stream_t *s)
  66269. +{
  66270. + int i;
  66271. +
  66272. + s->active = 1;
  66273. + for (i = 0; i < s->nbfrags; i++) {
  66274. + audio_buf_t *b = s->buf;
  66275. + down(&b->sem);
  66276. + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
  66277. + b->dma_addr, s->fragsize);
  66278. + NEXT_BUF(s, buf);
  66279. + }
  66280. +}
  66281. +
  66282. +
  66283. +static int audio_read(struct file *file, char *buffer,
  66284. + size_t count, loff_t * ppos)
  66285. +{
  66286. + char *buffer0 = buffer;
  66287. + audio_state_t *state = (audio_state_t *)file->private_data;
  66288. + audio_stream_t *s = state->input_stream;
  66289. + int chunksize, ret = 0;
  66290. +
  66291. + DPRINTK("audio_read: count=%d\n", count);
  66292. +
  66293. + if (ppos != &file->f_pos)
  66294. + return -ESPIPE;
  66295. + if (s->mapped)
  66296. + return -ENXIO;
  66297. +
  66298. + if (!s->active) {
  66299. + if (!s->buffers && audio_setup_buf(s))
  66300. + return -ENOMEM;
  66301. + audio_check_tx_spin(state);
  66302. + audio_prime_dma(s);
  66303. + }
  66304. +
  66305. + while (count > 0) {
  66306. + audio_buf_t *b = s->buf;
  66307. +
  66308. + /* Wait for a buffer to become full */
  66309. + if (file->f_flags & O_NONBLOCK) {
  66310. + ret = -EAGAIN;
  66311. + if (down_trylock(&b->sem))
  66312. + break;
  66313. + } else {
  66314. + ret = -ERESTARTSYS;
  66315. + if (down_interruptible(&b->sem))
  66316. + break;
  66317. + }
  66318. +
  66319. + /* Grab data from the current buffer */
  66320. + chunksize = b->size;
  66321. + if (chunksize > count)
  66322. + chunksize = count;
  66323. + DPRINTK("read %d from %d\n", chunksize, s->buf_idx);
  66324. + if (copy_to_user(buffer,
  66325. + b->start + s->fragsize - b->size,
  66326. + chunksize)) {
  66327. + up(&b->sem);
  66328. + return -EFAULT;
  66329. + }
  66330. + b->size -= chunksize;
  66331. + buffer += chunksize;
  66332. + count -= chunksize;
  66333. + if (b->size > 0) {
  66334. + up(&b->sem);
  66335. + break;
  66336. + }
  66337. +
  66338. + /* Make current buffer available for DMA again */
  66339. + sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
  66340. + b->dma_addr, s->fragsize);
  66341. + NEXT_BUF(s, buf);
  66342. + }
  66343. +
  66344. + if ((buffer - buffer0))
  66345. + ret = buffer - buffer0;
  66346. + DPRINTK("audio_read: return=%d\n", ret);
  66347. + return ret;
  66348. +}
  66349. +
  66350. +
  66351. +static int audio_mmap(struct file *file, struct vm_area_struct *vma)
  66352. +{
  66353. + audio_state_t *state = (audio_state_t *)file->private_data;
  66354. + audio_stream_t *s;
  66355. + unsigned long size, vma_addr;
  66356. + int i, ret;
  66357. +
  66358. + if (vma->vm_pgoff != 0)
  66359. + return -EINVAL;
  66360. +
  66361. + if (vma->vm_flags & VM_WRITE) {
  66362. + if (!state->wr_ref)
  66363. + return -EINVAL;;
  66364. + s = state->output_stream;
  66365. + } else if (vma->vm_flags & VM_READ) {
  66366. + if (!state->rd_ref)
  66367. + return -EINVAL;
  66368. + s = state->input_stream;
  66369. + } else return -EINVAL;
  66370. +
  66371. + if (s->mapped)
  66372. + return -EINVAL;
  66373. + size = vma->vm_end - vma->vm_start;
  66374. + if (size != s->fragsize * s->nbfrags)
  66375. + return -EINVAL;
  66376. + if (!s->buffers && audio_setup_buf(s))
  66377. + return -ENOMEM;
  66378. + vma_addr = vma->vm_start;
  66379. + for (i = 0; i < s->nbfrags; i++) {
  66380. + audio_buf_t *buf = &s->buffers[i];
  66381. + if (!buf->master)
  66382. + continue;
  66383. + ret = remap_page_range(vma_addr, buf->dma_addr, buf->master, vma->vm_page_prot);
  66384. + if (ret)
  66385. + return ret;
  66386. + vma_addr += buf->master;
  66387. + }
  66388. + s->mapped = 1;
  66389. +
  66390. + return 0;
  66391. +}
  66392. +
  66393. +
  66394. +static unsigned int audio_poll(struct file *file,
  66395. + struct poll_table_struct *wait)
  66396. +{
  66397. + audio_state_t *state = (audio_state_t *)file->private_data;
  66398. + audio_stream_t *is = state->input_stream;
  66399. + audio_stream_t *os = state->output_stream;
  66400. + unsigned int mask = 0;
  66401. + int i;
  66402. +
  66403. + DPRINTK("audio_poll(): mode=%s%s\n",
  66404. + (file->f_mode & FMODE_READ) ? "r" : "",
  66405. + (file->f_mode & FMODE_WRITE) ? "w" : "");
  66406. +
  66407. + if (file->f_mode & FMODE_READ) {
  66408. + /* Start audio input if not already active */
  66409. + if (!is->active) {
  66410. + if (!is->buffers && audio_setup_buf(is))
  66411. + return -ENOMEM;
  66412. + audio_check_tx_spin(state);
  66413. + audio_prime_dma(is);
  66414. + }
  66415. + poll_wait(file, &is->wq, wait);
  66416. + }
  66417. +
  66418. + if (file->f_mode & FMODE_WRITE) {
  66419. + if (!os->buffers && audio_setup_buf(os))
  66420. + return -ENOMEM;
  66421. + poll_wait(file, &os->wq, wait);
  66422. + }
  66423. +
  66424. + if (file->f_mode & FMODE_READ) {
  66425. + if (is->mapped) {
  66426. +/* if the buffer is mapped assume we care that there are more bytes available than
  66427. + when we last asked using SNDCTL_DSP_GETxPTR */
  66428. + if (is->bytecount != is->getptrCount)
  66429. + mask |= POLLIN | POLLRDNORM;
  66430. + } else {
  66431. + for (i = 0; i < is->nbfrags; i++) {
  66432. + if (atomic_read(&is->buffers[i].sem.count) > 0) {
  66433. + mask |= POLLIN | POLLRDNORM;
  66434. + break;
  66435. + }
  66436. + }
  66437. + }
  66438. + }
  66439. + if (file->f_mode & FMODE_WRITE) {
  66440. + if (os->mapped) {
  66441. + if (os->bytecount != os->getptrCount)
  66442. + mask |= POLLOUT | POLLWRNORM;
  66443. + } else {
  66444. + for (i = 0; i < os->nbfrags; i++) {
  66445. + if (atomic_read(&os->buffers[i].sem.count) > 0) {
  66446. + mask |= POLLOUT | POLLWRNORM;
  66447. + break;
  66448. + }
  66449. + }
  66450. + }
  66451. + }
  66452. +
  66453. + DPRINTK("audio_poll() returned mask of %s%s\n",
  66454. + (mask & POLLIN) ? "r" : "",
  66455. + (mask & POLLOUT) ? "w" : "");
  66456. +
  66457. + return mask;
  66458. +}
  66459. +
  66460. +
  66461. +static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
  66462. +{
  66463. + return -ESPIPE;
  66464. +}
  66465. +
  66466. +
  66467. +static int audio_set_fragments(audio_stream_t *s, int val)
  66468. +{
  66469. + if (s->active)
  66470. + return -EBUSY;
  66471. + if (s->buffers)
  66472. + audio_clear_buf(s);
  66473. + s->nbfrags = (val >> 16) & 0x7FFF;
  66474. + val &= 0xffff;
  66475. + if (val < 4)
  66476. + val = 4;
  66477. + if (val > 15)
  66478. + val = 15;
  66479. + s->fragsize = 1 << val;
  66480. + if (s->nbfrags < 2)
  66481. + s->nbfrags = 2;
  66482. + if (s->nbfrags * s->fragsize > 128 * 1024)
  66483. + s->nbfrags = 128 * 1024 / s->fragsize;
  66484. + if (audio_setup_buf(s))
  66485. + return -ENOMEM;
  66486. + return val|(s->nbfrags << 16);
  66487. +}
  66488. +
  66489. +static int audio_ioctl(struct inode *inode, struct file *file,
  66490. + uint cmd, ulong arg)
  66491. +{
  66492. + audio_state_t *state = (audio_state_t *)file->private_data;
  66493. + audio_stream_t *os = state->output_stream;
  66494. + audio_stream_t *is = state->input_stream;
  66495. + long val;
  66496. +
  66497. + /* dispatch based on command */
  66498. + switch (cmd) {
  66499. + case OSS_GETVERSION:
  66500. + return put_user(SOUND_VERSION, (int *)arg);
  66501. +
  66502. + case SNDCTL_DSP_GETBLKSIZE:
  66503. + if (file->f_mode & FMODE_WRITE)
  66504. + return put_user(os->fragsize, (int *)arg);
  66505. + else
  66506. + return put_user(is->fragsize, (int *)arg);
  66507. +
  66508. + case SNDCTL_DSP_GETCAPS:
  66509. + val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
  66510. + if (is && os)
  66511. + val |= DSP_CAP_DUPLEX;
  66512. + return put_user(val, (int *)arg);
  66513. +
  66514. + case SNDCTL_DSP_SETFRAGMENT:
  66515. + if (get_user(val, (long *) arg))
  66516. + return -EFAULT;
  66517. + if (file->f_mode & FMODE_READ) {
  66518. + int ret = audio_set_fragments(is, val);
  66519. + if (ret < 0)
  66520. + return ret;
  66521. + ret = put_user(ret, (int *)arg);
  66522. + if (ret)
  66523. + return ret;
  66524. + }
  66525. + if (file->f_mode & FMODE_WRITE) {
  66526. + int ret = audio_set_fragments(os, val);
  66527. + if (ret < 0)
  66528. + return ret;
  66529. + ret = put_user(ret, (int *)arg);
  66530. + if (ret)
  66531. + return ret;
  66532. + }
  66533. + return 0;
  66534. +
  66535. + case SNDCTL_DSP_SYNC:
  66536. + return audio_sync(file);
  66537. +
  66538. + case SNDCTL_DSP_SETDUPLEX:
  66539. + return 0;
  66540. +
  66541. + case SNDCTL_DSP_POST:
  66542. + return 0;
  66543. +
  66544. + case SNDCTL_DSP_GETTRIGGER:
  66545. + val = 0;
  66546. + if (file->f_mode & FMODE_READ && is->active && !is->stopped)
  66547. + val |= PCM_ENABLE_INPUT;
  66548. + if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
  66549. + val |= PCM_ENABLE_OUTPUT;
  66550. + return put_user(val, (int *)arg);
  66551. +
  66552. + case SNDCTL_DSP_SETTRIGGER:
  66553. + if (get_user(val, (int *)arg))
  66554. + return -EFAULT;
  66555. + if (file->f_mode & FMODE_READ) {
  66556. + if (val & PCM_ENABLE_INPUT) {
  66557. + if (!is->active) {
  66558. + if (!is->buffers && audio_setup_buf(is))
  66559. + return -ENOMEM;
  66560. + audio_prime_dma(is);
  66561. + }
  66562. + audio_check_tx_spin(state);
  66563. + if (is->stopped) {
  66564. + is->stopped = 0;
  66565. + sa1100_dma_resume(is->dma_ch);
  66566. + }
  66567. + } else {
  66568. + sa1100_dma_stop(is->dma_ch);
  66569. + is->stopped = 1;
  66570. + }
  66571. + }
  66572. + if (file->f_mode & FMODE_WRITE) {
  66573. + if (val & PCM_ENABLE_OUTPUT) {
  66574. + if (!os->active) {
  66575. + if (!os->buffers && audio_setup_buf(os))
  66576. + return -ENOMEM;
  66577. + if (os->mapped)
  66578. + audio_prime_dma(os);
  66579. + }
  66580. + if (os->stopped) {
  66581. + os->stopped = 0;
  66582. + sa1100_dma_resume(os->dma_ch);
  66583. + }
  66584. + } else {
  66585. + sa1100_dma_stop(os->dma_ch);
  66586. + os->stopped = 1;
  66587. + }
  66588. + }
  66589. + return 0;
  66590. +
  66591. + case SNDCTL_DSP_GETOPTR:
  66592. + case SNDCTL_DSP_GETIPTR:
  66593. + {
  66594. + count_info inf = { 0, };
  66595. + audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
  66596. + audio_buf_t *b;
  66597. + dma_addr_t ptr;
  66598. + int bytecount, offset, flags;
  66599. +
  66600. + if ((s == is && !(file->f_mode & FMODE_READ)) ||
  66601. + (s == os && !(file->f_mode & FMODE_WRITE)))
  66602. + return -EINVAL;
  66603. + if (s->active) {
  66604. + save_flags_cli(flags);
  66605. + if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {
  66606. + offset = ptr - b->dma_addr;
  66607. + inf.ptr = (b - s->buffers) * s->fragsize + offset;
  66608. + } else offset = 0;
  66609. + bytecount = s->bytecount + offset;
  66610. + s->getptrCount = s->bytecount; /* so poll can tell if it changes */
  66611. + inf.blocks = s->fragcount;
  66612. + s->fragcount = 0;
  66613. + restore_flags(flags);
  66614. + if (bytecount < 0)
  66615. + bytecount = 0;
  66616. + inf.bytes = bytecount;
  66617. + }
  66618. + return copy_to_user((void *)arg, &inf, sizeof(inf));
  66619. + }
  66620. +
  66621. + case SNDCTL_DSP_GETOSPACE:
  66622. + {
  66623. + audio_buf_info inf = { 0, };
  66624. + int i;
  66625. +
  66626. + if (!(file->f_mode & FMODE_WRITE))
  66627. + return -EINVAL;
  66628. + if (!os->buffers && audio_setup_buf(os))
  66629. + return -ENOMEM;
  66630. + for (i = 0; i < os->nbfrags; i++) {
  66631. + if (atomic_read(&os->buffers[i].sem.count) > 0) {
  66632. + if (os->buffers[i].size == 0)
  66633. + inf.fragments++;
  66634. + inf.bytes += os->fragsize - os->buffers[i].size;
  66635. + }
  66636. + }
  66637. + inf.fragstotal = os->nbfrags;
  66638. + inf.fragsize = os->fragsize;
  66639. + return copy_to_user((void *)arg, &inf, sizeof(inf));
  66640. + }
  66641. +
  66642. + case SNDCTL_DSP_GETISPACE:
  66643. + {
  66644. + audio_buf_info inf = { 0, };
  66645. + int i;
  66646. +
  66647. + if (!(file->f_mode & FMODE_READ))
  66648. + return -EINVAL;
  66649. + if (!is->buffers && audio_setup_buf(is))
  66650. + return -ENOMEM;
  66651. + for (i = 0; i < is->nbfrags; i++) {
  66652. + if (atomic_read(&is->buffers[i].sem.count) > 0) {
  66653. + if (is->buffers[i].size == is->fragsize)
  66654. + inf.fragments++;
  66655. + inf.bytes += is->buffers[i].size;
  66656. + }
  66657. + }
  66658. + inf.fragstotal = is->nbfrags;
  66659. + inf.fragsize = is->fragsize;
  66660. + return copy_to_user((void *)arg, &inf, sizeof(inf));
  66661. + }
  66662. +
  66663. + case SNDCTL_DSP_NONBLOCK:
  66664. + file->f_flags |= O_NONBLOCK;
  66665. + return 0;
  66666. +
  66667. + case SNDCTL_DSP_RESET:
  66668. + if (file->f_mode & FMODE_READ) {
  66669. + if (state->tx_spinning) {
  66670. + sa1100_dma_set_spin(os->dma_ch, 0, 0);
  66671. + state->tx_spinning = 0;
  66672. + }
  66673. + audio_reset_buf(is);
  66674. + }
  66675. + if (file->f_mode & FMODE_WRITE) {
  66676. + audio_reset_buf(os);
  66677. + }
  66678. + return 0;
  66679. +
  66680. + default:
  66681. + /*
  66682. + * Let the client of this module handle the
  66683. + * non generic ioctls
  66684. + */
  66685. + return state->client_ioctl(inode, file, cmd, arg);
  66686. + }
  66687. +
  66688. + return 0;
  66689. +}
  66690. +
  66691. +
  66692. +static int audio_release(struct inode *inode, struct file *file)
  66693. +{
  66694. + audio_state_t *state = (audio_state_t *)file->private_data;
  66695. + DPRINTK("audio_release\n");
  66696. +
  66697. + down(&state->sem);
  66698. +
  66699. + if (file->f_mode & FMODE_READ) {
  66700. + if (state->tx_spinning) {
  66701. + sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0);
  66702. + state->tx_spinning = 0;
  66703. + }
  66704. + audio_clear_buf(state->input_stream);
  66705. + if (!state->skip_dma_init) {
  66706. + sa1100_free_dma(state->input_stream->dma_ch);
  66707. + if (state->need_tx_for_rx && !state->wr_ref)
  66708. + sa1100_free_dma(state->output_stream->dma_ch);
  66709. + }
  66710. + state->rd_ref = 0;
  66711. + }
  66712. +
  66713. + if (file->f_mode & FMODE_WRITE) {
  66714. + audio_sync(file);
  66715. + audio_clear_buf(state->output_stream);
  66716. + if (!state->skip_dma_init)
  66717. + if (!state->need_tx_for_rx || !state->rd_ref)
  66718. + sa1100_free_dma(state->output_stream->dma_ch);
  66719. + state->wr_ref = 0;
  66720. + }
  66721. +
  66722. + if (!AUDIO_ACTIVE(state)) {
  66723. + if (state->hw_shutdown)
  66724. + state->hw_shutdown(state->data);
  66725. +#ifdef CONFIG_PM
  66726. + pm_unregister(state->pm_dev);
  66727. +#endif
  66728. + }
  66729. +
  66730. + up(&state->sem);
  66731. + return 0;
  66732. +}
  66733. +
  66734. +
  66735. +#ifdef CONFIG_PM
  66736. +
  66737. +static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
  66738. +{
  66739. + audio_state_t *state = (audio_state_t *)pm_dev->data;
  66740. +
  66741. + switch (req) {
  66742. + case PM_SUSPEND: /* enter D1-D3 */
  66743. + if (state->output_stream)
  66744. + sa1100_dma_sleep(state->output_stream->dma_ch);
  66745. + if (state->input_stream)
  66746. + sa1100_dma_sleep(state->input_stream->dma_ch);
  66747. + if (AUDIO_ACTIVE(state) && state->hw_shutdown)
  66748. + state->hw_shutdown(state->data);
  66749. + break;
  66750. + case PM_RESUME: /* enter D0 */
  66751. + if (AUDIO_ACTIVE(state) && state->hw_init)
  66752. + state->hw_init(state->data);
  66753. + if (state->input_stream)
  66754. + sa1100_dma_wakeup(state->input_stream->dma_ch);
  66755. + if (state->output_stream)
  66756. + sa1100_dma_wakeup(state->output_stream->dma_ch);
  66757. + break;
  66758. + }
  66759. + return 0;
  66760. +}
  66761. +
  66762. +#endif
  66763. +
  66764. +
  66765. +int sa1100_audio_attach(struct inode *inode, struct file *file,
  66766. + audio_state_t *state)
  66767. +{
  66768. + int err, need_tx_dma;
  66769. +
  66770. + DPRINTK("audio_open\n");
  66771. +
  66772. + down(&state->sem);
  66773. +
  66774. + /* access control */
  66775. + err = -ENODEV;
  66776. + if ((file->f_mode & FMODE_WRITE) && !state->output_stream)
  66777. + goto out;
  66778. + if ((file->f_mode & FMODE_READ) && !state->input_stream)
  66779. + goto out;
  66780. + err = -EBUSY;
  66781. + if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
  66782. + goto out;
  66783. + if ((file->f_mode & FMODE_READ) && state->rd_ref)
  66784. + goto out;
  66785. + err = -EINVAL;
  66786. + if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !state->output_stream)
  66787. + goto out;
  66788. +
  66789. + /* request DMA channels */
  66790. + if (state->skip_dma_init)
  66791. + goto skip_dma;
  66792. + need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
  66793. + ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
  66794. + if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
  66795. + need_tx_dma = 0;
  66796. + if (need_tx_dma) {
  66797. + err = sa1100_request_dma(&state->output_stream->dma_ch,
  66798. + state->output_id,
  66799. + state->output_dma);
  66800. + if (err)
  66801. + goto out;
  66802. + }
  66803. + if (file->f_mode & FMODE_READ) {
  66804. + err = sa1100_request_dma(&state->input_stream->dma_ch,
  66805. + state->input_id,
  66806. + state->input_dma);
  66807. + if (err) {
  66808. + if (need_tx_dma)
  66809. + sa1100_free_dma(state->output_stream->dma_ch);
  66810. + goto out;
  66811. + }
  66812. + }
  66813. +skip_dma:
  66814. +
  66815. + /* now complete initialisation */
  66816. + if (!AUDIO_ACTIVE(state)) {
  66817. + if (state->hw_init)
  66818. + state->hw_init(state->data);
  66819. +#ifdef CONFIG_PM
  66820. + state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback);
  66821. + if (state->pm_dev)
  66822. + state->pm_dev->data = state;
  66823. +#endif
  66824. + }
  66825. +
  66826. + if ((file->f_mode & FMODE_WRITE)) {
  66827. + state->wr_ref = 1;
  66828. + audio_clear_buf(state->output_stream);
  66829. + state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
  66830. + state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
  66831. + state->output_stream->mapped = 0;
  66832. + sa1100_dma_set_callback(state->output_stream->dma_ch,
  66833. + audio_dmaout_done_callback);
  66834. + init_waitqueue_head(&state->output_stream->wq);
  66835. + }
  66836. + if (file->f_mode & FMODE_READ) {
  66837. + state->rd_ref = 1;
  66838. + audio_clear_buf(state->input_stream);
  66839. + state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
  66840. + state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
  66841. + state->input_stream->mapped = 0;
  66842. + sa1100_dma_set_callback(state->input_stream->dma_ch,
  66843. + audio_dmain_done_callback);
  66844. + init_waitqueue_head(&state->input_stream->wq);
  66845. + }
  66846. +
  66847. + file->private_data = state;
  66848. + file->f_op->release = audio_release;
  66849. + file->f_op->write = audio_write;
  66850. + file->f_op->read = audio_read;
  66851. + file->f_op->mmap = audio_mmap;
  66852. + file->f_op->poll = audio_poll;
  66853. + file->f_op->ioctl = audio_ioctl;
  66854. + file->f_op->llseek = audio_llseek;
  66855. + err = 0;
  66856. +
  66857. +out:
  66858. + up(&state->sem);
  66859. + return err;
  66860. +}
  66861. +
  66862. +EXPORT_SYMBOL(sa1100_audio_attach);
  66863. +
  66864. +MODULE_AUTHOR("Nicolas Pitre");
  66865. +MODULE_DESCRIPTION("Common audio handling for the SA11x0 processor");
  66866. +MODULE_LICENSE("GPL");
  66867. diff -urN linux-2.4.26/drivers/sound/sa1100-audio.h linux-2.4.26-vrs1/drivers/sound/sa1100-audio.h
  66868. --- linux-2.4.26/drivers/sound/sa1100-audio.h 1970-01-01 01:00:00.000000000 +0100
  66869. +++ linux-2.4.26-vrs1/drivers/sound/sa1100-audio.h 2004-01-14 21:32:26.000000000 +0000
  66870. @@ -0,0 +1,68 @@
  66871. +/*
  66872. + * Common audio handling for the SA11x0
  66873. + *
  66874. + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
  66875. + *
  66876. + * This program is free software; you can redistribute it and/or
  66877. + * modify it under the terms of the GNU General Public License.
  66878. + */
  66879. +
  66880. +
  66881. +/*
  66882. + * Buffer Management
  66883. + */
  66884. +
  66885. +typedef struct {
  66886. + int size; /* buffer size */
  66887. + char *start; /* points to actual buffer */
  66888. + dma_addr_t dma_addr; /* physical buffer address */
  66889. + struct semaphore sem; /* down before touching the buffer */
  66890. + int master; /* owner for buffer allocation, contain size when true */
  66891. + struct audio_stream_s *stream; /* owning stream */
  66892. +} audio_buf_t;
  66893. +
  66894. +typedef struct audio_stream_s {
  66895. + audio_buf_t *buffers; /* pointer to audio buffer structures */
  66896. + audio_buf_t *buf; /* current buffer used by read/write */
  66897. + u_int buf_idx; /* index for the pointer above... */
  66898. + u_int fragsize; /* fragment i.e. buffer size */
  66899. + u_int nbfrags; /* nbr of fragments i.e. buffers */
  66900. + int bytecount; /* nbr of processed bytes */
  66901. + int getptrCount; /* value of bytecount last time anyone asked via GETxPTR */
  66902. + int fragcount; /* nbr of fragment transitions */
  66903. + dmach_t dma_ch; /* DMA channel ID */
  66904. + wait_queue_head_t wq; /* for poll */
  66905. + int mapped:1; /* mmap()'ed buffers */
  66906. + int active:1; /* actually in progress */
  66907. + int stopped:1; /* might be active but stopped */
  66908. +} audio_stream_t;
  66909. +
  66910. +/*
  66911. + * State structure for one instance
  66912. + */
  66913. +
  66914. +typedef struct {
  66915. + audio_stream_t *output_stream;
  66916. + audio_stream_t *input_stream;
  66917. + dma_device_t output_dma;
  66918. + dma_device_t input_dma;
  66919. + char *output_id;
  66920. + char *input_id;
  66921. + int rd_ref:1; /* open reference for recording */
  66922. + int wr_ref:1; /* open reference for playback */
  66923. + int need_tx_for_rx:1; /* if data must be sent while receiving */
  66924. + int tx_spinning:1; /* tx spinning active */
  66925. + int skip_dma_init:1; /* hack for the SA1111 */
  66926. + void *data;
  66927. + void (*hw_init)(void *);
  66928. + void (*hw_shutdown)(void *);
  66929. + int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
  66930. + struct pm_dev *pm_dev;
  66931. + struct semaphore sem; /* to protect against races in attach() */
  66932. +} audio_state_t;
  66933. +
  66934. +/*
  66935. + * Functions exported by this module
  66936. + */
  66937. +extern int sa1100_audio_attach( struct inode *inode, struct file *file,
  66938. + audio_state_t *state);
  66939. diff -urN linux-2.4.26/drivers/sound/sa1100ssp.c linux-2.4.26-vrs1/drivers/sound/sa1100ssp.c
  66940. --- linux-2.4.26/drivers/sound/sa1100ssp.c 1970-01-01 01:00:00.000000000 +0100
  66941. +++ linux-2.4.26-vrs1/drivers/sound/sa1100ssp.c 2004-01-14 21:32:26.000000000 +0000
  66942. @@ -0,0 +1,182 @@
  66943. +/*
  66944. + * Glue audio driver for a simple DAC on the SA1100's SSP port
  66945. + *
  66946. + * Copyright (c) 2001 Nicolas Pitre <nico@cam.org>
  66947. + *
  66948. + * This program is free software; you can redistribute it and/or
  66949. + * modify it under the terms of the GNU General Public License.
  66950. + *
  66951. + * History:
  66952. + *
  66953. + * 2001-06-04 Nicolas Pitre Initial release.
  66954. + *
  66955. + */
  66956. +
  66957. +#include <linux/module.h>
  66958. +#include <linux/init.h>
  66959. +#include <linux/types.h>
  66960. +#include <linux/fs.h>
  66961. +#include <linux/delay.h>
  66962. +#include <linux/pm.h>
  66963. +#include <linux/errno.h>
  66964. +#include <linux/sound.h>
  66965. +#include <linux/soundcard.h>
  66966. +
  66967. +#include <asm/semaphore.h>
  66968. +#include <asm/uaccess.h>
  66969. +#include <asm/hardware.h>
  66970. +#include <asm/dma.h>
  66971. +
  66972. +#include "sa1100-audio.h"
  66973. +
  66974. +
  66975. +#undef DEBUG
  66976. +#ifdef DEBUG
  66977. +#define DPRINTK( x... ) printk( ##x )
  66978. +#else
  66979. +#define DPRINTK( x... )
  66980. +#endif
  66981. +
  66982. +
  66983. +#define AUDIO_NAME "SA1100 SSP audio"
  66984. +
  66985. +#define AUDIO_FMT AFMT_S16_LE
  66986. +#define AUDIO_CHANNELS 2
  66987. +
  66988. +static int sample_rate = 44100;
  66989. +
  66990. +
  66991. +static void ssp_audio_init(void)
  66992. +{
  66993. + if (machine_is_lart()) {
  66994. + unsigned long flags;
  66995. + local_irq_save(flags);
  66996. +
  66997. + /* LART has the SSP port rewired to GPIO 10-13, 19 */
  66998. + /* alternate functions for the GPIOs */
  66999. + GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK |
  67000. + GPIO_SSP_SFRM | GPIO_SSP_CLK );
  67001. +
  67002. + /* Set the direction: 10, 12, 13 output; 11, 19 input */
  67003. + GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM );
  67004. + GPDR &= ~( GPIO_SSP_RXD | GPIO_SSP_CLK );
  67005. +
  67006. + /* enable SSP pin swap */
  67007. + PPAR |= PPAR_SPR;
  67008. +
  67009. + local_irq_restore(flags);
  67010. + }
  67011. +
  67012. + /* turn on the SSP */
  67013. + Ser4SSCR0 = 0;
  67014. + Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2) |
  67015. + SSCR0_SSE);
  67016. + Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk);
  67017. +}
  67018. +
  67019. +static void ssp_audio_shutdown(void)
  67020. +{
  67021. + Ser4SSCR0 = 0;
  67022. +}
  67023. +
  67024. +static int ssp_audio_ioctl( struct inode *inode, struct file *file,
  67025. + uint cmd, ulong arg)
  67026. +{
  67027. + long val;
  67028. + int ret = 0;
  67029. +
  67030. + /*
  67031. + * These are platform dependent ioctls which are not handled by the
  67032. + * generic sa1100-audio module.
  67033. + */
  67034. + switch (cmd) {
  67035. + case SNDCTL_DSP_STEREO:
  67036. + ret = get_user(val, (int *) arg);
  67037. + if (ret)
  67038. + return ret;
  67039. + /* Simple standard DACs are stereo only */
  67040. + ret = (val == 0) ? -EINVAL : 1;
  67041. + return put_user(ret, (int *) arg);
  67042. +
  67043. + case SNDCTL_DSP_CHANNELS:
  67044. + case SOUND_PCM_READ_CHANNELS:
  67045. + /* Simple standard DACs are stereo only */
  67046. + return put_user(AUDIO_CHANNELS, (long *) arg);
  67047. +
  67048. + case SNDCTL_DSP_SPEED:
  67049. + case SOUND_PCM_READ_RATE:
  67050. + /* We assume the clock doesn't change */
  67051. + return put_user(sample_rate, (long *) arg);
  67052. +
  67053. + case SNDCTL_DSP_SETFMT:
  67054. + case SNDCTL_DSP_GETFMTS:
  67055. + /* Simple standard DACs are 16-bit only */
  67056. + return put_user(AUDIO_FMT, (long *) arg);
  67057. +
  67058. + default:
  67059. + return -EINVAL;
  67060. + }
  67061. +
  67062. + return ret;
  67063. +}
  67064. +
  67065. +static audio_stream_t output_stream;
  67066. +
  67067. +static audio_state_t audio_state = {
  67068. + output_stream: &output_stream,
  67069. + output_dma: DMA_Ser4SSPWr,
  67070. + output_id: "Generic SSP sound",
  67071. + hw_init: ssp_audio_init,
  67072. + hw_shutdown: ssp_audio_shutdown,
  67073. + client_ioctl: ssp_audio_ioctl,
  67074. + sem: __MUTEX_INITIALIZER(audio_state.sem),
  67075. +};
  67076. +
  67077. +static int ssp_audio_open(struct inode *inode, struct file *file)
  67078. +{
  67079. + return sa1100_audio_attach(inode, file, &audio_state);
  67080. +}
  67081. +
  67082. +/*
  67083. + * Missing fields of this structure will be patched with the call
  67084. + * to sa1100_audio_attach().
  67085. + */
  67086. +static struct file_operations ssp_audio_fops = {
  67087. + open: ssp_audio_open,
  67088. + owner: THIS_MODULE
  67089. +};
  67090. +
  67091. +static int audio_dev_id;
  67092. +
  67093. +static int __init sa1100ssp_audio_init(void)
  67094. +{
  67095. + int ret;
  67096. +
  67097. + if (!machine_is_lart()) {
  67098. + printk(KERN_ERR AUDIO_NAME ": no support for this SA-1100 design!\n");
  67099. + /* look at ssp_audio_init() for specific initialisations */
  67100. + return -ENODEV;
  67101. + }
  67102. +
  67103. + /* register devices */
  67104. + audio_dev_id = register_sound_dsp(&ssp_audio_fops, -1);
  67105. +
  67106. + printk( KERN_INFO AUDIO_NAME " initialized\n" );
  67107. + return 0;
  67108. +}
  67109. +
  67110. +static void __exit sa1100ssp_audio_exit(void)
  67111. +{
  67112. + unregister_sound_dsp(audio_dev_id);
  67113. +}
  67114. +
  67115. +module_init(sa1100ssp_audio_init);
  67116. +module_exit(sa1100ssp_audio_exit);
  67117. +
  67118. +MODULE_AUTHOR("Nicolas Pitre");
  67119. +MODULE_DESCRIPTION("Glue audio driver for a simple DAC on the SA1100's SSP port");
  67120. +
  67121. +MODULE_PARM(sample_rate, "i");
  67122. +MODULE_PARM_DESC(sample_rate, "Sample rate of the audio DAC, default is 44100");
  67123. +
  67124. +EXPORT_NO_SYMBOLS;
  67125. diff -urN linux-2.4.26/drivers/sound/sa1111-ac97.c linux-2.4.26-vrs1/drivers/sound/sa1111-ac97.c
  67126. --- linux-2.4.26/drivers/sound/sa1111-ac97.c 1970-01-01 01:00:00.000000000 +0100
  67127. +++ linux-2.4.26-vrs1/drivers/sound/sa1111-ac97.c 2004-01-14 21:32:26.000000000 +0000
  67128. @@ -0,0 +1,518 @@
  67129. +/*
  67130. + * Glue audio driver for the CS4205 and CS4201 AC'97 codecs.
  67131. + * largely based on the framework provided by sa1111-uda1341.c.
  67132. + *
  67133. + * Copyright (c) 2002 Bertrik Sikken (bertrik.sikken@technolution.nl)
  67134. + * Copyright (c) 2002 Robert Whaley (rwhaley@applieddata.net)
  67135. + *
  67136. + * This program is free software; you can redistribute it and/or
  67137. + * modify it under the terms of the GNU General Public License.
  67138. + *
  67139. + * This driver makes use of the ac97_codec module (for mixer registers)
  67140. + * and the sa1100-audio module (for DMA).
  67141. + *
  67142. + * History:
  67143. + *
  67144. + * 2002-04-04 Initial version.
  67145. + * 2002-04-10 Updated mtd_audio_init to improve choppy sound
  67146. + * and hanging sound issue.
  67147. + * 2002-05-16 Updated for ADS Bitsy+ Robert Whaley
  67148. + * 2002-06-28 Cleanup and added retry for read register timeouts
  67149. + * 2002-08-14 Updated for ADS AGC Robert Whaley
  67150. + * 2002-12-26 Cleanup, remove CONFIG_PM (it's handled by sa1100-audio.c)
  67151. + *
  67152. + */
  67153. +
  67154. +#include <linux/module.h>
  67155. +#include <linux/init.h>
  67156. +#include <linux/types.h>
  67157. +#include <linux/fs.h>
  67158. +#include <linux/delay.h>
  67159. +#include <linux/pm.h>
  67160. +#include <linux/errno.h>
  67161. +#include <linux/proc_fs.h>
  67162. +#include <linux/sound.h>
  67163. +#include <linux/soundcard.h>
  67164. +#include <linux/ac97_codec.h>
  67165. +
  67166. +#include <asm/semaphore.h>
  67167. +#include <asm/uaccess.h>
  67168. +#include <asm/dma.h>
  67169. +#include <asm/hardware/sa1111.h>
  67170. +
  67171. +#include "sa1100-audio.h"
  67172. +
  67173. +/* SAC FIFO depth, low nibble is transmit fifo, high nibble is receive FIFO */
  67174. +#define SAC_FIFO_DEPTH 0x77
  67175. +
  67176. +// #define DEBUG
  67177. +
  67178. +#ifdef DEBUG
  67179. +#define DPRINTK( x... ) printk( ##x )
  67180. +#else
  67181. +#define DPRINTK( x... )
  67182. +#endif
  67183. +
  67184. +/*
  67185. + Our codec data
  67186. +*/
  67187. +static struct ac97_codec ac97codec;
  67188. +static int audio_dev_id, mixer_dev_id;
  67189. +static audio_stream_t output_stream, input_stream;
  67190. +
  67191. +/* proc info */
  67192. +
  67193. +struct proc_dir_entry *ac97_ps;
  67194. +
  67195. +static int sa1111_ac97_set_adc_rate(long rate);
  67196. +static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val);
  67197. +static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg);
  67198. +
  67199. +static int
  67200. +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  67201. +{
  67202. + /*
  67203. + * We only accept mixer (type 'M') ioctls.
  67204. + */
  67205. + if (_IOC_TYPE(cmd) != 'M') {
  67206. + return -EINVAL;
  67207. + }
  67208. +
  67209. + /* pass the ioctl to the ac97 mixer */
  67210. + return ac97codec.mixer_ioctl(&ac97codec, cmd, arg);
  67211. +}
  67212. +
  67213. +
  67214. +static struct file_operations sa1111_ac97_mixer_fops = {
  67215. + ioctl: mixer_ioctl,
  67216. + owner: THIS_MODULE
  67217. +};
  67218. +
  67219. +static void sa1111_ac97_power_off(void *dummy)
  67220. +{
  67221. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  67222. + /* turn off audio and audio amp */
  67223. + ADS_CPLD_PCON |= (ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
  67224. +
  67225. + /* make GPIO11 high impeadence */
  67226. + GPDR &= ~GPIO_GPIO11;
  67227. +
  67228. + /* disable SACR0 so we can make these pins high impeadence */
  67229. + SACR0 &= ~SACR0_ENB;
  67230. +
  67231. + /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
  67232. + PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
  67233. +
  67234. +#endif
  67235. +
  67236. +#ifdef CONFIG_SA1100_ADSAGC
  67237. + /* turn off audio and audio amp */
  67238. + ADS_CR1 &= ~(ADS_CR1_CODEC | ADS_CR1_AMP);
  67239. +
  67240. + /* disable SACR0 so we can make these pins high impeadence */
  67241. + SACR0 &= ~SACR0_ENB;
  67242. +
  67243. + /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
  67244. + PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
  67245. +
  67246. +#endif
  67247. +}
  67248. +
  67249. +
  67250. +static void sa1111_ac97_power_on(void *dummy)
  67251. +{
  67252. + int ret, i;
  67253. +
  67254. + /* disable L3 */
  67255. + SACR1 = 0;
  67256. +
  67257. + SKPCR |= (SKPCR_ACCLKEN); /* enable ac97 clock */
  67258. + udelay(50);
  67259. +
  67260. + /* BIT_CLK is input to SA1111, DMA thresholds 9 (both dirs) */
  67261. + SACR0 |= SACR0_BCKD | (SAC_FIFO_DEPTH << 8);
  67262. +
  67263. + /* reset SAC registers */
  67264. + SACR0 &= ~SACR0_RST;
  67265. + udelay(50);
  67266. + SACR0 |= SACR0_RST;
  67267. + udelay(50);
  67268. + SACR0 &= ~SACR0_RST;
  67269. +
  67270. + /* setup SA1111 to use AC'97 */
  67271. + SBI_SKCR |= SKCR_SELAC; /* select ac97 */
  67272. + udelay(50);
  67273. +
  67274. + /* issue a cold AC97 reset */
  67275. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  67276. +
  67277. + /* initialize reset line */
  67278. + GAFR &= ~GPIO_GPIO11;
  67279. + GPDR |= GPIO_GPIO11;
  67280. + GPSR = GPIO_GPIO11;
  67281. +
  67282. + /* turn on audio and audio amp */
  67283. + ADS_CPLD_PCON &= ~(ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
  67284. + mdelay(5);
  67285. +
  67286. + /* reset by lowering the reset pin momentarily */
  67287. + DPRINTK("reseting codec via GPIO11\n");
  67288. + GPCR = GPIO_GPIO11;
  67289. + udelay(5);
  67290. + GPSR = GPIO_GPIO11;
  67291. + udelay(10);
  67292. +
  67293. +#endif
  67294. +#ifdef CONFIG_SA1100_ADSAGC
  67295. +
  67296. + /* turn on audio and audio amp */
  67297. + DPRINTK("before turning on power. ADS_CR1: %x\n", ADS_CR1);
  67298. + ADS_CR1 |= (ADS_CR1_AMP | ADS_CR1_CODEC);
  67299. + DPRINTK("after turnning on power. ADS_CR1: %x\n", ADS_CR1);
  67300. + mdelay(5);
  67301. +
  67302. + /* reset by lowering the reset pin momentarily */
  67303. + DPRINTK("reseting codec via CPLD\n");
  67304. + ADS_CR1 |= ADS_CR1_AUDIO_RST;
  67305. + DPRINTK("after reset1. ADS_CR1: %x\n", ADS_CR1);
  67306. + udelay(5);
  67307. + ADS_CR1 &= ~ADS_CR1_AUDIO_RST;
  67308. + DPRINTK("after reset2. ADS_CR1: %x\n", ADS_CR1);
  67309. + udelay(10);
  67310. +
  67311. +#endif
  67312. + SACR2 = 0;
  67313. + udelay(50);
  67314. +
  67315. + DPRINTK("before SW reset: SACR2: %x\n", SACR2);
  67316. + SACR2 = SACR2_RESET;
  67317. + DPRINTK("after SW reset: SACR2: %x\n", SACR2);
  67318. + udelay(50);
  67319. +
  67320. + /* set AC97 slot 3 and 4 (PCM out) to valid */
  67321. + SACR2 = (SACR2_RESET | SACR2_TS3V | SACR2_TS4V);
  67322. +
  67323. + /* enable SAC */
  67324. + SACR0 |= SACR0_ENB;
  67325. +
  67326. + i = 100;
  67327. + while (!(SASR1 & SASR1_CRDY)) {
  67328. + if (!i--) {
  67329. + printk("Didn't get CRDY. SASR1=%x SKID=%x\n", SASR1, SBI_SKID);
  67330. + break;
  67331. + }
  67332. + udelay(50);
  67333. + }
  67334. +
  67335. + if (!(ret = ac97_probe_codec(&ac97codec))) {
  67336. + printk("ac97_probe_codec failed (%d)\n", ret);
  67337. + return;
  67338. + }
  67339. +
  67340. + /* mic ADC on, disable VRA, disable VRM */
  67341. + sa1111_ac97_write_reg(&ac97codec, AC97_EXTENDED_STATUS, 0x0200);
  67342. +}
  67343. +
  67344. +
  67345. +/*
  67346. + * Audio interface
  67347. + */
  67348. +
  67349. +
  67350. +static int sa1111_ac97_audio_ioctl(struct inode *inode, struct file *file,
  67351. + uint cmd, ulong arg)
  67352. +{
  67353. + long val;
  67354. + int ret = 0;
  67355. +
  67356. + DPRINTK("sa1111_ac97_audio_ioctl\n");
  67357. +
  67358. + /*
  67359. + * These are platform dependent ioctls which are not handled by the
  67360. + * generic sa1100-audio module.
  67361. + */
  67362. + switch (cmd) {
  67363. + case SNDCTL_DSP_STEREO:
  67364. + ret = get_user(val, (int *) arg);
  67365. + if (ret) {
  67366. + return ret;
  67367. + }
  67368. + /* the cs42xx is stereo only */
  67369. + ret = (val == 0) ? -EINVAL : 1;
  67370. + return put_user(ret, (int *) arg);
  67371. +
  67372. + case SNDCTL_DSP_CHANNELS:
  67373. + case SOUND_PCM_READ_CHANNELS:
  67374. + /* the cs42xx is stereo only */
  67375. + return put_user(2, (long *) arg);
  67376. +
  67377. +#define SA1100_AC97_IOCTL_EXTRAS
  67378. +
  67379. +#ifdef SA1100_AC97_IOCTL_EXTRAS
  67380. +
  67381. +#define SNDCTL_DSP_AC97_CMD _SIOWR('P', 99, int)
  67382. +#define SNDCTL_DSP_INPUT_SPEED _SIOWR('P', 98, int)
  67383. +#define SOUND_PCM_READ_INPUT_RATE _SIOWR('P', 97, int)
  67384. +
  67385. + case SNDCTL_DSP_AC97_CMD:
  67386. +
  67387. + ret = get_user(val, (long *) arg);
  67388. + if (ret) {
  67389. + break;
  67390. + }
  67391. + sa1111_ac97_write_reg(&ac97codec, (u8) ((val & 0xff000000) >> 24), (u16) (val & 0xffff));
  67392. + return 0;
  67393. +
  67394. +
  67395. + case SNDCTL_DSP_INPUT_SPEED:
  67396. + ret = get_user(val, (long *) arg);
  67397. + // acc code here to set the speed
  67398. + if (ret) {
  67399. + break;
  67400. + }
  67401. + // note that this only changes the ADC rate, not the
  67402. + // rate of the DAC.
  67403. + ret = sa1111_ac97_set_adc_rate(val);
  67404. + if (ret)
  67405. + break;
  67406. + return put_user(val, (long *) arg);
  67407. +
  67408. + case SOUND_PCM_READ_INPUT_RATE:
  67409. +
  67410. + return put_user((long) sa1111_ac97_read_reg(&ac97codec, 0x32), (long *) arg);
  67411. +
  67412. +
  67413. +#endif
  67414. +
  67415. + case SNDCTL_DSP_SPEED:
  67416. + ret = get_user(val, (long *) arg);
  67417. + if (ret) {
  67418. + break;
  67419. + }
  67420. +
  67421. + case SOUND_PCM_READ_RATE:
  67422. + /* only 48 kHz playback is supported by the SA1111 */
  67423. + return put_user(48000L, (long *) arg);
  67424. +
  67425. + case SNDCTL_DSP_SETFMT:
  67426. + case SNDCTL_DSP_GETFMTS:
  67427. + /* we can do 16-bit only */
  67428. + return put_user(AFMT_S16_LE, (long *) arg);
  67429. +
  67430. + default:
  67431. + /* Maybe this is meant for the mixer (As per OSS Docs) */
  67432. + return mixer_ioctl(inode, file, cmd, arg);
  67433. + }
  67434. +
  67435. + return ret;
  67436. +}
  67437. +
  67438. +
  67439. +static audio_state_t audio_state = {
  67440. + output_stream: &output_stream,
  67441. + input_stream: &input_stream,
  67442. + skip_dma_init: 1, /* done locally */
  67443. + hw_init: sa1111_ac97_power_on,
  67444. + hw_shutdown: sa1111_ac97_power_off,
  67445. + client_ioctl: sa1111_ac97_audio_ioctl,
  67446. + sem: __MUTEX_INITIALIZER(audio_state.sem),
  67447. +};
  67448. +
  67449. +
  67450. +static int sa1111_ac97_audio_open(struct inode *inode, struct file *file)
  67451. +{
  67452. + return sa1100_audio_attach(inode, file, &audio_state);
  67453. +}
  67454. +
  67455. +
  67456. +/*
  67457. + * Missing fields of this structure will be patched with the call
  67458. + * to sa1100_audio_attach().
  67459. + */
  67460. +static struct file_operations sa1111_ac97_audio_fops = {
  67461. + open: sa1111_ac97_audio_open,
  67462. + owner: THIS_MODULE
  67463. +};
  67464. +
  67465. +
  67466. +static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val)
  67467. +{
  67468. + int i;
  67469. +
  67470. + /* reset status bits */
  67471. + SASCR = SASCR_DTS;
  67472. +
  67473. + /* write command and data registers */
  67474. + ACCAR = reg << 12;
  67475. + ACCDR = val << 4;
  67476. +
  67477. + /* wait for data to be transmitted */
  67478. + i = 0;
  67479. + while ((SASR1 & SASR1_CADT) == 0) {
  67480. + udelay(50);
  67481. + if (++i > 10) {
  67482. + DPRINTK("sa1111_ac97_write_reg failed (data not transmitted. SASR1: %x)\n", SASR1);
  67483. + break;
  67484. + }
  67485. + }
  67486. +
  67487. + DPRINTK("<%03d> sa1111_ac97_write_reg, [%02X]=%04X\n", i, reg, val);
  67488. +}
  67489. +
  67490. +
  67491. +static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg)
  67492. +{
  67493. + u16 val;
  67494. + int i;
  67495. + int retry = 10;
  67496. +
  67497. + do {
  67498. + /* reset status bits */
  67499. + SASCR = SASCR_RDD | SASCR_STO;
  67500. +
  67501. + /* write command register */
  67502. + ACCAR = (reg | 0x80) << 12;
  67503. + ACCDR = 0;
  67504. +
  67505. + /* wait for SADR bit in SASR1 */
  67506. + i = 0;
  67507. + while ((SASR1 & SASR1_SADR) == 0) {
  67508. + udelay(50);
  67509. + if (++i > 10) {
  67510. + DPRINTK("<---> sa1111_ac97_read_reg failed\n");
  67511. + retry--;
  67512. + break;
  67513. + }
  67514. + if ((SASR1 & SASR1_RSTO) != 0) {
  67515. + DPRINTK("sa1111_ac97_read_reg *timeout*\n");
  67516. + retry--;
  67517. + break;
  67518. + }
  67519. + }
  67520. +
  67521. + } while ((SASR1 & SASR1_SADR) == 0 && retry > 0);
  67522. +
  67523. + val = ACSDR >> 4;
  67524. +
  67525. + DPRINTK("<%03d> sa1111_ac97_read_reg, [%02X]=%04X\n", i, reg, val);
  67526. + return val;
  67527. +}
  67528. +
  67529. +
  67530. +/* wait for codec ready */
  67531. +static void sa1111_ac97_ready(struct ac97_codec *dev)
  67532. +{
  67533. + int i;
  67534. + u16 val;
  67535. +
  67536. + i = 0;
  67537. + while ((SASR1 & SASR1_CRDY) == 0) {
  67538. + udelay(50);
  67539. + if (++i > 10) {
  67540. + DPRINTK("sa1111_ac97_ready failed\n");
  67541. + return;
  67542. + }
  67543. + }
  67544. + DPRINTK("codec_ready bit took %d cycles\n", i);
  67545. +
  67546. + /* Wait for analog parts of codec to initialise */
  67547. + i = 0;
  67548. + do {
  67549. + val = sa1111_ac97_read_reg(&ac97codec, AC97_POWER_CONTROL);
  67550. + if (++i > 100) {
  67551. + break;
  67552. + }
  67553. + mdelay(10);
  67554. + } while ((val & 0xF) != 0xF || val == 0xFFFF);
  67555. +
  67556. + /* the cs42xx typically takes 150 ms to initialise */
  67557. +
  67558. + DPRINTK("analog init took %d cycles\n", i);
  67559. +}
  67560. +
  67561. +
  67562. +static int __init sa1111_ac97_init(void)
  67563. +{
  67564. + int ret;
  67565. +
  67566. + // SBI_SKCR |= SKCR_RCLKEN;
  67567. +
  67568. + DPRINTK("sa1111_ac97_init\n");
  67569. +
  67570. + /* install the ac97 mixer module */
  67571. + ac97codec.codec_read = sa1111_ac97_read_reg;
  67572. + ac97codec.codec_write = sa1111_ac97_write_reg;
  67573. + ac97codec.codec_wait = sa1111_ac97_ready;
  67574. +
  67575. + /* Acquire and initialize DMA */
  67576. + ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
  67577. + SA1111_SAC_XMT_CHANNEL);
  67578. + if (ret < 0) {
  67579. + printk("DMA request for SAC output failed\n");
  67580. + return ret;
  67581. + }
  67582. +
  67583. + ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
  67584. + SA1111_SAC_RCV_CHANNEL);
  67585. + if (ret < 0) {
  67586. + printk("DMA request for SAC input failed\n");
  67587. + sa1100_free_dma(output_stream.dma_ch);
  67588. + return ret;
  67589. + }
  67590. + /* register devices */
  67591. + audio_dev_id = register_sound_dsp(&sa1111_ac97_audio_fops, -1);
  67592. + mixer_dev_id = register_sound_mixer(&sa1111_ac97_mixer_fops, -1);
  67593. +
  67594. +
  67595. + /* setup proc entry */
  67596. + ac97_ps = create_proc_read_entry ("driver/sa1111-ac97", 0, NULL,
  67597. + ac97_read_proc, &ac97codec);
  67598. +
  67599. + return 0;
  67600. +}
  67601. +
  67602. +
  67603. +static void __exit sa1111_ac97_exit(void)
  67604. +{
  67605. + SKPCR &= ~SKPCR_ACCLKEN; /* disable ac97 clock */
  67606. + SBI_SKCR &= ~SKCR_SELAC; /* deselect ac97 */
  67607. +
  67608. + unregister_sound_dsp(audio_dev_id);
  67609. + unregister_sound_mixer(mixer_dev_id);
  67610. + sa1100_free_dma(output_stream.dma_ch);
  67611. + sa1100_free_dma(input_stream.dma_ch);
  67612. +}
  67613. +
  67614. +static int sa1111_ac97_set_adc_rate(long rate)
  67615. +{
  67616. +
  67617. + // note this only changes the rate of the ADC, the DAC is fixed at 48K.
  67618. + // this is due to limitations of the SA1111 chip
  67619. +
  67620. + u16 code = rate;
  67621. +
  67622. + switch (rate) {
  67623. + case 8000:
  67624. + case 11025:
  67625. + case 16000:
  67626. + case 22050:
  67627. + case 32000:
  67628. + case 44100:
  67629. + case 48000:
  67630. + break;
  67631. + default:
  67632. + return -1;
  67633. + }
  67634. + sa1111_ac97_write_reg(&ac97codec, 0x2A, 0x0001);
  67635. + sa1111_ac97_write_reg(&ac97codec, 0x32, code);
  67636. + return 0;
  67637. +}
  67638. +
  67639. +module_init(sa1111_ac97_init);
  67640. +module_exit(sa1111_ac97_exit);
  67641. +
  67642. +MODULE_AUTHOR("Bertrik Sikken, Technolution B.V., Netherlands");
  67643. +MODULE_DESCRIPTION("Glue audio driver for AC'97 codec");
  67644. +MODULE_LICENSE("GPL");
  67645. +
  67646. +EXPORT_NO_SYMBOLS;
  67647. diff -urN linux-2.4.26/drivers/sound/sa1111-uda1341.c linux-2.4.26-vrs1/drivers/sound/sa1111-uda1341.c
  67648. --- linux-2.4.26/drivers/sound/sa1111-uda1341.c 1970-01-01 01:00:00.000000000 +0100
  67649. +++ linux-2.4.26-vrs1/drivers/sound/sa1111-uda1341.c 2004-01-14 21:32:26.000000000 +0000
  67650. @@ -0,0 +1,282 @@
  67651. +/*
  67652. + * Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.
  67653. + *
  67654. + * Copyright (c) 2000 John Dorsey
  67655. + *
  67656. + * This program is free software; you can redistribute it and/or
  67657. + * modify it under the terms of the GNU General Public License.
  67658. + *
  67659. + * History:
  67660. + *
  67661. + * 2000-09-04 John Dorsey SA-1111 Serial Audio Controller support
  67662. + * was initially added to the sa1100-uda1341.c
  67663. + * driver.
  67664. + *
  67665. + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
  67666. + * the former sa1100-uda1341.c driver.
  67667. + *
  67668. + * 2001-09-23 Russell King Remove old L3 bus driver.
  67669. + */
  67670. +
  67671. +#include <linux/config.h>
  67672. +#include <linux/module.h>
  67673. +#include <linux/init.h>
  67674. +#include <linux/types.h>
  67675. +#include <linux/fs.h>
  67676. +#include <linux/delay.h>
  67677. +#include <linux/sched.h>
  67678. +#include <linux/errno.h>
  67679. +#include <linux/sound.h>
  67680. +#include <linux/soundcard.h>
  67681. +#include <linux/ioport.h>
  67682. +#include <linux/pm.h>
  67683. +#include <linux/l3/l3.h>
  67684. +#include <linux/l3/uda1341.h>
  67685. +
  67686. +#include <asm/semaphore.h>
  67687. +#include <asm/mach-types.h>
  67688. +#include <asm/uaccess.h>
  67689. +#include <asm/hardware.h>
  67690. +#include <asm/dma.h>
  67691. +#include <asm/arch/assabet.h>
  67692. +#include <asm/hardware/sa1111.h>
  67693. +
  67694. +#include "sa1100-audio.h"
  67695. +
  67696. +#undef DEBUG
  67697. +#ifdef DEBUG
  67698. +#define DPRINTK( x... ) printk( ##x )
  67699. +#else
  67700. +#define DPRINTK( x... )
  67701. +#endif
  67702. +
  67703. +
  67704. +/*
  67705. + * Definitions
  67706. + */
  67707. +
  67708. +#define AUDIO_RATE_DEFAULT 22050
  67709. +
  67710. +#define AUDIO_CLK_BASE 561600
  67711. +
  67712. +
  67713. +
  67714. +/*
  67715. + * Mixer interface
  67716. + */
  67717. +
  67718. +static struct l3_client uda1341;
  67719. +
  67720. +static int
  67721. +mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  67722. +{
  67723. + /*
  67724. + * We only accept mixer (type 'M') ioctls.
  67725. + */
  67726. + if (_IOC_TYPE(cmd) != 'M')
  67727. + return -EINVAL;
  67728. +
  67729. + return l3_command(&uda1341, cmd, (void *)arg);
  67730. +}
  67731. +
  67732. +static struct file_operations uda1341_mixer_fops = {
  67733. + ioctl: mixer_ioctl,
  67734. + owner: THIS_MODULE
  67735. +};
  67736. +
  67737. +
  67738. +/*
  67739. + * Audio interface
  67740. + */
  67741. +
  67742. +static int audio_clk_div = (AUDIO_CLK_BASE + AUDIO_RATE_DEFAULT/2)/AUDIO_RATE_DEFAULT;
  67743. +
  67744. +static void sa1111_audio_init(void *dummy)
  67745. +{
  67746. +#ifdef CONFIG_ASSABET_NEPONSET
  67747. + if (machine_is_assabet()) {
  67748. + /* Select I2S audio (instead of AC-Link) */
  67749. + AUD_CTL = AUD_SEL_1341;
  67750. + }
  67751. +#endif
  67752. +#ifdef CONFIG_SA1100_JORNADA720
  67753. + if (machine_is_jornada720()) {
  67754. + /* LDD4 is speaker, LDD3 is microphone */
  67755. + PPSR &= ~(PPC_LDD3 | PPC_LDD4);
  67756. + PPDR |= PPC_LDD3 | PPC_LDD4;
  67757. + PPSR |= PPC_LDD4; /* enable speaker */
  67758. + PPSR |= PPC_LDD3; /* enable microphone */
  67759. + }
  67760. +#endif
  67761. +
  67762. + SBI_SKCR &= ~SKCR_SELAC;
  67763. +
  67764. + /* Enable the I2S clock and L3 bus clock: */
  67765. + SKPCR |= (SKPCR_I2SCLKEN | SKPCR_L3CLKEN);
  67766. +
  67767. + /* Activate and reset the Serial Audio Controller */
  67768. + SACR0 |= (SACR0_ENB | SACR0_RST);
  67769. + mdelay(5);
  67770. + SACR0 &= ~SACR0_RST;
  67771. +
  67772. + /* For I2S, BIT_CLK is supplied internally. The "SA-1111
  67773. + * Specification Update" mentions that the BCKD bit should
  67774. + * be interpreted as "0 = output". Default clock divider
  67775. + * is 22.05kHz.
  67776. + *
  67777. + * Select I2S, L3 bus. "Recording" and "Replaying"
  67778. + * (receive and transmit) are enabled.
  67779. + */
  67780. + SACR1 = SACR1_L3EN;
  67781. + SKAUD = audio_clk_div - 1;
  67782. +
  67783. + /* Initialize the UDA1341 internal state */
  67784. + l3_open(&uda1341);
  67785. +}
  67786. +
  67787. +static void sa1111_audio_shutdown(void *dummy)
  67788. +{
  67789. + l3_close(&uda1341);
  67790. + SACR0 &= ~SACR0_ENB;
  67791. +}
  67792. +
  67793. +static int sa1111_audio_ioctl( struct inode *inode, struct file *file,
  67794. + uint cmd, ulong arg)
  67795. +{
  67796. + long val;
  67797. + int ret = 0;
  67798. +
  67799. + switch (cmd) {
  67800. + case SNDCTL_DSP_STEREO:
  67801. + ret = get_user(val, (int *) arg);
  67802. + if (ret)
  67803. + return ret;
  67804. + /* the UDA1341 is stereo only */
  67805. + ret = (val == 0) ? -EINVAL : 1;
  67806. + return put_user(ret, (int *) arg);
  67807. +
  67808. + case SNDCTL_DSP_CHANNELS:
  67809. + case SOUND_PCM_READ_CHANNELS:
  67810. + /* the UDA1341 is stereo only */
  67811. + return put_user(2, (long *) arg);
  67812. +
  67813. + case SNDCTL_DSP_SPEED:
  67814. + ret = get_user(val, (long *) arg);
  67815. + if (ret) break;
  67816. + if (val < 8000) val = 8000;
  67817. + if (val > 48000) val = 48000;
  67818. + audio_clk_div = (AUDIO_CLK_BASE + val/2)/val;
  67819. + SKAUD = audio_clk_div - 1;
  67820. + /* fall through */
  67821. +
  67822. + case SOUND_PCM_READ_RATE:
  67823. + return put_user(AUDIO_CLK_BASE/audio_clk_div, (long *) arg);
  67824. +
  67825. + case SNDCTL_DSP_SETFMT:
  67826. + case SNDCTL_DSP_GETFMTS:
  67827. + /* we can do 16-bit only */
  67828. + return put_user(AFMT_S16_LE, (long *) arg);
  67829. +
  67830. + default:
  67831. + /* Maybe this is meant for the mixer (as per OSS Docs) */
  67832. + return mixer_ioctl(inode, file, cmd, arg);
  67833. + }
  67834. +
  67835. + return ret;
  67836. +}
  67837. +
  67838. +static audio_stream_t output_stream, input_stream;
  67839. +
  67840. +static audio_state_t audio_state = {
  67841. + output_stream: &output_stream,
  67842. + input_stream: &input_stream,
  67843. + skip_dma_init: 1, /* done locally */
  67844. + hw_init: sa1111_audio_init,
  67845. + hw_shutdown: sa1111_audio_shutdown,
  67846. + client_ioctl: sa1111_audio_ioctl,
  67847. + sem: __MUTEX_INITIALIZER(audio_state.sem),
  67848. +};
  67849. +
  67850. +static int sa1111_audio_open(struct inode *inode, struct file *file)
  67851. +{
  67852. + return sa1100_audio_attach(inode, file, &audio_state);
  67853. +}
  67854. +
  67855. +/*
  67856. + * Missing fields of this structure will be patched with the call
  67857. + * to sa1100_audio_attach().
  67858. + */
  67859. +static struct file_operations sa1111_audio_fops = {
  67860. + open: sa1111_audio_open,
  67861. + owner: THIS_MODULE
  67862. +};
  67863. +
  67864. +static int audio_dev_id, mixer_dev_id;
  67865. +
  67866. +static int __init sa1111_uda1341_init(void)
  67867. +{
  67868. + struct uda1341_cfg cfg;
  67869. + int ret;
  67870. +
  67871. + if ( !( (machine_is_assabet() && machine_has_neponset()) ||
  67872. + machine_is_jornada720() ||
  67873. + machine_is_badge4() ))
  67874. + return -ENODEV;
  67875. +
  67876. + if (!request_mem_region(_SACR0, 512, "sound"))
  67877. + return -EBUSY;
  67878. +
  67879. + ret = l3_attach_client(&uda1341, "l3-sa1111", "uda1341");
  67880. + if (ret)
  67881. + goto out;
  67882. +
  67883. + /* Acquire and initialize DMA */
  67884. + ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
  67885. + SA1111_SAC_XMT_CHANNEL);
  67886. + if (ret < 0)
  67887. + goto release_l3;
  67888. +
  67889. + ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
  67890. + SA1111_SAC_RCV_CHANNEL);
  67891. + if (ret < 0)
  67892. + goto release_dma;
  67893. +
  67894. + cfg.fs = 256;
  67895. + cfg.format = FMT_I2S;
  67896. + l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
  67897. +
  67898. + /* register devices */
  67899. + audio_dev_id = register_sound_dsp(&sa1111_audio_fops, -1);
  67900. + mixer_dev_id = register_sound_mixer(&uda1341_mixer_fops, -1);
  67901. +
  67902. + printk(KERN_INFO "Sound: SA1111 UDA1341: dsp id %d mixer id %d\n",
  67903. + audio_dev_id, mixer_dev_id);
  67904. + return 0;
  67905. +
  67906. +release_dma:
  67907. + sa1100_free_dma(output_stream.dma_ch);
  67908. +release_l3:
  67909. + l3_detach_client(&uda1341);
  67910. +out:
  67911. + release_mem_region(_SACR0, 512);
  67912. + return ret;
  67913. +}
  67914. +
  67915. +static void __exit sa1111_uda1341_exit(void)
  67916. +{
  67917. + unregister_sound_dsp(audio_dev_id);
  67918. + unregister_sound_mixer(mixer_dev_id);
  67919. + sa1100_free_dma(output_stream.dma_ch);
  67920. + sa1100_free_dma(input_stream.dma_ch);
  67921. + l3_detach_client(&uda1341);
  67922. +
  67923. + release_mem_region(_SACR0, 512);
  67924. +}
  67925. +
  67926. +module_init(sa1111_uda1341_init);
  67927. +module_exit(sa1111_uda1341_exit);
  67928. +
  67929. +MODULE_AUTHOR("John Dorsey, Nicolas Pitre");
  67930. +MODULE_DESCRIPTION("Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.");
  67931. +
  67932. +EXPORT_NO_SYMBOLS;
  67933. diff -urN linux-2.4.26/drivers/sound/uda1341.c linux-2.4.26-vrs1/drivers/sound/uda1341.c
  67934. --- linux-2.4.26/drivers/sound/uda1341.c 1970-01-01 01:00:00.000000000 +0100
  67935. +++ linux-2.4.26-vrs1/drivers/sound/uda1341.c 2004-01-14 21:32:26.000000000 +0000
  67936. @@ -0,0 +1,511 @@
  67937. +/*
  67938. + * Philips UDA1341 mixer device driver
  67939. + *
  67940. + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
  67941. + *
  67942. + * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V.
  67943. + *
  67944. + * This program is free software; you can redistribute it and/or
  67945. + * modify it under the terms of the GNU General Public License.
  67946. + *
  67947. + * History:
  67948. + *
  67949. + * 2000-05-21 Nicolas Pitre Initial release.
  67950. + *
  67951. + * 2000-08-19 Erik Bunce More inline w/ OSS API and UDA1341 docs
  67952. + * including fixed AGC and audio source handling
  67953. + *
  67954. + * 2000-11-30 Nicolas Pitre - More mixer functionalities.
  67955. + *
  67956. + * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
  67957. + * the former sa1100-uda1341.c driver.
  67958. + *
  67959. + * 2001-08-13 Russell King Re-written as part of the L3 interface
  67960. + */
  67961. +
  67962. +#include <linux/module.h>
  67963. +#include <linux/init.h>
  67964. +#include <linux/types.h>
  67965. +#include <linux/slab.h>
  67966. +#include <linux/errno.h>
  67967. +#include <linux/ioctl.h>
  67968. +#include <linux/soundcard.h>
  67969. +#include <linux/l3/l3.h>
  67970. +#include <linux/l3/uda1341.h>
  67971. +
  67972. +#include <asm/uaccess.h>
  67973. +
  67974. +#define DEF_VOLUME 65
  67975. +
  67976. +/*
  67977. + * UDA1341 L3 address and command types
  67978. + */
  67979. +#define UDA1341_L3ADDR 5
  67980. +#define UDA1341_DATA0 (UDA1341_L3ADDR << 2 | 0)
  67981. +#define UDA1341_DATA1 (UDA1341_L3ADDR << 2 | 1)
  67982. +#define UDA1341_STATUS (UDA1341_L3ADDR << 2 | 2)
  67983. +
  67984. +struct uda1341_regs {
  67985. + unsigned char stat0;
  67986. +#define STAT0 0x00
  67987. +#define STAT0_RST (1 << 6)
  67988. +#define STAT0_SC_MASK (3 << 4)
  67989. +#define STAT0_SC_512FS (0 << 4)
  67990. +#define STAT0_SC_384FS (1 << 4)
  67991. +#define STAT0_SC_256FS (2 << 4)
  67992. +#define STAT0_IF_MASK (7 << 1)
  67993. +#define STAT0_IF_I2S (0 << 1)
  67994. +#define STAT0_IF_LSB16 (1 << 1)
  67995. +#define STAT0_IF_LSB18 (2 << 1)
  67996. +#define STAT0_IF_LSB20 (3 << 1)
  67997. +#define STAT0_IF_MSB (4 << 1)
  67998. +#define STAT0_IF_LSB16MSB (5 << 1)
  67999. +#define STAT0_IF_LSB18MSB (6 << 1)
  68000. +#define STAT0_IF_LSB20MSB (7 << 1)
  68001. +#define STAT0_DC_FILTER (1 << 0)
  68002. +
  68003. + unsigned char stat1;
  68004. +#define STAT1 0x80
  68005. +#define STAT1_DAC_GAIN (1 << 6) /* gain of DAC */
  68006. +#define STAT1_ADC_GAIN (1 << 5) /* gain of ADC */
  68007. +#define STAT1_ADC_POL (1 << 4) /* polarity of ADC */
  68008. +#define STAT1_DAC_POL (1 << 3) /* polarity of DAC */
  68009. +#define STAT1_DBL_SPD (1 << 2) /* double speed playback */
  68010. +#define STAT1_ADC_ON (1 << 1) /* ADC powered */
  68011. +#define STAT1_DAC_ON (1 << 0) /* DAC powered */
  68012. +
  68013. + unsigned char data0_0;
  68014. +#define DATA0 0x00
  68015. +#define DATA0_VOLUME_MASK 0x3f
  68016. +#define DATA0_VOLUME(x) (x)
  68017. +
  68018. + unsigned char data0_1;
  68019. +#define DATA1 0x40
  68020. +#define DATA1_BASS(x) ((x) << 2)
  68021. +#define DATA1_BASS_MASK (15 << 2)
  68022. +#define DATA1_TREBLE(x) ((x))
  68023. +#define DATA1_TREBLE_MASK (3)
  68024. +
  68025. + unsigned char data0_2;
  68026. +#define DATA2 0x80
  68027. +#define DATA2_PEAKAFTER (1 << 5)
  68028. +#define DATA2_DEEMP_NONE (0 << 3)
  68029. +#define DATA2_DEEMP_32KHz (1 << 3)
  68030. +#define DATA2_DEEMP_44KHz (2 << 3)
  68031. +#define DATA2_DEEMP_48KHz (3 << 3)
  68032. +#define DATA2_MUTE (1 << 2)
  68033. +#define DATA2_FILTER_FLAT (0 << 0)
  68034. +#define DATA2_FILTER_MIN (1 << 0)
  68035. +#define DATA2_FILTER_MAX (3 << 0)
  68036. +
  68037. +#define EXTADDR(n) (0xc0 | (n))
  68038. +#define EXTDATA(d) (0xe0 | (d))
  68039. +
  68040. + unsigned char ext0;
  68041. +#define EXT0 0
  68042. +#define EXT0_CH1_GAIN(x) (x)
  68043. +
  68044. + unsigned char ext1;
  68045. +#define EXT1 1
  68046. +#define EXT1_CH2_GAIN(x) (x)
  68047. +
  68048. + unsigned char ext2;
  68049. +#define EXT2 2
  68050. +#define EXT2_MIC_GAIN_MASK (7 << 2)
  68051. +#define EXT2_MIC_GAIN(x) ((x) << 2)
  68052. +#define EXT2_MIXMODE_DOUBLEDIFF (0)
  68053. +#define EXT2_MIXMODE_CH1 (1)
  68054. +#define EXT2_MIXMODE_CH2 (2)
  68055. +#define EXT2_MIXMODE_MIX (3)
  68056. +
  68057. + unsigned char ext4;
  68058. +#define EXT4 4
  68059. +#define EXT4_AGC_ENABLE (1 << 4)
  68060. +#define EXT4_INPUT_GAIN_MASK (3)
  68061. +#define EXT4_INPUT_GAIN(x) ((x) & 3)
  68062. +
  68063. + unsigned char ext5;
  68064. +#define EXT5 5
  68065. +#define EXT5_INPUT_GAIN(x) ((x) >> 2)
  68066. +
  68067. + unsigned char ext6;
  68068. +#define EXT6 6
  68069. +#define EXT6_AGC_CONSTANT_MASK (7 << 2)
  68070. +#define EXT6_AGC_CONSTANT(x) ((x) << 2)
  68071. +#define EXT6_AGC_LEVEL_MASK (3)
  68072. +#define EXT6_AGC_LEVEL(x) (x)
  68073. +};
  68074. +
  68075. +#define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
  68076. +#define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
  68077. +
  68078. +struct uda1341 {
  68079. + struct uda1341_regs regs;
  68080. + int active;
  68081. + unsigned short volume;
  68082. + unsigned short bass;
  68083. + unsigned short treble;
  68084. + unsigned short line;
  68085. + unsigned short mic;
  68086. + int mod_cnt;
  68087. +};
  68088. +
  68089. +#define ADD_FIELD(reg,field) \
  68090. + *p++ = reg | uda->regs.field
  68091. +
  68092. +#define ADD_EXTFIELD(reg,field) \
  68093. + *p++ = EXTADDR(reg); \
  68094. + *p++ = EXTDATA(uda->regs.field);
  68095. +
  68096. +static void uda1341_sync(struct l3_client *clnt)
  68097. +{
  68098. + struct uda1341 *uda = clnt->driver_data;
  68099. + char buf[24], *p = buf;
  68100. +
  68101. + ADD_FIELD(STAT0, stat0);
  68102. + ADD_FIELD(STAT1, stat1);
  68103. +
  68104. + if (p != buf)
  68105. + l3_write(clnt, UDA1341_STATUS, buf, p - buf);
  68106. +
  68107. + p = buf;
  68108. + ADD_FIELD(DATA0, data0_0);
  68109. + ADD_FIELD(DATA1, data0_1);
  68110. + ADD_FIELD(DATA2, data0_2);
  68111. + ADD_EXTFIELD(EXT0, ext0);
  68112. + ADD_EXTFIELD(EXT1, ext1);
  68113. + ADD_EXTFIELD(EXT2, ext2);
  68114. + ADD_EXTFIELD(EXT4, ext4);
  68115. + ADD_EXTFIELD(EXT5, ext5);
  68116. + ADD_EXTFIELD(EXT6, ext6);
  68117. +
  68118. + if (p != buf)
  68119. + l3_write(clnt, UDA1341_DATA0, buf, p - buf);
  68120. +}
  68121. +
  68122. +static void uda1341_cmd_init(struct l3_client *clnt)
  68123. +{
  68124. + struct uda1341 *uda = clnt->driver_data;
  68125. + char buf[2];
  68126. +
  68127. + uda->active = 1;
  68128. +
  68129. + buf[0] = uda->regs.stat0 | STAT0_RST;
  68130. + buf[1] = uda->regs.stat0;
  68131. +
  68132. + l3_write(clnt, UDA1341_STATUS, buf, 2);
  68133. +
  68134. + /* resend all parameters */
  68135. + uda1341_sync(clnt);
  68136. +}
  68137. +
  68138. +static int uda1341_configure(struct l3_client *clnt, struct uda1341_cfg *conf)
  68139. +{
  68140. + struct uda1341 *uda = clnt->driver_data;
  68141. + int ret = 0;
  68142. +
  68143. + uda->regs.stat0 &= ~(STAT0_SC_MASK | STAT0_IF_MASK);
  68144. +
  68145. + switch (conf->fs) {
  68146. + case 512: uda->regs.stat0 |= STAT0_SC_512FS; break;
  68147. + case 384: uda->regs.stat0 |= STAT0_SC_384FS; break;
  68148. + case 256: uda->regs.stat0 |= STAT0_SC_256FS; break;
  68149. + default: ret = -EINVAL; break;
  68150. + }
  68151. +
  68152. + switch (conf->format) {
  68153. + case FMT_I2S: uda->regs.stat0 |= STAT0_IF_I2S; break;
  68154. + case FMT_LSB16: uda->regs.stat0 |= STAT0_IF_LSB16; break;
  68155. + case FMT_LSB18: uda->regs.stat0 |= STAT0_IF_LSB18; break;
  68156. + case FMT_LSB20: uda->regs.stat0 |= STAT0_IF_LSB20; break;
  68157. + case FMT_MSB: uda->regs.stat0 |= STAT0_IF_MSB; break;
  68158. + case FMT_LSB16MSB: uda->regs.stat0 |= STAT0_IF_LSB16MSB; break;
  68159. + case FMT_LSB18MSB: uda->regs.stat0 |= STAT0_IF_LSB18MSB; break;
  68160. + case FMT_LSB20MSB: uda->regs.stat0 |= STAT0_IF_LSB20MSB; break;
  68161. + }
  68162. +
  68163. + if (ret == 0 && uda->active) {
  68164. + char buf = uda->regs.stat0 | STAT0;
  68165. + l3_write(clnt, UDA1341_STATUS, &buf, 1);
  68166. + }
  68167. + return ret;
  68168. +}
  68169. +
  68170. +static int uda1341_update_direct(struct l3_client *clnt, int cmd, void *arg)
  68171. +{
  68172. + struct uda1341 *uda = clnt->driver_data;
  68173. + struct l3_gain *v = arg;
  68174. + char newreg;
  68175. + int val;
  68176. +
  68177. + switch (cmd) {
  68178. + case L3_SET_VOLUME: /* set volume. val = 0 to 100 => 62 to 1 */
  68179. + uda->regs.data0_0 = DATA0_VOLUME(62 - ((v->left * 61) / 100));
  68180. + newreg = uda->regs.data0_0 | DATA0;
  68181. + break;
  68182. +
  68183. + case L3_SET_BASS: /* set bass. val = 50 to 100 => 0 to 12 */
  68184. + val = v->left - 50;
  68185. + if (val < 0)
  68186. + val = 0;
  68187. + uda->regs.data0_1 &= ~DATA1_BASS_MASK;
  68188. + uda->regs.data0_1 |= DATA1_BASS((val * 12) / 50);
  68189. + newreg = uda->regs.data0_1 | DATA1;
  68190. + break;
  68191. +
  68192. + case L3_SET_TREBLE: /* set treble. val = 50 to 100 => 0 to 3 */
  68193. + val = v->left - 50;
  68194. + if (val < 0)
  68195. + val = 0;
  68196. + uda->regs.data0_1 &= ~DATA1_TREBLE_MASK;
  68197. + uda->regs.data0_1 |= DATA1_TREBLE((val * 3) / 50);
  68198. + newreg = uda->regs.data0_1 | DATA1;
  68199. + break;
  68200. +
  68201. + default:
  68202. + return -EINVAL;
  68203. + }
  68204. +
  68205. + if (uda->active)
  68206. + l3_write(clnt, UDA1341_DATA0, &newreg, 1);
  68207. + return 0;
  68208. +}
  68209. +
  68210. +static int uda1341_update_indirect(struct l3_client *clnt, int cmd, void *arg)
  68211. +{
  68212. + struct uda1341 *uda = clnt->driver_data;
  68213. + struct l3_gain *gain = arg;
  68214. + struct l3_agc *agc = arg;
  68215. + char buf[8], *p = buf;
  68216. + int val, ret = 0;
  68217. +
  68218. + switch (cmd) {
  68219. + case L3_SET_GAIN:
  68220. + val = 31 - (gain->left * 31 / 100);
  68221. + switch (gain->channel) {
  68222. + case 1:
  68223. + uda->regs.ext0 = EXT0_CH1_GAIN(val);
  68224. + ADD_EXTFIELD(EXT0, ext0);
  68225. + break;
  68226. +
  68227. + case 2:
  68228. + uda->regs.ext1 = EXT1_CH2_GAIN(val);
  68229. + ADD_EXTFIELD(EXT1, ext1);
  68230. + break;
  68231. +
  68232. + default:
  68233. + ret = -EINVAL;
  68234. + }
  68235. + break;
  68236. +
  68237. + case L3_INPUT_AGC:
  68238. + if (agc->channel == 2) {
  68239. + if (agc->enable)
  68240. + uda->regs.ext4 |= EXT4_AGC_ENABLE;
  68241. + else
  68242. + uda->regs.ext4 &= ~EXT4_AGC_ENABLE;
  68243. +#if 0
  68244. + agc->level
  68245. + agc->attack
  68246. + agc->decay
  68247. +#endif
  68248. + ADD_EXTFIELD(EXT4, ext4);
  68249. + } else
  68250. + ret = -EINVAL;
  68251. + break;
  68252. +
  68253. + default:
  68254. + ret = -EINVAL;
  68255. + break;
  68256. + }
  68257. +
  68258. + if (ret == 0 && uda->active)
  68259. + l3_write(clnt, UDA1341_DATA0, buf, p - buf);
  68260. +
  68261. + return ret;
  68262. +}
  68263. +
  68264. +static int uda1341_mixer_ioctl(struct l3_client *clnt, int cmd, void *arg)
  68265. +{
  68266. + struct uda1341 *uda = clnt->driver_data;
  68267. + struct l3_gain gain;
  68268. + int val, nr = _IOC_NR(cmd), ret = 0;
  68269. +
  68270. + if (cmd == SOUND_MIXER_INFO) {
  68271. + struct mixer_info mi;
  68272. +
  68273. + strncpy(mi.id, "UDA1341", sizeof(mi.id));
  68274. + strncpy(mi.name, "Philips UDA1341", sizeof(mi.name));
  68275. + mi.modify_counter = uda->mod_cnt;
  68276. + return copy_to_user(arg, &mi, sizeof(mi));
  68277. + }
  68278. +
  68279. + if (_IOC_DIR(cmd) & _IOC_WRITE) {
  68280. + ret = get_user(val, (int *)arg);
  68281. + if (ret)
  68282. + goto out;
  68283. +
  68284. + gain.left = val & 255;
  68285. + gain.right = val >> 8;
  68286. + gain.channel = 0;
  68287. +
  68288. + switch (nr) {
  68289. + case SOUND_MIXER_VOLUME:
  68290. + uda->volume = val;
  68291. + uda->mod_cnt++;
  68292. + uda1341_update_direct(clnt, L3_SET_VOLUME, &gain);
  68293. + break;
  68294. +
  68295. + case SOUND_MIXER_BASS:
  68296. + uda->bass = val;
  68297. + uda->mod_cnt++;
  68298. + uda1341_update_direct(clnt, L3_SET_BASS, &gain);
  68299. + break;
  68300. +
  68301. + case SOUND_MIXER_TREBLE:
  68302. + uda->treble = val;
  68303. + uda->mod_cnt++;
  68304. + uda1341_update_direct(clnt, L3_SET_TREBLE, &gain);
  68305. + break;
  68306. +
  68307. + case SOUND_MIXER_LINE:
  68308. + uda->line = val;
  68309. + gain.channel = 1;
  68310. + uda->mod_cnt++;
  68311. + uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
  68312. + break;
  68313. +
  68314. + case SOUND_MIXER_MIC:
  68315. + uda->mic = val;
  68316. + gain.channel = 2;
  68317. + uda->mod_cnt++;
  68318. + uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
  68319. + break;
  68320. +
  68321. + case SOUND_MIXER_RECSRC:
  68322. + break;
  68323. +
  68324. + default:
  68325. + ret = -EINVAL;
  68326. + }
  68327. + }
  68328. +
  68329. + if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
  68330. + int nr = _IOC_NR(cmd);
  68331. + ret = 0;
  68332. +
  68333. + switch (nr) {
  68334. + case SOUND_MIXER_VOLUME: val = uda->volume; break;
  68335. + case SOUND_MIXER_BASS: val = uda->bass; break;
  68336. + case SOUND_MIXER_TREBLE: val = uda->treble; break;
  68337. + case SOUND_MIXER_LINE: val = uda->line; break;
  68338. + case SOUND_MIXER_MIC: val = uda->mic; break;
  68339. + case SOUND_MIXER_RECSRC: val = REC_MASK; break;
  68340. + case SOUND_MIXER_RECMASK: val = REC_MASK; break;
  68341. + case SOUND_MIXER_DEVMASK: val = DEV_MASK; break;
  68342. + case SOUND_MIXER_CAPS: val = 0; break;
  68343. + case SOUND_MIXER_STEREODEVS: val = 0; break;
  68344. + default: val = 0; ret = -EINVAL; break;
  68345. + }
  68346. +
  68347. + if (ret == 0)
  68348. + ret = put_user(val, (int *)arg);
  68349. + }
  68350. +out:
  68351. + return ret;
  68352. +}
  68353. +
  68354. +static int uda1341_attach(struct l3_client *clnt)
  68355. +{
  68356. + struct uda1341 *uda;
  68357. +
  68358. + uda = kmalloc(sizeof(*uda), GFP_KERNEL);
  68359. + if (!uda)
  68360. + return -ENOMEM;
  68361. +
  68362. + memset(uda, 0, sizeof(*uda));
  68363. +
  68364. + uda->volume = DEF_VOLUME | DEF_VOLUME << 8;
  68365. + uda->bass = 50 | 50 << 8;
  68366. + uda->treble = 50 | 50 << 8;
  68367. + uda->line = 88 | 88 << 8;
  68368. + uda->mic = 88 | 88 << 8;
  68369. +
  68370. + uda->regs.stat0 = STAT0_SC_256FS | STAT0_IF_LSB16;
  68371. + uda->regs.stat1 = STAT1_DAC_GAIN | STAT1_ADC_GAIN |
  68372. + STAT1_ADC_ON | STAT1_DAC_ON;
  68373. + uda->regs.data0_0 = DATA0_VOLUME(62 - ((DEF_VOLUME * 61) / 100));
  68374. + uda->regs.data0_1 = DATA1_BASS(0) | DATA1_TREBLE(0);
  68375. + uda->regs.data0_2 = DATA2_PEAKAFTER | DATA2_DEEMP_NONE |
  68376. + DATA2_FILTER_MAX;
  68377. + uda->regs.ext0 = EXT0_CH1_GAIN(4);
  68378. + uda->regs.ext1 = EXT1_CH2_GAIN(4);
  68379. + uda->regs.ext2 = EXT2_MIXMODE_MIX | EXT2_MIC_GAIN(4);
  68380. + uda->regs.ext4 = EXT4_AGC_ENABLE | EXT4_INPUT_GAIN(0);
  68381. + uda->regs.ext5 = EXT5_INPUT_GAIN(0);
  68382. + uda->regs.ext6 = EXT6_AGC_CONSTANT(3) | EXT6_AGC_LEVEL(0);
  68383. +
  68384. + clnt->driver_data = uda;
  68385. +
  68386. + return 0;
  68387. +}
  68388. +
  68389. +static void uda1341_detach(struct l3_client *clnt)
  68390. +{
  68391. + kfree(clnt->driver_data);
  68392. +}
  68393. +
  68394. +static int
  68395. +uda1341_command(struct l3_client *clnt, int cmd, void *arg)
  68396. +{
  68397. + int ret = -EINVAL;
  68398. +
  68399. + if (_IOC_TYPE(cmd) == 'M')
  68400. + ret = uda1341_mixer_ioctl(clnt, cmd, arg);
  68401. + else if (cmd == L3_UDA1341_CONFIGURE)
  68402. + ret = uda1341_configure(clnt, arg);
  68403. +
  68404. + return ret;
  68405. +}
  68406. +
  68407. +static int uda1341_open(struct l3_client *clnt)
  68408. +{
  68409. + uda1341_cmd_init(clnt);
  68410. + return 0;
  68411. +}
  68412. +
  68413. +static void uda1341_close(struct l3_client *clnt)
  68414. +{
  68415. + struct uda1341 *uda = clnt->driver_data;
  68416. + uda->active = 0;
  68417. +}
  68418. +
  68419. +static struct l3_ops uda1341_ops = {
  68420. + open: uda1341_open,
  68421. + command: uda1341_command,
  68422. + close: uda1341_close,
  68423. +};
  68424. +
  68425. +static struct l3_driver uda1341 = {
  68426. + name: UDA1341_NAME,
  68427. + attach_client: uda1341_attach,
  68428. + detach_client: uda1341_detach,
  68429. + ops: &uda1341_ops,
  68430. + owner: THIS_MODULE,
  68431. +};
  68432. +
  68433. +static int __init uda1341_init(void)
  68434. +{
  68435. + return l3_add_driver(&uda1341);
  68436. +}
  68437. +
  68438. +static void __exit uda1341_exit(void)
  68439. +{
  68440. + l3_del_driver(&uda1341);
  68441. +}
  68442. +
  68443. +module_init(uda1341_init);
  68444. +module_exit(uda1341_exit);
  68445. +
  68446. +MODULE_AUTHOR("Nicolas Pitre");
  68447. +MODULE_DESCRIPTION("Philips UDA1341 CODEC driver");
  68448. diff -urN linux-2.4.26/drivers/sound/vidc.c linux-2.4.26-vrs1/drivers/sound/vidc.c
  68449. --- linux-2.4.26/drivers/sound/vidc.c 2001-10-11 17:43:30.000000000 +0100
  68450. +++ linux-2.4.26-vrs1/drivers/sound/vidc.c 2004-01-14 21:32:26.000000000 +0000
  68451. @@ -40,6 +40,7 @@
  68452. #endif
  68453. #define VIDC_SOUND_CLOCK (250000)
  68454. +#define VIDC_SOUND_CLOCK_EXT (176400)
  68455. /*
  68456. * When using SERIAL SOUND mode (external DAC), the number of physical
  68457. @@ -192,28 +193,43 @@
  68458. return vidc_audio_format;
  68459. }
  68460. +#define my_abs(i) ((i)<0 ? -(i) : (i))
  68461. +
  68462. static int vidc_audio_set_speed(int dev, int rate)
  68463. {
  68464. if (rate) {
  68465. - unsigned int hwctrl, hwrate;
  68466. + unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
  68467. unsigned int newsize, new2size;
  68468. - /*
  68469. - * If we have selected 44.1kHz, use the DAC clock.
  68470. - */
  68471. - if (0 && rate == 44100) {
  68472. - hwctrl = 0x00000002;
  68473. - hwrate = 3;
  68474. - } else {
  68475. - hwctrl = 0x00000003;
  68476. + hwctrl = 0x00000003;
  68477. - hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
  68478. - if (hwrate < 3)
  68479. - hwrate = 3;
  68480. - if (hwrate > 255)
  68481. - hwrate = 255;
  68482. + /* Using internal clock */
  68483. + hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
  68484. + if (hwrate < 3)
  68485. + hwrate = 3;
  68486. + if (hwrate > 255)
  68487. + hwrate = 255;
  68488. - rate = VIDC_SOUND_CLOCK / hwrate;
  68489. + /* Using exernal clock */
  68490. + hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
  68491. + if (hwrate_ext < 3)
  68492. + hwrate_ext = 3;
  68493. + if (hwrate_ext > 255)
  68494. + hwrate_ext = 255;
  68495. +
  68496. + rate_int = VIDC_SOUND_CLOCK / hwrate;
  68497. + rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
  68498. +
  68499. + /* Chose between external and internal clock */
  68500. + if (my_abs(rate_ext-rate) < my_abs(rate_int-rate)) {
  68501. + /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
  68502. + hwrate=hwrate_ext;
  68503. + hwctrl=0x00000002;
  68504. + rate=rate_ext;
  68505. + } else {
  68506. + /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
  68507. + hwctrl=0x00000003;
  68508. + rate=rate_int;
  68509. }
  68510. vidc_writel(0xb0000000 | (hwrate - 2));
  68511. @@ -225,13 +241,14 @@
  68512. if (newsize > 4096)
  68513. newsize = 4096;
  68514. for (new2size = 128; new2size < newsize; new2size <<= 1);
  68515. - if (new2size - newsize > newsize - (new2size >> 1))
  68516. - new2size >>= 1;
  68517. + if (new2size - newsize > newsize - (new2size >> 1))
  68518. + new2size >>= 1;
  68519. if (new2size > 4096) {
  68520. printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
  68521. newsize, new2size);
  68522. new2size = 4096;
  68523. }
  68524. + /*printk("VIDC: dma size %d\n", new2size);*/
  68525. dma_bufsize = new2size;
  68526. vidc_audio_rate = rate;
  68527. }
  68528. diff -urN linux-2.4.26/drivers/sound/waveartist.c linux-2.4.26-vrs1/drivers/sound/waveartist.c
  68529. --- linux-2.4.26/drivers/sound/waveartist.c 2001-10-25 21:53:52.000000000 +0100
  68530. +++ linux-2.4.26-vrs1/drivers/sound/waveartist.c 2004-01-14 21:32:26.000000000 +0000
  68531. @@ -247,17 +247,15 @@
  68532. printk("\n");
  68533. }
  68534. - if (inb(io_base + STATR) & CMD_RF) {
  68535. - int old_data;
  68536. -
  68537. - /* flush the port
  68538. - */
  68539. + /*
  68540. + * flush any stale command data from the port.
  68541. + */
  68542. + while (inb(io_base + STATR) & CMD_RF) {
  68543. + unsigned int old_data;
  68544. old_data = inw(io_base + CMDR);
  68545. -
  68546. - if (debug_flg & DEBUG_CMD)
  68547. - printk("flushed %04X...", old_data);
  68548. -
  68549. + printk("waveartist: flushing stale command data: 0x%04x pc=%p\n",
  68550. + old_data, __builtin_return_address(0));
  68551. udelay(10);
  68552. }
  68553. @@ -287,16 +285,19 @@
  68554. resp[i] = inw(io_base + CMDR);
  68555. }
  68556. - if (debug_flg & DEBUG_CMD) {
  68557. - if (!timed_out) {
  68558. - printk("waveartist_cmd: resp=");
  68559. -
  68560. - for (i = 0; i < nr_resp; i++)
  68561. - printk("%04X ", resp[i]);
  68562. -
  68563. - printk("\n");
  68564. - } else
  68565. - printk("waveartist_cmd: timed out\n");
  68566. + if (debug_flg & DEBUG_CMD && !timed_out) {
  68567. + printk("waveartist_cmd: resp=");
  68568. +
  68569. + for (i = 0; i < nr_resp; i++)
  68570. + printk("%04X ", resp[i]);
  68571. + printk("\n");
  68572. + }
  68573. +
  68574. + if (timed_out) {
  68575. + printk(KERN_ERR "waveartist_cmd: command timed out:");
  68576. + for (i = 0; i < nr_cmd; i++)
  68577. + printk(" %04x", cmd[i]);
  68578. + printk("\n");
  68579. }
  68580. return timed_out ? 1 : 0;
  68581. @@ -495,7 +496,6 @@
  68582. audio_devs[dev]->flags & DMA_AUTOMODE &&
  68583. intrflag &&
  68584. count == devc->xfer_count) {
  68585. - devc->audio_mode |= PCM_ENABLE_INPUT;
  68586. return; /*
  68587. * Auto DMA mode on. No need to react
  68588. */
  68589. @@ -571,9 +571,6 @@
  68590. wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
  68591. unsigned int speed, bits;
  68592. - if (devc->audio_mode)
  68593. - return 0;
  68594. -
  68595. speed = waveartist_get_speed(portc);
  68596. bits = waveartist_get_bits(portc);
  68597. diff -urN linux-2.4.26/drivers/ssi/Config.in linux-2.4.26-vrs1/drivers/ssi/Config.in
  68598. --- linux-2.4.26/drivers/ssi/Config.in 1970-01-01 01:00:00.000000000 +0100
  68599. +++ linux-2.4.26-vrs1/drivers/ssi/Config.in 2004-01-14 21:32:26.000000000 +0000
  68600. @@ -0,0 +1,11 @@
  68601. +
  68602. +mainmenu_option next_comment
  68603. +comment 'Synchronous Serial Interface'
  68604. +tristate 'Synchronous Serial Interface Support' CONFIG_SSI
  68605. +
  68606. +comment 'SSI Bus Drivers'
  68607. +dep_tristate ' CLPS711X SSI support' CONFIG_SSI_CLPS711X $CONFIG_SSI $CONFIG_ARCH_CLPS711X
  68608. +
  68609. +comment 'SSI Device Drivers'
  68610. +dep_tristate ' JUNO keyboard support' CONFIG_SSI_JUNO $CONFIG_SSI
  68611. +endmenu
  68612. diff -urN linux-2.4.26/drivers/ssi/Makefile linux-2.4.26-vrs1/drivers/ssi/Makefile
  68613. --- linux-2.4.26/drivers/ssi/Makefile 1970-01-01 01:00:00.000000000 +0100
  68614. +++ linux-2.4.26-vrs1/drivers/ssi/Makefile 2004-01-14 21:32:26.000000000 +0000
  68615. @@ -0,0 +1,50 @@
  68616. +#
  68617. +# Makefile for the SSI drivers
  68618. +#
  68619. +# Note! Dependencies are done automagically by 'make dep', which also
  68620. +# removes any old dependencies. DON'T put your own dependencies here
  68621. +# unless it's something special (ie not a .c file).
  68622. +#
  68623. +# Note 2! The CFLAGS definition is now inherited from the
  68624. +# parent makefile.
  68625. +#
  68626. +
  68627. +O_TARGET := ssi.o
  68628. +
  68629. +obj-y :=
  68630. +obj-m :=
  68631. +obj-n :=
  68632. +obj- :=
  68633. +
  68634. +export-objs :=
  68635. +list-multi :=
  68636. +
  68637. +obj-$(CONFIG_SSI) += ssi_core.o
  68638. +obj-$(CONFIG_SSI_CLPS711X) += clps711x_ssi1.o
  68639. +obj-y += juno.o
  68640. +
  68641. +# Extract lists of the multi-part drivers.
  68642. +# The 'int-*' lists are intermediate files used to build the multi's.
  68643. +
  68644. +multi-y := $(filter $(list-multi), $(obj-y))
  68645. +multi-m := $(filter $(list-multi), $(obj-m))
  68646. +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
  68647. +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
  68648. +
  68649. +# Files that are both resident and modular; remove from modular.
  68650. +
  68651. +obj-m := $(filter-out $(obj-y), $(obj-m))
  68652. +int-m := $(filter-out $(int-y), $(int-m))
  68653. +
  68654. +# Take multi-part drivers out of obj-y and put components in.
  68655. +
  68656. +obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
  68657. +
  68658. +# Translate to Rules.make lists.
  68659. +
  68660. +O_OBJS := $(filter-out $(export-objs), $(obj-y))
  68661. +OX_OBJS := $(filter $(export-objs), $(obj-y))
  68662. +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
  68663. +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
  68664. +
  68665. +include $(TOPDIR)/Rules.make
  68666. diff -urN linux-2.4.26/drivers/ssi/README linux-2.4.26-vrs1/drivers/ssi/README
  68667. --- linux-2.4.26/drivers/ssi/README 1970-01-01 01:00:00.000000000 +0100
  68668. +++ linux-2.4.26-vrs1/drivers/ssi/README 2004-01-14 21:32:26.000000000 +0000
  68669. @@ -0,0 +1,86 @@
  68670. + Synchronous Serial Interface bus driver
  68671. + ---------------------------------------
  68672. +
  68673. + EEEEE X X PPPP EEEEE RRRR IIIII M M EEEEE N N TTTTT AAA L
  68674. + E X X P P E R R I MM MM E NN N T A A L
  68675. + EEEE X PPPP EEEE RRRR I M M M EEEE N N N T AAAAA L
  68676. + E X X P E R R I M M E N NN T A A L
  68677. + EEEEE X X P EEEEE R R IIIII M M EEEEE N N T A A LLLLL
  68678. +
  68679. +This directory holds the SSI bus drivers. Basically, a SSI bus consists
  68680. +of the following signals:
  68681. +
  68682. + stxd Transmit data
  68683. + srxd Receive data
  68684. + sclk Clock
  68685. + sfrm Frame
  68686. + Chip selects (1 - n)
  68687. +
  68688. +There may be more than one device on a SSI bus, and each device can
  68689. +have different timing requirements. There are several frame formats:
  68690. +
  68691. +1. Texas Instruments Synchronous Serial Frame format
  68692. +
  68693. + sclk ____~_~_~_~_~_~_~_~____
  68694. + sfrm ____~~_________________
  68695. + stxd ------bn..........b0---
  68696. + srxd ------bn..........b0---
  68697. +
  68698. + - data latched in on the falling edge of the clock
  68699. + - data shifted out on the rising edge of the clock
  68700. +
  68701. +2. Motorola SPI frame format
  68702. +
  68703. + sclk ______~_~_~_~_~_~_~____
  68704. + sfrm ~~~~________________~~~
  68705. + stxd -----bn..........b0----
  68706. + srxd ----.bn..........b0----
  68707. +
  68708. + - data latched in on the rising edge of the clock
  68709. + - data shifted out on the falling edge of the clock, or falling edge
  68710. + of sfrm
  68711. +
  68712. +3. National Microwire format
  68713. +
  68714. + sclk ______~_~_~_~_~_~_~_~_~_~_~_~_~_____
  68715. + sfrm ~~~~_____________________________~~~
  68716. + stxd -----bn......b0---------------------
  68717. + srxd -----------------bn..........b0.----
  68718. +
  68719. + - data latched in on the rising edge of the clock
  68720. + - data shifted out on the falling edge of the clock
  68721. + - half duplex, one clock between transmission and reception
  68722. +
  68723. +Types of devices
  68724. +----------------
  68725. +
  68726. +The following types of devices can be found on a SSP bus:
  68727. +
  68728. + Sound chips
  68729. + Keyboard devices
  68730. + Touch screen devices
  68731. +
  68732. +Keyboard
  68733. +--------
  68734. +
  68735. +TX:
  68736. +0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
  68737. +1. select device
  68738. +2. keyboard responds asserting key_atn
  68739. +3. wait 0.1ms to 5ms
  68740. +4. transmit data byte
  68741. +5. wait >= 150us
  68742. +6. repeat step 4 until all data sent
  68743. +7. deselect device
  68744. +8. keyboard responds de-asserting key_atn
  68745. +9. wait >= 120us
  68746. +
  68747. +RX:
  68748. +0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
  68749. +1. keyboard asserts key_atn
  68750. +2. select device after 0.1ms < 5ms
  68751. +3. read data byte
  68752. +4. wait 150us
  68753. +5. if key_atn still asserted, goto 3
  68754. +6. deselect device
  68755. +7. wait >= 120us
  68756. diff -urN linux-2.4.26/drivers/ssi/clps711x_ssi1.c linux-2.4.26-vrs1/drivers/ssi/clps711x_ssi1.c
  68757. --- linux-2.4.26/drivers/ssi/clps711x_ssi1.c 1970-01-01 01:00:00.000000000 +0100
  68758. +++ linux-2.4.26-vrs1/drivers/ssi/clps711x_ssi1.c 2004-01-14 21:32:26.000000000 +0000
  68759. @@ -0,0 +1,237 @@
  68760. +/*
  68761. + * linux/drivers/ssi/clps711x_ssi1.c
  68762. + *
  68763. + * SSI bus driver for the CLPS711x SSI1 bus. We support EP7212
  68764. + * extensions as well.
  68765. + *
  68766. + * Frame sizes can be between 4 and 24 bits.
  68767. + * Config sizes can be between 4 and 16 bits.
  68768. + */
  68769. +#include <linux/init.h>
  68770. +#include <linux/sched.h>
  68771. +#include <linux/delay.h>
  68772. +
  68773. +#include <asm/mach-types.h>
  68774. +#include <asm/io.h>
  68775. +#include <asm/irq.h>
  68776. +
  68777. +#include <asm/hardware/ep7212.h>
  68778. +
  68779. +#include "ssi_bus.h"
  68780. +#include "ssi_dev.h"
  68781. +
  68782. +#define EP7212
  68783. +
  68784. +/*
  68785. + * Port E on the P720T is used for the SPI bus chip selects
  68786. + * 0 - Keyboard
  68787. + * 1 - Touch screen
  68788. + * 2 - CS4224 ADC/DAC
  68789. + * 7 - idle
  68790. + */
  68791. +
  68792. +#if 0
  68793. +/*
  68794. + * we place in the transmit buffer:
  68795. + * <control>
  68796. + * received data (binary):
  68797. + * 0xxxxxxxxxxxx000
  68798. + * where 'x' is the value
  68799. + */
  68800. +struct ssi_dev ads7846_dev = {
  68801. + name: "ADS7846",
  68802. + id: 1,
  68803. + proto: SSI_SPI,
  68804. + cfglen: 8,
  68805. + framelen: 24,
  68806. + clkpol: 0,
  68807. + clkfreq: 2500000,
  68808. +};
  68809. +
  68810. +/*
  68811. + * we place in the transmit buffer:
  68812. + * write: <20> <map> <data>...
  68813. + * received data discarded
  68814. + */
  68815. +struct ssi_dev cs4224_dev = {
  68816. + name: "CS4224",
  68817. + id: 2,
  68818. + proto: SSI_SPI,
  68819. + cfglen: 8,
  68820. + framelen: 8,
  68821. + clkpol: 0,
  68822. + clkfreq: 6000000,
  68823. +};
  68824. +#endif
  68825. +
  68826. +/*
  68827. + * Supplement with whatever method your board requires
  68828. + */
  68829. +static void ssi1_select_id(int id)
  68830. +{
  68831. + if (machine_is_p720t()) {
  68832. + clps_writel(7, PEDDR);
  68833. + clps_writel(id, PEDR);
  68834. + }
  68835. +}
  68836. +
  68837. +/*
  68838. + * Select the specified device. The upper layers will have already
  68839. + * checked that the bus transmit queue is idle. We need to make sure
  68840. + * that the interface itself is idle.
  68841. + */
  68842. +static int ssi1_select(struct ssi_bus *bus, struct ssi_dev *dev)
  68843. +{
  68844. + u_int id = dev ? dev->id : 7;
  68845. + u_int val;
  68846. +
  68847. + /*
  68848. + * Make sure that the interface is idle
  68849. + */
  68850. + do {
  68851. + val = clps_readl(SYSFLG1);
  68852. + } while (val & SYSFLG1_SSIBUSY);
  68853. +
  68854. + ssi1_select_id(7);
  68855. +
  68856. + if (dev) {
  68857. + /*
  68858. + * Select clock frequency. This is very rough,
  68859. + * and assumes that we're operating in PLL mode.
  68860. + */
  68861. + val = clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK;
  68862. +// if (dev->clkfreq <= 16000) /* <16kHz */
  68863. +// val |= SYSCON1_ADCKSEL(0);
  68864. +// else if (dev->clkfreq < 64000) /* <64kHz */
  68865. +// val |= SYSCON1_ADCKSEL(1);
  68866. +// else if (dev->clkfreq < 128000) /* <128kHz */
  68867. + val |= SYSCON1_ADCKSEL(2);
  68868. +// else /* >= 128kHz */
  68869. +// val |= SYSCON1_ADCKSEL(3);
  68870. + clps_writel(val, SYSCON1);
  68871. +
  68872. + bus->cfglen = dev->cfglen;
  68873. + bus->framelen = dev->framelen;
  68874. + bus->clkpol = dev->clkpol;
  68875. + bus->proto = dev->proto;
  68876. +
  68877. +#ifdef EP7212
  68878. + /*
  68879. + * Set the clock edge according to the device.
  68880. + * (set clkpol if the device reads data on the
  68881. + * falling edge of the clock signal).
  68882. + */
  68883. + val = ep_readl(SYSCON3) & ~SYSCON3_ADCCKNSEN;
  68884. + if (bus->clkpol && dev->proto != SSI_USAR)
  68885. + val |= SYSCON3_ADCCKNSEN;
  68886. + ep_writel(val, SYSCON3);
  68887. +#endif
  68888. +
  68889. + /*
  68890. + * Select the device
  68891. + */
  68892. + ssi1_select_id(id);
  68893. +
  68894. +#ifdef EP7212
  68895. + /*
  68896. + * If we are doing USAR, wait 30us, then set
  68897. + * the clock line low.
  68898. + */
  68899. + if (dev->proto == SSI_USAR) {
  68900. + udelay(150);
  68901. +
  68902. + val |= SYSCON3_ADCCKNSEN;
  68903. + ep_writel(val, SYSCON3);
  68904. + }
  68905. +#endif
  68906. + }
  68907. +
  68908. + return 0;
  68909. +}
  68910. +
  68911. +static void ssi1_int(int irq, void *dev_id, struct pt_regs *regs)
  68912. +{
  68913. + struct ssi_bus *bus = (struct ssi_bus *)dev_id;
  68914. +
  68915. + /*
  68916. + * Read the data word and queue it.
  68917. + */
  68918. + ssi_core_rcv(bus, clps_readl(SYNCIO));
  68919. +}
  68920. +
  68921. +/*
  68922. + * Enable transmission and/or of some bytes
  68923. + */
  68924. +static int ssi1_trans(struct ssi_bus *bus, u_int data)
  68925. +{
  68926. + u_int syncio;
  68927. +
  68928. +#ifdef EP7212
  68929. + data <<= 32 - bus->cfglen;
  68930. + syncio = bus->cfglen | bus->framelen << 7 | data;
  68931. +#else
  68932. + syncio = data | bus->framelen << 8;
  68933. +#endif
  68934. +
  68935. + clps_writel(syncio, SYNCIO);
  68936. + clps_writel(syncio | SYNCIO_TXFRMEN, SYNCIO);
  68937. + return 0;
  68938. +}
  68939. +
  68940. +/*
  68941. + * Initialise the SSI bus.
  68942. + */
  68943. +static int ssi1_bus_init(struct ssi_bus *bus)
  68944. +{
  68945. + int retval, val;
  68946. +
  68947. + retval = request_irq(IRQ_SSEOTI, ssi1_int, 0, "ssi1", bus);
  68948. + if (retval)
  68949. + return retval;
  68950. +
  68951. +#ifdef EP7212
  68952. + /*
  68953. + * EP7212 only! Set the configuration command length.
  68954. + * On the CLPS711x chips, it is fixed at 8 bits.
  68955. + */
  68956. + val = ep_readl(SYSCON3);
  68957. + val |= SYSCON3_ADCCON;
  68958. + ep_writel(val, SYSCON3);
  68959. +#endif
  68960. +
  68961. + ssi1_select(bus, NULL);
  68962. +
  68963. + PLD_SPI |= PLD_SPI_EN;
  68964. +
  68965. + return 0;
  68966. +}
  68967. +
  68968. +static void ssi1_bus_exit(struct ssi_bus *bus)
  68969. +{
  68970. + ssi1_select(bus, NULL);
  68971. +
  68972. + PLD_SPI &= ~PLD_SPI_EN;
  68973. +
  68974. + free_irq(IRQ_SSEOTI, bus);
  68975. +}
  68976. +
  68977. +struct ssi_bus clps711x_ssi1_bus = {
  68978. + name: "clps711x_ssi1",
  68979. + init: ssi1_bus_init,
  68980. + exit: ssi1_bus_exit,
  68981. + select: ssi1_select,
  68982. + trans: ssi1_trans,
  68983. +};
  68984. +
  68985. +static int __init clps711x_ssi1_init(void)
  68986. +{
  68987. + return ssi_register_bus(&clps711x_ssi1_bus);
  68988. +}
  68989. +
  68990. +static void __exit clps711x_ssi1_exit(void)
  68991. +{
  68992. + ssi_unregister_bus(&clps711x_ssi1_bus);
  68993. +}
  68994. +
  68995. +module_init(clps711x_ssi1_init);
  68996. +module_exit(clps711x_ssi1_exit);
  68997. diff -urN linux-2.4.26/drivers/ssi/juno.c linux-2.4.26-vrs1/drivers/ssi/juno.c
  68998. --- linux-2.4.26/drivers/ssi/juno.c 1970-01-01 01:00:00.000000000 +0100
  68999. +++ linux-2.4.26-vrs1/drivers/ssi/juno.c 2004-01-14 21:32:26.000000000 +0000
  69000. @@ -0,0 +1,131 @@
  69001. +#include <linux/module.h>
  69002. +#include <linux/types.h>
  69003. +#include <linux/init.h>
  69004. +#include <linux/sched.h>
  69005. +#include <linux/delay.h>
  69006. +
  69007. +#include <asm/io.h>
  69008. +#include <asm/irq.h>
  69009. +
  69010. +#include <asm/arch/syspld.h>
  69011. +
  69012. +#include "ssi_bus.h"
  69013. +#include "ssi_dev.h"
  69014. +
  69015. +extern struct ssi_bus clps711x_ssi1_bus;
  69016. +
  69017. +static u_int recvbuf[16];
  69018. +static volatile u_int ptr, rxed;
  69019. +
  69020. +static inline void juno_enable_irq(void)
  69021. +{
  69022. + enable_irq(IRQ_EINT1);
  69023. +}
  69024. +
  69025. +static inline void juno_disable_irq(void)
  69026. +{
  69027. + disable_irq(IRQ_EINT1);
  69028. +}
  69029. +
  69030. +static void juno_rcv(struct ssi_dev *dev, u_int data)
  69031. +{
  69032. + if (ptr < 16) {
  69033. + recvbuf[ptr] = data;
  69034. + ptr++;
  69035. + } else
  69036. + printk("juno_rcv: %04x\n", data);
  69037. + rxed = 1;
  69038. +}
  69039. +
  69040. +static void juno_irq(int irq, void *dev_id, struct pt_regs *regs)
  69041. +{
  69042. + struct ssi_dev *dev = dev_id;
  69043. +
  69044. + printk("juno_irq\n");
  69045. +
  69046. + ssi_select_device(dev->bus, dev);
  69047. +
  69048. + ptr = 0;
  69049. + do {
  69050. + rxed = 0;
  69051. + ssi_transmit_data(dev, 0xff);
  69052. + while (rxed == 0);
  69053. + udelay(150);
  69054. + } while (PLD_INT & PLD_INT_KBD_ATN);
  69055. +
  69056. + ssi_select_device(dev->bus, NULL);
  69057. +
  69058. + { int i;
  69059. + printk("juno_rcv: ");
  69060. + for (i = 0; i < ptr; i++)
  69061. + printk("%04x ", recvbuf[i]);
  69062. + printk("\n");
  69063. + }
  69064. +}
  69065. +
  69066. +static void juno_command(struct ssi_dev *dev, int cmd, int data)
  69067. +{
  69068. + ssi_transmit_data(dev, cmd);
  69069. + mdelay(1);
  69070. + ssi_transmit_data(dev, data);
  69071. + mdelay(1);
  69072. + ssi_transmit_data(dev, 0xa0 ^ 0xc0);
  69073. + mdelay(1);
  69074. +}
  69075. +
  69076. +static int juno_dev_init(struct ssi_dev *dev)
  69077. +{
  69078. + int retval;
  69079. +
  69080. + PLD_KBD |= PLD_KBD_EN;
  69081. + ptr = 16;
  69082. +
  69083. + mdelay(20);
  69084. +
  69085. + retval = request_irq(IRQ_EINT1, juno_irq, 0, dev->name, dev);
  69086. + if (retval)
  69087. + return retval;
  69088. +
  69089. + juno_disable_irq();
  69090. +
  69091. + if (ssi_select_device(dev->bus, dev) != 0) {
  69092. + printk("juno: ssi_select_dev failed\n");
  69093. + return -EBUSY;
  69094. + }
  69095. +
  69096. + mdelay(1);
  69097. +
  69098. + juno_command(dev, 0x80, 0x20);
  69099. +
  69100. + ssi_select_device(dev->bus, NULL);
  69101. +
  69102. + juno_enable_irq();
  69103. +
  69104. + return 0;
  69105. +}
  69106. +
  69107. +static struct ssi_dev juno_dev = {
  69108. + name: "Juno",
  69109. + id: 0,
  69110. + proto: SSI_USAR,
  69111. + cfglen: 8,
  69112. + framelen: 8,
  69113. + clkpol: 1,
  69114. + clkfreq: 250000,
  69115. + rcv: juno_rcv,
  69116. + init: juno_dev_init,
  69117. +};
  69118. +
  69119. +static int __init juno_init(void)
  69120. +{
  69121. + return ssi_register_device(&clps711x_ssi1_bus, &juno_dev);
  69122. +}
  69123. +
  69124. +static void __exit juno_exit(void)
  69125. +{
  69126. + ssi_unregister_device(&juno_dev);
  69127. +}
  69128. +
  69129. +module_init(juno_init);
  69130. +module_exit(juno_exit);
  69131. +
  69132. diff -urN linux-2.4.26/drivers/ssi/ssi_bus.h linux-2.4.26-vrs1/drivers/ssi/ssi_bus.h
  69133. --- linux-2.4.26/drivers/ssi/ssi_bus.h 1970-01-01 01:00:00.000000000 +0100
  69134. +++ linux-2.4.26-vrs1/drivers/ssi/ssi_bus.h 2004-01-14 21:32:26.000000000 +0000
  69135. @@ -0,0 +1,21 @@
  69136. +#include <linux/circ_buf.h>
  69137. +
  69138. +struct ssi_dev;
  69139. +
  69140. +struct ssi_bus {
  69141. + u_char cfglen;
  69142. + u_char framelen;
  69143. + u_char clkpol;
  69144. + u_char proto;
  69145. + struct ssi_dev *dev; /* current device */
  69146. + int (*select)(struct ssi_bus *, struct ssi_dev *);
  69147. + int (*trans)(struct ssi_bus *, u_int data);
  69148. + int (*init)(struct ssi_bus *);
  69149. + void (*exit)(struct ssi_bus *);
  69150. + char *name;
  69151. + u_int devices;
  69152. +};
  69153. +
  69154. +extern int ssi_core_rcv(struct ssi_bus *bus, u_int data);
  69155. +extern int ssi_register_bus(struct ssi_bus *bus);
  69156. +extern int ssi_unregister_bus(struct ssi_bus *bus);
  69157. diff -urN linux-2.4.26/drivers/ssi/ssi_core.c linux-2.4.26-vrs1/drivers/ssi/ssi_core.c
  69158. --- linux-2.4.26/drivers/ssi/ssi_core.c 1970-01-01 01:00:00.000000000 +0100
  69159. +++ linux-2.4.26-vrs1/drivers/ssi/ssi_core.c 2004-01-14 21:32:26.000000000 +0000
  69160. @@ -0,0 +1,175 @@
  69161. +/*
  69162. + * linux/drivers/ssi/ssi_core.c
  69163. + *
  69164. + * This file provides a common framework to allow multiple SSI devices
  69165. + * to work together on a single SSI bus.
  69166. + *
  69167. + * You can use this in two ways:
  69168. + * 1. select the device, queue up data, flush the data to the device,
  69169. + * (optionally) purge the received data, deselect the device.
  69170. + * 2. select the device, queue up one data word, flush to the device
  69171. + * read data word, queue up next data word, flush to the device...
  69172. + * deselect the device.
  69173. + */
  69174. +#include <linux/module.h>
  69175. +#include <linux/types.h>
  69176. +#include <linux/kernel.h>
  69177. +#include <linux/malloc.h>
  69178. +#include <linux/init.h>
  69179. +
  69180. +#include <asm/errno.h>
  69181. +
  69182. +#include "ssi_bus.h"
  69183. +#include "ssi_dev.h"
  69184. +
  69185. +#define DEBUG
  69186. +
  69187. +/**
  69188. + * ssi_core_rcv - pass received SSI data to the device
  69189. + * @bus: the bus that the data was received from
  69190. + * @data: the data word that was received
  69191. + *
  69192. + * This function is intended to be called by SSI bus device
  69193. + * drivers to pass received data to the device driver.
  69194. + */
  69195. +int ssi_core_rcv(struct ssi_bus *bus, u_int data)
  69196. +{
  69197. + struct ssi_dev *dev = bus->dev;
  69198. +
  69199. + if (dev && dev->rcv)
  69200. + dev->rcv(dev, data);
  69201. +
  69202. + return 0;
  69203. +}
  69204. +
  69205. +/**
  69206. + * ssi_transmit_data - queue SSI data for later transmission
  69207. + * @dev: device requesting data to be transmitted
  69208. + * @data: data word to be transmitted.
  69209. + *
  69210. + * Queue one data word of SSI data for later transmission.
  69211. + */
  69212. +int ssi_transmit_data(struct ssi_dev *dev, u_int data)
  69213. +{
  69214. + struct ssi_bus *bus = dev->bus;
  69215. +
  69216. + /*
  69217. + * Make sure that we currently own the bus
  69218. + */
  69219. + if (bus->dev != dev)
  69220. + BUG();
  69221. +
  69222. + bus->trans(bus, data);
  69223. + return 0;
  69224. +}
  69225. +
  69226. +/**
  69227. + * ssi_select_device - select a SSI device for later transactions
  69228. + * @dev: device to be selected
  69229. + */
  69230. +int ssi_select_device(struct ssi_bus *bus, struct ssi_dev *dev)
  69231. +{
  69232. + int retval;
  69233. +
  69234. +#ifdef DEBUG
  69235. + printk("SSI: selecting device %s on bus %s\n",
  69236. + dev ? dev->name : "<none>", bus->name);
  69237. +#endif
  69238. +
  69239. + /*
  69240. + * Select the device if it wasn't already selected.
  69241. + */
  69242. + retval = 0;
  69243. + if (bus->dev != dev) {
  69244. + retval = bus->select(bus, dev);
  69245. + bus->dev = dev;
  69246. + }
  69247. +
  69248. + return retval;
  69249. +}
  69250. +
  69251. +/**
  69252. + * ssi_register_device - register a SSI device with a SSI bus
  69253. + * @bus: bus
  69254. + * @dev: SSI device
  69255. + */
  69256. +int ssi_register_device(struct ssi_bus *bus, struct ssi_dev *dev)
  69257. +{
  69258. + int retval;
  69259. +
  69260. + dev->bus = bus;
  69261. + bus->devices++;
  69262. + retval = dev->init(dev);
  69263. + if (retval != 0) {
  69264. + dev->bus = NULL;
  69265. + bus->devices--;
  69266. + } else {
  69267. +#ifdef DEBUG
  69268. + printk("SSI: registered new device %s on bus %s\n", dev->name, bus->name);
  69269. +#endif
  69270. + }
  69271. + return retval;
  69272. +}
  69273. +
  69274. +/**
  69275. + * ssi_unregister_device - unregister a SSI device from a SSI bus
  69276. + * @dev: SSI device
  69277. + */
  69278. +int ssi_unregister_device(struct ssi_dev *dev)
  69279. +{
  69280. + struct ssi_bus *bus = dev->bus;
  69281. +
  69282. + if (bus->dev == dev)
  69283. + bus->dev = NULL;
  69284. +
  69285. + dev->bus = NULL;
  69286. + bus->devices--;
  69287. +#ifdef DEBUG
  69288. + printk("SSI: unregistered device %s on bus %s\n", dev->name, bus->name);
  69289. +#endif
  69290. + return 0;
  69291. +}
  69292. +
  69293. +/**
  69294. + * ssi_register_bus - register a SSI bus driver
  69295. + * @bus: bus
  69296. + */
  69297. +int ssi_register_bus(struct ssi_bus *bus)
  69298. +{
  69299. + int retval;
  69300. +
  69301. + retval = bus->init(bus);
  69302. + if (retval == 0) {
  69303. + bus->devices = 0;
  69304. +#ifdef DEBUG
  69305. + printk("SSI: registered new bus %s\n", bus->name);
  69306. +#endif
  69307. + }
  69308. +
  69309. + return retval;
  69310. +}
  69311. +
  69312. +/**
  69313. + * ssi_unregister_bus - unregister a SSI bus driver
  69314. + * @bus: bus
  69315. + */
  69316. +int ssi_unregister_bus(struct ssi_bus *bus)
  69317. +{
  69318. + int retval = -EBUSY;
  69319. + if (bus->devices == 0) {
  69320. + retval = 0;
  69321. + }
  69322. + return retval;
  69323. +}
  69324. +
  69325. +static int __init ssi_init(void)
  69326. +{
  69327. + return 0;
  69328. +}
  69329. +
  69330. +static void __exit ssi_exit(void)
  69331. +{
  69332. +}
  69333. +
  69334. +module_init(ssi_init);
  69335. +module_exit(ssi_exit);
  69336. diff -urN linux-2.4.26/drivers/ssi/ssi_dev.h linux-2.4.26-vrs1/drivers/ssi/ssi_dev.h
  69337. --- linux-2.4.26/drivers/ssi/ssi_dev.h 1970-01-01 01:00:00.000000000 +0100
  69338. +++ linux-2.4.26-vrs1/drivers/ssi/ssi_dev.h 2004-01-14 21:32:26.000000000 +0000
  69339. @@ -0,0 +1,21 @@
  69340. +struct ssi_bus;
  69341. +
  69342. +#define SSI_SPI 1
  69343. +#define SSI_MICROWIRE 2
  69344. +#define SSI_TISSF 3
  69345. +#define SSI_USAR 4
  69346. +
  69347. +struct ssi_dev {
  69348. + char *name;
  69349. + u_int id;
  69350. + u_int clkfreq;
  69351. + u_char cfglen;
  69352. + u_char framelen;
  69353. + u_char clkpol;
  69354. + u_char proto;
  69355. + void (*rcv)(struct ssi_dev *, u_int);
  69356. + int (*init)(struct ssi_dev *);
  69357. + struct ssi_bus *bus;
  69358. +};
  69359. +
  69360. +
  69361. diff -urN linux-2.4.26/drivers/usb/Config.in linux-2.4.26-vrs1/drivers/usb/Config.in
  69362. --- linux-2.4.26/drivers/usb/Config.in 2004-02-27 20:03:27.000000000 +0000
  69363. +++ linux-2.4.26-vrs1/drivers/usb/Config.in 2004-02-23 13:36:33.000000000 +0000
  69364. @@ -4,7 +4,13 @@
  69365. mainmenu_option next_comment
  69366. comment 'USB support'
  69367. -dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
  69368. +# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
  69369. +if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  69370. + tristate 'Support for USB' CONFIG_USB
  69371. +else
  69372. + define_bool CONFIG_USB n
  69373. +fi
  69374. +
  69375. if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
  69376. bool ' USB verbose debug messages' CONFIG_USB_DEBUG
  69377. diff -urN linux-2.4.26/drivers/usb/Makefile linux-2.4.26-vrs1/drivers/usb/Makefile
  69378. --- linux-2.4.26/drivers/usb/Makefile 2004-02-27 20:03:27.000000000 +0000
  69379. +++ linux-2.4.26-vrs1/drivers/usb/Makefile 2004-02-23 13:36:33.000000000 +0000
  69380. @@ -74,6 +74,14 @@
  69381. subdir-$(CONFIG_USB_OHCI) += host
  69382. ifeq ($(CONFIG_USB_OHCI),y)
  69383. + obj-y += host/usb-ohci.o host/usb-ohci-pci.o
  69384. +endif
  69385. +subdir-$(CONFIG_USB_OHCI_SA1111)+= host
  69386. +ifeq ($(CONFIG_USB_OHCI),y)
  69387. + obj-y += host/usb-ohci.o host/usb-ohci-sa1111.o
  69388. +endif
  69389. +subdir-$(CONFIG_USB_OHCI_AT91) += host
  69390. +ifeq ($(CONFIG_USB_OHCI_AT91),y)
  69391. obj-y += host/usb-ohci.o
  69392. endif
  69393. @@ -85,8 +93,6 @@
  69394. obj-$(CONFIG_USB_KBD) += usbkbd.o
  69395. obj-$(CONFIG_USB_AIPTEK) += aiptek.o
  69396. obj-$(CONFIG_USB_WACOM) += wacom.o
  69397. -obj-$(CONFIG_USB_KBTAB) += kbtab.o
  69398. -obj-$(CONFIG_USB_POWERMATE) += powermate.o
  69399. obj-$(CONFIG_USB_SCANNER) += scanner.o
  69400. obj-$(CONFIG_USB_ACM) += acm.o
  69401. diff -urN linux-2.4.26/drivers/usb/hcd.c linux-2.4.26-vrs1/drivers/usb/hcd.c
  69402. --- linux-2.4.26/drivers/usb/hcd.c 2004-04-19 11:44:27.000000000 +0100
  69403. +++ linux-2.4.26-vrs1/drivers/usb/hcd.c 2004-04-19 10:22:01.000000000 +0100
  69404. @@ -96,7 +96,7 @@
  69405. /* used when updating hcd data */
  69406. static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
  69407. -static struct usb_operations hcd_operations;
  69408. +/*static*/ struct usb_operations hcd_operations;
  69409. /*-------------------------------------------------------------------------*/
  69410. @@ -1208,13 +1208,21 @@
  69411. } else {
  69412. if (usb_pipecontrol (urb->pipe))
  69413. urb->setup_dma = pci_map_single (
  69414. +#ifdef CONFIG_PCI
  69415. hcd->pdev,
  69416. +#else
  69417. + NULL,
  69418. +#endif
  69419. urb->setup_packet,
  69420. sizeof (struct usb_ctrlrequest),
  69421. PCI_DMA_TODEVICE);
  69422. if (urb->transfer_buffer_length != 0)
  69423. urb->transfer_dma = pci_map_single (
  69424. +#ifdef CONFIG_PCI
  69425. hcd->pdev,
  69426. +#else
  69427. + NULL,
  69428. +#endif
  69429. urb->transfer_buffer,
  69430. urb->transfer_buffer_length,
  69431. usb_pipein (urb->pipe)
  69432. @@ -1424,7 +1432,7 @@
  69433. return 0;
  69434. }
  69435. -static struct usb_operations hcd_operations = {
  69436. +/*static*/ struct usb_operations hcd_operations = {
  69437. allocate: hcd_alloc_dev,
  69438. get_frame_number: hcd_get_frame_number,
  69439. submit_urb: hcd_submit_urb,
  69440. @@ -1434,7 +1442,7 @@
  69441. /*-------------------------------------------------------------------------*/
  69442. -static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
  69443. +/*static*/ void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
  69444. {
  69445. struct usb_hcd *hcd = __hcd;
  69446. int start = hcd->state;
  69447. @@ -1490,12 +1498,24 @@
  69448. /* For 2.4, don't unmap bounce buffer if it's a root hub operation. */
  69449. if (usb_pipecontrol (urb->pipe) && !is_root_hub_operation)
  69450. - pci_unmap_single (hcd->pdev, urb->setup_dma,
  69451. + pci_unmap_single (
  69452. +#ifdef CONFIG_PCI
  69453. + hcd->pdev,
  69454. +#else
  69455. + NULL,
  69456. +#endif
  69457. + urb->setup_dma,
  69458. sizeof (struct usb_ctrlrequest),
  69459. PCI_DMA_TODEVICE);
  69460. if ((urb->transfer_buffer_length != 0) && !is_root_hub_operation)
  69461. - pci_unmap_single (hcd->pdev, urb->transfer_dma,
  69462. + pci_unmap_single (
  69463. +#ifdef CONFIG_PCI
  69464. + hcd->pdev,
  69465. +#else
  69466. + NULL,
  69467. +#endif
  69468. + urb->transfer_dma,
  69469. urb->transfer_buffer_length,
  69470. usb_pipein (urb->pipe)
  69471. ? PCI_DMA_FROMDEVICE
  69472. diff -urN linux-2.4.26/drivers/usb/host/Config.in linux-2.4.26-vrs1/drivers/usb/host/Config.in
  69473. --- linux-2.4.26/drivers/usb/host/Config.in 2003-11-28 18:26:20.000000000 +0000
  69474. +++ linux-2.4.26-vrs1/drivers/usb/host/Config.in 2004-02-11 01:35:27.000000000 +0000
  69475. @@ -12,8 +12,13 @@
  69476. define_bool CONFIG_USB_UHCI_ALT n
  69477. fi
  69478. dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
  69479. +dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
  69480. if [ "$CONFIG_ARM" = "y" -o "$CONFIG_X86" = "y" -a "$CONFIG_X86_64" != "y" ]; then
  69481. # Cypress embedded USB controller on StrongARM or on x86 in PC/104
  69482. dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
  69483. dep_tristate ' SL811HS (x86, StrongARM) support, old driver' CONFIG_USB_SL811HS $CONFIG_USB $CONFIG_EXPERIMENTAL
  69484. fi
  69485. +if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
  69486. + dep_tristate ' AT91RM9200 OHCI-compatible host interface support' CONFIG_USB_OHCI_AT91 $CONFIG_USB
  69487. +fi
  69488. +
  69489. diff -urN linux-2.4.26/drivers/usb/host/Makefile linux-2.4.26-vrs1/drivers/usb/host/Makefile
  69490. --- linux-2.4.26/drivers/usb/host/Makefile 2003-11-28 18:26:20.000000000 +0000
  69491. +++ linux-2.4.26-vrs1/drivers/usb/host/Makefile 2004-02-11 01:29:25.000000000 +0000
  69492. @@ -8,9 +8,11 @@
  69493. obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
  69494. obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
  69495. obj-$(CONFIG_USB_UHCI) += usb-uhci.o
  69496. -obj-$(CONFIG_USB_OHCI) += usb-ohci.o
  69497. +obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o
  69498. obj-$(CONFIG_USB_SL811HS_ALT) += sl811.o
  69499. obj-$(CONFIG_USB_SL811HS) += hc_sl811.o
  69500. +obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o
  69501. +obj-$(CONFIG_USB_OHCI_AT91) += usb-ohci.o
  69502. # Extract lists of the multi-part drivers.
  69503. # The 'int-*' lists are the intermediate files used to build the multi's.
  69504. diff -urN linux-2.4.26/drivers/usb/host/usb-ohci-pci.c linux-2.4.26-vrs1/drivers/usb/host/usb-ohci-pci.c
  69505. --- linux-2.4.26/drivers/usb/host/usb-ohci-pci.c 1970-01-01 01:00:00.000000000 +0100
  69506. +++ linux-2.4.26-vrs1/drivers/usb/host/usb-ohci-pci.c 2004-01-14 21:32:26.000000000 +0000
  69507. @@ -0,0 +1,436 @@
  69508. +#include <linux/module.h>
  69509. +#include <linux/init.h>
  69510. +#include <linux/pci.h>
  69511. +#include <linux/kernel.h>
  69512. +#include <linux/slab.h>
  69513. +#include <linux/delay.h>
  69514. +#include <linux/interrupt.h> /* for in_interrupt() */
  69515. +#undef DEBUG
  69516. +#include <linux/usb.h>
  69517. +
  69518. +#include "usb-ohci.h"
  69519. +
  69520. +#ifdef CONFIG_PMAC_PBOOK
  69521. +#include <asm/machdep.h>
  69522. +#include <asm/pmac_feature.h>
  69523. +#include <asm/pci-bridge.h>
  69524. +#ifndef CONFIG_PM
  69525. +#define CONFIG_PM
  69526. +#endif
  69527. +#endif
  69528. +
  69529. +
  69530. +/*-------------------------------------------------------------------------*/
  69531. +
  69532. +/* Increment the module usage count, start the control thread and
  69533. + * return success. */
  69534. +
  69535. +static struct pci_driver ohci_pci_driver;
  69536. +extern spinlock_t usb_ed_lock;
  69537. +int __devinit
  69538. +hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
  69539. + const char *name, const char *slot_name);
  69540. +extern void hc_remove_ohci(ohci_t *ohci);
  69541. +
  69542. +static int __devinit
  69543. +hc_found_ohci (struct pci_dev *dev, int irq,
  69544. + void *mem_base, const struct pci_device_id *id)
  69545. +{
  69546. + unsigned long flags = id->driver_data;
  69547. +
  69548. + printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
  69549. +
  69550. + /* Check for NSC87560. We have to look at the bridge (fn1) to identify
  69551. + the USB (fn2). This quirk might apply to more or even all NSC stuff
  69552. + I don't know.. */
  69553. +
  69554. + if(dev->vendor == PCI_VENDOR_ID_NS)
  69555. + {
  69556. + struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
  69557. + if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
  69558. + flags |= OHCI_QUIRK_SUCKYIO;
  69559. +
  69560. + }
  69561. +
  69562. + if (flags & OHCI_QUIRK_SUCKYIO)
  69563. + printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
  69564. + if (flags & OHCI_QUIRK_AMD756)
  69565. + printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
  69566. +
  69567. + return hc_add_ohci(dev, irq, mem_base, flags,
  69568. + ohci_pci_driver.name, dev->slot_name);
  69569. +}
  69570. +
  69571. +/*-------------------------------------------------------------------------*/
  69572. +
  69573. +#ifdef CONFIG_PM
  69574. +
  69575. +/* controller died; cleanup debris, then restart */
  69576. +/* must not be called from interrupt context */
  69577. +
  69578. +static void hc_restart (ohci_t *ohci)
  69579. +{
  69580. + int temp;
  69581. + int i;
  69582. +
  69583. + if (ohci->pci_latency)
  69584. + pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
  69585. +
  69586. + ohci->disabled = 1;
  69587. + ohci->sleeping = 0;
  69588. + if (ohci->bus->root_hub)
  69589. + usb_disconnect (&ohci->bus->root_hub);
  69590. +
  69591. + /* empty the interrupt branches */
  69592. + for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
  69593. + for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
  69594. +
  69595. + /* no EDs to remove */
  69596. + ohci->ed_rm_list [0] = NULL;
  69597. + ohci->ed_rm_list [1] = NULL;
  69598. +
  69599. + /* empty control and bulk lists */
  69600. + ohci->ed_isotail = NULL;
  69601. + ohci->ed_controltail = NULL;
  69602. + ohci->ed_bulktail = NULL;
  69603. +
  69604. + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
  69605. + err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
  69606. + } else
  69607. + dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
  69608. +}
  69609. +
  69610. +#endif /* CONFIG_PM */
  69611. +
  69612. +/*-------------------------------------------------------------------------*/
  69613. +
  69614. +/* configured so that an OHCI device is always provided */
  69615. +/* always called with process context; sleeping is OK */
  69616. +
  69617. +static int __devinit
  69618. +ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
  69619. +{
  69620. + unsigned long mem_resource, mem_len;
  69621. + void *mem_base;
  69622. + int status;
  69623. +
  69624. + if (pci_enable_device(dev) < 0)
  69625. + return -ENODEV;
  69626. +
  69627. + if (!dev->irq) {
  69628. + err("found OHCI device with no IRQ assigned. check BIOS settings!");
  69629. + pci_disable_device (dev);
  69630. + return -ENODEV;
  69631. + }
  69632. +
  69633. + /* we read its hardware registers as memory */
  69634. + mem_resource = pci_resource_start(dev, 0);
  69635. + mem_len = pci_resource_len(dev, 0);
  69636. + if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
  69637. + dbg ("controller already in use");
  69638. + pci_disable_device (dev);
  69639. + return -EBUSY;
  69640. + }
  69641. +
  69642. + mem_base = ioremap_nocache (mem_resource, mem_len);
  69643. + if (!mem_base) {
  69644. + err("Error mapping OHCI memory");
  69645. + release_mem_region (mem_resource, mem_len);
  69646. + pci_disable_device (dev);
  69647. + return -EFAULT;
  69648. + }
  69649. +
  69650. + /* controller writes into our memory */
  69651. + pci_set_master (dev);
  69652. +
  69653. + status = hc_found_ohci (dev, dev->irq, mem_base, id);
  69654. + if (status < 0) {
  69655. + iounmap (mem_base);
  69656. + release_mem_region (mem_resource, mem_len);
  69657. + pci_disable_device (dev);
  69658. + }
  69659. + return status;
  69660. +}
  69661. +
  69662. +/*-------------------------------------------------------------------------*/
  69663. +
  69664. +/* may be called from interrupt context [interface spec] */
  69665. +/* may be called without controller present */
  69666. +/* may be called with controller, bus, and devices active */
  69667. +
  69668. +static void __devexit
  69669. +ohci_pci_remove (struct pci_dev *dev)
  69670. +{
  69671. + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
  69672. +
  69673. + dbg ("remove %s controller usb-%s%s%s",
  69674. + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
  69675. + dev->slot_name,
  69676. + ohci->disabled ? " (disabled)" : "",
  69677. + in_interrupt () ? " in interrupt" : ""
  69678. + );
  69679. +
  69680. + hc_remove_ohci(ohci);
  69681. +
  69682. + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
  69683. + pci_disable_device (dev);
  69684. +}
  69685. +
  69686. +
  69687. +#ifdef CONFIG_PM
  69688. +
  69689. +/*-------------------------------------------------------------------------*/
  69690. +
  69691. +static int
  69692. +ohci_pci_suspend (struct pci_dev *dev, u32 state)
  69693. +{
  69694. + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
  69695. + unsigned long flags;
  69696. + u16 cmd;
  69697. +
  69698. + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
  69699. + dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
  69700. + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
  69701. + return -EIO;
  69702. + }
  69703. +
  69704. + /* act as if usb suspend can always be used */
  69705. + info ("USB suspend: usb-%s", dev->slot_name);
  69706. + ohci->sleeping = 1;
  69707. +
  69708. + /* First stop processing */
  69709. + spin_lock_irqsave (&usb_ed_lock, flags);
  69710. + ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
  69711. + writel (ohci->hc_control, &ohci->regs->control);
  69712. + writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
  69713. + (void) readl (&ohci->regs->intrstatus);
  69714. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  69715. +
  69716. + /* Wait a frame or two */
  69717. + mdelay(1);
  69718. + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
  69719. + mdelay (1);
  69720. +
  69721. +#ifdef CONFIG_PMAC_PBOOK
  69722. + if (_machine == _MACH_Pmac)
  69723. + disable_irq (ohci->irq);
  69724. + /* else, 2.4 assumes shared irqs -- don't disable */
  69725. +#endif
  69726. + /* Enable remote wakeup */
  69727. + writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
  69728. +
  69729. + /* Suspend chip and let things settle down a bit */
  69730. + ohci->hc_control = OHCI_USB_SUSPEND;
  69731. + writel (ohci->hc_control, &ohci->regs->control);
  69732. + (void) readl (&ohci->regs->control);
  69733. + mdelay (500); /* No schedule here ! */
  69734. + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
  69735. + case OHCI_USB_RESET:
  69736. + dbg("Bus in reset phase ???");
  69737. + break;
  69738. + case OHCI_USB_RESUME:
  69739. + dbg("Bus in resume phase ???");
  69740. + break;
  69741. + case OHCI_USB_OPER:
  69742. + dbg("Bus in operational phase ???");
  69743. + break;
  69744. + case OHCI_USB_SUSPEND:
  69745. + dbg("Bus suspended");
  69746. + break;
  69747. + }
  69748. + /* In some rare situations, Apple's OHCI have happily trashed
  69749. + * memory during sleep. We disable it's bus master bit during
  69750. + * suspend
  69751. + */
  69752. + pci_read_config_word (dev, PCI_COMMAND, &cmd);
  69753. + cmd &= ~PCI_COMMAND_MASTER;
  69754. + pci_write_config_word (dev, PCI_COMMAND, cmd);
  69755. +#ifdef CONFIG_PMAC_PBOOK
  69756. + {
  69757. + struct device_node *of_node;
  69758. +
  69759. + /* Disable USB PAD & cell clock */
  69760. + of_node = pci_device_to_OF_node (ohci->ohci_dev);
  69761. + if (of_node)
  69762. + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
  69763. + }
  69764. +#endif
  69765. + return 0;
  69766. +}
  69767. +
  69768. +/*-------------------------------------------------------------------------*/
  69769. +
  69770. +static int
  69771. +ohci_pci_resume (struct pci_dev *dev)
  69772. +{
  69773. + ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
  69774. + int temp;
  69775. + unsigned long flags;
  69776. +
  69777. + /* guard against multiple resumes */
  69778. + atomic_inc (&ohci->resume_count);
  69779. + if (atomic_read (&ohci->resume_count) != 1) {
  69780. + err ("concurrent PCI resumes for usb-%s", dev->slot_name);
  69781. + atomic_dec (&ohci->resume_count);
  69782. + return 0;
  69783. + }
  69784. +
  69785. +#ifdef CONFIG_PMAC_PBOOK
  69786. + {
  69787. + struct device_node *of_node;
  69788. +
  69789. + /* Re-enable USB PAD & cell clock */
  69790. + of_node = pci_device_to_OF_node (ohci->ohci_dev);
  69791. + if (of_node)
  69792. + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
  69793. + }
  69794. +#endif
  69795. +
  69796. + /* did we suspend, or were we powered off? */
  69797. + ohci->hc_control = readl (&ohci->regs->control);
  69798. + temp = ohci->hc_control & OHCI_CTRL_HCFS;
  69799. +
  69800. +#ifdef DEBUG
  69801. + /* the registers may look crazy here */
  69802. + ohci_dump_status (ohci);
  69803. +#endif
  69804. +
  69805. + /* Re-enable bus mastering */
  69806. + pci_set_master(ohci->ohci_dev);
  69807. +
  69808. + switch (temp) {
  69809. +
  69810. + case OHCI_USB_RESET: // lost power
  69811. + info ("USB restart: usb-%s", dev->slot_name);
  69812. + hc_restart (ohci);
  69813. + break;
  69814. +
  69815. + case OHCI_USB_SUSPEND: // host wakeup
  69816. + case OHCI_USB_RESUME: // remote wakeup
  69817. + info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
  69818. + (temp == OHCI_USB_SUSPEND)
  69819. + ? "host" : "remote");
  69820. + ohci->hc_control = OHCI_USB_RESUME;
  69821. + writel (ohci->hc_control, &ohci->regs->control);
  69822. + (void) readl (&ohci->regs->control);
  69823. + mdelay (20); /* no schedule here ! */
  69824. + /* Some controllers (lucent) need a longer delay here */
  69825. + mdelay (15);
  69826. + temp = readl (&ohci->regs->control);
  69827. + temp = ohci->hc_control & OHCI_CTRL_HCFS;
  69828. + if (temp != OHCI_USB_RESUME) {
  69829. + err ("controller usb-%s won't resume", dev->slot_name);
  69830. + ohci->disabled = 1;
  69831. + return -EIO;
  69832. + }
  69833. +
  69834. + /* Some chips likes being resumed first */
  69835. + writel (OHCI_USB_OPER, &ohci->regs->control);
  69836. + (void) readl (&ohci->regs->control);
  69837. + mdelay (3);
  69838. +
  69839. + /* Then re-enable operations */
  69840. + spin_lock_irqsave (&usb_ed_lock, flags);
  69841. + ohci->disabled = 0;
  69842. + ohci->sleeping = 0;
  69843. + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
  69844. + if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
  69845. + if (ohci->ed_controltail)
  69846. + ohci->hc_control |= OHCI_CTRL_CLE;
  69847. + if (ohci->ed_bulktail)
  69848. + ohci->hc_control |= OHCI_CTRL_BLE;
  69849. + }
  69850. + writel (ohci->hc_control, &ohci->regs->control);
  69851. + writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
  69852. + writel (OHCI_INTR_SF, &ohci->regs->intrenable);
  69853. + /* Check for a pending done list */
  69854. + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
  69855. + (void) readl (&ohci->regs->intrdisable);
  69856. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  69857. +#ifdef CONFIG_PMAC_PBOOK
  69858. + if (_machine == _MACH_Pmac)
  69859. + enable_irq (ohci->irq);
  69860. +#endif
  69861. + if (ohci->hcca->done_head)
  69862. + dl_done_list (ohci, dl_reverse_done_list (ohci));
  69863. + writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
  69864. + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
  69865. + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
  69866. + break;
  69867. +
  69868. + default:
  69869. + warn ("odd PCI resume for usb-%s", dev->slot_name);
  69870. + }
  69871. +
  69872. + /* controller is operational, extra resumes are harmless */
  69873. + atomic_dec (&ohci->resume_count);
  69874. +
  69875. + return 0;
  69876. +}
  69877. +
  69878. +#endif /* CONFIG_PM */
  69879. +
  69880. +
  69881. +/*-------------------------------------------------------------------------*/
  69882. +
  69883. +static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
  69884. +
  69885. + /*
  69886. + * AMD-756 [Viper] USB has a serious erratum when used with
  69887. + * lowspeed devices like mice.
  69888. + */
  69889. + vendor: 0x1022,
  69890. + device: 0x740c,
  69891. + subvendor: PCI_ANY_ID,
  69892. + subdevice: PCI_ANY_ID,
  69893. +
  69894. + driver_data: OHCI_QUIRK_AMD756,
  69895. +
  69896. +} , {
  69897. +
  69898. + /* handle any USB OHCI controller */
  69899. + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
  69900. + class_mask: ~0,
  69901. +
  69902. + /* no matter who makes it */
  69903. + vendor: PCI_ANY_ID,
  69904. + device: PCI_ANY_ID,
  69905. + subvendor: PCI_ANY_ID,
  69906. + subdevice: PCI_ANY_ID,
  69907. +
  69908. + }, { /* end: all zeroes */ }
  69909. +};
  69910. +
  69911. +MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
  69912. +
  69913. +static struct pci_driver ohci_pci_driver = {
  69914. + name: "usb-ohci",
  69915. + id_table: &ohci_pci_ids [0],
  69916. +
  69917. + probe: ohci_pci_probe,
  69918. + remove: __devexit_p(ohci_pci_remove),
  69919. +
  69920. +#ifdef CONFIG_PM
  69921. + suspend: ohci_pci_suspend,
  69922. + resume: ohci_pci_resume,
  69923. +#endif /* PM */
  69924. +};
  69925. +
  69926. +
  69927. +/*-------------------------------------------------------------------------*/
  69928. +
  69929. +static int __init ohci_hcd_init (void)
  69930. +{
  69931. + return pci_module_init (&ohci_pci_driver);
  69932. +}
  69933. +
  69934. +/*-------------------------------------------------------------------------*/
  69935. +
  69936. +static void __exit ohci_hcd_cleanup (void)
  69937. +{
  69938. + pci_unregister_driver (&ohci_pci_driver);
  69939. +}
  69940. +
  69941. +module_init (ohci_hcd_init);
  69942. +module_exit (ohci_hcd_cleanup);
  69943. +
  69944. diff -urN linux-2.4.26/drivers/usb/host/usb-ohci-sa1111.c linux-2.4.26-vrs1/drivers/usb/host/usb-ohci-sa1111.c
  69945. --- linux-2.4.26/drivers/usb/host/usb-ohci-sa1111.c 1970-01-01 01:00:00.000000000 +0100
  69946. +++ linux-2.4.26-vrs1/drivers/usb/host/usb-ohci-sa1111.c 2004-01-14 21:32:26.000000000 +0000
  69947. @@ -0,0 +1,118 @@
  69948. +/*
  69949. + * linux/drivers/usb/usb-ohci-sa1111.c
  69950. + *
  69951. + * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
  69952. + * original OHCI driver modifications, and reworked into a cleaner form
  69953. + * by Russell King <rmk@arm.linux.org.uk>.
  69954. + */
  69955. +#include <linux/module.h>
  69956. +#include <linux/init.h>
  69957. +#include <linux/sched.h>
  69958. +#include <linux/ioport.h>
  69959. +#include <linux/interrupt.h>
  69960. +#include <linux/slab.h>
  69961. +#include <linux/usb.h>
  69962. +
  69963. +#include <asm/hardware.h>
  69964. +#include <asm/irq.h>
  69965. +#include <asm/io.h>
  69966. +#include <asm/pci.h>
  69967. +#include <asm/arch/assabet.h>
  69968. +#include <asm/arch/badge4.h>
  69969. +#include <asm/hardware/sa1111.h>
  69970. +
  69971. +#include "usb-ohci.h"
  69972. +
  69973. +int __devinit
  69974. +hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
  69975. + const char *name, const char *slot_name);
  69976. +extern void hc_remove_ohci(ohci_t *ohci);
  69977. +
  69978. +static ohci_t *sa1111_ohci;
  69979. +
  69980. +static void __init sa1111_ohci_configure(void)
  69981. +{
  69982. + unsigned int usb_rst = 0;
  69983. +
  69984. + if (machine_is_xp860() ||
  69985. + machine_has_neponset() ||
  69986. + machine_is_accelent_sa() ||
  69987. + machine_is_pfs168() ||
  69988. + machine_is_badge4())
  69989. + usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
  69990. +
  69991. + /*
  69992. + * Configure the power sense and control lines. Place the USB
  69993. + * host controller in reset.
  69994. + */
  69995. + USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
  69996. +
  69997. + /*
  69998. + * Now, carefully enable the USB clock, and take
  69999. + * the USB host controller out of reset.
  70000. + */
  70001. + SKPCR |= SKPCR_UCLKEN;
  70002. + udelay(11);
  70003. + USB_RESET = usb_rst;
  70004. +}
  70005. +
  70006. +static int __init sa1111_ohci_init(void)
  70007. +{
  70008. + int ret;
  70009. +
  70010. + /*
  70011. + * Request memory resources.
  70012. + */
  70013. +// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci"))
  70014. +// return -EBUSY;
  70015. +
  70016. + sa1111_ohci_configure();
  70017. +
  70018. + /*
  70019. + * Initialise the generic OHCI driver.
  70020. + */
  70021. + ret = hc_add_ohci(SA1111_FAKE_PCIDEV, NIRQHCIM,
  70022. + (void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci,
  70023. + "usb-ohci", "sa1111");
  70024. +
  70025. +// if (ret)
  70026. +// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
  70027. +
  70028. +#ifdef CONFIG_SA1100_BADGE4
  70029. + if (machine_is_badge4() && (!ret)) {
  70030. + /* found the controller, so now power the bus */
  70031. + badge4_set_5V(BADGE4_5V_USB, 1);
  70032. + }
  70033. +#endif
  70034. +
  70035. + return ret;
  70036. +}
  70037. +
  70038. +static void __exit sa1111_ohci_exit(void)
  70039. +{
  70040. + hc_remove_ohci(sa1111_ohci);
  70041. +
  70042. + /*
  70043. + * Put the USB host controller into reset.
  70044. + */
  70045. + USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
  70046. +
  70047. + /*
  70048. + * Stop the USB clock.
  70049. + */
  70050. + SKPCR &= ~SKPCR_UCLKEN;
  70051. +
  70052. + /*
  70053. + * Release memory resources.
  70054. + */
  70055. +// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
  70056. +
  70057. +#ifdef CONFIG_SA1100_BADGE4
  70058. + if (machine_is_badge4()) {
  70059. + badge4_set_5V(BADGE4_5V_USB, 0);
  70060. + }
  70061. +#endif
  70062. +}
  70063. +
  70064. +module_init(sa1111_ohci_init);
  70065. +module_exit(sa1111_ohci_exit);
  70066. diff -urN linux-2.4.26/drivers/usb/host/usb-ohci.c linux-2.4.26-vrs1/drivers/usb/host/usb-ohci.c
  70067. --- linux-2.4.26/drivers/usb/host/usb-ohci.c 2004-04-19 11:44:27.000000000 +0100
  70068. +++ linux-2.4.26-vrs1/drivers/usb/host/usb-ohci.c 2004-04-19 15:27:57.000000000 +0100
  70069. @@ -12,7 +12,6 @@
  70070. *
  70071. * History:
  70072. *
  70073. - * 2002/10/22 OHCI_USB_OPER for ALi lockup in IBM i1200 (ALEX <thchou@ali>)
  70074. * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on
  70075. * load failure (Matthew Frederickson)
  70076. * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and
  70077. @@ -81,16 +80,6 @@
  70078. #include "../hcd.h"
  70079. -#ifdef CONFIG_PMAC_PBOOK
  70080. -#include <asm/machdep.h>
  70081. -#include <asm/pmac_feature.h>
  70082. -#include <asm/pci-bridge.h>
  70083. -#ifndef CONFIG_PM
  70084. -#define CONFIG_PM
  70085. -#endif
  70086. -#endif
  70087. -
  70088. -
  70089. /*
  70090. * Version Information
  70091. */
  70092. @@ -98,12 +87,12 @@
  70093. #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
  70094. #define DRIVER_DESC "USB OHCI Host Controller Driver"
  70095. -/* For initializing controller (mask in an HCFS mode too) */
  70096. -#define OHCI_CONTROL_INIT \
  70097. - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
  70098. -
  70099. #define OHCI_UNLINK_TIMEOUT (HZ / 10)
  70100. +static LIST_HEAD (ohci_hcd_list);
  70101. +spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
  70102. +
  70103. +
  70104. /*-------------------------------------------------------------------------*/
  70105. /* AMD-756 (D2 rev) reports corrupt register contents in some cases.
  70106. @@ -130,57 +119,6 @@
  70107. /*-------------------------------------------------------------------------*
  70108. * URB support functions
  70109. *-------------------------------------------------------------------------*/
  70110. -
  70111. -static void ohci_complete_add(struct ohci *ohci, struct urb *urb)
  70112. -{
  70113. -
  70114. - if (urb->hcpriv != NULL) {
  70115. - printk("completing with non-null priv!\n");
  70116. - return;
  70117. - }
  70118. -
  70119. - if (ohci->complete_tail == NULL) {
  70120. - ohci->complete_head = urb;
  70121. - ohci->complete_tail = urb;
  70122. - } else {
  70123. - ohci->complete_head->hcpriv = urb;
  70124. - ohci->complete_tail = urb;
  70125. - }
  70126. -}
  70127. -
  70128. -static inline struct urb *ohci_complete_get(struct ohci *ohci)
  70129. -{
  70130. - struct urb *urb;
  70131. -
  70132. - if ((urb = ohci->complete_head) == NULL)
  70133. - return NULL;
  70134. - if (urb == ohci->complete_tail) {
  70135. - ohci->complete_tail = NULL;
  70136. - ohci->complete_head = NULL;
  70137. - } else {
  70138. - ohci->complete_head = urb->hcpriv;
  70139. - }
  70140. - urb->hcpriv = NULL;
  70141. - return urb;
  70142. -}
  70143. -
  70144. -static inline void ohci_complete(struct ohci *ohci)
  70145. -{
  70146. - struct urb *urb;
  70147. -
  70148. - spin_lock(&ohci->ohci_lock);
  70149. - while ((urb = ohci_complete_get(ohci)) != NULL) {
  70150. - spin_unlock(&ohci->ohci_lock);
  70151. - if (urb->dev) {
  70152. - usb_dec_dev_use (urb->dev);
  70153. - urb->dev = NULL;
  70154. - }
  70155. - if (urb->complete)
  70156. - (*urb->complete)(urb);
  70157. - spin_lock(&ohci->ohci_lock);
  70158. - }
  70159. - spin_unlock(&ohci->ohci_lock);
  70160. -}
  70161. /* free HCD-private data associated with this URB */
  70162. @@ -256,14 +194,20 @@
  70163. }
  70164. urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
  70165. - } else {
  70166. - if (urb->dev != NULL) {
  70167. - err ("Non-null dev at rm_priv time");
  70168. - // urb->dev = NULL;
  70169. - }
  70170. + usb_dec_dev_use (urb->dev);
  70171. + urb->dev = NULL;
  70172. }
  70173. }
  70174. +static void urb_rm_priv (struct urb * urb)
  70175. +{
  70176. + unsigned long flags;
  70177. +
  70178. + spin_lock_irqsave (&usb_ed_lock, flags);
  70179. + urb_rm_priv_locked (urb);
  70180. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70181. +}
  70182. +
  70183. /*-------------------------------------------------------------------------*/
  70184. #ifdef DEBUG
  70185. @@ -484,7 +428,7 @@
  70186. static void ohci_dump (ohci_t *controller, int verbose)
  70187. {
  70188. - dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
  70189. + dbg ("OHCI controller usb-%s state", controller->slot_name);
  70190. // dumps some of the state we know about
  70191. ohci_dump_status (controller);
  70192. @@ -507,6 +451,7 @@
  70193. {
  70194. urb_priv_t * urb_priv = urb->hcpriv;
  70195. struct urb * urbt;
  70196. + unsigned long flags;
  70197. int i;
  70198. if (!urb_priv)
  70199. @@ -514,8 +459,7 @@
  70200. /* just to be sure */
  70201. if (!urb->complete) {
  70202. - urb_rm_priv_locked (urb);
  70203. - ohci_complete_add(hc, urb); /* Just usb_dec_dev_use */
  70204. + urb_rm_priv (urb);
  70205. return -1;
  70206. }
  70207. @@ -531,18 +475,20 @@
  70208. usb_pipeout (urb->pipe)
  70209. ? PCI_DMA_TODEVICE
  70210. : PCI_DMA_FROMDEVICE);
  70211. +
  70212. if (urb->interval) {
  70213. urb->complete (urb);
  70214. -
  70215. +
  70216. /* implicitly requeued */
  70217. urb->actual_length = 0;
  70218. urb->status = -EINPROGRESS;
  70219. td_submit_urb (urb);
  70220. } else {
  70221. - urb_rm_priv_locked (urb);
  70222. - ohci_complete_add(hc, urb);
  70223. + urb_rm_priv(urb);
  70224. + urb->complete (urb);
  70225. }
  70226. - break;
  70227. + break;
  70228. +
  70229. case PIPE_ISOCHRONOUS:
  70230. for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
  70231. @@ -554,6 +500,7 @@
  70232. ? PCI_DMA_TODEVICE
  70233. : PCI_DMA_FROMDEVICE);
  70234. urb->complete (urb);
  70235. + spin_lock_irqsave (&usb_ed_lock, flags);
  70236. urb->actual_length = 0;
  70237. urb->status = USB_ST_URB_PENDING;
  70238. urb->start_frame = urb_priv->ed->last_iso + 1;
  70239. @@ -564,17 +511,18 @@
  70240. }
  70241. td_submit_urb (urb);
  70242. }
  70243. -
  70244. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70245. +
  70246. } else { /* unlink URB, call complete */
  70247. - urb_rm_priv_locked (urb);
  70248. - ohci_complete_add(hc, urb);
  70249. + urb_rm_priv (urb);
  70250. + urb->complete (urb);
  70251. }
  70252. break;
  70253. case PIPE_BULK:
  70254. case PIPE_CONTROL: /* unlink URB, call complete */
  70255. - urb_rm_priv_locked (urb);
  70256. - ohci_complete_add(hc, urb);
  70257. + urb_rm_priv (urb);
  70258. + urb->complete (urb);
  70259. break;
  70260. }
  70261. return 0;
  70262. @@ -594,7 +542,7 @@
  70263. int i, size = 0;
  70264. unsigned long flags;
  70265. int bustime = 0;
  70266. - int mem_flags = GFP_ATOMIC;
  70267. + int mem_flags = ALLOC_FLAGS;
  70268. if (!urb->dev || !urb->dev->bus)
  70269. return -ENODEV;
  70270. @@ -611,24 +559,20 @@
  70271. #ifdef DEBUG
  70272. urb_print (urb, "SUB", usb_pipein (pipe));
  70273. #endif
  70274. -
  70275. +
  70276. /* handle a request to the virtual root hub */
  70277. if (usb_pipedevice (pipe) == ohci->rh.devnum)
  70278. return rh_submit_urb (urb);
  70279. -
  70280. - spin_lock_irqsave(&ohci->ohci_lock, flags);
  70281. -
  70282. +
  70283. /* when controller's hung, permit only roothub cleanup attempts
  70284. * such as powering down ports */
  70285. if (ohci->disabled) {
  70286. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70287. usb_dec_dev_use (urb->dev);
  70288. return -ESHUTDOWN;
  70289. }
  70290. /* every endpoint has a ed, locate and fill it */
  70291. if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
  70292. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70293. usb_dec_dev_use (urb->dev);
  70294. return -ENOMEM;
  70295. }
  70296. @@ -650,7 +594,6 @@
  70297. case PIPE_ISOCHRONOUS: /* number of packets from URB */
  70298. size = urb->number_of_packets;
  70299. if (size <= 0) {
  70300. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70301. usb_dec_dev_use (urb->dev);
  70302. return -EINVAL;
  70303. }
  70304. @@ -670,9 +613,8 @@
  70305. /* allocate the private part of the URB */
  70306. urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *),
  70307. - GFP_ATOMIC);
  70308. + in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
  70309. if (!urb_priv) {
  70310. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70311. usb_dec_dev_use (urb->dev);
  70312. return -ENOMEM;
  70313. }
  70314. @@ -683,12 +625,13 @@
  70315. urb_priv->ed = ed;
  70316. /* allocate the TDs (updating hash chains) */
  70317. + spin_lock_irqsave (&usb_ed_lock, flags);
  70318. for (i = 0; i < size; i++) {
  70319. urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
  70320. if (!urb_priv->td[i]) {
  70321. urb_priv->length = i;
  70322. urb_free_priv (ohci, urb_priv);
  70323. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70324. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70325. usb_dec_dev_use (urb->dev);
  70326. return -ENOMEM;
  70327. }
  70328. @@ -696,7 +639,7 @@
  70329. if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
  70330. urb_free_priv (ohci, urb_priv);
  70331. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70332. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70333. usb_dec_dev_use (urb->dev);
  70334. return -EINVAL;
  70335. }
  70336. @@ -718,7 +661,7 @@
  70337. }
  70338. if (bustime < 0) {
  70339. urb_free_priv (ohci, urb_priv);
  70340. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70341. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70342. usb_dec_dev_use (urb->dev);
  70343. return bustime;
  70344. }
  70345. @@ -744,6 +687,9 @@
  70346. if (urb->timeout) {
  70347. struct list_head *entry;
  70348. + // FIXME: usb-uhci uses relative timeouts (like this),
  70349. + // while uhci uses absolute ones (probably better).
  70350. + // Pick one solution and change the affected drivers.
  70351. urb->timeout += jiffies;
  70352. list_for_each (entry, &ohci->timeout_list) {
  70353. @@ -757,11 +703,10 @@
  70354. /* drive timeouts by SF (messy, but works) */
  70355. writel (OHCI_INTR_SF, &ohci->regs->intrenable);
  70356. - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
  70357. }
  70358. #endif
  70359. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70360. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70361. return 0;
  70362. }
  70363. @@ -792,7 +737,6 @@
  70364. if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
  70365. return rh_unlink_urb (urb);
  70366. - spin_lock_irqsave(&ohci->ohci_lock, flags);
  70367. if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) {
  70368. if (!ohci->disabled) {
  70369. urb_priv_t * urb_priv;
  70370. @@ -802,7 +746,6 @@
  70371. */
  70372. if (!(urb->transfer_flags & USB_ASYNC_UNLINK)
  70373. && in_interrupt ()) {
  70374. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70375. err ("bug in call from %p; use async!",
  70376. __builtin_return_address(0));
  70377. return -EWOULDBLOCK;
  70378. @@ -811,10 +754,11 @@
  70379. /* flag the urb and its TDs for deletion in some
  70380. * upcoming SF interrupt delete list processing
  70381. */
  70382. + spin_lock_irqsave (&usb_ed_lock, flags);
  70383. urb_priv = urb->hcpriv;
  70384. if (!urb_priv || (urb_priv->state == URB_DEL)) {
  70385. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70386. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70387. return 0;
  70388. }
  70389. @@ -829,36 +773,26 @@
  70390. add_wait_queue (&unlink_wakeup, &wait);
  70391. urb_priv->wait = &unlink_wakeup;
  70392. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70393. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70394. /* wait until all TDs are deleted */
  70395. set_current_state(TASK_UNINTERRUPTIBLE);
  70396. - while (timeout && (urb->status == USB_ST_URB_PENDING)) {
  70397. + while (timeout && (urb->status == USB_ST_URB_PENDING))
  70398. timeout = schedule_timeout (timeout);
  70399. - set_current_state(TASK_UNINTERRUPTIBLE);
  70400. - }
  70401. set_current_state(TASK_RUNNING);
  70402. remove_wait_queue (&unlink_wakeup, &wait);
  70403. if (urb->status == USB_ST_URB_PENDING) {
  70404. err ("unlink URB timeout");
  70405. return -ETIMEDOUT;
  70406. }
  70407. -
  70408. - usb_dec_dev_use (urb->dev);
  70409. - urb->dev = NULL;
  70410. - if (urb->complete)
  70411. - urb->complete (urb);
  70412. } else {
  70413. /* usb_dec_dev_use done in dl_del_list() */
  70414. urb->status = -EINPROGRESS;
  70415. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70416. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70417. return -EINPROGRESS;
  70418. }
  70419. } else {
  70420. - urb_rm_priv_locked (urb);
  70421. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70422. - usb_dec_dev_use (urb->dev);
  70423. - urb->dev = NULL;
  70424. + urb_rm_priv (urb);
  70425. if (urb->transfer_flags & USB_ASYNC_UNLINK) {
  70426. urb->status = -ECONNRESET;
  70427. if (urb->complete)
  70428. @@ -866,8 +800,6 @@
  70429. } else
  70430. urb->status = -ENOENT;
  70431. }
  70432. - } else {
  70433. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70434. }
  70435. return 0;
  70436. }
  70437. @@ -910,14 +842,14 @@
  70438. * (freeing all the TDs, unlinking EDs) but we need
  70439. * to defend against bugs that prevent that.
  70440. */
  70441. - spin_lock_irqsave(&ohci->ohci_lock, flags);
  70442. + spin_lock_irqsave (&usb_ed_lock, flags);
  70443. for(i = 0; i < NUM_EDS; i++) {
  70444. ed = &(dev->ed[i]);
  70445. if (ed->state != ED_NEW) {
  70446. if (ed->state == ED_OPER) {
  70447. /* driver on that interface didn't unlink an urb */
  70448. dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
  70449. - ohci->ohci_dev->slot_name, usb_dev->devnum, i);
  70450. + ohci->slot_name, usb_dev->devnum, i);
  70451. ep_unlink (ohci, ed);
  70452. }
  70453. ep_rm_ed (usb_dev, ed);
  70454. @@ -925,7 +857,7 @@
  70455. cnt++;
  70456. }
  70457. }
  70458. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70459. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70460. /* if the controller is running, tds for those unlinked
  70461. * urbs get freed by dl_del_list at the next SF interrupt
  70462. @@ -962,7 +894,7 @@
  70463. } else {
  70464. /* likely some interface's driver has a refcount bug */
  70465. err ("bus %s devnum %d deletion in interrupt",
  70466. - ohci->ohci_dev->slot_name, usb_dev->devnum);
  70467. + ohci->slot_name, usb_dev->devnum);
  70468. BUG ();
  70469. }
  70470. }
  70471. @@ -1259,12 +1191,17 @@
  70472. td_t * td;
  70473. ed_t * ed_ret;
  70474. volatile ed_t * ed;
  70475. + unsigned long flags;
  70476. +
  70477. +
  70478. + spin_lock_irqsave (&usb_ed_lock, flags);
  70479. ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) |
  70480. (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]);
  70481. if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
  70482. /* pending delete request */
  70483. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70484. return NULL;
  70485. }
  70486. @@ -1277,6 +1214,7 @@
  70487. /* out of memory */
  70488. if (td)
  70489. td_free(ohci, td);
  70490. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70491. return NULL;
  70492. }
  70493. ed->hwTailP = cpu_to_le32 (td->td_dma);
  70494. @@ -1299,7 +1237,8 @@
  70495. ed->int_period = interval;
  70496. ed->int_load = load;
  70497. }
  70498. -
  70499. +
  70500. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70501. return ed_ret;
  70502. }
  70503. @@ -1340,7 +1279,6 @@
  70504. /* enable SOF interrupt */
  70505. writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
  70506. writel (OHCI_INTR_SF, &ohci->regs->intrenable);
  70507. - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
  70508. }
  70509. }
  70510. @@ -1362,7 +1300,11 @@
  70511. err("internal OHCI error: TD index > length");
  70512. return;
  70513. }
  70514. -
  70515. +#ifdef CONFIG_SA1111
  70516. + if (data & (1 << 20))
  70517. + panic("td_fill: A20 = 1: %08x\n", data);
  70518. +#endif
  70519. +
  70520. /* use this td as the next dummy */
  70521. td_pt = urb_priv->td [index];
  70522. td_pt->hwNextTD = 0;
  70523. @@ -1461,7 +1403,6 @@
  70524. if (!ohci->sleeping) {
  70525. wmb();
  70526. writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
  70527. - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
  70528. }
  70529. break;
  70530. @@ -1490,7 +1431,6 @@
  70531. if (!ohci->sleeping) {
  70532. wmb();
  70533. writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
  70534. - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
  70535. }
  70536. break;
  70537. @@ -1558,7 +1498,7 @@
  70538. /* handle an urb that is being unlinked */
  70539. -static void dl_del_urb (ohci_t *ohci, struct urb * urb)
  70540. +static void dl_del_urb (struct urb * urb)
  70541. {
  70542. wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
  70543. @@ -1566,9 +1506,12 @@
  70544. if (urb->transfer_flags & USB_ASYNC_UNLINK) {
  70545. urb->status = -ECONNRESET;
  70546. - ohci_complete_add(ohci, urb);
  70547. + if (urb->complete)
  70548. + urb->complete (urb);
  70549. } else {
  70550. urb->status = -ENOENT;
  70551. + if (urb->complete)
  70552. + urb->complete (urb);
  70553. /* unblock sohci_unlink_urb */
  70554. if (wait_head)
  70555. @@ -1587,7 +1530,10 @@
  70556. td_t * td_rev = NULL;
  70557. td_t * td_list = NULL;
  70558. urb_priv_t * urb_priv = NULL;
  70559. -
  70560. + unsigned long flags;
  70561. +
  70562. + spin_lock_irqsave (&usb_ed_lock, flags);
  70563. +
  70564. td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
  70565. ohci->hcca->done_head = 0;
  70566. @@ -1613,6 +1559,7 @@
  70567. td_rev = td_list;
  70568. td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;
  70569. }
  70570. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70571. return td_list;
  70572. }
  70573. @@ -1624,6 +1571,7 @@
  70574. static void dl_del_list (ohci_t * ohci, unsigned int frame)
  70575. {
  70576. + unsigned long flags;
  70577. ed_t * ed;
  70578. __u32 edINFO;
  70579. __u32 tdINFO;
  70580. @@ -1631,6 +1579,8 @@
  70581. __u32 * td_p;
  70582. int ctrl = 0, bulk = 0;
  70583. + spin_lock_irqsave (&usb_ed_lock, flags);
  70584. +
  70585. for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
  70586. tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
  70587. @@ -1651,7 +1601,7 @@
  70588. /* URB is done; clean up */
  70589. if (++(urb_priv->td_cnt) == urb_priv->length)
  70590. - dl_del_urb (ohci, urb);
  70591. + dl_del_urb (urb);
  70592. } else {
  70593. td_p = &td->hwNextTD;
  70594. }
  70595. @@ -1708,6 +1658,7 @@
  70596. }
  70597. ohci->ed_rm_list[frame] = NULL;
  70598. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70599. }
  70600. @@ -1724,7 +1675,9 @@
  70601. struct urb * urb;
  70602. urb_priv_t * urb_priv;
  70603. __u32 tdINFO, edHeadP, edTailP;
  70604. -
  70605. +
  70606. + unsigned long flags;
  70607. +
  70608. while (td_list) {
  70609. td_list_next = td_list->next_dl_td;
  70610. @@ -1753,10 +1706,13 @@
  70611. urb->status = cc_to_error[cc];
  70612. sohci_return_urb (ohci, urb);
  70613. } else {
  70614. - dl_del_urb (ohci, urb);
  70615. + spin_lock_irqsave (&usb_ed_lock, flags);
  70616. + dl_del_urb (urb);
  70617. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70618. }
  70619. }
  70620. + spin_lock_irqsave (&usb_ed_lock, flags);
  70621. if (ed->state != ED_NEW) {
  70622. edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
  70623. edTailP = le32_to_cpup (&ed->hwTailP);
  70624. @@ -1765,6 +1721,7 @@
  70625. if ((edHeadP == edTailP) && (ed->state == ED_OPER))
  70626. ep_unlink (ohci, ed);
  70627. }
  70628. + spin_unlock_irqrestore (&usb_ed_lock, flags);
  70629. td_list = td_list_next;
  70630. }
  70631. @@ -1855,7 +1812,7 @@
  70632. num_ports = roothub_a (ohci) & RH_A_NDP;
  70633. if (num_ports > MAX_ROOT_PORTS) {
  70634. err ("bogus NDP=%d for OHCI usb-%s", num_ports,
  70635. - ohci->ohci_dev->slot_name);
  70636. + ohci->slot_name);
  70637. err ("rereads as NDP=%d",
  70638. readl (&ohci->regs->roothub.a) & RH_A_NDP);
  70639. /* retry later; "should not happen" */
  70640. @@ -1955,8 +1912,7 @@
  70641. int leni = urb->transfer_buffer_length;
  70642. int len = 0;
  70643. int status = TD_CC_NOERROR;
  70644. - unsigned long flags;
  70645. -
  70646. +
  70647. __u32 datab[4];
  70648. __u8 * data_buf = (__u8 *) datab;
  70649. @@ -1965,16 +1921,13 @@
  70650. __u16 wIndex;
  70651. __u16 wLength;
  70652. - spin_lock_irqsave(&ohci->ohci_lock, flags);
  70653. -
  70654. if (usb_pipeint(pipe)) {
  70655. ohci->rh.urb = urb;
  70656. ohci->rh.send = 1;
  70657. ohci->rh.interval = urb->interval;
  70658. rh_init_int_timer(urb);
  70659. urb->status = cc_to_error [TD_CC_NOERROR];
  70660. -
  70661. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70662. +
  70663. return 0;
  70664. }
  70665. @@ -2146,7 +2099,6 @@
  70666. #endif
  70667. urb->hcpriv = NULL;
  70668. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70669. usb_dec_dev_use (usb_dev);
  70670. urb->dev = NULL;
  70671. if (urb->complete)
  70672. @@ -2159,16 +2111,13 @@
  70673. static int rh_unlink_urb (struct urb * urb)
  70674. {
  70675. ohci_t * ohci = urb->dev->bus->hcpriv;
  70676. - unsigned int flags;
  70677. - spin_lock_irqsave(&ohci->ohci_lock, flags);
  70678. if (ohci->rh.urb == urb) {
  70679. ohci->rh.send = 0;
  70680. del_timer (&ohci->rh.rh_int_timer);
  70681. ohci->rh.urb = NULL;
  70682. urb->hcpriv = NULL;
  70683. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70684. usb_dec_dev_use(urb->dev);
  70685. urb->dev = NULL;
  70686. if (urb->transfer_flags & USB_ASYNC_UNLINK) {
  70687. @@ -2177,8 +2126,6 @@
  70688. urb->complete (urb);
  70689. } else
  70690. urb->status = -ENOENT;
  70691. - } else {
  70692. - spin_unlock_irqrestore(&ohci->ohci_lock, flags);
  70693. }
  70694. return 0;
  70695. }
  70696. @@ -2213,16 +2160,12 @@
  70697. writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
  70698. dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
  70699. - ohci->ohci_dev->slot_name,
  70700. + ohci->slot_name,
  70701. readl (&ohci->regs->control));
  70702. /* Reset USB (needed by some controllers) */
  70703. writel (0, &ohci->regs->control);
  70704. -
  70705. - /* Force a state change from USBRESET to USBOPERATIONAL for ALi */
  70706. - (void) readl (&ohci->regs->control); /* PCI posting */
  70707. - writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control);
  70708. -
  70709. +
  70710. /* HC Reset requires max 10 ms delay */
  70711. writel (OHCI_HCR, &ohci->regs->cmdstatus);
  70712. while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
  70713. @@ -2291,8 +2234,6 @@
  70714. writel (RH_HS_LPSC, &ohci->regs->roothub.status);
  70715. #endif /* OHCI_USE_NPS */
  70716. - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
  70717. -
  70718. // POTPGT delay is bits 24-31, in 2 ms units.
  70719. mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
  70720. @@ -2322,7 +2263,7 @@
  70721. static void check_timeouts (struct ohci *ohci)
  70722. {
  70723. - spin_lock (&ohci->ohci_lock);
  70724. + spin_lock (&usb_ed_lock);
  70725. while (!list_empty (&ohci->timeout_list)) {
  70726. struct urb *urb;
  70727. @@ -2335,15 +2276,15 @@
  70728. continue;
  70729. urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
  70730. - spin_unlock (&ohci->ohci_lock);
  70731. + spin_unlock (&usb_ed_lock);
  70732. // outside the interrupt handler (in a timer...)
  70733. // this reference would race interrupts
  70734. sohci_unlink_urb (urb);
  70735. - spin_lock (&ohci->ohci_lock);
  70736. + spin_lock (&usb_ed_lock);
  70737. }
  70738. - spin_unlock (&ohci->ohci_lock);
  70739. + spin_unlock (&usb_ed_lock);
  70740. }
  70741. @@ -2357,8 +2298,6 @@
  70742. struct ohci_regs * regs = ohci->regs;
  70743. int ints;
  70744. - spin_lock (&ohci->ohci_lock);
  70745. -
  70746. /* avoid (slow) readl if only WDH happened */
  70747. if ((ohci->hcca->done_head != 0)
  70748. && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
  70749. @@ -2367,22 +2306,20 @@
  70750. /* cardbus/... hardware gone before remove() */
  70751. } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
  70752. ohci->disabled++;
  70753. - spin_unlock (&ohci->ohci_lock);
  70754. err ("%s device removed!", ohci->ohci_dev->slot_name);
  70755. return;
  70756. /* interrupt for some other device? */
  70757. } else if ((ints &= readl (&regs->intrenable)) == 0) {
  70758. - spin_unlock (&ohci->ohci_lock);
  70759. return;
  70760. - }
  70761. + }
  70762. // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
  70763. if (ints & OHCI_INTR_UE) {
  70764. ohci->disabled++;
  70765. err ("OHCI Unrecoverable Error, controller usb-%s disabled",
  70766. - ohci->ohci_dev->slot_name);
  70767. + ohci->slot_name);
  70768. // e.g. due to PCI Master/Target Abort
  70769. #ifdef DEBUG
  70770. @@ -2398,39 +2335,26 @@
  70771. if (ints & OHCI_INTR_WDH) {
  70772. writel (OHCI_INTR_WDH, &regs->intrdisable);
  70773. - (void)readl (&regs->intrdisable); /* PCI posting flush */
  70774. dl_done_list (ohci, dl_reverse_done_list (ohci));
  70775. writel (OHCI_INTR_WDH, &regs->intrenable);
  70776. - (void)readl (&regs->intrdisable); /* PCI posting flush */
  70777. }
  70778. if (ints & OHCI_INTR_SO) {
  70779. dbg("USB Schedule overrun");
  70780. writel (OHCI_INTR_SO, &regs->intrenable);
  70781. - (void)readl (&regs->intrdisable); /* PCI posting flush */
  70782. }
  70783. // FIXME: this assumes SOF (1/ms) interrupts don't get lost...
  70784. if (ints & OHCI_INTR_SF) {
  70785. unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
  70786. writel (OHCI_INTR_SF, &regs->intrdisable);
  70787. - (void)readl (&regs->intrdisable); /* PCI posting flush */
  70788. if (ohci->ed_rm_list[!frame] != NULL) {
  70789. dl_del_list (ohci, !frame);
  70790. }
  70791. - if (ohci->ed_rm_list[frame] != NULL) {
  70792. + if (ohci->ed_rm_list[frame] != NULL)
  70793. writel (OHCI_INTR_SF, &regs->intrenable);
  70794. - (void)readl (&regs->intrdisable); /* PCI posting flush */
  70795. - }
  70796. }
  70797. - /*
  70798. - * Finally, we are done with trashing about our hardware lists
  70799. - * and other CPUs are allowed in. The festive flipping of the lock
  70800. - * ensues as we struggle with the check_timeouts disaster.
  70801. - */
  70802. - spin_unlock (&ohci->ohci_lock);
  70803. -
  70804. if (!list_empty (&ohci->timeout_list)) {
  70805. check_timeouts (ohci);
  70806. // FIXME: enable SF as needed in a timer;
  70807. @@ -2442,9 +2366,6 @@
  70808. writel (ints, &regs->intrstatus);
  70809. writel (OHCI_INTR_MIE, &regs->intrenable);
  70810. - (void)readl (&regs->intrdisable); /* PCI posting flush */
  70811. -
  70812. - ohci_complete(ohci);
  70813. }
  70814. /*-------------------------------------------------------------------------*/
  70815. @@ -2475,10 +2396,14 @@
  70816. ohci->regs = mem_base;
  70817. ohci->ohci_dev = dev;
  70818. +#ifdef CONFIG_PCI
  70819. pci_set_drvdata(dev, ohci);
  70820. +#endif
  70821. + INIT_LIST_HEAD (&ohci->ohci_hcd_list);
  70822. + list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
  70823. +
  70824. INIT_LIST_HEAD (&ohci->timeout_list);
  70825. - spin_lock_init(&ohci->ohci_lock);
  70826. ohci->bus = usb_alloc_bus (&sohci_device_operations);
  70827. if (!ohci->bus) {
  70828. @@ -2501,7 +2426,7 @@
  70829. static void hc_release_ohci (ohci_t * ohci)
  70830. {
  70831. - dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
  70832. + dbg ("USB HC release ohci usb-%s", ohci->slot_name);
  70833. /* disconnect all devices */
  70834. if (ohci->bus->root_hub)
  70835. @@ -2514,7 +2439,9 @@
  70836. free_irq (ohci->irq, ohci);
  70837. ohci->irq = -1;
  70838. }
  70839. - pci_set_drvdata(ohci->ohci_dev, NULL);
  70840. +#ifdef CONFIG_PCI
  70841. + pci_set_drvdata(ohci->ohci_dev, 0);
  70842. +#endif
  70843. if (ohci->bus) {
  70844. if (ohci->bus->busnum != -1)
  70845. usb_deregister_bus (ohci->bus);
  70846. @@ -2522,6 +2449,9 @@
  70847. usb_free_bus (ohci->bus);
  70848. }
  70849. + list_del (&ohci->ohci_hcd_list);
  70850. + INIT_LIST_HEAD (&ohci->ohci_hcd_list);
  70851. +
  70852. ohci_mem_cleanup (ohci);
  70853. /* unmap the IO address space */
  70854. @@ -2534,17 +2464,15 @@
  70855. /*-------------------------------------------------------------------------*/
  70856. -/* Increment the module usage count, start the control thread and
  70857. - * return success. */
  70858. -
  70859. -static struct pci_driver ohci_pci_driver;
  70860. -
  70861. -static int __devinit
  70862. -hc_found_ohci (struct pci_dev *dev, int irq,
  70863. - void *mem_base, const struct pci_device_id *id)
  70864. +/*
  70865. + * Host bus independent add one OHCI host controller.
  70866. + */
  70867. +int __devinit
  70868. +hc_add_ohci(struct pci_dev *dev, int irq, void *mem_base, unsigned long flags,
  70869. + const char *name, const char *slot_name)
  70870. {
  70871. - ohci_t * ohci;
  70872. char buf[8], *bufp = buf;
  70873. + ohci_t * ohci;
  70874. int ret;
  70875. #ifndef __sparc__
  70876. @@ -2554,34 +2482,17 @@
  70877. #endif
  70878. printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
  70879. (unsigned long) mem_base, bufp);
  70880. - printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
  70881. -
  70882. +
  70883. ohci = hc_alloc_ohci (dev, mem_base);
  70884. if (!ohci) {
  70885. return -ENOMEM;
  70886. }
  70887. + ohci->slot_name = slot_name;
  70888. if ((ret = ohci_mem_init (ohci)) < 0) {
  70889. hc_release_ohci (ohci);
  70890. return ret;
  70891. }
  70892. - ohci->flags = id->driver_data;
  70893. -
  70894. - /* Check for NSC87560. We have to look at the bridge (fn1) to identify
  70895. - the USB (fn2). This quirk might apply to more or even all NSC stuff
  70896. - I don't know.. */
  70897. -
  70898. - if(dev->vendor == PCI_VENDOR_ID_NS)
  70899. - {
  70900. - struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
  70901. - if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
  70902. - ohci->flags |= OHCI_QUIRK_SUCKYIO;
  70903. -
  70904. - }
  70905. -
  70906. - if (ohci->flags & OHCI_QUIRK_SUCKYIO)
  70907. - printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
  70908. - if (ohci->flags & OHCI_QUIRK_AMD756)
  70909. - printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
  70910. + ohci->flags = flags;
  70911. if (hc_reset (ohci) < 0) {
  70912. hc_release_ohci (ohci);
  70913. @@ -2590,13 +2501,11 @@
  70914. /* FIXME this is a second HC reset; why?? */
  70915. writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
  70916. - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
  70917. wait_ms (10);
  70918. usb_register_bus (ohci->bus);
  70919. - if (request_irq (irq, hc_interrupt, SA_SHIRQ,
  70920. - ohci_pci_driver.name, ohci) != 0) {
  70921. + if (request_irq (irq, hc_interrupt, SA_SHIRQ, name, ohci) != 0) {
  70922. err ("request interrupt %s failed", bufp);
  70923. hc_release_ohci (ohci);
  70924. return -EBUSY;
  70925. @@ -2604,7 +2513,7 @@
  70926. ohci->irq = irq;
  70927. if (hc_start (ohci) < 0) {
  70928. - err ("can't start usb-%s", dev->slot_name);
  70929. + err ("can't start usb-%s", ohci->slot_name);
  70930. hc_release_ohci (ohci);
  70931. return -EBUSY;
  70932. }
  70933. @@ -2615,114 +2524,11 @@
  70934. return 0;
  70935. }
  70936. -/*-------------------------------------------------------------------------*/
  70937. -
  70938. -#ifdef CONFIG_PM
  70939. -
  70940. -/* controller died; cleanup debris, then restart */
  70941. -/* must not be called from interrupt context */
  70942. -
  70943. -static void hc_restart (ohci_t *ohci)
  70944. -{
  70945. - int temp;
  70946. - int i;
  70947. -
  70948. - if (ohci->pci_latency)
  70949. - pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
  70950. -
  70951. - ohci->disabled = 1;
  70952. - ohci->sleeping = 0;
  70953. - if (ohci->bus->root_hub)
  70954. - usb_disconnect (&ohci->bus->root_hub);
  70955. -
  70956. - /* empty the interrupt branches */
  70957. - for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
  70958. - for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
  70959. -
  70960. - /* no EDs to remove */
  70961. - ohci->ed_rm_list [0] = NULL;
  70962. - ohci->ed_rm_list [1] = NULL;
  70963. -
  70964. - /* empty control and bulk lists */
  70965. - ohci->ed_isotail = NULL;
  70966. - ohci->ed_controltail = NULL;
  70967. - ohci->ed_bulktail = NULL;
  70968. -
  70969. - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
  70970. - err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
  70971. - } else
  70972. - dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
  70973. -}
  70974. -
  70975. -#endif /* CONFIG_PM */
  70976. -
  70977. -/*-------------------------------------------------------------------------*/
  70978. -
  70979. -/* configured so that an OHCI device is always provided */
  70980. -/* always called with process context; sleeping is OK */
  70981. -
  70982. -static int __devinit
  70983. -ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
  70984. +/*
  70985. + * Host bus independent remove one OHCI host controller.
  70986. + */
  70987. +void __devexit hc_remove_ohci(ohci_t *ohci)
  70988. {
  70989. - unsigned long mem_resource, mem_len;
  70990. - void *mem_base;
  70991. - int status;
  70992. -
  70993. - if (pci_enable_device(dev) < 0)
  70994. - return -ENODEV;
  70995. -
  70996. - if (!dev->irq) {
  70997. - err("found OHCI device with no IRQ assigned. check BIOS settings!");
  70998. - pci_disable_device (dev);
  70999. - return -ENODEV;
  71000. - }
  71001. -
  71002. - /* we read its hardware registers as memory */
  71003. - mem_resource = pci_resource_start(dev, 0);
  71004. - mem_len = pci_resource_len(dev, 0);
  71005. - if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
  71006. - dbg ("controller already in use");
  71007. - pci_disable_device (dev);
  71008. - return -EBUSY;
  71009. - }
  71010. -
  71011. - mem_base = ioremap_nocache (mem_resource, mem_len);
  71012. - if (!mem_base) {
  71013. - err("Error mapping OHCI memory");
  71014. - release_mem_region (mem_resource, mem_len);
  71015. - pci_disable_device (dev);
  71016. - return -EFAULT;
  71017. - }
  71018. -
  71019. - /* controller writes into our memory */
  71020. - pci_set_master (dev);
  71021. -
  71022. - status = hc_found_ohci (dev, dev->irq, mem_base, id);
  71023. - if (status < 0) {
  71024. - iounmap (mem_base);
  71025. - release_mem_region (mem_resource, mem_len);
  71026. - pci_disable_device (dev);
  71027. - }
  71028. - return status;
  71029. -}
  71030. -
  71031. -/*-------------------------------------------------------------------------*/
  71032. -
  71033. -/* may be called from interrupt context [interface spec] */
  71034. -/* may be called without controller present */
  71035. -/* may be called with controller, bus, and devices active */
  71036. -
  71037. -static void __devexit
  71038. -ohci_pci_remove (struct pci_dev *dev)
  71039. -{
  71040. - ohci_t *ohci = pci_get_drvdata(dev);
  71041. -
  71042. - dbg ("remove %s controller usb-%s%s%s",
  71043. - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
  71044. - dev->slot_name,
  71045. - ohci->disabled ? " (disabled)" : "",
  71046. - in_interrupt () ? " in interrupt" : ""
  71047. - );
  71048. #ifdef DEBUG
  71049. ohci_dump (ohci, 1);
  71050. #endif
  71051. @@ -2739,270 +2545,8 @@
  71052. &ohci->regs->control);
  71053. hc_release_ohci (ohci);
  71054. -
  71055. - release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
  71056. - pci_disable_device (dev);
  71057. -}
  71058. -
  71059. -
  71060. -#ifdef CONFIG_PM
  71061. -
  71062. -/*-------------------------------------------------------------------------*/
  71063. -
  71064. -static int
  71065. -ohci_pci_suspend (struct pci_dev *dev, u32 state)
  71066. -{
  71067. - ohci_t *ohci = pci_get_drvdata(dev);
  71068. - unsigned long flags;
  71069. - u16 cmd;
  71070. -
  71071. - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
  71072. - dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
  71073. - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
  71074. - return -EIO;
  71075. - }
  71076. -
  71077. - /* act as if usb suspend can always be used */
  71078. - info ("USB suspend: usb-%s", dev->slot_name);
  71079. - ohci->sleeping = 1;
  71080. -
  71081. - /* First stop processing */
  71082. - spin_lock_irqsave (&ohci->ohci_lock, flags);
  71083. - ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
  71084. - writel (ohci->hc_control, &ohci->regs->control);
  71085. - writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
  71086. - (void) readl (&ohci->regs->intrstatus);
  71087. - spin_unlock_irqrestore (&ohci->ohci_lock, flags);
  71088. -
  71089. - /* Wait a frame or two */
  71090. - mdelay(1);
  71091. - if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
  71092. - mdelay (1);
  71093. -
  71094. -#ifdef CONFIG_PMAC_PBOOK
  71095. - if (_machine == _MACH_Pmac)
  71096. - disable_irq (ohci->irq);
  71097. - /* else, 2.4 assumes shared irqs -- don't disable */
  71098. -#endif
  71099. - /* Enable remote wakeup */
  71100. - writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
  71101. -
  71102. - /* Suspend chip and let things settle down a bit */
  71103. - ohci->hc_control = OHCI_USB_SUSPEND;
  71104. - writel (ohci->hc_control, &ohci->regs->control);
  71105. - (void) readl (&ohci->regs->control);
  71106. - mdelay (500); /* No schedule here ! */
  71107. - switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
  71108. - case OHCI_USB_RESET:
  71109. - dbg("Bus in reset phase ???");
  71110. - break;
  71111. - case OHCI_USB_RESUME:
  71112. - dbg("Bus in resume phase ???");
  71113. - break;
  71114. - case OHCI_USB_OPER:
  71115. - dbg("Bus in operational phase ???");
  71116. - break;
  71117. - case OHCI_USB_SUSPEND:
  71118. - dbg("Bus suspended");
  71119. - break;
  71120. - }
  71121. - /* In some rare situations, Apple's OHCI have happily trashed
  71122. - * memory during sleep. We disable it's bus master bit during
  71123. - * suspend
  71124. - */
  71125. - pci_read_config_word (dev, PCI_COMMAND, &cmd);
  71126. - cmd &= ~PCI_COMMAND_MASTER;
  71127. - pci_write_config_word (dev, PCI_COMMAND, cmd);
  71128. -#ifdef CONFIG_PMAC_PBOOK
  71129. - {
  71130. - struct device_node *of_node;
  71131. -
  71132. - /* Disable USB PAD & cell clock */
  71133. - of_node = pci_device_to_OF_node (ohci->ohci_dev);
  71134. - if (of_node)
  71135. - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
  71136. - }
  71137. -#endif
  71138. - return 0;
  71139. -}
  71140. -
  71141. -/*-------------------------------------------------------------------------*/
  71142. -
  71143. -static int
  71144. -ohci_pci_resume (struct pci_dev *dev)
  71145. -{
  71146. - ohci_t *ohci = pci_get_drvdata(dev);
  71147. - int temp;
  71148. - unsigned long flags;
  71149. -
  71150. - /* guard against multiple resumes */
  71151. - atomic_inc (&ohci->resume_count);
  71152. - if (atomic_read (&ohci->resume_count) != 1) {
  71153. - err ("concurrent PCI resumes for usb-%s", dev->slot_name);
  71154. - atomic_dec (&ohci->resume_count);
  71155. - return 0;
  71156. - }
  71157. -
  71158. -#ifdef CONFIG_PMAC_PBOOK
  71159. - {
  71160. - struct device_node *of_node;
  71161. -
  71162. - /* Re-enable USB PAD & cell clock */
  71163. - of_node = pci_device_to_OF_node (ohci->ohci_dev);
  71164. - if (of_node)
  71165. - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
  71166. - }
  71167. -#endif
  71168. -
  71169. - /* did we suspend, or were we powered off? */
  71170. - ohci->hc_control = readl (&ohci->regs->control);
  71171. - temp = ohci->hc_control & OHCI_CTRL_HCFS;
  71172. -
  71173. -#ifdef DEBUG
  71174. - /* the registers may look crazy here */
  71175. - ohci_dump_status (ohci);
  71176. -#endif
  71177. -
  71178. - /* Re-enable bus mastering */
  71179. - pci_set_master(ohci->ohci_dev);
  71180. -
  71181. - switch (temp) {
  71182. -
  71183. - case OHCI_USB_RESET: // lost power
  71184. - info ("USB restart: usb-%s", dev->slot_name);
  71185. - hc_restart (ohci);
  71186. - break;
  71187. -
  71188. - case OHCI_USB_SUSPEND: // host wakeup
  71189. - case OHCI_USB_RESUME: // remote wakeup
  71190. - info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
  71191. - (temp == OHCI_USB_SUSPEND)
  71192. - ? "host" : "remote");
  71193. - ohci->hc_control = OHCI_USB_RESUME;
  71194. - writel (ohci->hc_control, &ohci->regs->control);
  71195. - (void) readl (&ohci->regs->control);
  71196. - mdelay (20); /* no schedule here ! */
  71197. - /* Some controllers (lucent) need a longer delay here */
  71198. - mdelay (15);
  71199. - temp = readl (&ohci->regs->control);
  71200. - temp = ohci->hc_control & OHCI_CTRL_HCFS;
  71201. - if (temp != OHCI_USB_RESUME) {
  71202. - err ("controller usb-%s won't resume", dev->slot_name);
  71203. - ohci->disabled = 1;
  71204. - return -EIO;
  71205. - }
  71206. -
  71207. - /* Some chips likes being resumed first */
  71208. - writel (OHCI_USB_OPER, &ohci->regs->control);
  71209. - (void) readl (&ohci->regs->control);
  71210. - mdelay (3);
  71211. -
  71212. - /* Then re-enable operations */
  71213. - spin_lock_irqsave (&ohci->ohci_lock, flags);
  71214. - ohci->disabled = 0;
  71215. - ohci->sleeping = 0;
  71216. - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
  71217. - if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
  71218. - if (ohci->ed_controltail)
  71219. - ohci->hc_control |= OHCI_CTRL_CLE;
  71220. - if (ohci->ed_bulktail)
  71221. - ohci->hc_control |= OHCI_CTRL_BLE;
  71222. - }
  71223. - writel (ohci->hc_control, &ohci->regs->control);
  71224. - writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
  71225. - writel (OHCI_INTR_SF, &ohci->regs->intrenable);
  71226. - /* Check for a pending done list */
  71227. - writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
  71228. - (void) readl (&ohci->regs->intrdisable);
  71229. -#ifdef CONFIG_PMAC_PBOOK
  71230. - if (_machine == _MACH_Pmac)
  71231. - enable_irq (ohci->irq);
  71232. -#endif
  71233. - if (ohci->hcca->done_head)
  71234. - dl_done_list (ohci, dl_reverse_done_list (ohci));
  71235. - writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
  71236. - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
  71237. - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
  71238. - spin_unlock_irqrestore (&ohci->ohci_lock, flags);
  71239. - break;
  71240. -
  71241. - default:
  71242. - warn ("odd PCI resume for usb-%s", dev->slot_name);
  71243. - }
  71244. -
  71245. - /* controller is operational, extra resumes are harmless */
  71246. - atomic_dec (&ohci->resume_count);
  71247. -
  71248. - return 0;
  71249. -}
  71250. -
  71251. -#endif /* CONFIG_PM */
  71252. -
  71253. -
  71254. -/*-------------------------------------------------------------------------*/
  71255. -
  71256. -static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
  71257. -
  71258. - /*
  71259. - * AMD-756 [Viper] USB has a serious erratum when used with
  71260. - * lowspeed devices like mice.
  71261. - */
  71262. - vendor: 0x1022,
  71263. - device: 0x740c,
  71264. - subvendor: PCI_ANY_ID,
  71265. - subdevice: PCI_ANY_ID,
  71266. -
  71267. - driver_data: OHCI_QUIRK_AMD756,
  71268. -
  71269. -} , {
  71270. -
  71271. - /* handle any USB OHCI controller */
  71272. - class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
  71273. - class_mask: ~0,
  71274. -
  71275. - /* no matter who makes it */
  71276. - vendor: PCI_ANY_ID,
  71277. - device: PCI_ANY_ID,
  71278. - subvendor: PCI_ANY_ID,
  71279. - subdevice: PCI_ANY_ID,
  71280. -
  71281. - }, { /* end: all zeroes */ }
  71282. -};
  71283. -
  71284. -MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
  71285. -
  71286. -static struct pci_driver ohci_pci_driver = {
  71287. - name: "usb-ohci",
  71288. - id_table: &ohci_pci_ids [0],
  71289. -
  71290. - probe: ohci_pci_probe,
  71291. - remove: __devexit_p(ohci_pci_remove),
  71292. -
  71293. -#ifdef CONFIG_PM
  71294. - suspend: ohci_pci_suspend,
  71295. - resume: ohci_pci_resume,
  71296. -#endif /* PM */
  71297. -};
  71298. -
  71299. -
  71300. -/*-------------------------------------------------------------------------*/
  71301. -
  71302. -static int __init ohci_hcd_init (void)
  71303. -{
  71304. - return pci_module_init (&ohci_pci_driver);
  71305. }
  71306. -/*-------------------------------------------------------------------------*/
  71307. -
  71308. -static void __exit ohci_hcd_cleanup (void)
  71309. -{
  71310. - pci_unregister_driver (&ohci_pci_driver);
  71311. -}
  71312. -
  71313. -module_init (ohci_hcd_init);
  71314. -module_exit (ohci_hcd_cleanup);
  71315. -
  71316. -
  71317. MODULE_AUTHOR( DRIVER_AUTHOR );
  71318. MODULE_DESCRIPTION( DRIVER_DESC );
  71319. MODULE_LICENSE("GPL");
  71320. diff -urN linux-2.4.26/drivers/usb/host/usb-ohci.h linux-2.4.26-vrs1/drivers/usb/host/usb-ohci.h
  71321. --- linux-2.4.26/drivers/usb/host/usb-ohci.h 2004-04-19 11:44:27.000000000 +0100
  71322. +++ linux-2.4.26-vrs1/drivers/usb/host/usb-ohci.h 2004-04-19 17:13:29.000000000 +0100
  71323. @@ -384,12 +384,13 @@
  71324. #define OHCI_QUIRK_SUCKYIO 0x02 /* NSC superio */
  71325. struct ohci_regs * regs; /* OHCI controller's memory */
  71326. + struct list_head ohci_hcd_list; /* list of all ohci_hcd */
  71327. + struct ohci * next; // chain of ohci device contexts
  71328. struct list_head timeout_list;
  71329. // struct list_head urb_list; // list of all pending urbs
  71330. - spinlock_t ohci_lock; /* Covers all fields up & down */
  71331. - struct urb *complete_head, *complete_tail;
  71332. -
  71333. + // spinlock_t urb_list_lock; // lock to keep consistency
  71334. +
  71335. int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/
  71336. ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */
  71337. ed_t * ed_bulktail; /* last endpoint of bulk list */
  71338. @@ -403,6 +404,7 @@
  71339. /* PCI device handle, settings, ... */
  71340. struct pci_dev *ohci_dev;
  71341. + const char *slot_name;
  71342. u8 pci_latency;
  71343. struct pci_pool *td_cache;
  71344. struct pci_pool *dev_cache;
  71345. @@ -448,7 +450,7 @@
  71346. #endif
  71347. #ifndef CONFIG_PCI
  71348. -# error "usb-ohci currently requires PCI-based controllers"
  71349. +//# error "usb-ohci currently requires PCI-based controllers"
  71350. /* to support non-PCI OHCIs, you need custom bus/mem/... glue */
  71351. #endif
  71352. @@ -641,3 +643,6 @@
  71353. pci_pool_free (hc->dev_cache, dev, dev->dma);
  71354. }
  71355. +/* For initializing controller (mask in an HCFS mode too) */
  71356. +#define OHCI_CONTROL_INIT \
  71357. + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
  71358. diff -urN linux-2.4.26/drivers/video/Config.in linux-2.4.26-vrs1/drivers/video/Config.in
  71359. --- linux-2.4.26/drivers/video/Config.in 2004-02-27 20:03:27.000000000 +0000
  71360. +++ linux-2.4.26-vrs1/drivers/video/Config.in 2004-02-23 23:25:16.000000000 +0000
  71361. @@ -30,13 +30,28 @@
  71362. tristate ' Permedia3 support (EXPERIMENTAL)' CONFIG_FB_PM3
  71363. fi
  71364. fi
  71365. - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
  71366. - bool ' Acorn VIDC support' CONFIG_FB_ACORN
  71367. - fi
  71368. - dep_tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
  71369. - if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
  71370. - bool ' SA-1100 LCD support' CONFIG_FB_SA1100
  71371. + if [ "$CONFIG_ARM" = "y" ]; then
  71372. + if [ "$CONFIG_ARCH_ACORN" -o "$CONFIG_ARCH_RISCSTATION" ]; then
  71373. + bool ' Acorn VIDC support' CONFIG_FB_ACORN
  71374. + else
  71375. + define_bool CONFIG_FB_ACORN n
  71376. + fi
  71377. + dep_bool ' Anakin LCD support' CONFIG_FB_ANAKIN $CONFIG_ARCH_ANAKIN
  71378. + dep_bool ' CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X
  71379. + dep_bool ' SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100
  71380. + dep_bool ' MX1ADS LCD support' CONFIG_FB_DBMX1 $CONFIG_ARCH_MX1ADS
  71381. + if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then
  71382. + choice 'CerfBoard LCD Display Size' \
  71383. + "3.8_Color CONFIG_CERF_LCD_38_A \
  71384. + 3.8_Mono CONFIG_CERF_LCD_38_B \
  71385. + 5.7 CONFIG_CERF_LCD_57_A \
  71386. + 7.2 CONFIG_CERF_LCD_72_A" 5.7
  71387. + fi
  71388. + if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
  71389. + bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
  71390. + fi
  71391. fi
  71392. + dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
  71393. if [ "$CONFIG_APOLLO" = "y" ]; then
  71394. define_bool CONFIG_FB_APOLLO y
  71395. fi
  71396. @@ -265,7 +280,7 @@
  71397. "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \
  71398. "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
  71399. "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
  71400. - "$CONFIG_FB_TX3912" = "y" ]; then
  71401. + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" ]; then
  71402. define_tristate CONFIG_FBCON_MFB y
  71403. else
  71404. if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \
  71405. @@ -273,19 +288,20 @@
  71406. "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \
  71407. "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
  71408. "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
  71409. - "$CONFIG_FB_TX3912" = "m" ]; then
  71410. + "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
  71411. define_tristate CONFIG_FBCON_MFB m
  71412. fi
  71413. fi
  71414. if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
  71415. "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
  71416. - "$CONFIG_FB_TX3912" = "y" ]; then
  71417. + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
  71418. + "$CONFIG_FB_DBMX1" = "y" ]; then
  71419. define_tristate CONFIG_FBCON_CFB2 y
  71420. define_tristate CONFIG_FBCON_CFB4 y
  71421. else
  71422. if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
  71423. "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
  71424. - "$CONFIG_FB_TX3912" = "m" ]; then
  71425. + "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
  71426. define_tristate CONFIG_FBCON_CFB2 m
  71427. define_tristate CONFIG_FBCON_CFB4 m
  71428. fi
  71429. @@ -312,7 +328,8 @@
  71430. "$CONFIG_FB_TX3912" = "y" -o \
  71431. "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
  71432. "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
  71433. - "$CONFIG_FB_INTEL" = "y" ]; then
  71434. + "$CONFIG_FB_INTEL" = "y" -o \
  71435. + "$CONFIG_FB_DBMX1" = "y" ]; then
  71436. define_tristate CONFIG_FBCON_CFB8 y
  71437. else
  71438. if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
  71439. @@ -354,7 +371,9 @@
  71440. "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
  71441. "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
  71442. "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
  71443. - "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" ]; then
  71444. + "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
  71445. + "$CONFIG_FB_ANAKIN" = "y" -o \
  71446. + "$CONFIG_FB_DBMX1" = "y" ]; then
  71447. define_tristate CONFIG_FBCON_CFB16 y
  71448. else
  71449. if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
  71450. @@ -509,6 +528,9 @@
  71451. if [ "$CONFIG_AMIGA" = "y" ]; then
  71452. define_bool CONFIG_FONT_PEARL_8x8 y
  71453. fi
  71454. + if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
  71455. + define_bool CONFIG_FONT_ACORN_8x8 y
  71456. + fi
  71457. if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then
  71458. define_bool CONFIG_FONT_ACORN_8x8 y
  71459. fi
  71460. diff -urN linux-2.4.26/drivers/video/Makefile linux-2.4.26-vrs1/drivers/video/Makefile
  71461. --- linux-2.4.26/drivers/video/Makefile 2004-02-27 20:03:27.000000000 +0000
  71462. +++ linux-2.4.26-vrs1/drivers/video/Makefile 2004-02-23 13:36:35.000000000 +0000
  71463. @@ -55,6 +55,7 @@
  71464. obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
  71465. obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
  71466. obj-$(CONFIG_FB_CT65550) += chipsfb.o
  71467. +obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
  71468. obj-$(CONFIG_FB_CYBER) += cyberfb.o
  71469. obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
  71470. obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
  71471. @@ -68,7 +69,7 @@
  71472. obj-$(CONFIG_FB_TRIDENT) += tridentfb.o fbgen.o
  71473. obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
  71474. obj-$(CONFIG_FB_TGA) += tgafb.o fbgen.o
  71475. -obj-$(CONFIG_FB_VESA) += vesafb.o
  71476. +obj-$(CONFIG_FB_VESA) += vesafb.o
  71477. obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o
  71478. obj-$(CONFIG_FB_VIRGE) += virgefb.o
  71479. obj-$(CONFIG_FB_G364) += g364fb.o
  71480. @@ -126,14 +127,16 @@
  71481. obj-$(CONFIG_FB_SUN3) += sun3fb.o
  71482. obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
  71483. -obj-$(CONFIG_FB_HGA) += hgafb.o
  71484. +obj-$(CONFIG_FB_HGA) += hgafb.o
  71485. obj-$(CONFIG_FB_SA1100) += sa1100fb.o
  71486. -obj-$(CONFIG_FB_VIRTUAL) += vfb.o
  71487. +obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o
  71488. +obj-$(CONFIG_FB_VIRTUAL) += vfb.o
  71489. obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o
  71490. obj-$(CONFIG_FB_E1355) += epson1355fb.o fbgen.o
  71491. obj-$(CONFIG_FB_E1356) += epson1356fb.o
  71492. obj-$(CONFIG_FB_PVR2) += pvr2fb.o
  71493. obj-$(CONFIG_FB_VOODOO1) += sstfb.o
  71494. +obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
  71495. # Generic Low Level Drivers
  71496. @@ -169,4 +172,3 @@
  71497. -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
  71498. promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h
  71499. -
  71500. diff -urN linux-2.4.26/drivers/video/acornfb.c linux-2.4.26-vrs1/drivers/video/acornfb.c
  71501. --- linux-2.4.26/drivers/video/acornfb.c 2002-08-03 01:39:45.000000000 +0100
  71502. +++ linux-2.4.26-vrs1/drivers/video/acornfb.c 2004-01-14 21:32:26.000000000 +0000
  71503. @@ -752,11 +752,12 @@
  71504. }
  71505. #endif
  71506. #ifdef FBCON_HAS_CFB16
  71507. - if (bpp == 16 && regno < 16) {
  71508. + if (bpp == 16) {
  71509. int i;
  71510. - current_par.cmap.cfb16[regno] =
  71511. - regno | regno << 5 | regno << 10;
  71512. + if (regno < 16)
  71513. + current_par.cmap.cfb16[regno] =
  71514. + regno | regno << 5 | regno << 10;
  71515. pal.p = 0;
  71516. vidc_writel(0x10000000);
  71517. @@ -1215,7 +1216,7 @@
  71518. p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
  71519. p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
  71520. }
  71521. - acornfb_palette_write(i, current_par.palette[i]);
  71522. + acornfb_palette_write(i, p);
  71523. }
  71524. } else
  71525. #endif
  71526. diff -urN linux-2.4.26/drivers/video/anakinfb.c linux-2.4.26-vrs1/drivers/video/anakinfb.c
  71527. --- linux-2.4.26/drivers/video/anakinfb.c 1970-01-01 01:00:00.000000000 +0100
  71528. +++ linux-2.4.26-vrs1/drivers/video/anakinfb.c 2004-01-14 21:32:26.000000000 +0000
  71529. @@ -0,0 +1,221 @@
  71530. +/*
  71531. + * linux/drivers/video/anakinfb.c
  71532. + *
  71533. + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
  71534. + *
  71535. + * This program is free software; you can redistribute it and/or modify
  71536. + * it under the terms of the GNU General Public License version 2 as
  71537. + * published by the Free Software Foundation.
  71538. + *
  71539. + * Changelog:
  71540. + * 23-Apr-2001 TTC Created
  71541. + */
  71542. +
  71543. +#include <linux/types.h>
  71544. +#include <linux/fb.h>
  71545. +#include <linux/string.h>
  71546. +#include <linux/errno.h>
  71547. +#include <linux/init.h>
  71548. +#include <linux/module.h>
  71549. +
  71550. +#include <asm/io.h>
  71551. +
  71552. +#include <video/fbcon.h>
  71553. +#include <video/fbcon-cfb16.h>
  71554. +
  71555. +static u16 colreg[16];
  71556. +static int currcon = 0;
  71557. +static struct fb_info fb_info;
  71558. +static struct display display;
  71559. +
  71560. +static int
  71561. +anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  71562. + u_int *transp, struct fb_info *info)
  71563. +{
  71564. + if (regno > 15)
  71565. + return 1;
  71566. +
  71567. + *red = colreg[regno] & 0xf800;
  71568. + *green = colreg[regno] & 0x7e0 << 5;
  71569. + *blue = colreg[regno] & 0x1f << 11;
  71570. + *transp = 0;
  71571. + return 0;
  71572. +}
  71573. +
  71574. +static int
  71575. +anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  71576. + u_int transp, struct fb_info *info)
  71577. +{
  71578. + if (regno > 15)
  71579. + return 1;
  71580. +
  71581. + colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) |
  71582. + (blue & 0xf800 >> 11);
  71583. + return 0;
  71584. +}
  71585. +
  71586. +static int
  71587. +anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  71588. +{
  71589. + memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  71590. + strcpy(fix->id, "AnakinFB");
  71591. + fix->smem_start = VGA_START;
  71592. + fix->smem_len = VGA_SIZE;
  71593. + fix->type = FB_TYPE_PACKED_PIXELS;
  71594. + fix->type_aux = 0;
  71595. + fix->visual = FB_VISUAL_TRUECOLOR;
  71596. + fix->xpanstep = 0;
  71597. + fix->ypanstep = 0;
  71598. + fix->ywrapstep = 0;
  71599. + fix->line_length = 400 * 2;
  71600. + fix->accel = FB_ACCEL_NONE;
  71601. + return 0;
  71602. +}
  71603. +
  71604. +static int
  71605. +anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  71606. +{
  71607. + memset(var, 0, sizeof(struct fb_var_screeninfo));
  71608. + var->xres = 400;
  71609. + var->yres = 234;
  71610. + var->xres_virtual = 400;
  71611. + var->yres_virtual = 234;
  71612. + var->xoffset = 0;
  71613. + var->yoffset = 0;
  71614. + var->bits_per_pixel = 16;
  71615. + var->grayscale = 0;
  71616. + var->red.offset = 11;
  71617. + var->red.length = 5;
  71618. + var->green.offset = 5;
  71619. + var->green.length = 6;
  71620. + var->blue.offset = 0;
  71621. + var->blue.length = 5;
  71622. + var->transp.offset = 0;
  71623. + var->transp.length = 0;
  71624. + var->nonstd = 0;
  71625. + var->activate = FB_ACTIVATE_NOW;
  71626. + var->height = -1;
  71627. + var->width = -1;
  71628. + var->pixclock = 0;
  71629. + var->left_margin = 0;
  71630. + var->right_margin = 0;
  71631. + var->upper_margin = 0;
  71632. + var->lower_margin = 0;
  71633. + var->hsync_len = 0;
  71634. + var->vsync_len = 0;
  71635. + var->sync = 0;
  71636. + var->vmode = FB_VMODE_NONINTERLACED;
  71637. + return 0;
  71638. +}
  71639. +
  71640. +static int
  71641. +anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  71642. +{
  71643. + return -EINVAL;
  71644. +}
  71645. +
  71646. +static int
  71647. +anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  71648. + struct fb_info *info)
  71649. +{
  71650. + if (con == currcon)
  71651. + return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
  71652. + else if (fb_display[con].cmap.len)
  71653. + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  71654. + else
  71655. + fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
  71656. + return 0;
  71657. +}
  71658. +
  71659. +static int
  71660. +anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  71661. + struct fb_info *info)
  71662. +{
  71663. + int err;
  71664. +
  71665. + if (!fb_display[con].cmap.len) {
  71666. + if ((err = fb_alloc_cmap(&fb_display[con].cmap, 16, 0)))
  71667. + return err;
  71668. + }
  71669. + if (con == currcon)
  71670. + return fb_set_cmap(cmap, kspc, anakinfb_setcolreg, info);
  71671. + else
  71672. + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  71673. + return 0;
  71674. +}
  71675. +
  71676. +static int
  71677. +anakinfb_switch_con(int con, struct fb_info *info)
  71678. +{
  71679. + currcon = con;
  71680. + return 0;
  71681. +
  71682. +}
  71683. +
  71684. +static int
  71685. +anakinfb_updatevar(int con, struct fb_info *info)
  71686. +{
  71687. + return 0;
  71688. +}
  71689. +
  71690. +static void
  71691. +anakinfb_blank(int blank, struct fb_info *info)
  71692. +{
  71693. + /*
  71694. + * TODO: use I2C to blank/unblank the screen
  71695. + */
  71696. +}
  71697. +
  71698. +static struct fb_ops anakinfb_ops = {
  71699. + owner: THIS_MODULE,
  71700. + fb_get_fix: anakinfb_get_fix,
  71701. + fb_get_var: anakinfb_get_var,
  71702. + fb_set_var: anakinfb_set_var,
  71703. + fb_get_cmap: anakinfb_get_cmap,
  71704. + fb_set_cmap: anakinfb_set_cmap,
  71705. +};
  71706. +
  71707. +int __init
  71708. +anakinfb_init(void)
  71709. +{
  71710. + memset(&fb_info, 0, sizeof(struct fb_info));
  71711. + strcpy(fb_info.modename, "AnakinFB");
  71712. + fb_info.node = -1;
  71713. + fb_info.flags = FBINFO_FLAG_DEFAULT;
  71714. + fb_info.fbops = &anakinfb_ops;
  71715. + fb_info.disp = &display;
  71716. + strcpy(fb_info.fontname, "VGA8x16");
  71717. + fb_info.changevar = NULL;
  71718. + fb_info.switch_con = &anakinfb_switch_con;
  71719. + fb_info.updatevar = &anakinfb_updatevar;
  71720. + fb_info.blank = &anakinfb_blank;
  71721. +
  71722. + memset(&display, 0, sizeof(struct display));
  71723. + anakinfb_get_var(&display.var, 0, &fb_info);
  71724. + display.screen_base = ioremap(VGA_START, VGA_SIZE);
  71725. + display.visual = FB_VISUAL_TRUECOLOR;
  71726. + display.type = FB_TYPE_PACKED_PIXELS;
  71727. + display.type_aux = 0;
  71728. + display.ypanstep = 0;
  71729. + display.ywrapstep = 0;
  71730. + display.line_length = 400 * 2;
  71731. + display.can_soft_blank = 1;
  71732. + display.inverse = 0;
  71733. +
  71734. +#ifdef FBCON_HAS_CFB16
  71735. + display.dispsw = &fbcon_cfb16;
  71736. + display.dispsw_data = colreg;
  71737. +#else
  71738. + display.dispsw = &fbcon_dummy;
  71739. +#endif
  71740. +
  71741. + if (register_framebuffer(&fb_info) < 0)
  71742. + return -EINVAL;
  71743. +
  71744. + MOD_INC_USE_COUNT;
  71745. + return 0;
  71746. +}
  71747. +
  71748. +MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
  71749. +MODULE_DESCRIPTION("Anakin framebuffer driver");
  71750. +MODULE_SUPPORTED_DEVICE("fb");
  71751. diff -urN linux-2.4.26/drivers/video/clps711xfb.c linux-2.4.26-vrs1/drivers/video/clps711xfb.c
  71752. --- linux-2.4.26/drivers/video/clps711xfb.c 1970-01-01 01:00:00.000000000 +0100
  71753. +++ linux-2.4.26-vrs1/drivers/video/clps711xfb.c 2004-01-14 21:32:26.000000000 +0000
  71754. @@ -0,0 +1,677 @@
  71755. +/*
  71756. + * linux/drivers/video/clps711xfb.c
  71757. + *
  71758. + * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
  71759. + *
  71760. + * This program is free software; you can redistribute it and/or modify
  71761. + * it under the terms of the GNU General Public License as published by
  71762. + * the Free Software Foundation; either version 2 of the License, or
  71763. + * (at your option) any later version.
  71764. + *
  71765. + * This program is distributed in the hope that it will be useful,
  71766. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  71767. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  71768. + * GNU General Public License for more details.
  71769. + *
  71770. + * You should have received a copy of the GNU General Public License
  71771. + * along with this program; if not, write to the Free Software
  71772. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  71773. + *
  71774. + * Framebuffer driver for the CLPS7111 and EP7212 processors.
  71775. + */
  71776. +#include <linux/module.h>
  71777. +#include <linux/kernel.h>
  71778. +#include <linux/slab.h>
  71779. +#include <linux/fb.h>
  71780. +#include <linux/init.h>
  71781. +#include <linux/proc_fs.h>
  71782. +#include <linux/delay.h>
  71783. +
  71784. +#include <video/fbcon.h>
  71785. +#include <video/fbcon-cfb4.h>
  71786. +#include <video/fbcon-cfb2.h>
  71787. +#include <video/fbcon-mfb.h>
  71788. +
  71789. +#include <asm/hardware.h>
  71790. +#include <asm/mach-types.h>
  71791. +#include <asm/uaccess.h>
  71792. +
  71793. +#include <asm/hardware/clps7111.h>
  71794. +#include <asm/arch/syspld.h>
  71795. +
  71796. +static struct clps7111fb_info {
  71797. + struct fb_info fb;
  71798. + int currcon;
  71799. +} *cfb;
  71800. +
  71801. +#define CMAP_MAX_SIZE 16
  71802. +
  71803. +/* The /proc entry for the backlight. */
  71804. +static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
  71805. +
  71806. +static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
  71807. + int count, int *eof, void *data);
  71808. +static int clps7111fb_proc_backlight_write(struct file *file,
  71809. + const char *buffer, unsigned long count, void *data);
  71810. +
  71811. +/*
  71812. + * LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
  71813. + * This determines how many clocks + 1 of CL1 before the M signal toggles.
  71814. + * The number of lines on the display must not be divisible by this number.
  71815. + */
  71816. +static unsigned int lcd_ac_prescale = 13;
  71817. +
  71818. +/*
  71819. + * Set a single color register. Return != 0 for invalid regno.
  71820. + */
  71821. +static int
  71822. +clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  71823. + u_int transp, struct fb_info *info)
  71824. +{
  71825. + unsigned int level, mask, shift, pal;
  71826. +
  71827. + if (regno >= (1 << info->var.bits_per_pixel))
  71828. + return 1;
  71829. +
  71830. + /* gray = 0.30*R + 0.58*G + 0.11*B */
  71831. + level = (red * 77 + green * 151 + blue * 28) >> 20;
  71832. +
  71833. + /*
  71834. + * On an LCD, a high value is dark, while a low value is light.
  71835. + * So we invert the level.
  71836. + *
  71837. + * This isn't true on all machines, so we only do it on EDB7211.
  71838. + * --rmk
  71839. + */
  71840. + if (machine_is_edb7211() || machine_is_guidea07()) {
  71841. + level = 15 - level;
  71842. + }
  71843. +
  71844. + shift = 4 * (regno & 7);
  71845. + level <<= shift;
  71846. + mask = 15 << shift;
  71847. + level &= mask;
  71848. +
  71849. + regno = regno < 8 ? PALLSW : PALMSW;
  71850. +
  71851. + pal = clps_readl(regno);
  71852. + pal = (pal & ~mask) | level;
  71853. + clps_writel(pal, regno);
  71854. +
  71855. + return 0;
  71856. +}
  71857. +
  71858. +/*
  71859. + * Set the colormap
  71860. + */
  71861. +static int
  71862. +clps7111fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  71863. + struct fb_info *info)
  71864. +{
  71865. + struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
  71866. + struct fb_cmap *dcmap = &fb_display[con].cmap;
  71867. + int err = 0;
  71868. +
  71869. + /* no colormap allocated? */
  71870. + if (!dcmap->len)
  71871. + err = fb_alloc_cmap(dcmap, CMAP_MAX_SIZE, 0);
  71872. +
  71873. + if (!err && con == cfb->currcon) {
  71874. + err = fb_set_cmap(cmap, kspc, clps7111fb_setcolreg, &cfb->fb);
  71875. + dcmap = &cfb->fb.cmap;
  71876. + }
  71877. +
  71878. + if (!err)
  71879. + fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
  71880. +
  71881. + return err;
  71882. +}
  71883. +
  71884. +/*
  71885. + * Set the User Defined Part of the Display
  71886. + */
  71887. +static int
  71888. +clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
  71889. + struct fb_info *info)
  71890. +{
  71891. + struct display *display;
  71892. + unsigned int lcdcon, syscon, pixclock;
  71893. + int chgvar = 0;
  71894. +
  71895. + if (var->activate & FB_ACTIVATE_TEST)
  71896. + return 0;
  71897. +
  71898. + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
  71899. + return -EINVAL;
  71900. +
  71901. + if (cfb->fb.var.xres != var->xres)
  71902. + chgvar = 1;
  71903. + if (cfb->fb.var.yres != var->yres)
  71904. + chgvar = 1;
  71905. + if (cfb->fb.var.xres_virtual != var->xres_virtual)
  71906. + chgvar = 1;
  71907. + if (cfb->fb.var.yres_virtual != var->yres_virtual)
  71908. + chgvar = 1;
  71909. + if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
  71910. + chgvar = 1;
  71911. +
  71912. + if (con < 0) {
  71913. + display = cfb->fb.disp;
  71914. + chgvar = 0;
  71915. + } else {
  71916. + display = fb_display + con;
  71917. + }
  71918. +
  71919. + var->transp.msb_right = 0;
  71920. + var->transp.offset = 0;
  71921. + var->transp.length = 0;
  71922. + var->red.msb_right = 0;
  71923. + var->red.offset = 0;
  71924. + var->red.length = var->bits_per_pixel;
  71925. + var->green = var->red;
  71926. + var->blue = var->red;
  71927. +
  71928. + switch (var->bits_per_pixel) {
  71929. +#ifdef FBCON_HAS_MFB
  71930. + case 1:
  71931. + cfb->fb.fix.visual = FB_VISUAL_MONO01;
  71932. + display->dispsw = &fbcon_mfb;
  71933. + display->dispsw_data = NULL;
  71934. + break;
  71935. +#endif
  71936. +#ifdef FBCON_HAS_CFB2
  71937. + case 2:
  71938. + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  71939. + display->dispsw = &fbcon_cfb2;
  71940. + display->dispsw_data = NULL;
  71941. + break;
  71942. +#endif
  71943. +#ifdef FBCON_HAS_CFB4
  71944. + case 4:
  71945. + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  71946. + display->dispsw = &fbcon_cfb4;
  71947. + display->dispsw_data = NULL;
  71948. + break;
  71949. +#endif
  71950. + default:
  71951. + return -EINVAL;
  71952. + }
  71953. +
  71954. + display->next_line = var->xres_virtual * var->bits_per_pixel / 8;
  71955. +
  71956. + cfb->fb.fix.line_length = display->next_line;
  71957. +
  71958. + display->screen_base = cfb->fb.screen_base;
  71959. + display->line_length = cfb->fb.fix.line_length;
  71960. + display->visual = cfb->fb.fix.visual;
  71961. + display->type = cfb->fb.fix.type;
  71962. + display->type_aux = cfb->fb.fix.type_aux;
  71963. + display->ypanstep = cfb->fb.fix.ypanstep;
  71964. + display->ywrapstep = cfb->fb.fix.ywrapstep;
  71965. + display->can_soft_blank = 1;
  71966. + display->inverse = 0;
  71967. +
  71968. + cfb->fb.var = *var;
  71969. + cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
  71970. +
  71971. + /*
  71972. + * Update the old var. The fbcon drivers still use this.
  71973. + * Once they are using cfb->fb.var, this can be dropped.
  71974. + * --rmk
  71975. + */
  71976. + display->var = cfb->fb.var;
  71977. +
  71978. + /*
  71979. + * If we are setting all the virtual consoles, also set the
  71980. + * defaults used to create new consoles.
  71981. + */
  71982. + if (var->activate & FB_ACTIVATE_ALL)
  71983. + cfb->fb.disp->var = cfb->fb.var;
  71984. +
  71985. + if (chgvar && info && cfb->fb.changevar)
  71986. + cfb->fb.changevar(con);
  71987. +
  71988. + lcdcon = (var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 128 - 1;
  71989. + lcdcon |= ((var->xres_virtual / 16) - 1) << 13;
  71990. + lcdcon |= lcd_ac_prescale << 25;
  71991. +
  71992. + /*
  71993. + * Calculate pixel prescale value from the pixclock. This is:
  71994. + * 36.864MHz / pixclock_mhz - 1.
  71995. + * However, pixclock is in picoseconds, so this ends up being:
  71996. + * 36864000 * pixclock_ps / 10^12 - 1
  71997. + * and this will overflow the 32-bit math. We perform this as
  71998. + * (9 * 4096000 == 36864000):
  71999. + * pixclock_ps * 9 * (4096000 / 10^12) - 1
  72000. + */
  72001. + pixclock = 9 * info->var.pixclock / 244140 - 1;
  72002. + lcdcon |= pixclock << 19;
  72003. +
  72004. + if (info->var.bits_per_pixel == 4)
  72005. + lcdcon |= LCDCON_GSMD;
  72006. + if (info->var.bits_per_pixel >= 2)
  72007. + lcdcon |= LCDCON_GSEN;
  72008. +
  72009. + /*
  72010. + * LCDCON must only be changed while the LCD is disabled
  72011. + */
  72012. + syscon = clps_readl(SYSCON1);
  72013. + clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
  72014. + clps_writel(lcdcon, LCDCON);
  72015. + clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
  72016. +
  72017. + fb_set_cmap(&cfb->fb.cmap, 1, clps7111fb_setcolreg, &cfb->fb);
  72018. +
  72019. + return 0;
  72020. +}
  72021. +
  72022. +/*
  72023. + * Get the currently displayed virtual consoles colormap.
  72024. + */
  72025. +static int
  72026. +gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
  72027. +{
  72028. + fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
  72029. + return 0;
  72030. +}
  72031. +
  72032. +/*
  72033. + * Get the currently displayed virtual consoles fixed part of the display.
  72034. + */
  72035. +static int
  72036. +gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  72037. +{
  72038. + *fix = info->fix;
  72039. + return 0;
  72040. +}
  72041. +
  72042. +/*
  72043. + * Get the current user defined part of the display.
  72044. + */
  72045. +static int
  72046. +gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  72047. +{
  72048. + *var = info->var;
  72049. + return 0;
  72050. +}
  72051. +
  72052. +static struct fb_ops clps7111fb_ops = {
  72053. + owner: THIS_MODULE,
  72054. + fb_set_var: clps7111fb_set_var,
  72055. + fb_set_cmap: clps7111fb_set_cmap,
  72056. + fb_get_fix: gen_get_fix,
  72057. + fb_get_var: gen_get_var,
  72058. + fb_get_cmap: gen_get_cmap,
  72059. +};
  72060. +
  72061. +static int clps7111fb_switch(int con, struct fb_info *info)
  72062. +{
  72063. + struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
  72064. + struct display *disp;
  72065. + struct fb_cmap *cmap;
  72066. +
  72067. + if (cfb->currcon >= 0) {
  72068. + disp = fb_display + cfb->currcon;
  72069. +
  72070. + /*
  72071. + * Save the old colormap and video mode.
  72072. + */
  72073. + disp->var = cfb->fb.var;
  72074. + if (disp->cmap.len)
  72075. + fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
  72076. + }
  72077. +
  72078. + cfb->currcon = con;
  72079. + disp = fb_display + con;
  72080. +
  72081. + /*
  72082. + * Install the new colormap and change the video mode. By default,
  72083. + * fbcon sets all the colormaps and video modes to the default
  72084. + * values at bootup.
  72085. + */
  72086. + if (disp->cmap.len)
  72087. + cmap = &disp->cmap;
  72088. + else
  72089. + cmap = fb_default_cmap(CMAP_MAX_SIZE);
  72090. +
  72091. + fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
  72092. +
  72093. + cfb->fb.var = disp->var;
  72094. + cfb->fb.var.activate = FB_ACTIVATE_NOW;
  72095. +
  72096. + clps7111fb_set_var(&cfb->fb.var, con, &cfb->fb);
  72097. +
  72098. + return 0;
  72099. +}
  72100. +
  72101. +static int clps7111fb_updatevar(int con, struct fb_info *info)
  72102. +{
  72103. + return -EINVAL;
  72104. +}
  72105. +
  72106. +static void clps7111fb_blank(int blank, struct fb_info *info)
  72107. +{
  72108. + if (blank) {
  72109. + if (machine_is_edb7211()) {
  72110. + /* Turn off the LCD backlight. */
  72111. + clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
  72112. +
  72113. + /* Power off the LCD DC-DC converter. */
  72114. + clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
  72115. +
  72116. + /* Delay for a little while (half a second). */
  72117. + udelay(100);
  72118. +
  72119. + /* Power off the LCD panel. */
  72120. + clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
  72121. +
  72122. + /* Power off the LCD controller. */
  72123. + clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
  72124. + SYSCON1);
  72125. + }
  72126. + } else {
  72127. + if (machine_is_edb7211()) {
  72128. + /* Power up the LCD controller. */
  72129. + clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
  72130. + SYSCON1);
  72131. +
  72132. + /* Power up the LCD panel. */
  72133. + clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
  72134. +
  72135. + /* Delay for a little while. */
  72136. + udelay(100);
  72137. +
  72138. + /* Power up the LCD DC-DC converter. */
  72139. + clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
  72140. + PDDR);
  72141. +
  72142. + /* Turn on the LCD backlight. */
  72143. + clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
  72144. + }
  72145. + }
  72146. +}
  72147. +
  72148. +static int
  72149. +clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
  72150. + int count, int *eof, void *data)
  72151. +{
  72152. + /* We need at least two characters, one for the digit, and one for
  72153. + * the terminating NULL. */
  72154. + if (count < 2)
  72155. + return -EINVAL;
  72156. +
  72157. + if (machine_is_edb7211()) {
  72158. + return sprintf(page, "%d\n",
  72159. + (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
  72160. + }
  72161. +
  72162. + return 0;
  72163. +}
  72164. +
  72165. +static int
  72166. +clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
  72167. + unsigned long count, void *data)
  72168. +{
  72169. + unsigned char char_value;
  72170. + int value;
  72171. +
  72172. + if (count < 1) {
  72173. + return -EINVAL;
  72174. + }
  72175. +
  72176. + if (copy_from_user(&char_value, buffer, 1))
  72177. + return -EFAULT;
  72178. +
  72179. + value = char_value - '0';
  72180. +
  72181. + if (machine_is_edb7211()) {
  72182. + unsigned char port_d;
  72183. +
  72184. + port_d = clps_readb(PDDR);
  72185. +
  72186. + if (value) {
  72187. + port_d |= EDB_PD3_LCDBL;
  72188. + } else {
  72189. + port_d &= ~EDB_PD3_LCDBL;
  72190. + }
  72191. +
  72192. + clps_writeb(port_d, PDDR);
  72193. + }
  72194. +
  72195. + return count;
  72196. +}
  72197. +
  72198. +static void __init clps711x_guess_lcd_params(struct fb_info *info)
  72199. +{
  72200. + unsigned int lcdcon, syscon, size;
  72201. + unsigned long phys_base = PHYS_OFFSET;
  72202. + void *virt_base = (void *)PAGE_OFFSET;
  72203. +
  72204. + info->var.xres_virtual = 640;
  72205. + info->var.yres_virtual = 240;
  72206. + info->var.bits_per_pixel = 4;
  72207. + info->var.activate = FB_ACTIVATE_NOW;
  72208. + info->var.height = -1;
  72209. + info->var.width = -1;
  72210. + info->var.pixclock = 93006; /* 10.752MHz pixel clock */
  72211. +
  72212. + /*
  72213. + * If the LCD controller is already running, decode the values
  72214. + * in LCDCON to xres/yres/bpp/pixclock/acprescale
  72215. + */
  72216. + syscon = clps_readl(SYSCON1);
  72217. + if (syscon & SYSCON1_LCDEN) {
  72218. + lcdcon = clps_readl(LCDCON);
  72219. +
  72220. + /*
  72221. + * Decode GSMD and GSEN bits to bits per pixel
  72222. + * (in cs89712 docs, GSEN is GSMD1, GSMD is GSMD2)
  72223. + */
  72224. + switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
  72225. + case LCDCON_GSMD | LCDCON_GSEN:
  72226. + info->var.bits_per_pixel = 4;
  72227. + break;
  72228. +
  72229. + case LCDCON_GSEN:
  72230. + info->var.bits_per_pixel = 2;
  72231. + break;
  72232. +
  72233. + default:
  72234. + info->var.bits_per_pixel = 1;
  72235. + break;
  72236. + }
  72237. +
  72238. + /*
  72239. + * Decode xres/yres
  72240. + */
  72241. + info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
  72242. + info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
  72243. + (info->var.xres_virtual *
  72244. + info->var.bits_per_pixel);
  72245. +
  72246. + /*
  72247. + * Calculate pixclock
  72248. + */
  72249. + info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
  72250. +
  72251. + /*
  72252. + * Grab AC prescale
  72253. + */
  72254. + lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
  72255. + }
  72256. +
  72257. + info->var.xres = info->var.xres_virtual;
  72258. + info->var.yres = info->var.yres_virtual;
  72259. + info->var.grayscale = info->var.bits_per_pixel > 1;
  72260. +
  72261. + size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
  72262. +
  72263. + /*
  72264. + * Might be worth checking to see if we can use the on-board
  72265. + * RAM if size here...
  72266. + * CLPS7110 - no on-board SRAM
  72267. + * EP7212 - 38400 bytes
  72268. + */
  72269. + if (size <= 38400) {
  72270. + printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
  72271. + }
  72272. +
  72273. + if ((syscon & SYSCON1_LCDEN) == 0) {
  72274. + /*
  72275. + * The display isn't running. Ensure that
  72276. + * the display memory is empty.
  72277. + */
  72278. + memset(virt_base, 0, size);
  72279. + }
  72280. +
  72281. + info->screen_base = virt_base;
  72282. + info->fix.smem_start = phys_base;
  72283. + info->fix.smem_len = PAGE_ALIGN(size);
  72284. + info->fix.type = FB_TYPE_PACKED_PIXELS;
  72285. +}
  72286. +
  72287. +/* this function initializes the LCD registers as required by the Guide A07
  72288. +*/
  72289. +int __init clps711xfb_guidea07_init(void)
  72290. +{
  72291. + unsigned long videomem, videosize;
  72292. + unsigned int lcdcon, syscon;
  72293. +
  72294. + //LCDCON must only be changed while the LCD is disabled
  72295. + syscon = clps_readl(SYSCON1);
  72296. + clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
  72297. +
  72298. + printk(KERN_INFO "CLPS711xFB: setting up cs89712 SRAM as QVGA video framebuffer\n");
  72299. + clps_writel(0x6, FBADDR); //internal SRAM location
  72300. + videomem = (unsigned long)ioremap(SRAM_START, SRAM_SIZE);
  72301. + if (!videomem) {
  72302. + printk("ioremap failed!\n");
  72303. + kfree(cfb);
  72304. + return -EIO;
  72305. + }
  72306. +
  72307. + videosize = (320*240 * 4 / 8); //ie. 38400 or 0x9600
  72308. + memset((void *)videomem, 0, videosize); //clear the vid memory
  72309. +
  72310. + cfb->fb.screen_base = (void *)videomem;
  72311. + cfb->fb.fix.smem_start = SRAM_START; //must be physical address
  72312. + cfb->fb.fix.smem_len = videosize;
  72313. +
  72314. + cfb->fb.var.grayscale = 1;
  72315. + cfb->fb.var.bits_per_pixel = 4;
  72316. + cfb->fb.var.xres_virtual = 320;
  72317. + cfb->fb.var.activate = FB_ACTIVATE_NOW;
  72318. +
  72319. + // change to 4bpp mode
  72320. + lcdcon = clps_readl(LCDCON);
  72321. + lcdcon |= LCDCON_GSMD | LCDCON_GSEN; //4bpp
  72322. + //lcdcon |= 5 << 19; //pixel prescale value (pixclock)
  72323. + //lcdcon |= 13 << 25; //AC prescale value
  72324. + clps_writel(lcdcon, LCDCON);
  72325. +
  72326. + //reenable LCD
  72327. + clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
  72328. +
  72329. + return 0;
  72330. +}
  72331. +
  72332. +int __init clps711xfb_init(void)
  72333. +{
  72334. + int err = -ENOMEM;
  72335. +
  72336. + cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
  72337. + if (!cfb)
  72338. + goto out;
  72339. +
  72340. + memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
  72341. + strcpy(cfb->fb.fix.id, "clps7111");
  72342. +
  72343. + cfb->currcon = -1;
  72344. + cfb->fb.screen_base = (void *)PAGE_OFFSET;
  72345. + cfb->fb.fix.smem_start = PAGE_OFFSET;
  72346. + cfb->fb.fix.smem_len = 0x14000;
  72347. + cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
  72348. +
  72349. + cfb->fb.fbops = &clps7111fb_ops;
  72350. + cfb->fb.changevar = NULL;
  72351. + cfb->fb.switch_con = clps7111fb_switch;
  72352. + cfb->fb.updatevar = clps7111fb_updatevar;
  72353. + cfb->fb.blank = clps7111fb_blank;
  72354. + cfb->fb.flags = FBINFO_FLAG_DEFAULT;
  72355. + cfb->fb.disp = (struct display *)(cfb + 1);
  72356. +
  72357. + clps711x_guess_lcd_params(&cfb->fb);
  72358. +
  72359. + if (machine_is_guidea07()) {
  72360. + clps711xfb_guidea07_init();
  72361. + }
  72362. +
  72363. + if (machine_is_fortunet()) {
  72364. + cfb->fb.fix.smem_len = 0x20000;
  72365. + }
  72366. +
  72367. + fb_alloc_cmap(&cfb->fb.cmap, CMAP_MAX_SIZE, 0);
  72368. +
  72369. + /* Register the /proc entries. */
  72370. + clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
  72371. + &proc_root);
  72372. + if (clps7111fb_backlight_proc_entry == NULL) {
  72373. + printk("Couldn't create the /proc entry for the backlight.\n");
  72374. + return -EINVAL;
  72375. + }
  72376. +
  72377. + clps7111fb_backlight_proc_entry->read_proc =
  72378. + &clps7111fb_proc_backlight_read;
  72379. + clps7111fb_backlight_proc_entry->write_proc =
  72380. + &clps7111fb_proc_backlight_write;
  72381. +
  72382. + /*
  72383. + * Power up the LCD
  72384. + */
  72385. + if (machine_is_p720t()) {
  72386. + PLD_LCDEN = PLD_LCDEN_EN;
  72387. + PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
  72388. + }
  72389. +
  72390. + if (machine_is_edb7211()) {
  72391. + /* Power up the LCD panel. */
  72392. + clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
  72393. +
  72394. + /* Delay for a little while. */
  72395. + udelay(100);
  72396. +
  72397. + /* Power up the LCD DC-DC converter. */
  72398. + clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
  72399. +
  72400. + /* Turn on the LCD backlight. */
  72401. + clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
  72402. + }
  72403. +
  72404. + clps7111fb_set_var(&cfb->fb.var, -1, &cfb->fb);
  72405. + err = register_framebuffer(&cfb->fb);
  72406. +
  72407. +out: return err;
  72408. +}
  72409. +
  72410. +static void __exit clps711xfb_exit(void)
  72411. +{
  72412. + unregister_framebuffer(&cfb->fb);
  72413. + kfree(cfb);
  72414. +
  72415. + /*
  72416. + * Power down the LCD
  72417. + */
  72418. + if (machine_is_p720t()) {
  72419. + PLD_LCDEN = 0;
  72420. + PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
  72421. + }
  72422. +}
  72423. +
  72424. +#ifdef MODULE
  72425. +module_init(clps711xfb_init);
  72426. +#endif
  72427. +module_exit(clps711xfb_exit);
  72428. +
  72429. +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  72430. +MODULE_DESCRIPTION("CLPS711x framebuffer driver");
  72431. +MODULE_LICENSE("GPL");
  72432. diff -urN linux-2.4.26/drivers/video/cyber2000fb.c linux-2.4.26-vrs1/drivers/video/cyber2000fb.c
  72433. --- linux-2.4.26/drivers/video/cyber2000fb.c 2002-08-03 01:39:45.000000000 +0100
  72434. +++ linux-2.4.26-vrs1/drivers/video/cyber2000fb.c 2004-01-14 21:32:27.000000000 +0000
  72435. @@ -1,7 +1,7 @@
  72436. /*
  72437. * linux/drivers/video/cyber2000fb.c
  72438. *
  72439. - * Copyright (C) 1998-2000 Russell King
  72440. + * Copyright (C) 1998-2002 Russell King
  72441. *
  72442. * MIPS and 50xx clock support
  72443. * Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
  72444. @@ -13,22 +13,28 @@
  72445. * it under the terms of the GNU General Public License version 2 as
  72446. * published by the Free Software Foundation.
  72447. *
  72448. - * Intergraphics CyberPro 2000, 2010 and 5000 frame buffer device
  72449. + * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
  72450. *
  72451. * Based on cyberfb.c.
  72452. *
  72453. - * Note that we now use the new fbcon fix, var and cmap scheme. We do still
  72454. - * have to check which console is the currently displayed one however, since
  72455. - * especially for the colourmap stuff. Once fbcon has been fully migrated,
  72456. - * we can kill the last 5 references to cfb->currcon.
  72457. + * Note that we now use the new fbcon fix, var and cmap scheme. We do
  72458. + * still have to check which console is the currently displayed one
  72459. + * however, especially for the colourmap stuff.
  72460. *
  72461. - * We also use the new hotplug PCI subsystem. I'm not sure if there are any
  72462. - * such cards, but I'm erring on the side of caution. We don't want to go
  72463. - * pop just because someone does have one.
  72464. + * We also use the new hotplug PCI subsystem. I'm not sure if there
  72465. + * are any such cards, but I'm erring on the side of caution. We don't
  72466. + * want to go pop just because someone does have one.
  72467. *
  72468. - * Note that this doesn't work fully in the case of multiple CyberPro cards
  72469. - * with grabbers. We currently can only attach to the first CyberPro card
  72470. - * found.
  72471. + * Note that this doesn't work fully in the case of multiple CyberPro
  72472. + * cards with grabbers. We currently can only attach to the first
  72473. + * CyberPro card found.
  72474. + *
  72475. + * When we're in truecolour mode, we power down the LUT RAM as a power
  72476. + * saving feature. Also, when we enter any of the powersaving modes
  72477. + * (except soft blanking) we power down the RAMDACs. This saves about
  72478. + * 1W, which is roughly 8% of the power consumption of a NetWinder
  72479. + * (which, incidentally, is about the same saving as a 2.5in hard disk
  72480. + * entering standby mode.)
  72481. */
  72482. #include <linux/config.h>
  72483. #include <linux/module.h>
  72484. @@ -55,20 +61,16 @@
  72485. #include <video/fbcon-cfb24.h>
  72486. #include <video/fbcon-cfb32.h>
  72487. -/*
  72488. - * Define this if you don't want RGB565, but RGB555 for 16bpp displays.
  72489. - */
  72490. -/*#define CFB16_IS_CFB15*/
  72491. -
  72492. #include "cyber2000fb.h"
  72493. struct cfb_info {
  72494. struct fb_info fb;
  72495. struct display_switch *dispsw;
  72496. + struct display *display;
  72497. struct pci_dev *dev;
  72498. unsigned char *region;
  72499. unsigned char *regs;
  72500. - signed int currcon;
  72501. + u_int id;
  72502. int func_use_count;
  72503. u_long ref_ps;
  72504. @@ -81,10 +83,16 @@
  72505. u8 red, green, blue;
  72506. } palette[NR_PALETTE];
  72507. + u_char mem_ctl0;
  72508. u_char mem_ctl1;
  72509. u_char mem_ctl2;
  72510. u_char mclk_mult;
  72511. u_char mclk_div;
  72512. + /*
  72513. + * RAMDAC control register is both of these or'ed together
  72514. + */
  72515. + u_char ramdac_ctrl;
  72516. + u_char ramdac_powerdown;
  72517. };
  72518. static char default_font_storage[40];
  72519. @@ -144,7 +152,7 @@
  72520. {
  72521. int count = 100000;
  72522. - while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
  72523. + while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
  72524. if (!count--) {
  72525. debug_printf("accel_wait timed out\n");
  72526. cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
  72527. @@ -154,24 +162,23 @@
  72528. }
  72529. }
  72530. -static void cyber2000_accel_setup(struct display *p)
  72531. +static void cyber2000_accel_setup(struct display *display)
  72532. {
  72533. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72534. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72535. - cfb->dispsw->setup(p);
  72536. + cfb->dispsw->setup(display);
  72537. }
  72538. static void
  72539. -cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
  72540. +cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
  72541. int height, int width)
  72542. {
  72543. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72544. - struct fb_var_screeninfo *var = &p->fb_info->var;
  72545. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72546. + struct fb_var_screeninfo *var = &display->var;
  72547. u_long src, dst;
  72548. - u_int fh, fw;
  72549. - int cmd = CO_CMD_L_PATTERN_FGCOL;
  72550. + u_int fh, fw, cmd = CO_CMD_L_PATTERN_FGCOL;
  72551. - fw = fontwidth(p);
  72552. + fw = fontwidth(display);
  72553. sx *= fw;
  72554. dx *= fw;
  72555. width *= fw;
  72556. @@ -183,7 +190,7 @@
  72557. cmd |= CO_CMD_L_INC_LEFT;
  72558. }
  72559. - fh = fontheight(p);
  72560. + fh = fontheight(display);
  72561. sy *= fh;
  72562. dy *= fh;
  72563. height *= fh;
  72564. @@ -199,227 +206,265 @@
  72565. dst = dx + dy * var->xres_virtual;
  72566. cyber2000_accel_wait(cfb);
  72567. - cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
  72568. - cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
  72569. - cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
  72570. -
  72571. - if (var->bits_per_pixel != 24) {
  72572. - cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
  72573. - cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
  72574. - } else {
  72575. - cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
  72576. - cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
  72577. - cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
  72578. + cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
  72579. + cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
  72580. + cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
  72581. +
  72582. + if (var->bits_per_pixel == 24) {
  72583. + cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
  72584. + dst *= 3;
  72585. + src *= 3;
  72586. }
  72587. - cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
  72588. - cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
  72589. - cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
  72590. + cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
  72591. + cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
  72592. + cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
  72593. + cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
  72594. + cyber2000fb_writew(CO_CMD_H_FGSRCMAP|CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
  72595. }
  72596. static void
  72597. -cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
  72598. - int height, int width)
  72599. +cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
  72600. + int sx, int height, int width)
  72601. {
  72602. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72603. - struct fb_var_screeninfo *var = &p->fb_info->var;
  72604. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72605. + struct fb_var_screeninfo *var = &display->var;
  72606. u_long dst;
  72607. u_int fw, fh;
  72608. - u32 bgx = attr_bgcol_ec(p, conp);
  72609. + u32 bgx = attr_bgcol_ec(display, conp);
  72610. - fw = fontwidth(p);
  72611. - fh = fontheight(p);
  72612. + fw = fontwidth(display);
  72613. + fh = fontheight(display);
  72614. dst = sx * fw + sy * var->xres_virtual * fh;
  72615. width = width * fw - 1;
  72616. height = height * fh - 1;
  72617. cyber2000_accel_wait(cfb);
  72618. - cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
  72619. - cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
  72620. - cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
  72621. - cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
  72622. + cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
  72623. + cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
  72624. + cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
  72625. - switch (var->bits_per_pixel) {
  72626. - case 15:
  72627. - case 16:
  72628. - bgx = ((u16 *)p->dispsw_data)[bgx];
  72629. - case 8:
  72630. - cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
  72631. - break;
  72632. -
  72633. - case 24:
  72634. - cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
  72635. + if (var->bits_per_pixel == 24) {
  72636. cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
  72637. - bgx = ((u32 *)p->dispsw_data)[bgx];
  72638. - break;
  72639. -
  72640. - case 32:
  72641. - bgx = ((u32 *)p->dispsw_data)[bgx];
  72642. - cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
  72643. - break;
  72644. + dst *= 3;
  72645. }
  72646. - cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
  72647. + if (var->bits_per_pixel == 16)
  72648. + bgx = ((u16 *)display->dispsw_data)[bgx];
  72649. + else if (var->bits_per_pixel >= 24)
  72650. + bgx = ((u32 *)display->dispsw_data)[bgx];
  72651. +
  72652. + cyber2000fb_writel(bgx, CO_REG_FGCOLOUR, cfb);
  72653. + cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
  72654. + cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
  72655. cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
  72656. - cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
  72657. + cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
  72658. }
  72659. static void
  72660. -cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c,
  72661. +cyber2000_accel_putc(struct vc_data *conp, struct display *display, int c,
  72662. int yy, int xx)
  72663. {
  72664. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72665. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72666. cyber2000_accel_wait(cfb);
  72667. - cfb->dispsw->putc(conp, p, c, yy, xx);
  72668. + cfb->dispsw->putc(conp, display, c, yy, xx);
  72669. }
  72670. static void
  72671. -cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
  72672. +cyber2000_accel_putcs(struct vc_data *conp, struct display *display,
  72673. const unsigned short *s, int count, int yy, int xx)
  72674. {
  72675. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72676. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72677. cyber2000_accel_wait(cfb);
  72678. - cfb->dispsw->putcs(conp, p, s, count, yy, xx);
  72679. + cfb->dispsw->putcs(conp, display, s, count, yy, xx);
  72680. }
  72681. -static void cyber2000_accel_revc(struct display *p, int xx, int yy)
  72682. +static void cyber2000_accel_revc(struct display *display, int xx, int yy)
  72683. {
  72684. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72685. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72686. cyber2000_accel_wait(cfb);
  72687. - cfb->dispsw->revc(p, xx, yy);
  72688. + cfb->dispsw->revc(display, xx, yy);
  72689. }
  72690. static void
  72691. -cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p,
  72692. +cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
  72693. int bottom_only)
  72694. {
  72695. - struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
  72696. + struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
  72697. - cfb->dispsw->clear_margins(conp, p, bottom_only);
  72698. + cfb->dispsw->clear_margins(conp, display, bottom_only);
  72699. }
  72700. static struct display_switch fbcon_cyber_accel = {
  72701. - setup: cyber2000_accel_setup,
  72702. - bmove: cyber2000_accel_bmove,
  72703. - clear: cyber2000_accel_clear,
  72704. - putc: cyber2000_accel_putc,
  72705. - putcs: cyber2000_accel_putcs,
  72706. - revc: cyber2000_accel_revc,
  72707. - clear_margins: cyber2000_accel_clear_margins,
  72708. - fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16)
  72709. + .setup = cyber2000_accel_setup,
  72710. + .bmove = cyber2000_accel_bmove,
  72711. + .clear = cyber2000_accel_clear,
  72712. + .putc = cyber2000_accel_putc,
  72713. + .putcs = cyber2000_accel_putcs,
  72714. + .revc = cyber2000_accel_revc,
  72715. + .clear_margins = cyber2000_accel_clear_margins,
  72716. + .fontwidthmask = FONTWIDTH(8)|FONTWIDTH(16)
  72717. };
  72718. +static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
  72719. +{
  72720. + u_int mask = (1 << bf->length) - 1;
  72721. +
  72722. + return (val >> (16 - bf->length) & mask) << bf->offset;
  72723. +}
  72724. +
  72725. /*
  72726. * Set a single color register. Return != 0 for invalid regno.
  72727. */
  72728. static int
  72729. -cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  72730. - u_int transp, struct fb_info *info)
  72731. +cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  72732. + u_int transp, struct fb_info *info)
  72733. {
  72734. struct cfb_info *cfb = (struct cfb_info *)info;
  72735. + struct fb_var_screeninfo *var = &cfb->display->var;
  72736. + u32 pseudo_val;
  72737. + int ret = 1;
  72738. - u_int alpha = transp ^ 0xFFFF;
  72739. -
  72740. - if (regno >= NR_PALETTE)
  72741. + switch (cfb->fb.fix.visual) {
  72742. + default:
  72743. return 1;
  72744. - red >>= 8;
  72745. - green >>= 8;
  72746. - blue >>= 8;
  72747. - alpha >>= 8;
  72748. -
  72749. - cfb->palette[regno].red = red;
  72750. - cfb->palette[regno].green = green;
  72751. - cfb->palette[regno].blue = blue;
  72752. -
  72753. - switch (cfb->fb.var.bits_per_pixel) {
  72754. #ifdef FBCON_HAS_CFB8
  72755. - case 8:
  72756. + /*
  72757. + * Pseudocolour:
  72758. + * 8 8
  72759. + * pixel --/--+--/--> red lut --> red dac
  72760. + * | 8
  72761. + * +--/--> green lut --> green dac
  72762. + * | 8
  72763. + * +--/--> blue lut --> blue dac
  72764. + */
  72765. + case FB_VISUAL_PSEUDOCOLOR:
  72766. + if (regno >= NR_PALETTE)
  72767. + return 1;
  72768. +
  72769. + red >>= 8;
  72770. + green >>= 8;
  72771. + blue >>= 8;
  72772. +
  72773. + cfb->palette[regno].red = red;
  72774. + cfb->palette[regno].green = green;
  72775. + cfb->palette[regno].blue = blue;
  72776. +
  72777. cyber2000fb_writeb(regno, 0x3c8, cfb);
  72778. - cyber2000fb_writeb(red, 0x3c9, cfb);
  72779. + cyber2000fb_writeb(red, 0x3c9, cfb);
  72780. cyber2000fb_writeb(green, 0x3c9, cfb);
  72781. - cyber2000fb_writeb(blue, 0x3c9, cfb);
  72782. - break;
  72783. + cyber2000fb_writeb(blue, 0x3c9, cfb);
  72784. + return 0;
  72785. #endif
  72786. -#ifdef FBCON_HAS_CFB16
  72787. - case 16:
  72788. -#ifndef CFB16_IS_CFB15
  72789. - if (regno < 64) {
  72790. - /* write green */
  72791. + /*
  72792. + * Direct colour:
  72793. + * n rl
  72794. + * pixel --/--+--/--> red lut --> red dac
  72795. + * | gl
  72796. + * +--/--> green lut --> green dac
  72797. + * | bl
  72798. + * +--/--> blue lut --> blue dac
  72799. + * n = bpp, rl = red length, gl = green length, bl = blue length
  72800. + */
  72801. + case FB_VISUAL_DIRECTCOLOR:
  72802. + red >>= 8;
  72803. + green >>= 8;
  72804. + blue >>= 8;
  72805. +
  72806. + if (var->green.length == 6 && regno < 64) {
  72807. + cfb->palette[regno << 2].green = green;
  72808. +
  72809. + /*
  72810. + * The 6 bits of the green component are applied
  72811. + * to the high 6 bits of the LUT.
  72812. + */
  72813. cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
  72814. cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
  72815. cyber2000fb_writeb(green, 0x3c9, cfb);
  72816. cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
  72817. +
  72818. + green = cfb->palette[regno << 3].green;
  72819. +
  72820. + ret = 0;
  72821. }
  72822. - if (regno < 32) {
  72823. - /* write red,blue */
  72824. + if (var->green.length >= 5 && regno < 32) {
  72825. + cfb->palette[regno << 3].red = red;
  72826. + cfb->palette[regno << 3].green = green;
  72827. + cfb->palette[regno << 3].blue = blue;
  72828. +
  72829. + /*
  72830. + * The 5 bits of each colour component are
  72831. + * applied to the high 5 bits of the LUT.
  72832. + */
  72833. cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
  72834. cyber2000fb_writeb(red, 0x3c9, cfb);
  72835. - cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
  72836. + cyber2000fb_writeb(green, 0x3c9, cfb);
  72837. cyber2000fb_writeb(blue, 0x3c9, cfb);
  72838. + ret = 0;
  72839. }
  72840. - if (regno < 16)
  72841. - ((u16 *)cfb->fb.pseudo_palette)[regno] =
  72842. - ((red << 8) & 0xf800) |
  72843. - ((green << 3) & 0x07e0) |
  72844. - ((blue >> 3));
  72845. - break;
  72846. -#endif
  72847. -
  72848. - case 15:
  72849. - if (regno < 32) {
  72850. - cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
  72851. + if (var->green.length == 4 && regno < 16) {
  72852. + cfb->palette[regno << 4].red = red;
  72853. + cfb->palette[regno << 4].green = green;
  72854. + cfb->palette[regno << 4].blue = blue;
  72855. +
  72856. + /*
  72857. + * The 5 bits of each colour component are
  72858. + * applied to the high 5 bits of the LUT.
  72859. + */
  72860. + cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
  72861. cyber2000fb_writeb(red, 0x3c9, cfb);
  72862. cyber2000fb_writeb(green, 0x3c9, cfb);
  72863. cyber2000fb_writeb(blue, 0x3c9, cfb);
  72864. + ret = 0;
  72865. }
  72866. - if (regno < 16)
  72867. - ((u16 *)cfb->fb.pseudo_palette)[regno] =
  72868. - ((red << 7) & 0x7c00) |
  72869. - ((green << 2) & 0x03e0) |
  72870. - ((blue >> 3));
  72871. - break;
  72872. -
  72873. -#endif
  72874. -
  72875. -#ifdef FBCON_HAS_CFB24
  72876. - case 24:
  72877. - cyber2000fb_writeb(regno, 0x3c8, cfb);
  72878. - cyber2000fb_writeb(red, 0x3c9, cfb);
  72879. - cyber2000fb_writeb(green, 0x3c9, cfb);
  72880. - cyber2000fb_writeb(blue, 0x3c9, cfb);
  72881. - if (regno < 16)
  72882. - ((u32 *)cfb->fb.pseudo_palette)[regno] =
  72883. - (red << 16) | (green << 8) | blue;
  72884. + /*
  72885. + * Since this is only used for the first 16 colours, we
  72886. + * don't have to care about overflowing for regno >= 32
  72887. + */
  72888. + pseudo_val = regno << var->red.offset |
  72889. + regno << var->green.offset |
  72890. + regno << var->blue.offset;
  72891. break;
  72892. -#endif
  72893. -
  72894. -#ifdef FBCON_HAS_CFB32
  72895. - case 32:
  72896. - cyber2000fb_writeb(regno, 0x3c8, cfb);
  72897. - cyber2000fb_writeb(red, 0x3c9, cfb);
  72898. - cyber2000fb_writeb(green, 0x3c9, cfb);
  72899. - cyber2000fb_writeb(blue, 0x3c9, cfb);
  72900. - if (regno < 16)
  72901. - ((u32 *)cfb->fb.pseudo_palette)[regno] =
  72902. - (alpha << 24) | (red << 16) | (green << 8) | blue;
  72903. + /*
  72904. + * True colour:
  72905. + * n rl
  72906. + * pixel --/--+--/--> red dac
  72907. + * | gl
  72908. + * +--/--> green dac
  72909. + * | bl
  72910. + * +--/--> blue dac
  72911. + * n = bpp, rl = red length, gl = green length, bl = blue length
  72912. + */
  72913. + case FB_VISUAL_TRUECOLOR:
  72914. + pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
  72915. + pseudo_val |= convert_bitfield(red, &var->red);
  72916. + pseudo_val |= convert_bitfield(green, &var->green);
  72917. + pseudo_val |= convert_bitfield(blue, &var->blue);
  72918. break;
  72919. -#endif
  72920. + }
  72921. - default:
  72922. - return 1;
  72923. + /*
  72924. + * Now set our pseudo palette for the CFB16/24/32 drivers.
  72925. + */
  72926. + if (regno < 16) {
  72927. + if (var->bits_per_pixel == 16)
  72928. + ((u16 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
  72929. + else
  72930. + ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
  72931. + ret = 0;
  72932. }
  72933. - return 0;
  72934. + return ret;
  72935. }
  72936. struct par_info {
  72937. @@ -428,8 +473,8 @@
  72938. */
  72939. u_char clock_mult;
  72940. u_char clock_div;
  72941. - u_char visualid;
  72942. - u_char pixformat;
  72943. + u_char extseqmisc;
  72944. + u_char co_pixfmt;
  72945. u_char crtc_ofl;
  72946. u_char crtc[19];
  72947. u_int width;
  72948. @@ -439,8 +484,7 @@
  72949. /*
  72950. * Other
  72951. */
  72952. - u_char palette_ctrl;
  72953. - u_int vmode;
  72954. + u_char ramdac;
  72955. };
  72956. static const u_char crtc_idx[] = {
  72957. @@ -449,6 +493,18 @@
  72958. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
  72959. };
  72960. +static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
  72961. +{
  72962. + unsigned int i;
  72963. + unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
  72964. +
  72965. + cyber2000fb_writeb(0x56, 0x3ce, cfb);
  72966. + i = cyber2000fb_readb(0x3cf, cfb);
  72967. + cyber2000fb_writeb(i | 4, 0x3cf, cfb);
  72968. + cyber2000fb_writeb(val, 0x3c6, cfb);
  72969. + cyber2000fb_writeb(i, 0x3cf, cfb);
  72970. +}
  72971. +
  72972. static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
  72973. {
  72974. u_int i;
  72975. @@ -480,7 +536,7 @@
  72976. for (i = 0x0a; i < 0x10; i++)
  72977. cyber2000_crtcw(i, 0, cfb);
  72978. - cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
  72979. + cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
  72980. cyber2000_grphw(0x00, 0x00, cfb);
  72981. cyber2000_grphw(0x01, 0x00, cfb);
  72982. cyber2000_grphw(0x02, 0x00, cfb);
  72983. @@ -501,30 +557,17 @@
  72984. cyber2000_attrw(0x13, 0x00, cfb);
  72985. cyber2000_attrw(0x14, 0x00, cfb);
  72986. - /* woody: set the interlaced bit... */
  72987. - /* FIXME: what about doublescan? */
  72988. - cyber2000fb_writeb(0x11, 0x3ce, cfb);
  72989. - i = cyber2000fb_readb(0x3cf, cfb);
  72990. - if (hw->vmode == FB_VMODE_INTERLACED)
  72991. - i |= 0x20;
  72992. - else
  72993. - i &= ~0x20;
  72994. - cyber2000fb_writeb(i, 0x3cf, cfb);
  72995. -
  72996. /* PLL registers */
  72997. - cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
  72998. - cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
  72999. - cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
  73000. - cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
  73001. + cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
  73002. + cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
  73003. + cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
  73004. + cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
  73005. cyber2000_grphw(0x90, 0x01, cfb);
  73006. cyber2000_grphw(0xb9, 0x80, cfb);
  73007. cyber2000_grphw(0xb9, 0x00, cfb);
  73008. - cyber2000fb_writeb(0x56, 0x3ce, cfb);
  73009. - i = cyber2000fb_readb(0x3cf, cfb);
  73010. - cyber2000fb_writeb(i | 4, 0x3cf, cfb);
  73011. - cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
  73012. - cyber2000fb_writeb(i, 0x3cf, cfb);
  73013. + cfb->ramdac_ctrl = hw->ramdac;
  73014. + cyber2000fb_write_ramdac_ctrl(cfb);
  73015. cyber2000fb_writeb(0x20, 0x3c0, cfb);
  73016. cyber2000fb_writeb(0xff, 0x3c6, cfb);
  73017. @@ -532,31 +575,32 @@
  73018. cyber2000_grphw(0x14, hw->fetch, cfb);
  73019. cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
  73020. ((hw->pitch >> 4) & 0x30), cfb);
  73021. - cyber2000_grphw(0x77, hw->visualid, cfb);
  73022. + cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
  73023. - /* make sure we stay in linear mode */
  73024. - cyber2000_grphw(0x33, 0x0d, cfb);
  73025. +// cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
  73026. +// EXT_BIU_MISC_COP_ENABLE |
  73027. +// EXT_BIU_MISC_COP_BFC, cfb);
  73028. /*
  73029. * Set up accelerator registers
  73030. */
  73031. cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
  73032. cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
  73033. - cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
  73034. + cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
  73035. }
  73036. static inline int
  73037. cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
  73038. {
  73039. - u_int base;
  73040. + u_int base = var->yoffset * var->xres_virtual + var->xoffset;
  73041. - base = var->yoffset * var->xres_virtual + var->xoffset;
  73042. + base *= var->bits_per_pixel;
  73043. - /* have to be careful, because bits_per_pixel might be 15
  73044. - in this version of the driver -- dok@directfb.org 2002/06/13 */
  73045. - base *= (var->bits_per_pixel + 7) >> 3;
  73046. -
  73047. - base >>= 2;
  73048. + /*
  73049. + * Convert to bytes and shift two extra bits because DAC
  73050. + * can only start on 4 byte aligned data.
  73051. + */
  73052. + base >>= 5;
  73053. if (base >= 1 << 20)
  73054. return -EINVAL;
  73055. @@ -576,27 +620,20 @@
  73056. struct fb_info *info)
  73057. {
  73058. struct cfb_info *cfb = (struct cfb_info *)info;
  73059. - struct fb_cmap *dcmap = &fb_display[con].cmap;
  73060. + struct display *display = fb_display + con;
  73061. + struct fb_cmap *dcmap = &display->cmap;
  73062. int err = 0;
  73063. /* no colormap allocated? */
  73064. - if (!dcmap->len) {
  73065. - int size;
  73066. -
  73067. - if (cfb->fb.var.bits_per_pixel == 16)
  73068. - size = 32;
  73069. - else
  73070. - size = 256;
  73071. -
  73072. - err = fb_alloc_cmap(dcmap, size, 0);
  73073. - }
  73074. + if (!dcmap->len)
  73075. + err = fb_alloc_cmap(dcmap, 256, 0);
  73076. /*
  73077. * we should be able to remove this test once fbcon has been
  73078. * "improved" --rmk
  73079. */
  73080. - if (!err && con == cfb->currcon) {
  73081. - err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb);
  73082. + if (!err && display == cfb->display) {
  73083. + err = fb_set_cmap(cmap, kspc, cyber2000fb_setcolreg, &cfb->fb);
  73084. dcmap = &cfb->fb.cmap;
  73085. }
  73086. @@ -672,8 +709,9 @@
  73087. hw->crtc[16] = Vblankend;
  73088. hw->crtc[18] = 0xff;
  73089. - /* overflow - graphics reg 0x11 */
  73090. - /* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
  73091. + /*
  73092. + * overflow - graphics reg 0x11
  73093. + * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
  73094. * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
  73095. */
  73096. hw->crtc_ofl =
  73097. @@ -681,7 +719,12 @@
  73098. BIT(Vdispend, 10, 0x01, 1) |
  73099. BIT(Vsyncstart, 10, 0x01, 2) |
  73100. BIT(Vblankstart,10, 0x01, 3) |
  73101. - 1 << 4;
  73102. + EXT_CRT_VRTOFL_LINECOMP10;
  73103. +
  73104. + /* woody: set the interlaced bit... */
  73105. + /* FIXME: what about doublescan? */
  73106. + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
  73107. + hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
  73108. return 0;
  73109. }
  73110. @@ -787,7 +830,7 @@
  73111. vco = ref_ps * best_div1 / best_mult;
  73112. if ((ref_ps == 40690) && (vco < 5556))
  73113. /* Set VFSEL when VCO > 180MHz (5.556 ps). */
  73114. - hw->clock_div |= DCLK_DIV_VFSEL;
  73115. + hw->clock_div |= EXT_DCLK_DIV_VFSEL;
  73116. return 0;
  73117. }
  73118. @@ -801,58 +844,131 @@
  73119. cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,
  73120. struct par_info *hw)
  73121. {
  73122. + unsigned int mem;
  73123. int err;
  73124. hw->width = var->xres_virtual;
  73125. - hw->palette_ctrl = 0x06;
  73126. - hw->vmode = var->vmode;
  73127. + hw->ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
  73128. +
  73129. + var->transp.msb_right = 0;
  73130. + var->red.msb_right = 0;
  73131. + var->green.msb_right = 0;
  73132. + var->blue.msb_right = 0;
  73133. switch (var->bits_per_pixel) {
  73134. #ifdef FBCON_HAS_CFB8
  73135. case 8: /* PSEUDOCOLOUR, 256 */
  73136. - hw->pixformat = PIXFORMAT_8BPP;
  73137. - hw->visualid = VISUALID_256;
  73138. + hw->co_pixfmt = CO_PIXFMT_8BPP;
  73139. hw->pitch = hw->width >> 3;
  73140. + hw->extseqmisc = EXT_SEQ_MISC_8;
  73141. +
  73142. + var->transp.offset = 0;
  73143. + var->transp.length = 0;
  73144. + var->red.offset = 0;
  73145. + var->red.length = 8;
  73146. + var->green.offset = 0;
  73147. + var->green.length = 8;
  73148. + var->blue.offset = 0;
  73149. + var->blue.length = 8;
  73150. break;
  73151. #endif
  73152. #ifdef FBCON_HAS_CFB16
  73153. - case 16:/* DIRECTCOLOUR, 64k */
  73154. -#ifndef CFB16_IS_CFB15
  73155. - hw->pixformat = PIXFORMAT_16BPP;
  73156. - hw->visualid = VISUALID_64K;
  73157. - hw->pitch = hw->width >> 2;
  73158. - hw->palette_ctrl |= 0x10;
  73159. - break;
  73160. -#endif
  73161. - case 15:/* DIRECTCOLOUR, 32k */
  73162. - hw->pixformat = PIXFORMAT_16BPP;
  73163. - hw->visualid = VISUALID_32K;
  73164. + case 16:/* DIRECTCOLOUR, 64k or 32k */
  73165. + hw->co_pixfmt = CO_PIXFMT_16BPP;
  73166. hw->pitch = hw->width >> 2;
  73167. - hw->palette_ctrl |= 0x10;
  73168. - break;
  73169. + switch (var->green.length) {
  73170. + case 6: /* RGB565, 64k */
  73171. + hw->extseqmisc = EXT_SEQ_MISC_16_RGB565;
  73172. +
  73173. + var->transp.offset = 0;
  73174. + var->transp.length = 0;
  73175. + var->red.offset = 11;
  73176. + var->red.length = 5;
  73177. + var->green.offset = 5;
  73178. + var->green.length = 6;
  73179. + var->blue.offset = 0;
  73180. + var->blue.length = 5;
  73181. + break;
  73182. +
  73183. + default:
  73184. + case 5: /* RGB555, 32k */
  73185. + hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
  73186. +
  73187. + var->transp.offset = 0;
  73188. + var->transp.length = 0;
  73189. + var->red.offset = 10;
  73190. + var->red.length = 5;
  73191. + var->green.offset = 5;
  73192. + var->green.length = 5;
  73193. + var->blue.offset = 0;
  73194. + var->blue.length = 5;
  73195. + break;
  73196. +
  73197. + case 4: /* RGB444, 4k + transparency? */
  73198. + hw->extseqmisc = EXT_SEQ_MISC_16_RGB444;
  73199. +
  73200. + var->transp.offset = 12;
  73201. + var->transp.length = 4;
  73202. + var->red.offset = 8;
  73203. + var->red.length = 4;
  73204. + var->green.offset = 4;
  73205. + var->green.length = 4;
  73206. + var->blue.offset = 0;
  73207. + var->blue.length = 4;
  73208. + break;
  73209. + }
  73210. + break;
  73211. #endif
  73212. #ifdef FBCON_HAS_CFB24
  73213. case 24:/* TRUECOLOUR, 16m */
  73214. - hw->pixformat = PIXFORMAT_24BPP;
  73215. - hw->visualid = VISUALID_16M;
  73216. + hw->co_pixfmt = CO_PIXFMT_24BPP;
  73217. hw->width *= 3;
  73218. hw->pitch = hw->width >> 3;
  73219. - hw->palette_ctrl |= 0x10;
  73220. + hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
  73221. + hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
  73222. +
  73223. + var->transp.offset = 0;
  73224. + var->transp.length = 0;
  73225. + var->red.offset = 16;
  73226. + var->red.length = 8;
  73227. + var->green.offset = 8;
  73228. + var->green.length = 8;
  73229. + var->blue.offset = 0;
  73230. + var->blue.length = 8;
  73231. break;
  73232. #endif
  73233. #ifdef FBCON_HAS_CFB32
  73234. case 32:/* TRUECOLOUR, 16m */
  73235. - hw->pixformat = PIXFORMAT_32BPP;
  73236. - hw->visualid = VISUALID_16M_32;
  73237. + hw->co_pixfmt = CO_PIXFMT_32BPP;
  73238. hw->pitch = hw->width >> 1;
  73239. - hw->palette_ctrl |= 0x10;
  73240. + hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
  73241. + hw->extseqmisc = EXT_SEQ_MISC_32;
  73242. +
  73243. + var->transp.offset = 24;
  73244. + var->transp.length = 8;
  73245. + var->red.offset = 16;
  73246. + var->red.length = 8;
  73247. + var->green.offset = 8;
  73248. + var->green.length = 8;
  73249. + var->blue.offset = 0;
  73250. + var->blue.length = 8;
  73251. break;
  73252. #endif
  73253. default:
  73254. return -EINVAL;
  73255. }
  73256. + mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
  73257. + if (mem > cfb->fb.fix.smem_len)
  73258. + var->yres_virtual = cfb->fb.fix.smem_len * 8 /
  73259. + (var->bits_per_pixel * var->xres_virtual);
  73260. +
  73261. + if (var->yres > var->yres_virtual)
  73262. + var->yres = var->yres_virtual;
  73263. + if (var->xres > var->xres_virtual)
  73264. + var->xres = var->xres_virtual;
  73265. +
  73266. err = cyber2000fb_decode_clock(hw, cfb, var);
  73267. if (err)
  73268. return err;
  73269. @@ -880,7 +996,7 @@
  73270. struct cfb_info *cfb = (struct cfb_info *)info;
  73271. struct display *display;
  73272. struct par_info hw;
  73273. - int err, chgvar = 0;
  73274. + int err, chgvar;
  73275. /*
  73276. * CONUPDATE and SMOOTH_XPAN are equal. However,
  73277. @@ -888,11 +1004,11 @@
  73278. */
  73279. if (var->vmode & FB_VMODE_CONUPDATE) {
  73280. var->vmode |= FB_VMODE_YWRAP;
  73281. - var->xoffset = cfb->fb.var.xoffset;
  73282. - var->yoffset = cfb->fb.var.yoffset;
  73283. + var->xoffset = cfb->display->var.xoffset;
  73284. + var->yoffset = cfb->display->var.yoffset;
  73285. }
  73286. - err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
  73287. + err = cyber2000fb_decode_var(var, cfb, &hw);
  73288. if (err)
  73289. return err;
  73290. @@ -902,105 +1018,61 @@
  73291. if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
  73292. return -EINVAL;
  73293. - if (cfb->fb.var.xres != var->xres)
  73294. - chgvar = 1;
  73295. - if (cfb->fb.var.yres != var->yres)
  73296. - chgvar = 1;
  73297. - if (cfb->fb.var.xres_virtual != var->xres_virtual)
  73298. - chgvar = 1;
  73299. - if (cfb->fb.var.yres_virtual != var->yres_virtual)
  73300. - chgvar = 1;
  73301. - if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
  73302. - chgvar = 1;
  73303. -
  73304. if (con < 0) {
  73305. display = cfb->fb.disp;
  73306. - chgvar = 0;
  73307. } else {
  73308. display = fb_display + con;
  73309. }
  73310. - var->red.msb_right = 0;
  73311. - var->green.msb_right = 0;
  73312. - var->blue.msb_right = 0;
  73313. + chgvar = cfb->fb.var.xres != var->xres ||
  73314. + cfb->fb.var.yres != var->yres ||
  73315. + cfb->fb.var.xres_virtual != var->xres_virtual ||
  73316. + cfb->fb.var.yres_virtual != var->yres_virtual ||
  73317. + cfb->fb.var.bits_per_pixel != var->bits_per_pixel;
  73318. +
  73319. + if (memcmp(&cfb->fb.var.red, &var->red, sizeof(var->red)) ||
  73320. + memcmp(&cfb->fb.var.green, &var->green, sizeof(var->green)) ||
  73321. + memcmp(&cfb->fb.var.blue, &var->blue, sizeof(var->blue)))
  73322. + chgvar = 1;
  73323. +
  73324. + if (con < 0)
  73325. + chgvar = 0;
  73326. +
  73327. + /*
  73328. + * If we are setting all the virtual consoles, also set the
  73329. + * defaults used to create new consoles.
  73330. + */
  73331. + err = var->activate;
  73332. + var->activate = FB_ACTIVATE_NOW;
  73333. + if (err & FB_ACTIVATE_ALL)
  73334. + cfb->fb.disp->var = *var;
  73335. +
  73336. + cfb->fb.var = *var;
  73337. + cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
  73338. switch (var->bits_per_pixel) {
  73339. #ifdef FBCON_HAS_CFB8
  73340. case 8: /* PSEUDOCOLOUR, 256 */
  73341. - var->red.offset = 0;
  73342. - var->red.length = 8;
  73343. - var->green.offset = 0;
  73344. - var->green.length = 8;
  73345. - var->blue.offset = 0;
  73346. - var->blue.length = 8;
  73347. -
  73348. - cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  73349. cfb->dispsw = &fbcon_cfb8;
  73350. display->dispsw_data = NULL;
  73351. - display->next_line = var->xres_virtual;
  73352. break;
  73353. #endif
  73354. #ifdef FBCON_HAS_CFB16
  73355. - case 16:/* DIRECTCOLOUR, 64k */
  73356. -#ifndef CFB16_IS_CFB15
  73357. - var->red.offset = 11;
  73358. - var->red.length = 5;
  73359. - var->green.offset = 5;
  73360. - var->green.length = 6;
  73361. - var->blue.offset = 0;
  73362. - var->blue.length = 5;
  73363. -
  73364. - cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
  73365. - cfb->dispsw = &fbcon_cfb16;
  73366. - display->dispsw_data = cfb->fb.pseudo_palette;
  73367. - display->next_line = var->xres_virtual * 2;
  73368. - break;
  73369. -#endif
  73370. - case 15:/* DIRECTCOLOUR, 32k */
  73371. - var->bits_per_pixel = 15;
  73372. - var->red.offset = 10;
  73373. - var->red.length = 5;
  73374. - var->green.offset = 5;
  73375. - var->green.length = 5;
  73376. - var->blue.offset = 0;
  73377. - var->blue.length = 5;
  73378. -
  73379. - cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
  73380. + case 16:/* DIRECTCOLOUR */
  73381. cfb->dispsw = &fbcon_cfb16;
  73382. display->dispsw_data = cfb->fb.pseudo_palette;
  73383. - display->next_line = var->xres_virtual * 2;
  73384. break;
  73385. #endif
  73386. #ifdef FBCON_HAS_CFB24
  73387. case 24:/* TRUECOLOUR, 16m */
  73388. - var->red.offset = 16;
  73389. - var->red.length = 8;
  73390. - var->green.offset = 8;
  73391. - var->green.length = 8;
  73392. - var->blue.offset = 0;
  73393. - var->blue.length = 8;
  73394. -
  73395. - cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
  73396. cfb->dispsw = &fbcon_cfb24;
  73397. display->dispsw_data = cfb->fb.pseudo_palette;
  73398. - display->next_line = var->xres_virtual * 3;
  73399. break;
  73400. #endif
  73401. #ifdef FBCON_HAS_CFB32
  73402. case 32:/* TRUECOLOUR, 16m */
  73403. - var->transp.offset = 24;
  73404. - var->transp.length = 8;
  73405. - var->red.offset = 16;
  73406. - var->red.length = 8;
  73407. - var->green.offset = 8;
  73408. - var->green.length = 8;
  73409. - var->blue.offset = 0;
  73410. - var->blue.length = 8;
  73411. -
  73412. - cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
  73413. cfb->dispsw = &fbcon_cfb32;
  73414. display->dispsw_data = cfb->fb.pseudo_palette;
  73415. - display->next_line = var->xres_virtual * 4;
  73416. break;
  73417. #endif
  73418. default:/* in theory this should never happen */
  73419. @@ -1010,15 +1082,27 @@
  73420. break;
  73421. }
  73422. + /*
  73423. + * 8bpp displays are always pseudo colour.
  73424. + * 16bpp and above are direct colour or true colour, depending
  73425. + * on whether the RAMDAC palettes are bypassed. (Direct colour
  73426. + * has palettes, true colour does not.)
  73427. + */
  73428. + if (var->bits_per_pixel == 8)
  73429. + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  73430. + else if (hw.ramdac & RAMDAC_BYPASS)
  73431. + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
  73432. + else
  73433. + cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
  73434. +
  73435. if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy)
  73436. display->dispsw = &fbcon_cyber_accel;
  73437. else
  73438. display->dispsw = cfb->dispsw;
  73439. - cfb->fb.fix.line_length = display->next_line;
  73440. -
  73441. display->screen_base = cfb->fb.screen_base;
  73442. display->line_length = cfb->fb.fix.line_length;
  73443. + display->next_line = cfb->fb.fix.line_length;
  73444. display->visual = cfb->fb.fix.visual;
  73445. display->type = cfb->fb.fix.type;
  73446. display->type_aux = cfb->fb.fix.type_aux;
  73447. @@ -1026,31 +1110,15 @@
  73448. display->ywrapstep = cfb->fb.fix.ywrapstep;
  73449. display->can_soft_blank = 1;
  73450. display->inverse = 0;
  73451. + display->var = *var;
  73452. - cfb->fb.var = *var;
  73453. - cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
  73454. -
  73455. - /*
  73456. - * Update the old var. The fbcon drivers still use this.
  73457. - * Once they are using cfb->fb.var, this can be dropped.
  73458. - * --rmk
  73459. - */
  73460. - display->var = cfb->fb.var;
  73461. -
  73462. - /*
  73463. - * If we are setting all the virtual consoles, also set the
  73464. - * defaults used to create new consoles.
  73465. - */
  73466. - if (var->activate & FB_ACTIVATE_ALL)
  73467. - cfb->fb.disp->var = cfb->fb.var;
  73468. + cyber2000fb_set_timing(cfb, &hw);
  73469. + cyber2000fb_update_start(cfb, var);
  73470. + fb_set_cmap(&cfb->fb.cmap, 1, cyber2000fb_setcolreg, &cfb->fb);
  73471. - if (chgvar && info && cfb->fb.changevar)
  73472. + if (chgvar && cfb->fb.changevar)
  73473. cfb->fb.changevar(con);
  73474. - cyber2000fb_update_start(cfb, var);
  73475. - cyber2000fb_set_timing(cfb, &hw);
  73476. - fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb);
  73477. -
  73478. return 0;
  73479. }
  73480. @@ -1072,18 +1140,18 @@
  73481. if (var->xoffset > (var->xres_virtual - var->xres))
  73482. return -EINVAL;
  73483. - if (y_bottom > cfb->fb.var.yres_virtual)
  73484. + if (y_bottom > cfb->display->var.yres_virtual)
  73485. return -EINVAL;
  73486. if (cyber2000fb_update_start(cfb, var))
  73487. return -EINVAL;
  73488. - cfb->fb.var.xoffset = var->xoffset;
  73489. - cfb->fb.var.yoffset = var->yoffset;
  73490. + cfb->display->var.xoffset = var->xoffset;
  73491. + cfb->display->var.yoffset = var->yoffset;
  73492. if (var->vmode & FB_VMODE_YWRAP) {
  73493. - cfb->fb.var.vmode |= FB_VMODE_YWRAP;
  73494. + cfb->display->var.vmode |= FB_VMODE_YWRAP;
  73495. } else {
  73496. - cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
  73497. + cfb->display->var.vmode &= ~FB_VMODE_YWRAP;
  73498. }
  73499. return 0;
  73500. @@ -1106,22 +1174,18 @@
  73501. static int cyber2000fb_switch(int con, struct fb_info *info)
  73502. {
  73503. struct cfb_info *cfb = (struct cfb_info *)info;
  73504. - struct display *disp;
  73505. + struct display *display = cfb->display;
  73506. struct fb_cmap *cmap;
  73507. - if (cfb->currcon >= 0) {
  73508. - disp = fb_display + cfb->currcon;
  73509. -
  73510. + if (display) {
  73511. /*
  73512. * Save the old colormap and video mode.
  73513. */
  73514. - disp->var = cfb->fb.var;
  73515. - if (disp->cmap.len)
  73516. - fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
  73517. + if (display->cmap.len)
  73518. + fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);
  73519. }
  73520. - cfb->currcon = con;
  73521. - disp = fb_display + con;
  73522. + cfb->display = display = fb_display + con;
  73523. /*
  73524. * Install the new colormap and change the video mode. By default,
  73525. @@ -1132,73 +1196,88 @@
  73526. * depth of the new video mode. For now, we leave it at its
  73527. * default 256 entry.
  73528. */
  73529. - if (disp->cmap.len)
  73530. - cmap = &disp->cmap;
  73531. + if (display->cmap.len)
  73532. + cmap = &display->cmap;
  73533. else
  73534. - cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
  73535. + cmap = fb_default_cmap(1 << display->var.bits_per_pixel);
  73536. fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
  73537. - cfb->fb.var = disp->var;
  73538. - cfb->fb.var.activate = FB_ACTIVATE_NOW;
  73539. -
  73540. - cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb);
  73541. + display->var.activate = FB_ACTIVATE_NOW;
  73542. + cyber2000fb_set_var(&display->var, con, &cfb->fb);
  73543. return 0;
  73544. }
  73545. /*
  73546. * (Un)Blank the display.
  73547. + *
  73548. + * Blank the screen if blank_mode != 0, else unblank. If
  73549. + * blank == NULL then the caller blanks by setting the CLUT
  73550. + * (Color Look Up Table) to all black. Return 0 if blanking
  73551. + * succeeded, != 0 if un-/blanking failed due to e.g. a
  73552. + * video mode which doesn't support it. Implements VESA
  73553. + * suspend and powerdown modes on hardware that supports
  73554. + * disabling hsync/vsync:
  73555. + * blank_mode == 2: suspend vsync
  73556. + * blank_mode == 3: suspend hsync
  73557. + * blank_mode == 4: powerdown
  73558. + *
  73559. + * wms...Enable VESA DMPS compatible powerdown mode
  73560. + * run "setterm -powersave powerdown" to take advantage
  73561. */
  73562. static void cyber2000fb_blank(int blank, struct fb_info *info)
  73563. {
  73564. struct cfb_info *cfb = (struct cfb_info *)info;
  73565. + unsigned int sync = 0;
  73566. int i;
  73567. - /*
  73568. - * Blank the screen if blank_mode != 0, else unblank. If
  73569. - * blank == NULL then the caller blanks by setting the CLUT
  73570. - * (Color Look Up Table) to all black. Return 0 if blanking
  73571. - * succeeded, != 0 if un-/blanking failed due to e.g. a
  73572. - * video mode which doesn't support it. Implements VESA
  73573. - * suspend and powerdown modes on hardware that supports
  73574. - * disabling hsync/vsync:
  73575. - * blank_mode == 2: suspend vsync
  73576. - * blank_mode == 3: suspend hsync
  73577. - * blank_mode == 4: powerdown
  73578. - *
  73579. - * wms...Enable VESA DMPS compatible powerdown mode
  73580. - * run "setterm -powersave powerdown" to take advantage
  73581. - */
  73582. -
  73583. switch (blank) {
  73584. case 4: /* powerdown - both sync lines down */
  73585. - cyber2000_grphw(0x16, 0x05, cfb);
  73586. + sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
  73587. break;
  73588. case 3: /* hsync off */
  73589. - cyber2000_grphw(0x16, 0x01, cfb);
  73590. + sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
  73591. break;
  73592. case 2: /* vsync off */
  73593. - cyber2000_grphw(0x16, 0x04, cfb);
  73594. - break;
  73595. + sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
  73596. + break;
  73597. case 1: /* soft blank */
  73598. - cyber2000_grphw(0x16, 0x00, cfb);
  73599. + default: /* unblank */
  73600. + break;
  73601. + }
  73602. +
  73603. + cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
  73604. +
  73605. + if (blank <= 1) {
  73606. + /* turn on ramdacs */
  73607. + cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
  73608. + cyber2000fb_write_ramdac_ctrl(cfb);
  73609. + }
  73610. +
  73611. + /*
  73612. + * Soft blank/unblank the display.
  73613. + */
  73614. + if (blank) { /* soft blank */
  73615. for (i = 0; i < NR_PALETTE; i++) {
  73616. cyber2000fb_writeb(i, 0x3c8, cfb);
  73617. cyber2000fb_writeb(0, 0x3c9, cfb);
  73618. cyber2000fb_writeb(0, 0x3c9, cfb);
  73619. cyber2000fb_writeb(0, 0x3c9, cfb);
  73620. }
  73621. - break;
  73622. - default: /* unblank */
  73623. - cyber2000_grphw(0x16, 0x00, cfb);
  73624. + } else { /* unblank */
  73625. for (i = 0; i < NR_PALETTE; i++) {
  73626. cyber2000fb_writeb(i, 0x3c8, cfb);
  73627. cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
  73628. cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
  73629. cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
  73630. }
  73631. - break;
  73632. + }
  73633. +
  73634. + if (blank >= 2) {
  73635. + /* turn off ramdacs */
  73636. + cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN;
  73637. + cyber2000fb_write_ramdac_ctrl(cfb);
  73638. }
  73639. }
  73640. @@ -1233,51 +1312,61 @@
  73641. }
  73642. static struct fb_ops cyber2000fb_ops = {
  73643. - owner: THIS_MODULE,
  73644. - fb_set_var: cyber2000fb_set_var,
  73645. - fb_set_cmap: cyber2000fb_set_cmap,
  73646. - fb_pan_display: cyber2000fb_pan_display,
  73647. - fb_get_fix: gen_get_fix,
  73648. - fb_get_var: gen_get_var,
  73649. - fb_get_cmap: gen_get_cmap,
  73650. + .owner = THIS_MODULE,
  73651. + .fb_set_var = cyber2000fb_set_var,
  73652. + .fb_set_cmap = cyber2000fb_set_cmap,
  73653. + .fb_pan_display = cyber2000fb_pan_display,
  73654. + .fb_get_fix = gen_get_fix,
  73655. + .fb_get_var = gen_get_var,
  73656. + .fb_get_cmap = gen_get_cmap,
  73657. };
  73658. /*
  73659. + * This is the only "static" reference to the internal data structures
  73660. + * of this driver. It is here solely at the moment to support the other
  73661. + * CyberPro modules external to this driver.
  73662. + */
  73663. +static struct cfb_info *int_cfb_info;
  73664. +
  73665. +/*
  73666. * Enable access to the extended registers
  73667. */
  73668. -static void cyber2000fb_enable_extregs(struct cfb_info *cfb)
  73669. +void cyber2000fb_enable_extregs(struct cfb_info *cfb)
  73670. {
  73671. cfb->func_use_count += 1;
  73672. if (cfb->func_use_count == 1) {
  73673. int old;
  73674. - old = cyber2000_grphr(FUNC_CTL, cfb);
  73675. - cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
  73676. + old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
  73677. + old |= EXT_FUNC_CTL_EXTREGENBL;
  73678. + cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
  73679. }
  73680. }
  73681. /*
  73682. * Disable access to the extended registers
  73683. */
  73684. -static void cyber2000fb_disable_extregs(struct cfb_info *cfb)
  73685. +void cyber2000fb_disable_extregs(struct cfb_info *cfb)
  73686. {
  73687. if (cfb->func_use_count == 1) {
  73688. int old;
  73689. - old = cyber2000_grphr(FUNC_CTL, cfb);
  73690. - cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
  73691. + old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
  73692. + old &= ~EXT_FUNC_CTL_EXTREGENBL;
  73693. + cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
  73694. }
  73695. - cfb->func_use_count -= 1;
  73696. + if (cfb->func_use_count == 0)
  73697. + printk(KERN_ERR "disable_extregs: count = 0\n");
  73698. + else
  73699. + cfb->func_use_count -= 1;
  73700. }
  73701. -/*
  73702. - * This is the only "static" reference to the internal data structures
  73703. - * of this driver. It is here solely at the moment to support the other
  73704. - * CyberPro modules external to this driver.
  73705. - */
  73706. -static struct cfb_info *int_cfb_info;
  73707. +void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
  73708. +{
  73709. + memcpy(var, &cfb->display->var, sizeof(struct fb_var_screeninfo));
  73710. +}
  73711. /*
  73712. * Attach a capture/tv driver to the core CyberX0X0 driver.
  73713. @@ -1311,164 +1400,102 @@
  73714. EXPORT_SYMBOL(cyber2000fb_attach);
  73715. EXPORT_SYMBOL(cyber2000fb_detach);
  73716. +EXPORT_SYMBOL(cyber2000fb_enable_extregs);
  73717. +EXPORT_SYMBOL(cyber2000fb_disable_extregs);
  73718. +EXPORT_SYMBOL(cyber2000fb_get_fb_var);
  73719. /*
  73720. * These parameters give
  73721. * 640x480, hsync 31.5kHz, vsync 60Hz
  73722. */
  73723. static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
  73724. - refresh: 60,
  73725. - xres: 640,
  73726. - yres: 480,
  73727. - pixclock: 39722,
  73728. - left_margin: 56,
  73729. - right_margin: 16,
  73730. - upper_margin: 34,
  73731. - lower_margin: 9,
  73732. - hsync_len: 88,
  73733. - vsync_len: 2,
  73734. - sync: FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  73735. - vmode: FB_VMODE_NONINTERLACED
  73736. + .refresh = 60,
  73737. + .xres = 640,
  73738. + .yres = 480,
  73739. + .pixclock = 39722,
  73740. + .left_margin = 56,
  73741. + .right_margin = 16,
  73742. + .upper_margin = 34,
  73743. + .lower_margin = 9,
  73744. + .hsync_len = 88,
  73745. + .vsync_len = 2,
  73746. + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  73747. + .vmode = FB_VMODE_NONINTERLACED
  73748. };
  73749. +/* static register programming for all chips */
  73750. static char igs_regs[] __devinitdata = {
  73751. - 0x12, 0x00, 0x13, 0x00,
  73752. - 0x16, 0x00,
  73753. - 0x31, 0x00, 0x32, 0x00,
  73754. - 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
  73755. - 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01,
  73756. - 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00,
  73757. - 0x70, 0x0b, 0x73, 0x30,
  73758. - 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8
  73759. + EXT_CRT_IRQ, 0,
  73760. + EXT_CRT_TEST, 0,
  73761. + EXT_SYNC_CTL, 0,
  73762. + EXT_SEG_WRITE_PTR, 0,
  73763. + EXT_SEG_READ_PTR, 0,
  73764. + EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
  73765. + EXT_BIU_MISC_COP_ENABLE |
  73766. + EXT_BIU_MISC_COP_BFC,
  73767. + EXT_FUNC_CTL, 0,
  73768. + CURS_H_START, 0,
  73769. + CURS_H_START + 1, 0,
  73770. + CURS_H_PRESET, 0,
  73771. + CURS_V_START, 0,
  73772. + CURS_V_START + 1, 0,
  73773. + CURS_V_PRESET, 0,
  73774. + CURS_CTL, 0,
  73775. + EXT_ATTRIB_CTL, EXT_ATTRIB_CTL_EXT,
  73776. + EXT_OVERSCAN_RED, 0,
  73777. + EXT_OVERSCAN_GREEN, 0,
  73778. + EXT_OVERSCAN_BLUE, 0,
  73779. +};
  73780. +
  73781. +/* specific register setting for the 2000 series */
  73782. +static char igs_2000_regs[] __devinitdata = {
  73783. + /* some of these are questionable when we have a BIOS */
  73784. + EXT_MEM_CTL0, EXT_MEM_CTL0_7CLK |
  73785. + EXT_MEM_CTL0_RAS_1 |
  73786. + EXT_MEM_CTL0_MULTCAS,
  73787. + EXT_HIDDEN_CTL1, 0x30,
  73788. + EXT_FIFO_CTL, 0x0b,
  73789. + EXT_FIFO_CTL + 1, 0x17,
  73790. + 0x76, 0x00,
  73791. + EXT_HIDDEN_CTL4, 0xc8
  73792. };
  73793. /*
  73794. - * We need to wake up the CyberPro, and make sure its in linear memory
  73795. - * mode. Unfortunately, this is specific to the platform and card that
  73796. - * we are running on.
  73797. - *
  73798. - * On x86 and ARM, should we be initialising the CyberPro first via the
  73799. - * IO registers, and then the MMIO registers to catch all cases? Can we
  73800. - * end up in the situation where the chip is in MMIO mode, but not awake
  73801. - * on an x86 system?
  73802. - *
  73803. - * Note that on the NetWinder, the firmware automatically detects the
  73804. - * type, width and size, and leaves this in extended registers 0x71 and
  73805. - * 0x72 for us.
  73806. + * Initialise the CyberPro hardware.
  73807. */
  73808. -static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
  73809. +static void cyberpro_init_hw(struct cfb_info *cfb)
  73810. {
  73811. int i;
  73812. - /*
  73813. - * Wake up the CyberPro.
  73814. - */
  73815. -#ifdef __sparc__
  73816. -#ifdef __sparc_v9__
  73817. -#error "You loose, consult DaveM."
  73818. -#else
  73819. - /*
  73820. - * SPARC does not have an "outb" instruction, so we generate
  73821. - * I/O cycles storing into a reserved memory space at
  73822. - * physical address 0x3000000
  73823. - */
  73824. - {
  73825. - unsigned char *iop;
  73826. -
  73827. - iop = ioremap(0x3000000, 0x5000);
  73828. - if (iop == NULL) {
  73829. - prom_printf("iga5000: cannot map I/O\n");
  73830. - return -ENOMEM;
  73831. - }
  73832. -
  73833. - writeb(0x18, iop + 0x46e8);
  73834. - writeb(0x01, iop + 0x102);
  73835. - writeb(0x08, iop + 0x46e8);
  73836. - writeb(0x33, iop + 0x3ce);
  73837. - writeb(0x01, iop + 0x3cf);
  73838. -
  73839. - iounmap((void *)iop);
  73840. - }
  73841. -#endif
  73842. -
  73843. - if (at_boot) {
  73844. - /*
  73845. - * Use mclk from BIOS. Only read this if we're
  73846. - * initialising this card for the first time.
  73847. - * FIXME: what about hotplug?
  73848. - */
  73849. - cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
  73850. - cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
  73851. - }
  73852. -#endif
  73853. -#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
  73854. - /*
  73855. - * x86 and MIPS are simple, we just do regular
  73856. - * outb's instead of cyber2000fb_writeb.
  73857. - */
  73858. - outb(0x18, 0x46e8);
  73859. - outb(0x01, 0x102);
  73860. - outb(0x08, 0x46e8);
  73861. - outb(0x33, 0x3ce);
  73862. - outb(0x01, 0x3cf);
  73863. -
  73864. - if (at_boot) {
  73865. - /*
  73866. - * Use mclk from BIOS. Only read this if we're
  73867. - * initialising this card for the first time.
  73868. - * FIXME: what about hotplug?
  73869. - */
  73870. - cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
  73871. - cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
  73872. - }
  73873. -#endif
  73874. -#ifdef __arm__
  73875. - cyber2000fb_writeb(0x18, 0x46e8, cfb);
  73876. - cyber2000fb_writeb(0x01, 0x102, cfb);
  73877. - cyber2000fb_writeb(0x08, 0x46e8, cfb);
  73878. - cyber2000fb_writeb(0x33, 0x3ce, cfb);
  73879. - cyber2000fb_writeb(0x01, 0x3cf, cfb);
  73880. -
  73881. - /*
  73882. - * MCLK on the NetWinder and the Shark is fixed at 75MHz
  73883. - */
  73884. - cfb->mclk_mult = 0xdb;
  73885. - cfb->mclk_div = 0x54;
  73886. -#endif
  73887. -
  73888. - /*
  73889. - * Initialise the CyberPro
  73890. - */
  73891. for (i = 0; i < sizeof(igs_regs); i += 2)
  73892. cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
  73893. - if (at_boot) {
  73894. + if (cfb->id == ID_CYBERPRO_5000) {
  73895. /*
  73896. - * get the video RAM size and width from the VGA register.
  73897. - * This should have been already initialised by the BIOS,
  73898. - * but if it's garbage, claim default 1MB VRAM (woody)
  73899. + * On the CyberPro5XXXX, ensure that we're using the correct
  73900. + * PLL (5XXX's may be programmed to use an additional set of
  73901. + * PLLs.)
  73902. */
  73903. - cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
  73904. - cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
  73905. + unsigned char val;
  73906. + cyber2000fb_writeb(0xba, 0x3ce, cfb);
  73907. + val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
  73908. + cyber2000fb_writeb(val, 0x3cf, cfb);
  73909. + cyber2000fb_ops.fb_pan_display = NULL; /* FIXME: panning broken */
  73910. } else {
  73911. /*
  73912. - * Reprogram the MEM_CTL1 and MEM_CTL2 registers
  73913. + * Other supported chips (2000 series) appear to need
  73914. + * these registers programming
  73915. */
  73916. - cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
  73917. - cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
  73918. + for (i = 0; i < sizeof(igs_2000_regs); i += 2)
  73919. + cyber2000_grphw(igs_2000_regs[i],
  73920. + igs_2000_regs[i+1],
  73921. + cfb);
  73922. }
  73923. - /*
  73924. - * Ensure thatwe are using the correct PLL.
  73925. - * (CyberPro 5000's may be programmed to use
  73926. - * an additional set of PLLs.
  73927. - */
  73928. - cyber2000fb_writeb(0xba, 0x3ce, cfb);
  73929. - cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
  73930. }
  73931. static struct cfb_info * __devinit
  73932. -cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
  73933. +cyberpro_alloc_fb_info(unsigned int id, char *name)
  73934. {
  73935. struct cfb_info *cfb;
  73936. @@ -1480,10 +1507,9 @@
  73937. memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
  73938. - cfb->currcon = -1;
  73939. - cfb->dev = dev;
  73940. + cfb->id = id;
  73941. - if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
  73942. + if (id == ID_CYBERPRO_5000)
  73943. cfb->ref_ps = 40690; // 24.576 MHz
  73944. else
  73945. cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
  73946. @@ -1492,7 +1518,7 @@
  73947. cfb->divisors[1] = 2;
  73948. cfb->divisors[2] = 4;
  73949. - if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
  73950. + if (id == ID_CYBERPRO_2000)
  73951. cfb->divisors[3] = 8;
  73952. else
  73953. cfb->divisors[3] = 6;
  73954. @@ -1504,7 +1530,24 @@
  73955. cfb->fb.fix.xpanstep = 0;
  73956. cfb->fb.fix.ypanstep = 1;
  73957. cfb->fb.fix.ywrapstep = 0;
  73958. - cfb->fb.fix.accel = id->driver_data;
  73959. +
  73960. + switch (id) {
  73961. + case ID_IGA_1682:
  73962. + cfb->fb.fix.accel = 0;
  73963. + break;
  73964. +
  73965. + case ID_CYBERPRO_2000:
  73966. + cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
  73967. + break;
  73968. +
  73969. + case ID_CYBERPRO_2010:
  73970. + cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
  73971. + break;
  73972. +
  73973. + case ID_CYBERPRO_5000:
  73974. + cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
  73975. + break;
  73976. + }
  73977. cfb->fb.var.nonstd = 0;
  73978. cfb->fb.var.activate = FB_ACTIVATE_NOW;
  73979. @@ -1569,55 +1612,46 @@
  73980. return 0;
  73981. }
  73982. -static int __devinit
  73983. -cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
  73984. +/*
  73985. + * The CyberPro chips can be placed on many different bus types.
  73986. + * This probe function is common to all bus types. The bus-specific
  73987. + * probe function is expected to have:
  73988. + * - enabled access to the linear memory region
  73989. + * - memory mapped access to the registers
  73990. + * - initialised mem_ctl1 and mem_ctl2 appropriately.
  73991. + */
  73992. +static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
  73993. {
  73994. - struct cfb_info *cfb;
  73995. - u_int h_sync, v_sync;
  73996. u_long smem_size;
  73997. - char name[16];
  73998. + u_int h_sync, v_sync;
  73999. int err;
  74000. - sprintf(name, "CyberPro%4X", id->device);
  74001. -
  74002. - err = pci_enable_device(dev);
  74003. - if (err)
  74004. - return err;
  74005. -
  74006. - err = pci_request_regions(dev, name);
  74007. - if (err)
  74008. - return err;
  74009. -
  74010. - err = -ENOMEM;
  74011. - cfb = cyberpro_alloc_fb_info(dev, id, name);
  74012. - if (!cfb)
  74013. - goto failed_release;
  74014. -
  74015. - cfb->region = ioremap(pci_resource_start(dev, 0),
  74016. - pci_resource_len(dev, 0));
  74017. - if (!cfb->region)
  74018. - goto failed_ioremap;
  74019. -
  74020. - cfb->regs = cfb->region + MMIO_OFFSET;
  74021. + cyberpro_init_hw(cfb);
  74022. - cyberpro_init_hw(cfb, 1);
  74023. + /*
  74024. + * Get the video RAM size and width from the VGA register.
  74025. + * This should have been already initialised by the BIOS,
  74026. + * but if it's garbage, claim default 1MB VRAM (woody)
  74027. + */
  74028. + cfb->mem_ctl0 = cyber2000_grphr(EXT_MEM_CTL0, cfb);
  74029. + cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
  74030. + cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
  74031. + /*
  74032. + * Determine the size of the memory.
  74033. + */
  74034. switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
  74035. case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break;
  74036. case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break;
  74037. + case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
  74038. default: smem_size = 0x00100000; break;
  74039. }
  74040. - /*
  74041. - * Hmm, we _need_ a portable way of finding the address for
  74042. - * the remap stuff, both for mmio and for smem.
  74043. - */
  74044. - cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
  74045. - cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
  74046. - cfb->fb.fix.mmio_len = MMIO_SIZE;
  74047. cfb->fb.fix.smem_len = smem_size;
  74048. + cfb->fb.fix.mmio_len = MMIO_SIZE;
  74049. cfb->fb.screen_base = cfb->region;
  74050. + err = -EINVAL;
  74051. if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
  74052. &cyber2000fb_default_mode, 8)) {
  74053. printk("%s: no valid mode found\n", cfb->fb.fix.id);
  74054. @@ -1644,13 +1678,181 @@
  74055. v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
  74056. cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
  74057. - printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
  74058. + printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
  74059. cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
  74060. cfb->fb.var.xres, cfb->fb.var.yres,
  74061. h_sync / 1000, h_sync % 1000, v_sync);
  74062. err = register_framebuffer(&cfb->fb);
  74063. - if (err < 0)
  74064. +
  74065. +failed:
  74066. + return err;
  74067. +}
  74068. +
  74069. +static void cyberpro_common_resume(struct cfb_info *cfb)
  74070. +{
  74071. + cyberpro_init_hw(cfb);
  74072. +
  74073. + /*
  74074. + * Reprogram the MEM_CTL0, 1 and 2 registers
  74075. + */
  74076. + cyber2000_grphw(EXT_MEM_CTL0, cfb->mem_ctl0, cfb);
  74077. + cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
  74078. + cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
  74079. +
  74080. + /*
  74081. + * Restore the old video mode and the palette.
  74082. + * We also need to tell fbcon to redraw the console.
  74083. + */
  74084. + cfb->fb.var.activate = FB_ACTIVATE_NOW;
  74085. + cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
  74086. +}
  74087. +
  74088. +
  74089. +
  74090. +
  74091. +/*
  74092. + * PCI specific support.
  74093. + */
  74094. +
  74095. +/*
  74096. + * We need to wake up the CyberPro, and make sure its in linear memory
  74097. + * mode. Unfortunately, this is specific to the platform and card that
  74098. + * we are running on.
  74099. + *
  74100. + * On x86 and ARM, should we be initialising the CyberPro first via the
  74101. + * IO registers, and then the MMIO registers to catch all cases? Can we
  74102. + * end up in the situation where the chip is in MMIO mode, but not awake
  74103. + * on an x86 system?
  74104. + */
  74105. +static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
  74106. +{
  74107. + unsigned char val;
  74108. +
  74109. +#if defined(__sparc_v9__)
  74110. +#error "You loose, consult DaveM."
  74111. +#elif defined(__sparc__)
  74112. + /*
  74113. + * SPARC does not have an "outb" instruction, so we generate
  74114. + * I/O cycles storing into a reserved memory space at
  74115. + * physical address 0x3000000
  74116. + */
  74117. + unsigned char *iop;
  74118. +
  74119. + iop = ioremap(0x3000000, 0x5000);
  74120. + if (iop == NULL) {
  74121. + prom_printf("iga5000: cannot map I/O\n");
  74122. + return -ENOMEM;
  74123. + }
  74124. +
  74125. + writeb(0x18, iop + 0x46e8);
  74126. + writeb(0x01, iop + 0x102);
  74127. + writeb(0x08, iop + 0x46e8);
  74128. + writeb(EXT_BIU_MISC, iop + 0x3ce);
  74129. + writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
  74130. +
  74131. + iounmap((void *)iop);
  74132. +#elif defined(CONFIG_ARCH_SHARK)
  74133. + /*
  74134. + * Shark probably needs to do it this way rather than use the
  74135. + * IO method below. Since the CyberPro on the Shark isn't a
  74136. + * PCI device, we probably want to move this to a bus-specific
  74137. + * probe function. Do we even need to do this?
  74138. + */
  74139. + cyber2000fb_writeb(0x18, 0x46e8, cfb);
  74140. + cyber2000fb_writeb(0x01, 0x102, cfb);
  74141. + cyber2000fb_writeb(0x08, 0x46e8, cfb);
  74142. + cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
  74143. + cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
  74144. +#else
  74145. + /*
  74146. + * Most other machine types are "normal", so
  74147. + * we use the standard IO-based wakeup.
  74148. + */
  74149. + outb(0x18, 0x46e8);
  74150. + outb(0x01, 0x102);
  74151. + outb(0x08, 0x46e8);
  74152. + outb(EXT_BIU_MISC, 0x3ce);
  74153. + outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
  74154. +#endif
  74155. +
  74156. + /*
  74157. + * Allow the CyberPro to accept PCI burst accesses
  74158. + */
  74159. + val = cyber2000_grphr(EXT_BUS_CTL, cfb);
  74160. + if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
  74161. + printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
  74162. +
  74163. + val |= EXT_BUS_CTL_PCIBURST_WRITE;
  74164. +
  74165. + if (cfb->id == ID_CYBERPRO_5000)
  74166. + val |= EXT_BUS_CTL_PCIBURST_READ;
  74167. +
  74168. + cyber2000_grphw(EXT_BUS_CTL, val, cfb);
  74169. + }
  74170. +
  74171. + return 0;
  74172. +}
  74173. +
  74174. +static int __devinit
  74175. +cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
  74176. +{
  74177. + struct cfb_info *cfb;
  74178. + char name[16];
  74179. + int err;
  74180. +
  74181. + sprintf(name, "CyberPro%4X", id->device);
  74182. +
  74183. + err = pci_enable_device(dev);
  74184. + if (err)
  74185. + return err;
  74186. +
  74187. + err = pci_request_regions(dev, name);
  74188. + if (err)
  74189. + return err;
  74190. +
  74191. + err = -ENOMEM;
  74192. + cfb = cyberpro_alloc_fb_info(id->driver_data, name);
  74193. + if (!cfb)
  74194. + goto failed_release;
  74195. +
  74196. + cfb->dev = dev;
  74197. + cfb->region = ioremap(pci_resource_start(dev, 0),
  74198. + pci_resource_len(dev, 0));
  74199. + if (!cfb->region)
  74200. + goto failed_ioremap;
  74201. +
  74202. + cfb->regs = cfb->region + MMIO_OFFSET;
  74203. + cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
  74204. + cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
  74205. +
  74206. + /*
  74207. + * Bring up the hardware. This is expected to enable access
  74208. + * to the linear memory region, and allow access to the memory
  74209. + * mapped registers. Also, mem_ctl1 and mem_ctl2 must be
  74210. + * initialised.
  74211. + */
  74212. + err = cyberpro_pci_enable_mmio(cfb);
  74213. + if (err)
  74214. + goto failed;
  74215. +
  74216. + /*
  74217. + * Use MCLK from BIOS. FIXME: what about hotplug?
  74218. + */
  74219. + cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
  74220. + cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
  74221. +#ifdef __arm__
  74222. + if (machine_is_netwinder() || machine_is_shark()) {
  74223. + /*
  74224. + * MCLK on the NetWinder and the Shark is fixed at 75MHz
  74225. + */
  74226. + cfb->mclk_mult = 0xdb;
  74227. + cfb->mclk_div = 0x54;
  74228. + }
  74229. +#endif
  74230. +
  74231. + err = cyberpro_common_probe(cfb);
  74232. + if (err)
  74233. goto failed;
  74234. /*
  74235. @@ -1672,7 +1874,7 @@
  74236. return err;
  74237. }
  74238. -static void __devexit cyberpro_remove(struct pci_dev *dev)
  74239. +static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
  74240. {
  74241. struct cfb_info *cfb = pci_get_drvdata(dev);
  74242. @@ -1701,7 +1903,7 @@
  74243. }
  74244. }
  74245. -static int cyberpro_suspend(struct pci_dev *dev, u32 state)
  74246. +static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
  74247. {
  74248. return 0;
  74249. }
  74250. @@ -1709,41 +1911,44 @@
  74251. /*
  74252. * Re-initialise the CyberPro hardware
  74253. */
  74254. -static int cyberpro_resume(struct pci_dev *dev)
  74255. +static int cyberpro_pci_resume(struct pci_dev *dev)
  74256. {
  74257. struct cfb_info *cfb = pci_get_drvdata(dev);
  74258. if (cfb) {
  74259. - cyberpro_init_hw(cfb, 0);
  74260. -
  74261. - /*
  74262. - * Restore the old video mode and the palette.
  74263. - * We also need to tell fbcon to redraw the console.
  74264. - */
  74265. - cfb->fb.var.activate = FB_ACTIVATE_NOW;
  74266. - cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
  74267. + cyberpro_pci_enable_mmio(cfb);
  74268. + cyberpro_common_resume(cfb);
  74269. }
  74270. return 0;
  74271. }
  74272. static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
  74273. +// Not yet
  74274. +// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
  74275. +// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
  74276. { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
  74277. - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },
  74278. + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
  74279. { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
  74280. - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },
  74281. + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
  74282. { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
  74283. - PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },
  74284. + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
  74285. { 0, }
  74286. };
  74287. +MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
  74288. +
  74289. +#ifndef __devexit_p
  74290. +#define __devexit_p(x) (x)
  74291. +#endif
  74292. +
  74293. static struct pci_driver cyberpro_driver = {
  74294. - name: "CyberPro",
  74295. - probe: cyberpro_probe,
  74296. - remove: __devexit_p(cyberpro_remove),
  74297. - suspend: cyberpro_suspend,
  74298. - resume: cyberpro_resume,
  74299. - id_table: cyberpro_pci_table
  74300. + .name = "CyberPro",
  74301. + .probe = cyberpro_pci_probe,
  74302. + .remove = __devexit_p(cyberpro_pci_remove),
  74303. + .suspend = cyberpro_pci_suspend,
  74304. + .resume = cyberpro_pci_resume,
  74305. + .id_table = cyberpro_pci_table
  74306. };
  74307. /*
  74308. @@ -1768,5 +1973,4 @@
  74309. MODULE_AUTHOR("Russell King");
  74310. MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
  74311. -MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
  74312. MODULE_LICENSE("GPL");
  74313. diff -urN linux-2.4.26/drivers/video/cyber2000fb.h linux-2.4.26-vrs1/drivers/video/cyber2000fb.h
  74314. --- linux-2.4.26/drivers/video/cyber2000fb.h 2002-08-03 01:39:45.000000000 +0100
  74315. +++ linux-2.4.26-vrs1/drivers/video/cyber2000fb.h 2004-04-19 16:49:24.000000000 +0100
  74316. @@ -36,24 +36,55 @@
  74317. #define debug_printf(x...) do { } while (0)
  74318. #endif
  74319. -#define PIXFORMAT_8BPP 0
  74320. -#define PIXFORMAT_16BPP 1
  74321. -#define PIXFORMAT_24BPP 2
  74322. -#define PIXFORMAT_32BPP 3
  74323. -
  74324. -#define VISUALID_256 1
  74325. -#define VISUALID_64K 2
  74326. -#define VISUALID_16M_32 3
  74327. -#define VISUALID_16M 4
  74328. -#define VISUALID_32K 6
  74329. -
  74330. -#define FUNC_CTL 0x3c
  74331. -#define FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
  74332. -
  74333. -#define BIU_BM_CONTROL 0x3e
  74334. -#define BIU_BM_CONTROL_ENABLE 0x01 /* enable bus-master */
  74335. -#define BIU_BM_CONTROL_BURST 0x02 /* enable burst */
  74336. -#define BIU_BM_CONTROL_BACK2BACK 0x04 /* enable back to back */
  74337. +#define RAMDAC_RAMPWRDN 0x01
  74338. +#define RAMDAC_DAC8BIT 0x02
  74339. +#define RAMDAC_VREFEN 0x04
  74340. +#define RAMDAC_BYPASS 0x10
  74341. +#define RAMDAC_DACPWRDN 0x40
  74342. +
  74343. +#define EXT_CRT_VRTOFL 0x11
  74344. +#define EXT_CRT_VRTOFL_LINECOMP10 0x10
  74345. +#define EXT_CRT_VRTOFL_INTERLACE 0x20
  74346. +
  74347. +#define EXT_CRT_IRQ 0x12
  74348. +#define EXT_CRT_IRQ_ENABLE 0x01
  74349. +#define EXT_CRT_IRQ_ACT_HIGH 0x04
  74350. +
  74351. +#define EXT_CRT_TEST 0x13
  74352. +
  74353. +#define EXT_SYNC_CTL 0x16
  74354. +#define EXT_SYNC_CTL_HS_NORMAL 0x00
  74355. +#define EXT_SYNC_CTL_HS_0 0x01
  74356. +#define EXT_SYNC_CTL_HS_1 0x02
  74357. +#define EXT_SYNC_CTL_HS_HSVS 0x03
  74358. +#define EXT_SYNC_CTL_VS_NORMAL 0x00
  74359. +#define EXT_SYNC_CTL_VS_0 0x04
  74360. +#define EXT_SYNC_CTL_VS_1 0x08
  74361. +#define EXT_SYNC_CTL_VS_COMP 0x0c
  74362. +
  74363. +#define EXT_BUS_CTL 0x30
  74364. +#define EXT_BUS_CTL_LIN_1MB 0x00
  74365. +#define EXT_BUS_CTL_LIN_2MB 0x01
  74366. +#define EXT_BUS_CTL_LIN_4MB 0x02
  74367. +#define EXT_BUS_CTL_ZEROWAIT 0x04
  74368. +#define EXT_BUS_CTL_PCIBURST_WRITE 0x20
  74369. +#define EXT_BUS_CTL_PCIBURST_READ 0x80 /* CyberPro 5000 only */
  74370. +
  74371. +#define EXT_SEG_WRITE_PTR 0x31
  74372. +#define EXT_SEG_READ_PTR 0x32
  74373. +#define EXT_BIU_MISC 0x33
  74374. +#define EXT_BIU_MISC_LIN_ENABLE 0x01
  74375. +#define EXT_BIU_MISC_COP_ENABLE 0x04
  74376. +#define EXT_BIU_MISC_COP_BFC 0x08
  74377. +
  74378. +#define EXT_FUNC_CTL 0x3c
  74379. +#define EXT_FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
  74380. +
  74381. +#define PCI_BM_CTL 0x3e
  74382. +#define PCI_BM_CTL_ENABLE 0x01 /* enable bus-master */
  74383. +#define PCI_BM_CTL_BURST 0x02 /* enable burst */
  74384. +#define PCI_BM_CTL_BACK2BACK 0x04 /* enable back to back */
  74385. +#define PCI_BM_CTL_DUMMY 0x08 /* insert dummy cycle */
  74386. #define X_V2_VID_MEM_START 0x40
  74387. #define X_V2_VID_SRC_WIDTH 0x43
  74388. @@ -87,6 +118,19 @@
  74389. #define K_CAP_X2_CTL1 0x49
  74390. +#define CURS_H_START 0x50
  74391. +#define CURS_H_PRESET 0x52
  74392. +#define CURS_V_START 0x53
  74393. +#define CURS_V_PRESET 0x55
  74394. +#define CURS_CTL 0x56
  74395. +
  74396. +#define EXT_ATTRIB_CTL 0x57
  74397. +#define EXT_ATTRIB_CTL_EXT 0x01
  74398. +
  74399. +#define EXT_OVERSCAN_RED 0x58
  74400. +#define EXT_OVERSCAN_GREEN 0x59
  74401. +#define EXT_OVERSCAN_BLUE 0x5a
  74402. +
  74403. #define CAP_X_START 0x60
  74404. #define CAP_X_END 0x62
  74405. #define CAP_Y_START 0x64
  74406. @@ -96,46 +140,112 @@
  74407. #define CAP_DDA_Y_INIT 0x6c
  74408. #define CAP_DDA_Y_INC 0x6e
  74409. -#define MEM_CTL1 0x71
  74410. +#define EXT_MEM_CTL0 0x70
  74411. +#define EXT_MEM_CTL0_7CLK 0x01
  74412. +#define EXT_MEM_CTL0_RAS_1 0x02
  74413. +#define EXT_MEM_CTL0_RAS2CAS_1 0x04
  74414. +#define EXT_MEM_CTL0_MULTCAS 0x08
  74415. +#define EXT_MEM_CTL0_ASYM 0x10
  74416. +#define EXT_MEM_CTL0_CAS1ON 0x20
  74417. +#define EXT_MEM_CTL0_FIFOFLUSH 0x40
  74418. +#define EXT_MEM_CTL0_SEQRESET 0x80
  74419. +
  74420. +#define EXT_MEM_CTL1 0x71
  74421. +#define EXT_MEM_CTL1_PAR 0x00
  74422. +#define EXT_MEM_CTL1_SERPAR 0x01
  74423. +#define EXT_MEM_CTL1_SER 0x03
  74424. +#define EXT_MEM_CTL1_SYNC 0x04
  74425. +#define EXT_MEM_CTL1_VRAM 0x08
  74426. +#define EXT_MEM_CTL1_4K_REFRESH 0x10
  74427. +#define EXT_MEM_CTL1_256Kx4 0x00
  74428. +#define EXT_MEM_CTL1_512Kx8 0x40
  74429. +#define EXT_MEM_CTL1_1Mx16 0x60
  74430. -#define MEM_CTL2 0x72
  74431. +#define EXT_MEM_CTL2 0x72
  74432. +#define MEM_CTL2_SIZE_1MB 0x00
  74433. #define MEM_CTL2_SIZE_2MB 0x01
  74434. #define MEM_CTL2_SIZE_4MB 0x02
  74435. #define MEM_CTL2_SIZE_MASK 0x03
  74436. #define MEM_CTL2_64BIT 0x04
  74437. +#define EXT_HIDDEN_CTL1 0x73
  74438. +
  74439. #define EXT_FIFO_CTL 0x74
  74440. +#define EXT_SEQ_MISC 0x77
  74441. +#define EXT_SEQ_MISC_8 0x01
  74442. +#define EXT_SEQ_MISC_16_RGB565 0x02
  74443. +#define EXT_SEQ_MISC_32 0x03
  74444. +#define EXT_SEQ_MISC_24_RGB888 0x04
  74445. +#define EXT_SEQ_MISC_16_RGB555 0x06
  74446. +#define EXT_SEQ_MISC_8_RGB332 0x09
  74447. +#define EXT_SEQ_MISC_16_RGB444 0x0a
  74448. +
  74449. +#define EXT_HIDDEN_CTL4 0x7a
  74450. +
  74451. +#define CURS_MEM_START 0x7e /* bits 23..12 */
  74452. +
  74453. #define CAP_PIP_X_START 0x80
  74454. #define CAP_PIP_X_END 0x82
  74455. #define CAP_PIP_Y_START 0x84
  74456. #define CAP_PIP_Y_END 0x86
  74457. -#define CAP_NEW_CTL1 0x88
  74458. +#define EXT_CAP_CTL1 0x88
  74459. -#define CAP_NEW_CTL2 0x89
  74460. +#define EXT_CAP_CTL2 0x89
  74461. +#define EXT_CAP_CTL2_ODDFRAMEIRQ 0x01
  74462. +#define EXT_CAP_CTL2_ANYFRAMEIRQ 0x02
  74463. #define BM_CTRL0 0x9c
  74464. #define BM_CTRL1 0x9d
  74465. -#define CAP_MODE1 0xa4
  74466. -#define CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
  74467. -#define CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
  74468. -#define CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
  74469. -#define CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
  74470. -#define CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
  74471. -#define CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
  74472. -#define CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
  74473. -
  74474. -#define DCLK_MULT 0xb0
  74475. -#define DCLK_DIV 0xb1
  74476. -#define DCLK_DIV_VFSEL 0x20
  74477. -#define MCLK_MULT 0xb2
  74478. -#define MCLK_DIV 0xb3
  74479. -
  74480. -#define CAP_MODE2 0xa5
  74481. -
  74482. -#define Y_TV_CTL 0xae
  74483. +#define EXT_CAP_MODE1 0xa4
  74484. +#define EXT_CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
  74485. +#define EXT_CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
  74486. +#define EXT_CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
  74487. +#define EXT_CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
  74488. +#define EXT_CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
  74489. +#define EXT_CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
  74490. +#define EXT_CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
  74491. +
  74492. +#define EXT_CAP_MODE2 0xa5
  74493. +#define EXT_CAP_MODE2_CCIRINVOE 0x01
  74494. +#define EXT_CAP_MODE2_CCIRINVVGT 0x02
  74495. +#define EXT_CAP_MODE2_CCIRINVHGT 0x04
  74496. +#define EXT_CAP_MODE2_CCIRINVDG 0x08
  74497. +#define EXT_CAP_MODE2_DATEND 0x10
  74498. +#define EXT_CAP_MODE2_CCIRDGH 0x20
  74499. +#define EXT_CAP_MODE2_FIXSONY 0x40
  74500. +#define EXT_CAP_MODE2_SYNCFREEZE 0x80
  74501. +
  74502. +#define EXT_TV_CTL 0xae
  74503. +
  74504. +#define EXT_DCLK_MULT 0xb0
  74505. +#define EXT_DCLK_DIV 0xb1
  74506. +#define EXT_DCLK_DIV_VFSEL 0x20
  74507. +#define EXT_MCLK_MULT 0xb2
  74508. +#define EXT_MCLK_DIV 0xb3
  74509. +
  74510. +#define EXT_LATCH1 0xb5
  74511. +#define EXT_LATCH1_VAFC_EN 0x01 /* enable VAFC */
  74512. +
  74513. +#define EXT_FEATURE 0xb7
  74514. +#define EXT_FEATURE_BUS_MASK 0x07 /* host bus mask */
  74515. +#define EXT_FEATURE_BUS_PCI 0x00
  74516. +#define EXT_FEATURE_BUS_VL_STD 0x04
  74517. +#define EXT_FEATURE_BUS_VL_LINEAR 0x05
  74518. +#define EXT_FEATURE_1682 0x20 /* IGS 1682 compatibility */
  74519. +
  74520. +#define EXT_LATCH2 0xb6
  74521. +#define EXT_LATCH2_I2C_CLKEN 0x10
  74522. +#define EXT_LATCH2_I2C_CLK 0x20
  74523. +#define EXT_LATCH2_I2C_DATEN 0x40
  74524. +#define EXT_LATCH2_I2C_DAT 0x80
  74525. +
  74526. +#define EXT_XT_CTL 0xbe
  74527. +#define EXT_XT_CAP16 0x04
  74528. +#define EXT_XT_LINEARFB 0x08
  74529. +#define EXT_XT_PAL 0x10
  74530. #define EXT_MEM_START 0xc0 /* ext start address 21 bits */
  74531. #define HOR_PHASE_SHIFT 0xc2 /* high 3 bits */
  74532. @@ -160,25 +270,37 @@
  74533. #define EXT_VID_FMT_RGB565 0x02
  74534. #define EXT_VID_FMT_RGB888_24 0x03
  74535. #define EXT_VID_FMT_RGB888_32 0x04
  74536. +#define EXT_VID_FMT_RGB8 0x05
  74537. +#define EXT_VID_FMT_RGB4444 0x06
  74538. +#define EXT_VID_FMT_RGB8T 0x07
  74539. #define EXT_VID_FMT_DUP_PIX_ZOON 0x08 /* duplicate pixel zoom */
  74540. #define EXT_VID_FMT_MOD_3RD_PIX 0x20 /* modify 3rd duplicated pixel */
  74541. #define EXT_VID_FMT_DBL_H_PIX 0x40 /* double horiz pixels */
  74542. -#define EXT_VID_FMT_UV128 0x80 /* UV data offset by 128 */
  74543. +#define EXT_VID_FMT_YUV128 0x80 /* YUV data offset by 128 */
  74544. #define EXT_VID_DISP_CTL1 0xdc
  74545. #define EXT_VID_DISP_CTL1_INTRAM 0x01 /* video pixels go to internal RAM */
  74546. #define EXT_VID_DISP_CTL1_IGNORE_CCOMP 0x02 /* ignore colour compare registers */
  74547. #define EXT_VID_DISP_CTL1_NOCLIP 0x04 /* do not clip to 16235,16240 */
  74548. #define EXT_VID_DISP_CTL1_UV_AVG 0x08 /* U/V data is averaged */
  74549. -#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 */
  74550. -#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* vertical interpolation off */
  74551. +#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 (if YUV128 set) */
  74552. +#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* disable vertical interpolation */
  74553. #define EXT_VID_DISP_CTL1_FULL_WIN 0x40 /* video out window full */
  74554. #define EXT_VID_DISP_CTL1_ENABLE_WINDOW 0x80 /* enable video window */
  74555. #define EXT_VID_FIFO_CTL1 0xdd
  74556. +#define EXT_VID_FIFO_CTL1_OE_HIGH 0x02
  74557. +#define EXT_VID_FIFO_CTL1_INTERLEAVE 0x04 /* enable interleaved memory read */
  74558. +
  74559. +#define EXT_ROM_UCB4GH 0xe5
  74560. +#define EXT_ROM_UCB4GH_FREEZE 0x02 /* capture frozen */
  74561. +#define EXT_ROM_UCB4GH_ODDFRAME 0x04 /* 1 = odd frame captured */
  74562. +#define EXT_ROM_UCB4GH_1HL 0x08 /* first horizonal line after VGT falling edge */
  74563. +#define EXT_ROM_UCB4GH_ODD 0x10 /* odd frame indicator */
  74564. +#define EXT_ROM_UCB4GH_INTSTAT 0x20 /* video interrupt */
  74565. #define VFAC_CTL1 0xe8
  74566. -#define VFAC_CTL1_CAPTURE 0x01 /* capture enable */
  74567. +#define VFAC_CTL1_CAPTURE 0x01 /* capture enable (only when VSYNC high)*/
  74568. #define VFAC_CTL1_VFAC_ENABLE 0x02 /* vfac enable */
  74569. #define VFAC_CTL1_FREEZE_CAPTURE 0x04 /* freeze capture */
  74570. #define VFAC_CTL1_FREEZE_CAPTURE_SYNC 0x08 /* sync freeze capture */
  74571. @@ -197,6 +319,13 @@
  74572. #define VFAC_CTL2_INVERT_OVSYNC 0x80 /* invert other vsync input */
  74573. #define VFAC_CTL3 0xea
  74574. +#define VFAC_CTL3_CAP_LARGE_FIFO 0x01 /* large capture fifo */
  74575. +#define VFAC_CTL3_CAP_INTERLACE 0x02 /* capture odd and even fields */
  74576. +#define VFAC_CTL3_CAP_HOLD_4NS 0x00 /* hold capture data for 4ns */
  74577. +#define VFAC_CTL3_CAP_HOLD_2NS 0x04 /* hold capture data for 2ns */
  74578. +#define VFAC_CTL3_CAP_HOLD_6NS 0x08 /* hold capture data for 6ns */
  74579. +#define VFAC_CTL3_CAP_HOLD_0NS 0x0c /* hold capture data for 0ns */
  74580. +#define VFAC_CTL3_CHROMAKEY 0x20 /* capture data will be chromakeyed */
  74581. #define VFAC_CTL3_CAP_IRQ 0x40 /* enable capture interrupt */
  74582. #define CAP_MEM_START 0xeb /* 18 bits */
  74583. @@ -235,26 +364,98 @@
  74584. #define BM_COUNT 0xbc090 /* read-only */
  74585. /*
  74586. - * Graphics Co-processor
  74587. + * TV registers
  74588. */
  74589. -#define CO_CMD_L_PATTERN_FGCOL 0x8000
  74590. -#define CO_CMD_L_INC_LEFT 0x0004
  74591. -#define CO_CMD_L_INC_UP 0x0002
  74592. -
  74593. -#define CO_CMD_H_SRC_PIXMAP 0x2000
  74594. -#define CO_CMD_H_BLITTER 0x0800
  74595. +#define TV_VBLANK_EVEN_START 0xbe43c
  74596. +#define TV_VBLANK_EVEN_END 0xbe440
  74597. +#define TV_VBLANK_ODD_START 0xbe444
  74598. +#define TV_VBLANK_ODD_END 0xbe448
  74599. +#define TV_SYNC_YGAIN 0xbe44c
  74600. +#define TV_UV_GAIN 0xbe450
  74601. +#define TV_PED_UVDET 0xbe454
  74602. +#define TV_UV_BURST_AMP 0xbe458
  74603. +#define TV_HSYNC_START 0xbe45c
  74604. +#define TV_HSYNC_END 0xbe460
  74605. +#define TV_Y_DELAY1 0xbe464
  74606. +#define TV_Y_DELAY2 0xbe468
  74607. +#define TV_UV_DELAY1 0xbe46c
  74608. +#define TV_BURST_START 0xbe470
  74609. +#define TV_BURST_END 0xbe474
  74610. +#define TV_HBLANK_START 0xbe478
  74611. +#define TV_HBLANK_END 0xbe47c
  74612. +#define TV_PED_EVEN_START 0xbe480
  74613. +#define TV_PED_EVEN_END 0xbe484
  74614. +#define TV_PED_ODD_START 0xbe488
  74615. +#define TV_PED_ODD_END 0xbe48c
  74616. +#define TV_VSYNC_EVEN_START 0xbe490
  74617. +#define TV_VSYNC_EVEN_END 0xbe494
  74618. +#define TV_VSYNC_ODD_START 0xbe498
  74619. +#define TV_VSYNC_ODD_END 0xbe49c
  74620. +#define TV_SCFL 0xbe4a0
  74621. +#define TV_SCFH 0xbe4a4
  74622. +#define TV_SCP 0xbe4a8
  74623. +#define TV_DELAYBYPASS 0xbe4b4
  74624. +#define TV_EQL_END 0xbe4bc
  74625. +#define TV_SERR_START 0xbe4c0
  74626. +#define TV_SERR_END 0xbe4c4
  74627. +#define TV_CTL 0xbe4dc /* reflects a previous register- MVFCLR, MVPCLR etc P241*/
  74628. +#define TV_VSYNC_VGA_HS 0xbe4e8
  74629. +#define TV_FLICK_XMIN 0xbe514
  74630. +#define TV_FLICK_XMAX 0xbe518
  74631. +#define TV_FLICK_YMIN 0xbe51c
  74632. +#define TV_FLICK_YMAX 0xbe520
  74633. +/*
  74634. + * Graphics Co-processor
  74635. + */
  74636. #define CO_REG_CONTROL 0xbf011
  74637. +#define CO_CTRL_BUSY 0x80
  74638. +#define CO_CTRL_CMDFULL 0x04
  74639. +#define CO_CTRL_FIFOEMPTY 0x02
  74640. +#define CO_CTRL_READY 0x01
  74641. +
  74642. #define CO_REG_SRC_WIDTH 0xbf018
  74643. -#define CO_REG_PIX_FORMAT 0xbf01c
  74644. -#define CO_REG_FORE_MIX 0xbf048
  74645. -#define CO_REG_FOREGROUND 0xbf058
  74646. -#define CO_REG_WIDTH 0xbf060
  74647. -#define CO_REG_HEIGHT 0xbf062
  74648. +#define CO_REG_PIXFMT 0xbf01c
  74649. +#define CO_PIXFMT_32BPP 0x03
  74650. +#define CO_PIXFMT_24BPP 0x02
  74651. +#define CO_PIXFMT_16BPP 0x01
  74652. +#define CO_PIXFMT_8BPP 0x00
  74653. +
  74654. +#define CO_REG_FGMIX 0xbf048
  74655. +#define CO_FG_MIX_ZERO 0x00
  74656. +#define CO_FG_MIX_SRC_AND_DST 0x01
  74657. +#define CO_FG_MIX_SRC_AND_NDST 0x02
  74658. +#define CO_FG_MIX_SRC 0x03
  74659. +#define CO_FG_MIX_NSRC_AND_DST 0x04
  74660. +#define CO_FG_MIX_DST 0x05
  74661. +#define CO_FG_MIX_SRC_XOR_DST 0x06
  74662. +#define CO_FG_MIX_SRC_OR_DST 0x07
  74663. +#define CO_FG_MIX_NSRC_AND_NDST 0x08
  74664. +#define CO_FG_MIX_SRC_XOR_NDST 0x09
  74665. +#define CO_FG_MIX_NDST 0x0a
  74666. +#define CO_FG_MIX_SRC_OR_NDST 0x0b
  74667. +#define CO_FG_MIX_NSRC 0x0c
  74668. +#define CO_FG_MIX_NSRC_OR_DST 0x0d
  74669. +#define CO_FG_MIX_NSRC_OR_NDST 0x0e
  74670. +#define CO_FG_MIX_ONES 0x0f
  74671. +
  74672. +#define CO_REG_FGCOLOUR 0xbf058
  74673. +#define CO_REG_BGCOLOUR 0xbf05c
  74674. +#define CO_REG_PIXWIDTH 0xbf060
  74675. +#define CO_REG_PIXHEIGHT 0xbf062
  74676. #define CO_REG_X_PHASE 0xbf078
  74677. #define CO_REG_CMD_L 0xbf07c
  74678. +#define CO_CMD_L_PATTERN_FGCOL 0x8000
  74679. +#define CO_CMD_L_INC_LEFT 0x0004
  74680. +#define CO_CMD_L_INC_UP 0x0002
  74681. +
  74682. #define CO_REG_CMD_H 0xbf07e
  74683. -#define CO_REG_SRC_PTR 0xbf170
  74684. +#define CO_CMD_H_BGSRCMAP 0x8000 /* otherwise bg colour */
  74685. +#define CO_CMD_H_FGSRCMAP 0x2000 /* otherwise fg colour */
  74686. +#define CO_CMD_H_BLITTER 0x0800
  74687. +
  74688. +#define CO_REG_SRC1_PTR 0xbf170
  74689. +#define CO_REG_SRC2_PTR 0xbf174
  74690. #define CO_REG_DEST_PTR 0xbf178
  74691. #define CO_REG_DEST_WIDTH 0xbf218
  74692. @@ -269,6 +470,7 @@
  74693. char *fb;
  74694. char dev_name[32];
  74695. unsigned int fb_size;
  74696. + unsigned int chip_id;
  74697. /*
  74698. * The following is a pointer to be passed into the
  74699. @@ -288,10 +490,19 @@
  74700. void (*disable_extregs)(struct cfb_info *);
  74701. };
  74702. +#define ID_IGA_1682 0
  74703. +#define ID_CYBERPRO_2000 1
  74704. +#define ID_CYBERPRO_2010 2
  74705. +#define ID_CYBERPRO_5000 3
  74706. +
  74707. +struct fb_var_screeninfo;
  74708. +
  74709. /*
  74710. * Note! Writing to the Cyber20x0 registers from an interrupt
  74711. * routine is definitely a bad idea atm.
  74712. */
  74713. int cyber2000fb_attach(struct cyberpro_info *info, int idx);
  74714. void cyber2000fb_detach(int idx);
  74715. -
  74716. +void cyber2000fb_enable_extregs(struct cfb_info *cfb);
  74717. +void cyber2000fb_disable_extregs(struct cfb_info *cfb);
  74718. +void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
  74719. diff -urN linux-2.4.26/drivers/video/dbmx1fb.c linux-2.4.26-vrs1/drivers/video/dbmx1fb.c
  74720. --- linux-2.4.26/drivers/video/dbmx1fb.c 1970-01-01 01:00:00.000000000 +0100
  74721. +++ linux-2.4.26-vrs1/drivers/video/dbmx1fb.c 2004-01-14 21:32:27.000000000 +0000
  74722. @@ -0,0 +1,2002 @@
  74723. +/******************************************************************************
  74724. + Copyright (C) 2002 Motorola GSG-China
  74725. +
  74726. + This program is free software; you can redistribute it and/or
  74727. + modify it under the terms of the GNU General Public License
  74728. + as published by the Free Software Foundation; either version 2
  74729. + of the License, or (at your option) any later version.
  74730. +
  74731. + This program is distributed in the hope that it will be useful,
  74732. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  74733. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  74734. + GNU General Public License for more details.
  74735. +
  74736. + You should have received a copy of the GNU General Public License
  74737. + along with this program; if not, write to the Free Software
  74738. + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  74739. +*******************************************************************************/
  74740. +/*****************************************************************************
  74741. + * File Name: dbmx1fb.c
  74742. + *
  74743. + * Progammers: Chen Ning, Zhang Juan
  74744. + *
  74745. + * Date of Creations: 10 DEC,2001
  74746. + *
  74747. + * Synopsis:
  74748. + *
  74749. + * Descirption: DB-MX1 LCD controller Linux frame buffer driver
  74750. + * This file is subject to the terms and conditions of the
  74751. + * GNU General Public License. See the file COPYING in the main
  74752. + * directory of this archive for more details.
  74753. + *
  74754. + * Modification History:
  74755. + * 10 DEC, 2001, initialization version, frame work for frame buffer driver
  74756. + *
  74757. +*******************************************************************************/
  74758. +#include <linux/config.h>
  74759. +#include <linux/module.h>
  74760. +#include <linux/kernel.h>
  74761. +#include <linux/sched.h>
  74762. +#include <linux/errno.h>
  74763. +#include <linux/string.h>
  74764. +#include <linux/ctype.h>
  74765. +#include <linux/mm.h>
  74766. +#include <linux/tty.h>
  74767. +#include <linux/slab.h>
  74768. +#include <linux/init.h>
  74769. +#include <linux/fb.h>
  74770. +#include <linux/delay.h>
  74771. +#include <linux/wrapper.h>
  74772. +#include <linux/selection.h>
  74773. +#include <linux/console.h>
  74774. +#include <linux/kd.h>
  74775. +#include <linux/vt_kern.h>
  74776. +
  74777. +#include <asm/hardware.h>
  74778. +#include <asm/io.h>
  74779. +#include <asm/irq.h>
  74780. +#include <asm/mach-types.h>
  74781. +#include <asm/uaccess.h>
  74782. +#include <asm/proc/pgtable.h>
  74783. +
  74784. +#include <video/fbcon.h>
  74785. +#include <video/fbcon-mfb.h>
  74786. +#include <video/fbcon-cfb4.h>
  74787. +#include <video/fbcon-cfb8.h>
  74788. +#include <video/fbcon-cfb16.h>
  74789. +
  74790. +#include "asm/arch/hardware.h"
  74791. +#include "asm/arch/platform.h"
  74792. +#include "asm/arch/memory.h"
  74793. +
  74794. +#include "dbmx1fb.h"
  74795. +
  74796. +#undef SUP_TTY0
  74797. +
  74798. +#define LCD_PM
  74799. +#ifdef LCD_PM
  74800. +#include <linux/pm.h>
  74801. +struct pm_dev *pm;
  74802. +#endif
  74803. +
  74804. +// PLAM - make sure fbmem.c also has this defined for full screen frame
  74805. +// buffer support in SDRAM
  74806. +#define FULL_SCREEN
  74807. +
  74808. +#undef HARDWARE_CURSOR
  74809. +// #undef HARDWARE_CURSOR
  74810. +#undef DEBUG
  74811. +
  74812. +
  74813. +/********************************************************************************/
  74814. +#ifdef DEBUG
  74815. +# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
  74816. +#define FUNC_START DPRINTK(KERN_ERR"start\n");
  74817. +#define FUNC_END DPRINTK(KERN_ERR"end\n");
  74818. +#else
  74819. +# define DPRINTK(fmt, args...)
  74820. +#define FUNC_START
  74821. +#define FUNC_END
  74822. +#endif
  74823. +
  74824. +#define _IO_ADDRESS(r) ((r)+0xf0000000)
  74825. +unsigned int READREG(unsigned int r)
  74826. +{
  74827. + volatile unsigned int * reg;
  74828. + reg = (volatile unsigned int*) _IO_ADDRESS(r);
  74829. + return *reg;
  74830. +}
  74831. +void WRITEREG(unsigned int r, unsigned int val)
  74832. +{
  74833. + volatile unsigned int *reg;
  74834. + reg = (volatile unsigned int*) _IO_ADDRESS(r);
  74835. + *reg = val;
  74836. + return;
  74837. +}
  74838. +
  74839. +#define FONT_DATA ((unsigned char *)font->data)
  74840. +struct fbcon_font_desc *font;
  74841. +
  74842. +/* Local LCD controller parameters */
  74843. +struct dbmx1fb_par{
  74844. + u_char *screen_start_address; /* Screen Start Address */
  74845. + u_char *v_screen_start_address;/* Virtul Screen Start Address */
  74846. + unsigned long screen_memory_size; /* screen memory size */
  74847. + unsigned int palette_size;
  74848. + unsigned int max_xres;
  74849. + unsigned int max_yres;
  74850. + unsigned int xres;
  74851. + unsigned int yres;
  74852. + unsigned int xres_virtual;
  74853. + unsigned int yres_virtual;
  74854. + unsigned int max_bpp;
  74855. + unsigned int bits_per_pixel;
  74856. + unsigned int currcon;
  74857. + unsigned int visual;
  74858. + unsigned int TFT :1;
  74859. + unsigned int color :1 ;
  74860. + unsigned int sharp :1 ;
  74861. +
  74862. + unsigned short cfb16[16];
  74863. +};
  74864. +
  74865. +#ifdef HARDWARE_CURSOR
  74866. +/* hardware cursor parameters */
  74867. +struct dbmx1fb_cursor{
  74868. + // int enable;
  74869. + int startx;
  74870. + int starty;
  74871. + int blinkenable;
  74872. + int blink_rate;
  74873. + int width;
  74874. + int height;
  74875. + int color[3];
  74876. + int state;
  74877. +};
  74878. +
  74879. +/* Frame buffer of LCD information */
  74880. +struct dbmx1fb_info{
  74881. + struct display_switch dispsw;
  74882. + struct dbmx1fb_cursor cursor;
  74883. +};
  74884. +#endif // HARDWARE_CURSOR
  74885. +
  74886. +static u_char* p_framebuffer_memory_address;
  74887. +static u_char* v_framebuffer_memory_address;
  74888. +
  74889. +/* Fake monspecs to fill in fbinfo structure */
  74890. +static struct fb_monspecs monspecs __initdata = {
  74891. + 30000, 70000, 50, 65, 0 /* Generic */
  74892. +};
  74893. +
  74894. +/* color map initial */
  74895. +static unsigned short __attribute__((unused)) color4map[16] = {
  74896. + 0x0000, 0x000f, 0x00f0, 0x0f2a, 0x0f00, 0x0f0f, 0x0f88, 0x0ccc,
  74897. + 0x0888, 0x00ff, 0x00f8, 0x0f44, 0x0fa6, 0x0f22, 0x0ff0, 0x0fff
  74898. +};
  74899. +
  74900. +static unsigned short gray4map[16] = {
  74901. + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  74902. + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f
  74903. +};
  74904. +
  74905. +static struct display global_disp; /* Initial (default) Display Settings */
  74906. +static struct fb_info fb_info;
  74907. +static struct fb_var_screeninfo init_var = {};
  74908. +static struct dbmx1fb_par current_par={ };
  74909. +
  74910. +/* Frame buffer device API */
  74911. +static int dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con,
  74912. + struct fb_info *info);
  74913. +static int dbmx1fb_get_var(struct fb_var_screeninfo *var, int con,
  74914. + struct fb_info *info);
  74915. +static int dbmx1fb_set_var(struct fb_var_screeninfo *var, int con,
  74916. + struct fb_info *info);
  74917. +static int dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  74918. + struct fb_info *info);
  74919. +static int dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  74920. + struct fb_info *info);
  74921. +
  74922. +/* Interface to the low level driver */
  74923. +static int dbmx1fb_switch(int con, struct fb_info *info);
  74924. +static void dbmx1fb_blank(int blank, struct fb_info *info);
  74925. +static int dbmx1fb_updatevar(int con, struct fb_info *info);
  74926. +
  74927. +/* Internal routines */
  74928. +static int _reserve_fb_memory(void);
  74929. +static void _install_cmap(int con, struct fb_info *info);
  74930. +static void _enable_lcd_controller(void);
  74931. +static void _disable_lcd_controller(void);
  74932. +static int _encode_var(struct fb_var_screeninfo *var,
  74933. + struct dbmx1fb_par *par);
  74934. +static int _decode_var(struct fb_var_screeninfo *var,
  74935. + struct dbmx1fb_par *par);
  74936. +
  74937. +/* initialization routines */
  74938. +static void __init _init_lcd_system(void);
  74939. +static int __init _init_lcd(void);
  74940. +static void __init _init_fbinfo(void);
  74941. +static int __init _reserve_fb_memory(void);
  74942. +
  74943. +/* frame buffer ops */
  74944. +static struct fb_ops dbmx1fb_ops = {
  74945. + owner: THIS_MODULE,
  74946. + fb_get_fix: dbmx1fb_get_fix,
  74947. + fb_get_var: dbmx1fb_get_var,
  74948. + fb_set_var: dbmx1fb_set_var,
  74949. + fb_get_cmap: dbmx1fb_get_cmap,
  74950. + fb_set_cmap: dbmx1fb_set_cmap,
  74951. +};
  74952. +
  74953. +#ifdef HARDWARE_CURSOR
  74954. +/* Hardware Cursor */
  74955. +static void dbmx1fb_cursor(struct display *p, int mode, int x, int y);
  74956. +static int dbmx1fb_set_font(struct display *d, int width, int height);
  74957. +static UINT8 cursor_color_map[] = {0xf8};
  74958. +static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state);
  74959. +static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb);
  74960. +static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink);
  74961. +
  74962. +struct display_switch dbmx1fb_cfb4 = {
  74963. + setup: fbcon_cfb4_setup,
  74964. + bmove: fbcon_cfb4_bmove,
  74965. + clear: fbcon_cfb4_clear,
  74966. + putc: fbcon_cfb4_putc,
  74967. + putcs: fbcon_cfb4_putcs,
  74968. + revc: fbcon_cfb4_revc,
  74969. + cursor: dbmx1fb_cursor,
  74970. + set_font: dbmx1fb_set_font,
  74971. + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
  74972. +};
  74973. +
  74974. +struct display_switch dbmx1fb_cfb8 = {
  74975. + setup: fbcon_cfb8_setup,
  74976. + bmove: fbcon_cfb8_bmove,
  74977. + clear: fbcon_cfb8_clear,
  74978. + putc: fbcon_cfb8_putc,
  74979. + putcs: fbcon_cfb8_putcs,
  74980. + revc: fbcon_cfb8_revc,
  74981. + cursor: dbmx1fb_cursor,
  74982. + set_font: dbmx1fb_set_font,
  74983. + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
  74984. +};
  74985. +
  74986. +struct display_switch dbmx1fb_cfb16 = {
  74987. + setup: fbcon_cfb16_setup,
  74988. + bmove: fbcon_cfb16_bmove,
  74989. + clear: fbcon_cfb16_clear,
  74990. + putc: fbcon_cfb16_putc,
  74991. + putcs: fbcon_cfb16_putcs,
  74992. + revc: fbcon_cfb16_revc,
  74993. + cursor: dbmx1fb_cursor,
  74994. + set_font: dbmx1fb_set_font,
  74995. + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
  74996. +};
  74997. +#endif // HARDWARE_CURSOR
  74998. +
  74999. +
  75000. +/*****************************************************************************
  75001. + * Function Name: dbmx1fb_getcolreg()
  75002. + *
  75003. + * Input: regno : Color register ID
  75004. + * red : Color map red[]
  75005. + * green : Color map green[]
  75006. + * blue : Color map blue[]
  75007. + * transparent : Flag
  75008. + * info : Fb_info database
  75009. + *
  75010. + * Value Returned: int : Return status.If no error, return 0.
  75011. + *
  75012. + * Description: Transfer to fb_xxx_cmap handlers as parameters to
  75013. + * control color registers
  75014. + *
  75015. + * Modification History:
  75016. + * 10 DEC,2001, Chen Ning
  75017. +******************************************************************************/
  75018. +#define RED 0xf00
  75019. +#define GREEN 0xf0
  75020. +#define BLUE 0x0f
  75021. +static int dbmx1fb_getcolreg(u_int regno, u_int *red, u_int *green,
  75022. + u_int *blue, u_int *trans, struct fb_info *info)
  75023. +{
  75024. + unsigned int val;
  75025. +
  75026. + FUNC_START;
  75027. +
  75028. + if(regno >= current_par.palette_size)
  75029. + return 1;
  75030. +
  75031. + val = READREG(DBMX1_LCD_MAPRAM+regno);
  75032. +
  75033. + if((current_par.bits_per_pixel == 4)&&(!current_par.color))
  75034. + {
  75035. + *red = *green = *blue = (val & BLUE) << 4;//TODO:
  75036. + *trans = 0;
  75037. + }
  75038. + else
  75039. + {
  75040. + *red = (val & RED) << 4;
  75041. + *green = (val & GREEN) << 8;
  75042. + *blue = (val & BLUE) << 12;
  75043. + *trans = 0;
  75044. + }
  75045. +
  75046. + FUNC_END;
  75047. + return 0;
  75048. +}
  75049. +
  75050. +/*****************************************************************************
  75051. + * Function Name: dbmx1fb_setcolreg()
  75052. + *
  75053. + * Input: regno : Color register ID
  75054. + * red : Color map red[]
  75055. + * green : Color map green[]
  75056. + * blue : Color map blue[]
  75057. + * transparent : Flag
  75058. + * info : Fb_info database
  75059. + *
  75060. + * Value Returned: int : Return status.If no error, return 0.
  75061. + *
  75062. + * Description: Transfer to fb_xxx_cmap handlers as parameters to
  75063. + * control color registers
  75064. + *
  75065. + * Modification History:
  75066. + * 10 DEC,2001, Chen Ning
  75067. + *****************************************************************************/
  75068. +static int
  75069. +dbmx1fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  75070. + u_int trans, struct fb_info *info)
  75071. +{
  75072. + unsigned int val=0;
  75073. + FUNC_START
  75074. + if(regno >= current_par.palette_size)
  75075. + return 1;
  75076. +
  75077. + if((current_par.bits_per_pixel == 4)&&(!current_par.color))
  75078. + val = (blue & 0x00f) << 12;//TODO:
  75079. + else
  75080. + {
  75081. + val = (blue >> 12 ) & BLUE;
  75082. + val |= (green >> 8) & GREEN;
  75083. + val |= (red >> 4) & RED;
  75084. + }
  75085. +
  75086. + if (regno < 16) {
  75087. + current_par.cfb16[regno] =
  75088. + regno | regno << 5 | regno << 10;
  75089. +}
  75090. +
  75091. + WRITEREG(DBMX1_LCD_MAPRAM+regno, val);
  75092. + FUNC_END;
  75093. + return 0;
  75094. +}
  75095. +
  75096. +/*****************************************************************************
  75097. + * Function Name: dbmx1fb_get_cmap()
  75098. + *
  75099. + * Input: cmap : Ouput data pointer
  75100. + * kspc : Kernel space flag
  75101. + * con : Console ID
  75102. + * info : Frame buffer information
  75103. + *
  75104. + * Value Returned: int : Return status.If no error, return 0.
  75105. + *
  75106. + * Description: Data is copied from hardware or local or system DISPAY,
  75107. + * and copied to cmap.
  75108. + *
  75109. + * Modification History:
  75110. + * 10 DEC,2001, Chen Ning
  75111. +******************************************************************************/
  75112. +static int
  75113. +dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  75114. + struct fb_info *info)
  75115. +{
  75116. + int err = 0;
  75117. +
  75118. + FUNC_START;
  75119. + DPRINTK("current_par.visual=%d\n", current_par.visual);
  75120. + if (con == current_par.currcon)
  75121. + err = fb_get_cmap(cmap, kspc, dbmx1fb_getcolreg, info);
  75122. + else if (fb_display[con].cmap.len)
  75123. + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  75124. + else
  75125. + fb_copy_cmap(fb_default_cmap(current_par.palette_size),
  75126. + cmap, kspc ? 0 : 2);
  75127. + FUNC_END;
  75128. + return err;
  75129. +}
  75130. +
  75131. +/*****************************************************************************
  75132. + * Function Name: dbmx1fb_set_cmap()
  75133. + *
  75134. + * Input: cmap : Ouput data pointer
  75135. + * kspc : Kernel space flag
  75136. + * con : Console ID
  75137. + * info : Frame buffer information
  75138. + *
  75139. + * Value Returned: int : Return status.If no error, return 0.
  75140. + *
  75141. + * Description: Copy data from cmap and copy to DISPLAY. If DISPLAy has no cmap,
  75142. + * allocate memory for it. If DISPLAY is current console and visible,
  75143. + * then hardware color map shall be set.
  75144. + *
  75145. + * Modification History:
  75146. + * 10 DEC,2001, Chen Ning
  75147. +******************************************************************************/
  75148. +static int
  75149. +dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
  75150. +{
  75151. + int err = 0;
  75152. +
  75153. + FUNC_START;
  75154. + DPRINTK("current_par.visual=%d\n", current_par.visual);
  75155. + if (!fb_display[con].cmap.len)
  75156. + err = fb_alloc_cmap(&fb_display[con].cmap,
  75157. + current_par.palette_size, 0);
  75158. +
  75159. + if (!err) {
  75160. + if (con == current_par.currcon)
  75161. + err = fb_set_cmap(cmap, kspc, dbmx1fb_setcolreg,
  75162. + info);
  75163. + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  75164. + }
  75165. + FUNC_END;
  75166. + return err;
  75167. +}
  75168. +/*****************************************************************************
  75169. + * Function Name: dbmx1fb_get_var()
  75170. + *
  75171. + * Input: var : Iuput data pointer
  75172. + * con : Console ID
  75173. + * info : Frame buffer information
  75174. + *
  75175. + * Value Returned: int : Return status.If no error, return 0.
  75176. + *
  75177. + * Functions Called: _encode_var()
  75178. + *
  75179. + * Description: Get color map from current, or global display[console]
  75180. + * used by ioctl
  75181. + *
  75182. + * Modification History:
  75183. + * 10 DEC,2001, Chen Ning
  75184. +******************************************************************************/
  75185. +static int
  75186. +dbmx1fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  75187. +{
  75188. + if (con == -1) {
  75189. + _encode_var(var, &current_par);
  75190. + } else
  75191. + *var = fb_display[con].var;
  75192. + return 0;
  75193. +}
  75194. +
  75195. +
  75196. +/*****************************************************************************
  75197. + * Function Name: dbmx1fb_updatevar()
  75198. + *
  75199. + * Value Returned: VOID
  75200. + *
  75201. + * Functions Called: VOID
  75202. + *
  75203. + * Description: Fill in display switch with LCD information,
  75204. + *
  75205. + * Modification History:
  75206. + * 10 DEC,2001, Chen Ning
  75207. +******************************************************************************/
  75208. +static int dbmx1fb_updatevar(int con, struct fb_info *info)
  75209. +{
  75210. + DPRINTK("entered\n");
  75211. + return 0;
  75212. +}
  75213. +
  75214. +
  75215. +/*****************************************************************************
  75216. + * Function Name: dbmx1fb_set_dispsw()
  75217. + *
  75218. + * Input: display : Iuput data pointer
  75219. + * dbmx1fb_info : Frame buffer of LCD information
  75220. + *
  75221. + * Value Returned: VOID
  75222. + *
  75223. + * Functions Called: VOID
  75224. + *
  75225. + * Description: Fill in display switch with LCD information,
  75226. + *
  75227. + * Modification History:
  75228. + * 10 DEC,2001, Chen Ning
  75229. +******************************************************************************/
  75230. +static void dbmx1fb_set_dispsw(struct display *disp
  75231. +#ifdef HARDWARE_CURSOR
  75232. + ,struct dbmx1fb_info *info
  75233. +#endif
  75234. + )
  75235. +{
  75236. + FUNC_START;
  75237. + switch (disp->var.bits_per_pixel) {
  75238. +#ifdef HARDWARE_CURSOR
  75239. +#ifdef FBCON_HAS_CFB4
  75240. + case 4:
  75241. + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  75242. + info->dispsw = dbmx1fb_cfb4;
  75243. + disp->dispsw = &info->dispsw;
  75244. + disp->dispsw_data = NULL;
  75245. + break;
  75246. +#endif
  75247. +#ifdef FBCON_HAS_CFB8
  75248. + case 8:
  75249. + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  75250. + info->dispsw = dbmx1fb_cfb8;
  75251. + disp->dispsw = &info->dispsw;
  75252. + disp->dispsw_data = NULL;
  75253. + break;
  75254. +#endif
  75255. +#ifdef FBCON_HAS_CFB16
  75256. + case 12:
  75257. + case 16:
  75258. + fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
  75259. + info->dispsw = dbmx1fb_cfb16;
  75260. + disp->dispsw = &info->dispsw;
  75261. + disp->dispsw_data = current_par.cfb16;
  75262. + break;
  75263. +#endif
  75264. +#else //!HARDWARE_CURSOR
  75265. + /* first step disable the hardware cursor */
  75266. +#ifdef FBCON_HAS_CFB4
  75267. + case 4:
  75268. + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  75269. + disp->dispsw = &fbcon_cfb4;
  75270. + disp->dispsw_data = NULL;
  75271. + break;
  75272. +#endif
  75273. +#ifdef FBCON_HAS_CFB8
  75274. + case 8:
  75275. + fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
  75276. + disp->dispsw = &fbcon_cfb8;
  75277. + disp->dispsw_data = NULL;
  75278. + break;
  75279. +#endif
  75280. +#ifdef FBCON_HAS_CFB16
  75281. + case 12:
  75282. + case 16:
  75283. + fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
  75284. + disp->dispsw = &fbcon_cfb16;
  75285. + disp->dispsw_data = current_par.cfb16;
  75286. + break;
  75287. +#endif
  75288. +
  75289. +#endif // HARDWARE_CURSOR
  75290. + default:
  75291. + disp->dispsw = &fbcon_dummy;
  75292. + disp->dispsw_data = NULL;
  75293. + }
  75294. +#ifdef HARDWARE_CURSOR
  75295. + if (&info->cursor)
  75296. + {
  75297. + info->dispsw.cursor = dbmx1fb_cursor;
  75298. + info->dispsw.set_font = dbmx1fb_set_font;
  75299. + }
  75300. +#endif // HARDWARE_CURSOR
  75301. + FUNC_END;
  75302. +}
  75303. +
  75304. +/*****************************************************************************
  75305. + * Function Name: dbmx1fb_set_var()
  75306. + *
  75307. + * Input: var : Iuput data pointer
  75308. + * con : Console ID
  75309. + * info : Frame buffer information
  75310. + *
  75311. + * Value Returned: int : Return status.If no error, return 0.
  75312. + *
  75313. + * Functions Called: dbmx1fb_decode_var()
  75314. + * dbmx1fb_encode_var()
  75315. + * dbmx1fb_set_dispsw()
  75316. + *
  75317. + * Description: set current_par by var, also set display data, specially the console
  75318. + * related fileops, then enable the lcd controller, and set cmap to
  75319. + * hardware.
  75320. + *
  75321. + * Modification History:
  75322. + * 10 DEC,2001, Chen Ning
  75323. +******************************************************************************/
  75324. +static int
  75325. +dbmx1fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  75326. +{
  75327. + struct display *display;
  75328. + int err, chgvar = 0;
  75329. + struct dbmx1fb_par par;
  75330. +
  75331. + FUNC_START;
  75332. + if (con >= 0)
  75333. + display = &fb_display[con]; /* Display settings for console */
  75334. + else
  75335. + display = &global_disp; /* Default display settings */
  75336. +
  75337. + /* Decode var contents into a par structure, adjusting any */
  75338. + /* out of range values. */
  75339. + if ((err = _decode_var(var, &par))){
  75340. + DPRINTK("decode var error!");
  75341. + return err;
  75342. + }
  75343. +
  75344. + // Store adjusted par values into var structure
  75345. + _encode_var(var, &par);
  75346. +
  75347. + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
  75348. + return 0;
  75349. +
  75350. + else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
  75351. + ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
  75352. + return -EINVAL;
  75353. +
  75354. + if (con >= 0) {
  75355. + if ((display->var.xres != var->xres) ||
  75356. + (display->var.yres != var->yres) ||
  75357. + (display->var.xres_virtual != var->xres_virtual) ||
  75358. + (display->var.yres_virtual != var->yres_virtual) ||
  75359. + (display->var.sync != var->sync) ||
  75360. + (display->var.bits_per_pixel != var->bits_per_pixel) ||
  75361. + (memcmp(&display->var.red, &var->red, sizeof(var->red))) ||
  75362. + (memcmp(&display->var.green, &var->green, sizeof(var->green)
  75363. + )) ||
  75364. + (memcmp(&display->var.blue, &var->blue, sizeof(var->blue))))
  75365. + chgvar = 1;
  75366. + }
  75367. +
  75368. + display->var = *var;
  75369. + display->screen_base = par.v_screen_start_address;
  75370. + display->visual = par.visual;
  75371. + display->type = FB_TYPE_PACKED_PIXELS;
  75372. + display->type_aux = 0;
  75373. + display->ypanstep = 0;
  75374. + display->ywrapstep = 0;
  75375. + display->line_length =
  75376. + display->next_line = (var->xres * 16) / 8;
  75377. +
  75378. + display->can_soft_blank = 1;
  75379. + display->inverse = 0;
  75380. +
  75381. + dbmx1fb_set_dispsw(display
  75382. +#ifdef HARDWARE_CURSOR
  75383. + , (struct dbmx1fb_info *)info
  75384. +#endif // HARDWARE_CURSOR
  75385. + );
  75386. +
  75387. + /* If the console has changed and the console has defined */
  75388. + /* a changevar function, call that function. */
  75389. + if (chgvar && info && info->changevar)
  75390. + info->changevar(con); // TODO:
  75391. +
  75392. + /* If the current console is selected and it's not truecolor,
  75393. + * update the palette
  75394. + */
  75395. + if ((con == current_par.currcon) &&
  75396. + (current_par.visual != FB_VISUAL_TRUECOLOR)) {
  75397. + struct fb_cmap *cmap;
  75398. +
  75399. + current_par = par; // TODO ?
  75400. + if (display->cmap.len)
  75401. + cmap = &display->cmap;
  75402. + else
  75403. + cmap = fb_default_cmap(current_par.palette_size);
  75404. +
  75405. + fb_set_cmap(cmap, 1, dbmx1fb_setcolreg, info);
  75406. + }
  75407. +
  75408. + /* If the current console is selected, activate the new var. */
  75409. + if (con == current_par.currcon){
  75410. + init_var = *var; // TODO:gcc support structure copy?
  75411. + _enable_lcd_controller();
  75412. + }
  75413. +
  75414. + FUNC_END;
  75415. + return 0;
  75416. +}
  75417. +
  75418. +/*****************************************************************************
  75419. + * Function Name: dbmx1fb_get_fix()
  75420. + *
  75421. + * Input: fix : Ouput data pointer
  75422. + * con : Console ID
  75423. + * info : Frame buffer information
  75424. + *
  75425. + * Value Returned: int : Return status.If no error, return 0.
  75426. + *
  75427. + * Functions Called: VOID
  75428. + *
  75429. + * Description: get fix from display data, current_par data
  75430. + * used by ioctl
  75431. + *
  75432. + * Modification History:
  75433. + * 10 DEC,2001, Chen Ning
  75434. +******************************************************************************/
  75435. +static int
  75436. +dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  75437. +{
  75438. + struct display *display;
  75439. +
  75440. + FUNC_START;
  75441. + memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  75442. + strcpy(fix->id, DBMX1_NAME);
  75443. +
  75444. + if (con >= 0)
  75445. + {
  75446. + DPRINTK("Using console specific display for con=%d\n",con);
  75447. + display = &fb_display[con]; /* Display settings for console */
  75448. + }
  75449. + else
  75450. + display = &global_disp; /* Default display settings */
  75451. +
  75452. + fix->smem_start = (unsigned long)current_par.screen_start_address;
  75453. + fix->smem_len = current_par.screen_memory_size;
  75454. +//printk("dbmx1fb_get_fix, pointer fix: 0x%08x, smem_len: 0x%08x\n",fix,fix->smem_len);
  75455. + fix->type = display->type;
  75456. + fix->type_aux = display->type_aux;
  75457. + fix->xpanstep = 0;
  75458. + fix->ypanstep = display->ypanstep;
  75459. + fix->ywrapstep = display->ywrapstep;
  75460. + fix->visual = display->visual;
  75461. + fix->line_length = display->line_length;
  75462. + fix->accel = FB_ACCEL_NONE;
  75463. +
  75464. + FUNC_END;
  75465. + return 0;
  75466. +}
  75467. +
  75468. +/*****************************************************************************
  75469. + * Function Name: dbmx1fb_inter_handler()
  75470. + *
  75471. + * Input:
  75472. + *
  75473. + * Value Returned: VOID
  75474. + *
  75475. + * Functions Called: VOID
  75476. + *
  75477. + * Description: Interrupt handler
  75478. + *
  75479. + * Modification History:
  75480. + * 10 DEC,2001, Chen Ning
  75481. +******************************************************************************/
  75482. +static void dbmx1fb_inter_handler(int irq, void *dev_id, struct pt_regs *regs)
  75483. +{
  75484. + unsigned int intsr;
  75485. + FUNC_START;
  75486. + intsr = READREG(DBMX1_LCD_INTSR); // read to clear status
  75487. + printk(KERN_ERR"lcd interrupt!\n");
  75488. + FUNC_END;
  75489. + // handle
  75490. +}
  75491. +
  75492. +#ifdef LCD_PM
  75493. +#define PM_OPT " [pm]"
  75494. +#define LCD_PMST_RESUME 0
  75495. +#define LCD_PMST_SUSPEND 1
  75496. +static unsigned int lcd_pm_status = LCD_PMST_RESUME;
  75497. +
  75498. +void lcd_pm_resume(void)
  75499. +{
  75500. + if(lcd_pm_status == LCD_PMST_RESUME)
  75501. + return;
  75502. + WRITEREG(0x21c21c, 0x10000); // light on
  75503. + WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
  75504. + WRITEREG(DBMX1_LCD_PWMR, 0x00a9008a);
  75505. + lcd_pm_status = LCD_PMST_RESUME;
  75506. +// printk(KERN_ERR"lcd resumed\n");
  75507. +}
  75508. +
  75509. +void lcd_pm_suspend(void)
  75510. +{
  75511. + unsigned val;
  75512. + if(lcd_pm_status == LCD_PMST_SUSPEND)
  75513. + return;
  75514. + val = READREG(0x20502c);
  75515. + val |= 0x8000;
  75516. + WRITEREG(0x20502c, val);
  75517. + //To produce enough dealy time before trun off the LCDC.
  75518. + for(val=0;val<=600000;val++);
  75519. + val = READREG(0x21c21c);
  75520. + val &= ~0x10000;
  75521. + WRITEREG(0x21c21c, val); // light off
  75522. + WRITEREG(DBMX1_LCD_REFMCR, 0x0);
  75523. + lcd_pm_status = LCD_PMST_SUSPEND;
  75524. +// printk(KERN_ERR"lcd suspended\n");
  75525. +}
  75526. +
  75527. +int lcd_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
  75528. +{
  75529. + switch(rqst){
  75530. + case PM_RESUME:
  75531. + lcd_pm_resume();
  75532. + break;
  75533. + case PM_SUSPEND:
  75534. + lcd_pm_suspend();
  75535. + break;
  75536. + default:
  75537. + break;
  75538. + }
  75539. + return 0;
  75540. +}
  75541. +#endif // LCD_PM
  75542. +
  75543. +/*****************************************************************************
  75544. + * Function Name: dbmx1fb_init()
  75545. + *
  75546. + * Input: VOID
  75547. + *
  75548. + * Value Returned: int : Return status.If no error, return 0.
  75549. + *
  75550. + * Functions Called: _init_fbinfo()
  75551. + * disable_irq()
  75552. + * enable_irq()
  75553. + * _init_lcd()
  75554. + * dbmx1fb_init_cursor()
  75555. + *
  75556. + * Description: initialization module, all of init routine's entry point
  75557. + * initialize fb_info, init_var, current_par
  75558. + * and setup interrupt, memory, lcd controller
  75559. + *
  75560. + * Modification History:
  75561. + * 10 DEC,2001, Chen Ning
  75562. +******************************************************************************/
  75563. +int __init dbmx1fb_init(void)
  75564. +{
  75565. + int ret;
  75566. +#ifdef HARDWARE_CURSOR
  75567. + struct dbmx1fb_info *info;
  75568. +#endif // HARDWARE_CURSOR
  75569. +
  75570. + _init_lcd_system();
  75571. +
  75572. + _init_fbinfo();
  75573. +
  75574. + if ((ret = _reserve_fb_memory()) != 0){
  75575. + printk(KERN_ERR"failed for reserved DBMX frame buffer memory\n");
  75576. + return ret;
  75577. + }
  75578. +
  75579. +#if 0
  75580. + if (request_irq(IRQ_LCD,
  75581. + dbmx1fb_inter_handler,
  75582. + SA_INTERRUPT,
  75583. + DEV_NAME,
  75584. + NULL) != 0) {
  75585. + printk(KERN_ERR "dbmx1fb: failed in request_irq\n");
  75586. + return -EBUSY;
  75587. + }
  75588. +
  75589. + disable_irq(IRQ_LCD);
  75590. +#endif
  75591. + if (dbmx1fb_set_var(&init_var, -1, &fb_info))
  75592. + ; //current_par.allow_modeset = 0;
  75593. +
  75594. + _init_lcd();
  75595. + _enable_lcd_controller();
  75596. +
  75597. +#ifdef HARDWARE_CURSOR
  75598. + info = kmalloc(sizeof(struct dbmx1fb_info), GFP_KERNEL);
  75599. + if(info == NULL){
  75600. + printk(KERN_ERR"can not kmalloc dbmx1fb_info memory\n");
  75601. + return -1;
  75602. + }
  75603. +
  75604. + memset(info,0,sizeof(struct dbmx1fb_info));
  75605. +
  75606. + info->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
  75607. + info->cursor.blinkenable = 0;
  75608. + info->cursor.state = LCD_CURSOR_OFF;
  75609. + WRITEREG(DBMX1_LCD_LCXYP,0x90010001);
  75610. + WRITEREG(DBMX1_LCD_CURBLKCR,0x1F1F0000);
  75611. + WRITEREG(DBMX1_LCD_LCHCC,0x0000F800);
  75612. +
  75613. + DPRINTK(KERN_ERR"LCXYP = %x\n",READREG(DBMX1_LCD_LCXYP));
  75614. + DPRINTK(KERN_ERR"CURBLICR = %x\n",READREG(DBMX1_LCD_CURBLKCR));
  75615. + DPRINTK(KERN_ERR"LCHCC = %x\n",READREG(DBMX1_LCD_LCHCC));
  75616. +
  75617. + //dbmx1fb_set_cursor(info);
  75618. + //info->cursor = dbmx1fb_init_cursor(info);
  75619. +#endif // HARDWARE_CURSOR
  75620. +
  75621. + register_framebuffer(&fb_info);
  75622. +
  75623. +#ifdef LCD_PM
  75624. + pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, lcd_pm_handler);
  75625. + printk("register LCD power management successfully.\n");
  75626. +#endif
  75627. +#if 0
  75628. + enable_irq(IRQ_LCD); // TODO:
  75629. +#endif
  75630. + /* This driver cannot be unloaded at the moment */
  75631. + MOD_INC_USE_COUNT;
  75632. +
  75633. + return 0;
  75634. +}
  75635. +
  75636. +/*****************************************************************************
  75637. + * Function Name: dbmx1fb_setup()
  75638. + *
  75639. + * Input: info : VOID
  75640. + *
  75641. + * Value Returned: int : Return status.If no error, return 0.
  75642. + *
  75643. + * Functions Called: VOID
  75644. + *
  75645. + * Description: basically, this routine used to parse command line parameters, which
  75646. + * is initialization parameters for lcd controller, such as freq, xres,
  75647. + * yres, and so on
  75648. + *
  75649. + * Modification History:
  75650. + * 10 DEC,2001, Chen Ning
  75651. +******************************************************************************/
  75652. +int __init dbmx1fb_setup(char *options)
  75653. +{
  75654. + FUNC_START;
  75655. + FUNC_END;
  75656. + return 0;
  75657. +}
  75658. +
  75659. +/*****************************************************************************
  75660. + * Function Name: _init_fbinfo()
  75661. + *
  75662. + * Input: VOID
  75663. + *
  75664. + * Value Returned: VOID
  75665. + *
  75666. + * Functions Called: VOID
  75667. + *
  75668. + * Description: while 16bpp is used to store a 12 bits pixels packet, but
  75669. + * it is not a really 16bpp system. maybe in-compatiable with
  75670. + * other system or GUI.There are some field in var which specify
  75671. + * the red/green/blue offset in a 16bit word, just little endian is
  75672. + * concerned
  75673. + *
  75674. + * Modification History:
  75675. + * 10 DEC,2001, Chen Ning
  75676. +******************************************************************************/
  75677. +static void __init _init_fbinfo(void)
  75678. +{
  75679. +// Thomas Wong add this for debugging
  75680. +// *((unsigned char *)0xF5000008) = '&';
  75681. +
  75682. + FUNC_START;
  75683. + strcpy(fb_info.modename, DBMX1_NAME);
  75684. + strcpy(fb_info.fontname, "Acorn8x8");
  75685. +
  75686. + fb_info.node = -1;
  75687. + fb_info.flags = FBINFO_FLAG_DEFAULT; // Low-level driver is not a module
  75688. + fb_info.fbops = &dbmx1fb_ops;
  75689. + fb_info.monspecs = monspecs;
  75690. + fb_info.disp = &global_disp;
  75691. + fb_info.changevar = NULL;
  75692. + fb_info.switch_con = dbmx1fb_switch;
  75693. + fb_info.updatevar = dbmx1fb_updatevar;
  75694. + fb_info.blank = dbmx1fb_blank;
  75695. +
  75696. +/*
  75697. + * * setup initial parameters
  75698. + * */
  75699. + memset(&init_var, 0, sizeof(init_var));
  75700. +
  75701. + init_var.transp.length = 0;
  75702. + init_var.nonstd = 0;
  75703. + init_var.activate = FB_ACTIVATE_NOW;
  75704. + init_var.xoffset = 0;
  75705. + init_var.yoffset = 0;
  75706. + init_var.height = -1;
  75707. + init_var.width = -1;
  75708. + init_var.vmode = FB_VMODE_NONINTERLACED;
  75709. +
  75710. + if (1) {
  75711. + current_par.max_xres = LCD_MAXX;
  75712. + current_par.max_yres = LCD_MAXY;
  75713. + current_par.max_bpp = LCD_MAX_BPP; // 12
  75714. + init_var.red.length = 5; // 5;
  75715. + init_var.green.length = 6; // 6;
  75716. + init_var.blue.length = 5; // 5;
  75717. +#ifdef __LITTLE_ENDIAN
  75718. + init_var.red.offset = 11;
  75719. + init_var.green.offset = 5;
  75720. + init_var.blue.offset = 0;
  75721. +#endif //__LITTLE_ENDIAN
  75722. + init_var.grayscale = 16; // i suppose, TODO
  75723. + init_var.sync = 0;
  75724. + init_var.pixclock = 171521; // TODO
  75725. + }
  75726. +
  75727. + current_par.screen_start_address = NULL;
  75728. + current_par.v_screen_start_address = NULL;
  75729. + current_par.screen_memory_size = MAX_PIXEL_MEM_SIZE;
  75730. +// Thomas Wong add this for debugging
  75731. +//printk("_init_fbinfo, pointer to current_par: 0x%08x, screen_memory_size: 0x%08x\n", &current_par,current_par.screen_memory_size);
  75732. + current_par.currcon = -1; // TODO
  75733. +
  75734. + init_var.xres = current_par.max_xres;
  75735. + init_var.yres = current_par.max_yres;
  75736. + init_var.xres_virtual = init_var.xres;
  75737. + init_var.yres_virtual = init_var.yres;
  75738. + init_var.bits_per_pixel = current_par.max_bpp;
  75739. +
  75740. + FUNC_END;
  75741. +}
  75742. +
  75743. +/*****************************************************************************
  75744. + * Function Name: dbmx1fb_blank()
  75745. + *
  75746. + * Input: blank : Blank flag
  75747. + * info : Frame buffer database
  75748. + *
  75749. + * Value Returned: VOID
  75750. + *
  75751. + * Functions Called: _enable_lcd_controller()
  75752. + * _disable_lcd_controller()
  75753. + *
  75754. + * Description: blank the screen, if blank, disable lcd controller, while if no blank
  75755. + * set cmap and enable lcd controller
  75756. + *
  75757. + * Modification History:
  75758. + * 10 DEC,2001, Chen Ning
  75759. +******************************************************************************/
  75760. +static void
  75761. +dbmx1fb_blank(int blank, struct fb_info *info)
  75762. +{
  75763. +#ifdef SUP_TTY0
  75764. + int i;
  75765. +
  75766. + FUNC_START;
  75767. + DPRINTK("blank=%d info->modename=%s\n", blank, info->modename);
  75768. + if (blank) {
  75769. + if (current_par.visual != FB_VISUAL_TRUECOLOR)
  75770. + for (i = 0; i < current_par.palette_size; i++)
  75771. + ; // TODO
  75772. +//printk("Disable LCD\n");
  75773. + _disable_lcd_controller();
  75774. + }
  75775. + else {
  75776. + if (current_par.visual != FB_VISUAL_TRUECOLOR)
  75777. + dbmx1fb_set_cmap(&fb_display[current_par.currcon].cmap,
  75778. + 1,
  75779. + current_par.currcon, info);
  75780. +//printk("Enable LCD\n");
  75781. + _enable_lcd_controller();
  75782. + }
  75783. + FUNC_END;
  75784. +#endif //SUP_TTY0
  75785. +}
  75786. +
  75787. +/*****************************************************************************
  75788. + * Function Name: dbmx1fb_switch()
  75789. + *
  75790. + * Input: info : Frame buffer database
  75791. + *
  75792. + * Value Returned: VOID
  75793. + *
  75794. + * Functions Called:
  75795. + *
  75796. + * Description: Switch to another console
  75797. + *
  75798. + * Modification History:
  75799. + * 10 DEC,2001, Chen Ning
  75800. +******************************************************************************/
  75801. +static int dbmx1fb_switch(int con, struct fb_info *info)
  75802. +{
  75803. + FUNC_START;
  75804. + if (current_par.visual != FB_VISUAL_TRUECOLOR) {
  75805. + struct fb_cmap *cmap;
  75806. + if (current_par.currcon >= 0) {
  75807. + // Get the colormap for the selected console
  75808. + cmap = &fb_display[current_par.currcon].cmap;
  75809. +
  75810. + if (cmap->len)
  75811. + fb_get_cmap(cmap, 1, dbmx1fb_getcolreg, info);
  75812. + }
  75813. + }
  75814. +
  75815. + current_par.currcon = con;
  75816. + fb_display[con].var.activate = FB_ACTIVATE_NOW;
  75817. + dbmx1fb_set_var(&fb_display[con].var, con, info);
  75818. + FUNC_END;
  75819. + return 0;
  75820. +}
  75821. +
  75822. +/*****************************************************************************
  75823. + * Function Name: _encode_par()
  75824. + *
  75825. + * Input: var : Input var data
  75826. + * par : LCD controller parameters
  75827. + *
  75828. + * Value Returned: VOID
  75829. + *
  75830. + * Functions Called:
  75831. + *
  75832. + * Description: use current_par to set a var structure
  75833. + *
  75834. + * Modification History:
  75835. + * 10 DEC,2001, Chen Ning
  75836. +******************************************************************************/
  75837. +static int _encode_var(struct fb_var_screeninfo *var,
  75838. + struct dbmx1fb_par *par)
  75839. +{
  75840. + // Don't know if really want to zero var on entry.
  75841. + // Look at set_var to see. If so, may need to add extra params to par
  75842. +
  75843. + // memset(var, 0, sizeof(struct fb_var_screeninfo));
  75844. +
  75845. + var->xres = par->xres;
  75846. + var->yres = par->yres;
  75847. + var->xres_virtual = par->xres_virtual;
  75848. + var->yres_virtual = par->yres_virtual;
  75849. +
  75850. + var->bits_per_pixel = par->bits_per_pixel;
  75851. +
  75852. + DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
  75853. + switch(var->bits_per_pixel) {
  75854. + case 2:
  75855. + case 4:
  75856. + case 8:
  75857. + var->red.length = 4;
  75858. + var->green = var->red;
  75859. + var->blue = var->red;
  75860. + var->transp.length = 0;
  75861. + break;
  75862. + case 12: // This case should differ for Active/Passive mode
  75863. + case 16:
  75864. + if (1) {
  75865. + var->red.length = 4;
  75866. + var->blue.length = 4;
  75867. + var->green.length = 4;
  75868. + var->transp.length = 0;
  75869. +#ifdef __LITTLE_ENDIAN
  75870. + var->red.offset = 8;
  75871. + var->green.offset = 4;
  75872. + var->blue.offset = 0;
  75873. + var->transp.offset = 0;
  75874. +#endif // __LITTLE_ENDIAN
  75875. + }
  75876. + else
  75877. + {
  75878. + var->red.length = 5;
  75879. + var->blue.length = 5;
  75880. + var->green.length = 6;
  75881. + var->transp.length = 0;
  75882. + var->red.offset = 11;
  75883. + var->green.offset = 5;
  75884. + var->blue.offset = 0;
  75885. + var->transp.offset = 0;
  75886. + }
  75887. + break;
  75888. + }
  75889. +
  75890. + return 0;
  75891. +}
  75892. +
  75893. +/*****************************************************************************
  75894. + * Function Name: _decode_var
  75895. + *
  75896. + * Input: var : Input var data
  75897. + * par : LCD controller parameters
  75898. + *
  75899. + * Value Returned: VOID
  75900. + *
  75901. + * Functions Called: VOID
  75902. + *
  75903. + * Description: Get the video params out of 'var'. If a value doesn't fit,
  75904. + * round it up,if it's too big, return -EINVAL.
  75905. + *
  75906. + * Cautions: Round up in the following order: bits_per_pixel, xres,
  75907. + * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
  75908. + * bitfields, horizontal timing, vertical timing.
  75909. + *
  75910. + * Modification History:
  75911. + * 10 DEC,2001, Chen Ning
  75912. +******************************************************************************/
  75913. +static int _decode_var(struct fb_var_screeninfo *var,
  75914. + struct dbmx1fb_par *par)
  75915. +{
  75916. + *par = current_par;
  75917. +
  75918. + if ((par->xres = var->xres) < MIN_XRES)
  75919. + par->xres = MIN_XRES;
  75920. + if ((par->yres = var->yres) < MIN_YRES)
  75921. + par->yres = MIN_YRES;
  75922. + if (par->xres > current_par.max_xres)
  75923. + par->xres = current_par.max_xres;
  75924. + if (par->yres > current_par.max_yres)
  75925. + par->yres = current_par.max_yres;
  75926. + par->xres_virtual =
  75927. + var->xres_virtual < par->xres ? par->xres : var->xres_virtual;
  75928. + par->yres_virtual =
  75929. + var->yres_virtual < par->yres ? par->yres : var->yres_virtual;
  75930. + par->bits_per_pixel = var->bits_per_pixel;
  75931. +
  75932. + switch (par->bits_per_pixel) {
  75933. +#ifdef FBCON_HAS_CFB4
  75934. + case 4:
  75935. + par->visual = FB_VISUAL_PSEUDOCOLOR;
  75936. + par->palette_size = 16;
  75937. + break;
  75938. +#endif
  75939. +#ifdef FBCON_HAS_CFB8
  75940. + case 8:
  75941. + par->visual = FB_VISUAL_PSEUDOCOLOR;
  75942. + par->palette_size = 256;
  75943. + break;
  75944. +#endif
  75945. +#ifdef FBCON_HAS_CFB16
  75946. + case 12: // RGB 444
  75947. + case 16: /* RGB 565 */
  75948. + par->visual = FB_VISUAL_TRUECOLOR;
  75949. + par->palette_size = 0;
  75950. + break;
  75951. +#endif
  75952. + default:
  75953. + return -EINVAL;
  75954. + }
  75955. +
  75956. + par->screen_start_address =(u_char*)(
  75957. + (u_long)p_framebuffer_memory_address+PAGE_SIZE);
  75958. + par->v_screen_start_address =(u_char*)(
  75959. + (u_long)v_framebuffer_memory_address+PAGE_SIZE);
  75960. +
  75961. +// Thomas Wong - try to change start address here (map to SRAM, instead of SDRAM)
  75962. +#ifndef FULL_SCREEN
  75963. + par->screen_start_address =(u_char*)(0x00300000);
  75964. + par->v_screen_start_address =(u_char*)(0xF0300000);
  75965. +#endif
  75966. +
  75967. +// par->screen_start_address =(u_char*)(0x0BE00000);
  75968. +// par->v_screen_start_address =(u_char*)(0xFBE00000);
  75969. +
  75970. +// par->screen_start_address =(u_char*)(0x12000000);
  75971. +// par->v_screen_start_address =(u_char*)(0xF2000000);
  75972. +
  75973. + return 0;
  75974. +}
  75975. +
  75976. +
  75977. +/*****************************************************************************
  75978. + * Function Name: _reserve_fb_memory()
  75979. + *
  75980. + * Input: VOID
  75981. + *
  75982. + * Value Returned: VOID
  75983. + *
  75984. + * Functions Called:
  75985. + *
  75986. + * Description: get data out of var structure and set related LCD controller registers
  75987. + *
  75988. + * Modification History:
  75989. + * 10 DEC,2001, Chen Ning
  75990. +******************************************************************************/
  75991. +static int __init _reserve_fb_memory(void)
  75992. +{
  75993. + u_int required_pages;
  75994. + u_int extra_pages;
  75995. + u_int order;
  75996. + struct page *page;
  75997. + char *allocated_region;
  75998. +
  75999. + DPRINTK("frame buffer memory size = %x\n", (unsigned int)ALLOCATED_FB_MEM_SIZE);
  76000. + if (v_framebuffer_memory_address != NULL)
  76001. + return -EINVAL;
  76002. +
  76003. + /* Find order required to allocate enough memory for framebuffer */
  76004. + required_pages = ALLOCATED_FB_MEM_SIZE >> PAGE_SHIFT;
  76005. + for (order = 0 ; required_pages >> order ; order++) {;}
  76006. + extra_pages = (1 << order) - required_pages;
  76007. +
  76008. + if ((allocated_region =
  76009. + (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)) == NULL){
  76010. +
  76011. + DPRINTK("can not allocated memory\n");
  76012. + return -ENOMEM;
  76013. + }
  76014. +
  76015. +
  76016. + v_framebuffer_memory_address = (u_char *)allocated_region +
  76017. + (extra_pages << PAGE_SHIFT);
  76018. + p_framebuffer_memory_address = (u_char *)__virt_to_phys(
  76019. + (u_long)v_framebuffer_memory_address);
  76020. +#if 0
  76021. + printk(KERN_ERR"Frame buffer __get_free_pages vd:= %x, pd= %x",
  76022. + (unsigned int)v_framebuffer_memory_address,
  76023. + (unsigned int)p_framebuffer_memory_address);
  76024. +#endif
  76025. + /* Free all pages that we don't need but were given to us because */
  76026. + /* __get_free_pages() works on powers of 2. */
  76027. + for (;extra_pages;extra_pages--)
  76028. + free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT));
  76029. +
  76030. + /* Set reserved flag for fb memory to allow it to be remapped into */
  76031. + /* user space by the common fbmem driver using remap_page_range(). */
  76032. + for(page = virt_to_page(v_framebuffer_memory_address);
  76033. + page < virt_to_page(v_framebuffer_memory_address
  76034. + + ALLOCATED_FB_MEM_SIZE);
  76035. + page++)
  76036. + mem_map_reserve(page);
  76037. +#if 0
  76038. + /* Remap the fb memory to a non-buffered, non-cached region */
  76039. + v_framebuffer_memory_address = (u_char *)__ioremap(
  76040. + (u_long)p_framebuffer_memory_address,
  76041. + ALLOCATED_FB_MEM_SIZE,
  76042. + L_PTE_PRESENT |
  76043. + L_PTE_YOUNG |
  76044. + L_PTE_DIRTY |
  76045. + L_PTE_WRITE);
  76046. +#endif
  76047. + current_par.screen_start_address =(u_char*)(
  76048. + (u_long)p_framebuffer_memory_address+PAGE_SIZE);
  76049. + current_par.v_screen_start_address =(u_char*)(
  76050. + (u_long)v_framebuffer_memory_address+PAGE_SIZE);
  76051. +
  76052. + DPRINTK("physical screen start addres: %x\n",
  76053. + (u_long)p_framebuffer_memory_address+PAGE_SIZE);
  76054. +
  76055. +#ifndef FULL_SCREEN
  76056. +// Thomas Wong - we'll try to change the screen start address here
  76057. +// printk("\n\rMap LCD screen to SDRAM.\n\r");
  76058. +
  76059. + printk("\n\rMap LCD screen to embedded SRAM.\n\r");
  76060. + current_par.screen_start_address =(u_char*)(0x00300000);
  76061. + current_par.v_screen_start_address =(u_char*)(0xF0300000);
  76062. +#endif
  76063. +
  76064. +// printk("\n\rMap LCD screen to SDRAM 0xFBE00000.\n\r");
  76065. +// current_par.screen_start_address =(u_char*)(0x0BE00000);
  76066. +// current_par.v_screen_start_address =(u_char*)(0xFBE00000);
  76067. +
  76068. +// printk("\n\rMap LCD screen to SRAM 0x12000000.\n\r");
  76069. +// current_par.screen_start_address =(u_char*)(0x12000000);
  76070. +// current_par.v_screen_start_address =(u_char*)(0xF2000000);
  76071. +
  76072. + return (v_framebuffer_memory_address == NULL ? -EINVAL : 0);
  76073. +}
  76074. +
  76075. +/*****************************************************************************
  76076. + * Function Name: _enable_lcd_controller()
  76077. + *
  76078. + * Input: VOID
  76079. + *
  76080. + * Value Returned: VOID
  76081. + *
  76082. + * Functions Called:
  76083. + *
  76084. + * Description: enable Lcd controller, setup registers,
  76085. + * base on current_par value
  76086. + *
  76087. + * Modification History:
  76088. + * 10 DEC,2001, Chen Ning
  76089. +******************************************************************************/
  76090. +static void _enable_lcd_controller(void)
  76091. +{
  76092. + unsigned int val;
  76093. +#if 0
  76094. + int i;
  76095. + val =0;
  76096. +
  76097. + FUNC_START;
  76098. + _decode_var(&init_var, &current_par);
  76099. +
  76100. + val = current_par.xres/16;
  76101. + val <<= 20;
  76102. + val += current_par.yres;
  76103. + WRITEREG(DBMX1_LCD_XYMAX, val);
  76104. +
  76105. + val=0;
  76106. + val=current_par.xres_virtual /2;
  76107. + WRITEREG(DBMX1_LCD_VPW, val);
  76108. +
  76109. + switch(current_par.bits_per_pixel ){
  76110. + case 4: // for gray only
  76111. + for(i=0; i<16; i++){
  76112. + WRITEREG(DBMX1_LCD_MAPRAM+i, gray4map[i]);
  76113. + }
  76114. + WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_4);
  76115. + WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_4);
  76116. + WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_4);
  76117. + WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_4); // no interrupt
  76118. + WRITEREG(DBMX1_LCD_REFMCR, REFMCR_VAL_4);
  76119. + WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_4);
  76120. + WRITEREG(DBMX1_LCD_PWMR, PWMR_VAL);
  76121. + break;
  76122. + case 12:
  76123. + case 16:
  76124. + WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_12);
  76125. + WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_12);
  76126. + WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_12);
  76127. + WRITEREG(DBMX1_LCD_REFMCR, 0x0);
  76128. + WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
  76129. + WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
  76130. + WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002);
  76131. + WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
  76132. +
  76133. + break;
  76134. + }
  76135. +#else
  76136. + val = READREG(0x21c21c);
  76137. + val |= 0x0010000;
  76138. + WRITEREG(0x21c21c, val);
  76139. +
  76140. + WRITEREG(DBMX1_LCD_PWMR, 0x8200);
  76141. + WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
  76142. +
  76143. + // Thomas Wong - we want 0x8A not 0x200
  76144. +// WRITEREG(DBMX1_LCD_PWMR, 0x200);
  76145. +// PLAM -- for rev2 (endian bit)
  76146. +// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
  76147. + WRITEREG(DBMX1_LCD_PWMR, 0x00A9008A);
  76148. +// end PLAM
  76149. +#endif
  76150. +
  76151. + FUNC_END;
  76152. +}
  76153. +
  76154. +/*****************************************************************************
  76155. + * Function Name: _disable_lcd_controller()
  76156. + *
  76157. + * Input: VOID
  76158. + *
  76159. + * Value Returned: VOID
  76160. + *
  76161. + * Functions Called: VOID
  76162. + *
  76163. + * Description: just disable the LCD controller
  76164. + * disable lcd interrupt. others, i have no ideas
  76165. + *
  76166. + * Modification History:
  76167. + * 10 DEC,2001, Chen Ning
  76168. +******************************************************************************/
  76169. +static void _disable_lcd_controller(void)
  76170. +{
  76171. + unsigned int val;
  76172. + val = READREG(0x21c21c);
  76173. + val &= ~0x0010000;
  76174. + WRITEREG(0x21c21c, val);
  76175. +
  76176. + WRITEREG(DBMX1_LCD_PWMR, 0x8200);
  76177. +// WRITEREG(DBMX1_LCD_REFMCR, DISABLELCD_VAL);
  76178. + WRITEREG(0x205034, 0x0);
  76179. +}
  76180. +
  76181. +/*****************************************************************************
  76182. + * Function Name: _install_cmap
  76183. + *
  76184. + * Input: VOID
  76185. + *
  76186. + * Value Returned: VOID
  76187. + *
  76188. + * Functions Called:
  76189. + *
  76190. + * Description: set color map to hardware
  76191. + *
  76192. + * Modification History:
  76193. + * 10 DEC,2001, Chen Ning
  76194. +******************************************************************************/
  76195. +static void _install_cmap(int con, struct fb_info *info)
  76196. +{
  76197. + if (con != current_par.currcon)
  76198. + return ;
  76199. + if (fb_display[con].cmap.len)
  76200. + fb_set_cmap(&fb_display[con].cmap, 1, dbmx1fb_setcolreg, info);
  76201. + else
  76202. + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
  76203. + 1,
  76204. + dbmx1fb_setcolreg,
  76205. + info);
  76206. + return ;
  76207. +}
  76208. +
  76209. +/*****************************************************************************
  76210. + * Function Name: _init_lcd_system
  76211. + *
  76212. + * Input: VOID
  76213. + *
  76214. + * Value Returned: VOID
  76215. + *
  76216. + * Functions Called:
  76217. + *
  76218. + * Description: initialize the gpio port C and port D with DMA enable
  76219. + *
  76220. + * Modification History:
  76221. + * 10 DEC,2001, Chen Ning
  76222. +******************************************************************************/
  76223. +static void __init _init_lcd_system(void)
  76224. +{
  76225. +unsigned int val;
  76226. +
  76227. +/* Thomas Wong - we don't need DMA here
  76228. + // dma reset & enable
  76229. + val = READREG(0x209000);
  76230. + val |= 0x02;
  76231. + WRITEREG(0x209000, val);
  76232. + val = READREG(0x209000);
  76233. + val |= 0x01;
  76234. + WRITEREG(0x209000, val);
  76235. +*/
  76236. + // gpio
  76237. + //clear port D for LCD signal
  76238. + WRITEREG(0x21c320, 0x0);
  76239. + WRITEREG(0x21c338, 0x0);
  76240. +
  76241. + val = READREG(0x21c220);
  76242. + val |= 0x10000;
  76243. + WRITEREG(0x21c220, val);
  76244. + val = READREG(0x21c208);
  76245. + val |= 0x03;
  76246. + WRITEREG(0x21c208, val);
  76247. + val = READREG(0x21c200);
  76248. + val |= 0x10000;
  76249. + WRITEREG(0x21c200, val);
  76250. + val = READREG(0x21c238);
  76251. + val |= 0x10000;
  76252. + WRITEREG(0x21c238, val);
  76253. + val = READREG(0x21c21c);
  76254. + val |= 0x10000;
  76255. + WRITEREG(0x21c21c, val);
  76256. +
  76257. +}
  76258. +
  76259. +static void set_pclk(unsigned int fmhz)
  76260. +{
  76261. + unsigned int div= 96/fmhz;
  76262. + unsigned int reg;
  76263. + reg = READREG(0x21b020);
  76264. + reg &= ~0xf0;
  76265. + WRITEREG(0x21b020, reg);
  76266. + reg |= ((div-1)<<4) &0xf0;
  76267. + WRITEREG(0x21b020, reg);
  76268. +}
  76269. +
  76270. +/*****************************************************************************
  76271. + * Function Name: _init_lcd
  76272. + *
  76273. + * Input: VOID
  76274. + *
  76275. + * Value Returned: VOID
  76276. + *
  76277. + * Functions Called: _decode_var()
  76278. + *
  76279. + * Description: initialize the LCD controller, use current_par for 12bpp
  76280. + *
  76281. + * Modification History:
  76282. + * 10 DEC,2001, Chen Ning
  76283. +******************************************************************************/
  76284. +static int __init _init_lcd()
  76285. +{
  76286. +
  76287. + unsigned int val, rate;
  76288. + int i;
  76289. + unsigned char * pscr;
  76290. + //unsigned long pclk,temp,PCLKDIV2;
  76291. + //unsigned long MFI,MFN,PD,MFD,tempReg,MCUPLLCLK;
  76292. +
  76293. +
  76294. + _decode_var(&init_var, &current_par);
  76295. +
  76296. + // gpio begin
  76297. + val = READREG(0x21c21c);
  76298. + val &= ~0x00010000;
  76299. + WRITEREG(0x21c21c, val);
  76300. + DPRINTK(KERN_ERR"DR=%x\n", READREG(0x21c21c));
  76301. +
  76302. + // LCD regs
  76303. + DPRINTK(KERN_ERR"write SSA by %x\n",
  76304. + (unsigned int)current_par.screen_start_address);
  76305. + WRITEREG(DBMX1_LCD_SSA, (unsigned int)current_par.screen_start_address);
  76306. + DPRINTK(KERN_ERR"SSA=%x\n", READREG(DBMX1_LCD_SSA));
  76307. +
  76308. + val =0;
  76309. + val = current_par.xres/16;
  76310. + val = val<<20;
  76311. + val += current_par.yres;
  76312. + DPRINTK(KERN_ERR"par.x=%x, y=%x\n",
  76313. + current_par.xres,
  76314. + current_par.yres);
  76315. + WRITEREG(DBMX1_LCD_XYMAX, val);
  76316. + DPRINTK(KERN_ERR"XYMAX=%x\n", READREG(DBMX1_LCD_XYMAX));
  76317. +
  76318. + val=0;
  76319. + val=current_par.xres_virtual/2;
  76320. + WRITEREG(DBMX1_LCD_VPW, val);
  76321. + DPRINTK(KERN_ERR"VPW=%x\n", READREG(DBMX1_LCD_VPW));
  76322. +
  76323. + set_pclk(4);
  76324. +
  76325. + DPRINTK(KERN_ERR"DBMX1_LCD_PANELCFG=%x\n",
  76326. + READREG(DBMX1_LCD_PANELCFG));
  76327. +
  76328. + WRITEREG(DBMX1_LCD_HCFG, 0x04000f06);
  76329. + DPRINTK(KERN_ERR"DBMX1_LCD_HCFG=%x\n",
  76330. + READREG(DBMX1_LCD_HCFG));
  76331. +
  76332. + WRITEREG(DBMX1_LCD_VCFG, 0x04000907);
  76333. + DPRINTK(KERN_ERR"DBMX1_LCD_VCFG=%x\n",
  76334. + READREG(DBMX1_LCD_VCFG));
  76335. +
  76336. + WRITEREG(DBMX1_LCD_REFMCR, 0x0);
  76337. + DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
  76338. + READREG(DBMX1_LCD_REFMCR));
  76339. +
  76340. + WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
  76341. + DPRINTK(KERN_ERR"DBMX1_LCD_DMACR=%x\n",
  76342. + READREG(DBMX1_LCD_DMACR));
  76343. +
  76344. + WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
  76345. + DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
  76346. + READREG(DBMX1_LCD_PWMR));
  76347. +
  76348. + // Thomas Wong - we don't want to turn it on here
  76349. + /*
  76350. + WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002)
  76351. + DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
  76352. + READREG(DBMX1_LCD_REFMCR));
  76353. + */
  76354. +
  76355. + WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
  76356. + DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
  76357. + READREG(DBMX1_LCD_PWMR));
  76358. +
  76359. + // Thomas Wong
  76360. + WRITEREG(0x21B020, 0x000B005B);
  76361. +// PLAM -- for rev2 (new register and endian bits)
  76362. + WRITEREG(DBMX1_LCD_PANELCFG, 0xF8008B42); // little endian
  76363. +// WRITEREG(DBMX1_LCD_PANELCFG, 0xF8048B42); // big endian
  76364. + WRITEREG(DBMX1_LCD_LGPMR, 0x00090300);
  76365. +// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
  76366. + WRITEREG (DBMX1_LCD_PWMR, 0x009A008A);
  76367. +// end PLAM
  76368. +
  76369. +// PLAM -- for rev2 (new DMACR setting)
  76370. +// WRITEREG(DBMX1_LCD_DMACR, 0x800C0002);
  76371. + WRITEREG(DBMX1_LCD_DMACR, 0x00040008);
  76372. +//end PLAM
  76373. +
  76374. +
  76375. +#define DMACR_VAL_12 0x800C0002
  76376. +
  76377. +
  76378. +// WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_12);
  76379. +// DPRINTK(KERN_ERR"DBMX1_LCD_INTCR=%x\n",
  76380. +// READREG(DBMX1_LCD_INTCR));
  76381. +
  76382. + // warm up LCD
  76383. + for(i=0;i<10000000;i++) ;
  76384. +
  76385. + // gpio end
  76386. + val = READREG(0x21c21c);
  76387. + val |= 0x00010000;
  76388. + WRITEREG(0x21c21c, val);
  76389. + DPRINTK(KERN_ERR"DR=%x\n",
  76390. + READREG(0x21c21c));
  76391. +#if 0
  76392. + // clear screen
  76393. + pscr = current_par.v_screen_start_address;
  76394. + for(i=0; i< (current_par.screen_memory_size - 2*PAGE_SIZE); i++){
  76395. + *pscr++ = 0xff;
  76396. + }
  76397. +#endif
  76398. + DPRINTK(KERN_ERR"_init_lcd end \n");
  76399. +
  76400. + return 0;
  76401. +}
  76402. +
  76403. +#ifdef HARDWARE_CURSOR
  76404. +
  76405. +/*
  76406. + * Hardware cursor support
  76407. + */
  76408. + /*****************************************************************************
  76409. + * Function Name: dbmx1fb_set_cursor_color()
  76410. + *
  76411. + * Input: fb : frame buffer database
  76412. + * red : red component level in the cursor
  76413. + * green : green component level in the cursor
  76414. + * blue : blue component level in the cursor
  76415. + *
  76416. + * Value Returned: VOID
  76417. + *
  76418. + * Functions Called: VOID
  76419. + *
  76420. + * Description: Set color of hardware cursor
  76421. + *
  76422. + * Modification History:
  76423. + * 10 DEC,2001, Zhang Juan
  76424. +******************************************************************************/
  76425. +static void dbmx1fb_set_cursor_color(struct dbmx1fb_info *fb, UINT8 *red, UINT8 *green, UINT8 *blue)
  76426. +{
  76427. + struct dbmx1fb_cursor *c = &fb->cursor;
  76428. + UINT32 color;
  76429. +
  76430. + FUNC_START;
  76431. + c->color[0] = *red;
  76432. + c->color[1] = *green;
  76433. + c->color[2] = *blue;
  76434. + color = (UINT32)*red;
  76435. + color |= (UINT32)(*green>>5);
  76436. + color |= (UINT32)(*blue>>11);
  76437. +
  76438. + WRITEREG(DBMX1_LCD_LCHCC, color);
  76439. + FUNC_END;
  76440. +}
  76441. +
  76442. + /*****************************************************************************
  76443. + * Function Name: dbmx1fb_set_cursor()
  76444. + *
  76445. + * Input: fb : frame buffer database
  76446. + *
  76447. + * Value Returned: VOID
  76448. + *
  76449. + * Functions Called: VOID
  76450. + *
  76451. + * Description: Load information of hardware cursor
  76452. + *
  76453. + * Modification History:
  76454. + * 10 DEC,2001, Zhang Juan
  76455. +******************************************************************************/
  76456. +static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb)
  76457. +{
  76458. + struct dbmx1fb_cursor *c = &fb->cursor;
  76459. + UINT32 temp,tempReg,x,y;
  76460. +
  76461. + FUNC_START;
  76462. + //DPRINTK(KERN_ERR"BLINK_RATE=%x\n",c->blink_rate);
  76463. +// DPRINTK(KERN_ERR"width=%x\n",c->width);
  76464. +// DPRINTK(KERN_ERR"height=%x\n",c->height);
  76465. +
  76466. + x = c->startx << 16;
  76467. + if (c->state == LCD_CURSOR_ON)
  76468. + x |= CURSOR_ON_MASK;
  76469. +
  76470. +#ifdef FBCON_HAS_CFB4
  76471. + else if(c->state == LCD_CURSOR_REVERSED)
  76472. + x |= CURSOR_REVERSED_MASK;
  76473. + else if(c->state == LCD_CURSOR_ON_WHITE)
  76474. + x |= CURSOR_WHITE_MASK;
  76475. +#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
  76476. + else if(c->state == LCD_CURSOR_INVERT_BGD)
  76477. + x |= CURSOR_INVERT_MASK;
  76478. + else if(c->state == LCD_CURSOR_AND_BGD)
  76479. + x |= CURSOR_AND_BGD_MASK;
  76480. + else if(c->state == LCD_CURSOR_OR_BGD)
  76481. + x |= CURSOR_OR_BGD_MASK;
  76482. + else if(c->state == LCD_CURSOR_XOR_BGD)
  76483. + x |= CURSOR_XOR_BGD_MASK;
  76484. +#endif
  76485. + else
  76486. + x = c->startx;
  76487. +
  76488. + y = c->starty;
  76489. +
  76490. + temp = (UINT32)x | (UINT32)y;
  76491. + WRITEREG(DBMX1_LCD_LCXYP, temp);
  76492. + //DPRINTK(KERN_ERR"lcxyp=%x\n",READREG(DBMX1_LCD_LCXYP));
  76493. +
  76494. + temp = (UINT32)((c->width<<8) | (c->height));
  76495. + tempReg = (UINT32)((temp<<16) | c->blink_rate);
  76496. +
  76497. + WRITEREG(DBMX1_LCD_CURBLKCR, tempReg);
  76498. +
  76499. + //c->blink_rate = 10;
  76500. + if (c->blinkenable)
  76501. + dbmx1fb_set_cursor_blink(fb,c->blink_rate);
  76502. + DPRINTK(KERN_ERR"CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
  76503. + FUNC_END;
  76504. +}
  76505. +
  76506. + /*****************************************************************************
  76507. + * Function Name: dbmx1fb_set_cursor_blink()
  76508. + *
  76509. + * Input: fb : frame buffer database
  76510. + * blink : input blink frequency of cursor
  76511. + *
  76512. + * Value Returned: VOID
  76513. + *
  76514. + * Functions Called: VOID
  76515. + *
  76516. + * Description: Set blink frequency of hardware cursor
  76517. + *
  76518. + * Modification History:
  76519. + * 10 DEC,2001, Zhang Juan
  76520. +******************************************************************************/
  76521. +static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink)
  76522. +{
  76523. + struct dbmx1fb_cursor *c = &fb->cursor;
  76524. +
  76525. + unsigned long temp,tempReg;
  76526. + unsigned long PCD, XMAX, YMAX, PCLKDIV2;
  76527. + unsigned long tempMicroPeriod;
  76528. +
  76529. + FUNC_START;
  76530. + DPRINTK(KERN_ERR"dbmx1fb_set_cursor_blink\n");
  76531. +
  76532. + if(!c){
  76533. + DPRINTK(KERN_ERR"dangerouts, for c == null\n");
  76534. + }
  76535. + c->blink_rate = blink;
  76536. +
  76537. + tempReg = READREG(DBMX1_LCD_XYMAX);
  76538. + XMAX = (tempReg & XMAX_MASK) >> 20;
  76539. + YMAX = tempReg & YMAX_MASK;
  76540. + //XMAX = 240;
  76541. + //YMAX = 320;
  76542. + tempReg = READREG(PCDR);
  76543. + PCLKDIV2 = (tempReg & PCLKDIV2_MASK) >> 4;
  76544. + tempReg = READREG(DBMX1_LCD_PANELCFG);
  76545. + PCD = tempReg & PCD_MASK;
  76546. +
  76547. + temp = (PCLKDIV2 + 1);
  76548. +
  76549. + if (!blink)
  76550. + {
  76551. + /* disable the blinking cursor function when frequency is 0 */
  76552. + tempReg = READREG(DBMX1_LCD_CURBLKCR);
  76553. + tempReg &= CURSORBLINK_DIS_MASK;
  76554. + WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
  76555. + }
  76556. + else
  76557. + {
  76558. +
  76559. + tempMicroPeriod = temp * XMAX * YMAX * (PCD + 1);
  76560. + temp = 96*10000000/(blink * tempMicroPeriod);
  76561. + tempReg = READREG(DBMX1_LCD_CURBLKCR);
  76562. + tempReg |= CURSORBLINK_EN_MASK;
  76563. + tempReg |= temp;
  76564. + WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
  76565. + DPRINTK(KERN_ERR"Inter_CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
  76566. + }
  76567. +
  76568. + FUNC_END;
  76569. +}
  76570. +
  76571. + /*****************************************************************************
  76572. + * Function Name: dbmx1fb_set_cursor_state()
  76573. + *
  76574. + * Input: fb : frame buffer database
  76575. + * state : The status of the cursor to be set. e.g.
  76576. + * LCD_CURSOR_OFF
  76577. + * LCD_CURSOR_ON
  76578. + * LCD_CURSOR_REVERSED
  76579. + * LCD_CURSOR_ON_WHITE
  76580. + * LCD_CURSOR_OR_BGD
  76581. + * LCD_CURSOR_XOR_BGD
  76582. + * LCD_CURSOR_AND_BGD
  76583. + *
  76584. + * Value Returned: VOID
  76585. + *
  76586. + * Functions Called: VOID
  76587. + *
  76588. + * Description: Set state of cursor
  76589. + *
  76590. + * Modification History:
  76591. + * 10 DEC,2001, Zhang Juan
  76592. +******************************************************************************/
  76593. +static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state)
  76594. +{
  76595. + struct dbmx1fb_cursor *c = &fb->cursor;
  76596. + UINT32 temp;
  76597. +
  76598. + FUNC_START;
  76599. + c->state = state;
  76600. + temp = READREG(DBMX1_LCD_LCXYP);
  76601. + temp &= CURSOR_OFF_MASK;
  76602. +
  76603. + if (state == LCD_CURSOR_OFF)
  76604. + temp = temp;
  76605. + else if (state == LCD_CURSOR_ON)
  76606. + temp |= CURSOR_ON_MASK;
  76607. +#ifdef FBCON_HAS_CFB4
  76608. + else if (state == LCD_CURSOR_REVERSED)
  76609. + temp |= CURSOR_REVERSED_MASK;
  76610. + else if (state == LCD_CURSOR_ON_WHITE)
  76611. + temp |= CURSOR_WHITE_MASK;
  76612. +#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
  76613. + else if(state == LCD_CURSOR_INVERT_BGD)
  76614. + temp |= CURSOR_INVERT_MASK;
  76615. + else if (state == LCD_CURSOR_OR_BGD)
  76616. + temp |= CURSOR_OR_BGD_MASK;
  76617. + else if (state == LCD_CURSOR_XOR_BGD)
  76618. + temp |= CURSOR_XOR_BGD_MASK;
  76619. + else if (state == LCD_CURSOR_AND_BGD)
  76620. + temp |= CURSOR_AND_BGD_MASK;
  76621. +#endif
  76622. + WRITEREG(DBMX1_LCD_LCXYP,temp);
  76623. + DPRINTK(KERN_ERR"LCDXYP=%x\n",READREG(DBMX1_LCD_LCXYP));
  76624. + FUNC_END;
  76625. +}
  76626. +
  76627. +
  76628. +/*****************************************************************************
  76629. + * Function Name: dbmx1fb_cursor()
  76630. + *
  76631. + * Input: fb : frame buffer database
  76632. + *
  76633. + * Value Returned: cursor : The structure of hardware cursor
  76634. + *
  76635. + * Functions Called: dbmx1fb_set_cursor()
  76636. + * dbmx1fb_set_cursor_state()
  76637. + *
  76638. + * Description: The entry for display switch to operate hardware cursor
  76639. + *
  76640. + * Modification History:
  76641. + * 10 DEC,2001, Zhang Juan
  76642. +******************************************************************************/
  76643. +static void dbmx1fb_cursor(struct display *p, int mode, int x, int y)
  76644. +{
  76645. + struct dbmx1fb_info *fb = (struct dbmx1fb_info *)p->fb_info;
  76646. + struct dbmx1fb_cursor *c = &fb->cursor;
  76647. +
  76648. + FUNC_START;
  76649. + if (c==0) return;
  76650. +
  76651. +
  76652. + x *= fontwidth(p);
  76653. + y *= fontheight(p);
  76654. +
  76655. + c->startx = x;
  76656. + c->starty = y;
  76657. +
  76658. + switch (mode) {
  76659. + case CM_ERASE:
  76660. + dbmx1fb_set_cursor_state(fb,LCD_CURSOR_OFF);
  76661. + break;
  76662. +
  76663. + case CM_DRAW:
  76664. + case CM_MOVE:
  76665. + c->state = LCD_CURSOR_ON;
  76666. + dbmx1fb_set_cursor(fb);
  76667. + dbmx1fb_set_cursor_state(fb, c->state);
  76668. + break;
  76669. + }
  76670. + FUNC_END;
  76671. +}
  76672. +
  76673. +/*****************************************************************************
  76674. + * Function Name: dbmx1fb_set_font()
  76675. + *
  76676. + * Input: display : console datebase
  76677. + * width : The new width of cursor to be set.
  76678. + * height : The new height of cursor position to be set
  76679. + *
  76680. + * Value Returned: int : Return status.If no error, return 0.
  76681. + *
  76682. + * Functions Called: dbmx1fb_set_cursor()
  76683. + * dbmx1fb_set_cursor_color()
  76684. + *
  76685. + * Description: Set font for cursor
  76686. + *
  76687. + * Modification History:
  76688. + * 10 DEC,2001, Zhang Juan
  76689. +******************************************************************************/
  76690. +static int dbmx1fb_set_font(struct display *d, int width, int height)
  76691. +{
  76692. + struct dbmx1fb_info *fb=(struct dbmx1fb_info *)d->fb_info;
  76693. + struct dbmx1fb_cursor *c = &fb->cursor;
  76694. +
  76695. + FUNC_START;
  76696. + if(!d){
  76697. + printk(KERN_ERR"dbmx1fb_set_font d=null\n");
  76698. + return -1;
  76699. + }
  76700. +
  76701. + if (c) {
  76702. + if (!width || !height) {
  76703. + width = 16;
  76704. + height = 16;
  76705. + }
  76706. +
  76707. + c->width = width;
  76708. + c->height = height;
  76709. +
  76710. + DPRINTK(KERN_ERR"set cursor\n");
  76711. + dbmx1fb_set_cursor(fb);
  76712. + DPRINTK(KERN_ERR"set color cursor\n");
  76713. + dbmx1fb_set_cursor_color(fb, cursor_color_map,
  76714. + cursor_color_map, cursor_color_map);
  76715. + }else{
  76716. + DPRINTK(KERN_ERR"set cursor failed, cursor == null\n");
  76717. + }
  76718. +
  76719. + FUNC_END;
  76720. + return 1;
  76721. +}
  76722. +#endif // HARDWARE_CURSOR
  76723. +/* end of file */
  76724. +
  76725. diff -urN linux-2.4.26/drivers/video/dbmx1fb.h linux-2.4.26-vrs1/drivers/video/dbmx1fb.h
  76726. --- linux-2.4.26/drivers/video/dbmx1fb.h 1970-01-01 01:00:00.000000000 +0100
  76727. +++ linux-2.4.26-vrs1/drivers/video/dbmx1fb.h 2004-01-14 21:32:27.000000000 +0000
  76728. @@ -0,0 +1,213 @@
  76729. +/****************************************************************************
  76730. + *
  76731. + * Copyright (C) 2001, Chen Ning All Rights Reserved
  76732. + *
  76733. + * File Name: dbmx1fb.h
  76734. + *
  76735. + * Progammers: Chen Ning, Zhang Juan
  76736. + *
  76737. + * Date of Creations: 10 DEC,2001
  76738. + *
  76739. + * Synopsis:
  76740. + *
  76741. + * Descirption:
  76742. + *
  76743. + * Modification History:
  76744. + * 10 DEC, 2001, initialization version, frame work for frame buffer driver
  76745. + *
  76746. +*******************************************************************************/
  76747. +
  76748. +#ifndef LCDFB_H
  76749. +#define LCDFB_H
  76750. +#include "asm/arch/hardware.h"
  76751. +#include "asm/arch/platform.h"
  76752. +
  76753. +typedef signed char BOOLEAN;
  76754. +typedef unsigned char UINT8; /* Unsigned 8 bit quantity */
  76755. +typedef signed char SINT8; /* Signed 8 bit quantity */
  76756. +typedef unsigned short UINT16; /* Unsigned 16 bit quantity */
  76757. +typedef signed short SINT16; /* Signed 16 bit quantity */
  76758. +typedef unsigned long UINT32; /* Unsigned 32 bit quantity */
  76759. +typedef signed long SINT32; /* Signed 32 bit quantity */
  76760. +
  76761. +typedef volatile BOOLEAN VBOOLEAN;
  76762. +typedef volatile UINT8 VUINT8; /* Unsigned 8 bit quantity */
  76763. +typedef volatile SINT8 VSINT8; /* Signed 8 bit quantity */
  76764. +typedef volatile UINT16 VUINT16; /* Unsigned 16 bit quantity */
  76765. +typedef volatile SINT16 VSINT16; /* Signed 16 bit quantity */
  76766. +typedef volatile UINT32 VUINT32; /* Unsigned 32 bit quantity */
  76767. +typedef volatile SINT32 VSINT32; /* Signed 32 bit quantity */
  76768. +
  76769. +#define LCDBASE 0x00205000
  76770. +#define LCD_REGIONSIZE 0xc00
  76771. +
  76772. +#define DBMX1_LCD_SSA 0x00205000
  76773. +#define DBMX1_LCD_XYMAX 0x00205004
  76774. +#define DBMX1_LCD_VPW 0x00205008
  76775. +#define DBMX1_LCD_LCXYP 0x0020500c
  76776. +#define DBMX1_LCD_CURBLKCR 0x00205010
  76777. +#define DBMX1_LCD_LCHCC 0x00205014
  76778. +#define DBMX1_LCD_PANELCFG 0x00205018
  76779. +#define DBMX1_LCD_HCFG 0x0020501c
  76780. +#define DBMX1_LCD_VCFG 0x00205020
  76781. +#define DBMX1_LCD_POS 0x00205024
  76782. +#define DBMX1_LCD_LGPMR 0x00205028
  76783. +#define DBMX1_LCD_PWMR 0x0020502c
  76784. +#define DBMX1_LCD_DMACR 0x00205030
  76785. +#define DBMX1_LCD_REFMCR 0x00205034
  76786. +#define DBMX1_LCD_INTCR 0x00205038
  76787. +#define DBMX1_LCD_INTSR 0x00205040
  76788. +#define DBMX1_LCD_MAPRAM 0x00205800
  76789. +
  76790. +#define MPCTL0 0x0021B004
  76791. +#define PCDR 0X0021B020
  76792. +
  76793. +#define SSA DBMX1_LCD_SSA
  76794. +#define XYMAX DBMX1_LCD_XYMAX
  76795. +#define VPW DBMX1_LCD_VPW
  76796. +#define LCXYP DBMX1_LCD_LCXYP
  76797. +#define CURBLKCR DBMX1_LCD_CURBLKCR
  76798. +#define LCHCC DBMX1_LCD_LCHCC
  76799. +#define PANELCFG DBMX1_LCD_PANELCFG
  76800. +#define VCFG DBMX1_LCD_VCFG
  76801. +#define HCFG DBMX1_LCD_HCFG
  76802. +#define POS DBMX1_LCD_POS
  76803. +#define LGPMR DBMX1_LCD_LGPMR
  76804. +#define PWMR DBMX1_LCD_PWMR
  76805. +#define DMACR DBMX1_LCD_DMACR
  76806. +#define REFMCR DBMX1_LCD_REFMCR
  76807. +#define INTCR DBMX1_LCD_INTCR
  76808. +#define INTSR DBMX1_LCD_INTSR
  76809. +#define MAPRAM DBMX1_LCD_MAPRAM
  76810. +// default value
  76811. +#define SHARP_TFT_240x320
  76812. +
  76813. +#ifdef SHARP_TFT_240x320
  76814. +#define PANELCFG_VAL_12 0xf8008b48
  76815. +#define HCFG_VAL_12 0x04000f06
  76816. +#define VCFG_VAL_12 0x04000907
  76817. +#define PWMR_VAL 0x0000008a
  76818. +#define LCD_MAXX 240
  76819. +#define LCD_MAXY 320
  76820. +#else //SHARP_TFT_240x320
  76821. +
  76822. +#define PANELCFG_VAL_12 0xf8088c6b
  76823. +#define HCFG_VAL_12 0x04000f06
  76824. +#define VCFG_VAL_12 0x04010c03
  76825. +#define PWMR_VAL 0x00000200
  76826. +#define LCD_MAXX 320
  76827. +#define LCD_MAXY 240
  76828. +#endif // SHARP_TFT_240x320
  76829. +
  76830. +#define PANELCFG_VAL_4 0x20008c09
  76831. +#define PANELCFG_VAL_4C 0x60008c09
  76832. +
  76833. +#define HCFG_VAL_4 0x04000f07
  76834. +
  76835. +#define VCFG_VAL_4 0x04010c03
  76836. +
  76837. +
  76838. +#define REFMCR_VAL_4 0x00000003
  76839. +#define REFMCR_VAL_12 0x00000003
  76840. +#define DISABLELCD_VAL 0x00000000
  76841. +
  76842. +#define DMACR_VAL_4 0x800c0003 // 12 & 3 TRIGGER
  76843. +#define DMACR_VAL_12 0x00020008
  76844. +
  76845. +#define INTCR_VAL_4 0x00000000
  76846. +#define INTCR_VAL_12 0x00000000
  76847. +
  76848. +#define INTSR_UDRERR 0x00000008
  76849. +#define INTSR_ERRRESP 0x00000004
  76850. +#define INTSR_EOF 0x00000002
  76851. +#define INTSR_BOF 0x00000001
  76852. +
  76853. +#define MIN_XRES 64
  76854. +#define MIN_YRES 64
  76855. +
  76856. +#define LCD_MAX_BPP 16
  76857. +
  76858. +#if 0
  76859. +#define READREG(r) \
  76860. + inl(IO_ADDRESS(r))
  76861. +
  76862. +#define WRITEREG(r, val) \
  76863. + outl(val, IO_ADDRESS(r))
  76864. +#else
  76865. +#endif // 0
  76866. +
  76867. +#define MAX_PALETTE_NUM_ENTRIES 256
  76868. +#define MAX_PIXEL_MEM_SIZE \
  76869. + ((current_par.max_xres * current_par.max_yres * current_par.max_bpp)/8)
  76870. +#define MAX_FRAMEBUFFER_MEM_SIZE \
  76871. + (MAX_PIXEL_MEM_SIZE + 32)
  76872. +#define ALLOCATED_FB_MEM_SIZE \
  76873. + (PAGE_ALIGN(MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2))
  76874. +
  76875. + // TODO:
  76876. +#define FBCON_HAS_CFB4
  76877. +#define FBCON_HAS_CFB8
  76878. +#define FBCON_HAS_CFB16
  76879. +
  76880. +#define IRQ_LCD 12 // TODO: which irq?
  76881. +#define DBMX1_NAME "DBMX1FB"
  76882. +#define DEV_NAME DBMX1_NAME
  76883. +#define MAX_PALETTE_NUM_ENTRIES 256
  76884. +#define DEFAULT_CURSOR_BLINK_RATE (20)
  76885. +#define CURSOR_DRAW_DELAY (2)
  76886. +/*cursor status*/
  76887. +#define LCD_CURSOR_OFF 0
  76888. +#define LCD_CURSOR_ON 1
  76889. +
  76890. +#ifdef FBCON_HAS_CFB4
  76891. + #define LCD_CURSOR_REVERSED 2
  76892. + #define LCD_CURSOR_ON_WHITE 3
  76893. +#elif defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16)
  76894. + #define LCD_CURSOR_INVERT_BGD 2
  76895. + #define LCD_CURSOR_AND_BGD 3
  76896. + #define LCD_CURSOR_OR_BGD 4
  76897. + #define LCD_CURSOR_XOR_BGD 5
  76898. +#endif //FBCON_HAS_CFB4
  76899. +
  76900. +/* MASK use for caculating MCDUPLLCLK */
  76901. +#define MFI_MASK 0x00003C00
  76902. +#define MFN_MASK 0x000003FF
  76903. +#define PD_MASK 0x3C000000
  76904. +#define MFD_MASK 0x03FF0000
  76905. +#define PCLKDIV2_MASK 0x000000F0
  76906. +#define PCD_MASK 0x0000003F
  76907. +#define XMAX_MASK 0xF3F00000
  76908. +#define YMAX_MASK 0x000001FF
  76909. +#define HWAIT1_MASK 0x0000FF00
  76910. +#define HWAIT2_MASK 0x000000FF
  76911. +#define HWIDTH_MASK 0xFC000000
  76912. +#define PASSDIV_MASK 0x00FF0000
  76913. +#define VWAIT1_MASK 0x0000FF00
  76914. +#define VWAIT2_MASK 0x000000FF
  76915. +#define VWIDTH_MASK 0xFC000000
  76916. +#define CURSORBLINK_DIS_MASK 0x80000000
  76917. +
  76918. +#define DISPLAY_MODE_MASK 0x80000000
  76919. +
  76920. +#define MCU_FREQUENCE 32768
  76921. +#define COLOR_MASK 0x40000000
  76922. +
  76923. +/* MASK use for indicating the cursor status */
  76924. +#define CURSOR_ON_MASK 0x40000000
  76925. +#define CURSOR_OFF_MASK 0x0FFFFFFF
  76926. +#define MAX_CURSOR_WIDTH 31
  76927. +#define MAX_CURSOR_HEIGHT 31
  76928. +#define CURSORBLINK_EN_MASK 0x80000000
  76929. +
  76930. +#ifdef FBCON_HAS_CFB4
  76931. +#define CURSOR_REVERSED_MASK 0x80000000
  76932. +#define CURSOR_WHITE_MASK 0xC0000000
  76933. +#else
  76934. +#define CURSOR_INVERT_MASK 0x80000000
  76935. +#define CURSOR_AND_BGD_MASK 0xC0000000
  76936. +#define CURSOR_OR_BGD_MASK 0x50000000
  76937. +#define CURSOR_XOR_BGD_MASK 0x90000000
  76938. +#endif // FBCON_HAS_CFB4
  76939. +
  76940. +#endif //LCDFB_H
  76941. +
  76942. diff -urN linux-2.4.26/drivers/video/fbmem.c linux-2.4.26-vrs1/drivers/video/fbmem.c
  76943. --- linux-2.4.26/drivers/video/fbmem.c 2004-02-27 20:03:27.000000000 +0000
  76944. +++ linux-2.4.26-vrs1/drivers/video/fbmem.c 2004-02-27 22:56:39.000000000 +0000
  76945. @@ -61,7 +61,9 @@
  76946. extern int pm2fb_setup(char*);
  76947. extern int pm3fb_init(void);
  76948. extern int pm3fb_setup(char*);
  76949. +extern int clps711xfb_init(void);
  76950. extern int cyber2000fb_init(void);
  76951. +extern int cyber2000fb_setup(char*);
  76952. extern int retz3fb_init(void);
  76953. extern int retz3fb_setup(char*);
  76954. extern int clgenfb_init(void);
  76955. @@ -145,6 +147,8 @@
  76956. extern int sstfb_setup(char*);
  76957. extern int it8181fb_init(void);
  76958. extern int it8181fb_setup(char*);
  76959. +extern int anakinfb_init(void);
  76960. +extern int dbmx1fb_init(void);
  76961. static struct {
  76962. const char *name;
  76963. @@ -170,11 +174,14 @@
  76964. #ifdef CONFIG_FB_AMIGA
  76965. { "amifb", amifb_init, amifb_setup },
  76966. #endif
  76967. +#ifdef CONFIG_FB_CLPS711X
  76968. + { "clps711xfb", clps711xfb_init, NULL },
  76969. +#endif
  76970. #ifdef CONFIG_FB_CYBER
  76971. { "cyber", cyberfb_init, cyberfb_setup },
  76972. #endif
  76973. #ifdef CONFIG_FB_CYBER2000
  76974. - { "cyber2000", cyber2000fb_init, NULL },
  76975. + { "cyber2000", cyber2000fb_init, cyber2000fb_setup },
  76976. #endif
  76977. #ifdef CONFIG_FB_PM2
  76978. { "pm2fb", pm2fb_init, pm2fb_setup },
  76979. @@ -226,10 +233,10 @@
  76980. #endif
  76981. #ifdef CONFIG_FB_S3TRIO
  76982. { "s3trio", s3triofb_init, NULL },
  76983. -#endif
  76984. +#endif
  76985. #ifdef CONFIG_FB_FM2
  76986. { "fm2fb", fm2fb_init, fm2fb_setup },
  76987. -#endif
  76988. +#endif
  76989. #ifdef CONFIG_FB_SIS
  76990. { "sisfb", sisfb_init, sisfb_setup },
  76991. #endif
  76992. @@ -242,7 +249,7 @@
  76993. /*
  76994. * Generic drivers that are used as fallbacks
  76995. - *
  76996. + *
  76997. * These depend on resource management and must be initialized
  76998. * _after_ all other frame buffer devices that use resource
  76999. * management!
  77000. @@ -253,7 +260,7 @@
  77001. #endif
  77002. #ifdef CONFIG_FB_VESA
  77003. { "vesa", vesafb_init, vesafb_setup },
  77004. -#endif
  77005. +#endif
  77006. /*
  77007. * Chipset specific drivers that don't use resource management (yet)
  77008. @@ -276,7 +283,7 @@
  77009. #endif
  77010. #ifdef CONFIG_FB_HGA
  77011. { "hga", hgafb_init, hgafb_setup },
  77012. -#endif
  77013. +#endif
  77014. #ifdef CONFIG_FB_IGA
  77015. { "igafb", igafb_init, igafb_setup },
  77016. #endif
  77017. @@ -291,7 +298,7 @@
  77018. #endif
  77019. #ifdef CONFIG_FB_HP300
  77020. { "hpfb", hpfb_init, NULL },
  77021. -#endif
  77022. +#endif
  77023. #ifdef CONFIG_FB_G364
  77024. { "g364", g364fb_init, NULL },
  77025. #endif
  77026. @@ -307,6 +314,9 @@
  77027. #ifdef CONFIG_FB_TX3912
  77028. { "tx3912", tx3912fb_init, NULL },
  77029. #endif
  77030. +#ifdef CONFIG_FB_ANAKIN
  77031. + { "anakinfb", anakinfb_init, NULL },
  77032. +#endif
  77033. #ifdef CONFIG_FB_E1355
  77034. { "e1355fb", e1355fb_init, e1355fb_setup },
  77035. #endif
  77036. @@ -330,10 +340,13 @@
  77037. #endif
  77038. #ifdef CONFIG_FB_AU1100
  77039. { "au1100fb", au1100fb_init, au1100fb_setup },
  77040. -#endif
  77041. +#endif
  77042. #ifdef CONFIG_FB_IT8181
  77043. { "it8181fb", it8181fb_init, it8181fb_setup },
  77044. #endif
  77045. +#ifdef CONFIG_FB_DBMX1
  77046. + { "dbmx1fb", dbmx1fb_init, NULL },
  77047. +#endif
  77048. /*
  77049. @@ -342,7 +355,7 @@
  77050. #ifdef CONFIG_FB_VGA16
  77051. { "vga16", vga16fb_init, vga16fb_setup },
  77052. -#endif
  77053. +#endif
  77054. #ifdef CONFIG_FB_STI
  77055. { "stifb", stifb_init, stifb_setup },
  77056. #endif
  77057. @@ -371,7 +384,7 @@
  77058. struct fb_info *registered_fb[FB_MAX];
  77059. int num_registered_fb;
  77060. -extern int fbcon_softback_size;
  77061. +extern int fbcon_softback_size;
  77062. static int first_fb_vc;
  77063. static int last_fb_vc = MAX_NR_CONSOLES-1;
  77064. @@ -480,7 +493,7 @@
  77065. }
  77066. #endif /* CONFIG_KMOD */
  77067. -static int
  77068. +static int
  77069. fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
  77070. unsigned long arg)
  77071. {
  77072. @@ -492,7 +505,7 @@
  77073. struct fb_fix_screeninfo fix;
  77074. struct fb_con2fbmap con2fb;
  77075. int i;
  77076. -
  77077. +
  77078. if (! fb)
  77079. return -ENODEV;
  77080. switch (cmd) {
  77081. @@ -576,7 +589,7 @@
  77082. }
  77083. }
  77084. -static int
  77085. +static int
  77086. fb_mmap(struct file *file, struct vm_area_struct * vma)
  77087. {
  77088. int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
  77089. @@ -667,11 +680,11 @@
  77090. #elif defined(__sh__)
  77091. pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
  77092. #elif defined(__hppa__)
  77093. - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
  77094. + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
  77095. #elif defined(__ia64__)
  77096. vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  77097. #elif defined(__hppa__)
  77098. - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
  77099. + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
  77100. #else
  77101. #warning What do we have to do here??
  77102. #endif
  77103. @@ -724,7 +737,7 @@
  77104. return res;
  77105. }
  77106. -static int
  77107. +static int
  77108. fb_release(struct inode *inode, struct file *file)
  77109. {
  77110. int fbidx = GET_FB_IDX(inode->i_rdev);
  77111. @@ -856,7 +869,7 @@
  77112. *
  77113. */
  77114. -void __init
  77115. +void __init
  77116. fbmem_init(void)
  77117. {
  77118. int i;
  77119. @@ -904,7 +917,7 @@
  77120. if (!options || !*options)
  77121. return 0;
  77122. -
  77123. +
  77124. if (!strncmp(options, "scrollback:", 11)) {
  77125. options += 11;
  77126. if (*options) {
  77127. @@ -930,7 +943,7 @@
  77128. }
  77129. return 0;
  77130. }
  77131. -
  77132. +
  77133. if (!strncmp(options, "vc:", 3)) {
  77134. options += 3;
  77135. if (*options)
  77136. diff -urN linux-2.4.26/drivers/video/font_acorn_8x8.c linux-2.4.26-vrs1/drivers/video/font_acorn_8x8.c
  77137. --- linux-2.4.26/drivers/video/font_acorn_8x8.c 1998-09-30 04:56:33.000000000 +0100
  77138. +++ linux-2.4.26-vrs1/drivers/video/font_acorn_8x8.c 2004-01-14 21:32:27.000000000 +0000
  77139. @@ -11,33 +11,33 @@
  77140. /* 03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^C */
  77141. /* 04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^D */
  77142. /* 05 */ 0x00, 0x18, 0x3c, 0xe7, 0xe7, 0x3c, 0x18, 0x00, /* ^E */
  77143. -/* 06 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77144. -/* 07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77145. -/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77146. -/* 09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77147. -/* 0A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77148. -/* 0B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77149. -/* 0C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77150. -/* 0D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77151. -/* 0E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77152. -/* 0F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77153. +/* 06 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77154. +/* 07 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77155. +/* 08 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77156. +/* 09 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77157. +/* 0A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77158. +/* 0B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77159. +/* 0C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77160. +/* 0D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77161. +/* 0E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77162. +/* 0F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77163. /* 10 */ 0x00, 0x60, 0x78, 0x7e, 0x7e, 0x78, 0x60, 0x00, /* |> */
  77164. /* 11 */ 0x00, 0x06, 0x1e, 0x7e, 0x7e, 0x1e, 0x06, 0x00, /* <| */
  77165. -/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77166. -/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77167. -/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77168. -/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77169. -/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77170. -/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77171. -/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77172. -/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77173. -/* 1A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77174. -/* 1B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77175. -/* 1C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77176. -/* 1D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77177. +/* 12 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77178. +/* 13 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77179. +/* 14 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77180. +/* 15 */ 0x3c, 0x60, 0x3c, 0x66, 0x3c, 0x06, 0x3c, 0x00,
  77181. +/* 16 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77182. +/* 17 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77183. +/* 18 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77184. +/* 19 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77185. +/* 1A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77186. +/* 1B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77187. +/* 1C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77188. +/* 1D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77189. /* 1E */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00, /* /\ */
  77190. /* 1F */ 0x00, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00, /* \/ */
  77191. -/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
  77192. +/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
  77193. /* 21 */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, /* ! */
  77194. /* 22 */ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, /* " */
  77195. /* 23 */ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, /* # */
  77196. @@ -132,55 +132,55 @@
  77197. /* 7C */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* | */
  77198. /* 7D */ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, /* } */
  77199. /* 7E */ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, /* ~ */
  77200. -/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*  */
  77201. -/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77202. -/* 81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77203. -/* 82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77204. -/* 83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77205. -/* 84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77206. -/* 85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77207. -/* 86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77208. -/* 87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77209. -/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77210. -/* 89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77211. -/* 8A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77212. -/* 8B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77213. -/* 8C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77214. -/* 8D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77215. -/* 8E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77216. -/* 8F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77217. -/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77218. -/* 91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77219. -/* 92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77220. -/* 93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77221. -/* 94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77222. -/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77223. -/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77224. -/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77225. -/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77226. -/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77227. -/* 9A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77228. -/* 9B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77229. -/* 9C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77230. -/* 9D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77231. -/* 9E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77232. -/* 9F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77233. -/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77234. -/* A1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77235. -/* A2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77236. -/* A3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77237. -/* A4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77238. -/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77239. -/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77240. -/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77241. -/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77242. -/* A9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77243. -/* AA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77244. -/* AB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77245. -/* AC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77246. -/* AD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77247. -/* AE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77248. -/* AF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77249. +/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*  */
  77250. +/* 80 */ 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x30, 0x60,
  77251. +/* 81 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
  77252. +/* 82 */ 0x0c, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
  77253. +/* 83 */ 0x18, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
  77254. +/* 84 */ 0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
  77255. +/* 85 */ 0x30, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
  77256. +/* 86 */ 0x3c, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
  77257. +/* 87 */ 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x60,
  77258. +/* 88 */ 0x3c, 0x66, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
  77259. +/* 89 */ 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
  77260. +/* 8A */ 0x30, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
  77261. +/* 8B */ 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
  77262. +/* 8C */ 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
  77263. +/* 8D */ 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
  77264. +/* 8E */ 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
  77265. +/* 8F */ 0x18, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
  77266. +/* 90 */ 0x0c, 0x18, 0x7e, 0x60, 0x7c, 0x60, 0x7e, 0x00,
  77267. +/* 91 */ 0x00, 0x00, 0x3f, 0x0d, 0x3f, 0x6c, 0x3f, 0x00,
  77268. +/* 92 */ 0x3f, 0x66, 0x66, 0x7f, 0x66, 0x66, 0x67, 0x00,
  77269. +/* 93 */ 0x3c, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
  77270. +/* 94 */ 0x66, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
  77271. +/* 95 */ 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
  77272. +/* 96 */ 0x3c, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
  77273. +/* 97 */ 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
  77274. +/* 98 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c,
  77275. +/* 99 */ 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
  77276. +/* 9A */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
  77277. +/* 9B */ 0x08, 0x3e, 0x6b, 0x68, 0x6b, 0x3e, 0x08, 0x00,
  77278. +/* 9C */ 0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00,
  77279. +/* 9D */ 0x66, 0x3c, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00,
  77280. +/* 9E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77281. +/* 9F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77282. +/* A0 */ 0x0c, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
  77283. +/* A1 */ 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
  77284. +/* A2 */ 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
  77285. +/* A3 */ 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
  77286. +/* A4 */ 0x36, 0x6c, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x00,
  77287. +/* A5 */ 0x36, 0x6c, 0x00, 0x66, 0x76, 0x6e, 0x66, 0x00,
  77288. +/* A6 */ 0x1c, 0x06, 0x1e, 0x36, 0x1e, 0x00, 0x3e, 0x00,
  77289. +/* A7 */ 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00,
  77290. +/* A8 */ 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3c, 0x00,
  77291. +/* A9 */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77292. +/* AA */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77293. +/* AB */ 0x40, 0xc0, 0x40, 0x4f, 0x41, 0x0f, 0x08, 0x0f,
  77294. +/* AC */ 0x40, 0xc0, 0x40, 0x48, 0x48, 0x0a, 0x0f, 0x02,
  77295. +/* AD */ 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
  77296. +/* AE */ 0x00, 0x33, 0x66, 0xcc, 0xcc, 0x66, 0x33, 0x00,
  77297. +/* AF */ 0x00, 0xcc, 0x66, 0x33, 0x33, 0x66, 0xcc, 0x00,
  77298. /* B0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
  77299. /* B1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
  77300. /* B2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
  77301. @@ -229,37 +229,37 @@
  77302. /* DD */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
  77303. /* DE */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
  77304. /* DF */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  77305. -/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77306. -/* E1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77307. -/* E2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77308. -/* E3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77309. -/* E4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77310. -/* E5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77311. -/* E6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77312. -/* E7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77313. -/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77314. -/* E9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77315. -/* EA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77316. -/* EB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77317. -/* EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77318. -/* ED */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77319. -/* EE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77320. -/* EF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77321. -/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77322. -/* F1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77323. -/* F2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77324. -/* F3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77325. -/* F4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77326. -/* F5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77327. -/* F6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77328. -/* F7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77329. -/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77330. -/* F9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77331. -/* FA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77332. -/* FB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77333. -/* FC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77334. -/* FD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77335. -/* FE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  77336. +/* E0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77337. +/* E1 */ 0x3c, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x6c, 0xc0,
  77338. +/* E2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77339. +/* E3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77340. +/* E4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77341. +/* E5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77342. +/* E6 */ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x60,
  77343. +/* E7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77344. +/* E8 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77345. +/* E9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77346. +/* EA */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77347. +/* EB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77348. +/* EC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77349. +/* ED */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77350. +/* EE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77351. +/* EF */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77352. +/* F0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77353. +/* F1 */ 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
  77354. +/* F2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77355. +/* F3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77356. +/* F4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77357. +/* F5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77358. +/* F6 */ 0x00, 0x18, 0x00, 0xff, 0x00, 0x18, 0x00, 0x00,
  77359. +/* F7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77360. +/* F8 */ 0x3c, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
  77361. +/* F9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77362. +/* FA */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
  77363. +/* FB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77364. +/* FC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77365. +/* FD */ 0x38, 0x04, 0x18, 0x20, 0x3c, 0x00, 0x00, 0x00,
  77366. +/* FE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
  77367. /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  77368. };
  77369. diff -urN linux-2.4.26/drivers/video/pm3fb.c linux-2.4.26-vrs1/drivers/video/pm3fb.c
  77370. --- linux-2.4.26/drivers/video/pm3fb.c 2004-04-19 11:44:28.000000000 +0100
  77371. +++ linux-2.4.26-vrs1/drivers/video/pm3fb.c 2004-04-19 17:24:12.000000000 +0100
  77372. @@ -5,7 +5,6 @@
  77373. * Based on code written by:
  77374. * Sven Luther, <luther@dpt-info.u-strasbg.fr>
  77375. * Alan Hourihane, <alanh@fairlite.demon.co.uk>
  77376. - * Russel King, <rmk@arm.linux.org.uk>
  77377. * Based on linux/drivers/video/skeletonfb.c:
  77378. * Copyright (C) 1997 Geert Uytterhoeven
  77379. * Based on linux/driver/video/pm2fb.c:
  77380. @@ -16,14 +15,9 @@
  77381. * License. See the file COPYING in the main directory of this archive for
  77382. * more details.
  77383. *
  77384. - * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
  77385. + * $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $
  77386. *
  77387. * CHANGELOG:
  77388. - * Wed Nov 13 11:19:34 MET 2002, v 1.4.11C: option flatpanel: wasn't available in module, fixed.
  77389. - * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
  77390. - * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
  77391. - * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
  77392. - * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings.
  77393. * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes.
  77394. * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix.
  77395. * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG.
  77396. @@ -54,8 +48,8 @@
  77397. */
  77398. #include <linux/config.h>
  77399. -#include <linux/module.h>
  77400. #include <linux/version.h>
  77401. +#include <linux/module.h>
  77402. #include <linux/kernel.h>
  77403. #include <linux/errno.h>
  77404. #include <linux/string.h>
  77405. @@ -81,7 +75,6 @@
  77406. #include <asm/io.h>
  77407. #include <asm/uaccess.h>
  77408. -
  77409. #ifdef CONFIG_FB_OF
  77410. #include <asm/prom.h>
  77411. #endif
  77412. @@ -129,7 +122,6 @@
  77413. unsigned long refresh;
  77414. unsigned long powerdown;
  77415. };
  77416. -typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result;
  77417. #define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1)
  77418. #define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE }
  77419. @@ -192,21 +184,13 @@
  77420. PM3VideoControl_VSYNC_ACTIVE_HIGH
  77421. | PM3VideoControl_PIXELSIZE_8BIT}}, {
  77422. "1024x768-74-32", {
  77423. - 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
  77424. - 806, 1024, 0, 32,
  77425. - PM3VideoControl_ENABLE |
  77426. - PM3VideoControl_HSYNC_ACTIVE_HIGH
  77427. - |
  77428. - PM3VideoControl_VSYNC_ACTIVE_HIGH
  77429. - | PM3VideoControl_PIXELSIZE_32BIT}},
  77430. -/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/
  77431. - {
  77432. - "SGI1600SW", {
  77433. - 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32,
  77434. - 1056, 1600, 0, 8,
  77435. - PM3VideoControl_ENABLE|
  77436. - PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW|
  77437. - PM3VideoControl_PIXELSIZE_32BIT}},
  77438. + 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
  77439. + 806, 1024, 0, 32,
  77440. + PM3VideoControl_ENABLE |
  77441. + PM3VideoControl_HSYNC_ACTIVE_HIGH
  77442. + |
  77443. + PM3VideoControl_VSYNC_ACTIVE_HIGH
  77444. + | PM3VideoControl_PIXELSIZE_32BIT}},
  77445. /* ##### auto-generated mode, by fbtimings2pm3 */
  77446. /* Generated mode : "640x480-60" */
  77447. {
  77448. @@ -555,11 +539,9 @@
  77449. short noaccel[PM3_MAX_BOARD];
  77450. char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE];
  77451. short depth[PM3_MAX_BOARD];
  77452. -short flatpanel[PM3_MAX_BOARD];
  77453. static struct display disp[PM3_MAX_BOARD];
  77454. static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy";
  77455. short printtimings = 0;
  77456. -short forcesize[PM3_MAX_BOARD];
  77457. /* ********************* */
  77458. /* ***** prototype ***** */
  77459. @@ -567,8 +549,7 @@
  77460. /* card-specific */
  77461. static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info);
  77462. /* permedia3-specific */
  77463. -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
  77464. -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info);
  77465. +static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
  77466. static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info);
  77467. static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
  77468. unsigned long r);
  77469. @@ -684,7 +665,7 @@
  77470. NULL, NULL
  77471. };
  77472. #endif /* KERNEL_2_2 */
  77473. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  77474. +#ifdef KERNEL_2_4
  77475. struct fbgen_hwswitch pm3fb_switch = {
  77476. pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
  77477. pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, pm3fb_setcolreg,
  77478. @@ -697,7 +678,7 @@
  77479. fbgen_get_fix, fbgen_get_var, fbgen_set_var,
  77480. fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, pm3fb_ioctl, NULL, NULL
  77481. };
  77482. -#endif /* KERNEL_2_4 or KERNEL_2_5 */
  77483. +#endif /* KERNEL_2_4 */
  77484. #ifdef PM3FB_USE_ACCEL
  77485. #ifdef FBCON_HAS_CFB32
  77486. static struct display_switch pm3fb_cfb32 = {
  77487. @@ -728,75 +709,52 @@
  77488. #endif /* FBCON_HAS_CFB8 */
  77489. #endif /* PM3FB_USE_ACCEL */
  77490. -/* ****************************** */
  77491. -/* ***** card-specific data ***** */
  77492. -/* ****************************** */
  77493. -struct pm3fb_card_timings {
  77494. - unsigned long memsize; /* 0 for last value (i.e. default) */
  77495. - struct pm3fb_timings memt;
  77496. -};
  77497. -
  77498. -static struct pm3fb_card_timings t_FormacProFormance3[] = {
  77499. - { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} },
  77500. - { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */
  77501. -};
  77502. -
  77503. -static struct pm3fb_card_timings t_AppianJeronimo2000[] = {
  77504. - { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} },
  77505. - { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */
  77506. -};
  77507. -
  77508. -static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = {
  77509. - { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} },
  77510. - { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */
  77511. -};
  77512. -
  77513. +/* ********************************** */
  77514. +/* ***** card-specific function ***** */
  77515. +/* ********************************** */
  77516. static struct {
  77517. char cardname[32]; /* recognized card name */
  77518. u16 subvendor; /* subvendor of the card */
  77519. u16 subdevice; /* subdevice of the card */
  77520. u8 func; /* function of the card to which the extra init apply */
  77521. void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */
  77522. - struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */
  77523. + struct pm3fb_timings memt; /* default timing for the board WARNING : might be *card* - specific */
  77524. } cardbase[] = {
  77525. - { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL },
  77526. - { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL,
  77527. - t_AppianJeronimo2000
  77528. - },
  77529. + { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, PM3FB_UNKNOWN_TIMINGS },
  77530. + { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL, PM3FB_UNKNOWN_TIMINGS },
  77531. { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup,
  77532. - t_AppianJeronimo2000
  77533. + {0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} /* also in pm3fb_j2000_setup */
  77534. },
  77535. { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */
  77536. - t_FormacProFormance3
  77537. + { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} /* from the 16Mb ProFormance 3 */
  77538. },
  77539. - { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL },
  77540. + { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
  77541. { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL,
  77542. - t_3DLabsOxygenVX1
  77543. + { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000 }
  77544. },
  77545. - { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL },
  77546. - { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL },
  77547. - { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL },
  77548. - { "\0", 0x0, 0x0, 0, NULL, NULL }
  77549. + { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
  77550. + { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
  77551. + { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
  77552. + { "\0", 0x0, 0x0, 0, NULL, PM3FB_UNKNOWN_TIMINGS }
  77553. };
  77554. -/* ********************************** */
  77555. -/* ***** card-specific function ***** */
  77556. -/* ********************************** */
  77557. static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info)
  77558. { /* the appian j2000 require more initialization of the second head */
  77559. /* l_fb_info must point to the _second_ head of the J2000 */
  77560. DTRACE;
  77561. -
  77562. - l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */
  77563. +
  77564. + /* Memory timings for the Appian J2000 board. also in cardbase */
  77565. + l_fb_info->memt.caps = 0x02e311B8;
  77566. + l_fb_info->memt.timings = 0x07424905;
  77567. + l_fb_info->memt.control = 0x0c000003;
  77568. + l_fb_info->memt.refresh = 0x00000061;
  77569. + l_fb_info->memt.powerdown = 0x00000000;
  77570. pm3fb_write_memory_timings(l_fb_info);
  77571. }
  77572. -/* *************************************** */
  77573. -/* ***** permedia3-specific function ***** */
  77574. -/* *************************************** */
  77575. -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
  77576. +static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
  77577. {
  77578. l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps);
  77579. l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings);
  77580. @@ -811,35 +769,20 @@
  77581. (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE))
  77582. {
  77583. printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num);
  77584. - return(pm3fb_try_memory_timings(l_fb_info));
  77585. - }
  77586. - return(pm3fb_timing_ok);
  77587. -}
  77588. -
  77589. -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info)
  77590. -{
  77591. - if (cardbase[l_fb_info->board_type].c_memt)
  77592. - {
  77593. - int i = 0, done = 0;
  77594. - while (!done)
  77595. + if ((cardbase[l_fb_info->board_type].memt.caps != PM3FB_UNKNOWN_TIMING_VALUE) &&
  77596. + (cardbase[l_fb_info->board_type].memt.timings != PM3FB_UNKNOWN_TIMING_VALUE) &&
  77597. + (cardbase[l_fb_info->board_type].memt.control != PM3FB_UNKNOWN_TIMING_VALUE) &&
  77598. + (cardbase[l_fb_info->board_type].memt.refresh != PM3FB_UNKNOWN_TIMING_VALUE) &&
  77599. + (cardbase[l_fb_info->board_type].memt.powerdown != PM3FB_UNKNOWN_TIMING_VALUE))
  77600. {
  77601. - if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size)
  77602. - || !(cardbase[l_fb_info->board_type].c_memt[i].memsize))
  77603. - { /* will use the 0-sized timings by default */
  77604. - done = 1;
  77605. - l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt;
  77606. - printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n",
  77607. - l_fb_info->board_num,
  77608. - cardbase[l_fb_info->board_type].cardname,
  77609. - cardbase[l_fb_info->board_type].c_memt[i].memsize);
  77610. - pm3fb_write_memory_timings(l_fb_info);
  77611. - return(pm3fb_timing_retry);
  77612. - }
  77613. - i++;
  77614. + l_fb_info->memt = cardbase[l_fb_info->board_type].memt;
  77615. + printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s)\n", l_fb_info->board_num, cardbase[l_fb_info->board_type].cardname);
  77616. + pm3fb_write_memory_timings(l_fb_info);
  77617. }
  77618. - } else
  77619. - return(pm3fb_timing_problem);
  77620. - return(pm3fb_timing_ok);
  77621. + else
  77622. + return(1);
  77623. + }
  77624. + return(0);
  77625. }
  77626. static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info)
  77627. @@ -874,6 +817,10 @@
  77628. PM3RD_SClkControl_ENABLE);
  77629. }
  77630. +/* *************************************** */
  77631. +/* ***** permedia3-specific function ***** */
  77632. +/* *************************************** */
  77633. +
  77634. static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
  77635. unsigned long r)
  77636. {
  77637. @@ -1068,7 +1015,6 @@
  77638. /* write the mode to registers */
  77639. static void pm3fb_write_mode(struct pm3fb_info *l_fb_info)
  77640. {
  77641. - char tempsync = 0x00, tempmisc = 0x00;
  77642. DTRACE;
  77643. PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff);
  77644. @@ -1198,26 +1144,22 @@
  77645. /*
  77646. PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00);
  77647. */
  77648. - if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) ==
  77649. - PM3VideoControl_HSYNC_ACTIVE_HIGH)
  77650. - tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
  77651. - if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) ==
  77652. - PM3VideoControl_VSYNC_ACTIVE_HIGH)
  77653. - tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
  77654. -
  77655. - PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
  77656. - DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
  77657. -
  77658. - if (flatpanel[l_fb_info->board_num])
  77659. {
  77660. - PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE);
  77661. - PM3_WAIT(2);
  77662. - PM3_WRITE_REG(PM3VSConfiguration, 0x06);
  77663. - PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */
  77664. - tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
  77665. + char tempsync = 0x00;
  77666. +
  77667. + if ((l_fb_info->current_par->
  77668. + video & PM3VideoControl_HSYNC_MASK) ==
  77669. + PM3VideoControl_HSYNC_ACTIVE_HIGH)
  77670. + tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
  77671. + if ((l_fb_info->current_par->
  77672. + video & PM3VideoControl_VSYNC_MASK) ==
  77673. + PM3VideoControl_VSYNC_ACTIVE_HIGH)
  77674. + tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
  77675. +
  77676. + PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
  77677. + DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
  77678. }
  77679. - else
  77680. - PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
  77681. + PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
  77682. switch (l_fb_info->current_par->depth) {
  77683. case 8:
  77684. @@ -1226,7 +1168,8 @@
  77685. PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
  77686. PM3RD_ColorFormat_CI8_COLOR |
  77687. PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
  77688. - tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
  77689. + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
  77690. + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
  77691. break;
  77692. case 12:
  77693. PM3_WRITE_DAC_REG(PM3RD_PixelSize,
  77694. @@ -1235,8 +1178,9 @@
  77695. PM3RD_ColorFormat_4444_COLOR |
  77696. PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
  77697. PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
  77698. - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77699. - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
  77700. + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
  77701. + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77702. + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
  77703. break;
  77704. case 15:
  77705. PM3_WRITE_DAC_REG(PM3RD_PixelSize,
  77706. @@ -1245,8 +1189,9 @@
  77707. PM3RD_ColorFormat_5551_FRONT_COLOR |
  77708. PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
  77709. PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
  77710. - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77711. - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
  77712. + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
  77713. + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77714. + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
  77715. break;
  77716. case 16:
  77717. PM3_WRITE_DAC_REG(PM3RD_PixelSize,
  77718. @@ -1255,8 +1200,9 @@
  77719. PM3RD_ColorFormat_565_FRONT_COLOR |
  77720. PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
  77721. PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
  77722. - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77723. - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
  77724. + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
  77725. + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77726. + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
  77727. break;
  77728. case 32:
  77729. PM3_WRITE_DAC_REG(PM3RD_PixelSize,
  77730. @@ -1264,12 +1210,12 @@
  77731. PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
  77732. PM3RD_ColorFormat_8888_COLOR |
  77733. PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
  77734. - tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77735. - PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
  77736. + PM3_WRITE_DAC_REG(PM3RD_MiscControl,
  77737. + PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
  77738. + PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
  77739. break;
  77740. }
  77741. - PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc);
  77742. -
  77743. +
  77744. PM3_SHOW_CUR_MODE;
  77745. }
  77746. @@ -1391,9 +1337,8 @@
  77747. static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
  77748. {
  77749. - unsigned long memsize = 0, tempBypass, i, temp1, temp2;
  77750. + unsigned long memsize, tempBypass, i, temp1, temp2;
  77751. u16 subvendor, subdevice;
  77752. - pm3fb_timing_result ptr;
  77753. DTRACE;
  77754. @@ -1439,7 +1384,7 @@
  77755. /* card-specific setup is done, we preserve the final
  77756. memory timing for future reference */
  77757. - if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */
  77758. + if (pm3fb_preserve_memory_timings(l_fb_info)) { /* memory timings were wrong ! oops.... */
  77759. return(0);
  77760. }
  77761. @@ -1465,12 +1410,12 @@
  77762. temp1 = readl((l_fb_info->v_fb + (i * 1048576)));
  77763. #endif
  77764. #endif /* KERNEL_2_2 */
  77765. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  77766. +#ifdef KERNEL_2_4
  77767. fb_writel(i * 0x00345678,
  77768. (l_fb_info->v_fb + (i * 1048576)));
  77769. mb();
  77770. temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
  77771. -#endif /* KERNEL_2_4 or KERNEL_2_5 */
  77772. +#endif /* KERNEL_2_4 */
  77773. /* Let's check for wrapover, write will fail at 16MB boundary */
  77774. if (temp1 == (i * 0x00345678))
  77775. memsize = i;
  77776. @@ -1513,7 +1458,7 @@
  77777. ((i - 32) * 1048576)));
  77778. #endif
  77779. #endif /* KERNEL_2_2 */
  77780. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  77781. +#ifdef KERNEL_2_4
  77782. fb_writel(i * 0x00345678,
  77783. (l_fb_info->v_fb + (i * 1048576)));
  77784. mb();
  77785. @@ -1522,7 +1467,7 @@
  77786. temp2 =
  77787. fb_readl((l_fb_info->v_fb +
  77788. ((i - 32) * 1048576)));
  77789. -#endif /* KERNEL_2_4 or KERNEL_2_5 */
  77790. +#endif /* KERNEL_2_4 */
  77791. if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */
  77792. memsize = i;
  77793. else
  77794. @@ -1539,21 +1484,8 @@
  77795. DPRINTK(2, "Returning 0x%08lx bytes\n", memsize);
  77796. - if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize))
  77797. - {
  77798. - printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]);
  77799. - memsize = 1048576 * forcesize[l_fb_info->board_num];
  77800. - }
  77801. -
  77802. l_fb_info->fb_size = memsize;
  77803. -
  77804. - if (ptr == pm3fb_timing_retry)
  77805. - {
  77806. - printk(KERN_WARNING "pm3fb: retrying memory timings check");
  77807. - if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem)
  77808. - return(0);
  77809. - }
  77810. -
  77811. +
  77812. return (memsize);
  77813. }
  77814. @@ -1572,7 +1504,7 @@
  77815. writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
  77816. #endif
  77817. #endif
  77818. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  77819. +#ifdef KERNEL_2_4
  77820. fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
  77821. #endif
  77822. }
  77823. @@ -1601,7 +1533,7 @@
  77824. disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */
  77825. l_fb_info->gen.parsize = sizeof(struct pm3fb_par);
  77826. l_fb_info->gen.info.changevar = NULL;
  77827. - l_fb_info->gen.info.node = B_FREE;
  77828. + l_fb_info->gen.info.node = -1;
  77829. l_fb_info->gen.info.fbops = &pm3fb_ops;
  77830. l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]);
  77831. if (fontn[l_fb_info->board_num][0])
  77832. @@ -1766,7 +1698,6 @@
  77833. }
  77834. PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff);
  77835. - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
  77836. PM3_SLOW_WRITE_REG(PM3FBWriteMode,
  77837. PM3FBWriteMode_WriteEnable |
  77838. PM3FBWriteMode_OpaqueSpan |
  77839. @@ -1787,7 +1718,9 @@
  77840. PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095);
  77841. else
  77842. PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb);
  77843. -
  77844. +
  77845. + PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
  77846. +
  77847. switch (l_fb_info->current_par->depth) {
  77848. case 8:
  77849. PM3_SLOW_WRITE_REG(PM3DitherMode,
  77850. @@ -1843,10 +1776,7 @@
  77851. height = height * fontheight(p);
  77852. c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
  77853. - /* block fills in 32bpp are hard, but in low res (width <= 1600 :-)
  77854. - we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */
  77855. - if ((l_fb_info->current_par->width > 1600) ||
  77856. - (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) {
  77857. + if (l_fb_info->current_par->width > 1600) {
  77858. PM3_WAIT(4);
  77859. PM3_WRITE_REG(PM3Config2D,
  77860. @@ -1868,7 +1798,7 @@
  77861. PM3Render2D_SpanOperation |
  77862. (PM3Render2D_Width(width)) |
  77863. (PM3Render2D_Height(height)));
  77864. - } else {
  77865. + } else { /* block fills in 32bpp are hard, but in low res (width <= 1600 :-) we can use 16bpp operations */
  77866. PM3_WAIT(8);
  77867. PM3_WRITE_REG(PM3FBBlockColor, c);
  77868. @@ -1993,10 +1923,7 @@
  77869. PM3_WAIT(4);
  77870. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  77871. - PM3_WRITE_REG(PM3ForegroundColor, c);
  77872. - else
  77873. - PM3_WRITE_REG(PM3FBBlockColor, c);
  77874. + PM3_WRITE_REG(PM3FBBlockColor, c);
  77875. PM3_WRITE_REG(PM3Config2D,
  77876. PM3Config2D_UseConstantSource |
  77877. @@ -2007,23 +1934,14 @@
  77878. PM3_WRITE_REG(PM3RectanglePosition,
  77879. (PM3RectanglePosition_XOffset(sx)) |
  77880. (PM3RectanglePosition_YOffset(sy)));
  77881. -
  77882. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  77883. - PM3_WRITE_REG(PM3Render2D,
  77884. - PM3Render2D_XPositive |
  77885. - PM3Render2D_YPositive |
  77886. - PM3Render2D_Operation_Normal |
  77887. - PM3Render2D_SpanOperation |
  77888. - (PM3Render2D_Width(width)) |
  77889. - (PM3Render2D_Height(height)));
  77890. - else
  77891. - PM3_WRITE_REG(PM3Render2D,
  77892. - PM3Render2D_XPositive |
  77893. - PM3Render2D_YPositive |
  77894. - PM3Render2D_Operation_Normal |
  77895. - (PM3Render2D_Width(width)) |
  77896. - (PM3Render2D_Height(height)));
  77897. -
  77898. +
  77899. + PM3_WRITE_REG(PM3Render2D,
  77900. + PM3Render2D_XPositive |
  77901. + PM3Render2D_YPositive |
  77902. + PM3Render2D_Operation_Normal |
  77903. + (PM3Render2D_Width(width)) |
  77904. + (PM3Render2D_Height(height)));
  77905. +
  77906. pm3fb_wait_pm3(l_fb_info);
  77907. }
  77908. @@ -2049,69 +1967,45 @@
  77909. PM3Config2D_ForegroundROPEnable |
  77910. (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
  77911. PM3Config2D_FBWriteEnable);
  77912. -
  77913. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  77914. - PM3_WRITE_REG(PM3ForegroundColor, c);
  77915. - else
  77916. - PM3_WRITE_REG(PM3FBBlockColor, c);
  77917. -
  77918. +
  77919. + PM3_WRITE_REG(PM3FBBlockColor, c);
  77920. +
  77921. PM3_WRITE_REG(PM3RectanglePosition,
  77922. (PM3RectanglePosition_XOffset
  77923. (p->var.xoffset +
  77924. sx)) | (PM3RectanglePosition_YOffset(p->
  77925. var.
  77926. yoffset)));
  77927. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  77928. - PM3_WRITE_REG(PM3Render2D,
  77929. - PM3Render2D_XPositive |
  77930. - PM3Render2D_YPositive |
  77931. - PM3Render2D_Operation_Normal |
  77932. - PM3Render2D_SpanOperation |
  77933. - (PM3Render2D_Width(p->var.xres - sx)) |
  77934. - (PM3Render2D_Height(p->var.yres)));
  77935. - else
  77936. - PM3_WRITE_REG(PM3Render2D,
  77937. - PM3Render2D_XPositive |
  77938. - PM3Render2D_YPositive |
  77939. - PM3Render2D_Operation_Normal |
  77940. - (PM3Render2D_Width(p->var.xres - sx)) |
  77941. - (PM3Render2D_Height(p->var.yres)));
  77942. +
  77943. + PM3_WRITE_REG(PM3Render2D,
  77944. + PM3Render2D_XPositive |
  77945. + PM3Render2D_YPositive |
  77946. + PM3Render2D_Operation_Normal |
  77947. + (PM3Render2D_Width(p->var.xres - sx)) |
  77948. + (PM3Render2D_Height(p->var.yres)));
  77949. }
  77950. -
  77951. +
  77952. /* bottom margin left -> right */
  77953. PM3_WAIT(4);
  77954. -
  77955. +
  77956. PM3_WRITE_REG(PM3Config2D,
  77957. - PM3Config2D_UseConstantSource |
  77958. - PM3Config2D_ForegroundROPEnable |
  77959. - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
  77960. - PM3Config2D_FBWriteEnable);
  77961. -
  77962. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  77963. - PM3_WRITE_REG(PM3ForegroundColor, c);
  77964. - else
  77965. - PM3_WRITE_REG(PM3FBBlockColor, c);
  77966. -
  77967. -
  77968. + PM3Config2D_UseConstantSource |
  77969. + PM3Config2D_ForegroundROPEnable |
  77970. + (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
  77971. + PM3Config2D_FBWriteEnable);
  77972. +
  77973. + PM3_WRITE_REG(PM3FBBlockColor, c);
  77974. +
  77975. PM3_WRITE_REG(PM3RectanglePosition,
  77976. (PM3RectanglePosition_XOffset(p->var.xoffset)) |
  77977. (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
  77978. -
  77979. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  77980. - PM3_WRITE_REG(PM3Render2D,
  77981. - PM3Render2D_XPositive |
  77982. - PM3Render2D_YPositive |
  77983. - PM3Render2D_Operation_Normal |
  77984. - PM3Render2D_SpanOperation |
  77985. - (PM3Render2D_Width(p->var.xres)) |
  77986. - (PM3Render2D_Height(p->var.yres - sy)));
  77987. - else
  77988. - PM3_WRITE_REG(PM3Render2D,
  77989. - PM3Render2D_XPositive |
  77990. - PM3Render2D_YPositive |
  77991. - PM3Render2D_Operation_Normal |
  77992. - (PM3Render2D_Width(p->var.xres)) |
  77993. - (PM3Render2D_Height(p->var.yres - sy)));
  77994. +
  77995. + PM3_WRITE_REG(PM3Render2D,
  77996. + PM3Render2D_XPositive |
  77997. + PM3Render2D_YPositive |
  77998. + PM3Render2D_Operation_Normal |
  77999. + (PM3Render2D_Width(p->var.xres)) |
  78000. + (PM3Render2D_Height(p->var.yres - sy)));
  78001. pm3fb_wait_pm3(l_fb_info);
  78002. }
  78003. @@ -2289,7 +2183,7 @@
  78004. int c, int yy, int xx)
  78005. {
  78006. struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
  78007. - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
  78008. + u8 *cdat, asx = 0, asy = 0, o_x, o_y;
  78009. u32 fgx, bgx, ldat;
  78010. int sx, sy, i;
  78011. @@ -2399,7 +2293,7 @@
  78012. int xx)
  78013. {
  78014. struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
  78015. - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
  78016. + u8 *cdat, asx = 0, asy = 0, o_x, o_y;
  78017. u32 fgx, bgx, ldat;
  78018. int sx, sy, i, j;
  78019. u16 sc;
  78020. @@ -2517,12 +2411,7 @@
  78021. yy = yy * fontheight(p);
  78022. if (l_fb_info->current_par->depth == 8)
  78023. - {
  78024. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  78025. - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F);
  78026. - else
  78027. - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
  78028. - }
  78029. + PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
  78030. PM3_WAIT(3);
  78031. @@ -2548,12 +2437,7 @@
  78032. pm3fb_wait_pm3(l_fb_info);
  78033. if (l_fb_info->current_par->depth == 8)
  78034. - {
  78035. - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
  78036. - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF);
  78037. - else
  78038. - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
  78039. - }
  78040. + PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
  78041. }
  78042. #endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
  78043. @@ -2641,25 +2525,12 @@
  78044. unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
  78045. if (!(depth_supported(bd))) {
  78046. - printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n",
  78047. - bds, board_num);
  78048. + DPRINTK(1, "Invalid depth: %s\n", bds);
  78049. return;
  78050. }
  78051. depth[board_num] = bd;
  78052. }
  78053. -static void pm3fb_forcesize_setup(char *bds, unsigned long board_num)
  78054. -{
  78055. - unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
  78056. -
  78057. - if (bd > 64) {
  78058. - printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n",
  78059. - bds, board_num);
  78060. - return;
  78061. - }
  78062. - forcesize[board_num] = bd;
  78063. -}
  78064. -
  78065. static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
  78066. {
  78067. char *next;
  78068. @@ -2753,12 +2624,6 @@
  78069. pm3fb_bootdepth_setup(options, bn);
  78070. } else if (!strncmp(options, "printtimings", 12)) {
  78071. printtimings = 1;
  78072. - } else if (!strncmp(options, "flatpanel:", 10)) {
  78073. - options = pm3fb_boardnum_setup(options + 10, &bn);
  78074. - flatpanel[bn] = 1;
  78075. - } else if (!strncmp(options, "forcesize:", 10)) {
  78076. - options = pm3fb_boardnum_setup(options + 10, &bn);
  78077. - pm3fb_forcesize_setup(options, bn);
  78078. }
  78079. options = next;
  78080. }
  78081. @@ -3496,7 +3361,7 @@
  78082. pci_resource_start(l_fb_info->dev, 1);
  78083. l_fb_info->v_fb = (unsigned char *) -1;
  78084. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* full resource management, new in linux-2.4.x */
  78085. +#ifdef KERNEL_2_4 /* full resource management, new in linux-2.4.x */
  78086. if (!request_mem_region
  78087. ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
  78088. "pm3fb")) {
  78089. @@ -3513,10 +3378,8 @@
  78090. l_fb_info->board_num);
  78091. continue;
  78092. }
  78093. -#endif /* KERNEL_2_4 or KERNEL_2_5 */
  78094. - if (forcesize[l_fb_info->board_num])
  78095. - l_fb_info->fb_size = forcesize[l_fb_info->board_num];
  78096. -
  78097. +#endif /* KERNEL_2_4 */
  78098. +
  78099. l_fb_info->fb_size =
  78100. pm3fb_size_memory(l_fb_info);
  78101. @@ -3612,7 +3475,7 @@
  78102. /* ***** standard FB API init functions ***** */
  78103. /* ****************************************** */
  78104. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  78105. +#ifdef KERNEL_2_4
  78106. int __init pm3fb_setup(char *options)
  78107. #endif
  78108. #ifdef KERNEL_2_2
  78109. @@ -3628,12 +3491,12 @@
  78110. PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
  78111. g_options[PM3_OPTIONS_SIZE - 1] = 0;
  78112. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  78113. +#ifdef KERNEL_2_4
  78114. return (0);
  78115. #endif
  78116. }
  78117. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  78118. +#ifdef KERNEL_2_4
  78119. int __init pm3fb_init(void)
  78120. #endif
  78121. #ifdef KERNEL_2_2
  78122. @@ -3642,7 +3505,7 @@
  78123. {
  78124. DTRACE;
  78125. - DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $");
  78126. + DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $");
  78127. pm3fb_real_setup(g_options);
  78128. @@ -3651,7 +3514,7 @@
  78129. if (!fb_info[0].dev) { /* not even one board ??? */
  78130. DPRINTK(1, "No PCI Permedia3 board detected\n");
  78131. }
  78132. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  78133. +#ifdef KERNEL_2_4
  78134. return (0);
  78135. #endif
  78136. }
  78137. @@ -3754,11 +3617,7 @@
  78138. MODULE_PARM(depth,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
  78139. MODULE_PARM_DESC(depth,"boot-time depth");
  78140. MODULE_PARM(printtimings, "h");
  78141. -MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
  78142. -MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
  78143. -MODULE_PARM_DESC(forcesize, "force specified memory size");
  78144. -MODULE_PARM(flatpanel, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
  78145. -MODULE_PARM_DESC(flatpanel, "flatpanel (LCD) support (preliminary)");
  78146. +MODULE_PARM_DESC(printtimings, "print the memory timngs of the card(s)");
  78147. /*
  78148. MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
  78149. MODULE_GENERIC_TABLE(gtype,name)
  78150. @@ -3803,11 +3662,6 @@
  78151. sprintf(ts, ",depth:%d:%d", i, depth[i]);
  78152. strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
  78153. }
  78154. - if (flatpanel[i])
  78155. - {
  78156. - sprintf(ts, ",flatpanel:%d:", i);
  78157. - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
  78158. - }
  78159. }
  78160. g_options[PM3_OPTIONS_SIZE - 1] = '\0';
  78161. DPRINTK(1, "pm3fb use options: %s\n", g_options);
  78162. @@ -3837,14 +3691,14 @@
  78163. if (l_fb_info->vIOBase !=
  78164. (unsigned char *) -1) {
  78165. pm3fb_unmapIO(l_fb_info);
  78166. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
  78167. +#ifdef KERNEL_2_4
  78168. release_mem_region(l_fb_info->p_fb,
  78169. l_fb_info->
  78170. fb_size);
  78171. release_mem_region(l_fb_info->
  78172. pIOBase,
  78173. PM3_REGS_SIZE);
  78174. -#endif /* KERNEL_2_4 or KERNEL_2_5 */
  78175. +#endif /* KERNEL_2_4 */
  78176. }
  78177. unregister_framebuffer(&l_fb_info->gen.
  78178. info);
  78179. diff -urN linux-2.4.26/drivers/video/pm3fb.h linux-2.4.26-vrs1/drivers/video/pm3fb.h
  78180. --- linux-2.4.26/drivers/video/pm3fb.h 2002-11-28 23:53:15.000000000 +0000
  78181. +++ linux-2.4.26-vrs1/drivers/video/pm3fb.h 2004-01-14 21:32:27.000000000 +0000
  78182. @@ -8,7 +8,7 @@
  78183. * License. See the file COPYING in the main directory of this archive for
  78184. * more details.
  78185. *
  78186. - * $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
  78187. + * $Header: /home/pm3fb/pm3fb/pm3fb.h,v 1.30 2001/08/22 09:13:46 dolbeau Exp $
  78188. *
  78189. */
  78190. @@ -92,7 +92,6 @@
  78191. #define PM3MemBypassWriteMask 0x1008
  78192. #define PM3MemScratch 0x1010
  78193. #define PM3LocalMemCaps 0x1018
  78194. - #define PM3LocalMemCaps_NoWriteMask (1 << 28)
  78195. #define PM3LocalMemTimings 0x1020
  78196. #define PM3LocalMemControl 0x1028
  78197. #define PM3LocalMemRefresh 0x1030
  78198. @@ -1121,10 +1120,6 @@
  78199. /* kernel -specific definitions */
  78200. /* what kernel is this ? */
  78201. -#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
  78202. -#define KERNEL_2_5
  78203. -#endif
  78204. -
  78205. #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)))
  78206. #define KERNEL_2_4
  78207. #endif
  78208. @@ -1138,8 +1133,8 @@
  78209. #endif
  78210. #endif
  78211. -#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4)) && (!defined(KERNEL_2_5))
  78212. -#error "Only kernel 2.2.x, kernel 2.4.y and kernel 2.5.z might work"
  78213. +#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4))
  78214. +#error "Only kernel 2.2.x and kernel 2.4.y might work"
  78215. #endif
  78216. /* not sure if/why it's needed. doesn't work without on my PowerMac... */
  78217. @@ -1147,11 +1142,6 @@
  78218. #define MUST_BYTESWAP
  78219. #endif
  78220. -/* for compatibility between 2.5, 2.4 and 2.2 */
  78221. -#ifndef B_FREE
  78222. -#define B_FREE -1
  78223. -#endif
  78224. -
  78225. /* permedia3 -specific definitions */
  78226. #define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
  78227. #define PICOS2KHZ(a) (1000000000UL/(a))
  78228. @@ -1219,10 +1209,10 @@
  78229. #define PM3_READ_REG(r) readl((l_fb_info->vIOBase + r))
  78230. #endif /* MUST_BYTESWAP */
  78231. #endif /* KERNEL_2_2 */
  78232. -#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* native-endian access */
  78233. +#ifdef KERNEL_2_4 /* native-endian access */
  78234. #define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
  78235. #define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
  78236. -#endif /* KERNEL_2_4 or KERNEL_2_5 */
  78237. +#endif /* KERNEL_2_4 */
  78238. #define depth2bpp(d) ((d + 7L) & ~7L)
  78239. diff -urN linux-2.4.26/drivers/video/sa1100fb.c linux-2.4.26-vrs1/drivers/video/sa1100fb.c
  78240. --- linux-2.4.26/drivers/video/sa1100fb.c 2001-11-14 22:52:20.000000000 +0000
  78241. +++ linux-2.4.26-vrs1/drivers/video/sa1100fb.c 2004-01-14 21:32:27.000000000 +0000
  78242. @@ -23,11 +23,11 @@
  78243. * Thank you.
  78244. *
  78245. * Known problems:
  78246. - * - With the Neponset plugged into an Assabet, LCD powerdown
  78247. - * doesn't work (LCD stays powered up). Therefore we shouldn't
  78248. - * blank the screen.
  78249. - * - We don't limit the CPU clock rate nor the mode selection
  78250. - * according to the available SDRAM bandwidth.
  78251. + * - With the Neponset plugged into an Assabet, LCD powerdown
  78252. + * doesn't work (LCD stays powered up). Therefore we shouldn't
  78253. + * blank the screen.
  78254. + * - We don't limit the CPU clock rate nor the mode selection
  78255. + * according to the available SDRAM bandwidth.
  78256. *
  78257. * Other notes:
  78258. * - Linear grayscale palettes and the kernel.
  78259. @@ -41,6 +41,17 @@
  78260. * David Neuer. It's around 8 lines of C code, plus another 4 to
  78261. * detect if we are using grayscale.
  78262. *
  78263. + * - The following must never be specified in a panel definition:
  78264. + * LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
  78265. + *
  78266. + * - The following should be specified:
  78267. + * either LCCR0_Color or LCCR0_Mono
  78268. + * either LCCR0_Sngl or LCCR0_Dual
  78269. + * either LCCR0_Act or LCCR0_Pas
  78270. + * either LCCR3_OutEnH or LCCD3_OutEnL
  78271. + * either LCCR3_PixRsEdg or LCCR3_PixFlEdg
  78272. + * either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
  78273. + *
  78274. * Code Status:
  78275. * 1999/04/01:
  78276. * - Driver appears to be working for Brutus 320x200x8bpp mode. Other
  78277. @@ -147,6 +158,10 @@
  78278. *
  78279. * 2001/10/12: <rmk@arm.linux.org.uk>
  78280. * - Add patch 681/1 and clean up stork definitions.
  78281. + *
  78282. + * 2002/02/21: <abraham@2d3d.co.za>
  78283. + * - Added support for ICP LCD-Kit01 on Frodo.
  78284. + * - Added support for backlight via CPLDs on Frodo.
  78285. */
  78286. #include <linux/config.h>
  78287. @@ -169,6 +184,7 @@
  78288. #include <asm/mach-types.h>
  78289. #include <asm/uaccess.h>
  78290. #include <asm/arch/assabet.h>
  78291. +#include <asm/arch/shannon.h>
  78292. #include <video/fbcon.h>
  78293. #include <video/fbcon-mfb.h>
  78294. @@ -177,11 +193,6 @@
  78295. #include <video/fbcon-cfb16.h>
  78296. /*
  78297. - * enable this if your panel appears to have broken
  78298. - */
  78299. -#undef CHECK_COMPAT
  78300. -
  78301. -/*
  78302. * debugging?
  78303. */
  78304. #define DEBUG 0
  78305. @@ -197,243 +208,6 @@
  78306. void (*sa1100fb_blank_helper)(int blank);
  78307. EXPORT_SYMBOL(sa1100fb_blank_helper);
  78308. -
  78309. -#ifdef CHECK_COMPAT
  78310. -static void
  78311. -sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
  78312. - struct fb_var_screeninfo *var, u_int pcd)
  78313. -{
  78314. - struct sa1100fb_lcd_reg shadow;
  78315. - int different = 0;
  78316. -
  78317. - /*
  78318. - * These machines are good machines!
  78319. - */
  78320. - if (machine_is_assabet() || machine_is_h3600())
  78321. - return;
  78322. -
  78323. - /*
  78324. - * The following ones are bad, bad, bad.
  78325. - * Please make yours good!
  78326. - */
  78327. - if (machine_is_pangolin()) {
  78328. - DPRINTK("Configuring Pangolin LCD\n");
  78329. - shadow.lccr0 =
  78330. - LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
  78331. - LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
  78332. - LCCR0_LtlEnd + LCCR0_DMADel(0);
  78333. - shadow.lccr1 =
  78334. - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
  78335. - LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
  78336. - shadow.lccr2 =
  78337. - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
  78338. - LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
  78339. - shadow.lccr3 =
  78340. - LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
  78341. - LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
  78342. -
  78343. - DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
  78344. - pcd, LCCR3_PixClkDiv(pcd));
  78345. - }
  78346. - if (machine_is_freebird()) {
  78347. - DPRINTK("Configuring Freebird LCD\n");
  78348. -#if 1
  78349. - shadow.lccr0 = 0x00000038;
  78350. - shadow.lccr1 = 0x010108e0;
  78351. - shadow.lccr2 = 0x0000053f;
  78352. - shadow.lccr3 = 0x00000c20;
  78353. -#else
  78354. - shadow.lccr0 =
  78355. - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
  78356. - LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
  78357. - LCCR0_LtlEnd + LCCR0_DMADel(0);
  78358. - /* Check ,Chester */
  78359. - shadow.lccr1 =
  78360. - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
  78361. - LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
  78362. - /* Check ,Chester */
  78363. - shadow.lccr2 =
  78364. - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
  78365. - LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
  78366. - /* Check ,Chester */
  78367. - shadow.lccr3 =
  78368. - LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
  78369. - LCCR3_HorSnchH + LCCR3_ACBsCntOff +
  78370. - LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
  78371. -#endif
  78372. - }
  78373. - if (machine_is_brutus()) {
  78374. - DPRINTK("Configuring Brutus LCD\n");
  78375. - shadow.lccr0 =
  78376. - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
  78377. - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
  78378. - LCCR0_DMADel(0);
  78379. - shadow.lccr1 =
  78380. - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
  78381. - LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
  78382. - shadow.lccr2 =
  78383. - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
  78384. - LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
  78385. - shadow.lccr3 =
  78386. - LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
  78387. - LCCR3_HorSnchH + LCCR3_ACBsCntOff +
  78388. - LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
  78389. - }
  78390. - if (machine_is_huw_webpanel()) {
  78391. - DPRINTK("Configuring HuW LCD\n");
  78392. - shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
  78393. - shadow.lccr1 = LCCR1_DisWdth(var->xres) +
  78394. - LCCR1_HorSnchWdth(3) +
  78395. - LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
  78396. - shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
  78397. - shadow.lccr3 = 8 + LCCR3_OutEnH +
  78398. - LCCR3_PixRsEdg + LCCR3_VrtSnchH +
  78399. - LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
  78400. - }
  78401. - if (machine_is_lart()) {
  78402. - DPRINTK("Configuring LART LCD\n");
  78403. -#if defined LART_GREY_LCD
  78404. - shadow.lccr0 =
  78405. - LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
  78406. - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
  78407. - LCCR0_DMADel(0);
  78408. - shadow.lccr1 =
  78409. - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
  78410. - LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
  78411. - shadow.lccr2 =
  78412. - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
  78413. - LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
  78414. - shadow.lccr3 =
  78415. - LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
  78416. - LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
  78417. -#endif
  78418. -#if defined LART_COLOR_LCD
  78419. - shadow.lccr0 =
  78420. - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
  78421. - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
  78422. - LCCR0_DMADel(0);
  78423. - shadow.lccr1 =
  78424. - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
  78425. - LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
  78426. - shadow.lccr2 =
  78427. - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
  78428. - LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
  78429. - shadow.lccr3 =
  78430. - LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
  78431. - LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
  78432. - LCCR3_PixFlEdg;
  78433. -#endif
  78434. -#if defined LART_VIDEO_OUT
  78435. - shadow.lccr0 =
  78436. - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
  78437. - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
  78438. - LCCR0_DMADel(0);
  78439. - shadow.lccr1 =
  78440. - LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
  78441. - LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
  78442. - shadow.lccr2 =
  78443. - LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
  78444. - LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
  78445. - shadow.lccr3 =
  78446. - LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
  78447. - LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
  78448. - LCCR3_PixFlEdg + LCCR3_OutEnL;
  78449. -#endif
  78450. - }
  78451. - if (machine_is_graphicsclient()) {
  78452. - DPRINTK("Configuring GraphicsClient LCD\n");
  78453. - shadow.lccr0 =
  78454. - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
  78455. - shadow.lccr1 =
  78456. - LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
  78457. - LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
  78458. - shadow.lccr2 =
  78459. - LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
  78460. - LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
  78461. - shadow.lccr3 =
  78462. - LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
  78463. - LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
  78464. - }
  78465. - if (machine_is_omnimeter()) {
  78466. - DPRINTK("Configuring OMNI LCD\n");
  78467. - shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
  78468. - shadow.lccr1 =
  78469. - LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
  78470. - LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
  78471. - shadow.lccr2 = LCCR2_DisHght(var->yres);
  78472. - shadow.lccr3 =
  78473. - LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
  78474. -//jca (GetPCD(25) << LCD3_V_PCD);
  78475. - }
  78476. - if (machine_is_xp860()) {
  78477. - DPRINTK("Configuring XP860 LCD\n");
  78478. - shadow.lccr0 =
  78479. - LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
  78480. - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
  78481. - shadow.lccr1 =
  78482. - LCCR1_DisWdth(var->xres) +
  78483. - LCCR1_HorSnchWdth(var->hsync_len) +
  78484. - LCCR1_BegLnDel(var->left_margin) +
  78485. - LCCR1_EndLnDel(var->right_margin);
  78486. - shadow.lccr2 =
  78487. - LCCR2_DisHght(var->yres) +
  78488. - LCCR2_VrtSnchWdth(var->vsync_len) +
  78489. - LCCR2_BegFrmDel(var->upper_margin) +
  78490. - LCCR2_EndFrmDel(var->lower_margin);
  78491. - shadow.lccr3 =
  78492. - LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
  78493. - }
  78494. -
  78495. - /*
  78496. - * Ok, since we're calculating these values, we want to know
  78497. - * if the calculation is correct. If you see any of these
  78498. - * messages _PLEASE_ report the incident to me for diagnosis,
  78499. - * including details about what was happening when the
  78500. - * messages appeared. --rmk, 30 March 2001
  78501. - */
  78502. - if (shadow.lccr0 != new_regs->lccr0) {
  78503. - printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
  78504. - shadow.lccr1, new_regs->lccr1);
  78505. - different = 1;
  78506. - }
  78507. - if (shadow.lccr1 != new_regs->lccr1) {
  78508. - printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
  78509. - shadow.lccr1, new_regs->lccr1);
  78510. - different = 1;
  78511. - }
  78512. - if (shadow.lccr2 != new_regs->lccr2) {
  78513. - printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
  78514. - shadow.lccr2, new_regs->lccr2);
  78515. - different = 1;
  78516. - }
  78517. - if (shadow.lccr3 != new_regs->lccr3) {
  78518. - printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
  78519. - shadow.lccr3, new_regs->lccr3);
  78520. - different = 1;
  78521. - }
  78522. - if (different) {
  78523. - printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
  78524. - var->xres, var->hsync_len,
  78525. - var->left_margin, var->right_margin);
  78526. - printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
  78527. - var->yres, var->vsync_len,
  78528. - var->upper_margin, var->lower_margin);
  78529. -
  78530. - printk(KERN_ERR "Please report this to Russell King "
  78531. - "<rmk@arm.linux.org.uk>\n");
  78532. - }
  78533. -
  78534. - DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
  78535. - DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
  78536. - DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
  78537. - DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
  78538. -}
  78539. -#else
  78540. -#define sa1100fb_check_shadow(regs,var,pcd)
  78541. -#endif
  78542. -
  78543. -
  78544. -
  78545. /*
  78546. * IMHO this looks wrong. In 8BPP, length should be 8.
  78547. */
  78548. @@ -488,42 +262,56 @@
  78549. #endif
  78550. #endif
  78551. -#ifdef CONFIG_SA1100_H3600
  78552. -static struct sa1100fb_mach_info h3600_info __initdata = {
  78553. -#ifdef CONFIG_IPAQ_H3100
  78554. - pixclock: 407766, bpp: 4,
  78555. +#ifdef CONFIG_SA1100_H3XXX
  78556. +static struct sa1100fb_mach_info h3800_info __initdata = {
  78557. + pixclock: 174757, bpp: 16,
  78558. xres: 320, yres: 240,
  78559. - hsync_len: 26, vsync_len: 41,
  78560. - left_margin: 4, upper_margin: 0,
  78561. - right_margin: 4, lower_margin: 0,
  78562. + hsync_len: 3, vsync_len: 3,
  78563. + left_margin: 12, upper_margin: 10,
  78564. + right_margin: 17, lower_margin: 1,
  78565. - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  78566. - cmap_greyscale: 1, cmap_static: 1,
  78567. - cmap_inverse: 1,
  78568. + sync: 0, cmap_static: 1,
  78569. - lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
  78570. - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
  78571. -#else
  78572. - pixclock: 174757, bpp: 16,
  78573. + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78574. + lccr3: LCCR3_ACBsCntOff | LCCR3_PixFlEdg | LCCR3_OutEnH,
  78575. +};
  78576. +
  78577. +static struct sa1100fb_mach_info h3600_info __initdata = {
  78578. + pixclock: 174757, bpp: 16,
  78579. xres: 320, yres: 240,
  78580. hsync_len: 3, vsync_len: 3,
  78581. left_margin: 12, upper_margin: 10,
  78582. right_margin: 17, lower_margin: 1,
  78583. - sync: 0,
  78584. + sync: 0, cmap_static: 1,
  78585. lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78586. - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
  78587. -#endif
  78588. + lccr3: LCCR3_ACBsCntOff | LCCR3_OutEnH | LCCR3_PixFlEdg,
  78589. };
  78590. static struct sa1100fb_rgb h3600_rgb_16 = {
  78591. red: { offset: 12, length: 4, },
  78592. green: { offset: 7, length: 4, },
  78593. blue: { offset: 1, length: 4, },
  78594. - transp: { offset: 0, length: 0, },
  78595. + transp: { offset: 0, length: 0, },
  78596. +};
  78597. +
  78598. +static struct sa1100fb_mach_info h3100_info __initdata = {
  78599. + pixclock: 406977, bpp: 4,
  78600. + xres: 320, yres: 240,
  78601. +
  78602. + hsync_len: 26, vsync_len: 41,
  78603. + left_margin: 4, upper_margin: 0,
  78604. + right_margin: 4, lower_margin: 0,
  78605. +
  78606. + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  78607. + cmap_greyscale: 1,
  78608. + cmap_inverse: 1,
  78609. +
  78610. + lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
  78611. + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
  78612. };
  78613. #endif
  78614. @@ -618,6 +406,58 @@
  78615. #ifdef CONFIG_SA1100_GRAPHICSCLIENT
  78616. static struct sa1100fb_mach_info graphicsclient_info __initdata = {
  78617. +// for LQ64D343
  78618. + pixclock: 53500, bpp: 8,
  78619. + xres: 640, yres: 480,
  78620. +
  78621. + hsync_len: 9, vsync_len: 9,
  78622. + left_margin: 54, upper_margin: 24,
  78623. + right_margin: 54, lower_margin: 32,
  78624. +
  78625. + sync: 0,
  78626. +
  78627. + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78628. + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
  78629. +};
  78630. +#endif
  78631. +
  78632. +#ifdef CONFIG_SA1100_GRAPHICSMASTER
  78633. +static struct sa1100fb_mach_info graphicsmaster_info __initdata = {
  78634. +// for LQ64D343
  78635. + pixclock: 53500, bpp: 8,
  78636. + xres: 640, yres: 480,
  78637. +
  78638. + hsync_len: 9, vsync_len: 9,
  78639. + left_margin: 54, upper_margin: 24,
  78640. + right_margin: 54, lower_margin: 32,
  78641. +
  78642. + sync: 0,
  78643. +
  78644. + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78645. + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
  78646. +};
  78647. +#endif
  78648. +
  78649. +#ifdef CONFIG_SA1100_ADSBITSY
  78650. +static struct sa1100fb_mach_info adsbitsy_info __initdata = {
  78651. +// for LQ64D343
  78652. + pixclock: 53500, bpp: 8,
  78653. + xres: 640, yres: 480,
  78654. +
  78655. + hsync_len: 9, vsync_len: 9,
  78656. + left_margin: 54, upper_margin: 24,
  78657. + right_margin: 54, lower_margin: 32,
  78658. +
  78659. + sync: 0,
  78660. +
  78661. + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78662. + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
  78663. +};
  78664. +#endif
  78665. +
  78666. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  78667. +static struct sa1100fb_mach_info adsbitsyplus_info __initdata = {
  78668. +// for LQ64D343
  78669. pixclock: 53500, bpp: 8,
  78670. xres: 640, yres: 480,
  78671. @@ -699,7 +539,6 @@
  78672. lccr3: LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
  78673. };
  78674. #endif
  78675. -
  78676. #ifdef LART_KIT01_LCD
  78677. static struct sa1100fb_mach_info lart_kit01_info __initdata =
  78678. {
  78679. @@ -707,7 +546,7 @@
  78680. xres: 640, yres: 480,
  78681. hsync_len: 64, vsync_len: 3,
  78682. - left_margin: 122, upper_margin: 45,
  78683. + left_margin: 122, upper_margin: 45,
  78684. right_margin: 10, lower_margin: 10,
  78685. sync: 0,
  78686. @@ -717,6 +556,40 @@
  78687. };
  78688. #endif
  78689. +#ifdef CONFIG_SA1100_FRODO
  78690. +static struct sa1100fb_mach_info frodo_kit01_info __initdata =
  78691. +{
  78692. + /* best would be 41731 (25.8mhz), but we can only do 14.743mhz at 191.7mhz clock speed */
  78693. + pixclock: 73030, bpp: 16,
  78694. + xres: 640, yres: 480,
  78695. +
  78696. + hsync_len: 32, vsync_len: 19,
  78697. + left_margin: 120, upper_margin: 33,
  78698. + right_margin: 17, lower_margin: 12,
  78699. +
  78700. + sync: 0,
  78701. +
  78702. + lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78703. + lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg
  78704. +};
  78705. +#endif
  78706. +
  78707. +#ifdef CONFIG_SA1100_SHANNON
  78708. +static struct sa1100fb_mach_info shannon_info __initdata = {
  78709. + pixclock: 152500, bpp: 8,
  78710. + xres: 640, yres: 480,
  78711. +
  78712. + hsync_len: 4, vsync_len: 3,
  78713. + left_margin: 2, upper_margin: 0,
  78714. + right_margin: 1, lower_margin: 0,
  78715. +
  78716. + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  78717. +
  78718. + lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
  78719. + lccr3: LCCR3_ACBsDiv(512),
  78720. +};
  78721. +#endif
  78722. +
  78723. #ifdef CONFIG_SA1100_OMNIMETER
  78724. static struct sa1100fb_mach_info omnimeter_info __initdata = {
  78725. pixclock: 0, bpp: 4,
  78726. @@ -752,7 +625,24 @@
  78727. sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  78728. lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
  78729. - lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg,
  78730. + lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
  78731. +};
  78732. +#endif
  78733. +
  78734. +#ifdef CONFIG_SA1100_SIMPUTER
  78735. +static struct sa1100fb_mach_info simputer_info __initdata = {
  78736. + pixclock: 70000, bpp: 4,
  78737. + xres: 320, yres: 240,
  78738. +
  78739. + hsync_len: 9, vsync_len: 2,
  78740. + left_margin: 9, upper_margin: 0,
  78741. + right_margin: 2, lower_margin: 0,
  78742. +
  78743. + cmap_greyscale: 1,
  78744. + sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT ,
  78745. +
  78746. + lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
  78747. + lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(202),
  78748. };
  78749. #endif
  78750. @@ -828,7 +718,6 @@
  78751. #endif
  78752. -
  78753. static struct sa1100fb_mach_info * __init
  78754. sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
  78755. {
  78756. @@ -849,11 +738,17 @@
  78757. #endif
  78758. }
  78759. #endif
  78760. -#ifdef CONFIG_SA1100_H3600
  78761. +#ifdef CONFIG_SA1100_H3XXX
  78762. if (machine_is_h3600()) {
  78763. inf = &h3600_info;
  78764. fbi->rgb[RGB_16] = &h3600_rgb_16;
  78765. }
  78766. + if (machine_is_h3100()) {
  78767. + inf = &h3100_info;
  78768. + }
  78769. + if (machine_is_h3800()) {
  78770. + inf = &h3800_info;
  78771. + }
  78772. #endif
  78773. #ifdef CONFIG_SA1100_BRUTUS
  78774. if (machine_is_brutus()) {
  78775. @@ -876,6 +771,22 @@
  78776. inf = &graphicsclient_info;
  78777. }
  78778. #endif
  78779. +#ifdef CONFIG_SA1100_GRAPHICSMASTER
  78780. + if (machine_is_graphicsmaster()) {
  78781. + inf = &graphicsmaster_info;
  78782. + }
  78783. +#endif
  78784. +#ifdef CONFIG_SA1100_ADSBITSY
  78785. + if (machine_is_adsbitsy()) {
  78786. + inf = &adsbitsy_info;
  78787. + }
  78788. +#endif
  78789. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  78790. + if (machine_is_adsbitsyplus()) {
  78791. + inf = &adsbitsyplus_info;
  78792. + }
  78793. + }
  78794. +#endif
  78795. #ifdef CONFIG_SA1100_HUW_WEBPANEL
  78796. if (machine_is_huw_webpanel()) {
  78797. inf = &huw_webpanel_info;
  78798. @@ -897,6 +808,21 @@
  78799. #endif
  78800. }
  78801. #endif
  78802. +#ifdef CONFIG_SA1100_FRODO
  78803. + if (machine_is_frodo()) {
  78804. + inf = &frodo_kit01_info;
  78805. + }
  78806. +#endif
  78807. +#ifdef CONFIG_SA1100_SHANNON
  78808. + if (machine_is_shannon()) {
  78809. + inf = &shannon_info;
  78810. + }
  78811. +#endif
  78812. +#ifdef CONFIG_SA1100_SIMPUTER
  78813. + if (machine_is_simputer()) {
  78814. + inf = &simputer_info;
  78815. + }
  78816. +#endif
  78817. #ifdef CONFIG_SA1100_OMNIMETER
  78818. if (machine_is_omnimeter()) {
  78819. inf = &omnimeter_info;
  78820. @@ -1556,7 +1482,8 @@
  78821. unsigned int pcd;
  78822. if (pixclock) {
  78823. - pcd = get_cclk_frequency() * pixclock;
  78824. + pcd = cpufreq_get(0) / 100;
  78825. + pcd *= pixclock;
  78826. pcd /= 10000000;
  78827. pcd += 1; /* make up for integer math truncations */
  78828. } else {
  78829. @@ -1580,6 +1507,7 @@
  78830. return pcd;
  78831. }
  78832. +
  78833. /*
  78834. * sa1100fb_activate_var():
  78835. * Configures LCD Controller based on entries in var parameter. Settings are
  78836. @@ -1659,8 +1587,6 @@
  78837. if (pcd)
  78838. new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
  78839. - sa1100fb_check_shadow(&new_regs, var, pcd);
  78840. -
  78841. DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
  78842. DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
  78843. DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
  78844. @@ -1733,6 +1659,10 @@
  78845. if (machine_is_omnimeter())
  78846. LEDBacklightOn();
  78847. #endif
  78848. +#ifdef CONFIG_SA1100_FRODO
  78849. + if (machine_is_frodo())
  78850. + frodo_cpld_set (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
  78851. +#endif
  78852. }
  78853. /*
  78854. @@ -1755,6 +1685,10 @@
  78855. if (machine_is_omnimeter())
  78856. LEDBacklightOff();
  78857. #endif
  78858. +#ifdef CONFIG_SA1100_FRODO
  78859. + if (machine_is_frodo())
  78860. + frodo_cpld_clear (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
  78861. +#endif
  78862. }
  78863. static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
  78864. @@ -1773,20 +1707,25 @@
  78865. if (machine_is_omnimeter())
  78866. LCDPowerOn();
  78867. #endif
  78868. -#ifdef CONFIG_SA1100_H3600
  78869. - if (machine_is_h3600()) {
  78870. - set_h3600_egpio(EGPIO_H3600_LCD_ON |
  78871. - EGPIO_H3600_LCD_PCI |
  78872. - EGPIO_H3600_LCD_5V_ON |
  78873. - EGPIO_H3600_LVDD_ON);
  78874. - }
  78875. -#endif
  78876. + if (machine_is_h3xxx())
  78877. + set_h3600_egpio( IPAQ_EGPIO_LCD_ON ); /* Turn on power to the LCD */
  78878. #ifdef CONFIG_SA1100_STORK
  78879. if (machine_is_stork()) {
  78880. storkSetLCDCPLD(0, 1);
  78881. storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
  78882. }
  78883. #endif
  78884. +#ifdef CONFIG_SA1100_FRODO
  78885. + if (machine_is_frodo())
  78886. + sa1100fb_backlight_on(fbi);
  78887. +#endif
  78888. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  78889. + if (machine_is_adsbitsyplus()) {
  78890. + ADS_CPLD_PCON &= ~ADS_PCON_PANEL_ON;
  78891. + ADS_CPLD_SUPPC |= ADS_SUPPC_VEE_ON;
  78892. + }
  78893. +#endif
  78894. +
  78895. }
  78896. static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
  78897. @@ -1802,20 +1741,24 @@
  78898. if (machine_is_huw_webpanel())
  78899. BCR_set(BCR_TFT_NPWR);
  78900. #endif
  78901. -#ifdef CONFIG_SA1100_H3600
  78902. - if (machine_is_h3600()) {
  78903. - clr_h3600_egpio(EGPIO_H3600_LCD_ON |
  78904. - EGPIO_H3600_LCD_PCI |
  78905. - EGPIO_H3600_LCD_5V_ON |
  78906. - EGPIO_H3600_LVDD_ON);
  78907. - }
  78908. -#endif
  78909. + if (machine_is_h3xxx())
  78910. + clr_h3600_egpio( IPAQ_EGPIO_LCD_ON );
  78911. #ifdef CONFIG_SA1100_STORK
  78912. if (machine_is_stork()) {
  78913. storkSetLCDCPLD(0, 0);
  78914. storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
  78915. }
  78916. #endif
  78917. +#ifdef CONFIG_SA1100_FRODO
  78918. + if (machine_is_frodo())
  78919. + sa1100fb_backlight_off(fbi);
  78920. +#endif
  78921. +#ifdef CONFIG_SA1100_ADSBITSYPLUS
  78922. + if (machine_is_adsbitsyplus()) {
  78923. + ADS_CPLD_PCON |= ADS_PCON_PANEL_ON;
  78924. + ADS_CPLD_SUPPC &= ~ADS_SUPPC_VEE_ON;
  78925. + }
  78926. +#endif
  78927. }
  78928. static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
  78929. @@ -1911,15 +1854,29 @@
  78930. LCCR0 |= LCCR0_LEN;
  78931. #ifdef CONFIG_SA1100_GRAPHICSCLIENT
  78932. -#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
  78933. if (machine_is_graphicsclient()) {
  78934. // From ADS doc again...same as disable
  78935. set_current_state(TASK_UNINTERRUPTIBLE);
  78936. schedule_timeout(20 * HZ / 1000);
  78937. - GPSR |= GPIO_GPIO24;
  78938. + GPDR |= GPIO_GPIO24;
  78939. + GPSR = GPIO_GPIO24;
  78940. + }
  78941. +#endif
  78942. +#ifdef CONFIG_SA1100_GRAPHICSMASTER
  78943. + if (machine_is_graphicsmaster()) {
  78944. + // From ADS doc again...same as disable
  78945. + set_current_state(TASK_UNINTERRUPTIBLE);
  78946. + schedule_timeout(20 * HZ / 1000);
  78947. + GPDR |= GPIO_GPIO24;
  78948. + GPSR = GPIO_GPIO24;
  78949. }
  78950. #endif
  78951. + if (machine_is_shannon()) {
  78952. + GPDR |= SHANNON_GPIO_DISP_EN;
  78953. + GPSR |= SHANNON_GPIO_DISP_EN;
  78954. + }
  78955. +
  78956. DPRINTK("DBAR1 = %p\n", DBAR1);
  78957. DPRINTK("DBAR2 = %p\n", DBAR2);
  78958. DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
  78959. @@ -1935,7 +1892,6 @@
  78960. DPRINTK("Disabling LCD controller\n");
  78961. #ifdef CONFIG_SA1100_GRAPHICSCLIENT
  78962. -#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
  78963. if (machine_is_graphicsclient()) {
  78964. /*
  78965. * From ADS internal document:
  78966. @@ -1944,6 +1900,22 @@
  78967. *
  78968. * We'll wait 20msec.
  78969. */
  78970. + GPDR |= GPIO_GPIO24;
  78971. + GPCR |= GPIO_GPIO24;
  78972. + set_current_state(TASK_UNINTERRUPTIBLE);
  78973. + schedule_timeout(20 * HZ / 1000);
  78974. + }
  78975. +#endif
  78976. +#ifdef CONFIG_SA1100_GRAPHICSMASTER
  78977. + if (machine_is_graphicsmaster()) {
  78978. + /*
  78979. + * From ADS internal document:
  78980. + * GPIO24 should be LOW at least 10msec prior to disabling
  78981. + * the LCD interface.
  78982. + *
  78983. + * We'll wait 20msec.
  78984. + */
  78985. + GPDR |= GPIO_GPIO24;
  78986. GPCR |= GPIO_GPIO24;
  78987. set_current_state(TASK_UNINTERRUPTIBLE);
  78988. schedule_timeout(20 * HZ / 1000);
  78989. @@ -1958,12 +1930,15 @@
  78990. }
  78991. #endif
  78992. + if (machine_is_shannon()) {
  78993. + GPCR |= SHANNON_GPIO_DISP_EN;
  78994. + }
  78995. +
  78996. add_wait_queue(&fbi->ctrlr_wait, &wait);
  78997. set_current_state(TASK_UNINTERRUPTIBLE);
  78998. LCSR = 0xffffffff; /* Clear LCD Status Register */
  78999. LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
  79000. - enable_irq(IRQ_LCD); /* Enable LCD IRQ */
  79001. LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */
  79002. schedule_timeout(20 * HZ / 1000);
  79003. @@ -2006,12 +1981,13 @@
  79004. * Disable controller for clock change. If the
  79005. * controller is already disabled, then do nothing.
  79006. */
  79007. - if (old_state != C_DISABLE) {
  79008. + if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
  79009. fbi->state = state;
  79010. sa1100fb_disable_controller(fbi);
  79011. }
  79012. break;
  79013. + case C_DISABLE_PM:
  79014. case C_DISABLE:
  79015. /*
  79016. * Disable controller
  79017. @@ -2050,6 +2026,16 @@
  79018. }
  79019. break;
  79020. + case C_ENABLE_PM:
  79021. + /*
  79022. + * Re-enable the controller after PM. This is not
  79023. + * perfect - think about the case where we were doing
  79024. + * a clock change, and we suspended half-way through.
  79025. + */
  79026. + if (old_state != C_DISABLE_PM)
  79027. + break;
  79028. + /* fall through */
  79029. +
  79030. case C_ENABLE:
  79031. /*
  79032. * Power up the LCD screen, enable controller, and
  79033. @@ -2162,10 +2148,10 @@
  79034. if (state == 0) {
  79035. /* Enter D0. */
  79036. - set_ctrlr_state(fbi, C_ENABLE);
  79037. + set_ctrlr_state(fbi, C_ENABLE_PM);
  79038. } else {
  79039. /* Enter D1-D3. Disable the LCD controller. */
  79040. - set_ctrlr_state(fbi, C_DISABLE);
  79041. + set_ctrlr_state(fbi, C_DISABLE_PM);
  79042. }
  79043. }
  79044. DPRINTK("done\n");
  79045. @@ -2304,7 +2290,7 @@
  79046. goto failed;
  79047. ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
  79048. - fbi->fb.fix.id, fbi);
  79049. + "LCD", fbi);
  79050. if (ret) {
  79051. printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
  79052. goto failed;
  79053. diff -urN linux-2.4.26/drivers/video/sa1100fb.h linux-2.4.26-vrs1/drivers/video/sa1100fb.h
  79054. --- linux-2.4.26/drivers/video/sa1100fb.h 2001-10-25 21:53:52.000000000 +0100
  79055. +++ linux-2.4.26-vrs1/drivers/video/sa1100fb.h 2004-01-14 21:32:27.000000000 +0000
  79056. @@ -127,6 +127,8 @@
  79057. #define C_DISABLE_CLKCHANGE (2)
  79058. #define C_ENABLE_CLKCHANGE (3)
  79059. #define C_REENABLE (4)
  79060. +#define C_DISABLE_PM (5)
  79061. +#define C_ENABLE_PM (6)
  79062. #define SA1100_NAME "SA1100"
  79063. diff -urN linux-2.4.26/drivers/video/vga16fb.c linux-2.4.26-vrs1/drivers/video/vga16fb.c
  79064. --- linux-2.4.26/drivers/video/vga16fb.c 2001-11-14 22:52:20.000000000 +0000
  79065. +++ linux-2.4.26-vrs1/drivers/video/vga16fb.c 2004-04-04 22:51:02.000000000 +0100
  79066. @@ -142,7 +142,7 @@
  79067. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  79068. strcpy(fix->id,"VGA16 VGA");
  79069. - fix->smem_start = VGA_FB_PHYS;
  79070. + fix->smem_start = VGA_MAP_MEM(VGA_FB_PHYS);
  79071. fix->smem_len = VGA_FB_PHYS_LEN;
  79072. fix->type = FB_TYPE_VGA_PLANES;
  79073. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  79074. @@ -896,7 +896,7 @@
  79075. /* XXX share VGA_FB_PHYS region with vgacon */
  79076. - vga16fb.video_vbase = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN);
  79077. + vga16fb.video_vbase = ioremap(VGA_MAP_MEM(VGA_FB_PHYS), VGA_FB_PHYS_LEN);
  79078. if (!vga16fb.video_vbase) {
  79079. printk(KERN_ERR "vga16fb: unable to map device\n");
  79080. return -ENOMEM;
  79081. diff -urN linux-2.4.26/fs/adfs/dir.c linux-2.4.26-vrs1/fs/adfs/dir.c
  79082. --- linux-2.4.26/fs/adfs/dir.c 2000-09-18 23:14:06.000000000 +0100
  79083. +++ linux-2.4.26-vrs1/fs/adfs/dir.c 2004-01-14 21:32:27.000000000 +0000
  79084. @@ -23,7 +23,7 @@
  79085. /*
  79086. * For future. This should probably be per-directory.
  79087. */
  79088. -static rwlock_t adfs_dir_lock;
  79089. +static rwlock_t adfs_dir_lock = RW_LOCK_UNLOCKED;
  79090. static int
  79091. adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
  79092. diff -urN linux-2.4.26/fs/adfs/map.c linux-2.4.26-vrs1/fs/adfs/map.c
  79093. --- linux-2.4.26/fs/adfs/map.c 2001-10-25 21:53:53.000000000 +0100
  79094. +++ linux-2.4.26-vrs1/fs/adfs/map.c 2004-01-14 21:32:27.000000000 +0000
  79095. @@ -13,24 +13,27 @@
  79096. #include <linux/adfs_fs.h>
  79097. #include <linux/spinlock.h>
  79098. +#include <asm/unaligned.h>
  79099. +
  79100. #include "adfs.h"
  79101. /*
  79102. * For the future...
  79103. */
  79104. -static rwlock_t adfs_map_lock;
  79105. +static rwlock_t adfs_map_lock = RW_LOCK_UNLOCKED;
  79106. +/*
  79107. + * This is fun. We need to load up to 19 bits from the map at an
  79108. + * arbitary bit alignment. (We're limited to 19 bits by F+ version
  79109. + * 2).
  79110. + */
  79111. #define GET_FRAG_ID(_map,_start,_idmask) \
  79112. ({ \
  79113. - unsigned long _v2, _frag; \
  79114. - unsigned int _tmp; \
  79115. - _tmp = _start >> 5; \
  79116. - _frag = le32_to_cpu(_map[_tmp]); \
  79117. - _v2 = le32_to_cpu(_map[_tmp + 1]); \
  79118. - _tmp = start & 31; \
  79119. - _frag = (_frag >> _tmp) | (_v2 << (32 - _tmp)); \
  79120. + unsigned char *_m = _map + (_start >> 3); \
  79121. + u32 _frag = get_unaligned((u32 *)_m); \
  79122. + _frag >>= (_start & 7); \
  79123. _frag & _idmask; \
  79124. - })
  79125. + })
  79126. /*
  79127. * return the map bit offset of the fragment frag_id in
  79128. @@ -44,14 +47,13 @@
  79129. const unsigned int frag_id, unsigned int *offset)
  79130. {
  79131. const unsigned int mapsize = dm->dm_endbit;
  79132. - const unsigned int idmask = (1 << idlen) - 1;
  79133. - unsigned long *map = ((unsigned long *)dm->dm_bh->b_data) + 1;
  79134. + const u32 idmask = (1 << idlen) - 1;
  79135. + unsigned char *map = dm->dm_bh->b_data + 4;
  79136. unsigned int start = dm->dm_startbit;
  79137. unsigned int mapptr;
  79138. + u32 frag;
  79139. do {
  79140. - unsigned long frag;
  79141. -
  79142. frag = GET_FRAG_ID(map, start, idmask);
  79143. mapptr = start + idlen;
  79144. @@ -59,15 +61,17 @@
  79145. * find end of fragment
  79146. */
  79147. {
  79148. - unsigned long v2;
  79149. + u32 v, *_map = (u32 *)map;
  79150. - while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
  79151. + v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
  79152. + while (v == 0) {
  79153. mapptr = (mapptr & ~31) + 32;
  79154. if (mapptr >= mapsize)
  79155. goto error;
  79156. + v = le32_to_cpu(_map[mapptr >> 5]);
  79157. }
  79158. - mapptr += 1 + ffz(~v2);
  79159. + mapptr += 1 + ffz(~v);
  79160. }
  79161. if (frag == frag_id)
  79162. @@ -75,8 +79,11 @@
  79163. again:
  79164. start = mapptr;
  79165. } while (mapptr < mapsize);
  79166. + return -1;
  79167. error:
  79168. + printk(KERN_ERR "adfs: oversized fragment 0x%x at 0x%x-0x%x\n",
  79169. + frag, start, mapptr);
  79170. return -1;
  79171. found:
  79172. @@ -102,10 +109,10 @@
  79173. const unsigned int mapsize = dm->dm_endbit + 32;
  79174. const unsigned int idlen = asb->s_idlen;
  79175. const unsigned int frag_idlen = idlen <= 15 ? idlen : 15;
  79176. - const unsigned int idmask = (1 << frag_idlen) - 1;
  79177. - unsigned long *map = (unsigned long *)dm->dm_bh->b_data;
  79178. + const u32 idmask = (1 << frag_idlen) - 1;
  79179. + unsigned char *map = dm->dm_bh->b_data;
  79180. unsigned int start = 8, mapptr;
  79181. - unsigned long frag;
  79182. + u32 frag;
  79183. unsigned long total = 0;
  79184. /*
  79185. @@ -133,15 +140,17 @@
  79186. * find end of fragment
  79187. */
  79188. {
  79189. - unsigned long v2;
  79190. + u32 v, *_map = (u32 *)map;
  79191. - while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
  79192. + v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
  79193. + while (v == 0) {
  79194. mapptr = (mapptr & ~31) + 32;
  79195. if (mapptr >= mapsize)
  79196. goto error;
  79197. + v = le32_to_cpu(_map[mapptr >> 5]);
  79198. }
  79199. - mapptr += 1 + ffz(~v2);
  79200. + mapptr += 1 + ffz(~v);
  79201. }
  79202. total += mapptr - start;
  79203. diff -urN linux-2.4.26/fs/adfs/super.c linux-2.4.26-vrs1/fs/adfs/super.c
  79204. --- linux-2.4.26/fs/adfs/super.c 2002-02-25 19:38:07.000000000 +0000
  79205. +++ linux-2.4.26-vrs1/fs/adfs/super.c 2004-01-14 21:32:27.000000000 +0000
  79206. @@ -386,6 +386,14 @@
  79207. sb->u.adfs_sb.s_size = adfs_discsize(dr, sb->s_blocksize_bits);
  79208. sb->u.adfs_sb.s_version = dr->format_version;
  79209. sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize;
  79210. +
  79211. + printk(KERN_DEBUG "ADFS: idlen %d map bit size %d sector size %d\n",
  79212. + dr->idlen, 1 << dr->log2bpmb, 1 << dr->log2secsize);
  79213. + printk(KERN_DEBUG "ADFS: map size %d map2blk %d version %d share size %d\n",
  79214. + sb->u.adfs_sb.s_map_size,
  79215. + sb->u.adfs_sb.s_map2blk,
  79216. + sb->u.adfs_sb.s_version,
  79217. + 1 << sb->u.adfs_sb.s_log2sharesize);
  79218. sb->u.adfs_sb.s_map = adfs_read_map(sb, dr);
  79219. if (!sb->u.adfs_sb.s_map)
  79220. @@ -393,6 +401,8 @@
  79221. brelse(bh);
  79222. + printk(KERN_DEBUG "ADFS: ids per zone %d\n", sb->u.adfs_sb.s_ids_per_zone);
  79223. +
  79224. /*
  79225. * set up enough so that we can read an inode
  79226. */
  79227. diff -urN linux-2.4.26/fs/binfmt_aout.c linux-2.4.26-vrs1/fs/binfmt_aout.c
  79228. --- linux-2.4.26/fs/binfmt_aout.c 2001-11-03 01:39:20.000000000 +0000
  79229. +++ linux-2.4.26-vrs1/fs/binfmt_aout.c 2004-01-14 21:32:27.000000000 +0000
  79230. @@ -422,7 +422,11 @@
  79231. start_thread(regs, ex.a_entry, current->mm->start_stack);
  79232. if (current->ptrace & PT_PTRACED)
  79233. send_sig(SIGTRAP, current, 0);
  79234. +#ifndef __arm__
  79235. return 0;
  79236. +#else
  79237. + return regs->ARM_r0;
  79238. +#endif
  79239. }
  79240. static int load_aout_library(struct file *file)
  79241. @@ -452,8 +456,11 @@
  79242. /* For QMAGIC, the starting address is 0x20 into the page. We mask
  79243. this off to get the starting address for the page */
  79244. -
  79245. - start_addr = ex.a_entry & 0xfffff000;
  79246. +#ifndef __arm__
  79247. + start_addr = ex.a_entry & 0xfffff000;
  79248. +#else
  79249. + start_addr = ex.a_entry & 0xffff8000;
  79250. +#endif
  79251. if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
  79252. static unsigned long error_time;
  79253. diff -urN linux-2.4.26/fs/binfmt_elf.c linux-2.4.26-vrs1/fs/binfmt_elf.c
  79254. --- linux-2.4.26/fs/binfmt_elf.c 2004-04-19 11:44:28.000000000 +0100
  79255. +++ linux-2.4.26-vrs1/fs/binfmt_elf.c 2004-04-18 21:47:51.000000000 +0100
  79256. @@ -636,7 +636,6 @@
  79257. }
  79258. current->mm->start_stack = bprm->p;
  79259. -
  79260. /* Now we do a little grungy work by mmaping the ELF image into
  79261. the correct location in memory. At this point, we assume that
  79262. the image should be loaded at fixed address, not at a variable
  79263. diff -urN linux-2.4.26/fs/exec.c linux-2.4.26-vrs1/fs/exec.c
  79264. --- linux-2.4.26/fs/exec.c 2004-02-27 20:03:28.000000000 +0000
  79265. +++ linux-2.4.26-vrs1/fs/exec.c 2004-02-23 13:36:36.000000000 +0000
  79266. @@ -315,6 +315,7 @@
  79267. spin_unlock(&tsk->mm->page_table_lock);
  79268. /* no need for flush_tlb */
  79269. + memc_update_addr(tsk->mm, *pte, address);
  79270. return;
  79271. out:
  79272. spin_unlock(&tsk->mm->page_table_lock);
  79273. diff -urN linux-2.4.26/fs/jffs/inode-v23.c linux-2.4.26-vrs1/fs/jffs/inode-v23.c
  79274. --- linux-2.4.26/fs/jffs/inode-v23.c 2001-10-04 23:14:35.000000000 +0100
  79275. +++ linux-2.4.26-vrs1/fs/jffs/inode-v23.c 2004-01-14 21:32:27.000000000 +0000
  79276. @@ -10,7 +10,7 @@
  79277. * the Free Software Foundation; either version 2 of the License, or
  79278. * (at your option) any later version.
  79279. *
  79280. - * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
  79281. + * $Id: inode-v23.c,v 1.72 2002/01/31 11:42:57 cdavies Exp $
  79282. *
  79283. * Ported to Linux 2.3.x and MTD:
  79284. * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
  79285. @@ -48,6 +48,7 @@
  79286. #include <linux/stat.h>
  79287. #include <linux/blkdev.h>
  79288. #include <linux/quotaops.h>
  79289. +#include <linux/compatmac.h>
  79290. #include <asm/semaphore.h>
  79291. #include <asm/byteorder.h>
  79292. #include <asm/uaccess.h>
  79293. @@ -58,6 +59,11 @@
  79294. #include "jffs_proc.h"
  79295. #endif
  79296. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
  79297. +#define minor(x) MINOR(x)
  79298. +#define major(x) MAJOR(x)
  79299. +#endif
  79300. +
  79301. static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
  79302. static struct super_operations jffs_ops;
  79303. @@ -81,7 +87,7 @@
  79304. D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
  79305. kdevname(dev)));
  79306. - if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
  79307. + if (major(dev) != MTD_BLOCK_MAJOR) {
  79308. printk(KERN_WARNING "JFFS: Trying to mount a "
  79309. "non-mtd device.\n");
  79310. return 0;
  79311. @@ -358,7 +364,7 @@
  79312. inode->i_nlink = raw_inode->nlink;
  79313. inode->i_uid = raw_inode->uid;
  79314. inode->i_gid = raw_inode->gid;
  79315. - inode->i_rdev = 0;
  79316. + inode->i_rdev = NODEV;
  79317. inode->i_size = raw_inode->dsize;
  79318. inode->i_atime = raw_inode->atime;
  79319. inode->i_mtime = raw_inode->mtime;
  79320. diff -urN linux-2.4.26/fs/jffs/intrep.c linux-2.4.26-vrs1/fs/jffs/intrep.c
  79321. --- linux-2.4.26/fs/jffs/intrep.c 2003-06-13 15:51:37.000000000 +0100
  79322. +++ linux-2.4.26-vrs1/fs/jffs/intrep.c 2004-01-14 21:32:27.000000000 +0000
  79323. @@ -10,7 +10,7 @@
  79324. * the Free Software Foundation; either version 2 of the License, or
  79325. * (at your option) any later version.
  79326. *
  79327. - * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
  79328. + * $Id: intrep.c,v 1.104 2002/03/05 14:07:39 dwmw2 Exp $
  79329. *
  79330. * Ported to Linux 2.3.x and MTD:
  79331. * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
  79332. @@ -772,6 +772,9 @@
  79333. __u32 free_chunk_size1;
  79334. __u32 free_chunk_size2;
  79335. + __u32 largest_hole = 0;
  79336. + __u32 hole_end_offset = 0;
  79337. + __u32 head_offset;
  79338. #define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */
  79339. int num_free_space = 0; /* Flag err if more than TWO
  79340. @@ -884,6 +887,21 @@
  79341. (unsigned int) start,
  79342. (unsigned int)(test_start - start)));
  79343. + D1(printk("Reducing start to 0x%x from 0x%x\n",
  79344. + test_start, start));
  79345. + if (largest_hole < test_start - start){
  79346. +
  79347. + D3(printk("was hole = %x end_offset = %x\n",
  79348. + largest_hole, hole_end_offset));
  79349. + if (fmc->head) {
  79350. + largest_hole = test_start - start;
  79351. + hole_end_offset = test_start;
  79352. + }
  79353. + }
  79354. +
  79355. + D3(printk("now = %x end_offset = %x\n",
  79356. + largest_hole, hole_end_offset));
  79357. +
  79358. /* below, space from "start" to "pos" will be marked dirty. */
  79359. start = test_start;
  79360. @@ -956,6 +974,19 @@
  79361. num_free_space++;
  79362. D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
  79363. (unsigned int) start, (unsigned int) (pos - start)));
  79364. +
  79365. + if (largest_hole < pos - start) {
  79366. +
  79367. + D3(printk("was hole = %x end_offset = %x\n",
  79368. + largest_hole, hole_end_offset));
  79369. + if (fmc->head){
  79370. + largest_hole = pos - start;
  79371. + hole_end_offset = pos;
  79372. + }
  79373. +
  79374. + D3(printk("now = %x end_offset = %x\n",
  79375. + largest_hole, hole_end_offset));
  79376. + }
  79377. }else{
  79378. num_free_spc_not_accp++;
  79379. D1(printk("Free space (#%i) found but *Not* accepted: Starting "
  79380. @@ -968,7 +999,7 @@
  79381. (unsigned int) start, (unsigned int) (pos - start)));
  79382. jffs_fmalloced(fmc, (__u32) start,
  79383. (__u32) (pos - start), 0);
  79384. - }
  79385. + }
  79386. }
  79387. if(num_free_space > NUMFREEALLOWED){
  79388. @@ -1002,9 +1033,11 @@
  79389. to scan for the magic pattern. */
  79390. D1(printk("*************** Dirty flash memory or "
  79391. "bad inode: "
  79392. - "hexdump(pos = 0x%lx, len = 128):\n",
  79393. - (long)pos));
  79394. - D1(jffs_hexdump(fmc->mtd, pos, 128));
  79395. + "hexdump(pos = 0x%lx, len = %d):\n",
  79396. + (long)pos,
  79397. + end - pos > 128 ? 128 : end - pos));
  79398. + D1(jffs_hexdump(fmc->mtd, pos,
  79399. + end - pos > 128 ? 128 : end - pos));
  79400. for (pos += 4; pos < end; pos += 4) {
  79401. switch (flash_read_u32(fmc->mtd, pos)) {
  79402. @@ -1197,12 +1230,6 @@
  79403. return -ENOMEM;
  79404. }
  79405. - if ((err = jffs_insert_node(c, 0, &raw_inode,
  79406. - name, node)) < 0) {
  79407. - printk("JFFS: Failed to handle raw inode. "
  79408. - "(err = %d)\n", err);
  79409. - break;
  79410. - }
  79411. if (raw_inode.rename) {
  79412. struct jffs_delete_list *dl
  79413. = (struct jffs_delete_list *)
  79414. @@ -1226,6 +1253,12 @@
  79415. c->delete_list = dl;
  79416. node->data_size = 0;
  79417. }
  79418. + if ((err = jffs_insert_node(c, 0, &raw_inode,
  79419. + name, node)) < 0) {
  79420. + printk("JFFS: Failed to handle raw inode. "
  79421. + "(err = %d)\n", err);
  79422. + break;
  79423. + }
  79424. D3(jffs_print_node(node));
  79425. node = 0; /* Don't free the node! */
  79426. }
  79427. @@ -1242,7 +1275,19 @@
  79428. jffs_free_node(node);
  79429. DJM(no_jffs_node--);
  79430. }
  79431. - jffs_build_end(fmc);
  79432. + if (fmc->head && fmc->tail_extra &&
  79433. + fmc->head->offset + fmc->flash_size -
  79434. + fmc->tail_extra->offset - fmc->tail_extra->size > largest_hole) {
  79435. + head_offset = fmc->head->offset;
  79436. + }
  79437. + else {
  79438. + head_offset = hole_end_offset;
  79439. + }
  79440. +
  79441. + if (jffs_build_end(fmc, head_offset) < 0) {
  79442. + D(printk("jffs_build_end() failed\n"));
  79443. + return -ENOMEM;
  79444. + }
  79445. /* Free read buffer */
  79446. kfree (read_buf);
  79447. diff -urN linux-2.4.26/fs/jffs/jffs_fm.c linux-2.4.26-vrs1/fs/jffs/jffs_fm.c
  79448. --- linux-2.4.26/fs/jffs/jffs_fm.c 2001-10-04 23:13:18.000000000 +0100
  79449. +++ linux-2.4.26-vrs1/fs/jffs/jffs_fm.c 2004-01-14 21:32:27.000000000 +0000
  79450. @@ -10,7 +10,7 @@
  79451. * the Free Software Foundation; either version 2 of the License, or
  79452. * (at your option) any later version.
  79453. *
  79454. - * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
  79455. + * $Id: jffs_fm.c,v 1.29 2002/01/22 09:48:16 cdavies Exp $
  79456. *
  79457. * Ported to Linux 2.3.x and MTD:
  79458. * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
  79459. @@ -20,8 +20,14 @@
  79460. #include <linux/slab.h>
  79461. #include <linux/blkdev.h>
  79462. #include <linux/jffs.h>
  79463. +#include <linux/compatmac.h>
  79464. #include "jffs_fm.h"
  79465. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
  79466. +#define minor(x) MINOR(x)
  79467. +#define major(x) MAJOR(x)
  79468. +#endif
  79469. +
  79470. #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
  79471. static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
  79472. #endif
  79473. @@ -46,7 +52,7 @@
  79474. }
  79475. DJM(no_jffs_fmcontrol++);
  79476. - mtd = get_mtd_device(NULL, MINOR(dev));
  79477. + mtd = get_mtd_device(NULL, minor(dev));
  79478. if (!mtd) {
  79479. kfree(fmc);
  79480. @@ -89,8 +95,8 @@
  79481. /* When the flash memory scan has completed, this function should be called
  79482. before use of the control structure. */
  79483. -void
  79484. -jffs_build_end(struct jffs_fmcontrol *fmc)
  79485. +int
  79486. +jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset)
  79487. {
  79488. D3(printk("jffs_build_end()\n"));
  79489. @@ -99,13 +105,100 @@
  79490. fmc->tail = fmc->tail_extra;
  79491. }
  79492. else if (fmc->head_extra) {
  79493. - fmc->tail_extra->next = fmc->head;
  79494. - fmc->head->prev = fmc->tail_extra;
  79495. - fmc->head = fmc->head_extra;
  79496. + struct jffs_fm *fm, *cur;
  79497. +
  79498. + if (head_offset == fmc->head->offset){
  79499. + fmc->tail->next = fmc->head_extra;
  79500. + fmc->head_extra->prev = fmc->tail;
  79501. + fmc->tail = fmc->tail_extra;
  79502. + }
  79503. + else {
  79504. + fmc->tail_extra->next = fmc->head;
  79505. + fmc->head->prev = fmc->tail_extra;
  79506. + fmc->head = fmc->head_extra;
  79507. + while (fmc->head->offset != head_offset){
  79508. + fmc->tail->next = fmc->head;
  79509. + fmc->head = fmc->head->next;
  79510. + fmc->head->prev = 0;
  79511. + fmc->tail->next->prev = fmc->tail;
  79512. + fmc->tail = fmc->tail->next;
  79513. + fmc->tail->next = 0;
  79514. + }
  79515. + }
  79516. + /* Make sure the only free space we have is between tail and head.
  79517. + */
  79518. + for (cur = fmc->head; cur && cur != fmc->tail;) {
  79519. + if (cur->offset + cur->size < cur->next->offset) {
  79520. + if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
  79521. + D(printk("jffs_buid_end(): kmalloc failed!\n"));
  79522. + return -ENOMEM;
  79523. + }
  79524. + DJM(no_jffs_fm++);
  79525. + fm->size = cur->next->offset - cur->offset - cur->size;
  79526. + fm->offset = cur->offset + cur->size;
  79527. + fm->nodes = 0;
  79528. + fm->next = cur->next;
  79529. + fm->prev = cur;
  79530. + cur->next->prev = fm;
  79531. + cur->next = fm;
  79532. + cur = fm->next;
  79533. + fmc->free_size -= fm->size;
  79534. + fmc->dirty_size += fm->size;
  79535. + }
  79536. + else if (cur->offset > cur->next->offset) {
  79537. + if (cur->offset + cur->size < fmc->flash_size){
  79538. + if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))){
  79539. +
  79540. + D(printk("jffs_buid_end(): kmalloc failed!\n"));
  79541. + return -ENOMEM;
  79542. + }
  79543. + DJM(no_jffs_fm++);
  79544. + fm->size = fmc->flash_size -
  79545. + cur->offset - cur->size;
  79546. + fm->nodes = 0;
  79547. + fm->offset = cur->offset + cur->size;
  79548. + fm->next = cur->next;
  79549. + fm->prev = cur;
  79550. + cur->next->prev = fm;
  79551. + cur->next = fm;
  79552. + cur = fm->next;
  79553. + fmc->free_size -= fm->size;
  79554. + fmc->dirty_size += fm->size;
  79555. + }
  79556. + else {
  79557. + cur = cur->next;
  79558. + }
  79559. + if (cur->offset > 0) {
  79560. +
  79561. + if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
  79562. + D(printk("jffs_buid_end(): kmalloc failed!\n"));
  79563. + return -ENOMEM;
  79564. + }
  79565. + DJM(no_jffs_fm++);
  79566. + fm->size = cur->offset;
  79567. + fm->nodes = 0;
  79568. + fm->offset = 0;
  79569. + fm->next = cur;
  79570. + fm->prev = cur->prev;
  79571. + cur->prev->next = fm;
  79572. + cur->prev = fm;
  79573. + fmc->free_size -= fm->size;
  79574. + fmc->dirty_size += fm->size;
  79575. + }
  79576. + }
  79577. + else if (cur->offset + cur->size != cur->next->offset) {
  79578. + printk("jffs_build_end(): Internal error.\n");
  79579. + return -EINVAL;
  79580. + }
  79581. + else {
  79582. + cur = cur->next;
  79583. + }
  79584. + }
  79585. }
  79586. fmc->head_extra = 0; /* These two instructions should be omitted. */
  79587. fmc->tail_extra = 0;
  79588. D3(jffs_print_fmcontrol(fmc));
  79589. + return 0;
  79590. }
  79591. diff -urN linux-2.4.26/fs/jffs/jffs_fm.h linux-2.4.26-vrs1/fs/jffs/jffs_fm.h
  79592. --- linux-2.4.26/fs/jffs/jffs_fm.h 2001-10-04 23:13:18.000000000 +0100
  79593. +++ linux-2.4.26-vrs1/fs/jffs/jffs_fm.h 2004-04-19 17:25:23.000000000 +0100
  79594. @@ -10,7 +10,7 @@
  79595. * the Free Software Foundation; either version 2 of the License, or
  79596. * (at your option) any later version.
  79597. *
  79598. - * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
  79599. + * $Id: jffs_fm.h,v 1.14 2001/12/10 17:37:12 asanochkin Exp $
  79600. *
  79601. * Ported to Linux 2.3.x and MTD:
  79602. * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
  79603. @@ -123,7 +123,7 @@
  79604. struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, kdev_t dev);
  79605. -void jffs_build_end(struct jffs_fmcontrol *fmc);
  79606. +int jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset);
  79607. void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
  79608. int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
  79609. diff -urN linux-2.4.26/fs/partitions/Config.in linux-2.4.26-vrs1/fs/partitions/Config.in
  79610. --- linux-2.4.26/fs/partitions/Config.in 2002-11-28 23:53:15.000000000 +0000
  79611. +++ linux-2.4.26-vrs1/fs/partitions/Config.in 2004-01-14 21:32:27.000000000 +0000
  79612. @@ -6,6 +6,7 @@
  79613. bool ' Acorn partition support' CONFIG_ACORN_PARTITION
  79614. if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
  79615. # bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
  79616. + bool ' EESOX partition support' CONFIG_ACORN_PARTITION_EESOX
  79617. bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
  79618. bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
  79619. bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
  79620. @@ -52,6 +53,7 @@
  79621. define_bool CONFIG_ACORN_PARTITION y
  79622. define_bool CONFIG_ACORN_PARTITION_ADFS y
  79623. # define_bool CONFIG_ACORN_PARTITION_CUMANA y
  79624. + define_bool CONFIG_ACORN_PARTITION_EESOX y
  79625. define_bool CONFIG_ACORN_PARTITION_ICS y
  79626. define_bool CONFIG_ACORN_PARTITION_POWERTEC y
  79627. define_bool CONFIG_ACORN_PARTITION_RISCIX y
  79628. diff -urN linux-2.4.26/fs/partitions/acorn.c linux-2.4.26-vrs1/fs/partitions/acorn.c
  79629. --- linux-2.4.26/fs/partitions/acorn.c 2002-08-03 01:39:45.000000000 +0100
  79630. +++ linux-2.4.26-vrs1/fs/partitions/acorn.c 2004-01-14 21:32:27.000000000 +0000
  79631. @@ -7,7 +7,10 @@
  79632. * it under the terms of the GNU General Public License version 2 as
  79633. * published by the Free Software Foundation.
  79634. *
  79635. - * Scan ADFS partitions on hard disk drives.
  79636. + * Scan ADFS partitions on hard disk drives. Unfortunately, there
  79637. + * isn't a standard for partitioning drives on Acorn machines, so
  79638. + * every single manufacturer of SCSI and IDE cards created their own
  79639. + * method.
  79640. */
  79641. #include <linux/config.h>
  79642. #include <linux/kernel.h>
  79643. @@ -18,10 +21,18 @@
  79644. #include <linux/genhd.h>
  79645. #include <linux/fs.h>
  79646. #include <linux/pagemap.h>
  79647. +#include <linux/adfs_fs.h>
  79648. #include "check.h"
  79649. #include "acorn.h"
  79650. +/*
  79651. + * Partition types. (Oh for reusability)
  79652. + */
  79653. +#define PARTITION_RISCIX_MFM 1
  79654. +#define PARTITION_RISCIX_SCSI 2
  79655. +#define PARTITION_LINUX 9
  79656. +
  79657. static void
  79658. adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
  79659. {
  79660. @@ -61,6 +72,21 @@
  79661. }
  79662. #ifdef CONFIG_ACORN_PARTITION_RISCIX
  79663. +
  79664. +struct riscix_part {
  79665. + __u32 start;
  79666. + __u32 length;
  79667. + __u32 one;
  79668. + char name[16];
  79669. +};
  79670. +
  79671. +struct riscix_record {
  79672. + __u32 magic;
  79673. +#define RISCIX_MAGIC (0x4a657320)
  79674. + __u32 date;
  79675. + struct riscix_part part[8];
  79676. +};
  79677. +
  79678. static int
  79679. riscix_partition(struct gendisk *hd, struct block_device *bdev,
  79680. unsigned long first_sect, int minor, unsigned long nr_sects)
  79681. @@ -102,6 +128,15 @@
  79682. }
  79683. #endif
  79684. +#define LINUX_NATIVE_MAGIC 0xdeafa1de
  79685. +#define LINUX_SWAP_MAGIC 0xdeafab1e
  79686. +
  79687. +struct linux_part {
  79688. + __u32 magic;
  79689. + __u32 start_sect;
  79690. + __u32 nr_sects;
  79691. +};
  79692. +
  79693. static int
  79694. linux_partition(struct gendisk *hd, struct block_device *bdev,
  79695. unsigned long first_sect, int minor, unsigned long nr_sects)
  79696. @@ -136,7 +171,7 @@
  79697. }
  79698. #ifdef CONFIG_ACORN_PARTITION_CUMANA
  79699. -static int
  79700. +int
  79701. adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
  79702. unsigned long first_sector, int minor)
  79703. {
  79704. @@ -147,7 +182,7 @@
  79705. int first = 1;
  79706. /*
  79707. - * Try Cumana style partitions - sector 3 contains ADFS boot block
  79708. + * Try Cumana style partitions - sector 6 contains ADFS boot block
  79709. * with pointer to next 'drive'.
  79710. *
  79711. * There are unknowns in this code - is the 'cylinder number' of the
  79712. @@ -163,13 +198,13 @@
  79713. struct adfs_discrecord *dr;
  79714. unsigned int nr_sects;
  79715. - if (!(minor & mask))
  79716. - break;
  79717. -
  79718. data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
  79719. if (!data)
  79720. return -1;
  79721. + if (!(minor & mask))
  79722. + break;
  79723. +
  79724. dr = adfs_partition(hd, name, data, first_sector, minor++);
  79725. if (!dr)
  79726. break;
  79727. @@ -229,7 +264,7 @@
  79728. * hda1 = ADFS partition on first drive.
  79729. * hda2 = non-ADFS partition.
  79730. */
  79731. -static int
  79732. +int
  79733. adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
  79734. unsigned long first_sector, int minor)
  79735. {
  79736. @@ -282,11 +317,18 @@
  79737. break;
  79738. }
  79739. }
  79740. + printk("\n");
  79741. return 1;
  79742. }
  79743. #endif
  79744. #ifdef CONFIG_ACORN_PARTITION_ICS
  79745. +
  79746. +struct ics_part {
  79747. + __u32 start;
  79748. + __s32 size;
  79749. +};
  79750. +
  79751. static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
  79752. {
  79753. Sector sect;
  79754. @@ -303,6 +345,22 @@
  79755. }
  79756. /*
  79757. + * Check for a valid ICS partition using the checksum.
  79758. + */
  79759. +static inline int valid_ics_sector(const unsigned char *data)
  79760. +{
  79761. + unsigned long sum;
  79762. + int i;
  79763. +
  79764. + for (i = 0, sum = 0x50617274; i < 508; i++)
  79765. + sum += data[i];
  79766. +
  79767. + sum -= le32_to_cpu(*(__u32 *)(&data[508]));
  79768. +
  79769. + return sum == 0;
  79770. +}
  79771. +
  79772. +/*
  79773. * Purpose: allocate ICS partitions.
  79774. * Params : hd - pointer to gendisk structure to store partition info.
  79775. * dev - device number to access.
  79776. @@ -314,15 +372,14 @@
  79777. * hda2 = ADFS partition 1 on first drive.
  79778. * ..etc..
  79779. */
  79780. -static int
  79781. +int
  79782. adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
  79783. unsigned long first_sector, int minor)
  79784. {
  79785. + const unsigned char *data;
  79786. + const struct ics_part *p;
  79787. + unsigned int mask = (1 << hd->minor_shift) - 1;
  79788. Sector sect;
  79789. - unsigned char *data;
  79790. - unsigned long sum;
  79791. - unsigned int i, mask = (1 << hd->minor_shift) - 1;
  79792. - struct ics_part *p;
  79793. /*
  79794. * Try ICS style partitions - sector 0 contains partition info.
  79795. @@ -331,21 +388,14 @@
  79796. if (!data)
  79797. return -1;
  79798. - /*
  79799. - * check for a valid checksum
  79800. - */
  79801. - for (i = 0, sum = 0x50617274; i < 508; i++)
  79802. - sum += data[i];
  79803. -
  79804. - sum -= le32_to_cpu(*(__u32 *)(&data[508]));
  79805. - if (sum) {
  79806. - put_dev_sector(sect);
  79807. - return 0; /* not ICS partition table */
  79808. + if (!valid_ics_sector(data)) {
  79809. + put_dev_sector(sect);
  79810. + return 0;
  79811. }
  79812. printk(" [ICS]");
  79813. - for (p = (struct ics_part *)data; p->size; p++) {
  79814. + for (p = (const struct ics_part *)data; p->size; p++) {
  79815. unsigned long start;
  79816. long size;
  79817. @@ -355,12 +405,19 @@
  79818. start = le32_to_cpu(p->start);
  79819. size = le32_to_cpu(p->size);
  79820. + /*
  79821. + * Negative sizes tell the RISC OS ICS driver to ignore
  79822. + * this partition - in effect it says that this does not
  79823. + * contain an ADFS filesystem.
  79824. + */
  79825. if (size < 0) {
  79826. size = -size;
  79827. /*
  79828. - * We use the first sector to identify what type
  79829. - * this partition is...
  79830. + * Our own extension - We use the first sector
  79831. + * of the partition to identify what type this
  79832. + * partition is. We must not make this visible
  79833. + * to the filesystem.
  79834. */
  79835. if (size > 1 && adfspart_check_ICSLinux(bdev, start)) {
  79836. start += 1;
  79837. @@ -375,10 +432,32 @@
  79838. }
  79839. put_dev_sector(sect);
  79840. + printk("\n");
  79841. return 1;
  79842. }
  79843. #endif
  79844. +#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  79845. +struct ptec_part {
  79846. + __u32 unused1;
  79847. + __u32 unused2;
  79848. + __u32 start;
  79849. + __u32 size;
  79850. + __u32 unused5;
  79851. + char type[8];
  79852. +};
  79853. +
  79854. +static inline int valid_ptec_sector(const unsigned char *data)
  79855. +{
  79856. + unsigned char checksum = 0x2a;
  79857. + int i;
  79858. +
  79859. + for (i = 0; i < 511; i++)
  79860. + checksum += data[i];
  79861. +
  79862. + return checksum == data[511];
  79863. +}
  79864. +
  79865. /*
  79866. * Purpose: allocate ICS partitions.
  79867. * Params : hd - pointer to gendisk structure to store partition info.
  79868. @@ -391,32 +470,27 @@
  79869. * hda2 = ADFS partition 1 on first drive.
  79870. * ..etc..
  79871. */
  79872. -#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  79873. -static int
  79874. +int
  79875. adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
  79876. unsigned long first_sector, int minor)
  79877. {
  79878. Sector sect;
  79879. - unsigned char *data;
  79880. - struct ptec_partition *p;
  79881. - unsigned char checksum;
  79882. + const unsigned char *data;
  79883. + const struct ptec_part *p;
  79884. int i;
  79885. data = read_dev_sector(bdev, 0, &sect);
  79886. if (!data)
  79887. return -1;
  79888. - for (checksum = 0x2a, i = 0; i < 511; i++)
  79889. - checksum += data[i];
  79890. -
  79891. - if (checksum != data[511]) {
  79892. + if (!valid_ptec_sector(data)) {
  79893. put_dev_sector(sect);
  79894. return 0;
  79895. }
  79896. printk(" [POWERTEC]");
  79897. - for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
  79898. + for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) {
  79899. unsigned long start;
  79900. unsigned long size;
  79901. @@ -430,49 +504,82 @@
  79902. }
  79903. put_dev_sector(sect);
  79904. + printk("\n");
  79905. return 1;
  79906. }
  79907. #endif
  79908. -static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = {
  79909. -#ifdef CONFIG_ACORN_PARTITION_ICS
  79910. - adfspart_check_ICS,
  79911. -#endif
  79912. -#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  79913. - adfspart_check_POWERTEC,
  79914. -#endif
  79915. -#ifdef CONFIG_ACORN_PARTITION_CUMANA
  79916. - adfspart_check_CUMANA,
  79917. -#endif
  79918. -#ifdef CONFIG_ACORN_PARTITION_ADFS
  79919. - adfspart_check_ADFS,
  79920. -#endif
  79921. - NULL
  79922. +#ifdef CONFIG_ACORN_PARTITION_EESOX
  79923. +struct eesox_part {
  79924. + char magic[6];
  79925. + char name[10];
  79926. + u32 start;
  79927. + u32 unused6;
  79928. + u32 unused7;
  79929. + u32 unused8;
  79930. };
  79931. +
  79932. /*
  79933. - * Purpose: initialise all the partitions on an ADFS drive.
  79934. - * These may be other ADFS partitions or a Linux/RiscBSD/RISCiX
  79935. - * partition.
  79936. + * Guess who created this format?
  79937. + */
  79938. +static const char eesox_name[] = {
  79939. + 'N', 'e', 'i', 'l', ' ',
  79940. + 'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' '
  79941. +};
  79942. +
  79943. +/*
  79944. + * EESOX SCSI partition format.
  79945. *
  79946. - * Params : hd - pointer to gendisk structure
  79947. - * dev - device number to access
  79948. - * first_sect - first available sector on the disk.
  79949. - * first_minor - first available minor on this device.
  79950. + * This is a goddamned awful partition format. We don't seem to store
  79951. + * the size of the partition in this table, only the start addresses.
  79952. *
  79953. - * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
  79954. + * There are two possibilities where the size comes from:
  79955. + * 1. The individual ADFS boot block entries that are placed on the disk.
  79956. + * 2. The start address of the next entry.
  79957. */
  79958. -int acorn_partition(struct gendisk *hd, struct block_device *bdev,
  79959. - unsigned long first_sect, int first_minor)
  79960. +int
  79961. +adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
  79962. + unsigned long first_sector, int minor)
  79963. {
  79964. + Sector sect;
  79965. + const unsigned char *data;
  79966. + unsigned char buffer[256];
  79967. + struct eesox_part *p;
  79968. + u32 start = first_sector;
  79969. int i;
  79970. - for (i = 0; partfn[i]; i++) {
  79971. - int r = partfn[i](hd, bdev, first_sect, first_minor);
  79972. - if (r) {
  79973. - if (r > 0)
  79974. - printk("\n");
  79975. - return r;
  79976. - }
  79977. + data = read_dev_sector(bdev, 7, &sect);
  79978. + if (!data)
  79979. + return -1;
  79980. +
  79981. + /*
  79982. + * "Decrypt" the partition table. God knows why...
  79983. + */
  79984. + for (i = 0; i < 256; i++)
  79985. + buffer[i] = data[i] ^ eesox_name[i & 15];
  79986. +
  79987. + put_dev_sector(sect);
  79988. +
  79989. + for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) {
  79990. + u32 next;
  79991. +
  79992. + if (memcmp(p->magic, "Eesox", 6))
  79993. + break;
  79994. +
  79995. + next = le32_to_cpu(p->start) + first_sector;
  79996. + if (i)
  79997. + add_gd_partition(hd, minor++, start, next - start);
  79998. + start = next;
  79999. }
  80000. - return 0;
  80001. +
  80002. + if (i != 0) {
  80003. + unsigned long size;
  80004. +
  80005. + size = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects;
  80006. + add_gd_partition(hd, minor++, start, size - start);
  80007. + printk("\n");
  80008. + }
  80009. +
  80010. + return i ? 1 : 0;
  80011. }
  80012. +#endif
  80013. diff -urN linux-2.4.26/fs/partitions/acorn.h linux-2.4.26-vrs1/fs/partitions/acorn.h
  80014. --- linux-2.4.26/fs/partitions/acorn.h 2001-11-22 19:48:07.000000000 +0000
  80015. +++ linux-2.4.26-vrs1/fs/partitions/acorn.h 2004-01-14 21:32:27.000000000 +0000
  80016. @@ -1,55 +1,28 @@
  80017. /*
  80018. - * fs/partitions/acorn.h
  80019. + * linux/fs/partitions/acorn.h
  80020. *
  80021. - * Copyright (C) 1996-1998 Russell King
  80022. - */
  80023. -#include <linux/adfs_fs.h>
  80024. -
  80025. -/*
  80026. - * Partition types. (Oh for reusability)
  80027. + * Copyright (C) 1996-2001 Russell King.
  80028. + *
  80029. + * I _hate_ this partitioning mess - why can't we have one defined
  80030. + * format, and everyone stick to it?
  80031. */
  80032. -#define PARTITION_RISCIX_MFM 1
  80033. -#define PARTITION_RISCIX_SCSI 2
  80034. -#define PARTITION_LINUX 9
  80035. -
  80036. -struct riscix_part {
  80037. - __u32 start;
  80038. - __u32 length;
  80039. - __u32 one;
  80040. - char name[16];
  80041. -};
  80042. -
  80043. -struct riscix_record {
  80044. - __u32 magic;
  80045. -#define RISCIX_MAGIC (0x4a657320)
  80046. - __u32 date;
  80047. - struct riscix_part part[8];
  80048. -};
  80049. -
  80050. -#define LINUX_NATIVE_MAGIC 0xdeafa1de
  80051. -#define LINUX_SWAP_MAGIC 0xdeafab1e
  80052. -
  80053. -struct linux_part {
  80054. - __u32 magic;
  80055. - __u32 start_sect;
  80056. - __u32 nr_sects;
  80057. -};
  80058. -
  80059. -struct ics_part {
  80060. - __u32 start;
  80061. - __s32 size;
  80062. -};
  80063. -
  80064. -struct ptec_partition {
  80065. - __u32 unused1;
  80066. - __u32 unused2;
  80067. - __u32 start;
  80068. - __u32 size;
  80069. - __u32 unused5;
  80070. - char type[8];
  80071. -};
  80072. -
  80073. -
  80074. -int acorn_partition(struct gendisk *hd, struct block_device *bdev,
  80075. - unsigned long first_sect, int first_minor);
  80076. +int
  80077. +adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
  80078. + unsigned long first_sector, int minor);
  80079. +
  80080. +int
  80081. +adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
  80082. + unsigned long first_sector, int minor);
  80083. +
  80084. +int
  80085. +adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
  80086. + unsigned long first_sector, int minor);
  80087. +
  80088. +int
  80089. +adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
  80090. + unsigned long first_sector, int minor);
  80091. +
  80092. +int
  80093. +adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
  80094. + unsigned long first_sector, int minor);
  80095. diff -urN linux-2.4.26/fs/partitions/check.c linux-2.4.26-vrs1/fs/partitions/check.c
  80096. --- linux-2.4.26/fs/partitions/check.c 2004-02-27 20:03:28.000000000 +0000
  80097. +++ linux-2.4.26-vrs1/fs/partitions/check.c 2004-02-24 09:37:29.000000000 +0000
  80098. @@ -40,8 +40,30 @@
  80099. int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
  80100. static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
  80101. -#ifdef CONFIG_ACORN_PARTITION
  80102. - acorn_partition,
  80103. + /*
  80104. + * Probe partition formats with tables at disk address 0
  80105. + * that also have an ADFS boot block at 0xdc0.
  80106. + */
  80107. +#ifdef CONFIG_ACORN_PARTITION_ICS
  80108. + adfspart_check_ICS,
  80109. +#endif
  80110. +#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  80111. + adfspart_check_POWERTEC,
  80112. +#endif
  80113. +#ifdef CONFIG_ACORN_PARTITION_EESOX
  80114. + adfspart_check_EESOX,
  80115. +#endif
  80116. +
  80117. + /*
  80118. + * Now move on to formats that only have partition info at
  80119. + * disk address 0xdc0. These should come before MSDOS
  80120. + * partition tables.
  80121. + */
  80122. +#ifdef CONFIG_ACORN_PARTITION_CUMANA
  80123. + adfspart_check_CUMANA,
  80124. +#endif
  80125. +#ifdef CONFIG_ACORN_PARTITION_ADFS
  80126. + adfspart_check_ADFS,
  80127. #endif
  80128. #ifdef CONFIG_SGI_PARTITION
  80129. sgi_partition,
  80130. @@ -79,13 +101,25 @@
  80131. NULL
  80132. };
  80133. +static char *raid_name (struct gendisk *hd, unsigned int unit, unsigned int part,
  80134. + int major_base, char *buf)
  80135. +{
  80136. + int ctlr = hd->major - major_base;
  80137. + if (part == 0)
  80138. + sprintf(buf, "%s/c%dd%d", hd->major_name, ctlr, unit);
  80139. + else
  80140. + sprintf(buf, "%s/c%dd%dp%d", hd->major_name, ctlr, unit,
  80141. + part);
  80142. + return buf;
  80143. +}
  80144. +
  80145. /*
  80146. * This is ucking fugly but its probably the best thing for 2.4.x
  80147. * Take it as a clear reminder that: 1) we should put the device name
  80148. * generation in the object kdev_t points to in 2.5.
  80149. * and 2) ioctls better work on half-opened devices.
  80150. */
  80151. -
  80152. +
  80153. #ifdef CONFIG_ARCH_S390
  80154. int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
  80155. int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
  80156. @@ -104,10 +138,11 @@
  80157. char *disk_name (struct gendisk *hd, int minor, char *buf)
  80158. {
  80159. const char *maj = hd->major_name;
  80160. - unsigned int unit = (minor >> hd->minor_shift);
  80161. - unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
  80162. + unsigned int unit = minor >> hd->minor_shift;
  80163. + unsigned int part = minor & (( 1 << hd->minor_shift) - 1);
  80164. + char *p;
  80165. - if ((unit < hd->nr_real) && hd->part[minor].de) {
  80166. + if (unit < hd->nr_real && hd->part[minor].de) {
  80167. int pos;
  80168. pos = devfs_generate_path (hd->part[minor].de, buf, 64);
  80169. @@ -153,51 +188,32 @@
  80170. }
  80171. if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
  80172. unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
  80173. - if (unit+'a' > 'z') {
  80174. - unit -= 26;
  80175. - sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
  80176. - if (part)
  80177. - sprintf(buf + 4, "%d", part);
  80178. - return buf;
  80179. - }
  80180. }
  80181. if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
  80182. - int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
  80183. - if (part == 0)
  80184. - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  80185. - else
  80186. - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  80187. - return buf;
  80188. - }
  80189. + return raid_name(hd, unit, part, COMPAQ_SMART2_MAJOR, buf);
  80190. + }
  80191. if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
  80192. - int ctlr = hd->major - COMPAQ_CISS_MAJOR;
  80193. - if (part == 0)
  80194. - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  80195. - else
  80196. - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  80197. - return buf;
  80198. + return raid_name(hd, unit, part, COMPAQ_CISS_MAJOR, buf);
  80199. }
  80200. if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
  80201. - int ctlr = hd->major - DAC960_MAJOR;
  80202. + return raid_name(hd, unit, part, DAC960_MAJOR, buf);
  80203. + }
  80204. + if (hd->major == ATARAID_MAJOR) {
  80205. + int disk = minor >> hd->minor_shift;
  80206. + int part = minor & (( 1 << hd->minor_shift) - 1);
  80207. if (part == 0)
  80208. - sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  80209. + sprintf(buf, "%s/d%d", maj, disk);
  80210. else
  80211. - sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  80212. + sprintf(buf, "%s/d%dp%d", maj, disk, part);
  80213. return buf;
  80214. }
  80215. - if (hd->major == ATARAID_MAJOR) {
  80216. - int disk = minor >> hd->minor_shift;
  80217. - int part = minor & (( 1 << hd->minor_shift) - 1);
  80218. - if (part == 0)
  80219. - sprintf(buf, "%s/d%d", maj, disk);
  80220. - else
  80221. - sprintf(buf, "%s/d%dp%d", maj, disk, part);
  80222. - return buf;
  80223. - }
  80224. - if (part)
  80225. - sprintf(buf, "%s%c%d", maj, unit+'a', part);
  80226. + p = buf;
  80227. + if (unit <= 26)
  80228. + p += sprintf(buf, "%s%c", maj, 'a' + unit);
  80229. else
  80230. - sprintf(buf, "%s%c", maj, unit+'a');
  80231. + p += sprintf(buf, "%s%c%c", maj, 'a' + unit / 26, 'a' + unit % 26);
  80232. + if (part)
  80233. + sprintf(p, "%d", part);
  80234. return buf;
  80235. }
  80236. @@ -207,7 +223,7 @@
  80237. void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
  80238. {
  80239. #ifndef CONFIG_DEVFS_FS
  80240. - char buf[40];
  80241. + char buf[MAX_DISKNAME_LEN];
  80242. #endif
  80243. hd->part[minor].start_sect = start;
  80244. @@ -229,7 +245,7 @@
  80245. static int first_time = 1;
  80246. unsigned long first_sector;
  80247. struct block_device *bdev;
  80248. - char buf[64];
  80249. + char buf[MAX_DISKNAME_LEN];
  80250. int i;
  80251. if (first_time)
  80252. diff -urN linux-2.4.26/fs/proc/array.c linux-2.4.26-vrs1/fs/proc/array.c
  80253. --- linux-2.4.26/fs/proc/array.c 2003-11-28 18:26:21.000000000 +0000
  80254. +++ linux-2.4.26-vrs1/fs/proc/array.c 2004-01-14 21:39:17.000000000 +0000
  80255. @@ -362,15 +362,15 @@
  80256. task->cmin_flt,
  80257. task->maj_flt,
  80258. task->cmaj_flt,
  80259. - task->times.tms_utime,
  80260. - task->times.tms_stime,
  80261. - task->times.tms_cutime,
  80262. - task->times.tms_cstime,
  80263. + hz_to_std(task->times.tms_utime),
  80264. + hz_to_std(task->times.tms_stime),
  80265. + hz_to_std(task->times.tms_cutime),
  80266. + hz_to_std(task->times.tms_cstime),
  80267. priority,
  80268. nice,
  80269. 0UL /* removed */,
  80270. task->it_real_value,
  80271. - task->start_time,
  80272. + hz_to_std(task->start_time),
  80273. vsize,
  80274. mm ? mm->rss : 0, /* you might want to shift this left 3 */
  80275. task->rlim[RLIMIT_RSS].rlim_cur,
  80276. @@ -417,6 +417,7 @@
  80277. end = PMD_SIZE;
  80278. do {
  80279. pte_t page = *pte;
  80280. + unsigned long pfn;
  80281. struct page *ptpage;
  80282. address += PAGE_SIZE;
  80283. @@ -426,8 +427,11 @@
  80284. ++*total;
  80285. if (!pte_present(page))
  80286. continue;
  80287. - ptpage = pte_page(page);
  80288. - if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage))
  80289. + pfn = pte_pfn(page);
  80290. + if (!pfn_valid(pfn))
  80291. + continue;
  80292. + ptpage = pfn_to_page(pfn);
  80293. + if (PageReserved(ptpage))
  80294. continue;
  80295. ++*pages;
  80296. if (pte_dirty(page))
  80297. @@ -609,14 +613,14 @@
  80298. len = sprintf(buffer,
  80299. "cpu %lu %lu\n",
  80300. - task->times.tms_utime,
  80301. - task->times.tms_stime);
  80302. + hz_to_std(task->times.tms_utime),
  80303. + hz_to_std(task->times.tms_stime));
  80304. for (i = 0 ; i < smp_num_cpus; i++)
  80305. len += sprintf(buffer + len, "cpu%d %lu %lu\n",
  80306. i,
  80307. - task->per_cpu_utime[cpu_logical_map(i)],
  80308. - task->per_cpu_stime[cpu_logical_map(i)]);
  80309. + hz_to_std(task->per_cpu_utime[cpu_logical_map(i)]),
  80310. + hz_to_std(task->per_cpu_stime[cpu_logical_map(i)]));
  80311. return len;
  80312. }
  80313. diff -urN linux-2.4.26/fs/proc/proc_misc.c linux-2.4.26-vrs1/fs/proc/proc_misc.c
  80314. --- linux-2.4.26/fs/proc/proc_misc.c 2003-11-28 18:26:21.000000000 +0000
  80315. +++ linux-2.4.26-vrs1/fs/proc/proc_misc.c 2004-01-26 00:27:12.000000000 +0000
  80316. @@ -308,16 +308,16 @@
  80317. {
  80318. int i, len = 0;
  80319. extern unsigned long total_forks;
  80320. - unsigned long jif = jiffies;
  80321. + unsigned long jif = hz_to_std(jiffies);
  80322. unsigned int sum = 0, user = 0, nice = 0, system = 0;
  80323. int major, disk;
  80324. for (i = 0 ; i < smp_num_cpus; i++) {
  80325. int cpu = cpu_logical_map(i), j;
  80326. - user += kstat.per_cpu_user[cpu];
  80327. - nice += kstat.per_cpu_nice[cpu];
  80328. - system += kstat.per_cpu_system[cpu];
  80329. + user += hz_to_std(kstat.per_cpu_user[cpu]);
  80330. + nice += hz_to_std(kstat.per_cpu_nice[cpu]);
  80331. + system += hz_to_std(kstat.per_cpu_system[cpu]);
  80332. #if !defined(CONFIG_ARCH_S390)
  80333. for (j = 0 ; j < NR_IRQS ; j++)
  80334. sum += kstat.irqs[cpu][j];
  80335. @@ -331,10 +331,10 @@
  80336. proc_sprintf(page, &off, &len,
  80337. "cpu%d %u %u %u %lu\n",
  80338. i,
  80339. - kstat.per_cpu_user[cpu_logical_map(i)],
  80340. - kstat.per_cpu_nice[cpu_logical_map(i)],
  80341. - kstat.per_cpu_system[cpu_logical_map(i)],
  80342. - jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
  80343. + hz_to_std(kstat.per_cpu_user[cpu_logical_map(i)]),
  80344. + hz_to_std(kstat.per_cpu_nice[cpu_logical_map(i)]),
  80345. + hz_to_std(kstat.per_cpu_system[cpu_logical_map(i)]),
  80346. + jif - hz_to_std( kstat.per_cpu_user[cpu_logical_map(i)] \
  80347. + kstat.per_cpu_nice[cpu_logical_map(i)] \
  80348. + kstat.per_cpu_system[cpu_logical_map(i)]));
  80349. proc_sprintf(page, &off, &len,
  80350. @@ -440,12 +440,14 @@
  80351. return proc_calc_metrics(page, start, off, count, eof, len);
  80352. }
  80353. +#ifdef CONFIG_GENERIC_ISA_DMA
  80354. static int dma_read_proc(char *page, char **start, off_t off,
  80355. int count, int *eof, void *data)
  80356. {
  80357. int len = get_dma_list(page);
  80358. return proc_calc_metrics(page, start, off, count, eof, len);
  80359. }
  80360. +#endif
  80361. static int cmdline_read_proc(char *page, char **start, off_t off,
  80362. int count, int *eof, void *data)
  80363. @@ -613,7 +615,9 @@
  80364. {"interrupts", interrupts_read_proc},
  80365. #endif
  80366. {"filesystems", filesystems_read_proc},
  80367. +#ifdef CONFIG_GENERIC_ISA_DMA
  80368. {"dma", dma_read_proc},
  80369. +#endif
  80370. {"cmdline", cmdline_read_proc},
  80371. #ifdef CONFIG_SGI_DS1286
  80372. {"rtc", ds1286_read_proc},
  80373. diff -urN linux-2.4.26/fs/stat.c linux-2.4.26-vrs1/fs/stat.c
  80374. --- linux-2.4.26/fs/stat.c 2004-02-27 20:03:28.000000000 +0000
  80375. +++ linux-2.4.26-vrs1/fs/stat.c 2004-02-27 23:57:43.000000000 +0000
  80376. @@ -26,7 +26,9 @@
  80377. }
  80378. -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
  80379. +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
  80380. + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
  80381. + !defined(__x86_64__) && !defined(__mips__)
  80382. /*
  80383. * For backward compatibility? Maybe this should be moved
  80384. @@ -38,7 +40,7 @@
  80385. struct __old_kernel_stat tmp;
  80386. memset(&tmp, 0, sizeof(struct __old_kernel_stat));
  80387. -
  80388. +
  80389. if (warncount > 0) {
  80390. warncount--;
  80391. printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
  80392. @@ -58,7 +60,7 @@
  80393. #if BITS_PER_LONG == 32
  80394. if (inode->i_size > MAX_NON_LFS)
  80395. return -EOVERFLOW;
  80396. -#endif
  80397. +#endif
  80398. tmp.st_size = inode->i_size;
  80399. tmp.st_atime = inode->i_atime;
  80400. tmp.st_mtime = inode->i_mtime;
  80401. @@ -84,7 +86,7 @@
  80402. #if BITS_PER_LONG == 32
  80403. if (inode->i_size > MAX_NON_LFS)
  80404. return -EOVERFLOW;
  80405. -#endif
  80406. +#endif
  80407. tmp.st_size = inode->i_size;
  80408. tmp.st_atime = inode->i_atime;
  80409. tmp.st_mtime = inode->i_mtime;
  80410. @@ -129,7 +131,9 @@
  80411. }
  80412. -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
  80413. +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
  80414. + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
  80415. + !defined(__x86_64__) && !defined(__mips__)
  80416. /*
  80417. * For backward compatibility? Maybe this should be moved
  80418. * into arch/i386 instead?
  80419. @@ -165,7 +169,9 @@
  80420. return error;
  80421. }
  80422. -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
  80423. +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
  80424. + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
  80425. + !defined(__x86_64__) && !defined(__mips__)
  80426. /*
  80427. * For backward compatibility? Maybe this should be moved
  80428. @@ -203,7 +209,9 @@
  80429. return error;
  80430. }
  80431. -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
  80432. +#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
  80433. + !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
  80434. + !defined(__x86_64__) && !defined(__mips__)
  80435. /*
  80436. * For backward compatibility? Maybe this should be moved
  80437. diff -urN linux-2.4.26/include/asm-alpha/ide.h linux-2.4.26-vrs1/include/asm-alpha/ide.h
  80438. --- linux-2.4.26/include/asm-alpha/ide.h 2003-06-13 15:51:38.000000000 +0100
  80439. +++ linux-2.4.26-vrs1/include/asm-alpha/ide.h 2004-01-14 21:32:27.000000000 +0000
  80440. @@ -19,35 +19,15 @@
  80441. #define MAX_HWIFS 4
  80442. #endif
  80443. -static __inline__ int ide_default_irq(ide_ioreg_t base)
  80444. -{
  80445. - switch (base) {
  80446. - case 0x1f0: return 14;
  80447. - case 0x170: return 15;
  80448. - case 0x1e8: return 11;
  80449. - case 0x168: return 10;
  80450. - default:
  80451. - return 0;
  80452. - }
  80453. -}
  80454. -
  80455. -static __inline__ ide_ioreg_t ide_default_io_base(int index)
  80456. -{
  80457. - switch (index) {
  80458. - case 0: return 0x1f0;
  80459. - case 1: return 0x170;
  80460. - case 2: return 0x1e8;
  80461. - case 3: return 0x168;
  80462. - default:
  80463. - return 0;
  80464. - }
  80465. -}
  80466. +#define ide_default_io_base(i) ((ide_ioreg_t)0)
  80467. +#define ide_default_irq(b) (0)
  80468. static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
  80469. {
  80470. ide_ioreg_t reg = data_port;
  80471. int i;
  80472. + memset(hw, 0, sizeof(*hw));
  80473. for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
  80474. hw->io_ports[i] = reg;
  80475. reg += 1;
  80476. @@ -55,7 +35,7 @@
  80477. if (ctrl_port) {
  80478. hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
  80479. } else {
  80480. - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
  80481. + hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
  80482. }
  80483. if (irq != NULL)
  80484. *irq = 0;
  80485. @@ -70,13 +50,19 @@
  80486. {
  80487. #ifndef CONFIG_BLK_DEV_IDEPCI
  80488. hw_regs_t hw;
  80489. - int index;
  80490. - for (index = 0; index < MAX_HWIFS; index++) {
  80491. - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
  80492. - hw.irq = ide_default_irq(ide_default_io_base(index));
  80493. - ide_register_hw(&hw, NULL);
  80494. - }
  80495. + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
  80496. + hw.irq = 14;
  80497. + ide_register_hw(&hw, NULL);
  80498. + ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
  80499. + hw.irq = 15;
  80500. + ide_register_hw(&hw, NULL);
  80501. + ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
  80502. + hw.irq = 11;
  80503. + ide_register_hw(&hw, NULL);
  80504. + ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
  80505. + hw.irq = 10;
  80506. + ide_register_hw(&hw, NULL);
  80507. #endif /* CONFIG_BLK_DEV_IDEPCI */
  80508. }
  80509. diff -urN linux-2.4.26/include/asm-alpha/param.h linux-2.4.26-vrs1/include/asm-alpha/param.h
  80510. --- linux-2.4.26/include/asm-alpha/param.h 2000-11-08 07:37:31.000000000 +0000
  80511. +++ linux-2.4.26-vrs1/include/asm-alpha/param.h 2004-01-14 21:32:27.000000000 +0000
  80512. @@ -13,6 +13,9 @@
  80513. # else
  80514. # define HZ 1200
  80515. # endif
  80516. +#ifdef __KERNEL__
  80517. +# define hz_to_std(a) (a)
  80518. +#endif
  80519. #endif
  80520. #define EXEC_PAGESIZE 8192
  80521. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200.h
  80522. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200.h 2003-08-25 12:44:43.000000000 +0100
  80523. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200.h 2004-04-10 12:28:14.000000000 +0100
  80524. @@ -171,7 +171,7 @@
  80525. #define AT91C_PA23_TXD2 (AT91C_PIO_PA23) // USART 2 Transmit Data
  80526. #define AT91C_PA23_IRQ3 (AT91C_PIO_PA23) // Interrupt input 3
  80527. #define AT91C_PIO_PA24 (1 << 24)
  80528. -#define AT91C_PA24_SCK2 (AT91C_PIO_PA24) // USART2 Serial Clock
  80529. +#define AT91C_PA24_SCK2 (AT91C_PIO_PA24) // USART 2 Serial Clock
  80530. #define AT91C_PA24_PCK1 (AT91C_PIO_PA24) // PMC Programmable Clock Output 1
  80531. #define AT91C_PIO_PA25 (1 << 25)
  80532. #define AT91C_PA25_TWD (AT91C_PIO_PA25) // TWI Two-wire Serial Data
  80533. @@ -260,7 +260,7 @@
  80534. #define AT91C_PIO_PB21 (1 << 21)
  80535. #define AT91C_PB21_RXD1 (AT91C_PIO_PB21) // USART 1 Receive Data
  80536. #define AT91C_PIO_PB22 (1 << 22)
  80537. -#define AT91C_PB22_SCK1 (AT91C_PIO_PB22) // USART1 Serial Clock
  80538. +#define AT91C_PB22_SCK1 (AT91C_PIO_PB22) // USART 1 Serial Clock
  80539. #define AT91C_PIO_PB23 (1 << 23)
  80540. #define AT91C_PB23_DCD1 (AT91C_PIO_PB23) // USART 1 Data Carrier Detect
  80541. #define AT91C_PIO_PB24 (1 << 24)
  80542. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h
  80543. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h 1970-01-01 01:00:00.000000000 +0100
  80544. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h 2004-03-04 21:44:12.000000000 +0000
  80545. @@ -0,0 +1,127 @@
  80546. +// ----------------------------------------------------------------------------
  80547. +// ATMEL Microcontroller Software Support - ROUSSET -
  80548. +// ----------------------------------------------------------------------------
  80549. +// The software is delivered "AS IS" without warranty or condition of any
  80550. +// kind, either express, implied or statutory. This includes without
  80551. +// limitation any warranty or condition with respect to merchantability or
  80552. +// fitness for any particular purpose, or against the infringements of
  80553. +// intellectual property rights of others.
  80554. +// ----------------------------------------------------------------------------
  80555. +// File Name : AT91RM9200.h
  80556. +// Object : AT91RM9200 / MCI definitions
  80557. +// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
  80558. +//
  80559. +// ----------------------------------------------------------------------------
  80560. +
  80561. +#ifndef AT91RM9200_MCI_H
  80562. +#define AT91RM9200_MCI_H
  80563. +
  80564. +// *****************************************************************************
  80565. +// SOFTWARE API DEFINITION FOR Multimedia Card Interface
  80566. +// *****************************************************************************
  80567. +#ifndef __ASSEMBLY__
  80568. +
  80569. +typedef struct _AT91S_MCI {
  80570. + AT91_REG MCI_CR; // MCI Control Register
  80571. + AT91_REG MCI_MR; // MCI Mode Register
  80572. + AT91_REG MCI_DTOR; // MCI Data Timeout Register
  80573. + AT91_REG MCI_SDCR; // MCI SD Card Register
  80574. + AT91_REG MCI_ARGR; // MCI Argument Register
  80575. + AT91_REG MCI_CMDR; // MCI Command Register
  80576. + AT91_REG Reserved0[2]; //
  80577. + AT91_REG MCI_RSPR[4]; // MCI Response Register
  80578. + AT91_REG MCI_RDR; // MCI Receive Data Register
  80579. + AT91_REG MCI_TDR; // MCI Transmit Data Register
  80580. + AT91_REG Reserved1[2]; //
  80581. + AT91_REG MCI_SR; // MCI Status Register
  80582. + AT91_REG MCI_IER; // MCI Interrupt Enable Register
  80583. + AT91_REG MCI_IDR; // MCI Interrupt Disable Register
  80584. + AT91_REG MCI_IMR; // MCI Interrupt Mask Register
  80585. + AT91_REG Reserved2[44]; //
  80586. + AT91_REG MCI_RPR; // Receive Pointer Register
  80587. + AT91_REG MCI_RCR; // Receive Counter Register
  80588. + AT91_REG MCI_TPR; // Transmit Pointer Register
  80589. + AT91_REG MCI_TCR; // Transmit Counter Register
  80590. + AT91_REG MCI_RNPR; // Receive Next Pointer Register
  80591. + AT91_REG MCI_RNCR; // Receive Next Counter Register
  80592. + AT91_REG MCI_TNPR; // Transmit Next Pointer Register
  80593. + AT91_REG MCI_TNCR; // Transmit Next Counter Register
  80594. + AT91_REG MCI_PTCR; // PDC Transfer Control Register
  80595. + AT91_REG MCI_PTSR; // PDC Transfer Status Register
  80596. +} AT91S_MCI, *AT91PS_MCI;
  80597. +
  80598. +#endif
  80599. +
  80600. +// -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register --------
  80601. +#define AT91C_MCI_MCIEN ((unsigned int) 0x1 << 0) // (MCI) Multimedia Interface Enable
  80602. +#define AT91C_MCI_MCIDIS ((unsigned int) 0x1 << 1) // (MCI) Multimedia Interface Disable
  80603. +#define AT91C_MCI_PWSEN ((unsigned int) 0x1 << 2) // (MCI) Power Save Mode Enable
  80604. +#define AT91C_MCI_PWSDIS ((unsigned int) 0x1 << 3) // (MCI) Power Save Mode Disable
  80605. +// -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register --------
  80606. +#define AT91C_MCI_CLKDIV ((unsigned int) 0x1 << 0) // (MCI) Clock Divider
  80607. +#define AT91C_MCI_PWSDIV ((unsigned int) 0x1 << 8) // (MCI) Power Saving Divider
  80608. +#define AT91C_MCI_PDCPADV ((unsigned int) 0x1 << 14) // (MCI) PDC Padding Value
  80609. +#define AT91C_MCI_PDCMODE ((unsigned int) 0x1 << 15) // (MCI) PDC Oriented Mode
  80610. +#define AT91C_MCI_BLKLEN ((unsigned int) 0x1 << 18) // (MCI) Data Block Length
  80611. +// -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register --------
  80612. +#define AT91C_MCI_DTOCYC ((unsigned int) 0x1 << 0) // (MCI) Data Timeout Cycle Number
  80613. +#define AT91C_MCI_DTOMUL ((unsigned int) 0x7 << 4) // (MCI) Data Timeout Multiplier
  80614. +#define AT91C_MCI_DTOMUL_1 ((unsigned int) 0x0 << 4) // (MCI) DTOCYC x 1
  80615. +#define AT91C_MCI_DTOMUL_16 ((unsigned int) 0x1 << 4) // (MCI) DTOCYC x 16
  80616. +#define AT91C_MCI_DTOMUL_128 ((unsigned int) 0x2 << 4) // (MCI) DTOCYC x 128
  80617. +#define AT91C_MCI_DTOMUL_256 ((unsigned int) 0x3 << 4) // (MCI) DTOCYC x 256
  80618. +#define AT91C_MCI_DTOMUL_1024 ((unsigned int) 0x4 << 4) // (MCI) DTOCYC x 1024
  80619. +#define AT91C_MCI_DTOMUL_4096 ((unsigned int) 0x5 << 4) // (MCI) DTOCYC x 4096
  80620. +#define AT91C_MCI_DTOMUL_65536 ((unsigned int) 0x6 << 4) // (MCI) DTOCYC x 65536
  80621. +#define AT91C_MCI_DTOMUL_1048576 ((unsigned int) 0x7 << 4) // (MCI) DTOCYC x 1048576
  80622. +// -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register --------
  80623. +#define AT91C_MCI_SCDSEL ((unsigned int) 0x1 << 0) // (MCI) SD Card Selector
  80624. +#define AT91C_MCI_SCDBUS ((unsigned int) 0x1 << 7) // (MCI) SD Card Bus Width
  80625. +// -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register --------
  80626. +#define AT91C_MCI_CMDNB ((unsigned int) 0x1F << 0) // (MCI) Command Number
  80627. +#define AT91C_MCI_RSPTYP ((unsigned int) 0x3 << 6) // (MCI) Response Type
  80628. +#define AT91C_MCI_RSPTYP_NO ((unsigned int) 0x0 << 6) // (MCI) No response
  80629. +#define AT91C_MCI_RSPTYP_48 ((unsigned int) 0x1 << 6) // (MCI) 48-bit response
  80630. +#define AT91C_MCI_RSPTYP_136 ((unsigned int) 0x2 << 6) // (MCI) 136-bit response
  80631. +#define AT91C_MCI_SPCMD ((unsigned int) 0x7 << 8) // (MCI) Special CMD
  80632. +#define AT91C_MCI_SPCMD_NONE ((unsigned int) 0x0 << 8) // (MCI) Not a special CMD
  80633. +#define AT91C_MCI_SPCMD_INIT ((unsigned int) 0x1 << 8) // (MCI) Initialization CMD
  80634. +#define AT91C_MCI_SPCMD_SYNC ((unsigned int) 0x2 << 8) // (MCI) Synchronized CMD
  80635. +#define AT91C_MCI_SPCMD_IT_CMD ((unsigned int) 0x4 << 8) // (MCI) Interrupt command
  80636. +#define AT91C_MCI_SPCMD_IT_REP ((unsigned int) 0x5 << 8) // (MCI) Interrupt response
  80637. +#define AT91C_MCI_OPDCMD ((unsigned int) 0x1 << 11) // (MCI) Open Drain Command
  80638. +#define AT91C_MCI_MAXLAT ((unsigned int) 0x1 << 12) // (MCI) Maximum Latency for Command to respond
  80639. +#define AT91C_MCI_TRCMD ((unsigned int) 0x3 << 16) // (MCI) Transfer CMD
  80640. +#define AT91C_MCI_TRCMD_NO ((unsigned int) 0x0 << 16) // (MCI) No transfer
  80641. +#define AT91C_MCI_TRCMD_START ((unsigned int) 0x1 << 16) // (MCI) Start transfer
  80642. +#define AT91C_MCI_TRCMD_STOP ((unsigned int) 0x2 << 16) // (MCI) Stop transfer
  80643. +#define AT91C_MCI_TRDIR ((unsigned int) 0x1 << 18) // (MCI) Transfer Direction
  80644. +#define AT91C_MCI_TRTYP ((unsigned int) 0x3 << 19) // (MCI) Transfer Type
  80645. +#define AT91C_MCI_TRTYP_BLOCK ((unsigned int) 0x0 << 19) // (MCI) Block Transfer type
  80646. +#define AT91C_MCI_TRTYP_MULTIPLE ((unsigned int) 0x1 << 19) // (MCI) Multiple Block transfer type
  80647. +#define AT91C_MCI_TRTYP_STREAM ((unsigned int) 0x2 << 19) // (MCI) Stream transfer type
  80648. +// -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register --------
  80649. +#define AT91C_MCI_CMDRDY ((unsigned int) 0x1 << 0) // (MCI) Command Ready flag
  80650. +#define AT91C_MCI_RXRDY ((unsigned int) 0x1 << 1) // (MCI) RX Ready flag
  80651. +#define AT91C_MCI_TXRDY ((unsigned int) 0x1 << 2) // (MCI) TX Ready flag
  80652. +#define AT91C_MCI_BLKE ((unsigned int) 0x1 << 3) // (MCI) Data Block Transfer Ended flag
  80653. +#define AT91C_MCI_DTIP ((unsigned int) 0x1 << 4) // (MCI) Data Transfer in Progress flag
  80654. +#define AT91C_MCI_NOTBUSY ((unsigned int) 0x1 << 5) // (MCI) Data Line Not Busy flag
  80655. +#define AT91C_MCI_ENDRX ((unsigned int) 0x1 << 6) // (MCI) End of RX Buffer flag
  80656. +#define AT91C_MCI_ENDTX ((unsigned int) 0x1 << 7) // (MCI) End of TX Buffer flag
  80657. +#define AT91C_MCI_RXBUFF ((unsigned int) 0x1 << 14) // (MCI) RX Buffer Full flag
  80658. +#define AT91C_MCI_TXBUFE ((unsigned int) 0x1 << 15) // (MCI) TX Buffer Empty flag
  80659. +#define AT91C_MCI_RINDE ((unsigned int) 0x1 << 16) // (MCI) Response Index Error flag
  80660. +#define AT91C_MCI_RDIRE ((unsigned int) 0x1 << 17) // (MCI) Response Direction Error flag
  80661. +#define AT91C_MCI_RCRCE ((unsigned int) 0x1 << 18) // (MCI) Response CRC Error flag
  80662. +#define AT91C_MCI_RENDE ((unsigned int) 0x1 << 19) // (MCI) Response End Bit Error flag
  80663. +#define AT91C_MCI_RTOE ((unsigned int) 0x1 << 20) // (MCI) Response Time-out Error flag
  80664. +#define AT91C_MCI_DCRCE ((unsigned int) 0x1 << 21) // (MCI) data CRC Error flag
  80665. +#define AT91C_MCI_DTOE ((unsigned int) 0x1 << 22) // (MCI) Data timeout Error flag
  80666. +#define AT91C_MCI_OVRE ((unsigned int) 0x1 << 30) // (MCI) Overrun flag
  80667. +#define AT91C_MCI_UNRE ((unsigned int) 0x1 << 31) // (MCI) Underrun flag
  80668. +// -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register --------
  80669. +// -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register --------
  80670. +// -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register --------
  80671. +
  80672. +#endif
  80673. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h
  80674. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h 1970-01-01 01:00:00.000000000 +0100
  80675. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h 2004-03-04 21:44:12.000000000 +0000
  80676. @@ -0,0 +1,129 @@
  80677. +// ----------------------------------------------------------------------------
  80678. +// ATMEL Microcontroller Software Support - ROUSSET -
  80679. +// ----------------------------------------------------------------------------
  80680. +// The software is delivered "AS IS" without warranty or condition of any
  80681. +// kind, either express, implied or statutory. This includes without
  80682. +// limitation any warranty or condition with respect to merchantability or
  80683. +// fitness for any particular purpose, or against the infringements of
  80684. +// intellectual property rights of others.
  80685. +// ----------------------------------------------------------------------------
  80686. +// File Name : AT91RM9200.h
  80687. +// Object : AT91RM9200 / SSC definitions
  80688. +// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
  80689. +//
  80690. +// ----------------------------------------------------------------------------
  80691. +
  80692. +#ifndef AT91RM9200_SSC_H
  80693. +#define AT91RM9200_SSC_H
  80694. +
  80695. +// *****************************************************************************
  80696. +// SOFTWARE API DEFINITION FOR Synchronous Serial Controller Interface
  80697. +// *****************************************************************************
  80698. +#ifndef __ASSEMBLY__
  80699. +
  80700. +typedef struct _AT91S_SSC {
  80701. + AT91_REG SSC_CR; // Control Register
  80702. + AT91_REG SSC_CMR; // Clock Mode Register
  80703. + AT91_REG Reserved0[2]; //
  80704. + AT91_REG SSC_RCMR; // Receive Clock ModeRegister
  80705. + AT91_REG SSC_RFMR; // Receive Frame Mode Register
  80706. + AT91_REG SSC_TCMR; // Transmit Clock Mode Register
  80707. + AT91_REG SSC_TFMR; // Transmit Frame Mode Register
  80708. + AT91_REG SSC_RHR; // Receive Holding Register
  80709. + AT91_REG SSC_THR; // Transmit Holding Register
  80710. + AT91_REG Reserved1[2]; //
  80711. + AT91_REG SSC_RSHR; // Receive Sync Holding Register
  80712. + AT91_REG SSC_TSHR; // Transmit Sync Holding Register
  80713. + AT91_REG SSC_RC0R; // Receive Compare 0 Register
  80714. + AT91_REG SSC_RC1R; // Receive Compare 1 Register
  80715. + AT91_REG SSC_SR; // Status Register
  80716. + AT91_REG SSC_IER; // Interrupt Enable Register
  80717. + AT91_REG SSC_IDR; // Interrupt Disable Register
  80718. + AT91_REG SSC_IMR; // Interrupt Mask Register
  80719. + AT91_REG Reserved2[44]; //
  80720. + AT91_REG SSC_RPR; // Receive Pointer Register
  80721. + AT91_REG SSC_RCR; // Receive Counter Register
  80722. + AT91_REG SSC_TPR; // Transmit Pointer Register
  80723. + AT91_REG SSC_TCR; // Transmit Counter Register
  80724. + AT91_REG SSC_RNPR; // Receive Next Pointer Register
  80725. + AT91_REG SSC_RNCR; // Receive Next Counter Register
  80726. + AT91_REG SSC_TNPR; // Transmit Next Pointer Register
  80727. + AT91_REG SSC_TNCR; // Transmit Next Counter Register
  80728. + AT91_REG SSC_PTCR; // PDC Transfer Control Register
  80729. + AT91_REG SSC_PTSR; // PDC Transfer Status Register
  80730. +} AT91S_SSC, *AT91PS_SSC;
  80731. +
  80732. +#endif
  80733. +
  80734. +// -------- SSC_CR : (SSC Offset: 0x0) SSC Control Register --------
  80735. +#define AT91C_SSC_RXEN ( 0x1 << 0) // (SSC) Receive Enable
  80736. +#define AT91C_SSC_RXDIS ( 0x1 << 1) // (SSC) Receive Disable
  80737. +#define AT91C_SSC_TXEN ( 0x1 << 8) // (SSC) Transmit Enable
  80738. +#define AT91C_SSC_TXDIS ( 0x1 << 9) // (SSC) Transmit Disable
  80739. +#define AT91C_SSC_SWRST ( 0x1 << 15) // (SSC) Software Reset
  80740. +// -------- SSC_RCMR : (SSC Offset: 0x10) SSC Receive Clock Mode Register --------
  80741. +#define AT91C_SSC_CKS ( 0x3 << 0) // (SSC) Receive/Transmit Clock Selection
  80742. +#define AT91C_SSC_CKS_DIV ( 0x0) // (SSC) Divided Clock
  80743. +#define AT91C_SSC_CKS_TK ( 0x1) // (SSC) TK Clock signal
  80744. +#define AT91C_SSC_CKS_RK ( 0x2) // (SSC) RK pin
  80745. +#define AT91C_SSC_CKO ( 0x7 << 2) // (SSC) Receive/Transmit Clock Output Mode Selection
  80746. +#define AT91C_SSC_CKO_NONE ( 0x0 << 2) // (SSC) Receive/Transmit Clock Output Mode: None RK pin: Input-only
  80747. +#define AT91C_SSC_CKO_CONTINOUS ( 0x1 << 2) // (SSC) Continuous Receive/Transmit Clock RK pin: Output
  80748. +#define AT91C_SSC_CKO_DATA_TX ( 0x2 << 2) // (SSC) Receive/Transmit Clock only during data transfers RK pin: Output
  80749. +#define AT91C_SSC_CKI ( 0x1 << 5) // (SSC) Receive/Transmit Clock Inversion
  80750. +#define AT91C_SSC_CKG ( 0x3 << 6) // (SSC) Receive/Transmit Clock Gating Selection
  80751. +#define AT91C_SSC_CKG_NONE ( 0x0 << 6) // (SSC) Receive/Transmit Clock Gating: None, continuous clock
  80752. +#define AT91C_SSC_CKG_LOW ( 0x1 << 6) // (SSC) Receive/Transmit Clock enabled only if RF Low
  80753. +#define AT91C_SSC_CKG_HIGH ( 0x2 << 6) // (SSC) Receive/Transmit Clock enabled only if RF High
  80754. +#define AT91C_SSC_START ( 0xF << 8) // (SSC) Receive/Transmit Start Selection
  80755. +#define AT91C_SSC_START_CONTINOUS ( 0x0 << 8) // (SSC) Continuous, as soon as the receiver is enabled, and immediately after the end of transfer of the previous data.
  80756. +#define AT91C_SSC_START_TX ( 0x1 << 8) // (SSC) Transmit/Receive start
  80757. +#define AT91C_SSC_START_LOW_RF ( 0x2 << 8) // (SSC) Detection of a low level on RF input
  80758. +#define AT91C_SSC_START_HIGH_RF ( 0x3 << 8) // (SSC) Detection of a high level on RF input
  80759. +#define AT91C_SSC_START_FALL_RF ( 0x4 << 8) // (SSC) Detection of a falling edge on RF input
  80760. +#define AT91C_SSC_START_RISE_RF ( 0x5 << 8) // (SSC) Detection of a rising edge on RF input
  80761. +#define AT91C_SSC_START_LEVEL_RF ( 0x6 << 8) // (SSC) Detection of any level change on RF input
  80762. +#define AT91C_SSC_START_EDGE_RF ( 0x7 << 8) // (SSC) Detection of any edge on RF input
  80763. +#define AT91C_SSC_START_0 ( 0x8 << 8) // (SSC) Compare 0
  80764. +#define AT91C_SSC_STOP ( 0x1 << 12) // (SSC) Receive Stop Selection
  80765. +#define AT91C_SSC_STTOUT ( 0x1 << 15) // (SSC) Receive/Transmit Start Output Selection
  80766. +#define AT91C_SSC_STTDLY ( 0xFF << 16) // (SSC) Receive/Transmit Start Delay
  80767. +#define AT91C_SSC_PERIOD ( 0xFF << 24) // (SSC) Receive/Transmit Period Divider Selection
  80768. +// -------- SSC_RFMR : (SSC Offset: 0x14) SSC Receive Frame Mode Register --------
  80769. +#define AT91C_SSC_DATLEN ( 0x1F << 0) // (SSC) Data Length
  80770. +#define AT91C_SSC_LOOP ( 0x1 << 5) // (SSC) Loop Mode
  80771. +#define AT91C_SSC_MSBF ( 0x1 << 7) // (SSC) Most Significant Bit First
  80772. +#define AT91C_SSC_DATNB ( 0xF << 8) // (SSC) Data Number per Frame
  80773. +#define AT91C_SSC_FSLEN ( 0xF << 16) // (SSC) Receive/Transmit Frame Sync length
  80774. +#define AT91C_SSC_FSOS ( 0x7 << 20) // (SSC) Receive/Transmit Frame Sync Output Selection
  80775. +#define AT91C_SSC_FSOS_NONE ( 0x0 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: None RK pin Input-only
  80776. +#define AT91C_SSC_FSOS_NEGATIVE ( 0x1 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Negative Pulse
  80777. +#define AT91C_SSC_FSOS_POSITIVE ( 0x2 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Positive Pulse
  80778. +#define AT91C_SSC_FSOS_LOW ( 0x3 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver Low during data transfer
  80779. +#define AT91C_SSC_FSOS_HIGH ( 0x4 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver High during data transfer
  80780. +#define AT91C_SSC_FSOS_TOGGLE ( 0x5 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Toggling at each start of data transfer
  80781. +#define AT91C_SSC_FSEDGE ( 0x1 << 24) // (SSC) Frame Sync Edge Detection
  80782. +// -------- SSC_TCMR : (SSC Offset: 0x18) SSC Transmit Clock Mode Register --------
  80783. +// -------- SSC_TFMR : (SSC Offset: 0x1c) SSC Transmit Frame Mode Register --------
  80784. +#define AT91C_SSC_DATDEF ( 0x1 << 5) // (SSC) Data Default Value
  80785. +#define AT91C_SSC_FSDEN ( 0x1 << 23) // (SSC) Frame Sync Data Enable
  80786. +// -------- SSC_SR : (SSC Offset: 0x40) SSC Status Register --------
  80787. +#define AT91C_SSC_TXRDY ( 0x1 << 0) // (SSC) Transmit Ready
  80788. +#define AT91C_SSC_TXEMPTY ( 0x1 << 1) // (SSC) Transmit Empty
  80789. +#define AT91C_SSC_ENDTX ( 0x1 << 2) // (SSC) End Of Transmission
  80790. +#define AT91C_SSC_TXBUFE ( 0x1 << 3) // (SSC) Transmit Buffer Empty
  80791. +#define AT91C_SSC_RXRDY ( 0x1 << 4) // (SSC) Receive Ready
  80792. +#define AT91C_SSC_OVRUN ( 0x1 << 5) // (SSC) Receive Overrun
  80793. +#define AT91C_SSC_ENDRX ( 0x1 << 6) // (SSC) End of Reception
  80794. +#define AT91C_SSC_RXBUFF ( 0x1 << 7) // (SSC) Receive Buffer Full
  80795. +#define AT91C_SSC_CP0 ( 0x1 << 8) // (SSC) Compare 0
  80796. +#define AT91C_SSC_CP1 ( 0x1 << 9) // (SSC) Compare 1
  80797. +#define AT91C_SSC_TXSYN ( 0x1 << 10) // (SSC) Transmit Sync
  80798. +#define AT91C_SSC_RXSYN ( 0x1 << 11) // (SSC) Receive Sync
  80799. +#define AT91C_SSC_TXENA ( 0x1 << 16) // (SSC) Transmit Enable
  80800. +#define AT91C_SSC_RXENA ( 0x1 << 17) // (SSC) Receive Enable
  80801. +// -------- SSC_IER : (SSC Offset: 0x44) SSC Interrupt Enable Register --------
  80802. +// -------- SSC_IDR : (SSC Offset: 0x48) SSC Interrupt Disable Register --------
  80803. +// -------- SSC_IMR : (SSC Offset: 0x4c) SSC Interrupt Mask Register --------
  80804. +
  80805. +#endif
  80806. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h
  80807. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h 1970-01-01 01:00:00.000000000 +0100
  80808. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h 2004-03-04 21:44:12.000000000 +0000
  80809. @@ -0,0 +1,165 @@
  80810. +// ----------------------------------------------------------------------------
  80811. +// ATMEL Microcontroller Software Support - ROUSSET -
  80812. +// ----------------------------------------------------------------------------
  80813. +// The software is delivered "AS IS" without warranty or condition of any
  80814. +// kind, either express, implied or statutory. This includes without
  80815. +// limitation any warranty or condition with respect to merchantability or
  80816. +// fitness for any particular purpose, or against the infringements of
  80817. +// intellectual property rights of others.
  80818. +// ----------------------------------------------------------------------------
  80819. +// File Name : AT91RM9200.h
  80820. +// Object : AT91RM9200 definitions
  80821. +// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
  80822. +//
  80823. +// ----------------------------------------------------------------------------
  80824. +
  80825. +#ifndef AT91RM9200_TC_H
  80826. +#define AT91RM9200_TC_H
  80827. +
  80828. +// *****************************************************************************
  80829. +// SOFTWARE API DEFINITION FOR Timer Counter Channel Interface
  80830. +// *****************************************************************************
  80831. +#ifndef __ASSEMBLY__
  80832. +
  80833. +typedef struct _AT91S_TC {
  80834. + AT91_REG TC_CCR; // Channel Control Register
  80835. + AT91_REG TC_CMR; // Channel Mode Register
  80836. + AT91_REG Reserved0[2]; //
  80837. + AT91_REG TC_CV; // Counter Value
  80838. + AT91_REG TC_RA; // Register A
  80839. + AT91_REG TC_RB; // Register B
  80840. + AT91_REG TC_RC; // Register C
  80841. + AT91_REG TC_SR; // Status Register
  80842. + AT91_REG TC_IER; // Interrupt Enable Register
  80843. + AT91_REG TC_IDR; // Interrupt Disable Register
  80844. + AT91_REG TC_IMR; // Interrupt Mask Register
  80845. +} AT91S_TC, *AT91PS_TC;
  80846. +
  80847. +typedef struct _AT91S_TCB {
  80848. + AT91S_TC TCB_TC0; // TC Channel 0
  80849. + AT91_REG Reserved0[4]; //
  80850. + AT91S_TC TCB_TC1; // TC Channel 1
  80851. + AT91_REG Reserved1[4]; //
  80852. + AT91S_TC TCB_TC2; // TC Channel 2
  80853. + AT91_REG Reserved2[4]; //
  80854. + AT91_REG TCB_BCR; // TC Block Control Register
  80855. + AT91_REG TCB_BMR; // TC Block Mode Register
  80856. +} AT91S_TCB, *AT91PS_TCB;
  80857. +
  80858. +#endif
  80859. +
  80860. +// -------- TC_CCR : (TC Offset: 0x0) TC Channel Control Register --------
  80861. +#define AT91C_TC_CLKEN ( 0x1 << 0) // (TC) Counter Clock Enable Command
  80862. +#define AT91C_TC_CLKDIS ( 0x1 << 1) // (TC) Counter Clock Disable Command
  80863. +#define AT91C_TC_SWTRG ( 0x1 << 2) // (TC) Software Trigger Command
  80864. +// -------- TC_CMR : (TC Offset: 0x4) TC Channel Mode Register: Capture Mode / Waveform Mode --------
  80865. +#define AT91C_TC_TCCLKS ( 0x7 << 0) // (TC) Clock Selection
  80866. +#define AT91C_TC_TIMER_DIV1_CLOCK ( 0x0 << 0) // (TC) MCK/2
  80867. +#define AT91C_TC_TIMER_DIV2_CLOCK ( 0x1 << 0) // (TC) MCK/8
  80868. +#define AT91C_TC_TIMER_DIV3_CLOCK ( 0x2 << 0) // (TC) MCK/32
  80869. +#define AT91C_TC_TIMER_DIV4_CLOCK ( 0x3 << 0) // (TC) MCK/128
  80870. +#define AT91C_TC_TIMER_DIV5_CLOCK ( 0x4 << 0) // (TC) MCK/256 = SLOW CLOCK
  80871. +#define AT91C_TC_TIMER_XC0 ( 0x5 << 0) // (TC) XC0
  80872. +#define AT91C_TC_TIMER_XC1 ( 0x6 << 0) // (TC) XC1
  80873. +#define AT91C_TC_TIMER_XC2 ( 0x7 << 0) // (TC) XC2
  80874. +#define AT91C_TC_CLKI ( 0x1 << 3) // (TC) Clock Invert
  80875. +#define AT91C_TC_BURST ( 0x3 << 4) // (TC) Burst Signal Selection
  80876. +#define AT91C_TC_CPCSTOP ( 0x1 << 6) // (TC) Counter Clock Stopped with RC Compare
  80877. +#define AT91C_TC_CPCDIS ( 0x1 << 7) // (TC) Counter Clock Disable with RC Compare
  80878. +#define AT91C_TC_EEVTEDG ( 0x3 << 8) // (TC) External Event Edge Selection
  80879. +#define AT91C_TC_EEVTEDG_NONE ( 0x0 << 8) // (TC) Edge: None
  80880. +#define AT91C_TC_EEVTEDG_RISING ( 0x1 << 8) // (TC) Edge: rising edge
  80881. +#define AT91C_TC_EEVTEDG_FALLING ( 0x2 << 8) // (TC) Edge: falling edge
  80882. +#define AT91C_TC_EEVTEDG_BOTH ( 0x3 << 8) // (TC) Edge: each edge
  80883. +#define AT91C_TC_EEVT ( 0x3 << 10) // (TC) External Event Selection
  80884. +#define AT91C_TC_EEVT_NONE ( 0x0 << 10) // (TC) Signal selected as external event: TIOB TIOB direction: input
  80885. +#define AT91C_TC_EEVT_RISING ( 0x1 << 10) // (TC) Signal selected as external event: XC0 TIOB direction: output
  80886. +#define AT91C_TC_EEVT_FALLING ( 0x2 << 10) // (TC) Signal selected as external event: XC1 TIOB direction: output
  80887. +#define AT91C_TC_EEVT_BOTH ( 0x3 << 10) // (TC) Signal selected as external event: XC2 TIOB direction: output
  80888. +#define AT91C_TC_ENETRG ( 0x1 << 12) // (TC) External Event Trigger enable
  80889. +#define AT91C_TC_WAVESEL ( 0x3 << 13) // (TC) Waveform Selection
  80890. +#define AT91C_TC_WAVESEL_UP ( 0x0 << 13) // (TC) UP mode without atomatic trigger on RC Compare
  80891. +#define AT91C_TC_WAVESEL_UP_AUTO ( 0x1 << 13) // (TC) UP mode with automatic trigger on RC Compare
  80892. +#define AT91C_TC_WAVESEL_UPDOWN ( 0x2 << 13) // (TC) UPDOWN mode without automatic trigger on RC Compare
  80893. +#define AT91C_TC_WAVESEL_UPDOWN_AUTO ( 0x3 << 13) // (TC) UPDOWN mode with automatic trigger on RC Compare
  80894. +#define AT91C_TC_CPCTRG ( 0x1 << 14) // (TC) RC Compare Trigger Enable
  80895. +#define AT91C_TC_WAVE ( 0x1 << 15) // (TC)
  80896. +#define AT91C_TC_ACPA ( 0x3 << 16) // (TC) RA Compare Effect on TIOA
  80897. +#define AT91C_TC_ACPA_NONE ( 0x0 << 16) // (TC) Effect: none
  80898. +#define AT91C_TC_ACPA_SET ( 0x1 << 16) // (TC) Effect: set
  80899. +#define AT91C_TC_ACPA_CLEAR ( 0x2 << 16) // (TC) Effect: clear
  80900. +#define AT91C_TC_ACPA_TOGGLE ( 0x3 << 16) // (TC) Effect: toggle
  80901. +#define AT91C_TC_ACPC ( 0x3 << 18) // (TC) RC Compare Effect on TIOA
  80902. +#define AT91C_TC_ACPC_NONE ( 0x0 << 18) // (TC) Effect: none
  80903. +#define AT91C_TC_ACPC_SET ( 0x1 << 18) // (TC) Effect: set
  80904. +#define AT91C_TC_ACPC_CLEAR ( 0x2 << 18) // (TC) Effect: clear
  80905. +#define AT91C_TC_ACPC_TOGGLE ( 0x3 << 18) // (TC) Effect: toggle
  80906. +#define AT91C_TC_AEEVT ( 0x3 << 20) // (TC) External Event Effect on TIOA
  80907. +#define AT91C_TC_AEEVT_NONE ( 0x0 << 20) // (TC) Effect: none
  80908. +#define AT91C_TC_AEEVT_SET ( 0x1 << 20) // (TC) Effect: set
  80909. +#define AT91C_TC_AEEVT_CLEAR ( 0x2 << 20) // (TC) Effect: clear
  80910. +#define AT91C_TC_AEEVT_TOGGLE ( 0x3 << 20) // (TC) Effect: toggle
  80911. +#define AT91C_TC_ASWTRG ( 0x3 << 22) // (TC) Software Trigger Effect on TIOA
  80912. +#define AT91C_TC_ASWTRG_NONE ( 0x0 << 22) // (TC) Effect: none
  80913. +#define AT91C_TC_ASWTRG_SET ( 0x1 << 22) // (TC) Effect: set
  80914. +#define AT91C_TC_ASWTRG_CLEAR ( 0x2 << 22) // (TC) Effect: clear
  80915. +#define AT91C_TC_ASWTRG_TOGGLE ( 0x3 << 22) // (TC) Effect: toggle
  80916. +#define AT91C_TC_BCPB ( 0x3 << 24) // (TC) RB Compare Effect on TIOB
  80917. +#define AT91C_TC_BCPB_NONE ( 0x0 << 24) // (TC) Effect: none
  80918. +#define AT91C_TC_BCPB_SET ( 0x1 << 24) // (TC) Effect: set
  80919. +#define AT91C_TC_BCPB_CLEAR ( 0x2 << 24) // (TC) Effect: clear
  80920. +#define AT91C_TC_BCPB_TOGGLE ( 0x3 << 24) // (TC) Effect: toggle
  80921. +#define AT91C_TC_BCPC ( 0x3 << 26) // (TC) RC Compare Effect on TIOB
  80922. +#define AT91C_TC_BCPC_NONE ( 0x0 << 26) // (TC) Effect: none
  80923. +#define AT91C_TC_BCPC_SET ( 0x1 << 26) // (TC) Effect: set
  80924. +#define AT91C_TC_BCPC_CLEAR ( 0x2 << 26) // (TC) Effect: clear
  80925. +#define AT91C_TC_BCPC_TOGGLE ( 0x3 << 26) // (TC) Effect: toggle
  80926. +#define AT91C_TC_BEEVT ( 0x3 << 28) // (TC) External Event Effect on TIOB
  80927. +#define AT91C_TC_BEEVT_NONE ( 0x0 << 28) // (TC) Effect: none
  80928. +#define AT91C_TC_BEEVT_SET ( 0x1 << 28) // (TC) Effect: set
  80929. +#define AT91C_TC_BEEVT_CLEAR ( 0x2 << 28) // (TC) Effect: clear
  80930. +#define AT91C_TC_BEEVT_TOGGLE ( 0x3 << 28) // (TC) Effect: toggle
  80931. +#define AT91C_TC_BSWTRG ( 0x3 << 30) // (TC) Software Trigger Effect on TIOB
  80932. +#define AT91C_TC_BSWTRG_NONE ( 0x0 << 30) // (TC) Effect: none
  80933. +#define AT91C_TC_BSWTRG_SET ( 0x1 << 30) // (TC) Effect: set
  80934. +#define AT91C_TC_BSWTRG_CLEAR ( 0x2 << 30) // (TC) Effect: clear
  80935. +#define AT91C_TC_BSWTRG_TOGGLE ( 0x3 << 30) // (TC) Effect: toggle
  80936. +// -------- TC_SR : (TC Offset: 0x20) TC Channel Status Register --------
  80937. +#define AT91C_TC_COVFS ( 0x1 << 0) // (TC) Counter Overflow
  80938. +#define AT91C_TC_LOVRS ( 0x1 << 1) // (TC) Load Overrun
  80939. +#define AT91C_TC_CPAS ( 0x1 << 2) // (TC) RA Compare
  80940. +#define AT91C_TC_CPBS ( 0x1 << 3) // (TC) RB Compare
  80941. +#define AT91C_TC_CPCS ( 0x1 << 4) // (TC) RC Compare
  80942. +#define AT91C_TC_LDRAS ( 0x1 << 5) // (TC) RA Loading
  80943. +#define AT91C_TC_LDRBS ( 0x1 << 6) // (TC) RB Loading
  80944. +#define AT91C_TC_ETRCS ( 0x1 << 7) // (TC) External Trigger
  80945. +#define AT91C_TC_ETRGS ( 0x1 << 16) // (TC) Clock Enabling
  80946. +#define AT91C_TC_MTIOA ( 0x1 << 17) // (TC) TIOA Mirror
  80947. +#define AT91C_TC_MTIOB ( 0x1 << 18) // (TC) TIOA Mirror
  80948. +// -------- TC_IER : (TC Offset: 0x24) TC Channel Interrupt Enable Register --------
  80949. +// -------- TC_IDR : (TC Offset: 0x28) TC Channel Interrupt Disable Register --------
  80950. +// -------- TC_IMR : (TC Offset: 0x2c) TC Channel Interrupt Mask Register --------
  80951. +
  80952. +// *****************************************************************************
  80953. +// SOFTWARE API DEFINITION FOR Timer Counter Interface
  80954. +// *****************************************************************************
  80955. +// -------- TCB_BCR : (TCB Offset: 0xc0) TC Block Control Register --------
  80956. +#define AT91C_TCB_SYNC ( 0x1 << 0) // (TCB) Synchro Command
  80957. +// -------- TCB_BMR : (TCB Offset: 0xc4) TC Block Mode Register --------
  80958. +#define AT91C_TCB_TC0XC0S ( 0x1 << 0) // (TCB) External Clock Signal 0 Selection
  80959. +#define AT91C_TCB_TC0XC0S_TCLK0 ( 0x0) // (TCB) TCLK0 connected to XC0
  80960. +#define AT91C_TCB_TC0XC0S_NONE ( 0x1) // (TCB) None signal connected to XC0
  80961. +#define AT91C_TCB_TC0XC0S_TIOA1 ( 0x2) // (TCB) TIOA1 connected to XC0
  80962. +#define AT91C_TCB_TC0XC0S_TIOA2 ( 0x3) // (TCB) TIOA2 connected to XC0
  80963. +#define AT91C_TCB_TC1XC1S ( 0x1 << 2) // (TCB) External Clock Signal 1 Selection
  80964. +#define AT91C_TCB_TC1XC1S_TCLK1 ( 0x0 << 2) // (TCB) TCLK1 connected to XC1
  80965. +#define AT91C_TCB_TC1XC1S_NONE ( 0x1 << 2) // (TCB) None signal connected to XC1
  80966. +#define AT91C_TCB_TC1XC1S_TIOA0 ( 0x2 << 2) // (TCB) TIOA0 connected to XC1
  80967. +#define AT91C_TCB_TC1XC1S_TIOA2 ( 0x3 << 2) // (TCB) TIOA2 connected to XC1
  80968. +#define AT91C_TCB_TC2XC2S ( 0x1 << 4) // (TCB) External Clock Signal 2 Selection
  80969. +#define AT91C_TCB_TC2XC2S_TCLK2 ( 0x0 << 4) // (TCB) TCLK2 connected to XC2
  80970. +#define AT91C_TCB_TC2XC2S_NONE ( 0x1 << 4) // (TCB) None signal connected to XC2
  80971. +#define AT91C_TCB_TC2XC2S_TIOA0 ( 0x2 << 4) // (TCB) TIOA0 connected to XC2
  80972. +#define AT91C_TCB_TC2XC2S_TIOA2 ( 0x3 << 4) // (TCB) TIOA2 connected to XC2
  80973. +
  80974. +#endif
  80975. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/at91rm9200dk.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/at91rm9200dk.h
  80976. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/at91rm9200dk.h 2003-08-25 12:44:43.000000000 +0100
  80977. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/at91rm9200dk.h 2004-04-10 12:40:23.000000000 +0100
  80978. @@ -17,9 +17,9 @@
  80979. /* AT91RM92000 clocks */
  80980. #define AT91C_MAIN_CLOCK 179712000 /* from 18.432 MHz crystal (18432000 / 4 * 39) */
  80981. -#define AT91C_MASTER_CLOCK 59904000 /* peripheral clock (AT91C_MASTER_CLOCK / 3) */
  80982. +#define AT91C_MASTER_CLOCK 59904000 /* peripheral clock (AT91C_MAIN_CLOCK / 3) */
  80983. #define AT91C_SLOW_CLOCK 32768 /* slow clock */
  80984. -
  80985. +#define AT91_PLLB_INIT 0x1048be0e /* (18.432 / 14 * 73) /2 = 47.9714 *
  80986. /* FLASH */
  80987. #define AT91_FLASH_BASE 0x10000000 // NCS0: Flash physical base address
  80988. @@ -68,6 +68,7 @@
  80989. #define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
  80990. #define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
  80991. +#define AT91C_CONSOLE_DEFAULT_BAUDRATE 115200 /* default serial console baud-rate */
  80992. /*
  80993. * Serial port configuration.
  80994. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/csb337.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/csb337.h
  80995. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/csb337.h 1970-01-01 01:00:00.000000000 +0100
  80996. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/csb337.h 2004-04-10 12:42:27.000000000 +0100
  80997. @@ -0,0 +1,82 @@
  80998. +/*
  80999. + * linux/include/asm-arm/arch-at91rm9200/csb337.h
  81000. + *
  81001. + * Copyright (c) 2003 Christopher Bahns & David Knickerbocker
  81002. + * Polaroid Corporation
  81003. + *
  81004. + * This program is free software; you can redistribute it and/or modify
  81005. + * it under the terms of the GNU General Public License as published by
  81006. + * the Free Software Foundation; either version 2 of the License, or
  81007. + * (at your option) any later version.
  81008. + *
  81009. + */
  81010. +
  81011. +#ifndef __ASM_ARCH_HARDWARE_CSB337_H
  81012. +#define __ASM_ARCH_HARDWARE_CSB337_H
  81013. +
  81014. +
  81015. +/* AT91RM92000 clocks on CSB337 */
  81016. +#define AT91C_MAIN_CLOCK 184320000
  81017. +#define AT91C_MASTER_CLOCK 46080000 /* peripheral clock (AT91C_MAIN_CLOCK / 4) */
  81018. +#define AT91C_SLOW_CLOCK 32768 /* slow clock */
  81019. +#define AT91_PLLB_INIT 0x1257be17 /* (3.68 / 23 * 600) /2 = 96/2 = 48 */
  81020. +
  81021. +/* FLASH */
  81022. +#define AT91_FLASH_BASE 0x10000000 // NCS0: Flash physical base address
  81023. +
  81024. +/* SDRAM */
  81025. +#define AT91_SDRAM_BASE 0x20000000 // NCS1: SDRAM physical base address
  81026. +
  81027. +/* SmartMedia */
  81028. +#define AT91_SMARTMEDIA_BASE 0x40000000 // NCS3: Smartmedia physical base address
  81029. +
  81030. +/* Multi-Master Memory controller */
  81031. +#define AT91_UHP_BASE 0x00300000 // USB Host controller
  81032. +
  81033. +
  81034. +/* Peripheral interrupt configuration */
  81035. +#define AT91_SMR_FIQ (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (FIQ)
  81036. +#define AT91_SMR_SYS (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // System Peripheral
  81037. +#define AT91_SMR_PIOA (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller A
  81038. +#define AT91_SMR_PIOB (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller B
  81039. +#define AT91_SMR_PIOC (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller C
  81040. +#define AT91_SMR_PIOD (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller D
  81041. +#define AT91_SMR_US0 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 0
  81042. +#define AT91_SMR_US1 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 1
  81043. +#define AT91_SMR_US2 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 2
  81044. +#define AT91_SMR_US3 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 3
  81045. +#define AT91_SMR_MCI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Multimedia Card Interface
  81046. +#define AT91_SMR_UDP (AT91C_AIC_PRIOR_4 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Device Port
  81047. +#define AT91_SMR_TWI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Two-Wire Interface
  81048. +#define AT91_SMR_SPI (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Peripheral Interface
  81049. +#define AT91_SMR_SSC0 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 0
  81050. +#define AT91_SMR_SSC1 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 1
  81051. +#define AT91_SMR_SSC2 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 2
  81052. +#define AT91_SMR_TC0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 0
  81053. +#define AT91_SMR_TC1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 1
  81054. +#define AT91_SMR_TC2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 2
  81055. +#define AT91_SMR_TC3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 3
  81056. +#define AT91_SMR_TC4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 4
  81057. +#define AT91_SMR_TC5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 5
  81058. +#define AT91_SMR_UHP (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Host port
  81059. +#define AT91_SMR_EMAC (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Ethernet MAC
  81060. +#define AT91_SMR_IRQ0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ0)
  81061. +#define AT91_SMR_IRQ1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ1)
  81062. +#define AT91_SMR_IRQ2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ2)
  81063. +#define AT91_SMR_IRQ3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ3)
  81064. +#define AT91_SMR_IRQ4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ4)
  81065. +#define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
  81066. +#define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
  81067. +
  81068. +
  81069. +#define AT91C_CONSOLE_DEFAULT_BAUDRATE 38400
  81070. +
  81071. +/*
  81072. + * Serial port configuration.
  81073. + * 0 .. 3 = USART0 .. USART3
  81074. + * 4 = DBGU
  81075. + */
  81076. +#define AT91C_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
  81077. +#define AT91C_CONSOLE 0 /* ttyS0 */
  81078. +
  81079. +#endif
  81080. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/hardware.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/hardware.h
  81081. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/hardware.h 2003-08-25 12:44:43.000000000 +0100
  81082. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/hardware.h 2004-04-10 12:28:14.000000000 +0100
  81083. @@ -60,6 +60,7 @@
  81084. #define AT91C_BASE_SRAM 0x00200000 /* Internal SRAM base address */
  81085. +#define AT91C_SRAM_SIZE 0x00004000 /* Internal SRAM SIZE (16Kb) */
  81086. #define AT91C_NR_UART 5 /* 4 USART3's and one DBGU port */
  81087. @@ -82,5 +83,8 @@
  81088. #include <asm/arch/at91rm9200dk.h>
  81089. #endif
  81090. +#ifdef CONFIG_MACH_CSB337
  81091. +#include <asm/arch/csb337.h>
  81092. +#endif
  81093. #endif
  81094. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/pio.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/pio.h
  81095. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/pio.h 2003-08-25 12:44:43.000000000 +0100
  81096. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/pio.h 2004-03-04 22:06:48.000000000 +0000
  81097. @@ -66,6 +66,18 @@
  81098. }
  81099. /*
  81100. + * Configure interrupt from Ethernet PHY.
  81101. + */
  81102. +static inline void AT91_CfgPIO_EMAC_PHY(void) {
  81103. + AT91_SYS->PMC_PCER = 1 << AT91C_ID_PIOC; /* enable peripheral clock */
  81104. +#ifdef CONFIG_MACH_CSB337
  81105. + AT91_SYS->PIOC_ODR = AT91C_PIO_PC2;
  81106. +#else
  81107. + AT91_SYS->PIOC_ODR = AT91C_PIO_PC4;
  81108. +#endif
  81109. +}
  81110. +
  81111. +/*
  81112. * Enable the Two-Wire interface.
  81113. */
  81114. static inline void AT91_CfgPIO_TWI(void) {
  81115. diff -urN linux-2.4.26/include/asm-arm/arch-at91rm9200/time.h linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/time.h
  81116. --- linux-2.4.26/include/asm-arm/arch-at91rm9200/time.h 2003-08-25 12:44:43.000000000 +0100
  81117. +++ linux-2.4.26-vrs1/include/asm-arm/arch-at91rm9200/time.h 2004-04-10 12:21:08.000000000 +0100
  81118. @@ -27,6 +27,21 @@
  81119. extern unsigned long (*gettimeoffset)(void);
  81120. /*
  81121. + * The ST_CRTR is updated asynchronously to the master clock. It is therefore
  81122. + * necessary to read it twice (with the same value) to ensure accuracy.
  81123. + */
  81124. +static inline unsigned long read_CRTR(void) {
  81125. + unsigned long x1, x2;
  81126. +
  81127. + do {
  81128. + x1 = AT91_SYS->ST_CRTR;
  81129. + x2 = AT91_SYS->ST_CRTR;
  81130. + } while (x1 != x2);
  81131. +
  81132. + return x1;
  81133. +}
  81134. +
  81135. +/*
  81136. * Returns number of microseconds since last timer interrupt. Note that interrupts
  81137. * will have been disabled by do_gettimeofday()
  81138. * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
  81139. @@ -36,7 +51,7 @@
  81140. {
  81141. unsigned long elapsed;
  81142. - elapsed = (AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
  81143. + elapsed = (read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
  81144. return (unsigned long)(elapsed * tick) / LATCH;
  81145. }
  81146. @@ -48,11 +63,12 @@
  81147. {
  81148. if (AT91_SYS->ST_SR & AT91C_ST_PITS) { /* This is a shared interrupt */
  81149. do {
  81150. + do_leds();
  81151. do_timer(regs);
  81152. AT91_SYS->ST_RTAR = (AT91_SYS->ST_RTAR + LATCH) & AT91C_ST_ALMV;
  81153. - } while (((AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
  81154. + } while (((read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
  81155. do_profile(regs);
  81156. }
  81157. diff -urN linux-2.4.26/include/asm-arm/arch-clps711x/system.h linux-2.4.26-vrs1/include/asm-arm/arch-clps711x/system.h
  81158. --- linux-2.4.26/include/asm-arm/arch-clps711x/system.h 2003-06-13 15:51:38.000000000 +0100
  81159. +++ linux-2.4.26-vrs1/include/asm-arm/arch-clps711x/system.h 2004-01-14 21:32:27.000000000 +0000
  81160. @@ -28,8 +28,8 @@
  81161. {
  81162. clps_writel(1, HALT);
  81163. __asm__ __volatile__(
  81164. - "mov r0, r0
  81165. - mov r0, r0");
  81166. + "mov r0, r0\n\t"
  81167. + "mov r0, r0");
  81168. }
  81169. static inline void arch_reset(char mode)
  81170. diff -urN linux-2.4.26/include/asm-arm/arch-integrator/uncompress.h linux-2.4.26-vrs1/include/asm-arm/arch-integrator/uncompress.h
  81171. --- linux-2.4.26/include/asm-arm/arch-integrator/uncompress.h 2002-08-03 01:39:45.000000000 +0100
  81172. +++ linux-2.4.26-vrs1/include/asm-arm/arch-integrator/uncompress.h 2004-01-14 21:32:29.000000000 +0000
  81173. @@ -18,6 +18,8 @@
  81174. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  81175. */
  81176. +#include <asm/hardware/serial_amba.h>
  81177. +
  81178. #define AMBA_UART_DR (*(volatile unsigned char *)0x16000000)
  81179. #define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
  81180. #define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
  81181. @@ -30,21 +32,25 @@
  81182. */
  81183. static void puts(const char *s)
  81184. {
  81185. + /* Do nothing if the UART is not enabled. */
  81186. + if (!(AMBA_UART_CR & AMBA_UARTCR_UARTEN))
  81187. + return;
  81188. +
  81189. while (*s) {
  81190. - while (AMBA_UART_FR & (1 << 5))
  81191. + while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
  81192. barrier();
  81193. AMBA_UART_DR = *s;
  81194. if (*s == '\n') {
  81195. - while (AMBA_UART_FR & (1 << 5))
  81196. + while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
  81197. barrier();
  81198. AMBA_UART_DR = '\r';
  81199. }
  81200. s++;
  81201. }
  81202. - while (AMBA_UART_FR & (1 << 3));
  81203. + while (AMBA_UART_FR & AMBA_UARTFR_BUSY);
  81204. }
  81205. /*
  81206. diff -urN linux-2.4.26/include/asm-arm/arch-riscstation/system.h linux-2.4.26-vrs1/include/asm-arm/arch-riscstation/system.h
  81207. --- linux-2.4.26/include/asm-arm/arch-riscstation/system.h 2003-08-25 12:44:43.000000000 +0100
  81208. +++ linux-2.4.26-vrs1/include/asm-arm/arch-riscstation/system.h 2004-04-19 20:40:16.000000000 +0100
  81209. @@ -1,5 +1,5 @@
  81210. /*
  81211. - * linux/include/asm-arm/arch-rpc/system.h
  81212. + * linux/include/asm-arm/arch-riscstation/system.h
  81213. *
  81214. * Copyright (C) 1996-1999 Russell King.
  81215. *
  81216. @@ -18,7 +18,7 @@
  81217. static inline void arch_reset(char mode)
  81218. {
  81219. - iomd_writeb(0, IOMD_ROMCR0);
  81220. + iomd_writeb(0x40, IOMD_ROMCR0);
  81221. /*
  81222. * Jump into the ROM
  81223. diff -urN linux-2.4.26/include/asm-arm/arch-rpc/uncompress.h linux-2.4.26-vrs1/include/asm-arm/arch-rpc/uncompress.h
  81224. --- linux-2.4.26/include/asm-arm/arch-rpc/uncompress.h 2003-08-25 12:44:43.000000000 +0100
  81225. +++ linux-2.4.26-vrs1/include/asm-arm/arch-rpc/uncompress.h 2004-04-09 19:29:57.000000000 +0100
  81226. @@ -11,29 +11,12 @@
  81227. #include <asm/hardware.h>
  81228. #include <asm/io.h>
  81229. +#include <asm/setup.h>
  81230. int video_num_columns, video_num_lines, video_size_row;
  81231. int white, bytes_per_char_h;
  81232. extern unsigned long con_charconvtable[256];
  81233. -struct param_struct {
  81234. - unsigned long page_size;
  81235. - unsigned long nr_pages;
  81236. - unsigned long ramdisk_size;
  81237. - unsigned long mountrootrdonly;
  81238. - unsigned long rootdev;
  81239. - unsigned long video_num_cols;
  81240. - unsigned long video_num_rows;
  81241. - unsigned long video_x;
  81242. - unsigned long video_y;
  81243. - unsigned long memc_control_reg;
  81244. - unsigned char sounddefault;
  81245. - unsigned char adfsdrives;
  81246. - unsigned char bytes_per_char_h;
  81247. - unsigned char bytes_per_char_v;
  81248. - unsigned long unused[256/4-11];
  81249. -};
  81250. -
  81251. static const unsigned long palette_4[16] = {
  81252. 0x00000000,
  81253. 0x000000cc,
  81254. @@ -69,8 +52,12 @@
  81255. unsigned char c;
  81256. char *ptr;
  81257. - x = params->video_x;
  81258. - y = params->video_y;
  81259. + /* Don't bother when using a tagged list */
  81260. + if (((struct tag *)params)->hdr.tag == ATAG_CORE)
  81261. + return;
  81262. +
  81263. + x = params->u1.s.video_x;
  81264. + y = params->u1.s.video_y;
  81265. while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
  81266. if ( c == '\n' ) {
  81267. @@ -79,7 +66,7 @@
  81268. y--;
  81269. }
  81270. } else {
  81271. - ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
  81272. + ptr = VIDMEM + ((y*video_num_columns*params->u1.s.bytes_per_char_v+x)*bytes_per_char_h);
  81273. ll_write_char(ptr, c, white);
  81274. if ( ++x >= video_num_columns ) {
  81275. x = 0;
  81276. @@ -90,8 +77,6 @@
  81277. }
  81278. }
  81279. - params->video_x = x;
  81280. - params->video_y = y;
  81281. }
  81282. static void error(char *x);
  81283. @@ -103,9 +88,13 @@
  81284. {
  81285. int i;
  81286. - video_num_lines = params->video_num_rows;
  81287. - video_num_columns = params->video_num_cols;
  81288. - bytes_per_char_h = params->bytes_per_char_h;
  81289. + /* Don't bother when using a tagged list */
  81290. + if (((struct tag *)params)->hdr.tag == ATAG_CORE)
  81291. + return;
  81292. +
  81293. + video_num_lines = params->u1.s.video_num_rows;
  81294. + video_num_columns = params->u1.s.video_num_cols;
  81295. + bytes_per_char_h = params->u1.s.bytes_per_char_h;
  81296. video_size_row = video_num_columns * bytes_per_char_h;
  81297. if (bytes_per_char_h == 4)
  81298. for (i = 0; i < 256; i++)
  81299. @@ -140,7 +129,7 @@
  81300. white = 7;
  81301. }
  81302. - if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
  81303. + if (params->u1.s.nr_pages * params->u1.s.page_size < 4096*1024) error("<4M of mem\n");
  81304. }
  81305. #endif
  81306. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-clock.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-clock.h
  81307. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-clock.h 1970-01-01 01:00:00.000000000 +0100
  81308. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-clock.h 2004-03-07 13:04:06.000000000 +0000
  81309. @@ -0,0 +1,76 @@
  81310. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-clock.h
  81311. + *
  81312. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  81313. + * http://www.simtec.co.uk/products/SWLINUX/
  81314. + *
  81315. + * This program is free software; you can redistribute it and/or modify
  81316. + * it under the terms of the GNU General Public License version 2 as
  81317. + * published by the Free Software Foundation.
  81318. + *
  81319. + * S3C2410 clock register definitions
  81320. + *
  81321. + * Changelog:
  81322. + * 19-06-2003 BJD Created file
  81323. + */
  81324. +
  81325. +#ifndef ASMARM_ARCH_S3C2410_CLOCK_H
  81326. +#define ASMARM_ARCH_S3C2410_CLOCK_H
  81327. +
  81328. +#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
  81329. +
  81330. +#define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
  81331. +
  81332. +#define S3C2410_LOCKTIME S3C2410_CLKREG(0x00)
  81333. +#define S3C2410_MPLLCON S3C2410_CLKREG(0x04)
  81334. +#define S3C2410_UPLLCON S3C2410_CLKREG(0x08)
  81335. +#define S3C2410_CLKCON S3C2410_CLKREG(0x0C)
  81336. +#define S3C2410_CLKSLOW S3C2410_CLKREG(0x10)
  81337. +#define S3C2410_CLKDIVN S3C2410_CLKREG(0x14)
  81338. +
  81339. +#define S3C2410_PLLCON_MDIVSHIFT 12
  81340. +#define S3C2410_PLLCON_PDIVSHIFT 4
  81341. +#define S3C2410_PLLCON_SDIVSHIFT 0
  81342. +#define S3C2410_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1)
  81343. +#define S3C2410_PLLCON_PDIVMASK ((1<<5)-1)
  81344. +#define S3C2410_PLLCON_SDIVMASK 3
  81345. +
  81346. +/* DCLKCON register addresses in gpio.h */
  81347. +
  81348. +#define S3C2410_DCLKCON_DCLK0EN (1<<0)
  81349. +#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1)
  81350. +#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1)
  81351. +#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4)
  81352. +#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8)
  81353. +
  81354. +#define S3C2410_DCLKCON_DCLK1EN (1<<16)
  81355. +#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17)
  81356. +#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17)
  81357. +#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20)
  81358. +
  81359. +#define S3C2410_CLKDIVN_PDIVN (1<<0)
  81360. +#define S3C2410_CLKDIVN_HDIVN (1<<1)
  81361. +
  81362. +static inline unsigned int
  81363. +s3c2410_get_pll(int pllval, int baseclk)
  81364. +{
  81365. + int mdiv, pdiv, sdiv;
  81366. +
  81367. + mdiv = pllval >> S3C2410_PLLCON_MDIVSHIFT;
  81368. + pdiv = pllval >> S3C2410_PLLCON_PDIVSHIFT;
  81369. + sdiv = pllval >> S3C2410_PLLCON_SDIVSHIFT;
  81370. +
  81371. + mdiv &= S3C2410_PLLCON_MDIVMASK;
  81372. + pdiv &= S3C2410_PLLCON_PDIVMASK;
  81373. + sdiv &= S3C2410_PLLCON_SDIVMASK;
  81374. +
  81375. + return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
  81376. +}
  81377. +
  81378. +#endif /* ASMARM_ARCH_S3C2410_CLOCK_H */
  81379. +
  81380. +
  81381. +
  81382. +
  81383. +
  81384. +
  81385. +
  81386. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-gpio.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-gpio.h
  81387. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-gpio.h 1970-01-01 01:00:00.000000000 +0100
  81388. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-gpio.h 2004-03-07 13:01:28.000000000 +0000
  81389. @@ -0,0 +1,602 @@
  81390. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-gpio.h
  81391. + *
  81392. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  81393. + * http://www.simtec.co.uk/products/SWLINUX/
  81394. + *
  81395. + * This program is free software; you can redistribute it and/or modify
  81396. + * it under the terms of the GNU General Public License version 2 as
  81397. + * published by the Free Software Foundation.
  81398. + *
  81399. + * S3C2410 GPIO register definitions
  81400. + *
  81401. + * Changelog:
  81402. + * 19-06-2003 BJD Created file
  81403. + * 23-06-2003 BJD Updated GSTATUS registers
  81404. + */
  81405. +
  81406. +#ifndef ASMARM_ARCH_S3C2410_GPIO_H
  81407. +#define ASMARM_ARCH_S3C2410_GPIO_H
  81408. +
  81409. +/* configure GPIO ports A..G */
  81410. +
  81411. +#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
  81412. +
  81413. +/* port A - 22bits, zero in bit X makes pin X output
  81414. + * 1 makes port special function, this is default
  81415. +*/
  81416. +#define S3C2410_GPACON S3C2410_GPIOREG(0x00)
  81417. +#define S3C2410_GPADAT S3C2410_GPIOREG(0x04)
  81418. +
  81419. +/* 0x08 and 0x0c are reserved */
  81420. +
  81421. +/* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
  81422. + * 00 = input, 01 = output, 10=special function, 11=reserved
  81423. + * bit 0,1 = pin 0, 2,3= pin 1...
  81424. + *
  81425. + * CPBUP = pull up resistor control, 1=disabled, 0=enabled
  81426. +*/
  81427. +
  81428. +#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)
  81429. +#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
  81430. +#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
  81431. +
  81432. +/* no i/o pin in port b can have value 3! */
  81433. +
  81434. +#define S3C2410_GPB0_INP (0x00 << 0)
  81435. +#define S3C2410_GPB0_OUTP (0x01 << 0)
  81436. +#define S3C2410_GPB0_TOUT0 (0x02 << 0)
  81437. +
  81438. +#define S3C2410_GPB1_INP (0x00 << 2)
  81439. +#define S3C2410_GPB1_OUTP (0x01 << 2)
  81440. +#define S3C2410_GPB1_TOUT1 (0x02 << 2)
  81441. +
  81442. +#define S3C2410_GPB2_INP (0x00 << 4)
  81443. +#define S3C2410_GPB2_OUTP (0x01 << 4)
  81444. +#define S3C2410_GPB2_TOUT2 (0x02 << 4)
  81445. +
  81446. +#define S3C2410_GPB3_INP (0x00 << 6)
  81447. +#define S3C2410_GPB3_OUTP (0x01 << 6)
  81448. +#define S3C2410_GPB3_TOUT3 (0x02 << 6)
  81449. +
  81450. +#define S3C2410_GPB4_INP (0x00 << 8)
  81451. +#define S3C2410_GPB4_OUTP (0x01 << 8)
  81452. +#define S3C2410_GPB4_TCLK0 (0x02 << 8)
  81453. +#define S3C2410_GPB4_MASK (0x03 << 8)
  81454. +
  81455. +#define S3C2410_GPB5_INP (0x00 << 10)
  81456. +#define S3C2410_GPB5_OUTP (0x01 << 10)
  81457. +#define S3C2410_GPB5_nXBACK (0x02 << 10)
  81458. +
  81459. +#define S3C2410_GPB6_INP (0x00 << 12)
  81460. +#define S3C2410_GPB6_OUTP (0x01 << 12)
  81461. +#define S3C2410_GPB6_nXBREQ (0x02 << 12)
  81462. +
  81463. +#define S3C2410_GPB7_INP (0x00 << 14)
  81464. +#define S3C2410_GPB7_OUTP (0x01 << 14)
  81465. +#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
  81466. +
  81467. +#define S3C2410_GPB8_INP (0x00 << 16)
  81468. +#define S3C2410_GPB8_OUTP (0x01 << 16)
  81469. +#define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
  81470. +
  81471. +#define S3C2410_GPB9_INP (0x00 << 18)
  81472. +#define S3C2410_GPB9_OUTP (0x01 << 18)
  81473. +#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
  81474. +
  81475. +#define S3C2410_GPB10_INP (0x00 << 18)
  81476. +#define S3C2410_GPB10_OUTP (0x01 << 18)
  81477. +#define S3C2410_GPB10_nXDRE0 (0x02 << 18)
  81478. +
  81479. +/* Port C consits of 16 GPIO/Special function
  81480. + *
  81481. + * almost identical setup to port b, but the special functions are mostly
  81482. + * to do with the video system's sync/etc.
  81483. +*/
  81484. +
  81485. +#define S3C2410_GPCCON S3C2410_GPIOREG(0x20)
  81486. +#define S3C2410_GPCDAT S3C2410_GPIOREG(0x24)
  81487. +#define S3C2410_GPCUP S3C2410_GPIOREG(0x28)
  81488. +
  81489. +#define S3C2410_GPC0_INP (0x00 << 0)
  81490. +#define S3C2410_GPC0_OUTP (0x01 << 0)
  81491. +#define S3C2410_GPC0_LEND (0x02 << 0)
  81492. +
  81493. +#define S3C2410_GPC1_INP (0x00 << 2)
  81494. +#define S3C2410_GPC1_OUTP (0x01 << 2)
  81495. +#define S3C2410_GPC1_VCLK (0x02 << 2)
  81496. +
  81497. +#define S3C2410_GPC2_INP (0x00 << 4)
  81498. +#define S3C2410_GPC2_OUTP (0x01 << 4)
  81499. +#define S3C2410_GPC2_VLINE (0x02 << 4)
  81500. +
  81501. +#define S3C2410_GPC3_INP (0x00 << 6)
  81502. +#define S3C2410_GPC3_OUTP (0x01 << 6)
  81503. +#define S3C2410_GPC3_VFRAME (0x02 << 6)
  81504. +
  81505. +#define S3C2410_GPC4_INP (0x00 << 8)
  81506. +#define S3C2410_GPC4_OUTP (0x01 << 8)
  81507. +#define S3C2410_GPC4_VM (0x02 << 8)
  81508. +
  81509. +#define S3C2410_GPC5_INP (0x00 << 10)
  81510. +#define S3C2410_GPC5_OUTP (0x01 << 10)
  81511. +#define S3C2410_GPC5_LCDVF0 (0x02 << 10)
  81512. +
  81513. +#define S3C2410_GPC6_INP (0x00 << 12)
  81514. +#define S3C2410_GPC6_OUTP (0x01 << 12)
  81515. +#define S3C2410_GPC6_LCDVF1 (0x02 << 12)
  81516. +
  81517. +#define S3C2410_GPC7_INP (0x00 << 14)
  81518. +#define S3C2410_GPC7_OUTP (0x01 << 14)
  81519. +#define S3C2410_GPC7_LCDVF2 (0x02 << 14)
  81520. +
  81521. +#define S3C2410_GPC8_INP (0x00 << 16)
  81522. +#define S3C2410_GPC8_OUTP (0x01 << 16)
  81523. +#define S3C2410_GPC8_VD0 (0x02 << 16)
  81524. +
  81525. +#define S3C2410_GPC9_INP (0x00 << 18)
  81526. +#define S3C2410_GPC9_OUTP (0x01 << 18)
  81527. +#define S3C2410_GPC9_VD1 (0x02 << 18)
  81528. +
  81529. +#define S3C2410_GPC10_INP (0x00 << 20)
  81530. +#define S3C2410_GPC10_OUTP (0x01 << 20)
  81531. +#define S3C2410_GPC10_VD2 (0x02 << 20)
  81532. +
  81533. +#define S3C2410_GPC11_INP (0x00 << 22)
  81534. +#define S3C2410_GPC11_OUTP (0x01 << 22)
  81535. +#define S3C2410_GPC11_VD3 (0x02 << 22)
  81536. +
  81537. +#define S3C2410_GPC12_INP (0x00 << 24)
  81538. +#define S3C2410_GPC12_OUTP (0x01 << 24)
  81539. +#define S3C2410_GPC12_VD4 (0x02 << 24)
  81540. +
  81541. +#define S3C2410_GPC13_INP (0x00 << 26)
  81542. +#define S3C2410_GPC13_OUTP (0x01 << 26)
  81543. +#define S3C2410_GPC13_VD5 (0x02 << 26)
  81544. +
  81545. +#define S3C2410_GPC14_INP (0x00 << 28)
  81546. +#define S3C2410_GPC14_OUTP (0x01 << 28)
  81547. +#define S3C2410_GPC14_VD6 (0x02 << 28)
  81548. +
  81549. +#define S3C2410_GPC15_INP (0x00 << 30)
  81550. +#define S3C2410_GPC15_OUTP (0x01 << 30)
  81551. +#define S3C2410_GPC15_VD7 (0x02 << 30)
  81552. +
  81553. +/* Port D consists of 16 GPIO/Special function
  81554. + *
  81555. + * almost identical setup to port b, but the special functions are mostly
  81556. + * to do with the video system's data.
  81557. +*/
  81558. +
  81559. +#define S3C2410_GPDCON S3C2410_GPIOREG(0x30)
  81560. +#define S3C2410_GPDDAT S3C2410_GPIOREG(0x34)
  81561. +#define S3C2410_GPDUP S3C2410_GPIOREG(0x38)
  81562. +
  81563. +#define S3C2410_GPD0_INP (0x00 << 0)
  81564. +#define S3C2410_GPD0_OUTP (0x01 << 0)
  81565. +#define S3C2410_GPD0_VD8 (0x02 << 0)
  81566. +
  81567. +#define S3C2410_GPD1_INP (0x00 << 2)
  81568. +#define S3C2410_GPD1_OUTP (0x01 << 2)
  81569. +#define S3C2410_GPD1_VD9 (0x02 << 2)
  81570. +
  81571. +#define S3C2410_GPD2_INP (0x00 << 4)
  81572. +#define S3C2410_GPD2_OUTP (0x01 << 4)
  81573. +#define S3C2410_GPD2_VD10 (0x02 << 4)
  81574. +
  81575. +#define S3C2410_GPD3_INP (0x00 << 6)
  81576. +#define S3C2410_GPD3_OUTP (0x01 << 6)
  81577. +#define S3C2410_GPD3_VD11 (0x02 << 6)
  81578. +
  81579. +#define S3C2410_GPD4_INP (0x00 << 8)
  81580. +#define S3C2410_GPD4_OUTP (0x01 << 8)
  81581. +#define S3C2410_GPD4_VD12 (0x02 << 8)
  81582. +
  81583. +#define S3C2410_GPD5_INP (0x00 << 10)
  81584. +#define S3C2410_GPD5_OUTP (0x01 << 10)
  81585. +#define S3C2410_GPD5_VD13 (0x02 << 10)
  81586. +
  81587. +#define S3C2410_GPD6_INP (0x00 << 12)
  81588. +#define S3C2410_GPD6_OUTP (0x01 << 12)
  81589. +#define S3C2410_GPD6_VD14 (0x02 << 12)
  81590. +
  81591. +#define S3C2410_GPD7_INP (0x00 << 14)
  81592. +#define S3C2410_GPD7_OUTP (0x01 << 14)
  81593. +#define S3C2410_GPD7_VD15 (0x02 << 14)
  81594. +
  81595. +#define S3C2410_GPD8_INP (0x00 << 16)
  81596. +#define S3C2410_GPD8_OUTP (0x01 << 16)
  81597. +#define S3C2410_GPD8_VD16 (0x02 << 16)
  81598. +
  81599. +#define S3C2410_GPD9_INP (0x00 << 18)
  81600. +#define S3C2410_GPD9_OUTP (0x01 << 18)
  81601. +#define S3C2410_GPD9_VD17 (0x02 << 18)
  81602. +
  81603. +#define S3C2410_GPD10_INP (0x00 << 20)
  81604. +#define S3C2410_GPD10_OUTP (0x01 << 20)
  81605. +#define S3C2410_GPD10_VD18 (0x02 << 20)
  81606. +
  81607. +#define S3C2410_GPD11_INP (0x00 << 22)
  81608. +#define S3C2410_GPD11_OUTP (0x01 << 22)
  81609. +#define S3C2410_GPD11_VD19 (0x02 << 22)
  81610. +
  81611. +#define S3C2410_GPD12_INP (0x00 << 24)
  81612. +#define S3C2410_GPD12_OUTP (0x01 << 24)
  81613. +#define S3C2410_GPD12_VD20 (0x02 << 24)
  81614. +
  81615. +#define S3C2410_GPD13_INP (0x00 << 26)
  81616. +#define S3C2410_GPD13_OUTP (0x01 << 26)
  81617. +#define S3C2410_GPD13_VD21 (0x02 << 26)
  81618. +
  81619. +#define S3C2410_GPD14_INP (0x00 << 28)
  81620. +#define S3C2410_GPD14_OUTP (0x01 << 28)
  81621. +#define S3C2410_GPD14_VD22 (0x02 << 28)
  81622. +
  81623. +#define S3C2410_GPD15_INP (0x00 << 30)
  81624. +#define S3C2410_GPD15_OUTP (0x01 << 30)
  81625. +#define S3C2410_GPD15_VD23 (0x02 << 30)
  81626. +
  81627. +/* Port E consists of 16 GPIO/Special function
  81628. + *
  81629. + * again, the same as port B, but dealing with I2S, SDI, and
  81630. + * more miscellaneous functions
  81631. +*/
  81632. +
  81633. +#define S3C2410_GPECON S3C2410_GPIOREG(0x40)
  81634. +#define S3C2410_GPEDAT S3C2410_GPIOREG(0x44)
  81635. +#define S3C2410_GPEUP S3C2410_GPIOREG(0x48)
  81636. +
  81637. +#define S3C2410_GPE0_INP (0x00 << 0)
  81638. +#define S3C2410_GPE0_OUTP (0x01 << 0)
  81639. +#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
  81640. +#define S3C2410_GPE0_MASK (0x03 << 0)
  81641. +
  81642. +#define S3C2410_GPE1_INP (0x00 << 2)
  81643. +#define S3C2410_GPE1_OUTP (0x01 << 2)
  81644. +#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
  81645. +#define S3C2410_GPE1_MASK (0x03 << 2)
  81646. +
  81647. +#define S3C2410_GPE2_INP (0x00 << 4)
  81648. +#define S3C2410_GPE2_OUTP (0x01 << 4)
  81649. +#define S3C2410_GPE2_CDCLK (0x02 << 4)
  81650. +
  81651. +#define S3C2410_GPE3_INP (0x00 << 6)
  81652. +#define S3C2410_GPE3_OUTP (0x01 << 6)
  81653. +#define S3C2410_GPE3_I2SSDI (0x02 << 6)
  81654. +#define S3C2410_GPE3_MASK (0x03 << 6)
  81655. +
  81656. +#define S3C2410_GPE4_INP (0x00 << 8)
  81657. +#define S3C2410_GPE4_OUTP (0x01 << 8)
  81658. +#define S3C2410_GPE4_I2SSDO (0x02 << 8)
  81659. +#define S3C2410_GPE4_MASK (0x03 << 8)
  81660. +
  81661. +#define S3C2410_GPE5_INP (0x00 << 10)
  81662. +#define S3C2410_GPE5_OUTP (0x01 << 10)
  81663. +#define S3C2410_GPE5_SDCLK (0x02 << 10)
  81664. +
  81665. +#define S3C2410_GPE6_INP (0x00 << 12)
  81666. +#define S3C2410_GPE6_OUTP (0x01 << 12)
  81667. +#define S3C2410_GPE6_SDCLK (0x02 << 12)
  81668. +
  81669. +#define S3C2410_GPE7_INP (0x00 << 14)
  81670. +#define S3C2410_GPE7_OUTP (0x01 << 14)
  81671. +#define S3C2410_GPE7_SDCMD (0x02 << 14)
  81672. +
  81673. +#define S3C2410_GPE8_INP (0x00 << 16)
  81674. +#define S3C2410_GPE8_OUTP (0x01 << 16)
  81675. +#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
  81676. +
  81677. +#define S3C2410_GPE9_INP (0x00 << 18)
  81678. +#define S3C2410_GPE9_OUTP (0x01 << 18)
  81679. +#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
  81680. +
  81681. +#define S3C2410_GPE10_INP (0x00 << 20)
  81682. +#define S3C2410_GPE10_OUTP (0x01 << 20)
  81683. +#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
  81684. +
  81685. +#define S3C2410_GPE11_INP (0x00 << 22)
  81686. +#define S3C2410_GPE11_OUTP (0x01 << 22)
  81687. +#define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
  81688. +
  81689. +#define S3C2410_GPE12_INP (0x00 << 24)
  81690. +#define S3C2410_GPE12_OUTP (0x01 << 24)
  81691. +#define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
  81692. +
  81693. +#define S3C2410_GPE13_INP (0x00 << 26)
  81694. +#define S3C2410_GPE13_OUTP (0x01 << 26)
  81695. +#define S3C2410_GPE13_SPICLK0 (0x02 << 26)
  81696. +
  81697. +#define S3C2410_GPE14_INP (0x00 << 28)
  81698. +#define S3C2410_GPE14_OUTP (0x01 << 28)
  81699. +#define S3C2410_GPE14_IICSCL (0x02 << 28)
  81700. +#define S3C2410_GPE14_MASK (0x03 << 28)
  81701. +
  81702. +#define S3C2410_GPE15_INP (0x00 << 30)
  81703. +#define S3C2410_GPE15_OUTP (0x01 << 30)
  81704. +#define S3C2410_GPE15_IICSDA (0x02 << 30)
  81705. +#define S3C2410_GPE15_MASK (0x03 << 30)
  81706. +
  81707. +#define S3C2410_GPE_PUPDIS(x) (1<<(x))
  81708. +
  81709. +/* Port F consists of 8 GPIO/Special function
  81710. + *
  81711. + * GPIO / interrupt inputs
  81712. + *
  81713. + * GPFCON has 2 bits for each of the input pins on port F
  81714. + * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 undefined
  81715. + *
  81716. + * pull up works like all other ports.
  81717. +*/
  81718. +
  81719. +#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)
  81720. +#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)
  81721. +#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)
  81722. +
  81723. +
  81724. +#define S3C2410_GPF0_INP (0x00 << 0)
  81725. +#define S3C2410_GPF0_OUTP (0x01 << 0)
  81726. +#define S3C2410_GPF0_EINT0 (0x02 << 0)
  81727. +
  81728. +#define S3C2410_GPF1_INP (0x00 << 2)
  81729. +#define S3C2410_GPF1_OUTP (0x01 << 2)
  81730. +#define S3C2410_GPF1_EINT1 (0x02 << 2)
  81731. +
  81732. +#define S3C2410_GPF2_INP (0x00 << 4)
  81733. +#define S3C2410_GPF2_OUTP (0x01 << 4)
  81734. +#define S3C2410_GPF2_EINT2 (0x02 << 4)
  81735. +
  81736. +#define S3C2410_GPF3_INP (0x00 << 6)
  81737. +#define S3C2410_GPF3_OUTP (0x01 << 6)
  81738. +#define S3C2410_GPF3_EINT3 (0x02 << 6)
  81739. +
  81740. +#define S3C2410_GPF4_INP (0x00 << 8)
  81741. +#define S3C2410_GPF4_OUTP (0x01 << 8)
  81742. +#define S3C2410_GPF4_EINT4 (0x02 << 8)
  81743. +
  81744. +#define S3C2410_GPF5_INP (0x00 << 10)
  81745. +#define S3C2410_GPF5_OUTP (0x01 << 10)
  81746. +#define S3C2410_GPF5_EINT5 (0x02 << 10)
  81747. +
  81748. +#define S3C2410_GPF6_INP (0x00 << 12)
  81749. +#define S3C2410_GPF6_OUTP (0x01 << 12)
  81750. +#define S3C2410_GPF6_EINT6 (0x02 << 12)
  81751. +
  81752. +#define S3C2410_GPF7_INP (0x00 << 14)
  81753. +#define S3C2410_GPF7_OUTP (0x01 << 14)
  81754. +#define S3C2410_GPF7_EINT7 (0x02 << 14)
  81755. +
  81756. +/* Port G consists of 8 GPIO/IRQ/Special function
  81757. + *
  81758. + * GPGCON has 2 bits for each of the input pins on port F
  81759. + * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  81760. + *
  81761. + * pull up works like all other ports.
  81762. +*/
  81763. +
  81764. +#define S3C2410_GPGCON S3C2410_GPIOREG(0x60)
  81765. +#define S3C2410_GPGDAT S3C2410_GPIOREG(0x64)
  81766. +#define S3C2410_GPGUP S3C2410_GPIOREG(0x68)
  81767. +
  81768. +#define S3C2410_GPG0_INP (0x00 << 0)
  81769. +#define S3C2410_GPG0_OUTP (0x01 << 0)
  81770. +#define S3C2410_GPG0_EINT8 (0x02 << 0)
  81771. +
  81772. +#define S3C2410_GPG1_INP (0x00 << 2)
  81773. +#define S3C2410_GPG1_OUTP (0x01 << 2)
  81774. +#define S3C2410_GPG1_EINT9 (0x02 << 2)
  81775. +
  81776. +#define S3C2410_GPG2_INP (0x00 << 4)
  81777. +#define S3C2410_GPG2_OUTP (0x01 << 4)
  81778. +#define S3C2410_GPG2_EINT10 (0x02 << 4)
  81779. +
  81780. +#define S3C2410_GPG3_INP (0x00 << 6)
  81781. +#define S3C2410_GPG3_OUTP (0x01 << 6)
  81782. +#define S3C2410_GPG3_EINT11 (0x02 << 6)
  81783. +
  81784. +#define S3C2410_GPG4_INP (0x00 << 8)
  81785. +#define S3C2410_GPG4_OUTP (0x01 << 8)
  81786. +#define S3C2410_GPG4_EINT12 (0x02 << 8)
  81787. +#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
  81788. +
  81789. +#define S3C2410_GPG5_INP (0x00 << 10)
  81790. +#define S3C2410_GPG5_OUTP (0x01 << 10)
  81791. +#define S3C2410_GPG5_EINT13 (0x02 << 10)
  81792. +#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
  81793. +
  81794. +#define S3C2410_GPG6_INP (0x00 << 12)
  81795. +#define S3C2410_GPG6_OUTP (0x01 << 12)
  81796. +#define S3C2410_GPG6_EINT14 (0x02 << 12)
  81797. +#define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
  81798. +
  81799. +#define S3C2410_GPG7_INP (0x00 << 14)
  81800. +#define S3C2410_GPG7_OUTP (0x01 << 14)
  81801. +#define S3C2410_GPG7_EINT15 (0x02 << 14)
  81802. +#define S3C2410_GPG7_SPICLK1 (0x03 << 14)
  81803. +
  81804. +#define S3C2410_GPG8_INP (0x00 << 16)
  81805. +#define S3C2410_GPG8_OUTP (0x01 << 16)
  81806. +#define S3C2410_GPG8_EINT16 (0x02 << 16)
  81807. +
  81808. +#define S3C2410_GPG9_INP (0x00 << 18)
  81809. +#define S3C2410_GPG9_OUTP (0x01 << 18)
  81810. +#define S3C2410_GPG9_EINT17 (0x02 << 18)
  81811. +
  81812. +#define S3C2410_GPG10_INP (0x00 << 20)
  81813. +#define S3C2410_GPG10_OUTP (0x01 << 20)
  81814. +#define S3C2410_GPG10_EINT18 (0x02 << 20)
  81815. +
  81816. +#define S3C2410_GPG11_INP (0x00 << 22)
  81817. +#define S3C2410_GPG11_OUTP (0x01 << 22)
  81818. +#define S3C2410_GPG11_EINT19 (0x02 << 22)
  81819. +#define S3C2410_GPG11_TCLK1 (0x03 << 22)
  81820. +
  81821. +#define S3C2410_GPG12_INP (0x00 << 24)
  81822. +#define S3C2410_GPG12_OUTP (0x01 << 24)
  81823. +#define S3C2410_GPG12_EINT18 (0x02 << 24)
  81824. +#define S3C2410_GPG12_XMON (0x03 << 24)
  81825. +
  81826. +#define S3C2410_GPG13_INP (0x00 << 26)
  81827. +#define S3C2410_GPG13_OUTP (0x01 << 26)
  81828. +#define S3C2410_GPG13_EINT18 (0x02 << 26)
  81829. +#define S3C2410_GPG13_nXPON (0x03 << 26)
  81830. +
  81831. +#define S3C2410_GPG14_INP (0x00 << 28)
  81832. +#define S3C2410_GPG14_OUTP (0x01 << 28)
  81833. +#define S3C2410_GPG14_EINT18 (0x02 << 28)
  81834. +#define S3C2410_GPG14_YMON (0x03 << 28)
  81835. +
  81836. +#define S3C2410_GPG15_INP (0x00 << 30)
  81837. +#define S3C2410_GPG15_OUTP (0x01 << 30)
  81838. +#define S3C2410_GPG15_EINT18 (0x02 << 30)
  81839. +#define S3C2410_GPG15_nYPON (0x03 << 30)
  81840. +
  81841. +
  81842. +#define S3C2410_GPG_PUPDIS(x) (1<<(x))
  81843. +
  81844. +/* Port H consists of11 GPIO/serial/Misc pins
  81845. + *
  81846. + * GPGCON has 2 bits for each of the input pins on port F
  81847. + * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  81848. + *
  81849. + * pull up works like all other ports.
  81850. +*/
  81851. +
  81852. +#define S3C2410_GPHCON S3C2410_GPIOREG(0x70)
  81853. +#define S3C2410_GPHDAT S3C2410_GPIOREG(0x74)
  81854. +#define S3C2410_GPHUP S3C2410_GPIOREG(0x78)
  81855. +
  81856. +#define S3C2410_GPH0_INP (0x00 << 0)
  81857. +#define S3C2410_GPH0_OUTP (0x01 << 0)
  81858. +#define S3C2410_GPH0_nCTS0 (0x02 << 0)
  81859. +
  81860. +#define S3C2410_GPH1_INP (0x00 << 2)
  81861. +#define S3C2410_GPH1_OUTP (0x01 << 2)
  81862. +#define S3C2410_GPH1_nRTS0 (0x02 << 2)
  81863. +
  81864. +#define S3C2410_GPH2_INP (0x00 << 4)
  81865. +#define S3C2410_GPH2_OUTP (0x01 << 4)
  81866. +#define S3C2410_GPH2_TXD0 (0x02 << 4)
  81867. +
  81868. +#define S3C2410_GPH3_INP (0x00 << 6)
  81869. +#define S3C2410_GPH3_OUTP (0x01 << 6)
  81870. +#define S3C2410_GPH3_RXD0 (0x02 << 6)
  81871. +
  81872. +#define S3C2410_GPH4_INP (0x00 << 8)
  81873. +#define S3C2410_GPH4_OUTP (0x01 << 8)
  81874. +#define S3C2410_GPH4_TXD1 (0x02 << 8)
  81875. +
  81876. +#define S3C2410_GPH5_INP (0x00 << 10)
  81877. +#define S3C2410_GPH5_OUTP (0x01 << 10)
  81878. +#define S3C2410_GPH5_RXD1 (0x02 << 10)
  81879. +
  81880. +#define S3C2410_GPH6_INP (0x00 << 12)
  81881. +#define S3C2410_GPH6_OUTP (0x01 << 12)
  81882. +#define S3C2410_GPH6_TXD2 (0x02 << 12)
  81883. +#define S3C2410_GPH6_nRTS1 (0x03 << 12)
  81884. +
  81885. +#define S3C2410_GPH7_INP (0x00 << 14)
  81886. +#define S3C2410_GPH7_OUTP (0x01 << 14)
  81887. +#define S3C2410_GPH7_RXD2 (0x02 << 14)
  81888. +#define S3C2410_GPH7_nCTS1 (0x03 << 14)
  81889. +
  81890. +#define S3C2410_GPH8_INP (0x00 << 16)
  81891. +#define S3C2410_GPH8_OUTP (0x01 << 16)
  81892. +#define S3C2410_GPH8_UCLK (0x02 << 16)
  81893. +
  81894. +#define S3C2410_GPH9_INP (0x00 << 18)
  81895. +#define S3C2410_GPH9_OUTP (0x01 << 18)
  81896. +#define S3C2410_GPH9_CLKOUT0 (0x02 << 18)
  81897. +
  81898. +#define S3C2410_GPH10_INP (0x00 << 20)
  81899. +#define S3C2410_GPH10_OUTP (0x01 << 20)
  81900. +#define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
  81901. +
  81902. +/* miscellaneous control */
  81903. +
  81904. +#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
  81905. +#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
  81906. +
  81907. +/* see clock.h for dclk definitions */
  81908. +
  81909. +/* pullup control on databus */
  81910. +#define S3C2410_MISCCR_SPUCR_HEN (0)
  81911. +#define S3C2410_MISCCR_SPUCR_HDIS (1<<0)
  81912. +#define S3C2410_MISCCR_SPUCR_LEN (0)
  81913. +#define S3C2410_MISCCR_SPUCR_LDIS (1<<1)
  81914. +
  81915. +#define S3C2410_MISCCR_USBDEV (0)
  81916. +#define S3C2410_MISCCR_USBHOST (1<<3)
  81917. +
  81918. +#define S3C2410_MISCCR_CLK0_MPLL (0<<4)
  81919. +#define S3C2410_MISCCR_CLK0_UPLL (1<<4)
  81920. +#define S3C2410_MISCCR_CLK0_FCLK (2<<4)
  81921. +#define S3C2410_MISCCR_CLK0_HCLK (3<<4)
  81922. +#define S3C2410_MISCCR_CLK0_PCLK (4<<4)
  81923. +#define S3C2410_MISCCR_CLK0_DCLK0 (5<<4)
  81924. +
  81925. +#define S3C2410_MISCCR_CLK1_MPLL (0<<8)
  81926. +#define S3C2410_MISCCR_CLK1_UPLL (1<<8)
  81927. +#define S3C2410_MISCCR_CLK1_FCLK (2<<8)
  81928. +#define S3C2410_MISCCR_CLK1_HCLK (3<<8)
  81929. +#define S3C2410_MISCCR_CLK1_PCLK (4<<8)
  81930. +#define S3C2410_MISCCR_CLK1_DCLK1 (5<<8)
  81931. +
  81932. +#define S3C2410_MISCCR_USBSUSPND0 (1<<12)
  81933. +#define S3C2410_MISCCR_USBSUSPND1 (1<<13)
  81934. +
  81935. +#define S3C2410_MISCCR_nRSTCON (1<<16)
  81936. +
  81937. +/* external interrupt control... */
  81938. +/* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
  81939. + * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
  81940. + * S3C2410_EXTINT2 -> irq sense control for EINT16..EINT23
  81941. + *
  81942. + * note S3C2410_EXTINT2 has filtering options for EINT16..EINT23
  81943. + *
  81944. + * Samsung datasheet p9-25
  81945. +*/
  81946. +
  81947. +#define S3C2410_EXTINT0 S3C2410_GPIOREG(0x88)
  81948. +#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
  81949. +#define S3C2410_EXTINT2 S3C2410_GPIOREG(0x90)
  81950. +
  81951. +/* values for S3C2410_EXTINT0/1/2 */
  81952. +#define S3C2410_EXTINT_LOWLEV (0x00)
  81953. +#define S3C2410_EXTINT_HILEV (0x01)
  81954. +#define S3C2410_EXTINT_FALLEDGE (0x02)
  81955. +#define S3C2410_EXTINT_RISEEDGE (0x04)
  81956. +#define S3C2410_EXTINT_BOTHEDGE (0x06)
  81957. +
  81958. +/* interrupt filtering conrrol for EINT16..EINT23 */
  81959. +#define S3C2410_EINFLT0 S3C2410_GPIOREG(0x94)
  81960. +#define S3C2410_EINFLT1 S3C2410_GPIOREG(0x98)
  81961. +#define S3C2410_EINFLT2 S3C2410_GPIOREG(0x9C)
  81962. +#define S3C2410_EINFLT3 S3C2410_GPIOREG(0xA0)
  81963. +
  81964. +/* mask: 0=enable, 1=disable
  81965. + * 1 bit EINT, 4=EINT4, 23=EINT23
  81966. + * EINT0,1,2,3 are not handled here.
  81967. +*/
  81968. +#define S3C2410_EINTMASK S3C2410_GPIOREG(0xA4)
  81969. +#define S3C2410_EINTPEND S3C2410_GPIOREG(0xA8)
  81970. +
  81971. +/* GSTATUS have miscellaneous information in them
  81972. + *
  81973. + */
  81974. +
  81975. +#define S3C2410_GSTATUS0 S3C2410_GPIOREG(0x0AC)
  81976. +#define S3C2410_GSTATUS1 S3C2410_GPIOREG(0x0B0)
  81977. +#define S3C2410_GSTATUS2 S3C2410_GPIOREG(0x0B4)
  81978. +#define S3C2410_GSTATUS3 S3C2410_GPIOREG(0x0B8)
  81979. +#define S3C2410_GSTATUS4 S3C2410_GPIOREG(0x0BC)
  81980. +
  81981. +#define S3C2410_GSTATUS0_nWAIT (1<<3)
  81982. +#define S3C2410_GSTATUS0_NCON (1<<2)
  81983. +#define S3C2410_GSTATUS0_RnB (1<<1)
  81984. +#define S3C2410_GSTATUS0_nBATTFLT (1<<0)
  81985. +
  81986. +#define S3C2410_GSTATUS2_WTRESET (1<<2)
  81987. +#define S3C2410_GSTATUs2_OFFRESET (1<<1)
  81988. +#define S3C2410_GSTATUS2_PONRESET (1<<0)
  81989. +
  81990. +#endif /* ASMARM_ARCH_S3C2410_GPIO_H */
  81991. +
  81992. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-iis.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-iis.h
  81993. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-iis.h 1970-01-01 01:00:00.000000000 +0100
  81994. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-iis.h 2004-03-07 13:00:06.000000000 +0000
  81995. @@ -0,0 +1,61 @@
  81996. +/* linux/include/asm/hardware/s3c2410/iis.h
  81997. + *
  81998. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  81999. + * http://www.simtec.co.uk/products/SWLINUX/
  82000. + *
  82001. + * This program is free software; you can redistribute it and/or modify
  82002. + * it under the terms of the GNU General Public License version 2 as
  82003. + * published by the Free Software Foundation.
  82004. + *
  82005. + * S3C2410 IIS register definition
  82006. + *
  82007. + * Changelog:
  82008. + * 19-06-2003 BJD Created file
  82009. + * 26-06-2003 BJD Finished off definitions for register addresses
  82010. + */
  82011. +
  82012. +#ifndef ASMARM_ARCH_S3C2410_IIS_H
  82013. +#define ASMARM_ARCH_S3C2410_IIS_H
  82014. +
  82015. +#define S3C2410_IISCON (S3C2410_VA_IIS + 0x00)
  82016. +
  82017. +#define S3C2410_IISCON_LRINDEX (1<<8)
  82018. +#define S3C2410_IISCON_TXFIFORDY (1<<7)
  82019. +#define S3C2410_IISCON_RXFIFORDY (1<<6)
  82020. +#define S3C2410_IISCON_TXDMAEN (1<<5)
  82021. +#define S3C2410_IISCON_RXDMAEN (1<<4)
  82022. +#define S3C2410_IISCON_TXIDLE (1<<3)
  82023. +#define S3C2410_IISCON_RXIDLE (1<<2)
  82024. +#define S3C2410_IISCON_IISEN (1<<0)
  82025. +
  82026. +#define S3C2410_IISMOD (S3C2410_VA_IIS + 0x04)
  82027. +
  82028. +#define S3C2410_IISMOD_SLAVE (1<<8)
  82029. +#define S3C2410_IISMOD_NOXFER (0<<6)
  82030. +#define S3C2410_IISMOD_RXMODE (1<<6)
  82031. +#define S3C2410_IISMOD_TXMODE (2<<6)
  82032. +#define S3C2410_IISMOD_TXRXMODE (3<<6)
  82033. +#define S3C2410_IISMOD_LR_LLOW (0<<5)
  82034. +#define S3C2410_IISMOD_LR_RLOW (1<<5)
  82035. +#define S3C2410_IISMOD_IIS (0<<4)
  82036. +#define S3C2410_IISMOD_MSB (1<<4)
  82037. +#define S3C2410_IISMOD_8BIT (0<<3)
  82038. +#define S3C2410_IISMOD_16BIT (1<<3)
  82039. +#define S3C2410_IISMOD_256FS (0<<1)
  82040. +#define S3C2410_IISMOD_384FS (1<<1)
  82041. +#define S3C2410_IISMOD_16FS (0<<0)
  82042. +#define S3C2410_IISMOD_32FS (1<<0)
  82043. +#define S3C2410_IISMOD_48FS (2<<0)
  82044. +
  82045. +#define S3C2410_IISPSR (S3C2410_VA_IIS + 0x08)
  82046. +
  82047. +#define S3C2410_IISFCON (S3C2410_VA_IIS + 0x0c)
  82048. +
  82049. +#define S3C2410_IISFCON_TXDMA (1<<15)
  82050. +#define S3C2410_IISFCON_RXDMA (1<<14)
  82051. +#define S3C2410_IISFCON_TXENABLE (1<<13)
  82052. +#define S3C2410_IISFCON_RXENABLE (1<<12)
  82053. +
  82054. +#define S3C2410_IISFIFO (S3C2410_VA_IIS + 0x10)
  82055. +
  82056. +#endif /* ASMARM_ARCH_S3C2410_IIS_H */
  82057. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-irq.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-irq.h
  82058. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-irq.h 1970-01-01 01:00:00.000000000 +0100
  82059. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-irq.h 2004-03-07 12:59:08.000000000 +0000
  82060. @@ -0,0 +1,34 @@
  82061. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-irq.h
  82062. + *
  82063. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  82064. + * http://www.simtec.co.uk/products/SWLINUX/
  82065. + *
  82066. + * This program is free software; you can redistribute it and/or modify
  82067. + * it under the terms of the GNU General Public License version 2 as
  82068. + * published by the Free Software Foundation.
  82069. + *
  82070. + * Changelog:
  82071. + * 19-06-2003 BJD Created file
  82072. + */
  82073. +
  82074. +#ifndef ASMARM_ARCH_S3C2410_IRQ_H
  82075. +#define ASMARM_ARCH_S3C2410_IRQ_H
  82076. +
  82077. +/* interrupt controller */
  82078. +
  82079. +#define S3C2410_IRQREG(x) ((x) + S3C2410_VA_IRQ)
  82080. +#define S3C2410_EINTREG(x) ((x) + S3C2410_VA_GPIO)
  82081. +
  82082. +#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
  82083. +#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
  82084. +#define S3C2410_INTMSK S3C2410_IRQREG(0x008)
  82085. +#define S3C2410_PRIORITY S3C2410_IRQREG(0x00C)
  82086. +#define S3C2410_INTPND S3C2410_IRQREG(0x010)
  82087. +#define S3C2410_INTOFFSET S3C2410_IRQREG(0x014)
  82088. +#define S3C2410_SUBSRCPND S3C2410_IRQREG(0x018)
  82089. +#define S3C2410_INTSUBMSK S3C2410_IRQREG(0x01C)
  82090. +
  82091. +#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
  82092. +#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8)
  82093. +
  82094. +#endif /* ASMARM_ARCH_S3C2410_IRQ_H */
  82095. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-lcd.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-lcd.h
  82096. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-lcd.h 1970-01-01 01:00:00.000000000 +0100
  82097. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-lcd.h 2004-03-07 13:05:04.000000000 +0000
  82098. @@ -0,0 +1,107 @@
  82099. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-lcd.h
  82100. + *
  82101. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  82102. + * http://www.simtec.co.uk/products/SWLINUX/
  82103. + *
  82104. + * This program is free software; you can redistribute it and/or modify
  82105. + * it under the terms of the GNU General Public License version 2 as
  82106. + * published by the Free Software Foundation.
  82107. + *
  82108. + *
  82109. + *
  82110. + * Changelog:
  82111. + * 12-06-2003 BJD Created file
  82112. + * 26-06-2003 BJD Updated LCDCON register definitions
  82113. +*/
  82114. +
  82115. +#ifndef ASMARM_ARCH_S3C2410_LCD_H
  82116. +#define ASMARM_ARCH_S3C2410_LCD_H
  82117. +
  82118. +#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
  82119. +
  82120. +/* LCD control registers */
  82121. +#define S3C2410_LCDCON1 S3C2410_LCDREG(0x00)
  82122. +#define S3C2410_LCDCON2 S3C2410_LCDREG(0x04)
  82123. +#define S3C2410_LCDCON3 S3C2410_LCDREG(0x08)
  82124. +#define S3C2410_LCDCON4 S3C2410_LCDREG(0x0C)
  82125. +#define S3C2410_LCDCON5 S3C2410_LCDREG(0x10)
  82126. +
  82127. +#define S3C2410_LCDCON1_CLKVAL(x) ((x) << 8)
  82128. +#define S3C2410_LCDCON1_MMODE (1<<7)
  82129. +#define S3C2410_LCDCON1_DSCAN4 (0<<5)
  82130. +#define S3C2410_LCDCON1_STN4 (1<<5)
  82131. +#define S3C2410_LCDCON1_STN8 (2<<5)
  82132. +#define S3C2410_LCDCON1_TFT (3<<5)
  82133. +
  82134. +#define S3C2410_LCDCON1_STN1BPP (0<<1)
  82135. +#define S3C2410_LCDCON1_STN2GREY (1<<1)
  82136. +#define S3C2410_LCDCON1_STN4GREY (2<<1)
  82137. +#define S3C2410_LCDCON1_STN8BPP (3<<1)
  82138. +#define S3C2410_LCDCON1_STN12BPP (4<<1)
  82139. +
  82140. +#define S3C2410_LCDCON1_TFT1BPP (8<<1)
  82141. +#define S3C2410_LCDCON1_TFT2BPP (9<<1)
  82142. +#define S3C2410_LCDCON1_TFT4BPP (10<<1)
  82143. +#define S3C2410_LCDCON1_TFT8BPP (11<<1)
  82144. +#define S3C2410_LCDCON1_TFT16BPP (12<<1)
  82145. +#define S3C2410_LCDCON1_TFT24BPP (13<<1)
  82146. +
  82147. +#define S3C2410_LCDCON1_ENVDI (1)
  82148. +
  82149. +#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
  82150. +#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
  82151. +#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
  82152. +#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)
  82153. +
  82154. +#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
  82155. +#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
  82156. +#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
  82157. +#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
  82158. +#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
  82159. +
  82160. +#define S3C2410_LCDCON4_MVAL(x) ((x) << 8)
  82161. +#define S3C2410_LCDCON4_HSPW(x) ((x) << 0)
  82162. +#define S3C2410_LCDCON4_WLH(x) ((x) << 0)
  82163. +
  82164. +#define S3C2410_LCDCON5_BPP24BL (1<<12)
  82165. +#define S3C2410_LCDCON5_FRM565 (1<<11)
  82166. +#define S3C2410_LCDCON5_INVVCLK (1<<10)
  82167. +#define S3C2410_LCDCON5_INVVLINE (1<<9)
  82168. +#define S3C2410_LCDCON5_INVVFRAME (1<<8)
  82169. +#define S3C2410_LCDCON5_INVVD (1<<7)
  82170. +#define S3C2410_LCDCON5_INVVSYNC (1<<8)
  82171. +#define S3C2410_LCDCON5_INVHSYNC (1<<9)
  82172. +#define S3C2410_LCDCON5_INVVDEN (1<<6)
  82173. +#define S3C2410_LCDCON5_INVPWREN (1<<5)
  82174. +#define S3C2410_LCDCON5_INVLEND (1<<4)
  82175. +#define S3C2410_LCDCON5_PWREN (1<<3)
  82176. +#define S3C2410_LCDCON5_ENLEND (1<<2)
  82177. +#define S3C2410_LCDCON5_BSWP (1<<1)
  82178. +#define S3C2410_LCDCON5_HWSWP (1<<0)
  82179. +
  82180. +/* framebuffer start addressed */
  82181. +#define S3C2410_LCDSADDR1 S3C2410_LCDREG(0x14)
  82182. +#define S3C2410_LCDSADDR2 S3C2410_LCDREG(0x18)
  82183. +#define S3C2410_LCDSADDR3 S3C2410_LCDREG(0x1C)
  82184. +
  82185. +/* colour lookup and miscellaneous controls */
  82186. +
  82187. +#define S3C2410_REDLUT S3C2410_LCDREG(0x20)
  82188. +#define S3C2410_GREENLUT S3C2410_LCDREG(0x24)
  82189. +#define S3C2410_BLUELUT S3C2410_LCDREG(0x28)
  82190. +
  82191. +#define S3C2410_DITHMODE S3C2410_LCDREG(0x4C)
  82192. +#define S3C2410_TPAL S3C2410_LCDREG(0x50)
  82193. +
  82194. +/* interrupt info */
  82195. +#define S3C2410_LCDINTPND S3C2410_LCDREG(0x54)
  82196. +#define S3C2410_LCDSRCPND S3C2410_LCDREG(0x58)
  82197. +#define S3C2410_LCDINTMSK S3C2410_LCDREG(0x5C)
  82198. +#define S3C2410_LPCSEL S3C2410_LCDREG(0x60)
  82199. +
  82200. +#define S3C2410_TFTPAL(x) S3C2410_LCDREG((0x400 + (x)*4))
  82201. +
  82202. +#endif /* ASMARM_ARCH_S3C2410_LCD_H */
  82203. +
  82204. +
  82205. +
  82206. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-rtc.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-rtc.h
  82207. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-rtc.h 1970-01-01 01:00:00.000000000 +0100
  82208. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-rtc.h 2004-03-07 12:56:48.000000000 +0000
  82209. @@ -0,0 +1,61 @@
  82210. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-rtc.h
  82211. + *
  82212. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  82213. + * http://www.simtec.co.uk/products/SWLINUX/
  82214. + *
  82215. + * This program is free software; you can redistribute it and/or modify
  82216. + * it under the terms of the GNU General Public License version 2 as
  82217. + * published by the Free Software Foundation.
  82218. + *
  82219. + * S3C2410 Timer configuration
  82220. + *
  82221. + * Changelog:
  82222. + * 05-06-2003 BJD Created file
  82223. + */
  82224. +
  82225. +#ifndef ASMARM_ARCH_S3C2410_RTC_H
  82226. +#define ASMARM_ARCH_S3C2410_RTC_H
  82227. +
  82228. +#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
  82229. +
  82230. +#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
  82231. +#define S3C2410_RTCCON_RTCEN (1<<0)
  82232. +#define S3C2410_RTCCON_CLKRST (1<<3)
  82233. +
  82234. +#define S3C2410_TICNT S3C2410_RTCREG(0x44)
  82235. +#define S3C2410_TICNT_ENABLE (1<<7)
  82236. +
  82237. +#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
  82238. +#define S3C2410_RTCALM_ALMEN (1<<6)
  82239. +#define S3C2410_RTCALM_YEAREN (1<<5)
  82240. +#define S3C2410_RTCALM_MONEN (1<<4)
  82241. +#define S3C2410_RTCALM_DAYEN (1<<3)
  82242. +#define S3C2410_RTCALM_HOUREN (1<<2)
  82243. +#define S3C2410_RTCALM_MINEN (1<<1)
  82244. +#define S3C2410_RTCALM_SECEN (1<<0)
  82245. +
  82246. +#define S3C2410_RTCALM_ALL \
  82247. + S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\
  82248. + S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\
  82249. + S3C2410_RTCALM_SECEN
  82250. +
  82251. +
  82252. +#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
  82253. +#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
  82254. +#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
  82255. +
  82256. +#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
  82257. +#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
  82258. +#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
  82259. +
  82260. +#define S3C2410_RTCRST S3C2410_RTCREG(0x6c)
  82261. +
  82262. +#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
  82263. +#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
  82264. +#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
  82265. +#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
  82266. +#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
  82267. +#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
  82268. +#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
  82269. +
  82270. +#endif /* ASMARM_ARCH_S3C2410_RTC_H */
  82271. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-serial.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-serial.h
  82272. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-serial.h 1970-01-01 01:00:00.000000000 +0100
  82273. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-serial.h 2004-03-07 12:55:58.000000000 +0000
  82274. @@ -0,0 +1,98 @@
  82275. +/*
  82276. + * linux/include/asm-arm/arch-s3c2410/S3C2410-serial.h
  82277. + *
  82278. + * Internal header file for Samsung S3C2410 serial ports (UART0-2)
  82279. + *
  82280. + * Copyright (C) 2002 Shane Nay (shane@minirl.com)
  82281. + *
  82282. + * Additional defines, (c) 2003 Simtec Electronics (linux@simtec.co.uk)
  82283. + *
  82284. + * Adapted from:
  82285. + *
  82286. + * Internal header file for MX1ADS serial ports (UART1 & 2)
  82287. + *
  82288. + * Copyright (C) 2002 Shane Nay (shane@minirl.com)
  82289. + *
  82290. + * This program is free software; you can redistribute it and/or modify
  82291. + * it under the terms of the GNU General Public License as published by
  82292. + * the Free Software Foundation; either version 2 of the License, or
  82293. + * (at your option) any later version.
  82294. + *
  82295. + * This program is distributed in the hope that it will be useful,
  82296. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  82297. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  82298. + * GNU General Public License for more details.
  82299. + *
  82300. + * You should have received a copy of the GNU General Public License
  82301. + * along with this program; if not, write to the Free Software
  82302. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  82303. + */
  82304. +
  82305. +#ifndef ASMARM_ARCH_S3C2410_SERIAL_H
  82306. +#define ASMARM_ARCH_S3C2410_SERIAL_H
  82307. +
  82308. +#define S3C2410_UARTRXH0_OFF (0x24)
  82309. +#define S3C2410_UARTTXH0_OFF (0x20)
  82310. +#define S3C2410_UARTLCON_OFF (0x00)
  82311. +#define S3C2410_UARTCON_OFF (0x04)
  82312. +#define S3C2410_UARTFCON_OFF (0x08)
  82313. +#define S3C2410_UARTMCON_OFF (0x0C)
  82314. +#define S3C2410_UARTBRDIV_OFF (0x28)
  82315. +#define S3C2410_UARTTRSTAT_OFF (0x10)
  82316. +#define S3C2410_UARTERSTAT_OFF (0x14)
  82317. +#define S3C2410_UARTFSTAT_OFF (0x18)
  82318. +#define S3C2410_UARTMSTAT_OFF (0x1C)
  82319. +
  82320. +
  82321. +#define S3C2410_UART1_OFF (0x4000)
  82322. +#define S3C2410_UART2_OFF (0x8000)
  82323. +
  82324. +#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
  82325. +
  82326. +#define S3C2410_LCON_CS5 (0x0)
  82327. +#define S3C2410_LCON_CS6 (0x1)
  82328. +#define S3C2410_LCON_CS7 (0x2)
  82329. +#define S3C2410_LCON_CS8 (0x3)
  82330. +
  82331. +#define S3C2410_LCON_PNONE (0x0)
  82332. +#define S3C2410_LCON_PEVEN ((0x5)<<3)
  82333. +#define S3C2410_LCON_PODD ((0x4)<<3)
  82334. +
  82335. +#define S3C2410_UMCON_AFC (0x10)
  82336. +#define S3C2410_UMCON_RTS (0x1)
  82337. +
  82338. +#define S3C2410_UMSTAT_CTS (0x1)
  82339. +
  82340. +#define S3C2410_UCON_SBREAK (1<<4)
  82341. +
  82342. +#define S3C2410_UCON_TXILEVEL (1<<9)
  82343. +#define S3C2410_UCON_RXILEVEL (1<<8)
  82344. +#define S3C2410_UCON_TXIRQMODE (1<<2)
  82345. +#define S3C2410_UCON_RXIRQMODE (1<<0)
  82346. +#define S3C2410_UCON_RXFIFO_TOI (1<<7)
  82347. +
  82348. +#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL \
  82349. + | S3C2410_UCON_TXIRQMODE | S3C2410_UCON_RXIRQMODE \
  82350. + | S3C2410_UCON_RXFIFO_TOI)
  82351. +
  82352. +#define S3C2410_UFCON_FIFOMODE (1<<0)
  82353. +#define S3C2410_UFCON_TXTRIG0 (0<<6)
  82354. +#define S3C2410_UFCON_RXTRIG8 (1<<4)
  82355. +#define S3C2410_UFCON_RXTRIG12 (2<<4)
  82356. +
  82357. +#define S3C2410_UFCON_RESETBOTH (3<<1)
  82358. +
  82359. +#define S3C2410_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | S3C2410_UFCON_TXTRIG0 \
  82360. + | S3C2410_UFCON_RXTRIG8 )
  82361. +
  82362. +#define S3C2410_UFSTAT_TXFULL (1<<9)
  82363. +#define S3C2410_UFSTAT_RXFULL (1<<8)
  82364. +#define S3C2410_UFSTAT_TXMASK (15<<4)
  82365. +#define S3C2410_UFSTAT_TXSHIFT (4)
  82366. +#define S3C2410_UFSTAT_RXMASK (15<<0)
  82367. +#define S3C2410_UFSTAT_RXSHIFT (0)
  82368. +
  82369. +#define S3C2410_UTRSTAT_TXFE (1<<1)
  82370. +#define S3C2410_UTRSTAT_RXDR (1<<0)
  82371. +
  82372. +#endif /* ASMARM_ARCH_S3C2410_SERIAL_H */
  82373. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-timer.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-timer.h
  82374. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-timer.h 1970-01-01 01:00:00.000000000 +0100
  82375. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-timer.h 2004-03-07 12:55:07.000000000 +0000
  82376. @@ -0,0 +1,81 @@
  82377. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-timer.h
  82378. + *
  82379. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  82380. + * http://www.simtec.co.uk/products/SWLINUX/
  82381. + *
  82382. + * This program is free software; you can redistribute it and/or modify
  82383. + * it under the terms of the GNU General Public License version 2 as
  82384. + * published by the Free Software Foundation.
  82385. + *
  82386. + * S3C2410 Timer configuration
  82387. + *
  82388. + * Changelog:
  82389. + * 05-06-2003 BJD Created file
  82390. + * 26-06-2003 BJD Added more timer definitions to mux / control
  82391. + */
  82392. +
  82393. +#ifndef ASMARM_ARCH_S3C2410_TIMER_H
  82394. +#define ASMARM_ARCH_S3C2410_TIMER_H
  82395. +
  82396. +#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
  82397. +#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
  82398. +
  82399. +#define S3C2410_TCFG0 S3C2410_TIMERREG(0x00)
  82400. +#define S3C2410_TCFG1 S3C2410_TIMERREG(0x04)
  82401. +#define S3C2410_TCON S3C2410_TIMERREG(0x08)
  82402. +
  82403. +
  82404. +#define S3C2410_TCFG1_MUX4_TCLK1 (4<<16)
  82405. +#define S3C2410_TCFG1_MUX4_MASK (15<<16)
  82406. +
  82407. +#define S3C2410_TCFG1_MUX3_TCLK1 (4<<12)
  82408. +#define S3C2410_TCFG1_MUX3_MASK (15<<12)
  82409. +
  82410. +#define S3C2410_TCFG1_MUX2_TCLK1 (4<<8)
  82411. +#define S3C2410_TCFG1_MUX2_MASK (15<<8)
  82412. +
  82413. +#define S3C2410_TCFG1_MUX1_TCLK0 (4<<4)
  82414. +#define S3C2410_TCFG1_MUX1_MASK (15<<4)
  82415. +
  82416. +#define S3C2410_TCFG1_MUX0_TCLK0 (4<<0)
  82417. +#define S3C2410_TCFG1_MUX0_MASK (15<<0)
  82418. +
  82419. +/* for each timer, we have an count buffer, an compare buffer and an
  82420. + * observation buffer
  82421. + */
  82422. +
  82423. +/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
  82424. +
  82425. +#define S3C2410_TCNTB(tmr) S3C2410_TIMERREG2(tmr, 0x00)
  82426. +#define S3C2410_TCMPB(tmr) S3C2410_TIMERREG2(tmr, 0x04)
  82427. +#define S3C2410_TCNTO(tmr) S3C2410_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
  82428. +
  82429. +#define S3C2410_TCON_T4RELOAD (1<<22)
  82430. +#define S3C2410_TCON_T4MANUALUPD (1<<21)
  82431. +#define S3C2410_TCON_T4START (1<<20)
  82432. +
  82433. +#define S3C2410_TCON_T3RELOAD (1<<19)
  82434. +#define S3C2410_TCON_T3INVERT (1<<18)
  82435. +#define S3C2410_TCON_T3MANUALUPD (1<<17)
  82436. +#define S3C2410_TCON_T3START (1<<16)
  82437. +
  82438. +#define S3C2410_TCON_T2RELOAD (1<<15)
  82439. +#define S3C2410_TCON_T2INVERT (1<<14)
  82440. +#define S3C2410_TCON_T2MANUALUPD (1<<13)
  82441. +#define S3C2410_TCON_T2START (1<<12)
  82442. +
  82443. +#define S3C2410_TCON_T1RELOAD (1<<11)
  82444. +#define S3C2410_TCON_T1INVERT (1<<10)
  82445. +#define S3C2410_TCON_T1MANUALUPD (1<<9)
  82446. +#define S3C2410_TCON_T1START (1<<8)
  82447. +
  82448. +#define S3C2410_TCON_T0DEADZONE (1<<4)
  82449. +#define S3C2410_TCON_T0RELOAD (1<<3)
  82450. +#define S3C2410_TCON_T0INVERT (1<<2)
  82451. +#define S3C2410_TCON_T0MANUALUPD (1<<1)
  82452. +#define S3C2410_TCON_T0START (1<<0)
  82453. +
  82454. +#endif /* ASMARM_ARCH_S3C2410_TIMER_H */
  82455. +
  82456. +
  82457. +
  82458. diff -urN linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h
  82459. --- linux-2.4.26/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h 1970-01-01 01:00:00.000000000 +0100
  82460. +++ linux-2.4.26-vrs1/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h 2004-03-07 12:37:53.000000000 +0000
  82461. @@ -0,0 +1,40 @@
  82462. +/* linux/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h
  82463. + *
  82464. + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  82465. + * http://www.simtec.co.uk/products/SWLINUX/
  82466. + *
  82467. + * This program is free software; you can redistribute it and/or modify
  82468. + * it under the terms of the GNU General Public License version 2 as
  82469. + * published by the Free Software Foundation.
  82470. + *
  82471. + * S3C2410 Watchdog timer control
  82472. + *
  82473. + * Changelog:
  82474. + * 21-06-2003 BJD Created file
  82475. +*/
  82476. +
  82477. +#ifndef ASMARM_ARCH_S3C2410_WATCHDOG_H
  82478. +#define ASMARM_ARCH_S3C2410_WATCHDOG_H
  82479. +
  82480. +#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
  82481. +
  82482. +#define S3C2410_WTCON S3C2410_WDOGREG(0x00)
  82483. +#define S3C2410_WTDAT S3C2410_WDOGREG(0x04)
  82484. +#define S3C2410_WTCNT S3C2410_WDOGREG(0x08)
  82485. +
  82486. +/* the watchdog can either generate a reset pulse, or an interrupt. */
  82487. +
  82488. +#define S3C2410_WTCON_RSTEN (0x01)
  82489. +#define S3C2410_WTCON_INTEN (1<<2)
  82490. +#define S3C2410_WTCON_ENABLE (1<<5)
  82491. +
  82492. +#define S3C2410_WTCON_DIV16 (0<<3)
  82493. +#define S3C2410_WTCON_DIV32 (1<<3)
  82494. +#define S3C2410_WTCON_DIV64 (2<<3)
  82495. +#define S3C2410_WTCON_DIV128 (3<<3)
  82496. +
  82497. +#define S3C2410_WTCON_PRESCALE(x) ((x) << 8)
  82498. +
  82499. +#endif /* ASMARM_ARCH_S3C2410_WATCHDOG_H */
  82500. +
  82501. +
  82502. diff -urN linux-2.4.26/include/asm-arm/bugs.h linux-2.4.26-vrs1/include/asm-arm/bugs.h
  82503. --- linux-2.4.26/include/asm-arm/bugs.h 2000-09-18 23:15:23.000000000 +0100
  82504. +++ linux-2.4.26-vrs1/include/asm-arm/bugs.h 2004-02-23 01:01:28.000000000 +0000
  82505. @@ -10,8 +10,17 @@
  82506. #ifndef __ASM_BUGS_H
  82507. #define __ASM_BUGS_H
  82508. +#include <linux/config.h>
  82509. #include <asm/proc-fns.h>
  82510. -#define check_bugs() cpu_check_bugs()
  82511. +extern void check_writebuffer_bugs(void);
  82512. +
  82513. +static inline void check_bugs(void)
  82514. +{
  82515. +#ifdef CONFIG_CPU_32
  82516. + check_writebuffer_bugs();
  82517. +#endif
  82518. + cpu_check_bugs();
  82519. +}
  82520. #endif
  82521. diff -urN linux-2.4.26/include/asm-arm/div64.h linux-2.4.26-vrs1/include/asm-arm/div64.h
  82522. --- linux-2.4.26/include/asm-arm/div64.h 2000-01-13 21:30:31.000000000 +0000
  82523. +++ linux-2.4.26-vrs1/include/asm-arm/div64.h 2004-01-14 21:32:29.000000000 +0000
  82524. @@ -4,9 +4,13 @@
  82525. /* We're not 64-bit, but... */
  82526. #define do_div(n,base) \
  82527. ({ \
  82528. - int __res; \
  82529. - __res = ((unsigned long)n) % (unsigned int)base; \
  82530. - n = ((unsigned long)n) / (unsigned int)base; \
  82531. + register int __res asm("r2") = base; \
  82532. + register unsigned long long __n asm("r0") = n; \
  82533. + asm("bl do_div64" \
  82534. + : "=r" (__n), "=r" (__res) \
  82535. + : "0" (__n), "1" (__res) \
  82536. + : "r3", "ip", "lr", "cc"); \
  82537. + n = __n; \
  82538. __res; \
  82539. })
  82540. diff -urN linux-2.4.26/include/asm-arm/elf.h linux-2.4.26-vrs1/include/asm-arm/elf.h
  82541. --- linux-2.4.26/include/asm-arm/elf.h 2003-11-28 18:26:21.000000000 +0000
  82542. +++ linux-2.4.26-vrs1/include/asm-arm/elf.h 2004-04-19 20:37:56.000000000 +0100
  82543. @@ -45,8 +45,8 @@
  82544. #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
  82545. -/* When the program starts, a1 contains a pointer to a function to be
  82546. - registered with atexit, as per the SVR4 ABI. A value of 0 means we
  82547. +/* When the program starts, a1 contains a pointer to a function to be
  82548. + registered with atexit, as per the SVR4 ABI. A value of 0 means we
  82549. have no such handler. */
  82550. #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0
  82551. diff -urN linux-2.4.26/include/asm-arm/mach/dma.h linux-2.4.26-vrs1/include/asm-arm/mach/dma.h
  82552. --- linux-2.4.26/include/asm-arm/mach/dma.h 2003-08-25 12:44:43.000000000 +0100
  82553. +++ linux-2.4.26-vrs1/include/asm-arm/mach/dma.h 2004-03-04 21:39:05.000000000 +0000
  82554. @@ -41,6 +41,7 @@
  82555. unsigned int dma_base; /* Controller base address */
  82556. int dma_irq; /* Controller IRQ */
  82557. struct scatterlist cur_sg; /* Current controller buffer */
  82558. + unsigned int state; /* RiscPC DMA status */
  82559. struct dma_ops *d_ops;
  82560. };
  82561. diff -urN linux-2.4.26/include/asm-arm/mach/serial_at91rm9200.h linux-2.4.26-vrs1/include/asm-arm/mach/serial_at91rm9200.h
  82562. --- linux-2.4.26/include/asm-arm/mach/serial_at91rm9200.h 2003-08-25 12:44:43.000000000 +0100
  82563. +++ linux-2.4.26-vrs1/include/asm-arm/mach/serial_at91rm9200.h 2004-03-04 21:52:13.000000000 +0000
  82564. @@ -10,7 +10,6 @@
  82565. #include <linux/config.h>
  82566. struct uart_port;
  82567. -struct uart_info;
  82568. /*
  82569. * This is a temporary structure for registering these
  82570. @@ -22,11 +21,11 @@
  82571. void (*enable_ms)(struct uart_port *);
  82572. void (*pm)(struct uart_port *, u_int, u_int);
  82573. int (*set_wake)(struct uart_port *, u_int);
  82574. - int (*open)(struct uart_port *, struct uart_info *);
  82575. - void (*close)(struct uart_port *, struct uart_info *);
  82576. + int (*open)(struct uart_port *);
  82577. + void (*close)(struct uart_port *);
  82578. };
  82579. -#if defined(CONFIG_SERIAL_AT91RM9200)
  82580. +#if defined(CONFIG_SERIAL_AT91)
  82581. void at91rm9200_register_uart_fns(struct at91rm9200_port_fns *fns);
  82582. void at91rm9200_register_uart(int idx, int port);
  82583. #else
  82584. diff -urN linux-2.4.26/include/asm-arm/pci.h linux-2.4.26-vrs1/include/asm-arm/pci.h
  82585. --- linux-2.4.26/include/asm-arm/pci.h 2003-11-28 18:26:21.000000000 +0000
  82586. +++ linux-2.4.26-vrs1/include/asm-arm/pci.h 2004-04-19 20:38:16.000000000 +0100
  82587. @@ -113,6 +113,28 @@
  82588. /* nothing to do */
  82589. }
  82590. +/*
  82591. + * pci_{map,unmap}_page maps a kernel page to a dma_addr_t. identical
  82592. + * to pci_map_single, but takes a struct page instead of a virtual address
  82593. + */
  82594. +static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
  82595. + unsigned long offset, size_t size,
  82596. + int direction)
  82597. +{
  82598. + void *start;
  82599. + BUG_ON(direction == PCI_DMA_NONE);
  82600. + start = page_address(page) + offset;
  82601. + consistent_sync(start, size, direction);
  82602. + return virt_to_bus(start);
  82603. +}
  82604. +
  82605. +static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
  82606. + size_t size, int direction)
  82607. +{
  82608. + BUG_ON(direction == PCI_DMA_NONE);
  82609. + /* Nothing to do */
  82610. +}
  82611. +
  82612. /* Whether pci_unmap_{single,page} is a nop depends upon the
  82613. * configuration.
  82614. */
  82615. diff -urN linux-2.4.26/include/asm-arm/proc-armv/processor.h linux-2.4.26-vrs1/include/asm-arm/proc-armv/processor.h
  82616. --- linux-2.4.26/include/asm-arm/proc-armv/processor.h 2003-08-25 12:44:43.000000000 +0100
  82617. +++ linux-2.4.26-vrs1/include/asm-arm/proc-armv/processor.h 2004-02-22 23:56:12.000000000 +0000
  82618. @@ -54,7 +54,9 @@
  82619. regs->ARM_cpsr = USR_MODE; \
  82620. else \
  82621. regs->ARM_cpsr = USR26_MODE; \
  82622. - regs->ARM_pc = pc; /* pc */ \
  82623. + if (elf_hwcap & HWCAP_THUMB && pc & 1) \
  82624. + regs->ARM_cpsr |= PSR_T_BIT; \
  82625. + regs->ARM_pc = pc & ~1; /* pc */ \
  82626. regs->ARM_sp = sp; /* sp */ \
  82627. regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
  82628. regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
  82629. diff -urN linux-2.4.26/include/asm-arm/proc-armv/ptrace.h linux-2.4.26-vrs1/include/asm-arm/proc-armv/ptrace.h
  82630. --- linux-2.4.26/include/asm-arm/proc-armv/ptrace.h 2000-11-28 01:07:59.000000000 +0000
  82631. +++ linux-2.4.26-vrs1/include/asm-arm/proc-armv/ptrace.h 2004-01-14 21:32:29.000000000 +0000
  82632. @@ -33,6 +33,16 @@
  82633. #define CC_N_BIT (1 << 31)
  82634. #define PCMASK 0
  82635. +/* 2.5 versions */
  82636. +#define PSR_T_BIT 0x00000020
  82637. +#define PSR_F_BIT 0x00000040
  82638. +#define PSR_I_BIT 0x00000080
  82639. +#define PSR_J_BIT 0x01000000
  82640. +#define PSR_V_BIT 0x10000000
  82641. +#define PSR_C_BIT 0x20000000
  82642. +#define PSR_Z_BIT 0x40000000
  82643. +#define PSR_N_BIT 0x80000000
  82644. +
  82645. #ifndef __ASSEMBLY__
  82646. /* this struct defines the way the registers are stored on the
  82647. diff -urN linux-2.4.26/include/asm-arm/proc-armv/uaccess.h linux-2.4.26-vrs1/include/asm-arm/proc-armv/uaccess.h
  82648. --- linux-2.4.26/include/asm-arm/proc-armv/uaccess.h 2001-10-25 21:53:55.000000000 +0100
  82649. +++ linux-2.4.26-vrs1/include/asm-arm/proc-armv/uaccess.h 2004-04-19 20:37:56.000000000 +0100
  82650. @@ -12,12 +12,11 @@
  82651. * Note that this is actually 0x1,0000,0000
  82652. */
  82653. #define KERNEL_DS 0x00000000
  82654. -#define USER_DS PAGE_OFFSET
  82655. +#define USER_DS TASK_SIZE
  82656. static inline void set_fs (mm_segment_t fs)
  82657. {
  82658. current->addr_limit = fs;
  82659. -
  82660. modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
  82661. }
  82662. @@ -38,7 +37,7 @@
  82663. : "cc"); \
  82664. (flag == 0); })
  82665. -#define __put_user_asm_byte(x,addr,err) \
  82666. +#define __put_user_asm_byte(x,__pu_addr,err) \
  82667. __asm__ __volatile__( \
  82668. "1: strbt %1,[%2],#0\n" \
  82669. "2:\n" \
  82670. @@ -51,18 +50,18 @@
  82671. " .align 3\n" \
  82672. " .long 1b, 3b\n" \
  82673. " .previous" \
  82674. - : "=r" (err) \
  82675. - : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
  82676. + : "+r" (err) \
  82677. + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
  82678. + : "cc")
  82679. -#define __put_user_asm_half(x,addr,err) \
  82680. +#define __put_user_asm_half(x,__pu_addr,err) \
  82681. ({ \
  82682. unsigned long __temp = (unsigned long)(x); \
  82683. - unsigned long __ptr = (unsigned long)(addr); \
  82684. - __put_user_asm_byte(__temp, __ptr, err); \
  82685. - __put_user_asm_byte(__temp >> 8, __ptr + 1, err); \
  82686. + __put_user_asm_byte(__temp, __pu_addr, err); \
  82687. + __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
  82688. })
  82689. -#define __put_user_asm_word(x,addr,err) \
  82690. +#define __put_user_asm_word(x,__pu_addr,err) \
  82691. __asm__ __volatile__( \
  82692. "1: strt %1,[%2],#0\n" \
  82693. "2:\n" \
  82694. @@ -75,8 +74,28 @@
  82695. " .align 3\n" \
  82696. " .long 1b, 3b\n" \
  82697. " .previous" \
  82698. - : "=r" (err) \
  82699. - : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
  82700. + : "+r" (err) \
  82701. + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
  82702. + : "cc")
  82703. +
  82704. +#define __put_user_asm_dword(x,__pu_addr,err) \
  82705. + __asm__ __volatile__( \
  82706. + "1: strt %R2, [%1], #4\n" \
  82707. + "2: strt %Q2, [%1], #0\n" \
  82708. + "3:\n" \
  82709. + " .section .fixup,\"ax\"\n" \
  82710. + " .align 2\n" \
  82711. + "4: mov %0, %3\n" \
  82712. + " b 3b\n" \
  82713. + " .previous\n" \
  82714. + " .section __ex_table,\"a\"\n" \
  82715. + " .align 3\n" \
  82716. + " .long 1b, 4b\n" \
  82717. + " .long 2b, 4b\n" \
  82718. + " .previous" \
  82719. + : "+r" (err), "+r" (__pu_addr) \
  82720. + : "r" (x), "i" (-EFAULT) \
  82721. + : "cc")
  82722. #define __get_user_asm_byte(x,addr,err) \
  82723. __asm__ __volatile__( \
  82724. @@ -92,18 +111,18 @@
  82725. " .align 3\n" \
  82726. " .long 1b, 3b\n" \
  82727. " .previous" \
  82728. - : "=r" (err), "=&r" (x) \
  82729. - : "r" (addr), "i" (-EFAULT), "0" (err))
  82730. + : "+r" (err), "=&r" (x) \
  82731. + : "r" (addr), "i" (-EFAULT) \
  82732. + : "cc")
  82733. -#define __get_user_asm_half(x,addr,err) \
  82734. +#define __get_user_asm_half(x,__gu_addr,err) \
  82735. ({ \
  82736. - unsigned long __b1, __b2, __ptr = (unsigned long)addr; \
  82737. - __get_user_asm_byte(__b1, __ptr, err); \
  82738. - __get_user_asm_byte(__b2, __ptr + 1, err); \
  82739. + unsigned long __b1, __b2; \
  82740. + __get_user_asm_byte(__b1, __gu_addr, err); \
  82741. + __get_user_asm_byte(__b2, __gu_addr + 1, err); \
  82742. (x) = __b1 | (__b2 << 8); \
  82743. })
  82744. -
  82745. #define __get_user_asm_word(x,addr,err) \
  82746. __asm__ __volatile__( \
  82747. "1: ldrt %1,[%2],#0\n" \
  82748. @@ -118,8 +137,9 @@
  82749. " .align 3\n" \
  82750. " .long 1b, 3b\n" \
  82751. " .previous" \
  82752. - : "=r" (err), "=&r" (x) \
  82753. - : "r" (addr), "i" (-EFAULT), "0" (err))
  82754. + : "+r" (err), "=&r" (x) \
  82755. + : "r" (addr), "i" (-EFAULT) \
  82756. + : "cc")
  82757. extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
  82758. #define __do_copy_from_user(to,from,n) \
  82759. diff -urN linux-2.4.26/include/asm-arm/proc-fns.h linux-2.4.26-vrs1/include/asm-arm/proc-fns.h
  82760. --- linux-2.4.26/include/asm-arm/proc-fns.h 2003-08-25 12:44:43.000000000 +0100
  82761. +++ linux-2.4.26-vrs1/include/asm-arm/proc-fns.h 2004-04-19 20:37:56.000000000 +0100
  82762. @@ -76,6 +76,30 @@
  82763. # define CPU_NAME arm926
  82764. # endif
  82765. # endif
  82766. +# ifdef CONFIG_CPU_ARM1020
  82767. +# ifdef CPU_NAME
  82768. +# undef MULTI_CPU
  82769. +# define MULTI_CPU
  82770. +# else
  82771. +# define CPU_NAME arm1020
  82772. +# endif
  82773. +# endif
  82774. +# ifdef CONFIG_CPU_ARM1020E
  82775. +# ifdef CPU_NAME
  82776. +# undef MULTI_CPU
  82777. +# define MULTI_CPU
  82778. +# else
  82779. +# define CPU_NAME arm1020E
  82780. +# endif
  82781. +# endif
  82782. +# ifdef CONFIG_CPU_ARM1022
  82783. +# ifdef CPU_NAME
  82784. +# undef MULTI_CPU
  82785. +# define MULTI_CPU
  82786. +# else
  82787. +# define CPU_NAME arm1022
  82788. +# endif
  82789. +# endif
  82790. # ifdef CONFIG_CPU_ARM1026
  82791. # ifdef CPU_NAME
  82792. # undef MULTI_CPU
  82793. diff -urN linux-2.4.26/include/asm-arm/processor.h linux-2.4.26-vrs1/include/asm-arm/processor.h
  82794. --- linux-2.4.26/include/asm-arm/processor.h 2003-08-25 12:44:43.000000000 +0100
  82795. +++ linux-2.4.26-vrs1/include/asm-arm/processor.h 2004-04-19 20:37:56.000000000 +0100
  82796. @@ -43,6 +43,7 @@
  82797. #include <asm/atomic.h>
  82798. #include <asm/ptrace.h>
  82799. #include <asm/arch/memory.h>
  82800. +#include <asm/elf.h>
  82801. #include <asm/proc/processor.h>
  82802. #include <asm/types.h>
  82803. diff -urN linux-2.4.26/include/asm-arm/system.h linux-2.4.26-vrs1/include/asm-arm/system.h
  82804. --- linux-2.4.26/include/asm-arm/system.h 2003-08-25 12:44:43.000000000 +0100
  82805. +++ linux-2.4.26-vrs1/include/asm-arm/system.h 2004-04-19 20:37:56.000000000 +0100
  82806. @@ -29,6 +29,10 @@
  82807. void die_if_kernel(const char *str, struct pt_regs *regs, int err);
  82808. +void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
  82809. + struct pt_regs *),
  82810. + int sig, const char *name);
  82811. +
  82812. #include <asm/proc-fns.h>
  82813. #define xchg(ptr,x) \
  82814. @@ -89,6 +93,14 @@
  82815. #define sti() local_irq_enable()
  82816. #define clf() __clf()
  82817. #define stf() __stf()
  82818. +
  82819. +#define irqs_disabled() \
  82820. +({ \
  82821. + unsigned long flags; \
  82822. + local_save_flags(flags); \
  82823. + flags & PSR_I_BIT; \
  82824. +})
  82825. +
  82826. #define save_flags(x) local_save_flags(x)
  82827. #define restore_flags(x) local_irq_restore(x)
  82828. #define save_flags_cli(x) local_irq_save(x)
  82829. diff -urN linux-2.4.26/include/asm-arm/termios.h linux-2.4.26-vrs1/include/asm-arm/termios.h
  82830. --- linux-2.4.26/include/asm-arm/termios.h 2001-06-12 03:15:27.000000000 +0100
  82831. +++ linux-2.4.26-vrs1/include/asm-arm/termios.h 2004-01-14 21:32:29.000000000 +0000
  82832. @@ -47,6 +47,8 @@
  82833. #define TIOCM_OUT2 0x4000
  82834. #define TIOCM_LOOP 0x8000
  82835. +#define TIOCM_MODEM_BITS TIOCM_OUT2 /* IRDA support */
  82836. +
  82837. /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
  82838. /* line disciplines */
  82839. diff -urN linux-2.4.26/include/asm-arm/uaccess.h linux-2.4.26-vrs1/include/asm-arm/uaccess.h
  82840. --- linux-2.4.26/include/asm-arm/uaccess.h 2001-10-25 21:53:55.000000000 +0100
  82841. +++ linux-2.4.26-vrs1/include/asm-arm/uaccess.h 2004-04-19 20:37:56.000000000 +0100
  82842. @@ -74,14 +74,14 @@
  82843. __asm__ __volatile__ ("bl __get_user_" #__s \
  82844. : "=&r" (__e), "=r" (__r1) \
  82845. : "0" (__p) \
  82846. - : __i)
  82847. + : __i, "cc")
  82848. #define get_user(x,p) \
  82849. ({ \
  82850. const register typeof(*(p)) *__p asm("r0") = (p); \
  82851. register typeof(*(p)) __r1 asm("r1"); \
  82852. register int __e asm("r0"); \
  82853. - switch (sizeof(*(p))) { \
  82854. + switch (sizeof(*(__p))) { \
  82855. case 1: \
  82856. __get_user_x(__r1, __p, __e, 1, "lr"); \
  82857. break; \
  82858. @@ -100,8 +100,31 @@
  82859. __e; \
  82860. })
  82861. -#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
  82862. -#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
  82863. +#define __get_user(x,ptr) \
  82864. +({ \
  82865. + long __gu_err = 0; \
  82866. + __get_user_err((x),(ptr),__gu_err); \
  82867. + __gu_err; \
  82868. +})
  82869. +
  82870. +#define __get_user_error(x,ptr,err) \
  82871. +({ \
  82872. + __get_user_err((x),(ptr),err); \
  82873. + (void) 0; \
  82874. +})
  82875. +
  82876. +#define __get_user_err(x,ptr,err) \
  82877. +do { \
  82878. + unsigned long __gu_addr = (unsigned long)(ptr); \
  82879. + unsigned long __gu_val; \
  82880. + switch (sizeof(*(ptr))) { \
  82881. + case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
  82882. + case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
  82883. + case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \
  82884. + default: (__gu_val) = __get_user_bad(); \
  82885. + } \
  82886. + (x) = (__typeof__(*(ptr)))__gu_val; \
  82887. +} while (0)
  82888. extern int __put_user_1(void *, unsigned int);
  82889. extern int __put_user_2(void *, unsigned int);
  82890. @@ -113,22 +136,22 @@
  82891. __asm__ __volatile__ ("bl __put_user_" #__s \
  82892. : "=&r" (__e) \
  82893. : "0" (__p), "r" (__r1) \
  82894. - : __i)
  82895. + : __i, "cc")
  82896. #define put_user(x,p) \
  82897. ({ \
  82898. const register typeof(*(p)) __r1 asm("r1") = (x); \
  82899. const register typeof(*(p)) *__p asm("r0") = (p); \
  82900. register int __e asm("r0"); \
  82901. - switch (sizeof(*(p))) { \
  82902. + switch (sizeof(*(__p))) { \
  82903. case 1: \
  82904. - __put_user_x(__r1, __p, __e, 1, "r2", "lr"); \
  82905. + __put_user_x(__r1, __p, __e, 1, "ip", "lr"); \
  82906. break; \
  82907. case 2: \
  82908. - __put_user_x(__r1, __p, __e, 2, "r2", "lr"); \
  82909. + __put_user_x(__r1, __p, __e, 2, "ip", "lr"); \
  82910. break; \
  82911. case 4: \
  82912. - __put_user_x(__r1, __p, __e, 4, "r2", "lr"); \
  82913. + __put_user_x(__r1, __p, __e, 4, "ip", "lr"); \
  82914. break; \
  82915. case 8: \
  82916. __put_user_x(__r1, __p, __e, 8, "ip", "lr"); \
  82917. @@ -138,8 +161,31 @@
  82918. __e; \
  82919. })
  82920. -#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
  82921. -#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
  82922. +#define __put_user(x,ptr) \
  82923. +({ \
  82924. + long __pu_err = 0; \
  82925. + __put_user_err((x),(ptr),__pu_err); \
  82926. + __pu_err; \
  82927. +})
  82928. +
  82929. +#define __put_user_error(x,ptr,err) \
  82930. +({ \
  82931. + __put_user_err((x),(ptr),err); \
  82932. + (void) 0; \
  82933. +})
  82934. +
  82935. +#define __put_user_err(x,ptr,err) \
  82936. +do { \
  82937. + unsigned long __pu_addr = (unsigned long)(ptr); \
  82938. + __typeof__(*(ptr)) __pu_val = (x); \
  82939. + switch (sizeof(*(ptr))) { \
  82940. + case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
  82941. + case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
  82942. + case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \
  82943. + case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \
  82944. + default: __put_user_bad(); \
  82945. + } \
  82946. +} while (0)
  82947. static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
  82948. {
  82949. @@ -209,82 +255,4 @@
  82950. return res;
  82951. }
  82952. -/*
  82953. - * These are the work horses of the get/put_user functions
  82954. - */
  82955. -#if 0
  82956. -#define __get_user_check(x,ptr,size) \
  82957. -({ \
  82958. - long __gu_err = -EFAULT, __gu_val = 0; \
  82959. - const __typeof__(*(ptr)) *__gu_addr = (ptr); \
  82960. - if (access_ok(VERIFY_READ,__gu_addr,size)) { \
  82961. - __gu_err = 0; \
  82962. - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
  82963. - } \
  82964. - (x) = (__typeof__(*(ptr)))__gu_val; \
  82965. - __gu_err; \
  82966. -})
  82967. -#endif
  82968. -
  82969. -#define __get_user_nocheck(x,ptr,size) \
  82970. -({ \
  82971. - long __gu_err = 0, __gu_val; \
  82972. - __get_user_size(__gu_val,(ptr),(size),__gu_err); \
  82973. - (x) = (__typeof__(*(ptr)))__gu_val; \
  82974. - __gu_err; \
  82975. -})
  82976. -
  82977. -#define __get_user_nocheck_error(x,ptr,size,err) \
  82978. -({ \
  82979. - long __gu_val; \
  82980. - __get_user_size(__gu_val,(ptr),(size),(err)); \
  82981. - (x) = (__typeof__(*(ptr)))__gu_val; \
  82982. - (void) 0; \
  82983. -})
  82984. -
  82985. -#define __put_user_check(x,ptr,size) \
  82986. -({ \
  82987. - long __pu_err = -EFAULT; \
  82988. - __typeof__(*(ptr)) *__pu_addr = (ptr); \
  82989. - if (access_ok(VERIFY_WRITE,__pu_addr,size)) { \
  82990. - __pu_err = 0; \
  82991. - __put_user_size((x),__pu_addr,(size),__pu_err); \
  82992. - } \
  82993. - __pu_err; \
  82994. -})
  82995. -
  82996. -#define __put_user_nocheck(x,ptr,size) \
  82997. -({ \
  82998. - long __pu_err = 0; \
  82999. - __typeof__(*(ptr)) *__pu_addr = (ptr); \
  83000. - __put_user_size((x),__pu_addr,(size),__pu_err); \
  83001. - __pu_err; \
  83002. -})
  83003. -
  83004. -#define __put_user_nocheck_error(x,ptr,size,err) \
  83005. -({ \
  83006. - __put_user_size((x),(ptr),(size),err); \
  83007. - (void) 0; \
  83008. -})
  83009. -
  83010. -#define __get_user_size(x,ptr,size,retval) \
  83011. -do { \
  83012. - switch (size) { \
  83013. - case 1: __get_user_asm_byte(x,ptr,retval); break; \
  83014. - case 2: __get_user_asm_half(x,ptr,retval); break; \
  83015. - case 4: __get_user_asm_word(x,ptr,retval); break; \
  83016. - default: (x) = __get_user_bad(); \
  83017. - } \
  83018. -} while (0)
  83019. -
  83020. -#define __put_user_size(x,ptr,size,retval) \
  83021. -do { \
  83022. - switch (size) { \
  83023. - case 1: __put_user_asm_byte(x,ptr,retval); break; \
  83024. - case 2: __put_user_asm_half(x,ptr,retval); break; \
  83025. - case 4: __put_user_asm_word(x,ptr,retval); break; \
  83026. - default: __put_user_bad(); \
  83027. - } \
  83028. -} while (0)
  83029. -
  83030. #endif /* _ASMARM_UACCESS_H */
  83031. diff -urN linux-2.4.26/include/asm-arm/unistd.h linux-2.4.26-vrs1/include/asm-arm/unistd.h
  83032. --- linux-2.4.26/include/asm-arm/unistd.h 2003-08-25 12:44:43.000000000 +0100
  83033. +++ linux-2.4.26-vrs1/include/asm-arm/unistd.h 2004-03-05 15:14:07.000000000 +0000
  83034. @@ -31,7 +31,7 @@
  83035. #define __NR_write (__NR_SYSCALL_BASE+ 4)
  83036. #define __NR_open (__NR_SYSCALL_BASE+ 5)
  83037. #define __NR_close (__NR_SYSCALL_BASE+ 6)
  83038. -#define __NR_waitpid (__NR_SYSCALL_BASE+ 7)
  83039. + /* 7 was sys_waitpid */
  83040. #define __NR_creat (__NR_SYSCALL_BASE+ 8)
  83041. #define __NR_link (__NR_SYSCALL_BASE+ 9)
  83042. #define __NR_unlink (__NR_SYSCALL_BASE+ 10)
  83043. @@ -41,8 +41,8 @@
  83044. #define __NR_mknod (__NR_SYSCALL_BASE+ 14)
  83045. #define __NR_chmod (__NR_SYSCALL_BASE+ 15)
  83046. #define __NR_lchown (__NR_SYSCALL_BASE+ 16)
  83047. -#define __NR_break (__NR_SYSCALL_BASE+ 17)
  83048. -
  83049. + /* 17 was sys_break */
  83050. + /* 18 was sys_stat */
  83051. #define __NR_lseek (__NR_SYSCALL_BASE+ 19)
  83052. #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
  83053. #define __NR_mount (__NR_SYSCALL_BASE+ 21)
  83054. @@ -52,14 +52,14 @@
  83055. #define __NR_stime (__NR_SYSCALL_BASE+ 25)
  83056. #define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
  83057. #define __NR_alarm (__NR_SYSCALL_BASE+ 27)
  83058. -
  83059. + /* 28 was sys_fstat */
  83060. #define __NR_pause (__NR_SYSCALL_BASE+ 29)
  83061. #define __NR_utime (__NR_SYSCALL_BASE+ 30)
  83062. -#define __NR_stty (__NR_SYSCALL_BASE+ 31)
  83063. -#define __NR_gtty (__NR_SYSCALL_BASE+ 32)
  83064. + /* 31 was sys_stty */
  83065. + /* 32 was sys_gtty */
  83066. #define __NR_access (__NR_SYSCALL_BASE+ 33)
  83067. #define __NR_nice (__NR_SYSCALL_BASE+ 34)
  83068. -#define __NR_ftime (__NR_SYSCALL_BASE+ 35)
  83069. + /* 35 was sys_ftime */
  83070. #define __NR_sync (__NR_SYSCALL_BASE+ 36)
  83071. #define __NR_kill (__NR_SYSCALL_BASE+ 37)
  83072. #define __NR_rename (__NR_SYSCALL_BASE+ 38)
  83073. @@ -68,22 +68,23 @@
  83074. #define __NR_dup (__NR_SYSCALL_BASE+ 41)
  83075. #define __NR_pipe (__NR_SYSCALL_BASE+ 42)
  83076. #define __NR_times (__NR_SYSCALL_BASE+ 43)
  83077. -#define __NR_prof (__NR_SYSCALL_BASE+ 44)
  83078. + /* 44 was sys_prof */
  83079. #define __NR_brk (__NR_SYSCALL_BASE+ 45)
  83080. #define __NR_setgid (__NR_SYSCALL_BASE+ 46)
  83081. #define __NR_getgid (__NR_SYSCALL_BASE+ 47)
  83082. -#define __NR_signal (__NR_SYSCALL_BASE+ 48)
  83083. + /* 48 was sys_signal */
  83084. #define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
  83085. #define __NR_getegid (__NR_SYSCALL_BASE+ 50)
  83086. #define __NR_acct (__NR_SYSCALL_BASE+ 51)
  83087. #define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
  83088. -#define __NR_lock (__NR_SYSCALL_BASE+ 53)
  83089. + /* 53 was sys_lock */
  83090. #define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
  83091. #define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
  83092. -#define __NR_mpx (__NR_SYSCALL_BASE+ 56)
  83093. + /* 56 was sys_mpx */
  83094. #define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
  83095. #define __NR_ulimit (__NR_SYSCALL_BASE+ 58)
  83096. -
  83097. + /* 58 was sys_ulimit */
  83098. + /* 59 was sys_olduname */
  83099. #define __NR_umask (__NR_SYSCALL_BASE+ 60)
  83100. #define __NR_chroot (__NR_SYSCALL_BASE+ 61)
  83101. #define __NR_ustat (__NR_SYSCALL_BASE+ 62)
  83102. @@ -92,8 +93,8 @@
  83103. #define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
  83104. #define __NR_setsid (__NR_SYSCALL_BASE+ 66)
  83105. #define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
  83106. -#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68)
  83107. -#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69)
  83108. + /* 68 was sys_sgetmask */
  83109. + /* 69 was sys_ssetmask */
  83110. #define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
  83111. #define __NR_setregid (__NR_SYSCALL_BASE+ 71)
  83112. #define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
  83113. @@ -108,7 +109,7 @@
  83114. #define __NR_setgroups (__NR_SYSCALL_BASE+ 81)
  83115. #define __NR_select (__NR_SYSCALL_BASE+ 82)
  83116. #define __NR_symlink (__NR_SYSCALL_BASE+ 83)
  83117. -
  83118. + /* 84 was sys_lstat */
  83119. #define __NR_readlink (__NR_SYSCALL_BASE+ 85)
  83120. #define __NR_uselib (__NR_SYSCALL_BASE+ 86)
  83121. #define __NR_swapon (__NR_SYSCALL_BASE+ 87)
  83122. @@ -122,10 +123,10 @@
  83123. #define __NR_fchown (__NR_SYSCALL_BASE+ 95)
  83124. #define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
  83125. #define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
  83126. -#define __NR_profil (__NR_SYSCALL_BASE+ 98)
  83127. + /* 98 was sys_profil */
  83128. #define __NR_statfs (__NR_SYSCALL_BASE+ 99)
  83129. #define __NR_fstatfs (__NR_SYSCALL_BASE+100)
  83130. -#define __NR_ioperm (__NR_SYSCALL_BASE+101)
  83131. + /* 101 was sys_ioperm */
  83132. #define __NR_socketcall (__NR_SYSCALL_BASE+102)
  83133. #define __NR_syslog (__NR_SYSCALL_BASE+103)
  83134. #define __NR_setitimer (__NR_SYSCALL_BASE+104)
  83135. @@ -133,10 +134,10 @@
  83136. #define __NR_stat (__NR_SYSCALL_BASE+106)
  83137. #define __NR_lstat (__NR_SYSCALL_BASE+107)
  83138. #define __NR_fstat (__NR_SYSCALL_BASE+108)
  83139. -
  83140. -
  83141. + /* 109 was sys_uname */
  83142. + /* 110 was sys_iopl */
  83143. #define __NR_vhangup (__NR_SYSCALL_BASE+111)
  83144. -#define __NR_idle (__NR_SYSCALL_BASE+112)
  83145. + /* 112 was sys_idle */
  83146. #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
  83147. #define __NR_wait4 (__NR_SYSCALL_BASE+114)
  83148. #define __NR_swapoff (__NR_SYSCALL_BASE+115)
  83149. @@ -147,7 +148,7 @@
  83150. #define __NR_clone (__NR_SYSCALL_BASE+120)
  83151. #define __NR_setdomainname (__NR_SYSCALL_BASE+121)
  83152. #define __NR_uname (__NR_SYSCALL_BASE+122)
  83153. -#define __NR_modify_ldt (__NR_SYSCALL_BASE+123)
  83154. + /* 123 was sys_modify_ldt */
  83155. #define __NR_adjtimex (__NR_SYSCALL_BASE+124)
  83156. #define __NR_mprotect (__NR_SYSCALL_BASE+125)
  83157. #define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
  83158. @@ -161,7 +162,7 @@
  83159. #define __NR_bdflush (__NR_SYSCALL_BASE+134)
  83160. #define __NR_sysfs (__NR_SYSCALL_BASE+135)
  83161. #define __NR_personality (__NR_SYSCALL_BASE+136)
  83162. -#define __NR_afs_syscall (__NR_SYSCALL_BASE+137) /* Syscall for Andrew File System */
  83163. + /* 137 was sys_afs_syscall */
  83164. #define __NR_setfsuid (__NR_SYSCALL_BASE+138)
  83165. #define __NR_setfsgid (__NR_SYSCALL_BASE+139)
  83166. #define __NR__llseek (__NR_SYSCALL_BASE+140)
  83167. @@ -190,7 +191,7 @@
  83168. #define __NR_mremap (__NR_SYSCALL_BASE+163)
  83169. #define __NR_setresuid (__NR_SYSCALL_BASE+164)
  83170. #define __NR_getresuid (__NR_SYSCALL_BASE+165)
  83171. -#define __NR_vm86 (__NR_SYSCALL_BASE+166)
  83172. + /* 166 was sys_vm86 */
  83173. #define __NR_query_module (__NR_SYSCALL_BASE+167)
  83174. #define __NR_poll (__NR_SYSCALL_BASE+168)
  83175. #define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
  83176. diff -urN linux-2.4.26/include/asm-i386/ide.h linux-2.4.26-vrs1/include/asm-i386/ide.h
  83177. --- linux-2.4.26/include/asm-i386/ide.h 2003-06-13 15:51:38.000000000 +0100
  83178. +++ linux-2.4.26-vrs1/include/asm-i386/ide.h 2004-01-14 21:32:29.000000000 +0000
  83179. @@ -23,39 +23,15 @@
  83180. # endif
  83181. #endif
  83182. -static __inline__ int ide_default_irq(ide_ioreg_t base)
  83183. -{
  83184. - switch (base) {
  83185. - case 0x1f0: return 14;
  83186. - case 0x170: return 15;
  83187. - case 0x1e8: return 11;
  83188. - case 0x168: return 10;
  83189. - case 0x1e0: return 8;
  83190. - case 0x160: return 12;
  83191. - default:
  83192. - return 0;
  83193. - }
  83194. -}
  83195. -
  83196. -static __inline__ ide_ioreg_t ide_default_io_base(int index)
  83197. -{
  83198. - switch (index) {
  83199. - case 0: return 0x1f0;
  83200. - case 1: return 0x170;
  83201. - case 2: return 0x1e8;
  83202. - case 3: return 0x168;
  83203. - case 4: return 0x1e0;
  83204. - case 5: return 0x160;
  83205. - default:
  83206. - return 0;
  83207. - }
  83208. -}
  83209. +#define ide_default_io_base(i) ((ide_ioreg_t)0)
  83210. +#define ide_default_irq(b) (0)
  83211. static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
  83212. {
  83213. ide_ioreg_t reg = data_port;
  83214. int i;
  83215. + memset(hw, 0, sizeof(*hw));
  83216. for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
  83217. hw->io_ports[i] = reg;
  83218. reg += 1;
  83219. @@ -63,7 +39,7 @@
  83220. if (ctrl_port) {
  83221. hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
  83222. } else {
  83223. - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
  83224. + hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
  83225. }
  83226. if (irq != NULL)
  83227. *irq = 0;
  83228. @@ -74,14 +50,25 @@
  83229. {
  83230. #ifndef CONFIG_BLK_DEV_IDEPCI
  83231. hw_regs_t hw;
  83232. - int index;
  83233. - for(index = 0; index < MAX_HWIFS; index++) {
  83234. - memset(&hw, 0, sizeof hw);
  83235. - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
  83236. - hw.irq = ide_default_irq(ide_default_io_base(index));
  83237. - ide_register_hw(&hw, NULL);
  83238. - }
  83239. + ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
  83240. + hw.irq = 14;
  83241. + ide_register_hw(&hw, NULL);
  83242. + ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
  83243. + hw.irq = 15;
  83244. + ide_register_hw(&hw, NULL);
  83245. + ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
  83246. + hw.irq = 11;
  83247. + ide_register_hw(&hw, NULL);
  83248. + ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
  83249. + hw.irq = 10;
  83250. + ide_register_hw(&hw, NULL);
  83251. + ide_init_hwif_ports(&hw, 0x1e0, 0x3e6, NULL);
  83252. + hw.irq = 8;
  83253. + ide_register_hw(&hw, NULL);
  83254. + ide_init_hwif_ports(&hw, 0x160, 0x366, NULL);
  83255. + hw.irq = 12;
  83256. + ide_register_hw(&hw, NULL);
  83257. #endif /* CONFIG_BLK_DEV_IDEPCI */
  83258. }
  83259. diff -urN linux-2.4.26/include/asm-i386/param.h linux-2.4.26-vrs1/include/asm-i386/param.h
  83260. --- linux-2.4.26/include/asm-i386/param.h 2000-10-27 19:04:43.000000000 +0100
  83261. +++ linux-2.4.26-vrs1/include/asm-i386/param.h 2004-01-14 21:32:29.000000000 +0000
  83262. @@ -3,6 +3,16 @@
  83263. #ifndef HZ
  83264. #define HZ 100
  83265. +#ifdef __KERNEL__
  83266. +#if HZ == 100
  83267. +/* X86 is defined to provide userspace with a world where HZ=100
  83268. + We have to do this, (x*const)/const2 isnt optimised out because its not
  83269. + a null operation as it might overflow.. */
  83270. +#define hz_to_std(a) (a)
  83271. +#else
  83272. +#define hz_to_std(a) ((a)*(100/HZ)+((a)*(100%HZ))/HZ)
  83273. +#endif
  83274. +#endif
  83275. #endif
  83276. #define EXEC_PAGESIZE 4096
  83277. diff -urN linux-2.4.26/include/asm-i386/pgtable.h linux-2.4.26-vrs1/include/asm-i386/pgtable.h
  83278. --- linux-2.4.26/include/asm-i386/pgtable.h 2002-11-28 23:53:15.000000000 +0000
  83279. +++ linux-2.4.26-vrs1/include/asm-i386/pgtable.h 2004-01-14 21:32:29.000000000 +0000
  83280. @@ -361,7 +361,6 @@
  83281. #endif /* !__ASSEMBLY__ */
  83282. /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
  83283. -#define PageSkip(page) (0)
  83284. #define kern_addr_valid(addr) (1)
  83285. #define io_remap_page_range remap_page_range
  83286. diff -urN linux-2.4.26/include/asm-ia64/param.h linux-2.4.26-vrs1/include/asm-ia64/param.h
  83287. --- linux-2.4.26/include/asm-ia64/param.h 2004-04-19 11:44:28.000000000 +0100
  83288. +++ linux-2.4.26-vrs1/include/asm-ia64/param.h 2004-04-18 21:47:52.000000000 +0100
  83289. @@ -4,12 +4,14 @@
  83290. /*
  83291. * Fundamental kernel parameters.
  83292. *
  83293. - * Based on <asm-i386/param.h>.
  83294. - *
  83295. - * Modified 1998, 1999, 2002-2003
  83296. - * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  83297. + * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
  83298. + * David Mosberger-Tang <davidm@hpl.hp.com>
  83299. */
  83300. +#ifdef __KERNEL__
  83301. +#define hz_to_std(a) (a)
  83302. +#endif
  83303. +
  83304. #define EXEC_PAGESIZE 65536
  83305. #ifndef NGROUPS
  83306. diff -urN linux-2.4.26/include/asm-m68k/param.h linux-2.4.26-vrs1/include/asm-m68k/param.h
  83307. --- linux-2.4.26/include/asm-m68k/param.h 2001-01-04 21:00:55.000000000 +0000
  83308. +++ linux-2.4.26-vrs1/include/asm-m68k/param.h 2004-01-14 21:32:30.000000000 +0000
  83309. @@ -3,6 +3,9 @@
  83310. #ifndef HZ
  83311. #define HZ 100
  83312. +#ifdef __KERNEL__
  83313. +#define hz_to_std(a) (a)
  83314. +#endif
  83315. #endif
  83316. #define EXEC_PAGESIZE 8192
  83317. diff -urN linux-2.4.26/include/asm-mips/ide.h linux-2.4.26-vrs1/include/asm-mips/ide.h
  83318. --- linux-2.4.26/include/asm-mips/ide.h 2003-08-25 12:44:43.000000000 +0100
  83319. +++ linux-2.4.26-vrs1/include/asm-mips/ide.h 2004-01-14 21:39:23.000000000 +0000
  83320. @@ -27,7 +27,7 @@
  83321. int (*ide_default_irq)(ide_ioreg_t base);
  83322. ide_ioreg_t (*ide_default_io_base)(int index);
  83323. void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port,
  83324. - ide_ioreg_t ctrl_port, int *irq);
  83325. + ide_ioreg_t ctrl_port, int *irq);
  83326. };
  83327. extern struct ide_ops *ide_ops;
  83328. diff -urN linux-2.4.26/include/asm-ppc/param.h linux-2.4.26-vrs1/include/asm-ppc/param.h
  83329. --- linux-2.4.26/include/asm-ppc/param.h 2003-06-13 15:51:38.000000000 +0100
  83330. +++ linux-2.4.26-vrs1/include/asm-ppc/param.h 2004-01-14 21:32:30.000000000 +0000
  83331. @@ -3,6 +3,9 @@
  83332. #ifndef HZ
  83333. #define HZ 100
  83334. +#ifdef __KERNEL__
  83335. +#define hz_to_std(a) (a)
  83336. +#endif
  83337. #endif
  83338. #define EXEC_PAGESIZE 4096
  83339. diff -urN linux-2.4.26/include/asm-s390/param.h linux-2.4.26-vrs1/include/asm-s390/param.h
  83340. --- linux-2.4.26/include/asm-s390/param.h 2001-02-13 22:13:44.000000000 +0000
  83341. +++ linux-2.4.26-vrs1/include/asm-s390/param.h 2004-01-14 21:32:30.000000000 +0000
  83342. @@ -11,6 +11,9 @@
  83343. #ifndef HZ
  83344. #define HZ 100
  83345. +#ifdef __KERNEL__
  83346. +#define hz_to_std(a) (a)
  83347. +#endif
  83348. #endif
  83349. #define EXEC_PAGESIZE 4096
  83350. diff -urN linux-2.4.26/include/asm-sh/param.h linux-2.4.26-vrs1/include/asm-sh/param.h
  83351. --- linux-2.4.26/include/asm-sh/param.h 2001-01-04 21:19:13.000000000 +0000
  83352. +++ linux-2.4.26-vrs1/include/asm-sh/param.h 2004-01-14 21:32:30.000000000 +0000
  83353. @@ -3,6 +3,9 @@
  83354. #ifndef HZ
  83355. #define HZ 100
  83356. +#ifdef __KERNEL__
  83357. +#define hz_to_std(a) (a)
  83358. +#endif
  83359. #endif
  83360. #define EXEC_PAGESIZE 4096
  83361. diff -urN linux-2.4.26/include/asm-sparc/param.h linux-2.4.26-vrs1/include/asm-sparc/param.h
  83362. --- linux-2.4.26/include/asm-sparc/param.h 2000-10-30 22:34:12.000000000 +0000
  83363. +++ linux-2.4.26-vrs1/include/asm-sparc/param.h 2004-01-14 21:32:30.000000000 +0000
  83364. @@ -4,6 +4,9 @@
  83365. #ifndef HZ
  83366. #define HZ 100
  83367. +#ifdef __KERNEL__
  83368. +#define hz_to_std(a) (a)
  83369. +#endif
  83370. #endif
  83371. #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
  83372. diff -urN linux-2.4.26/include/asm-sparc64/ide.h linux-2.4.26-vrs1/include/asm-sparc64/ide.h
  83373. --- linux-2.4.26/include/asm-sparc64/ide.h 2003-06-13 15:51:38.000000000 +0100
  83374. +++ linux-2.4.26-vrs1/include/asm-sparc64/ide.h 2004-01-14 21:32:30.000000000 +0000
  83375. @@ -25,21 +25,12 @@
  83376. # endif
  83377. #endif
  83378. -static __inline__ int ide_default_irq(ide_ioreg_t base)
  83379. -{
  83380. - return 0;
  83381. -}
  83382. -
  83383. -static __inline__ ide_ioreg_t ide_default_io_base(int index)
  83384. -{
  83385. - return 0;
  83386. -}
  83387. -
  83388. static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
  83389. {
  83390. - ide_ioreg_t reg = data_port;
  83391. + ide_ioreg_t reg = data_port;
  83392. int i;
  83393. + memset(&hw, 0, sizeof(hw));
  83394. for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
  83395. hw->io_ports[i] = reg;
  83396. reg += 1;
  83397. @@ -60,16 +51,6 @@
  83398. */
  83399. static __inline__ void ide_init_default_hwifs(void)
  83400. {
  83401. -#ifndef CONFIG_BLK_DEV_IDEPCI
  83402. - hw_regs_t hw;
  83403. - int index;
  83404. -
  83405. - for (index = 0; index < MAX_HWIFS; index++) {
  83406. - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
  83407. - hw.irq = ide_default_irq(ide_default_io_base(index));
  83408. - ide_register_hw(&hw, NULL);
  83409. - }
  83410. -#endif /* CONFIG_BLK_DEV_IDEPCI */
  83411. }
  83412. #undef SUPPORT_SLOW_DATA_PORTS
  83413. diff -urN linux-2.4.26/include/asm-sparc64/param.h linux-2.4.26-vrs1/include/asm-sparc64/param.h
  83414. --- linux-2.4.26/include/asm-sparc64/param.h 2000-10-30 22:34:12.000000000 +0000
  83415. +++ linux-2.4.26-vrs1/include/asm-sparc64/param.h 2004-01-14 21:32:30.000000000 +0000
  83416. @@ -4,6 +4,9 @@
  83417. #ifndef HZ
  83418. #define HZ 100
  83419. +#ifdef __KERNEL__
  83420. +#define hz_to_std(a) (a)
  83421. +#endif
  83422. #endif
  83423. #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
  83424. diff -urN linux-2.4.26/include/linux/console_struct.h linux-2.4.26-vrs1/include/linux/console_struct.h
  83425. --- linux-2.4.26/include/linux/console_struct.h 2003-06-13 15:51:38.000000000 +0100
  83426. +++ linux-2.4.26-vrs1/include/linux/console_struct.h 2004-01-14 21:32:30.000000000 +0000
  83427. @@ -7,6 +7,8 @@
  83428. * Fields marked with [#] must be set by the low-level driver.
  83429. * Fields marked with [!] can be changed by the low-level driver
  83430. * to achieve effects such as fast scrolling by changing the origin.
  83431. + *
  83432. + * 11/07/1998 RMK Changed vc_state to be a function pointer
  83433. */
  83434. #ifndef _LINUX_CONSOLE_STRUCT_H_
  83435. @@ -34,7 +36,11 @@
  83436. unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
  83437. unsigned int vc_x, vc_y; /* Cursor position */
  83438. unsigned int vc_top, vc_bottom; /* Scrolling region */
  83439. +#ifdef CONSOLE_WIP
  83440. + int (*vc_state)(int currcons, struct tty_struct *tty, unsigned int c);
  83441. +#else
  83442. unsigned int vc_state; /* Escape sequence parser state */
  83443. +#endif
  83444. unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
  83445. unsigned long vc_origin; /* [!] Start of real screen */
  83446. unsigned long vc_scr_end; /* [!] End of real screen */
  83447. diff -urN linux-2.4.26/include/linux/cpufreq.h linux-2.4.26-vrs1/include/linux/cpufreq.h
  83448. --- linux-2.4.26/include/linux/cpufreq.h 1970-01-01 01:00:00.000000000 +0100
  83449. +++ linux-2.4.26-vrs1/include/linux/cpufreq.h 2004-01-14 21:32:30.000000000 +0000
  83450. @@ -0,0 +1,94 @@
  83451. +/*
  83452. + * linux/include/linux/cpufreq.h
  83453. + *
  83454. + * Copyright (C) 2001 Russell King
  83455. + *
  83456. + * $Id: cpufreq.h,v 1.5.2.1 2002/05/03 13:26:27 rmk Exp $
  83457. + *
  83458. + * This program is free software; you can redistribute it and/or modify
  83459. + * it under the terms of the GNU General Public License version 2 as
  83460. + * published by the Free Software Foundation.
  83461. + */
  83462. +#ifndef _LINUX_CPUFREQ_H
  83463. +#define _LINUX_CPUFREQ_H
  83464. +
  83465. +#include <linux/config.h>
  83466. +#include <linux/notifier.h>
  83467. +
  83468. +#ifndef CONFIG_SMP
  83469. +#define cpufreq_current(cpu) ((void)(cpu), __cpufreq_cur)
  83470. +#define cpufreq_max(cpu) ((void)(cpu), __cpufreq_max)
  83471. +#define cpufreq_min(cpu) ((void)(cpu), __cpufreq_min)
  83472. +#else
  83473. +/*
  83474. + * Should be something like:
  83475. + *
  83476. + * typedef struct {
  83477. + * u_int current;
  83478. + * u_int max;
  83479. + * u_int min;
  83480. + * } __cacheline_aligned cpufreq_info_t;
  83481. + *
  83482. + * static cpufreq_info_t cpufreq_info;
  83483. + *
  83484. + * #define cpufreq_current(cpu) (cpufreq_info[cpu].current)
  83485. + * #define cpufreq_max(cpu) (cpufreq_info[cpu].max)
  83486. + * #define cpufreq_min(cpu) (cpufreq_info[cpu].min)
  83487. + *
  83488. + * Maybe we should find some other per-cpu structure to
  83489. + * bury this in?
  83490. + */
  83491. +#error fill in SMP version
  83492. +#endif
  83493. +
  83494. +struct cpufreq_info {
  83495. + unsigned int old_freq;
  83496. + unsigned int new_freq;
  83497. +};
  83498. +
  83499. +/*
  83500. + * The max and min frequency rates that the registered device
  83501. + * can tolerate. Never set any element this structure directly -
  83502. + * always use cpu_updateminmax.
  83503. + */
  83504. +struct cpufreq_minmax {
  83505. + unsigned int min_freq;
  83506. + unsigned int max_freq;
  83507. + unsigned int cur_freq;
  83508. + unsigned int new_freq;
  83509. +};
  83510. +
  83511. +static inline
  83512. +void cpufreq_updateminmax(void *arg, unsigned int min, unsigned int max)
  83513. +{
  83514. + struct cpufreq_minmax *minmax = arg;
  83515. +
  83516. + if (minmax->min_freq < min)
  83517. + minmax->min_freq = min;
  83518. + if (minmax->max_freq > max)
  83519. + minmax->max_freq = max;
  83520. +}
  83521. +
  83522. +#define CPUFREQ_MINMAX (0)
  83523. +#define CPUFREQ_PRECHANGE (1)
  83524. +#define CPUFREQ_POSTCHANGE (2)
  83525. +
  83526. +int cpufreq_register_notifier(struct notifier_block *nb);
  83527. +int cpufreq_unregister_notifier(struct notifier_block *nb);
  83528. +
  83529. +int cpufreq_setmax(void);
  83530. +int cpufreq_restore(void);
  83531. +int cpufreq_set(unsigned int khz);
  83532. +unsigned int cpufreq_get(int cpu);
  83533. +
  83534. +/*
  83535. + * These two functions are only available at init time.
  83536. + */
  83537. +void cpufreq_init(unsigned int khz,
  83538. + unsigned int min_freq,
  83539. + unsigned int max_freq);
  83540. +
  83541. +void cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
  83542. + void (*setspeed)(unsigned int));
  83543. +
  83544. +#endif
  83545. diff -urN linux-2.4.26/include/linux/i2c-id.h linux-2.4.26-vrs1/include/linux/i2c-id.h
  83546. --- linux-2.4.26/include/linux/i2c-id.h 2004-02-27 20:03:29.000000000 +0000
  83547. +++ linux-2.4.26-vrs1/include/linux/i2c-id.h 2004-02-27 22:47:10.000000000 +0000
  83548. @@ -20,16 +20,16 @@
  83549. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  83550. /* ------------------------------------------------------------------------- */
  83551. -/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */
  83552. +/* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
  83553. #ifndef I2C_ID_H
  83554. #define I2C_ID_H
  83555. /*
  83556. * This file is part of the i2c-bus package and contains the identifier
  83557. * values for drivers, adapters and other folk populating these serial
  83558. - * worlds.
  83559. + * worlds.
  83560. *
  83561. - * These will change often (i.e. additions) , therefore this has been
  83562. + * These will change often (i.e. additions) , therefore this has been
  83563. * separated from the functional interface definitions of the i2c api.
  83564. *
  83565. */
  83566. @@ -38,10 +38,10 @@
  83567. * ---- Driver types -----------------------------------------------------
  83568. * device id name + number function description, i2c address(es)
  83569. *
  83570. - * Range 1000-1999 range is defined in sensors/sensors.h
  83571. - * Range 0x100 - 0x1ff is for V4L2 Common Components
  83572. + * Range 1000-1999 range is defined in sensors/sensors.h
  83573. + * Range 0x100 - 0x1ff is for V4L2 Common Components
  83574. * Range 0xf000 - 0xffff is reserved for local experimentation, and should
  83575. - * never be used in official drivers
  83576. + * never be used in official drivers
  83577. */
  83578. #define I2C_DRIVERID_MSP3400 1
  83579. @@ -90,7 +90,12 @@
  83580. #define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
  83581. #define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
  83582. #define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
  83583. +#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */
  83584. +#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */
  83585. #define I2C_DRIVERID_ADV7175 48 /* ADV 7175/7176 video encoder */
  83586. +#define I2C_DRIVERID_ZR36067 49 /* Zoran 36067 video encoder */
  83587. +#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
  83588. +#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
  83589. #define I2C_DRIVERID_MAX1617 56 /* temp sensor */
  83590. #define I2C_DRIVERID_SAA7191 57 /* video decoder */
  83591. #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
  83592. @@ -102,8 +107,10 @@
  83593. #define I2C_DRIVERID_I2CDEV 900
  83594. #define I2C_DRIVERID_I2CPROC 901
  83595. +#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
  83596. +#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */
  83597. -/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
  83598. +/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
  83599. These were originally in sensors.h in the lm_sensors package */
  83600. #define I2C_DRIVERID_LM78 1002
  83601. #define I2C_DRIVERID_LM75 1003
  83602. @@ -131,6 +138,12 @@
  83603. #define I2C_DRIVERID_ADM1024 1025
  83604. #define I2C_DRIVERID_IT87 1026
  83605. #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
  83606. +#define I2C_DRIVERID_FSCPOS 1028
  83607. +#define I2C_DRIVERID_FSCSCY 1029
  83608. +#define I2C_DRIVERID_PCF8591 1030
  83609. +#define I2C_DRIVERID_SMSC47M1 1031
  83610. +#define I2C_DRIVERID_VT1211 1032
  83611. +#define I2C_DRIVERID_LM92 1033
  83612. /*
  83613. * ---- Adapter types ----------------------------------------------------
  83614. @@ -147,7 +160,8 @@
  83615. #define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
  83616. #define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
  83617. #define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
  83618. -
  83619. +#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */
  83620. +#define I2C_ALGO_SAA7134 0x090000
  83621. #define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
  83622. #define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
  83623. @@ -156,13 +170,15 @@
  83624. #define I2C_ALGO_SGI 0x130000 /* SGI algorithm */
  83625. +#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
  83626. +
  83627. #define I2C_ALGO_EXP 0x800000 /* experimental */
  83628. #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
  83629. #define I2C_ALGO_SHIFT 0x10 /* right shift to get index values */
  83630. #define I2C_HW_ADAPS 0x10000 /* # adapter types */
  83631. -#define I2C_HW_MASK 0xffff
  83632. +#define I2C_HW_MASK 0xffff
  83633. /* hw specific modules that are defined per algorithm layer
  83634. @@ -182,9 +198,13 @@
  83635. #define I2C_HW_B_I810 0x0a /* Intel I810 */
  83636. #define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
  83637. #define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
  83638. +#define I2C_HW_B_SAVG 0x0d /* Savage 4 */
  83639. #define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
  83640. #define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
  83641. #define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
  83642. +#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
  83643. +#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface */
  83644. +#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */
  83645. /* --- PCF 8584 based algorithms */
  83646. #define I2C_HW_P_LP 0x00 /* Parallel port interface */
  83647. @@ -197,6 +217,12 @@
  83648. /* --- MPC8xx PowerPC adapters */
  83649. #define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
  83650. +/* --- ITE based algorithms */
  83651. +#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
  83652. +
  83653. +/* --- PowerPC on-chip adapters */
  83654. +#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
  83655. +
  83656. /* --- Broadcom SiByte adapters */
  83657. #define I2C_HW_SIBYTE 0x00
  83658. diff -urN linux-2.4.26/include/linux/ide.h linux-2.4.26-vrs1/include/linux/ide.h
  83659. --- linux-2.4.26/include/linux/ide.h 2004-04-19 11:44:28.000000000 +0100
  83660. +++ linux-2.4.26-vrs1/include/linux/ide.h 2004-04-19 20:38:18.000000000 +0100
  83661. @@ -287,7 +287,9 @@
  83662. * Check for an interrupt and acknowledge the interrupt status
  83663. */
  83664. struct hwif_s;
  83665. +struct ide_drive_s;
  83666. typedef int (ide_ack_intr_t)(struct hwif_s *);
  83667. +typedef void (ide_xfer_data_t)(struct ide_drive_s *, void *, unsigned int);
  83668. #ifndef NO_DMA
  83669. #define NO_DMA 255
  83670. @@ -311,10 +313,14 @@
  83671. typedef struct hw_regs_s {
  83672. ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
  83673. int irq; /* our irq number */
  83674. - int dma; /* our dma entry */
  83675. + int dma; /* our dma number */
  83676. ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
  83677. + ide_xfer_data_t *ide_output_data; /* write data to i/face */
  83678. + ide_xfer_data_t *ide_input_data; /* read data from i/face */
  83679. + ide_xfer_data_t *atapi_output_bytes; /* write bytes to i/face */
  83680. + ide_xfer_data_t *atapi_input_bytes; /* read bytes from i/face */
  83681. void *priv; /* interface specific data */
  83682. - hwif_chipset_t chipset;
  83683. + hwif_chipset_t chipset;
  83684. sata_ioreg_t sata_scr[SATA_NR_PORTS];
  83685. sata_ioreg_t sata_misc[SATA_NR_PORTS];
  83686. } hw_regs_t;
  83687. diff -urN linux-2.4.26/include/linux/l3/algo-bit.h linux-2.4.26-vrs1/include/linux/l3/algo-bit.h
  83688. --- linux-2.4.26/include/linux/l3/algo-bit.h 1970-01-01 01:00:00.000000000 +0100
  83689. +++ linux-2.4.26-vrs1/include/linux/l3/algo-bit.h 2004-01-14 21:32:30.000000000 +0000
  83690. @@ -0,0 +1,39 @@
  83691. +/*
  83692. + * linux/include/linux/l3/algo-bit.h
  83693. + *
  83694. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  83695. + *
  83696. + * This program is free software; you can redistribute it and/or modify
  83697. + * it under the terms of the GNU General Public License as published by
  83698. + * the Free Software Foundation; either version 2 of the License.
  83699. + *
  83700. + * L3 Bus bit-banging algorithm. Derived from i2c-algo-bit.h by
  83701. + * Simon G. Vogl.
  83702. + */
  83703. +#ifndef L3_ALGO_BIT_H
  83704. +#define L3_ALGO_BIT_H 1
  83705. +
  83706. +#include <linux/l3/l3.h>
  83707. +
  83708. +struct l3_algo_bit_data {
  83709. + void (*setdat) (void *data, int state);
  83710. + void (*setclk) (void *data, int state);
  83711. + void (*setmode)(void *data, int state);
  83712. + void (*setdir) (void *data, int in); /* set data direction */
  83713. + int (*getdat) (void *data);
  83714. +
  83715. + void *data;
  83716. +
  83717. + /* bus timings (us) */
  83718. + int data_hold;
  83719. + int data_setup;
  83720. + int clock_high;
  83721. + int mode_hold;
  83722. + int mode_setup;
  83723. + int mode;
  83724. +};
  83725. +
  83726. +int l3_bit_add_bus(struct l3_adapter *);
  83727. +int l3_bit_del_bus(struct l3_adapter *);
  83728. +
  83729. +#endif
  83730. diff -urN linux-2.4.26/include/linux/l3/l3.h linux-2.4.26-vrs1/include/linux/l3/l3.h
  83731. --- linux-2.4.26/include/linux/l3/l3.h 1970-01-01 01:00:00.000000000 +0100
  83732. +++ linux-2.4.26-vrs1/include/linux/l3/l3.h 2004-04-19 20:42:23.000000000 +0100
  83733. @@ -0,0 +1,208 @@
  83734. +/*
  83735. + * linux/include/linux/l3/l3.h
  83736. + *
  83737. + * Copyright (C) 2001 Russell King, All Rights Reserved.
  83738. + *
  83739. + * This program is free software; you can redistribute it and/or modify
  83740. + * it under the terms of the GNU General Public License as published by
  83741. + * the Free Software Foundation; either version 2 of the License.
  83742. + *
  83743. + * Derived from i2c.h by Simon G. Vogl
  83744. + */
  83745. +#ifndef L3_H
  83746. +#define L3_H
  83747. +
  83748. +struct l3_msg {
  83749. + unsigned char addr; /* slave address */
  83750. + unsigned char flags;
  83751. +#define L3_M_RD 0x01
  83752. +#define L3_M_NOADDR 0x02
  83753. + unsigned short len; /* msg length */
  83754. + unsigned char *buf; /* pointer to msg data */
  83755. +};
  83756. +
  83757. +#ifdef __KERNEL__
  83758. +
  83759. +#include <linux/types.h>
  83760. +#include <linux/list.h>
  83761. +
  83762. +struct l3_client;
  83763. +
  83764. +struct l3_ops {
  83765. + int (*open)(struct l3_client *);
  83766. + int (*command)(struct l3_client *, int cmd, void *arg);
  83767. + void (*close)(struct l3_client *);
  83768. +};
  83769. +
  83770. +/*
  83771. + * A driver is capable of handling one or more physical devices present on
  83772. + * L3 adapters. This information is used to inform the driver of adapter
  83773. + * events.
  83774. + */
  83775. +struct l3_driver {
  83776. + /*
  83777. + * This name is used to uniquely identify the driver.
  83778. + * It should be the same as the module name.
  83779. + */
  83780. + char name[32];
  83781. +
  83782. + /*
  83783. + * Notifies the driver that a new client wishes to use its
  83784. + * services. Note that the module use count will be increased
  83785. + * prior to this function being called. In addition, the
  83786. + * clients driver and adapter fields will have been setup.
  83787. + */
  83788. + int (*attach_client)(struct l3_client *);
  83789. +
  83790. + /*
  83791. + * Notifies the driver that the client has finished with its
  83792. + * services, and any memory that it allocated for this client
  83793. + * should be cleaned up. In addition the chip should be
  83794. + * shut down.
  83795. + */
  83796. + void (*detach_client)(struct l3_client *);
  83797. +
  83798. + /*
  83799. + * Possible operations on the driver.
  83800. + */
  83801. + struct l3_ops *ops;
  83802. +
  83803. + /*
  83804. + * Module structure, if any.
  83805. + */
  83806. + struct module *owner;
  83807. +
  83808. + /*
  83809. + * drivers list
  83810. + */
  83811. + struct list_head drivers;
  83812. +};
  83813. +
  83814. +struct l3_adapter;
  83815. +
  83816. +struct l3_algorithm {
  83817. + /* textual description */
  83818. + char name[32];
  83819. +
  83820. + /* perform bus transactions */
  83821. + int (*xfer)(struct l3_adapter *, struct l3_msg msgs[], int num);
  83822. +};
  83823. +
  83824. +struct semaphore;
  83825. +
  83826. +/*
  83827. + * l3_adapter is the structure used to identify a physical L3 bus along
  83828. + * with the access algorithms necessary to access it.
  83829. + */
  83830. +struct l3_adapter {
  83831. + /*
  83832. + * This name is used to uniquely identify the adapter.
  83833. + * It should be the same as the module name.
  83834. + */
  83835. + char name[32];
  83836. +
  83837. + /*
  83838. + * the algorithm to access the bus
  83839. + */
  83840. + struct l3_algorithm *algo;
  83841. +
  83842. + /*
  83843. + * Algorithm specific data
  83844. + */
  83845. + void *algo_data;
  83846. +
  83847. + /*
  83848. + * This may be NULL, or should point to the module struct
  83849. + */
  83850. + struct module *owner;
  83851. +
  83852. + /*
  83853. + * private data for the adapter
  83854. + */
  83855. + void *data;
  83856. +
  83857. + /*
  83858. + * Our lock. Unlike the i2c layer, we allow this to be used for
  83859. + * other stuff, like the i2c layer lock. Some people implement
  83860. + * i2c stuff using the same signals as the l3 bus.
  83861. + */
  83862. + struct semaphore *lock;
  83863. +
  83864. + /*
  83865. + * List of attached clients.
  83866. + */
  83867. + struct list_head clients;
  83868. +
  83869. + /*
  83870. + * List of all adapters.
  83871. + */
  83872. + struct list_head adapters;
  83873. +};
  83874. +
  83875. +/*
  83876. + * l3_client identifies a single device (i.e. chip) that is connected to an
  83877. + * L3 bus. The behaviour is defined by the routines of the driver. This
  83878. + * function is mainly used for lookup & other admin. functions.
  83879. + */
  83880. +struct l3_client {
  83881. + struct l3_adapter *adapter; /* the adapter we sit on */
  83882. + struct l3_driver *driver; /* and our access routines */
  83883. + void *driver_data; /* private driver data */
  83884. + struct list_head __adap;
  83885. +};
  83886. +
  83887. +
  83888. +extern int l3_add_adapter(struct l3_adapter *);
  83889. +extern int l3_del_adapter(struct l3_adapter *);
  83890. +
  83891. +extern int l3_add_driver(struct l3_driver *);
  83892. +extern int l3_del_driver(struct l3_driver *);
  83893. +
  83894. +extern int l3_attach_client(struct l3_client *, const char *, const char *);
  83895. +extern int l3_detach_client(struct l3_client *);
  83896. +
  83897. +extern int l3_transfer(struct l3_adapter *, struct l3_msg msgs[], int);
  83898. +extern int l3_write(struct l3_client *, int, const char *, int);
  83899. +extern int l3_read(struct l3_client *, int, char *, int);
  83900. +
  83901. +/**
  83902. + * l3_command - send a command to a L3 device driver
  83903. + * @client: registered client structure
  83904. + * @cmd: device driver command
  83905. + * @arg: device driver arguments
  83906. + *
  83907. + * Ask the L3 device driver to perform some function. Further information
  83908. + * should be sought from the device driver in question.
  83909. + *
  83910. + * Returns negative error code on failure.
  83911. + */
  83912. +static inline int l3_command(struct l3_client *clnt, int cmd, void *arg)
  83913. +{
  83914. + struct l3_ops *ops = clnt->driver->ops;
  83915. + int ret = -EINVAL;
  83916. +
  83917. + if (ops && ops->command)
  83918. + ret = ops->command(clnt, cmd, arg);
  83919. +
  83920. + return ret;
  83921. +}
  83922. +
  83923. +static inline int l3_open(struct l3_client *clnt)
  83924. +{
  83925. + struct l3_ops *ops = clnt->driver->ops;
  83926. + int ret = 0;
  83927. +
  83928. + if (ops && ops->open)
  83929. + ret = ops->open(clnt);
  83930. + return ret;
  83931. +}
  83932. +
  83933. +static inline void l3_close(struct l3_client *clnt)
  83934. +{
  83935. + struct l3_ops *ops = clnt->driver->ops;
  83936. + if (ops && ops->close)
  83937. + ops->close(clnt);
  83938. +}
  83939. +#endif
  83940. +
  83941. +#endif /* L3_H */
  83942. diff -urN linux-2.4.26/include/linux/l3/uda1341.h linux-2.4.26-vrs1/include/linux/l3/uda1341.h
  83943. --- linux-2.4.26/include/linux/l3/uda1341.h 1970-01-01 01:00:00.000000000 +0100
  83944. +++ linux-2.4.26-vrs1/include/linux/l3/uda1341.h 2004-01-14 21:32:30.000000000 +0000
  83945. @@ -0,0 +1,50 @@
  83946. +/*
  83947. + * linux/include/linux/l3/uda1341.h
  83948. + *
  83949. + * Philips UDA1341 mixer device driver
  83950. + *
  83951. + * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
  83952. + *
  83953. + * This program is free software; you can redistribute it and/or
  83954. + * modify it under the terms of the GNU General Public License.
  83955. + */
  83956. +
  83957. +#define UDA1341_NAME "uda1341"
  83958. +
  83959. +struct uda1341_cfg {
  83960. + unsigned int fs:16;
  83961. + unsigned int format:3;
  83962. +};
  83963. +
  83964. +#define FMT_I2S 0
  83965. +#define FMT_LSB16 1
  83966. +#define FMT_LSB18 2
  83967. +#define FMT_LSB20 3
  83968. +#define FMT_MSB 4
  83969. +#define FMT_LSB16MSB 5
  83970. +#define FMT_LSB18MSB 6
  83971. +#define FMT_LSB20MSB 7
  83972. +
  83973. +#define L3_UDA1341_CONFIGURE 0x13410001
  83974. +
  83975. +struct l3_gain {
  83976. + unsigned int left:8;
  83977. + unsigned int right:8;
  83978. + unsigned int unused:8;
  83979. + unsigned int channel:8;
  83980. +};
  83981. +
  83982. +#define L3_SET_VOLUME 0x13410002
  83983. +#define L3_SET_TREBLE 0x13410003
  83984. +#define L3_SET_BASS 0x13410004
  83985. +#define L3_SET_GAIN 0x13410005
  83986. +
  83987. +struct l3_agc {
  83988. + unsigned int level:8;
  83989. + unsigned int enable:1;
  83990. + unsigned int attack:7;
  83991. + unsigned int decay:8;
  83992. + unsigned int channel:8;
  83993. +};
  83994. +
  83995. +#define L3_INPUT_AGC 0x13410006
  83996. diff -urN linux-2.4.26/include/linux/mm.h linux-2.4.26-vrs1/include/linux/mm.h
  83997. --- linux-2.4.26/include/linux/mm.h 2003-11-28 18:26:21.000000000 +0000
  83998. +++ linux-2.4.26-vrs1/include/linux/mm.h 2004-04-19 20:37:56.000000000 +0100
  83999. @@ -685,6 +685,12 @@
  84000. extern struct page * vmalloc_to_page(void *addr);
  84001. +#ifndef __arm__
  84002. +#define memc_update_addr(x,y,z)
  84003. +#define memc_update_mm(x)
  84004. +#define memc_clear(x,y)
  84005. +#endif
  84006. +
  84007. #endif /* __KERNEL__ */
  84008. #endif
  84009. diff -urN linux-2.4.26/include/linux/mtd/cfi.h linux-2.4.26-vrs1/include/linux/mtd/cfi.h
  84010. --- linux-2.4.26/include/linux/mtd/cfi.h 2003-06-13 15:51:38.000000000 +0100
  84011. +++ linux-2.4.26-vrs1/include/linux/mtd/cfi.h 2004-04-19 16:49:02.000000000 +0100
  84012. @@ -287,8 +287,10 @@
  84013. #define P_ID_AMD_STD 2
  84014. #define P_ID_INTEL_STD 3
  84015. #define P_ID_AMD_EXT 4
  84016. +#define P_ID_ST_ADV 32
  84017. #define P_ID_MITSUBISHI_STD 256
  84018. #define P_ID_MITSUBISHI_EXT 257
  84019. +#define P_ID_SST_PAGE 258
  84020. #define P_ID_RESERVED 65535
  84021. diff -urN linux-2.4.26/include/linux/pci.h linux-2.4.26-vrs1/include/linux/pci.h
  84022. --- linux-2.4.26/include/linux/pci.h 2004-04-19 11:44:28.000000000 +0100
  84023. +++ linux-2.4.26-vrs1/include/linux/pci.h 2004-04-19 20:38:16.000000000 +0100
  84024. @@ -411,6 +411,7 @@
  84025. char name[90]; /* device name */
  84026. char slot_name[8]; /* slot name */
  84027. + u32 saved_state[16]; /* for saving the config space before suspend */
  84028. int active; /* ISAPnP: device is active */
  84029. int ro; /* ISAPnP: read only */
  84030. unsigned short regs; /* ISAPnP: supported registers */
  84031. @@ -497,6 +498,8 @@
  84032. struct pbus_set_ranges_data
  84033. {
  84034. + int found_vga:1;
  84035. + int prefetch_valid:1;
  84036. unsigned long io_start, io_end;
  84037. unsigned long mem_start, mem_end;
  84038. unsigned long prefetch_start, prefetch_end;
  84039. @@ -638,6 +641,8 @@
  84040. int pci_restore_state(struct pci_dev *dev, u32 *buffer);
  84041. int pci_set_power_state(struct pci_dev *dev, int state);
  84042. int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
  84043. +int pci_generic_suspend_save(struct pci_dev *pdev, u32 state);
  84044. +int pci_generic_resume_restore(struct pci_dev *pdev);
  84045. /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
  84046. diff -urN linux-2.4.26/include/linux/pld/pld_epxa.h linux-2.4.26-vrs1/include/linux/pld/pld_epxa.h
  84047. --- linux-2.4.26/include/linux/pld/pld_epxa.h 1970-01-01 01:00:00.000000000 +0100
  84048. +++ linux-2.4.26-vrs1/include/linux/pld/pld_epxa.h 2004-01-14 21:32:30.000000000 +0000
  84049. @@ -0,0 +1,35 @@
  84050. +#ifndef __LINUX_EPXAPLD_H
  84051. +#define __LINUX_EPXAPLD_H
  84052. +
  84053. +/*
  84054. + * linux/drivers/char/pld/epxapld.h
  84055. + *
  84056. + * Pld driver for Altera EPXA Excalibur devices
  84057. + *
  84058. + * Copyright 2001 Altera Corporation
  84059. + *
  84060. + * This program is free software; you can redistribute it and/or modify
  84061. + * it under the terms of the GNU General Public License as published by
  84062. + * the Free Software Foundation; either version 2 of the License, or
  84063. + * (at your option) any later version.
  84064. + *
  84065. + * This program is distributed in the hope that it will be useful,
  84066. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  84067. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  84068. + * GNU General Public License for more details.
  84069. + *
  84070. + * You should have received a copy of the GNU General Public License
  84071. + * along with this program; if not, write to the Free Software
  84072. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  84073. + *
  84074. + * $Id: $
  84075. + *
  84076. + */
  84077. +#define PLD_IOC_MAGIC 'p'
  84078. +#if !defined(KERNEL) || defined(CONFIG_PLD_HOTSWAP)
  84079. +#define PLD_IOC_ADD_PLD_DEV _IOW(PLD_IOC_MAGIC, 0xa0, struct pldhs_dev_desc)
  84080. +#define PLD_IOC_REMOVE_PLD_DEVS _IO(PLD_IOC_MAGIC, 0xa1)
  84081. +#define PLD_IOC_SET_INT_MODE _IOW(PLD_IOC_MAGIC, 0xa2, int)
  84082. +#endif
  84083. +
  84084. +#endif
  84085. diff -urN linux-2.4.26/include/linux/pld/pld_hotswap.h linux-2.4.26-vrs1/include/linux/pld/pld_hotswap.h
  84086. --- linux-2.4.26/include/linux/pld/pld_hotswap.h 1970-01-01 01:00:00.000000000 +0100
  84087. +++ linux-2.4.26-vrs1/include/linux/pld/pld_hotswap.h 2004-01-14 21:32:30.000000000 +0000
  84088. @@ -0,0 +1,87 @@
  84089. +#ifndef __LINUX_PLD_HOTSWAP_H
  84090. +#define __LINUX_PLD_HOTSWAP_H
  84091. +/*
  84092. + * linux/drivers/char/pld/pld_hotswap.h
  84093. + *
  84094. + * Pld driver for Altera EPXA Excalibur devices
  84095. + *
  84096. + * Copyright 2001 Altera Corporation
  84097. + *
  84098. + * This program is free software; you can redistribute it and/or modify
  84099. + * it under the terms of the GNU General Public License as published by
  84100. + * the Free Software Foundation; either version 2 of the License, or
  84101. + * (at your option) any later version.
  84102. + *
  84103. + * This program is distributed in the hope that it will be useful,
  84104. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  84105. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  84106. + * GNU General Public License for more details.
  84107. + *
  84108. + * You should have received a copy of the GNU General Public License
  84109. + * along with this program; if not, write to the Free Software
  84110. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  84111. + *
  84112. + * $Id: $
  84113. + *
  84114. + */
  84115. +
  84116. +/*
  84117. + * The pld_hotswap ops contain the basic operation required for adding
  84118. + * and removing devices from the system.
  84119. + */
  84120. +
  84121. +struct pldhs_dev_info{
  84122. + unsigned int size;
  84123. + unsigned short vendor_id;
  84124. + unsigned short product_id;
  84125. + unsigned char fsize;
  84126. + unsigned char nsize;
  84127. + unsigned short pssize;
  84128. + unsigned short cmdsize;
  84129. + unsigned char irq;
  84130. + unsigned char version;
  84131. + unsigned int base_addr;
  84132. + unsigned int reg_size;
  84133. +};
  84134. +
  84135. +struct pldhs_dev_desc{
  84136. + struct pldhs_dev_info* info;
  84137. + char* name;
  84138. + void* data;
  84139. +};
  84140. +
  84141. +#include <linux/pld/pld_epxa.h>
  84142. +
  84143. +
  84144. +#ifdef __KERNEL__
  84145. +struct pld_hotswap_ops{
  84146. + struct list_head list;
  84147. + char* name;
  84148. + int (*add_device)(struct pldhs_dev_info *dev_info, void* dev_ps_data);
  84149. + int (*remove_devices)(void);
  84150. + int (*proc_read)(char* buf,char** start,off_t offset,int count,int *eof,void *data);
  84151. +};
  84152. +
  84153. +/*
  84154. + * These functions are called by the device drivers to register functions
  84155. + * which should be called when devices are added and removed
  84156. + */
  84157. +extern int pldhs_register_driver(struct pld_hotswap_ops *drv);
  84158. +extern int pldhs_unregister_driver(char *driver);
  84159. +
  84160. +/*
  84161. + * These functions are called by the pld loader to add and remove
  84162. + * device instances from the system. The call the functions regsistered
  84163. + * the the particular deriver for this purpose
  84164. + */
  84165. +extern int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data);
  84166. +extern int pldhs_remove_devices(void);
  84167. +
  84168. +/* Macro for formatting data to appear in the proc/pld file */
  84169. +#define PLDHS_READ_PROC_DATA(buf,name,index,base,irq,ps_string) \
  84170. + sprintf(buf,":%s:%d Base Address, %#lx, IRQ, %d#\n%s\n",\
  84171. + name,index,base,irq,ps_string)
  84172. +
  84173. +#endif
  84174. +
  84175. +#endif
  84176. diff -urN linux-2.4.26/include/linux/serial.h linux-2.4.26-vrs1/include/linux/serial.h
  84177. --- linux-2.4.26/include/linux/serial.h 2002-08-03 01:39:45.000000000 +0100
  84178. +++ linux-2.4.26-vrs1/include/linux/serial.h 2004-04-19 20:38:03.000000000 +0100
  84179. @@ -48,7 +48,7 @@
  84180. unsigned char *iomem_base;
  84181. unsigned short iomem_reg_shift;
  84182. unsigned int port_high;
  84183. - int reserved[1];
  84184. + unsigned long iomap_base; /* cookie passed into ioremap */
  84185. };
  84186. /*
  84187. diff -urN linux-2.4.26/include/linux/serialP.h linux-2.4.26-vrs1/include/linux/serialP.h
  84188. --- linux-2.4.26/include/linux/serialP.h 2002-08-03 01:39:45.000000000 +0100
  84189. +++ linux-2.4.26-vrs1/include/linux/serialP.h 2004-04-19 20:38:16.000000000 +0100
  84190. @@ -157,8 +157,8 @@
  84191. struct pci_dev *dev;
  84192. };
  84193. -extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
  84194. -extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
  84195. +//extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
  84196. +//extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
  84197. #ifndef PCI_ANY_ID
  84198. #define PCI_ANY_ID (~0)
  84199. diff -urN linux-2.4.26/include/linux/serial_core.h linux-2.4.26-vrs1/include/linux/serial_core.h
  84200. --- linux-2.4.26/include/linux/serial_core.h 1970-01-01 01:00:00.000000000 +0100
  84201. +++ linux-2.4.26-vrs1/include/linux/serial_core.h 2004-04-19 16:49:19.000000000 +0100
  84202. @@ -0,0 +1,441 @@
  84203. +/*
  84204. + * linux/drivers/char/serial_core.h
  84205. + *
  84206. + * Copyright (C) 2000 Deep Blue Solutions Ltd.
  84207. + *
  84208. + * This program is free software; you can redistribute it and/or modify
  84209. + * it under the terms of the GNU General Public License as published by
  84210. + * the Free Software Foundation; either version 2 of the License, or
  84211. + * (at your option) any later version.
  84212. + *
  84213. + * This program is distributed in the hope that it will be useful,
  84214. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  84215. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  84216. + * GNU General Public License for more details.
  84217. + *
  84218. + * You should have received a copy of the GNU General Public License
  84219. + * along with this program; if not, write to the Free Software
  84220. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  84221. + *
  84222. + * $Id: serial_core.h,v 1.9.2.3 2001/11/26 22:32:45 rmk Exp $
  84223. + */
  84224. +
  84225. +/*
  84226. + * The type definitions. These are from Ted Ts'o's serial.h
  84227. + */
  84228. +#define PORT_UNKNOWN 0
  84229. +#define PORT_8250 1
  84230. +#define PORT_16450 2
  84231. +#define PORT_16550 3
  84232. +#define PORT_16550A 4
  84233. +#define PORT_CIRRUS 5
  84234. +#define PORT_16650 6
  84235. +#define PORT_16650V2 7
  84236. +#define PORT_16750 8
  84237. +#define PORT_STARTECH 9
  84238. +#define PORT_16C950 10
  84239. +#define PORT_16654 11
  84240. +#define PORT_16850 12
  84241. +#define PORT_RSA 13
  84242. +#define PORT_NS16550A 14
  84243. +#define PORT_MAX_8250 14 /* max port ID */
  84244. +
  84245. +/*
  84246. + * ARM specific type numbers. These are not currently guaranteed
  84247. + * to be implemented, and will change in the future. These are
  84248. + * separate so any additions to the old serial.c that occur before
  84249. + * we are merged can be easily merged here.
  84250. + */
  84251. +#define PORT_AMBA 32
  84252. +#define PORT_CLPS711X 33
  84253. +#define PORT_SA1100 34
  84254. +#define PORT_UART00 35
  84255. +#define PORT_21285 37
  84256. +
  84257. +/* Sparc type numbers. */
  84258. +#define PORT_SUNZILOG 38
  84259. +#define PORT_SUNSAB 39
  84260. +
  84261. +/* NEC v850. */
  84262. +#define PORT_NB85E_UART 40
  84263. +
  84264. +/* NEC PC-9800 */
  84265. +#define PORT_8251_PC98 41
  84266. +#define PORT_19K_PC98 42
  84267. +#define PORT_FIFO_PC98 43
  84268. +#define PORT_VFAST_PC98 44
  84269. +#define PORT_PC9861 45
  84270. +#define PORT_PC9801_101 46
  84271. +
  84272. +/* DZ */
  84273. +#define PORT_DZ 47
  84274. +
  84275. +#define PORT_OMAHA 48
  84276. +#define PORT_AT91RM9200 49
  84277. +
  84278. +
  84279. +#ifdef __KERNEL__
  84280. +
  84281. +#include <linux/config.h>
  84282. +#include <linux/interrupt.h>
  84283. +#include <linux/circ_buf.h>
  84284. +#include <linux/serial.h>
  84285. +#include <linux/spinlock.h>
  84286. +
  84287. +struct uart_port;
  84288. +struct uart_info;
  84289. +struct serial_struct;
  84290. +
  84291. +/*
  84292. + * This structure describes all the operations that can be
  84293. + * done on the physical hardware.
  84294. + */
  84295. +struct uart_ops {
  84296. + unsigned int (*tx_empty)(struct uart_port *);
  84297. + void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
  84298. + unsigned int (*get_mctrl)(struct uart_port *);
  84299. + void (*stop_tx)(struct uart_port *, unsigned int tty_stop);
  84300. + void (*start_tx)(struct uart_port *, unsigned int tty_start);
  84301. + void (*send_xchar)(struct uart_port *, char ch);
  84302. + void (*stop_rx)(struct uart_port *);
  84303. + void (*enable_ms)(struct uart_port *);
  84304. + void (*break_ctl)(struct uart_port *, int ctl);
  84305. + int (*startup)(struct uart_port *);
  84306. + void (*shutdown)(struct uart_port *);
  84307. + void (*change_speed)(struct uart_port *, unsigned int cflag, unsigned int iflag, unsigned int quot);
  84308. + void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate);
  84309. + int (*set_wake)(struct uart_port *, unsigned int state);
  84310. +
  84311. + /*
  84312. + * Return a string describing the type of the port
  84313. + */
  84314. + const char *(*type)(struct uart_port *);
  84315. +
  84316. + /*
  84317. + * Release IO and memory resources used by the port.
  84318. + * This includes iounmap if necessary.
  84319. + */
  84320. + void (*release_port)(struct uart_port *);
  84321. +
  84322. + /*
  84323. + * Request IO and memory resources used by the port.
  84324. + * This includes iomapping the port if necessary.
  84325. + */
  84326. + int (*request_port)(struct uart_port *);
  84327. + void (*config_port)(struct uart_port *, int);
  84328. + int (*verify_port)(struct uart_port *, struct serial_struct *);
  84329. + int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
  84330. +};
  84331. +
  84332. +#define UART_CONFIG_TYPE (1 << 0)
  84333. +#define UART_CONFIG_IRQ (1 << 1)
  84334. +
  84335. +struct uart_icount {
  84336. + __u32 cts;
  84337. + __u32 dsr;
  84338. + __u32 rng;
  84339. + __u32 dcd;
  84340. + __u32 rx;
  84341. + __u32 tx;
  84342. + __u32 frame;
  84343. + __u32 overrun;
  84344. + __u32 parity;
  84345. + __u32 brk;
  84346. + __u32 buf_overrun;
  84347. +};
  84348. +
  84349. +struct uart_port {
  84350. + spinlock_t lock; /* port lock */
  84351. + unsigned int iobase; /* in/out[bwl] */
  84352. + char *membase; /* read/write[bwl] */
  84353. + unsigned char fifosize; /* tx fifo size */
  84354. + unsigned char x_char; /* xon/xoff char */
  84355. + unsigned char regshift; /* reg offset shift */
  84356. + unsigned char iotype; /* io access style */
  84357. +
  84358. +#define UPIO_PORT (0)
  84359. +#define UPIO_HUB6 (1)
  84360. +#define UPIO_MEM (2)
  84361. +
  84362. + unsigned int read_status_mask; /* driver specific */
  84363. + unsigned int ignore_status_mask; /* driver specific */
  84364. +
  84365. + struct uart_info *info; /* pointer to parent info */
  84366. + struct uart_icount icount; /* statistics */
  84367. +
  84368. + struct console *cons; /* struct console, if any */
  84369. + unsigned long sysrq; /* sysrq timeout */
  84370. +
  84371. + unsigned int flags;
  84372. +
  84373. +#define UPF_HUP_NOTIFY ASYNC_HUP_NOTIFY
  84374. +#define UPF_FOURPORT ASYNC_FOURPORT
  84375. +#define UPF_SAK ASYNC_SAK
  84376. +#define UPF_SPLIT_TERMIOS ASYNC_SPLIT_TERMIOS
  84377. +#define UPF_SPD_MASK (0x1030)
  84378. +#define UPF_SPD_HI (0x0010)
  84379. +#define UPF_SPD_VHI (0x0020)
  84380. +#define UPF_SPD_CUST (0x0030)
  84381. +#define UPF_SPD_SHI (0x1000)
  84382. +#define UPF_SPD_WARP (0x1010)
  84383. +#define UPF_SKIP_TEST ASYNC_SKIP_TEST
  84384. +#define UPF_AUTO_IRQ ASYNC_AUTO_IRQ
  84385. +#define UPF_SESSION_LOCKOUT ASYNC_SESSION_LOCKOUT
  84386. +#define UPF_PGRP_LOCKOUT ASYNCPGRP_LOCKOUT
  84387. +#define UPF_CALLOUT_NOHUP ASYNC_CALLOUT_NOHUP
  84388. +#define UPF_HARDPPS_CD ASYNC_HARDPPS_CD
  84389. + /* 12 */
  84390. +#define UPF_LOW_LATENCY ASYNC_LOW_LATENCY
  84391. +#define UPF_BUGGY_UART ASYNC_BUGGY_UART
  84392. +#define UPF_AUTOPROBE ASYNC_AUTOPROBE
  84393. +#define UPF_MAGIC_MULTIPLIER (1 << 16)
  84394. +#define UPF_BOOT_ONLYMCA ASYNC_BOOT_ONLYMCA
  84395. +#define UPF_CONS_FLOW ASYNC_CONS_FLOW
  84396. +#define UPF_SHARE_IRQ ASYNC_SHARE_IRQ
  84397. +#define UPF_BOOT_AUTOCONF ASYNC_BOOT_AUTOCONF
  84398. +#define UPF_RESOURCES (1 << 30)
  84399. +#define UPF_IOREMAP (1 << 31)
  84400. +
  84401. +#define UPF_CHANGE_MASK (0x17fff)
  84402. +#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY)
  84403. +
  84404. + unsigned int mctrl; /* current modem ctrl settings */
  84405. + unsigned int timeout; /* character-based timeout */
  84406. + unsigned int type; /* port type */
  84407. + struct uart_ops *ops;
  84408. + unsigned int uartclk; /* base uart clock */
  84409. + unsigned int custom_divisor;
  84410. + unsigned int irq; /* irq number */
  84411. + unsigned int line; /* port index */
  84412. + unsigned long mapbase; /* for ioremap */
  84413. + unsigned char hub6; /* this should be in the 8250 driver */
  84414. + unsigned char unused[7];
  84415. +};
  84416. +
  84417. +/*
  84418. + * This is the state information which is persistent across opens.
  84419. + * The low level driver must not to touch any elements contained
  84420. + * within.
  84421. + */
  84422. +struct uart_state {
  84423. + unsigned int close_delay;
  84424. + unsigned int closing_wait;
  84425. +
  84426. +#define USF_CLOSING_WAIT_INF (0)
  84427. +#define USF_CLOSING_WAIT_NONE (65535)
  84428. +
  84429. + struct termios normal_termios;
  84430. + struct termios callout_termios;
  84431. +
  84432. + int count;
  84433. + struct uart_info *info;
  84434. + struct uart_port *port;
  84435. +
  84436. + struct semaphore sem;
  84437. +#ifdef CONFIG_PM
  84438. + struct pm_dev *pm;
  84439. +#endif
  84440. +};
  84441. +
  84442. +#define UART_XMIT_SIZE 1024
  84443. +/*
  84444. + * This is the state information which is only valid when the port
  84445. + * is open; it may be freed by the core driver once the device has
  84446. + * been closed. Either the low level driver or the core can modify
  84447. + * stuff here.
  84448. + */
  84449. +struct uart_info {
  84450. + struct tty_struct *tty;
  84451. + struct circ_buf xmit;
  84452. + unsigned int flags;
  84453. +
  84454. +/*
  84455. + * These are the flags that specific to info->flags, and reflect our
  84456. + * internal state. They can not be accessed via port->flags. Low
  84457. + * level drivers must not change these, but may query them instead.
  84458. + */
  84459. +#define UIF_CHECK_CD ASYNC_CHECK_CD
  84460. +#define UIF_CTS_FLOW ASYNC_CTS_FLOW
  84461. +#define UIF_CALLOUT_ACTIVE ASYNC_CALLOUT_ACTIVE
  84462. +#define UIF_NORMAL_ACTIVE ASYNC_NORMAL_ACTIVE
  84463. +#define UIF_INITIALIZED ASYNC_INITIALIZED
  84464. +
  84465. + unsigned char *tmpbuf;
  84466. + struct semaphore tmpbuf_sem;
  84467. +
  84468. + unsigned int driver_priv;
  84469. + int blocked_open;
  84470. + pid_t session;
  84471. + pid_t pgrp;
  84472. +
  84473. + struct tasklet_struct tlet;
  84474. +
  84475. + wait_queue_head_t open_wait;
  84476. + wait_queue_head_t delta_msr_wait;
  84477. +};
  84478. +
  84479. +/* number of characters left in xmit buffer before we ask for more */
  84480. +#define WAKEUP_CHARS 256
  84481. +
  84482. +struct module;
  84483. +struct tty_driver;
  84484. +
  84485. +struct uart_driver {
  84486. + struct module *owner;
  84487. + int normal_major;
  84488. + const char *normal_name;
  84489. + struct tty_driver *normal_driver;
  84490. + int callout_major;
  84491. + const char *callout_name;
  84492. + struct tty_driver *callout_driver;
  84493. + struct tty_struct **table;
  84494. + struct termios **termios;
  84495. + struct termios **termios_locked;
  84496. + int minor;
  84497. + int nr;
  84498. + struct console *cons;
  84499. +
  84500. + /*
  84501. + * these are private; the low level driver should not
  84502. + * touch these; they should be initialised to NULL
  84503. + */
  84504. + struct uart_state *state;
  84505. +};
  84506. +
  84507. +void uart_write_wakeup(struct uart_port *port);
  84508. +struct uart_port *uart_get_console(struct uart_port *ports, int nr,
  84509. + struct console *c);
  84510. +void uart_parse_options(char *options, int *baud, int *parity, int *bits,
  84511. + int *flow);
  84512. +int uart_set_options(struct uart_port *port, struct console *co, int baud,
  84513. + int parity, int bits, int flow);
  84514. +
  84515. +/*
  84516. + * Port/driver registration/removal
  84517. + */
  84518. +int uart_register_driver(struct uart_driver *uart);
  84519. +void uart_unregister_driver(struct uart_driver *uart);
  84520. +void uart_unregister_port(struct uart_driver *reg, int line);
  84521. +int uart_register_port(struct uart_driver *reg, struct uart_port *port);
  84522. +int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
  84523. +int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
  84524. +
  84525. +#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
  84526. +#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
  84527. +
  84528. +#define uart_circ_chars_pending(circ) \
  84529. + (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
  84530. +
  84531. +#define uart_circ_chars_free(circ) \
  84532. + (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
  84533. +
  84534. +#define uart_tx_stopped(port) \
  84535. + ((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
  84536. +
  84537. +/*
  84538. + * The following are helper functions for the low level drivers.
  84539. + */
  84540. +#ifdef SUPPORT_SYSRQ
  84541. +static inline int
  84542. +uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
  84543. + struct pt_regs *regs)
  84544. +{
  84545. + if (port->sysrq) {
  84546. + if (ch && time_before(jiffies, port->sysrq)) {
  84547. + handle_sysrq(ch, regs, NULL, NULL);
  84548. + port->sysrq = 0;
  84549. + return 1;
  84550. + }
  84551. + port->sysrq = 0;
  84552. + }
  84553. + return 0;
  84554. +}
  84555. +#else
  84556. +#define uart_handle_sysrq_char(port,ch,regs) (0)
  84557. +#endif
  84558. +
  84559. +/*
  84560. + * We do the SysRQ and SAK checking like this...
  84561. + */
  84562. +static inline int uart_handle_break(struct uart_port *port)
  84563. +{
  84564. + struct uart_info *info = port->info;
  84565. +#ifdef SUPPORT_SYSRQ
  84566. + if (port->cons && port->cons->index == port->line) {
  84567. + if (!port->sysrq) {
  84568. + port->sysrq = jiffies + HZ*5;
  84569. + return 1;
  84570. + }
  84571. + port->sysrq = 0;
  84572. + }
  84573. +#endif
  84574. + if (port->flags & UPF_SAK)
  84575. + do_SAK(info->tty);
  84576. + return 0;
  84577. +}
  84578. +
  84579. +/**
  84580. + * uart_handle_dcd_change - handle a change of carrier detect state
  84581. + * @port: uart_port structure for the open port
  84582. + * @status: new carrier detect status, nonzero if active
  84583. + */
  84584. +static inline void
  84585. +uart_handle_dcd_change(struct uart_port *port, unsigned int status)
  84586. +{
  84587. + struct uart_info *info = port->info;
  84588. +
  84589. + port->icount.dcd++;
  84590. +
  84591. +#ifdef CONFIG_HARD_PPS
  84592. + if ((port->flags & UPF_HARDPPS_CD) && status)
  84593. + hardpps();
  84594. +#endif
  84595. +
  84596. + if (info->flags & UIF_CHECK_CD) {
  84597. + if (status)
  84598. + wake_up_interruptible(&info->open_wait);
  84599. + else if (!((info->flags & UIF_CALLOUT_ACTIVE) &&
  84600. + (port->flags & UPF_CALLOUT_NOHUP))) {
  84601. + if (info->tty)
  84602. + tty_hangup(info->tty);
  84603. + }
  84604. + }
  84605. +}
  84606. +
  84607. +/**
  84608. + * uart_handle_cts_change - handle a change of clear-to-send state
  84609. + * @port: uart_port structure for the open port
  84610. + * @status: new clear to send status, nonzero if active
  84611. + */
  84612. +static inline void
  84613. +uart_handle_cts_change(struct uart_port *port, unsigned int status)
  84614. +{
  84615. + struct uart_info *info = port->info;
  84616. + struct tty_struct *tty = info->tty;
  84617. +
  84618. + port->icount.cts++;
  84619. +
  84620. + if (info->flags & UIF_CTS_FLOW) {
  84621. + if (tty->hw_stopped) {
  84622. + if (status) {
  84623. + tty->hw_stopped = 0;
  84624. + port->ops->start_tx(port, 0);
  84625. + uart_write_wakeup(port);
  84626. + }
  84627. + } else {
  84628. + if (!status) {
  84629. + tty->hw_stopped = 1;
  84630. + port->ops->stop_tx(port, 0);
  84631. + }
  84632. + }
  84633. + }
  84634. +}
  84635. +
  84636. +/*
  84637. + * UART_ENABLE_MS - determine if port should enable modem status irqs
  84638. + */
  84639. +#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
  84640. + (cflag) & CRTSCTS || \
  84641. + !((cflag) & CLOCAL))
  84642. +
  84643. +#endif
  84644. diff -urN linux-2.4.26/include/linux/serial_reg.h linux-2.4.26-vrs1/include/linux/serial_reg.h
  84645. --- linux-2.4.26/include/linux/serial_reg.h 2001-05-02 00:05:00.000000000 +0100
  84646. +++ linux-2.4.26-vrs1/include/linux/serial_reg.h 2004-01-14 21:32:30.000000000 +0000
  84647. @@ -121,6 +121,7 @@
  84648. /*
  84649. * These are the definitions for the Modem Control Register
  84650. */
  84651. +#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */
  84652. #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
  84653. #define UART_MCR_OUT2 0x08 /* Out2 complement */
  84654. #define UART_MCR_OUT1 0x04 /* Out1 complement */
  84655. diff -urN linux-2.4.26/include/linux/zlib.h linux-2.4.26-vrs1/include/linux/zlib.h
  84656. --- linux-2.4.26/include/linux/zlib.h 2002-11-28 23:53:15.000000000 +0000
  84657. +++ linux-2.4.26-vrs1/include/linux/zlib.h 2004-01-14 21:32:30.000000000 +0000
  84658. @@ -31,7 +31,7 @@
  84659. #ifndef _ZLIB_H
  84660. #define _ZLIB_H
  84661. -#include <linux/zconf.h>
  84662. +#include "zconf.h"
  84663. #ifdef __cplusplus
  84664. extern "C" {
  84665. diff -urN linux-2.4.26/init/do_mounts.c linux-2.4.26-vrs1/init/do_mounts.c
  84666. --- linux-2.4.26/init/do_mounts.c 2003-11-28 18:26:21.000000000 +0000
  84667. +++ linux-2.4.26-vrs1/init/do_mounts.c 2004-01-14 21:39:29.000000000 +0000
  84668. @@ -888,7 +888,7 @@
  84669. */
  84670. void prepare_namespace(void)
  84671. {
  84672. - int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
  84673. + int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
  84674. #ifdef CONFIG_ALL_PPC
  84675. extern void arch_discover_root(void);
  84676. arch_discover_root();
  84677. @@ -951,6 +951,7 @@
  84678. static unsigned inptr; /* index of next byte to be processed in inbuf */
  84679. static unsigned outcnt; /* bytes in output buffer */
  84680. static int exit_code;
  84681. +static int unzip_error;
  84682. static long bytes_out;
  84683. static int crd_infd, crd_outfd;
  84684. @@ -998,13 +999,17 @@
  84685. /* ===========================================================================
  84686. * Fill the input buffer. This is called only when the buffer is empty
  84687. * and at least one byte is really needed.
  84688. + * Returning -1 does not guarantee that gunzip() will ever return.
  84689. */
  84690. static int __init fill_inbuf(void)
  84691. {
  84692. if (exit_code) return -1;
  84693. insize = read(crd_infd, inbuf, INBUFSIZ);
  84694. - if (insize == 0) return -1;
  84695. + if (insize == 0) {
  84696. + error("RAMDISK: ran out of compressed data\n");
  84697. + return -1;
  84698. + }
  84699. inptr = 1;
  84700. @@ -1018,10 +1023,15 @@
  84701. static void __init flush_window(void)
  84702. {
  84703. ulg c = crc; /* temporary variable */
  84704. - unsigned n;
  84705. + unsigned n, written;
  84706. uch *in, ch;
  84707. - write(crd_outfd, window, outcnt);
  84708. + written = write(crd_outfd, window, outcnt);
  84709. + if (written != outcnt && unzip_error == 0) {
  84710. + printk(KERN_ERR "RAMDISK: incomplete write (%d != %d), "
  84711. + "only wrote %ld\n", written, outcnt, bytes_out);
  84712. + unzip_error = 1;
  84713. + }
  84714. in = window;
  84715. for (n = 0; n < outcnt; n++) {
  84716. ch = *in++;
  84717. @@ -1036,6 +1046,7 @@
  84718. {
  84719. printk(KERN_ERR "%s", x);
  84720. exit_code = 1;
  84721. + unzip_error = 1;
  84722. }
  84723. static int __init crd_load(int in_fd, int out_fd)
  84724. @@ -1064,6 +1075,8 @@
  84725. }
  84726. makecrc();
  84727. result = gunzip();
  84728. + if (unzip_error)
  84729. + result = 1;
  84730. kfree(inbuf);
  84731. kfree(window);
  84732. return result;
  84733. diff -urN linux-2.4.26/kernel/Makefile linux-2.4.26-vrs1/kernel/Makefile
  84734. --- linux-2.4.26/kernel/Makefile 2001-09-17 05:22:40.000000000 +0100
  84735. +++ linux-2.4.26-vrs1/kernel/Makefile 2004-01-14 21:32:30.000000000 +0000
  84736. @@ -9,16 +9,19 @@
  84737. O_TARGET := kernel.o
  84738. -export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
  84739. +export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
  84740. + printk.o fork.o cpufreq.o
  84741. -obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
  84742. +obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
  84743. module.o exit.o itimer.o info.o time.o softirq.o resource.o \
  84744. sysctl.o acct.o capability.o ptrace.o timer.o user.o \
  84745. signal.o sys.o kmod.o context.o
  84746. +obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
  84747. obj-$(CONFIG_UID16) += uid16.o
  84748. obj-$(CONFIG_MODULES) += ksyms.o
  84749. obj-$(CONFIG_PM) += pm.o
  84750. +obj-$(CONFIG_CPU_FREQ) += cpufreq.o
  84751. ifneq ($(CONFIG_IA64),y)
  84752. # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
  84753. diff -urN linux-2.4.26/kernel/cpufreq.c linux-2.4.26-vrs1/kernel/cpufreq.c
  84754. --- linux-2.4.26/kernel/cpufreq.c 1970-01-01 01:00:00.000000000 +0100
  84755. +++ linux-2.4.26-vrs1/kernel/cpufreq.c 2004-01-14 21:32:30.000000000 +0000
  84756. @@ -0,0 +1,536 @@
  84757. +/*
  84758. + * linux/kernel/cpufreq.c
  84759. + *
  84760. + * Copyright (C) 2001 Russell King
  84761. + *
  84762. + * $Id: cpufreq.c,v 1.17.2.2 2002/05/03 13:26:27 rmk Exp $
  84763. + *
  84764. + * This program is free software; you can redistribute it and/or modify
  84765. + * it under the terms of the GNU General Public License version 2 as
  84766. + * published by the Free Software Foundation.
  84767. + *
  84768. + * CPU speed changing core functionality. We provide the following
  84769. + * services to the system:
  84770. + * - notifier lists to inform other code of the freq change both
  84771. + * before and after the freq change.
  84772. + * - the ability to change the freq speed
  84773. + *
  84774. + * ** You'll need to add CTL_CPU = 10 to include/linux/sysctl.h if
  84775. + * it's not already present.
  84776. + *
  84777. + * When this appears in the kernel, the sysctl enums will move to
  84778. + * include/linux/sysctl.h
  84779. + */
  84780. +#include <linux/config.h>
  84781. +#include <linux/types.h>
  84782. +#include <linux/module.h>
  84783. +#include <linux/notifier.h>
  84784. +#include <linux/cpufreq.h>
  84785. +#include <linux/kernel.h>
  84786. +#include <linux/delay.h>
  84787. +#include <linux/init.h>
  84788. +#include <linux/smp.h>
  84789. +#include <linux/fs.h>
  84790. +#include <linux/sysctl.h>
  84791. +
  84792. +#include <asm/semaphore.h>
  84793. +#include <asm/system.h>
  84794. +#include <asm/uaccess.h>
  84795. +#include <linux/interrupt.h> /* requires system.h */
  84796. +
  84797. +/*
  84798. + * This list is for kernel code that needs to handle
  84799. + * changes to devices when the CPU clock speed changes.
  84800. + */
  84801. +static struct notifier_block *cpufreq_notifier_list;
  84802. +static DECLARE_MUTEX_LOCKED(cpufreq_sem);
  84803. +static unsigned long cpufreq_ref_loops;
  84804. +static unsigned int cpufreq_ref_freq;
  84805. +static int cpufreq_initialised;
  84806. +static unsigned int (*cpufreq_validatespeed)(unsigned int);
  84807. +static void (*cpufreq_setspeed)(unsigned int);
  84808. +
  84809. +#ifndef CONFIG_SMP
  84810. +static unsigned int __cpufreq_max;
  84811. +static unsigned int __cpufreq_min;
  84812. +static unsigned int __cpufreq_cur;
  84813. +#endif
  84814. +
  84815. +static unsigned long scale(unsigned long ref, u_int div, u_int mult)
  84816. +{
  84817. + unsigned long new_jiffy_l, new_jiffy_h;
  84818. +
  84819. + /*
  84820. + * Recalculate loops_per_jiffy. We do it this way to
  84821. + * avoid math overflow on 32-bit machines. Maybe we
  84822. + * should make this architecture dependent? If you have
  84823. + * a better way of doing this, please replace!
  84824. + *
  84825. + * new = old * mult / div
  84826. + */
  84827. + new_jiffy_h = ref / div;
  84828. + new_jiffy_l = (ref % div) / 100;
  84829. + new_jiffy_h *= mult;
  84830. + new_jiffy_l = new_jiffy_l * mult / div;
  84831. +
  84832. + return new_jiffy_h + new_jiffy_l * 100;
  84833. +}
  84834. +
  84835. +/*
  84836. + * cpufreq_max command line parameter. Use:
  84837. + * cpufreq=59000-221000
  84838. + * to set the CPU frequency to 59 to 221MHz.
  84839. + */
  84840. +static int __init cpufreq_setup(char *str)
  84841. +{
  84842. + unsigned int min, max;
  84843. + int i;
  84844. +
  84845. + min = 0;
  84846. + max = simple_strtoul(str, &str, 0);
  84847. + if (*str == '-') {
  84848. + min = max;
  84849. + max = simple_strtoul(str + 1, NULL, 0);
  84850. + }
  84851. +
  84852. + for (i = 0; i < smp_num_cpus; i++) {
  84853. + cpufreq_max(i) = max;
  84854. + cpufreq_min(i) = min;
  84855. + }
  84856. +
  84857. + return 1;
  84858. +}
  84859. +
  84860. +__setup("cpufreq=", cpufreq_setup);
  84861. +
  84862. +/**
  84863. + * cpufreq_register_notifier - register a driver with cpufreq
  84864. + * @nb: notifier function to register
  84865. + *
  84866. + * Add a driver to the list of drivers that which to be notified about
  84867. + * CPU clock rate changes. The driver will be called three times on
  84868. + * clock change.
  84869. + *
  84870. + * This function may sleep, and has the same return conditions as
  84871. + * notifier_chain_register.
  84872. + */
  84873. +int cpufreq_register_notifier(struct notifier_block *nb)
  84874. +{
  84875. + int ret;
  84876. +
  84877. + down(&cpufreq_sem);
  84878. + ret = notifier_chain_register(&cpufreq_notifier_list, nb);
  84879. + up(&cpufreq_sem);
  84880. +
  84881. + return ret;
  84882. +}
  84883. +
  84884. +EXPORT_SYMBOL(cpufreq_register_notifier);
  84885. +
  84886. +/**
  84887. + * cpufreq_unregister_notifier - unregister a driver with cpufreq
  84888. + * @nb: notifier block to be unregistered
  84889. + *
  84890. + * Remove a driver from the CPU frequency notifier lists.
  84891. + *
  84892. + * This function may sleep, and has the same return conditions as
  84893. + * notifier_chain_unregister.
  84894. + */
  84895. +int cpufreq_unregister_notifier(struct notifier_block *nb)
  84896. +{
  84897. + int ret;
  84898. +
  84899. + down(&cpufreq_sem);
  84900. + ret = notifier_chain_unregister(&cpufreq_notifier_list, nb);
  84901. + up(&cpufreq_sem);
  84902. +
  84903. + return ret;
  84904. +}
  84905. +
  84906. +EXPORT_SYMBOL(cpufreq_unregister_notifier);
  84907. +
  84908. +/*
  84909. + * This notifier alters the system "loops_per_jiffy" for the clock
  84910. + * speed change. We ignore CPUFREQ_MINMAX here.
  84911. + */
  84912. +static void adjust_jiffies(unsigned long val, struct cpufreq_info *ci)
  84913. +{
  84914. + if ((val == CPUFREQ_PRECHANGE && ci->old_freq < ci->new_freq) ||
  84915. + (val == CPUFREQ_POSTCHANGE && ci->old_freq > ci->new_freq))
  84916. + loops_per_jiffy = scale(cpufreq_ref_loops, cpufreq_ref_freq,
  84917. + ci->new_freq);
  84918. +}
  84919. +
  84920. +#ifdef CONFIG_PM
  84921. +/**
  84922. + * cpufreq_restore - restore the CPU clock frequency after resume
  84923. + *
  84924. + * Restore the CPU clock frequency so that our idea of the current
  84925. + * frequency reflects the actual hardware.
  84926. + */
  84927. +int cpufreq_restore(void)
  84928. +{
  84929. + unsigned long old_cpus;
  84930. + int cpu = smp_processor_id();
  84931. + int ret;
  84932. +
  84933. + if (!cpufreq_initialised)
  84934. + panic("cpufreq_restore() called before initialisation!");
  84935. + if (in_interrupt())
  84936. + panic("cpufreq_restore() called from interrupt context!");
  84937. +
  84938. + /*
  84939. + * Bind to the current CPU.
  84940. + */
  84941. + old_cpus = current->cpus_allowed;
  84942. + current->cpus_allowed = 1UL << cpu_logical_map(cpu);
  84943. +
  84944. + down(&cpufreq_sem);
  84945. +
  84946. + ret = -ENXIO;
  84947. + if (cpufreq_setspeed) {
  84948. + cpufreq_setspeed(cpufreq_current(cpu));
  84949. + ret = 0;
  84950. + }
  84951. +
  84952. + up(&cpufreq_sem);
  84953. +
  84954. + current->cpus_allowed = old_cpus;
  84955. +
  84956. + return ret;
  84957. +}
  84958. +
  84959. +EXPORT_SYMBOL_GPL(cpufreq_restore);
  84960. +#endif
  84961. +
  84962. +/**
  84963. + * cpu_setfreq - change the CPU clock frequency.
  84964. + * @freq: frequency (in kHz) at which we should run.
  84965. + *
  84966. + * Set the CPU clock frequency, informing all registered users of
  84967. + * the change. We bound the frequency according to the cpufreq_max
  84968. + * command line parameter, and the parameters the registered users
  84969. + * will allow.
  84970. + *
  84971. + * This function must be called from process context, and on the
  84972. + * cpu that we wish to change the frequency of.
  84973. + *
  84974. + * We return 0 if successful. (we are currently always successful).
  84975. + */
  84976. +int cpufreq_set(unsigned int freq)
  84977. +{
  84978. + unsigned long old_cpus;
  84979. + struct cpufreq_info clkinfo;
  84980. + struct cpufreq_minmax minmax;
  84981. + int cpu = smp_processor_id();
  84982. + int ret;
  84983. +
  84984. + if (!cpufreq_initialised)
  84985. + panic("cpufreq_set() called before initialisation!");
  84986. + if (in_interrupt())
  84987. + panic("cpufreq_set() called from interrupt context!");
  84988. +
  84989. + /*
  84990. + * Bind to the current CPU.
  84991. + */
  84992. + old_cpus = current->cpus_allowed;
  84993. + current->cpus_allowed = 1UL << cpu_logical_map(cpu);
  84994. +
  84995. + down(&cpufreq_sem);
  84996. + ret = -ENXIO;
  84997. + if (!cpufreq_setspeed || !cpufreq_validatespeed)
  84998. + goto out;
  84999. +
  85000. + /*
  85001. + * Don't allow the CPU to be clocked over the limit.
  85002. + */
  85003. + minmax.min_freq = cpufreq_min(cpu);
  85004. + minmax.max_freq = cpufreq_max(cpu);
  85005. + minmax.cur_freq = cpufreq_current(cpu);
  85006. + minmax.new_freq = freq;
  85007. +
  85008. + /*
  85009. + * Find out what the registered devices will currently tolerate,
  85010. + * and limit the requested clock rate to these values. Drivers
  85011. + * must not rely on the 'new_freq' value - it is only a guide.
  85012. + */
  85013. + notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_MINMAX, &minmax);
  85014. + if (freq < minmax.min_freq)
  85015. + freq = minmax.min_freq;
  85016. + if (freq > minmax.max_freq)
  85017. + freq = minmax.max_freq;
  85018. +
  85019. + /*
  85020. + * Ask the CPU specific code to validate the speed. If the speed
  85021. + * is not acceptable, make it acceptable. Current policy is to
  85022. + * round the frequency down to the value the processor actually
  85023. + * supports.
  85024. + */
  85025. + freq = cpufreq_validatespeed(freq);
  85026. +
  85027. + if (cpufreq_current(cpu) != freq) {
  85028. + clkinfo.old_freq = cpufreq_current(cpu);
  85029. + clkinfo.new_freq = freq;
  85030. +
  85031. + notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_PRECHANGE,
  85032. + &clkinfo);
  85033. +
  85034. + adjust_jiffies(CPUFREQ_PRECHANGE, &clkinfo);
  85035. +
  85036. + /*
  85037. + * Actually set the CPU frequency.
  85038. + */
  85039. + cpufreq_setspeed(freq);
  85040. + cpufreq_current(cpu) = freq;
  85041. + adjust_jiffies(CPUFREQ_POSTCHANGE, &clkinfo);
  85042. +
  85043. + notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_POSTCHANGE,
  85044. + &clkinfo);
  85045. + }
  85046. +
  85047. + ret = 0;
  85048. +
  85049. + out:
  85050. + up(&cpufreq_sem);
  85051. +
  85052. + current->cpus_allowed = old_cpus;
  85053. +
  85054. + return ret;
  85055. +}
  85056. +
  85057. +EXPORT_SYMBOL_GPL(cpufreq_set);
  85058. +
  85059. +/**
  85060. + * cpufreq_setmax - set the CPU to maximum frequency
  85061. + *
  85062. + * Sets the CPU this function is executed on to maximum frequency.
  85063. + */
  85064. +int cpufreq_setmax(void)
  85065. +{
  85066. + return cpufreq_set(cpufreq_max(smp_processor_id()));
  85067. +}
  85068. +
  85069. +EXPORT_SYMBOL_GPL(cpufreq_setmax);
  85070. +
  85071. +/**
  85072. + * cpufreq_get - return the current CPU clock frequency in 1kHz
  85073. + * @cpu: cpu number to obtain frequency for
  85074. + *
  85075. + * Returns the specified CPUs frequency in kHz.
  85076. + */
  85077. +unsigned int cpufreq_get(int cpu)
  85078. +{
  85079. + if (!cpufreq_initialised)
  85080. + panic("cpufreq_get() called before initialisation!");
  85081. + return cpufreq_current(cpu);
  85082. +}
  85083. +
  85084. +EXPORT_SYMBOL(cpufreq_get);
  85085. +
  85086. +#ifdef CONFIG_SYSCTL
  85087. +
  85088. +static int
  85089. +cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
  85090. + void *buffer, size_t *lenp)
  85091. +{
  85092. + char buf[16], *p;
  85093. + int cpu = 0, len, left = *lenp;
  85094. +
  85095. + if (!left || (filp->f_pos && !write)) {
  85096. + *lenp = 0;
  85097. + return 0;
  85098. + }
  85099. +
  85100. + if (write) {
  85101. + unsigned int freq;
  85102. +
  85103. + len = left;
  85104. + if (left > sizeof(buf))
  85105. + left = sizeof(buf);
  85106. + if (copy_from_user(buf, buffer, left))
  85107. + return -EFAULT;
  85108. + buf[sizeof(buf) - 1] = '\0';
  85109. +
  85110. + freq = simple_strtoul(buf, &p, 0);
  85111. + cpufreq_set(freq);
  85112. + } else {
  85113. + len = sprintf(buf, "%d\n", cpufreq_get(cpu));
  85114. + if (len > left)
  85115. + len = left;
  85116. + if (copy_to_user(buffer, buf, len))
  85117. + return -EFAULT;
  85118. + }
  85119. +
  85120. + *lenp = len;
  85121. + filp->f_pos += len;
  85122. + return 0;
  85123. +}
  85124. +
  85125. +static int
  85126. +cpufreq_sysctl(ctl_table *table, int *name, int nlen,
  85127. + void *oldval, size_t *oldlenp,
  85128. + void *newval, size_t newlen, void **context)
  85129. +{
  85130. + int cpu = 0;
  85131. +
  85132. + if (oldval && oldlenp) {
  85133. + size_t oldlen;
  85134. +
  85135. + if (get_user(oldlen, oldlenp))
  85136. + return -EFAULT;
  85137. +
  85138. + if (oldlen != sizeof(unsigned int))
  85139. + return -EINVAL;
  85140. +
  85141. + if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
  85142. + put_user(sizeof(unsigned int), oldlenp))
  85143. + return -EFAULT;
  85144. + }
  85145. + if (newval && newlen) {
  85146. + unsigned int freq;
  85147. +
  85148. + if (newlen != sizeof(unsigned int))
  85149. + return -EINVAL;
  85150. +
  85151. + if (get_user(freq, (unsigned int *)newval))
  85152. + return -EFAULT;
  85153. +
  85154. + cpufreq_set(freq);
  85155. + }
  85156. + return 1;
  85157. +}
  85158. +
  85159. +enum {
  85160. + CPU_NR_FREQ_MAX = 1,
  85161. + CPU_NR_FREQ_MIN = 2,
  85162. + CPU_NR_FREQ = 3
  85163. +};
  85164. +
  85165. +static ctl_table ctl_cpu_vars[4] = {
  85166. + {
  85167. + ctl_name: CPU_NR_FREQ_MAX,
  85168. + procname: "speed-max",
  85169. + data: &cpufreq_max(0),
  85170. + maxlen: sizeof(cpufreq_max(0)),
  85171. + mode: 0444,
  85172. + proc_handler: proc_dointvec,
  85173. + },
  85174. + {
  85175. + ctl_name: CPU_NR_FREQ_MIN,
  85176. + procname: "speed-min",
  85177. + data: &cpufreq_min(0),
  85178. + maxlen: sizeof(cpufreq_min(0)),
  85179. + mode: 0444,
  85180. + proc_handler: proc_dointvec,
  85181. + },
  85182. + {
  85183. + ctl_name: CPU_NR_FREQ,
  85184. + procname: "speed",
  85185. + mode: 0644,
  85186. + proc_handler: cpufreq_procctl,
  85187. + strategy: cpufreq_sysctl,
  85188. + },
  85189. + {
  85190. + ctl_name: 0,
  85191. + }
  85192. +};
  85193. +
  85194. +enum {
  85195. + CPU_NR = 1,
  85196. +};
  85197. +
  85198. +static ctl_table ctl_cpu_nr[2] = {
  85199. + {
  85200. + ctl_name: CPU_NR,
  85201. + procname: "0",
  85202. + mode: 0555,
  85203. + child: ctl_cpu_vars,
  85204. + },
  85205. + {
  85206. + ctl_name: 0,
  85207. + }
  85208. +};
  85209. +
  85210. +static ctl_table ctl_cpu[2] = {
  85211. + {
  85212. + ctl_name: CTL_CPU,
  85213. + procname: "cpu",
  85214. + mode: 0555,
  85215. + child: ctl_cpu_nr,
  85216. + },
  85217. + {
  85218. + ctl_name: 0,
  85219. + }
  85220. +};
  85221. +
  85222. +static inline void cpufreq_sysctl_init(void)
  85223. +{
  85224. + register_sysctl_table(ctl_cpu, 0);
  85225. +}
  85226. +
  85227. +#else
  85228. +#define cpufreq_sysctl_init()
  85229. +#endif
  85230. +
  85231. +/**
  85232. + * cpufreq_setfunctions - Set CPU clock functions
  85233. + * @validate: pointer to validation function
  85234. + * @setspeed: pointer to setspeed function
  85235. + */
  85236. +void
  85237. +cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
  85238. + void (*setspeed)(unsigned int))
  85239. +{
  85240. + down(&cpufreq_sem);
  85241. + cpufreq_validatespeed = validate;
  85242. + cpufreq_setspeed = setspeed;
  85243. + up(&cpufreq_sem);
  85244. +}
  85245. +
  85246. +EXPORT_SYMBOL_GPL(cpufreq_setfunctions);
  85247. +
  85248. +/**
  85249. + * cpufreq_init - Initialise the cpufreq core
  85250. + * @freq: current CPU clock speed.
  85251. + * @min_freq: minimum CPU clock speed.
  85252. + * @max_freq: maximum CPU clock speed.
  85253. + *
  85254. + * Initialise the cpufreq core. If the cpufreq_max command line
  85255. + * parameter has not been specified, we set the maximum clock rate
  85256. + * to the current CPU clock rate.
  85257. + */
  85258. +void cpufreq_init(unsigned int freq,
  85259. + unsigned int min_freq,
  85260. + unsigned int max_freq)
  85261. +{
  85262. + /*
  85263. + * If the user doesn't tell us their maximum frequency,
  85264. + * or if it is invalid, use the values determined
  85265. + * by the cpufreq-arch-specific initialization functions.
  85266. + * The validatespeed code is responsible for limiting
  85267. + * this further.
  85268. + */
  85269. + if (max_freq && ((cpufreq_max(0) == 0) || (cpufreq_max(0) > max_freq)))
  85270. + cpufreq_max(0) = max_freq;
  85271. + if (min_freq && ((cpufreq_min(0) == 0) || (cpufreq_min(0) < min_freq)))
  85272. + cpufreq_min(0) = min_freq;
  85273. +
  85274. + if (cpufreq_max(0) == 0)
  85275. + cpufreq_max(0) = freq;
  85276. +
  85277. + printk(KERN_INFO "CPU clock: %d.%03d MHz (%d.%03d-%d.%03d MHz)\n",
  85278. + freq / 1000, freq % 1000,
  85279. + cpufreq_min(0) / 1000, cpufreq_min(0) % 1000,
  85280. + cpufreq_max(0) / 1000, cpufreq_max(0) % 1000);
  85281. +
  85282. + cpufreq_ref_loops = loops_per_jiffy;
  85283. + cpufreq_ref_freq = freq;
  85284. + cpufreq_current(smp_processor_id()) = freq;
  85285. +
  85286. + cpufreq_initialised = 1;
  85287. + up(&cpufreq_sem);
  85288. +
  85289. + cpufreq_sysctl_init();
  85290. +}
  85291. +
  85292. +EXPORT_SYMBOL_GPL(cpufreq_init);
  85293. diff -urN linux-2.4.26/kernel/exit.c linux-2.4.26-vrs1/kernel/exit.c
  85294. --- linux-2.4.26/kernel/exit.c 2002-11-28 23:53:15.000000000 +0000
  85295. +++ linux-2.4.26-vrs1/kernel/exit.c 2004-01-14 21:32:30.000000000 +0000
  85296. @@ -587,7 +587,7 @@
  85297. return retval;
  85298. }
  85299. -#if !defined(__alpha__) && !defined(__ia64__)
  85300. +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
  85301. /*
  85302. * sys_waitpid() remains for compatibility. waitpid() should be
  85303. diff -urN linux-2.4.26/kernel/fork.c linux-2.4.26-vrs1/kernel/fork.c
  85304. --- linux-2.4.26/kernel/fork.c 2004-04-19 11:44:28.000000000 +0100
  85305. +++ linux-2.4.26-vrs1/kernel/fork.c 2004-04-18 21:47:52.000000000 +0100
  85306. @@ -75,7 +75,11 @@
  85307. * value: the thread structures can take up at most half
  85308. * of memory.
  85309. */
  85310. +#if THREAD_SIZE > PAGE_SIZE
  85311. max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8;
  85312. +#else
  85313. + max_threads = (mempages * PAGE_SIZE) / (8 * THREAD_SIZE);
  85314. +#endif
  85315. init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
  85316. init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
  85317. @@ -220,6 +224,7 @@
  85318. fail_nomem:
  85319. flush_tlb_mm(current->mm);
  85320. + memc_update_mm(mm);
  85321. return retval;
  85322. }
  85323. diff -urN linux-2.4.26/kernel/ksyms.c linux-2.4.26-vrs1/kernel/ksyms.c
  85324. --- linux-2.4.26/kernel/ksyms.c 2004-02-27 20:03:29.000000000 +0000
  85325. +++ linux-2.4.26-vrs1/kernel/ksyms.c 2004-02-23 13:36:41.000000000 +0000
  85326. @@ -345,6 +345,7 @@
  85327. /* tty routines */
  85328. EXPORT_SYMBOL(tty_hangup);
  85329. +EXPORT_SYMBOL(tty_vhangup);
  85330. EXPORT_SYMBOL(tty_wait_until_sent);
  85331. EXPORT_SYMBOL(tty_check_change);
  85332. EXPORT_SYMBOL(tty_hung_up_p);
  85333. @@ -439,9 +440,11 @@
  85334. EXPORT_SYMBOL(kiobuf_wait_for_io);
  85335. /* dma handling */
  85336. +#ifdef CONFIG_GENERIC_ISA_DMA
  85337. EXPORT_SYMBOL(request_dma);
  85338. EXPORT_SYMBOL(free_dma);
  85339. EXPORT_SYMBOL(dma_spin_lock);
  85340. +#endif
  85341. #ifdef HAVE_DISABLE_HLT
  85342. EXPORT_SYMBOL(disable_hlt);
  85343. EXPORT_SYMBOL(enable_hlt);
  85344. diff -urN linux-2.4.26/kernel/signal.c linux-2.4.26-vrs1/kernel/signal.c
  85345. --- linux-2.4.26/kernel/signal.c 2004-02-27 20:03:29.000000000 +0000
  85346. +++ linux-2.4.26-vrs1/kernel/signal.c 2004-02-23 13:36:41.000000000 +0000
  85347. @@ -778,8 +778,8 @@
  85348. info.si_uid = tsk->uid;
  85349. /* FIXME: find out whether or not this is supposed to be c*time. */
  85350. - info.si_utime = tsk->times.tms_utime;
  85351. - info.si_stime = tsk->times.tms_stime;
  85352. + info.si_utime = hz_to_std(tsk->times.tms_utime);
  85353. + info.si_stime = hz_to_std(tsk->times.tms_stime);
  85354. status = tsk->exit_code & 0x7f;
  85355. why = SI_KERNEL; /* shouldn't happen */
  85356. @@ -1277,7 +1277,7 @@
  85357. #endif /* __sparc__ */
  85358. #endif
  85359. -#if !defined(__alpha__) && !defined(__ia64__)
  85360. +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
  85361. /*
  85362. * For backwards compatibility. Functionality superseded by sigprocmask.
  85363. */
  85364. @@ -1305,7 +1305,8 @@
  85365. }
  85366. #endif /* !defined(__alpha__) */
  85367. -#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__)
  85368. +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && \
  85369. + !defined(__arm__)
  85370. /*
  85371. * For backwards compatibility. Functionality superseded by sigaction.
  85372. */
  85373. @@ -1322,4 +1323,4 @@
  85374. return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
  85375. }
  85376. -#endif /* !alpha && !__ia64__ && !defined(__mips__) */
  85377. +#endif /* !alpha && !__ia64__ && !defined(__mips__) && !defined(__arm__) */
  85378. diff -urN linux-2.4.26/kernel/sys.c linux-2.4.26-vrs1/kernel/sys.c
  85379. --- linux-2.4.26/kernel/sys.c 2003-11-28 18:26:21.000000000 +0000
  85380. +++ linux-2.4.26-vrs1/kernel/sys.c 2004-01-14 21:39:29.000000000 +0000
  85381. @@ -801,16 +801,23 @@
  85382. asmlinkage long sys_times(struct tms * tbuf)
  85383. {
  85384. + struct tms temp;
  85385. +
  85386. /*
  85387. * In the SMP world we might just be unlucky and have one of
  85388. * the times increment as we use it. Since the value is an
  85389. * atomically safe type this is just fine. Conceptually its
  85390. * as if the syscall took an instant longer to occur.
  85391. */
  85392. - if (tbuf)
  85393. - if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
  85394. + if (tbuf) {
  85395. + temp.tms_utime = hz_to_std(current->times.tms_utime);
  85396. + temp.tms_stime = hz_to_std(current->times.tms_stime);
  85397. + temp.tms_cutime = hz_to_std(current->times.tms_cutime);
  85398. + temp.tms_cstime = hz_to_std(current->times.tms_cstime);
  85399. + if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
  85400. return -EFAULT;
  85401. - return jiffies;
  85402. + }
  85403. + return hz_to_std(jiffies);
  85404. }
  85405. /*
  85406. diff -urN linux-2.4.26/lib/string.c linux-2.4.26-vrs1/lib/string.c
  85407. --- linux-2.4.26/lib/string.c 2002-08-03 01:39:46.000000000 +0100
  85408. +++ linux-2.4.26-vrs1/lib/string.c 2004-01-14 21:32:30.000000000 +0000
  85409. @@ -188,10 +188,10 @@
  85410. */
  85411. char * strchr(const char * s, int c)
  85412. {
  85413. - for(; *s != (char) c; ++s)
  85414. - if (*s == '\0')
  85415. - return NULL;
  85416. - return (char *) s;
  85417. + for(; *s != '\0'; ++s)
  85418. + if (*s == (char) c)
  85419. + return (char *) s;
  85420. + return NULL;
  85421. }
  85422. #endif
  85423. diff -urN linux-2.4.26/mm/Makefile linux-2.4.26-vrs1/mm/Makefile
  85424. --- linux-2.4.26/mm/Makefile 2002-08-03 01:39:46.000000000 +0100
  85425. +++ linux-2.4.26-vrs1/mm/Makefile 2004-01-14 21:32:30.000000000 +0000
  85426. @@ -18,4 +18,5 @@
  85427. obj-$(CONFIG_HIGHMEM) += highmem.o
  85428. +obj-y += debug.o
  85429. include $(TOPDIR)/Rules.make
  85430. diff -urN linux-2.4.26/mm/debug.c linux-2.4.26-vrs1/mm/debug.c
  85431. --- linux-2.4.26/mm/debug.c 1970-01-01 01:00:00.000000000 +0100
  85432. +++ linux-2.4.26-vrs1/mm/debug.c 2004-02-23 00:34:41.000000000 +0000
  85433. @@ -0,0 +1,159 @@
  85434. +/*
  85435. + * linux/mm/debug.c
  85436. + *
  85437. + * Copyright (C) 2001 Russell King.
  85438. + *
  85439. + * This program is free software; you can redistribute it and/or modify
  85440. + * it under the terms of the GNU General Public License version 2 as
  85441. + * published by the Free Software Foundation.
  85442. + *
  85443. + * Dump out page information on SysRQ-G, and provide show_page_info()
  85444. + *
  85445. + * You are advised to use a serial console with this patch - it
  85446. + * saturates a 38400baud link for 1 minute on a 32MB machine.
  85447. + */
  85448. +#include <linux/kernel.h>
  85449. +#include <linux/mm.h>
  85450. +#include <linux/pagemap.h>
  85451. +#include <linux/sysrq.h>
  85452. +#include <linux/init.h>
  85453. +
  85454. +/*
  85455. + * We print out the following information for each page in the system:
  85456. + * address: use count, age, mapping, [RSsr] rD [acd]
  85457. + *
  85458. + * The flags are:
  85459. + * R - reserved
  85460. + * S - in swapcache
  85461. + * s - slab page
  85462. + *
  85463. + * r - referenced
  85464. + * D - dirty
  85465. + *
  85466. + * a - active page
  85467. + */
  85468. +static void page_detail(struct page *page)
  85469. +{
  85470. + if (!page)
  85471. + return;
  85472. +
  85473. + printk("%p: %2d %p [%c%c%c] %c%c [%c]\n",
  85474. + page_address(page),
  85475. + page_count(page),
  85476. + page->mapping,
  85477. +
  85478. + PageReserved(page) ? 'R' : '-',
  85479. + PageSwapCache(page) ? 'S' : '-',
  85480. + PageSlab(page) ? 's' : '-',
  85481. +
  85482. + PageReferenced(page) ? 'r' : '-',
  85483. + PageDirty(page) ? 'D' : '-',
  85484. +
  85485. + PageActive(page) ? 'a' : '-');
  85486. +}
  85487. +
  85488. +/*
  85489. + * This version collects statistics
  85490. + */
  85491. +static int anon_pages, slab_pages, resvd_pages, unused_pages;
  85492. +
  85493. +static void page_statistics(struct page *page)
  85494. +{
  85495. + if (page) {
  85496. + if (PageReserved(page))
  85497. + resvd_pages++;
  85498. + else if (PageSlab(page))
  85499. + slab_pages++;
  85500. + else if (!page_count(page))
  85501. + unused_pages ++;
  85502. + else if (!page->mapping)
  85503. + anon_pages ++;
  85504. + return;
  85505. + }
  85506. +
  85507. + printk(" anon: %d, slab: %d, reserved: %d, free: %d\n",
  85508. + anon_pages, slab_pages, resvd_pages, unused_pages);
  85509. +}
  85510. +
  85511. +static void show_zone_info(zone_t *zone, void (*fn)(struct page *))
  85512. +{
  85513. + int i;
  85514. +
  85515. + printk(" total %ld, free %ld\n",
  85516. + zone->size, zone->free_pages);
  85517. +
  85518. + anon_pages = 0;
  85519. + slab_pages = 0;
  85520. + resvd_pages = 0;
  85521. + unused_pages = 0;
  85522. +
  85523. + for (i = 0; i < zone->size; i++) {
  85524. + struct page *page = zone->zone_mem_map + i;
  85525. +
  85526. + fn(page);
  85527. + }
  85528. +
  85529. + fn(NULL);
  85530. +}
  85531. +
  85532. +static void show_node_info(pg_data_t *pg, void (*fn)(struct page *))
  85533. +{
  85534. + int type;
  85535. +
  85536. + for (type = 0; type < MAX_NR_ZONES; type++) {
  85537. + zone_t *zone = pg->node_zones + type;
  85538. +
  85539. + if (zone->size == 0)
  85540. + continue;
  85541. +
  85542. + printk("----- Zone %d ------\n", type);
  85543. +
  85544. + show_zone_info(zone, fn);
  85545. + }
  85546. +}
  85547. +
  85548. +static void __show_page_info(void (*fn)(struct page *))
  85549. +{
  85550. + pg_data_t *pg;
  85551. + int pgdat = 0;
  85552. +
  85553. + for (pg = pgdat_list; pg; pg = pg->node_next) {
  85554. +
  85555. + printk("===== Node %d =====\n", pgdat++);
  85556. +
  85557. + show_node_info(pg, fn);
  85558. + }
  85559. +}
  85560. +
  85561. +void show_page_info(void)
  85562. +{
  85563. + __show_page_info(page_detail);
  85564. +}
  85565. +
  85566. +static void
  85567. +show_pg_info(int key, struct pt_regs *regs, struct kbd_struct *kd,
  85568. + struct tty_struct *tty)
  85569. +{
  85570. + void (*fn)(struct page *);
  85571. + show_mem();
  85572. + if (key == 'g')
  85573. + fn = page_detail;
  85574. + else
  85575. + fn = page_statistics;
  85576. + __show_page_info(fn);
  85577. +}
  85578. +
  85579. +static struct sysrq_key_op page_info_op = {
  85580. + handler: show_pg_info,
  85581. + help_msg: "paGeinfo",
  85582. + action_msg: "Page Info",
  85583. +};
  85584. +
  85585. +static int __init debug_mm_init(void)
  85586. +{
  85587. + register_sysrq_key('g', &page_info_op);
  85588. + register_sysrq_key('h', &page_info_op);
  85589. + return 0;
  85590. +}
  85591. +
  85592. +__initcall(debug_mm_init);
  85593. diff -urN linux-2.4.26/mm/filemap.c linux-2.4.26-vrs1/mm/filemap.c
  85594. --- linux-2.4.26/mm/filemap.c 2004-04-19 11:44:28.000000000 +0100
  85595. +++ linux-2.4.26-vrs1/mm/filemap.c 2004-04-18 21:47:52.000000000 +0100
  85596. @@ -2210,10 +2210,14 @@
  85597. pte_t pte = *ptep;
  85598. if (pte_present(pte)) {
  85599. - struct page *page = pte_page(pte);
  85600. - if (VALID_PAGE(page) && !PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
  85601. - flush_tlb_page(vma, address);
  85602. - set_page_dirty(page);
  85603. + unsigned long pfn = pte_pfn(pte);
  85604. +
  85605. + if (pfn_valid(pfn)) {
  85606. + struct page *page = pfn_to_page(pfn);
  85607. + if (!PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
  85608. + flush_tlb_page(vma, address);
  85609. + set_page_dirty(page);
  85610. + }
  85611. }
  85612. }
  85613. return 0;
  85614. diff -urN linux-2.4.26/mm/memory.c linux-2.4.26-vrs1/mm/memory.c
  85615. --- linux-2.4.26/mm/memory.c 2003-11-28 18:26:21.000000000 +0000
  85616. +++ linux-2.4.26-vrs1/mm/memory.c 2004-01-14 21:39:29.000000000 +0000
  85617. @@ -77,8 +77,13 @@
  85618. */
  85619. void __free_pte(pte_t pte)
  85620. {
  85621. - struct page *page = pte_page(pte);
  85622. - if ((!VALID_PAGE(page)) || PageReserved(page))
  85623. + unsigned long pfn = pte_pfn(pte);
  85624. + struct page *page;
  85625. +
  85626. + if (!pfn_valid(pfn))
  85627. + return;
  85628. + page = pfn_to_page(pfn);
  85629. + if (PageReserved(page))
  85630. return;
  85631. if (pte_dirty(pte))
  85632. set_page_dirty(page);
  85633. @@ -232,6 +237,7 @@
  85634. do {
  85635. pte_t pte = *src_pte;
  85636. struct page *ptepage;
  85637. + unsigned long pfn;
  85638. /* copy_one_pte */
  85639. @@ -241,9 +247,11 @@
  85640. swap_duplicate(pte_to_swp_entry(pte));
  85641. goto cont_copy_pte_range;
  85642. }
  85643. - ptepage = pte_page(pte);
  85644. - if ((!VALID_PAGE(ptepage)) ||
  85645. - PageReserved(ptepage))
  85646. + pfn = pte_pfn(pte);
  85647. + if (!pfn_valid(pfn))
  85648. + goto cont_copy_pte_range;
  85649. + ptepage = pfn_to_page(pfn);
  85650. + if (PageReserved(ptepage))
  85651. goto cont_copy_pte_range;
  85652. /* If it's a COW mapping, write protect it both in the parent and the child */
  85653. @@ -314,9 +322,13 @@
  85654. if (pte_none(pte))
  85655. continue;
  85656. if (pte_present(pte)) {
  85657. - struct page *page = pte_page(pte);
  85658. - if (VALID_PAGE(page) && !PageReserved(page))
  85659. - freed ++;
  85660. + unsigned long pfn = pte_pfn(pte);
  85661. +
  85662. + if (pfn_valid(pfn)) {
  85663. + struct page *page = pfn_to_page(pfn);
  85664. + if (!PageReserved(page))
  85665. + freed ++;
  85666. + }
  85667. /* This will eventually call __free_pte on the pte. */
  85668. tlb_remove_page(tlb, ptep, address + offset);
  85669. } else {
  85670. @@ -354,17 +366,37 @@
  85671. return freed;
  85672. }
  85673. +void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long address, unsigned long end)
  85674. +{
  85675. + int freed = 0;
  85676. + pgd_t * dir;
  85677. +
  85678. + if (address >= end)
  85679. + BUG();
  85680. + dir = pgd_offset(mm, address);
  85681. + do {
  85682. + freed += zap_pmd_range(tlb, dir, address, end - address);
  85683. + address = (address + PGDIR_SIZE) & PGDIR_MASK;
  85684. + dir++;
  85685. + } while (address && (address < end));
  85686. +
  85687. + /*
  85688. + * Update rss for the mm_struct (not necessarily current->mm)
  85689. + * Notice that rss is an unsigned long.
  85690. + */
  85691. + if (mm->rss > freed)
  85692. + mm->rss -= freed;
  85693. + else
  85694. + mm->rss = 0;
  85695. +}
  85696. +
  85697. /*
  85698. * remove user pages in a given range.
  85699. */
  85700. void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
  85701. {
  85702. - mmu_gather_t *tlb;
  85703. - pgd_t * dir;
  85704. unsigned long start = address, end = address + size;
  85705. - int freed = 0;
  85706. -
  85707. - dir = pgd_offset(mm, address);
  85708. + mmu_gather_t *tlb;
  85709. /*
  85710. * This is a long-lived spinlock. That's fine.
  85711. @@ -377,25 +409,10 @@
  85712. BUG();
  85713. spin_lock(&mm->page_table_lock);
  85714. flush_cache_range(mm, address, end);
  85715. - tlb = tlb_gather_mmu(mm);
  85716. -
  85717. - do {
  85718. - freed += zap_pmd_range(tlb, dir, address, end - address);
  85719. - address = (address + PGDIR_SIZE) & PGDIR_MASK;
  85720. - dir++;
  85721. - } while (address && (address < end));
  85722. - /* this will flush any remaining tlb entries */
  85723. + tlb = tlb_gather_mmu(mm);
  85724. + unmap_page_range(tlb, mm, address, end);
  85725. tlb_finish_mmu(tlb, start, end);
  85726. -
  85727. - /*
  85728. - * Update rss for the mm_struct (not necessarily current->mm)
  85729. - * Notice that rss is an unsigned long.
  85730. - */
  85731. - if (mm->rss > freed)
  85732. - mm->rss -= freed;
  85733. - else
  85734. - mm->rss = 0;
  85735. spin_unlock(&mm->page_table_lock);
  85736. }
  85737. @@ -407,6 +424,7 @@
  85738. pgd_t *pgd;
  85739. pmd_t *pmd;
  85740. pte_t *ptep, pte;
  85741. + unsigned long pfn;
  85742. pgd = pgd_offset(mm, address);
  85743. if (pgd_none(*pgd) || pgd_bad(*pgd))
  85744. @@ -423,8 +441,11 @@
  85745. pte = *ptep;
  85746. if (pte_present(pte)) {
  85747. if (!write ||
  85748. - (pte_write(pte) && pte_dirty(pte)))
  85749. - return pte_page(pte);
  85750. + (pte_write(pte) && pte_dirty(pte))) {
  85751. + pfn = pte_pfn(pte);
  85752. + if (pfn_valid(pfn))
  85753. + return pfn_to_page(pfn);
  85754. + }
  85755. }
  85756. out:
  85757. @@ -439,7 +460,8 @@
  85758. static inline struct page * get_page_map(struct page *page)
  85759. {
  85760. - if (!VALID_PAGE(page))
  85761. + unsigned long pfn = page_to_pfn(page);
  85762. + if (!pfn_valid(pfn))
  85763. return 0;
  85764. return page;
  85765. }
  85766. @@ -826,22 +848,22 @@
  85767. unsigned long phys_addr, pgprot_t prot)
  85768. {
  85769. unsigned long end;
  85770. + unsigned long pfn;
  85771. address &= ~PMD_MASK;
  85772. end = address + size;
  85773. if (end > PMD_SIZE)
  85774. end = PMD_SIZE;
  85775. + pfn = phys_addr >> PAGE_SHIFT;
  85776. do {
  85777. - struct page *page;
  85778. pte_t oldpage;
  85779. oldpage = ptep_get_and_clear(pte);
  85780. - page = virt_to_page(__va(phys_addr));
  85781. - if ((!VALID_PAGE(page)) || PageReserved(page))
  85782. - set_pte(pte, mk_pte_phys(phys_addr, prot));
  85783. + if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
  85784. + set_pte(pte, pfn_pte(pfn, prot));
  85785. forget_pte(oldpage);
  85786. address += PAGE_SIZE;
  85787. - phys_addr += PAGE_SIZE;
  85788. + pfn++;
  85789. pte++;
  85790. } while (address && (address < end));
  85791. }
  85792. @@ -949,10 +971,11 @@
  85793. unsigned long address, pte_t *page_table, pte_t pte)
  85794. {
  85795. struct page *old_page, *new_page;
  85796. + unsigned long pfn = pte_pfn(pte);
  85797. - old_page = pte_page(pte);
  85798. - if (!VALID_PAGE(old_page))
  85799. + if (!pfn_valid(pfn))
  85800. goto bad_wp_page;
  85801. + old_page = pte_page(pte);
  85802. if (!TryLockPage(old_page)) {
  85803. int reuse = can_share_swap_page(old_page);
  85804. @@ -996,7 +1019,7 @@
  85805. bad_wp_page:
  85806. spin_unlock(&mm->page_table_lock);
  85807. - printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
  85808. + printk("do_wp_page: bogus page at address %08lx\n", address);
  85809. return -1;
  85810. no_mem:
  85811. page_cache_release(old_page);
  85812. diff -urN linux-2.4.26/mm/mmap.c linux-2.4.26-vrs1/mm/mmap.c
  85813. --- linux-2.4.26/mm/mmap.c 2004-02-27 20:03:29.000000000 +0000
  85814. +++ linux-2.4.26-vrs1/mm/mmap.c 2004-02-23 13:36:41.000000000 +0000
  85815. @@ -18,6 +18,9 @@
  85816. #include <asm/uaccess.h>
  85817. #include <asm/pgalloc.h>
  85818. +#include <asm/tlb.h>
  85819. +
  85820. +extern void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long start, unsigned long end);
  85821. /*
  85822. * WARNING: the debugging will use recursive algorithms so never enable this
  85823. @@ -915,6 +918,8 @@
  85824. * old method of shifting the VA >> by PGDIR_SHIFT doesn't work.
  85825. */
  85826. start_index = pgd_index(first);
  85827. + if (start_index < FIRST_USER_PGD_NR)
  85828. + start_index = FIRST_USER_PGD_NR;
  85829. end_index = pgd_index(last);
  85830. if (end_index > start_index) {
  85831. clear_page_tables(mm, start_index, end_index - start_index);
  85832. @@ -1046,7 +1051,6 @@
  85833. len = PAGE_ALIGN(len);
  85834. if (!len)
  85835. return addr;
  85836. -
  85837. if ((addr + len) > TASK_SIZE || (addr + len) < addr)
  85838. return -EINVAL;
  85839. @@ -1135,45 +1139,58 @@
  85840. /* Release all mmaps. */
  85841. void exit_mmap(struct mm_struct * mm)
  85842. {
  85843. + mmu_gather_t *tlb;
  85844. struct vm_area_struct * mpnt;
  85845. release_segments(mm);
  85846. spin_lock(&mm->page_table_lock);
  85847. +
  85848. + tlb = tlb_gather_mmu(mm);
  85849. +
  85850. + flush_cache_mm(mm);
  85851. + mpnt = mm->mmap;
  85852. + while (mpnt) {
  85853. + unsigned long start = mpnt->vm_start;
  85854. + unsigned long end = mpnt->vm_end;
  85855. +
  85856. + mm->map_count--;
  85857. + remove_shared_vm_struct(mpnt);
  85858. + unmap_page_range(tlb, mm, start, end);
  85859. + mpnt = mpnt->vm_next;
  85860. + }
  85861. +
  85862. + /* This is just debugging */
  85863. + if (mm->map_count)
  85864. + BUG();
  85865. +
  85866. + tlb_finish_mmu(tlb, 0, TASK_SIZE);
  85867. +
  85868. mpnt = mm->mmap;
  85869. mm->mmap = mm->mmap_cache = NULL;
  85870. mm->mm_rb = RB_ROOT;
  85871. mm->rss = 0;
  85872. - spin_unlock(&mm->page_table_lock);
  85873. mm->total_vm = 0;
  85874. mm->locked_vm = 0;
  85875. - flush_cache_mm(mm);
  85876. + spin_unlock(&mm->page_table_lock);
  85877. +
  85878. + clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
  85879. +
  85880. + /*
  85881. + * Walk the list again, actually closing and freeing it
  85882. + * without holding any MM locks.
  85883. + */
  85884. while (mpnt) {
  85885. struct vm_area_struct * next = mpnt->vm_next;
  85886. - unsigned long start = mpnt->vm_start;
  85887. - unsigned long end = mpnt->vm_end;
  85888. - unsigned long size = end - start;
  85889. -
  85890. if (mpnt->vm_ops) {
  85891. if (mpnt->vm_ops->close)
  85892. mpnt->vm_ops->close(mpnt);
  85893. }
  85894. - mm->map_count--;
  85895. - remove_shared_vm_struct(mpnt);
  85896. - zap_page_range(mm, start, size);
  85897. if (mpnt->vm_file)
  85898. fput(mpnt->vm_file);
  85899. kmem_cache_free(vm_area_cachep, mpnt);
  85900. mpnt = next;
  85901. }
  85902. -
  85903. - /* This is just debugging */
  85904. - if (mm->map_count)
  85905. - BUG();
  85906. -
  85907. - clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
  85908. -
  85909. - flush_tlb_mm(mm);
  85910. }
  85911. /* Insert vm structure into process list sorted by address
  85912. diff -urN linux-2.4.26/mm/slab.c linux-2.4.26-vrs1/mm/slab.c
  85913. --- linux-2.4.26/mm/slab.c 2003-11-28 18:26:21.000000000 +0000
  85914. +++ linux-2.4.26-vrs1/mm/slab.c 2004-01-14 21:39:29.000000000 +0000
  85915. @@ -1391,7 +1391,7 @@
  85916. #if DEBUG
  85917. # define CHECK_NR(pg) \
  85918. do { \
  85919. - if (!VALID_PAGE(pg)) { \
  85920. + if (!virt_addr_valid(pg)) { \
  85921. printk(KERN_ERR "kfree: out of range ptr %lxh.\n", \
  85922. (unsigned long)objp); \
  85923. BUG(); \
  85924. @@ -1950,12 +1950,12 @@
  85925. name = cachep->name;
  85926. {
  85927. char tmp;
  85928. - mm_segment_t old_fs;
  85929. + mm_segment_t old_fs;
  85930. old_fs = get_fs();
  85931. set_fs(KERNEL_DS);
  85932. if (__get_user(tmp, name))
  85933. name = "broken";
  85934. - set_fs(old_fs);
  85935. + set_fs (old_fs);
  85936. }
  85937. seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
  85938. diff -urN linux-2.4.26/mm/vmalloc.c linux-2.4.26-vrs1/mm/vmalloc.c
  85939. --- linux-2.4.26/mm/vmalloc.c 2004-04-19 11:44:28.000000000 +0100
  85940. +++ linux-2.4.26-vrs1/mm/vmalloc.c 2004-04-18 21:47:52.000000000 +0100
  85941. @@ -44,8 +44,13 @@
  85942. if (pte_none(page))
  85943. continue;
  85944. if (pte_present(page)) {
  85945. - struct page *ptpage = pte_page(page);
  85946. - if (VALID_PAGE(ptpage) && (!PageReserved(ptpage)))
  85947. + unsigned long pfn = pte_pfn(page);
  85948. + struct page *ptpage;
  85949. +
  85950. + if (!pfn_valid(pfn))
  85951. + continue;
  85952. + ptpage = pfn_to_page(pfn);
  85953. + if (!PageReserved(ptpage))
  85954. __free_page(ptpage);
  85955. continue;
  85956. }
  85957. diff -urN linux-2.4.26/mm/vmscan.c linux-2.4.26-vrs1/mm/vmscan.c
  85958. --- linux-2.4.26/mm/vmscan.c 2004-02-27 20:03:29.000000000 +0000
  85959. +++ linux-2.4.26-vrs1/mm/vmscan.c 2004-02-23 13:36:41.000000000 +0000
  85960. @@ -121,6 +121,7 @@
  85961. drop_pte:
  85962. mm->rss--;
  85963. UnlockPage(page);
  85964. + memc_clear(vma->vm_mm, page);
  85965. {
  85966. int freeable = page_count(page) - !!page->buffers <= 2;
  85967. page_cache_release(page);
  85968. @@ -206,13 +207,16 @@
  85969. do {
  85970. if (pte_present(*pte)) {
  85971. - struct page *page = pte_page(*pte);
  85972. + unsigned long pfn = pte_pfn(*pte);
  85973. - if (VALID_PAGE(page) && !PageReserved(page)) {
  85974. - count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
  85975. - if (!count) {
  85976. - address += PAGE_SIZE;
  85977. - break;
  85978. + if (pfn_valid(pfn)) {
  85979. + struct page *page = pfn_to_page(pfn);
  85980. + if (!PageReserved(page)) {
  85981. + count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
  85982. + if (!count) {
  85983. + address += PAGE_SIZE;
  85984. + break;
  85985. + }
  85986. }
  85987. }
  85988. }
  85989. diff -urN linux-2.4.26/net/irda/af_irda.c linux-2.4.26-vrs1/net/irda/af_irda.c
  85990. --- linux-2.4.26/net/irda/af_irda.c 2003-11-28 18:26:21.000000000 +0000
  85991. +++ linux-2.4.26-vrs1/net/irda/af_irda.c 2004-01-14 21:39:30.000000000 +0000
  85992. @@ -1176,7 +1176,7 @@
  85993. #endif /* CONFIG_IRDA_ULTRA */
  85994. kfree(self);
  85995. MOD_DEC_USE_COUNT;
  85996. -
  85997. +
  85998. return;
  85999. }
  86000. @@ -2571,19 +2571,15 @@
  86001. sock_register(&irda_family_ops);
  86002. irda_packet_type.type = htons(ETH_P_IRDA);
  86003. - dev_add_pack(&irda_packet_type);
  86004. + dev_add_pack(&irda_packet_type);
  86005. register_netdevice_notifier(&irda_dev_notifier);
  86006. -
  86007. irda_init();
  86008. #ifdef MODULE
  86009. - irda_device_init(); /* Called by init/main.c when non-modular */
  86010. + irda_device_init(); /* Called by init/main.c when non-modular */
  86011. #endif
  86012. return 0;
  86013. }
  86014. -#ifdef MODULE
  86015. -module_init(irda_proto_init); /* If non-module, called from init/main.c */
  86016. -#endif
  86017. /*
  86018. * Function irda_proto_cleanup (void)
  86019. @@ -2591,25 +2587,27 @@
  86020. * Remove IrDA protocol layer
  86021. *
  86022. */
  86023. -#ifdef MODULE
  86024. -void irda_proto_cleanup(void)
  86025. +static void __exit irda_proto_cleanup(void)
  86026. {
  86027. irda_packet_type.type = htons(ETH_P_IRDA);
  86028. - dev_remove_pack(&irda_packet_type);
  86029. + dev_remove_pack(&irda_packet_type);
  86030. +
  86031. + unregister_netdevice_notifier(&irda_dev_notifier);
  86032. - unregister_netdevice_notifier(&irda_dev_notifier);
  86033. -
  86034. sock_unregister(PF_IRDA);
  86035. +
  86036. irda_cleanup();
  86037. -
  86038. - return;
  86039. }
  86040. +
  86041. +#ifdef MODULE
  86042. +module_init(irda_proto_init);
  86043. module_exit(irda_proto_cleanup);
  86044. -
  86045. +
  86046. MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
  86047. -MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
  86048. +MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
  86049. MODULE_LICENSE("GPL");
  86050. #ifdef CONFIG_IRDA_DEBUG
  86051. MODULE_PARM(irda_debug, "1l");
  86052. #endif
  86053. -#endif /* MODULE */
  86054. +#endif
  86055. +
  86056. diff -urN linux-2.4.26/net/irda/iriap.c linux-2.4.26-vrs1/net/irda/iriap.c
  86057. --- linux-2.4.26/net/irda/iriap.c 2002-11-28 23:53:16.000000000 +0000
  86058. +++ linux-2.4.26-vrs1/net/irda/iriap.c 2004-01-14 21:32:30.000000000 +0000
  86059. @@ -1004,18 +1004,20 @@
  86060. switch (attrib->value->type) {
  86061. case IAS_INTEGER:
  86062. - len += sprintf(buf+len, "%d\n",
  86063. + len += sprintf(buf+len, "%d",
  86064. attrib->value->t.integer);
  86065. break;
  86066. case IAS_STRING:
  86067. - len += sprintf(buf+len, "\"%s\"\n",
  86068. + len += sprintf(buf+len, "\"%s\"",
  86069. attrib->value->t.string);
  86070. break;
  86071. case IAS_OCT_SEQ:
  86072. - len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
  86073. + len += sprintf(buf+len,
  86074. + "octet sequence (%d bytes)",
  86075. + attrib->value->len);
  86076. break;
  86077. case IAS_MISSING:
  86078. - len += sprintf(buf+len, "missing\n");
  86079. + len += sprintf(buf+len, "missing");
  86080. break;
  86081. default:
  86082. IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
  86083. @@ -1027,6 +1029,7 @@
  86084. hashbin_get_next(obj->attribs);
  86085. }
  86086. obj = (struct ias_object *) hashbin_get_next(objects);
  86087. + len += sprintf(buf+len, "\n");
  86088. }
  86089. restore_flags(flags);
  86090. diff -urN linux-2.4.26/net/irda/irlan/irlan_common.c linux-2.4.26-vrs1/net/irda/irlan/irlan_common.c
  86091. --- linux-2.4.26/net/irda/irlan/irlan_common.c 2003-11-28 18:26:21.000000000 +0000
  86092. +++ linux-2.4.26-vrs1/net/irda/irlan/irlan_common.c 2004-01-14 21:39:31.000000000 +0000
  86093. @@ -317,6 +317,9 @@
  86094. del_timer(&self->watchdog_timer);
  86095. + /* since irlan_do_*_event gobble the skb, we must get it once -- rmk */
  86096. + skb_get(skb);
  86097. +
  86098. /* If you want to pass the skb to *both* state machines, you will
  86099. * need to skb_clone() it, so that you don't free it twice.
  86100. * As the state machines don't need it, git rid of it here...
  86101. diff -urN linux-2.4.26/net/irda/irlap_event.c linux-2.4.26-vrs1/net/irda/irlap_event.c
  86102. --- linux-2.4.26/net/irda/irlap_event.c 2003-11-28 18:26:21.000000000 +0000
  86103. +++ linux-2.4.26-vrs1/net/irda/irlap_event.c 2004-01-14 21:39:31.000000000 +0000
  86104. @@ -532,7 +532,7 @@
  86105. #endif /* CONFIG_IRDA_ULTRA */
  86106. case RECV_TEST_CMD:
  86107. /* Remove test frame header */
  86108. - skb_pull(skb, sizeof(struct test_frame));
  86109. + skb_pull(skb, 10 /*sizeof(struct test_frame)*/);
  86110. /*
  86111. * Send response. This skb will not be sent out again, and
  86112. @@ -740,7 +740,7 @@
  86113. switch (event) {
  86114. case CONNECT_RESPONSE:
  86115. - skb_pull(skb, sizeof(struct snrm_frame));
  86116. + skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
  86117. ASSERT(self->netdev != NULL, return -1;);
  86118. @@ -870,7 +870,7 @@
  86119. ASSERT(self->netdev != NULL, return -1;);
  86120. - skb_pull(skb, sizeof(struct snrm_frame));
  86121. + skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
  86122. irlap_qos_negotiate(self, skb);
  86123. @@ -902,7 +902,7 @@
  86124. /* Negotiate connection parameters */
  86125. ASSERT(skb->len > 10, return -1;);
  86126. - skb_pull(skb, sizeof(struct ua_frame));
  86127. + skb_pull(skb, 10 /*sizeof(struct ua_frame)*/);
  86128. ASSERT(self->netdev != NULL, return -1;);
  86129. diff -urN linux-2.4.26/net/irda/irlap_frame.c linux-2.4.26-vrs1/net/irda/irlap_frame.c
  86130. --- linux-2.4.26/net/irda/irlap_frame.c 2003-11-28 18:26:21.000000000 +0000
  86131. +++ linux-2.4.26-vrs1/net/irda/irlap_frame.c 2004-02-22 11:42:55.000000000 +0000
  86132. @@ -1,5 +1,5 @@
  86133. /*********************************************************************
  86134. - *
  86135. + *
  86136. * Filename: irlap_frame.c
  86137. * Version: 1.0
  86138. * Description: Build and transmit IrLAP frames
  86139. @@ -8,18 +8,18 @@
  86140. * Created at: Tue Aug 19 10:27:26 1997
  86141. * Modified at: Wed Jan 5 08:59:04 2000
  86142. * Modified by: Dag Brattli <dagb@cs.uit.no>
  86143. - *
  86144. - * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  86145. + *
  86146. + * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  86147. * All Rights Reserved.
  86148. * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
  86149. - *
  86150. - * This program is free software; you can redistribute it and/or
  86151. - * modify it under the terms of the GNU General Public License as
  86152. - * published by the Free Software Foundation; either version 2 of
  86153. + *
  86154. + * This program is free software; you can redistribute it and/or
  86155. + * modify it under the terms of the GNU General Public License as
  86156. + * published by the Free Software Foundation; either version 2 of
  86157. * the License, or (at your option) any later version.
  86158. *
  86159. * Neither Dag Brattli nor University of Tromsø admit liability nor
  86160. - * provide warranty for any of this software. This material is
  86161. + * provide warranty for any of this software. This material is
  86162. * provided "AS-IS" and at no charge.
  86163. *
  86164. ********************************************************************/
  86165. @@ -29,11 +29,12 @@
  86166. #include <linux/if_ether.h>
  86167. #include <linux/netdevice.h>
  86168. #include <linux/irda.h>
  86169. -
  86170. +
  86171. #include <net/pkt_sched.h>
  86172. #include <net/sock.h>
  86173. -
  86174. +
  86175. #include <asm/byteorder.h>
  86176. +#include <asm/unaligned.h>
  86177. #include <net/irda/irda.h>
  86178. #include <net/irda/irda_device.h>
  86179. @@ -46,18 +47,18 @@
  86180. /*
  86181. * Function irlap_insert_info (self, skb)
  86182. *
  86183. - * Insert minimum turnaround time and speed information into the skb. We
  86184. + * Insert minimum turnaround time and speed information into the skb. We
  86185. * need to do this since it's per packet relevant information. Safe to
  86186. * have this function inlined since it's only called from one place
  86187. */
  86188. -static inline void irlap_insert_info(struct irlap_cb *self,
  86189. +static inline void irlap_insert_info(struct irlap_cb *self,
  86190. struct sk_buff *skb)
  86191. {
  86192. struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
  86193. - /*
  86194. + /*
  86195. * Insert MTT (min. turn time) and speed into skb, so that the
  86196. - * device driver knows which settings to use
  86197. + * device driver knows which settings to use
  86198. */
  86199. cb->magic = LAP_MAGIC;
  86200. cb->mtt = self->mtt_required;
  86201. @@ -65,15 +66,15 @@
  86202. /* Reset */
  86203. self->mtt_required = 0;
  86204. -
  86205. - /*
  86206. - * Delay equals negotiated BOFs count, plus the number of BOFs to
  86207. - * force the negotiated minimum turnaround time
  86208. +
  86209. + /*
  86210. + * Delay equals negotiated BOFs count, plus the number of BOFs to
  86211. + * force the negotiated minimum turnaround time
  86212. */
  86213. cb->xbofs = self->bofs_count;
  86214. cb->next_xbofs = self->next_bofs;
  86215. cb->xbofs_delay = self->xbofs_delay;
  86216. -
  86217. +
  86218. /* Reset XBOF's delay (used only for getting min turn time) */
  86219. self->xbofs_delay = 0;
  86220. /* Put the correct xbofs value for the next packet */
  86221. @@ -104,7 +105,7 @@
  86222. *
  86223. * Transmits a connect SNRM command frame
  86224. */
  86225. -void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
  86226. +void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
  86227. {
  86228. struct sk_buff *skb;
  86229. struct snrm_frame *frame;
  86230. @@ -118,7 +119,7 @@
  86231. if (!skb)
  86232. return;
  86233. - frame = (struct snrm_frame *) skb_put(skb, 2);
  86234. + frame = (struct snrm_frame *) skb_put(skb, 2);
  86235. /* Insert connection address field */
  86236. if (qos)
  86237. @@ -128,17 +129,17 @@
  86238. /* Insert control field */
  86239. frame->control = SNRM_CMD | PF_BIT;
  86240. -
  86241. +
  86242. /*
  86243. - * If we are establishing a connection then insert QoS paramerters
  86244. + * If we are establishing a connection then insert QoS paramerters
  86245. */
  86246. if (qos) {
  86247. skb_put(skb, 9); /* 21 left */
  86248. - frame->saddr = cpu_to_le32(self->saddr);
  86249. - frame->daddr = cpu_to_le32(self->daddr);
  86250. + put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
  86251. + put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
  86252. frame->ncaddr = self->caddr;
  86253. -
  86254. +
  86255. ret = irlap_insert_qos_negotiation_params(self, skb);
  86256. if (ret < 0) {
  86257. dev_kfree_skb(skb);
  86258. @@ -154,13 +155,13 @@
  86259. * Received SNRM (Set Normal Response Mode) command frame
  86260. *
  86261. */
  86262. -static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
  86263. - struct irlap_info *info)
  86264. +static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
  86265. + struct irlap_info *info)
  86266. {
  86267. struct snrm_frame *frame;
  86268. frame = (struct snrm_frame *) skb->data;
  86269. -
  86270. +
  86271. if (skb->len >= sizeof(struct snrm_frame)) {
  86272. /* Copy the new connection address ignoring the C/R bit */
  86273. info->caddr = frame->ncaddr & 0xFE;
  86274. @@ -170,11 +171,11 @@
  86275. IRDA_DEBUG(3, "%s(), invalid connection address!\n", __FUNCTION__);
  86276. return;
  86277. }
  86278. -
  86279. +
  86280. /* Copy peer device address */
  86281. - info->daddr = le32_to_cpu(frame->saddr);
  86282. - info->saddr = le32_to_cpu(frame->daddr);
  86283. -
  86284. + info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
  86285. + info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
  86286. +
  86287. /* Only accept if addressed directly to us */
  86288. if (info->saddr != self->saddr) {
  86289. IRDA_DEBUG(2, "%s(), not addressed to us!\n", __FUNCTION__);
  86290. @@ -198,9 +199,9 @@
  86291. struct sk_buff *skb;
  86292. struct ua_frame *frame;
  86293. int ret;
  86294. -
  86295. +
  86296. IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
  86297. -
  86298. +
  86299. ASSERT(self != NULL, return;);
  86300. ASSERT(self->magic == LAP_MAGIC, return;);
  86301. @@ -212,13 +213,13 @@
  86302. return;
  86303. frame = (struct ua_frame *) skb_put(skb, 10);
  86304. -
  86305. +
  86306. /* Build UA response */
  86307. frame->caddr = self->caddr;
  86308. frame->control = UA_RSP | PF_BIT;
  86309. - frame->saddr = cpu_to_le32(self->saddr);
  86310. - frame->daddr = cpu_to_le32(self->daddr);
  86311. + put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
  86312. + put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
  86313. /* Should we send QoS negotiation parameters? */
  86314. if (qos) {
  86315. @@ -243,7 +244,7 @@
  86316. {
  86317. struct sk_buff *skb = NULL;
  86318. __u8 *frame;
  86319. -
  86320. +
  86321. ASSERT(self != NULL, return;);
  86322. ASSERT(self->magic == LAP_MAGIC, return;);
  86323. @@ -252,7 +253,7 @@
  86324. return;
  86325. frame = skb_put( skb, 2);
  86326. -
  86327. +
  86328. if (self->state == LAP_NDM)
  86329. frame[0] = CBROADCAST;
  86330. else
  86331. @@ -260,7 +261,7 @@
  86332. frame[1] = DM_RSP | PF_BIT;
  86333. - irlap_queue_xmit(self, skb);
  86334. + irlap_queue_xmit(self, skb);
  86335. }
  86336. /*
  86337. @@ -269,11 +270,11 @@
  86338. * Send disconnect (DISC) frame
  86339. *
  86340. */
  86341. -void irlap_send_disc_frame(struct irlap_cb *self)
  86342. +void irlap_send_disc_frame(struct irlap_cb *self)
  86343. {
  86344. struct sk_buff *skb = NULL;
  86345. __u8 *frame;
  86346. -
  86347. +
  86348. IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
  86349. ASSERT(self != NULL, return;);
  86350. @@ -284,7 +285,7 @@
  86351. return;
  86352. frame = skb_put(skb, 2);
  86353. -
  86354. +
  86355. frame[0] = self->caddr | CMD_FRAME;
  86356. frame[1] = DISC_CMD | PF_BIT;
  86357. @@ -295,17 +296,17 @@
  86358. * Function irlap_send_discovery_xid_frame (S, s, command)
  86359. *
  86360. * Build and transmit a XID (eXchange station IDentifier) discovery
  86361. - * frame.
  86362. + * frame.
  86363. */
  86364. -void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
  86365. - __u8 command, discovery_t *discovery)
  86366. +void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
  86367. + __u8 command, discovery_t *discovery)
  86368. {
  86369. struct sk_buff *skb = NULL;
  86370. struct xid_frame *frame;
  86371. - __u32 bcast = BROADCAST;
  86372. + __u32 bcast = BROADCAST, daddr;
  86373. __u8 *info;
  86374. - IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
  86375. + IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
  86376. command);
  86377. ASSERT(self != NULL, return;);
  86378. @@ -328,13 +329,14 @@
  86379. }
  86380. frame->ident = XID_FORMAT;
  86381. - frame->saddr = cpu_to_le32(self->saddr);
  86382. -
  86383. if (command)
  86384. - frame->daddr = cpu_to_le32(bcast);
  86385. + daddr = bcast;
  86386. else
  86387. - frame->daddr = cpu_to_le32(discovery->daddr);
  86388. -
  86389. + daddr = discovery->daddr;
  86390. +
  86391. + put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
  86392. + put_unaligned(cpu_to_le32(daddr), &frame->daddr);
  86393. +
  86394. switch (S) {
  86395. case 1:
  86396. frame->flags = 0x00;
  86397. @@ -353,10 +355,10 @@
  86398. break;
  86399. }
  86400. - frame->slotnr = s;
  86401. + frame->slotnr = s;
  86402. frame->version = 0x00;
  86403. - /*
  86404. + /*
  86405. * Provide info for final slot only in commands, and for all
  86406. * responses. Send the second byte of the hint only if the
  86407. * EXTENSION bit is set in the first byte.
  86408. @@ -365,7 +367,7 @@
  86409. int len;
  86410. if (discovery->hints.byte[0] & HINT_EXTENSION) {
  86411. - info = skb_put(skb, 2);
  86412. + info = skb_put(skb, 2);
  86413. info[0] = discovery->hints.byte[0];
  86414. info[1] = discovery->hints.byte[1];
  86415. } else {
  86416. @@ -378,7 +380,7 @@
  86417. len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
  86418. info = skb_put(skb, len);
  86419. memcpy(info, discovery->nickname, len);
  86420. - }
  86421. + }
  86422. irlap_queue_xmit(self, skb);
  86423. }
  86424. @@ -388,9 +390,9 @@
  86425. * Received a XID discovery response
  86426. *
  86427. */
  86428. -static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
  86429. - struct sk_buff *skb,
  86430. - struct irlap_info *info)
  86431. +static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
  86432. + struct sk_buff *skb,
  86433. + struct irlap_info *info)
  86434. {
  86435. struct xid_frame *xid;
  86436. discovery_t *discovery = NULL;
  86437. @@ -404,8 +406,8 @@
  86438. xid = (struct xid_frame *) skb->data;
  86439. - info->daddr = le32_to_cpu(xid->saddr);
  86440. - info->saddr = le32_to_cpu(xid->daddr);
  86441. + info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
  86442. + info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
  86443. /* Make sure frame is addressed to us */
  86444. if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
  86445. @@ -439,11 +441,11 @@
  86446. discovery->charset = discovery_info[1];
  86447. text = (char *) &discovery_info[2];
  86448. }
  86449. - /*
  86450. - * Terminate info string, should be safe since this is where the
  86451. + /*
  86452. + * Terminate info string, should be safe since this is where the
  86453. * FCS bytes resides.
  86454. */
  86455. - skb->data[skb->len] = '\0';
  86456. + skb->data[skb->len] = '\0';
  86457. strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
  86458. discovery->name_len = strlen(discovery->nickname);
  86459. @@ -458,9 +460,9 @@
  86460. * Received a XID discovery command
  86461. *
  86462. */
  86463. -static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
  86464. - struct sk_buff *skb,
  86465. - struct irlap_info *info)
  86466. +static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
  86467. + struct sk_buff *skb,
  86468. + struct irlap_info *info)
  86469. {
  86470. struct xid_frame *xid;
  86471. discovery_t *discovery = NULL;
  86472. @@ -469,8 +471,8 @@
  86473. xid = (struct xid_frame *) skb->data;
  86474. - info->daddr = le32_to_cpu(xid->saddr);
  86475. - info->saddr = le32_to_cpu(xid->daddr);
  86476. + info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
  86477. + info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
  86478. /* Make sure frame is addressed to us */
  86479. if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
  86480. @@ -497,11 +499,11 @@
  86481. return;
  86482. }
  86483. info->s = xid->slotnr;
  86484. -
  86485. +
  86486. discovery_info = skb_pull(skb, sizeof(struct xid_frame));
  86487. - /*
  86488. - * Check if last frame
  86489. + /*
  86490. + * Check if last frame
  86491. */
  86492. if (info->s == 0xff) {
  86493. /* Check if things are sane at this point... */
  86494. @@ -518,7 +520,7 @@
  86495. WARNING("%s(), unable to malloc!\n", __FUNCTION__);
  86496. return;
  86497. }
  86498. -
  86499. +
  86500. discovery->daddr = info->daddr;
  86501. discovery->saddr = self->saddr;
  86502. discovery->timestamp = jiffies;
  86503. @@ -533,11 +535,11 @@
  86504. discovery->charset = discovery_info[1];
  86505. text = (char *) &discovery_info[2];
  86506. }
  86507. - /*
  86508. - * Terminate string, should be safe since this is where the
  86509. + /*
  86510. + * Terminate string, should be safe since this is where the
  86511. * FCS bytes resides.
  86512. */
  86513. - skb->data[skb->len] = '\0';
  86514. + skb->data[skb->len] = '\0';
  86515. strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
  86516. discovery->name_len = strlen(discovery->nickname);
  86517. @@ -554,7 +556,7 @@
  86518. * Build and transmit RR (Receive Ready) frame. Notice that it is currently
  86519. * only possible to send RR frames with the poll bit set.
  86520. */
  86521. -void irlap_send_rr_frame(struct irlap_cb *self, int command)
  86522. +void irlap_send_rr_frame(struct irlap_cb *self, int command)
  86523. {
  86524. struct sk_buff *skb;
  86525. __u8 *frame;
  86526. @@ -562,9 +564,9 @@
  86527. skb = dev_alloc_skb(16);
  86528. if (!skb)
  86529. return;
  86530. -
  86531. +
  86532. frame = skb_put(skb, 2);
  86533. -
  86534. +
  86535. frame[0] = self->caddr;
  86536. frame[0] |= (command) ? CMD_FRAME : 0;
  86537. @@ -576,7 +578,7 @@
  86538. /*
  86539. * Function irlap_send_rd_frame (self)
  86540. *
  86541. - * Request disconnect. Used by a secondary station to request the
  86542. + * Request disconnect. Used by a secondary station to request the
  86543. * disconnection of the link.
  86544. */
  86545. void irlap_send_rd_frame(struct irlap_cb *self)
  86546. @@ -587,9 +589,9 @@
  86547. skb = dev_alloc_skb(16);
  86548. if (!skb)
  86549. return;
  86550. -
  86551. +
  86552. frame = skb_put(skb, 2);
  86553. -
  86554. +
  86555. frame[0] = self->caddr;
  86556. frame[1] = RD_RSP | PF_BIT;
  86557. @@ -603,8 +605,8 @@
  86558. * making it inline since its called only from one single place
  86559. * (irlap_driver_rcv).
  86560. */
  86561. -static inline void irlap_recv_rr_frame(struct irlap_cb *self,
  86562. - struct sk_buff *skb,
  86563. +static inline void irlap_recv_rr_frame(struct irlap_cb *self,
  86564. + struct sk_buff *skb,
  86565. struct irlap_info *info, int command)
  86566. {
  86567. info->nr = skb->data[1] >> 5;
  86568. @@ -620,7 +622,7 @@
  86569. {
  86570. struct sk_buff *skb = NULL;
  86571. __u8 *frame;
  86572. -
  86573. +
  86574. ASSERT( self != NULL, return;);
  86575. ASSERT( self->magic == LAP_MAGIC, return;);
  86576. @@ -629,7 +631,7 @@
  86577. return;
  86578. frame = skb_put( skb, 2);
  86579. -
  86580. +
  86581. frame[0] = self->caddr;
  86582. frame[0] |= (command) ? CMD_FRAME : 0;
  86583. @@ -639,7 +641,7 @@
  86584. frame[2] = 0;
  86585. - IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
  86586. + IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
  86587. irlap_queue_xmit(self, skb);
  86588. }
  86589. @@ -650,8 +652,8 @@
  86590. * Received RNR (Receive Not Ready) frame from peer station
  86591. *
  86592. */
  86593. -static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
  86594. - struct irlap_info *info, int command)
  86595. +static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
  86596. + struct irlap_info *info, int command)
  86597. {
  86598. info->nr = skb->data[1] >> 5;
  86599. @@ -663,13 +665,13 @@
  86600. irlap_do_event(self, RECV_RNR_RSP, skb, info);
  86601. }
  86602. -static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
  86603. +static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
  86604. struct irlap_info *info, int command)
  86605. {
  86606. IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
  86607. info->nr = skb->data[1] >> 5;
  86608. -
  86609. +
  86610. /* Check if this is a command or a response frame */
  86611. if (command)
  86612. irlap_do_event(self, RECV_REJ_CMD, skb, info);
  86613. @@ -677,13 +679,13 @@
  86614. irlap_do_event(self, RECV_REJ_RSP, skb, info);
  86615. }
  86616. -static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
  86617. +static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
  86618. struct irlap_info *info, int command)
  86619. {
  86620. IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
  86621. info->nr = skb->data[1] >> 5;
  86622. -
  86623. +
  86624. /* Check if this is a command or a response frame */
  86625. if (command)
  86626. irlap_do_event(self, RECV_SREJ_CMD, skb, info);
  86627. @@ -691,7 +693,7 @@
  86628. irlap_do_event(self, RECV_SREJ_RSP, skb, info);
  86629. }
  86630. -static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
  86631. +static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
  86632. struct irlap_info *info, int command)
  86633. {
  86634. IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
  86635. @@ -709,9 +711,9 @@
  86636. * Received UA (Unnumbered Acknowledgement) frame
  86637. *
  86638. */
  86639. -static inline void irlap_recv_ua_frame(struct irlap_cb *self,
  86640. - struct sk_buff *skb,
  86641. - struct irlap_info *info)
  86642. +static inline void irlap_recv_ua_frame(struct irlap_cb *self,
  86643. + struct sk_buff *skb,
  86644. + struct irlap_info *info)
  86645. {
  86646. irlap_do_event(self, RECV_UA_RSP, skb, info);
  86647. }
  86648. @@ -728,25 +730,25 @@
  86649. if (skb->data[1] == I_FRAME) {
  86650. - /*
  86651. + /*
  86652. * Insert frame sequence number (Vs) in control field before
  86653. * inserting into transmit window queue.
  86654. */
  86655. skb->data[1] = I_FRAME | (self->vs << 1);
  86656. -
  86657. +
  86658. /* Copy buffer */
  86659. tx_skb = skb_clone(skb, GFP_ATOMIC);
  86660. if (tx_skb == NULL) {
  86661. return;
  86662. }
  86663. -
  86664. - /*
  86665. - * Insert frame in store, in case of retransmissions
  86666. +
  86667. + /*
  86668. + * Insert frame in store, in case of retransmissions
  86669. */
  86670. skb_queue_tail(&self->wx_list, skb_get(skb));
  86671. -
  86672. +
  86673. self->vs = (self->vs + 1) % 8;
  86674. - self->ack_required = FALSE;
  86675. + self->ack_required = FALSE;
  86676. self->window -= 1;
  86677. irlap_send_i_frame( self, tx_skb, CMD_FRAME);
  86678. @@ -761,40 +763,40 @@
  86679. *
  86680. * Send I(nformation) frame as primary with poll bit set
  86681. */
  86682. -void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
  86683. +void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
  86684. {
  86685. struct sk_buff *tx_skb;
  86686. /* Stop P timer */
  86687. del_timer(&self->poll_timer);
  86688. -
  86689. +
  86690. /* Is this reliable or unreliable data? */
  86691. if (skb->data[1] == I_FRAME) {
  86692. -
  86693. - /*
  86694. +
  86695. + /*
  86696. * Insert frame sequence number (Vs) in control field before
  86697. * inserting into transmit window queue.
  86698. */
  86699. skb->data[1] = I_FRAME | (self->vs << 1);
  86700. -
  86701. +
  86702. /* Copy buffer */
  86703. tx_skb = skb_clone(skb, GFP_ATOMIC);
  86704. if (tx_skb == NULL) {
  86705. return;
  86706. }
  86707. -
  86708. - /*
  86709. - * Insert frame in store, in case of retransmissions
  86710. +
  86711. + /*
  86712. + * Insert frame in store, in case of retransmissions
  86713. */
  86714. skb_queue_tail(&self->wx_list, skb_get(skb));
  86715. -
  86716. - /*
  86717. +
  86718. + /*
  86719. * Set poll bit if necessary. We do this to the copied
  86720. * skb, since retransmitted need to set or clear the poll
  86721. - * bit depending on when they are sent.
  86722. + * bit depending on when they are sent.
  86723. */
  86724. tx_skb->data[1] |= PF_BIT;
  86725. -
  86726. +
  86727. self->vs = (self->vs + 1) % 8;
  86728. self->ack_required = FALSE;
  86729. @@ -827,8 +829,8 @@
  86730. * Send I(nformation) frame as secondary with final bit set
  86731. *
  86732. */
  86733. -void irlap_send_data_secondary_final(struct irlap_cb *self,
  86734. - struct sk_buff *skb)
  86735. +void irlap_send_data_secondary_final(struct irlap_cb *self,
  86736. + struct sk_buff *skb)
  86737. {
  86738. struct sk_buff *tx_skb = NULL;
  86739. @@ -839,26 +841,26 @@
  86740. /* Is this reliable or unreliable data? */
  86741. if (skb->data[1] == I_FRAME) {
  86742. - /*
  86743. + /*
  86744. * Insert frame sequence number (Vs) in control field before
  86745. * inserting into transmit window queue.
  86746. */
  86747. skb->data[1] = I_FRAME | (self->vs << 1);
  86748. -
  86749. +
  86750. tx_skb = skb_clone(skb, GFP_ATOMIC);
  86751. if (tx_skb == NULL) {
  86752. return;
  86753. - }
  86754. + }
  86755. /* Insert frame in store */
  86756. skb_queue_tail(&self->wx_list, skb_get(skb));
  86757. -
  86758. +
  86759. tx_skb->data[1] |= PF_BIT;
  86760. -
  86761. - self->vs = (self->vs + 1) % 8;
  86762. +
  86763. + self->vs = (self->vs + 1) % 8;
  86764. self->ack_required = FALSE;
  86765. -
  86766. - irlap_send_i_frame(self, tx_skb, RSP_FRAME);
  86767. +
  86768. + irlap_send_i_frame(self, tx_skb, RSP_FRAME);
  86769. } else {
  86770. if (self->ack_required) {
  86771. irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
  86772. @@ -885,32 +887,32 @@
  86773. * Send I(nformation) frame as secondary without final bit set
  86774. *
  86775. */
  86776. -void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
  86777. +void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
  86778. {
  86779. struct sk_buff *tx_skb = NULL;
  86780. /* Is this reliable or unreliable data? */
  86781. if (skb->data[1] == I_FRAME) {
  86782. -
  86783. - /*
  86784. +
  86785. + /*
  86786. * Insert frame sequence number (Vs) in control field before
  86787. * inserting into transmit window queue.
  86788. */
  86789. skb->data[1] = I_FRAME | (self->vs << 1);
  86790. -
  86791. +
  86792. tx_skb = skb_clone(skb, GFP_ATOMIC);
  86793. if (tx_skb == NULL) {
  86794. return;
  86795. - }
  86796. -
  86797. + }
  86798. +
  86799. /* Insert frame in store */
  86800. skb_queue_tail(&self->wx_list, skb_get(skb));
  86801. -
  86802. +
  86803. self->vs = (self->vs + 1) % 8;
  86804. - self->ack_required = FALSE;
  86805. + self->ack_required = FALSE;
  86806. self->window -= 1;
  86807. - irlap_send_i_frame(self, tx_skb, RSP_FRAME);
  86808. + irlap_send_i_frame(self, tx_skb, RSP_FRAME);
  86809. } else {
  86810. irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
  86811. self->window -= 1;
  86812. @@ -920,8 +922,8 @@
  86813. /*
  86814. * Function irlap_resend_rejected_frames (nr)
  86815. *
  86816. - * Resend frames which has not been acknowledged. Should be safe to
  86817. - * traverse the list without locking it since this function will only be
  86818. + * Resend frames which has not been acknowledged. Should be safe to
  86819. + * traverse the list without locking it since this function will only be
  86820. * called from interrupt context (BH)
  86821. */
  86822. void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
  86823. @@ -943,8 +945,8 @@
  86824. while (skb != NULL) {
  86825. irlap_wait_min_turn_around(self, &self->qos_tx);
  86826. - /* We copy the skb to be retransmitted since we will have to
  86827. - * modify it. Cloning will confuse packet sniffers
  86828. + /* We copy the skb to be retransmitted since we will have to
  86829. + * modify it. Cloning will confuse packet sniffers
  86830. */
  86831. /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
  86832. tx_skb = skb_copy(skb, GFP_ATOMIC);
  86833. @@ -959,17 +961,17 @@
  86834. /* Clear old Nr field + poll bit */
  86835. tx_skb->data[1] &= 0x0f;
  86836. - /*
  86837. + /*
  86838. * Set poll bit on the last frame retransmitted
  86839. */
  86840. if (count-- == 1)
  86841. tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
  86842. else
  86843. tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
  86844. -
  86845. +
  86846. irlap_send_i_frame(self, tx_skb, command);
  86847. - /*
  86848. + /*
  86849. * If our skb is the last buffer in the list, then
  86850. * we are finished, if not, move to the next sk-buffer
  86851. */
  86852. @@ -979,23 +981,23 @@
  86853. skb = skb->next;
  86854. }
  86855. #if 0 /* Not yet */
  86856. - /*
  86857. + /*
  86858. * We can now fill the window with additinal data frames
  86859. */
  86860. while (skb_queue_len( &self->txq) > 0) {
  86861. -
  86862. +
  86863. IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
  86864. - if ((skb_queue_len( &self->txq) > 0) &&
  86865. + if ((skb_queue_len( &self->txq) > 0) &&
  86866. (self->window > 0)) {
  86867. - skb = skb_dequeue( &self->txq);
  86868. + skb = skb_dequeue( &self->txq);
  86869. ASSERT(skb != NULL, return;);
  86870. /*
  86871. - * If send window > 1 then send frame with pf
  86872. + * If send window > 1 then send frame with pf
  86873. * bit cleared
  86874. - */
  86875. - if ((self->window > 1) &&
  86876. - skb_queue_len(&self->txq) > 0)
  86877. + */
  86878. + if ((self->window > 1) &&
  86879. + skb_queue_len(&self->txq) > 0)
  86880. {
  86881. irlap_send_data_primary(self, skb);
  86882. } else {
  86883. @@ -1023,14 +1025,14 @@
  86884. if (skb != NULL) {
  86885. irlap_wait_min_turn_around(self, &self->qos_tx);
  86886. - /* We copy the skb to be retransmitted since we will have to
  86887. - * modify it. Cloning will confuse packet sniffers
  86888. + /* We copy the skb to be retransmitted since we will have to
  86889. + * modify it. Cloning will confuse packet sniffers
  86890. */
  86891. /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
  86892. tx_skb = skb_copy(skb, GFP_ATOMIC);
  86893. if (!tx_skb) {
  86894. IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
  86895. - return;
  86896. + return;
  86897. }
  86898. /* Unlink tx_skb from list */
  86899. tx_skb->next = tx_skb->prev = NULL;
  86900. @@ -1041,7 +1043,7 @@
  86901. /* Set poll/final bit */
  86902. tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
  86903. -
  86904. +
  86905. irlap_send_i_frame(self, tx_skb, command);
  86906. }
  86907. }
  86908. @@ -1052,15 +1054,15 @@
  86909. * Contruct and transmit an Unnumbered Information (UI) frame
  86910. *
  86911. */
  86912. -void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
  86913. +void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
  86914. __u8 caddr, int command)
  86915. {
  86916. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  86917. -
  86918. +
  86919. ASSERT(self != NULL, return;);
  86920. ASSERT(self->magic == LAP_MAGIC, return;);
  86921. ASSERT(skb != NULL, return;);
  86922. -
  86923. +
  86924. /* Insert connection address */
  86925. skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
  86926. @@ -1072,13 +1074,13 @@
  86927. *
  86928. * Contruct and transmit Information (I) frame
  86929. */
  86930. -void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
  86931. - int command)
  86932. +void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
  86933. + int command)
  86934. {
  86935. /* Insert connection address */
  86936. skb->data[0] = self->caddr;
  86937. skb->data[0] |= (command) ? CMD_FRAME : 0;
  86938. -
  86939. +
  86940. /* Insert next to receive (Vr) */
  86941. skb->data[1] |= (self->vr << 5); /* insert nr */
  86942. @@ -1091,9 +1093,9 @@
  86943. * Receive and parse an I (Information) frame, no harm in making it inline
  86944. * since it's called only from one single place (irlap_driver_rcv).
  86945. */
  86946. -static inline void irlap_recv_i_frame(struct irlap_cb *self,
  86947. - struct sk_buff *skb,
  86948. - struct irlap_info *info, int command)
  86949. +static inline void irlap_recv_i_frame(struct irlap_cb *self,
  86950. + struct sk_buff *skb,
  86951. + struct irlap_info *info, int command)
  86952. {
  86953. info->nr = skb->data[1] >> 5; /* Next to receive */
  86954. info->pf = skb->data[1] & PF_BIT; /* Final bit */
  86955. @@ -1112,7 +1114,7 @@
  86956. * Receive and parse an Unnumbered Information (UI) frame
  86957. *
  86958. */
  86959. -static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
  86960. +static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
  86961. struct irlap_info *info)
  86962. {
  86963. IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
  86964. @@ -1128,19 +1130,19 @@
  86965. * Received Frame Reject response.
  86966. *
  86967. */
  86968. -static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
  86969. - struct irlap_info *info)
  86970. +static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
  86971. + struct irlap_info *info)
  86972. {
  86973. __u8 *frame;
  86974. int w, x, y, z;
  86975. IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
  86976. -
  86977. +
  86978. ASSERT(self != NULL, return;);
  86979. ASSERT(self->magic == LAP_MAGIC, return;);
  86980. ASSERT(skb != NULL, return;);
  86981. ASSERT(info != NULL, return;);
  86982. -
  86983. +
  86984. frame = skb->data;
  86985. info->nr = frame[2] >> 5; /* Next to receive */
  86986. @@ -1151,11 +1153,11 @@
  86987. x = frame[3] & 0x02;
  86988. y = frame[3] & 0x04;
  86989. z = frame[3] & 0x08;
  86990. -
  86991. +
  86992. if (w) {
  86993. IRDA_DEBUG(0, "Rejected control field is undefined or not "
  86994. "implemented.\n");
  86995. - }
  86996. + }
  86997. if (x) {
  86998. IRDA_DEBUG(0, "Rejected control field was invalid because it "
  86999. "contained a non permitted I field.\n");
  87000. @@ -1178,7 +1180,7 @@
  87001. * Send a test frame response
  87002. *
  87003. */
  87004. -void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
  87005. +void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
  87006. struct sk_buff *cmd)
  87007. {
  87008. struct sk_buff *skb;
  87009. @@ -1191,7 +1193,7 @@
  87010. /* Broadcast frames must include saddr and daddr fields */
  87011. if (caddr == CBROADCAST) {
  87012. - frame = (struct test_frame *)
  87013. + frame = (struct test_frame *)
  87014. skb_put(skb, sizeof(struct test_frame));
  87015. /* Insert the swapped addresses */
  87016. @@ -1218,28 +1220,28 @@
  87017. * Receive a test frame
  87018. *
  87019. */
  87020. -static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
  87021. +static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
  87022. struct irlap_info *info, int command)
  87023. {
  87024. struct test_frame *frame;
  87025. IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
  87026. -
  87027. +
  87028. frame = (struct test_frame *) skb->data;
  87029. -
  87030. +
  87031. /* Broadcast frames must carry saddr and daddr fields */
  87032. if (info->caddr == CBROADCAST) {
  87033. if (skb->len < sizeof(struct test_frame)) {
  87034. IRDA_DEBUG(0, "%s() test frame to short!\n", __FUNCTION__);
  87035. return;
  87036. }
  87037. -
  87038. +
  87039. /* Read and swap addresses */
  87040. - info->daddr = le32_to_cpu(frame->saddr);
  87041. - info->saddr = le32_to_cpu(frame->daddr);
  87042. + info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
  87043. + info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
  87044. /* Make sure frame is addressed to us */
  87045. - if ((info->saddr != self->saddr) &&
  87046. + if ((info->saddr != self->saddr) &&
  87047. (info->saddr != BROADCAST)) {
  87048. return;
  87049. }
  87050. @@ -1254,18 +1256,18 @@
  87051. /*
  87052. * Function irlap_driver_rcv (skb, netdev, ptype)
  87053. *
  87054. - * Called when a frame is received. Dispatches the right receive function
  87055. + * Called when a frame is received. Dispatches the right receive function
  87056. * for processing of the frame.
  87057. *
  87058. */
  87059. -int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
  87060. +int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
  87061. struct packet_type *ptype)
  87062. {
  87063. struct irlap_info info;
  87064. struct irlap_cb *self;
  87065. int command;
  87066. __u8 control;
  87067. -
  87068. +
  87069. /* FIXME: should we get our own field? */
  87070. self = (struct irlap_cb *) dev->atalk_ptr;
  87071. @@ -1281,10 +1283,10 @@
  87072. dev_kfree_skb(skb);
  87073. return -1;
  87074. }
  87075. -
  87076. +
  87077. command = skb->data[0] & CMD_FRAME;
  87078. info.caddr = skb->data[0] & CBROADCAST;
  87079. -
  87080. +
  87081. info.pf = skb->data[1] & PF_BIT;
  87082. info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */
  87083. @@ -1295,7 +1297,7 @@
  87084. IRDA_DEBUG(0, "%s(), wrong connection address!\n", __FUNCTION__);
  87085. goto out;
  87086. }
  87087. - /*
  87088. + /*
  87089. * Optimize for the common case and check if the frame is an
  87090. * I(nformation) frame. Only I-frames have bit 0 set to 0
  87091. */
  87092. @@ -1304,11 +1306,11 @@
  87093. goto out;
  87094. }
  87095. /*
  87096. - * We now check is the frame is an S(upervisory) frame. Only
  87097. + * We now check is the frame is an S(upervisory) frame. Only
  87098. * S-frames have bit 0 set to 1 and bit 1 set to 0
  87099. */
  87100. if (~control & 0x02) {
  87101. - /*
  87102. + /*
  87103. * Received S(upervisory) frame, check which frame type it is
  87104. * only the first nibble is of interest
  87105. */
  87106. @@ -1332,8 +1334,8 @@
  87107. }
  87108. goto out;
  87109. }
  87110. - /*
  87111. - * This must be a C(ontrol) frame
  87112. + /*
  87113. + * This must be a C(ontrol) frame
  87114. */
  87115. switch (control) {
  87116. case XID_RSP:
  87117. @@ -1369,6 +1371,6 @@
  87118. break;
  87119. }
  87120. out:
  87121. - dev_kfree_skb(skb);
  87122. + dev_kfree_skb(skb);
  87123. return 0;
  87124. }
  87125. diff -urN linux-2.4.26/net/irda/irttp.c linux-2.4.26-vrs1/net/irda/irttp.c
  87126. --- linux-2.4.26/net/irda/irttp.c 2003-11-28 18:26:21.000000000 +0000
  87127. +++ linux-2.4.26-vrs1/net/irda/irttp.c 2004-01-14 21:39:31.000000000 +0000
  87128. @@ -1665,8 +1665,8 @@
  87129. }
  87130. self->rx_sdu_size = 0;
  87131. }
  87132. -
  87133. - /*
  87134. +
  87135. + /*
  87136. * It's not trivial to keep track of how many credits are available
  87137. * by incrementing at each packet, because delivery may fail
  87138. * (irttp_do_data_indication() may requeue the frame) and because
  87139. @@ -1676,7 +1676,7 @@
  87140. * to send remote_credit.
  87141. * No need to spinlock, write is atomic and self correcting...
  87142. * Jean II
  87143. - */
  87144. + */
  87145. self->avail_credit = (self->initial_credit -
  87146. (self->remote_credit +
  87147. skb_queue_len(&self->rx_queue) +
  87148. diff -urN linux-2.4.26/net/sched/Config.in linux-2.4.26-vrs1/net/sched/Config.in
  87149. --- linux-2.4.26/net/sched/Config.in 2004-04-19 11:44:28.000000000 +0100
  87150. +++ linux-2.4.26-vrs1/net/sched/Config.in 2004-04-18 21:47:52.000000000 +0100
  87151. @@ -3,9 +3,9 @@
  87152. #
  87153. tristate ' CBQ packet scheduler' CONFIG_NET_SCH_CBQ
  87154. tristate ' HTB packet scheduler' CONFIG_NET_SCH_HTB
  87155. -tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ
  87156. +dep_tristate ' CSZ packet scheduler (experimental)' CONFIG_NET_SCH_CSZ $CONFIG_EXPERIMENTAL
  87157. #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
  87158. -tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFSC
  87159. +tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
  87160. if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then
  87161. dep_tristate ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM
  87162. fi