123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396 |
- /* aha152x.c -- Adaptec AHA-152x driver
- * Author: Jürgen E. Fischer, fischer@norbit.de
- * Copyright 1993-2004 Jürgen E. Fischer
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- *
- * $Id: aha152x.c,v 2.7 2004/01/24 11:42:59 fischer Exp $
- *
- * $Log: aha152x.c,v $
- * Revision 2.7 2004/01/24 11:42:59 fischer
- * - gather code that is not used by PCMCIA at the end
- * - move request_region for !PCMCIA case to detection
- * - migration to new scsi host api (remove legacy code)
- * - free host scribble before scsi_done
- * - fix error handling
- * - one isapnp device added to id_table
- *
- * Revision 2.6 2003/10/30 20:52:47 fischer
- * - interfaces changes for kernel 2.6
- * - aha152x_probe_one introduced for pcmcia stub
- * - fixed pnpdev handling
- * - instead of allocation a new one, reuse command for request sense after check condition and reset
- * - fixes race in is_complete
- *
- * Revision 2.5 2002/04/14 11:24:53 fischer
- * - isapnp support
- * - abort fixed
- * - 2.5 support
- *
- * Revision 2.4 2000/12/16 12:53:56 fischer
- * - allow REQUEST SENSE to be queued
- * - handle shared PCI interrupts
- *
- * Revision 2.3 2000/11/04 16:40:26 fischer
- * - handle data overruns
- * - extend timeout for data phases
- *
- * Revision 2.2 2000/08/08 19:54:53 fischer
- * - minor changes
- *
- * Revision 2.1 2000/05/17 16:23:17 fischer
- * - signature update
- * - fix for data out w/o scatter gather
- *
- * Revision 2.0 1999/12/25 15:07:32 fischer
- * - interrupt routine completly reworked
- * - basic support for new eh code
- *
- * Revision 1.21 1999/11/10 23:46:36 fischer
- * - default to synchronous operation
- * - synchronous negotiation fixed
- * - added timeout to loops
- * - debugging output can be controlled through procfs
- *
- * Revision 1.20 1999/11/07 18:37:31 fischer
- * - synchronous operation works
- * - resid support for sg driver
- *
- * Revision 1.19 1999/11/02 22:39:59 fischer
- * - moved leading comments to README.aha152x
- * - new additional module parameters
- * - updates for 2.3
- * - support for the Tripace TC1550 controller
- * - interrupt handling changed
- *
- * Revision 1.18 1996/09/07 20:10:40 fischer
- * - fixed can_queue handling (multiple outstanding commands working again)
- *
- * Revision 1.17 1996/08/17 16:05:14 fischer
- * - biosparam improved
- * - interrupt verification
- * - updated documentation
- * - cleanups
- *
- * Revision 1.16 1996/06/09 00:04:56 root
- * - added configuration symbols for insmod (aha152x/aha152x1)
- *
- * Revision 1.15 1996/04/30 14:52:06 fischer
- * - proc info fixed
- * - support for extended translation for >1GB disks
- *
- * Revision 1.14 1996/01/17 15:11:20 fischer
- * - fixed lockup in MESSAGE IN phase after reconnection
- *
- * Revision 1.13 1996/01/09 02:15:53 fischer
- * - some cleanups
- * - moved request_irq behind controller initialization
- * (to avoid spurious interrupts)
- *
- * Revision 1.12 1995/12/16 12:26:07 fischer
- * - barrier()s added
- * - configurable RESET delay added
- *
- * Revision 1.11 1995/12/06 21:18:35 fischer
- * - some minor updates
- *
- * Revision 1.10 1995/07/22 19:18:45 fischer
- * - support for 2 controllers
- * - started synchronous data transfers (not working yet)
- *
- * Revision 1.9 1995/03/18 09:20:24 root
- * - patches for PCMCIA and modules
- *
- * Revision 1.8 1995/01/21 22:07:19 root
- * - snarf_region => request_region
- * - aha152x_intr interface change
- *
- * Revision 1.7 1995/01/02 23:19:36 root
- * - updated COMMAND_SIZE to cmd_len
- * - changed sti() to restore_flags()
- * - fixed some #ifdef which generated warnings
- *
- * Revision 1.6 1994/11/24 20:35:27 root
- * - problem with odd number of bytes in fifo fixed
- *
- * Revision 1.5 1994/10/30 14:39:56 root
- * - abort code fixed
- * - debugging improved
- *
- * Revision 1.4 1994/09/12 11:33:01 root
- * - irqaction to request_irq
- * - abortion updated
- *
- * Revision 1.3 1994/08/04 13:53:05 root
- * - updates for mid-level-driver changes
- * - accept unexpected BUSFREE phase as error condition
- * - parity check now configurable
- *
- * Revision 1.2 1994/07/03 12:56:36 root
- * - cleaned up debugging code
- * - more tweaking on reset delays
- * - updated abort/reset code (pretty untested...)
- *
- * Revision 1.1 1994/05/28 21:18:49 root
- * - update for mid-level interface change (abort-reset)
- * - delays after resets adjusted for some slow devices
- *
- * Revision 1.0 1994/03/25 12:52:00 root
- * - Fixed "more data than expected" problem
- * - added new BIOS signatures
- *
- * Revision 0.102 1994/01/31 20:44:12 root
- * - minor changes in insw/outsw handling
- *
- * Revision 0.101 1993/12/13 01:16:27 root
- * - fixed STATUS phase (non-GOOD stati were dropped sometimes;
- * fixes problems with CD-ROM sector size detection & media change)
- *
- * Revision 0.100 1993/12/10 16:58:47 root
- * - fix for unsuccessful selections in case of non-continuous id assignments
- * on the scsi bus.
- *
- * Revision 0.99 1993/10/24 16:19:59 root
- * - fixed DATA IN (rare read errors gone)
- *
- * Revision 0.98 1993/10/17 12:54:44 root
- * - fixed some recent fixes (shame on me)
- * - moved initialization of scratch area to aha152x_queue
- *
- * Revision 0.97 1993/10/09 18:53:53 root
- * - DATA IN fixed. Rarely left data in the fifo.
- *
- * Revision 0.96 1993/10/03 00:53:59 root
- * - minor changes on DATA IN
- *
- * Revision 0.95 1993/09/24 10:36:01 root
- * - change handling of MSGI after reselection
- * - fixed sti/cli
- * - minor changes
- *
- * Revision 0.94 1993/09/18 14:08:22 root
- * - fixed bug in multiple outstanding command code
- * - changed detection
- * - support for kernel command line configuration
- * - reset corrected
- * - changed message handling
- *
- * Revision 0.93 1993/09/15 20:41:19 root
- * - fixed bugs with multiple outstanding commands
- *
- * Revision 0.92 1993/09/13 02:46:33 root
- * - multiple outstanding commands work (no problems with IBM drive)
- *
- * Revision 0.91 1993/09/12 20:51:46 root
- * added multiple outstanding commands
- * (some problem with this $%&? IBM device remain)
- *
- * Revision 0.9 1993/09/12 11:11:22 root
- * - corrected auto-configuration
- * - changed the auto-configuration (added some '#define's)
- * - added support for dis-/reconnection
- *
- * Revision 0.8 1993/09/06 23:09:39 root
- * - added support for the drive activity light
- * - minor changes
- *
- * Revision 0.7 1993/09/05 14:30:15 root
- * - improved phase detection
- * - now using the new snarf_region code of 0.99pl13
- *
- * Revision 0.6 1993/09/02 11:01:38 root
- * first public release; added some signatures and biosparam()
- *
- * Revision 0.5 1993/08/30 10:23:30 root
- * fixed timing problems with my IBM drive
- *
- * Revision 0.4 1993/08/29 14:06:52 root
- * fixed some problems with timeouts due incomplete commands
- *
- * Revision 0.3 1993/08/28 15:55:03 root
- * writing data works too. mounted and worked on a dos partition
- *
- * Revision 0.2 1993/08/27 22:42:07 root
- * reading data works. Mounted a msdos partition.
- *
- * Revision 0.1 1993/08/25 13:38:30 root
- * first "damn thing doesn't work" version
- *
- * Revision 0.0 1993/08/14 19:54:25 root
- * empty function bodies; detect() works.
- *
- *
- **************************************************************************
- see Documentation/scsi/aha152x.txt for configuration details
- **************************************************************************/
- #include <linux/module.h>
- #include <asm/irq.h>
- #include <linux/io.h>
- #include <linux/blkdev.h>
- #include <linux/completion.h>
- #include <linux/errno.h>
- #include <linux/string.h>
- #include <linux/wait.h>
- #include <linux/ioport.h>
- #include <linux/delay.h>
- #include <linux/proc_fs.h>
- #include <linux/interrupt.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/isapnp.h>
- #include <linux/spinlock.h>
- #include <linux/workqueue.h>
- #include <linux/list.h>
- #include <linux/slab.h>
- #include <scsi/scsicam.h>
- #include "scsi.h"
- #include <scsi/scsi_dbg.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_transport_spi.h>
- #include <scsi/scsi_eh.h>
- #include "aha152x.h"
- static LIST_HEAD(aha152x_host_list);
- /* DEFINES */
- /* For PCMCIA cards, always use AUTOCONF */
- #if defined(PCMCIA) || defined(MODULE)
- #if !defined(AUTOCONF)
- #define AUTOCONF
- #endif
- #endif
- #if !defined(AUTOCONF) && !defined(SETUP0)
- #error define AUTOCONF or SETUP0
- #endif
- #define DO_LOCK(flags) spin_lock_irqsave(&QLOCK,flags)
- #define DO_UNLOCK(flags) spin_unlock_irqrestore(&QLOCK,flags)
- #define LEAD "(scsi%d:%d:%d) "
- #define INFO_LEAD KERN_INFO LEAD
- #define CMDINFO(cmd) \
- (cmd) ? ((cmd)->device->host->host_no) : -1, \
- (cmd) ? ((cmd)->device->id & 0x0f) : -1, \
- (cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1
- static inline void
- CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
- {
- scsi_set_resid(cmd, scsi_get_resid(cmd) + inc);
- }
- #define DELAY_DEFAULT 1000
- #if defined(PCMCIA)
- #define IRQ_MIN 0
- #define IRQ_MAX 16
- #else
- #define IRQ_MIN 9
- #if defined(__PPC)
- #define IRQ_MAX (nr_irqs-1)
- #else
- #define IRQ_MAX 12
- #endif
- #endif
- enum {
- not_issued = 0x0001, /* command not yet issued */
- selecting = 0x0002, /* target is being selected */
- identified = 0x0004, /* IDENTIFY was sent */
- disconnected = 0x0008, /* target disconnected */
- completed = 0x0010, /* target sent COMMAND COMPLETE */
- aborted = 0x0020, /* ABORT was sent */
- resetted = 0x0040, /* BUS DEVICE RESET was sent */
- spiordy = 0x0080, /* waiting for SPIORDY to raise */
- syncneg = 0x0100, /* synchronous negotiation in progress */
- aborting = 0x0200, /* ABORT is pending */
- resetting = 0x0400, /* BUS DEVICE RESET is pending */
- check_condition = 0x0800, /* requesting sense after CHECK CONDITION */
- };
- MODULE_AUTHOR("Jürgen Fischer");
- MODULE_DESCRIPTION(AHA152X_REVID);
- MODULE_LICENSE("GPL");
- #if !defined(PCMCIA)
- #if defined(MODULE)
- static int io[] = {0, 0};
- module_param_hw_array(io, int, ioport, NULL, 0);
- MODULE_PARM_DESC(io,"base io address of controller");
- static int irq[] = {0, 0};
- module_param_hw_array(irq, int, irq, NULL, 0);
- MODULE_PARM_DESC(irq,"interrupt for controller");
- static int scsiid[] = {7, 7};
- module_param_array(scsiid, int, NULL, 0);
- MODULE_PARM_DESC(scsiid,"scsi id of controller");
- static int reconnect[] = {1, 1};
- module_param_array(reconnect, int, NULL, 0);
- MODULE_PARM_DESC(reconnect,"allow targets to disconnect");
- static int parity[] = {1, 1};
- module_param_array(parity, int, NULL, 0);
- MODULE_PARM_DESC(parity,"use scsi parity");
- static int sync[] = {1, 1};
- module_param_array(sync, int, NULL, 0);
- MODULE_PARM_DESC(sync,"use synchronous transfers");
- static int delay[] = {DELAY_DEFAULT, DELAY_DEFAULT};
- module_param_array(delay, int, NULL, 0);
- MODULE_PARM_DESC(delay,"scsi reset delay");
- static int exttrans[] = {0, 0};
- module_param_array(exttrans, int, NULL, 0);
- MODULE_PARM_DESC(exttrans,"use extended translation");
- static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
- module_param_array(aha152x, int, NULL, 0);
- MODULE_PARM_DESC(aha152x, "parameters for first controller");
- static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
- module_param_array(aha152x1, int, NULL, 0);
- MODULE_PARM_DESC(aha152x1, "parameters for second controller");
- #endif /* MODULE */
- #ifdef __ISAPNP__
- static struct isapnp_device_id id_table[] = {
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1515), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1520), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2015), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1522), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2215), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1530), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3015), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1532), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3215), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x6360), 0 },
- { ISAPNP_DEVICE_SINGLE_END, }
- };
- MODULE_DEVICE_TABLE(isapnp, id_table);
- #endif /* ISAPNP */
- #endif /* !PCMCIA */
- static struct scsi_host_template aha152x_driver_template;
- /*
- * internal states of the host
- *
- */
- enum aha152x_state {
- idle=0,
- unknown,
- seldo,
- seldi,
- selto,
- busfree,
- msgo,
- cmd,
- msgi,
- status,
- datai,
- datao,
- parerr,
- rsti,
- maxstate
- };
- /*
- * current state information of the host
- *
- */
- struct aha152x_hostdata {
- struct scsi_cmnd *issue_SC;
- /* pending commands to issue */
- struct scsi_cmnd *current_SC;
- /* current command on the bus */
- struct scsi_cmnd *disconnected_SC;
- /* commands that disconnected */
- struct scsi_cmnd *done_SC;
- /* command that was completed */
- spinlock_t lock;
- /* host lock */
- #if defined(AHA152X_STAT)
- int total_commands;
- int disconnections;
- int busfree_without_any_action;
- int busfree_without_old_command;
- int busfree_without_new_command;
- int busfree_without_done_command;
- int busfree_with_check_condition;
- int count[maxstate];
- int count_trans[maxstate];
- unsigned long time[maxstate];
- #endif
- int commands; /* current number of commands */
- int reconnect; /* disconnection allowed */
- int parity; /* parity checking enabled */
- int synchronous; /* synchronous transferes enabled */
- int delay; /* reset out delay */
- int ext_trans; /* extended translation enabled */
- int swint; /* software-interrupt was fired during detect() */
- int service; /* bh needs to be run */
- int in_intr; /* bh is running */
- /* current state,
- previous state,
- last state different from current state */
- enum aha152x_state state, prevstate, laststate;
- int target;
- /* reconnecting target */
- unsigned char syncrate[8];
- /* current synchronous transfer agreements */
- unsigned char syncneg[8];
- /* 0: no negotiation;
- * 1: negotiation in progress;
- * 2: negotiation completed
- */
- int cmd_i;
- /* number of sent bytes of current command */
- int msgi_len;
- /* number of received message bytes */
- unsigned char msgi[256];
- /* received message bytes */
- int msgo_i, msgo_len;
- /* number of sent bytes and length of current messages */
- unsigned char msgo[256];
- /* pending messages */
- int data_len;
- /* number of sent/received bytes in dataphase */
- unsigned long io_port0;
- unsigned long io_port1;
- #ifdef __ISAPNP__
- struct pnp_dev *pnpdev;
- #endif
- struct list_head host_list;
- };
- /*
- * host specific command extension
- *
- */
- struct aha152x_scdata {
- struct scsi_cmnd *next; /* next sc in queue */
- struct completion *done;/* semaphore to block on */
- struct scsi_eh_save ses;
- };
- /* access macros for hostdata */
- #define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata)
- #define HOSTNO ((shpnt)->host_no)
- #define CURRENT_SC (HOSTDATA(shpnt)->current_SC)
- #define DONE_SC (HOSTDATA(shpnt)->done_SC)
- #define ISSUE_SC (HOSTDATA(shpnt)->issue_SC)
- #define DISCONNECTED_SC (HOSTDATA(shpnt)->disconnected_SC)
- #define QLOCK (HOSTDATA(shpnt)->lock)
- #define QLOCKER (HOSTDATA(shpnt)->locker)
- #define QLOCKERL (HOSTDATA(shpnt)->lockerl)
- #define STATE (HOSTDATA(shpnt)->state)
- #define PREVSTATE (HOSTDATA(shpnt)->prevstate)
- #define LASTSTATE (HOSTDATA(shpnt)->laststate)
- #define RECONN_TARGET (HOSTDATA(shpnt)->target)
- #define CMD_I (HOSTDATA(shpnt)->cmd_i)
- #define MSGO(i) (HOSTDATA(shpnt)->msgo[i])
- #define MSGO_I (HOSTDATA(shpnt)->msgo_i)
- #define MSGOLEN (HOSTDATA(shpnt)->msgo_len)
- #define ADDMSGO(x) (MSGOLEN<256 ? (void)(MSGO(MSGOLEN++)=x) : aha152x_error(shpnt,"MSGO overflow"))
- #define MSGI(i) (HOSTDATA(shpnt)->msgi[i])
- #define MSGILEN (HOSTDATA(shpnt)->msgi_len)
- #define ADDMSGI(x) (MSGILEN<256 ? (void)(MSGI(MSGILEN++)=x) : aha152x_error(shpnt,"MSGI overflow"))
- #define DATA_LEN (HOSTDATA(shpnt)->data_len)
- #define SYNCRATE (HOSTDATA(shpnt)->syncrate[CURRENT_SC->device->id])
- #define SYNCNEG (HOSTDATA(shpnt)->syncneg[CURRENT_SC->device->id])
- #define DELAY (HOSTDATA(shpnt)->delay)
- #define EXT_TRANS (HOSTDATA(shpnt)->ext_trans)
- #define TC1550 (HOSTDATA(shpnt)->tc1550)
- #define RECONNECT (HOSTDATA(shpnt)->reconnect)
- #define PARITY (HOSTDATA(shpnt)->parity)
- #define SYNCHRONOUS (HOSTDATA(shpnt)->synchronous)
- #define HOSTIOPORT0 (HOSTDATA(shpnt)->io_port0)
- #define HOSTIOPORT1 (HOSTDATA(shpnt)->io_port1)
- #define SCDATA(SCpnt) ((struct aha152x_scdata *) (SCpnt)->host_scribble)
- #define SCNEXT(SCpnt) SCDATA(SCpnt)->next
- #define SCSEM(SCpnt) SCDATA(SCpnt)->done
- #define SG_ADDRESS(buffer) ((char *) sg_virt((buffer)))
- /* state handling */
- static void seldi_run(struct Scsi_Host *shpnt);
- static void seldo_run(struct Scsi_Host *shpnt);
- static void selto_run(struct Scsi_Host *shpnt);
- static void busfree_run(struct Scsi_Host *shpnt);
- static void msgo_init(struct Scsi_Host *shpnt);
- static void msgo_run(struct Scsi_Host *shpnt);
- static void msgo_end(struct Scsi_Host *shpnt);
- static void cmd_init(struct Scsi_Host *shpnt);
- static void cmd_run(struct Scsi_Host *shpnt);
- static void cmd_end(struct Scsi_Host *shpnt);
- static void datai_init(struct Scsi_Host *shpnt);
- static void datai_run(struct Scsi_Host *shpnt);
- static void datai_end(struct Scsi_Host *shpnt);
- static void datao_init(struct Scsi_Host *shpnt);
- static void datao_run(struct Scsi_Host *shpnt);
- static void datao_end(struct Scsi_Host *shpnt);
- static void status_run(struct Scsi_Host *shpnt);
- static void msgi_run(struct Scsi_Host *shpnt);
- static void msgi_end(struct Scsi_Host *shpnt);
- static void parerr_run(struct Scsi_Host *shpnt);
- static void rsti_run(struct Scsi_Host *shpnt);
- static void is_complete(struct Scsi_Host *shpnt);
- /*
- * driver states
- *
- */
- static struct {
- char *name;
- void (*init)(struct Scsi_Host *);
- void (*run)(struct Scsi_Host *);
- void (*end)(struct Scsi_Host *);
- int spio;
- } states[] = {
- { "idle", NULL, NULL, NULL, 0},
- { "unknown", NULL, NULL, NULL, 0},
- { "seldo", NULL, seldo_run, NULL, 0},
- { "seldi", NULL, seldi_run, NULL, 0},
- { "selto", NULL, selto_run, NULL, 0},
- { "busfree", NULL, busfree_run, NULL, 0},
- { "msgo", msgo_init, msgo_run, msgo_end, 1},
- { "cmd", cmd_init, cmd_run, cmd_end, 1},
- { "msgi", NULL, msgi_run, msgi_end, 1},
- { "status", NULL, status_run, NULL, 1},
- { "datai", datai_init, datai_run, datai_end, 0},
- { "datao", datao_init, datao_run, datao_end, 0},
- { "parerr", NULL, parerr_run, NULL, 0},
- { "rsti", NULL, rsti_run, NULL, 0},
- };
- /* setup & interrupt */
- static irqreturn_t intr(int irq, void *dev_id);
- static void reset_ports(struct Scsi_Host *shpnt);
- static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
- static void done(struct Scsi_Host *shpnt, int error);
- /* diagnostics */
- static void show_command(struct scsi_cmnd * ptr);
- static void show_queues(struct Scsi_Host *shpnt);
- static void disp_enintr(struct Scsi_Host *shpnt);
- /*
- * queue services:
- *
- */
- static inline void append_SC(struct scsi_cmnd **SC, struct scsi_cmnd *new_SC)
- {
- struct scsi_cmnd *end;
- SCNEXT(new_SC) = NULL;
- if (!*SC)
- *SC = new_SC;
- else {
- for (end = *SC; SCNEXT(end); end = SCNEXT(end))
- ;
- SCNEXT(end) = new_SC;
- }
- }
- static inline struct scsi_cmnd *remove_first_SC(struct scsi_cmnd ** SC)
- {
- struct scsi_cmnd *ptr;
- ptr = *SC;
- if (ptr) {
- *SC = SCNEXT(*SC);
- SCNEXT(ptr)=NULL;
- }
- return ptr;
- }
- static inline struct scsi_cmnd *remove_lun_SC(struct scsi_cmnd ** SC,
- int target, int lun)
- {
- struct scsi_cmnd *ptr, *prev;
- for (ptr = *SC, prev = NULL;
- ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
- prev = ptr, ptr = SCNEXT(ptr))
- ;
- if (ptr) {
- if (prev)
- SCNEXT(prev) = SCNEXT(ptr);
- else
- *SC = SCNEXT(ptr);
- SCNEXT(ptr)=NULL;
- }
- return ptr;
- }
- static inline struct scsi_cmnd *remove_SC(struct scsi_cmnd **SC,
- struct scsi_cmnd *SCp)
- {
- struct scsi_cmnd *ptr, *prev;
- for (ptr = *SC, prev = NULL;
- ptr && SCp!=ptr;
- prev = ptr, ptr = SCNEXT(ptr))
- ;
- if (ptr) {
- if (prev)
- SCNEXT(prev) = SCNEXT(ptr);
- else
- *SC = SCNEXT(ptr);
- SCNEXT(ptr)=NULL;
- }
- return ptr;
- }
- static irqreturn_t swintr(int irqno, void *dev_id)
- {
- struct Scsi_Host *shpnt = dev_id;
- HOSTDATA(shpnt)->swint++;
- SETPORT(DMACNTRL0, INTEN);
- return IRQ_HANDLED;
- }
- struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
- {
- struct Scsi_Host *shpnt;
- shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata));
- if (!shpnt) {
- printk(KERN_ERR "aha152x: scsi_host_alloc failed\n");
- return NULL;
- }
- memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
- INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list);
- /* need to have host registered before triggering any interrupt */
- list_add_tail(&HOSTDATA(shpnt)->host_list, &aha152x_host_list);
- shpnt->io_port = setup->io_port;
- shpnt->n_io_port = IO_RANGE;
- shpnt->irq = setup->irq;
- if (!setup->tc1550) {
- HOSTIOPORT0 = setup->io_port;
- HOSTIOPORT1 = setup->io_port;
- } else {
- HOSTIOPORT0 = setup->io_port+0x10;
- HOSTIOPORT1 = setup->io_port-0x10;
- }
- spin_lock_init(&QLOCK);
- RECONNECT = setup->reconnect;
- SYNCHRONOUS = setup->synchronous;
- PARITY = setup->parity;
- DELAY = setup->delay;
- EXT_TRANS = setup->ext_trans;
- SETPORT(SCSIID, setup->scsiid << 4);
- shpnt->this_id = setup->scsiid;
- if (setup->reconnect)
- shpnt->can_queue = AHA152X_MAXQUEUE;
- /* RESET OUT */
- printk("aha152x: resetting bus...\n");
- SETPORT(SCSISEQ, SCSIRSTO);
- mdelay(256);
- SETPORT(SCSISEQ, 0);
- mdelay(DELAY);
- reset_ports(shpnt);
- printk(KERN_INFO
- "aha152x%d%s: "
- "vital data: rev=%x, "
- "io=0x%03lx (0x%03lx/0x%03lx), "
- "irq=%d, "
- "scsiid=%d, "
- "reconnect=%s, "
- "parity=%s, "
- "synchronous=%s, "
- "delay=%d, "
- "extended translation=%s\n",
- shpnt->host_no, setup->tc1550 ? " (tc1550 mode)" : "",
- GETPORT(REV) & 0x7,
- shpnt->io_port, HOSTIOPORT0, HOSTIOPORT1,
- shpnt->irq,
- shpnt->this_id,
- RECONNECT ? "enabled" : "disabled",
- PARITY ? "enabled" : "disabled",
- SYNCHRONOUS ? "enabled" : "disabled",
- DELAY,
- EXT_TRANS ? "enabled" : "disabled");
- /* not expecting any interrupts */
- SETPORT(SIMODE0, 0);
- SETPORT(SIMODE1, 0);
- if (request_irq(shpnt->irq, swintr, IRQF_SHARED, "aha152x", shpnt)) {
- printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq);
- goto out_host_put;
- }
- HOSTDATA(shpnt)->swint = 0;
- printk(KERN_INFO "aha152x%d: trying software interrupt, ", shpnt->host_no);
- mb();
- SETPORT(DMACNTRL0, SWINT|INTEN);
- mdelay(1000);
- free_irq(shpnt->irq, shpnt);
- if (!HOSTDATA(shpnt)->swint) {
- if (TESTHI(DMASTAT, INTSTAT)) {
- printk("lost.\n");
- } else {
- printk("failed.\n");
- }
- SETPORT(DMACNTRL0, INTEN);
- printk(KERN_ERR "aha152x%d: irq %d possibly wrong. "
- "Please verify.\n", shpnt->host_no, shpnt->irq);
- goto out_host_put;
- }
- printk("ok.\n");
- /* clear interrupts */
- SETPORT(SSTAT0, 0x7f);
- SETPORT(SSTAT1, 0xef);
- if (request_irq(shpnt->irq, intr, IRQF_SHARED, "aha152x", shpnt)) {
- printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq);
- goto out_host_put;
- }
- if( scsi_add_host(shpnt, NULL) ) {
- free_irq(shpnt->irq, shpnt);
- printk(KERN_ERR "aha152x%d: failed to add host.\n", shpnt->host_no);
- goto out_host_put;
- }
- scsi_scan_host(shpnt);
- return shpnt;
- out_host_put:
- list_del(&HOSTDATA(shpnt)->host_list);
- scsi_host_put(shpnt);
- return NULL;
- }
- void aha152x_release(struct Scsi_Host *shpnt)
- {
- if (!shpnt)
- return;
- scsi_remove_host(shpnt);
- if (shpnt->irq)
- free_irq(shpnt->irq, shpnt);
- #if !defined(PCMCIA)
- if (shpnt->io_port)
- release_region(shpnt->io_port, IO_RANGE);
- #endif
- #ifdef __ISAPNP__
- if (HOSTDATA(shpnt)->pnpdev)
- pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
- #endif
- list_del(&HOSTDATA(shpnt)->host_list);
- scsi_host_put(shpnt);
- }
- /*
- * setup controller to generate interrupts depending
- * on current state (lock has to be acquired)
- *
- */
- static int setup_expected_interrupts(struct Scsi_Host *shpnt)
- {
- if(CURRENT_SC) {
- CURRENT_SC->SCp.phase |= 1 << 16;
- if(CURRENT_SC->SCp.phase & selecting) {
- SETPORT(SSTAT1, SELTO);
- SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
- SETPORT(SIMODE1, ENSELTIMO);
- } else {
- SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0);
- SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
- }
- } else if(STATE==seldi) {
- SETPORT(SIMODE0, 0);
- SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
- } else {
- SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
- SETPORT(SIMODE1, ENSCSIRST | ( (ISSUE_SC||DONE_SC) ? ENBUSFREE : 0));
- }
- if(!HOSTDATA(shpnt)->in_intr)
- SETBITS(DMACNTRL0, INTEN);
- return TESTHI(DMASTAT, INTSTAT);
- }
- /*
- * Queue a command and setup interrupts for a free bus.
- */
- static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
- struct completion *complete,
- int phase, void (*done)(struct scsi_cmnd *))
- {
- struct Scsi_Host *shpnt = SCpnt->device->host;
- unsigned long flags;
- SCpnt->scsi_done = done;
- SCpnt->SCp.phase = not_issued | phase;
- SCpnt->SCp.Status = 0x1; /* Ilegal status by SCSI standard */
- SCpnt->SCp.Message = 0;
- SCpnt->SCp.have_data_in = 0;
- SCpnt->SCp.sent_command = 0;
- if(SCpnt->SCp.phase & (resetting|check_condition)) {
- if (!SCpnt->host_scribble || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
- scmd_printk(KERN_ERR, SCpnt, "cannot reuse command\n");
- return FAILED;
- }
- } else {
- SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
- if(!SCpnt->host_scribble) {
- scmd_printk(KERN_ERR, SCpnt, "allocation failed\n");
- return FAILED;
- }
- }
- SCNEXT(SCpnt) = NULL;
- SCSEM(SCpnt) = complete;
- /* setup scratch area
- SCp.ptr : buffer pointer
- SCp.this_residual : buffer length
- SCp.buffer : next buffer
- SCp.buffers_residual : left buffers in list
- SCp.phase : current state of the command */
- if ((phase & resetting) || !scsi_sglist(SCpnt)) {
- SCpnt->SCp.ptr = NULL;
- SCpnt->SCp.this_residual = 0;
- scsi_set_resid(SCpnt, 0);
- SCpnt->SCp.buffer = NULL;
- SCpnt->SCp.buffers_residual = 0;
- } else {
- scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
- SCpnt->SCp.buffer = scsi_sglist(SCpnt);
- SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer);
- SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
- SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1;
- }
- DO_LOCK(flags);
- #if defined(AHA152X_STAT)
- HOSTDATA(shpnt)->total_commands++;
- #endif
- /* Turn led on, when this is the first command. */
- HOSTDATA(shpnt)->commands++;
- if (HOSTDATA(shpnt)->commands==1)
- SETPORT(PORTA, 1);
- append_SC(&ISSUE_SC, SCpnt);
- if(!HOSTDATA(shpnt)->in_intr)
- setup_expected_interrupts(shpnt);
- DO_UNLOCK(flags);
- return 0;
- }
- /*
- * queue a command
- *
- */
- static int aha152x_queue_lck(struct scsi_cmnd *SCpnt,
- void (*done)(struct scsi_cmnd *))
- {
- return aha152x_internal_queue(SCpnt, NULL, 0, done);
- }
- static DEF_SCSI_QCMD(aha152x_queue)
- /*
- *
- */
- static void reset_done(struct scsi_cmnd *SCpnt)
- {
- if(SCSEM(SCpnt)) {
- complete(SCSEM(SCpnt));
- } else {
- printk(KERN_ERR "aha152x: reset_done w/o completion\n");
- }
- }
- /*
- * Abort a command
- *
- */
- static int aha152x_abort(struct scsi_cmnd *SCpnt)
- {
- struct Scsi_Host *shpnt = SCpnt->device->host;
- struct scsi_cmnd *ptr;
- unsigned long flags;
- DO_LOCK(flags);
- ptr=remove_SC(&ISSUE_SC, SCpnt);
- if(ptr) {
- HOSTDATA(shpnt)->commands--;
- if (!HOSTDATA(shpnt)->commands)
- SETPORT(PORTA, 0);
- DO_UNLOCK(flags);
- kfree(SCpnt->host_scribble);
- SCpnt->host_scribble=NULL;
- return SUCCESS;
- }
- DO_UNLOCK(flags);
- /*
- * FIXME:
- * for current command: queue ABORT for message out and raise ATN
- * for disconnected command: pseudo SC with ABORT message or ABORT on reselection?
- *
- */
- scmd_printk(KERN_ERR, SCpnt,
- "cannot abort running or disconnected command\n");
- return FAILED;
- }
- /*
- * Reset a device
- *
- */
- static int aha152x_device_reset(struct scsi_cmnd * SCpnt)
- {
- struct Scsi_Host *shpnt = SCpnt->device->host;
- DECLARE_COMPLETION(done);
- int ret, issued, disconnected;
- unsigned char old_cmd_len = SCpnt->cmd_len;
- unsigned long flags;
- unsigned long timeleft;
- if(CURRENT_SC==SCpnt) {
- scmd_printk(KERN_ERR, SCpnt, "cannot reset current device\n");
- return FAILED;
- }
- DO_LOCK(flags);
- issued = remove_SC(&ISSUE_SC, SCpnt) == NULL;
- disconnected = issued && remove_SC(&DISCONNECTED_SC, SCpnt);
- DO_UNLOCK(flags);
- SCpnt->cmd_len = 0;
- aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
- timeleft = wait_for_completion_timeout(&done, 100*HZ);
- if (!timeleft) {
- /* remove command from issue queue */
- DO_LOCK(flags);
- remove_SC(&ISSUE_SC, SCpnt);
- DO_UNLOCK(flags);
- }
- SCpnt->cmd_len = old_cmd_len;
- DO_LOCK(flags);
- if(SCpnt->SCp.phase & resetted) {
- HOSTDATA(shpnt)->commands--;
- if (!HOSTDATA(shpnt)->commands)
- SETPORT(PORTA, 0);
- kfree(SCpnt->host_scribble);
- SCpnt->host_scribble=NULL;
- ret = SUCCESS;
- } else {
- /* requeue */
- if(!issued) {
- append_SC(&ISSUE_SC, SCpnt);
- } else if(disconnected) {
- append_SC(&DISCONNECTED_SC, SCpnt);
- }
- ret = FAILED;
- }
- DO_UNLOCK(flags);
- return ret;
- }
- static void free_hard_reset_SCs(struct Scsi_Host *shpnt,
- struct scsi_cmnd **SCs)
- {
- struct scsi_cmnd *ptr;
- ptr=*SCs;
- while(ptr) {
- struct scsi_cmnd *next;
- if(SCDATA(ptr)) {
- next = SCNEXT(ptr);
- } else {
- scmd_printk(KERN_DEBUG, ptr,
- "queue corrupted at %p\n", ptr);
- next = NULL;
- }
- if (!ptr->device->soft_reset) {
- remove_SC(SCs, ptr);
- HOSTDATA(shpnt)->commands--;
- kfree(ptr->host_scribble);
- ptr->host_scribble=NULL;
- }
- ptr = next;
- }
- }
- /*
- * Reset the bus
- *
- * AIC-6260 has a hard reset (MRST signal), but apparently
- * one cannot trigger it via software. So live with
- * a soft reset; no-one seemed to have cared.
- */
- static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
- {
- unsigned long flags;
- DO_LOCK(flags);
- free_hard_reset_SCs(shpnt, &ISSUE_SC);
- free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
- SETPORT(SCSISEQ, SCSIRSTO);
- mdelay(256);
- SETPORT(SCSISEQ, 0);
- mdelay(DELAY);
- setup_expected_interrupts(shpnt);
- if(HOSTDATA(shpnt)->commands==0)
- SETPORT(PORTA, 0);
- DO_UNLOCK(flags);
- return SUCCESS;
- }
- /*
- * Reset the bus
- *
- */
- static int aha152x_bus_reset(struct scsi_cmnd *SCpnt)
- {
- return aha152x_bus_reset_host(SCpnt->device->host);
- }
- /*
- * Restore default values to the AIC-6260 registers and reset the fifos
- *
- */
- static void reset_ports(struct Scsi_Host *shpnt)
- {
- unsigned long flags;
- /* disable interrupts */
- SETPORT(DMACNTRL0, RSTFIFO);
- SETPORT(SCSISEQ, 0);
- SETPORT(SXFRCTL1, 0);
- SETPORT(SCSISIG, 0);
- SETRATE(0);
- /* clear all interrupt conditions */
- SETPORT(SSTAT0, 0x7f);
- SETPORT(SSTAT1, 0xef);
- SETPORT(SSTAT4, SYNCERR | FWERR | FRERR);
- SETPORT(DMACNTRL0, 0);
- SETPORT(DMACNTRL1, 0);
- SETPORT(BRSTCNTRL, 0xf1);
- /* clear SCSI fifos and transfer count */
- SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
- SETPORT(SXFRCTL0, CH1);
- DO_LOCK(flags);
- setup_expected_interrupts(shpnt);
- DO_UNLOCK(flags);
- }
- /*
- * Reset the host (bus and controller)
- *
- */
- int aha152x_host_reset_host(struct Scsi_Host *shpnt)
- {
- aha152x_bus_reset_host(shpnt);
- reset_ports(shpnt);
- return SUCCESS;
- }
- /*
- * Return the "logical geometry"
- *
- */
- static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev,
- sector_t capacity, int *info_array)
- {
- struct Scsi_Host *shpnt = sdev->host;
- /* try default translation */
- info_array[0] = 64;
- info_array[1] = 32;
- info_array[2] = (unsigned long)capacity / (64 * 32);
- /* for disks >1GB do some guessing */
- if (info_array[2] >= 1024) {
- int info[3];
- /* try to figure out the geometry from the partition table */
- if (scsicam_bios_param(bdev, capacity, info) < 0 ||
- !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) {
- if (EXT_TRANS) {
- printk(KERN_NOTICE
- "aha152x: unable to verify geometry for disk with >1GB.\n"
- " using extended translation.\n");
- info_array[0] = 255;
- info_array[1] = 63;
- info_array[2] = (unsigned long)capacity / (255 * 63);
- } else {
- printk(KERN_NOTICE
- "aha152x: unable to verify geometry for disk with >1GB.\n"
- " Using default translation. Please verify yourself.\n"
- " Perhaps you need to enable extended translation in the driver.\n"
- " See Documentation/scsi/aha152x.txt for details.\n");
- }
- } else {
- info_array[0] = info[0];
- info_array[1] = info[1];
- info_array[2] = info[2];
- if (info[0] == 255 && !EXT_TRANS) {
- printk(KERN_NOTICE
- "aha152x: current partition table is using extended translation.\n"
- " using it also, although it's not explicitly enabled.\n");
- }
- }
- }
- return 0;
- }
- /*
- * Internal done function
- *
- */
- static void done(struct Scsi_Host *shpnt, int error)
- {
- if (CURRENT_SC) {
- if(DONE_SC)
- scmd_printk(KERN_ERR, CURRENT_SC,
- "there's already a completed command %p "
- "- will cause abort\n", DONE_SC);
- DONE_SC = CURRENT_SC;
- CURRENT_SC = NULL;
- DONE_SC->result = error;
- } else
- printk(KERN_ERR "aha152x: done() called outside of command\n");
- }
- static struct work_struct aha152x_tq;
- /*
- * Run service completions on the card with interrupts enabled.
- *
- */
- static void run(struct work_struct *work)
- {
- struct aha152x_hostdata *hd;
- list_for_each_entry(hd, &aha152x_host_list, host_list) {
- struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
- is_complete(shost);
- }
- }
- /*
- * Interrupt handler
- *
- */
- static irqreturn_t intr(int irqno, void *dev_id)
- {
- struct Scsi_Host *shpnt = dev_id;
- unsigned long flags;
- unsigned char rev, dmacntrl0;
- /*
- * Read a couple of registers that are known to not be all 1's. If
- * we read all 1's (-1), that means that either:
- *
- * a. The host adapter chip has gone bad, and we cannot control it,
- * OR
- * b. The host adapter is a PCMCIA card that has been ejected
- *
- * In either case, we cannot do anything with the host adapter at
- * this point in time. So just ignore the interrupt and return.
- * In the latter case, the interrupt might actually be meant for
- * someone else sharing this IRQ, and that driver will handle it.
- */
- rev = GETPORT(REV);
- dmacntrl0 = GETPORT(DMACNTRL0);
- if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
- return IRQ_NONE;
- if( TESTLO(DMASTAT, INTSTAT) )
- return IRQ_NONE;
- /* no more interrupts from the controller, while we're busy.
- INTEN is restored by the BH handler */
- CLRBITS(DMACNTRL0, INTEN);
- DO_LOCK(flags);
- if( HOSTDATA(shpnt)->service==0 ) {
- HOSTDATA(shpnt)->service=1;
- /* Poke the BH handler */
- INIT_WORK(&aha152x_tq, run);
- schedule_work(&aha152x_tq);
- }
- DO_UNLOCK(flags);
- return IRQ_HANDLED;
- }
- /*
- * busfree phase
- * - handle completition/disconnection/error of current command
- * - start selection for next command (if any)
- */
- static void busfree_run(struct Scsi_Host *shpnt)
- {
- unsigned long flags;
- #if defined(AHA152X_STAT)
- int action=0;
- #endif
- SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
- SETPORT(SXFRCTL0, CH1);
- SETPORT(SSTAT1, CLRBUSFREE);
- if(CURRENT_SC) {
- #if defined(AHA152X_STAT)
- action++;
- #endif
- CURRENT_SC->SCp.phase &= ~syncneg;
- if(CURRENT_SC->SCp.phase & completed) {
- /* target sent COMMAND COMPLETE */
- done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
- } else if(CURRENT_SC->SCp.phase & aborted) {
- done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_ABORT << 16));
- } else if(CURRENT_SC->SCp.phase & resetted) {
- done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_RESET << 16));
- } else if(CURRENT_SC->SCp.phase & disconnected) {
- /* target sent DISCONNECT */
- #if defined(AHA152X_STAT)
- HOSTDATA(shpnt)->disconnections++;
- #endif
- append_SC(&DISCONNECTED_SC, CURRENT_SC);
- CURRENT_SC->SCp.phase |= 1 << 16;
- CURRENT_SC = NULL;
- } else {
- done(shpnt, DID_ERROR << 16);
- }
- #if defined(AHA152X_STAT)
- } else {
- HOSTDATA(shpnt)->busfree_without_old_command++;
- #endif
- }
- DO_LOCK(flags);
- if(DONE_SC) {
- #if defined(AHA152X_STAT)
- action++;
- #endif
- if(DONE_SC->SCp.phase & check_condition) {
- struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
- struct aha152x_scdata *sc = SCDATA(cmd);
- scsi_eh_restore_cmnd(cmd, &sc->ses);
- cmd->SCp.Status = SAM_STAT_CHECK_CONDITION;
- HOSTDATA(shpnt)->commands--;
- if (!HOSTDATA(shpnt)->commands)
- SETPORT(PORTA, 0); /* turn led off */
- } else if(DONE_SC->SCp.Status==SAM_STAT_CHECK_CONDITION) {
- #if defined(AHA152X_STAT)
- HOSTDATA(shpnt)->busfree_with_check_condition++;
- #endif
- if(!(DONE_SC->SCp.phase & not_issued)) {
- struct aha152x_scdata *sc;
- struct scsi_cmnd *ptr = DONE_SC;
- DONE_SC=NULL;
- sc = SCDATA(ptr);
- /* It was allocated in aha152x_internal_queue? */
- BUG_ON(!sc);
- scsi_eh_prep_cmnd(ptr, &sc->ses, NULL, 0, ~0);
- DO_UNLOCK(flags);
- aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done);
- DO_LOCK(flags);
- }
- }
- if(DONE_SC && DONE_SC->scsi_done) {
- struct scsi_cmnd *ptr = DONE_SC;
- DONE_SC=NULL;
- /* turn led off, when no commands are in the driver */
- HOSTDATA(shpnt)->commands--;
- if (!HOSTDATA(shpnt)->commands)
- SETPORT(PORTA, 0); /* turn led off */
- if(ptr->scsi_done != reset_done) {
- kfree(ptr->host_scribble);
- ptr->host_scribble=NULL;
- }
- DO_UNLOCK(flags);
- ptr->scsi_done(ptr);
- DO_LOCK(flags);
- }
- DONE_SC=NULL;
- #if defined(AHA152X_STAT)
- } else {
- HOSTDATA(shpnt)->busfree_without_done_command++;
- #endif
- }
- if(ISSUE_SC)
- CURRENT_SC = remove_first_SC(&ISSUE_SC);
- DO_UNLOCK(flags);
- if(CURRENT_SC) {
- #if defined(AHA152X_STAT)
- action++;
- #endif
- CURRENT_SC->SCp.phase |= selecting;
- /* clear selection timeout */
- SETPORT(SSTAT1, SELTO);
- SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->device->id);
- SETPORT(SXFRCTL1, (PARITY ? ENSPCHK : 0 ) | ENSTIMER);
- SETPORT(SCSISEQ, ENSELO | ENAUTOATNO | (DISCONNECTED_SC ? ENRESELI : 0));
- } else {
- #if defined(AHA152X_STAT)
- HOSTDATA(shpnt)->busfree_without_new_command++;
- #endif
- SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
- }
- #if defined(AHA152X_STAT)
- if(!action)
- HOSTDATA(shpnt)->busfree_without_any_action++;
- #endif
- }
- /*
- * Selection done (OUT)
- * - queue IDENTIFY message and SDTR to selected target for message out
- * (ATN asserted automagically via ENAUTOATNO in busfree())
- */
- static void seldo_run(struct Scsi_Host *shpnt)
- {
- SETPORT(SCSISIG, 0);
- SETPORT(SSTAT1, CLRBUSFREE);
- SETPORT(SSTAT1, CLRPHASECHG);
- CURRENT_SC->SCp.phase &= ~(selecting|not_issued);
- SETPORT(SCSISEQ, 0);
- if (TESTLO(SSTAT0, SELDO)) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "aha152x: passing bus free condition\n");
- done(shpnt, DID_NO_CONNECT << 16);
- return;
- }
- SETPORT(SSTAT0, CLRSELDO);
- ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
- if (CURRENT_SC->SCp.phase & aborting) {
- ADDMSGO(ABORT);
- } else if (CURRENT_SC->SCp.phase & resetting) {
- ADDMSGO(BUS_DEVICE_RESET);
- } else if (SYNCNEG==0 && SYNCHRONOUS) {
- CURRENT_SC->SCp.phase |= syncneg;
- MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
- SYNCNEG=1; /* negotiation in progress */
- }
- SETRATE(SYNCRATE);
- }
- /*
- * Selection timeout
- * - return command to mid-level with failure cause
- *
- */
- static void selto_run(struct Scsi_Host *shpnt)
- {
- SETPORT(SCSISEQ, 0);
- SETPORT(SSTAT1, CLRSELTIMO);
- if (!CURRENT_SC)
- return;
- CURRENT_SC->SCp.phase &= ~selecting;
- if (CURRENT_SC->SCp.phase & aborted)
- done(shpnt, DID_ABORT << 16);
- else if (TESTLO(SSTAT0, SELINGO))
- done(shpnt, DID_BUS_BUSY << 16);
- else
- /* ARBITRATION won, but SELECTION failed */
- done(shpnt, DID_NO_CONNECT << 16);
- }
- /*
- * Selection in done
- * - put current command back to issue queue
- * (reconnection of a disconnected nexus instead
- * of successful selection out)
- *
- */
- static void seldi_run(struct Scsi_Host *shpnt)
- {
- int selid;
- int target;
- unsigned long flags;
- SETPORT(SCSISIG, 0);
- SETPORT(SSTAT0, CLRSELDI);
- SETPORT(SSTAT1, CLRBUSFREE);
- SETPORT(SSTAT1, CLRPHASECHG);
- if(CURRENT_SC) {
- if(!(CURRENT_SC->SCp.phase & not_issued))
- scmd_printk(KERN_ERR, CURRENT_SC,
- "command should not have been issued yet\n");
- DO_LOCK(flags);
- append_SC(&ISSUE_SC, CURRENT_SC);
- DO_UNLOCK(flags);
- CURRENT_SC = NULL;
- }
- if (!DISCONNECTED_SC)
- return;
- RECONN_TARGET=-1;
- selid = GETPORT(SELID) & ~(1 << shpnt->this_id);
- if (selid==0) {
- shost_printk(KERN_INFO, shpnt,
- "target id unknown (%02x)\n", selid);
- return;
- }
- for(target=7; !(selid & (1 << target)); target--)
- ;
- if(selid & ~(1 << target)) {
- shost_printk(KERN_INFO, shpnt,
- "multiple targets reconnected (%02x)\n", selid);
- }
- SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
- SETPORT(SCSISEQ, 0);
- SETRATE(HOSTDATA(shpnt)->syncrate[target]);
- RECONN_TARGET=target;
- }
- /*
- * message in phase
- * - handle initial message after reconnection to identify
- * reconnecting nexus
- * - queue command on DISCONNECTED_SC on DISCONNECT message
- * - set completed flag on COMMAND COMPLETE
- * (other completition code moved to busfree_run)
- * - handle response to SDTR
- * - clear synchronous transfer agreements on BUS RESET
- *
- * FIXME: what about SAVE POINTERS, RESTORE POINTERS?
- *
- */
- static void msgi_run(struct Scsi_Host *shpnt)
- {
- for(;;) {
- int sstat1 = GETPORT(SSTAT1);
- if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT))
- return;
- if (TESTLO(SSTAT0, SPIORDY))
- return;
- ADDMSGI(GETPORT(SCSIDAT));
- if(!CURRENT_SC) {
- if(LASTSTATE!=seldi) {
- shost_printk(KERN_ERR, shpnt,
- "message in w/o current command"
- " not after reselection\n");
- }
- /*
- * Handle reselection
- */
- if(!(MSGI(0) & IDENTIFY_BASE)) {
- shost_printk(KERN_ERR, shpnt,
- "target didn't identify after reselection\n");
- continue;
- }
- CURRENT_SC = remove_lun_SC(&DISCONNECTED_SC, RECONN_TARGET, MSGI(0) & 0x3f);
- if (!CURRENT_SC) {
- show_queues(shpnt);
- shost_printk(KERN_ERR, shpnt,
- "no disconnected command"
- " for target %d/%d\n",
- RECONN_TARGET, MSGI(0) & 0x3f);
- continue;
- }
- CURRENT_SC->SCp.Message = MSGI(0);
- CURRENT_SC->SCp.phase &= ~disconnected;
- MSGILEN=0;
- /* next message if any */
- continue;
- }
- CURRENT_SC->SCp.Message = MSGI(0);
- switch (MSGI(0)) {
- case DISCONNECT:
- if (!RECONNECT)
- scmd_printk(KERN_WARNING, CURRENT_SC,
- "target was not allowed to disconnect\n");
- CURRENT_SC->SCp.phase |= disconnected;
- break;
- case COMMAND_COMPLETE:
- CURRENT_SC->SCp.phase |= completed;
- break;
- case MESSAGE_REJECT:
- if (SYNCNEG==1) {
- scmd_printk(KERN_INFO, CURRENT_SC,
- "Synchronous Data Transfer Request"
- " was rejected\n");
- SYNCNEG=2; /* negotiation completed */
- } else
- scmd_printk(KERN_INFO, CURRENT_SC,
- "inbound message (MESSAGE REJECT)\n");
- break;
- case SAVE_POINTERS:
- break;
- case RESTORE_POINTERS:
- break;
- case EXTENDED_MESSAGE:
- if(MSGILEN<2 || MSGILEN<MSGI(1)+2) {
- /* not yet completed */
- continue;
- }
- switch (MSGI(2)) {
- case EXTENDED_SDTR:
- {
- long ticks;
- if (MSGI(1) != 3) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "SDTR message length!=3\n");
- break;
- }
- if (!HOSTDATA(shpnt)->synchronous)
- break;
- printk(INFO_LEAD, CMDINFO(CURRENT_SC));
- spi_print_msg(&MSGI(0));
- printk("\n");
- ticks = (MSGI(3) * 4 + 49) / 50;
- if (syncneg) {
- /* negotiation in progress */
- if (ticks > 9 || MSGI(4) < 1 || MSGI(4) > 8) {
- ADDMSGO(MESSAGE_REJECT);
- scmd_printk(KERN_INFO,
- CURRENT_SC,
- "received Synchronous Data Transfer Request invalid - rejected\n");
- break;
- }
- SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
- } else if (ticks <= 9 && MSGI(4) >= 1) {
- ADDMSGO(EXTENDED_MESSAGE);
- ADDMSGO(3);
- ADDMSGO(EXTENDED_SDTR);
- if (ticks < 4) {
- ticks = 4;
- ADDMSGO(50);
- } else
- ADDMSGO(MSGI(3));
- if (MSGI(4) > 8)
- MSGI(4) = 8;
- ADDMSGO(MSGI(4));
- SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
- } else {
- /* requested SDTR is too slow, do it asynchronously */
- scmd_printk(KERN_INFO,
- CURRENT_SC,
- "Synchronous Data Transfer Request too slow - Rejecting\n");
- ADDMSGO(MESSAGE_REJECT);
- }
- /* negotiation completed */
- SYNCNEG=2;
- SETRATE(SYNCRATE);
- }
- break;
- case BUS_DEVICE_RESET:
- {
- int i;
- for(i=0; i<8; i++) {
- HOSTDATA(shpnt)->syncrate[i]=0;
- HOSTDATA(shpnt)->syncneg[i]=0;
- }
- }
- break;
- case EXTENDED_MODIFY_DATA_POINTER:
- case EXTENDED_EXTENDED_IDENTIFY:
- case EXTENDED_WDTR:
- default:
- ADDMSGO(MESSAGE_REJECT);
- break;
- }
- break;
- }
- MSGILEN=0;
- }
- }
- static void msgi_end(struct Scsi_Host *shpnt)
- {
- if(MSGILEN>0)
- scmd_printk(KERN_WARNING, CURRENT_SC,
- "target left before message completed (%d)\n",
- MSGILEN);
- if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE))
- SETPORT(SCSISIG, P_MSGI | SIG_ATNO);
- }
- /*
- * message out phase
- *
- */
- static void msgo_init(struct Scsi_Host *shpnt)
- {
- if(MSGOLEN==0) {
- if((CURRENT_SC->SCp.phase & syncneg) && SYNCNEG==2 && SYNCRATE==0) {
- ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
- } else {
- scmd_printk(KERN_INFO, CURRENT_SC,
- "unexpected MESSAGE OUT phase; rejecting\n");
- ADDMSGO(MESSAGE_REJECT);
- }
- }
- }
- /*
- * message out phase
- *
- */
- static void msgo_run(struct Scsi_Host *shpnt)
- {
- while(MSGO_I<MSGOLEN) {
- if (TESTLO(SSTAT0, SPIORDY))
- return;
- if (MSGO_I==MSGOLEN-1) {
- /* Leave MESSAGE OUT after transfer */
- SETPORT(SSTAT1, CLRATNO);
- }
- if (MSGO(MSGO_I) & IDENTIFY_BASE)
- CURRENT_SC->SCp.phase |= identified;
- if (MSGO(MSGO_I)==ABORT)
- CURRENT_SC->SCp.phase |= aborted;
- if (MSGO(MSGO_I)==BUS_DEVICE_RESET)
- CURRENT_SC->SCp.phase |= resetted;
- SETPORT(SCSIDAT, MSGO(MSGO_I++));
- }
- }
- static void msgo_end(struct Scsi_Host *shpnt)
- {
- if(MSGO_I<MSGOLEN) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "message sent incompletely (%d/%d)\n",
- MSGO_I, MSGOLEN);
- if(SYNCNEG==1) {
- scmd_printk(KERN_INFO, CURRENT_SC,
- "Synchronous Data Transfer Request was rejected\n");
- SYNCNEG=2;
- }
- }
- MSGO_I = 0;
- MSGOLEN = 0;
- }
- /*
- * command phase
- *
- */
- static void cmd_init(struct Scsi_Host *shpnt)
- {
- if (CURRENT_SC->SCp.sent_command) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "command already sent\n");
- done(shpnt, DID_ERROR << 16);
- return;
- }
- CMD_I=0;
- }
- /*
- * command phase
- *
- */
- static void cmd_run(struct Scsi_Host *shpnt)
- {
- while(CMD_I<CURRENT_SC->cmd_len) {
- if (TESTLO(SSTAT0, SPIORDY))
- return;
- SETPORT(SCSIDAT, CURRENT_SC->cmnd[CMD_I++]);
- }
- }
- static void cmd_end(struct Scsi_Host *shpnt)
- {
- if(CMD_I<CURRENT_SC->cmd_len)
- scmd_printk(KERN_ERR, CURRENT_SC,
- "command sent incompletely (%d/%d)\n",
- CMD_I, CURRENT_SC->cmd_len);
- else
- CURRENT_SC->SCp.sent_command++;
- }
- /*
- * status phase
- *
- */
- static void status_run(struct Scsi_Host *shpnt)
- {
- if (TESTLO(SSTAT0, SPIORDY))
- return;
- CURRENT_SC->SCp.Status = GETPORT(SCSIDAT);
- }
- /*
- * data in phase
- *
- */
- static void datai_init(struct Scsi_Host *shpnt)
- {
- SETPORT(DMACNTRL0, RSTFIFO);
- SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
- SETPORT(SXFRCTL0, CH1|CLRSTCNT);
- SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
- SETPORT(SIMODE0, 0);
- SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE);
- DATA_LEN=0;
- }
- static void datai_run(struct Scsi_Host *shpnt)
- {
- unsigned long the_time;
- int fifodata, data_count;
- /*
- * loop while the phase persists or the fifos are not empty
- *
- */
- while(TESTLO(DMASTAT, INTSTAT) || TESTLO(DMASTAT, DFIFOEMP) || TESTLO(SSTAT2, SEMPTY)) {
- /* FIXME: maybe this should be done by setting up
- * STCNT to trigger ENSWRAP interrupt, instead of
- * polling for DFIFOFULL
- */
- the_time=jiffies + 100*HZ;
- while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT) && time_before(jiffies,the_time))
- barrier();
- if(TESTLO(DMASTAT, DFIFOFULL|INTSTAT)) {
- scmd_printk(KERN_ERR, CURRENT_SC, "datai timeout\n");
- break;
- }
- if(TESTHI(DMASTAT, DFIFOFULL)) {
- fifodata = 128;
- } else {
- the_time=jiffies + 100*HZ;
- while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time))
- barrier();
- if(TESTLO(SSTAT2, SEMPTY)) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "datai sempty timeout");
- break;
- }
- fifodata = GETPORT(FIFOSTAT);
- }
- if(CURRENT_SC->SCp.this_residual>0) {
- while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) {
- data_count = fifodata > CURRENT_SC->SCp.this_residual ?
- CURRENT_SC->SCp.this_residual :
- fifodata;
- fifodata -= data_count;
- if (data_count & 1) {
- SETPORT(DMACNTRL0, ENDMA|_8BIT);
- *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
- CURRENT_SC->SCp.this_residual--;
- DATA_LEN++;
- SETPORT(DMACNTRL0, ENDMA);
- }
- if (data_count > 1) {
- data_count >>= 1;
- insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
- CURRENT_SC->SCp.ptr += 2 * data_count;
- CURRENT_SC->SCp.this_residual -= 2 * data_count;
- DATA_LEN += 2 * data_count;
- }
- if (CURRENT_SC->SCp.this_residual == 0 &&
- CURRENT_SC->SCp.buffers_residual > 0) {
- /* advance to next buffer */
- CURRENT_SC->SCp.buffers_residual--;
- CURRENT_SC->SCp.buffer++;
- CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
- CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
- }
- }
- } else if (fifodata > 0) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "no buffers left for %d(%d) bytes"
- " (data overrun!?)\n",
- fifodata, GETPORT(FIFOSTAT));
- SETPORT(DMACNTRL0, ENDMA|_8BIT);
- while(fifodata>0) {
- int data;
- data=GETPORT(DATAPORT);
- fifodata--;
- DATA_LEN++;
- }
- SETPORT(DMACNTRL0, ENDMA|_8BIT);
- }
- }
- if(TESTLO(DMASTAT, INTSTAT) ||
- TESTLO(DMASTAT, DFIFOEMP) ||
- TESTLO(SSTAT2, SEMPTY) ||
- GETPORT(FIFOSTAT)>0) {
- /*
- * something went wrong, if there's something left in the fifos
- * or the phase didn't change
- */
- scmd_printk(KERN_ERR, CURRENT_SC,
- "fifos should be empty and phase should have changed\n");
- }
- if(DATA_LEN!=GETSTCNT()) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "manual transfer count differs from automatic "
- "(count=%d;stcnt=%d;diff=%d;fifostat=%d)",
- DATA_LEN, GETSTCNT(), GETSTCNT()-DATA_LEN,
- GETPORT(FIFOSTAT));
- mdelay(10000);
- }
- }
- static void datai_end(struct Scsi_Host *shpnt)
- {
- CMD_INC_RESID(CURRENT_SC, -GETSTCNT());
- SETPORT(SXFRCTL0, CH1|CLRSTCNT);
- SETPORT(DMACNTRL0, 0);
- }
- /*
- * data out phase
- *
- */
- static void datao_init(struct Scsi_Host *shpnt)
- {
- SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO);
- SETPORT(DMACNTRL0, WRITE_READ | ENDMA);
- SETPORT(SXFRCTL0, CH1|CLRSTCNT);
- SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
- SETPORT(SIMODE0, 0);
- SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE );
- DATA_LEN = scsi_get_resid(CURRENT_SC);
- }
- static void datao_run(struct Scsi_Host *shpnt)
- {
- unsigned long the_time;
- int data_count;
- /* until phase changes or all data sent */
- while(TESTLO(DMASTAT, INTSTAT) && CURRENT_SC->SCp.this_residual>0) {
- data_count = 128;
- if(data_count > CURRENT_SC->SCp.this_residual)
- data_count=CURRENT_SC->SCp.this_residual;
- if(TESTLO(DMASTAT, DFIFOEMP)) {
- scmd_printk(KERN_ERR, CURRENT_SC,
- "datao fifo not empty (%d)",
- GETPORT(FIFOSTAT));
- break;
- }
- if(data_count & 1) {
- SETPORT(DMACNTRL0,WRITE_READ|ENDMA|_8BIT);
- SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
- CURRENT_SC->SCp.this_residual--;
- CMD_INC_RESID(CURRENT_SC, -1);
- SETPORT(DMACNTRL0,WRITE_READ|ENDMA);
- }
- if(data_count > 1) {
- data_count >>= 1;
- outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
- CURRENT_SC->SCp.ptr += 2 * data_count;
- CURRENT_SC->SCp.this_residual -= 2 * data_count;
- CMD_INC_RESID(CURRENT_SC, -2 * data_count);
- }
- if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) {
- /* advance to next buffer */
- CURRENT_SC->SCp.buffers_residual--;
- CURRENT_SC->SCp.buffer++;
- CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
- CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
- }
- the_time=jiffies + 100*HZ;
- while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time))
- barrier();
- if(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) {
- scmd_printk(KERN_ERR, CURRENT_SC, "dataout timeout\n");
- break;
- }
- }
- }
- static void datao_end(struct Scsi_Host *shpnt)
- {
- if(TESTLO(DMASTAT, DFIFOEMP)) {
- int data_count = (DATA_LEN - scsi_get_resid(CURRENT_SC)) -
- GETSTCNT();
- CMD_INC_RESID(CURRENT_SC, data_count);
- data_count -= CURRENT_SC->SCp.ptr -
- SG_ADDRESS(CURRENT_SC->SCp.buffer);
- while(data_count>0) {
- CURRENT_SC->SCp.buffer--;
- CURRENT_SC->SCp.buffers_residual++;
- data_count -= CURRENT_SC->SCp.buffer->length;
- }
- CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) -
- data_count;
- CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length +
- data_count;
- }
- SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
- SETPORT(SXFRCTL0, CH1);
- SETPORT(DMACNTRL0, 0);
- }
- /*
- * figure out what state we're in
- *
- */
- static int update_state(struct Scsi_Host *shpnt)
- {
- int dataphase=0;
- unsigned int stat0 = GETPORT(SSTAT0);
- unsigned int stat1 = GETPORT(SSTAT1);
- PREVSTATE = STATE;
- STATE=unknown;
- if(stat1 & SCSIRSTI) {
- STATE=rsti;
- SETPORT(SCSISEQ,0);
- SETPORT(SSTAT1,SCSIRSTI);
- } else if (stat0 & SELDI && PREVSTATE == busfree) {
- STATE=seldi;
- } else if(stat0 & SELDO && CURRENT_SC && (CURRENT_SC->SCp.phase & selecting)) {
- STATE=seldo;
- } else if(stat1 & SELTO) {
- STATE=selto;
- } else if(stat1 & BUSFREE) {
- STATE=busfree;
- SETPORT(SSTAT1,BUSFREE);
- } else if(stat1 & SCSIPERR) {
- STATE=parerr;
- SETPORT(SSTAT1,SCSIPERR);
- } else if(stat1 & REQINIT) {
- switch(GETPORT(SCSISIG) & P_MASK) {
- case P_MSGI: STATE=msgi; break;
- case P_MSGO: STATE=msgo; break;
- case P_DATAO: STATE=datao; break;
- case P_DATAI: STATE=datai; break;
- case P_STATUS: STATE=status; break;
- case P_CMD: STATE=cmd; break;
- }
- dataphase=1;
- }
- if((stat0 & SELDI) && STATE!=seldi && !dataphase) {
- scmd_printk(KERN_INFO, CURRENT_SC, "reselection missed?");
- }
- if(STATE!=PREVSTATE) {
- LASTSTATE=PREVSTATE;
- }
- return dataphase;
- }
- /*
- * handle parity error
- *
- * FIXME: in which phase?
- *
- */
- static void parerr_run(struct Scsi_Host *shpnt)
- {
- scmd_printk(KERN_ERR, CURRENT_SC, "parity error\n");
- done(shpnt, DID_PARITY << 16);
- }
- /*
- * handle reset in
- *
- */
- static void rsti_run(struct Scsi_Host *shpnt)
- {
- struct scsi_cmnd *ptr;
- shost_printk(KERN_NOTICE, shpnt, "scsi reset in\n");
- ptr=DISCONNECTED_SC;
- while(ptr) {
- struct scsi_cmnd *next = SCNEXT(ptr);
- if (!ptr->device->soft_reset) {
- remove_SC(&DISCONNECTED_SC, ptr);
- kfree(ptr->host_scribble);
- ptr->host_scribble=NULL;
- ptr->result = DID_RESET << 16;
- ptr->scsi_done(ptr);
- }
- ptr = next;
- }
- if(CURRENT_SC && !CURRENT_SC->device->soft_reset)
- done(shpnt, DID_RESET << 16 );
- }
- /*
- * bottom-half handler
- *
- */
- static void is_complete(struct Scsi_Host *shpnt)
- {
- int dataphase;
- unsigned long flags;
- int pending;
- if(!shpnt)
- return;
- DO_LOCK(flags);
- if( HOSTDATA(shpnt)->service==0 ) {
- DO_UNLOCK(flags);
- return;
- }
- HOSTDATA(shpnt)->service = 0;
- if(HOSTDATA(shpnt)->in_intr) {
- DO_UNLOCK(flags);
- /* aha152x_error never returns.. */
- aha152x_error(shpnt, "bottom-half already running!?");
- }
- HOSTDATA(shpnt)->in_intr++;
- /*
- * loop while there are interrupt conditions pending
- *
- */
- do {
- unsigned long start = jiffies;
- DO_UNLOCK(flags);
- dataphase=update_state(shpnt);
- /*
- * end previous state
- *
- */
- if(PREVSTATE!=STATE && states[PREVSTATE].end)
- states[PREVSTATE].end(shpnt);
- /*
- * disable SPIO mode if previous phase used it
- * and this one doesn't
- *
- */
- if(states[PREVSTATE].spio && !states[STATE].spio) {
- SETPORT(SXFRCTL0, CH1);
- SETPORT(DMACNTRL0, 0);
- if(CURRENT_SC)
- CURRENT_SC->SCp.phase &= ~spiordy;
- }
- /*
- * accept current dataphase phase
- *
- */
- if(dataphase) {
- SETPORT(SSTAT0, REQINIT);
- SETPORT(SCSISIG, GETPORT(SCSISIG) & P_MASK);
- SETPORT(SSTAT1, PHASECHG);
- }
- /*
- * enable SPIO mode if previous didn't use it
- * and this one does
- *
- */
- if(!states[PREVSTATE].spio && states[STATE].spio) {
- SETPORT(DMACNTRL0, 0);
- SETPORT(SXFRCTL0, CH1|SPIOEN);
- if(CURRENT_SC)
- CURRENT_SC->SCp.phase |= spiordy;
- }
- /*
- * initialize for new state
- *
- */
- if(PREVSTATE!=STATE && states[STATE].init)
- states[STATE].init(shpnt);
- /*
- * handle current state
- *
- */
- if(states[STATE].run)
- states[STATE].run(shpnt);
- else
- scmd_printk(KERN_ERR, CURRENT_SC,
- "unexpected state (%x)\n", STATE);
- /*
- * setup controller to interrupt on
- * the next expected condition and
- * loop if it's already there
- *
- */
- DO_LOCK(flags);
- pending=setup_expected_interrupts(shpnt);
- #if defined(AHA152X_STAT)
- HOSTDATA(shpnt)->count[STATE]++;
- if(PREVSTATE!=STATE)
- HOSTDATA(shpnt)->count_trans[STATE]++;
- HOSTDATA(shpnt)->time[STATE] += jiffies-start;
- #endif
- } while(pending);
- /*
- * enable interrupts and leave bottom-half
- *
- */
- HOSTDATA(shpnt)->in_intr--;
- SETBITS(DMACNTRL0, INTEN);
- DO_UNLOCK(flags);
- }
- /*
- * Dump the current driver status and panic
- */
- static void aha152x_error(struct Scsi_Host *shpnt, char *msg)
- {
- shost_printk(KERN_EMERG, shpnt, "%s\n", msg);
- show_queues(shpnt);
- panic("aha152x panic\n");
- }
- /*
- * display enabled interrupts
- */
- static void disp_enintr(struct Scsi_Host *shpnt)
- {
- int s0, s1;
- s0 = GETPORT(SIMODE0);
- s1 = GETPORT(SIMODE1);
- shost_printk(KERN_DEBUG, shpnt,
- "enabled interrupts (%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
- (s0 & ENSELDO) ? "ENSELDO " : "",
- (s0 & ENSELDI) ? "ENSELDI " : "",
- (s0 & ENSELINGO) ? "ENSELINGO " : "",
- (s0 & ENSWRAP) ? "ENSWRAP " : "",
- (s0 & ENSDONE) ? "ENSDONE " : "",
- (s0 & ENSPIORDY) ? "ENSPIORDY " : "",
- (s0 & ENDMADONE) ? "ENDMADONE " : "",
- (s1 & ENSELTIMO) ? "ENSELTIMO " : "",
- (s1 & ENATNTARG) ? "ENATNTARG " : "",
- (s1 & ENPHASEMIS) ? "ENPHASEMIS " : "",
- (s1 & ENBUSFREE) ? "ENBUSFREE " : "",
- (s1 & ENSCSIPERR) ? "ENSCSIPERR " : "",
- (s1 & ENPHASECHG) ? "ENPHASECHG " : "",
- (s1 & ENREQINIT) ? "ENREQINIT " : "");
- }
- /*
- * Show the command data of a command
- */
- static void show_command(struct scsi_cmnd *ptr)
- {
- scsi_print_command(ptr);
- scmd_printk(KERN_DEBUG, ptr,
- "request_bufflen=%d; resid=%d; "
- "phase |%s%s%s%s%s%s%s%s%s; next=0x%p",
- scsi_bufflen(ptr), scsi_get_resid(ptr),
- (ptr->SCp.phase & not_issued) ? "not issued|" : "",
- (ptr->SCp.phase & selecting) ? "selecting|" : "",
- (ptr->SCp.phase & identified) ? "identified|" : "",
- (ptr->SCp.phase & disconnected) ? "disconnected|" : "",
- (ptr->SCp.phase & completed) ? "completed|" : "",
- (ptr->SCp.phase & spiordy) ? "spiordy|" : "",
- (ptr->SCp.phase & syncneg) ? "syncneg|" : "",
- (ptr->SCp.phase & aborted) ? "aborted|" : "",
- (ptr->SCp.phase & resetted) ? "resetted|" : "",
- (SCDATA(ptr)) ? SCNEXT(ptr) : NULL);
- }
- /*
- * Dump the queued data
- */
- static void show_queues(struct Scsi_Host *shpnt)
- {
- struct scsi_cmnd *ptr;
- unsigned long flags;
- DO_LOCK(flags);
- printk(KERN_DEBUG "\nqueue status:\nissue_SC:\n");
- for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
- show_command(ptr);
- DO_UNLOCK(flags);
- printk(KERN_DEBUG "current_SC:\n");
- if (CURRENT_SC)
- show_command(CURRENT_SC);
- else
- printk(KERN_DEBUG "none\n");
- printk(KERN_DEBUG "disconnected_SC:\n");
- for (ptr = DISCONNECTED_SC; ptr; ptr = SCDATA(ptr) ? SCNEXT(ptr) : NULL)
- show_command(ptr);
- disp_enintr(shpnt);
- }
- static void get_command(struct seq_file *m, struct scsi_cmnd * ptr)
- {
- int i;
- seq_printf(m, "%p: target=%d; lun=%d; cmnd=( ",
- ptr, ptr->device->id, (u8)ptr->device->lun);
- for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++)
- seq_printf(m, "0x%02x ", ptr->cmnd[i]);
- seq_printf(m, "); resid=%d; residual=%d; buffers=%d; phase |",
- scsi_get_resid(ptr), ptr->SCp.this_residual,
- ptr->SCp.buffers_residual);
- if (ptr->SCp.phase & not_issued)
- seq_puts(m, "not issued|");
- if (ptr->SCp.phase & selecting)
- seq_puts(m, "selecting|");
- if (ptr->SCp.phase & disconnected)
- seq_puts(m, "disconnected|");
- if (ptr->SCp.phase & aborted)
- seq_puts(m, "aborted|");
- if (ptr->SCp.phase & identified)
- seq_puts(m, "identified|");
- if (ptr->SCp.phase & completed)
- seq_puts(m, "completed|");
- if (ptr->SCp.phase & spiordy)
- seq_puts(m, "spiordy|");
- if (ptr->SCp.phase & syncneg)
- seq_puts(m, "syncneg|");
- seq_printf(m, "; next=0x%p\n", SCNEXT(ptr));
- }
- static void get_ports(struct seq_file *m, struct Scsi_Host *shpnt)
- {
- int s;
- seq_printf(m, "\n%s: %s(%s) ", CURRENT_SC ? "on bus" : "waiting", states[STATE].name, states[PREVSTATE].name);
- s = GETPORT(SCSISEQ);
- seq_puts(m, "SCSISEQ( ");
- if (s & TEMODEO)
- seq_puts(m, "TARGET MODE ");
- if (s & ENSELO)
- seq_puts(m, "SELO ");
- if (s & ENSELI)
- seq_puts(m, "SELI ");
- if (s & ENRESELI)
- seq_puts(m, "RESELI ");
- if (s & ENAUTOATNO)
- seq_puts(m, "AUTOATNO ");
- if (s & ENAUTOATNI)
- seq_puts(m, "AUTOATNI ");
- if (s & ENAUTOATNP)
- seq_puts(m, "AUTOATNP ");
- if (s & SCSIRSTO)
- seq_puts(m, "SCSIRSTO ");
- seq_puts(m, ");");
- seq_puts(m, " SCSISIG(");
- s = GETPORT(SCSISIG);
- switch (s & P_MASK) {
- case P_DATAO:
- seq_puts(m, "DATA OUT");
- break;
- case P_DATAI:
- seq_puts(m, "DATA IN");
- break;
- case P_CMD:
- seq_puts(m, "COMMAND");
- break;
- case P_STATUS:
- seq_puts(m, "STATUS");
- break;
- case P_MSGO:
- seq_puts(m, "MESSAGE OUT");
- break;
- case P_MSGI:
- seq_puts(m, "MESSAGE IN");
- break;
- default:
- seq_puts(m, "*invalid*");
- break;
- }
- seq_puts(m, "); ");
- seq_printf(m, "INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
- seq_puts(m, "SSTAT( ");
- s = GETPORT(SSTAT0);
- if (s & TARGET)
- seq_puts(m, "TARGET ");
- if (s & SELDO)
- seq_puts(m, "SELDO ");
- if (s & SELDI)
- seq_puts(m, "SELDI ");
- if (s & SELINGO)
- seq_puts(m, "SELINGO ");
- if (s & SWRAP)
- seq_puts(m, "SWRAP ");
- if (s & SDONE)
- seq_puts(m, "SDONE ");
- if (s & SPIORDY)
- seq_puts(m, "SPIORDY ");
- if (s & DMADONE)
- seq_puts(m, "DMADONE ");
- s = GETPORT(SSTAT1);
- if (s & SELTO)
- seq_puts(m, "SELTO ");
- if (s & ATNTARG)
- seq_puts(m, "ATNTARG ");
- if (s & SCSIRSTI)
- seq_puts(m, "SCSIRSTI ");
- if (s & PHASEMIS)
- seq_puts(m, "PHASEMIS ");
- if (s & BUSFREE)
- seq_puts(m, "BUSFREE ");
- if (s & SCSIPERR)
- seq_puts(m, "SCSIPERR ");
- if (s & PHASECHG)
- seq_puts(m, "PHASECHG ");
- if (s & REQINIT)
- seq_puts(m, "REQINIT ");
- seq_puts(m, "); ");
- seq_puts(m, "SSTAT( ");
- s = GETPORT(SSTAT0) & GETPORT(SIMODE0);
- if (s & TARGET)
- seq_puts(m, "TARGET ");
- if (s & SELDO)
- seq_puts(m, "SELDO ");
- if (s & SELDI)
- seq_puts(m, "SELDI ");
- if (s & SELINGO)
- seq_puts(m, "SELINGO ");
- if (s & SWRAP)
- seq_puts(m, "SWRAP ");
- if (s & SDONE)
- seq_puts(m, "SDONE ");
- if (s & SPIORDY)
- seq_puts(m, "SPIORDY ");
- if (s & DMADONE)
- seq_puts(m, "DMADONE ");
- s = GETPORT(SSTAT1) & GETPORT(SIMODE1);
- if (s & SELTO)
- seq_puts(m, "SELTO ");
- if (s & ATNTARG)
- seq_puts(m, "ATNTARG ");
- if (s & SCSIRSTI)
- seq_puts(m, "SCSIRSTI ");
- if (s & PHASEMIS)
- seq_puts(m, "PHASEMIS ");
- if (s & BUSFREE)
- seq_puts(m, "BUSFREE ");
- if (s & SCSIPERR)
- seq_puts(m, "SCSIPERR ");
- if (s & PHASECHG)
- seq_puts(m, "PHASECHG ");
- if (s & REQINIT)
- seq_puts(m, "REQINIT ");
- seq_puts(m, "); ");
- seq_puts(m, "SXFRCTL0( ");
- s = GETPORT(SXFRCTL0);
- if (s & SCSIEN)
- seq_puts(m, "SCSIEN ");
- if (s & DMAEN)
- seq_puts(m, "DMAEN ");
- if (s & CH1)
- seq_puts(m, "CH1 ");
- if (s & CLRSTCNT)
- seq_puts(m, "CLRSTCNT ");
- if (s & SPIOEN)
- seq_puts(m, "SPIOEN ");
- if (s & CLRCH1)
- seq_puts(m, "CLRCH1 ");
- seq_puts(m, "); ");
- seq_puts(m, "SIGNAL( ");
- s = GETPORT(SCSISIG);
- if (s & SIG_ATNI)
- seq_puts(m, "ATNI ");
- if (s & SIG_SELI)
- seq_puts(m, "SELI ");
- if (s & SIG_BSYI)
- seq_puts(m, "BSYI ");
- if (s & SIG_REQI)
- seq_puts(m, "REQI ");
- if (s & SIG_ACKI)
- seq_puts(m, "ACKI ");
- seq_puts(m, "); ");
- seq_printf(m, "SELID(%02x), ", GETPORT(SELID));
- seq_printf(m, "STCNT(%d), ", GETSTCNT());
- seq_puts(m, "SSTAT2( ");
- s = GETPORT(SSTAT2);
- if (s & SOFFSET)
- seq_puts(m, "SOFFSET ");
- if (s & SEMPTY)
- seq_puts(m, "SEMPTY ");
- if (s & SFULL)
- seq_puts(m, "SFULL ");
- seq_printf(m, "); SFCNT (%d); ", s & (SFULL | SFCNT));
- s = GETPORT(SSTAT3);
- seq_printf(m, "SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f);
- seq_puts(m, "SSTAT4( ");
- s = GETPORT(SSTAT4);
- if (s & SYNCERR)
- seq_puts(m, "SYNCERR ");
- if (s & FWERR)
- seq_puts(m, "FWERR ");
- if (s & FRERR)
- seq_puts(m, "FRERR ");
- seq_puts(m, "); ");
- seq_puts(m, "DMACNTRL0( ");
- s = GETPORT(DMACNTRL0);
- seq_printf(m, "%s ", s & _8BIT ? "8BIT" : "16BIT");
- seq_printf(m, "%s ", s & DMA ? "DMA" : "PIO");
- seq_printf(m, "%s ", s & WRITE_READ ? "WRITE" : "READ");
- if (s & ENDMA)
- seq_puts(m, "ENDMA ");
- if (s & INTEN)
- seq_puts(m, "INTEN ");
- if (s & RSTFIFO)
- seq_puts(m, "RSTFIFO ");
- if (s & SWINT)
- seq_puts(m, "SWINT ");
- seq_puts(m, "); ");
- seq_puts(m, "DMASTAT( ");
- s = GETPORT(DMASTAT);
- if (s & ATDONE)
- seq_puts(m, "ATDONE ");
- if (s & WORDRDY)
- seq_puts(m, "WORDRDY ");
- if (s & DFIFOFULL)
- seq_puts(m, "DFIFOFULL ");
- if (s & DFIFOEMP)
- seq_puts(m, "DFIFOEMP ");
- seq_puts(m, ")\n");
- seq_puts(m, "enabled interrupts( ");
- s = GETPORT(SIMODE0);
- if (s & ENSELDO)
- seq_puts(m, "ENSELDO ");
- if (s & ENSELDI)
- seq_puts(m, "ENSELDI ");
- if (s & ENSELINGO)
- seq_puts(m, "ENSELINGO ");
- if (s & ENSWRAP)
- seq_puts(m, "ENSWRAP ");
- if (s & ENSDONE)
- seq_puts(m, "ENSDONE ");
- if (s & ENSPIORDY)
- seq_puts(m, "ENSPIORDY ");
- if (s & ENDMADONE)
- seq_puts(m, "ENDMADONE ");
- s = GETPORT(SIMODE1);
- if (s & ENSELTIMO)
- seq_puts(m, "ENSELTIMO ");
- if (s & ENATNTARG)
- seq_puts(m, "ENATNTARG ");
- if (s & ENPHASEMIS)
- seq_puts(m, "ENPHASEMIS ");
- if (s & ENBUSFREE)
- seq_puts(m, "ENBUSFREE ");
- if (s & ENSCSIPERR)
- seq_puts(m, "ENSCSIPERR ");
- if (s & ENPHASECHG)
- seq_puts(m, "ENPHASECHG ");
- if (s & ENREQINIT)
- seq_puts(m, "ENREQINIT ");
- seq_puts(m, ")\n");
- }
- static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
- {
- if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
- return -EINVAL;
- #if defined(AHA152X_STAT)
- if(length>13 && strncmp("reset", buffer+8, 5)==0) {
- int i;
- HOSTDATA(shpnt)->total_commands=0;
- HOSTDATA(shpnt)->disconnections=0;
- HOSTDATA(shpnt)->busfree_without_any_action=0;
- HOSTDATA(shpnt)->busfree_without_old_command=0;
- HOSTDATA(shpnt)->busfree_without_new_command=0;
- HOSTDATA(shpnt)->busfree_without_done_command=0;
- HOSTDATA(shpnt)->busfree_with_check_condition=0;
- for (i = idle; i<maxstate; i++) {
- HOSTDATA(shpnt)->count[i]=0;
- HOSTDATA(shpnt)->count_trans[i]=0;
- HOSTDATA(shpnt)->time[i]=0;
- }
- shost_printk(KERN_INFO, shpnt, "aha152x: stats reset.\n");
- } else
- #endif
- {
- return -EINVAL;
- }
- return length;
- }
- static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
- {
- int i;
- struct scsi_cmnd *ptr;
- unsigned long flags;
- seq_puts(m, AHA152X_REVID "\n");
- seq_printf(m, "ioports 0x%04lx to 0x%04lx\n",
- shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1);
- seq_printf(m, "interrupt 0x%02x\n", shpnt->irq);
- seq_printf(m, "disconnection/reconnection %s\n",
- RECONNECT ? "enabled" : "disabled");
- seq_printf(m, "parity checking %s\n",
- PARITY ? "enabled" : "disabled");
- seq_printf(m, "synchronous transfers %s\n",
- SYNCHRONOUS ? "enabled" : "disabled");
- seq_printf(m, "%d commands currently queued\n", HOSTDATA(shpnt)->commands);
- if(SYNCHRONOUS) {
- seq_puts(m, "synchronously operating targets (tick=50 ns):\n");
- for (i = 0; i < 8; i++)
- if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
- seq_printf(m, "target %d: period %dT/%dns; req/ack offset %d\n",
- i,
- (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
- (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
- HOSTDATA(shpnt)->syncrate[i] & 0x0f);
- }
- seq_puts(m, "\nqueue status:\n");
- DO_LOCK(flags);
- if (ISSUE_SC) {
- seq_puts(m, "not yet issued commands:\n");
- for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
- get_command(m, ptr);
- } else
- seq_puts(m, "no not yet issued commands\n");
- DO_UNLOCK(flags);
- if (CURRENT_SC) {
- seq_puts(m, "current command:\n");
- get_command(m, CURRENT_SC);
- } else
- seq_puts(m, "no current command\n");
- if (DISCONNECTED_SC) {
- seq_puts(m, "disconnected commands:\n");
- for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
- get_command(m, ptr);
- } else
- seq_puts(m, "no disconnected commands\n");
- get_ports(m, shpnt);
- #if defined(AHA152X_STAT)
- seq_printf(m, "statistics:\n"
- "total commands: %d\n"
- "disconnections: %d\n"
- "busfree with check condition: %d\n"
- "busfree without old command: %d\n"
- "busfree without new command: %d\n"
- "busfree without done command: %d\n"
- "busfree without any action: %d\n"
- "state "
- "transitions "
- "count "
- "time\n",
- HOSTDATA(shpnt)->total_commands,
- HOSTDATA(shpnt)->disconnections,
- HOSTDATA(shpnt)->busfree_with_check_condition,
- HOSTDATA(shpnt)->busfree_without_old_command,
- HOSTDATA(shpnt)->busfree_without_new_command,
- HOSTDATA(shpnt)->busfree_without_done_command,
- HOSTDATA(shpnt)->busfree_without_any_action);
- for(i=0; i<maxstate; i++) {
- seq_printf(m, "%-10s %-12d %-12d %-12ld\n",
- states[i].name,
- HOSTDATA(shpnt)->count_trans[i],
- HOSTDATA(shpnt)->count[i],
- HOSTDATA(shpnt)->time[i]);
- }
- #endif
- return 0;
- }
- static int aha152x_adjust_queue(struct scsi_device *device)
- {
- blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
- return 0;
- }
- static struct scsi_host_template aha152x_driver_template = {
- .module = THIS_MODULE,
- .name = AHA152X_REVID,
- .proc_name = "aha152x",
- .show_info = aha152x_show_info,
- .write_info = aha152x_set_info,
- .queuecommand = aha152x_queue,
- .eh_abort_handler = aha152x_abort,
- .eh_device_reset_handler = aha152x_device_reset,
- .eh_bus_reset_handler = aha152x_bus_reset,
- .bios_param = aha152x_biosparam,
- .can_queue = 1,
- .this_id = 7,
- .sg_tablesize = SG_ALL,
- .use_clustering = DISABLE_CLUSTERING,
- .slave_alloc = aha152x_adjust_queue,
- };
- #if !defined(PCMCIA)
- static int setup_count;
- static struct aha152x_setup setup[2];
- /* possible i/o addresses for the AIC-6260; default first */
- static unsigned short ports[] = { 0x340, 0x140 };
- #if !defined(SKIP_BIOSTEST)
- /* possible locations for the Adaptec BIOS; defaults first */
- static unsigned int addresses[] =
- {
- 0xdc000, /* default first */
- 0xc8000,
- 0xcc000,
- 0xd0000,
- 0xd4000,
- 0xd8000,
- 0xe0000,
- 0xeb800, /* VTech Platinum SMP */
- 0xf0000,
- };
- /* signatures for various AIC-6[23]60 based controllers.
- The point in detecting signatures is to avoid useless and maybe
- harmful probes on ports. I'm not sure that all listed boards pass
- auto-configuration. For those which fail the BIOS signature is
- obsolete, because user intervention to supply the configuration is
- needed anyway. May be an information whether or not the BIOS supports
- extended translation could be also useful here. */
- static struct signature {
- unsigned char *signature;
- int sig_offset;
- int sig_length;
- } signatures[] =
- {
- { "Adaptec AHA-1520 BIOS", 0x102e, 21 },
- /* Adaptec 152x */
- { "Adaptec AHA-1520B", 0x000b, 17 },
- /* Adaptec 152x rev B */
- { "Adaptec AHA-1520B", 0x0026, 17 },
- /* Iomega Jaz Jet ISA (AIC6370Q) */
- { "Adaptec ASW-B626 BIOS", 0x1029, 21 },
- /* on-board controller */
- { "Adaptec BIOS: ASW-B626", 0x000f, 22 },
- /* on-board controller */
- { "Adaptec ASW-B626 S2", 0x2e6c, 19 },
- /* on-board controller */
- { "Adaptec BIOS:AIC-6360", 0x000c, 21 },
- /* on-board controller */
- { "ScsiPro SP-360 BIOS", 0x2873, 19 },
- /* ScsiPro-Controller */
- { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },
- /* Gigabyte Local-Bus-SCSI */
- { "Adaptec BIOS:AVA-282X", 0x000c, 21 },
- /* Adaptec 282x */
- { "Adaptec IBM Dock II SCSI", 0x2edd, 24 },
- /* IBM Thinkpad Dock II */
- { "Adaptec BIOS:AHA-1532P", 0x001c, 22 },
- /* IBM Thinkpad Dock II SCSI */
- { "DTC3520A Host Adapter BIOS", 0x318a, 26 },
- /* DTC 3520A ISA SCSI */
- };
- #endif /* !SKIP_BIOSTEST */
- /*
- * Test, if port_base is valid.
- *
- */
- static int aha152x_porttest(int io_port)
- {
- int i;
- SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
- for (i = 0; i < 16; i++)
- SETPORT(io_port + O_STACK, i);
- SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
- for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++)
- ;
- return (i == 16);
- }
- static int tc1550_porttest(int io_port)
- {
- int i;
- SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
- for (i = 0; i < 16; i++)
- SETPORT(io_port + O_STACK, i);
- SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
- for (i = 0; i < 16 && GETPORT(io_port + O_TC_STACK) == i; i++)
- ;
- return (i == 16);
- }
- static int checksetup(struct aha152x_setup *setup)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(ports) && (setup->io_port != ports[i]); i++)
- ;
- if (i == ARRAY_SIZE(ports))
- return 0;
- if (!request_region(setup->io_port, IO_RANGE, "aha152x")) {
- printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup->io_port);
- return 0;
- }
- if( aha152x_porttest(setup->io_port) ) {
- setup->tc1550=0;
- } else if( tc1550_porttest(setup->io_port) ) {
- setup->tc1550=1;
- } else {
- release_region(setup->io_port, IO_RANGE);
- return 0;
- }
- release_region(setup->io_port, IO_RANGE);
- if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX))
- return 0;
- if ((setup->scsiid < 0) || (setup->scsiid > 7))
- return 0;
- if ((setup->reconnect < 0) || (setup->reconnect > 1))
- return 0;
- if ((setup->parity < 0) || (setup->parity > 1))
- return 0;
- if ((setup->synchronous < 0) || (setup->synchronous > 1))
- return 0;
- if ((setup->ext_trans < 0) || (setup->ext_trans > 1))
- return 0;
- return 1;
- }
- static int __init aha152x_init(void)
- {
- int i, j, ok;
- #if defined(AUTOCONF)
- aha152x_config conf;
- #endif
- #ifdef __ISAPNP__
- struct pnp_dev *dev=NULL, *pnpdev[2] = {NULL, NULL};
- #endif
- if ( setup_count ) {
- printk(KERN_INFO "aha152x: processing commandline: ");
- for (i = 0; i<setup_count; i++) {
- if (!checksetup(&setup[i])) {
- printk(KERN_ERR "\naha152x: %s\n", setup[i].conf);
- printk(KERN_ERR "aha152x: invalid line\n");
- }
- }
- printk("ok\n");
- }
- #if defined(SETUP0)
- if (setup_count < ARRAY_SIZE(setup)) {
- struct aha152x_setup override = SETUP0;
- if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
- if (!checksetup(&override)) {
- printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
- override.io_port,
- override.irq,
- override.scsiid,
- override.reconnect,
- override.parity,
- override.synchronous,
- override.delay,
- override.ext_trans);
- } else
- setup[setup_count++] = override;
- }
- }
- #endif
- #if defined(SETUP1)
- if (setup_count < ARRAY_SIZE(setup)) {
- struct aha152x_setup override = SETUP1;
- if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
- if (!checksetup(&override)) {
- printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
- override.io_port,
- override.irq,
- override.scsiid,
- override.reconnect,
- override.parity,
- override.synchronous,
- override.delay,
- override.ext_trans);
- } else
- setup[setup_count++] = override;
- }
- }
- #endif
- #if defined(MODULE)
- if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) {
- if(aha152x[0]!=0) {
- setup[setup_count].conf = "";
- setup[setup_count].io_port = aha152x[0];
- setup[setup_count].irq = aha152x[1];
- setup[setup_count].scsiid = aha152x[2];
- setup[setup_count].reconnect = aha152x[3];
- setup[setup_count].parity = aha152x[4];
- setup[setup_count].synchronous = aha152x[5];
- setup[setup_count].delay = aha152x[6];
- setup[setup_count].ext_trans = aha152x[7];
- } else if (io[0] != 0 || irq[0] != 0) {
- if(io[0]!=0) setup[setup_count].io_port = io[0];
- if(irq[0]!=0) setup[setup_count].irq = irq[0];
- setup[setup_count].scsiid = scsiid[0];
- setup[setup_count].reconnect = reconnect[0];
- setup[setup_count].parity = parity[0];
- setup[setup_count].synchronous = sync[0];
- setup[setup_count].delay = delay[0];
- setup[setup_count].ext_trans = exttrans[0];
- }
- if (checksetup(&setup[setup_count]))
- setup_count++;
- else
- printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
- setup[setup_count].io_port,
- setup[setup_count].irq,
- setup[setup_count].scsiid,
- setup[setup_count].reconnect,
- setup[setup_count].parity,
- setup[setup_count].synchronous,
- setup[setup_count].delay,
- setup[setup_count].ext_trans);
- }
- if (setup_count<ARRAY_SIZE(setup) && (aha152x1[0]!=0 || io[1]!=0 || irq[1]!=0)) {
- if(aha152x1[0]!=0) {
- setup[setup_count].conf = "";
- setup[setup_count].io_port = aha152x1[0];
- setup[setup_count].irq = aha152x1[1];
- setup[setup_count].scsiid = aha152x1[2];
- setup[setup_count].reconnect = aha152x1[3];
- setup[setup_count].parity = aha152x1[4];
- setup[setup_count].synchronous = aha152x1[5];
- setup[setup_count].delay = aha152x1[6];
- setup[setup_count].ext_trans = aha152x1[7];
- } else if (io[1] != 0 || irq[1] != 0) {
- if(io[1]!=0) setup[setup_count].io_port = io[1];
- if(irq[1]!=0) setup[setup_count].irq = irq[1];
- setup[setup_count].scsiid = scsiid[1];
- setup[setup_count].reconnect = reconnect[1];
- setup[setup_count].parity = parity[1];
- setup[setup_count].synchronous = sync[1];
- setup[setup_count].delay = delay[1];
- setup[setup_count].ext_trans = exttrans[1];
- }
- if (checksetup(&setup[setup_count]))
- setup_count++;
- else
- printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
- setup[setup_count].io_port,
- setup[setup_count].irq,
- setup[setup_count].scsiid,
- setup[setup_count].reconnect,
- setup[setup_count].parity,
- setup[setup_count].synchronous,
- setup[setup_count].delay,
- setup[setup_count].ext_trans);
- }
- #endif
- #ifdef __ISAPNP__
- for(i=0; setup_count<ARRAY_SIZE(setup) && id_table[i].vendor; i++) {
- while ( setup_count<ARRAY_SIZE(setup) &&
- (dev=pnp_find_dev(NULL, id_table[i].vendor, id_table[i].function, dev)) ) {
- if (pnp_device_attach(dev) < 0)
- continue;
- if (pnp_activate_dev(dev) < 0) {
- pnp_device_detach(dev);
- continue;
- }
- if (!pnp_port_valid(dev, 0)) {
- pnp_device_detach(dev);
- continue;
- }
- if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) {
- pnp_device_detach(dev);
- continue;
- }
- setup[setup_count].io_port = pnp_port_start(dev, 0);
- setup[setup_count].irq = pnp_irq(dev, 0);
- setup[setup_count].scsiid = 7;
- setup[setup_count].reconnect = 1;
- setup[setup_count].parity = 1;
- setup[setup_count].synchronous = 1;
- setup[setup_count].delay = DELAY_DEFAULT;
- setup[setup_count].ext_trans = 0;
- #if defined(__ISAPNP__)
- pnpdev[setup_count] = dev;
- #endif
- printk (KERN_INFO
- "aha152x: found ISAPnP adapter at io=0x%03x, irq=%d\n",
- setup[setup_count].io_port, setup[setup_count].irq);
- setup_count++;
- }
- }
- #endif
- #if defined(AUTOCONF)
- if (setup_count<ARRAY_SIZE(setup)) {
- #if !defined(SKIP_BIOSTEST)
- ok = 0;
- for (i = 0; i < ARRAY_SIZE(addresses) && !ok; i++) {
- void __iomem *p = ioremap(addresses[i], 0x4000);
- if (!p)
- continue;
- for (j = 0; j<ARRAY_SIZE(signatures) && !ok; j++)
- ok = check_signature(p + signatures[j].sig_offset,
- signatures[j].signature, signatures[j].sig_length);
- iounmap(p);
- }
- if (!ok && setup_count == 0)
- return -ENODEV;
- printk(KERN_INFO "aha152x: BIOS test: passed, ");
- #else
- printk(KERN_INFO "aha152x: ");
- #endif /* !SKIP_BIOSTEST */
- ok = 0;
- for (i = 0; i < ARRAY_SIZE(ports) && setup_count < 2; i++) {
- if ((setup_count == 1) && (setup[0].io_port == ports[i]))
- continue;
- if (!request_region(ports[i], IO_RANGE, "aha152x")) {
- printk(KERN_ERR "aha152x: io port 0x%x busy.\n", ports[i]);
- continue;
- }
- if (aha152x_porttest(ports[i])) {
- setup[setup_count].tc1550 = 0;
- conf.cf_port =
- (GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
- } else if (tc1550_porttest(ports[i])) {
- setup[setup_count].tc1550 = 1;
- conf.cf_port =
- (GETPORT(ports[i] + O_TC_PORTA) << 8) + GETPORT(ports[i] + O_TC_PORTB);
- } else {
- release_region(ports[i], IO_RANGE);
- continue;
- }
- release_region(ports[i], IO_RANGE);
- ok++;
- setup[setup_count].io_port = ports[i];
- setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
- setup[setup_count].scsiid = conf.cf_id;
- setup[setup_count].reconnect = conf.cf_tardisc;
- setup[setup_count].parity = !conf.cf_parity;
- setup[setup_count].synchronous = conf.cf_syncneg;
- setup[setup_count].delay = DELAY_DEFAULT;
- setup[setup_count].ext_trans = 0;
- setup_count++;
- }
- if (ok)
- printk("auto configuration: ok, ");
- }
- #endif
- printk("%d controller(s) configured\n", setup_count);
- for (i=0; i<setup_count; i++) {
- if ( request_region(setup[i].io_port, IO_RANGE, "aha152x") ) {
- struct Scsi_Host *shpnt = aha152x_probe_one(&setup[i]);
- if( !shpnt ) {
- release_region(setup[i].io_port, IO_RANGE);
- #if defined(__ISAPNP__)
- } else if( pnpdev[i] ) {
- HOSTDATA(shpnt)->pnpdev=pnpdev[i];
- pnpdev[i]=NULL;
- #endif
- }
- } else {
- printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup[i].io_port);
- }
- #if defined(__ISAPNP__)
- if( pnpdev[i] )
- pnp_device_detach(pnpdev[i]);
- #endif
- }
- return 0;
- }
- static void __exit aha152x_exit(void)
- {
- struct aha152x_hostdata *hd, *tmp;
- list_for_each_entry_safe(hd, tmp, &aha152x_host_list, host_list) {
- struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
- aha152x_release(shost);
- }
- }
- module_init(aha152x_init);
- module_exit(aha152x_exit);
- #if !defined(MODULE)
- static int __init aha152x_setup(char *str)
- {
- int ints[10];
- get_options(str, ARRAY_SIZE(ints), ints);
- if(setup_count>=ARRAY_SIZE(setup)) {
- printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
- return 1;
- }
- setup[setup_count].conf = str;
- setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340;
- setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11;
- setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7;
- setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
- setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
- setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
- setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
- setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
- if (ints[0] > 8) { /*}*/
- printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
- "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
- } else {
- setup_count++;
- return 0;
- }
- return 1;
- }
- __setup("aha152x=", aha152x_setup);
- #endif
- #endif /* !PCMCIA */
|