diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/miniport/trantor/source/n53c400.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/miniport/trantor/source/n53c400.c')
-rw-r--r-- | private/ntos/miniport/trantor/source/n53c400.c | 525 |
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. +//----------------------------------------------------------------------- + |