BIOS.Adaptec7.Mod 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970
  1. MODULE Adaptec7; (** AUTHOR "prk"; PURPOSE "Adaptec 7xxx SCSI driver"; *)
  2. IMPORT
  3. SYSTEM, KernelLog, PCI, Machine, Kernel, Objects, Modules,
  4. SCSI, Script := Adaptec7Script;
  5. CONST
  6. (*debug flags*)
  7. traceCalls = 0;
  8. traceInts = 1;
  9. traceMsg = 2;
  10. traceSequencer = 4;
  11. traceReset = 5;
  12. traceConfig = 6;
  13. tracePeriod = 7;
  14. traceCmds = 8;
  15. traceSeeprom = 9;
  16. traceTermination = 10;
  17. traceSmall = 16;
  18. traceAIC7880 = 17;
  19. traceAIC7890 = 18;
  20. traceAHA2940 = 19;
  21. traceNoHandling = 20;
  22. (*traceDog = 21;*)
  23. traceNoRegister = 22;
  24. traceSync = 23;
  25. (* Buffer sizes*)
  26. QBufferSize = 3 * 256;
  27. SCBBufferSize = 128*32;
  28. BufferAlignment = 32;
  29. (* Message.Dir *)
  30. Sending = 0; Receiving = 1;
  31. (* Bus.sync Command Synchronization *)
  32. Free = 0; InUse = 1; Terminated = 2;
  33. (*Bus.chip: enumeration *)
  34. AIC7770 = 1; AIC7850 = 2; AIC7860 = 3; AIC7870 = 4; AIC7880 = 5; AIC7890 = 6;
  35. AIC7895 = 7; AIC7896 = 8;
  36. (*Bus.feature *)
  37. FeatUltra = 1; FeatUltra2 = 2; FeatWide = 3; FeatTwin = 4; FeatMoreSRAM = 5; FeatCmdChan = 6;
  38. FeatQueueRegs = 7; FeatSGPreload = 8; FeatSpioCap = 9;
  39. (*Bus.flag *)
  40. FlagPageSCB = 1; FlagNewEepromFMT = 2; FlagBiosEnabled = 3; FlagMultiChannel = 4; FlagChnlB = 5; FlagChnlC = 6;
  41. FlagSeepromFound = 7; FlagChannelBPrimary = 8; FlagExtendTransA = 9; FlagExternalSRam = 10; FlagAbortPending = 11;
  42. FlagHandlingReqInits = 12;
  43. (*HSCB Control *)
  44. HwScbTypeMask = 03X; HwScbMsgMask = 0F6X;
  45. HwScbDisconnected = 3; HwScbDiscEnable = 6; HwScbMessage = 7;
  46. (*SCSI Register Block *)
  47. (* 00H SCSI Sequencer Control *) SCSISEQ = 00H;
  48. (* Bit 0 SCSI Reset Out *) SCSIRSTO = 0;
  49. (* Bit 1 Enable Auto ATN on parity *) ENAUTOATNP = 1;
  50. (* Bit 4 Enable Reselection *) ENRSELI = 4;
  51. (* Bit 5 Enable Selection in *) ENSELI = 5;
  52. (* Bit 6 Enable Selection out *) ENSELO = 6;
  53. (* 01H SCSI Transfer Control 0 Register *) SXFRCTL0 = 01H;
  54. (* Bit 3 SCSI PIO Enable *) SPIOEN = 3;
  55. (* Bit 5 *) FAST20 = 5;
  56. (* Bit 7 Digital Filtering On *) DFON = 7;
  57. (* 02H SCSI Transfer Control 1 Register *) SXFRCTL1 = 02H;
  58. (* Bit 0 SCSI Termination Power Enable *) STPWEN = 0;
  59. (* Bit 1 Active Negation Enable *) ACTNEGEN = 1;
  60. (* Bit 2 Enable Selection timeout *) ENSTIMER = 2;
  61. (* Bit 5 Enable Parity Check *) ENSPCHK = 5;
  62. (* 03H SCSI Control Signal *) SCSISIG = 03H;
  63. (* Bit 0 Ack *) ACK = 0;
  64. (* Bit 1 *) REQ = 1;
  65. (* Bit 2 *) BSY = 2;
  66. (* Bit 3 *) SEL = 3;
  67. (* Bit 4 *) ATN = 4;
  68. (* Bit 5 *) MSG = 5;
  69. (* Bit 6 *) IO = 6;
  70. (* Bit 7 *) CD = 7;
  71. (* 04H SCSI Rate Control *) SCSIRATE = 04H;
  72. (* Bit 7 Wide Transer control *) WIDEXFER = 7;
  73. (* 05H SCSI ID *) SCSIID = 05H;
  74. SCSIOFFSET = 05H;
  75. (* 06H SCSI Data Low *) SCSIDATL = 06H;
  76. (* 0BH SCSI Status 0 *) SSTAT0 = 0BH;
  77. (* 0BH Clear SCSI Interrupt 0 *) CLRSINT0 = 0BH;
  78. (* Bit 1 CLRSPIORDY *) CLRSPIORDY = 1;
  79. (* Bit 3 CLRSWRAP *) CLRSWRAP = 3;
  80. (* Bit 4 CLRSELINGO *) CLRSELINGO = 4;
  81. (* Bit 5 CLRSELDI *) CLRSELDI = 5;
  82. (* Bit 6 CLRSELDO *) CLRSELDO = 6;
  83. (* 0CH SCSI Status 1 *) SSTAT1 = 0CH;
  84. (* Bit 0 *) REQINIT = 0;
  85. (* Bit 2 SCSI Parity Error *) SCSIPERR = 2;
  86. (* Bit 3 Bus Free Flag *) BUSFREE = 3;
  87. (* Bit 5 Scsi Reset *) SCSIRSTI = 5;
  88. (* Bit 7 Selection Time Out *) SELTO = 7;
  89. (* 0CH Clear SCSI Interrupt 1 *) CLRSINT1 = 0CH;
  90. (* Bit 0 CLRREQINIT *) CLRREQINIT = 0;
  91. (* Bit 1 CLRPHASECHG *) CLRPHASECHG = 1;
  92. (* Bit 2 CLRSCSIPERR *) CLRSCSIPERR = 2;
  93. (* Bit 3 CLRBUSFREE *) CLRBUSFREE = 3;
  94. (* Bit 5 CLRSCSIRSTI *) CLRSCSIRSTI = 5;
  95. (* Bit 6 CLRATNO *) CLRATNO = 6;
  96. (* Bit 7 CLRSELTIMEO *) CLRSELTIMEO = 7;
  97. CLRSINT1ALL = {0..3, 5..7};
  98. (* 0DH SCSI Status 2 *) SSTAT2 = 0DH;
  99. (* Bit 4 SCSI Expander Active *) EXPACTIVE = 4;
  100. (* 0EH SCSI Status 3 *) SSTAT3 = 0EH;
  101. (* 0FH SCSI ID for Ultra2 Chips *) SCSIIDULTRA2 = 0FH;
  102. (* 10H SCSI Interrupt Mode 0 *) SIMODE0 = 10H;
  103. (* 11H SCSI Interrupt Mode 1 *) SIMODE1 = 11H;
  104. (* Bit 1 Enable ReqInit *) ENREQINIT = 0;
  105. (* Bit 2 Enable Scsi Parity Error *) ENSCSIPERR = 2;
  106. (* Bit 3 Enable Bus Free *) ENBUSFREE = 3;
  107. (* Bit 5 Enable Scsi Reset *) ENSCSIRST = 5;
  108. (* Bit 7 Enable Time-out *) ENSELTIMO = 7;
  109. (* 12H SCSI Bus Low *) SCSIBUSL = 12H;
  110. (* 1BH Serial Port I/O Cabability register *) SPIOCAP = 1BH;
  111. (* Bit 0 Termination and cable detection *) SSPIOCPS = 0;
  112. (* 1DH Board Control *) BRDCTL = 1DH;
  113. (* Bit 0 7890 only: Board Strobe *) BRDSTBULTRA2 = 0;
  114. (* Bit 1 7890 only: Board Read/Write *) BRDRWULTRA2 = 1;
  115. (* Bit 2 Board Read/Write *) BRDRW = 2;
  116. (* Bit 3 Board Chip Select *) BRDCS = 3;
  117. (* Bit 4 Board Strobe *) BRDSTB = 4;
  118. (* 1EH Serial EEPROM Control *) SEECTL = 1EH;
  119. (* Bit 0 Serial EEPROM Data In *) SEEDI = 0;
  120. (* Bit 1 Serial EEPROM Data Out *) SEEDO = 1;
  121. (* Bit 2 Serial EEPROM Clock *) SEECK = 2;
  122. (* Bit 3 Serial EEPROM Chip Select *) SEECS = 3;
  123. (* Bit 4 Serial EEPROM Ready *) SEERDY = 4;
  124. (* Bit 5 Serial EEPROM Mode Select *) SEEMS = 5;
  125. (* 1FH SCSI Block Control *) SBLKCTL = 1FH;
  126. (* Bit 1 Select Wide *) SELWIDE = 1;
  127. (* Bit 3 SELBUSB *) SELBUSB = 3;
  128. (* Bit 3 LVD transceiver active *) ENAB40 = 3;
  129. (* Bit 5 Auto Flush Disable *) AUTOFLUSHDIS = 5;
  130. (* Bit 6 Diagnostic LED on *) DIAGLEDON = 6;
  131. (* Bit 7 Diagnostic LED Enable *) DIAGLEDEN =7;
  132. (* Scratch RAM *)
  133. (* 20H 1 byte per target starting at this address for configuration values*) TARGSCSIRATE = 20H;
  134. (* 30H Bit vector of targets that have ULTRA enabled. *) ULTRAENB = 30H;
  135. (* 32H Bit vector of targets that have disconnection disabled*) DISCDSB = 32H;
  136. (* 34H buffer to designate the type or message to send to a target*) MSGOUT = 34H;
  137. (* 35H Parameters for DMA Logic*) DMAPARAMS = 35H;
  138. (* 36H *) SEQFLAGS = 36H;
  139. (* 37H SAVED_TCL*) SAVEDTCL = 37H;
  140. (* 38H SG_COUNT*)
  141. (* 39H SG_NEXT*)
  142. (* 3DH LASTPHASE*) LASTPHASE = 3DH;
  143. (* Signals are declared in SCSISIG *) PHASEMASK = {CD, MSG, IO};
  144. (* Patterns*)
  145. PhaseStatus = {CD, IO};
  146. PhaseCommand = {CD};
  147. PhaseMsgOut = {CD, MSG};
  148. PhaseMsgIn = {CD, MSG, IO};
  149. PhaseDataIn = {IO};
  150. PhaseDataOut = {};
  151. PhaseBusFree = {0};
  152. (* 3EH WAITINGSCBH*) WAITINGSCBH = 3EH;
  153. (* 3FH DISCONNECTEDSCBH*) DISCONNECTEDSCBH = 3FH;
  154. (* 40H head of list of SCBs that are not in use. Used for SCB paging*) FREESCBH = 40H;
  155. (* 41H HSCB_ADDR*) HSCBARRAY = 41H;
  156. (* 45H SCBID_ADDR*) SCBIDADDR = 45H;
  157. (* 49H TMODE_CMDADDR*) TMODECMDADDR = 49H;
  158. (* 4DH KERNEL_QINPOS*) KERNELQINPOS = 4DH;
  159. (* 4EH QINPOS*) QINPOS = 4EH;
  160. (* 4FH QOUTPOS*) QOUTPOS = 4FH;
  161. (* 50H TMODE_CMDADDR_NEXT*) TMODECMDADDRNEXT = 50H;
  162. (* 51H ARG_1 / RETURN_1*) RETURN1 = 51H;
  163. (* Phase Mismatch *) MSGOUTPHASEMIS = {4};
  164. (* Send Sense *) SENDSENSE = {6};
  165. (* Send Msg *) SENDMSG = {7};
  166. (* 52H ARG_2 *)
  167. (* 53H LAST_MSG*) LASTMSG = 53H;
  168. (* 54H PREFETCH_CNT*)
  169. (* 5AH Scsi Configuration *) SCSICONF = 5AH;
  170. (* Bit 6 Reset SCSI-Bus at boot *) RESETSCSI = 6;
  171. (* Bit 7 Termination Enable *) TERMENB = 7;
  172. (* 60H Sequencer Control *) SEQCTL = 60H;
  173. (* Bit 0 Load Ram *) LOADRAM = 0;
  174. (* Bit 1 Reset *) SEQRESET = 1;
  175. (* Bit 4 Fast Mode *) FASTMODE = 4;
  176. (* Bit 5 Fail disable *) FAILDIS = 5;
  177. (* Bit 7 Parity Error disable *) PERRORDIS = 7;
  178. (* 61H Sequencer RAM Data *) SEQRAM = 61H;
  179. (* 62H Sequencer Address Registers *) SEQADDR0 = 62H;
  180. (* 63H *) SEQADDR1 = 63H;
  181. (* 65H *) SINDEX = 65H;
  182. (* Sequencer (SCSI Phase Engine)*)
  183. (* 70H 1 byte per target SCSI offset values for Ultra2 controllers *) TARGOFFSET = 70H;
  184. (* Bus Registers*)
  185. (* 84H Board Control*) BCTL = 84H;
  186. (* Bit 0 Enable *) ENABLE = 0;
  187. (* 84H Device Space Command*) DSCOMMAND0 = 84H;
  188. (* Bit 0 *) CIOPARCKEN = 0;
  189. (* bit 1 *) USCBSIZE32 = 1;
  190. (* Bit 5 Memory Parity Check Enable *) MPARCKEN = 5;
  191. (* Bit 6 Data Parity Check Enable *) DPARCKEN = 6;
  192. (* Bit 7 Cache Threshold Enable *) CACHETHEN = 7;
  193. (* 86H DSPCI Status *) DSPCISTATUS = 86H;
  194. (* Read when 100% empty, write when 100% full *) DFTHRSH100 = {6, 7};
  195. (* 87H Host Control, Overall host control of the device*) HCNTRL = 87H;
  196. (* Bit 0 Chip Reset / Chip Reset Acknowledge *) CHIPRST = 0;
  197. (* Bit 1 Interrupt Enable *) INTEN = 1;
  198. (* Bit 2 Pause Enable *) PAUSE = 2;
  199. (* 90H Gate one of the four SCBs into the SCBARRAY window*) SCBPTR = 90H;
  200. (* 91H Interrupt Status *) INTSTAT = 91H;
  201. (* Bit 0 Sequencer Interrupt *) SEQINT = 0H;
  202. (* Bit 1 Command Completed *) CMDCMPLT = 1H;
  203. (* Bit 2 Scsi Interrupt *) SCSIINT = 2H;
  204. (* Bit 3 Break address *) BRKADRINT = 3H;
  205. (* Sequencer Interrupt Mask *) SEQINTMASK = {0, 4..7};
  206. (* Interrupt Values*)
  207. DataOverrun = 0EH; MsgInPhaseMis = 0DH; TracePoint2 = 0CH;
  208. TracePoint = 0BH; AwaitingMsg = 0AH; Residual = 08H;
  209. BadStatus = 07H; RejectMsg = 06H; AbortRequested = 05H;
  210. ExtendedMsg = 04H; NoMatch = 03H; NoIdent = 02H;
  211. SendReject = 01H; BadPhase = 00H;
  212. (* 92H Write: Clear Interrupt Status *) CLRINT = 92H;
  213. (* Bit 0 Clear Sequencer Interrupt *) CLRSEQINT = 0;
  214. (* Bit 1 Clear Command Complete Interrupt *) CLRCMDINT = 1;
  215. (* Bit 2 Clear SCSI Interrupt *) CLRSCSIINT = 2;
  216. (* Bit 3 Clear Break Address Interrupt *) CLRBRKADRINT = 3;
  217. (* Bit 4 Clear Parity Errors*) CLRPARERR = 4;
  218. (* 92H Read: Hard Error *) ERROR = 92H;
  219. (* Bit 0 Illegal Hardware Address *) ILLHADDR = 0;
  220. (* Bit 1 Illegal Software Address *) ILLSADDR = 1;
  221. (* Bit 2 Illegal Opcode Error *) ILLOPCODE = 2;
  222. (* Bit 3 Sequencer Parity Error *) SQPARERR = 3;
  223. (* Bit 6 Pci error *) PCIERRSTAT = 6;
  224. (* 94H Data FIFO Status *) DFSTATUS = 94H;
  225. (* SCB Definition: this field give direct access to the scb pointed by SCBPTR*)
  226. (* A0H SCB Control *) SCBCONTROL = 0A0H;
  227. (* Bit 3 Disconnected*) DISCONNECTED = 3;
  228. (* Bit 6 Disconnect Enabled*) DISCENB = 6;
  229. (* A1H *) SCBTCL = 0A1H;
  230. (* A2H Target Status *) SCBTARGETSTATUS = 0A2H;
  231. (* A3H SG / Count *) SCBSGCOUNT = 0A3H;
  232. (* A4H SG / Ptr *) SCBSGPTR = 0A4H;
  233. (* A8H *) SCBRESIDSGCNT = 0A8H;
  234. (* A9H *) SCBRESIDDCNT = 0A9H;
  235. (* ACH *) SCBDATAPTR = 0ACH;
  236. (* B0H *) SCBDATACNT = 0B0H;
  237. (* B4H *) SCBCMDPTR = 0B4H;
  238. (* B8H *) SCBCMDLEN = 0B8H;
  239. (* B9H *) SCBTAG = 0B9H;
  240. (* BAH *) SCBNEXT = 0BAH;
  241. (* BBH *) SCBPREV = 0BBH;
  242. (* BCH *) SCBBUSYTARGETS = 0BCH;
  243. (* F0H CCSCBBADDR, 7895/6/7 only *) CCSCBBADDR = 0F0H;
  244. (* F4H Host New SCB Queue Offset *) HNSCBQOFF = 0F4H;
  245. (* F6H Sequencer New SCB Queue Offset *) SNSCBQOFF = 0F6H;
  246. (* F8H Sequencer Done SCB Queue Offset *) SDSCBQOFF = 0F8H;
  247. (* FAH Queue Offset Control & Status *) QOFFCTLSTA = 0FAH;
  248. (* Queue size = 256 *) SCBQSIZE256 = {1, 2};
  249. (* FBH Data FIFO Threshold *) DFFTHRSH = 0FBH;
  250. (* Write starts when 75% full *) WRDFFTHRSH75 = {6};
  251. (* Read starts when 75% empty *) RDDFFTHRSH75 = {2};
  252. (*PCI Registers*)
  253. (* 40H Device Configuration *) DEVCONFIG = 40H;
  254. (* Bit 2 RAMPSM_ULTRA2 7895/6 only? *) RAMPSMULTRA2 = 2;
  255. (* Bit 3 Byte Parity Error Enable *) BERREN = 3;
  256. (* Bit 3 SCBRAMSELULTRA2??? *) SCBRAMSELULTRA2 = 3;
  257. (* Bit 4 External SCB Parity Enable *) EXTSCBPEN = 4;
  258. (* Bit 7 SCB RAM Select, not 7890 *) SCBRAMSEL = 7;
  259. (* Bit 9 RAM Present Mode *) RAMPSM = 9;
  260. (* Bit 16 SCBSIZE32, 7895 only? *) SCBSIZE32 = 16;
  261. (* Bit 31 PCI Error Generation Disable *) PCIERRGENDIS = 31;
  262. SCAMCTL = 1AH; (*ultra2 only*)
  263. (* HW-SCB Offsets *)
  264. HScontrol = 0;
  265. HStarget = 1;
  266. HSstatus = 2;
  267. HSSGcount = 3;
  268. HSSGptr = 4;
  269. HSresSGcnt = 8;
  270. HSresDataCnt = 9;
  271. HSdataPtr = 12;
  272. HSdataCnt = 16;
  273. HScmdPtr = 20;
  274. HScmdLen = 24;
  275. HStag = 25;
  276. HSnext = 26;
  277. HSprev = 27;
  278. HSpar = 28;
  279. TYPE
  280. Interrupt = OBJECT
  281. VAR
  282. root: Bus; int: LONGINT;
  283. PROCEDURE HandleInterrupt;
  284. VAR int, err: SET; d: Bus;
  285. BEGIN
  286. INC(aIntCount);
  287. d := root;
  288. WHILE d # NIL DO
  289. int := SYSTEM.VAL(SET, d.Get1(d, INTSTAT));
  290. err := SYSTEM.VAL(SET, d.Get1(d, ERROR));
  291. IF d.interruptable & ((int # {}) OR (err # {})) THEN
  292. IF traceSmall IN trace THEN KernelLog.Char("<") END;
  293. IF CMDCMPLT IN int THEN
  294. IF traceSmall IN trace THEN KernelLog.Char("C") END;
  295. IntCommand(d)
  296. END;
  297. IF (BRKADRINT IN int) OR (err # {}) THEN
  298. IF traceSmall IN trace THEN KernelLog.Char("B") END;
  299. IntBrkAdr(d)
  300. END;
  301. IF SEQINT IN int THEN
  302. IF traceSmall IN trace THEN KernelLog.Char("S") END;
  303. IntSeqHandle(d, LSH(SYSTEM.VAL(LONGINT, int), -4))
  304. END;
  305. IF SCSIINT IN int THEN
  306. IF traceSmall IN trace THEN KernelLog.Char("s") END;
  307. IntScsiHandle(d)
  308. END;
  309. IF traceSmall IN trace THEN KernelLog.Char(">") END;
  310. END;
  311. d := d.next
  312. END
  313. END HandleInterrupt;
  314. PROCEDURE Cleanup;
  315. BEGIN
  316. Objects.RemoveHandler(SELF.HandleInterrupt, int)
  317. END Cleanup;
  318. PROCEDURE & Init*(irq: LONGINT);
  319. BEGIN
  320. int := Machine.IRQ0 + irq;
  321. Objects.InstallHandler(SELF.HandleInterrupt, int)
  322. END Init;
  323. END Interrupt;
  324. (*
  325. Watchdog = POINTER TO RECORD (Timer)
  326. VAR
  327. stop: BOOLEAN;
  328. dev, ms, count: LONGINT;
  329. bus: Bus;
  330. PROCEDURE & InitW(ms, count: LONGINT; bus: Bus; dev: LONGINT);
  331. BEGIN
  332. KernelLog.String("Watchdog installed"); KernelLog.Ln;
  333. Init;
  334. SELF.count := count; SELF.ms := ms;
  335. SELF.dev := dev; SELF.bus := bus
  336. END InitW;
  337. BEGIN {ACTIVE}
  338. Wait(ms);
  339. WHILE ~stop & (count > 0) DO
  340. WriteBusState(bus);
  341. Wait(ms);
  342. DEC(count)
  343. END;
  344. IF ~stop THEN (*timeouted*)
  345. bus.Synchronize(dev, bus.sync[dev], Terminated)
  346. END;
  347. KernelLog.String("Watchdog terminated"); KernelLog.Ln;
  348. END Watchdog;
  349. *)
  350. Message = RECORD
  351. buf: ARRAY 6 OF CHAR;
  352. pos, len, dir: SHORTINT;
  353. END;
  354. Bus = OBJECT (SCSI.Bus)
  355. VAR
  356. (* card configuration *)
  357. flags, features: SET;
  358. chip: SHORTINT;
  359. interruptable: BOOLEAN;
  360. irq: SHORTINT; (* interrupt line *)
  361. scsiId: SHORTINT;
  362. sync: ARRAY 16 OF SHORTINT; (* bus synchronization: only one cmd per device *)
  363. (* card IO information *)
  364. busNo, devNo, slotNo: LONGINT; (* PCI Address *)
  365. buffers: ARRAY (QBufferSize + SCBBufferSize + BufferAlignment) OF CHAR; (* Q and SCB buffers *)
  366. scbArea: LONGINT; (* virtual address of the hardware scb buffer, shared with the sequencer *)
  367. queueArea: LONGINT; (*virtual address of the queue buffers, shared with the sequencer *)
  368. in, out: LONGINT; (*pointer to next scb*)
  369. base: ADDRESS; (*virtual address for memory mapped IO / port address for port based IO *)
  370. Put1: PROCEDURE (d: Bus; offset: LONGINT; val: CHAR);
  371. Get1: PROCEDURE (d: Bus; offset: LONGINT): CHAR;
  372. (* cached values *)
  373. width: SHORTINT; (* 8 or 16, iff FeatWide *)
  374. negotiateWidth: SET; (*handle transmission width whenever possible*)
  375. negotiateSync: SET; (*handle transmission sync whenever possible*)
  376. msg: Message; (*message from/to device. Only one buffer: the message phase is not prehempted*)
  377. result, status: ARRAY 16 OF SHORTINT;
  378. next: Bus; (*list of all Ada7 busses *)
  379. PROCEDURE Synchronize(dev: LONGINT; await, set: SHORTINT);
  380. PROCEDURE Data;
  381. BEGIN
  382. KernelLog.String("Sync ["); KernelLog.Int(dev, 0); KernelLog.String("] ");
  383. KernelLog.Int(await, 0); KernelLog.String(" -> "); KernelLog.Int(set, 0)
  384. END Data;
  385. BEGIN {EXCLUSIVE}
  386. IF traceSync IN trace THEN BusNameMsg(SELF, " ->"); Data; KernelLog.Ln; END;
  387. AWAIT(sync[dev] = await);
  388. IF traceSync IN trace THEN BusNameMsg(SELF, " <-"); Data; KernelLog.Ln END;
  389. sync[dev] := set
  390. END Synchronize;
  391. PROCEDURE Submit*(VAR c: SCSI.Command);
  392. BEGIN
  393. Synchronize(c.target, Free, InUse);
  394. BusSchedule(SELF, c); (* return only when command Terminated *)
  395. c.result := result[c.target];
  396. c.status := status[c.target];
  397. Synchronize(c.target, Terminated, Free); (* activate/allow next command *)
  398. END Submit;
  399. PROCEDURE & Init*(id, bus, dev, slot: LONGINT);
  400. BEGIN
  401. flags := card[id].flags;
  402. features := card[id].features;
  403. chip := card[id].chip;
  404. interruptable := FALSE;
  405. COPY(card[id].name, fullname);
  406. busNo := bus; devNo := dev; slotNo := slot;
  407. IF firstBus = NIL THEN firstBus := SELF END;
  408. END Init;
  409. END Bus;
  410. RateTableDesc = RECORD
  411. period: SHORTINT; (* 1/4 of nsec, same as sync negotiation message *)
  412. rate: CHAR; (* rate for normal/fast/ultra cards *)
  413. u2rate: CHAR; (* rate ultra2 cards *)
  414. speed: LONGINT; (* speed in 100 KB/s for 8-bit bus *)
  415. END;
  416. (* Description of the cards we're know about *)
  417. CardTable = RECORD
  418. signature: LONGINT;
  419. chip: SHORTINT;
  420. flags, features: SET;
  421. name: ARRAY 32 OF CHAR;
  422. END;
  423. VAR
  424. timer: Kernel.Timer;
  425. interrupt: ARRAY 32 OF Interrupt;
  426. card: ARRAY 19 OF CardTable; (*description of the known cards*)
  427. rateTable: ARRAY 13 OF RateTableDesc;
  428. firstBus: Bus;
  429. trace: SET;
  430. aExecute,
  431. aIntScsiSeltoProblem1, aIntScsiSeltoProblem2,
  432. aIntScsiReset, aIntScsiSelto, aIntScsiBusFree, aIntScsiParity, aIntScsiReqInit, aIntScsiSpecial, aIntScsiUnknown,
  433. aIntSeqNoMatch, aIntSeqSendReject, aIntSeqNoIdent, aIntSeqBadPhase, aIntSeqExtendedMsg,
  434. aIntSeqRejectMsg, aIntSeqBadStatus, aIntSeqAwaitingMsg, aIntSeqDataOverrun,
  435. aIntCount, aIntCmdCount, aIntBrkAdrCount, aIntSeqCount, aIntScsiCount: LONGINT;
  436. (* Debug Procedures *)
  437. PROCEDURE ToDo(desc: ARRAY OF CHAR);
  438. BEGIN
  439. KernelLog.Enter;
  440. KernelLog.String(desc); KernelLog.String(" not implemented yet");
  441. KernelLog.Exit
  442. END ToDo;
  443. PROCEDURE BusName(b: Bus);
  444. BEGIN
  445. KernelLog.Char("["); KernelLog.Hex(b.busNo, -2);
  446. KernelLog.Char("/"); KernelLog.Hex(b.devNo, -2);
  447. KernelLog.Char("/"); KernelLog.Hex(b.slotNo, -2); KernelLog.String("] ");
  448. END BusName;
  449. PROCEDURE BusNameMsg(b: Bus; str: ARRAY OF CHAR);
  450. BEGIN
  451. KernelLog.Char("["); KernelLog.Hex(b.busNo, -2);
  452. KernelLog.Char("/"); KernelLog.Hex(b.devNo, -2);
  453. KernelLog.Char("/"); KernelLog.Hex(b.slotNo, -2); KernelLog.String("] ");
  454. KernelLog.String(str)
  455. END BusNameMsg;
  456. PROCEDURE Reg(d: Bus; off: LONGINT; name: ARRAY OF CHAR);
  457. BEGIN
  458. KernelLog.String(name); KernelLog.Hex(ORD(d.Get1(d, off)), -2)
  459. END Reg;
  460. PROCEDURE DumpCurSCB(d: Bus);
  461. BEGIN
  462. Reg(d, SCBPTR, "CurSCB = ");
  463. Reg(d, SCBCONTROL, " Ctrl = ");
  464. Reg(d, SCBTCL, " Targ = ");
  465. Reg(d, SCBTAG, " Tag = ");
  466. Reg(d, SCBPREV, " Prev = ");
  467. Reg(d, SCBNEXT, " Next = ");
  468. KernelLog.Ln;
  469. END DumpCurSCB;
  470. PROCEDURE DumpBusList(d: Bus; list: LONGINT; name: ARRAY OF CHAR);
  471. VAR ch, save: CHAR;
  472. BEGIN
  473. BusName(d); KernelLog.String(name);
  474. save := d.Get1(d, SCBPTR);
  475. ch := d.Get1(d, list);
  476. WHILE ch # 0FFX DO
  477. KernelLog.String("->"); KernelLog.Hex(ORD(ch), -2);
  478. d.Put1(d, SCBPTR, ch); ch := d.Get1(d, SCBNEXT);
  479. END;
  480. KernelLog.Ln;
  481. d.Put1(d, SCBPTR, save);
  482. END DumpBusList;
  483. PROCEDURE DumpAllLists(d: Bus);
  484. BEGIN
  485. DumpBusList(d, FREESCBH, "Free");
  486. DumpBusList(d, WAITINGSCBH, "Wait");
  487. DumpBusList(d, DISCONNECTEDSCBH, "Disc");
  488. END DumpAllLists;
  489. (* IO Procedures to be installed into the Bus structures to comunicate with hardware *)
  490. PROCEDURE PortPut(d: Bus; offset: LONGINT; val: CHAR);
  491. BEGIN
  492. Machine.Portout8(d.base+offset, val)
  493. END PortPut;
  494. PROCEDURE PortGet(d: Bus; offset: LONGINT): CHAR;
  495. VAR ch: CHAR;
  496. BEGIN
  497. Machine.Portin8(d.base+offset, ch); RETURN ch
  498. END PortGet;
  499. PROCEDURE MemoryPut(d: Bus; offset: LONGINT; val: CHAR);
  500. BEGIN
  501. SYSTEM.PUT(d.base+offset, val)
  502. END MemoryPut;
  503. PROCEDURE MemoryGet(d: Bus; offset: LONGINT): CHAR;
  504. VAR ch: CHAR;
  505. BEGIN
  506. SYSTEM.GET(d.base+offset, ch); RETURN ch
  507. END MemoryGet;
  508. (* Common Code Patterns *)
  509. PROCEDURE MakeTarget(targ, chan, lun: LONGINT): CHAR;
  510. BEGIN
  511. RETURN CHR(LSH(targ MOD 16, 4)+LSH(chan MOD 2, 3)+lun MOD 8)
  512. END MakeTarget;
  513. (* Sync / Width functions *)
  514. (* GetTableIndex - Return the index to start the search in the rateTable *)
  515. PROCEDURE GetTableIndex(ultra, ultra2: BOOLEAN): LONGINT;
  516. BEGIN
  517. IF ultra2 THEN RETURN 0 ELSIF ultra THEN RETURN 2 ELSE RETURN 5 END
  518. END GetTableIndex;
  519. PROCEDURE GetMaxOffset(wide, ultra2: BOOLEAN): CHAR;
  520. BEGIN
  521. IF ultra2 THEN RETURN 7FX
  522. ELSIF wide THEN RETURN 08X
  523. ELSE RETURN 0FX
  524. END
  525. END GetMaxOffset;
  526. PROCEDURE SetWidth(d: Bus; wide: BOOLEAN);
  527. VAR index: LONGINT; rate: SET;
  528. BEGIN
  529. index := ORD(d.Get1(d, SCBTAG));
  530. rate := SYSTEM.VAL(SET, d.Get1(d, TARGSCSIRATE + index));
  531. IF wide THEN
  532. INCL(rate, WIDEXFER)
  533. ELSE
  534. EXCL(rate, WIDEXFER)
  535. END;
  536. d.Put1(d, TARGSCSIRATE + index, SYSTEM.VAL(CHAR, rate));
  537. d.Put1(d, SCSIRATE, SYSTEM.VAL(CHAR, rate));
  538. BusNameMsg(d, "Device["); KernelLog.Int(index, 0); KernelLog.String("].width=");
  539. KernelLog.Int(SYSTEM.VAL(SHORTINT, wide), 0); KernelLog.Ln
  540. END SetWidth;
  541. PROCEDURE SetSyncRate(d: Bus; period, offset: LONGINT);
  542. VAR i, index, speed: LONGINT; ultra2, ultra, wide: BOOLEAN; ctrl0, rate: CHAR; set: SET;
  543. BEGIN
  544. ultra2 := FeatUltra2 IN d.features;
  545. ultra := FeatUltra IN d.features;
  546. index := ORD(d.Get1(d, SCBTAG));
  547. i := GetTableIndex(ultra, ultra2);
  548. WHILE (i < LEN(rateTable)) & (period > rateTable[i].period) DO INC(i) END;
  549. IF i = LEN(rateTable) THEN
  550. i := -1; offset := 0; (*async*)
  551. END;
  552. rate := d.Get1(d, TARGSCSIRATE + index);
  553. rate := SYSTEM.VAL(CHAR, SYSTEM.VAL(SET, rate) * {WIDEXFER});
  554. wide := rate # 0X;
  555. IF ultra2 THEN
  556. IF i # -1 THEN rate := CHR(ORD(rate) + ORD(rateTable[i].u2rate)) END;
  557. d.Put1(d, SCSIRATE, rate);
  558. d.Put1(d, SCSIOFFSET, CHR(offset));
  559. d.Put1(d, TARGSCSIRATE+index, rate);
  560. d.Put1(d, TARGOFFSET+index, CHR(offset))
  561. ELSE
  562. IF i # -1 THEN
  563. ASSERT(offset < 10H);
  564. rate := CHR(ORD(rate) + ORD(rateTable[i].rate) + (offset MOD 10H));
  565. ultra := i < 5
  566. ELSE
  567. ultra := FALSE
  568. END;
  569. d.Put1(d, SCSIRATE, rate);
  570. d.Put1(d, TARGSCSIRATE + index, rate);
  571. ctrl0 := d.Get1(d, SXFRCTL0);
  572. set := SYSTEM.VAL(SET, d.Get1(d, ULTRAENB + index DIV 8));
  573. IF ultra THEN
  574. ctrl0 := SYSTEM.VAL(CHAR, SYSTEM.VAL(SET, ctrl0) + {FAST20});
  575. INCL(set, index MOD 8)
  576. ELSE
  577. ctrl0 := SYSTEM.VAL(CHAR, SYSTEM.VAL(SET, ctrl0) - {FAST20});
  578. EXCL(set, index MOD 8)
  579. END;
  580. d.Put1(d, SXFRCTL0, ctrl0);
  581. d.Put1(d, ULTRAENB + index DIV 8, SYSTEM.VAL(CHAR, set))
  582. END;
  583. BusNameMsg(d, "Device["); KernelLog.Int(index, 0); KernelLog.String("].rate=");
  584. IF i = -1 THEN
  585. KernelLog.String("async")
  586. ELSE
  587. KernelLog.Int(rateTable[i].period, 0); KernelLog.Char("/"); KernelLog.Int(offset, 0);
  588. speed := rateTable[i].speed;
  589. IF wide THEN speed := speed*2 END;
  590. KernelLog.Int(speed DIV 10, 4); KernelLog.Char("."); KernelLog.Int(speed MOD 10, 0);
  591. KernelLog.String(" MB/s")
  592. END;
  593. KernelLog.Ln
  594. END SetSyncRate;
  595. (* Queues Functions *)
  596. (*
  597. Queue Layout
  598. +000H untagged queue
  599. +100H out queue
  600. +200H in queue
  601. *)
  602. PROCEDURE QUntaggedSet(d: Bus; i: LONGINT; ch: CHAR);
  603. BEGIN
  604. SYSTEM.PUT(d.queueArea+i, ch)
  605. END QUntaggedSet;
  606. PROCEDURE QOutSet(d: Bus; i: LONGINT; ch: CHAR);
  607. BEGIN
  608. SYSTEM.PUT(d.queueArea+100H+i, ch)
  609. END QOutSet;
  610. PROCEDURE QOutGet(d: Bus; i: LONGINT): CHAR;
  611. VAR ch: CHAR;
  612. BEGIN
  613. SYSTEM.GET(d.queueArea+100H+i, ch); RETURN ch
  614. END QOutGet;
  615. PROCEDURE QInSet(d: Bus; i: LONGINT; ch: CHAR);
  616. BEGIN
  617. SYSTEM.PUT(d.queueArea+200H+i, ch)
  618. END QInSet;
  619. PROCEDURE QInit(d: Bus);
  620. VAR paddr, i: LONGINT;
  621. BEGIN
  622. IF traceCalls IN trace THEN BusNameMsg(d, "QInit"); KernelLog.Ln END;
  623. (*
  624. Machine.NewPhysicalPage(paddr);
  625. Machine.MapPhysical(paddr, Machine.PageSize, d.queueArea);
  626. *)
  627. paddr := ADDRESSOF(d.buffers[0]);
  628. INC(paddr, (-paddr) MOD BufferAlignment);
  629. d.queueArea := paddr;
  630. FOR i := 0 TO 255 DO
  631. QUntaggedSet(d, i, 0FFX); QOutSet(d, i, 0FFX); QInSet(d, i, 0FFX)
  632. END;
  633. d.in := 0;
  634. d.out := 0;
  635. d.Put1(d, SCBIDADDR, CHR(paddr));
  636. d.Put1(d, SCBIDADDR+1, CHR(LSH(paddr, -8)));
  637. d.Put1(d, SCBIDADDR+2, CHR(LSH(paddr, -16)));
  638. d.Put1(d, SCBIDADDR+3, CHR(LSH(paddr, -24)));
  639. d.Put1(d, QINPOS, 0X);
  640. d.Put1(d, KERNELQINPOS, 0X);
  641. d.Put1(d, QOUTPOS, 0X);
  642. IF FeatQueueRegs IN d.features THEN
  643. d.Put1(d, QOFFCTLSTA, 6X); (* Queue size = 256 *)
  644. d.Put1(d, SDSCBQOFF, 0X);
  645. d.Put1(d, SNSCBQOFF, 0X);
  646. d.Put1(d, HNSCBQOFF, 0X)
  647. END;
  648. d.Put1(d, WAITINGSCBH, 0FFX);
  649. d.Put1(d, DISCONNECTEDSCBH, 0FFX);
  650. END QInit;
  651. (* HW-SCB Functions *)
  652. (*
  653. HW SCB Layout:
  654. 00 1 control
  655. 01 1 target
  656. 02 1 status
  657. 03 1 SG count
  658. 04 4 SG pointer
  659. 08 1 residual SG count
  660. 09 3 residual Data count
  661. 12 4 data ptr
  662. 16 4 data cnt
  663. 20 4 cmd ptr
  664. 24 1 cmd len
  665. 25 1 tag
  666. 26 1 next
  667. 27 1 prev
  668. 28 4 par
  669. *)
  670. PROCEDURE HSSet(d: Bus; num, offset: LONGINT; val: CHAR);
  671. BEGIN SYSTEM.PUT(d.scbArea + num*32 + offset, val)
  672. END HSSet;
  673. PROCEDURE HSSet4(d: Bus; num, offset: LONGINT; val: LONGINT);
  674. BEGIN SYSTEM.PUT(d.scbArea + num*32 + offset, val)
  675. END HSSet4;
  676. PROCEDURE HSFreeCurrent(d: Bus);
  677. BEGIN
  678. d.Put1(d, SCBTAG, 0FFX);
  679. d.Put1(d, SCBCONTROL, 0X);
  680. d.Put1(d, SCBNEXT, d.Get1(d, FREESCBH));
  681. d.Put1(d, FREESCBH, d.Get1(d, SCBPTR))
  682. END HSFreeCurrent;
  683. PROCEDURE HSFreeScb(d: Bus; index: LONGINT);
  684. BEGIN
  685. HSSet(d, index, HScontrol, 0X);
  686. HSSet(d, index, HSstatus, 0X);
  687. HSSet(d, index, HStarget, 0FFX)
  688. END HSFreeScb;
  689. PROCEDURE HSInit(d: Bus);
  690. VAR paddr, i: LONGINT; quit: BOOLEAN;
  691. BEGIN
  692. IF traceCalls IN trace THEN BusNameMsg(d, "HSInit"); KernelLog.Ln END;
  693. (*allocate hw-scb buffer*)
  694. (*
  695. Machine.NewPhysicalPage(paddr);
  696. Machine.MapPhysical(paddr, Machine.PageSize, d.scbArea);
  697. *)
  698. paddr := ADDRESSOF(d.buffers[QBufferSize]);
  699. INC(paddr, (-paddr) MOD BufferAlignment);
  700. d.scbArea := paddr;
  701. FOR i := 0 TO 127 DO
  702. SYSTEM.PUT(d.scbArea + i*32 + HScontrol, 0X); (* control := 0X *)
  703. SYSTEM.PUT(d.scbArea + i*32 + HStag, CHR(i)); (* tag := i *)
  704. END;
  705. d.Put1(d, HSCBARRAY, CHR(paddr));
  706. d.Put1(d, HSCBARRAY+1, CHR(LSH(paddr, -8)));
  707. d.Put1(d, HSCBARRAY+2, CHR(LSH(paddr, -16)));
  708. d.Put1(d, HSCBARRAY+3, CHR(LSH(paddr, -24)));
  709. (* clear and initialize host scb table *)
  710. d.Put1(d, FREESCBH, 0X);
  711. i := 0; quit := FALSE;
  712. WHILE (i < 255) & ~quit DO
  713. d.Put1(d, SCBPTR, CHR(i));
  714. d.Put1(d, SCBCONTROL, CHR(i));
  715. IF i # ORD(d.Get1(d, SCBCONTROL)) THEN
  716. quit := TRUE
  717. ELSE
  718. d.Put1(d, SCBPTR, 0X);
  719. IF d.Get1(d, SCBCONTROL) # 0X THEN
  720. quit := TRUE
  721. ELSE
  722. d.Put1(d, SCBPTR, CHR(i));
  723. d.Put1(d, SCBCONTROL, 0X);
  724. d.Put1(d, SCBNEXT, CHR(i+1));
  725. d.Put1(d, SCBPREV, CHR(i-1));
  726. d.Put1(d, SCBTAG, 0FFX);
  727. d.Put1(d, SCBBUSYTARGETS, 0FFX);
  728. d.Put1(d, SCBBUSYTARGETS+1, 0FFX);
  729. d.Put1(d, SCBBUSYTARGETS+2, 0FFX);
  730. d.Put1(d, SCBBUSYTARGETS+3, 0FFX);
  731. INC(i)
  732. END
  733. END
  734. END;
  735. d.Put1(d, SCBPTR, CHR(i-1)); (*last SCB terminates the list*)
  736. d.Put1(d, SCBNEXT, 0FFX);
  737. d.Put1(d, SCBPTR, 0X); (*clear first SCB control byte (may have been changed)*)
  738. d.Put1(d, SCBCONTROL, 0X);
  739. IF i = 255 THEN EXCL(d.flags, FlagPageSCB) END;
  740. BusNameMsg(d, "SCB = "); KernelLog.Int(i, 0); KernelLog.Ln
  741. END HSInit;
  742. (* Sequencer Functions *)
  743. PROCEDURE SeqPause(d: Bus);
  744. BEGIN
  745. IF traceSequencer IN trace THEN BusNameMsg(d, "SeqPause"); KernelLog.Ln END;
  746. d.Put1(d, HCNTRL, SYSTEM.VAL(CHAR, {INTEN, PAUSE}));
  747. WHILE ~(PAUSE IN SYSTEM.VAL(SET, d.Get1(d, HCNTRL))) DO END;
  748. END SeqPause;
  749. PROCEDURE SeqUnpause(d: Bus);
  750. BEGIN
  751. IF traceSequencer IN trace THEN BusNameMsg(d, "SeqUnpause") END;
  752. IF ~(FlagHandlingReqInits IN d.flags) THEN
  753. IF traceSequencer IN trace THEN KernelLog.String("*") END;
  754. d.Put1(d, HCNTRL, SYSTEM.VAL(CHAR, {INTEN}))
  755. ELSE
  756. ToDo("Ada7: Unpausing the sequencer while in message mode")
  757. END;
  758. IF traceSequencer IN trace THEN KernelLog.Ln END;
  759. END SeqUnpause;
  760. PROCEDURE SeqLoad(d: Bus);
  761. VAR i, line: LONGINT;
  762. BEGIN
  763. IF traceCalls IN trace THEN BusNameMsg(d, "LoadSequencer"); KernelLog.Ln END;
  764. Script.Init(FeatUltra2 IN d.features, FeatUltra IN d.features, FeatWide IN d.features, FeatTwin IN d.features,
  765. FlagPageSCB IN d.flags, FeatQueueRegs IN d.features, FeatCmdChan IN d.features, FALSE, AIC7895 = d.chip);
  766. i := 0;
  767. d.Put1(d, SEQCTL, SYSTEM.VAL(CHAR, {PERRORDIS,LOADRAM,FAILDIS,FASTMODE}));
  768. d.Put1(d, SEQADDR0, 0X);
  769. d.Put1(d, SEQADDR1, 0X);
  770. WHILE Script.GetNext(SYSTEM.VAL(SET, line)) DO
  771. d.Put1(d, SEQRAM, CHR(line));
  772. d.Put1(d, SEQRAM, CHR(LSH(line, -8)));
  773. d.Put1(d, SEQRAM, CHR(LSH(line, -16)));
  774. d.Put1(d, SEQRAM, CHR(LSH(line, -24)));
  775. INC(i)
  776. END;
  777. BusNameMsg(d, "Sequencer Loaded lines="); KernelLog.Int(i, 0); KernelLog.Ln;
  778. d.Put1(d, SEQCTL, SYSTEM.VAL(CHAR, {FASTMODE,SEQRESET}));
  779. END SeqLoad;
  780. (* PCI Functions *)
  781. PROCEDURE PCIClearInt(d: Bus);
  782. CONST DPR = 0; RMA = 5; RTA = 4;
  783. VAR res, dw: LONGINT; bus, dev, slot: LONGINT;
  784. BEGIN
  785. bus := d.busNo; dev := d.devNo; slot := d.slotNo;
  786. res := PCI.ReadConfigByte(bus, dev, slot, 7H, dw);
  787. res := PCI.WriteConfigByte(bus, dev, slot, 7H, dw); (* Clear PCI-Status *)
  788. IF {DPR, RMA, RTA} * SYSTEM.VAL(SET, dw) # {} THEN
  789. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRPARERR}))
  790. END;
  791. END PCIClearInt;
  792. PROCEDURE PCIInit(d: Bus; bus, dev, slot: LONGINT);
  793. VAR res, dw: LONGINT;
  794. BEGIN
  795. IF traceCalls IN trace THEN BusNameMsg(d, "PCIInit"); KernelLog.Ln END;
  796. res:=PCI.ReadConfigByte(bus, dev, slot, PCI.IntlReg, dw); (*irq*)
  797. d.irq := SHORT(SHORT(dw));
  798. BusName(d); KernelLog.String("irq="); KernelLog.Int(d.irq, 0);
  799. res:=PCI.ReadConfigDword(bus, dev, slot, PCI.Adr1Reg, dw); (*memio*)
  800. IF dw = 0 THEN
  801. res:=PCI.ReadConfigDword(bus, dev, slot, PCI.Adr0Reg, dw); (*iobase*)
  802. d.base := dw - 1;
  803. d.Put1 := PortPut;
  804. d.Get1 := PortGet;
  805. KernelLog.String(" Port="); KernelLog.Int(d.base, 0)
  806. ELSE
  807. dw := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, dw) * {3..31}); (* clear io mode & 64 bit flags*)
  808. Machine.MapPhysical(dw, 100H, d.base);
  809. d.Put1 := MemoryPut;
  810. d.Get1 := MemoryGet;
  811. KernelLog.String(" MemMap="); KernelLog.Hex(dw, 0); KernelLog.String("/"); KernelLog.Hex(d.base, 0)
  812. END;
  813. KernelLog.Ln;
  814. res:=PCI.ReadConfigWord(bus, dev, slot, PCI.CmdReg, dw);
  815. dw := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, dw) + {8, 6, 4, 2, 1, 0}); (*Serren, Perren, Mwricen, Master, MSpace, ISpace*)
  816. res:=PCI.WriteConfigWord(bus, dev, slot, PCI.CmdReg, dw);
  817. res:=PCI.ReadConfigDword(bus, dev, slot, DEVCONFIG, dw);
  818. dw := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, dw) + {PCIERRGENDIS} - {BERREN});
  819. IF d.chip = AIC7895 THEN
  820. dw := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, dw) + {SCBSIZE32});
  821. END;
  822. res:=PCI.WriteConfigDword(bus, dev, slot, DEVCONFIG, dw);
  823. SeqPause(d);
  824. PCIClearInt(d);
  825. END PCIInit;
  826. (* Message Handling *)
  827. PROCEDURE MsgStart(d: Bus);
  828. VAR t: SET;
  829. BEGIN
  830. INCL(d.flags, FlagHandlingReqInits);
  831. t := SYSTEM.VAL(SET, d.Get1(d, SIMODE1));
  832. d.Put1(d, SIMODE1, SYSTEM.VAL(CHAR, t + {ENREQINIT}));
  833. END MsgStart;
  834. PROCEDURE MsgStop(d: Bus);
  835. VAR t: SET;
  836. BEGIN
  837. t := SYSTEM.VAL(SET, d.Get1(d, SIMODE1));
  838. d.Put1(d, SIMODE1, SYSTEM.VAL(CHAR, t - {ENREQINIT}));
  839. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  840. EXCL(d.flags, FlagHandlingReqInits);
  841. END MsgStop;
  842. PROCEDURE MsgCompose(d: Bus; index: LONGINT; VAR msg: Message);
  843. VAR i: LONGINT;
  844. BEGIN
  845. IF index IN d.negotiateWidth THEN
  846. EXCL(d.negotiateWidth, index);
  847. msg.buf[0] := SCSI.MsgExtended;
  848. msg.buf[1] := SCSI.MsgExtWdTrLen;
  849. msg.buf[2] := SCSI.MsgExtWdTr;
  850. msg.buf[3] := SCSI.MsgExtWdTr16Bit; (*always ask for the max*)
  851. msg.len := 4;
  852. msg.pos := 0;
  853. msg.dir := Sending
  854. ELSIF index IN d.negotiateSync THEN
  855. EXCL(d.negotiateSync, index);
  856. i := GetTableIndex(FeatUltra IN d.features, FeatUltra2 IN d.features);
  857. msg.buf[0] := SCSI.MsgExtended;
  858. msg.buf[1] := SCSI.MsgExtSdTrLen;
  859. msg.buf[2] := SCSI.MsgExtSdTr;
  860. msg.buf[3] := CHR(rateTable[i].period); (* ask for min period (fastest) *)
  861. msg.buf[4] := GetMaxOffset(FeatWide IN d.features, FeatUltra2 IN d.features); (* ask for the max offset *)
  862. msg.len := 5;
  863. msg.pos := 0;
  864. msg.dir := Sending
  865. ELSE
  866. ToDo("Adaptec7.MsgCompose: negotiate what?");
  867. END
  868. END MsgCompose;
  869. PROCEDURE MsgParse(d: Bus; VAR msg: Message): BOOLEAN;
  870. VAR reject, done, wide: BOOLEAN; period, offset: LONGINT; t: SET;
  871. BEGIN
  872. reject := FALSE; done := FALSE;
  873. IF msg.buf[0] # SCSI.MsgExtended THEN
  874. reject := TRUE
  875. ELSIF msg.len <= 2 THEN (*ExtMsg are 4 or 5 bytes*)
  876. done := FALSE
  877. ELSIF msg.buf[2] = SCSI.MsgExtSdTr THEN (*sync handling*)
  878. IF msg.buf[1] # SCSI.MsgExtSdTrLen THEN
  879. reject := TRUE
  880. ELSIF msg.len < ORD(SCSI.MsgExtSdTrLen)+2 THEN
  881. done := FALSE
  882. ELSE
  883. done := TRUE;
  884. period := ORD(msg.buf[3]);
  885. offset := ORD(msg.buf[4]);
  886. BusNameMsg(d, "SyncMsg "); KernelLog.Int(period, 0); KernelLog.Char("/");
  887. KernelLog.Int(offset, 0); KernelLog.Ln;
  888. SetSyncRate(d, period, offset)
  889. END
  890. ELSIF msg.buf[2] = SCSI.MsgExtWdTr THEN (*width handling*)
  891. IF msg.buf[1] # SCSI.MsgExtWdTrLen THEN
  892. reject := TRUE
  893. ELSIF msg.len < ORD(SCSI.MsgExtWdTrLen)+2 THEN
  894. done := FALSE
  895. ELSE
  896. done := TRUE;
  897. wide := msg.buf[3] = SCSI.MsgExtWdTr16Bit;
  898. BusNameMsg(d, "WidthMsg "); KernelLog.Int(ORD(msg.buf[3]), 0); KernelLog.Ln;
  899. SetWidth(d, wide);
  900. END
  901. ELSE
  902. reject := TRUE
  903. END;
  904. IF reject THEN
  905. d.Put1(d, MSGOUT, SCSI.MsgMessageReject);
  906. t := SYSTEM.VAL(SET, d.Get1(d, SCSISIG));
  907. d.Put1(d, SCSISIG, SYSTEM.VAL(CHAR, t + {ATN}))
  908. END;
  909. RETURN reject OR done
  910. END MsgParse;
  911. PROCEDURE MsgTransmit(d: Bus; VAR msg: Message);
  912. VAR t: SET; done: BOOLEAN; ch: CHAR;
  913. BEGIN
  914. t := SYSTEM.VAL(SET, d.Get1(d, SCSISIG));
  915. IF msg.dir = Sending THEN
  916. IF traceSmall IN trace THEN
  917. KernelLog.Char("["); KernelLog.Hex(ORD(msg.buf[msg.pos]), -2); KernelLog.Char("]")
  918. END;
  919. IF msg.pos = msg.len-1 THEN (* last byte *)
  920. done := TRUE;
  921. d.Put1(d, SINDEX, msg.buf[msg.pos]);
  922. d.Put1(d, RETURN1, 0X)
  923. ELSIF (t * PHASEMASK) # PhaseMsgOut THEN (* Phase Mismatch *)
  924. IF traceSmall IN trace THEN KernelLog.Char("&") END;
  925. done := TRUE;
  926. d.Put1(d, RETURN1, SYSTEM.VAL(CHAR, MSGOUTPHASEMIS))
  927. ELSE
  928. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, {CLRREQINIT}));
  929. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  930. d.Put1(d, SCSIDATL, msg.buf[msg.pos]);
  931. INC(msg.pos);
  932. END;
  933. ELSE
  934. done := (t * PHASEMASK) # PhaseMsgIn;
  935. IF ~done THEN
  936. msg.buf[msg.pos] := SYSTEM.VAL(CHAR, d.Get1(d, SCSIBUSL));
  937. IF traceSmall IN trace THEN
  938. KernelLog.Char("("); KernelLog.Hex(ORD(msg.buf[msg.pos]), -2); KernelLog.Char(")")
  939. END;
  940. INC(msg.len); INC(msg.pos);
  941. done := MsgParse(d, d.msg);
  942. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, {CLRREQINIT}));
  943. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  944. ch := d.Get1(d, SCSIDATL);
  945. IF ch # msg.buf[msg.pos-1] THEN KernelLog.String("Ada7.MsgTransmit, strange"); KernelLog.Ln END;
  946. ELSE
  947. KernelLog.String("Ada7.MsgTransmit, phase mismatch "); KernelLog.Hex(SYSTEM.VAL(LONGINT, t), -2);
  948. KernelLog.Ln
  949. END
  950. END;
  951. IF done THEN
  952. MsgStop(d); SeqUnpause(d)
  953. END
  954. END MsgTransmit;
  955. (* Interrupt Handling *)
  956. PROCEDURE Done(d: Bus; index: LONGINT); (* command terminated / aborted: remove scb and finish *)
  957. BEGIN
  958. (*
  959. BusNameMsg(d, "Done = "); KernelLog.Int(index, 0); KernelLog.Ln;
  960. *)
  961. QUntaggedSet(d, index, 0FFX);
  962. HSFreeScb(d, index);
  963. IF d.sync[index] = InUse THEN
  964. d.Synchronize(index, InUse, Terminated)
  965. ELSE
  966. KernelLog.String("PANIC: done called but not in use!"); KernelLog.Ln
  967. END;
  968. END Done;
  969. PROCEDURE IntCommand(d: Bus);
  970. VAR index: LONGINT;
  971. BEGIN
  972. INC(aIntCmdCount);
  973. IF traceInts IN trace THEN
  974. BusNameMsg(d, "IntCmdCmplt"); KernelLog.Ln;
  975. DumpAllLists(d);
  976. Reg(d, RETURN1, " RETURN = "); Reg(d, SCBPTR, " SCBPTR = "); KernelLog.Ln
  977. END;
  978. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRCMDINT}));
  979. index := ORD(QOutGet(d, d.out));
  980. WHILE index # ORD(0FFX) DO
  981. QOutSet(d, d.out, 0FFX);
  982. d.out := (d.out + 1) MOD 256;
  983. Done(d, index);
  984. index := ORD(QOutGet(d, d.out))
  985. END
  986. END IntCommand;
  987. PROCEDURE IntBrkAdr(d: Bus);
  988. VAR error: SET;
  989. BEGIN
  990. INC(aIntBrkAdrCount);
  991. error := SYSTEM.VAL(SET, d.Get1(d, ERROR));
  992. IF PCIERRSTAT IN error THEN
  993. ToDo("Adaptec7.IntBrkAdr/PCIERRSTAT");
  994. PCIClearInt(d)
  995. END;
  996. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRPARERR, CLRBRKADRINT}));
  997. (*
  998. Sequence is interrupted by a break position. This should not happen (I do not
  999. set any breakpoint).
  1000. Restart the sequencer
  1001. *)
  1002. (*
  1003. ToDo("IntBrkAdr");
  1004. d.Put1(d, SEQCTL, SYSTEM.VAL(CHAR, {FASTMODE, SEQRESET}));
  1005. *)
  1006. SeqUnpause(d)
  1007. END IntBrkAdr;
  1008. PROCEDURE IntSeqHandle(d: Bus; code: LONGINT);
  1009. CONST trace = {traceInts};
  1010. VAR active, ch: CHAR; index: LONGINT;
  1011. BEGIN
  1012. IF FALSE & (traceInts IN trace) THEN
  1013. BusNameMsg(d, "IntSeqHandle"); KernelLog.Ln;
  1014. DumpAllLists(d);
  1015. Reg(d, RETURN1, " RETURN = "); Reg(d, SCBPTR, " SCBPTR = "); Reg(d, SCBTARGETSTATUS, " TargStat = "); KernelLog.Ln
  1016. END;
  1017. INC(aIntSeqCount);
  1018. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSEQINT}));
  1019. active := d.Get1(d, SCBPTR); index := ORD(d.Get1(d, SCBTAG));
  1020. CASE code OF
  1021. | NoMatch:
  1022. IF traceInts IN trace THEN BusNameMsg(d, "IntSeqHandle.NoMatch"); KernelLog.Ln END;
  1023. INC(aIntSeqNoMatch);
  1024. ch := d.Get1(d, SCSISEQ);
  1025. d.Put1(d, SCSISEQ, SYSTEM.VAL(CHAR, SYSTEM.VAL(SET, ch) * {ENSELI, ENRSELI, ENAUTOATNP}))
  1026. | SendReject:
  1027. IF traceInts IN trace THEN BusNameMsg(d, "IntSeqHandle.SendReject"); KernelLog.Ln END;
  1028. INC(aIntSeqSendReject)
  1029. | NoIdent:
  1030. INC(aIntSeqNoIdent);
  1031. ToDo("IntSeqHandle.NoIdent")
  1032. | BadPhase:
  1033. IF traceInts IN trace THEN BusNameMsg(d, "IntSeqHandle.BadPhase"); KernelLog.Ln END;
  1034. INC(aIntSeqBadPhase);
  1035. IF PhaseBusFree = SYSTEM.VAL(SET, d.Get1(d, LASTPHASE)) THEN
  1036. d.Put1(d, SEQCTL, SYSTEM.VAL(CHAR, {FASTMODE, SEQRESET}))
  1037. END
  1038. | ExtendedMsg:
  1039. IF (traceInts IN trace) THEN BusNameMsg(d, "IntSeqHandle.ExtendedMsg"); KernelLog.Ln END;
  1040. INC(aIntSeqExtendedMsg);
  1041. MsgStart(d);
  1042. d.msg.dir := Receiving; d.msg.pos := 0; d.msg.len := 0;
  1043. RETURN (*don't unpause the sequencer!*)
  1044. | RejectMsg:
  1045. IF (traceInts IN trace) THEN BusNameMsg(d, "IntSeqHandle.RejectMsg"); KernelLog.Ln END;
  1046. INC(aIntSeqRejectMsg);
  1047. | BadStatus:
  1048. (* result of the status phase *)
  1049. INC(aIntSeqBadStatus);
  1050. d.Put1(d, RETURN1, 0X);
  1051. d.status[index] := SHORT(ORD(d.Get1(d, SCBTARGETSTATUS)));
  1052. IF traceInts IN trace THEN
  1053. BusNameMsg(d, "IntSeq.BadStatus[");
  1054. KernelLog.Int(index, 0); KernelLog.String("] = "); KernelLog.Int(d.status[index], 0); KernelLog.Ln;
  1055. Reg(d, SSTAT0, "STAT0 = "); Reg(d, SSTAT1, " STAT1 = "); Reg(d, SSTAT2, " STAT2 = "); Reg(d, SSTAT3, " STAT3 = ");
  1056. Reg(d, ERROR, " ERROR = ");
  1057. Reg(d, DSCOMMAND0, " CMD0 = "); Reg(d, DSPCISTATUS, " DSPCISTATUS = "); KernelLog.Ln;
  1058. DumpAllLists(d);
  1059. Reg(d, RETURN1, " RETURN = "); Reg(d, SCBPTR, " SCBPTR = "); Reg(d, SCBTARGETSTATUS, " TargStat = ");
  1060. Reg(d, DFSTATUS, " DFSTATUS = "); Reg(d, DFFTHRSH, " DFFTHRSH = ");
  1061. KernelLog.Ln;
  1062. DumpCurSCB(d);
  1063. END
  1064. | AwaitingMsg: (* ScbMessage was in the scb control tag: now the sequencer asks if we have a message *)
  1065. IF traceInts IN trace THEN BusNameMsg(d, "IntSeqHandle.AwaitingMsg"); KernelLog.Ln END;
  1066. INC(aIntSeqAwaitingMsg);
  1067. MsgStart(d);
  1068. MsgCompose(d, index, d.msg); (*prepare the message in the buffer, send during the scsi interrupt*)
  1069. RETURN (*don't unpause the sequencer!*)
  1070. | DataOverrun:
  1071. INC(aIntSeqDataOverrun);
  1072. IF TRUE & (traceInts IN trace) THEN BusNameMsg(d, "IntSeqHandle.DataOverrun"); KernelLog.Ln END;
  1073. d.status[index] := SCSI.CommandTerminated;
  1074. d.result[index] := SCSI.Error;
  1075. END;
  1076. SeqUnpause(d)
  1077. END IntSeqHandle;
  1078. PROCEDURE IntScsiSeltoHandle(d: Bus);
  1079. VAR t: SET; index: LONGINT;
  1080. BEGIN
  1081. INC(aIntScsiSelto);
  1082. IF d.Get1(d, WAITINGSCBH) # d.Get1(d, SCBPTR) THEN
  1083. INC(aIntScsiSeltoProblem1);
  1084. BusNameMsg(d, "Selto: WAITING # SCBPTR"); KernelLog.Ln
  1085. END;
  1086. d.Put1(d, SCBPTR, d.Get1(d, WAITINGSCBH));
  1087. index := ORD(d.Get1(d, SCBTAG));
  1088. IF (traceInts IN trace) THEN
  1089. BusNameMsg(d, "IntScsiHandle.Selto"); KernelLog.Int(index, 0); KernelLog.Ln;
  1090. DumpCurSCB(d)
  1091. END;
  1092. IF d.sync[index] # InUse THEN
  1093. INC(aIntScsiSeltoProblem2);
  1094. ToDo("IntScsiHandle.Selto/Invalid Index");
  1095. BusNameMsg(d, "IntScsiHandle.Selto"); KernelLog.Int(ORD(d.Get1(d, WAITINGSCBH)), 0);
  1096. KernelLog.Char("/"); KernelLog.Int(index, 0); KernelLog.Ln;
  1097. DumpCurSCB(d);
  1098. DumpAllLists(d);
  1099. ELSE
  1100. d.status[index] := SCSI.CommandTerminated;
  1101. d.result[index] := SCSI.TimeOut;
  1102. EXCL(d.negotiateWidth, index);
  1103. EXCL(d.negotiateSync, index);
  1104. d.Put1(d, SCBCONTROL, 0X);
  1105. d.Put1(d, MSGOUT, SCSI.MsgNoop);
  1106. d.Put1(d, WAITINGSCBH, d.Get1(d, SCBNEXT));
  1107. HSFreeCurrent(d);
  1108. Done(d, index)
  1109. END;
  1110. d.Put1(d, SCSISEQ, 0X);
  1111. t := SYSTEM.VAL(SET, d.Get1(d, SIMODE1));
  1112. d.Put1(d, SIMODE1, SYSTEM.VAL(CHAR, t - {ENREQINIT, ENBUSFREE}));
  1113. EXCL(d.flags, FlagHandlingReqInits);
  1114. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, {CLRSELTIMEO,CLRBUSFREE}));
  1115. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  1116. d.Put1(d, SEQCTL, SYSTEM.VAL(CHAR, {FASTMODE, SEQRESET}));
  1117. SeqUnpause(d)
  1118. END IntScsiSeltoHandle;
  1119. PROCEDURE IntScsiResetHandle(d: Bus);
  1120. PROCEDURE TraverseList(d: Bus; list: LONGINT; debugMsg: ARRAY OF CHAR);
  1121. VAR ptr: CHAR; index: LONGINT;
  1122. BEGIN
  1123. ptr := d.Get1(d, list);
  1124. WHILE ptr # 0FFX DO
  1125. d.Put1(d, SCBPTR, ptr);
  1126. index := ORD(d.Get1(d, SCBTAG));
  1127. KernelLog.String(debugMsg); KernelLog.Hex(ORD(ptr), -2); KernelLog.Char("/");
  1128. KernelLog.Hex(index, -2); KernelLog.Ln;
  1129. ptr := d.Get1(d, SCBNEXT);
  1130. HSFreeCurrent(d);
  1131. d.status[index] := SCSI.NotGood;
  1132. d.result[index] := SCSI.Reset;
  1133. Done(d, index)
  1134. END;
  1135. END TraverseList;
  1136. BEGIN
  1137. (* the bus is reset. Kill outstanding commands and reconfigure bus*)
  1138. IF TRUE & (traceInts IN trace) THEN
  1139. BusNameMsg(d, "IntScsiResetHandle"); KernelLog.Ln;
  1140. DumpAllLists(d);
  1141. END;
  1142. INC(aIntScsiReset);
  1143. BusConfigure(d);
  1144. TraverseList(d, WAITINGSCBH, "waiting list ");
  1145. TraverseList(d, DISCONNECTEDSCBH, "disc list");
  1146. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, {CLRSCSIRSTI}));
  1147. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  1148. SeqUnpause(d)
  1149. END IntScsiResetHandle;
  1150. PROCEDURE IntScsiHandle(d: Bus);
  1151. VAR status: SET;
  1152. BEGIN
  1153. IF traceInts IN trace THEN
  1154. BusNameMsg(d, "IntScsiHandle"); KernelLog.Ln;
  1155. DumpAllLists(d);
  1156. Reg(d, SSTAT1, "STAT1 = "); Reg(d, SIMODE1, " SIMODE1 = ");
  1157. Reg(d, RETURN1, " RETURN = "); Reg(d, SCBPTR, " SCBPTR = "); KernelLog.Ln
  1158. END;
  1159. INC(aIntScsiCount);
  1160. status := SYSTEM.VAL(SET, d.Get1(d, SSTAT1));
  1161. IF SCSIRSTI IN status THEN
  1162. IntScsiResetHandle(d)
  1163. ELSIF SELTO IN status THEN
  1164. IntScsiSeltoHandle(d)
  1165. ELSIF BUSFREE IN status THEN
  1166. INC(aIntScsiBusFree);
  1167. ToDo("IntScsiHandle.BusFree");
  1168. Reg(d, LASTPHASE, "LASTPHASE"); KernelLog.Ln;
  1169. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, {CLRBUSFREE}));
  1170. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  1171. d.Put1(d, SEQCTL, SYSTEM.VAL(CHAR, {FASTMODE, SEQRESET}));
  1172. SeqUnpause(d)
  1173. ELSIF SCSIPERR IN status THEN
  1174. INC(aIntScsiParity);
  1175. IF TRUE & (traceInts IN trace) THEN BusNameMsg(d, "IntScsiHandle.SCSIPERR"); KernelLog.Ln END;
  1176. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, {CLRSCSIPERR}));
  1177. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  1178. SeqUnpause(d)
  1179. ELSIF (REQINIT IN status) & (FlagHandlingReqInits IN d.flags) THEN
  1180. IF traceInts IN trace THEN BusNameMsg(d, "IntScsiHandle.ReqInit"); KernelLog.Ln END;
  1181. INC(aIntScsiReqInit);
  1182. MsgTransmit(d, d.msg);
  1183. ELSIF (1 IN status) & (FlagHandlingReqInits IN d.flags) THEN
  1184. INC(aIntScsiSpecial);
  1185. KernelLog.Char("("); KernelLog.Hex(ORD(d.Get1(d, SCSIBUSL)), -2); KernelLog.Char(")");
  1186. ToDo("IntScsiHandle.Unexpected message");
  1187. ELSE
  1188. INC(aIntScsiUnknown);
  1189. ToDo("IntScsiHandle.Unknown");
  1190. KernelLog.String("SSTAT1 = "); KernelLog.Hex(SYSTEM.VAL(LONGINT, status), -2); KernelLog.Ln;
  1191. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT}));
  1192. SeqUnpause(d)
  1193. END
  1194. END IntScsiHandle;
  1195. PROCEDURE IntClear(d: Bus);
  1196. BEGIN
  1197. d.Put1(d, CLRSINT0, SYSTEM.VAL(CHAR, {CLRSELDO, CLRSELDI, CLRSELINGO}));
  1198. d.Put1(d, CLRSINT1, SYSTEM.VAL(CHAR, CLRSINT1ALL));
  1199. d.Put1(d, CLRINT, SYSTEM.VAL(CHAR, {CLRSCSIINT, CLRSEQINT, CLRBRKADRINT, CLRPARERR}))
  1200. END IntClear;
  1201. PROCEDURE IntInstall(d: Bus);
  1202. BEGIN
  1203. IntClear(d);
  1204. IF interrupt[d.irq] = NIL THEN NEW(interrupt[d.irq], d.irq) END;
  1205. d.next := interrupt[d.irq].root; interrupt[d.irq].root := d;
  1206. BusNameMsg(d, "IntHandler installed, "); KernelLog.Int(d.irq, 0); KernelLog.Ln;
  1207. END IntInstall;
  1208. (* ScbControl - Compote the control byte for dev-th device *)
  1209. PROCEDURE ScbControl(d: Bus; dev: LONGINT): CHAR;
  1210. BEGIN
  1211. IF dev IN d.negotiateWidth THEN
  1212. IF traceSmall IN trace THEN KernelLog.Char("W") END;
  1213. (*EXCL(dev, d.negotiateWidth);*) (*done in message handling! Only one msg per device*)
  1214. RETURN SYSTEM.VAL(CHAR, {HwScbMessage})
  1215. ELSIF dev IN d.negotiateSync THEN
  1216. IF traceSmall IN trace THEN KernelLog.Char("S") END;
  1217. RETURN SYSTEM.VAL(CHAR, {HwScbMessage})
  1218. END;
  1219. RETURN 0X
  1220. END ScbControl;
  1221. (* BusSchedule - Schedule a new command for execution *)
  1222. PROCEDURE BusSchedule(d: Bus; VAR c: SCSI.Command);
  1223. CONST MaxRange = 64;
  1224. VAR index, num, useRange, sgaddr: LONGINT; target: CHAR; range: ARRAY 2, MaxRange+1 OF Machine.Range;
  1225. (*dog: Watchdog;*)
  1226. cmd: ARRAY 2, 16 OF CHAR; cmdBlock: LONGINT;
  1227. BEGIN
  1228. INC(aExecute);
  1229. IF (0 > c.target) OR (c.target >= d.width) OR ~(c.lun IN {0..7}) OR ~(c.chan IN {0,1}) THEN (*Invalid Destination*)
  1230. d.Synchronize(c.target, InUse, Free);
  1231. HALT(200)
  1232. END;
  1233. IF (c.dlen > MaxRange * 4096) THEN (* max pages: change range to increment this limit *)
  1234. d.Synchronize(c.target, InUse, Free);
  1235. HALT(201)
  1236. END;
  1237. (*IF traceDog IN trace THEN NEW(dog, 1000, 5, d, c.target) END;*)
  1238. index := c.target; (* this will be the scb used! *)
  1239. IF traceSmall IN trace THEN
  1240. KernelLog.Char("{"); KernelLog.Hex(ORD(c.cmd[0]), -2); KernelLog.Char("}")
  1241. END;
  1242. IF traceCmds IN trace THEN
  1243. BusNameMsg(d, "schedule ["); KernelLog.Int(index, 0); KernelLog.String("] = ");
  1244. KernelLog.Hex(ORD(c.cmd[0]), -2);
  1245. END;
  1246. d.status[index] := SCSI.Good;
  1247. d.result[index] := SCSI.OK;
  1248. target := MakeTarget(c.target, c.chan, c.lun);
  1249. HSSet(d, index, HScontrol, ScbControl(d, index));
  1250. HSSet(d, index, HStarget, target);
  1251. Machine.TranslateVirtual(ADDRESSOF(c.cmd[0]), c.clen, num, range[0]);
  1252. ASSERT(num # 0, 202);
  1253. IF num > 1 THEN (* The command buffer doesn't fit on one page, create own temp buffer *)
  1254. cmdBlock := -1;
  1255. REPEAT
  1256. INC(cmdBlock);
  1257. Machine.TranslateVirtual(ADDRESSOF(cmd[cmdBlock, 0]), c.clen, num, range[0]);
  1258. UNTIL num = 1;
  1259. SYSTEM.MOVE(ADDRESSOF(c.cmd[0]), ADDRESSOF(cmd[cmdBlock, 0]), c.clen);
  1260. END;
  1261. HSSet4(d, index, HScmdPtr, range[0, 0].adr);
  1262. HSSet(d, index, HScmdLen, CHR(c.clen));
  1263. IF c.dlen = 0 THEN
  1264. IF traceCmds IN trace THEN
  1265. KernelLog.String(" No Data "); KernelLog.Ln
  1266. END;
  1267. HSSet(d, index, HSSGcount, 0X);
  1268. HSSet4(d, index, HSSGptr, 0);
  1269. HSSet4(d, index, HSdataPtr, 0);
  1270. HSSet4(d, index, HSdataCnt, 0)
  1271. ELSE
  1272. ASSERT(c.dataAddr # 0);
  1273. (* the data can be spread across many physical pages, I thus use a scatter-gather list
  1274. for the data. Now the list itself could also be on a page boundary: I declare two adjacent ranges
  1275. and at least one of them will fit on one page. *)
  1276. Machine.TranslateVirtual(ADDRESSOF(range[0, 0]), 16*SIZEOF(Machine.Range), num, range[0]);
  1277. IF num = 1 THEN (* whole range[0] fits in one memory page *)
  1278. useRange := 0;
  1279. ELSE
  1280. Machine.TranslateVirtual(ADDRESSOF(range[1, 0]), 16*SIZEOF(Machine.Range), num, range[0]);
  1281. ASSERT(num = 1, 203);
  1282. useRange := 1;
  1283. IF traceCmds IN trace THEN KernelLog.Char("+")END;
  1284. END;
  1285. sgaddr := range[0, 0].adr;
  1286. Machine.TranslateVirtual(c.dataAddr, c.dlen, num, range[useRange]);
  1287. ASSERT(num # 0, 204);
  1288. IF traceCmds IN trace THEN
  1289. IF num > 1 THEN KernelLog.Char("%") ELSE KernelLog.Char("$") END
  1290. END;
  1291. HSSet(d, index, HSSGcount, CHR(num));
  1292. HSSet4(d, index, HSSGptr, sgaddr+SIZEOF(Machine.Range)); (*pass address to 2nd block*)
  1293. HSSet4(d, index, HSdataPtr, range[useRange, 0].adr);
  1294. HSSet4(d, index, HSdataCnt, range[useRange, 0].size);
  1295. IF traceCmds IN trace THEN
  1296. KernelLog.String(" Data = "); KernelLog.Int(c.dlen, 0);
  1297. KernelLog.Int(useRange, 2);
  1298. KernelLog.Int(num, 2);
  1299. KernelLog.Ln;
  1300. END;
  1301. END;
  1302. QUntaggedSet(d, ORD(target), CHR(index));
  1303. QInSet(d, d.in, CHR(index));
  1304. d.in := (d.in+1) MOD 256;
  1305. IF FeatQueueRegs IN d.features THEN
  1306. d.Put1(d, HNSCBQOFF, CHR(d.in))
  1307. ELSE
  1308. SeqPause(d);
  1309. d.Put1(d, KERNELQINPOS, CHR(d.in));
  1310. SeqUnpause(d)
  1311. END;
  1312. d.Synchronize(c.target, Terminated, Terminated); (* don't free: let bus.Submit copy results *)
  1313. (*IF traceDog IN trace THEN dog.stop := TRUE END;*) (*kill watchdog*)
  1314. IF traceCmds IN trace THEN
  1315. BusNameMsg(d, "schedule ["); KernelLog.Int(index, 0); KernelLog.String("] result = ");
  1316. KernelLog.Int(d.status[index], 0); KernelLog.Char("/"); KernelLog.Int(d.result[index], 0);
  1317. KernelLog.Ln
  1318. END;
  1319. END BusSchedule;
  1320. (* Reset Bus *)
  1321. PROCEDURE BusReset(d: Bus);
  1322. (* if bus reset is called during bus operations, then the timer must be made local to the bus to avoid race conditions *)
  1323. VAR mode1, seq: SET;
  1324. BEGIN
  1325. BusNameMsg(d, "BusR");
  1326. mode1 := SYSTEM.VAL(SET, d.Get1(d, SIMODE1));
  1327. d.Put1(d, SIMODE1, SYSTEM.VAL(CHAR, mode1 - {ENSCSIRST}));
  1328. d.Put1(d, SCSISEQ, SYSTEM.VAL(CHAR, {SCSIRSTO})); (*d.Put1(d, SCSISEQ, d.Get1(d, SCSISEQ) + {SCSIRSTO});*)
  1329. KernelLog.Char("e");
  1330. REPEAT
  1331. timer.Sleep(5);
  1332. seq :=SYSTEM.VAL(SET, d.Get1(d, SCSISEQ))
  1333. UNTIL (SCSIRSTO IN seq);
  1334. KernelLog.Char("s");
  1335. timer.Sleep(10);
  1336. d.Put1(d, SCSISEQ, 0X);
  1337. timer.Sleep(5);
  1338. KernelLog.Char("e");
  1339. IntClear(d);
  1340. d.Put1(d, SIMODE1, SYSTEM.VAL(CHAR, mode1 + {ENSCSIRST}));
  1341. KernelLog.Char("t"); KernelLog.Ln
  1342. END BusReset;
  1343. PROCEDURE BusChipReset(d: Bus);
  1344. VAR t: Kernel.MilliTimer;
  1345. BEGIN
  1346. IF {traceCalls, traceReset} * trace # {} THEN BusNameMsg(d, "ResetChip"); KernelLog.Ln END;
  1347. d.Put1(d, HCNTRL, SYSTEM.VAL(CHAR, {PAUSE, CHIPRST}));
  1348. Kernel.SetTimer(t, 1000); (*1 sec*)
  1349. REPEAT
  1350. UNTIL (CHIPRST IN SYSTEM.VAL(SET, d.Get1(d, HCNTRL))) OR Kernel.Expired(t);
  1351. SeqPause(d); (*pause & clear rst bit*)
  1352. END BusChipReset;
  1353. PROCEDURE BusDetectWidth(d: Bus);
  1354. VAR s: SET;
  1355. BEGIN
  1356. s := SYSTEM.VAL(SET, d.Get1(d, SBLKCTL));
  1357. s := s * {SELWIDE, SELBUSB};
  1358. d.wide := FALSE; d.width := 8; (*default values*)
  1359. IF s = {SELWIDE} THEN
  1360. BusNameMsg(d, "bus is wide"); KernelLog.Ln;
  1361. INCL(d.features, FeatWide);
  1362. d.wide := TRUE; d.width := 16
  1363. ELSIF s = {SELBUSB} THEN
  1364. BusNameMsg(d, "multichannel card"); KernelLog.Ln;
  1365. IF ~(FlagMultiChannel IN d.flags) THEN
  1366. BusNameMsg(d, "WARNING: this card is not declared as multichannel"); KernelLog.Ln
  1367. END;
  1368. INCL(d.features, FeatTwin);
  1369. INCL(d.flags, FlagMultiChannel)
  1370. ELSIF s # {} THEN
  1371. BusNameMsg(d, "PANIC: this card is both wide and multichannel"); KernelLog.Ln;
  1372. HALT(99)
  1373. END
  1374. END BusDetectWidth;
  1375. PROCEDURE BusConfigureChannels(d: Bus); (*special setups for multichannel boards*)
  1376. VAR chip: SHORTINT; set: SET;
  1377. BEGIN
  1378. chip := d.chip;
  1379. IF FlagMultiChannel IN d.flags THEN
  1380. IF chip IN {AIC7870, AIC7880} THEN
  1381. IF d.slotNo = 5 THEN INCL(d.flags, FlagChnlB) (*3940, 3940Ultra*)
  1382. ELSIF d.slotNo = 8 THEN INCL(d.flags, FlagChnlB) (*3985, 3985Ultra*)
  1383. ELSIF d.slotNo = 12 THEN INCL(d.flags, FlagChnlC) (*3985, 3985Ultra*)
  1384. END
  1385. ELSIF chip IN {AIC7895, AIC7896} THEN
  1386. IF d.devNo # 0 THEN INCL(d.flags, FlagChnlB) END;
  1387. END;
  1388. END;
  1389. (*set of DEVCONFIG.SCBSIZE32 for 7895 done in InitPCIBus*)
  1390. set := SYSTEM.VAL(SET, d.Get1(d, DSCOMMAND0));
  1391. IF chip IN {AIC7890, AIC7896} THEN
  1392. d.Put1(d, SCAMCTL, 0X);
  1393. set := set + {CACHETHEN, MPARCKEN, USCBSIZE32, CIOPARCKEN} - {DPARCKEN}
  1394. ELSIF chip IN {AIC7850, AIC7860} THEN
  1395. set := set + {CACHETHEN, MPARCKEN}- {DPARCKEN}
  1396. END;
  1397. d.Put1(d, DSCOMMAND0, SYSTEM.VAL(CHAR, set))
  1398. END BusConfigureChannels;
  1399. PROCEDURE BusConfigure(d: Bus);
  1400. VAR i: LONGINT;
  1401. BEGIN
  1402. (* Init Speed/Width/Scratch RAM *)
  1403. d.scsiId := 7; (* host card id = 7 *)
  1404. i := d.width;
  1405. IF ~(traceNoHandling IN trace) THEN
  1406. IF d.wide THEN
  1407. d.negotiateWidth := {0 .. d.width-1};
  1408. END;
  1409. d.negotiateSync := {0 .. d.width-1}
  1410. END;
  1411. WHILE i > 0 DO
  1412. DEC(i);
  1413. d.Put1(d, TARGSCSIRATE+i, 0X); (* dev[i] = async / 8-bit wide*)
  1414. IF FeatUltra2 IN d.features THEN
  1415. d.Put1(d, TARGOFFSET+i, 0X); (* dev[i] = no offset *)
  1416. END
  1417. END;
  1418. d.Put1(d, ULTRAENB, 0X); (* no ultra *)
  1419. d.Put1(d, ULTRAENB+1, 0X);
  1420. d.Put1(d, DISCDSB, 0X); (* no disconnect *)
  1421. d.Put1(d, DISCDSB+1, 0X);
  1422. d.Put1(d, SCSICONF, SYSTEM.VAL(CHAR, {ENSPCHK, RESETSCSI}));
  1423. d.Put1(d, SCSICONF+1, CHR(d.scsiId))
  1424. END BusConfigure;
  1425. PROCEDURE BusInit(d: Bus);
  1426. VAR sblkctr: SET;
  1427. PROCEDURE InitChannel;
  1428. BEGIN
  1429. IF FeatUltra2 IN d.flags THEN
  1430. d.Put1(d, SCSIIDULTRA2, CHR(d.scsiId))
  1431. ELSE
  1432. d.Put1(d, SCSIID, CHR(d.scsiId))
  1433. END;
  1434. d.Put1(d, SXFRCTL0, SYSTEM.VAL(CHAR, {DFON, SPIOEN}));
  1435. d.Put1(d, SXFRCTL1, SYSTEM.VAL(CHAR, {ENSPCHK, ENSTIMER, ACTNEGEN, STPWEN}));
  1436. d.Put1(d, SIMODE0, 0X);
  1437. d.Put1(d, SIMODE1, SYSTEM.VAL(CHAR,{ENSELTIMO, ENSCSIRST, ENSCSIPERR}));
  1438. d.Put1(d, SCSIRATE, 0X);
  1439. END InitChannel;
  1440. BEGIN
  1441. IF d.chip = AIC7770 THEN d.Put1(d, BCTL, SYSTEM.VAL(CHAR, {ENABLE})) END;
  1442. sblkctr := SYSTEM.VAL(SET, d.Get1(d, SBLKCTL));
  1443. sblkctr := sblkctr - {AUTOFLUSHDIS, DIAGLEDEN};
  1444. d.Put1(d, SBLKCTL, SYSTEM.VAL(CHAR, sblkctr));
  1445. d.Put1(d, MSGOUT, SCSI.MsgNoop);
  1446. d.Put1(d, LASTMSG, SCSI.MsgNoop);
  1447. d.Put1(d, SEQFLAGS, 0X);
  1448. d.Put1(d, TMODECMDADDR, 0X);
  1449. d.Put1(d, TMODECMDADDR+1, 0X);
  1450. d.Put1(d, TMODECMDADDR+2, 0X);
  1451. d.Put1(d, TMODECMDADDR+3, 0X);
  1452. d.Put1(d, TMODECMDADDRNEXT, 0X);
  1453. IF FeatTwin IN d.features THEN
  1454. d.Put1(d, SBLKCTL, SYSTEM.VAL(CHAR, sblkctr+{SELBUSB}));
  1455. InitChannel;
  1456. BusReset(d);
  1457. d.Put1(d, SBLKCTL, SYSTEM.VAL(CHAR, sblkctr))
  1458. END;
  1459. InitChannel;
  1460. IF FeatUltra2 IN d.features THEN
  1461. d.Put1(d, DFFTHRSH, SYSTEM.VAL(CHAR, WRDFFTHRSH75 + RDDFFTHRSH75))
  1462. ELSE
  1463. d.Put1(d, DSPCISTATUS, SYSTEM.VAL(CHAR, DFTHRSH100))
  1464. END;
  1465. BusReset(d);
  1466. d.interruptable := TRUE;
  1467. END BusInit;
  1468. (* Bus detection *)
  1469. PROCEDURE Detect;
  1470. VAR dummy, idx, bus, dev, slot, res, signature, i: LONGINT; host: Bus;
  1471. BEGIN
  1472. IF traceCalls IN trace THEN KernelLog.String("Ada7: Detect"); KernelLog.Ln END;
  1473. IF PCI.Done = PCI.PCIPresent(dummy, dummy, dummy) THEN
  1474. idx := 0;
  1475. WHILE PCI.Done = PCI.FindPCIClassCode(010000H (*scsi card*), idx, bus, dev, slot) DO
  1476. res := PCI.ReadConfigDword(bus, dev, slot, PCI.DevReg, signature); (*signature = VendID / DevID*)
  1477. i := LEN(card)-1;
  1478. REPEAT DEC(i) UNTIL (i < 0) OR (card[i].signature = signature);
  1479. IF i >= 0 THEN
  1480. NEW(host, i, bus, dev, slot);
  1481. BusNameMsg(host, card[i].name); KernelLog.Ln;
  1482. PCIInit(host, bus, dev, slot);
  1483. BusChipReset(host);
  1484. BusDetectWidth(host);
  1485. BusConfigureChannels(host);
  1486. BusConfigure(host);
  1487. HSInit(host);
  1488. QInit(host);
  1489. SeqLoad(host);
  1490. BusInit(host);
  1491. IntInstall(host);
  1492. SeqUnpause(host);
  1493. IF ~(traceNoRegister IN trace) THEN
  1494. timer.Sleep(1000); (*wait for the bus reset to complete*)
  1495. SCSI.RegisterBus(host)
  1496. END
  1497. END;
  1498. INC(idx)
  1499. END
  1500. ELSE
  1501. KernelLog.String("Ada7: No PCI present"); KernelLog.Ln
  1502. END;
  1503. END Detect;
  1504. (* Module Termination Functions *)
  1505. PROCEDURE Cleanup;
  1506. VAR d: Bus; i: LONGINT;
  1507. BEGIN
  1508. IF Modules.shutdown # Modules.None THEN RETURN END;
  1509. FOR i := 0 TO 31 DO
  1510. IF interrupt[i] # NIL THEN
  1511. d := interrupt[i].root;
  1512. WHILE d # NIL DO
  1513. SeqPause(d);
  1514. SCSI.RemoveBus(d);
  1515. ToDo("Ada7: free buffers");
  1516. BusNameMsg(d, "Removed"); KernelLog.Ln;
  1517. d := d.next
  1518. END;
  1519. interrupt[i].Cleanup
  1520. END
  1521. END;
  1522. firstBus := NIL;
  1523. END Cleanup;
  1524. PROCEDURE Init;
  1525. CONST
  1526. ultraFlags = {FlagPageSCB, FlagNewEepromFMT, FlagBiosEnabled};
  1527. ultra2Features = {FeatMoreSRAM, FeatUltra2, FeatCmdChan, FeatQueueRegs, FeatSGPreload};
  1528. PROCEDURE Card(i: LONGINT; sig: HUGEINT; chip: SHORTINT; flags, features: SET; name: ARRAY OF CHAR);
  1529. BEGIN
  1530. card[i].signature := SHORT(sig);
  1531. card[i].chip := chip;
  1532. card[i].flags := flags; card[i].features := features;
  1533. COPY(name, card[i].name)
  1534. END Card;
  1535. PROCEDURE Table(i: LONGINT; period: SHORTINT; rate, u2rate: CHAR; speed: LONGINT);
  1536. BEGIN
  1537. rateTable[i].period := period;
  1538. rateTable[i].rate := rate;
  1539. rateTable[i].u2rate := u2rate;
  1540. rateTable[i].speed := speed
  1541. END Table;
  1542. BEGIN
  1543. IF traceAIC7890 IN trace THEN
  1544. Card(15, 001F9005H, AIC7890, ultraFlags, ultra2Features, "Adaptec AIC-7890/1 Ultra2");
  1545. ELSIF traceAIC7880 IN trace THEN
  1546. Card(9, 80789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled}, {FeatUltra}, "Adaptec AIC-7880 Ultra");
  1547. ELSIF traceAHA2940 IN trace THEN
  1548. Card(10, 81789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled}, {FeatUltra}, "Adaptec AHA-294X Ultra");
  1549. ELSE
  1550. Card(0, 50789004H, AIC7850, {}, {FeatSpioCap}, "Adaptec AIC-7850");
  1551. Card(1, 55789004H, AIC7850, {FlagPageSCB}, {FeatSpioCap}, "Adaptec AIC-7855");
  1552. Card(2, 60789004H, AIC7860, ultraFlags, {FeatUltra, FeatSpioCap}, "Adaptec AIC-7860 Ultra");
  1553. Card(3, 61789004H, AIC7860, ultraFlags, {FeatUltra, FeatSpioCap}, "Adaptec AHA-2940A Ultra");
  1554. Card(4, 70789004H, AIC7870, {FlagPageSCB, FlagBiosEnabled}, {}, "Adaptec AIC-7870");
  1555. Card(5, 71789004H, AIC7870, {FlagPageSCB, FlagBiosEnabled}, {}, "Adaptec AHA-294X");
  1556. Card(6, 72789004H, AIC7870, {FlagPageSCB, FlagBiosEnabled, FlagMultiChannel}, {}, "Adaptec AHA-394X");
  1557. Card(7, 73789004H, AIC7870, {FlagPageSCB, FlagBiosEnabled, FlagMultiChannel}, {}, "Adaptec AHA-398X");
  1558. Card(8, 74789004H, AIC7870, {FlagPageSCB, FlagBiosEnabled}, {}, "Adaptec AHA-2944");
  1559. Card(9, 80789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled}, {FeatUltra}, "Adaptec AIC-7880 Ultra");
  1560. Card(10, 81789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled}, {FeatUltra}, "Adaptec AHA-294X Ultra");
  1561. Card(11, 82789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled, FlagMultiChannel}, {FeatUltra}, "Adaptec AHA-394X Ultra");
  1562. Card(12, 83789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled, FlagMultiChannel}, {FeatUltra}, "Adaptec AHA-398X Ultra");
  1563. Card(13, 84789004H, AIC7880, {FlagPageSCB, FlagBiosEnabled}, {FeatUltra},"Adaptec AHA-2944 Ultra");
  1564. Card(14, 78959004H, AIC7895, ultraFlags + {FlagMultiChannel}, {FeatMoreSRAM, FeatUltra, FeatCmdChan}, "Adaptec AIC-7895 Ultra");
  1565. Card(15, 001F9005H, AIC7890, ultraFlags, ultra2Features, "Adaptec AIC-7890/1 Ultra2");
  1566. Card(16, 00109005H, AIC7890, ultraFlags, ultra2Features, "Adaptec AHA-294X Ultra2");
  1567. Card(17, 005F9005H, AIC7896, ultraFlags + {FlagMultiChannel}, ultra2Features, "Adaptec AIC-7896/7 Ultra2");
  1568. Card(18, 00509005H, AIC7896, ultraFlags + {FlagMultiChannel}, ultra2Features, "Adaptec AHA-394X Ultra2");
  1569. END;
  1570. Table(0, 10, 0FFX, 13X, 400);
  1571. Table(1, 11, 0FFX, 14X, 200);
  1572. Table(2, 12, 0X, 15X, 200);
  1573. Table(3, 15, 10X, 16X, 160);
  1574. Table(4, 18, 20X, 17X, 133);
  1575. Table(5, 25, 00X, 18X, 100);
  1576. Table(6, 31, 10X, 19X, 80);
  1577. Table(7, 37, 20X, 1AX, 67);
  1578. Table(8, 43, 30X, 1BX, 57);
  1579. Table(9, 50, 40X, 1CX, 50);
  1580. Table(10, 56, 50X, 0FFX, 44);
  1581. Table(11, 62, 60X, 0FFX, 40);
  1582. Table(12, 68, 70X, 0FFX, 36);
  1583. Modules.InstallTermHandler(Cleanup)
  1584. END Init;
  1585. (*
  1586. PROCEDURE WriteBusState(d: Bus);
  1587. BEGIN
  1588. BusName(d);
  1589. Reg(d, ERROR, "ERROR = ");
  1590. Reg(d, INTSTAT, " INTSTAT = ");
  1591. Reg(d, HCNTRL, " HCNTRL = ");
  1592. (*
  1593. SeqPause(d);
  1594. Reg(d, SIMODE0, " SIMODE0 = ");
  1595. Reg(d, SIMODE1, " SIMODE1 = ");
  1596. SeqUnpause(d);
  1597. *)
  1598. KernelLog.Ln;
  1599. END WriteBusState;
  1600. PROCEDURE WriteScsiState(d: Bus);
  1601. BEGIN
  1602. SeqPause(d);
  1603. BusNameMsg(d, "Scsi State");
  1604. Reg(d, SSTAT0, " S0=");
  1605. Reg(d, SSTAT1, " S1=");
  1606. Reg(d, SSTAT2, " S2=");
  1607. Reg(d, SIMODE0, " M0=");
  1608. Reg(d, SIMODE1, " M1=");
  1609. KernelLog.Ln;
  1610. SeqUnpause(d);
  1611. END WriteScsiState;
  1612. PROCEDURE WriteBusConfig(d: Bus);
  1613. VAR i: LONGINT; name: ARRAY 8 OF CHAR; Hex: ARRAY 17 OF CHAR;
  1614. BEGIN
  1615. Hex := "0123456789ABCDEF";
  1616. BusNameMsg(d, d.name); KernelLog.Ln;
  1617. Reg(d, ULTRAENB, "Ultra0="); Reg(d, ULTRAENB+1, " Ultra1=");
  1618. Reg(d, DISCDSB, " Disc0="); Reg(d, DISCDSB+1, " Disc1=");
  1619. Reg(d, SCSICONF, " Conf0="); Reg(d, SCSICONF+1, " Conf1="); KernelLog.Ln;
  1620. name := " rateX=";
  1621. FOR i := 0 TO d.width-1 DO
  1622. name[5] := Hex[i];
  1623. Reg(d, TARGSCSIRATE+i, name);
  1624. IF FeatUltra2 IN d.features THEN Reg(d, TARGOFFSET+i, "/") END;
  1625. IF i MOD 4 = 3 THEN KernelLog.Ln END
  1626. END;
  1627. END WriteBusConfig;
  1628. PROCEDURE WriteBusConfig2(d: Bus);
  1629. VAR i: LONGINT; name: ARRAY 8 OF CHAR; Hex: ARRAY 17 OF CHAR;
  1630. PROCEDURE Bit(d: Bus; base, bit: LONGINT; msg: ARRAY OF CHAR);
  1631. VAR set: SET;
  1632. BEGIN
  1633. set := SYSTEM.VAL(SET, d.Get1(d, base + bit DIV 8));
  1634. IF (bit MOD 8) IN set THEN KernelLog.String(msg) END
  1635. END Bit;
  1636. BEGIN
  1637. Hex := "0123456789ABCDEF";
  1638. BusNameMsg(d, d.name); KernelLog.Ln;
  1639. FOR i := 0 TO d.width-1 DO
  1640. KernelLog.String("Device"); KernelLog.Char(Hex[i]);
  1641. Reg(d, TARGSCSIRATE+i, " rate = ");
  1642. IF FeatUltra2 IN d.features THEN Reg(d, TARGOFFSET+i, "/") END;
  1643. Bit(d, ULTRAENB, i, " ultra"); Bit(d, DISCDSB, i, " disc");
  1644. KernelLog.Ln
  1645. END;
  1646. END WriteBusConfig2;
  1647. PROCEDURE WriteConfig*;
  1648. BEGIN
  1649. WriteBusConfig(firstBus);
  1650. WriteBusConfig2(firstBus);
  1651. END WriteConfig;
  1652. PROCEDURE WriteLists*;
  1653. VAR d: Bus;
  1654. BEGIN
  1655. d := firstBus;
  1656. SeqPause(d);
  1657. DumpAllLists(d);
  1658. SeqUnpause(d)
  1659. END WriteLists;
  1660. PROCEDURE FullDump*;
  1661. VAR d: Bus;
  1662. BEGIN
  1663. d := firstBus;
  1664. BusNameMsg(d, "Full Dump!"); KernelLog.Ln;
  1665. KernelLog.Memory(d.base, 100H); KernelLog.Ln
  1666. END FullDump;
  1667. PROCEDURE BusState*;
  1668. BEGIN WriteBusState(firstBus);
  1669. END BusState;
  1670. PROCEDURE ScsiState*;
  1671. BEGIN WriteScsiState(firstBus)
  1672. END ScsiState;
  1673. PROCEDURE Test*;
  1674. VAR d: Bus; res: WORD;
  1675. BEGIN
  1676. d := firstBus;
  1677. KernelLog.String("Adaptec7.Test"); KernelLog.Int(aCount, 0); KernelLog.Ln;
  1678. INC(aCount);
  1679. SCSI.DoTestUnitReady(d, 0, 0, res);
  1680. KernelLog.String("res = "); KernelLog.Int(res, 0); KernelLog.Ln
  1681. END Test;
  1682. PROCEDURE Scan*;
  1683. VAR d: Bus; res: WORD; i: SHORTINT; inq: SCSI.InquiryData;
  1684. BEGIN
  1685. d := firstBus;
  1686. KernelLog.String("Adaptec7.Scan"); KernelLog.Int(aCount, 0); KernelLog.Ln;
  1687. SCSI.DoInquiry(d, SHORT(SHORT(aCount MOD 8)), 0, inq, res);
  1688. INC(aCount);
  1689. END Scan;
  1690. PROCEDURE Stress*;
  1691. VAR d: Bus; i, key, code, res: LONGINT; data: ARRAY 64*1024 OF CHAR;
  1692. dev: Disks.DeviceTable;
  1693. BEGIN
  1694. d := firstBus;
  1695. Disks.GetRegistered(dev);
  1696. i := 0;
  1697. WHILE (i < LEN(dev)) & (dev[i].name # "SCSI0.2") DO INC(i) END;
  1698. KernelLog.String("Adaptec7.Stress / No Data"); KernelLog.Ln;
  1699. FOR i := 0 TO 1000 DO
  1700. SCSI.DoTestUnitReady(d, SHORT(SHORT(i MOD 8)), 0, res)
  1701. END;
  1702. KernelLog.String("Adaptec7.Stress / Small Data"); KernelLog.Ln;
  1703. FOR i := 0 TO 1000 DO
  1704. SCSI.DoSense(d, SHORT(SHORT(i MOD 8)), 0, key, code, res)
  1705. END;
  1706. KernelLog.String("Adaptec7.Stress / Medium Data"); KernelLog.Ln;
  1707. FOR i := 0 TO 1000 DO
  1708. dev[i].Transfer(Disks.Read, i*5, 1, data, 0, res)
  1709. END;
  1710. KernelLog.String("Adaptec7.Stress / Big Data"); KernelLog.Ln;
  1711. FOR i := 0 TO 1000 DO
  1712. dev[i].Transfer(Disks.Read, i*5, 16, data, 0, res)
  1713. END;
  1714. KernelLog.String("Adaptec7.Stress / Done"); KernelLog.Ln;
  1715. END Stress;
  1716. PROCEDURE Speed*;
  1717. VAR dev: Disks.DeviceTable; c, i, run, elap, size, res: LONGINT; data: ARRAY 64*1024 OF CHAR;
  1718. t: Kernel.MilliTimer;
  1719. BEGIN
  1720. Disks.GetRegistered(dev);
  1721. i := 0;
  1722. WHILE (i < LEN(dev)) & (dev[i].name # "SCSI0.2") DO INC(i) END;
  1723. dev[i].GetSize(size, res);
  1724. KernelLog.String("Size is = "); KernelLog.Int(size, 0); KernelLog.Ln;
  1725. FOR run := 0 TO 7 DO
  1726. size := ASH(1, run);
  1727. Kernel.SetTimer(t, 0);
  1728. FOR c := 0 TO 2047 DO
  1729. dev[i].Transfer(Disks.Read, ASH(c, run), size, data, 0, res)
  1730. END;
  1731. elap := Kernel.Elapsed(t);
  1732. KernelLog.String("blkSize = "); KernelLog.Int(512*size, 0);
  1733. KernelLog.String(" elapsed = "); KernelLog.Int(elap, 0);
  1734. KernelLog.String(" rate (KB/s) = "); KernelLog.Int(1000*1024*size DIV elap, 0);
  1735. KernelLog.Ln;
  1736. END
  1737. END Speed;
  1738. PROCEDURE Register*;
  1739. BEGIN
  1740. SCSI.RegisterBus(firstBus)
  1741. END Register;
  1742. *)
  1743. PROCEDURE KillAll*; (*last resort when a command dies... *)
  1744. VAR i, j: LONGINT; d: Bus;
  1745. BEGIN
  1746. FOR i := 0 TO 31 DO
  1747. IF interrupt[i] # NIL THEN
  1748. d := interrupt[i].root;
  1749. WHILE d # NIL DO
  1750. FOR j := 0 TO d.width-1 DO
  1751. d.Synchronize(j, d.sync[j], Terminated)
  1752. END;
  1753. d := d.next
  1754. END
  1755. END
  1756. END
  1757. END KillAll;
  1758. PROCEDURE Install*;
  1759. END Install;
  1760. BEGIN
  1761. KernelLog.String("Adaptec7 - 0.41 / prk"); KernelLog.Ln;
  1762. NEW(timer);
  1763. Init;
  1764. Detect;
  1765. END Adaptec7.
  1766. System.Free Adaptec7 ~ System.Free SCSI ~
  1767. System.State Adaptec7 ~
  1768. Adaptec7.Cleanup
  1769. Adaptec7.Detect
  1770. Adaptec7.FullDump
  1771. Adaptec7.WriteConfig
  1772. Adaptec7.BusState Adaptec7.ScsiState
  1773. Adaptec7.WriteLists
  1774. Adaptec7.Test
  1775. Adaptec7.Speed
  1776. Adaptec7.Scan
  1777. Adaptec7.Register
  1778. !OFSTools.Mount TEST AosFS SCSI0.2#2,R ~
  1779. OFSTools.Mount USER AosFS SCSI0.0#6,R ~
  1780. OFSTools.Unmount ^ ~
  1781. OFSTools.Watch
  1782. System.Directory USER:* ~
  1783. (*
  1784. 15.10.01 0.41 prk wrong constant offset for DFF_THRSH discovered and corrected
  1785. 26.03.01 0.4 prk adapted for the new Machine. Queue and SCB Buffers now anchored in Bus structure
  1786. 20.02.01 0.3 prk own Timer removed, use Kernel.Timer instead, Watchdog commented out
  1787. Failures:
  1788. 200: Invalid Target
  1789. 201: Data Size > 64KB
  1790. 202: TranslateVirtual, num = 0 for the cmd buffer
  1791. 203: TranslateVirtual, num invalid for the range buffer
  1792. 204: TranslateVirtual, num = 0 for the data buffer
  1793. Todos:
  1794. 300: Command spans page boundary [obsolete]
  1795. *)
  1796. (*
  1797. ToDo:
  1798. 2 Disconnection
  1799. 2 Ultra handling in SetSync
  1800. 3 use CHAR consts instead of Bits/SETs -> use memory IO always (port IO is not needed)
  1801. 4 BusCleanup: free buffers
  1802. *)