summaryrefslogtreecommitdiffstats
path: root/private/ntos/miniport/trantor/source/n53c400.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/miniport/trantor/source/n53c400.c')
-rw-r--r--private/ntos/miniport/trantor/source/n53c400.c525
1 files changed, 525 insertions, 0 deletions
diff --git a/private/ntos/miniport/trantor/source/n53c400.c b/private/ntos/miniport/trantor/source/n53c400.c
new file mode 100644
index 000000000..30cf94bd0
--- /dev/null
+++ b/private/ntos/miniport/trantor/source/n53c400.c
@@ -0,0 +1,525 @@
+//-----------------------------------------------------------------------
+//
+// File: N53C400.C
+//
+// N53C400 access file.
+//
+// These routines are independent of the card the N53C400 is on. The
+// cardxxxx.h file must define the following routines:
+//
+// N53C400PortPut
+// N53C400PortGet
+// N53C400PortSet
+// N53C400PortClear
+// N53C400PortTest
+// N53C400PortGetBuffer
+// N53C400PortPutBuffer
+//
+// These routines could be defined by some other include file instead of
+// cardxxxx.h, as the pc9010 defines the needed n5380xxxxxxxx routines.
+//
+//
+// Revisions:
+// 09-01-92 KJB First.
+// 02-19-93 KJB Added support for data underrun read & write.
+// transfer only 2 128 bytes fifos at a time
+// might want to change this back if dataunderrun ok.
+// 03-01-93 KJB Added N53C400CheckAdapter to check specifically for
+// N53C400 and perform a chip reset on the 53C400 before
+// checking.
+// 03-02-93 KJB/JAP Phase checking for data phase moved to scsifnc.c.
+// Wait for last byte sent in write bytes.
+// 03-02-93 JAP Cleaned comments.
+// 03-02-93 KJB Fixed Names-- baseIoAddress back.
+// 03-03-93 JAP Cleaned comments again, reverting func declarations.
+// 03-05-93 JAP Changed N53C400DisableInterrupt() and N53C400EnableInterrupt
+// to mirror what is done in ASM code.
+// 03-07-93 KJB WriteBytesFast now returns the correct error code
+// when error occurs during slow write.
+// 03-11-93 JAP Changed retcode equates to reflect new names.
+// 03-11-93 KJB Changes code to reflect new 5380 names.
+// 03-17-93 JAP Removed unreference lablellings.
+// 03-25-93 JAP Fixed up typedef and prototype inconsistencies
+// 04-05-93 KJB DEBUG_LEVEL used by DebugPrint for NT.
+// 05-14-93 KJB Added CardParseCommandString for card specific
+// standard string parsing across platforms.
+// Changed CardCheckAdapter to accept an
+// Initialization info from command line, ie
+// force bi-directional ports, etc.
+// All functions that used to take an PBASE_REGISTER
+// parameter now take PWORKSPACE. CardCheckAdapter
+// takes the both a PINIT and a PWORKSPACE parameters.
+// 05-17-93 KJB Added ErrorLogging capabilities (used by WINNT).
+//
+//-----------------------------------------------------------------------
+
+
+#include CARDTXXX_H
+
+//-----------------------------------------------------------------------
+//
+// Local prototypes
+//
+//-----------------------------------------------------------------------
+
+USHORT N53C400Wait5380Access (PADAPTER_INFO g, ULONG usec);
+USHORT N53C400WaitHostBufferReady (PADAPTER_INFO g, ULONG usec);
+
+
+//-----------------------------------------------------------------------
+//
+// Routines
+//
+//-----------------------------------------------------------------------
+
+//-----------------------------------------------------------------------
+//
+// N53C400CheckAdapter
+//
+// This routine checks for the presense of a 53C400.
+//
+//-----------------------------------------------------------------------
+
+BOOLEAN N53C400CheckAdapter (PADAPTER_INFO g)
+{
+ USHORT rval;
+
+ // Reset the N53C400 chip.
+ // WARNING -- Could be destructive to other cards @ this port
+
+ N53C400PortPut (g, N53C400_CONTROL, CR_RST);
+
+ // check by testing the 5380
+
+ rval = N5380CheckAdapter (g);
+
+ return (BOOLEAN) rval;
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400WaitHostBufferReady
+//
+// This routine waits until the 53c400's 128 byte queue is ready with
+// or for data.
+//
+//-----------------------------------------------------------------------
+
+USHORT N53C400WaitHostBufferReady (PADAPTER_INFO g, ULONG usec)
+{
+ ULONG i;
+ USHORT rval;
+
+ // see if the flag comes back quickly
+
+ for (i = 0; i < TIMEOUT_QUICK; i++) {
+ if (!N53C400PortTest (g, N53C400_STATUS, SR_HBFR_RDY)) {
+ return 0;
+ }
+ }
+
+ // ok, it did not come back quickly, we will yield to other processes
+
+ for (i = 0; i < usec; i++) {
+ if (!N53C400PortTest (g, N53C400_STATUS, SR_HBFR_RDY)) {
+ return 0;
+ }
+
+ // if we suddenly have access, then phase mismatch and over/underrun
+
+ if (N53C400PortTest (g, N53C400_STATUS, SR_ACCESS)) {
+ rval = RET_STATUS_DATA_OVERRUN;
+ DebugPrint((DEBUG_LEVEL,"Error - 0 - ScsiWaitHostBufferReady\n"));
+ goto error;
+ }
+
+ ScsiPortStallExecution(1);
+ }
+
+ // reset the n53c400 in the case of a timeout
+
+ N53C400PortPut (g, N53C400_CONTROL, CR_RST);
+
+ TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 30);
+
+ rval = RET_STATUS_TIMEOUT;
+
+error:
+ DebugPrint((DEBUG_LEVEL,"Error - 1 - ScsiWaitHostBufferReady\n"));
+
+ // return with an error, non-zero indicates timeout
+
+ return rval;
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400Wait5380Access
+//
+// Waits until 5380 access is allowed.
+//
+//-----------------------------------------------------------------------
+
+USHORT N53C400Wait5380Access (PADAPTER_INFO g, ULONG usec)
+{
+ ULONG i;
+
+ // see if the flag comes back quickly
+
+ for (i = 0; i < TIMEOUT_QUICK; i++) {
+ if (N53C400PortTest (g, N53C400_STATUS, SR_ACCESS)) {
+ return 0;
+ }
+ }
+
+ // ok, it did not come back quickly, we will yield to other processes
+
+ for (i = 0; i < usec; i++) {
+ if (N53C400PortTest (g, N53C400_STATUS, SR_ACCESS)) {
+ return 0;
+ }
+ ScsiPortStallExecution(1);
+ }
+
+ DebugPrint((DEBUG_LEVEL,"Error - ScsiWait5380Access\n"));
+
+ TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 31);
+
+ // return with an error, non-zero indicates timeout
+
+ return RET_STATUS_TIMEOUT;
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400WriteyBytesFast
+//
+// Write the bytes from a n53c400 as fast as possible.
+//
+//-----------------------------------------------------------------------
+
+USHORT N53C400WriteBytesFast (PADAPTER_INFO g, PUCHAR pbytes,
+ ULONG len, PULONG pActualLen, UCHAR phase)
+{
+ ULONG i;
+ USHORT rval = 0;
+ ULONG remainder;
+ ULONG cnt;
+ ULONG blocks;
+ ULONG total_blocks;
+ UCHAR tmp;
+
+ remainder = len % 128;
+ total_blocks = cnt = len / 128;
+
+ // are there any 128 byte blocks to be received
+
+ while (cnt) {
+
+ // send up to 256 128 bytes blocks at a time
+
+ blocks = (cnt > 256) ? 256 : cnt;
+ cnt -= blocks;
+
+ // clear any interrupt condition on the 5380
+
+ N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp);
+
+ // Clear the 53c400 dir bit.
+ // Don't preserve any bits in this register.
+
+ N53C400PortPut (g, N53C400_CONTROL, 0);
+
+ // set the dma bit of 5380, and enable end of dma int
+
+ N5380PortSet (g, N5380_MODE, MR_DMA_MODE |
+ MR_ENABLE_EODMA_INTERRUPT);
+
+ // start the dma on the 5380
+
+ N5380PortPut (g, N5380_START_DMA_SEND, 1);
+
+ // write the count of 128 byte blocks
+
+ N53C400PortPut (g, N53C400_COUNTER, (UCHAR)blocks);
+
+ for (i = 0; i < blocks; i++) {
+
+ // wait for host buffer ready
+
+ if (rval = N53C400WaitHostBufferReady (g, TIMEOUT_REQUEST)) {
+
+ DebugPrint((DEBUG_LEVEL,"Error - 0 - N53C400WriteBytesFast\n"));
+
+ // calculate # of bytes transferred
+ // not including this one
+
+ *pActualLen = (total_blocks - (cnt+blocks-i)) * 128;
+
+ goto error_clear_dma;
+ }
+
+ N53C400PortPutBuffer (g, N53C400_HOST_BFR, pbytes, 128);
+ pbytes += 128;
+ }
+
+ // wait for access to 5380
+
+ if (rval = N53C400Wait5380Access (g, TIMEOUT_REQUEST)) {
+
+ // if timeout, do reset
+
+ N53C400PortPut (g, N53C400_CONTROL, CR_RST);
+ }
+
+ // wait for last byte to be sent
+
+ if (rval = N5380WaitLastByteSent (g, TIMEOUT_REQUEST)) {
+ goto error_clear_dma;
+ }
+
+ // clear dma mode
+
+ N5380PortClear (g, N5380_MODE, MR_DMA_MODE |
+ MR_ENABLE_EODMA_INTERRUPT);
+ N5380DisableInterrupt (g);
+ }
+
+ // calculate # of bytes transferred
+
+ *pActualLen = (total_blocks - cnt) * 128;
+
+ // If xfr count was not a multiple of 128, write remainder slowly.
+
+ if (remainder) {
+
+ ULONG bytes_xferred;
+
+ rval = ScsiWriteBytesSlow (g, pbytes, remainder, &bytes_xferred,
+ phase);
+
+ *pActualLen += bytes_xferred;
+ }
+
+done:
+ return rval;
+
+error_clear_dma:
+
+ // clear dma mode
+
+ N5380PortClear(g,N5380_MODE, MR_DMA_MODE |
+ MR_ENABLE_EODMA_INTERRUPT);
+ N5380DisableInterrupt(g);
+
+ goto done;
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400ReadyBytesFast
+//
+// Read the bytes from a n53c400 as fast as possible.
+//
+//-----------------------------------------------------------------------
+
+USHORT N53C400ReadBytesFast (PADAPTER_INFO g, PUCHAR pbytes,
+ ULONG len, PULONG pActualLen, UCHAR phase)
+{
+ ULONG i;
+ USHORT rval = 0;
+ ULONG remainder;
+ ULONG cnt;
+ ULONG blocks;
+ ULONG total_blocks;
+ UCHAR tmp;
+
+ // For uneven transfers (here not a multiple of 256),
+ // assume we could have an underrun. Read bytes slow to prevent it...
+
+ if ((len % 256)) {
+ rval = ScsiReadBytesSlow (g, pbytes, len, pActualLen, phase);
+ goto done;
+ }
+
+ remainder = len % 128;
+ total_blocks = cnt = len / 128;
+
+ // are there any 128 byte blocks to be received
+
+ while (cnt) {
+
+ blocks = (cnt > 256) ? 256 : cnt;
+ cnt -= blocks;
+
+ // clear any interrupt condition on the 5380
+
+ N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp);
+
+ // set the 53c400 dir bit
+ // don't preserve any bits in this register...
+
+ N53C400PortPut (g, N53C400_CONTROL, CR_DIR);
+
+ // set the dma bit of 5380, enable end of dma int
+
+ N5380PortSet (g, N5380_MODE, MR_DMA_MODE |
+ MR_ENABLE_EODMA_INTERRUPT);
+
+ // start the dma on the 5380
+
+ N5380PortPut (g, N5380_START_INITIATOR_RECEIVE, 1);
+
+ // write the count of 128 byte blocks
+
+ N53C400PortPut (g, N53C400_COUNTER, (UCHAR)blocks);
+
+ for (i = 0; i < blocks; i++) {
+
+ // wait for host buffer ready
+
+ if (rval = N53C400WaitHostBufferReady (g, TIMEOUT_REQUEST)) {
+
+ // WHAT DO YOU DO when the transfer ends early and the n5380
+ // has some of the bytes in its buffers? HELP!!!
+
+ DebugPrint((DEBUG_LEVEL,"Error - 0 - N53C400ReadBytesFast\n"));
+
+ N53C400PortGetBuffer (g, N53C400_HOST_BFR, pbytes, 128);
+
+ // clear dma mode
+
+ N5380PortClear (g, N5380_MODE, MR_DMA_MODE |
+ MR_ENABLE_EODMA_INTERRUPT);
+ N5380DisableInterrupt (g);
+
+ // calculate # of bytes transferred, not including this one
+
+ *pActualLen = (total_blocks - (cnt+blocks-i)) * 128;
+
+ goto done;
+ }
+
+ N53C400PortGetBuffer (g, N53C400_HOST_BFR, pbytes, 128);
+ pbytes += 128;
+ }
+
+ // wait for access to 5380
+
+ if (rval = N53C400Wait5380Access (g, TIMEOUT_REQUEST)) {
+
+ // if timeout, do reset
+
+ N53C400PortPut (g, N53C400_CONTROL, CR_RST);
+ }
+
+ // clear dma mode
+
+ N5380PortClear (g, N5380_MODE, MR_DMA_MODE |
+ MR_ENABLE_EODMA_INTERRUPT);
+ N5380DisableInterrupt (g);
+ }
+
+ // calculate # of bytes transferred
+
+ *pActualLen = (total_blocks - cnt) * 128;
+
+ // If xfr count was not a multiple of 128, read remainder slowly
+
+ if (remainder) {
+
+ ULONG bytes_xferred;
+
+ ScsiReadBytesSlow (g,pbytes, remainder, &bytes_xferred,
+ phase);
+
+ *pActualLen += bytes_xferred;
+ }
+
+done:
+
+ return rval;
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400DisableInterrupt
+//
+// Disable interrupts on the N53C400
+//
+//-----------------------------------------------------------------------
+
+VOID N53C400DisableInterrupt (PADAPTER_INFO g)
+{
+ UCHAR tmp;
+
+ // disable interrupt in the 53c400 for 5380 ints
+
+ N53C400PortGet (g, N53C400_CONTROL, &tmp);
+ tmp &= (CR_DIR | CR_BFR_INT | CR_SH_INT);
+ N53C400PortPut (g, N53C400_CONTROL, tmp);
+
+ // disable the interrupt on the 5380
+
+ N5380DisableInterrupt (g);
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400EnableInterrupt
+//
+// Enable interrupts on the N53C400
+//
+//-----------------------------------------------------------------------
+
+VOID N53C400EnableInterrupt (PADAPTER_INFO g)
+{
+ UCHAR tmp;
+
+ // set the dma bit of 5380 so we can get phase mismatch ints
+
+ N5380EnableInterrupt (g);
+
+ // enable interrupt in the 53c400 for 5380 interrupts
+
+ N53C400PortGet (g, N53C400_CONTROL, &tmp);
+ tmp &= (CR_DIR | CR_BFR_INT | CR_5380_INT | CR_SH_INT);
+ tmp |= CR_5380_INT;
+ N53C400PortPut (g, N53C400_CONTROL, tmp);
+}
+
+
+//-----------------------------------------------------------------------
+//
+// N53C400ResetBus
+//
+// Reset the SCSI bus
+//
+//-----------------------------------------------------------------------
+
+VOID N53C400ResetBus (PADAPTER_INFO g)
+{
+ // reset the 53c400
+
+ N53C400PortPut (g, N53C400_CONTROL, CR_RST);
+
+ // disable interrupts
+
+ N53C400DisableInterrupt (g);
+
+ // reset the scsi bus
+
+ N5380ResetBus (g);
+}
+
+
+//-----------------------------------------------------------------------
+// End Of File.
+//-----------------------------------------------------------------------
+