NT4/private/ntos/miniport/trantor/source/t128.c
2020-09-30 17:12:29 +02:00

484 lines
12 KiB
C

//---------------------------------------------------------------------
//
// T128.C
//
// T128 Logic Specific File
//
// These routines are independent of the card the T128 logic is on. The
// cardxxxx.h file must define the following routines:
//
// T128PortPut
// T128PortGet
// T128PortSet
// T128PortClear
// T128PortTest
//
// These routines could be defined by some other include file instead of
// cardxxxx.h, as the pc9010 defines the needed n5380xxxxxxxx routines.
//
// Revisions:
// 02-25-93 KJB First.
// 03-05-93 KJB Added call to N5380DisableDmaWrite.
// 03-11-93 JAP Changed retcode equates to reflect new names.
// 03-11-92 KJB Changed to use new N5380.H names.
// 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-14-93 KJB Remove all WINNT specific #ifdef i386 references.
// 05-17-93 KJB Added ErrorLogging capabilities (used by WINNT).
//
//---------------------------------------------------------------------
#include CARDTXXX_H
// Local Routines
USHORT T128WaitXfrReady(PADAPTER_INFO g, ULONG usec);
VOID T128ResetDmaTimeout(PADAPTER_INFO g);
VOID T128EnableDmaRead(PADAPTER_INFO g);
VOID T128EnableDmaWrite(PADAPTER_INFO g);
VOID T128DisableDmaRead(PADAPTER_INFO g);
VOID T128DisableDmaWrite(PADAPTER_INFO g);
//
// T128ResetBus
//
// Resets the card, and the SCSI bus to a completely known, clean state.
//
VOID T128ResetBus(PADAPTER_INFO g)
{
// disable interrupts, t228 only
T128PortClear(g,T128_CONTROL,CR_INTENB);
// disable any dma xfer that was occuring
T128DisableDmaRead(g);
// reset the scsi bus
N5380ResetBus(g);
}
//
// T128EnableInterrupt
//
// Enables the interrupt on the card and on the 5380.
//
VOID T128EnableInterrupt(PADAPTER_INFO g)
{
// all t128 to send interrupts
T128PortSet(g,T128_CONTROL,CR_INTENB);
// enable interrupts on the 5380
N5380EnableInterrupt(g);
}
//
// T128DisableInterrupt
//
// Disables the interrupt on the card and on the 5380.
//
VOID T128DisableInterrupt(PADAPTER_INFO g)
{
// disable the signal from the 5380
N5380DisableInterrupt(g);
// disable the bit from the t128 control register
// this has an effect only on the t228
T128PortClear(g,T128_CONTROL ,CR_INTENB);
}
//
// T128WaitXfrReady
//
// This routine waits till the t120 status register says the xfr is ready.
//
USHORT T128WaitXfrReady(PADAPTER_INFO g, ULONG usec)
{
ULONG i;
// see if the flag comes back quickly
for (i=0;i<TIMEOUT_QUICK;i++) {
// wait for card to be ready
if (T128PortTest(g, T128_STATUS, SR_XFR_READY)) {
return 0;
}
}
// ok, it did not come back quickly, we will yield to other processes
for (i=0;i<usec;i++) {
// wait for card to be ready
if (T128PortTest(g, T128_STATUS, SR_XFR_READY)) {
return 0;
}
// see if bus free
if (!N5380PortTest(g,N5380_CURRENT_STATUS,CS_BSY)) {
TrantorLogError (g->BaseIoAddress, RET_STATUS_UNEXPECTED_BUS_FREE, 1);
return RET_STATUS_UNEXPECTED_BUS_FREE;
}
// since we have taken some time... check for phase change
if (!N5380PortTest(g,N5380_DMA_STATUS,DS_PHASE_MATCH)) {
return RET_STATUS_DATA_OVERRUN;
}
// wait for card to be ready
if (T128PortTest(g, T128_STATUS, SR_TIMEOUT)) {
TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 2);
return RET_STATUS_TIMEOUT;
}
ScsiPortStallExecution(1);
}
DebugPrint((DEBUG_LEVEL,"Error - T128WaitXfrReady\n"));
// return with an error, non-zero indicates timeout
TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 3);
return RET_STATUS_TIMEOUT;
}
//
// T128ResetDmaTimeout
//
// Resets the t128's dma timout bit.
//
VOID T128ResetDmaTimeout(PADAPTER_INFO g)
{
// is the timeout flagged?
if (T128PortTest(g, T128_STATUS, SR_TIMEOUT)) {
// toggle the t120 timeout bit to clear any timeout
T128PortSet(g, T128_CONTROL, CR_TIMEOUT);
T128PortClear(g, T128_CONTROL, CR_TIMEOUT);
}
}
//
// T128EnableDmaRead
//
// Enables the DMA read operation for the T128.
//
VOID T128EnableDmaRead(PADAPTER_INFO g)
{
// toggle the t120 timeout bit to clear any timeout
T128ResetDmaTimeout(g);
// start dma on the 5380
N5380EnableDmaRead(g);
}
//
// T128EnableDmaWrite
//
// Enables the DMA write operation for the T128.
//
VOID T128EnableDmaWrite(PADAPTER_INFO g)
{
// toggle the t120 timeout bit to clear any timeout
T128ResetDmaTimeout(g);
// start dma on the 5380
N5380EnableDmaWrite(g);
}
//
// T128DisableDmaRead
//
// Clears the current DMA operation for the T128.
//
VOID T128DisableDmaRead(PADAPTER_INFO g)
{
// toggle the t120 timeout bit to clear any timeout
T128ResetDmaTimeout(g);
// disable dma on the 5380
N5380DisableDmaRead(g);
}
//
// T128DisableDmaWrite
//
// Clears the current DMA operation for the T128.
//
VOID T128DisableDmaWrite(PADAPTER_INFO g)
{
// toggle the t120 timeout bit to clear any timeout
T128ResetDmaTimeout(g);
// disable dma on the 5380
N5380DisableDmaWrite(g);
}
//
// T128ReadBytesFast
//
// This routine is used by the ScsiFnc routines to write bytes to the scsi
// bus quickly. The ScsiFnc routines don't know how to do this quickly for
// a particular card, so they call this. This routine can be mapped to the
// slower ScsiReadBytesSlow routine for small transferrs or if this routine
// is not supported.
//
USHORT T128ReadBytesFast(PADAPTER_INFO g, PUCHAR pbytes,
ULONG len, PULONG pActualLen, UCHAR phase)
{
USHORT rval = 0;
// for small transfers, use slow method
if (len<0x200) {
rval = ScsiReadBytesSlow(g, pbytes, len,
pActualLen, phase);
return rval;
}
// start dma for this card
T128EnableDmaRead(g);
{
PVOID t128_data = (PUCHAR)g->BaseIoAddress + T128_DATA;
ULONG xfer_count = len;
// we have a 16 bit VGA problem
// must only move from even addresses
_asm {
pushf
push eax
push ebx
push ecx
push edx
push esi
push edi
push ds
push es
#ifdef MODE_32BIT
mov esi,t128_data
mov edi,pbytes
mov ecx,len
#else
mov esi, word ptr t128_data
mov edi, word ptr pbytes
mov ds, word ptr t128_data+2
mov es, word ptr pbytes+2
mov cx, word ptr len
#endif // MODE_32BIT
cld
get_bytes:
test [esi-0x1e0],SR_XFR_READY
jz big_wait
ready:
movsb
dec esi
dec ecx
jnz get_bytes
}
goto done_asm;
big_wait:
_asm {
test [esi-0x1e0],SR_XFR_READY
jnz ready
test [esi-0x1e0],SR_XFR_READY
jnz ready
test [esi-0x1e0],SR_XFR_READY
jnz ready
test [esi-0x1e0],SR_XFR_READY
jnz ready
mov eax,TIMEOUT_READWRITE_LOOP
loop1:
mov ebx,0x10000
loop2:
test [esi-0x1e0],SR_XFR_READY
jnz ready
test [esi-(8-N5380_CURRENT_STATUS)*0x20],CS_REQ
jz no_req
test [esi-(8-N5380_DMA_STATUS)*0x20],DS_PHASE_MATCH
jz phase_error
no_req:
dec ebx
jnz loop2
dec eax
jnz loop1
mov rval,RET_STATUS_TIMEOUT
jmp short done_asm
phase_error:
mov rval,RET_STATUS_DATA_OVERRUN
done_asm:
pop es
pop ds
#ifdef MODE_32BIT
mov xfer_count,ecx
#else
mov word ptr xfer_count,ecx
#endif
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
popf
}
// compute actual xfer len
*pActualLen = len - xfer_count;
}
// disable dma
T128DisableDmaRead(g);
// some error checking...
if (rval == RET_STATUS_TIMEOUT) {
TrantorLogError (g->BaseIoAddress, rval, 4);
}
return rval;
}
//
// T128WriteBytesFast
//
// This routine is used by the ScsiFnc routines to write bytes to the scsi
// bus quickly. The ScsiFnc routines don't know how to do this quickly for
// a particular card, so they call this. This routine can be mapped to the
// slower ScsiWriteBytesSlow routine for small transferrs or if this routine
// is not supported.
//
USHORT T128WriteBytesFast(PADAPTER_INFO g, PUCHAR pbytes,
ULONG len, PULONG pActualLen, UCHAR phase)
{
USHORT rval = 0;
// for small transfers, use slow method
if (len<0x200) {
rval = ScsiWriteBytesSlow(g, pbytes, len,
pActualLen, phase);
return rval;
}
// start dma for this card
T128EnableDmaWrite(g);
{
PVOID t128_data = (PUCHAR)g->BaseIoAddress + T128_DATA;
ULONG xfer_count = len;
// we have a 16 bit VGA problem
// must only move from even addresses
_asm {
pushf
push eax
push ebx
push ecx
push edx
push esi
push edi
push ds
push es
#ifdef MODE_32BIT
mov edi,t128_data
mov esi,pbytes
mov ecx,len
#define segment_override ds
#else
mov edi, word ptr t128_data
mov esi, word ptr pbytes
mov es, word ptr t128_data+2
mov ds, word ptr pbytes+2
mov cx, word ptr len
#define segment_override es
#endif // MODE_32BIT
cld
get_bytes:
test segment_override:[edi-0x1e0],SR_XFR_READY
jz big_wait
ready:
movsb
dec edi
dec ecx
jnz get_bytes
}
goto done_asm;
_asm {
big_wait:
test segment_override:[edi-0x1e0],SR_XFR_READY
jnz ready
test segment_override:[edi-0x1e0],SR_XFR_READY
jnz ready
test segment_override:[edi-0x1e0],SR_XFR_READY
jnz ready
test segment_override:[edi-0x1e0],SR_XFR_READY
jnz ready
mov eax,TIMEOUT_READWRITE_LOOP
loop1:
mov ebx,0x10000
loop2:
test segment_override:[edi-0x1e0],SR_XFR_READY
jnz ready
test segment_override:[edi-(8-N5380_CURRENT_STATUS)*0x20],CS_REQ
jz no_req
test segment_override:[edi-(8-N5380_DMA_STATUS)*0x20],DS_PHASE_MATCH
jz phase_error
no_req:
dec ebx
jnz loop2
dec eax
jnz loop1
mov rval,RET_STATUS_TIMEOUT
jmp done_asm
phase_error:
mov rval,RET_STATUS_DATA_OVERRUN
done_asm:
pop es
pop ds
#ifdef MODE_32BIT
mov xfer_count,ecx
#else
mov word ptr xfer_count,ecx
#endif
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
popf
}
// compute actual xfer len
*pActualLen = len - xfer_count;
}
// disable dma
T128DisableDmaWrite(g);
// some error checking...
if (rval == RET_STATUS_TIMEOUT) {
TrantorLogError (g->BaseIoAddress, rval, 5);
}
return rval;
}