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.

617 lines
15 KiB

4 years ago
  1. //----------------------------------------------------------------------
  2. //
  3. // MV101.C
  4. //
  5. // Trantor MV101 access file.
  6. //
  7. // These routines are independent of the card the MV101 logic is on. The
  8. // cardxxxx.h file must define the following routines:
  9. //
  10. // MV101PortPut
  11. // MV101PortGet
  12. // MV101PortSet
  13. // MV101PortClear
  14. // MV101PortTest
  15. //
  16. // These routines could be defined by some other include file instead of
  17. // cardxxxx.h, as the pc9010 defines the needed n5380xxxxxxxx routines.
  18. //
  19. // Revisions:
  20. // 02-25-93 KJB First.
  21. // 03-05-93 KJB Added call to N5380DisableDmaWrite.
  22. // 03-11-93 JAP Changed retcode equates to reflect new names.
  23. // 03-11-93 KJB Changed to use new N5380.H names.
  24. // 03-19-93 JAP Implemented condition build FAR and NEAR pointers
  25. // 03-25-93 JAP Fixed up typedef and prototype inconsistencies
  26. // 04-05-93 KJB DEBUG_LEVEL used by DebugPrint for NT.
  27. // 05-13-93 KJB Added CardParseCommandString for card specific
  28. // standard string parsing across platforms.
  29. // Changed CardCheckAdapter to accept an
  30. // Initialization info from command line, ie
  31. // force bi-directional ports, etc.
  32. // All functions that used to take an PBASE_REGISTER
  33. // parameter now take PWORKSPACE. CardCheckAdapter
  34. // takes the both the PBASE_REGISTER and the
  35. // PWORKSPACE parameters. Auto Request Sense is
  36. // now supported.
  37. // 05-13-93 KJB Merged Microsoft Bug fixes to card detection.
  38. // 05-14-93 KJB Remove all WINNT specific #ifdef i386 references.
  39. // 05-17-93 KJB Added ErrorLogging capabilities (used by WINNT).
  40. //
  41. //----------------------------------------------------------------------
  42. #include CARDTXXX_H
  43. #include "findpas.h"
  44. //
  45. // local functions
  46. //
  47. VOID MV101ResetDmaTimeout (PADAPTER_INFO g);
  48. VOID MV101EnableDmaWrite (PADAPTER_INFO g);
  49. VOID MV101EnableDmaRead (PADAPTER_INFO g);
  50. USHORT MV101WaitXfrReady (PADAPTER_INFO g, ULONG usec);
  51. //
  52. // local redefines
  53. //
  54. #define MV101DisableDmaRead N5380DisableDmaRead
  55. #define MV101DisableDmaWrite N5380DisableDmaWrite
  56. //
  57. // N5380PortPut
  58. //
  59. // This routine is used by the N5380.C module to write byte to a 5380
  60. // controller. This allows the module to be card independent. Other
  61. // modules that assume a N5380 may also use this function.
  62. //
  63. VOID N5380PortPut (PADAPTER_INFO g, UCHAR reg, UCHAR byte)
  64. {
  65. if (reg<4) {
  66. PortIOPut((PUCHAR)g->BaseIoAddress+MV101_5380_1+reg,byte);
  67. } else {
  68. PortIOPut((PUCHAR)g->BaseIoAddress+MV101_5380_2+reg-4,byte);
  69. }
  70. }
  71. //
  72. // N5380PortGet
  73. //
  74. // This routine is used by the N5380.C module to get a byte from a 5380
  75. // controller. This allows the module to be card independent. Other
  76. // modules that assume a N5380 may also use this function.
  77. //
  78. VOID N5380PortGet (PADAPTER_INFO g, UCHAR reg, PUCHAR byte)
  79. {
  80. if (reg<4) {
  81. PortIOGet ((PUCHAR)g->BaseIoAddress+MV101_5380_1+reg, byte);
  82. } else {
  83. PortIOGet ((PUCHAR)g->BaseIoAddress+MV101_5380_2+reg-4,byte);
  84. }
  85. }
  86. //
  87. // MV101CheckAdapter
  88. //
  89. // This routine sees if there is an adapter at this address. If so,
  90. // then this adapter is initialized.
  91. //
  92. BOOLEAN MV101CheckAdapter (PADAPTER_INFO g)
  93. {
  94. FOUNDINFO fi;
  95. //
  96. // FindPasHardware does it's own mapping of port bases.
  97. // Set the base to zero and indicate which port is currently being
  98. // polled.
  99. //
  100. fi.PROBase = 0;
  101. fi.ProPort = (ULONG) g->BaseIoAddress;
  102. if (!FindPasHardware(&fi)) {
  103. return FALSE;
  104. }
  105. // for old boards, we use bit 1 for drq mask during dma xfers
  106. if (fi.wBoardRev == PAS_VERSION_1) {
  107. g->DRQMask = 0x01;
  108. } else {
  109. g->DRQMask = 0x80;
  110. }
  111. // is there an adapter here?
  112. if (N5380CheckAdapter (g)) {
  113. // found a 5380, initialize special dma hardware for
  114. // dma fast read and writes.
  115. MV101PortPut (g,MV101_SYSTEM_CONFIG4,0x49);
  116. MV101PortPut (g,MV101_TIMEOUT_COUNTER,0x30);
  117. MV101PortPut (g,MV101_TIMEOUT_STATUS,0x01);
  118. MV101PortPut (g,MV101_WAIT_STATE,0x01);
  119. return TRUE;
  120. } else {
  121. return FALSE;
  122. }
  123. }
  124. //
  125. // MV101WaitXfrReady
  126. //
  127. // This routine waits till the DRQ flag goes up.
  128. //
  129. USHORT MV101WaitXfrReady (PADAPTER_INFO g, ULONG usec)
  130. {
  131. ULONG i;
  132. // see if the flag comes back quickly
  133. for (i=0;i<TIMEOUT_QUICK;i++) {
  134. // wait for card to be ready
  135. if (MV101PortTest(g, MV101_DRQ_PORT, g->DRQMask)) {
  136. return 0;
  137. }
  138. }
  139. // ok, it did not come back quickly, we will yield to other processes
  140. for (i=0; i < usec; i++) {
  141. // wait for card to be ready
  142. if (MV101PortTest (g, MV101_DRQ_PORT, g->DRQMask)) {
  143. return 0;
  144. }
  145. // see if bus free
  146. if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) {
  147. TrantorLogError (g->BaseIoAddress, RET_STATUS_UNEXPECTED_BUS_FREE, 100);
  148. return RET_STATUS_UNEXPECTED_BUS_FREE;
  149. }
  150. // since we have taken some time... check for phase change
  151. if (!N5380PortTest (g, N5380_DMA_STATUS, DS_PHASE_MATCH)) {
  152. return RET_STATUS_DATA_OVERRUN;
  153. }
  154. // wait for card to be ready
  155. ScsiPortStallExecution(1);
  156. }
  157. DebugPrint ((DEBUG_LEVEL,"Error - MV101WaitXfrReady\n"));
  158. // return with an error, non-zero indicates timeout
  159. TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 102);
  160. return RET_STATUS_TIMEOUT;
  161. }
  162. //
  163. // MV101ResetDmaTimeout
  164. //
  165. // Resets the dma timout bit.
  166. //
  167. VOID MV101ResetDmaTimeout (PADAPTER_INFO g)
  168. {
  169. MV101PortPut (g, MV101_TIMEOUT_STATUS, 0x01);
  170. }
  171. //
  172. // MV101EnableDmaRead
  173. //
  174. // Enables the DMA read operation for the T128.
  175. //
  176. VOID MV101EnableDmaRead (PADAPTER_INFO g)
  177. {
  178. // start dma on the 5380
  179. N5380EnableDmaRead(g);
  180. // toggle the t120 timeout bit to clear any timeout
  181. MV101ResetDmaTimeout(g);
  182. }
  183. //
  184. // MV101EnableDmaWrite
  185. //
  186. // Enables the DMA write operation for the T128.
  187. //
  188. VOID MV101EnableDmaWrite (PADAPTER_INFO g)
  189. {
  190. // start dma on the 5380
  191. N5380EnableDmaWrite (g);
  192. // toggle the t120 timeout bit to clear any timeout
  193. MV101ResetDmaTimeout (g);
  194. }
  195. //
  196. // MV101SetInterruptLevel
  197. //
  198. // The Media Vision MV101s need to be programmed for interrupts.
  199. // In particular, one needs to set the interrupt level into a register.
  200. //
  201. VOID MV101SetInterruptLevel (PADAPTER_INFO g, UCHAR level)
  202. {
  203. // int from drive active high
  204. MV101PortSet (g, MV101_SYSTEM_CONFIG4, 0x04);
  205. // enable interrupts for the card
  206. MV101PortSet (g, MV101_SYSTEM_CONFIG4, 0x20);
  207. // set the interrupt level in IO port config register 3
  208. MV101PortClear(g,MV101_IO_PORT_CONFIG3,0xf0);
  209. if (level < 8) {
  210. MV101PortSet (g, MV101_IO_PORT_CONFIG3,
  211. (UCHAR)((level-1)<<4));
  212. }
  213. else {
  214. MV101PortSet (g, MV101_IO_PORT_CONFIG3,
  215. (UCHAR)((7+level-10)<<4));
  216. }
  217. }
  218. //
  219. // MV101EnableInterrupt
  220. //
  221. // Enables the interrupt on the card and on the 5380.
  222. //
  223. VOID MV101EnableInterrupt (PADAPTER_INFO g)
  224. {
  225. // interrupt reset for tmv1 card
  226. MV101PortSet (g, MV101_TIMEOUT_STATUS, 0x01);
  227. // enable interrupts on the 5380
  228. N5380EnableInterrupt (g);
  229. }
  230. //
  231. // MV101DisableInterrupt
  232. //
  233. // Disables the interrupt on the card and on the 5380.
  234. //
  235. VOID MV101DisableInterrupt (PADAPTER_INFO g)
  236. {
  237. // interrupt reset for tmv1 card
  238. MV101PortSet (g, MV101_TIMEOUT_STATUS, 0x01);
  239. // disable the signal from the 5380
  240. N5380DisableInterrupt (g);
  241. }
  242. //
  243. // MV101ReadBytesFast
  244. //
  245. // This routine is used by the ScsiFnc routines to read bytes to the scsi
  246. // bus quickly. The ScsiFnc routines don't know how to do this quickly for
  247. // a particular card, so they call this. This routine can be mapped to the
  248. // slower ScsiReadBytesSlow routine for small transferrs or if this routine
  249. // is not supported.
  250. //
  251. USHORT MV101ReadBytesFast (PADAPTER_INFO g, PUCHAR pbytes,
  252. ULONG len, PULONG pActualLen, UCHAR phase)
  253. {
  254. USHORT rval = 0;
  255. // for small transfers, use slow loop (inquiry and other stuff)
  256. if (len < 512) {
  257. rval = ScsiReadBytesSlow (g, pbytes, len,
  258. pActualLen, phase);
  259. return rval;
  260. }
  261. // start dma for this card
  262. MV101EnableDmaRead (g);
  263. // wait for buffer to be ready
  264. if (rval = MV101WaitXfrReady (g,TIMEOUT_REQUEST)) {
  265. goto done;
  266. }
  267. // due to the speed of i/o instructions in 486 protected mode,
  268. // we can afford to do all the drq checking. There is no need for
  269. // the 'blind mode' rep insb transfers. These have been tried and
  270. // the result is "20 FF FF FF 20 FF FF 41", indicating that we are
  271. // two to three times faster than the card, hence we can afford to
  272. // poll the card.
  273. {
  274. PUCHAR dma_port = (PUCHAR)g->BaseIoAddress + MV101_DMA_PORT;
  275. PUCHAR drq_port = (PUCHAR)g->BaseIoAddress + MV101_DRQ_PORT;
  276. ULONG xfer_count = len;
  277. UCHAR drq_mask = g->DRQMask;
  278. _asm {
  279. pushf
  280. push esi
  281. push edi
  282. push es
  283. cld
  284. mov ah,drq_mask
  285. #ifdef MODE_32BIT
  286. mov edx,dma_port
  287. mov esi,drq_port
  288. mov edi,pbytes
  289. mov ecx,len
  290. #else
  291. mov edx,word ptr dma_port
  292. mov esi,word ptr drq_port
  293. mov edi,word ptr pbytes
  294. mov ecx,word ptr len
  295. mov es,word ptr pbytes+2
  296. #endif
  297. loop1:
  298. xchg edx,esi // dx drq_port
  299. in al,dx
  300. test al,ah
  301. jnz ready
  302. in al,dx
  303. test al,ah
  304. jnz ready
  305. in al,dx
  306. test al,ah
  307. jnz ready
  308. push ecx
  309. mov ecx,TIMEOUT_READWRITE_LOOP
  310. loop3:
  311. mov ebx,0x10000
  312. loop2:
  313. in al,dx
  314. test al,ah
  315. jnz ready1
  316. in al,dx
  317. test al,ah
  318. jnz ready1
  319. // check for phase mismatch
  320. sub dx, MV101_DRQ_PORT - MV101_5380_2 // dx = N5380_CURRENT_STATUS
  321. in al,dx
  322. test al,CS_REQ
  323. jz no_req
  324. add dx, (N5380_DMA_STATUS - N5380_CURRENT_STATUS) // dx = N5380_DMA_STATUS
  325. in al,dx
  326. test al,DS_PHASE_MATCH
  327. jz phase_error
  328. sub dx, N5380_DMA_STATUS - N5380_CURRENT_STATUS // dx = N5380_CURRENT_STATUS
  329. no_req:
  330. add dx, MV101_DRQ_PORT - MV101_5380_2 // dx = MV101_DRQ
  331. dec ebx
  332. jnz loop2
  333. dec ecx
  334. jnz loop3
  335. pop ecx
  336. mov rval,RET_STATUS_TIMEOUT
  337. jmp short timeout
  338. phase_error:
  339. pop ecx
  340. mov rval,RET_STATUS_DATA_OVERRUN
  341. jmp short timeout
  342. ready1:
  343. pop ecx
  344. // jmp ready
  345. ready:
  346. xchg edx,esi // dx dma_port
  347. insb
  348. dec ecx
  349. jnz loop1
  350. timeout:
  351. pop es
  352. #ifdef MODE_32BIT
  353. mov xfer_count,ecx
  354. #else
  355. mov word ptr xfer_count,ecx
  356. #endif
  357. pop edi
  358. pop esi
  359. popf
  360. }
  361. // compute actual xfer len
  362. *pActualLen = len - xfer_count;
  363. }
  364. done:
  365. // disable dma
  366. MV101DisableDmaRead (g);
  367. // check for errors...
  368. if (rval == RET_STATUS_TIMEOUT) {
  369. TrantorLogError (g->BaseIoAddress, rval, 103);
  370. }
  371. return rval;
  372. }
  373. //
  374. // MV101WriteBytesFast
  375. //
  376. // This routine is used by the ScsiFnc routines to write bytes to the scsi
  377. // bus quickly. The ScsiFnc routines don't know how to do this quickly for
  378. // a particular card, so they call this. This routine can be mapped to the
  379. // slower ScsiReadBytesSlow routine for small transferrs or if this routine
  380. // is not supported.
  381. //
  382. USHORT MV101WriteBytesFast (PADAPTER_INFO g, PUCHAR pbytes,
  383. ULONG len, PULONG pActualLen, UCHAR phase)
  384. {
  385. USHORT rval = 0;
  386. // for small transfers, use slow loop (inquiry and other stuff)
  387. if (len < 512) {
  388. rval = ScsiWriteBytesSlow (g, pbytes, len,
  389. pActualLen, phase);
  390. return rval;
  391. }
  392. // start dma for this card
  393. MV101EnableDmaWrite (g);
  394. // wait for buffer to be ready
  395. if (rval = MV101WaitXfrReady (g, TIMEOUT_REQUEST)) {
  396. goto done;
  397. }
  398. // due to the speed of i/o instructions in 486 protected mode,
  399. // we can afford to do all the drq checking. There is no need for
  400. // the 'blind mode' rep insb transfers. These have been tried and
  401. // the result is "20 FF FF FF 20 FF FF 41", indicating that we are
  402. // two to three times faster than the card, hence we can afford to
  403. // poll the card.
  404. {
  405. PUCHAR dma_port = (PUCHAR)g->BaseIoAddress + MV101_DMA_PORT;
  406. PUCHAR drq_port = (PUCHAR)g->BaseIoAddress + MV101_DRQ_PORT;
  407. ULONG xfer_count = len;
  408. UCHAR drq_mask = g->DRQMask;
  409. _asm {
  410. pushf
  411. push esi
  412. push edi
  413. push ds
  414. cld
  415. mov ah,drq_mask
  416. #ifdef MODE_32BIT
  417. mov edx,dma_port
  418. mov edi,drq_port
  419. mov esi,pbytes
  420. mov ecx,len
  421. #else
  422. mov edx,word ptr dma_port
  423. mov edi,word ptr drq_port
  424. mov esi,word ptr pbytes
  425. mov ecx,word ptr len
  426. mov ds, word ptr pbytes+2
  427. #endif
  428. loop1:
  429. xchg edx,edi // edx drq_port
  430. in al,dx
  431. test al,ah
  432. jnz ready
  433. in al,dx
  434. test al,ah
  435. jnz ready
  436. in al,dx
  437. test al,ah
  438. jnz ready
  439. push ecx
  440. mov ecx,TIMEOUT_READWRITE_LOOP
  441. loop3:
  442. mov ebx,0x10000
  443. loop2:
  444. in al,dx
  445. test al,ah
  446. jnz ready1
  447. in al,dx
  448. test al,ah
  449. jnz ready1
  450. // check for phase mismatch
  451. sub dx, MV101_DRQ_PORT - MV101_5380_2 // dx = N5380_CURRENT_STATUS
  452. in al,dx
  453. test al,CS_REQ
  454. jz no_req
  455. add dx, N5380_DMA_STATUS - N5380_CURRENT_STATUS // dx = N5380_DMA_STATUS
  456. in al,dx
  457. test al,DS_PHASE_MATCH
  458. jz phase_error
  459. sub dx, N5380_DMA_STATUS - N5380_CURRENT_STATUS // dx = N5380_CURRENT_STATUS
  460. no_req:
  461. add dx, MV101_DRQ_PORT - MV101_5380_2 // dx = MV101_DRQ_PORT
  462. dec ebx
  463. jnz loop2
  464. dec ecx
  465. jnz loop3
  466. pop ecx
  467. mov rval,RET_STATUS_TIMEOUT
  468. jmp short timeout
  469. phase_error:
  470. pop ecx
  471. mov rval,RET_STATUS_DATA_OVERRUN
  472. jmp short timeout
  473. ready1:
  474. pop ecx
  475. // jmp ready
  476. ready:
  477. xchg edx,edi // edx dma_port
  478. outsb
  479. dec ecx
  480. jnz loop1
  481. timeout:
  482. pop ds
  483. #ifdef MODE_32BIT
  484. mov xfer_count,ecx
  485. #else
  486. mov word ptr xfer_count,ecx
  487. #endif
  488. pop edi
  489. pop esi
  490. popf
  491. }
  492. // compute actual xfer len
  493. *pActualLen = len - xfer_count;
  494. }
  495. done:
  496. // disable dma
  497. MV101DisableDmaWrite (g);
  498. // check for errors...
  499. if (rval == RET_STATUS_TIMEOUT) {
  500. TrantorLogError (g->BaseIoAddress, rval, 104);
  501. }
  502. return rval;
  503. }