From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/miniport/trantor/source/cardt128.c | 377 ++++++ private/ntos/miniport/trantor/source/cardt13b.c | 299 +++++ private/ntos/miniport/trantor/source/cardt160.c | 273 +++++ private/ntos/miniport/trantor/source/cardt338.c | 246 ++++ private/ntos/miniport/trantor/source/cardt348.c | 220 ++++ private/ntos/miniport/trantor/source/cardtmv1.c | 266 +++++ private/ntos/miniport/trantor/source/cardutil.c | 110 ++ private/ntos/miniport/trantor/source/ep3c.c | 1418 +++++++++++++++++++++++ private/ntos/miniport/trantor/source/ep3c2.asm | 526 +++++++++ private/ntos/miniport/trantor/source/findpas.c | 303 +++++ private/ntos/miniport/trantor/source/mv101.c | 617 ++++++++++ private/ntos/miniport/trantor/source/n5380.c | 970 ++++++++++++++++ private/ntos/miniport/trantor/source/n53c400.c | 525 +++++++++ private/ntos/miniport/trantor/source/p3c.c | 1069 +++++++++++++++++ private/ntos/miniport/trantor/source/parallel.c | 86 ++ private/ntos/miniport/trantor/source/pc9010.c | 851 ++++++++++++++ private/ntos/miniport/trantor/source/port.c | 62 + private/ntos/miniport/trantor/source/portio.c | 87 ++ private/ntos/miniport/trantor/source/portmem.c | 67 ++ private/ntos/miniport/trantor/source/scsifnc.c | 586 ++++++++++ private/ntos/miniport/trantor/source/scsiport.c | 181 +++ private/ntos/miniport/trantor/source/sl386.c | 285 +++++ private/ntos/miniport/trantor/source/t128.c | 483 ++++++++ private/ntos/miniport/trantor/source/t338.c | 763 ++++++++++++ 24 files changed, 10670 insertions(+) create mode 100644 private/ntos/miniport/trantor/source/cardt128.c create mode 100644 private/ntos/miniport/trantor/source/cardt13b.c create mode 100644 private/ntos/miniport/trantor/source/cardt160.c create mode 100644 private/ntos/miniport/trantor/source/cardt338.c create mode 100644 private/ntos/miniport/trantor/source/cardt348.c create mode 100644 private/ntos/miniport/trantor/source/cardtmv1.c create mode 100644 private/ntos/miniport/trantor/source/cardutil.c create mode 100644 private/ntos/miniport/trantor/source/ep3c.c create mode 100644 private/ntos/miniport/trantor/source/ep3c2.asm create mode 100644 private/ntos/miniport/trantor/source/findpas.c create mode 100644 private/ntos/miniport/trantor/source/mv101.c create mode 100644 private/ntos/miniport/trantor/source/n5380.c create mode 100644 private/ntos/miniport/trantor/source/n53c400.c create mode 100644 private/ntos/miniport/trantor/source/p3c.c create mode 100644 private/ntos/miniport/trantor/source/parallel.c create mode 100644 private/ntos/miniport/trantor/source/pc9010.c create mode 100644 private/ntos/miniport/trantor/source/port.c create mode 100644 private/ntos/miniport/trantor/source/portio.c create mode 100644 private/ntos/miniport/trantor/source/portmem.c create mode 100644 private/ntos/miniport/trantor/source/scsifnc.c create mode 100644 private/ntos/miniport/trantor/source/scsiport.c create mode 100644 private/ntos/miniport/trantor/source/sl386.c create mode 100644 private/ntos/miniport/trantor/source/t128.c create mode 100644 private/ntos/miniport/trantor/source/t338.c (limited to 'private/ntos/miniport/trantor/source') diff --git a/private/ntos/miniport/trantor/source/cardt128.c b/private/ntos/miniport/trantor/source/cardt128.c new file mode 100644 index 000000000..c86faea98 --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardt128.c @@ -0,0 +1,377 @@ +//------------------------------------------------------------------------ +// CARDT128.C +// +// T128 Adapter Specific File +// +// See also cardtxxx.h, cardtxxx.h may redefine some functions with #defines. +// +// Revisions: +// 09-01-92 KJB First. +// 01-08-93 KJB Moved CardPort routines to port.c. +// 02-18-93 KJB Allowed for data underrun for read & write. +// 02-25-93 KJB Reorganized routines. +// 03-23-93 KJB Reorged for functional library interface. +// 03-26-93 JAP Fixed up typedef and prototype inconsistencies +// 04-05-93 KJB Fixed definition problem for WINNT. +// Involving CardAddressRange... +// 04-26-93 JAP Added AdapterInterrupts[] and CardGetIRQ(). +// 05-05-93 KJB Fixed CheckAdapter to check timeout condition +// So that memory won't seem like an adapter. +// 05-06-93 KJB Merged some Microsoft code to make CheckAdapter +// more stringent. +// 05-12-93 JAP Altered CardGetShortName() to return only +// the type of card. +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// +//------------------------------------------------------------------------ + +#include CARDTXXX_H + +#ifdef WINNT +//------------------------------------------------------------------------ +// The address ranges the card will use. These are accessed by trantor.c +// to inform NTOS of the resources we are using. +//------------------------------------------------------------------------ + +const CardAddressRange cardAddressRange [] = + { + {0x00,0x2000,TRUE}, + }; + +#endif + +//------------------------------------------------------------------------ +// The following table specifies the ports to be checked when searching for +// an adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +#ifdef MODE_32BIT +CONST ULONG AdapterAddresses [] = + {0XCC000, 0XC8000, 0XDC000, 0XD8000, 0}; +#else +CONST ULONG AdapterAddresses [] = + {0XCC000000, 0XC8000000, 0XDC000000, 0XD8000000, 0}; +#endif + + +//------------------------------------------------------------------------ +// The following table specifies the possible interrupts that +// can be used by the adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST USHORT AdapterInterrupts [] = + {3, 5, 7, 10, 12, 14, 15, 0}; + +//----------------------------------------------------------------------- +// +// The following routines are stub routines to provide an entry +// point for the library. They reference the correct routines for +// the appropriate card. Only these routines may be called from outside +// the library. See the rouines they reference for a description of +// the rouines, if the meaning is unclear. +// +//----------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// the maximum transfer size +// by decreasinge this we can get better system performace since +// the data transfer occurs with interrupts disabled, this might be +// decreased for our smaller cards +// Used only by WINNT +//----------------------------------------------------------------------- + +ULONG CardMaxTransferSize (VOID) +{ + return 16*1024L; +} + + +// we use interrupts + +BOOLEAN CardSupportsInterrupts (VOID) +{ + return TRUE; +} + + +// default interrupt number is 5 + +#define CARD_DEFAULT_INTERRUPT_LEVEL 5 + +UCHAR CardDefaultInterruptLevel (VOID) +{ + return 5; +} + + +// the following info is for initialization only +// this card is memory mapped + +BOOLEAN CardAddressRangeInIoSpace (VOID) +{ + return FALSE; +} + +// we use 0x2000 bytes in memory space + +USHORT CardAddressRangeLength (VOID) +{ + return 0x2000; +} + + +// The following is used along with the constant structure in card.c +// to define the precise i/o addresses a card will use + +USHORT CardNumberOfAddressRanges (VOID) +{ + return 1; +} + + +USHORT CardStartCommandInterrupt (PTSRB t) +{ + return ScsiStartCommandInterrupt (t); +} + + +USHORT CardDoCommand (PTSRB t) +{ + return ScsiDoCommand (t); +} + + +USHORT CardFinishCommandInterrupt (PTSRB t) +{ + return ScsiFinishCommandInterrupt (t); +} + + +BOOLEAN CardInterrupt (PADAPTER_INFO g) +{ + return N5380Interrupt (g); +} + + +//----------------------------------------------------------------------- +// +// BOOLEAN CardCheckAdapter +// +// This routine checks for the presense of the card. +// Initializes a workspace for the adapter at this address. +// Returns TRUE if adapter found. +// +//----------------------------------------------------------------------- + +BOOLEAN CardCheckAdapter (PWORKSPACE w, PINIT init) +{ + PADAPTER_INFO g = (PADAPTER_INFO) w; + UCHAR tmp0,tmp1,tmp2; + UCHAR tmp; + UCHAR rval; + ULONG index; + + // + // Initialize workspace and takes card specific parameter information + // Just the BaseIoAddress for the t13b. + // + + g->BaseIoAddress = init->BaseIoAddress; + + // save old values of control and status + + T128PortGet(g,T128_CONTROL,&tmp0); + T128PortGet(g,T128_STATUS,&tmp1); + + // check the timeout bit of the t128 + + // this should set the timeout bit + + T128PortGet(g,T128_DATA,&tmp2); + + if (!T128PortTest(g,T128_STATUS,SR_TIMEOUT)) { + + // this is not a t128, restore registers + + T128PortPut(g,T128_CONTROL,tmp0); + T128PortPut(g,T128_STATUS,tmp1); + + return FALSE; + } + + // clear timeout condition + + T128PortPut(g,T128_CONTROL,CR_TIMEOUT); + T128PortPut(g,T128_CONTROL,0); + + // + // The t128 has a 32 byte stride on the access to the 5380 registers. + // Taking advantage of this stride a check is first made that each of + // the location in the stride have the same value. After this is + // complete, the same destructive scan is made for the data value as + // for other 5380 based adapters. + // + + N5380PortGet (g, N5380_CURRENT_DATA, &tmp); + + for (index = 0; index < 0x20; index++) { + T128PortGet (g, + T128_5380+(N5380_CURRENT_DATA*0x20)+index, + &rval); + if (rval != tmp) { + return FALSE; + } + } + + N5380PortGet (g, N5380_INITIATOR_COMMAND, &tmp); + + for (index = 0; index < 0x20; index++) { + T128PortGet (g, + T128_5380+(N5380_INITIATOR_COMMAND*0x20)+index, + &rval); + if (rval != tmp) { + return FALSE; + } + } + + N5380PortGet (g, N5380_CURRENT_STATUS, &tmp); + + for (index = 0; index < 0x20; index++) { + T128PortGet (g, + T128_5380+(N5380_CURRENT_STATUS*0x20)+index, + &rval); + if (rval != tmp) { + return FALSE; + } + } + + // + // The non-destructive portion of this has passed. + // NOTE: May want to reset the bus or the adapter at some point + // + // CardResetBus(g); + + // set the phase to NULL + + if (rval = (UCHAR) N5380SetPhase (g,PHASE_NULL)) { + return FALSE; + } + + // check to see that the 5380 data register behaves as expected + + N5380PortPut (g, N5380_INITIATOR_COMMAND, IC_DATA_BUS); + + // check for 0x55 write/read in data register stride + + N5380PortPut (g, N5380_OUTPUT_DATA, 0x55); + ScsiPortStallExecution (1); + for (index = 0; index < 0x20; index++) { + T128PortGet (g, + T128_5380+(N5380_CURRENT_DATA*0x20)+index, + &rval); + if (rval != 0x55) { + return FALSE; + } + } + + // check for 0xaa write/read in data register stride + + N5380PortPut (g, N5380_OUTPUT_DATA, 0xaa); + ScsiPortStallExecution (1); + for (index = 0; index < 0x20; index++) { + T128PortGet (g, + T128_5380+(N5380_CURRENT_DATA*0x20)+index, + &rval); + if (rval != 0xaa) { + return FALSE; + } + } + + // + // It is pretty clear this is a 128, but do one last check for + // the 5380. + // + + N5380PortPut (g, N5380_INITIATOR_COMMAND, 0); + ScsiPortStallExecution (1); + N5380PortGet (g, N5380_CURRENT_DATA, &tmp); + + // data now should not match .... + + if (tmp == 0xaa) { + return FALSE; + } + + return TRUE; +} + +// +// CardParseCommandString(PINIT p, PCHAR str) +// +// Parses the command string to get all card specific parameters. +// Will fill in defaults where no parameters are supplied, or +// if the str pointer is NULL. +// +// Returns false if it could not parse the string given. +// +// Can be used to parse the string piece by piece, by sending +// the same INIT structure each time. Send NULL as the string +// first time to initialize the PINIT structure to the standard defaults. +// +// BaseIoAddress will be set to NULL by default, and the program can +// detect that it has changed during parsing and just search for the +// card as specified by the command line argument if it has changed. If +// it does not change, the program should cycle through all valid addresses. +// +BOOLEAN CardParseCommandString(PINIT init, PCHAR str) +{ + // for now, just fill in some defaults + + init->BaseIoAddress = NULL; + + return TRUE; +} + + +void CardSetInterruptLevel (PADAPTER_INFO g, UCHAR level) +{ + return; +} + + +PUCHAR CardGetName (VOID) +{ + return "T128 SCSI Host Adapter"; +} + + +PUCHAR CardGetShortName (VOID) +{ + return "T128"; +} + + +UCHAR CardGetType (VOID) +{ + return CARDTYPE_T120; +} + + +VOID CardDisableInterrupt (PADAPTER_INFO g) +{ + T128DisableInterrupt(g); +} + + +VOID CardEnableInterrupt (PADAPTER_INFO g) +{ + T128EnableInterrupt (g); +} + + +VOID CardResetBus (PADAPTER_INFO g) +{ + T128ResetBus (g); +} + + diff --git a/private/ntos/miniport/trantor/source/cardt13b.c b/private/ntos/miniport/trantor/source/cardt13b.c new file mode 100644 index 000000000..468aa4e11 --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardt13b.c @@ -0,0 +1,299 @@ +//----------------------------------------------------------------------- +// +// CARDT13B.C +// +// T13B Adapter Specific File +// +// See also cardtxxx.h, cardtxxx.h may redefine some functions with #defines. +// +// Revisions: +// 09-01-92 KJB First. +// 01-08-92 KJB Now use ScsiPortWrite[Read]BufferUshort routines. +// 02-17-93 JAP Cleaned comments. +// 02-18-93 KJB Fixed Cleaned comments. +// 02-24-93 KJB Restructured file. +// 03-22-93 JAP Added arrays for port and IRQ values for NetWare support. +// These are conditionally built if NOVELL is defined. +// 03-22-93 KJB Reorged for functional library interface. +// 03-26-93 JAP Fixed up typedef and prototype inconsistencies +// 04-22-93 JAP Added AdapterInterrupts[] and CardGetIRQ(). +// 05-05-93 KJB Added check of T13B_SWITCH register in CheckAdapter. +// So we won't interfere with a T160. +// 05-12-93 JAP Altered CardGetShortName() to return only +// the type of card. +// 05-13-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 the PBASE_REGISTER and the +// PWORKSPACE parameters. Auto Request Sense is +// now supported. +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// +//----------------------------------------------------------------------- + + +#include CARDTXXX_H + +//----------------------------------------------------------------------- +// The following table specifies the ports to be checked when searching for +// an adapter. A zero entry terminates the search. +//----------------------------------------------------------------------- + +CONST ULONG AdapterAddresses [] = {0X350, 0X340, 0X250, 0X240, 0}; + +#ifdef WINNT +//----------------------------------------------------------------------- +// +// The address ranges the card will use. These are accessed by trantor.c +// to inform NTOS of the resources we are using. +// +//----------------------------------------------------------------------- + +CONST CardAddressRange cardAddressRange [] = +{ + {0x00,0x10,FALSE}, // 0x350 - 0x35f +}; +#endif + + +//------------------------------------------------------------------------ +// The following table specifies the possible interrupts that +// can be used by the adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST USHORT AdapterInterrupts [] = + {3, 5, 7, 0}; + + +//----------------------------------------------------------------------- +// +// The following routines are stub routines to provide an entry +// point for the library. They reference the correct routines for +// the appropriate card. Only these routines may be called from outside +// the library. See the rouines they reference for a description of +// the routines, if the meaning is unclear. +// +//----------------------------------------------------------------------- + +// +// The following is used along with the constant structure in card.c +// to define the precise i/o addresses a card will use +// + +USHORT CardNumberOfAddressRanges (VOID) +{ + return 1; +} + + +// the maximum transfer size +// by decreasing this we can get better system performace since +// the data transfer occurs with interrupts disabled, this might be +// decreased for our smaller cards +// Used only by WINNT + +ULONG CardMaxTransferSize (VOID) +{ + return (32*1024L); +} + + +// the following info is for initialization only +// this card is IO mapped + +BOOLEAN CardAddressRangeInIoSpace (VOID) +{ + return TRUE; +} + + +// we use 16 addresses in IO space + +USHORT CardAddressRangeLength (VOID) +{ + return 16; +} + + +// we use interrupts + +BOOLEAN CardSupportsInterrupts (VOID) +{ + return TRUE; +} + + +// default interrupt level + +UCHAR CardDefaultInterruptLevel (VOID) +{ + return 5; +} + + +USHORT CardStartCommandInterrupt (PTSRB t) +{ + return (ScsiStartCommandInterrupt (t)); +} + + +USHORT CardFinishCommandInterrupt (PTSRB t) +{ + return (ScsiFinishCommandInterrupt (t)); +} + + +USHORT CardDoCommand (PTSRB t) +{ + return (ScsiDoCommand (t)); +} + + +// +// BOOLEAN CardCheckAdapter +// +// Initializes a workspace for the adapter at this address. +// Returns TRUE if adapter found. +// +BOOLEAN CardCheckAdapter (PWORKSPACE w, PINIT init) +{ + PADAPTER_INFO g = (PADAPTER_INFO) w; + UCHAR tmp,tmp0; + + // + // Initialize workspace and takes card specific parameter information + // Just the BaseIoAddress for the t13b. + // + + g->BaseIoAddress = init->BaseIoAddress; + + // + // Do a few sanity check reads to see if there is a possibility an + // adapter is present at this address. + // + + N53C400PortGet(g,N5380_CURRENT_DATA,&tmp); + N53C400PortGet(g,N5380_INITIATOR_COMMAND,&tmp0); + + if (tmp == 0xff && tmp0 == 0xff) { + + // nothing there. + return FALSE; + } + + N53C400PortGet(g,N5380_MODE,&tmp); + N53C400PortGet(g,N5380_TARGET_COMMAND,&tmp0); + + if (((tmp & 0xcf) != 0xcf) || ((tmp0 & 0xcf) != 0xcf)) { + + // mode and command always init as 0xff. This is not a 13b + return FALSE; + } + + // check to see if there is a t160 on this port? + // try to write to the switch register. + + N53C400PortGet(g,T13B_SWITCH,&tmp0); + N53C400PortPut(g,T13B_SWITCH,0x5c); + N53C400PortGet(g,T13B_SWITCH,&tmp); + + // restore original value + + N53C400PortPut(g,T13B_SWITCH,tmp0); + + if (tmp == 0x5c) { + // we have a t160, return false + return FALSE; + } + + return (N53C400CheckAdapter (g)); +} + +// +// CardParseCommandString(PINIT p, PCHAR str) +// +// Parses the command string to get all card specific parameters. +// Will fill in defaults where no parameters are supplied, or +// if the str pointer is NULL. +// +// Returns false if it could not parse the string given. +// +// Can be used to parse the string piece by piece, by sending +// the same INIT structure each time. Send NULL as the string +// first time to initialize the PINIT structure to the standard defaults. +// +BOOLEAN CardParseCommandString(PINIT init, PCHAR str) +{ + // for now, just fill in some defaults + + init->BaseIoAddress = NULL; + + return TRUE; +} + + +BOOLEAN CardInterrupt (PADAPTER_INFO g) +{ + return (N5380Interrupt (g)); +} + + +void CardEnableInterrupt (PADAPTER_INFO g) +{ + N53C400EnableInterrupt (g); +} + + +void CardDisableInterrupt (PADAPTER_INFO g) +{ + N53C400DisableInterrupt (g); +} + + +void CardResetBus (PADAPTER_INFO g) +{ + N53C400ResetBus (g); +} + +PUCHAR CardGetName (VOID) +{ + return "T13B SCSI Host Adapter"; +} + + +PUCHAR CardGetShortName (VOID) +{ + return "T130B"; +} + + +UCHAR CardGetType (VOID) +{ + return CARDTYPE_T130B; +} + + + #ifdef NOVELL +//----------------------------------------------------------------------- +// NOVELL Port and IRQ Tables +// +// Novell needs these defined in a specific format: +// long integer array with the number of entries at head of list. +//----------------------------------------------------------------------- + +// The following table specifies the port values Novell will prompt +// the user with if no port is specified on the LOAD command line. + +CONST ULONG possible_port [] = {4, 0X350, 0X340, 0X250, 0X240}; + +// The following table specifies the IRQ values Novell will prompt +// the user with if no IRQ is specified on the LOAD command line. + +CONST ULONG possible_irq [] = {3, 3, 5, 7}; + + #endif // #ifdef NOVELL + diff --git a/private/ntos/miniport/trantor/source/cardt160.c b/private/ntos/miniport/trantor/source/cardt160.c new file mode 100644 index 000000000..2d22df1be --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardt160.c @@ -0,0 +1,273 @@ +//----------------------------------------------------------------------- +// +// CARDT160.C +// +// T160 Adapter Specific File +// +// See also cardtxxx.h, cardtxxx.h may redefine some functions with #defines. +// +// Revisions: +// 02-24-93 KJB First. +// 03-24-93 KJB Reorged for functional library interface. +// 03-26-93 JAP Fixed up typedef and prototype inconsistencies +// 03-29-93 JAP Added arrays for port and IRQ values for NetWare support. +// These are conditionally built if NOVELL is defined. +// 04-05-93 KJB Fixed definition problem for WINNT. +// Involving CardAddressRange... +// 04-22-93 JAP Added AdapterInterrupts[] and CardGetIRQ(). +// 05-12-93 JAP Altered CardGetShortName() to return only +// the type of card. +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// 05-17-93 KJB Fixed warnings. +// +//----------------------------------------------------------------------- + + +#include CARDTXXX_H + + +//------------------------------------------------------------------------ +// The following table specifies the possible interrupts that +// can be used by the adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST USHORT AdapterInterrupts [] = + {3, 5, 7, 10, 12, 14, 15, 0}; + + +//----------------------------------------------------------------------- +// The following table specifies the ports to be checked when searching for +// an adapter. A zero entry terminates the search. +//----------------------------------------------------------------------- + +CONST ULONG AdapterAddresses [] = + {0X350, 0X340, 0X250, 0X240, 0x330, 0x360, 0x230, 0x260, 0}; + + +#ifdef WINNT +//----------------------------------------------------------------------- +// +// The address ranges the card will use. These are accessed by trantor.c +// to inform NTOS of the resources we are using. +// +//----------------------------------------------------------------------- + +CONST CardAddressRange cardAddressRange [] = +{ + {0x00,0x10,FALSE}, // 0x350 - 0x35f +}; +#endif + + +//----------------------------------------------------------------------- +// +// BOOLEAN CardCheckAdapter +// +// This routine checks for the presense of the card. +// Initializes a workspace for the adapter at this address. +// Returns TRUE if adapter found. +// +//----------------------------------------------------------------------- + +BOOLEAN CardCheckAdapter (PWORKSPACE w, PINIT init) +{ + PADAPTER_INFO g = (PADAPTER_INFO) w; + BOOLEAN rval; + + + // + // Initialize workspace and takes card specific parameter information + // Just the BaseIoAddress for the t13b. + // + + g->BaseIoAddress = init->BaseIoAddress; + + // perform normal PC9010 Check Adapter + + rval = PC9010CheckAdapter(g); + + // if no adapter was found, we could have disrupted a t13b + // is the following necessary? + + if (!rval) { + + // reset the 53c400 of the t13b, if we messed it up + // n53c400 reset reg same as PC9010 config reg + // WARNING - Could be destructive to other cards... + + PC9010PortSet(g,PC9010_CONFIG,0x80); + PC9010PortSet(g,PC9010_CONFIG,0); + + } + + return rval; +} + + +// +// CardParseCommandString(PINIT p, PCHAR str) +// +// Parses the command string to get all card specific parameters. +// Will fill in defaults where no parameters are supplied, or +// if the str pointer is NULL. +// +// Returns false if it could not parse the string given. +// +// Can be used to parse the string piece by piece, by sending +// the same INIT structure each time. Send NULL as the string +// first time to initialize the PINIT structure to the standard defaults. +// +BOOLEAN CardParseCommandString(PINIT init, PCHAR str) +{ + // for now, just fill in some defaults + + init->BaseIoAddress = NULL; + + return TRUE; +} + +// +// The following is used along with the constant structure in card.c +// to define the precise i/o addresses a card will use +// + +USHORT CardNumberOfAddressRanges (VOID) +{ + return 1; +} + + +// the maximum transfer size +// by decreasing this we can get better system performace since +// the data transfer occurs with interrupts disabled, this might be +// decreased for our smaller cards +// Used only by WINNT + +ULONG CardMaxTransferSize (VOID) +{ + return (32*1024L); +} + + +// the following info is for initialization only +// this card is IO mapped + +BOOLEAN CardAddressRangeInIoSpace (VOID) +{ + return TRUE; +} + + +// we use 16 addresses in IO space + +USHORT CardAddressRangeLength (VOID) +{ + return 16; +} + + +// we use interrupts + +BOOLEAN CardSupportsInterrupts (VOID) +{ + return TRUE; +} + + +// default interrupt level + +UCHAR CardDefaultInterruptLevel (VOID) +{ + return 12; +} + + +USHORT CardStartCommandInterrupt (PTSRB t) +{ + return (ScsiStartCommandInterrupt (t)); +} + + +USHORT CardFinishCommandInterrupt (PTSRB t) +{ + return (ScsiFinishCommandInterrupt (t)); +} + + +USHORT CardDoCommand (PTSRB t) +{ + return (ScsiDoCommand (t)); +} + + +BOOLEAN CardInterrupt (PADAPTER_INFO g) +{ + return (N5380Interrupt (g)); +} + + +VOID CardEnableInterrupt (PADAPTER_INFO g) +{ + PC9010EnableInterrupt (g); +} + + +VOID CardDisableInterrupt (PADAPTER_INFO g) +{ + PC9010DisableInterrupt (g); +} + + +VOID CardResetBus (PADAPTER_INFO g) +{ + PC9010ResetBus (g); +} + + +VOID CardSetInterruptLevel (PADAPTER_INFO g, UCHAR level) +{ + return; +} + + +PUCHAR CardGetName (VOID) +{ + return "T160 16-Bit SCSI Host Adapter"; +} + + +PUCHAR CardGetShortName (VOID) +{ + return "T160"; +} + + +UCHAR CardGetType (VOID) +{ + return CARDTYPE_T160; +} + + + #ifdef NOVELL +//----------------------------------------------------------------------- +// NOVELL Port and IRQ Tables +// +// Novell needs these defined in a specific format: +// long integer array with the number of entries at head of list. +//----------------------------------------------------------------------- + +// The following table specifies the port values Novell will prompt +// the user with if no port is specified on the LOAD command line. + +CONST ULONG possible_port [] = + {8, 0x350, 0x340, 0x250, 0x240, 0x330, 0x360, 0x230, 0x260}; + +// The following table specifies the IRQ values Novell will prompt +// the user with if no IRQ is specified on the LOAD command line. + +CONST ULONG possible_irq [] = {7, 3, 5, 7, 10, 12, 14, 15}; + + #endif // #ifdef NOVELL + + + diff --git a/private/ntos/miniport/trantor/source/cardt338.c b/private/ntos/miniport/trantor/source/cardt338.c new file mode 100644 index 000000000..d0b69a42f --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardt338.c @@ -0,0 +1,246 @@ +//----------------------------------------------------------------------- +// +// CARDT338.C +// +// T338 Adapter Specific File +// +// See also cardtxxx.h, cardtxxx.h may redefine some functions with #defines. +// +// Revisions: +// 02-01-93 KJB First. +// 02-25-93 KJB Reorganized, supports dataunderrun with long delay +// for under run on large xfers. Can we fix this? +// 03-22-93 KJB Reorged for functional library interface. +// 03-26-93 JAP Fixed up typedef and prototype inconsistencies +// 04-22-93 JAP Added AdapterInterrupts[] and CardGetIRQ(). +// 05-12-93 JAP Altered CardGetShortName() to return only +// the type of card. +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// 05-17-93 KJB Fixed compiler warnings. +// +//----------------------------------------------------------------------- + + +#include CARDTXXX_H + + +#ifdef WINNT +// +// The address ranges the card will use. These are accessed by trantor.c +// to inform NTOS of the resources we are using. +// +CONST CardAddressRange cardAddressRange[] = + { + {0x00,0x03,FALSE}, // 0x3bc - 0x3be + }; +#endif + + +//------------------------------------------------------------------------ +// The following table specifies the possible interrupts that +// can be used by the adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST USHORT AdapterInterrupts [] = {0}; // no interrupts + + +//------------------------------------------------------------------------ +// The following table specifies the ports to be checked when searching for +// an adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST ULONG AdapterAddresses[] = {0X3bc, 0X378, 0X278,0}; + + +//----------------------------------------------------------------------- +// +// The following routines are stub routines to provide an entry +// point for the library. They reference the correct routines for +// the appropriate card. Only these routines may be called from outside +// the library. See the rouines they reference for a description of +// the rouines, if the meaning is unclear. +// +//----------------------------------------------------------------------- + +// the maximum transfer size +// by decreasing this we can get better system performace since +// the data transfer occurs with interrupts disabled, this might be +// decreased for our smaller cards +// Used only by WINNT + +ULONG CardMaxTransferSize (VOID) +{ + return 8*1024L; +} + + +// the following info is for initialization only +// the t348 is IO mapped + +BOOLEAN CardAddressRangeInIoSpace (VOID) +{ + return TRUE; +} + + +// we use 3 addresses in IO space + +USHORT CardAddressRangeLength (VOID) +{ + return 0x3; +} + + +// The following is used along with the constant structure in card.c +// to define the precise i/o addresses a card will use + +USHORT CardNumberOfAddressRanges (VOID) +{ + return 1; +} + + +// the t348 does not use interrupts + +BOOLEAN CardSupportsInterrupts (VOID) +{ + return FALSE; +} + + +// for now, must choose an interupt that doesn't conflict +// microsoft: jeff said later they will have a method + +UCHAR CardDefaultInterruptLevel (VOID) +{ + return 15; +} + +//----------------------------------------------------------------------- +// +// Redefined routines +// +//----------------------------------------------------------------------- + +// These are card specific routines, but since this card has a 5380, we +// will redefine these to the generic n5380 or other routines. + + +//----------------------------------------------------------------------- +// +// BOOLEAN CardCheckAdapter +// +// This routine checks for the presense of the card. +// Initializes a workspace for the adapter at this address. +// Returns TRUE if adapter found. +// +//----------------------------------------------------------------------- + +BOOLEAN CardCheckAdapter (PWORKSPACE w, PINIT init) +{ + PADAPTER_INFO g = (PADAPTER_INFO) w; + + // + // Initialize workspace and takes card specific parameter information + // Just the BaseIoAddress for the t13b. + // + + g->BaseIoAddress = init->BaseIoAddress; + + return (T338CheckAdapter (g)); +} + +// +// CardParseCommandString(PINIT p, PCHAR str) +// +// Parses the command string to get all card specific parameters. +// Will fill in defaults where no parameters are supplied, or +// if the str pointer is NULL. +// +// Returns false if it could not parse the string given. +// +// Can be used to parse the string piece by piece, by sending +// the same INIT structure each time. Send NULL as the string +// first time to initialize the PINIT structure to the standard defaults. +// +// BaseIoAddress will be set to NULL by default, and the program can +// detect that it has changed during parsing and just search for the +// card as specified by the command line argument if it has changed. If +// it does not change, the program should cycle through all valid addresses. +// +BOOLEAN CardParseCommandString(PINIT init, PCHAR str) +{ + // for now, just fill in some defaults + + init->BaseIoAddress = NULL; + + return TRUE; +} + + +BOOLEAN CardInterrupt (PADAPTER_INFO g) +{ + return (T338Interrupt (g)); +} + + +VOID CardResetBus (PADAPTER_INFO g) +{ + T338ResetBus (g); +} + + +VOID CardDisableInterrupt (PADAPTER_INFO g) +{ + N5380DisableInterrupt (g); +} + + +VOID CardEnableInterrupt (PADAPTER_INFO g) +{ + N5380EnableInterrupt (g); +} + + +VOID CardSetInterruptLevel (PADAPTER_INFO g, UCHAR level) +{ + return; +} + + +USHORT CardDoCommand (PTSRB t) +{ + return (T338DoCommand (t)); +} + + +USHORT CardStartCommandInterrupt (PTSRB t) +{ + return (T338StartCommandInterrupt (t)); +} + + +USHORT CardFinishCommandInterrupt (PTSRB t) +{ + return (T338FinishCommandInterrupt (t)); +} + + +PUCHAR CardGetName (VOID) +{ + return "T338 SCSI Host Adapter"; +} + + +PUCHAR CardGetShortName (VOID) +{ + return "T338"; +} + + +UCHAR CardGetType (VOID) +{ + return CARDTYPE_T338; +} + + diff --git a/private/ntos/miniport/trantor/source/cardt348.c b/private/ntos/miniport/trantor/source/cardt348.c new file mode 100644 index 000000000..4d2976514 --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardt348.c @@ -0,0 +1,220 @@ +//------------------------------------------------------------------------ +// +// CARDT348.C +// +// T348 Adapter Specific File +// +// See also cardtxxx.h, cardtxxx.h may redefine some functions with #defines. +// +// Revisions: +// 09-01-92 KJB First. +// 02-25-93 KJB Reorganized, supports dataunderrun with long delay +// for under run on large xfers. Can we fix this? +// 03-22-93 KJB Reorged for functional library interface. +// 03-26-93 JAP Fixed up prototype typedef inconsistencies +// 04-05-93 KJB Fixed definition problem for WINNT. +// Involving CardAddressRange... +// 04-22-93 JAP Added AdapterInterrupts[] and CardGetIRQ(). +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// 05-17-93 KJB Fixed warning message. +// +//------------------------------------------------------------------------ + + +#include CARDTXXX_H + +#ifdef WINNT +// +// The address ranges the card will use. These are accessed by trantor.c +// to inform NTOS of the resources we are using. +// +CONST CardAddressRange cardAddressRange[] = + { + {0x00,0x03,FALSE}, // 0x3bc - 0x3be + }; +#endif + + +//------------------------------------------------------------------------ +// The following table specifies the possible interrupts that +// can be used by the adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST USHORT AdapterInterrupts [] = {0}; // no interrupts + + +//------------------------------------------------------------------------ +// The following table specifies the ports to be checked when searching for +// an adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST ULONG AdapterAddresses [] = {0X3bc, 0X378, 0X278, 0}; + + +//----------------------------------------------------------------------- +// +// The following routines are stub routines to provide an entry +// point for the library. They reference the correct routines for +// the appropriate card. Only these routines may be called from outside +// the library. See the rouines they reference for a description of +// the rouines, if the meaning is unclear. +// +//----------------------------------------------------------------------- + +//------------------------------------------------------------------------ +// the maximum transfer size +// by decreasing this we can get better system performace since +// the data transfer occurs with interrupts disabled, this might be +// decreased for our smaller cards +// Used only by WINNT +//------------------------------------------------------------------------ + +ULONG CardMaxTransferSize(VOID) +{ + return 2*1024L; +} + + +// the following info is for initialization only +// the t348 is IO mapped + +BOOLEAN CardAddressRangeInIoSpace(VOID) +{ + return TRUE; +} + + +// we use 3 addresses in IO space + +USHORT CardAddressRangeLength(VOID) +{ + return 3; +} + + +// The following is used along with the constant structure in card.c +// to define the precise i/o addresses a card will use + +USHORT CardNumberOfAddressRanges(VOID) +{ + return 1; +} + + +// the t348 does not use interrupts + +BOOLEAN CardSupportsInterrupts(VOID) +{ + return FALSE; +} + +// for now, must choose an interupt that doesn't conflict +// microsoft: jeff said later they will have a method + +UCHAR CardDefaultInterruptLevel(VOID) +{ + return 15; +} + +USHORT CardDoCommand(PTSRB t) +{ + return P3CDoCommand(t); +} +USHORT CardFinishCommandInterrupt(PTSRB t) +{ + return P3CFinishCommandInterrupt(t); +} +USHORT CardStartCommandInterrupt(PTSRB t) +{ + return P3CStartCommandInterrupt(t); +} + +// +// BOOLEAN CardCheckAdapter +// +// Initializes a workspace for the adapter at this address. +// Returns TRUE if adapter found. +// +BOOLEAN CardCheckAdapter (PWORKSPACE w, PINIT init) +{ + PADAPTER_INFO g = (PADAPTER_INFO) w; + + // + // Initialize workspace and takes card specific parameter information + // to set how the card will be used. For example, command line information + // to force the parallel port to bi-directional or uni-directional modes. + // + + // if no init structure, use all defaults + if (init) { + g->ParallelPortType = init->ParallelPortType; + } else { + g->ParallelPortType = PT_UNKNOWN; + } + + g->BaseIoAddress = init->BaseIoAddress; + + return P3CCheckAdapter(g); +} + +// +// CardParseCommandString(PINIT p, PCHAR str) +// +// Parses the command string to get all card specific parameters. +// Will fill in defaults where no parameters are supplied, or +// if the str pointer is NULL. +// +// Returns false if it could not parse the string given. +// +// Can be used to parse the string piece by piece, by sending +// the same INIT structure each time. Send NULL as the string +// first time to initialize the PINIT structure to the standard defaults. +// +// BaseIoAddress will be set to NULL by default, and the program can +// detect that it has changed during parsing and just search for the +// card as specified by the command line argument if it has changed. If +// it does not change, the program should cycle through all valid addresses. +// +BOOLEAN CardParseCommandString(PINIT init, PCHAR str) +{ + // for now, just fill in some defaults + + init->ParallelPortType = PT_UNKNOWN; + init->BaseIoAddress = NULL; + + return TRUE; +} + +BOOLEAN CardInterrupt(PADAPTER_INFO g) +{ + return P3CInterrupt(g); +} +VOID CardDisableInterrupt(PADAPTER_INFO g) +{ + N5380DisableInterrupt(g); +} +VOID CardEnableInterrupt(PADAPTER_INFO g) +{ + N5380EnableInterrupt(g); +} +VOID CardResetBus(PADAPTER_INFO g) +{ + P3CResetBus(g); +} +VOID CardSetInterruptLevel(PADAPTER_INFO g,UCHAR level) +{ + return; +} +PUCHAR CardGetName(VOID) +{ + return "T348 SCSI Host Adapter"; +} +PUCHAR CardGetShortName(VOID) +{ + return "T348.1.0"; +} +UCHAR CardGetType(VOID) +{ + return CARDTYPE_T348; +} + diff --git a/private/ntos/miniport/trantor/source/cardtmv1.c b/private/ntos/miniport/trantor/source/cardtmv1.c new file mode 100644 index 000000000..152213c2c --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardtmv1.c @@ -0,0 +1,266 @@ +//------------------------------------------------------------------------- +// +// CARDTMV1.C +// +// TMV1 Adapter Specific File +// +// See also cardtxxx.h, cardtxxx.h may redefine some functions with #defines. +// +// Revisions: +// 09-01-92 KJB First. +// 03-26-93 JAP Fixed up typedef and prototype inconsistencies +// 04-05-93 KJB Fixed definition problem for WINNT. +// Involving CardAddressRange... +// 04-22-93 JAP Added AdapterInterrupts[] and CardGetIRQ(). +// 05-05-93 KJB Fixed CardSetInterruptLevel so that it calls +// MV101SetInterruptLevel like it should. +// 05-12-93 JAP Altered CardGetShortName() to return only +// the type of card. +// 05-13-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 the PBASE_REGISTER and the +// PWORKSPACE parameters. Auto Request Sense is +// now supported. +// 05-13-93 KJB Merged Microsoft Bug fixes to card detection. +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// 05-17-93 KJB CardAddressRangeLength now return 0xffff. +// Fixed compiler warnings. +// +//------------------------------------------------------------------------- + + +#include CARDTXXX_H + +#ifdef WINNT +//------------------------------------------------------------------------ +// The address ranges the card will use. These are accessed by trantor.c +// to inform NTOS of the resources we are using. +//------------------------------------------------------------------------ +CONST CardAddressRange cardAddressRange[] = + { + {0x1c00,0x04,FALSE}, // 0x1f88 + {0x3c00,0x04,FALSE}, // 0x3f88 + {0x4000,0x02,FALSE}, // 0x4388 + {0x5c00,0x04,FALSE}, // 0x5f88 + {0x8003,0x01,FALSE}, // 0x838b + {0xbc00,0x01,FALSE} // 0xbf88 + }; +#endif + + +//------------------------------------------------------------------------ +// The following table specifies the possible interrupts that +// can be used by the adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST USHORT AdapterInterrupts [] = + {2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 15, 0}; + + +//------------------------------------------------------------------------ +// The following table specifies the ports to be checked when searching for +// an adapter. A zero entry terminates the search. +//------------------------------------------------------------------------ + +CONST ULONG AdapterAddresses[] = + {0x388, 0x384, 0x38C, 0x288, 0x280, 0x284, 0x28C, 0x0}; + + +//----------------------------------------------------------------------- +// +// The following routines are stub routines to provide an entry +// point for the library. They reference the correct routines for +// the appropriate card. Only these routines may be called from outside +// the library. See the rouines they reference for a description of +// the rouines, if the meaning is unclear. +// +//----------------------------------------------------------------------- + +//------------------------------------------------------------------------ +// the maximum transfer size +// by decreasinge this we can get better system performace since +// the data transfer occurs with interrupts disabled, this might be +// decreased for our smaller cards +// Used only by WINNT +//------------------------------------------------------------------------ + +ULONG CardMaxTransferSize (VOID) +{ + return 16*1024L; +} + + +// we use interrupts + +BOOLEAN CardSupportsInterrupts (VOID) +{ + return TRUE; +} + + +// default interrupt number is 10 + +UCHAR CardDefaultInterruptLevel (VOID) +{ + return 15; +} + + +// the following info is for initialization only +// this card is memory mapped + +BOOLEAN CardAddressRangeInIoSpace (VOID) +{ + return TRUE; +} + + +// we use 0x10000 bytes in memory space + +USHORT CardAddressRangeLength (VOID) +{ +// return 0x10000; + return 0xffff; +} + + +// The following is used along with the constant structure in card.c +// to define the precise i/o addresses a card will use + +USHORT CardNumberOfAddressRanges (VOID) +{ + return 0; +} + + +USHORT CardStartCommandInterrupt (PTSRB t) +{ + return (ScsiStartCommandInterrupt (t)); +} + + +USHORT CardFinishCommandInterrupt (PTSRB t) +{ + return (ScsiFinishCommandInterrupt (t)); +} + +USHORT CardDoCommand (PTSRB t) +{ + return (ScsiDoCommand (t)); +} + +// +// BOOLEAN CardCheckAdapter +// +// Initializes a workspace for the adapter at this address. +// Returns TRUE if adapter found. +// +BOOLEAN CardCheckAdapter (PWORKSPACE w, PINIT init) +{ + PADAPTER_INFO g = (PADAPTER_INFO) w; + BOOLEAN rval; + + // + // Initialize workspace and takes card specific parameter information + // to set how the card will be used. For example, command line info + // to force the parallel port to bi-directional or uni-directional modes. + // + + g->BaseIoAddress = init->BaseIoAddress; + + // if no init structure, use all defaults + + if (init) { + g->InterruptLevel = init->InterruptLevel; + } else { + g->InterruptLevel = CardDefaultInterruptLevel(); + } + + rval = MV101CheckAdapter (g); + + // if card found, set interrupt level + + if (rval) { + + MV101SetInterruptLevel (g, g->InterruptLevel); + } + + return rval; +} + +// +// CardParseCommandString(PINIT p, PCHAR str) +// +// Parses the command string to get all card specific parameters. +// Will fill in defaults where no parameters are supplied, or +// if the str pointer is NULL. +// +// Returns false if it could not parse the string given. +// +// Can be used to parse the string piece by piece, by sending +// the same INIT structure each time. Send NULL as the string +// first time to initialize the PINIT structure to the standard defaults. +// +// BaseIoAddress will be set to NULL by default, and the program can +// detect that it has changed during parsing and just search for the +// card as specified by the command line argument if it has changed. If +// it does not change, the program should cycle through all valid addresses. +// +BOOLEAN CardParseCommandString(PINIT init, PCHAR str) +{ + // for now, just fill in some defaults + + init->InterruptLevel = CardDefaultInterruptLevel(); + init->BaseIoAddress = NULL; + + return TRUE; +} + + +VOID CardEnableInterrupt (PADAPTER_INFO g) +{ + MV101EnableInterrupt (g); +} + + +VOID CardDisableInterrupt (PADAPTER_INFO g) +{ + MV101DisableInterrupt (g); +} + + +BOOLEAN CardInterrupt (PADAPTER_INFO g) +{ + return (N5380Interrupt (g)); +} + + +VOID CardResetBus (PADAPTER_INFO g) +{ + N5380ResetBus (g); +} + + +PUCHAR CardGetName (VOID) +{ + return "Media Vision Pro Audio Spectrum"; +} + + +PUCHAR CardGetShortName (VOID) +{ + return "Pro Audio"; +} + + +UCHAR CardGetType (VOID) +{ + return CARDTYPE_TMV1; +} + + diff --git a/private/ntos/miniport/trantor/source/cardutil.c b/private/ntos/miniport/trantor/source/cardutil.c new file mode 100644 index 000000000..ef0a4b151 --- /dev/null +++ b/private/ntos/miniport/trantor/source/cardutil.c @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------- +// +// CARDUTIL.C +// +// Utility File for all common card routines. +// +// History: +// +// 02-20-93 KJB/SG First, Placed SG's CardGetNumber function here. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// 05-12-93 JAP Added version control information. +// This file should be updated changing the version numbers +// on EACH significant change to ANY low-level driver. +// The cause of upping a version should be placed in this +// files history. (currently Version 1.0) +// 05-12-93 KJB Moved code from cardtxxx.c to here. +// 05-12-93 KJB Fixed bugs in CardGetVersion. +// 05-15-93 KJB Fixed warnings in CardGetNumber. +// +//------------------------------------------------------------------------- + +#include CARDTXXX_H + +#define CDRIVER_MAJOR_VERSION 1 +#define CDRIVER_MINOR_VERSION 0 + +// +// Static constant arrays defined in cardtxxx.c +// +extern PBASE_REGISTER AdapterAddresses[]; +extern USHORT AdapterInterrupts[]; + +//----------------------------------------------------------------------- +// CardGetVersion() +// +// Return the CDRIVER version number values. +// +// Input: Pointer to ULONG to be filled with major version number +// Pointer to ULONG to be filled with minor version number +// +// Output: None. Major and minor version variables are filled. +//----------------------------------------------------------------------- + +VOID CardGetVersion (PULONG pMajorVersion, PULONG pMinorVersion) +{ + *pMajorVersion = CDRIVER_MAJOR_VERSION; + *pMinorVersion = CDRIVER_MINOR_VERSION; +} + + +//----------------------------------------------------------------------- +// CardGetNumber () +// +// Returns the index number of the given adapter address from the +// AdapterAddresses table. +// Return -1, if the address is not found in the table. +//----------------------------------------------------------------------- + +USHORT CardGetNumber (PBASE_REGISTER basePort) +{ + USHORT i; + + for (i = 0; AdapterAddresses [i] != 0; i++) { + if (AdapterAddresses [i] == basePort) + return i; + } + + return 0xffff; +} + +//----------------------------------------------------------------------- +// +// CardGetWorkspaceSize +// +//----------------------------------------------------------------------- +USHORT CardGetWorkspaceSize(void ) +{ + return sizeof (ADAPTER_INFO); +} + +//------------------------------------------------------------------------ +// CardGetIRQ +// +// Returns the nth possible adapter interrupt. +// Returns 0 when the last possible interrupt has been exceeded. +//------------------------------------------------------------------------ + +USHORT CardGetIRQ (USHORT i) +{ + return AdapterInterrupts [i]; +} + + +//------------------------------------------------------------------------ +// CardAddress +// +// Returns the nth adapter address. +// Returns 0 when the last address has been exceeded. +//------------------------------------------------------------------------ + +PBASE_REGISTER CardAddress (USHORT i) +{ + return ((PBASE_REGISTER)AdapterAddresses [i]); +} + +//----------------------------------------------------------------------- +// End Of File. +//----------------------------------------------------------------------- + + diff --git a/private/ntos/miniport/trantor/source/ep3c.c b/private/ntos/miniport/trantor/source/ep3c.c new file mode 100644 index 000000000..d0a960136 --- /dev/null +++ b/private/ntos/miniport/trantor/source/ep3c.c @@ -0,0 +1,1418 @@ +//----------------------------------------------------------------------- +// +// EP3C.C +// +// Trantor EP3C access file. +// +// Revisions: +// 03-31-93 KJB First. +// 04-09-93 KJB Changed "in edx,al" and "out edx,al" references to +// use only the dx register: in al,dx. +// Changed loop instructions to dec ecx, jnz. +// 04-21-93 KJB Fixed initialization error for os/2: static +// variables must be initialized. +// 05-05-93 KJB Disable Checking for EPP port for debug purposes. +// TEMPORARY. +// 05-05-93 KJB Added ReadFifoUni/BiDirSlow routines to do P_BUSY +// checking to allow bytes to get ready. +// 05-11-93 KJB Added WriteFifoUniDirSlow routine to do P_BUSY +// checking to allow bytes to get ready. +// 05-17-93 JAP Made in-line assemble routines conditionally coded. +// Only #ifdef WINNT will these routines be read in. +// Otherwise, look in ep3c2.asm. +// 05-17-93 KJB Fixed some compiler warnings. +// +//----------------------------------------------------------------------- + +#include CARDTXXX_H + +// Local Functions + +VOID EP3CSetPrinterMode(PADAPTER_INFO g, UCHAR data, UCHAR control); +VOID EP3CSetScsiMode(PADAPTER_INFO g, PUCHAR data, PUCHAR control); + +USHORT EP3CReadBytesFastBiDir(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase); +USHORT EP3CReadBytesFastUniDir(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase); +VOID EP3CSetRegisterUniDir(PADAPTER_INFO g, UCHAR reg); +VOID EP3CSetRegisterEPP(PADAPTER_INFO g, UCHAR reg); +BOOLEAN EP3CCheckAdapterType(PADAPTER_INFO g); +VOID EP3CSetParallelPortType(PADAPTER_INFO g); + +VOID EP3CReadFifoUniDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes); +VOID EP3CReadFifoBiDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes); +VOID EP3CReadFifoEPP(PBASE_REGISTER baseIoAddress, PUCHAR pbytes); +VOID EP3CWriteFifoUniDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes); +VOID EP3CWriteFifoEPP(PBASE_REGISTER baseIoAddress, PUCHAR pbytes); + +// for writes, uni-directional is the same as bi-directional + +#define EP3CSetRegisterBiDir EP3CSetRegisterUniDir +#define EP3CWriteFifoBiDir EP3CWriteFifoUniDir +#define EP3CWriteDataRegisterBiDir EP3CWriteDataRegisterUniDir +#define EP3CWriteControlRegisterBiDir EP3CWriteControlRegisterUniDir + +/// for control registers, epp is the same as bi-dir + +#define EP3CWriteControlRegisterEPP EP3CWriteControlRegisterBiDir +#define EP3CReadControlRegisterEPP EP3CReadControlRegisterBiDir + +// local redefinitions + +#define EP3CPortPut(g, reg, value) \ + (*(g->EP3CWriteControlRegister))(g,reg,value) + +#define EP3CPortGet(g, reg, value) \ + (*(g->EP3CReadControlRegister))(g, value) + +// +// VOID EP3CPortSet +// +// Or's bits into an EP3C register. +// +VOID EP3CPortSet(PADAPTER_INFO g, UCHAR reg, UCHAR value) +{ + UCHAR tmp; + + EP3CPortGet(g,reg,&tmp); + tmp |= value; + EP3CPortPut(g,reg,tmp); +} + +// +// VOID EP3CPortClear +// +// Clears all bits in the EP3C register with value. +// +VOID EP3CPortClear(PADAPTER_INFO g, UCHAR reg, UCHAR value) +{ + UCHAR tmp; + + EP3CPortGet(g,reg,&tmp); + tmp &= (value ^ 0xff); + EP3CPortPut(g,reg,tmp); +} + +// +// VOID EP3CPortTest +// +// Tests bits in value with the EP3C register. +// +BOOLEAN EP3CPortTest(PADAPTER_INFO g, UCHAR reg, UCHAR value) +{ + UCHAR tmp; + + EP3CPortGet(g,reg,&tmp); + return (tmp & value); +} + +// +// VOID EP3CSetRegisterUniDir(PADAPTER_INFO g, UCHAR reg) +// +// Sets the register that will be accessed. +// +VOID EP3CSetRegisterUniDir(PADAPTER_INFO g, UCHAR reg) +{ + UCHAR tmp; + + // write to adr reg 1 + + tmp = (reg & EP3C_ADRS); + EP3CPortPut(g,EP3C_AREG1,tmp); +} + +// +// VOID EP3CSetRegisterEPP(PADAPTER_INFO g, UCHAR reg) +// +// Sets the register that will be accessed. +// +VOID EP3CSetRegisterEPP(PADAPTER_INFO g, UCHAR reg) +{ + ParallelPortPut(g->BaseIoAddress,EPP_AUTO_ADDRESS,reg); +} + +// +// VOID EP3CWriteControlRegisterUniDir +// +// Writes to an adr register of the ep3c using a uni-directional port. +// +VOID EP3CWriteControlRegisterUniDir(PADAPTER_INFO g, UCHAR areg, + UCHAR value) +{ + UCHAR tmp; + + // output the value and register to the parallel data reg + tmp = value | areg; + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,tmp); + + // write to ep3c + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & (0xff ^ P_BUFEN); + tmp = tmp | P_STB; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + tmp = tmp | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // negate P_STB & P_SLC, to end write + + tmp = tmp & (0xff ^ (P_STB | P_SLC)); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // note: we leave P_BUFEN asserted. +} + +// +// VOID EP3CReadControlRegisterBiDir +// +// Reads from an adr register of the ep3c using a bi-directional port. +// NOTE: always read areg1 since areg2 is write-only. +// +VOID EP3CReadControlRegisterBiDir(PADAPTER_INFO g, PUCHAR value) +{ + UCHAR tmp; + + // negate P_BUFEN and assert P_SLC + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp | P_BUFEN | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read data register + + ParallelPortGet(g->BaseIoAddress,PARALLEL_DATA,value); + + // negate P_BUFEN and negate P_SLC + + tmp = (tmp & ((P_SLC | P_BUFEN) ^ 0xff)); +// tmp = (tmp & (P_SLC ^ 0xff)) | P_BUFEN; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// VOID EP3CReadControlRegisterUniDir +// +// Reads from an adr register of the ep3c using a uni-directional port. +// NOTE: always read areg1 since areg2 is write-only. +// +VOID EP3CReadControlRegisterUniDir(PADAPTER_INFO g, PUCHAR value) +{ + UCHAR tmp; + UCHAR tmp1; + + // select high nibble + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0x80); + + // assert P_BUFEN and assert P_SLC + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & (P_BUFEN ^ 0xff) | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read high nibble + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&tmp); + + // compute high nibble + tmp = (tmp << 1) & 0xf0; + + // select low nibble + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0x00); + + // read low nibble + + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&tmp1); + + // compute low nibble + + tmp1 = (tmp1 >> 3) & 0x0f; + + // compute and return byte + + *value = tmp1 | tmp; + + // leave P_BUFEN asserted, negate P_SLC + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & ((P_BUFEN | P_SLC) ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// VOID EP3CReadDataRegisterUniDir +// +// Reads a byte from a register thru the ep3c, using uni-dir mode. +// +VOID EP3CReadDataRegisterUniDir(PADAPTER_INFO g, + UCHAR reg, PUCHAR byte) +{ + UCHAR tmp; + UCHAR tmp1; + + // set the register we want to access + + (*(g->EP3CSetRegister))(g, reg); + + // select high nibble + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0x80); + + // assert P_BUFEN and assert P_AFX + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & (P_BUFEN ^ 0xff) | P_AFX; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read high nibble + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&tmp); + + // compute high nibble + tmp = (tmp << 1) & 0xf0; + + // select low nibble + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0x00); + + // read low nibble + + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&tmp1); + + // compute low nibble + + tmp1 = (tmp1 >> 3) & 0x0f; + + // compute and return byte + + *byte = tmp1 | tmp; + + // leave P_BUFEN asserted, negate P_AFX + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & ((P_BUFEN | P_AFX) ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + +} + +// +// VOID EP3CReadDataRegisterBiDir +// +// Reads a byte from a register thru the EP3C, using bi-dir mode. +// +VOID EP3CReadDataRegisterBiDir(PADAPTER_INFO g, + UCHAR reg, PUCHAR byte) +{ + UCHAR tmp; + + // set the register we want to access + + (*(g->EP3CSetRegister))(g, reg); + + // negate P_BUFEN, assert P_AFX + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp | P_BUFEN | P_AFX; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read the data byte + + ParallelPortGet(g->BaseIoAddress,PARALLEL_DATA,byte); + + // negate P_BUFEN, and P_AFX + + tmp = tmp & ((P_BUFEN | P_AFX) ^ 0xff); +// tmp = tmp | P_BUFEN & (P_AFX ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// VOID EP3CReadDataRegisterEPP +// +// Reads a byte from a register thru the EP3C, using epp mode. +// +VOID EP3CReadDataRegisterEPP(PADAPTER_INFO g, + UCHAR reg, PUCHAR byte) +{ + // set the register we want to access + + (*(g->EP3CSetRegister))(g, reg); + + // read the data byte + + ParallelPortGet(g->BaseIoAddress,EPP_AUTO_DATA,byte); + +} + +// +// VOID EP3CWriteDataRegisterUniDir +// +// Writes the a register thru the EP3C. +// +VOID EP3CWriteDataRegisterUniDir(PADAPTER_INFO g, + UCHAR reg, UCHAR byte) +{ + UCHAR tmp; + + // set the register we want to access + + (*(g->EP3CSetRegister))(g, reg); + + // output the byte on the data lines + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,byte); + + // assert P_BUFEN and P_STB + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & (0xff ^ P_BUFEN) | P_STB; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // assert P_AFX + + tmp = tmp | P_AFX; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // negate P_STB & P_AFX, to end write + + tmp = tmp & (0xff ^ (P_STB | P_AFX)); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // negate P_BUFEN + +// tmp = tmp | P_BUFEN; +// ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// VOID EP3CWriteDataRegisterEPP +// +// Writes the a register thru the EP3C. +// +VOID EP3CWriteDataRegisterEPP(PADAPTER_INFO g, + UCHAR reg, UCHAR byte) +{ + // set the register we want to access + + (*(g->EP3CSetRegister))(g, reg); + + // output the byte on the data lines + + ParallelPortPut(g->BaseIoAddress,EPP_AUTO_DATA,byte); + +} + +// +// VOID EP3CReadFifoEPP +// +// Reads bytes for epp parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +VOID EP3CReadFifoEPP(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + ScsiPortReadPortBufferUshort ( + (PUSHORT)&(((PUCHAR)baseIoAddress)[EPP_AUTO_DATA]), + (PUSHORT)pbytes, 64); +} + + +// +// VOID EP3CWriteFifoEPP +// +// Writes bytes thru epp parallel port to the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// + +VOID EP3CWriteFifoEPP(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + ScsiPortWritePortBufferUshort ( + (PUSHORT)&(((PUCHAR)baseIoAddress)[EPP_AUTO_DATA]), + (PUSHORT)pbytes, 64); +} + +// +// VOID EP3CDisableInterrupt +// +// Disables the interrupt. +// + +VOID EP3CDisableInterrupt(PADAPTER_INFO g) +{ + // set global flag for EP3CSetPrinterMode + g->EnableInterrupt = FALSE; + + // see if the EP3C_IRQEN is asserted, if so clear it + if (EP3CPortTest(g,EP3C_AREG1,EP3C_IRQEN)) { + + // clear the interrupts + // NOTE: a positive going edge toggles the state of EP3C_IRQEN + + EP3CPortSet(g, EP3C_AREG1, EP3C_IRQEN); + EP3CPortClear(g, EP3C_AREG1, EP3C_IRQEN); + } + + // finally, we can disable the core interrupts + N53C400DisableInterrupt(g); +} + +// +// VOID EP3CEnableInterrupt +// +// Enables the interrupt. +// + +VOID EP3CEnableInterrupt(PADAPTER_INFO g) +{ + UCHAR tmp; + + // set global flag for EP3CSetPrinterMode + + g->EnableInterrupt = TRUE; + + // see if the EP3C_IRQEN is not asserted, if so assert it + + EP3CPortGet(g, EP3C_AREG1, &tmp); + if (!(tmp & EP3C_IRQEN)) { + + // set the interrupts + // NOTE: a positive going edge toggles the state of EP3C_IRQEN + + EP3CPortPut(g, EP3C_AREG1, EP3C_IRQEN); + EP3CPortPut(g, EP3C_AREG1, 0); + } + + // finally, we can disable the core interrupts + N53C400EnableInterrupt(g); +} + +// +// EP3CSetPrinterMode +// +// This routine sets the EP3C to printer pass through mode. This is the +// default mode and should be set after the brief use of scsi mode. +// +VOID EP3CSetPrinterMode(PADAPTER_INFO g, UCHAR data, UCHAR control) +{ + UCHAR tmp; + + // restore data register + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,data); + + // restore control register + // leave p_init negated, P_BUFEN asserted + // also set P_IRQEN based on g->EnableInterrupt + + tmp = control | P_INIT & (P_BUFEN ^ 0xff); + if (g->EnableInterrupt) { + tmp = tmp | P_IRQEN; + } else { + tmp = tmp & (P_IRQEN ^ 0xff); + } + + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// EP3CSetScsiMode +// +// This routine sets the EP3C into scsi mode. Now the parallel port can +// be used to send commands the the n5380. This mode should be set only +// briefly during when the scsi command is being executed. +// +VOID EP3CSetScsiMode(PADAPTER_INFO g, PUCHAR data, PUCHAR control) +{ + UCHAR tmp; + USHORT i; + + // save parallel data + ParallelPortGet(g->BaseIoAddress,PARALLEL_DATA,data); + + // zero data register + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0); + + // save parallel control + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,control); + *control = *control & (P_BUFEN ^ 0xff); + + // store current interrupt state + + g->EnableInterrupt = (*control & P_IRQEN); + + // put our data pattern on the data bus + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0xf7); + + // negate P_SLC, P_BUFEN already asserted + tmp = *control; + tmp = tmp & (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // assert init + tmp = tmp & (P_INIT ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // assert P_SLC + tmp = tmp | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // negate P_SLC + tmp = tmp & (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // set to the appropriate mode: UNI, BI, etc.. + + if (g->ParallelPortType == PT_UNI) { + EP3CPortPut(g,(UCHAR)EP3C_AREG2, + (UCHAR)(EP3C_UNIDIR | g->Delay) ); + } else { + EP3CPortPut(g,EP3C_AREG2,(UCHAR)(0 | g->Delay)); + } + + // read in the signature bytes + + for (i=0;i<2;i++) { + EP3CPortGet(g, EP3C_AREG1, &g->SignatureBytes[i]); + } + +} + +// +// EP3CCheckAdapter +// +// This routine is used to sense the presense of the EP3C adapter out +// on the Parallel port. It will only detect the adapter if a device +// is providing termination power. +// +BOOLEAN EP3CCheckAdapter(PADAPTER_INFO g) +{ + BOOLEAN rval = FALSE; + static CONST UCHAR ParallelPortType = PT_UNI; + static CONST UCHAR types[] = { PT_EPP, PT_BI, PT_UNI }; + USHORT i; + + // default the delay to 2 for now + g->Delay = 7; + + if (g->ParallelPortType == PT_UNKNOWN) { + + // try to locate as all types + + for (i=0;i<3;i++) { + + g->ParallelPortType = types[i]; + + // do we have a type[i] port? + + if (rval = EP3CCheckAdapterType(g)) { + + break; + + } + } + } else { + + // try only the parallel port type specified + + rval = EP3CCheckAdapterType(g); + } + + return rval; +} + +// +// VOID EP3CSetParallelType +// +// Sets this code to use the type of paralle port given by +// g->ParallePortType, either PT_UNI, PT_BI, or PT_EPP. +// +VOID EP3CSetParallelPortType(PADAPTER_INFO g) +{ + + switch (g->ParallelPortType) { + case PT_UNI: + + // set the port type dependent routines + + g->EP3CWriteControlRegister = EP3CWriteControlRegisterUniDir; + g->EP3CReadControlRegister = EP3CReadControlRegisterUniDir; + g->EP3CReadDataRegister = EP3CReadDataRegisterUniDir; + g->EP3CWriteDataRegister = EP3CWriteDataRegisterUniDir; + g->EP3CReadFifo = EP3CReadFifoUniDir; +// g->EP3CReadFifo = EP3CReadFifoUniDirSlow; + g->EP3CWriteFifo = EP3CWriteFifoUniDir; + g->EP3CSetRegister = EP3CSetRegisterUniDir; + + break; + case PT_BI: + + // set the port type dependent routines + + g->EP3CWriteControlRegister = EP3CWriteControlRegisterBiDir; + g->EP3CReadControlRegister = EP3CReadControlRegisterBiDir; + g->EP3CReadDataRegister = EP3CReadDataRegisterBiDir; + g->EP3CWriteDataRegister = EP3CWriteDataRegisterBiDir; + g->EP3CReadFifo = EP3CReadFifoBiDir; +// g->EP3CReadFifo = EP3CReadFifoBiDirSlow; + g->EP3CWriteFifo = EP3CWriteFifoBiDir; + g->EP3CSetRegister = EP3CSetRegisterBiDir; + + break; + + case PT_EPP: + // set the port type dependent routines + + g->EP3CWriteControlRegister = EP3CWriteControlRegisterEPP; + g->EP3CReadControlRegister = EP3CReadControlRegisterEPP; + g->EP3CReadDataRegister = EP3CReadDataRegisterEPP; + g->EP3CWriteDataRegister = EP3CWriteDataRegisterEPP; + g->EP3CReadFifo = EP3CReadFifoEPP; + g->EP3CWriteFifo = EP3CWriteFifoEPP; + g->EP3CSetRegister = EP3CSetRegisterEPP; + + break; + } +} + +// +// BOOLEAN EP3CCheckAdapterType +// +// Checks for an adapter on a parallel port of the given type. +// +BOOLEAN EP3CCheckAdapterType(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + + // if epp type, then try to initialize 386sl code + if (g->ParallelPortType == PT_EPP) { + if (!SL386EnableEPP()) { + return FALSE; + } + } + + // configure for the correct type of parallel port + + EP3CSetParallelPortType(g); + + // set scsi mode, reads signature bytes. + + EP3CSetScsiMode(g,&data,&control); + + // set parallel port for use by printer + + EP3CSetPrinterMode(g,data,control); + + // compare the signature bytes + + if ((g->SignatureBytes[0] == 0xe8) && (g->SignatureBytes[1] == 0xff) ) { + return TRUE; + } + + return FALSE; +} + +// +// EP3CDoCommand +// +// Called by the main loop to start a scsi command. This functions is the +// main entry point for all cards. It returns an SRB status code as defined +// in ..\..\inc\srb.h. A status code of RET_STATUS_PENDING means that the +// request has been sent to the controller and an interrupt is needed to +// finish the request. When this interrupt occurs CardFinishCommandInterrupt +// will be called. +// +USHORT EP3CDoCommand(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + EP3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiDoCommand(t); + + // put the parallel adapter back to parallel mode + + EP3CSetPrinterMode(g, data, control); + return rval; +} + +// +// EP3CStartCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the EP3C does not support interrupts on its own. +// +// +USHORT EP3CStartCommandInterrupt(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + EP3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiStartCommandInterrupt(t); + + // put the parallel adapter back to parallel mode + + EP3CSetPrinterMode(g, data, control); + + return rval; +} + +// +// EP3CFinishCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the EP3C does not support interrupts on its own. +// +// +USHORT EP3CFinishCommandInterrupt(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + EP3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiFinishCommandInterrupt(t); + + // put the parallel adapter back to parallel mode + + EP3CSetPrinterMode(g, data, control); + + return rval; +} + +// +// EP3CInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the EP3C does not support interrupts on its own. +// +BOOLEAN EP3CInterrupt(PADAPTER_INFO g) +{ + BOOLEAN rval; + UCHAR data; + UCHAR control; + + // put the parallel adapter into scsi mode + + EP3CSetScsiMode(g, &data, &control); + + rval = N5380Interrupt(g); + + // put the parallel adapter back to parallel mode + + EP3CSetPrinterMode(g, data, control); + + return rval; +} + +// +// EP3CResetBus +// +// Resets the SCSI Bus +// +VOID EP3CResetBus(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + + // reset the EP3C + + EP3CPortSet(g,EP3C_AREG2,EP3C_RST); + + // put the parallel adapter into scsi mode + + EP3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + N53C400ResetBus(g); + + // put the parallel adapter back to parallel mode + + EP3CSetPrinterMode(g, data, control); +} + +// +// N53C400PortPut +// +// This routine is used by the N53C400.C module to write byte to a 53C400 +// controller. This allows the module to be card independent. Other +// modules that assume a N53C400 may also use this function. +// +VOID N53C400PortPut(PADAPTER_INFO g,UCHAR reg,UCHAR byte) +{ + (*(g->EP3CWriteDataRegister))(g, reg, byte); +} + +// +// N53C400PortGet +// +// This routine is used by the N53C400.C module to get a byte from a 53C400 +// controller. This allows the module to be card independent. Other +// modules that assume a N53C400 may also use this function. +// +VOID N53C400PortGet(PADAPTER_INFO g,UCHAR reg,PUCHAR byte) +{ + (*(g->EP3CReadDataRegister))(g, reg, byte); +} + +// +// VOID N53C400PortSet +// +// Sets the bit pattern at the given register. +// +VOID N53C400PortSet(PADAPTER_INFO g,UCHAR reg,UCHAR byte) +{ + UCHAR tmp; + (*(g->EP3CReadDataRegister))(g, reg, &tmp); + tmp |= byte; + (*(g->EP3CWriteDataRegister))(g, reg, tmp); +} + +// +// VOID N53C400PortClear +// +// Clears a bit pattern at the given register. +// +VOID N53C400PortClear(PADAPTER_INFO g,UCHAR reg,UCHAR byte) +{ + UCHAR tmp; + + (*(g->EP3CReadDataRegister))(g, reg, &tmp); + tmp &= (byte ^ 0xff); + (*(g->EP3CWriteDataRegister))(g, reg, tmp); +} + +// +// BOOLEAN N53C400PortTest +// +// Tests for a bit pattern on the given register. +// +BOOLEAN N53C400PortTest(PADAPTER_INFO g,UCHAR reg,UCHAR byte) +{ + UCHAR tmp; + + (*(g->EP3CReadDataRegister))(g, reg, &tmp); + return (tmp & byte); +} + + +// +// VOID N53C400PortGetBuffer +// +// Gets a buffer of 128 bytes from the n53c400. Note, the len here +// is ignored. +// +VOID N53C400PortGetBuffer(PADAPTER_INFO g, UCHAR reg, + PUCHAR pbytes, ULONG len) +{ + // set the 53c400 register to access + + (*(g->EP3CSetRegister))(g,reg); + + // read the fifo + + (*(g->EP3CReadFifo))(g->BaseIoAddress, pbytes); +} + +// +// VOID N53C400PortPutBuffer +// +// Puts a buffer of 128 bytes from the n53c400. Note, the len here +// is ignored. +// +VOID N53C400PortPutBuffer(PADAPTER_INFO g, UCHAR reg, + PUCHAR pbytes, ULONG len) +{ + // set the 53c400 register to access + + (*(g->EP3CSetRegister))(g,reg); + + // read the fifo + + (*(g->EP3CWriteFifo))(g->BaseIoAddress, pbytes); +} + +//====================================================================== +// Conditionally-coded routines using in-line assembler. +//====================================================================== + +#ifdef WINNT + + +//---------------------------------------------------------------------- +// VOID EP3CReadFifoUniDir +// +// Reads bytes for uni-directional parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +//---------------------------------------------------------------------- + +VOID EP3CReadFifoUniDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi, pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + loop0: + mov al, 0x80 + out dx,al // select high nibble + + jmp delay0 + delay0: + + add edx,2 // DX -> ctl reg + mov al,P_AFX // assert bufen and afx + out dx,al // assert dreg read + + jmp delay1 + delay1: + + dec edx // DX -> stat reg + in al,dx // read high nibble + + jmp delay2 + delay2: + + mov ah,al + shl ah,1 + and ah,0f0h // AH -> adj high nibble + dec edx // DX -> data reg + sub al,al + out dx,al // select low nibble + + jmp delay3 + delay3: + + inc edx // DX -> stat reg + in al,dx // read low nibble + + shr al,1 + shr al,1 + shr al,1 + and al,0fh // AL = adj low nibble + or al,ah // AL = recombined byte + + mov [edi],al // store + inc edi // bump buf ptr + + inc edx // DX -> ctl reg + xor al,al // negate afx (bufen stays asserted) + out dx,al // end read + + jmp delay4 + delay4: + + sub edx,2 // DX -> data reg + dec ecx + jnz loop0 + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CReadFifoUniDirSlow +// +// Reads bytes for uni-directional parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +// USES FULL HANDSHAKING +// +//---------------------------------------------------------------------- + +VOID EP3CReadFifoUniDirSlow(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi, pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + inc edx // edx - status register + mov ecx, 128 + loop0: + + dec edx // edx - data register + mov al, 0x80 + out dx,al // select high nibble + + jmp delay0 + delay0: + + add edx,2 // DX -> ctl reg + mov al,P_AFX // assert bufen and afx + out dx,al // assert dreg read + + // wait till ready, P_BUSY asserted + dec edx // edx - status register + loop1: + in al,dx + test al, P_BUSY + jnz loop1 + + // delay to make sure we get high nibble in + jmp delay01 + delay01: + in al,dx + + mov ah,al + shl ah,1 + and ah,0f0h // AH -> adj high nibble + dec edx // DX -> data reg + sub al,al + out dx,al // select low nibble + + jmp delay3 + delay3: + + inc edx // DX -> stat reg + in al,dx // read low nibble + + shr al,1 + shr al,1 + shr al,1 + and al,0fh // AL = adj low nibble + or al,ah // AL = recombined byte + + mov [edi],al // store + inc edi // bump buf ptr + + inc edx // DX -> ctl reg + xor al,al // negate afx (bufen stays asserted) + out dx,al // end read + + dec edx // DX -> status register + // wait for P_BUSY deasserted + loop2: + in al,dx + test al, P_BUSY + jz loop2 + + dec ecx + jnz loop0 + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CReadFifoBiDir +// +// Reads bytes for bi-directional parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +//---------------------------------------------------------------------- + +VOID EP3CReadFifoBiDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + add edx, 2 // edx - control register + loop0: + mov al, P_BUFEN + P_AFX + out dx, al + + jmp delay0 + delay0: + + sub edx,2 // edx - data register + + in al,dx + mov [edi], al + inc edi + + add edx,2 // edx - control register + + mov al, P_BUFEN + out dx, al + + jmp delay1 // is this needed, there is a loop? + delay1: + + dec ecx + jnz loop0 + + xor al,al // leave control regiser 0'd + out dx, al + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CReadFifoBiDirSlow +// +// Reads bytes for bi-directional parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +// USES FULL HANDSHAKING +// +//---------------------------------------------------------------------- + +VOID EP3CReadFifoBiDirSlow(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + add edx, 0x02 // edx - control register + + // wait for data to be ready, P_BUSY asserted + loop0: + mov al, P_BUFEN + P_AFX + out dx, al + + dec edx // edx - status register + loop1: + in al,dx + test al, P_BUSY + jnz loop1 + + dec edx // edx - data register + + in al,dx + mov [edi], al + inc edi + + add edx,2 // edx - control register + + // end data read cycle + mov al, P_BUFEN + out dx, al + + dec edx // edx - status register + + // wait for P_BUSY deasserted + loop2: + in al,dx + test al, P_BUSY + jz loop2 + + inc edx // edx - control register + + dec ecx + jnz loop0 + + xor al,al // leave control regiser 0'd + out dx, al + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CWriteFifoUniDir +// +// Writes bytes thru uni-directional parallel port to the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +//---------------------------------------------------------------------- + +VOID EP3CWriteFifoUniDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + + loop0: + mov al,[edi] + out dx,al + inc edi + + add edx,2 ;DX -> ctl reg + mov al,P_STB ;assert bufen, stb + out dx,al + or al,P_AFX ;assert dreg write + out dx,al + + jmp delay0 + delay0: + ;leave bufen asserted + mov al,0 ; and negate afx, stb + out dx,al ;end write + + jmp delay1 + delay1: + + sub edx,2 ;DX -> data reg + dec ecx + jnz loop0 + +// let's leave control register 0'd for all these fifo routines... +// add edx,2 ;DX -> ctl reg +// or al,P_BUFEN ;negate bufen +// out dx,al + + + jmp delay2 + delay2: + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CWriteFifoUniDirSlow +// +// Writes bytes thru uni-directional parallel port to the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +// USES FULL HANDSHAKING +// +//---------------------------------------------------------------------- + +VOID EP3CWriteFifoUniDirSlow(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + + loop0: + mov al,[edi] + out dx,al + inc edi + + add edx,2 ;DX -> ctl reg + mov al,P_STB ;assert bufen, stb + out dx,al + or al,P_AFX ;assert dreg write + out dx,al + + // wait till ready, P_BUSY asserted + dec edx // edx - status register + loop1: + in al,dx + test al, P_BUSY + jnz loop1 + + inc edx // edx - control register + + ;leave bufen asserted + mov al,0 ; and negate afx, stb + out dx,al ;end write + + dec edx // edx - status register + + // wait for P_BUSY deasserted + loop2: + in al,dx + test al, P_BUSY + jz loop2 + + dec edx // edx - data register + + dec ecx + jnz loop0 + +// let's leave control register 0'd for all these fifo routines... +// add edx,2 ;DX -> ctl reg +// or al,P_BUFEN ;negate bufen +// out dx,al + + pop edi + pop ds + } +} + +#endif // #ifdef WINNT diff --git a/private/ntos/miniport/trantor/source/ep3c2.asm b/private/ntos/miniport/trantor/source/ep3c2.asm new file mode 100644 index 000000000..b57ac5a89 --- /dev/null +++ b/private/ntos/miniport/trantor/source/ep3c2.asm @@ -0,0 +1,526 @@ + page +;*********************************************************************** +; +; (C) Copyright 1992 Trantor Systems, Ltd. +; All Rights Reserved. +; +; This program is an unpublished copyrighted work which is proprietary +; to Trantor Systems, Ltd. and contains confidential information that +; is not to be reproduced or disclosed to any other person or entity +; without prior written consent from Trantor Systems, Ltd. in each +; and every instance. +; +; WARNING: Unauthorized reproduction of this program as well as +; unauthorized preparation of derivative works based upon the +; program or distribution of copies by sale, rental, lease or +; lending are violations of federal copyright laws and state trade +; secret laws, punishable by civil and criminal penalties. +; +;*********************************************************************** + title EP3C2.ASM +;----------------------------------------------------------------------- +; +; EP3C2.ASM +; +; FIFO I/O Routines for the EP3C chip. +; Assembly coded for speed. These are only some of the routines +; needed for the EP3C. The rest are in EP3C.C. +; +; History +; ------- +; 05-17-93 JAP First, from ep3c.c +; +;----------------------------------------------------------------------- + +;----------------------------------------------------------------------- +; stack frame equates +;----------------------------------------------------------------------- + +ep3c_param2 equ 12 +ep3c_param1 equ 8 +ep3c_retAdrs equ 4 +ep3c_bp equ 0 + +ep3c_pbytes equ ep3c_param2 +ep3c_baseIoAddress equ ep3c_param1 + + +;----------------------------------------------------------------------- +; Macros +;----------------------------------------------------------------------- + +;----------------------------------------------------------------------- +; get_params +; +; Puts parameters into registers: +; edx -> baseIoAddress +; ds:[edi] -> pbytes +;----------------------------------------------------------------------- + +get_params macro + + ifdef MODE_32BIT + + mov edi, dword ptr [ebp].ep3c_pbytes + mov edx, dword ptr [ebp].ep3c_baseIoAddress + + else + + mov edi, word ptr ss:[bp].ep3c_pbytes + mov ds, word ptr ss:[bp].ep3c_pbytes+2 + mov edx, word ptr ss:[bp].ep3c_baseIoAddress + + endif ;MODE_32BIT + + endm + + +;----------------------------------------------------------------------- +; Routines +;----------------------------------------------------------------------- + +;----------------------------------------------------------------------- +; EP3CReadFifoUniDir +; +; VOID EP3CReadFifoUniDir (PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +; +; Reads bytes for uni-directional parallel port from the 53c400 +; 128 byte buffer. The register must already be set the the +; 53c400 buffer register. +; +;----------------------------------------------------------------------- + +EP3CReadFifoUniDir proc far + + push ds + push edi + + get_params + + mov ecx, 128 + +loop0: + mov al, 0x80 + out dx, al ;select high nibble + jmp delay0 + +delay0: + add edx,2 ;DX -> ctl reg + mov al,P_AFX ;assert bufen and afx + out dx,al ;assert dreg read + jmp delay1 + +delay1: + dec edx ;DX -> stat reg + in al,dx ;read high nibble + jmp delay2 + +delay2: + mov ah,al + shl ah,1 + and ah,0f0h ;AH -> adj high nibble + dec edx ;DX -> data reg + sub al,al + out dx,al ;select low nibble + jmp delay3 + +delay3: + inc edx ;DX -> stat reg + in al,dx ;read low nibble + + shr al,1 + shr al,1 + shr al,1 + and al,0fh ;AL = adj low nibble + or al,ah ;AL = recombined byte + + mov [edi],al ;store + inc edi ;bump buf ptr + + inc edx ;DX -> ctl reg + xor al,al ;negate afx (bufen stays asserted) + out dx,al ;end read + jmp delay4 + +delay4: + sub edx,2 ;DX -> data reg + dec ecx + jnz loop0 + + pop edi + pop ds + ret + +EP3CReadFifoUniDir endp + +;----------------------------------------------------------------------- +; +; EP3CReadFifoUniDirSlow +; +; VOID EP3CReadFifoUniDirSlow (PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +; +; Reads bytes for uni-directional parallel port from the 53c400 +; 128 byte buffer. The register must already be set the the +; 53c400 buffer register. +; +; USES FULL HANDSHAKING +; +;----------------------------------------------------------------------- + +EP3CReadFifoUniDirSlow proc far + + push ds + push edi + + get_params + + inc edx // edx - status register + mov ecx, 128 + +loop0: + dec edx // edx - data register + mov al, 0x80 + out dx,al // select high nibble + jmp delay0 + +delay0: + add edx, 2 // DX -> ctl reg + mov al, P_AFX // assert bufen and afx + out dx, al // assert dreg read + +; wait till ready, P_BUSY asserted + + dec edx // edx - status register + +loop1: + in al,dx + test al, P_BUSY + jnz loop1 + +; delay to make sure we get high nibble in + + jmp delay01 + +delay01: + in al,dx + + mov ah,al + shl ah,1 + and ah,0f0h // AH -> adj high nibble + dec edx // DX -> data reg + sub al,al + out dx,al // select low nibble + + jmp delay3 + +delay3: + inc edx // DX -> stat reg + in al,dx // read low nibble + + shr al,1 + shr al,1 + shr al,1 + and al,0fh // AL = adj low nibble + or al,ah // AL = recombined byte + + mov [edi],al // store + inc edi // bump buf ptr + + inc edx // DX -> ctl reg + xor al,al // negate afx (bufen stays asserted) + out dx,al // end read + + dec edx // DX -> status register + +; wait for P_BUSY deasserted + +loop2: + in al,dx + test al, P_BUSY + jz loop2 + + dec ecx + jnz loop0 + + pop edi + pop ds + ret + +EP3CReadFifoUniDirSlow endp + + +//---------------------------------------------------------------------- +// +// VOID EP3CReadFifoBiDir +// +// Reads bytes for bi-directional parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +//---------------------------------------------------------------------- + +VOID EP3CReadFifoBiDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + add edx, 2 // edx - control register + loop0: + mov al, P_BUFEN + P_AFX + out dx, al + + jmp delay0 + delay0: + + sub edx,2 // edx - data register + + in al,dx + mov [edi], al + inc edi + + add edx,2 // edx - control register + + mov al, P_BUFEN + out dx, al + + jmp delay1 // is this needed, there is a loop? + delay1: + + dec ecx + jnz loop0 + + xor al,al // leave control regiser 0'd + out dx, al + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CReadFifoBiDirSlow +// +// Reads bytes for bi-directional parallel port from the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +// USES FULL HANDSHAKING +// +//---------------------------------------------------------------------- + +VOID EP3CReadFifoBiDirSlow(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + add edx, 0x02 // edx - control register + + // wait for data to be ready, P_BUSY asserted + loop0: + mov al, P_BUFEN + P_AFX + out dx, al + + dec edx // edx - status register + loop1: + in al,dx + test al, P_BUSY + jnz loop1 + + dec edx // edx - data register + + in al,dx + mov [edi], al + inc edi + + add edx,2 // edx - control register + + // end data read cycle + mov al, P_BUFEN + out dx, al + + dec edx // edx - status register + + // wait for P_BUSY deasserted + loop2: + in al,dx + test al, P_BUSY + jz loop2 + + inc edx // edx - control register + + dec ecx + jnz loop0 + + xor al,al // leave control regiser 0'd + out dx, al + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CWriteFifoUniDir +// +// Writes bytes thru uni-directional parallel port to the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +//---------------------------------------------------------------------- + +VOID EP3CWriteFifoUniDir(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + + loop0: + mov al,[edi] + out dx,al + inc edi + + add edx,2 ;DX -> ctl reg + mov al,P_STB ;assert bufen, stb + out dx,al + or al,P_AFX ;assert dreg write + out dx,al + + jmp delay0 + delay0: + ;leave bufen asserted + mov al,0 ; and negate afx, stb + out dx,al ;end write + + jmp delay1 + delay1: + + sub edx,2 ;DX -> data reg + dec ecx + jnz loop0 + +// let's leave control register 0'd for all these fifo routines... +// add edx,2 ;DX -> ctl reg +// or al,P_BUFEN ;negate bufen +// out dx,al + + + jmp delay2 + delay2: + + pop edi + pop ds + } +} + + +//---------------------------------------------------------------------- +// +// VOID EP3CWriteFifoUniDirSlow +// +// Writes bytes thru uni-directional parallel port to the 53c400 +// 128 byte buffer. The register must already be set the the +// 53c400 buffer register. +// +// USES FULL HANDSHAKING +// +//---------------------------------------------------------------------- + +VOID EP3CWriteFifoUniDirSlow(PBASE_REGISTER baseIoAddress, PUCHAR pbytes) +{ + _asm { + push ds + push edi + +#ifdef MODE_32BIT + mov edi,pbytes + mov edx, baseIoAddress +#else + mov edi, word ptr pbytes + mov ds, word ptr pbytes+2 + mov edx, word ptr baseIoAddress +#endif // MODE_32BIT + mov ecx, 128 + + loop0: + mov al,[edi] + out dx,al + inc edi + + add edx,2 ;DX -> ctl reg + mov al,P_STB ;assert bufen, stb + out dx,al + or al,P_AFX ;assert dreg write + out dx,al + + // wait till ready, P_BUSY asserted + dec edx // edx - status register + loop1: + in al,dx + test al, P_BUSY + jnz loop1 + + inc edx // edx - control register + + ;leave bufen asserted + mov al,0 ; and negate afx, stb + out dx,al ;end write + + dec edx // edx - status register + + // wait for P_BUSY deasserted + loop2: + in al,dx + test al, P_BUSY + jz loop2 + + dec edx // edx - data register + + dec ecx + jnz loop0 + +// let's leave control register 0'd for all these fifo routines... +// add edx,2 ;DX -> ctl reg +// or al,P_BUFEN ;negate bufen +// out dx,al + + pop edi + pop ds + } +} + + + \ No newline at end of file diff --git a/private/ntos/miniport/trantor/source/findpas.c b/private/ntos/miniport/trantor/source/findpas.c new file mode 100644 index 000000000..7b60bdb8c --- /dev/null +++ b/private/ntos/miniport/trantor/source/findpas.c @@ -0,0 +1,303 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + findpas.c + +Abstract: + + This module contains code configuration code MediaVision's Pro audio + spectrum. The card is run in Sound Blaster compatibiltiy mode. + + Support is provided for volume setting and line input and + microphone mix level setting. + + The card is located by searching. No user configuration is supported. + +Author: + + Adapted from work by Robin Speed (RobinSp) 17-Oct-1992 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include CARDTXXX_H +#include "findpas.h" + + + +//--------------========================--------------------------- +//---------====< GLOBAL DATA SECTION >====------------------------- +//--------------========================--------------------------- + +// The board signature is the first value in the PAS 16 wakeup sequence +// BC is the factory default. A board jumpered to recognize the BD signature +// will not respond to a BC init command. + +UCHAR SignatureTable[4]={0xBC,0xBD,0xBE,0xBF}; + +// +// MPU stuff here until we work out what we want +// + +#define MPU_ADDR 0x330 + +#define MPU_IRQ 2 +#define MPU_EMUL_IRQ EMUL_IRQ_2 + + +// +// Local routines +// + + +BOOLEAN +VerifyProHardware( + PFOUNDINFO pFI, + ULONG port); + +BOOLEAN +WakeUpAtAddress( + PFOUNDINFO pFoundInfo, + ULONG wPort); + +; /*\ +;---|*|------====< DWORD GetProTableRead() >====------ +;---|*| +;---|*| Detects which version of the Pro AudioSpectrum is installed +;---|*| +;---|*| Entry Conditions: +;---|*| Pointer to Profile Structure. If the caller wants to specify +;---|*| the preferred base address for cards not yet init'd, they +;---|*| are passed in this structure. The NumFound field indicates +;---|*| the number of location requests and the board address elements +;---|*| indicate the locations. +;---|*| +;---|*| Also passed in pointer to port (the one we found in the registry +;---|*| if any +;---|*| +;---|*| Exit Conditions: +;---|*| Returns number of cards found +;---|*| ProFile structure has been updated. +;---|*| +; \*/ + + +int +FindPasHardware( + PFOUNDINFO pFoundInfo +) + // PSB_CONFIG_DATA ConfigData ) +{ + + if (WakeUpAtAddress(pFoundInfo, pFoundInfo->ProPort)) { + + return 1; + } + + return 0; +} + +; /*\ +;---|*|------====< int VerifyProHardware() >====------ +;---|*| +;---|*| Detects which version of the Pro AudioSpectrum is installed +;---|*| +;---|*| Entry Conditions: +;---|*| pFI - found info pointer -- has PROBase mapped I/O space. +;---|*| port - I/O port location to search -- not mapped. +;---|*| +;---|*| Exit Conditions: +;---|*| Returns TRUE if ProAudio found. +;---|*| Returns FALSE if not found. +;---|*| +; \*/ + + +BOOLEAN +VerifyProHardware( + PFOUNDINFO pFI, + ULONG port) +{ + UCHAR bData, bTemp; + + DebugPrint((DEBUG_LEVEL,"VerifyProHardware (proport %X,probase %X, port %X)\n",pFI->ProPort,pFI->PROBase,port)); + pFI->TranslateCode = port ^ DEFAULT_BASE; + + bData=PASX_IN (pFI, INTERRUPT_CTRL_REG); + + if (bData==0xFF) { // 0xFF usually means nothing there + goto VerifyFailed; + } + pFI->wBoardRev= (bData >>5); // board rev is 3 topmost bits + + switch (pFI->wBoardRev) { +#ifndef WINNT + // winnt does not want support for old cards, this code recognizes + // some sound blasters + case PAS_VERSION_1: +#endif + //case PAS_PLUS: // same boardrev as PAS_SIXTEEN + case PAS_STUDIO: + case PAS_SIXTEEN: + case PAS_CDPC: + case 4: // Memphis + break; + + default: + goto VerifyFailed; // unknown hardware type + } + + PASX_OUT(pFI, INTERRUPT_CTRL_REG, bData ^ 0xE0); // try changing version bits + bTemp=PASX_IN (pFI, INTERRUPT_CTRL_REG); // they should be read only + + if ((bTemp & (D7+D6+D5)) != (bData & (D7+D6+D5))) { + PASX_OUT(pFI, INTERRUPT_CTRL_REG, bData); // Excuse me, stranger. + goto VerifyFailed; + } + + if (pFI->wBoardRev==PAS_VERSION_1) { + + pFI->Caps.CapsBits.CDInterfaceType=SCSI_TYPE; + + // + // test for Enhanced SCSI mod (U48) + // + + PASX_OUT(pFI, ENHANCED_SCSI_DETECT_REG, 0 ); // write to try changing version bits + ScsiPortStallExecution(10); // wait 10 us + bTemp=PASX_IN ( pFI, ENHANCED_SCSI_DETECT_REG ); // they should be read only + + switch (bTemp & 1) { // bit0==1 means old SCSI PAL + case 0: + pFI->Caps.CapsBits.EnhancedSCSI=TRUE; + // allow to fall thru + + case 1: + goto ProVerified; + } + } else { + // if PAS hardware installed, the reset bit can never be on + + bTemp=PASX_IN (pFI, SYSTEM_CONFIG_1); // get PAS config register + if (bTemp & D7) { // D7 is reset bit + goto VerifyFailed; + } + + bTemp=PASX_IN (pFI, SLAVE_MODE_READ); + + if (bTemp & SLAVE_MODE_OPL3) { + pFI->Caps.CapsBits.OPL_3=TRUE; + } + + if (bTemp & SLAVE_MODE_16) { + pFI->Caps.CapsBits.DAC16=TRUE; + pFI->Caps.CapsBits.DualDAC=TRUE; + + // if 16-bit DAC, and not a CDPC, it has a 508 chip. + // Note: PAS 16 w/ VGA will have Mixer 508 also. + + if (pFI->wBoardRev != PAS_CDPC) { + pFI->Caps.CapsBits.Mixer_508=TRUE; + } + } + + pFI->Caps.CapsBits.CDInterfaceType=(bTemp & (D1+D0)); + + if (pFI->Caps.CapsBits.CDInterfaceType==SCSI_TYPE) { + pFI->Caps.CapsBits.SCSI_IO_16=TRUE; + } + + pFI->Caps.CapsBits.Slot16=TRUE; + pFI->Caps.CapsBits.SoundBlaster=TRUE; + + bTemp=PASX_IN (pFI, MASTER_MODE_READ); // get slave bits + if ((bTemp & D0)==0) { + pFI->Caps.CapsBits.MCA=TRUE; + } + + if (bTemp & D2) { + pFI->Caps.CapsBits.CDPC=TRUE; + } + + pFI->wChipRev=PASX_IN (pFI, CHIP_REV); + } + +ProVerified: + + DebugPrint((DEBUG_LEVEL,"\n\nFound PRO hardware at %X\n", port)); + pFI->ProPort=port; // found at this port + return TRUE; + +//////////////////////////////// + +VerifyFailed: + pFI->wBoardRev=0; // found at this port + pFI->Caps.dwCaps=0; // No Board, No Caps + return FALSE; +} + +; /*\ +;---|*|------====< int WakeUpAtAddress(WORD wPort) >====------ +;---|*| +;---|*| Tries to wake up sleeping relocatable hardware at a specified +;---|*| address. Does not check for hardware already in that location +;---|*| If it does wake up a card, it does the minimum amount of +;---|*| initialization to enable the hardware. +;---|*| +;---|*| Entry Conditions: +;---|*| wPort= Base I/O address to wake card up at. +;---|*| +;---|*| Exit Conditions: +;---|*| Returns TRUE if ProAudio hardware found. +;---|*| Returns FALSE if not. +;---|*| +; \*/ +BOOLEAN +WakeUpAtAddress( + PFOUNDINFO pFoundInfo, + ULONG wPort) +{ + int i,j; + + DebugPrint((DEBUG_LEVEL,"WakeUpAtAddress (proport %X,probase %X, port %X)\n",pFoundInfo->ProPort,pFoundInfo->PROBase,wPort)); + for (i = 0; i < sizeof(SignatureTable) / sizeof(SignatureTable[0]); i++) { + for (j = 0; j < 20; j++) { + WRITE_PORT_UCHAR(pFoundInfo->PROBase + PAS_2_WAKE_UP_REG, SignatureTable[i]); + ScsiPortStallExecution(1); + WRITE_PORT_UCHAR(pFoundInfo->PROBase + PAS_2_WAKE_UP_REG, (UCHAR)((wPort >> 2) & 0xFF)); + ScsiPortStallExecution(1); + } + + if (VerifyProHardware(pFoundInfo, wPort)) { + + // + // Found one - wTranslateCode translates to the board's + // correct port. + // + + pFoundInfo->Caps.CapsBits.Did_HW_Init=TRUE; + + if (pFoundInfo->wBoardRev > PAS_VERSION_1 ) { + /* Only enable FM feature if we're going to sit at + the right address */ + + UCHAR Features = PCM_FEATURE_ENABLE | MIXER_FEATURE_ENABLE | + SB_FEATURE_ENABLE | FM_FEATURE_ENABLE; + + PASX_OUT(pFoundInfo, FEATURE_ENABLE, Features); + } + + return (TRUE); + } + } + return (FALSE); // not found +} + diff --git a/private/ntos/miniport/trantor/source/mv101.c b/private/ntos/miniport/trantor/source/mv101.c new file mode 100644 index 000000000..549106fd9 --- /dev/null +++ b/private/ntos/miniport/trantor/source/mv101.c @@ -0,0 +1,617 @@ +//---------------------------------------------------------------------- +// +// MV101.C +// +// Trantor MV101 access file. +// +// These routines are independent of the card the MV101 logic is on. The +// cardxxxx.h file must define the following routines: +// +// MV101PortPut +// MV101PortGet +// MV101PortSet +// MV101PortClear +// MV101PortTest +// +// 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-93 KJB Changed to use new N5380.H names. +// 03-19-93 JAP Implemented condition build FAR and NEAR pointers +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// 04-05-93 KJB DEBUG_LEVEL used by DebugPrint for NT. +// 05-13-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 the PBASE_REGISTER and the +// PWORKSPACE parameters. Auto Request Sense is +// now supported. +// 05-13-93 KJB Merged Microsoft Bug fixes to card detection. +// 05-14-93 KJB Remove all WINNT specific #ifdef i386 references. +// 05-17-93 KJB Added ErrorLogging capabilities (used by WINNT). +// +//---------------------------------------------------------------------- + +#include CARDTXXX_H +#include "findpas.h" + +// +// local functions +// + +VOID MV101ResetDmaTimeout (PADAPTER_INFO g); +VOID MV101EnableDmaWrite (PADAPTER_INFO g); +VOID MV101EnableDmaRead (PADAPTER_INFO g); +USHORT MV101WaitXfrReady (PADAPTER_INFO g, ULONG usec); + +// +// local redefines +// +#define MV101DisableDmaRead N5380DisableDmaRead +#define MV101DisableDmaWrite N5380DisableDmaWrite + +// +// N5380PortPut +// +// This routine is used by the N5380.C module to write byte to a 5380 +// controller. This allows the module to be card independent. Other +// modules that assume a N5380 may also use this function. +// + +VOID N5380PortPut (PADAPTER_INFO g, UCHAR reg, UCHAR byte) +{ + if (reg<4) { + PortIOPut((PUCHAR)g->BaseIoAddress+MV101_5380_1+reg,byte); + } else { + PortIOPut((PUCHAR)g->BaseIoAddress+MV101_5380_2+reg-4,byte); + } +} + +// +// N5380PortGet +// +// This routine is used by the N5380.C module to get a byte from a 5380 +// controller. This allows the module to be card independent. Other +// modules that assume a N5380 may also use this function. +// + +VOID N5380PortGet (PADAPTER_INFO g, UCHAR reg, PUCHAR byte) +{ + if (reg<4) { + PortIOGet ((PUCHAR)g->BaseIoAddress+MV101_5380_1+reg, byte); + } else { + PortIOGet ((PUCHAR)g->BaseIoAddress+MV101_5380_2+reg-4,byte); + } +} + +// +// MV101CheckAdapter +// +// This routine sees if there is an adapter at this address. If so, +// then this adapter is initialized. +// +BOOLEAN MV101CheckAdapter (PADAPTER_INFO g) +{ + FOUNDINFO fi; + + // + // FindPasHardware does it's own mapping of port bases. + // Set the base to zero and indicate which port is currently being + // polled. + // + + fi.PROBase = 0; + fi.ProPort = (ULONG) g->BaseIoAddress; + + if (!FindPasHardware(&fi)) { + return FALSE; + } + + // for old boards, we use bit 1 for drq mask during dma xfers + if (fi.wBoardRev == PAS_VERSION_1) { + g->DRQMask = 0x01; + } else { + g->DRQMask = 0x80; + } + + // is there an adapter here? + if (N5380CheckAdapter (g)) { + // found a 5380, initialize special dma hardware for + // dma fast read and writes. + + MV101PortPut (g,MV101_SYSTEM_CONFIG4,0x49); + MV101PortPut (g,MV101_TIMEOUT_COUNTER,0x30); + MV101PortPut (g,MV101_TIMEOUT_STATUS,0x01); + MV101PortPut (g,MV101_WAIT_STATE,0x01); + return TRUE; + } else { + return FALSE; + } +} + +// +// MV101WaitXfrReady +// +// This routine waits till the DRQ flag goes up. +// +USHORT MV101WaitXfrReady (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i=0;iDRQMask)) { + 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 (MV101PortTest (g, MV101_DRQ_PORT, g->DRQMask)) { + return 0; + } + + // see if bus free + + if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) { + + TrantorLogError (g->BaseIoAddress, RET_STATUS_UNEXPECTED_BUS_FREE, 100); + + 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 + + ScsiPortStallExecution(1); + } + + DebugPrint ((DEBUG_LEVEL,"Error - MV101WaitXfrReady\n")); + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 102); + + return RET_STATUS_TIMEOUT; +} + + +// +// MV101ResetDmaTimeout +// +// Resets the dma timout bit. +// + +VOID MV101ResetDmaTimeout (PADAPTER_INFO g) +{ + MV101PortPut (g, MV101_TIMEOUT_STATUS, 0x01); +} + + +// +// MV101EnableDmaRead +// +// Enables the DMA read operation for the T128. +// + +VOID MV101EnableDmaRead (PADAPTER_INFO g) +{ + // start dma on the 5380 + + N5380EnableDmaRead(g); + + // toggle the t120 timeout bit to clear any timeout + + MV101ResetDmaTimeout(g); +} + + +// +// MV101EnableDmaWrite +// +// Enables the DMA write operation for the T128. +// + +VOID MV101EnableDmaWrite (PADAPTER_INFO g) +{ + // start dma on the 5380 + + N5380EnableDmaWrite (g); + + // toggle the t120 timeout bit to clear any timeout + + MV101ResetDmaTimeout (g); +} + + +// +// MV101SetInterruptLevel +// +// The Media Vision MV101s need to be programmed for interrupts. +// In particular, one needs to set the interrupt level into a register. +// + +VOID MV101SetInterruptLevel (PADAPTER_INFO g, UCHAR level) +{ + // int from drive active high + + MV101PortSet (g, MV101_SYSTEM_CONFIG4, 0x04); + + // enable interrupts for the card + + MV101PortSet (g, MV101_SYSTEM_CONFIG4, 0x20); + + // set the interrupt level in IO port config register 3 + + MV101PortClear(g,MV101_IO_PORT_CONFIG3,0xf0); + + if (level < 8) { + MV101PortSet (g, MV101_IO_PORT_CONFIG3, + (UCHAR)((level-1)<<4)); + } + else { + MV101PortSet (g, MV101_IO_PORT_CONFIG3, + (UCHAR)((7+level-10)<<4)); + } +} + + +// +// MV101EnableInterrupt +// +// Enables the interrupt on the card and on the 5380. +// + +VOID MV101EnableInterrupt (PADAPTER_INFO g) +{ + // interrupt reset for tmv1 card + + MV101PortSet (g, MV101_TIMEOUT_STATUS, 0x01); + + // enable interrupts on the 5380 + + N5380EnableInterrupt (g); +} + + +// +// MV101DisableInterrupt +// +// Disables the interrupt on the card and on the 5380. +// + +VOID MV101DisableInterrupt (PADAPTER_INFO g) +{ + // interrupt reset for tmv1 card + + MV101PortSet (g, MV101_TIMEOUT_STATUS, 0x01); + + // disable the signal from the 5380 + + N5380DisableInterrupt (g); +} + + +// +// MV101ReadBytesFast +// +// This routine is used by the ScsiFnc routines to read 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 MV101ReadBytesFast (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + + // for small transfers, use slow loop (inquiry and other stuff) + + if (len < 512) { + rval = ScsiReadBytesSlow (g, pbytes, len, + pActualLen, phase); + return rval; + } + + // start dma for this card + + MV101EnableDmaRead (g); + + // wait for buffer to be ready + + if (rval = MV101WaitXfrReady (g,TIMEOUT_REQUEST)) { + goto done; + } + + // due to the speed of i/o instructions in 486 protected mode, + // we can afford to do all the drq checking. There is no need for + // the 'blind mode' rep insb transfers. These have been tried and + // the result is "20 FF FF FF 20 FF FF 41", indicating that we are + // two to three times faster than the card, hence we can afford to + // poll the card. + { + PUCHAR dma_port = (PUCHAR)g->BaseIoAddress + MV101_DMA_PORT; + PUCHAR drq_port = (PUCHAR)g->BaseIoAddress + MV101_DRQ_PORT; + ULONG xfer_count = len; + UCHAR drq_mask = g->DRQMask; + + _asm { + pushf + push esi + push edi + push es + cld + mov ah,drq_mask +#ifdef MODE_32BIT + mov edx,dma_port + mov esi,drq_port + mov edi,pbytes + mov ecx,len +#else + mov edx,word ptr dma_port + mov esi,word ptr drq_port + mov edi,word ptr pbytes + mov ecx,word ptr len + mov es,word ptr pbytes+2 +#endif + loop1: + xchg edx,esi // dx drq_port + in al,dx + test al,ah + jnz ready + in al,dx + test al,ah + jnz ready + in al,dx + test al,ah + jnz ready + + push ecx + mov ecx,TIMEOUT_READWRITE_LOOP + loop3: + mov ebx,0x10000 + loop2: + in al,dx + test al,ah + jnz ready1 + in al,dx + test al,ah + jnz ready1 + + // check for phase mismatch + + sub dx, MV101_DRQ_PORT - MV101_5380_2 // dx = N5380_CURRENT_STATUS + in al,dx + test al,CS_REQ + jz no_req + add dx, (N5380_DMA_STATUS - N5380_CURRENT_STATUS) // dx = N5380_DMA_STATUS + in al,dx + test al,DS_PHASE_MATCH + jz phase_error + sub dx, N5380_DMA_STATUS - N5380_CURRENT_STATUS // dx = N5380_CURRENT_STATUS + no_req: + add dx, MV101_DRQ_PORT - MV101_5380_2 // dx = MV101_DRQ + + dec ebx + jnz loop2 + dec ecx + jnz loop3 + pop ecx + mov rval,RET_STATUS_TIMEOUT + jmp short timeout + phase_error: + pop ecx + mov rval,RET_STATUS_DATA_OVERRUN + jmp short timeout + ready1: + pop ecx + // jmp ready + + ready: + xchg edx,esi // dx dma_port + insb + dec ecx + jnz loop1 + timeout: + pop es +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + pop edi + pop esi + popf + } + + // compute actual xfer len + *pActualLen = len - xfer_count; + } + +done: + // disable dma + + MV101DisableDmaRead (g); + + // check for errors... + + if (rval == RET_STATUS_TIMEOUT) { + TrantorLogError (g->BaseIoAddress, rval, 103); + } + + return rval; +} + + +// +// MV101WriteBytesFast +// +// 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 MV101WriteBytesFast (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + + // for small transfers, use slow loop (inquiry and other stuff) + + if (len < 512) { + rval = ScsiWriteBytesSlow (g, pbytes, len, + pActualLen, phase); + return rval; + } + + // start dma for this card + + MV101EnableDmaWrite (g); + + // wait for buffer to be ready + + if (rval = MV101WaitXfrReady (g, TIMEOUT_REQUEST)) { + goto done; + } + + // due to the speed of i/o instructions in 486 protected mode, + // we can afford to do all the drq checking. There is no need for + // the 'blind mode' rep insb transfers. These have been tried and + // the result is "20 FF FF FF 20 FF FF 41", indicating that we are + // two to three times faster than the card, hence we can afford to + // poll the card. + { + PUCHAR dma_port = (PUCHAR)g->BaseIoAddress + MV101_DMA_PORT; + PUCHAR drq_port = (PUCHAR)g->BaseIoAddress + MV101_DRQ_PORT; + ULONG xfer_count = len; + UCHAR drq_mask = g->DRQMask; + _asm { + pushf + push esi + push edi + push ds + cld + mov ah,drq_mask +#ifdef MODE_32BIT + mov edx,dma_port + mov edi,drq_port + mov esi,pbytes + mov ecx,len +#else + mov edx,word ptr dma_port + mov edi,word ptr drq_port + mov esi,word ptr pbytes + mov ecx,word ptr len + mov ds, word ptr pbytes+2 +#endif + loop1: + xchg edx,edi // edx drq_port + in al,dx + test al,ah + jnz ready + in al,dx + test al,ah + jnz ready + in al,dx + test al,ah + jnz ready + + push ecx + mov ecx,TIMEOUT_READWRITE_LOOP + loop3: + mov ebx,0x10000 + loop2: + in al,dx + test al,ah + jnz ready1 + in al,dx + test al,ah + jnz ready1 + + // check for phase mismatch + + sub dx, MV101_DRQ_PORT - MV101_5380_2 // dx = N5380_CURRENT_STATUS + in al,dx + test al,CS_REQ + jz no_req + add dx, N5380_DMA_STATUS - N5380_CURRENT_STATUS // dx = N5380_DMA_STATUS + in al,dx + test al,DS_PHASE_MATCH + jz phase_error + sub dx, N5380_DMA_STATUS - N5380_CURRENT_STATUS // dx = N5380_CURRENT_STATUS + no_req: + add dx, MV101_DRQ_PORT - MV101_5380_2 // dx = MV101_DRQ_PORT + + dec ebx + jnz loop2 + dec ecx + jnz loop3 + pop ecx + mov rval,RET_STATUS_TIMEOUT + jmp short timeout + phase_error: + pop ecx + mov rval,RET_STATUS_DATA_OVERRUN + jmp short timeout + ready1: + pop ecx + // jmp ready + + ready: + xchg edx,edi // edx dma_port + outsb + dec ecx + jnz loop1 + timeout: + pop ds +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + pop edi + pop esi + popf + } + + // compute actual xfer len + *pActualLen = len - xfer_count; + } + +done: + // disable dma + + MV101DisableDmaWrite (g); + + // check for errors... + + if (rval == RET_STATUS_TIMEOUT) { + TrantorLogError (g->BaseIoAddress, rval, 104); + } + + return rval; +} diff --git a/private/ntos/miniport/trantor/source/n5380.c b/private/ntos/miniport/trantor/source/n5380.c new file mode 100644 index 000000000..011d7ca16 --- /dev/null +++ b/private/ntos/miniport/trantor/source/n5380.c @@ -0,0 +1,970 @@ +//----------------------------------------------------------------------- +// +// N5380.C +// +// N5380 access file. +// +// These routines are independent of the card the N5380 is on. The +// cardxxxx.h file must define the following routines: +// +// N5380PortPut +// N5380PortGet +// +// These routines could be defined by some other include file instead of +// cardxxxx.h, as the n53c400 defines the needed n5380xxxxxxxx routines. +// +// Revisions: +// 09-01-92 KJB First. +// 03-02-93 KJB/JAP Added N5380WaitLastByteSent. +// 03-02-93 JAP Cleaned comments. +// 03-02-93 KJB Fixed Names-- baseIoAddress back. +// 03-05-93 KJB Added N5380DisableDmaWrite routine to check for +// last byte sent. N5380DisableDma name changed to +// N5380DisableDmaRead. +// 03-11-93 JAP Changed retcode equates to reflect new names. +// 03-11-93 KJB Changes code to reflect new 5380 names. +// 03-19-93 JAP Implemented condition build FAR and NEAR pointers +// 03-23-93 KJB Changed for new functional interface. +// 03-24-93 KJB Added some debug code. +// 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 + +//----------------------------------------------------------------------- +// +// N5380CheckAdapter +// +// This routine checks for the presense of a 5380. +// +//----------------------------------------------------------------------- + +BOOLEAN N5380CheckAdapter (PADAPTER_INFO g) +{ + UCHAR tmp; + USHORT rval; + + // NOTE: May want to reset the bus or the adapter at some point + // + // CardResetBus(g); + + // set the phase to NULL + + if (rval = N5380SetPhase (g,PHASE_NULL)) { + return FALSE; + } + + // check to see that the 5380 data register behaves as expected + + N5380PortPut (g, N5380_INITIATOR_COMMAND, IC_DATA_BUS); + + // check for 0x55 write/read in data register + + N5380PortPut (g, N5380_OUTPUT_DATA, 0x55); + ScsiPortStallExecution (1); + N5380PortGet (g, N5380_CURRENT_DATA, &tmp); + + if (tmp != 0x55) { + return FALSE; + } + + // check for 0xaa write/read in data register + + N5380PortPut (g, N5380_OUTPUT_DATA, 0xaa); + ScsiPortStallExecution (1); + N5380PortGet (g, N5380_CURRENT_DATA, &tmp); + + if (tmp != 0xaa) { + return FALSE; + } + + N5380PortPut (g, N5380_INITIATOR_COMMAND, 0); + ScsiPortStallExecution (1); + N5380PortGet (g, N5380_CURRENT_DATA, &tmp); + + // data now should not match .... + + if (tmp == 0xaa) { + return FALSE; + } + + return TRUE; +} + + +//----------------------------------------------------------------------- +// +// N5380Select +// +// This routine selects a device through the 5380. +// +//----------------------------------------------------------------------- + +USHORT N5380Select (PADAPTER_INFO g, UCHAR target, UCHAR lun) +{ + USHORT rval; + + // set the phase to NULL + + if (rval = N5380SetPhase (g, PHASE_NULL)) { + return rval; + } + + // wait for bsy to go away if someone else is using bus + + if (rval = N5380WaitNoBusy (g, TIMEOUT_BUSY)) { + return rval; + } + + // assert our id and the target id on the bus + + N5380PortPut (g, N5380_OUTPUT_DATA, + (UCHAR)((1 << HOST_ID) | (1 << target))); + + // assert the data on the bus and assert select + + N5380PortSet (g, N5380_INITIATOR_COMMAND, + IC_SEL | IC_DATA_BUS); + + // wait for bsy to be asserted + + if (rval = N5380WaitBusy (g, 250)) { + + // clear the data bus + + N5380PortPut (g, N5380_OUTPUT_DATA, 0); + + // clear select and IC_DATA + + N5380PortClear (g, N5380_INITIATOR_COMMAND, + IC_SEL | IC_DATA_BUS); + + TrantorLogError (g->BaseIoAddress, RET_STATUS_SELECTION_TIMEOUT, 10); + + return RET_STATUS_SELECTION_TIMEOUT; + } + + // clear the data bus + + N5380PortPut (g, N5380_OUTPUT_DATA, 0); + + // assert the data on the bus, clear select , IC_DATA already set + + N5380PortClear (g, N5380_INITIATOR_COMMAND, IC_SEL); + + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380WaitBusy +// +// This routine waits for the busy line to be asserted. +// +//----------------------------------------------------------------------- + +USHORT N5380WaitBusy (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + if (N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for ( i = 0; i < usec; i++) { + if (N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 11); + + return RET_STATUS_TIMEOUT; +} + + #if 0 +//----------------------------------------------------------------------- +// +// N5380SelectArbitration +// +// This routine selects a device using arbitration. +// +//----------------------------------------------------------------------- + +USHORT N5380SelectArbitration (PADAPTER_INFO g, UCHAR target, UCHAR lun) +{ + USHORT rval; + + // set the phase to NULL + + if (rval = N5380SetPhase (g, PHASE_NULL)) { + return rval; + } + + // put our id bit on the bus + + N5380PortPut (g, N5380_OUTPUT_DATA, (UCHAR)(1 << HOST_ID)); + + // begin arbitration + + N5380PortSet (g, N5380_MODE, MR_ARBITRATE); + + // wait for bsy to go away if someone else is using bus + + if (rval = N5380WaitArbitration (g, TIMEOUT_BUSY)) { + goto done; + } + + // did we win? + + if (N5380PortTest (g, N5380_INITIATOR_COMMAND, + IC_LOST_ARBITRATION)) { + rval = RET_STATUS_BUSY; + TrantorLogError (g->BaseIoAddress, rval, 12); + goto done; + } + + // we have won, we are device 7, the highest, no one could beat us + // assert our id and the target id on the bus + + N5380PortPut (g, N5380_OUTPUT_DATA, + (UCHAR)((1 << HOST_ID) | (1 << target))); + + // assert the data on the bus and assert select + + N5380PortSet (g, N5380_INITIATOR_COMMAND, + IC_SEL | IC_DATA); + + // clear arb bit + + N5380PortClear (g, N5380_MODE, MR_ARBITRATE); + + // wait for bsy to be asserted + + if (rval = N5380WaitBusy (g, 250)) { + + // clear the data bus + + N5380PortPut (g, N5380_OUTPUT_DATA, 0); + + // clear select and IC_DATA + + N5380PortClear (g, N5380_INITIATOR_COMMAND, + IC_SEL | IC_DATA_BUS); + + rval = RET_STATUS_SELECTION_TIMEOUT; + + TrantorLogError (g->BaseIoAddress, rval, 13); + + goto done; + } + + // clear the data bus + + N5380PortPut (g, N5380_OUTPUT_DATA, 0); + + // assert the data on the bus, clear select , IC_DATA already set + + N5380PortClear (g, N5380_INITIATOR_COMMAND, IC_SEL); + + // Could go to command phase now, and clear spurrious interrupts... + // This is what the T160 does in our assembly code... + + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380WaitArbitration +// +// This routine waits for the arbitration to finish. +// +//----------------------------------------------------------------------- + +USHORT N5380WaitArbitration (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + if (!N5380PortTest (g, N5380_INITIATOR_COMMAND, + IC_ARBITRATION_IN_PROGRESS)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < usec; i++) { + if (!N5380PortTest (g, N5380_INITIATOR_COMMAND, + IC_ARBITRATION_IN_PROGRESS)) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 14); + + return RET_STATUS_TIMEOUT; +} + + #endif + + +//----------------------------------------------------------------------- +// +// N5380WaitNoBusy +// +// This routine waits for the Busy line to be deasserted. +// +//----------------------------------------------------------------------- + +USHORT N5380WaitNoBusy (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < usec; i++) { + if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 15); + + return RET_STATUS_TIMEOUT; +} + + +//----------------------------------------------------------------------- +// +// N5380WaitRequest +// +// This routine waits for request to be asserted. +// +//----------------------------------------------------------------------- + +USHORT N5380WaitRequest (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + if (N5380PortTest (g, N5380_CURRENT_STATUS, CS_REQ)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for ( i = 0; i < usec; i++) { + if (N5380PortTest (g, N5380_CURRENT_STATUS, CS_REQ)) { + return 0; + } + if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_BSY)) { + + TrantorLogError (g->BaseIoAddress, RET_STATUS_UNEXPECTED_BUS_FREE,16); + + return RET_STATUS_UNEXPECTED_BUS_FREE; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 17); + + return RET_STATUS_TIMEOUT; +} + + +//----------------------------------------------------------------------- +// +// N5380WaitLastByteSent +// +// This routine waits for last byte of dma transfer to be sent. +// +// Note: Not all 5380 chips have this feature. +// This routine should only be used when you are certain +// that the chips have this feature (e.g. with the n53c400). +// +//----------------------------------------------------------------------- + +USHORT N5380WaitLastByteSent (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + if (N5380PortTest (g, N5380_TARGET_COMMAND, + TC_LAST_BYTE_SENT)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < usec; i++) { + if (N5380PortTest (g, N5380_TARGET_COMMAND, + TC_LAST_BYTE_SENT)) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 18); + + return RET_STATUS_TIMEOUT; +} + + +//----------------------------------------------------------------------- +// +// N5380WaitNoRequest +// +// This routine waits for request to be deasserted. +// +//----------------------------------------------------------------------- + +USHORT N5380WaitNoRequest (PADAPTER_INFO g, ULONG usec) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_REQ)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < usec; i++) { + if (!N5380PortTest (g, N5380_CURRENT_STATUS, CS_REQ)) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 19); + + return RET_STATUS_TIMEOUT; +} + + +//----------------------------------------------------------------------- +// +// N5380GetPhase +// +// This routine returns the current scsi bus phase. +// +//----------------------------------------------------------------------- + +USHORT N5380GetPhase (PADAPTER_INFO g, PUCHAR phase) +{ + UCHAR tmp; + USHORT rval; + + // wait for request to be asserted + + if (rval = N5380WaitRequest (g, TIMEOUT_REQUEST)) { + return rval; + } + + // get current phase + + N5380PortGet (g, N5380_CURRENT_STATUS, &tmp); + + // return the phase + + *phase = (tmp >> 2) & 0x7; + + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380SetPhase +// +// This routine sets the 5380's expected bus phase in the target command +// register. +// +//----------------------------------------------------------------------- + +USHORT N5380SetPhase (PADAPTER_INFO g, UCHAR phase) +{ + UCHAR tmp; + + // phase must correspond the the bits of the target command register + + N5380PortPut (g, N5380_TARGET_COMMAND, phase); + + N5380PortGet (g, N5380_MODE, &tmp); + + // set the assert data bus bit to the right direction + + if (phase & TC_IO) { + + // IO is set + + if (tmp & MR_TARGET_MODE) { + + // we are in target mode always set the assert data bit + + N5380PortSet (g, N5380_INITIATOR_COMMAND, + IC_DATA_BUS); + } + else { + + // we are in initiator mode clear the data enable bit + + N5380PortClear (g, N5380_INITIATOR_COMMAND, + IC_DATA_BUS); + } + } + else { + + // IO is not set + + if (tmp & MR_TARGET_MODE) { + + // we are in initiator mode always set the assert data bit + + N5380PortClear (g, N5380_INITIATOR_COMMAND, + IC_DATA_BUS); + } + else { + + // we are in target mode clear the data assert bit + + N5380PortSet (g, N5380_INITIATOR_COMMAND, + IC_DATA_BUS); + } + } + + // no errors can occur from this function + + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380PutByte +// +// This routine writes a byte to the scsi bus using the req/ack protocol. +// To use this routine the phase should be set correctly using N5380SetPhase. +// +//----------------------------------------------------------------------- + +USHORT N5380PutByte(PADAPTER_INFO g, ULONG usec, UCHAR byte) +{ + USHORT rval; + + // put data byte to data register + + N5380PortPut (g, N5380_OUTPUT_DATA, byte); + + // wait for request to be asserted + + if (rval = N5380ToggleAck (g, usec)) { + return rval; + } + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380GetByte +// +// This routine reads a byte from the scsi bus using the req/ack protocol. +// To use this routine the phase should be set correctly using N5380SetPhase. +// +//----------------------------------------------------------------------- + +USHORT N5380GetByte (PADAPTER_INFO g, ULONG usec, PUCHAR byte) +{ + USHORT rval; + + // get data byte from data register + + N5380PortGet (g, N5380_CURRENT_DATA, byte); + + // wait for request to be asserted + + if (rval = N5380ToggleAck (g, usec)) { + return rval; + } + + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380ToggleAck +// +// This routine performs the req/ack handshake. It asserted ack, waits +// for request to be deasserted and then clears ack. +// +//----------------------------------------------------------------------- + +USHORT N5380ToggleAck (PADAPTER_INFO g, ULONG usec) +{ + USHORT rval; + UCHAR tmp; + + // assert ack + + N5380PortGet (g, N5380_INITIATOR_COMMAND, &tmp); + tmp = tmp | IC_ACK; + N5380PortPut (g, N5380_INITIATOR_COMMAND, tmp); + + // wait for request to be disappear + + if (rval = N5380WaitNoRequest (g, usec)) { + return rval; + } + + // clear ack + + N5380PortGet (g, N5380_INITIATOR_COMMAND, &tmp); + tmp = tmp & (IC_ACK^0xff); + N5380PortPut (g, N5380_INITIATOR_COMMAND, tmp); + + return 0; +} + + +//----------------------------------------------------------------------- +// +// N5380ResetBus +// +// This routine performs a Scsi Bus reset. +// +//----------------------------------------------------------------------- + +VOID N5380ResetBus (PADAPTER_INFO g) +{ + // reset the scsi bus + + N5380PortPut (g, N5380_INITIATOR_COMMAND, IC_RST); + + // leave signal asserted for a little while... + + ScsiPortStallExecution (SCSI_RESET_TIME); + + // Clear reset + + N5380PortPut (g, N5380_INITIATOR_COMMAND, 0); +} + + +//----------------------------------------------------------------------- +// +// N5380EnableDmaWrite +// +// This routine does the needed 5380 setup and initiates a dma write. +// +//----------------------------------------------------------------------- + +VOID N5380EnableDmaWrite (PADAPTER_INFO g) +{ + UCHAR tmp; + + // clear any interrupt condition on the 5380 + + N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp); + + // set the dma bit of 5380 + + N5380PortSet (g, N5380_MODE, MR_DMA_MODE); + + // start the dma on the 5380 + + N5380PortPut (g, N5380_START_DMA_SEND, 1); +} + + +//----------------------------------------------------------------------- +// +// N5380EnableDmaRead +// +// This routine does the needed 5380 setup and initiates a dma read. +// +//----------------------------------------------------------------------- + +VOID N5380EnableDmaRead (PADAPTER_INFO g) +{ + UCHAR tmp; + + // clear any interrupt condition on the 5380 + + N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp); + + // set the dma bit of 5380 + + N5380PortSet (g, N5380_MODE, MR_DMA_MODE); + + // start the dma on the 5380 + + N5380PortPut (g, N5380_START_INITIATOR_RECEIVE, 1); +} + + +//----------------------------------------------------------------------- +// +// N5380DisableDmaRead +// +// This routine disables dma for a read on the 5380. +// +//----------------------------------------------------------------------- + +VOID N5380DisableDmaRead (PADAPTER_INFO g) +{ + // Clear the dma bit of 5380 + + N5380PortClear (g, N5380_MODE, MR_DMA_MODE); +} + +//----------------------------------------------------------------------- +// +// N5380DisableDmaWrite +// +// This routine disables dma on the 5380 for a write command, it will +// wait until the last byte is sent. +// +//----------------------------------------------------------------------- + +VOID N5380DisableDmaWrite (PADAPTER_INFO g) +{ + USHORT i; + UCHAR ack_count; + + // for write commands... + // wait till last byte has been sent, don't assume the 5380 + // has a last byte sent bit in the target command register, + // not all 5380s have these + + // will need 3 samples with ack, without request + ack_count = 3; + for (i=0;i<1000;i++) { + + if (N5380PortTest(g,N5380_CURRENT_STATUS,CS_REQ)) { + + // will need 3 samples with ack, without request + ack_count = 3; + + // if request, do we have a phase mismatch? + + if (!N5380PortTest(g,N5380_DMA_STATUS, + DS_PHASE_MATCH)) { + + // yes, then we have gone onto the next phase, end of dma ok + + break; + } + + } else { + + if (N5380PortTest(g,N5380_DMA_STATUS,DS_ACK)) { + + // ack and no request, decrement our end of sample counter + ack_count--; + + if (!ack_count) { + + // sampled 3 times without request or ack.. we're done + break; + } + } + } + } + + // Clear the dma bit of 5380 + + N5380PortClear (g, N5380_MODE, MR_DMA_MODE); +} + +//----------------------------------------------------------------------- +// +// N5380Interrupt +// +// This routine checks to see if the 5380 has asserted its interrupts line. +// +//----------------------------------------------------------------------- + +BOOLEAN N5380Interrupt (PADAPTER_INFO g) +{ + return (N5380PortTest (g, N5380_DMA_STATUS, + DS_INTERRUPT_REQUEST)); +} + + +//----------------------------------------------------------------------- +// +// N5380DisableInterrupt +// +// This routine clears any pending 5380 interrupt condition. +// +//----------------------------------------------------------------------- + +VOID N5380DisableInterrupt (PADAPTER_INFO g) +{ + UCHAR tmp; + + // clear DMA mode + + N5380PortClear (g, N5380_MODE, MR_DMA_MODE); + + // clear any interrupt condition on the 5380 + + N5380PortGet (g, N5380_RESET_INTERRUPT, &tmp); +} + + +//----------------------------------------------------------------------- +// +// N5380PortSet +// +// Sets a mask in a 5380 register. +// +//----------------------------------------------------------------------- + +VOID N5380PortSet (PADAPTER_INFO g, UCHAR reg, UCHAR byte) +{ + UCHAR tmp; + + N5380PortGet (g, reg, &tmp); + tmp |= byte; + N5380PortPut (g, reg, tmp); +} + + +//----------------------------------------------------------------------- +// +// N5380PortClear +// +// Clears the given bit mask in a 5380 register. +// +//----------------------------------------------------------------------- + +VOID N5380PortClear (PADAPTER_INFO g, UCHAR reg, UCHAR byte) +{ + UCHAR tmp; + + N5380PortGet (g, reg, &tmp); + tmp &= (byte^0xff); + N5380PortPut (g, reg, tmp); +} + + +//----------------------------------------------------------------------- +// +// N5380PortTest +// +// Tests a bit mask in a 5380 register. +// +//----------------------------------------------------------------------- + +BOOLEAN N5380PortTest (PADAPTER_INFO g, UCHAR reg, UCHAR mask) +{ + UCHAR tmp; + + N5380PortGet (g, reg, &tmp); + return (tmp & mask); +} + + +//----------------------------------------------------------------------- +// +// N5380DebugDump +// +// Dumps registers 0-5 to the debug terminal. +// +//----------------------------------------------------------------------- +#ifdef WINNT +VOID N5380DebugDump (PADAPTER_INFO g) +{ + UCHAR tmp; + USHORT i; + + DebugPrint((DEBUG_LEVEL, "5380 registers:")); + for (i = 0; i < 6; i++) { + N5380PortGet (g, (UCHAR)i, &tmp); + DebugPrint((DEBUG_LEVEL, " %02x", tmp)); + } + DebugPrint((DEBUG_LEVEL, "\n")); +} +#else +#ifdef DOS +VOID N5380DebugDump (PADAPTER_INFO g) +{ + UCHAR tmp; + int i; + + printf("5380 registers:"); + for (i = 0; i < 6; i++) { + N5380PortGet (g, (UCHAR)i, &tmp); + printf (" %02x", tmp); + } + printf ("\n"); +} +#else +VOID N5380DebugDump (PADAPTER_INFO g) +{ +} +#endif +#endif + +//----------------------------------------------------------------------- +// End Of File. +//----------------------------------------------------------------------- + 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. +//----------------------------------------------------------------------- + diff --git a/private/ntos/miniport/trantor/source/p3c.c b/private/ntos/miniport/trantor/source/p3c.c new file mode 100644 index 000000000..275330e5c --- /dev/null +++ b/private/ntos/miniport/trantor/source/p3c.c @@ -0,0 +1,1069 @@ +//----------------------------------------------------------------------- +// +// P3C.C +// +// Trantor P3C access file. +// +// Revisions: +// 09-01-92 KJB First. +// 02-25-93 KJB Reorganized, supports dataunderrun with long delay +// for under run on large xfers. Can we fix this? +// 03-11-93 JAP Changed retcode equates to reflect new names. +// 03-11-93 KJB Changed to use N5380Enable/DisableDmaRead/Write +// routines. +// 03-12-93 KJB Now supports polling thru CardInterrupt and +// StartCommandInterrupt/FinishCommandInterrupt. +// 03-19-93 JAP Implemented condition build FAR and NEAR pointers +// 03-22-93 KJB Added support for scatter gather: P3CDoIo. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// 03-26-93 KJB Uni and bi directional read ports. +// 04-05-93 KJB Removed assembly loop instruction to work with +// winnt compiler. Removed unused variables. +// 05-14-93 KJB Remove all WINNT specific #ifdef i386 references. +// 05-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// 05-17-93 KJB Fixed bugs where the wrong parameter was being +// passed in EP3CDo/Start/FinishCommandInterrupt. +// +//----------------------------------------------------------------------- + +#include CARDTXXX_H + +// Local Functions + +VOID P3CPutControl(PADAPTER_INFO g,UCHAR mode, UCHAR reg); +VOID P3CSetPrinterMode(PADAPTER_INFO g, UCHAR data, UCHAR control); +VOID P3CSetScsiMode(PADAPTER_INFO g, PUCHAR data, PUCHAR control); + +USHORT P3CReadBytesFastBiDir(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase); +USHORT P3CReadBytesFastUniDir(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase); +BOOLEAN P3CCheckAdapterBiDir(PADAPTER_INFO g); +BOOLEAN P3CCheckAdapterUniDir(PADAPTER_INFO g); + + +// +// P3CPutControl +// +// This routine writes the p3c mode and the n5380 register number to the +// P3C. +// +VOID P3CPutControl(PADAPTER_INFO g,UCHAR mode, UCHAR reg) +{ + + UCHAR tmp; + + // output the mode and 5380 register to the parallel data reg + tmp = (mode & (PC_ADRS ^ 0xff)) | reg; + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,tmp); + + // + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = tmp & (0xff ^ P_BUFEN); + tmp = tmp | P_STB; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + tmp = tmp & (0xff ^ P_STB); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// P3CSetPrinterMode +// +// This routine sets the P3C to printer pass through mode. This is the +// default mode and should be set after the brief use of scsi mode. +// +VOID P3CSetPrinterMode(PADAPTER_INFO g, UCHAR data, UCHAR control) +{ + UCHAR tmp; + + // to prevent glitching, put P3C into read sig nibble mode + P3CPutControl(g,PCCC_MODE_RSIG_NIBBLE,0); + + // restore data register + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,data); + + // restore control register + // leave p_init negated + tmp = control | P_INIT; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// P3CSetScsiMode +// +// This routine sets the P3C into scsi mode. Now the parallel port can +// be used to send commands the the n5380. This mode should be set only +// briefly during when the scsi command is being executed. +// +VOID P3CSetScsiMode(PADAPTER_INFO g, PUCHAR data, PUCHAR control) +{ + UCHAR tmp; + + // save parallel data + ParallelPortGet(g->BaseIoAddress,PARALLEL_DATA,data); + + // zero data register + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0); + + // save parallel control + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,control); + *control = *control & (P_BUFEN ^ 0xff); + + // if in peripheral mode, get out to avoid glitch + tmp = *control | P_INIT; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // set ID pattern to data register + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0xfe); + + // clear slc and init on control + tmp = tmp & ((P_SLC | P_INIT) ^0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // assert slc + tmp = tmp | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // clear all bits in control + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); +} + +// +// P3CCheckAdapter +// +// This routine is used to sense the presense of the P3C adapter out +// on the Parallel port. It will only detect the adapter if a device +// is providing termination power. +// +BOOLEAN P3CCheckAdapter(PADAPTER_INFO g) +{ + BOOLEAN rval = FALSE; + + if (g->ParallelPortType == PT_UNKNOWN) { + // do we have a bi-directional port? + + if (P3CCheckAdapterBiDir(g)) { + + // yes, bi-directional port with a p3c + + g->ParallelPortType = PT_BI; + rval = TRUE; + + } else { + + // well, not bi-directional, but perhaps uni-directional? + + if (P3CCheckAdapterUniDir(g)) { + + // yes, uni-directional parallel port with P3C connected + + g->ParallelPortType = PT_UNI; + rval = TRUE; + } + } + } else { + // we are to try the specific type given + + if (g->ParallelPortType == PT_BI) { + + // check only bi-directional + + rval = P3CCheckAdapterBiDir(g); + + } else { + + if (g->ParallelPortType == PT_BI) { + + // check only uni-directional + + rval = P3CCheckAdapterUniDir(g); + + } else { + + // it is some other type we don't support + + rval = FALSE; + } + } + } + + + return rval; +} + +// +// BOOLEAN P3CCheckAdapterUniDir(PADAPTER_INFO g) +// +// Checks for an adapter on a uni-directional parallel port. +// +BOOLEAN P3CCheckAdapterUniDir(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + UCHAR tmp; + UCHAR sig0,sig1; + UCHAR sig_byte[3]; + USHORT i; + + // set scsi mode + P3CSetScsiMode(g,&data,&control); + + // set read sig nibble mode + P3CPutControl(g,PCCC_MODE_RSIG_NIBBLE,0); + + // zero data reg to get max contention during read signature + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0); + + for (i=0;i<3;i++) { + // Assert SLC + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = (tmp & (P_BUFEN ^ 0xff)) | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read in the status reg, it has the low nibble + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&sig0); + + // Deassert SLC + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = (tmp & (P_BUFEN ^ 0xff)) & (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // note: there must be a delay here for timing + + // Assert SLC + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = (tmp & (P_BUFEN ^ 0xff)) | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read in the status reg, it has the high nibble + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&sig1); + + // Deassert SLC + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp = (tmp & (P_BUFEN ^ 0xff)) & (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + sig_byte[i] = ((sig0 >> 3) & 0xf) | ((sig1 << 1) & 0xf0); + } + + // set parallel port for use by printer + + P3CSetPrinterMode(g,data,control); + + // compare the signature bytes + if ((sig_byte[0] == 0x6c) && (sig_byte[1] == 0x55) && + (sig_byte[2] == 0xaa)) { + return TRUE; + } + + return FALSE; +} + +// +// BOOLEAN P3CCheckAdapterBiDir(PADAPTER_INFO g) +// +// Checks for an adapter on a bi-directional parallel port +// +// +BOOLEAN P3CCheckAdapterBiDir(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + UCHAR tmp; + UCHAR sig_byte[3]; + USHORT i; + + // set scsi mode + P3CSetScsiMode(g,&data,&control); + + // set parallel port for BI-DIR if ps2 + // NOTE: this is destructive to NCR machines + // also, I don't know details about how this wakes up the + // ps/2's, it was copied directly from the t348.asm code. + +#ifndef MACHINE_NCR + PortIOPut((PVOID)0x94,0x7f); + PortIOGet((PVOID)0x102,&tmp); + tmp = tmp & 0x7f; + PortIOPut((PVOID)0x102,tmp); + PortIOPut((PVOID)0x94,0xff); +#endif + + // set read sig byte mode + + P3CPutControl(g,PCCC_MODE_RSIG_BYTE,0); + + // control register used to ack bytes + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,&tmp); + tmp |= P_BUFEN; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + for (i=0;i<3;i++) { + + // clock next byte in... + // Assert SLC + tmp = tmp | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // read in the byte + ParallelPortGet(g->BaseIoAddress,PARALLEL_DATA,&sig_byte[i]); + + // Deassert SLC + tmp &= (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // note: there must be a delay here for timing, C will provide it + + // Assert SLC + tmp |= P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // now upper nibble is on status register + + // Deassert SLC + tmp &= (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // ready to clock next byte in... + } + + // set parallel port for use by printer + + P3CSetPrinterMode(g,data,control); + + // compare the signature bytes + if ((sig_byte[0] == 0x6c) && (sig_byte[1] == 0x55) && + (sig_byte[2] == 0xaa)) { + return TRUE; + } + + return FALSE; +} + +// +// P3CDoCommand +// +// Called by the main loop to start a scsi command. This functions is the +// main entry point for all cards. It returns an SRB status code as defined +// in ..\..\inc\srb.h. A status code of RET_STATUS_PENDING means that the +// request has been sent to the controller and an interrupt is needed to +// finish the request. When this interrupt occurs CardFinishCommandInterrupt +// will be called. +// +USHORT P3CDoCommand(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + P3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiDoCommand(t); + + // put the parallel adapter back to parallel mode + + P3CSetPrinterMode(g, data, control); + return rval; +} + +// +// P3CStartCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the P3C does not support interrupts on its own. +// +// +USHORT P3CStartCommandInterrupt(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + P3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiStartCommandInterrupt(t); + + // put the parallel adapter back to parallel mode + + P3CSetPrinterMode(g, data, control); + + return rval; +} + +// +// P3CFinishCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the P3C does not support interrupts on its own. +// +// +USHORT P3CFinishCommandInterrupt(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + P3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiFinishCommandInterrupt(t); + + // put the parallel adapter back to parallel mode + + P3CSetPrinterMode(g, data, control); + + return rval; +} + +// +// P3CInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the P3C does not support interrupts on its own. +// +BOOLEAN P3CInterrupt(PADAPTER_INFO g) +{ + BOOLEAN rval; + UCHAR data; + UCHAR control; + + // put the parallel adapter into scsi mode + + P3CSetScsiMode(g, &data, &control); + + rval = N5380Interrupt(g); + + // put the parallel adapter back to parallel mode + + P3CSetPrinterMode(g, data, control); + + return rval; +} + +// +// P3CResetBus +// +// Resets the SCSI Bus +// +VOID P3CResetBus(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + + // put the parallel adapter into scsi mode + + P3CSetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + N5380ResetBus(g); + + // put the parallel adapter back to parallel mode + + P3CSetPrinterMode(g, data, control); +} + +// +// P3CWriteBytesFast +// +// 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 P3CWriteBytesFast(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + UCHAR control; + UCHAR tmp; + + // use slow mode for odd xfers (inquiry type commands) and audio + if (len % 512) { + return ScsiWriteBytesSlow(g, pbytes, len, + pActualLen, phase); + } + + // enable dma on 5380 + N5380EnableDmaWrite(g); + + // put the P3C into write dma mode + P3CPutControl(g,PCCC_MODE_WDMA,0); + + // start control reg off zero'ed, enable dma write mode + control = 0; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); + + { + ULONG xfer_count = len; + UCHAR control; + PBASE_REGISTER baseIoAddress = g->BaseIoAddress; + + control = 0; + _asm { + push esi + push ds +#ifdef MODE_32BIT + mov edx,baseIoAddress + mov esi,pbytes + mov ecx,len +#else + mov dx, word ptr baseIoAddress + mov si, word ptr pbytes + mov cx, word ptr len + mov ds, word ptr pbytes+2 +#endif // MODE_32BIT + mov bl,control // mask for control reg + mov bh,P_AFX // strobe mask + add dx,2 // dx points to control reg + get_bytes: + dec dx // dx points to status register + in al,dx + test al,P_BUSY + jz big_wait + ready: + dec dx // dx points to parallel data reg + mov al,[esi] + out dx,al + + add dx,2 // dx points to control reg + xor bl,bh + mov al,bl + out dx,al // give strobe, clock next data byte + + inc esi + dec ecx + jnz get_bytes + } + goto done_asm; + _asm { +big_wait: + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + // wait for a while before going to a bigger timeout + push ecx + push ebx + mov ebx,TIMEOUT_READWRITE_LOOP + loop0: + mov ecx,0x10000 + loop1: + in al,dx + test al,P_BUSY + jnz ready1 + in al,dx + test al,P_BUSY + jnz ready1 + dec ecx + jnz loop1 + dec ebx + jnz loop0 + pop ebx + pop ecx + jmp short error + ready1: + pop ebx + pop ecx + jmp short ready + error: + mov rval,RET_STATUS_TIMEOUT + done_asm: + pop ds + pop esi +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + } + + // compute actual xfer len + + *pActualLen = len - xfer_count; + } + + // clear the dma mode of 5380 + N5380DisableDmaWrite(g); + + // if data underrun, return the under/over run error message + + if (rval) { + + // phase mismatch means data under/over run + + N5380GetPhase(g,&tmp); + + if (tmp == PHASE_STATUS) { + rval = RET_STATUS_DATA_OVERRUN; + } + } + + return rval; +} + +// +// P3CReadBytesFast +// +// 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. +// +#pragma optimize("",off) +USHORT P3CReadBytesFast(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + + // use slow mode for odd xfers (inquiry type commands) and audio + if (len % 512) { + return ScsiReadBytesSlow(g, pbytes, len, + pActualLen, phase); + } + + N5380EnableDmaRead(g); + + // call the correct read fast routine based on the type of port + + if (g->ParallelPortType == PT_BI) { + rval = P3CReadBytesFastBiDir(g, pbytes, len, + pActualLen, phase); + } else { + rval = P3CReadBytesFastUniDir(g, pbytes, len, + pActualLen, phase); + } + + // clear the dma mode + N5380DisableDmaRead(g); + + // if data underrun, return the under/over run error message + + if (rval) { + UCHAR tmp; + + // phase mismatch means data under/over run + + N5380GetPhase(g,&tmp); + + if (tmp == PHASE_STATUS) { + rval = RET_STATUS_DATA_OVERRUN; + } + } + + return rval; +} + +// +// USHORT P3CReadBytesFastBiDir(PADAPTER_INFO g, PUCHAR pbytes, +// +// Reads bytes fast on a bi-directional parallel port. +// +USHORT P3CReadBytesFastBiDir(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + + // put the P3C into read dma mode + + P3CPutControl(g,PCCC_MODE_RDMA_BYTE,0); + + // start control reg with P_SLC and P_BUFEN + + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,P_SLC | P_BUFEN); + + // for inline assembly, we don't have to save eax-edx registers + { + ULONG xfer_count = len; + UCHAR control; + PBASE_REGISTER baseIoAddress = g->BaseIoAddress; + + // keep track of control register + control = P_SLC | P_BUFEN; + + _asm { + push esi + push ds +#ifdef MODE_32BIT + mov edx,baseIoAddress + mov esi,pbytes + mov ecx,len +#else + mov dx, word ptr baseIoAddress + mov si, word ptr pbytes + mov cx, word ptr len + mov ds, word ptr pbytes+2 +#endif // MODE_32BIT + mov bl,control // mask for control reg + mov bh,P_AFX // strobe mask + add dx,2 // dx points to control register + get_bytes: + dec dx // dx points to status register + in al,dx + test al,P_BUSY + jz big_wait + + ready: + dec dx // dx points to data register + + // get next byte + in al,dx + mov [esi],al + + // toggle strobe and select high nibble + add dx,2 // dx points to control register + xor bl,bh + mov al,bl + out dx,al // strobe to ack byte + + // loop + inc esi + dec ecx + jnz get_bytes + } + goto done_asm; + _asm { +big_wait: + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + // wait for a while before going to a bigger timeout + push ecx + push ebx + mov ebx,TIMEOUT_READWRITE_LOOP + loop0: + mov ecx,0x10000 + loop1: + in al,dx + test al,P_BUSY + jnz ready1 + in al,dx + test al,P_BUSY + jnz ready1 + + dec ecx + jnz loop1 + dec ebx + jnz loop0 + pop ebx + pop ecx + jmp short error + ready1: + pop ebx + pop ecx + } + goto ready; + _asm { + error: + mov rval,RET_STATUS_TIMEOUT + done_asm: + pop ds + pop esi +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + } + + // compute actual xfer len + + *pActualLen = len - xfer_count; + } + + // zero control register, disable read dma mode + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); + + return rval; +} + +// +// USHORT P3CReadBytesFastUniDir(PADAPTER_INFO g, PUCHAR pbytes, +// +// Reads bytes fast on a uni-directional parallel port. +// +USHORT P3CReadBytesFastUniDir(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + UCHAR data; + + // put the P3C into read dma mode + P3CPutControl(g,PCCC_MODE_RDMA_NIBBLE,0); + + // start data reg to select high nibble + data = 0x80; + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,data); + data = 0; + + // start control reg with P_SLC + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,P_SLC); + + // for inline assembly, we don't have to save eax-edx registers + { + ULONG xfer_count = len; + PBASE_REGISTER baseIoAddress = g->BaseIoAddress; + + _asm { + push esi + push ds +#ifdef MODE_32BIT + mov edx,baseIoAddress + mov esi,pbytes + mov ecx,len +#else + mov dx, word ptr baseIoAddress + mov si, word ptr pbytes + mov cx, word ptr len + mov ds, word ptr pbytes+2 +#endif // MODE_32BIT + mov bl,data + get_bytes: + inc dx // dx points to status register + in al,dx + test al,P_BUSY + jz big_wait + + // save the high nibble + ready: + mov ah,al + + // select lower nibble + dec dx // dx points to data register + mov al,bl + out dx,al + + // calculate high nibble + shl ah,1 + and ah,0f0h + + // get lower nibble + inc dx // dx points to status register + in al,dx + mov bh,al + + // toggle strobe and select high nibble + dec dx // dx points to data register + xor bl,0x40 + mov al,bl + or al,80h + out dx,al + +// +// We need some delay here for the t348 to respond to the strobe +// and lower the p_busy line. This loop serves the purpose and +// allows us to break out early in some cases. I have tried this +// with cx = 1 and this is not enough time. cx = 2 is enough, but +// for faster 486's or 586's this may need to be boosted higher. +// +// Note: the jmp $+2 that has been in our 348 code for DOS runs +// significantly faster on the 486, and out instructions are also +// much faster in protected mode! This totally threw off the timing +// of our DOS code. +// -KJB +// +#if 0 + push cx + mov cx,100 + inc dx // dx points to status register +loop1: + in al,dx + test al,P_BUSY + jz out1 + dec cx + jnz loop1 +out1: + pop cx + dec dx // dx points to data register +#endif + + // compute low nibble and the whole byte + shr bh,1 + shr bh,1 + shr bh,1 + and bh,0fh + or ah,bh + mov al,ah + + + // store data and loop + mov [esi],al + inc esi + dec ecx + jnz get_bytes + } + goto done_asm; + _asm { +big_wait: + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + in al,dx + test al,P_BUSY + jnz ready + + // wait for a while before going to a bigger timeout + push ecx + push ebx + mov ebx,TIMEOUT_READWRITE_LOOP + loop0: + mov ecx,0x10000 + loop1: + in al,dx + test al,P_BUSY + jnz ready1 + in al,dx + test al,P_BUSY + jnz ready1 + + dec ecx + jnz loop1 + dec ebx + jnz loop0 + pop ebx + pop ecx + jmp short error + ready1: + pop ebx + pop ecx + } + goto ready; + _asm { + error: + mov rval,RET_STATUS_TIMEOUT + done_asm: + pop ds + pop esi +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + } + + // compute actual xfer len + + *pActualLen = len - xfer_count; + } + + // zero control register, disable read dma mode + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); + + return rval; +} +#pragma optimize("",on) + +// +// N5380PortPut +// +// This routine is used by the N5380.C module to write byte to a 5380 +// controller. This allows the module to be card independent. Other +// modules that assume a N5380 may also use this function. +// +VOID N5380PortPut(PADAPTER_INFO g,UCHAR reg,UCHAR byte) +{ + + P3CPutControl(g,PCCC_MODE_WPER,reg); + + // write the byte + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,byte); + + // toggle the data_ready line + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,P_SLC); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); +} + +// +// N5380PortGet +// +// This routine is used by the N5380.C module to get a byte from a 5380 +// controller. This allows the module to be card independent. Other +// modules that assume a N5380 may also use this function. +// +VOID N5380PortGet(PADAPTER_INFO g,UCHAR reg,PUCHAR byte) +{ + UCHAR tmp,tmp1; + + P3CPutControl(g,PCCC_MODE_RPER_NIBBLE,reg); + + // assert slc + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,P_SLC); + + // select high nibble + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0x80); + + // read high nibble + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&tmp); + + // compute high nibble + tmp = (tmp << 1) & 0xf0; + + // select low nibble + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,0x00); + + // read low nibble + ParallelPortGet(g->BaseIoAddress,PARALLEL_STATUS,&tmp1); + + // compute low nibble + tmp1 = (tmp1 >> 3) & 0x0f; + + // compute and return byte + *byte = tmp1 | tmp; + + // clear slc + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); +} diff --git a/private/ntos/miniport/trantor/source/parallel.c b/private/ntos/miniport/trantor/source/parallel.c new file mode 100644 index 000000000..f88c8ad2e --- /dev/null +++ b/private/ntos/miniport/trantor/source/parallel.c @@ -0,0 +1,86 @@ +#ifdef i386 +//-------------------------------------------------------------------- +// +// PARALLEL.C +// +// Parallel port access file. +// +// Revisions: +// 09-01-92 KJB First. +// 03-11-93 JAP Changed retcode equates to reflect new names. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +//-------------------------------------------------------------------- + +#include CARDTXXX_H + +// +// ParallelWaitBusy +// +// This routine waits until the busy line is 1. +// + +USHORT ParallelWaitBusy (PBASE_REGISTER baseIoAddress, ULONG usec, PUCHAR data) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + ParallelPortGet (baseIoAddress, PARALLEL_STATUS, data); + if (*data & P_BUSY) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < usec; i++) { + ParallelPortGet (baseIoAddress, PARALLEL_STATUS, data); + if (*data & P_BUSY) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + return RET_STATUS_TIMEOUT; +} + + +// +// ParallelWaitNoBusy +// +// This routine waits until the busy line is 0. +// + +USHORT ParallelWaitNoBusy (PBASE_REGISTER baseIoAddress, ULONG usec, PUCHAR data) +{ + ULONG i; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + ParallelPortGet (baseIoAddress, PARALLEL_STATUS, data); + if (!(*data & P_BUSY)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < usec; i++) { + ParallelPortGet (baseIoAddress, PARALLEL_STATUS, data); + if (!(*data & P_BUSY)) { + return 0; + } + ScsiPortStallExecution (1); + } + + // return with an error, non-zero indicates timeout + + return RET_STATUS_TIMEOUT; +} + + +#endif diff --git a/private/ntos/miniport/trantor/source/pc9010.c b/private/ntos/miniport/trantor/source/pc9010.c new file mode 100644 index 000000000..85fc41a0e --- /dev/null +++ b/private/ntos/miniport/trantor/source/pc9010.c @@ -0,0 +1,851 @@ +//--------------------------------------------------------------------- +// +// File: PC9010.C +// +// PC9010 access file. +// +// These routines are independent of the card the PC9010 is on. The +// cardxxxx.h file must define the following routines: +// +// PC9010PortPut +// PC9010PortGet +// PC9010PortSet +// PC9010PortClear +// PC9010PortTest +// +// PC9010PortGetWord +// PC9010PortGetBufferWord +// PC9010PortPutWord +// PC9010PortPutBufferWord +// +// These routines could be defined by some other include file instead of +// cardxxxx.h, as the pc9010 defines the needed N5380xxxxxxxx routines. +// +// NOTES: +// 8 bit mode is not supported now. +// When data overrun occurs, the wrong number of bytes sent is returned +// this occurs only during writes to a scsi device and the device +// does not accept all bytes sent. The fifo of the pc9010 fills +// and we don't know how many of the bytes have been transfered +// across the bus... +// +// Revisions: +// 02-24-92 KJB First, does not support 8 bit mode, since we will +// not be shipping any 8 bit adapters! +// 03-11-93 JAP Changed retcode equates to reflect new names. +// 03-11-92 KJB Changed to use new N5380.H names. +// 03-26-93 JAP Fixed up typedef and prototype inconsistencies +// 04-05-93 KJB DEBUG_LEVEL used by DebugPrint for NT. +// 05-17-93 KJB Fixed warning message. +// +//--------------------------------------------------------------------- + + +#include CARDTXXX_H + + +// switch setting on PC9010 for 16 bit transfers +// warning specific to T160 right now... + +#define TRANSFER_MODE_16BIT 0x2 + +// +// Local Routines +// +USHORT PC9010ReadBytes8Bit(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen); +USHORT PC9010ReadBytes16Bit(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen); +USHORT PC9010WriteBytes8Bit(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen); +USHORT PC9010WriteBytes16Bit(PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen); +VOID PC9010FifoDataTransferSetup(PADAPTER_INFO g, + BOOLEAN *mode_16bit); +USHORT PC9010WaitTillFifoReady(PADAPTER_INFO g, + BOOLEAN (*ReadyRoutine)(PADAPTER_INFO g) ); +BOOLEAN PC9010Read16ReadyRoutine(PADAPTER_INFO g); +BOOLEAN PC9010Write16ReadyRoutine(PADAPTER_INFO g); +BOOLEAN PC9010FifoEmptyRoutine(PADAPTER_INFO g); + + +// +// Redefined Routines +// + +#define PC9010WaitTillFifoEmpty(g) \ + PC9010WaitTillFifoReady(g, PC9010FifoEmptyRoutine); + +// +// PC9010CheckAdapter +// +// This routine checks for the presense of a pc9010. +// + +BOOLEAN PC9010CheckAdapter (PADAPTER_INFO g) +{ + UCHAR tmp; + + // try to clear the config bit of the control register + + PC9010PortClear (g, PC9010_CONTROL, CTR_CONFIG); + + if (PC9010PortTest (g, PC9010_CONTROL, CTR_CONFIG)) { + goto not_pc9010; + } + + // try to set the config bit of the control register + + PC9010PortSet (g, PC9010_CONTROL, CTR_CONFIG); + + if (!PC9010PortTest (g, PC9010_CONTROL, CTR_CONFIG)) { + goto not_pc9010; + } + + // the config bit is set, now read the configuration info + + PC9010PortGet (g, PC9010_CONFIG, &tmp); + + if (tmp != PC9010_JEDEC_ID) { + goto not_pc9010; + } + + // this next byte sould be # of continuation chars, = 0 + + PC9010PortGet (g, PC9010_CONFIG, &tmp); + + if (tmp) { + goto not_pc9010; + } + + // now we will assume we have a pc9010 + + // initialize registers to 0 + + PC9010PortPut (g, PC9010_CONTROL, 0); + N5380PortPut (g, N5380_INITIATOR_COMMAND, 0); + N5380PortPut (g, N5380_MODE, 0); + + return TRUE; + +not_pc9010: + + // the pc9010 was not found + + return FALSE; +} + + +// +// PC9010WaitTillFifoReady +// +// Waits until fifo is ready to transfer something, checks for phase +// change and will timeout. +// +// The procedural parameter, ReadyRoutine, allows this routine to +// function for all modes: read, write, 16 and 8 bit modes. +// + +USHORT PC9010WaitTillFifoReady (PADAPTER_INFO g, + BOOLEAN (*ReadyRoutine)(PADAPTER_INFO g)) +{ + ULONG i; + USHORT rval = 0; + + for (i = 0; i < TIMEOUT_QUICK; i++) { + + // is the fifo ready? + + if ((*ReadyRoutine)(g)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < TIMEOUT_REQUEST; i++) { + + // is the fifo ready? + + if ((*ReadyRoutine)(g)) { + return 0; + } + + // check for phase mismatch + + // disable the fifo, temporarily + + PC9010PortClear (g, PC9010_CONTROL, CTR_FEN); + + // note: the PC9010 will take 3 machine clocks to recognize this, + // the C code will provide these with no problem! + + while (PC9010PortTest (g, PC9010_CONTROL, CTR_FEN)); + + // check for request and phase mismatch + + if (N5380PortTest (g, N5380_CURRENT_STATUS, CS_REQ) && + !N5380PortTest (g, N5380_DMA_STATUS, DS_PHASE_MATCH)) { + + // phase mismatch, means data under/overrun + + rval = RET_STATUS_DATA_OVERRUN; + DebugPrint((DEBUG_LEVEL,"Error - 0 - PC9010WaitTillFifoReady\n")); + goto error; + } + + // re-enable the fifo + + PC9010PortSet (g, PC9010_CONTROL, CTR_FEN); + + ScsiPortStallExecution (1); + } + + rval = RET_STATUS_TIMEOUT; + +error: + DebugPrint((DEBUG_LEVEL,"Error - 1 - PC9010WaitTillFifoReady\n")); + + // return with an error + + return rval; +} + + +#if 0 +// We can use the other routine + +// +// PC9010WaitTillFifoEmpty +// +// Waits until fifo is empty to transfer something. +// +USHORT PC9010WaitTillFifoEmpty (PADAPTER_INFO g) +{ + ULONG i; + USHORT rval = 0; + UCHAR tmp; + + // see if the flag comes back quickly + + for (i = 0; i < TIMEOUT_QUICK; i++) { + + // is the fifo empty? + + if (PC9010PortTest (g, PC9010_FIFO_STATUS, FSR_FEMP)) { + return 0; + } + } + + // ok, it did not come back quickly, we will yield to other processes + + for (i = 0; i < TIMEOUT_REQUEST; i++) { + + // is the fifo empty? + + if (PC9010PortTest (g, PC9010_FIFO_STATUS, FSR_FEMP)) { + return 0; + } + + ScsiPortStallExecution (1); + } + + rval = RET_STATUS_TIMEOUT; + +error: + DebugPrint((DEBUG_LEVEL,"Error - 1 - PC9010WaitTillFifoEmpty\n")); + + // return with an error + + return rval; +} +#endif + + +// +// PC9010FifoEmptyRoutine +// +// Check to see if the fifo is ready to read 16 bits. +// + +BOOLEAN PC9010FifoEmptyRoutine (PADAPTER_INFO g) +{ + // if both lanes of fifo are not empty then return true + + return (PC9010PortTest (g, PC9010_FIFO_STATUS, FSR_FEMP)); +} + + +// +// PC9010Read16ReadyRoutine +// +// Check to see if the fifo is ready to read 16 bits. +// + +BOOLEAN PC9010Read16ReadyRoutine (PADAPTER_INFO g) +{ + // if both lanes of fifo are not empty then return true + + return (!PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLEMP | FSR_FHEMP)); +} + +// +// PC9010FifoDataTransferSetup +// +// Setup the PC9010 chip for data transfer, either read or write. +// + +VOID PC9010FifoDataTransferSetup (PADAPTER_INFO g, + BOOLEAN *mode_16bit) +{ + USHORT rval = 0; + UCHAR tmp; + + // disable the fifo + + PC9010PortClear (g, PC9010_CONTROL, CTR_FEN); + + // reset the fifo + + PC9010PortSet (g, PC9010_CONTROL, CTR_FRST); + + // clear reset, config, swsel, dir , selecting low switch bank + + PC9010PortClear (g, PC9010_CONTROL, + CTR_FRST | CTR_CONFIG | CTR_SWSEL | CTR_FDIR); + + // check for 16 bit mode, switch 2 = 0 + // note: this is specific to a trantor card: the t160... + + PC9010PortGet (g, PC9010_CONFIG, &tmp); + *mode_16bit = !(tmp & TRANSFER_MODE_16BIT); + + // set the 16 bit mode or 8 bit for the fifo + + if (*mode_16bit) { + PC9010PortSet (g, PC9010_CONTROL, CTR_F16); + } + else { + PC9010PortClear (g, PC9010_CONTROL, CTR_F16); + } +} + + +// +// PC9010ReadBytes8Bit +// +// Reads bytes for the PC9010 in 8 bit mode. +// + +USHORT PC9010ReadBytes8Bit (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen) +{ + return RET_STATUS_ERROR; +} + + +// +// PC9010ReadBytes16Bit +// +// Reads bytes for the PC9010 in 16 bit mode. +// + +USHORT PC9010ReadBytes16Bit (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen) +{ + PUCHAR pBuffer = pbytes; + PUCHAR pBufferEnd = &pBuffer[len]; + USHORT rval = 0; + USHORT tmpw; + + // 16 bit read loop + + while (pBuffer != pBufferEnd) { + + // can we do a big transfer? + + if (PC9010PortTest (g, PC9010_FIFO_STATUS, FSR_FFUL)) { + + PC9010PortGetBufferWord (g, PC9010_FIFO, pBuffer, 64); + pBuffer += 128; + + } + else { + + // is either fifo lane empty + + if (PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLEMP | FSR_FHEMP)) { + + // At least one half of the FIFO is empty. While waiting to + // read more data, monitor the 5380 to check for SCSI bus phase + // change (data underrun) or other errors. + + // NOTE: The lo half of the FIFO may contain data. If we're only + // waiting for one more byte, transfer it immediately and exit. + // If the FIFO is completely empty (if low FIFO empty, high FIFO + // is also empty, since data goes into low FIFO first), or we're + // waiting for more than 1 additional byte then it's necessary to + // check for SCSI errors. + + if (!PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLEMP) && pBuffer == pBufferEnd-1) { + + // the low lane has a byte, and it is the last byte of + // the transfer + + // read a word and discard the high byte + + PC9010PortGetWord (g, PC9010_FIFO, &tmpw); + *pBuffer = (UCHAR)tmpw; + pBuffer += 1; + + } + else { + + // could be a byte in fifo, but + // there are no words in the fifo, possible + // phase change, or we have to wait + + if (rval = PC9010WaitTillFifoReady(g, + PC9010Read16ReadyRoutine)) { + + // there has been a phase change, or timeout + + if (rval == RET_STATUS_TIMEOUT) { + + // for timeouts, just exit... + + goto done_error; + } + + // phase change, transfer any data remaining in fifo + + // is either fifo lane empty? + if (PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLEMP | FSR_FHEMP)) { + + // is the low lane empty? + + if (PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLEMP)) { + + // low lane is empty, all bytes have been xferred + + goto done_error; + } + + // one byte remaining in low lane, transfer it + // read a word and discard the high byte + + PC9010PortGetWord (g, PC9010_FIFO, &tmpw); + *pBuffer = (UCHAR)tmpw; + pBuffer +=1; + + // that was the last byte ever, exit + goto done_error; + } + + // there is at least a word in the fifo, fall through, + // we will get this phase error again later when + // all words have been transferred. + + } + } + } + else { + + // both lanes have at least one byte + + PC9010PortGetWord (g, PC9010_FIFO, pBuffer); + pBuffer +=2; + + } + } + } + +done_error: + + // if all bytes have been transferred and a phase change occured, + // then there was no over/underrun at all + + if (rval == RET_STATUS_DATA_OVERRUN) { + if (pBuffer == pBufferEnd) { + + // all bytes were transferred, no error + + rval = 0; + } + } + + // store the transfer len + + *pActualLen = pBuffer - pbytes; + + return rval; +} + + +// +// PC9010WriteBytes8Bit +// +// Writes bytes for the PC9010 in 8 bit mode. +// + +USHORT PC9010WriteBytes8Bit (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen) +{ + return RET_STATUS_ERROR; +} + + +// +// PC9010WriteBytes16Bit +// +// Writes bytes for the PC9010 in 16 bit mode. +// The len must be an even number of bytes... +// +USHORT PC9010WriteBytes16Bit (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen) +{ + PUCHAR pBuffer = pbytes; + PUCHAR pBufferEnd = &pBuffer[len]; + USHORT rval = 0; + + // 16 bit read loop + + while (pBuffer != pBufferEnd) { + + // can we do a big transfer? + + if (PC9010PortTest (g, PC9010_FIFO_STATUS, FSR_FEMP)) { + + ULONG count; + + // The FIFO is empty. Fill the FIFO in one burst. + // + // Transfer the lesser of the fifo size or the remaining number + // of bytes. + // + // Since we're doing word transfers we need to be careful if the + // number of remaining bytes is odd and less than the FIFO size. + // We handle this by bursting only an even number of bytes. If + // there is an odd balance remaining we pick it up later. + + count = pBufferEnd-pBuffer; + + if (count >= PC9010_FIFO_SIZE) { + + // we have at least FIFO_SIZE bytes to send, fill the fifo + + PC9010PortPutBufferWord(g, PC9010_FIFO, + pBuffer, 64); + pBuffer += PC9010_FIFO_SIZE; + + } + else { + + // write only the number of words we have + // if we have only one byte, we will get that later + + PC9010PortPutBufferWord (g, PC9010_FIFO, + pBuffer, count/2); + pBuffer += count; + } + } + else { + + // is either fifo lane full? + + if (!PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLFUL | FSR_FHFUL)) { + + // neither lane is full, we can write a word... + + PC9010PortPutWord (g, PC9010_FIFO, + *(PUSHORT)pBuffer); + pBuffer += 2; + + } + else { + + // at least one of the fifo lanes is full, wait until ready + // checking for phase mismatch or timeout + + if (rval = PC9010WaitTillFifoReady (g, + PC9010Write16ReadyRoutine)) { + + // there has been a phase change, or timeout + // just exit... + + goto done_error; + } + } + } + } + + // If there has been no error, wait for the FIFO to empty. + // + // NOTE: The way this is currently coded, a SCSI error could occur + // after the last byte is written to the FIFO but before the last + // byte is written from the FIFO to the 5380, causing the code to + // hang. To solve this problem the 5380 should probably be set for + // interrupting on phase change and on loss of BSY. Then, code + // can wait for one of those events, the FIFO to empty, or a + // time-out. -RCB + + rval = PC9010WaitTillFifoEmpty (g); + +done_error: + + // store the transfer len + + *pActualLen = pBuffer - pbytes; + + return rval; +} + + +// +// PC9010Write16ReadyRoutine +// +// Check to see if the fifo is ready to read 16 bits. +// +BOOLEAN PC9010Write16ReadyRoutine (PADAPTER_INFO g) +{ + // if both lanes of fifo are not full then return true + + return (!PC9010PortTest (g, PC9010_FIFO_STATUS, + FSR_FLFUL | FSR_FHFUL)); +} + + +// +// PC9010ReadBytesFast +// +// Read the bytes from a nPC9010 as fast as possible. +// + +USHORT PC9010ReadBytesFast (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + BOOLEAN mode_16bit; + + // TEST CODE!!! to throw off the byte count!! +// rval = ScsiReadBytesSlow(g,pbytes,1,pActualLen,phase); +// pbytes++; +// len--; + + // prepare the PC9010 for data transfer + + PC9010FifoDataTransferSetup(g,&mode_16bit); + + // start internal 5380 for data transfer + + N5380EnableDmaRead (g); + + // enable our fifo now + + PC9010PortSet (g,PC9010_CONTROL,CTR_FEN); + + //----------------------------------------------------------------------- + // READ LOOP + // + // NOTE: In both 8-bit and 16-bit read loops we tacitly assume + // that the target will never try to send more bytes than we + // have requested. In other words, if there are bytes in the + // FIFO, in some conditions we'll transfer the bytes without + // checking whether or not the host has actually requested that + // many bytes. + // + //----------------------------------------------------------------------- + + // If the transfer length is longer than the FIFO is deep and + // is less than or equal to 2048 bytes, wait briefly for the + // FIFO to fill. This behavior is designed to optimize the + // performance of short transfers where "byte banging" the + // FIFO actually leads to lower performance than waiting for + // a burst. If the transfer length is outside this range, or + // if the FIFO doesn't fill quickly, go ahead with the transfer + // immediately. + // + // THE REASONING: + // + // Transfers shorter than the FIFO depth could never fill the + // FIFO, so there is no sense waiting for FIFO full. + // + // On the other end of the range, "byte-banging" typically + // occurs for no more than one depth of the FIFO (128 bytes). + // So, the time to "byte-bang" 128 bytes starts to become a + // very small fraction of the overall transfer time when 2048 + // bytes (one CD-ROM sector) or more are transferred. + // + // How long is a brief wait? If we poll the FIFO flags 128 + // times (one FIFO depth) and the FIFO is still not full, then + // the SCSI device is clearly slower than we are. In this case + // we might as well start "byte-banging". Fast SCSI devices + // will easily fill the FIFO in the time it takes to poll the + // FIFO flags that many times. + + if (len > PC9010_FIFO_SIZE && len < 2048) { + ULONG i; + + // loop for a while, waiting for fifo to fill + + for (i = 0; i < PC9010_FIFO_SIZE; i++) { + if (PC9010PortTest (g, PC9010_FIFO_STATUS, FSR_FFUL)) { + break; + } + } + } + + if (mode_16bit) { + rval = PC9010ReadBytes16Bit (g, pbytes, len, pActualLen); + } else { + rval = PC9010ReadBytes8Bit (g, pbytes, len, pActualLen); + } + + // disable our fifo, wait for it to register as disabled + + PC9010PortClear (g, PC9010_CONTROL, CTR_FEN); + while (PC9010PortTest (g, PC9010_CONTROL, CTR_FEN)); + + // disable 5380 dma + + N5380DisableDmaRead (g); + + return rval; +} + + +// +// PC9010WriteBytesFast +// +// Write the bytes from a nPC9010 as fast as possible. +// + +USHORT PC9010WriteBytesFast (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + BOOLEAN mode_16bit; + ULONG bytes_left = 0; + + // TEST CODE!!! to throw off the byte count!! +// rval = ScsiWriteBytesSlow(g,pbytes,1,pActualLen,phase); +// pbytes++; +// len--; + + // prepare the PC9010 for data transfer + + PC9010FifoDataTransferSetup (g, &mode_16bit); + + // start internal 5380 for data transfer + + N5380EnableDmaWrite (g); + + // enable our fifo now, setting direction flag + + PC9010PortSet (g, PC9010_CONTROL, CTR_FEN | CTR_FDIR); + + if (mode_16bit) { + + // transfer only an even number of bytes + // transfer the odd byte later + + bytes_left = len&1; + rval = PC9010WriteBytes16Bit (g, pbytes, + len-bytes_left, pActualLen); + + } + else { + + rval = PC9010WriteBytes8Bit (g, pbytes, len, pActualLen); + } + + // disable our fifo, wait for it to register as disabled + + PC9010PortClear (g, PC9010_CONTROL, CTR_FEN); + while (PC9010PortTest (g, PC9010_CONTROL, CTR_FEN)); + + // disable 5380 dma + + N5380DisableDmaWrite (g); + + // do we have to transfer one byte? + + if (!rval && bytes_left) { + ULONG tmp_len; + + rval = ScsiWriteBytesSlow (g, &pbytes[len-1], + bytes_left, &tmp_len, phase); + + *pActualLen += tmp_len; + } + + return rval; +} + + +// +// PC9010DisableInterrupt +// +// Disable interrupts on the PC9010 +// + +VOID PC9010DisableInterrupt (PADAPTER_INFO g) +{ + + // disable the interrupt on the 5380 + + N5380DisableInterrupt (g); + + // disable interrupt in the PC9010 for 5380 ints + + PC9010PortClear (g, PC9010_CONTROL, CTR_IRQEN); +} + + +// +// PC9010EnableInterrupt +// +// Enable interrupts from the PC9010 +// + +VOID PC9010EnableInterrupt (PADAPTER_INFO g) +{ + + // set the dma bit of 5380 so we can get phase mismatch ints + + N5380EnableInterrupt (g); + + // enable interrupt in the PC9010 + + PC9010PortPut (g, PC9010_CONTROL, CTR_IRQEN); +} + + +// +// PC9010ResetBus +// +// Reset the SCSI bus +// + +VOID PC9010ResetBus (PADAPTER_INFO g) +{ + // reset the PC9010 + + PC9010PortPut (g, PC9010_CONTROL, CTR_FRST); + + // disable interrupts + + PC9010DisableInterrupt (g); + + // reset the scsi bus + + N5380ResetBus (g); +} + + diff --git a/private/ntos/miniport/trantor/source/port.c b/private/ntos/miniport/trantor/source/port.c new file mode 100644 index 000000000..e2246b3c6 --- /dev/null +++ b/private/ntos/miniport/trantor/source/port.c @@ -0,0 +1,62 @@ +//---------------------------------------------------------------------- +// File: PORT.C +// +// Contains generic port access routines. +// +// Revisions: +// 01-08-93 KJB First. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// +//---------------------------------------------------------------------- + +#include CARDTXXX_H + + +// +// CardPortSet +// +// This routine sets a mask on a certain port. It or's the mask with +// the value currently at the port. Works only for ports where all bits +// are readable and writable. +// + +VOID CardPortSet (PUCHAR baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + CardPortGet (baseIoAddress,&tmp); + tmp = tmp | mask; + CardPortPut (baseIoAddress,tmp); +} + + +// +// CardPortClear +// +// This routine clears a mask on a certain port. It and's the inverse with +// the value currently at the port. Works only for ports where all bits +// are readable and writable. +// +VOID CardPortClear (PUCHAR baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + CardPortGet(baseIoAddress,&tmp); + tmp = tmp & (0xff ^ mask); + CardPortPut(baseIoAddress,tmp); +} + +// +// CardPortTest +// +// This routine clears a mask on a certain port. It and's the mask with +// the value currently at the port. This result is returned. +// +BOOLEAN CardPortTest(PUCHAR baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + CardPortGet(baseIoAddress,&tmp); + return (tmp & mask); +} + diff --git a/private/ntos/miniport/trantor/source/portio.c b/private/ntos/miniport/trantor/source/portio.c new file mode 100644 index 000000000..b4726ad22 --- /dev/null +++ b/private/ntos/miniport/trantor/source/portio.c @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------- +// +// File: PORTIO.C +// +// Contains generic port access routines for I/O cards. +// +// Revisions: +// 02-24-93 KJB First. +// 03-22-93 KJB Reorged for stub function library. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// 04-05-93 KJB Added functions for word io. Changed PUCHAR to +// PBASE_REGISTER. +// +//------------------------------------------------------------------------- + +#include CARDTXXX_H + +// +// PortIOSet +// +// This routine sets a mask on a certain port. It or's the mask with +// the value currently at the port. Works only for ports where all bits +// are readable and writable. +// +VOID PortIOSet(PBASE_REGISTER baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + PortIOGet(baseIoAddress,&tmp); + tmp = tmp | mask; + PortIOPut(baseIoAddress,tmp); +} +VOID PortIOSetWord(PBASE_REGISTER baseIoAddress, USHORT mask) +{ + USHORT tmp; + + PortIOGetWord(baseIoAddress,&tmp); + tmp = tmp | mask; + PortIOPutWord(baseIoAddress,tmp); +} + +// +// PortIOClear +// +// This routine clears a mask on a certain port. It and's the inverse with +// the value currently at the port. Works only for ports where all bits +// are readable and writable. +// +VOID PortIOClear(PBASE_REGISTER baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + PortIOGet(baseIoAddress,&tmp); + tmp = tmp & (0xff ^ mask); + PortIOPut(baseIoAddress,tmp); +} +VOID PortIOClearWord(PBASE_REGISTER baseIoAddress, USHORT mask) +{ + USHORT tmp; + + PortIOGetWord(baseIoAddress,&tmp); + tmp = tmp & (0xff ^ mask); + PortIOPutWord(baseIoAddress,tmp); +} + +// +// PortIOTest +// +// This routine clears a mask on a certain port. It and's the mask with +// the value currently at the port. This result is returned. +// +BOOLEAN PortIOTest(PBASE_REGISTER baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + PortIOGet(baseIoAddress,&tmp); + return (tmp & mask); +} +BOOLEAN PortIOTestWord(PBASE_REGISTER baseIoAddress, USHORT theval) +{ + USHORT tmpw; + + PortIOGetWord(baseIoAddress, &tmpw); + return tmpw & theval; +} + + diff --git a/private/ntos/miniport/trantor/source/portmem.c b/private/ntos/miniport/trantor/source/portmem.c new file mode 100644 index 000000000..343f3f12f --- /dev/null +++ b/private/ntos/miniport/trantor/source/portmem.c @@ -0,0 +1,67 @@ +#ifdef i386 +//------------------------------------------------------------------------ +// +// File: PORTMEM.C +// +// Contains generic memory mapped port access routines. +// +// Revisions: +// 01-08-93 KJB First. +// 02-25-93 KJB Renamed routines from CardPort to PortMem. +// +//------------------------------------------------------------------------ + +#include CARDTXXX_H + +// +// PortMemSet +// +// This routine sets a mask on a certain port. It or's the mask with +// the value currently at the port. Works only for ports where all bits +// are readable and writable. +// + +VOID PortMemSet (PUCHAR baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + PortMemGet (baseIoAddress, &tmp); + tmp = tmp | mask; + PortMemPut (baseIoAddress, tmp); +} + + +// +// PortMemClear +// +// This routine clears a mask on a certain port. It and's the inverse with +// the value currently at the port. Works only for ports where all bits +// are readable and writable. +// + +VOID PortMemClear (PUCHAR baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + PortMemGet (baseIoAddress, &tmp); + tmp = tmp & (0xff ^ mask); + PortMemPut (baseIoAddress, tmp); +} + + +// +// PortMemTest +// +// This routine clears a mask on a certain port. It and's the mask with +// the value currently at the port. This result is returned. +// + +BOOLEAN PortMemTest (PUCHAR baseIoAddress, UCHAR mask) +{ + UCHAR tmp; + + PortMemGet (baseIoAddress, &tmp); + return (tmp & mask); +} + +#endif diff --git a/private/ntos/miniport/trantor/source/scsifnc.c b/private/ntos/miniport/trantor/source/scsifnc.c new file mode 100644 index 000000000..422a700d7 --- /dev/null +++ b/private/ntos/miniport/trantor/source/scsifnc.c @@ -0,0 +1,586 @@ +//--------------------------------------------------------------------- +// +// File: SCSIFNC.C +// +// N5380 Scsi Functions file. Contains higher level scsi functions. +// +// Revisions: +// 09-01-92 KJB First. +// 03-02-93 KJB/JAP Wait for phase change before doing i/o. +// 03-11-93 JAP Changed retcode equates to reflect new names. +// 03-12-93 KJB FinishCommandInterrupt now calls CardDisableInterrupt +// 03-19-93 JAP Implemented condition build FAR and NEAR pointers +// 03-23-93 KJB Changed for new functional interface. +// 03-24-93 KJB ScsiStartCommandInterrupt can now return +// RET_STATUS_MISSED_INTERRUPT, in which case caller +// should pretend interrupt happened and call +// FinishCommandInterrupt. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// 03-31-93 JAP/KJB Added code to handle data overflow: +// DATAIN: target sends more bytes than we have +// been asked to receive +// DATAOUT: target requests more bytes than we have +// been asked to send +// 04-05-93 KJB DEBUG_LEVEL used by DebugPrint for NT. +// 04-05-93 KJB Changed DoIo, now it will not return +// DATA_OVERRUN when there is no data to transfer. +// 04-09-93 KJB Check for phase mismatch before returning that +// we missed an interrupt. +// 05-13-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 the PBASE_REGISTER and the +// PWORKSPACE parameters. Auto Request Sense is +// now supported. +// 05-13-93 KJB Added RequestSenseValid field to TSRB. +// 05-16-93 KJB Fixed bug: finishcommandinterrupt was returning +// RET_STATUS_PENDING when length of xfer was 0. +// Now return RET_STATUS_ERROR when Status != 0. +// +//--------------------------------------------------------------------- + +#include CARDTXXX_H + +// +// Local functions +// +void ScsiDoRequestSense(PTSRB t); + +// +// ScsiSendCommand +// +// Selects a target and sends a scsi command during command phase. +// + +USHORT ScsiSendCommand (PADAPTER_INFO g, UCHAR target, + UCHAR lun, PUCHAR pcmd, UCHAR cmdlen) +{ + USHORT rval; + ULONG tmp; + + // select the target + + if (rval = N5380Select (g, target, lun)) { + if (rval != RET_STATUS_SELECTION_TIMEOUT) { + DebugPrint((DEBUG_LEVEL,"ScsiSendCommand-0 Error: %x\n",rval)); + } + return rval; + } + + // set the phase to Command + + if (rval = N5380SetPhase (g, PHASE_COMMAND)) { + DebugPrint((DEBUG_LEVEL,"ScsiSendCommand-1 Error: %x\n",rval)); + return rval; + } + + // send the command bytes + + if (rval = CardWriteBytesCommand (g, pcmd, (ULONG)cmdlen, + &tmp, PHASE_COMMAND)) { + DebugPrint((DEBUG_LEVEL,"ScsiSendCommand-2 Error: %x\n",rval)); + return rval; + } + + return 0; +} + + +// +// ScsiDoCommand +// +// Executes a complete scsi command: all phase sequences without using +// interrupts. +// + +USHORT ScsiDoCommand (PTSRB t) +{ + USHORT rval; + PADAPTER_INFO g = t->pWorkspace; + + // select the target and send the command bytes + + if (rval = ScsiSendCommand (g, t->Target, t->Lun, t->pCommand, + t->CommandLen)) { + DebugPrint((DEBUG_LEVEL,"ScsiDoCommand-0 Error: %x\n",rval)); + goto done; + } + + if (rval = ScsiFinishCommandInterrupt (t)) { + if (rval!=RET_STATUS_SUCCESS) { + DebugPrint((DEBUG_LEVEL,"ScsiDoCommand-1 Error: %x\n",rval)); + } + } + +done: + t->ReturnCode = rval; + + return rval; +} + + +// +// ScsiStartCommandInterrupt +// +// Executes a scsi command up to the end of command phase. After this, the +// interrupt will come in and ScsiFinishCommandInterrupt should be called to +// complete the data, status, and message phases. +// + +USHORT ScsiStartCommandInterrupt (PTSRB t) +{ + USHORT rval; + PADAPTER_INFO g = t->pWorkspace; + + // select the target and send the command bytes + + if (rval = ScsiSendCommand (g, t->Target, t->Lun, t->pCommand, + t->CommandLen)) { + DebugPrint((DEBUG_LEVEL,"ScsiStartCommandInterrupt-0 Error: %x\n",rval)); + goto done; + } + + // enable the interrupt + + CardEnableInterrupt (g); + + // if request is already up, we may have missed the interrupt, it is done + + if (N5380PortTest (g, N5380_CURRENT_STATUS, CS_REQ)) { + + // and we are not still in command phase + + if (!N5380PortTest(g, N5380_DMA_STATUS, DS_PHASE_MATCH)) { + rval = RET_STATUS_MISSED_INTERRUPT; + goto done; + } + } + + rval = RET_STATUS_PENDING; + +done: + t->ReturnCode = rval; + return rval; +} + +// +// ScsiFinishComamndInterrupt +// +// Called to finish a command that has been started by ScsiStartCommandInterupt. +// This function completes the data, status, and message phases. +// + +USHORT ScsiFinishCommandInterrupt (PTSRB t) +{ + USHORT rval = 0; + USHORT rval_stat = 0; + PADAPTER_INFO g = t->pWorkspace; + + + // set actual transfer length to 0 + + t->ActualDataLen = 0; + + // set request sense valid flag to FALSE + + t->Flags.RequestSenseValid = FALSE; + + // is there a data phase?? + + if (t->DataLen) { + + // read/write the data if there is a data phase + + rval = ScsiDoIo (t); + + } + + // if no errors, return RET_STATUS_SUCCESS. + + if (!rval) { + rval = RET_STATUS_SUCCESS; + } + + // get the stat and message bytes + + if (rval_stat = ScsiGetStat (g, &t->Status)) { + DebugPrint((DEBUG_LEVEL,"ScsiFinishCommandInterrupt-0 Error: %x\n",rval_stat)); + rval = rval_stat; + goto done; + } + + // if not any other error, return a general status error to indicate + // that the status byte was bad. + + if (!rval_stat) { + + // no errors get status, was there a status check condition? + + if (t->Status == 0x02) { + + if (t->Flags.DoRequestSense) { + ScsiDoRequestSense(t); + } + + } + + if (t->Status) { + + // return with error when there was a non-zero status + + rval = RET_STATUS_ERROR; + } + + } + + if (rval!=RET_STATUS_SUCCESS) { + DebugPrint((DEBUG_LEVEL,"ScsiFinishCommandInterrupt-1 Error: %x\n",rval)); + } + +done: + // disable the interrupt + + CardDisableInterrupt(g); + + // for now, we never return pending + + t->ReturnCode = rval; + return rval; +} + +// +// ScsiDoRequestSense +// +// Do a request sense and store the information in the current tsrb. +// Works on the stack, does not harm the current tsrb. +// +VOID ScsiDoRequestSense(PTSRB t) +{ + PADAPTER_INFO g = t->pWorkspace; + // allocate on stack ok, since we don't use interrupt for the sense cmd + TSRB tsrb; + PTSRB t0 = &tsrb; + UCHAR pSenseCmd[6]; + USHORT rval; + + pSenseCmd[0] = 0x03; + pSenseCmd[1] = 0x00; + pSenseCmd[2] = 0x00; + pSenseCmd[3] = 0x00; + pSenseCmd[4] = t->SenseDataLen; + pSenseCmd[5] = 0x00; + + // copy most of the tsrb information from the current tsrb + + *t0 = *t; + + // get the sense information + + t0->Flags.DoRequestSense = FALSE; // don't request sense info here + t0->pCommand = pSenseCmd; + t0->CommandLen = 6; + t0->Dir = TSRB_DIR_IN; + t0->pData = t->pSenseData; + t0->DataLen = t->SenseDataLen; + + rval = CardDoCommand(t0); // don't use interrupts + + if (rval == RET_STATUS_SUCCESS) { + t->Flags.RequestSenseValid = TRUE; + } +} + +// +// ScsiWriteBytesSlow +// +// This functions writes bytes to the scsi bus using the slow req/ack +// handshake. Faster methods are generally avaiable, but they are dependent +// on how the card inplements the dma capabilities of the 5380. This +// is a sure-fire slow method that works. It is great to bring up new cards. +// + +USHORT ScsiWriteBytesSlow (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + ULONG i; + USHORT rval = 0; + UCHAR tmp; + + for (i=0;ipWorkspace; + + // wait for next phase, errors in phase will be caught below + + if (rval = N5380GetPhase (g, &tmp)) { + goto done; + } + + if (t->DataLen && tmp != PHASE_DATAIN && tmp != PHASE_DATAOUT) { + + // phase is not data in/out and we were expecting data, len !=0 + + rval = RET_STATUS_DATA_OVERRUN; + goto done; + } + + + // phase is now either data in or data out + + if (t->Dir == TSRB_DIR_UNKNOWN) { + + // must be read/write, use phase bits to determine it + + if (tmp == PHASE_DATAOUT) { + t->Dir = TSRB_DIR_OUT; + } + else if (tmp == PHASE_DATAIN) { + t->Dir = TSRB_DIR_IN; + } + + // else: pass thru, don't transfer any data, must be in status phase + + } + + + if (t->Dir == TSRB_DIR_OUT) { + + // data write + + // set the phase to data out + + if (rval = N5380SetPhase (g, PHASE_DATAOUT)) { + return RET_STATUS_ERROR; + } + + // send the bytes + + if (rval = CardWriteBytesFast (g, t->pData, t->DataLen, + &t->ActualDataLen, PHASE_DATAOUT)) { + DebugPrint((DEBUG_LEVEL,"ScsiDoIo-0 Error: %x\n",rval)); + return rval; + } + + // Check for Data Overflow. + + while ((N5380GetPhase (g,&phase) == 0) && + (phase == PHASE_DATAOUT)) { + + // DATA OVERFLOW: + // Target requests more bytes than we have been asked to send. + // Send a dummy byte of 0 until we are out of DATAOUT phase. + + ULONG tmpDataLen; + UCHAR dummy = 0; + + if (rval = ScsiWriteBytesSlow (g, &dummy, 1, + &tmpDataLen, PHASE_DATAOUT)) { + DebugPrint((DEBUG_LEVEL,"ScsiDoIo-2 Error: %x\n",rval)); + return rval; + } + } + } + + else if (t->Dir == TSRB_DIR_IN) { + + // data read + + // set the phase to data in + + if (rval = N5380SetPhase (g, PHASE_DATAIN)) { + return RET_STATUS_ERROR; + } + + // read the bytes + + if (rval = CardReadBytesFast (g, t->pData, t->DataLen, + &t->ActualDataLen, PHASE_DATAIN)) { + DebugPrint((DEBUG_LEVEL,"ScsiDoIo-1 Error: %x\n",rval)); + return rval; + } + + // Check for Data Overflow. + + while ((N5380GetPhase(g,&phase) == 0) && + phase == PHASE_DATAIN) { + + // DATA OVERFLOW: + // Target sends more bytes than we have been asked to receive. + // Swallow up extra bytes until we are out of DATAIN phase. + + ULONG tmpDataLen; + UCHAR dummy; + + if (rval = ScsiReadBytesSlow (g, &dummy, 1, + &tmpDataLen, PHASE_DATAIN)) { + DebugPrint((DEBUG_LEVEL,"ScsiDoIo-3 Error: %x\n",rval)); + return rval; + } + } + } + +done: + return rval; +} + + +// +// ScsiGetStat +// +// This function gets the status and message bytes. +// + +USHORT ScsiGetStat (PADAPTER_INFO g, PUCHAR pstatus) +{ + UCHAR tmp; + USHORT rval; + + // set the phase to Status Phase + + if (rval = N5380SetPhase (g, PHASE_STATUS)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-0 Error: %x\n",rval)); + return rval; + } + + // wait for request to be asserted + + if (rval = N5380GetPhase (g,&tmp)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-1 Error: %x\n",rval)); + return rval; + } + + // see if phase match + + if (PHASE_STATUS != tmp) { + return RET_STATUS_PHASE_SEQ_FAILURE; + } + + // get the status byte + + if (rval = N5380GetByte (g, TIMEOUT_REQUEST, pstatus)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-2 Error: %x\n",rval)); + return rval; + } + + // set the phase to Message In Phase + + if (rval = N5380SetPhase (g, PHASE_MSGIN)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-3 Error: %x\n",rval)); + return rval; + } + + // wait for request to be asserted + + if (rval = N5380GetPhase (g,&tmp)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-4 Error: %x\n",rval)); + return rval; + } + + // see if phase match + + if (PHASE_MSGIN != tmp) { + return RET_STATUS_PHASE_SEQ_FAILURE; + } + + // get the msg byte, throw it away + + if (rval = N5380GetByte (g, TIMEOUT_REQUEST, &tmp)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-5 Error: %x\n",rval)); + return rval; + } + + // set the phase to NULL to up N5380 back to normal + + if (rval = N5380SetPhase (g, PHASE_NULL)) { + DebugPrint((DEBUG_LEVEL,"ScsiGetStat-6 Error: %x\n",rval)); + return rval; + } + + return rval; +} + diff --git a/private/ntos/miniport/trantor/source/scsiport.c b/private/ntos/miniport/trantor/source/scsiport.c new file mode 100644 index 000000000..30be5fc84 --- /dev/null +++ b/private/ntos/miniport/trantor/source/scsiport.c @@ -0,0 +1,181 @@ +//------------------------------------------------------------------------ +// +// SCSIPORT.C +// +// DOS Port Access File +// +// Contains functions to access I/O and memory ports. Some of these +// routines may not be called for some cards. IO access routines are +// called for IO mapped cards, Mem access routines are called for Mem +// mapped cards. +// +// For DOS these are simple assembly functions. +// +// Revisions: +// 01-29-93 KJB First. +// 03-03-93 KJB Improved comments. +// 03-22-93 KJB Reorged for stub function library. +// 03-25-93 JAP Fixed up typedef and prototype inconsistencies +// +//------------------------------------------------------------------------ + + +#include CARDTXXX_H + +// +// ScsiPortReadPortUchar +// +// Does an "in" instruction from i/o port p. +// Returns the value. +// + +UCHAR ScsiPortReadPortUchar (PUCHAR p) +{ + UCHAR rval; + + _asm { + mov dx,word ptr p + in al,dx + mov rval,al + } + return rval; +} + +// +// ScsiPortWritePortUchar +// +// Does an "out" instruction to i/o port p. +// +VOID ScsiPortWritePortUchar(PUCHAR p,UCHAR b) +{ + _asm { + mov dx,word ptr p + mov al,b + out dx,al + } +} + +// +// ScsiPortReadPortUshort +// +// Does an "in" instruction from i/o port p. +// Returns the value. +// +USHORT ScsiPortReadPortUshort(PUSHORT p) +{ + USHORT rval; + + _asm { + mov dx,word ptr p + in ax,dx + mov rval,ax + } + return rval; +} + +// +// ScsiPortWritePortUshort +// +// Does an "out" instruction to i/o port p. +// +VOID ScsiPortWritePortUshort(PUSHORT p,USHORT w) +{ + _asm { + mov dx,word ptr p + mov ax,w + out dx,ax + } +} + +// +// ScsiPortWritePortBufferUshort +// +// Does an "rep outsw" instruction to i/o port p. +// +VOID ScsiPortWritePortBufferUshort(PUSHORT p, PUSHORT buffer, ULONG len) +{ + _asm { + push ds + push esi + mov dx,word ptr p + mov esi,word ptr buffer + mov ds,word ptr buffer+2 + mov cx,word ptr len + rep outsw + pop esi + pop ds + } +} + +// +// ScsiPortReadPortBufferUshort +// +// Does an rep "insw" instruction from i/o port p. +// +VOID ScsiPortReadPortBufferUshort(PUSHORT p, PUSHORT buffer, ULONG len) +{ + _asm { + push es + push edi + mov dx,word ptr p + mov di,word ptr buffer + mov es,word ptr buffer+2 + mov cx,word ptr len + rep insw + pop edi + pop es + } +} + +// +// ScsiPortReadPortRegisterUchar +// +// Reads a memory mapped i/o address. +// Returns the value. +// +UCHAR ScsiPortReadRegisterUchar(PUCHAR p) +{ + UCHAR rval; + + _asm { + push es + mov bx,word ptr p + mov es,word ptr p+2 + mov al,es:[bx] + mov rval, al + pop es + } + return rval; +} + +// +// ScsiPortWritePortRegisterUchar +// +// Writes a value to a memory mapped i/o address. +// +VOID ScsiPortWriteRegisterUchar(PUCHAR p,UCHAR b) +{ + _asm { + push es + mov bx,word ptr p + mov es,word ptr p+2 + mov al, b + mov es:[bx],al + pop es + } +} + +// +// ScsiPortStallExecution +// +// Stalls executeion for time micro seconds. Should be processor, +// independent, but for now we will do just a loop. +// +VOID ScsiPortStallExecution(ULONG time) +{ + ULONG i; + + if (time>1) { + for (i=0;i> PPC_SEL_POS; + fpp_cntl = fpp_xlate[tmpb]; // new FPP_CNTL value + + //----------------------------------------------------------------------- + // Disable PS/2 style registers. + //----------------------------------------------------------------------- + + if (!SL386EnableConfig()) { + rval = FALSE; + goto done; + } + + PortIOPut((PBASE_REGISTER) SL_CFG_INDEX,SL_CFGR2); + PortIOClear((PBASE_REGISTER)SL_CFG_DATA,C2_PS2); + + SL386DisableConfig(); + + //----------------------------------------------------------------------- + // Set "fast" mode in FPP_CNTL register. + //----------------------------------------------------------------------- + + PortIOPut((PBASE_REGISTER)SL_SF_INDEX,SL_FPP_CNTL); + + // test current FPP_CNTL value + if (PortIOTest((PBASE_REGISTER)SL_SF_DATA,FPP_FM)) { + // already in fast mode + // make sure that "ext" mode is set + PortIOSet((PBASE_REGISTER)SL_SF_DATA,FPP_FM); + PortIOGet((PBASE_REGISTER)SL_SF_DATA,&fpp_cntl); // save fpp_cntl value + } else { + PortIOPut((PBASE_REGISTER)SL_SF_DATA,fpp_cntl); + } + + // epp mode now set + + //----------------------------------------------------------------------- + // Disable special features. + //----------------------------------------------------------------------- + + PortIOPut((PBASE_REGISTER)SL_SFS_DISABLE,0x01); //dummy write to SFS_DISABLE + + + //----------------------------------------------------------------------- + // Restore original CFGR2. + //----------------------------------------------------------------------- + + + if (!SL386EnableConfig()) { + rval = FALSE; + goto done; + } + + // select CFGR2 + PortIOPut((PBASE_REGISTER)SL_CFG_INDEX,SL_CFGR2); + PortIOPut((PBASE_REGISTER)SL_CFG_DATA,cfgr2); + + SL386DisableConfig(); + + // Based on bits 4,5 in the FPP_CNTL register, determine the + // parallel port I/O base port. + // We won't do this now, it is not consistent with modularity of + // the code. + + rval = TRUE; + +done: + RESTORE_INTERRUPT_FLAG(); + return rval; +} + + +//----------------------------------------------------------------------- +// +// SL386EnableConfig +// +// Enables the 386SL configuration space. +// +// Note: Caller should disable interrupts before calling this +// routine. +// +// Returns: TRUE if 386SL successfully enabled. +// +//----------------------------------------------------------------------- + +BOOLEAN SL386EnableConfig(VOID ) +{ + UCHAR tmpb; + USHORT tmpw; + BOOLEAN rval; + + // Unlock CPUPWRMODE register. + // + // byte write 0h to port 23h + // byte write 80h to port 22h + // word write 0080h to port 22h + + PortIOPut((PBASE_REGISTER)(SL_CPUPWRMODE+1),0x00); + PortIOPut((PBASE_REGISTER)SL_CPUPWRMODE,0x80); + PortIOPutWord((PBASE_REGISTER)SL_CPUPWRMODE,0x80); + + // Attempt to read the 386SL signature register (30EH, OMCU). + // Value should be 43xxh. + + PortIOPutWord((PBASE_REGISTER)SL_CPUPWRMODE,PM_UID_CMCU+PM_UE); + PortIOGetWord((PBASE_REGISTER)0x30e,&tmpw); + if ((tmpw & 0xff00) != 0x43) { + rval = FALSE; + goto done; + } + + PortIOGetWord((PBASE_REGISTER)SL_CPUPWRMODE,&tmpw); + tmpw = tmpw & (0xffff ^ (PM_UID + PM_UE)); + PortIOPutWord((PBASE_REGISTER)SL_CPUPWRMODE,tmpw); + + // Lock CPUPWRMODE register. + + PortIOGetWord((PBASE_REGISTER)SL_CPUPWRMODE,&tmpw); + tmpw = tmpw | PM_CFG_LOCK; + PortIOPutWord((PBASE_REGISTER)SL_CPUPWRMODE,tmpw); + + // Enable I/O configuration space. + + PortIOGet((PBASE_REGISTER)SL_CNFG_ENA1,&tmpb); + PortIOGet((PBASE_REGISTER)SL_CNFG_ENA2,&tmpb); + PortIOGet((PBASE_REGISTER)SL_CNFG_ENA3,&tmpb); + PortIOGet((PBASE_REGISTER)SL_CNFG_ENA4,&tmpb); + + // return success if lock status is 0 + rval = !PortIOTestWord((PBASE_REGISTER)SL_CPUPWRMODE,PM_LS); + +done: + return rval; +} + + +//----------------------------------------------------------------------- +// +// SL386DisableConfig +// +// Disables 386SL configuration space. +// +//----------------------------------------------------------------------- + +VOID SL386DisableConfig(VOID ) +{ + PortIOPut((PBASE_REGISTER)SL_CFG_INDEX, SL_IDXLCK); + PortIOPut((PBASE_REGISTER)SL_CFG_DATA, SL_IDXLCK_VAL); +} + diff --git a/private/ntos/miniport/trantor/source/t128.c b/private/ntos/miniport/trantor/source/t128.c new file mode 100644 index 000000000..c9f57c15f --- /dev/null +++ b/private/ntos/miniport/trantor/source/t128.c @@ -0,0 +1,483 @@ +//--------------------------------------------------------------------- +// +// 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;iBaseIoAddress, 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; +} diff --git a/private/ntos/miniport/trantor/source/t338.c b/private/ntos/miniport/trantor/source/t338.c new file mode 100644 index 000000000..e36bf3c12 --- /dev/null +++ b/private/ntos/miniport/trantor/source/t338.c @@ -0,0 +1,763 @@ +//--------------------------------------------------------------------- +// +// T338.C +// +// Trantor T338 Logic Module. Contains functions to access the T338 +// adapter. +// +// Revisions: +// 02-01-93 KJB First. +// 02-23-93 KJB Reorganized, supports dataunderrun with long delay +// for under run on large xfers. Can we fix this? +// 03-11-93 JAP Changed retcode equates to reflect new names. +// 03-11-93 KJB Changed to use N5380Enable/DisableDmaRead/Write +// routines. +// 03-12-93 KJB Now supports polling thru CardInterrupt and +// StartCommandInterrupt/FinishCommandInterrupt. +// 03-19-93 JAP Implemented condition build FAR and NEAR pointers +// 03-22-93 KJB Added support for scatter gather: T338DoIo. +// 03-24-93 KJB Fixed SetScsiMode so it does not reset the n5380! +// 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-14-93 KJB Removed P3CDoIo, it did not work for scatter gather. +// 05-16-93 KJB Fixed parameter bugs introduced while doing the +// PWORKSPACE changes. +// 05-17-93 KJB Fixed compiler warnings. +// +//--------------------------------------------------------------------- + +#include CARDTXXX_H + +// Local Functions + +VOID T338PutControl(PADAPTER_INFO g,UCHAR mode, UCHAR reg); +VOID T338SetPrinterMode(PADAPTER_INFO g, UCHAR data, UCHAR control); +VOID T338SetScsiMode(PADAPTER_INFO g, PUCHAR data, PUCHAR control); + +// +// T338PutControl +// +// Puts a control byte to the T338 style adapter. This sets the mode +// to IOR or IOW and the address byte of the N5380 register. +// +VOID T338PutControl(PADAPTER_INFO g,UCHAR mode, UCHAR reg) +{ + UCHAR tmp; + + // the following bits are active low: IOW, IOR, MR + + tmp = reg | (mode ^ (T338_MR | T338_IOW | T338_IOR)); + + // put the control byte on the data lines + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,tmp); + + // assert slc to indicate byte is there + + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,P_SLC); + + // clear slc + + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,0); +} + +// +// T338SetPrinterMode +// +// This routine sets the T338 to printer pass through mode. This is the +// default mode and should be set after the brief use of scsi mode. +// +VOID T338SetPrinterMode(PADAPTER_INFO g, UCHAR data, UCHAR control) +{ + UCHAR tmp; + + // do we have to disable interrupts? + + // negate all control signals... + + T338PutControl(g,0,0); + + // restore data register + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA,data); + + // leave p_init negated (1) + + tmp = control | P_INIT; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// T338SetScsiMode +// +// This routine sets the T338 into scsi mode. Now the parallel port can +// be used to send commands the the n5380. This mode should be set only +// briefly during when the scsi command is being executed. +// +VOID T338SetScsiMode(PADAPTER_INFO g, PUCHAR data, PUCHAR control) +{ + UCHAR tmp; + + // save parallel data + + ParallelPortGet(g->BaseIoAddress,PARALLEL_DATA,data); + + // zero data register + // note: the signals IOW,IOR,MR are active low, so assert them.. + + ParallelPortPut(g->BaseIoAddress,PARALLEL_DATA, + T338_MR | T338_IOW | T338_IOR); + + // save parallel control + + ParallelPortGet(g->BaseIoAddress,PARALLEL_CONTROL,control); + *control = *control & (P_BUFEN ^ 0xff); + + // clear p_init and set p_slc + + tmp = (*control & (P_INIT ^ 0xff) ) | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // clear p_init and set p_slc + + tmp = (*control & (P_INIT ^ 0xff) ) | P_SLC; + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); + + // clear slc, leave p_init asserted (0) + + tmp = tmp & (P_SLC ^ 0xff); + ParallelPortPut(g->BaseIoAddress,PARALLEL_CONTROL,tmp); +} + +// +// T338CheckAdapter +// +// This routine is used to sense the presense of the T338 adapter out +// on the Parallel port. It will only detect the adapter if a device +// is providing termination power. +// +BOOLEAN T338CheckAdapter(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + BOOLEAN rval; + + // set scsi mode + + T338SetScsiMode(g,&data,&control); + + // reset the 5380 + + T338PutControl(g,T338_MR,0); + T338PutControl(g,0,0); + + // check to see if a 5380 is there + + rval = N5380CheckAdapter(g); + + // set parallel port for use by printer + + T338SetPrinterMode(g,data,control); + + return rval; +} + +// +// T338DoCommand +// +// Called by the main loop to start a scsi command. This functions is the +// main entry point for all cards. It returns an SRB status code as defined +// in ..\..\inc\srb.h. A status code of RET_STATUS_PENDING means that the +// request has been sent to the controller and an interrupt is needed to +// finish the request. When this interrupt occurs CardFinishCommandInterrupt +// will be called. +// +USHORT T338DoCommand(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + T338SetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiDoCommand(t); + + // put the parallel adapter back to parallel mode + + T338SetPrinterMode(g, data, control); + + return rval; +} + +// +// T338StartCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the T338 does not support interrupts on its own. +// +// +USHORT T338StartCommandInterrupt(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the parallel adapter into scsi mode + + T338SetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiStartCommandInterrupt(t); + + // put the parallel adapter back to parallel mode + + T338SetPrinterMode(g, data, control); + + return rval; +} + +// +// T338FinishCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the T338 does not support interrupts on its own. +// +// +USHORT T338FinishCommandInterrupt(PTSRB t) +{ + USHORT rval; + UCHAR data; + UCHAR control; + PADAPTER_INFO g = t->pWorkspace; + + // put the T338 into ScsiMode + + T338SetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + rval = ScsiFinishCommandInterrupt(t); + + // put the parallel adapter back to parallel mode + + T338SetPrinterMode(g, data, control); + + return rval; +} + +// +// T338StartCommandInterrupt +// +// This routines allow the driver to be polled by checking its +// CardInterrupt by for example using the timer interrupt, since +// the T338 does not support interrupts on its own. +// +BOOLEAN T338Interrupt(PADAPTER_INFO g) +{ + BOOLEAN rval; + UCHAR data; + UCHAR control; + + // put the parallel adapter into scsi mode + + T338SetScsiMode(g, &data, &control); + + rval = N5380Interrupt(g); + + // put the parallel adapter back to parallel mode + + T338SetPrinterMode(g, data, control); + + return rval; +} + +// +// +// T338ResetBus +// +// Resets the SCSI Bus +// +VOID T338ResetBus(PADAPTER_INFO g) +{ + UCHAR data; + UCHAR control; + + // put the parallel adapter into scsi mode + + T338SetScsiMode(g, &data, &control); + + // execute the complete command now, without interrupts + + N5380ResetBus(g); + + // put the parallel adapter back to parallel mode + + T338SetPrinterMode(g, data, control); +} + +// +// T338WriteBytesFast +// +// 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 T338WriteBytesFast (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + + // use slow mode for odd xfers (inquiry type commands) & audio + + if (len % 512) { + return ScsiWriteBytesSlow (g, pbytes, len, + pActualLen, phase); + } + + // start dma mode + + N5380EnableDmaWrite (g); + + // put the T338 into write dma mode + + T338PutControl (g,T338_IOW,0); + + { + ULONG xfer_count = len; + PBASE_REGISTER baseIoAddress = g->BaseIoAddress; + + _asm { + push esi + push ds +#ifdef MODE_32BIT + mov edx,baseIoAddress + mov esi,pbytes + mov ecx,len +#else + mov dx, word ptr baseIoAddress + mov si, word ptr pbytes + mov cx, word ptr len + mov ds, word ptr pbytes+2 +#endif // MODE_32BIT + + add dx,2 // dx points to control reg + + get_bytes: + dec dx // dx points to status register + in al,dx + test al,P_BUSY + jnz big_wait + + ready: + dec dx // dx points to parallel data reg + mov al,[esi] + out dx,al + + // assert DACK + + add dx,2 // dx points to control reg + mov al, P_AFX + out dx,al + + // deassert DACK + + mov al,0 + out dx,al + + inc esi + dec ecx + jnz get_bytes + } + goto done_asm; + _asm { +big_wait: + in al,dx + test al,P_BUSY + jz ready + + in al,dx + test al,P_BUSY + jz ready + + in al,dx + test al,P_BUSY + jz ready + + in al,dx + test al,P_BUSY + jz ready + + // wait for a while before going to a bigger timeout + push ecx + push ebx + mov ebx,TIMEOUT_READWRITE_LOOP + loop0: + mov ecx,0x10000 + loop1: + in al,dx + test al,P_BUSY + jz ready1 + in al,dx + test al,P_BUSY + jz ready1 + + dec ecx + jnz loop1 + dec ebx + jnz loop0 + pop ebx + pop ecx + jmp short error + ready1: + pop ebx + pop ecx + jmp short ready + error: + mov rval,RET_STATUS_TIMEOUT + done_asm: + pop ds + pop esi +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + } + + // compute actual xfer len + + *pActualLen = len - xfer_count; + } + + // clear the dma bit of 5380 + + N5380DisableDmaWrite (g); + + // if data underrun, return the under/over run error message + + if (rval) { + UCHAR tmp; + + // phase mismatch means data under/over run + + N5380GetPhase (g,&tmp); + + if (tmp == PHASE_STATUS) { + rval = RET_STATUS_DATA_OVERRUN; + } + } + + return rval; +} + +// +// T338ReadBytesFast +// +// 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. +// +#pragma optimize("",off) +USHORT T338ReadBytesFast (PADAPTER_INFO g, PUCHAR pbytes, + ULONG len, PULONG pActualLen, UCHAR phase) +{ + USHORT rval = 0; + + // use slow mode for small xfers (inquiry type commands) and audio + + if (len % 512) { + return ScsiReadBytesSlow (g, pbytes, len, + pActualLen, phase); + } + + // start dma read + + N5380EnableDmaRead (g); + + // put the t338 into read mode + + T338PutControl (g,T338_IOR,0); + + // to be fast, for 386 machines, this must be coded in assembly + // for inline assembly, we don't have to save eax-edx registers + { + ULONG xfer_count = len; + PBASE_REGISTER baseIoAddress = g->BaseIoAddress; + + _asm { + push esi + push ds +#ifdef MODE_32BIT + mov edx, baseIoAddress + mov esi,pbytes + mov ecx,len +#else + mov dx, word ptr baseIoAddress + mov si, word ptr pbytes + mov cx, word ptr len + mov ds, word ptr pbytes+2 +#endif // MODE_32BIT + inc dx // dx points to status register + + get_bytes: + in al,dx + test al,P_BUSY + jnz big_wait + + ready: + + // assert DACK, the P_AFX bit + + inc dx // dx points to control register + mov al,P_AFX + out dx,al + + // select high nibble + + sub dx,2 // dx points to data register + mov al,0x80 + out dx,al + + // get high nibble + + inc dx // dx points to status register + in al,dx + mov ah,al + + // select lower nibble + + dec dx // dx points to data register + xor al,al + out dx,al + + // calculate high nibble + + shl ah,1 + and ah,0f0h + + // get lower nibble + + inc dx // dx points to status register + in al,dx + mov bh,al + + // deassert DACK, clear P_AFX + + inc dx // dx points to control register + xor al,al + out dx,al + + dec dx // dx points to status register + + // compute low nibble and the whole byte + + shr bh,1 + shr bh,1 + shr bh,1 + and bh,0fh + or ah,bh + mov al,ah + + + // store data and loop + + mov [esi],al + inc esi + dec ecx + jnz get_bytes + } + goto done_asm; + _asm { +big_wait: + in al,dx + test al,P_BUSY + jz ready + + in al,dx + test al,P_BUSY + jz ready + + in al,dx + test al,P_BUSY + jz ready + + in al,dx + test al,P_BUSY + jz ready + + // wait for a while before going to a bigger timeout + push ecx + push ebx + mov ebx,TIMEOUT_READWRITE_LOOP + loop0: + mov ecx,0x10000 + loop1: + in al,dx + test al,P_BUSY + jz ready1 + in al,dx + test al,P_BUSY + jz ready1 + + dec ecx + jnz loop1 + dec ebx + jnz loop0 + pop ebx + pop ecx + jmp short error + ready1: + pop ebx + pop ecx + } + goto ready; + _asm { + error: + mov rval,RET_STATUS_TIMEOUT + done_asm: + pop ds + pop esi +#ifdef MODE_32BIT + mov xfer_count,ecx +#else + mov word ptr xfer_count,ecx +#endif + } + + // compute actual xfer len + + *pActualLen = len - xfer_count; + } + + // zero control register, disable read dma mode + ParallelPortPut (g->BaseIoAddress,PARALLEL_CONTROL,0); + + // clear the dma read mode + N5380DisableDmaRead (g); + + // if data underrun, return the under/over run error message + + if (rval) { + UCHAR tmp; + + // phase mismatch means data under/over run + + N5380GetPhase (g,&tmp); + + if (tmp == PHASE_STATUS) { + rval = RET_STATUS_DATA_OVERRUN; + } + } + + return rval; +} + +#pragma optimize("",on) + +// +// N5380PortPut +// +// This routine is used by the N5380.C module to write byte to a 5380 +// controller. This allows the module to be card independent. Other +// modules that assume a N5380 may also use this function. +// +VOID N5380PortPut (PADAPTER_INFO g,UCHAR reg,UCHAR byte) +{ + + // set T338 logic into data write mode + + T338PutControl (g, T338_IOW, reg); + + // write the byte + + ParallelPortPut (g->BaseIoAddress, PARALLEL_DATA, byte); + + // toggle the strobe line + + ParallelPortPut (g->BaseIoAddress, PARALLEL_CONTROL, P_STB); + ParallelPortPut (g->BaseIoAddress, PARALLEL_CONTROL, 0); + + // clear data write mode + + T338PutControl (g, 0, 0); +} + + +// +// N5380PortGet +// +// This routine is used by the N5380.C module to get a byte from a 5380 +// controller. This allows the module to be card independent. Other +// modules that assume a N5380 may also use this function. +// + +VOID N5380PortGet (PADAPTER_INFO g, UCHAR reg, PUCHAR byte) +{ + UCHAR tmp,tmp1; + + // set T338 logic to read mode + + T338PutControl (g, T338_IOR, reg); + + // select high nibble + + ParallelPortPut (g->BaseIoAddress, PARALLEL_DATA, 0x80); + + // assert stb + + ParallelPortPut (g->BaseIoAddress, PARALLEL_CONTROL, P_STB); + + // read high nibble + + ParallelPortGet (g->BaseIoAddress, PARALLEL_STATUS, &tmp); + + // compute high nibble + + tmp = (tmp << 1) & 0xf0; + + // select low nibble + + ParallelPortPut (g->BaseIoAddress, PARALLEL_DATA, 0x00); + + // read low nibble + + ParallelPortGet (g->BaseIoAddress, PARALLEL_STATUS, &tmp1); + + // compute low nibble + + tmp1 = (tmp1 >> 3) & 0x0f; + + // compute and return byte + + *byte = tmp1 | tmp; + + // clear slc + + ParallelPortPut (g->BaseIoAddress, PARALLEL_CONTROL, 0); + + // clear data read mode + + T338PutControl (g, 0, 0); +} + + -- cgit v1.2.3