BIOS.SymbiosASPI.Mod 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE SymbiosASPI; (** non-portable *)
  3. (** AUTHOR "ryser"; PURPOSE "NCR/Symbios SCSI layer"; *)
  4. (* Symbios/NCR SCSI Disk driver for Aos, Q&D port from the Native Oberon version by Peter Ryser *)
  5. IMPORT SYSTEM, Machine, KernelLog, Modules, Objects, PCI, NCRScript;
  6. CONST
  7. intdebug = FALSE; devlistdebug = FALSE; fifodebug = FALSE; scsidebug = FALSE;
  8. ManagerId = "ASPI for Oberon";
  9. (* Exported ASPI Constants *)
  10. SSComp* = 0X; SSFailedInit* = 1X; SSInvalidHa* = 2X; SSNoDevice* = 3X;
  11. SSPending* = 4X; SSAborted* = 5X; SSAbortFail* = 6X; SSErr* = 7X;
  12. SSInvalidSRB* = 8X; SSInvalidPathId* = 9X; SSBufferToBig* = 10X; SSBufferAlign* = 11X;
  13. SSSecurityViolation* = 12X;
  14. FlagsDirIn* = 0; FlagsDirOut* = 1; FlagsEventNotify* = 2;
  15. FlagsPosting* = 3; FlagsEnResCount* = 4;
  16. HaStatOk* = 0X; HaStatTimeout* = 1X; HaStatCommandTimeout* = 2X;
  17. HaStatSelectionTimeout* = 3X; HaStatMessageReject* = 4X; HaStatBusReset* = 5X;
  18. HaStatParityError* = 6X; HaStatReqSenseFailed* = 7X; HaStatDoDu* = 8X;
  19. HaStatBusFree* = 9X; HaStatPhaseErr* = 10X;
  20. StatusGood* = 0X; StatusChkCond* = 2X; StatusBusy* = 8X; StatusResConf* = 18X;
  21. StatMask = {1..5};
  22. DiskNotInt13* = 3X; DiskInt13AndDos* = 2X; DiskInt13* = 1X;
  23. (* NCR Device & Version Id's *)
  24. NCRVendorId = 1000H;
  25. DevIDs = 8;
  26. C810DevId = 1H; C810VerId = 0H; C810AVerId = 10H; C810ALVVerId = 20H;
  27. C810APDevId = 5H;
  28. C815DevId = 4H;
  29. C820DevId = 2H;
  30. C825DevId = 3H; C825VerId = 0H; C825AVerId = 10H;
  31. C860DevId = 6H; C860VerId = 0H; C860LVVerId = 10H;
  32. C875DevId = 0FH;
  33. C896DevId = 0BH;
  34. (* NCR 53C810 Registers *)
  35. SCNTL0 = 00H; SCNTL1 = 01H; SCNTL2 = 02H; SCNTL3 = 03H;
  36. SCID = 04H; SXFER = 05H; SDID = 06H; GPREG = 07H;
  37. SFBR = 08H; SOCL = 09H; SSID = 0AH; SBCL = 0BH;
  38. DSTAT = 0CH; SSTAT0 = 0DH; SSTAT1 = 0EH; SSTAT2 = 0FH;
  39. DSA = 10H; ISTAT = 14H; CTEST0 = 18H; CTEST1 = 19H;
  40. CTEST2 = 1AH; CTEST3 = 1BH; TEMP = 1CH; DFIFO = 20H;
  41. CTEST4 = 21H; CTEST5 = 22H; CTEST6 = 23H; DBC = 24H;
  42. DCMD = 27H; DNAD = 28H; DSP = 2CH; DSPS = 30H;
  43. SCRATCHA = 34H; SCRATCHA0 = 34H; SCRATCHA1 = 35H; SCRATCHA2 = 36H; SCRATCHA3 = 37H;
  44. DMODE = 38H; DIEN = 39H; SBR = 3AH; DCNTL = 3BH;
  45. ADDER = 3CH; SIEN0 = 40H; SIEN1 = 41H;
  46. SIST0 = 42H; SIST1 = 43H; SLPAR = 44H; SWIDE = 45H;
  47. MACNTL = 46H; GPCNTL = 47H; STIME0 = 48H; STIME1 = 49H;
  48. RESPID0 = 4AH; RESPID1 = 4BH; STEST0 = 4CH; STEST1 = 4DH;
  49. STEST2 = 4EH; STEST3 = 4FH; SIDL = 50H; SODL = 54H;
  50. SODL1 = 55H; SBDL = 58H;
  51. SCRATCHB = 5CH; SCRATCHB0 = 5CH; SCRATCHB1 = 5DH; SCRATCHB2 = 5EH; SCRATCHB3 = 5FH;
  52. SCRATCHC = 60H; SCRATCHC0 = 60H; SCRATCHC1 = 61H; SCRATCHC2 = 62H; SCRATCHC3 = 63H;
  53. SCRATCHD = 64H; SCRATCHD0 = 64H; SCRATCHD1 = 65H; SCRATCHD2 = 66H; SCRATCHD3 = 67H;
  54. SCRATCHE = 68H; SCRATCHE0 = 68H; SCRATCHE1 = 69H; SCRATCHE2 = 6AH; SCRATCHE3 = 6BH;
  55. SCRATCHF = 6CH; SCRATCHF0 = 6CH; SCRATCHF1 = 6DH; SCRATCHF2 = 6EH; SCRATCHF3 = 6FH;
  56. SCRATCHG = 70H; SCRATCHG0 = 70H; SCRATCHG1 = 71H; SCRATCHG2 = 72H; SCRATCHG3 = 73H;
  57. SCRATCHH = 74H; SCRATCHH0 = 74H; SCRATCHH1 = 75H; SCRATCHH2 = 76H; SCRATCHH3 = 77H;
  58. SCRATCHI = 78H; SCRATCHI0 = 78H; SCRATCHI1 = 79H; SCRATCHI2 = 7AH; SCRATCHI3 = 7BH;
  59. SCRATCHJ = 7CH; SCRATCHJ0 = 7CH; SCRATCHJ1 = 7DH; SCRATCHJ2 = 7EH; SCRATCHJ3 = 7FH;
  60. DidBadTarget = 4H; DidParity = 6H; DidError = 7H; DidGross = 8H;
  61. DidPhaseMismatch = 100H; DidSCSIInterrupt = 101H; DidDMAInterrupt = 102H;
  62. DisconnectIdent = 0H; (* use 40H for disconnection enabled *)
  63. MaxTarget = 7; (* target id's from 0 to 6 allowed; id 7 for NCR-Chip *)
  64. MaxLun = 8; (* lun id's from 0 to 7 allowed *)
  65. (* Constants for testing and measuring *)
  66. read* = 0; write* = 1; seek* = 2;
  67. MaxRanges* = 33; (* 33 ranges enough for max transfer of 128K *)
  68. PageSize = 4096;
  69. TYPE
  70. Time* = HUGEINT;
  71. (* Data structure for measuring *)
  72. Measure* = POINTER TO MeasureDesc;
  73. MeasureDesc* = RECORD
  74. started*: LONGINT;
  75. IssueTime*, DeadLineTime*: Time;
  76. EnterTime*, LeaveTime*, ReenterTime*: Time
  77. END;
  78. (* ASPI Command Structures *)
  79. SRB* = POINTER TO SRBDesc;
  80. SRBDesc* = RECORD
  81. Status*, HaId*: CHAR;
  82. Flags*: SET
  83. END;
  84. HaInquirySRB* = POINTER TO HaInquirySRBDesc;
  85. HaInquirySRBDesc* = RECORD (SRBDesc)
  86. HaCount*, HaScsiId*: CHAR;
  87. HaManagerId*, HaIdentifier*, HaUnique*: ARRAY 16 OF CHAR
  88. END;
  89. GetDevTypeSRB* = POINTER TO GetDevTypeSRBDesc;
  90. GetDevTypeSRBDesc* = RECORD (SRBDesc)
  91. Target*, Lun*, DevType*: CHAR
  92. END;
  93. ExecIOCmdSRB* = POINTER TO ExecIOCmdSRBDesc;
  94. ExecIOCmdSRBDesc* = RECORD (SRBDesc)
  95. Target*, Lun*, SenseLen*, CDBLen*, HaStat*, TargStat*: CHAR;
  96. BufLen*, BufPointer*: LONGINT; (* virtual address *)
  97. CDB*: ARRAY 16 OF CHAR;
  98. SenseArea*: ARRAY 257 OF CHAR;
  99. next*: ExecIOCmdSRB;
  100. (* fields for measuring *)
  101. meas*: Measure; (* # NIL => measure. pentium only. *)
  102. END;
  103. AbortCmdSRB* = POINTER TO AbortCmdSRBDesc;
  104. AbortCmdSRBDesc* = RECORD (SRBDesc)
  105. ToAbort: ExecIOCmdSRB
  106. END;
  107. ResetDevCmdSRB* = POINTER TO ResetDevCmdSRBDesc;
  108. ResetDevCmdSRBDesc* = RECORD (SRBDesc)
  109. Target*, Lun*, HaStat*, TargStat*: CHAR
  110. END;
  111. GetDiskInfoCmdSRB* = POINTER TO GetDiskInfoCmdSRBDesc;
  112. GetDiskInfoCmdSRBDesc* = RECORD (SRBDesc)
  113. Target*, Lun*, DriveFlags*, Int13HDriveInfo*, Heads*, Sectors*: CHAR
  114. END;
  115. (* Lun structure *)
  116. LunDesc = RECORD
  117. DevType: CHAR
  118. END;
  119. (* Target structure *)
  120. TargetPtr = POINTER TO TargetDescc;
  121. TargetDescc = RECORD
  122. first, last: ExecIOCmdSRB;
  123. id: LONGINT; (* target id *)
  124. luns: LONGINT; (* available LUN's for this target *)
  125. lun: ARRAY MaxLun OF LunDesc;
  126. bufTab: NCRScript.BufferTable
  127. END;
  128. (* Host Adapter Structure *)
  129. DevicePtr = OBJECT
  130. VAR
  131. devId, vendId, cmd, status, revId, classCode, CLS, latTimer, hdrType,
  132. baseAdr0, baseAdr1, baseAdr2, baseAdr3, baseAdr4, baseAdr5,
  133. CIS, subId, subVenId, baseAdrROM, intL, intP, minGnt, maxLat: LONGINT;
  134. devIdx, busNr, devNr, fktNr: LONGINT;
  135. ioport, memadr: LONGINT;
  136. memaccess: BOOLEAN;
  137. (* SCSI target support *)
  138. targetReady: SET;
  139. dnad, dbc, dfifo, sstat0, sstat1, sstat2, ctest2, msgInPtr, identLen, targetNum: LONGINT;
  140. msgIn, msgOut: CHAR;
  141. target: ARRAY MaxTarget OF TargetPtr;
  142. curTarget: TargetPtr;
  143. msgInBuf: ARRAY 64 OF CHAR;
  144. identify: ARRAY 7 OF CHAR;
  145. PROCEDURE HandleInterrupt;
  146. BEGIN
  147. InterruptHandler(SELF)
  148. END HandleInterrupt;
  149. END DevicePtr;
  150. VAR
  151. IDs: ARRAY DevIDs OF LONGINT;
  152. DevNum, Initres: LONGINT;
  153. Devs: ARRAY DevIDs OF DevicePtr;
  154. disconnected: LONGINT;
  155. PROCEDURE GetTime(VAR time: Time);
  156. BEGIN time := Machine.GetTimer ();
  157. END GetTime;
  158. PROCEDURE LogInt(i: LONGINT);
  159. BEGIN
  160. KernelLog.Int(i, 1)
  161. END LogInt;
  162. PROCEDURE LogHex(i: LONGINT);
  163. BEGIN
  164. KernelLog.Hex(i, 8)
  165. END LogHex;
  166. PROCEDURE CheckAlign(target: TargetPtr): BOOLEAN;
  167. VAR adr: ADDRESS;
  168. BEGIN
  169. adr := ADDRESSOF(target.bufTab[0].count);
  170. RETURN (adr MOD 4 = 0) & (adr DIV PageSize = (adr+SIZEOF(NCRScript.BufferTable)-1) DIV PageSize)
  171. END CheckAlign;
  172. PROCEDURE Wait(t: LONGINT);
  173. BEGIN
  174. t := t*100000;
  175. WHILE t > 0 DO DEC(t) END
  176. END Wait;
  177. PROCEDURE PhysAdr(adr: ADDRESS; size: SIZE): Machine.Address32;
  178. VAR n, i: LONGINT; size0: ADDRESS; phys: ARRAY MaxRanges OF Machine.Range;
  179. BEGIN
  180. ASSERT(size <= PageSize, 100);
  181. Machine.TranslateVirtual(adr, size, n, phys);
  182. i := 0; size0 := 0;
  183. WHILE (i < n) & (phys[0].adr + size0 = phys[i].adr) DO (* find contiguous memory range *)
  184. INC(size0, phys[i].size); INC(i)
  185. END;
  186. ASSERT(i = n, 101); (* range contiguous *)
  187. RETURN Machine.Ensure32BitAddress (phys[0].adr);
  188. END PhysAdr;
  189. PROCEDURE SetTableEntry(VAR t: NCRScript.TableEntry; adr: ADDRESS; count: LONGINT);
  190. BEGIN
  191. t.count := count;
  192. t.address := PhysAdr(adr, count)
  193. END SetTableEntry;
  194. PROCEDURE Read8(Dev: DevicePtr; adr: LONGINT; VAR val: CHAR);
  195. BEGIN
  196. IF Dev.memaccess THEN (* Memory mapped access *)
  197. adr := adr + Dev.memadr;
  198. SYSTEM.GET(adr, val)
  199. ELSE (* IO based access *)
  200. (* adr := adr + Dev.ioport; *)
  201. Machine.Portin8(adr + Dev.ioport, val)
  202. END
  203. END Read8;
  204. PROCEDURE Read32(Dev: DevicePtr; adr: LONGINT; VAR val: LONGINT);
  205. BEGIN
  206. IF Dev.memaccess THEN (* Memory mapped access *)
  207. (* adr := adr + Dev.memadr; *)
  208. SYSTEM.GET(adr + Dev.memadr, val)
  209. ELSE (* IO based access *)
  210. (* adr := adr + Dev.ioport; *)
  211. Machine.Portin32(adr + Dev.ioport, val)
  212. END
  213. END Read32;
  214. PROCEDURE Write8(Dev: DevicePtr; adr: LONGINT; val: CHAR);
  215. BEGIN
  216. IF Dev.memaccess THEN (* Memory mapped access *)
  217. adr := adr + Dev.memadr;
  218. SYSTEM.PUT(adr, val)
  219. ELSE (* IO based access *)
  220. (* adr := adr + Dev.ioport; *)
  221. Machine.Portout8(adr + Dev.ioport, val)
  222. END
  223. END Write8;
  224. PROCEDURE Write32(Dev: DevicePtr; adr, val: LONGINT);
  225. BEGIN
  226. IF Dev.memaccess THEN (* Memory mapped access *)
  227. adr := adr + Dev.memadr;
  228. SYSTEM.PUT(adr, val)
  229. ELSE (* IO based access *)
  230. (* adr := adr + Dev.ioport; *)
  231. Machine.Portout32(adr + Dev.ioport, val)
  232. END
  233. END Write32;
  234. PROCEDURE InitIDs;
  235. BEGIN
  236. IDs[0] := C810DevId; IDs[1] := C810APDevId; IDs[2] := C815DevId; IDs[3] := C820DevId;
  237. IDs[4] := C825DevId; IDs[5] := C860DevId; IDs[6] := C875DevId; IDs[7] := C896DevId
  238. END InitIDs;
  239. PROCEDURE PCIFindSYMDevice(Dev: DevicePtr): LONGINT;
  240. VAR res, res1, regVal: LONGINT;
  241. BEGIN
  242. res := PCI.FindPCIDevice(Dev.devId, NCRVendorId, Dev.devIdx, Dev.busNr, Dev.devNr, Dev.fktNr);
  243. (*
  244. KernelLog.String("PCIFindSYMDevice"); KernelLog.Ln;
  245. KernelLog.String(" Device: "); LogInt(Dev.devId); KernelLog.Ln;
  246. KernelLog.String(" Vendor: "); LogInt(NCRVendorId); KernelLog.Ln;
  247. KernelLog.String(" Index: "); LogInt(Dev.devIdx); KernelLog.Ln;
  248. KernelLog.String(" res: "); LogInt(res); KernelLog.Ln;
  249. *)
  250. IF res = PCI.Done THEN
  251. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.CmdReg, regVal); ASSERT(res1 = PCI.Done, 100);
  252. Dev.cmd := regVal MOD 10000H; Dev.status := regVal DIV 10000H;
  253. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.RevIdReg, regVal); ASSERT(res1 = PCI.Done, 101);
  254. Dev.revId := regVal MOD 100H; Dev.classCode := regVal DIV 100H;
  255. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.CLSReg, regVal); ASSERT(res1 = PCI.Done, 102);
  256. Dev.CLS := regVal MOD 100H; Dev.latTimer := (regVal DIV 100H) MOD 100H;
  257. Dev.hdrType := (regVal DIV 10000H) MOD 100H;
  258. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.Adr0Reg, Dev.baseAdr0); ASSERT(res1 = PCI.Done, 110);
  259. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.Adr1Reg, Dev.baseAdr1); ASSERT(res1 = PCI.Done, 111);
  260. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.Adr2Reg, Dev.baseAdr2); ASSERT(res1 = PCI.Done, 112);
  261. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.Adr3Reg, Dev.baseAdr3); ASSERT(res1 = PCI.Done, 113);
  262. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.Adr4Reg, Dev.baseAdr4); ASSERT(res1 = PCI.Done, 114);
  263. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.Adr5Reg, Dev.baseAdr5); ASSERT(res1 = PCI.Done, 115);
  264. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.CISReg, Dev.CIS); ASSERT(res1 = PCI.Done, 103);
  265. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.SubvReg, regVal); ASSERT(res1 = PCI.Done, 104);
  266. Dev.subVenId := regVal MOD 10000H; Dev.subId := regVal DIV 10000H;
  267. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.ROMReg, Dev.baseAdrROM); ASSERT(res1 = PCI.Done, 105);
  268. res1 := PCI.ReadConfigDword(Dev.busNr, Dev.devNr, Dev.fktNr, PCI.IntlReg, regVal); ASSERT(res1 = PCI.Done, 106);
  269. Dev.intL := regVal MOD 100H; Dev.intP := (regVal DIV 100H) MOD 100H;
  270. Dev.minGnt := (regVal DIV 10000H) MOD 100H; Dev.maxLat := (regVal DIV 1000000H);
  271. Dev.ioport := (Dev.baseAdr0 - 1) MOD 10000H; Dev.memadr := Dev.baseAdr1;
  272. Dev.memaccess := FALSE;
  273. KernelLog.String("intL="); KernelLog.Int(Dev.intL, 1);
  274. Objects.InstallHandler(Dev.HandleInterrupt, Machine.IRQ0+Dev.intL); (* fixme: check if valid *)
  275. (* initialize SCSI options for this host adapter *)
  276. Dev.msgInPtr := 0; Dev.dbc := 0; Dev.dnad := 0;
  277. Dev.dfifo := 0; Dev.sstat0 := 0; Dev.sstat1 := 0; Dev.sstat2 := 0; Dev.ctest2 := 0;
  278. Dev.targetReady := {}; Dev.targetNum := 0;
  279. Dev.identify[0] := 0X; Dev.identify[1] := 1X; Dev.identify[2] := 3X;
  280. Dev.identify[3] := 1X; Dev.identify[4] := 19X; Dev.identify[5] := 8X;
  281. END;
  282. RETURN res
  283. END PCIFindSYMDevice;
  284. PROCEDURE BuildDeviceList(VAR Devices: ARRAY OF DevicePtr; MaxDev: LONGINT): LONGINT;
  285. VAR i, NumDev: LONGINT;
  286. BEGIN
  287. i := 0; NumDev := 0; NEW(Devices[0]);
  288. WHILE i < DevIDs DO
  289. Devices[NumDev].devId := IDs[i];
  290. Devices[NumDev].devIdx := 0;
  291. WHILE (i < DevIDs) & (PCIFindSYMDevice(Devices[NumDev]) # PCI.DeviceNotFound) DO
  292. INC(NumDev); NEW(Devices[NumDev]);
  293. Devices[NumDev].devIdx := Devices[NumDev-1].devIdx+1;
  294. Devices[NumDev].devId := Devices[NumDev-1].devId
  295. END;
  296. INC(i)
  297. END;
  298. RETURN NumDev
  299. END BuildDeviceList;
  300. PROCEDURE ShowDeviceList(VAR Devices: ARRAY OF DevicePtr; MaxDev: LONGINT);
  301. VAR i: LONGINT; d: DevicePtr;
  302. BEGIN
  303. i := 0;
  304. WHILE i < MaxDev DO
  305. d := Devices[i];
  306. KernelLog.String("Device "); LogInt(i); KernelLog.Ln;
  307. KernelLog.String(" busNr: "); LogInt(d.busNr); KernelLog.Ln;
  308. KernelLog.String(" devNr: "); LogInt(d.devNr); KernelLog.Ln;
  309. KernelLog.String(" fktNr: "); LogInt(d.fktNr); KernelLog.Ln;
  310. KernelLog.String(" devIdx: "); LogInt(d.devIdx); KernelLog.Ln;
  311. KernelLog.String(" vendId: "); LogInt(d.vendId); KernelLog.Ln;
  312. KernelLog.String(" devId: "); LogInt(d.devId); KernelLog.Ln;
  313. KernelLog.String(" cmd: "); LogInt(d.cmd); KernelLog.Ln;
  314. KernelLog.String(" status: "); LogInt(d.status); KernelLog.Ln;
  315. KernelLog.String(" revId: "); LogInt(d.revId); KernelLog.Ln;
  316. KernelLog.String(" classCode: "); LogInt(d.classCode); KernelLog.Ln;
  317. KernelLog.String(" CLS: "); LogInt(d.CLS); KernelLog.Ln;
  318. KernelLog.String(" latTimer: "); LogInt(d.latTimer); KernelLog.Ln;
  319. KernelLog.String(" hdrType: "); LogInt(d.hdrType); KernelLog.Ln;
  320. KernelLog.String(" baseAdr 0: "); LogInt(d.baseAdr0); KernelLog.Ln;
  321. KernelLog.String(" baseAdr 1: "); LogInt(d.baseAdr1); KernelLog.Ln;
  322. KernelLog.String(" baseAdr 2: "); LogInt(d.baseAdr2); KernelLog.Ln;
  323. KernelLog.String(" baseAdr 3: "); LogInt(d.baseAdr3); KernelLog.Ln;
  324. KernelLog.String(" baseAdr 4: "); LogInt(d.baseAdr4); KernelLog.Ln;
  325. KernelLog.String(" baseAdr 5: "); LogInt(d.baseAdr5); KernelLog.Ln;
  326. KernelLog.String(" CIS: "); LogInt(d.CIS); KernelLog.Ln;
  327. KernelLog.String(" subId: "); LogInt(d.subId); KernelLog.Ln;
  328. KernelLog.String(" subVenId: "); LogInt(d.subVenId); KernelLog.Ln;
  329. KernelLog.String(" baseAdrROM: "); LogInt(d.baseAdrROM); KernelLog.Ln;
  330. KernelLog.String(" Int Line: "); LogInt(d.intL); KernelLog.Ln;
  331. KernelLog.String(" Int Pin: "); LogInt(d.intP); KernelLog.Ln;
  332. KernelLog.String(" Min Gnt: "); LogInt(d.minGnt); KernelLog.Ln;
  333. KernelLog.String(" Max Lat: "); LogInt(d.maxLat); KernelLog.Ln;
  334. INC(i)
  335. END;
  336. END ShowDeviceList;
  337. PROCEDURE dsaEntryOut(Dev: DevicePtr; i: LONGINT);
  338. VAR adr, nr: LONGINT; val: CHAR;
  339. BEGIN
  340. nr := Dev.curTarget.bufTab[i].count;
  341. adr := Dev.curTarget.bufTab[i].address;
  342. IF nr > 20 THEN nr := 20 END;
  343. WHILE nr > 0 DO
  344. SYSTEM.GET(adr, val);
  345. LogInt(ORD(val)); KernelLog.Char(" ");
  346. INC(adr); DEC(nr)
  347. END;
  348. KernelLog.Ln
  349. END dsaEntryOut;
  350. PROCEDURE dsaStrucOut(Dev: DevicePtr);
  351. BEGIN
  352. KernelLog.String("DSA Structure"); KernelLog.Ln;
  353. KernelLog.String(" dsaSelect: "); LogHex(Dev.curTarget.bufTab[NCRScript.dsaSelect].count); KernelLog.Ln;
  354. KernelLog.String(" dsaMsgOut: "); dsaEntryOut(Dev, NCRScript.dsaMsgOut);
  355. KernelLog.String(" dsaCmd: "); dsaEntryOut(Dev, NCRScript.dsaCmd);
  356. KernelLog.String(" dsaStatus: "); dsaEntryOut(Dev, NCRScript.dsaStatus);
  357. KernelLog.String(" dsaData("); LogInt(Dev.curTarget.bufTab[NCRScript.dsaData].count); KernelLog.String(", ");
  358. LogInt(Dev.curTarget.bufTab[NCRScript.dsaData].address); KernelLog.String("): "); dsaEntryOut(Dev, NCRScript.dsaData);
  359. KernelLog.String(" dsaMsgIn: "); dsaEntryOut(Dev, NCRScript.dsaMsgIn)
  360. END dsaStrucOut;
  361. PROCEDURE InitSiop(Dev: DevicePtr);
  362. VAR val: CHAR;
  363. BEGIN
  364. (* Reset SCSI Bus *)
  365. (*
  366. Read8(dev, SCNTL1, val); val := CHR((ORD(val) DIV 16)*16 + ORD(val) MOD 4 + 8);
  367. Write8(dev, SCNTL1, val); Wait(10); val := CHR((ORD(val) DIV 16)*16 + ORD(val) MOD 4);
  368. Write8(dev, SCNTL1, val); Wait(10);
  369. *)
  370. (* Reset & Init 53C810 *)
  371. Write8(Dev, ISTAT, 40X); Write8(Dev, ISTAT, 0X); (* Reset *)
  372. Read8(Dev, DMODE, val);
  373. val := CHR((ORD(val) DIV 2)*2); Write8(Dev, DMODE, val); (* enable automatic script start *)
  374. Write8(Dev, SCID, 47X); (* SCSI Id 7; respond to Selection (* & Reselection +40X *)*)
  375. Write8(Dev, RESPID0, 80X); (* set response mask for id 7 *)
  376. Write8(Dev, STIME0, 0FX);
  377. Write8(Dev, DIEN, 7DX); (* enable DMA interrupts *)
  378. Write8(Dev, SIEN0, 8FX); (* enable SCSI interrupts *)
  379. Write8(Dev, SIEN1, 5X); (* ?? *)
  380. Write8(Dev, STEST3, 80X); (* enable active negotiation *)
  381. Read8(Dev, STEST1, val);
  382. KernelLog.Enter; KernelLog.String("STEST1: "); LogInt(ORD(val)); KernelLog.Exit;
  383. Write32(Dev, DSP, NCRScript.ScriptsAddress + NCRScript.EntWaitReselect)
  384. END InitSiop;
  385. PROCEDURE ReadIntRegs(Dev: DevicePtr; istats: SET; VAR dstats, sist0s, sist1s: SET);
  386. VAR ch: CHAR;
  387. BEGIN
  388. IF 0 IN istats THEN
  389. Read8(Dev, DSTAT, ch);
  390. dstats := SYSTEM.VAL(SET, ch);
  391. IF intdebug THEN KernelLog.String("DSTAT: "); LogHex(ORD(ch)); KernelLog.Ln END;
  392. END;
  393. IF 1 IN istats THEN
  394. (* Wait(2); *) Read8(Dev, SIST0, ch);
  395. sist0s := SYSTEM.VAL(SET, ch);
  396. IF intdebug THEN KernelLog.String("SIST0: "); LogHex(ORD(ch)); KernelLog.Ln; END;
  397. (* Wait(2); *) Read8(Dev, SIST1, ch);
  398. sist1s := SYSTEM.VAL(SET, ch);
  399. IF intdebug THEN KernelLog.String("SIST1: "); LogHex(ORD(ch)); KernelLog.Ln END;
  400. END
  401. END ReadIntRegs;
  402. PROCEDURE SetSynchParameters(Dev: DevicePtr; tp, offs: CHAR);
  403. VAR xferp: LONGINT;
  404. BEGIN
  405. ASSERT(tp >= 19X, 100);
  406. ASSERT(offs <= 8X, 101);
  407. xferp := ((16*ORD(tp) - 1) DIV 100) - 3; (* transfer period *)
  408. xferp := xferp*16+ORD(offs);
  409. Dev.curTarget.bufTab[NCRScript.dsaSelect].count :=
  410. (Dev.curTarget.bufTab[NCRScript.dsaSelect].count DIV 10000H)*10000H+xferp*100H;
  411. Write8(Dev, SXFER, CHR(xferp));
  412. IF intdebug THEN KernelLog.String("SXFER: "); LogInt(xferp); KernelLog.Ln END;
  413. END SetSynchParameters;
  414. (* --- Interrupt Handler --- *)
  415. PROCEDURE StartNextCommand(Dev: DevicePtr; VAR nextdsp: LONGINT);
  416. VAR targ: LONGINT; srb: ExecIOCmdSRB; val: CHAR; vals: SET;
  417. BEGIN
  418. Read8(Dev, ISTAT, val);
  419. vals := SYSTEM.VAL(SET, val); EXCL(vals, 5); val := SYSTEM.VAL(CHAR, vals);
  420. Write8(Dev, ISTAT, val); (* ClearSIGP *)
  421. IF Dev.targetReady # {} THEN
  422. REPEAT
  423. Dev.targetNum := (Dev.targetNum+1) MOD MaxTarget;
  424. UNTIL Dev.targetNum IN Dev.targetReady;
  425. targ := Dev.targetNum; Dev.curTarget := Dev.target[targ];
  426. EXCL(Dev.targetReady, targ);
  427. srb := Dev.curTarget.first;
  428. srb.TargStat := 0FFX;
  429. Dev.identify[0] := CHR(DisconnectIdent + 80H + ORD(srb.Lun));
  430. (*
  431. Dev.curTarget.bufTab[NCRScript.dsaMsgOut].count := Dev.identLen;
  432. Dev.curTarget.bufTab[NCRScript.dsaMsgOut].address := ADDRESSOF(Dev.identify[0]);
  433. Dev.curTarget.bufTab[NCRScript.dsaCmd].count := ORD(srb.CDBLen);
  434. Dev.curTarget.bufTab[NCRScript.dsaCmd].address := ADDRESSOF(srb.CDB[0]);
  435. Dev.curTarget.bufTab[NCRScript.dsaData].count := srb.BufLen;
  436. Dev.curTarget.bufTab[NCRScript.dsaData].address := srb.BufPointer;
  437. Dev.curTarget.bufTab[NCRScript.dsaStatus].count := 1;
  438. Dev.curTarget.bufTab[NCRScript.dsaStatus].address := ADDRESSOF(srb.TargStat);
  439. Dev.curTarget.bufTab[NCRScript.dsaMsgIn].count := 1;
  440. Dev.curTarget.bufTab[NCRScript.dsaMsgIn].address := ADDRESSOF(Dev.msgIn);
  441. Write32(Dev, DSA, ADDRESSOF(Dev.curTarget.bufTab[0].count));
  442. *)
  443. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaMsgOut], ADDRESSOF(Dev.identify[0]), Dev.identLen);
  444. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaCmd], ADDRESSOF(srb.CDB[0]), ORD(srb.CDBLen));
  445. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaData], srb.BufPointer, srb.BufLen);
  446. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaStatus], ADDRESSOF(srb.TargStat), 1);
  447. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaMsgIn], ADDRESSOF(Dev.msgIn), 1);
  448. Write32(Dev, DSA, PhysAdr(ADDRESSOF(Dev.curTarget.bufTab[0].count), SIZEOF(NCRScript.BufferTable)));
  449. Dev.dnad := srb.BufPointer; Dev.dbc := srb.BufLen; (* if save pointer messages arrives before sending/receiving data *)
  450. nextdsp := NCRScript.EntSelection;
  451. IF srb.meas # NIL THEN GetTime(srb.meas.EnterTime); INC(srb.meas.started) END;
  452. ELSE nextdsp := NCRScript.EntWaitReselect
  453. END
  454. END StartNextCommand;
  455. PROCEDURE FinishCommand(Dev: DevicePtr; VAR nextdsp: LONGINT);
  456. VAR srb: ExecIOCmdSRB;
  457. BEGIN
  458. IF Dev.curTarget # NIL THEN
  459. srb := Dev.curTarget.first; Dev.curTarget.first := srb.next;
  460. IF srb.next = NIL THEN Dev.curTarget.last := NIL
  461. ELSE INCL(Dev.targetReady, Dev.curTarget.id)
  462. END;
  463. IF srb.TargStat = StatusGood THEN srb.Status := SSComp
  464. ELSE srb.Status := SSErr
  465. END;
  466. StartNextCommand(Dev, nextdsp)
  467. END
  468. END FinishCommand;
  469. PROCEDURE ReloadDSA(Dev: DevicePtr);
  470. VAR val, xferp: CHAR; targ: LONGINT;
  471. BEGIN
  472. Read8(Dev, SFBR, val);
  473. targ := ORD(val); ASSERT(targ DIV 80H = 1, 100);
  474. targ := targ MOD 80H; ASSERT(targ < MaxTarget, 101);
  475. Dev.curTarget := Dev.target[targ];
  476. xferp := CHR(Dev.curTarget.bufTab[NCRScript.dsaSelect].count DIV 100H);
  477. Write8(Dev, SXFER, xferp);
  478. (*
  479. Write32(Dev, DSA, ADDRESSOF(Dev.curTarget.bufTab[0].count))
  480. *)
  481. Write32(Dev, DSA, PhysAdr(ADDRESSOF(Dev.curTarget.bufTab[0].count), SIZEOF(NCRScript.BufferTable)))
  482. END ReloadDSA;
  483. PROCEDURE abnormFinished(Dev: DevicePtr; code: LONGINT; VAR nextdsp: LONGINT);
  484. BEGIN
  485. IF TRUE (* intdebug *) THEN
  486. KernelLog.Enter;
  487. KernelLog.String("Abnormal Finished: ");
  488. LogInt(Dev.devIdx); KernelLog.Char(" ");
  489. IF Dev.curTarget # NIL THEN
  490. LogInt(Dev.curTarget.id); KernelLog.Char(" ");
  491. LogInt(ORD(Dev.curTarget.first.Lun)); KernelLog.Char(" ");
  492. ELSE
  493. KernelLog.String("curTarget=NIL ")
  494. END;
  495. LogHex(code);
  496. KernelLog.Exit
  497. END;
  498. FinishCommand(Dev, nextdsp);
  499. END abnormFinished;
  500. PROCEDURE PhaseMismatch(Dev: DevicePtr; istats, dstats, sist0s, sist1s: SET; VAR nextdsp: LONGINT);
  501. VAR sbcl: CHAR; sbcls, sstat0s: SET; val: CHAR; dfifo: LONGINT;
  502. BEGIN
  503. Read8(Dev, SBCL, sbcl);
  504. sbcls := SYSTEM.VAL(SET, sbcl);
  505. Read32(Dev, DBC, Dev.dbc); Dev.dbc := Dev.dbc MOD 1000000H;
  506. Read32(Dev, DNAD, Dev.dnad);
  507. Read8(Dev, DFIFO, val); Dev.dfifo := ORD(val);
  508. Read8(Dev, SSTAT0, val); Dev.sstat0 := ORD(val); sstat0s := SYSTEM.VAL(SET, Dev.sstat0);
  509. Read8(Dev, SSTAT1, val); Dev.sstat1 := ORD(val);
  510. Read8(Dev, SSTAT2, val); Dev.sstat2 := ORD(val);
  511. Read8(Dev, CTEST2, val); Dev.ctest2 := ORD(val);
  512. dfifo := Dev.dfifo - (Dev.dbc MOD 100H) MOD 80H;
  513. IF 5 IN sstat0s THEN INC(dfifo) END;
  514. IF 6 IN sstat0s THEN INC(dfifo) END;
  515. IF intdebug OR fifodebug THEN
  516. KernelLog.String("SBCL: "); LogHex(ORD(sbcl)); KernelLog.Ln;
  517. KernelLog.String("DBC: "); LogInt(Dev.dbc); KernelLog.Ln;
  518. KernelLog.String("DNAD: "); LogInt(Dev.dnad); KernelLog.Ln;
  519. KernelLog.String("DFIFO: "); LogInt(Dev.dfifo); KernelLog.Ln;
  520. KernelLog.String("SSTAT0: "); LogHex(Dev.sstat0); KernelLog.Ln;
  521. KernelLog.String("SSTAT1: "); LogHex(Dev.sstat1); KernelLog.Ln;
  522. KernelLog.String("SSTAT2: "); LogHex(Dev.sstat2); KernelLog.Ln;
  523. KernelLog.String("CTEST2: "); LogHex(Dev.ctest2); KernelLog.Ln;
  524. KernelLog.String("Bytes in FIFO: "); LogHex(dfifo); KernelLog.Ln;
  525. IF (Dev.dfifo - (Dev.dbc MOD 100H)) MOD 80H # 0 THEN KernelLog.String("!!! DMA FIFO not empty !!!"); KernelLog.Ln END;
  526. END;
  527. INC(Dev.dbc, dfifo); DEC(Dev.dnad, dfifo);
  528. IF {0,1,2}*sbcls = {0,1} THEN (* status phase *)
  529. IF intdebug OR fifodebug THEN dsaStrucOut(Dev); KernelLog.String("Jumping to command complete"); KernelLog.Ln; END;
  530. nextdsp := NCRScript.EntResumeStatusPhase
  531. ELSIF {0,1,2}*sbcls = {0,1,2} THEN (* msg in *)
  532. IF intdebug OR fifodebug THEN dsaStrucOut(Dev); KernelLog.String("Jumping to message in"); KernelLog.Ln END;
  533. nextdsp := NCRScript.EntResumeMsgInPhase
  534. ELSE abnormFinished(Dev, DidPhaseMismatch, nextdsp) (* interrupt not handled; abort command *)
  535. END
  536. END PhaseMismatch;
  537. PROCEDURE SCSIInterrupt(Dev: DevicePtr; istats, dstats, sist0s, sist1s: SET; VAR nextdsp: LONGINT);
  538. VAR fatal: BOOLEAN; ch: CHAR;
  539. BEGIN
  540. fatal := FALSE;
  541. IF 2 IN sist1s THEN (* selection/reselection timeout *)
  542. fatal := TRUE;
  543. abnormFinished(Dev, DidBadTarget, nextdsp)
  544. END;
  545. IF 2 IN sist0s THEN (* unexpected Disconnect *)
  546. fatal := TRUE;
  547. abnormFinished(Dev, DidError, nextdsp);
  548. END;
  549. IF 1 IN sist0s THEN (* Parity Error *)
  550. fatal := TRUE;
  551. abnormFinished(Dev, DidParity, nextdsp);
  552. (* nextdsp := NCRScripts.EntInitiatorAbort *)
  553. END;
  554. IF 3 IN sist0s THEN (* Gross Error *)
  555. fatal := TRUE;
  556. abnormFinished(Dev, DidGross, nextdsp);
  557. (* nextdsp := NCRScripts.EntInitiatorAbort *)
  558. END;
  559. IF 7 IN sist0s THEN (* Phase mismatch *)
  560. fatal := TRUE;
  561. PhaseMismatch(Dev, istats, dstats, sist0s, sist1s, nextdsp)
  562. END;
  563. IF fatal THEN (* empty DMA & SCSI FIFO *)
  564. IF ~(0 IN istats) THEN ReadIntRegs(Dev, {0}, dstats, sist0s, sist1s) END; (* force reading of dstat reg *)
  565. IF ~(7 IN dstats) THEN
  566. IF intdebug OR fifodebug THEN KernelLog.String("DMA FIFO not empty"); KernelLog.Ln; END;
  567. Write8(Dev, CTEST3, 4X);
  568. REPEAT Read8(Dev, CTEST3, ch) UNTIL ~(2 IN SYSTEM.VAL(SET, ch))
  569. END;
  570. Write8(Dev, STEST3, 2X);
  571. REPEAT Read8(Dev, STEST3, ch) UNTIL ~(1 IN SYSTEM.VAL(SET, ch))
  572. ELSE
  573. abnormFinished(Dev, DidSCSIInterrupt, nextdsp) (* did not handle interrupt condition *)
  574. END;
  575. END SCSIInterrupt;
  576. PROCEDURE DMAInterrupt(Dev: DevicePtr; istats, dstats, sist0s, sist1s: SET; VAR nextdsp: LONGINT);
  577. VAR i, interrupt: LONGINT; ch: CHAR;
  578. BEGIN
  579. IF 2 IN dstats THEN (* Scripts interrupt instruction *)
  580. Read32(Dev, DSPS, interrupt);
  581. IF intdebug THEN
  582. KernelLog.String("Scripts interrupt: "); LogHex(interrupt); KernelLog.Ln;
  583. IF interrupt DIV 10H # 3 THEN
  584. KernelLog.String("DBC: "); LogInt(Dev.dbc); KernelLog.Ln;
  585. KernelLog.String("DNAD: "); LogInt(Dev.dnad); KernelLog.Ln;
  586. dsaStrucOut(Dev)
  587. END
  588. END;
  589. CASE interrupt OF
  590. NCRScript.AIntErrUnexpectedPhase:
  591. IF intdebug THEN KernelLog.String("!!! Fatal Error !!!"); KernelLog.Ln END;
  592. Wait(2); Read8(Dev, SBCL, ch);
  593. IF intdebug THEN KernelLog.String("SBCL: "); LogHex(ORD(ch)); KernelLog.Ln; END
  594. | NCRScript.AIntErrSelectFailed: (* reselection during selection *)
  595. INCL(Dev.targetReady, Dev.curTarget.id);
  596. nextdsp := NCRScript.EntWaitReselect;
  597. IF intdebug THEN KernelLog.String("Reselection during selection: next interrupt must be AIntReselected"); KernelLog.Ln END
  598. | NCRScript.AIntHandleMsgIn:
  599. Dev.msgInBuf[Dev.msgInPtr] := Dev.msgIn; INC(Dev.msgInPtr);
  600. IF intdebug THEN
  601. KernelLog.String("msgInBuf: ");
  602. FOR i := 0 TO Dev.msgInPtr-1 DO LogInt(ORD(Dev.msgInBuf[i])); KernelLog.Char(" ") END;
  603. KernelLog.Ln
  604. END;
  605. CASE Dev.msgInPtr OF
  606. 1:
  607. CASE Dev.msgInBuf[0] OF
  608. 0X: (* command complete message *)
  609. Dev.msgInPtr := 0;
  610. nextdsp := NCRScript.EntCommandComplete
  611. | 1X: (* extended message *)
  612. nextdsp := NCRScript.EntCompleteMsgInPhase
  613. | 2X: (* save data pointer *)
  614. ASSERT(Dev.dnad = Dev.curTarget.bufTab[NCRScript.dsaData].count -
  615. Dev.dbc + Dev.curTarget.bufTab[NCRScript.dsaData].address, 100);
  616. Dev.msgInPtr := 0;
  617. (*
  618. Dev.curTarget.bufTab[NCRScript.dsaData].count := Dev.dbc;
  619. Dev.curTarget.bufTab[NCRScript.dsaData].address := Dev.dnad;
  620. *)
  621. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaData], Dev.dnad, Dev.dbc);
  622. nextdsp := NCRScript.EntCompleteMsgInPhase
  623. | 3X: (* restore data pointer *)
  624. Dev.msgInPtr := 0;
  625. nextdsp := NCRScript.EntCompleteMsgInPhase
  626. | 4X: (* disconnect *)
  627. INC(disconnected);
  628. Dev.msgInPtr := 0;
  629. nextdsp := NCRScript.EntDisconnected
  630. | 7X: (* message reject *) (* hopefully only for synch transfer req *)
  631. Dev.msgInPtr := 0;
  632. Read8(Dev, SOCL, ch); ch := CHR((ORD(ch) DIV 16) * 16 + ORD(ch) MOD 8); (* Reset atn bit -> finish msg out phase *)
  633. Write8(Dev, SOCL, ch);
  634. nextdsp := NCRScript.EntCompleteMsgInPhase
  635. | 80X..87X: (* Identify *)
  636. Dev.msgInPtr := 0;
  637. nextdsp := NCRScript.EntCompleteMsgInPhase
  638. ELSE (* other message: reject *)
  639. Dev.msgInPtr := 0; Dev.msgOut := 7X;
  640. (*
  641. Dev.curTarget.bufTab[NCRScript.dsaMsgOut].address := ADDRESSOF(Dev.msgOut);
  642. Dev.curTarget.bufTab[NCRScript.dsaMsgOut].count := 1;
  643. *)
  644. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaMsgOut], ADDRESSOF(Dev.msgOut), 1);
  645. nextdsp := NCRScript.EntRejectMsg
  646. END
  647. | 2, 3:
  648. CASE Dev.msgInBuf[1] OF
  649. 2X, 3X: (* 2 byte extended message *)
  650. nextdsp := NCRScript.EntCompleteMsgInPhase
  651. ELSE (* some msg bytes more *)
  652. Dev.msgInPtr := 0; Dev.msgOut := 7X;
  653. (*
  654. Dev.curTarget.bufTab[NCRScript.dsaMsgOut].address := ADDRESSOF(Dev.msgOut);
  655. Dev.curTarget.bufTab[NCRScript.dsaMsgOut].count := 1;
  656. *)
  657. SetTableEntry(Dev.curTarget.bufTab[NCRScript.dsaMsgOut], ADDRESSOF(Dev.msgOut), 1);
  658. nextdsp := NCRScript.EntRejectMsg
  659. END
  660. | 4:
  661. IF Dev.msgInBuf[1] = 2X THEN Dev.msgInPtr := 0 END;
  662. nextdsp := NCRScript.EntCompleteMsgInPhase
  663. | 5:
  664. ASSERT(Dev.msgInBuf[1] = 3X, 101);
  665. Dev.msgInPtr := 0;
  666. nextdsp := NCRScript.EntCompleteMsgInPhase;
  667. IF Dev.msgInBuf[2] = 1X THEN SetSynchParameters(Dev, Dev.msgInBuf[3], Dev.msgInBuf[4]) END
  668. END
  669. | NCRScript.AIntNormDisc: StartNextCommand(Dev, nextdsp)
  670. | NCRScript.AIntGotSIGP: StartNextCommand(Dev, nextdsp)
  671. | NCRScript.AIntReselected: ReloadDSA(Dev); nextdsp := NCRScript.EntResumeMsgInPhase
  672. | NCRScript.AIntMsgOutPhase: nextdsp := NCRScript.EntResumeMsgOutPhase
  673. | NCRScript.AIntCmdPhase: nextdsp := NCRScript.EntResumeCmdPhase
  674. | NCRScript.AIntDataInPhase: nextdsp := NCRScript.EntResumeDataInPhase
  675. | NCRScript.AIntDataOutPhase: nextdsp := NCRScript.EntResumeDataOutPhase
  676. | NCRScript.AIntStatusPhase: nextdsp := NCRScript.EntResumeStatusPhase
  677. | NCRScript.AIntMsgInPhase: nextdsp := NCRScript.EntResumeMsgInPhase
  678. | NCRScript.AIntNormCommandComplete: FinishCommand(Dev, nextdsp) (* start of next command included *)
  679. ELSE HALT(102)
  680. END
  681. ELSE
  682. abnormFinished(Dev, DidDMAInterrupt, nextdsp) (* did not handle interrupt condition *)
  683. END;
  684. END DMAInterrupt;
  685. PROCEDURE InterruptHandler(Dev: DevicePtr);
  686. VAR istat: CHAR; nextdsp, dspval, nr: LONGINT; istats, dstats, sist0s, sist1s: SET; cursrb: ExecIOCmdSRB;
  687. BEGIN {EXCLUSIVE}
  688. IF intdebug THEN KernelLog.String("Entering InterruptHandler"); KernelLog.Ln; END;
  689. nr := 0;
  690. (*IF intdebug THEN KernelLog.String("Device nr: "); LogInt(dev); KernelLog.Ln; END;*)
  691. REPEAT
  692. nextdsp := -1;
  693. Read8(Dev, ISTAT, istat);
  694. istats := SYSTEM.VAL(SET, istat);
  695. IF intdebug THEN LogInt(nr); KernelLog.String(" ISTAT: "); LogHex(ORD(istat)); KernelLog.Ln; END;
  696. IF 2 IN istats THEN (* INTFLY *)
  697. IF intdebug THEN
  698. KernelLog.String("Scripts INTFLY"); KernelLog.Ln;
  699. END;
  700. cursrb := Dev.curTarget.first;
  701. IF (cursrb # NIL) & (cursrb.meas # NIL) THEN GetTime(cursrb.meas.ReenterTime) END;
  702. Write8(Dev, ISTAT, istat);
  703. END;
  704. IF (0 IN istats) OR (1 IN istats) THEN
  705. ReadIntRegs(Dev, istats, dstats, sist0s, sist1s);
  706. Read32(Dev, DSP, dspval);
  707. IF intdebug THEN LogInt(nr); KernelLog.String(" DSP: "); LogInt(dspval); KernelLog.Ln END;
  708. IF 1 IN istats THEN SCSIInterrupt(Dev, istats, dstats, sist0s, sist1s, nextdsp) END;
  709. IF 0 IN istats THEN DMAInterrupt(Dev, istats, dstats, sist0s, sist1s, nextdsp) END;
  710. IF nextdsp # -1 THEN
  711. IF intdebug THEN KernelLog.String("Restarting SCSI Proc"); KernelLog.Ln; END;
  712. Write32(Dev, DSP, NCRScript.ScriptsAddress + nextdsp)
  713. END
  714. END;
  715. INC(nr)
  716. UNTIL istats*{0..2} = {};
  717. IF intdebug THEN KernelLog.String("Leaving InterruptHandler"); KernelLog.Ln; END
  718. END InterruptHandler;
  719. (* --- End of Interrupt Handler --- *)
  720. PROCEDURE HaInquiry(srb: HaInquirySRB);
  721. VAR i: LONGINT;
  722. BEGIN
  723. srb.HaCount := CHR(DevNum);
  724. srb.HaManagerId := ManagerId;
  725. IF (srb.HaId = 0X) & (DevNum = 0) THEN srb.Status := SSComp
  726. ELSIF srb.HaId < CHR(DevNum) THEN
  727. srb.HaScsiId := 7X; (* is fix, at least for the moment (I assume, that will be a LONG moment) *)
  728. srb.Status := SSComp;
  729. CASE Devs[ORD(srb.HaId)].devId OF
  730. C810DevId: srb.HaIdentifier := "53C810"
  731. | C810APDevId: srb.HaIdentifier := "53C810AP"
  732. | C815DevId: srb.HaIdentifier := "53C815"
  733. | C820DevId: srb.HaIdentifier := "53C820"
  734. | C825DevId: srb.HaIdentifier := "53C825"
  735. | C860DevId: srb.HaIdentifier := "53C860"
  736. | C875DevId: srb.HaIdentifier := "53C875"
  737. | C896DevId: srb.HaIdentifier := "53C896"
  738. END;
  739. FOR i := 8 TO 15 DO srb.HaUnique[i] := 0X END;
  740. srb.HaUnique[0] := 3X; srb.HaUnique[1] := 0X; srb.HaUnique[2] := 0X; srb.HaUnique[3] := 8X;
  741. srb.HaUnique[4] := 0FFX; srb.HaUnique[5] := 0FFX; srb.HaUnique[6] := 0FFX; srb.HaUnique[7] := 0X;
  742. ELSE srb.Status := SSInvalidHa
  743. END;
  744. END HaInquiry;
  745. PROCEDURE GetDevType(srb: GetDevTypeSRB);
  746. VAR dev, targ, lun: LONGINT;
  747. BEGIN
  748. dev := ORD(srb.HaId); targ := ORD(srb.Target); lun := ORD(srb.Lun);
  749. IF dev >= DevNum THEN srb.Status := SSInvalidHa
  750. ELSIF (targ >= MaxTarget) OR (lun >= MaxLun) THEN srb.Status := SSNoDevice
  751. ELSE
  752. IF lun >= Devs[dev].target[targ].luns THEN
  753. srb.Status := SSNoDevice;
  754. srb.DevType := 1FX
  755. ELSE
  756. srb.Status := SSComp;
  757. srb.DevType := Devs[dev].target[targ].lun[lun].DevType
  758. END
  759. END
  760. END GetDevType;
  761. PROCEDURE Insert(srb: ExecIOCmdSRB; dev, targ, lun: LONGINT);
  762. VAR val: CHAR; vals: SET;
  763. BEGIN
  764. Machine.Cli();
  765. srb.Status := SSPending; srb.TargStat := 0FFX; srb.next := NIL;
  766. IF Devs[dev].target[targ].first = NIL THEN
  767. Devs[dev].target[targ].first := srb; Devs[dev].target[targ].last := srb;
  768. INCL(Devs[dev].targetReady, targ);
  769. Read8(Devs[dev], ISTAT, val);
  770. vals := SYSTEM.VAL(SET, val); INCL(vals, 5); val := SYSTEM.VAL(CHAR, vals);
  771. Write8(Devs[dev], ISTAT, val) (* SetSIGP *)
  772. ELSE
  773. Devs[dev].target[targ].last.next := srb; Devs[dev].target[targ].last := srb
  774. END;
  775. Machine.Sti()
  776. END Insert;
  777. PROCEDURE ExecIOCmd(srb: ExecIOCmdSRB);
  778. VAR dev, targ, lun: LONGINT;
  779. BEGIN
  780. dev := ORD(srb.HaId); targ := ORD(srb.Target); lun := ORD(srb.Lun);
  781. IF (dev >= DevNum) OR (targ >= MaxTarget) OR (lun >= MaxLun) THEN srb.Status := SSInvalidSRB
  782. ELSE Insert(srb, dev, targ, lun)
  783. END
  784. END ExecIOCmd;
  785. PROCEDURE AbortCmd(srb: AbortCmdSRB);
  786. BEGIN
  787. KernelLog.String("not implemented"); KernelLog.Ln;
  788. srb.Status := SSAbortFail
  789. END AbortCmd;
  790. PROCEDURE ResetDevCmd(srb: ResetDevCmdSRB);
  791. BEGIN
  792. KernelLog.String("not implemented"); KernelLog.Ln;
  793. srb.Status := SSErr
  794. END ResetDevCmd;
  795. PROCEDURE GetDiskInfo(srb: GetDiskInfoCmdSRB);
  796. BEGIN
  797. KernelLog.String("not implemented"); KernelLog.Ln;
  798. srb.Status := SSErr
  799. END GetDiskInfo;
  800. PROCEDURE SendASPICommand*(srb: SRB; wait: BOOLEAN);
  801. BEGIN {EXCLUSIVE}
  802. IF srb IS HaInquirySRB THEN HaInquiry(srb(HaInquirySRB))
  803. ELSIF srb IS GetDevTypeSRB THEN GetDevType(srb(GetDevTypeSRB))
  804. ELSIF srb IS ExecIOCmdSRB THEN ExecIOCmd(srb(ExecIOCmdSRB))
  805. ELSIF srb IS AbortCmdSRB THEN AbortCmd(srb(AbortCmdSRB))
  806. ELSIF srb IS ResetDevCmdSRB THEN ResetDevCmd(srb(ResetDevCmdSRB))
  807. ELSIF srb IS GetDiskInfoCmdSRB THEN GetDiskInfo(srb(GetDiskInfoCmdSRB))
  808. ELSE HALT(100) (* unknown ASPI-Function, shouldn't happen *)
  809. END;
  810. IF wait THEN
  811. AWAIT(srb.Status # SSPending)
  812. END
  813. END SendASPICommand;
  814. PROCEDURE InitTargets(Dev: DevicePtr);
  815. VAR
  816. targ, lun: LONGINT;
  817. srb: ExecIOCmdSRB;
  818. data: ARRAY 0FFH OF CHAR;
  819. BEGIN
  820. NEW(srb);
  821. srb.HaId := CHR(Dev.devIdx); srb.Flags := {};
  822. srb.BufLen := LEN(data); srb.BufPointer := Machine.Ensure32BitAddress (ADDRESSOF(data)); srb.SenseLen := 0X;
  823. srb.CDBLen := 6X;
  824. srb.CDB[0] := 12X; srb.CDB[1] := 0X; srb.CDB[2] := 0X; srb.CDB[3] := 0X; srb.CDB[4] := 0FFX; srb.CDB[5] := 0X;
  825. srb.meas := NIL;
  826. targ := 0;
  827. WHILE targ < MaxTarget DO
  828. REPEAT
  829. NEW(Dev.target[targ]); Dev.curTarget := Dev.target[targ]
  830. UNTIL CheckAlign(Dev.curTarget); (* fixme *)
  831. Dev.target[targ].first := NIL; Dev.target[targ].last := NIL; Dev.target[targ].luns := 0;
  832. Dev.target[targ].bufTab[NCRScript.dsaSelect].count := 11H*1000000H + targ*10000H;
  833. Dev.target[targ].id := targ;
  834. Dev.identLen := 6; (* try synchronous negotiation on lun 0 *)
  835. srb.Target := CHR(targ);
  836. lun := 0;
  837. WHILE (lun < MaxLun) & (lun = Dev.target[targ].luns) DO
  838. srb.Lun := CHR(lun);
  839. Dev.identify[0] := CHR(DisconnectIdent + 80H + lun);
  840. srb.CDB[1] := CHR(LSH(lun, 5));
  841. SendASPICommand(srb, TRUE);
  842. IF (srb.Status = SSComp) & (data[0] # 7FX) THEN
  843. Dev.target[targ].lun[Dev.target[targ].luns].DevType := data[0];
  844. KernelLog.Enter;
  845. LogInt(Dev.devIdx); KernelLog.Char(" "); LogInt(targ); KernelLog.Char(" ");
  846. LogInt(lun); KernelLog.Char(" "); LogInt(ORD(data[0]));
  847. IF scsidebug THEN
  848. KernelLog.Memory(ADDRESSOF(data), 144)
  849. END;
  850. KernelLog.Exit;
  851. INC(Dev.target[targ].luns)
  852. END;
  853. Dev.identLen := 1;
  854. INC(lun)
  855. END;
  856. INC(targ)
  857. END
  858. END InitTargets;
  859. PROCEDURE InitASPI;
  860. VAR res: CHAR; res1, version, lastPCIbus, hwMech, dev: LONGINT;
  861. BEGIN
  862. res := SSFailedInit; DevNum := 0;
  863. res1 := PCI.PCIPresent(version, lastPCIbus, hwMech);
  864. IF res1 = PCI.Done THEN
  865. DevNum := BuildDeviceList(Devs, DevIDs);
  866. IF devlistdebug THEN ShowDeviceList(Devs, DevNum) END;
  867. res := SSComp;
  868. dev := 0;
  869. WHILE dev < DevNum DO
  870. InitSiop(Devs[dev]);
  871. InitTargets(Devs[dev]);
  872. INC(dev)
  873. END
  874. END;
  875. Initres := ORD(res)
  876. END InitASPI;
  877. PROCEDURE GetASPISupportInfo*(): LONGINT;
  878. BEGIN
  879. RETURN LSH(Initres, 8) + DevNum
  880. END GetASPISupportInfo;
  881. PROCEDURE Stop;
  882. VAR i: LONGINT;
  883. BEGIN
  884. IF Modules.shutdown = Modules.None THEN
  885. FOR i := 0 TO DevNum-1 DO
  886. Objects.RemoveHandler(Devs[i].HandleInterrupt, Machine.IRQ0+Devs[i].intL)
  887. END;
  888. DevNum := 0
  889. END
  890. END Stop;
  891. BEGIN
  892. Modules.InstallTermHandler(Stop);
  893. NCRScript.ScriptsAddress := PhysAdr(NCRScript.ScriptsAddress, LEN(NCRScript.Script)*4);
  894. InitIDs;
  895. disconnected := 0;
  896. InitASPI
  897. END SymbiosASPI.