Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

525 lines
14 KiB

4 years ago
  1. //-----------------------------------------------------------------------
  2. //
  3. // File: N53C400.C
  4. //
  5. // N53C400 access file.
  6. //
  7. // These routines are independent of the card the N53C400 is on. The
  8. // cardxxxx.h file must define the following routines:
  9. //
  10. // N53C400PortPut
  11. // N53C400PortGet
  12. // N53C400PortSet
  13. // N53C400PortClear
  14. // N53C400PortTest
  15. // N53C400PortGetBuffer
  16. // N53C400PortPutBuffer
  17. //
  18. // These routines could be defined by some other include file instead of
  19. // cardxxxx.h, as the pc9010 defines the needed n5380xxxxxxxx routines.
  20. //
  21. //
  22. // Revisions:
  23. // 09-01-92 KJB First.
  24. // 02-19-93 KJB Added support for data underrun read & write.
  25. // transfer only 2 128 bytes fifos at a time
  26. // might want to change this back if dataunderrun ok.
  27. // 03-01-93 KJB Added N53C400CheckAdapter to check specifically for
  28. // N53C400 and perform a chip reset on the 53C400 before
  29. // checking.
  30. // 03-02-93 KJB/JAP Phase checking for data phase moved to scsifnc.c.
  31. // Wait for last byte sent in write bytes.
  32. // 03-02-93 JAP Cleaned comments.
  33. // 03-02-93 KJB Fixed Names-- baseIoAddress back.
  34. // 03-03-93 JAP Cleaned comments again, reverting func declarations.
  35. // 03-05-93 JAP Changed N53C400DisableInterrupt() and N53C400EnableInterrupt
  36. // to mirror what is done in ASM code.
  37. // 03-07-93 KJB WriteBytesFast now returns the correct error code
  38. // when error occurs during slow write.
  39. // 03-11-93 JAP Changed retcode equates to reflect new names.
  40. // 03-11-93 KJB Changes code to reflect new 5380 names.
  41. // 03-17-93 JAP Removed unreference lablellings.
  42. // 03-25-93 JAP Fixed up typedef and prototype inconsistencies
  43. // 04-05-93 KJB DEBUG_LEVEL used by DebugPrint for NT.
  44. // 05-14-93 KJB Added CardParseCommandString for card specific
  45. // standard string parsing across platforms.
  46. // Changed CardCheckAdapter to accept an
  47. // Initialization info from command line, ie
  48. // force bi-directional ports, etc.
  49. // All functions that used to take an PBASE_REGISTER
  50. // parameter now take PWORKSPACE. CardCheckAdapter
  51. // takes the both a PINIT and a PWORKSPACE parameters.
  52. // 05-17-93 KJB Added ErrorLogging capabilities (used by WINNT).
  53. //
  54. //-----------------------------------------------------------------------
  55. #include CARDTXXX_H
  56. //-----------------------------------------------------------------------
  57. //
  58. // Local prototypes
  59. //
  60. //-----------------------------------------------------------------------
  61. USHORT N53C400Wait5380Access (PADAPTER_INFO g, ULONG usec);
  62. USHORT N53C400WaitHostBufferReady (PADAPTER_INFO g, ULONG usec);
  63. //-----------------------------------------------------------------------
  64. //
  65. // Routines
  66. //
  67. //-----------------------------------------------------------------------
  68. //-----------------------------------------------------------------------
  69. //
  70. // N53C400CheckAdapter
  71. //
  72. // This routine checks for the presense of a 53C400.
  73. //
  74. //-----------------------------------------------------------------------
  75. BOOLEAN N53C400CheckAdapter (PADAPTER_INFO g)
  76. {
  77. USHORT rval;
  78. // Reset the N53C400 chip.
  79. // WARNING -- Could be destructive to other cards @ this port
  80. N53C400PortPut (g, N53C400_CONTROL, CR_RST);
  81. // check by testing the 5380
  82. rval = N5380CheckAdapter (g);
  83. return (BOOLEAN) rval;
  84. }
  85. //-----------------------------------------------------------------------
  86. //
  87. // N53C400WaitHostBufferReady
  88. //
  89. // This routine waits until the 53c400's 128 byte queue is ready with
  90. // or for data.
  91. //
  92. //-----------------------------------------------------------------------
  93. USHORT N53C400WaitHostBufferReady (PADAPTER_INFO g, ULONG usec)
  94. {
  95. ULONG i;
  96. USHORT rval;
  97. // see if the flag comes back quickly
  98. for (i = 0; i < TIMEOUT_QUICK; i++) {
  99. if (!N53C400PortTest (g, N53C400_STATUS, SR_HBFR_RDY)) {
  100. return 0;
  101. }
  102. }
  103. // ok, it did not come back quickly, we will yield to other processes
  104. for (i = 0; i < usec; i++) {
  105. if (!N53C400PortTest (g, N53C400_STATUS, SR_HBFR_RDY)) {
  106. return 0;
  107. }
  108. // if we suddenly have access, then phase mismatch and over/underrun
  109. if (N53C400PortTest (g, N53C400_STATUS, SR_ACCESS)) {
  110. rval = RET_STATUS_DATA_OVERRUN;
  111. DebugPrint((DEBUG_LEVEL,"Error - 0 - ScsiWaitHostBufferReady\n"));
  112. goto error;
  113. }
  114. ScsiPortStallExecution(1);
  115. }
  116. // reset the n53c400 in the case of a timeout
  117. N53C400PortPut (g, N53C400_CONTROL, CR_RST);
  118. TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 30);
  119. rval = RET_STATUS_TIMEOUT;
  120. error:
  121. DebugPrint((DEBUG_LEVEL,"Error - 1 - ScsiWaitHostBufferReady\n"));
  122. // return with an error, non-zero indicates timeout
  123. return rval;
  124. }
  125. //-----------------------------------------------------------------------
  126. //
  127. // N53C400Wait5380Access
  128. //
  129. // Waits until 5380 access is allowed.
  130. //
  131. //-----------------------------------------------------------------------
  132. USHORT N53C400Wait5380Access (PADAPTER_INFO g, ULONG usec)
  133. {
  134. ULONG i;
  135. // see if the flag comes back quickly
  136. for (i = 0; i < TIMEOUT_QUICK; i++) {
  137. if (N53C400PortTest (g, N53C400_STATUS, SR_ACCESS)) {
  138. return 0;
  139. }
  140. }
  141. // ok, it did not come back quickly, we will yield to other processes
  142. for (i = 0; i < usec; i++) {
  143. if (N53C400PortTest (g, N53C400_STATUS, SR_ACCESS)) {
  144. return 0;
  145. }
  146. ScsiPortStallExecution(1);
  147. }
  148. DebugPrint((DEBUG_LEVEL,"Error - ScsiWait5380Access\n"));
  149. TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 31);
  150. // return with an error, non-zero indicates timeout
  151. return RET_STATUS_TIMEOUT;
  152. }
  153. //-----------------------------------------------------------------------
  154. //
  155. // N53C400WriteyBytesFast
  156. //
  157. // Write the bytes from a n53c400 as fast as possible.
  158. //
  159. //-----------------------------------------------------------------------
  160. USHORT N53C400WriteBytesFast (PADAPTER_INFO g, PUCHAR pbytes,
  161. ULONG len, PULONG pActualLen, UCHAR phase)
  162. {
  163. ULONG i;
  164. USHORT rval = 0;
  165. ULONG remainder;
  166. ULONG cnt;
  167. ULONG blocks;
  168. ULONG total_blocks;
  169. UCHAR tmp;
  170. remainder = len % 128;
  171. total_blocks = cnt = len / 128;
  172. // are there any 128 byte blocks to be received
  173. while (cnt) {
  174. // send up to 256 128 bytes blocks at a time
  175. blocks = (cnt > 256) ? 256 : cnt;
  176. cnt -= blocks;
  177. // clear any interrupt condition on the 5380
  178. N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp);
  179. // Clear the 53c400 dir bit.
  180. // Don't preserve any bits in this register.
  181. N53C400PortPut (g, N53C400_CONTROL, 0);
  182. // set the dma bit of 5380, and enable end of dma int
  183. N5380PortSet (g, N5380_MODE, MR_DMA_MODE |
  184. MR_ENABLE_EODMA_INTERRUPT);
  185. // start the dma on the 5380
  186. N5380PortPut (g, N5380_START_DMA_SEND, 1);
  187. // write the count of 128 byte blocks
  188. N53C400PortPut (g, N53C400_COUNTER, (UCHAR)blocks);
  189. for (i = 0; i < blocks; i++) {
  190. // wait for host buffer ready
  191. if (rval = N53C400WaitHostBufferReady (g, TIMEOUT_REQUEST)) {
  192. DebugPrint((DEBUG_LEVEL,"Error - 0 - N53C400WriteBytesFast\n"));
  193. // calculate # of bytes transferred
  194. // not including this one
  195. *pActualLen = (total_blocks - (cnt+blocks-i)) * 128;
  196. goto error_clear_dma;
  197. }
  198. N53C400PortPutBuffer (g, N53C400_HOST_BFR, pbytes, 128);
  199. pbytes += 128;
  200. }
  201. // wait for access to 5380
  202. if (rval = N53C400Wait5380Access (g, TIMEOUT_REQUEST)) {
  203. // if timeout, do reset
  204. N53C400PortPut (g, N53C400_CONTROL, CR_RST);
  205. }
  206. // wait for last byte to be sent
  207. if (rval = N5380WaitLastByteSent (g, TIMEOUT_REQUEST)) {
  208. goto error_clear_dma;
  209. }
  210. // clear dma mode
  211. N5380PortClear (g, N5380_MODE, MR_DMA_MODE |
  212. MR_ENABLE_EODMA_INTERRUPT);
  213. N5380DisableInterrupt (g);
  214. }
  215. // calculate # of bytes transferred
  216. *pActualLen = (total_blocks - cnt) * 128;
  217. // If xfr count was not a multiple of 128, write remainder slowly.
  218. if (remainder) {
  219. ULONG bytes_xferred;
  220. rval = ScsiWriteBytesSlow (g, pbytes, remainder, &bytes_xferred,
  221. phase);
  222. *pActualLen += bytes_xferred;
  223. }
  224. done:
  225. return rval;
  226. error_clear_dma:
  227. // clear dma mode
  228. N5380PortClear(g,N5380_MODE, MR_DMA_MODE |
  229. MR_ENABLE_EODMA_INTERRUPT);
  230. N5380DisableInterrupt(g);
  231. goto done;
  232. }
  233. //-----------------------------------------------------------------------
  234. //
  235. // N53C400ReadyBytesFast
  236. //
  237. // Read the bytes from a n53c400 as fast as possible.
  238. //
  239. //-----------------------------------------------------------------------
  240. USHORT N53C400ReadBytesFast (PADAPTER_INFO g, PUCHAR pbytes,
  241. ULONG len, PULONG pActualLen, UCHAR phase)
  242. {
  243. ULONG i;
  244. USHORT rval = 0;
  245. ULONG remainder;
  246. ULONG cnt;
  247. ULONG blocks;
  248. ULONG total_blocks;
  249. UCHAR tmp;
  250. // For uneven transfers (here not a multiple of 256),
  251. // assume we could have an underrun. Read bytes slow to prevent it...
  252. if ((len % 256)) {
  253. rval = ScsiReadBytesSlow (g, pbytes, len, pActualLen, phase);
  254. goto done;
  255. }
  256. remainder = len % 128;
  257. total_blocks = cnt = len / 128;
  258. // are there any 128 byte blocks to be received
  259. while (cnt) {
  260. blocks = (cnt > 256) ? 256 : cnt;
  261. cnt -= blocks;
  262. // clear any interrupt condition on the 5380
  263. N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp);
  264. // set the 53c400 dir bit
  265. // don't preserve any bits in this register...
  266. N53C400PortPut (g, N53C400_CONTROL, CR_DIR);
  267. // set the dma bit of 5380, enable end of dma int
  268. N5380PortSet (g, N5380_MODE, MR_DMA_MODE |
  269. MR_ENABLE_EODMA_INTERRUPT);
  270. // start the dma on the 5380
  271. N5380PortPut (g, N5380_START_INITIATOR_RECEIVE, 1);
  272. // write the count of 128 byte blocks
  273. N53C400PortPut (g, N53C400_COUNTER, (UCHAR)blocks);
  274. for (i = 0; i < blocks; i++) {
  275. // wait for host buffer ready
  276. if (rval = N53C400WaitHostBufferReady (g, TIMEOUT_REQUEST)) {
  277. // WHAT DO YOU DO when the transfer ends early and the n5380
  278. // has some of the bytes in its buffers? HELP!!!
  279. DebugPrint((DEBUG_LEVEL,"Error - 0 - N53C400ReadBytesFast\n"));
  280. N53C400PortGetBuffer (g, N53C400_HOST_BFR, pbytes, 128);
  281. // clear dma mode
  282. N5380PortClear (g, N5380_MODE, MR_DMA_MODE |
  283. MR_ENABLE_EODMA_INTERRUPT);
  284. N5380DisableInterrupt (g);
  285. // calculate # of bytes transferred, not including this one
  286. *pActualLen = (total_blocks - (cnt+blocks-i)) * 128;
  287. goto done;
  288. }
  289. N53C400PortGetBuffer (g, N53C400_HOST_BFR, pbytes, 128);
  290. pbytes += 128;
  291. }
  292. // wait for access to 5380
  293. if (rval = N53C400Wait5380Access (g, TIMEOUT_REQUEST)) {
  294. // if timeout, do reset
  295. N53C400PortPut (g, N53C400_CONTROL, CR_RST);
  296. }
  297. // clear dma mode
  298. N5380PortClear (g, N5380_MODE, MR_DMA_MODE |
  299. MR_ENABLE_EODMA_INTERRUPT);
  300. N5380DisableInterrupt (g);
  301. }
  302. // calculate # of bytes transferred
  303. *pActualLen = (total_blocks - cnt) * 128;
  304. // If xfr count was not a multiple of 128, read remainder slowly
  305. if (remainder) {
  306. ULONG bytes_xferred;
  307. ScsiReadBytesSlow (g,pbytes, remainder, &bytes_xferred,
  308. phase);
  309. *pActualLen += bytes_xferred;
  310. }
  311. done:
  312. return rval;
  313. }
  314. //-----------------------------------------------------------------------
  315. //
  316. // N53C400DisableInterrupt
  317. //
  318. // Disable interrupts on the N53C400
  319. //
  320. //-----------------------------------------------------------------------
  321. VOID N53C400DisableInterrupt (PADAPTER_INFO g)
  322. {
  323. UCHAR tmp;
  324. // disable interrupt in the 53c400 for 5380 ints
  325. N53C400PortGet (g, N53C400_CONTROL, &tmp);
  326. tmp &= (CR_DIR | CR_BFR_INT | CR_SH_INT);
  327. N53C400PortPut (g, N53C400_CONTROL, tmp);
  328. // disable the interrupt on the 5380
  329. N5380DisableInterrupt (g);
  330. }
  331. //-----------------------------------------------------------------------
  332. //
  333. // N53C400EnableInterrupt
  334. //
  335. // Enable interrupts on the N53C400
  336. //
  337. //-----------------------------------------------------------------------
  338. VOID N53C400EnableInterrupt (PADAPTER_INFO g)
  339. {
  340. UCHAR tmp;
  341. // set the dma bit of 5380 so we can get phase mismatch ints
  342. N5380EnableInterrupt (g);
  343. // enable interrupt in the 53c400 for 5380 interrupts
  344. N53C400PortGet (g, N53C400_CONTROL, &tmp);
  345. tmp &= (CR_DIR | CR_BFR_INT | CR_5380_INT | CR_SH_INT);
  346. tmp |= CR_5380_INT;
  347. N53C400PortPut (g, N53C400_CONTROL, tmp);
  348. }
  349. //-----------------------------------------------------------------------
  350. //
  351. // N53C400ResetBus
  352. //
  353. // Reset the SCSI bus
  354. //
  355. //-----------------------------------------------------------------------
  356. VOID N53C400ResetBus (PADAPTER_INFO g)
  357. {
  358. // reset the 53c400
  359. N53C400PortPut (g, N53C400_CONTROL, CR_RST);
  360. // disable interrupts
  361. N53C400DisableInterrupt (g);
  362. // reset the scsi bus
  363. N5380ResetBus (g);
  364. }
  365. //-----------------------------------------------------------------------
  366. // End Of File.
  367. //-----------------------------------------------------------------------