12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014 |
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/delay.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/spinlock.h>
- #include <linux/stat.h>
- #include <linux/kernel.h>
- #include <linux/proc_fs.h>
- #include <linux/string.h>
- #include <linux/interrupt.h>
- #include <linux/ioport.h>
- #include <linux/slab.h>
- #include <linux/jiffies.h>
- #include <linux/dma-mapping.h>
- #include <asm/io.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
- #include <scsi/scsi_device.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_tcq.h>
- #include "initio.h"
- #define SENSE_SIZE 14
- #define i91u_MAXQUEUE 2
- #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"
- #define I950_DEVICE_ID 0x9500
- #define I940_DEVICE_ID 0x9400
- #define I935_DEVICE_ID 0x9401
- #define I920_DEVICE_ID 0x0002
- #ifdef DEBUG_i91u
- static unsigned int i91u_debug = DEBUG_DEFAULT;
- #endif
- static int initio_tag_enable = 1;
- #ifdef DEBUG_i91u
- static int setup_debug = 0;
- #endif
- static void i91uSCBPost(u8 * pHcb, u8 * pScb);
- static struct pci_device_id i91u_pci_devices[] = {
- { PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_INIT, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_DOMEX, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { }
- };
- MODULE_DEVICE_TABLE(pci, i91u_pci_devices);
- #define DEBUG_INTERRUPT 0
- #define DEBUG_QUEUE 0
- #define DEBUG_STATE 0
- #define INT_DISC 0
- static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);
- static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);
- static int tulip_main(struct initio_host * host);
- static int initio_next_state(struct initio_host * host);
- static int initio_state_1(struct initio_host * host);
- static int initio_state_2(struct initio_host * host);
- static int initio_state_3(struct initio_host * host);
- static int initio_state_4(struct initio_host * host);
- static int initio_state_5(struct initio_host * host);
- static int initio_state_6(struct initio_host * host);
- static int initio_state_7(struct initio_host * host);
- static int initio_xfer_data_in(struct initio_host * host);
- static int initio_xfer_data_out(struct initio_host * host);
- static int initio_xpad_in(struct initio_host * host);
- static int initio_xpad_out(struct initio_host * host);
- static int initio_status_msg(struct initio_host * host);
- static int initio_msgin(struct initio_host * host);
- static int initio_msgin_sync(struct initio_host * host);
- static int initio_msgin_accept(struct initio_host * host);
- static int initio_msgout_reject(struct initio_host * host);
- static int initio_msgin_extend(struct initio_host * host);
- static int initio_msgout_ide(struct initio_host * host);
- static int initio_msgout_abort_targ(struct initio_host * host);
- static int initio_msgout_abort_tag(struct initio_host * host);
- static int initio_bus_device_reset(struct initio_host * host);
- static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);
- static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);
- static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);
- static int int_initio_busfree(struct initio_host * host);
- static int int_initio_scsi_rst(struct initio_host * host);
- static int int_initio_bad_seq(struct initio_host * host);
- static int int_initio_resel(struct initio_host * host);
- static int initio_sync_done(struct initio_host * host);
- static int wdtr_done(struct initio_host * host);
- static int wait_tulip(struct initio_host * host);
- static int initio_wait_done_disc(struct initio_host * host);
- static int initio_wait_disc(struct initio_host * host);
- static void tulip_scsi(struct initio_host * host);
- static int initio_post_scsi_rst(struct initio_host * host);
- static void initio_se2_ew_en(unsigned long base);
- static void initio_se2_ew_ds(unsigned long base);
- static int initio_se2_rd_all(unsigned long base);
- static void initio_se2_update_all(unsigned long base);
- static void initio_read_eeprom(unsigned long base);
- static NVRAM i91unvram;
- static NVRAM *i91unvramp;
- static u8 i91udftNvRam[64] =
- {
-
- 0x25, 0xc9,
- 0x40,
- 0x01,
-
- 0x95,
- 0x00,
- 0x00,
- 0x01,
- NBC1_DEFAULT,
- 0,
- 0,
- 0,
-
- 7,
- NCC1_DEFAULT,
- 0,
- 0x10,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
-
- 7,
- NCC1_DEFAULT,
- 0,
- 0x10,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0};
- static u8 initio_rate_tbl[8] =
- {
-
- 12,
- 18,
- 25,
- 31,
- 37,
- 43,
- 50,
- 62
- };
- static void initio_do_pause(unsigned amount)
- {
-
- unsigned long the_time = jiffies + amount;
- while (time_before_eq(jiffies, the_time))
- cpu_relax();
- }
- static void initio_se2_instr(unsigned long base, u8 instr)
- {
- int i;
- u8 b;
- outb(SE2CS | SE2DO, base + TUL_NVRAM);
- udelay(30);
- outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM);
- udelay(30);
- for (i = 0; i < 8; i++) {
- if (instr & 0x80)
- b = SE2CS | SE2DO;
- else
- b = SE2CS;
- outb(b, base + TUL_NVRAM);
- udelay(30);
- outb(b | SE2CLK, base + TUL_NVRAM);
- udelay(30);
- instr <<= 1;
- }
- outb(SE2CS, base + TUL_NVRAM);
- udelay(30);
- }
- void initio_se2_ew_en(unsigned long base)
- {
- initio_se2_instr(base, 0x30);
- outb(0, base + TUL_NVRAM);
- udelay(30);
- }
- void initio_se2_ew_ds(unsigned long base)
- {
- initio_se2_instr(base, 0);
- outb(0, base + TUL_NVRAM);
- udelay(30);
- }
- static u16 initio_se2_rd(unsigned long base, u8 addr)
- {
- u8 instr, rb;
- u16 val = 0;
- int i;
- instr = (u8) (addr | 0x80);
- initio_se2_instr(base, instr);
- for (i = 15; i >= 0; i--) {
- outb(SE2CS | SE2CLK, base + TUL_NVRAM);
- udelay(30);
- outb(SE2CS, base + TUL_NVRAM);
-
- rb = inb(base + TUL_NVRAM);
- rb &= SE2DI;
- val += (rb << i);
- udelay(30);
- }
- outb(0, base + TUL_NVRAM);
- udelay(30);
- return val;
- }
- static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
- {
- u8 rb;
- u8 instr;
- int i;
- instr = (u8) (addr | 0x40);
- initio_se2_instr(base, instr);
- for (i = 15; i >= 0; i--) {
- if (val & 0x8000)
- outb(SE2CS | SE2DO, base + TUL_NVRAM);
- else
- outb(SE2CS, base + TUL_NVRAM);
- udelay(30);
- outb(SE2CS | SE2CLK, base + TUL_NVRAM);
- udelay(30);
- val <<= 1;
- }
- outb(SE2CS, base + TUL_NVRAM);
- udelay(30);
- outb(0, base + TUL_NVRAM);
- udelay(30);
- outb(SE2CS, base + TUL_NVRAM);
- udelay(30);
- for (;;) {
- outb(SE2CS | SE2CLK, base + TUL_NVRAM);
- udelay(30);
- outb(SE2CS, base + TUL_NVRAM);
- udelay(30);
- if ((rb = inb(base + TUL_NVRAM)) & SE2DI)
- break;
- }
- outb(0, base + TUL_NVRAM);
- }
- static int initio_se2_rd_all(unsigned long base)
- {
- int i;
- u16 chksum = 0;
- u16 *np;
- i91unvramp = &i91unvram;
- np = (u16 *) i91unvramp;
- for (i = 0; i < 32; i++)
- *np++ = initio_se2_rd(base, i);
-
- if (i91unvramp->NVM_Signature != INI_SIGNATURE)
- return -1;
-
- np = (u16 *) i91unvramp;
- for (i = 0; i < 31; i++)
- chksum += *np++;
- if (i91unvramp->NVM_CheckSum != chksum)
- return -1;
- return 1;
- }
- static void initio_se2_update_all(unsigned long base)
- {
- int i;
- u16 chksum = 0;
- u16 *np, *np1;
- i91unvramp = &i91unvram;
-
- np = (u16 *) i91udftNvRam;
- for (i = 0; i < 31; i++)
- chksum += *np++;
- *np = chksum;
- initio_se2_ew_en(base);
- np = (u16 *) i91udftNvRam;
- np1 = (u16 *) i91unvramp;
- for (i = 0; i < 32; i++, np++, np1++) {
- if (*np != *np1)
- initio_se2_wr(base, i, *np);
- }
- initio_se2_ew_ds(base);
- }
- static void initio_read_eeprom(unsigned long base)
- {
- u8 gctrl;
- i91unvramp = &i91unvram;
-
- gctrl = inb(base + TUL_GCTRL);
- outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
- if (initio_se2_rd_all(base) != 1) {
- initio_se2_update_all(base);
- initio_se2_rd_all(base);
- }
-
- gctrl = inb(base + TUL_GCTRL);
- outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
- }
- static void initio_stop_bm(struct initio_host * host)
- {
- if (inb(host->addr + TUL_XStatus) & XPEND) {
- outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
-
- while ((inb(host->addr + TUL_Int) & XABT) == 0)
- cpu_relax();
- }
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- }
- static int initio_reset_scsi(struct initio_host * host, int seconds)
- {
- outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);
- while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))
- cpu_relax();
-
- outb(0, host->addr + TUL_SSignal);
-
-
-
- initio_do_pause(seconds * HZ);
- inb(host->addr + TUL_SInt);
- return SCSI_RESET_SUCCESS;
- }
- static void initio_init(struct initio_host * host, u8 *bios_addr)
- {
- int i;
- u8 *flags;
- u8 *heads;
-
- initio_read_eeprom(host->addr);
- if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
- host->max_tar = 8;
- else
- host->max_tar = 16;
- host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
- host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
- host->idmask = ~(1 << host->scsi_id);
- #ifdef CHK_PARITY
-
- outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);
- #endif
-
- outb(0x1F, host->addr + TUL_Mask);
- initio_stop_bm(host);
-
- outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);
-
- outb(host->scsi_id << 4, host->addr + TUL_SScsiId);
-
- if (host->config & HCC_EN_PAR)
- host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
- else
- host->sconf1 = (TSC_INITDEFAULT);
- outb(host->sconf1, host->addr + TUL_SConfig);
-
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- outb(0, host->addr + TUL_SPeriod);
-
- outb(153, host->addr + TUL_STimeOut);
-
- outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),
- host->addr + TUL_XCtrl);
- outb(((host->config & HCC_AUTO_TERM) >> 4) |
- (inb(host->addr + TUL_GCTRL1) & 0xFE),
- host->addr + TUL_GCTRL1);
- for (i = 0,
- flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
- heads = bios_addr + 0x180;
- i < host->max_tar;
- i++, flags++) {
- host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
- if (host->targets[i].flags & TCF_EN_255)
- host->targets[i].drv_flags = TCF_DRV_255_63;
- else
- host->targets[i].drv_flags = 0;
- host->targets[i].js_period = 0;
- host->targets[i].sconfig0 = host->sconf1;
- host->targets[i].heads = *heads++;
- if (host->targets[i].heads == 255)
- host->targets[i].drv_flags = TCF_DRV_255_63;
- else
- host->targets[i].drv_flags = 0;
- host->targets[i].sectors = *heads++;
- host->targets[i].flags &= ~TCF_BUSY;
- host->act_tags[i] = 0;
- host->max_tags[i] = 0xFF;
- }
- printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
- host->addr, host->pci_dev->irq,
- host->bios_addr, host->scsi_id);
-
- if (host->config & HCC_SCSI_RESET) {
- printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");
- initio_reset_scsi(host, 10);
- }
- outb(0x17, host->addr + TUL_SCFG1);
- outb(0xE9, host->addr + TUL_SIntEnable);
- }
- static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)
- {
- struct scsi_ctrl_blk *scb;
- unsigned long flags;
- spin_lock_irqsave(&host->avail_lock, flags);
- if ((scb = host->first_avail) != NULL) {
- #if DEBUG_QUEUE
- printk("find scb at %p\n", scb);
- #endif
- if ((host->first_avail = scb->next) == NULL)
- host->last_avail = NULL;
- scb->next = NULL;
- scb->status = SCB_RENT;
- }
- spin_unlock_irqrestore(&host->avail_lock, flags);
- return scb;
- }
- static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)
- {
- unsigned long flags;
- #if DEBUG_QUEUE
- printk("Release SCB %p; ", cmnd);
- #endif
- spin_lock_irqsave(&(host->avail_lock), flags);
- cmnd->srb = NULL;
- cmnd->status = 0;
- cmnd->next = NULL;
- if (host->last_avail != NULL) {
- host->last_avail->next = cmnd;
- host->last_avail = cmnd;
- } else {
- host->first_avail = cmnd;
- host->last_avail = cmnd;
- }
- spin_unlock_irqrestore(&(host->avail_lock), flags);
- }
- static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
- printk("Append pend SCB %p; ", scbp);
- #endif
- scbp->status = SCB_PEND;
- scbp->next = NULL;
- if (host->last_pending != NULL) {
- host->last_pending->next = scbp;
- host->last_pending = scbp;
- } else {
- host->first_pending = scbp;
- host->last_pending = scbp;
- }
- }
- static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
- printk("Push pend SCB %p; ", scbp);
- #endif
- scbp->status = SCB_PEND;
- if ((scbp->next = host->first_pending) != NULL) {
- host->first_pending = scbp;
- } else {
- host->first_pending = scbp;
- host->last_pending = scbp;
- }
- }
- static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)
- {
- struct scsi_ctrl_blk *first;
- first = host->first_pending;
- while (first != NULL) {
- if (first->opcode != ExecSCSI)
- return first;
- if (first->tagmsg == 0) {
- if ((host->act_tags[first->target] == 0) &&
- !(host->targets[first->target].flags & TCF_BUSY))
- return first;
- } else {
- if ((host->act_tags[first->target] >=
- host->max_tags[first->target]) |
- (host->targets[first->target].flags & TCF_BUSY)) {
- first = first->next;
- continue;
- }
- return first;
- }
- first = first->next;
- }
- return first;
- }
- static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
- struct scsi_ctrl_blk *tmp, *prev;
- #if DEBUG_QUEUE
- printk("unlink pend SCB %p; ", scb);
- #endif
- prev = tmp = host->first_pending;
- while (tmp != NULL) {
- if (scb == tmp) {
- if (tmp == host->first_pending) {
- if ((host->first_pending = tmp->next) == NULL)
- host->last_pending = NULL;
- } else {
- prev->next = tmp->next;
- if (tmp == host->last_pending)
- host->last_pending = prev;
- }
- tmp->next = NULL;
- break;
- }
- prev = tmp;
- tmp = tmp->next;
- }
- }
- static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
- printk("append busy SCB %p; ", scbp);
- #endif
- if (scbp->tagmsg)
- host->act_tags[scbp->target]++;
- else
- host->targets[scbp->target].flags |= TCF_BUSY;
- scbp->status = SCB_BUSY;
- scbp->next = NULL;
- if (host->last_busy != NULL) {
- host->last_busy->next = scbp;
- host->last_busy = scbp;
- } else {
- host->first_busy = scbp;
- host->last_busy = scbp;
- }
- }
- static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)
- {
- struct scsi_ctrl_blk *tmp;
- if ((tmp = host->first_busy) != NULL) {
- if ((host->first_busy = tmp->next) == NULL)
- host->last_busy = NULL;
- tmp->next = NULL;
- if (tmp->tagmsg)
- host->act_tags[tmp->target]--;
- else
- host->targets[tmp->target].flags &= ~TCF_BUSY;
- }
- #if DEBUG_QUEUE
- printk("Pop busy SCB %p; ", tmp);
- #endif
- return tmp;
- }
- static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
- struct scsi_ctrl_blk *tmp, *prev;
- #if DEBUG_QUEUE
- printk("unlink busy SCB %p; ", scb);
- #endif
- prev = tmp = host->first_busy;
- while (tmp != NULL) {
- if (scb == tmp) {
- if (tmp == host->first_busy) {
- if ((host->first_busy = tmp->next) == NULL)
- host->last_busy = NULL;
- } else {
- prev->next = tmp->next;
- if (tmp == host->last_busy)
- host->last_busy = prev;
- }
- tmp->next = NULL;
- if (tmp->tagmsg)
- host->act_tags[tmp->target]--;
- else
- host->targets[tmp->target].flags &= ~TCF_BUSY;
- break;
- }
- prev = tmp;
- tmp = tmp->next;
- }
- return;
- }
- struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)
- {
- struct scsi_ctrl_blk *tmp, *prev;
- u16 scbp_tarlun;
- prev = tmp = host->first_busy;
- while (tmp != NULL) {
- scbp_tarlun = (tmp->lun << 8) | (tmp->target);
- if (scbp_tarlun == tarlun) {
- break;
- }
- prev = tmp;
- tmp = tmp->next;
- }
- #if DEBUG_QUEUE
- printk("find busy SCB %p; ", tmp);
- #endif
- return tmp;
- }
- static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
- printk("append done SCB %p; ", scbp);
- #endif
- scbp->status = SCB_DONE;
- scbp->next = NULL;
- if (host->last_done != NULL) {
- host->last_done->next = scbp;
- host->last_done = scbp;
- } else {
- host->first_done = scbp;
- host->last_done = scbp;
- }
- }
- struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)
- {
- struct scsi_ctrl_blk *tmp;
- if ((tmp = host->first_done) != NULL) {
- if ((host->first_done = tmp->next) == NULL)
- host->last_done = NULL;
- tmp->next = NULL;
- }
- #if DEBUG_QUEUE
- printk("find done SCB %p; ",tmp);
- #endif
- return tmp;
- }
- static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)
- {
- unsigned long flags;
- struct scsi_ctrl_blk *tmp, *prev;
- spin_lock_irqsave(&host->semaph_lock, flags);
- if ((host->semaph == 0) && (host->active == NULL)) {
-
- outb(0x1F, host->addr + TUL_Mask);
- spin_unlock_irqrestore(&host->semaph_lock, flags);
-
- tulip_main(host);
- spin_lock_irqsave(&host->semaph_lock, flags);
- host->semaph = 1;
- outb(0x0F, host->addr + TUL_Mask);
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_SNOOZE;
- }
- prev = tmp = host->first_pending;
- while (tmp != NULL) {
-
- if (tmp->srb == srbp) {
- if (tmp == host->active) {
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_BUSY;
- } else if (tmp == host->first_pending) {
- if ((host->first_pending = tmp->next) == NULL)
- host->last_pending = NULL;
- } else {
- prev->next = tmp->next;
- if (tmp == host->last_pending)
- host->last_pending = prev;
- }
- tmp->hastat = HOST_ABORTED;
- tmp->flags |= SCF_DONE;
- if (tmp->flags & SCF_POST)
- (*tmp->post) ((u8 *) host, (u8 *) tmp);
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_SUCCESS;
- }
- prev = tmp;
- tmp = tmp->next;
- }
- prev = tmp = host->first_busy;
- while (tmp != NULL) {
- if (tmp->srb == srbp) {
- if (tmp == host->active) {
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_BUSY;
- } else if (tmp->tagmsg == 0) {
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_BUSY;
- } else {
- host->act_tags[tmp->target]--;
- if (tmp == host->first_busy) {
- if ((host->first_busy = tmp->next) == NULL)
- host->last_busy = NULL;
- } else {
- prev->next = tmp->next;
- if (tmp == host->last_busy)
- host->last_busy = prev;
- }
- tmp->next = NULL;
- tmp->hastat = HOST_ABORTED;
- tmp->flags |= SCF_DONE;
- if (tmp->flags & SCF_POST)
- (*tmp->post) ((u8 *) host, (u8 *) tmp);
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_SUCCESS;
- }
- }
- prev = tmp;
- tmp = tmp->next;
- }
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return SCSI_ABORT_NOT_RUNNING;
- }
- static int initio_bad_seq(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- printk("initio_bad_seg c=%d\n", host->index);
- if ((scb = host->active) != NULL) {
- initio_unlink_busy_scb(host, scb);
- scb->hastat = HOST_BAD_PHAS;
- scb->tastat = 0;
- initio_append_done_scb(host, scb);
- }
- initio_stop_bm(host);
- initio_reset_scsi(host, 8);
- return initio_post_scsi_rst(host);
- }
- static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
- unsigned long flags;
- scb->mode = 0;
- scb->sgidx = 0;
- scb->sgmax = scb->sglen;
- spin_lock_irqsave(&host->semaph_lock, flags);
- initio_append_pend_scb(host, scb);
- if (host->semaph == 1) {
-
- outb(0x1F, host->addr + TUL_Mask);
- host->semaph = 0;
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- tulip_main(host);
- spin_lock_irqsave(&host->semaph_lock, flags);
- host->semaph = 1;
- outb(0x0F, host->addr + TUL_Mask);
- }
- spin_unlock_irqrestore(&host->semaph_lock, flags);
- return;
- }
- static int initio_isr(struct initio_host * host)
- {
- if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {
- if (host->semaph == 1) {
- outb(0x1F, host->addr + TUL_Mask);
-
- host->semaph = 0;
- tulip_main(host);
- host->semaph = 1;
- outb(0x0F, host->addr + TUL_Mask);
- return 1;
- }
- }
- return 0;
- }
- static int tulip_main(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- for (;;) {
- tulip_scsi(host);
-
- while ((scb = initio_find_done_scb(host)) != NULL) {
- if (scb->tastat == INI_QUEUE_FULL) {
- host->max_tags[scb->target] =
- host->act_tags[scb->target] - 1;
- scb->tastat = 0;
- initio_append_pend_scb(host, scb);
- continue;
- }
- if (!(scb->mode & SCM_RSENS)) {
- if (scb->tastat == 2) {
-
- if (scb->flags & SCF_SENSE) {
- u8 len;
- len = scb->senselen;
- if (len == 0)
- len = 1;
- scb->buflen = scb->senselen;
- scb->bufptr = scb->senseptr;
- scb->flags &= ~(SCF_SG | SCF_DIR);
-
- scb->mode = SCM_RSENS;
- scb->ident &= 0xBF;
- scb->tagmsg = 0;
- scb->tastat = 0;
- scb->cdblen = 6;
- scb->cdb[0] = SCSICMD_RequestSense;
- scb->cdb[1] = 0;
- scb->cdb[2] = 0;
- scb->cdb[3] = 0;
- scb->cdb[4] = len;
- scb->cdb[5] = 0;
- initio_push_pend_scb(host, scb);
- break;
- }
- }
- } else {
- if (scb->tastat == 2) {
- scb->hastat = HOST_BAD_PHAS;
- }
- scb->tastat = 2;
- }
- scb->flags |= SCF_DONE;
- if (scb->flags & SCF_POST) {
-
- (*scb->post) ((u8 *) host, (u8 *) scb);
- }
- }
-
- if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)
- continue;
- if (host->active)
- return 1;
-
- if (initio_find_first_pend_scb(host) == NULL)
- return 1;
- }
-
- }
- static void tulip_scsi(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- struct target_control *active_tc;
-
- if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {
- host->phase = host->jsstatus0 & TSS_PH_MASK;
- host->jsstatus1 = inb(host->addr + TUL_SStatus1);
- host->jsint = inb(host->addr + TUL_SInt);
- if (host->jsint & TSS_SCSIRST_INT) {
- int_initio_scsi_rst(host);
- return;
- }
- if (host->jsint & TSS_RESEL_INT) {
- if (int_initio_resel(host) == 0)
- initio_next_state(host);
- return;
- }
- if (host->jsint & TSS_SEL_TIMEOUT) {
- int_initio_busfree(host);
- return;
- }
- if (host->jsint & TSS_DISC_INT) {
- int_initio_busfree(host);
- return;
- }
- if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
- if ((scb = host->active) != NULL)
- initio_next_state(host);
- return;
- }
- }
- if (host->active != NULL)
- return;
- if ((scb = initio_find_first_pend_scb(host)) == NULL)
- return;
-
- outb((host->scsi_id << 4) | (scb->target & 0x0F),
- host->addr + TUL_SScsiId);
- if (scb->opcode == ExecSCSI) {
- active_tc = &host->targets[scb->target];
- if (scb->tagmsg)
- active_tc->drv_flags |= TCF_DRV_EN_TAG;
- else
- active_tc->drv_flags &= ~TCF_DRV_EN_TAG;
- outb(active_tc->js_period, host->addr + TUL_SPeriod);
- if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
- initio_select_atn_stop(host, scb);
- } else {
- if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
- initio_select_atn_stop(host, scb);
- } else {
- if (scb->tagmsg)
- initio_select_atn3(host, scb);
- else
- initio_select_atn(host, scb);
- }
- }
- if (scb->flags & SCF_POLL) {
- while (wait_tulip(host) != -1) {
- if (initio_next_state(host) == -1)
- break;
- }
- }
- } else if (scb->opcode == BusDevRst) {
- initio_select_atn_stop(host, scb);
- scb->next_state = 8;
- if (scb->flags & SCF_POLL) {
- while (wait_tulip(host) != -1) {
- if (initio_next_state(host) == -1)
- break;
- }
- }
- } else if (scb->opcode == AbortCmd) {
- if (initio_abort_srb(host, scb->srb) != 0) {
- initio_unlink_pend_scb(host, scb);
- initio_release_scb(host, scb);
- } else {
- scb->opcode = BusDevRst;
- initio_select_atn_stop(host, scb);
- scb->next_state = 8;
- }
- } else {
- initio_unlink_pend_scb(host, scb);
- scb->hastat = 0x16;
- initio_append_done_scb(host, scb);
- }
- return;
- }
- static int initio_next_state(struct initio_host * host)
- {
- int next;
- next = host->active->next_state;
- for (;;) {
- switch (next) {
- case 1:
- next = initio_state_1(host);
- break;
- case 2:
- next = initio_state_2(host);
- break;
- case 3:
- next = initio_state_3(host);
- break;
- case 4:
- next = initio_state_4(host);
- break;
- case 5:
- next = initio_state_5(host);
- break;
- case 6:
- next = initio_state_6(host);
- break;
- case 7:
- next = initio_state_7(host);
- break;
- case 8:
- return initio_bus_device_reset(host);
- default:
- return initio_bad_seq(host);
- }
- if (next <= 0)
- return next;
- }
- }
- static int initio_state_1(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- struct target_control *active_tc = host->active_tc;
- #if DEBUG_STATE
- printk("-s1-");
- #endif
-
- initio_unlink_pend_scb(host, scb);
- initio_append_busy_scb(host, scb);
- outb(active_tc->sconfig0, host->addr + TUL_SConfig );
-
- if (host->phase == MSG_OUT) {
- outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- outb(scb->ident, host->addr + TUL_SFifo);
- if (scb->tagmsg) {
- outb(scb->tagmsg, host->addr + TUL_SFifo);
- outb(scb->tagid, host->addr + TUL_SFifo);
- }
- if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
- active_tc->flags |= TCF_WDTR_DONE;
- outb(MSG_EXTEND, host->addr + TUL_SFifo);
- outb(2, host->addr + TUL_SFifo);
- outb(3, host->addr + TUL_SFifo);
- outb(1, host->addr + TUL_SFifo);
- } else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
- active_tc->flags |= TCF_SYNC_DONE;
- outb(MSG_EXTEND, host->addr + TUL_SFifo);
- outb(3, host->addr + TUL_SFifo);
- outb(1, host->addr + TUL_SFifo);
- outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
- outb(MAX_OFFSET, host->addr + TUL_SFifo);
- }
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- }
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
-
- return 3;
- }
- static int initio_state_2(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- struct target_control *active_tc = host->active_tc;
- #if DEBUG_STATE
- printk("-s2-");
- #endif
- initio_unlink_pend_scb(host, scb);
- initio_append_busy_scb(host, scb);
- outb(active_tc->sconfig0, host->addr + TUL_SConfig);
- if (host->jsstatus1 & TSS_CMD_PH_CMP)
- return 4;
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
-
- return 3;
- }
- static int initio_state_3(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- struct target_control *active_tc = host->active_tc;
- int i;
- #if DEBUG_STATE
- printk("-s3-");
- #endif
- for (;;) {
- switch (host->phase) {
- case CMD_OUT:
- for (i = 0; i < (int) scb->cdblen; i++)
- outb(scb->cdb[i], host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- if (host->phase == CMD_OUT)
- return initio_bad_seq(host);
- return 4;
- case MSG_IN:
- scb->next_state = 3;
- if (initio_msgin(host) == -1)
- return -1;
- break;
- case STATUS_IN:
- if (initio_status_msg(host) == -1)
- return -1;
- break;
- case MSG_OUT:
- if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
- outb(MSG_NOP, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- } else {
- active_tc->flags |= TCF_SYNC_DONE;
- outb(MSG_EXTEND, host->addr + TUL_SFifo);
- outb(3, host->addr + TUL_SFifo);
- outb(1, host->addr + TUL_SFifo);
- outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
- outb(MAX_OFFSET, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);
- }
- break;
- default:
- return initio_bad_seq(host);
- }
- }
- }
- static int initio_state_4(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- #if DEBUG_STATE
- printk("-s4-");
- #endif
- if ((scb->flags & SCF_DIR) == SCF_NO_XF) {
- return 6;
- }
- for (;;) {
- if (scb->buflen == 0)
- return 6;
- switch (host->phase) {
- case STATUS_IN:
- if ((scb->flags & SCF_DIR) != 0)
- scb->hastat = HOST_DO_DU;
- if ((initio_status_msg(host)) == -1)
- return -1;
- break;
- case MSG_IN:
- scb->next_state = 0x4;
- if (initio_msgin(host) == -1)
- return -1;
- break;
- case MSG_OUT:
- if (host->jsstatus0 & TSS_PAR_ERROR) {
- scb->buflen = 0;
- scb->hastat = HOST_DO_DU;
- if (initio_msgout_ide(host) == -1)
- return -1;
- return 6;
- } else {
- outb(MSG_NOP, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- }
- break;
- case DATA_IN:
- return initio_xfer_data_in(host);
- case DATA_OUT:
- return initio_xfer_data_out(host);
- default:
- return initio_bad_seq(host);
- }
- }
- }
- static int initio_state_5(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- long cnt, xcnt;
- #if DEBUG_STATE
- printk("-s5-");
- #endif
-
- cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;
- if (inb(host->addr + TUL_XCmd) & 0x20) {
-
-
- if (host->jsstatus0 & TSS_PAR_ERROR)
- scb->hastat = HOST_DO_DU;
- if (inb(host->addr + TUL_XStatus) & XPEND) {
-
- outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);
-
- while (inb(host->addr + TUL_XStatus) & XPEND)
- cpu_relax();
- }
- } else {
-
- if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {
- if (host->active_tc->js_period & TSC_WIDE_SCSI)
- cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;
- else
- cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);
- }
- if (inb(host->addr + TUL_XStatus) & XPEND) {
- outb(TAX_X_ABT, host->addr + TUL_XCmd);
-
- while ((inb(host->addr + TUL_Int) & XABT) == 0)
- cpu_relax();
- }
- if ((cnt == 1) && (host->phase == DATA_OUT)) {
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- cnt = 0;
- } else {
- if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- }
- }
- if (cnt == 0) {
- scb->buflen = 0;
- return 6;
- }
-
- xcnt = (long) scb->buflen - cnt;
- scb->buflen = (u32) cnt;
- if (scb->flags & SCF_SG) {
- struct sg_entry *sgp;
- unsigned long i;
- sgp = &scb->sglist[scb->sgidx];
- for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {
- xcnt -= (long) sgp->len;
- if (xcnt < 0) {
- xcnt += (long) sgp->len;
- sgp->data += (u32) xcnt;
- sgp->len -= (u32) xcnt;
- scb->bufptr += ((u32) (i - scb->sgidx) << 3);
-
- scb->sglen = (u8) (scb->sgmax - i);
-
- scb->sgidx = (u16) i;
-
- return 4;
- }
-
- }
- return 6;
- } else {
- scb->bufptr += (u32) xcnt;
- }
- return 4;
- }
- static int initio_state_6(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- #if DEBUG_STATE
- printk("-s6-");
- #endif
- for (;;) {
- switch (host->phase) {
- case STATUS_IN:
- if ((initio_status_msg(host)) == -1)
- return -1;
- break;
- case MSG_IN:
- scb->next_state = 6;
- if ((initio_msgin(host)) == -1)
- return -1;
- break;
- case MSG_OUT:
- outb(MSG_NOP, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- break;
- case DATA_IN:
- return initio_xpad_in(host);
- case DATA_OUT:
- return initio_xpad_out(host);
- default:
- return initio_bad_seq(host);
- }
- }
- }
- int initio_state_7(struct initio_host * host)
- {
- int cnt, i;
- #if DEBUG_STATE
- printk("-s7-");
- #endif
-
- cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;
- if (cnt) {
- for (i = 0; i < cnt; i++)
- inb(host->addr + TUL_SFifo);
- }
- switch (host->phase) {
- case DATA_IN:
- case DATA_OUT:
- return initio_bad_seq(host);
- default:
- return 6;
- }
- }
- static int initio_xfer_data_in(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- if ((scb->flags & SCF_DIR) == SCF_DOUT)
- return 6;
- outl(scb->buflen, host->addr + TUL_SCnt0);
- outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd);
- if (scb->flags & SCF_SG) {
- outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
- outl(scb->bufptr, host->addr + TUL_XAddH);
- outb(TAX_SG_IN, host->addr + TUL_XCmd);
- } else {
- outl(scb->buflen, host->addr + TUL_XCntH);
- outl(scb->bufptr, host->addr + TUL_XAddH);
- outb(TAX_X_IN, host->addr + TUL_XCmd);
- }
- scb->next_state = 0x5;
- return 0;
- }
- static int initio_xfer_data_out(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- if ((scb->flags & SCF_DIR) == SCF_DIN)
- return 6;
- outl(scb->buflen, host->addr + TUL_SCnt0);
- outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);
- if (scb->flags & SCF_SG) {
- outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
- outl(scb->bufptr, host->addr + TUL_XAddH);
- outb(TAX_SG_OUT, host->addr + TUL_XCmd);
- } else {
- outl(scb->buflen, host->addr + TUL_XCntH);
- outl(scb->bufptr, host->addr + TUL_XAddH);
- outb(TAX_X_OUT, host->addr + TUL_XCmd);
- }
- scb->next_state = 0x5;
- return 0;
- }
- int initio_xpad_in(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- struct target_control *active_tc = host->active_tc;
- if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
- scb->hastat = HOST_DO_DU;
- for (;;) {
- if (active_tc->js_period & TSC_WIDE_SCSI)
- outl(2, host->addr + TUL_SCnt0);
- else
- outl(1, host->addr + TUL_SCnt0);
- outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- if (host->phase != DATA_IN) {
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- return 6;
- }
- inb(host->addr + TUL_SFifo);
- }
- }
- int initio_xpad_out(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- struct target_control *active_tc = host->active_tc;
- if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
- scb->hastat = HOST_DO_DU;
- for (;;) {
- if (active_tc->js_period & TSC_WIDE_SCSI)
- outl(2, host->addr + TUL_SCnt0);
- else
- outl(1, host->addr + TUL_SCnt0);
- outb(0, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- if ((wait_tulip(host)) == -1)
- return -1;
- if (host->phase != DATA_OUT) {
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- return 6;
- }
- }
- }
- int initio_status_msg(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- u8 msg;
- outb(TSC_CMD_COMP, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
-
- scb->tastat = inb(host->addr + TUL_SFifo);
- if (host->phase == MSG_OUT) {
- if (host->jsstatus0 & TSS_PAR_ERROR)
- outb(MSG_PARITY, host->addr + TUL_SFifo);
- else
- outb(MSG_NOP, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- if (host->phase == MSG_IN) {
- msg = inb(host->addr + TUL_SFifo);
- if (host->jsstatus0 & TSS_PAR_ERROR) {
- if ((initio_msgin_accept(host)) == -1)
- return -1;
- if (host->phase != MSG_OUT)
- return initio_bad_seq(host);
- outb(MSG_PARITY, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- if (msg == 0) {
- if ((scb->tastat & 0x18) == 0x10)
- return initio_bad_seq(host);
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
- return initio_wait_done_disc(host);
- }
- if (msg == MSG_LINK_COMP || msg == MSG_LINK_FLAG) {
- if ((scb->tastat & 0x18) == 0x10)
- return initio_msgin_accept(host);
- }
- }
- return initio_bad_seq(host);
- }
- int int_initio_busfree(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- if (scb != NULL) {
- if (scb->status & SCB_SELECT) {
- initio_unlink_pend_scb(host, scb);
- scb->hastat = HOST_SEL_TOUT;
- initio_append_done_scb(host, scb);
- } else {
- initio_unlink_busy_scb(host, scb);
- scb->hastat = HOST_BUS_FREE;
- initio_append_done_scb(host, scb);
- }
- host->active = NULL;
- host->active_tc = NULL;
- }
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- return -1;
- }
- static int int_initio_scsi_rst(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- int i;
-
- if (inb(host->addr + TUL_XStatus) & 0x01) {
- outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
-
- while ((inb(host->addr + TUL_Int) & 0x04) == 0)
- cpu_relax();
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- }
-
- while ((scb = initio_pop_busy_scb(host)) != NULL) {
- scb->hastat = HOST_BAD_PHAS;
- initio_append_done_scb(host, scb);
- }
- host->active = NULL;
- host->active_tc = NULL;
-
- for (i = 0; i < host->max_tar; i++)
- host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
- return -1;
- }
- int int_initio_resel(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- struct target_control *active_tc;
- u8 tag, msg = 0;
- u8 tar, lun;
- if ((scb = host->active) != NULL) {
-
- if (scb->status & SCB_SELECT)
- scb->status &= ~SCB_SELECT;
- host->active = NULL;
- }
-
- tar = inb(host->addr + TUL_SBusId);
-
- lun = inb(host->addr + TUL_SIdent) & 0x0F;
-
- active_tc = &host->targets[tar];
- host->active_tc = active_tc;
- outb(active_tc->sconfig0, host->addr + TUL_SConfig);
- outb(active_tc->js_period, host->addr + TUL_SPeriod);
-
- if (active_tc->drv_flags & TCF_DRV_EN_TAG) {
- if ((initio_msgin_accept(host)) == -1)
- return -1;
- if (host->phase != MSG_IN)
- goto no_tag;
- outl(1, host->addr + TUL_SCnt0);
- outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- msg = inb(host->addr + TUL_SFifo);
- if (msg < MSG_STAG || msg > MSG_OTAG)
- goto no_tag;
- if (initio_msgin_accept(host) == -1)
- return -1;
- if (host->phase != MSG_IN)
- goto no_tag;
- outl(1, host->addr + TUL_SCnt0);
- outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- tag = inb(host->addr + TUL_SFifo);
- scb = host->scb + tag;
- if (scb->target != tar || scb->lun != lun) {
- return initio_msgout_abort_tag(host);
- }
- if (scb->status != SCB_BUSY) {
- return initio_msgout_abort_tag(host);
- }
- host->active = scb;
- if ((initio_msgin_accept(host)) == -1)
- return -1;
- } else {
- no_tag:
- if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {
- return initio_msgout_abort_targ(host);
- }
- host->active = scb;
- if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {
- if ((initio_msgin_accept(host)) == -1)
- return -1;
- }
- }
- return 0;
- }
- static int int_initio_bad_seq(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- int i;
- initio_reset_scsi(host, 10);
- while ((scb = initio_pop_busy_scb(host)) != NULL) {
- scb->hastat = HOST_BAD_PHAS;
- initio_append_done_scb(host, scb);
- }
- for (i = 0; i < host->max_tar; i++)
- host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
- return -1;
- }
- static int initio_msgout_abort_targ(struct initio_host * host)
- {
- outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
- if (initio_msgin_accept(host) == -1)
- return -1;
- if (host->phase != MSG_OUT)
- return initio_bad_seq(host);
- outb(MSG_ABORT, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return initio_wait_disc(host);
- }
- static int initio_msgout_abort_tag(struct initio_host * host)
- {
- outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
- if (initio_msgin_accept(host) == -1)
- return -1;
- if (host->phase != MSG_OUT)
- return initio_bad_seq(host);
- outb(MSG_ABORT_TAG, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return initio_wait_disc(host);
- }
- static int initio_msgin(struct initio_host * host)
- {
- struct target_control *active_tc;
- for (;;) {
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outl(1, host->addr + TUL_SCnt0);
- outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- switch (inb(host->addr + TUL_SFifo)) {
- case MSG_DISC:
- outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
- return initio_wait_disc(host);
- case MSG_SDP:
- case MSG_RESTORE:
- case MSG_NOP:
- initio_msgin_accept(host);
- break;
- case MSG_REJ:
- outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),
- host->addr + TUL_SSignal);
- active_tc = host->active_tc;
- if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
- outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),
- host->addr + TUL_SSignal);
- initio_msgin_accept(host);
- break;
- case MSG_EXTEND:
- initio_msgin_extend(host);
- break;
- case MSG_IGNOREWIDE:
- initio_msgin_accept(host);
- break;
- case MSG_COMP:
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
- return initio_wait_done_disc(host);
- default:
- initio_msgout_reject(host);
- break;
- }
- if (host->phase != MSG_IN)
- return host->phase;
- }
-
- }
- static int initio_msgout_reject(struct initio_host * host)
- {
- outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
- if (initio_msgin_accept(host) == -1)
- return -1;
- if (host->phase == MSG_OUT) {
- outb(MSG_REJ, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- return host->phase;
- }
- static int initio_msgout_ide(struct initio_host * host)
- {
- outb(MSG_IDE, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- static int initio_msgin_extend(struct initio_host * host)
- {
- u8 len, idx;
- if (initio_msgin_accept(host) != MSG_IN)
- return host->phase;
-
- outl(1, host->addr + TUL_SCnt0);
- outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- len = inb(host->addr + TUL_SFifo);
- host->msg[0] = len;
- for (idx = 1; len != 0; len--) {
- if ((initio_msgin_accept(host)) != MSG_IN)
- return host->phase;
- outl(1, host->addr + TUL_SCnt0);
- outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
- if (wait_tulip(host) == -1)
- return -1;
- host->msg[idx++] = inb(host->addr + TUL_SFifo);
- }
- if (host->msg[1] == 1) {
- u8 r;
- if (host->msg[0] != 3)
- return initio_msgout_reject(host);
- if (host->active_tc->flags & TCF_NO_SYNC_NEGO) {
- host->msg[3] = 0;
- } else {
- if (initio_msgin_sync(host) == 0 &&
- (host->active_tc->flags & TCF_SYNC_DONE)) {
- initio_sync_done(host);
- return initio_msgin_accept(host);
- }
- }
- r = inb(host->addr + TUL_SSignal);
- outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,
- host->addr + TUL_SSignal);
- if (initio_msgin_accept(host) != MSG_OUT)
- return host->phase;
-
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- initio_sync_done(host);
- outb(MSG_EXTEND, host->addr + TUL_SFifo);
- outb(3, host->addr + TUL_SFifo);
- outb(1, host->addr + TUL_SFifo);
- outb(host->msg[2], host->addr + TUL_SFifo);
- outb(host->msg[3], host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- if (host->msg[0] != 2 || host->msg[1] != 3)
- return initio_msgout_reject(host);
-
- if (host->active_tc->flags & TCF_NO_WDTR) {
- host->msg[2] = 0;
- } else {
- if (host->msg[2] > 2)
- return initio_msgout_reject(host);
- if (host->msg[2] == 2) {
- host->msg[2] = 1;
- } else {
- if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {
- wdtr_done(host);
- if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
- outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
- return initio_msgin_accept(host);
- }
- }
- }
- outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
- if (initio_msgin_accept(host) != MSG_OUT)
- return host->phase;
-
- outb(MSG_EXTEND, host->addr + TUL_SFifo);
- outb(2, host->addr + TUL_SFifo);
- outb(3, host->addr + TUL_SFifo);
- outb(host->msg[2], host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- static int initio_msgin_sync(struct initio_host * host)
- {
- char default_period;
- default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];
- if (host->msg[3] > MAX_OFFSET) {
- host->msg[3] = MAX_OFFSET;
- if (host->msg[2] < default_period) {
- host->msg[2] = default_period;
- return 1;
- }
- if (host->msg[2] >= 59)
- host->msg[3] = 0;
- return 1;
- }
-
- if (host->msg[3] == 0) {
- return 0;
- }
- if (host->msg[2] < default_period) {
- host->msg[2] = default_period;
- return 1;
- }
- if (host->msg[2] >= 59) {
- host->msg[3] = 0;
- return 1;
- }
- return 0;
- }
- static int wdtr_done(struct initio_host * host)
- {
- host->active_tc->flags &= ~TCF_SYNC_DONE;
- host->active_tc->flags |= TCF_WDTR_DONE;
- host->active_tc->js_period = 0;
- if (host->msg[2])
- host->active_tc->js_period |= TSC_WIDE_SCSI;
- host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;
- outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
- outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
- return 1;
- }
- static int initio_sync_done(struct initio_host * host)
- {
- int i;
- host->active_tc->flags |= TCF_SYNC_DONE;
- if (host->msg[3]) {
- host->active_tc->js_period |= host->msg[3];
- for (i = 0; i < 8; i++) {
- if (initio_rate_tbl[i] >= host->msg[2])
- break;
- }
- host->active_tc->js_period |= (i << 4);
- host->active_tc->sconfig0 |= TSC_ALT_PERIOD;
- }
- outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
- outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
- return -1;
- }
- static int initio_post_scsi_rst(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb;
- struct target_control *active_tc;
- int i;
- host->active = NULL;
- host->active_tc = NULL;
- host->flags = 0;
- while ((scb = initio_pop_busy_scb(host)) != NULL) {
- scb->hastat = HOST_BAD_PHAS;
- initio_append_done_scb(host, scb);
- }
-
- active_tc = &host->targets[0];
- for (i = 0; i < host->max_tar; active_tc++, i++) {
- active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-
- active_tc->js_period = 0;
- active_tc->sconfig0 = host->sconf1;
- host->act_tags[0] = 0;
- host->targets[i].flags &= ~TCF_BUSY;
- }
- return -1;
- }
- static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
- scb->status |= SCB_SELECT;
- scb->next_state = 0x1;
- host->active = scb;
- host->active_tc = &host->targets[scb->target];
- outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);
- }
- static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
- int i;
- scb->status |= SCB_SELECT;
- scb->next_state = 0x2;
- outb(scb->ident, host->addr + TUL_SFifo);
- for (i = 0; i < (int) scb->cdblen; i++)
- outb(scb->cdb[i], host->addr + TUL_SFifo);
- host->active_tc = &host->targets[scb->target];
- host->active = scb;
- outb(TSC_SEL_ATN, host->addr + TUL_SCmd);
- }
- static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
- int i;
- scb->status |= SCB_SELECT;
- scb->next_state = 0x2;
- outb(scb->ident, host->addr + TUL_SFifo);
- outb(scb->tagmsg, host->addr + TUL_SFifo);
- outb(scb->tagid, host->addr + TUL_SFifo);
- for (i = 0; i < scb->cdblen; i++)
- outb(scb->cdb[i], host->addr + TUL_SFifo);
- host->active_tc = &host->targets[scb->target];
- host->active = scb;
- outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);
- }
- int initio_bus_device_reset(struct initio_host * host)
- {
- struct scsi_ctrl_blk *scb = host->active;
- struct target_control *active_tc = host->active_tc;
- struct scsi_ctrl_blk *tmp, *prev;
- u8 tar;
- if (host->phase != MSG_OUT)
- return int_initio_bad_seq(host);
- initio_unlink_pend_scb(host, scb);
- initio_release_scb(host, scb);
- tar = scb->target;
- active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
-
-
- prev = tmp = host->first_busy;
- while (tmp != NULL) {
- if (tmp->target == tar) {
-
- if (tmp == host->first_busy) {
- if ((host->first_busy = tmp->next) == NULL)
- host->last_busy = NULL;
- } else {
- prev->next = tmp->next;
- if (tmp == host->last_busy)
- host->last_busy = prev;
- }
- tmp->hastat = HOST_ABORTED;
- initio_append_done_scb(host, tmp);
- }
-
- else {
- prev = tmp;
- }
- tmp = tmp->next;
- }
- outb(MSG_DEVRST, host->addr + TUL_SFifo);
- outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
- return initio_wait_disc(host);
- }
- static int initio_msgin_accept(struct initio_host * host)
- {
- outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
- return wait_tulip(host);
- }
- static int wait_tulip(struct initio_host * host)
- {
- while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
- & TSS_INT_PENDING))
- cpu_relax();
- host->jsint = inb(host->addr + TUL_SInt);
- host->phase = host->jsstatus0 & TSS_PH_MASK;
- host->jsstatus1 = inb(host->addr + TUL_SStatus1);
- if (host->jsint & TSS_RESEL_INT)
- return int_initio_resel(host);
- if (host->jsint & TSS_SEL_TIMEOUT)
- return int_initio_busfree(host);
- if (host->jsint & TSS_SCSIRST_INT)
- return int_initio_scsi_rst(host);
- if (host->jsint & TSS_DISC_INT) {
- if (host->flags & HCF_EXPECT_DONE_DISC) {
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- initio_unlink_busy_scb(host, host->active);
- host->active->hastat = 0;
- initio_append_done_scb(host, host->active);
- host->active = NULL;
- host->active_tc = NULL;
- host->flags &= ~HCF_EXPECT_DONE_DISC;
- outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- return -1;
- }
- if (host->flags & HCF_EXPECT_DISC) {
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- host->active = NULL;
- host->active_tc = NULL;
- host->flags &= ~HCF_EXPECT_DISC;
- outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- return -1;
- }
- return int_initio_busfree(host);
- }
-
- if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))
- return host->phase;
- return host->phase;
- }
- static int initio_wait_disc(struct initio_host * host)
- {
- while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))
- cpu_relax();
- host->jsint = inb(host->addr + TUL_SInt);
- if (host->jsint & TSS_SCSIRST_INT)
- return int_initio_scsi_rst(host);
- if (host->jsint & TSS_DISC_INT) {
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- host->active = NULL;
- return -1;
- }
- return initio_bad_seq(host);
- }
- static int initio_wait_done_disc(struct initio_host * host)
- {
- while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
- & TSS_INT_PENDING))
- cpu_relax();
- host->jsint = inb(host->addr + TUL_SInt);
- if (host->jsint & TSS_SCSIRST_INT)
- return int_initio_scsi_rst(host);
- if (host->jsint & TSS_DISC_INT) {
- outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
- outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
- initio_unlink_busy_scb(host, host->active);
- initio_append_done_scb(host, host->active);
- host->active = NULL;
- return -1;
- }
- return initio_bad_seq(host);
- }
- static irqreturn_t i91u_intr(int irqno, void *dev_id)
- {
- struct Scsi_Host *dev = dev_id;
- unsigned long flags;
- int r;
-
- spin_lock_irqsave(dev->host_lock, flags);
- r = initio_isr((struct initio_host *)dev->hostdata);
- spin_unlock_irqrestore(dev->host_lock, flags);
- if (r)
- return IRQ_HANDLED;
- else
- return IRQ_NONE;
- }
- static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)
- {
- struct scatterlist *sglist;
- struct sg_entry *sg;
- int i, nseg;
- long total_len;
- dma_addr_t dma_addr;
-
- cblk->post = i91uSCBPost;
- cblk->srb = cmnd;
- cblk->opcode = ExecSCSI;
- cblk->flags = SCF_POST;
- cblk->target = cmnd->device->id;
- cblk->lun = cmnd->device->lun;
- cblk->ident = cmnd->device->lun | DISC_ALLOW;
- cblk->flags |= SCF_SENSE;
-
- dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
- SENSE_SIZE, DMA_FROM_DEVICE);
- cblk->senseptr = (u32)dma_addr;
- cblk->senselen = SENSE_SIZE;
- cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
- cblk->cdblen = cmnd->cmd_len;
-
- cblk->hastat = 0;
- cblk->tastat = 0;
-
- memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);
-
- if (cmnd->device->tagged_supported) {
- cblk->tagmsg = SIMPLE_QUEUE_TAG;
- } else {
- cblk->tagmsg = 0;
- }
-
- nseg = scsi_dma_map(cmnd);
- BUG_ON(nseg < 0);
- if (nseg) {
- dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
- sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
- DMA_BIDIRECTIONAL);
- cblk->bufptr = (u32)dma_addr;
- cmnd->SCp.dma_handle = dma_addr;
- cblk->sglen = nseg;
- cblk->flags |= SCF_SG;
- total_len = 0;
- sg = &cblk->sglist[0];
- scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
- sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
- sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
- total_len += sg_dma_len(sglist);
- ++sg;
- }
- cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?
- total_len : scsi_bufflen(cmnd);
- } else {
- cblk->buflen = 0;
- cblk->sglen = 0;
- }
- }
- static int i91u_queuecommand_lck(struct scsi_cmnd *cmd,
- void (*done)(struct scsi_cmnd *))
- {
- struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
- struct scsi_ctrl_blk *cmnd;
- cmd->scsi_done = done;
- cmnd = initio_alloc_scb(host);
- if (!cmnd)
- return SCSI_MLQUEUE_HOST_BUSY;
- initio_build_scb(host, cmnd, cmd);
- initio_exec_scb(host, cmnd);
- return 0;
- }
- static DEF_SCSI_QCMD(i91u_queuecommand)
- static int i91u_bus_reset(struct scsi_cmnd * cmnd)
- {
- struct initio_host *host;
- host = (struct initio_host *) cmnd->device->host->hostdata;
- spin_lock_irq(cmnd->device->host->host_lock);
- initio_reset_scsi(host, 0);
- spin_unlock_irq(cmnd->device->host->host_lock);
- return SUCCESS;
- }
- static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,
- sector_t capacity, int *info_array)
- {
- struct initio_host *host;
- struct target_control *tc;
- host = (struct initio_host *) sdev->host->hostdata;
- tc = &host->targets[sdev->id];
- if (tc->heads) {
- info_array[0] = tc->heads;
- info_array[1] = tc->sectors;
- info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;
- } else {
- if (tc->drv_flags & TCF_DRV_255_63) {
- info_array[0] = 255;
- info_array[1] = 63;
- info_array[2] = (unsigned long)capacity / 255 / 63;
- } else {
- info_array[0] = 64;
- info_array[1] = 32;
- info_array[2] = (unsigned long)capacity >> 11;
- }
- }
- #if defined(DEBUG_BIOSPARAM)
- if (i91u_debug & debug_biosparam) {
- printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
- info_array[0], info_array[1], info_array[2]);
- printk("WARNING: check, if the bios geometry is correct.\n");
- }
- #endif
- return 0;
- }
- static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
- {
-
- if (cmnd->SCp.ptr) {
- dma_unmap_single(&pci_dev->dev,
- (dma_addr_t)((unsigned long)cmnd->SCp.ptr),
- SENSE_SIZE, DMA_FROM_DEVICE);
- cmnd->SCp.ptr = NULL;
- }
-
- if (scsi_sg_count(cmnd)) {
- dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
- sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
- DMA_BIDIRECTIONAL);
- scsi_dma_unmap(cmnd);
- }
- }
- static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)
- {
- struct scsi_cmnd *cmnd;
- struct initio_host *host;
- struct scsi_ctrl_blk *cblk;
- host = (struct initio_host *) host_mem;
- cblk = (struct scsi_ctrl_blk *) cblk_mem;
- if ((cmnd = cblk->srb) == NULL) {
- printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");
- WARN_ON(1);
- initio_release_scb(host, cblk);
- return;
- }
-
- switch (cblk->hastat) {
- case 0x0:
- case 0xa:
- case 0xb:
- cblk->hastat = 0;
- break;
- case 0x11:
- cblk->hastat = DID_TIME_OUT;
- break;
- case 0x14:
- cblk->hastat = DID_RESET;
- break;
- case 0x1a:
- cblk->hastat = DID_ABORT;
- break;
- case 0x12:
- case 0x13:
- case 0x16:
- default:
- printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);
- cblk->hastat = DID_ERROR;
- break;
- }
- cmnd->result = cblk->tastat | (cblk->hastat << 16);
- i91u_unmap_scb(host->pci_dev, cmnd);
- cmnd->scsi_done(cmnd);
- initio_release_scb(host, cblk);
- }
- static struct scsi_host_template initio_template = {
- .proc_name = "INI9100U",
- .name = "Initio INI-9X00U/UW SCSI device driver",
- .queuecommand = i91u_queuecommand,
- .eh_bus_reset_handler = i91u_bus_reset,
- .bios_param = i91u_biosparam,
- .can_queue = MAX_TARGETS * i91u_MAXQUEUE,
- .this_id = 1,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- };
- static int initio_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
- {
- struct Scsi_Host *shost;
- struct initio_host *host;
- u32 reg;
- u16 bios_seg;
- struct scsi_ctrl_blk *scb, *tmp, *prev = NULL ;
- int num_scb, i, error;
- error = pci_enable_device(pdev);
- if (error)
- return error;
- pci_read_config_dword(pdev, 0x44, (u32 *) & reg);
- bios_seg = (u16) (reg & 0xFF);
- if (((reg & 0xFF00) >> 8) == 0xFF)
- reg = 0;
- bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
- printk(KERN_WARNING "i91u: Could not set 32 bit DMA mask\n");
- error = -ENODEV;
- goto out_disable_device;
- }
- shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));
- if (!shost) {
- printk(KERN_WARNING "initio: Could not allocate host structure.\n");
- error = -ENOMEM;
- goto out_disable_device;
- }
- host = (struct initio_host *)shost->hostdata;
- memset(host, 0, sizeof(struct initio_host));
- host->addr = pci_resource_start(pdev, 0);
- host->bios_addr = bios_seg;
- if (!request_region(host->addr, 256, "i91u")) {
- printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);
- error = -ENODEV;
- goto out_host_put;
- }
- if (initio_tag_enable)
- num_scb = MAX_TARGETS * i91u_MAXQUEUE;
- else
- num_scb = MAX_TARGETS + 3;
- for (; num_scb >= MAX_TARGETS + 3; num_scb--) {
- i = num_scb * sizeof(struct scsi_ctrl_blk);
- if ((scb = kzalloc(i, GFP_DMA)) != NULL)
- break;
- }
- if (!scb) {
- printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");
- error = -ENOMEM;
- goto out_release_region;
- }
- host->pci_dev = pdev;
- host->semaph = 1;
- spin_lock_init(&host->semaph_lock);
- host->num_scbs = num_scb;
- host->scb = scb;
- host->next_pending = scb;
- host->next_avail = scb;
- for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {
- tmp->tagid = i;
- if (i != 0)
- prev->next = tmp;
- prev = tmp;
- }
- prev->next = NULL;
- host->scb_end = tmp;
- host->first_avail = scb;
- host->last_avail = prev;
- spin_lock_init(&host->avail_lock);
- initio_init(host, phys_to_virt(((u32)bios_seg << 4)));
- host->jsstatus0 = 0;
- shost->io_port = host->addr;
- shost->n_io_port = 0xff;
- shost->can_queue = num_scb;
- shost->unique_id = host->addr;
- shost->max_id = host->max_tar;
- shost->max_lun = 32;
- shost->irq = pdev->irq;
- shost->this_id = host->scsi_id;
- shost->base = host->addr;
- shost->sg_tablesize = TOTAL_SG_ENTRY;
- error = request_irq(pdev->irq, i91u_intr, IRQF_DISABLED|IRQF_SHARED, "i91u", shost);
- if (error < 0) {
- printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);
- goto out_free_scbs;
- }
- pci_set_drvdata(pdev, shost);
- error = scsi_add_host(shost, &pdev->dev);
- if (error)
- goto out_free_irq;
- scsi_scan_host(shost);
- return 0;
- out_free_irq:
- free_irq(pdev->irq, shost);
- out_free_scbs:
- kfree(host->scb);
- out_release_region:
- release_region(host->addr, 256);
- out_host_put:
- scsi_host_put(shost);
- out_disable_device:
- pci_disable_device(pdev);
- return error;
- }
- static void initio_remove_one(struct pci_dev *pdev)
- {
- struct Scsi_Host *host = pci_get_drvdata(pdev);
- struct initio_host *s = (struct initio_host *)host->hostdata;
- scsi_remove_host(host);
- free_irq(pdev->irq, host);
- release_region(s->addr, 256);
- scsi_host_put(host);
- pci_disable_device(pdev);
- }
- MODULE_LICENSE("GPL");
- static struct pci_device_id initio_pci_tbl[] = {
- {PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0,}
- };
- MODULE_DEVICE_TABLE(pci, initio_pci_tbl);
- static struct pci_driver initio_pci_driver = {
- .name = "initio",
- .id_table = initio_pci_tbl,
- .probe = initio_probe_one,
- .remove = __devexit_p(initio_remove_one),
- };
- static int __init initio_init_driver(void)
- {
- return pci_register_driver(&initio_pci_driver);
- }
- static void __exit initio_exit_driver(void)
- {
- pci_unregister_driver(&initio_pci_driver);
- }
- MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
- MODULE_AUTHOR("Initio Corporation");
- MODULE_LICENSE("GPL");
- module_init(initio_init_driver);
- module_exit(initio_exit_driver);
|