summaryrefslogtreecommitdiffstats
path: root/private/ntos/miniport/trantor/source
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/miniport/trantor/source
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/miniport/trantor/source')
-rw-r--r--private/ntos/miniport/trantor/source/cardt128.c377
-rw-r--r--private/ntos/miniport/trantor/source/cardt13b.c299
-rw-r--r--private/ntos/miniport/trantor/source/cardt160.c273
-rw-r--r--private/ntos/miniport/trantor/source/cardt338.c246
-rw-r--r--private/ntos/miniport/trantor/source/cardt348.c220
-rw-r--r--private/ntos/miniport/trantor/source/cardtmv1.c266
-rw-r--r--private/ntos/miniport/trantor/source/cardutil.c110
-rw-r--r--private/ntos/miniport/trantor/source/ep3c.c1418
-rw-r--r--private/ntos/miniport/trantor/source/ep3c2.asm526
-rw-r--r--private/ntos/miniport/trantor/source/findpas.c303
-rw-r--r--private/ntos/miniport/trantor/source/mv101.c617
-rw-r--r--private/ntos/miniport/trantor/source/n5380.c970
-rw-r--r--private/ntos/miniport/trantor/source/n53c400.c525
-rw-r--r--private/ntos/miniport/trantor/source/p3c.c1069
-rw-r--r--private/ntos/miniport/trantor/source/parallel.c86
-rw-r--r--private/ntos/miniport/trantor/source/pc9010.c851
-rw-r--r--private/ntos/miniport/trantor/source/port.c62
-rw-r--r--private/ntos/miniport/trantor/source/portio.c87
-rw-r--r--private/ntos/miniport/trantor/source/portmem.c67
-rw-r--r--private/ntos/miniport/trantor/source/scsifnc.c586
-rw-r--r--private/ntos/miniport/trantor/source/scsiport.c181
-rw-r--r--private/ntos/miniport/trantor/source/sl386.c285
-rw-r--r--private/ntos/miniport/trantor/source/t128.c483
-rw-r--r--private/ntos/miniport/trantor/source/t338.c763
24 files changed, 10670 insertions, 0 deletions
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;i<TIMEOUT_QUICK;i++) {
+
+ // wait for card to be ready
+
+ if (MV101PortTest(g, MV101_DRQ_PORT, g->DRQMask)) {
+ 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;i<len;i++) {
+
+ // wait for request to be asserted
+
+ if (rval = N5380GetPhase (g, &tmp)) {
+ DebugPrint((DEBUG_LEVEL,"ScsiWriteBytesSlow-0 Error: %x\n",rval));
+ goto done;
+ }
+
+ // see if phase match
+
+ if (phase != tmp) {
+ rval = RET_STATUS_DATA_OVERRUN;
+ goto done;
+ }
+
+ if (rval = N5380PutByte (g, TIMEOUT_REQUEST, pbytes[i])) {
+ DebugPrint((DEBUG_LEVEL,"ScsiWriteBytesSlow-1 Error: %x\n",rval));
+ goto done;
+ }
+ }
+
+done:
+ *pActualLen = i;
+ return rval;
+}
+
+
+//
+// ScsiReadBytesSlow
+//
+// This functions reads 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 ScsiReadBytesSlow (PADAPTER_INFO g, PUCHAR pbytes,
+ ULONG len, PULONG pActualLen, UCHAR phase)
+{
+ ULONG i;
+ USHORT rval = 0;
+ UCHAR tmp;
+
+ for (i = 0; i < len; i++) {
+
+ // wait for request to be asserted
+
+ if (rval = N5380GetPhase (g, &tmp)) {
+ DebugPrint((DEBUG_LEVEL,"ScsiReadBytesSlow-0 Error: %x\n",rval));
+ goto done;
+ }
+
+ // see if phase match
+
+ if (phase != tmp) {
+ rval = RET_STATUS_DATA_OVERRUN;
+ goto done;
+ }
+
+ if (rval = N5380GetByte (g, TIMEOUT_REQUEST, &pbytes[i])) {
+ DebugPrint((DEBUG_LEVEL,"ScsiReadBytesSlow-1 Error: %x\n",rval));
+ goto done;
+ }
+ }
+
+done:
+ *pActualLen = i;
+ return rval;
+}
+
+
+//
+// ScsiDoIo
+//
+// This function does the I/O during a data phase.
+//
+
+USHORT ScsiDoIo (PTSRB t)
+{
+ USHORT rval;
+ UCHAR tmp;
+ UCHAR phase;
+ PADAPTER_INFO g = t->pWorkspace;
+
+ // 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<time;i++);
+ }
+}
diff --git a/private/ntos/miniport/trantor/source/sl386.c b/private/ntos/miniport/trantor/source/sl386.c
new file mode 100644
index 000000000..249cd634e
--- /dev/null
+++ b/private/ntos/miniport/trantor/source/sl386.c
@@ -0,0 +1,285 @@
+//-----------------------------------------------------------------------
+//
+// SL386.C
+//
+// Trantor SL386 access file.
+//
+// Revisions:
+// 04-07-93 KJB First.
+//
+//-----------------------------------------------------------------------
+
+#include CARDTXXX_H
+
+//
+// Local Routines
+//
+
+BOOLEAN SL386EnableConfig(VOID );
+VOID SL386DisableConfig(VOID );
+
+//
+// Local Definitions
+//
+
+#define CLEAR_INTERRUPT_FLAG() \
+ _asm { \
+ pushf \
+ } \
+ _asm {cli}
+
+#define RESTORE_INTERRUPT_FLAG() \
+ _asm { \
+ popf \
+ }
+
+//-----------------------------------------------------------------------
+//
+// 80386SL EPP OVERVIEW
+//
+// The "fast" (EPP) parallel port mode of the 80386SL processor
+// is enabled through the following steps:
+//
+// Enable 386SL Special Features:
+//
+// Disable interrupts.
+// Unlock CPUPWRMODE register.
+// Set CPUCNFG Lock bit in CPUPWRMODE register.
+// Unlock 386SL configuration register space.
+// Write index of CFGR2 to CFGINDEX register.
+// Set SFIO_EN bit in CFGR2 (write to CFGDATA register).
+// Enable special features by dummy write to SFS_ENABLE.
+// Disable 386SL configuration space (write 0fah to
+// CFGINDEX and 01h to CFGDATA).
+// Enable interrupts.
+//
+// Select "fast" mode for parallel port:
+//
+// Disable interrupts.
+// Write index of FPP_CNTL to SFS_INDEX register.
+// Set FAST_MODE and EXT_MODE bits in FPP_CNTL
+// (write to SFS_DATA register).
+// Enable interrupts.
+//
+// Disable 386SL Special Features:
+//
+// Disable special features by dummy write to SFS_DISABLE.
+//
+//
+// Notes:
+//
+// When setting the parallel port to "fast" mode the port address
+// is controlled by the FPP_CNTL register. It is probably a good
+// idea to read the currently selected port address from the
+// PPCONTROL register and using that address the first time the
+// parallel port is set to fast mode.
+//
+// When setting the FAST_MODE bit it is not necessary to set the
+// EXT_MODE bit (FPP_CNTL register). EXT_MODE need only be set if
+// software needs to perform non-EPP byte read cycles in addition
+// to normal EPP cycles.
+//
+//-----------------------------------------------------------------------
+
+//-----------------------------------------------------------------------
+//
+// SL386EnableEPP
+//
+// Attempts to enable the "fast" (EPP) parallel port on the
+// 386SL.
+//
+//-----------------------------------------------------------------------
+
+BOOLEAN SL386EnableEPP(VOID )
+{
+ // The following translation table is used to convert PPCONFIG
+ // values (LPTSL1,LPTSL0) to FPP_CNTL values.
+
+ static CONST UCHAR fpp_xlate[] = {
+ FPP_FM + FPP_EM + FPP_CTL_LPT1,
+ FPP_FM + FPP_EM + FPP_CTL_LPT2,
+ FPP_FM + FPP_EM + FPP_CTL_LPT2,
+ FPP_CTL_DIS
+ };
+
+ UCHAR fpp_cntl;
+ UCHAR cfgr2;
+ UCHAR tmpb;
+ BOOLEAN rval;
+
+ CLEAR_INTERRUPT_FLAG();
+
+ //-----------------------------------------------------------------------
+ // Enable 386SL special features.
+ //-----------------------------------------------------------------------
+
+ if (!SL386EnableConfig()) {
+ rval = FALSE;
+ goto done;
+ }
+
+ // select CFGR2
+ PortIOPut((PBASE_REGISTER)SL_CFG_INDEX,SL_CFGR2);
+ PortIOGet((PBASE_REGISTER)SL_CFG_DATA,&tmpb);
+ cfgr2 = tmpb; // save CFGR2 value
+ tmpb |= C2_SFIO + C2_PS2; // set SFIO_EN
+ PortIOPut((PBASE_REGISTER)SL_CFG_DATA,tmpb);
+ PortIOPut((PBASE_REGISTER)SL_SFS_ENABLE,tmpb); // dummy write to SFS_ENABLE
+
+ SL386DisableConfig();
+
+ //-----------------------------------------------------------------------
+ // Read PPCONFIG and translate to FPP_CNTL setting.
+ //-----------------------------------------------------------------------
+
+ PortIOGet((PBASE_REGISTER)SL_PPCONFIG,&tmpb);
+ tmpb &= PPC_SEL;
+ tmpb = tmpb >> 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;i<TIMEOUT_QUICK;i++) {
+
+ // wait for card to be ready
+ if (T128PortTest(g, T128_STATUS, SR_XFR_READY)) {
+ return 0;
+ }
+ }
+
+ // ok, it did not come back quickly, we will yield to other processes
+ for (i=0;i<usec;i++) {
+
+ // wait for card to be ready
+ if (T128PortTest(g, T128_STATUS, SR_XFR_READY)) {
+ return 0;
+ }
+
+ // see if bus free
+ if (!N5380PortTest(g,N5380_CURRENT_STATUS,CS_BSY)) {
+ TrantorLogError (g->BaseIoAddress, RET_STATUS_UNEXPECTED_BUS_FREE, 1);
+ return RET_STATUS_UNEXPECTED_BUS_FREE;
+ }
+
+ // since we have taken some time... check for phase change
+ if (!N5380PortTest(g,N5380_DMA_STATUS,DS_PHASE_MATCH)) {
+ return RET_STATUS_DATA_OVERRUN;
+ }
+
+ // wait for card to be ready
+ if (T128PortTest(g, T128_STATUS, SR_TIMEOUT)) {
+ TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 2);
+ return RET_STATUS_TIMEOUT;
+ }
+
+ ScsiPortStallExecution(1);
+ }
+
+ DebugPrint((DEBUG_LEVEL,"Error - T128WaitXfrReady\n"));
+
+ // return with an error, non-zero indicates timeout
+ TrantorLogError (g->BaseIoAddress, RET_STATUS_TIMEOUT, 3);
+ return RET_STATUS_TIMEOUT;
+}
+
+//
+// T128ResetDmaTimeout
+//
+// Resets the t128's dma timout bit.
+//
+VOID T128ResetDmaTimeout(PADAPTER_INFO g)
+{
+ // is the timeout flagged?
+ if (T128PortTest(g, T128_STATUS, SR_TIMEOUT)) {
+
+ // toggle the t120 timeout bit to clear any timeout
+
+ T128PortSet(g, T128_CONTROL, CR_TIMEOUT);
+ T128PortClear(g, T128_CONTROL, CR_TIMEOUT);
+ }
+}
+
+//
+// T128EnableDmaRead
+//
+// Enables the DMA read operation for the T128.
+//
+VOID T128EnableDmaRead(PADAPTER_INFO g)
+{
+ // toggle the t120 timeout bit to clear any timeout
+ T128ResetDmaTimeout(g);
+
+ // start dma on the 5380
+ N5380EnableDmaRead(g);
+}
+
+//
+// T128EnableDmaWrite
+//
+// Enables the DMA write operation for the T128.
+//
+VOID T128EnableDmaWrite(PADAPTER_INFO g)
+{
+ // toggle the t120 timeout bit to clear any timeout
+ T128ResetDmaTimeout(g);
+
+ // start dma on the 5380
+ N5380EnableDmaWrite(g);
+}
+
+//
+// T128DisableDmaRead
+//
+// Clears the current DMA operation for the T128.
+//
+VOID T128DisableDmaRead(PADAPTER_INFO g)
+{
+ // toggle the t120 timeout bit to clear any timeout
+ T128ResetDmaTimeout(g);
+
+ // disable dma on the 5380
+ N5380DisableDmaRead(g);
+}
+
+//
+// T128DisableDmaWrite
+//
+// Clears the current DMA operation for the T128.
+//
+VOID T128DisableDmaWrite(PADAPTER_INFO g)
+{
+ // toggle the t120 timeout bit to clear any timeout
+ T128ResetDmaTimeout(g);
+
+ // disable dma on the 5380
+ N5380DisableDmaWrite(g);
+}
+
+//
+// T128ReadBytesFast
+//
+// This routine is used by the ScsiFnc routines to write bytes to the scsi
+// bus quickly. The ScsiFnc routines don't know how to do this quickly for
+// a particular card, so they call this. This routine can be mapped to the
+// slower ScsiReadBytesSlow routine for small transferrs or if this routine
+// is not supported.
+//
+USHORT T128ReadBytesFast(PADAPTER_INFO g, PUCHAR pbytes,
+ ULONG len, PULONG pActualLen, UCHAR phase)
+{
+ USHORT rval = 0;
+
+ // for small transfers, use slow method
+ if (len<0x200) {
+ rval = ScsiReadBytesSlow(g, pbytes, len,
+ pActualLen, phase);
+ return rval;
+ }
+
+ // start dma for this card
+ T128EnableDmaRead(g);
+
+ {
+ PVOID t128_data = (PUCHAR)g->BaseIoAddress + T128_DATA;
+ ULONG xfer_count = len;
+
+ // we have a 16 bit VGA problem
+ // must only move from even addresses
+
+ _asm {
+ pushf
+ push eax
+ push ebx
+ push ecx
+ push edx
+ push esi
+ push edi
+ push ds
+ push es
+#ifdef MODE_32BIT
+ mov esi,t128_data
+ mov edi,pbytes
+ mov ecx,len
+#else
+ mov esi, word ptr t128_data
+ mov edi, word ptr pbytes
+ mov ds, word ptr t128_data+2
+ mov es, word ptr pbytes+2
+ mov cx, word ptr len
+#endif // MODE_32BIT
+ cld
+ get_bytes:
+ test [esi-0x1e0],SR_XFR_READY
+ jz big_wait
+ ready:
+ movsb
+ dec esi
+ dec ecx
+ jnz get_bytes
+ }
+
+ goto done_asm;
+big_wait:
+ _asm {
+ test [esi-0x1e0],SR_XFR_READY
+ jnz ready
+ test [esi-0x1e0],SR_XFR_READY
+ jnz ready
+ test [esi-0x1e0],SR_XFR_READY
+ jnz ready
+ test [esi-0x1e0],SR_XFR_READY
+ jnz ready
+
+ mov eax,TIMEOUT_READWRITE_LOOP
+ loop1:
+ mov ebx,0x10000
+ loop2:
+ test [esi-0x1e0],SR_XFR_READY
+ jnz ready
+ test [esi-(8-N5380_CURRENT_STATUS)*0x20],CS_REQ
+ jz no_req
+ test [esi-(8-N5380_DMA_STATUS)*0x20],DS_PHASE_MATCH
+ jz phase_error
+ no_req:
+
+ dec ebx
+ jnz loop2
+ dec eax
+ jnz loop1
+ mov rval,RET_STATUS_TIMEOUT
+ jmp short done_asm
+ phase_error:
+ mov rval,RET_STATUS_DATA_OVERRUN
+ done_asm:
+ pop es
+ pop ds
+#ifdef MODE_32BIT
+ mov xfer_count,ecx
+#else
+ mov word ptr xfer_count,ecx
+#endif
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ popf
+
+ }
+
+ // compute actual xfer len
+ *pActualLen = len - xfer_count;
+ }
+
+ // disable dma
+
+ T128DisableDmaRead(g);
+
+ // some error checking...
+
+ if (rval == RET_STATUS_TIMEOUT) {
+ TrantorLogError (g->BaseIoAddress, rval, 4);
+ }
+
+ return rval;
+}
+
+//
+// T128WriteBytesFast
+//
+// This routine is used by the ScsiFnc routines to write bytes to the scsi
+// bus quickly. The ScsiFnc routines don't know how to do this quickly for
+// a particular card, so they call this. This routine can be mapped to the
+// slower ScsiWriteBytesSlow routine for small transferrs or if this routine
+// is not supported.
+//
+USHORT T128WriteBytesFast(PADAPTER_INFO g, PUCHAR pbytes,
+ ULONG len, PULONG pActualLen, UCHAR phase)
+{
+ USHORT rval = 0;
+
+ // for small transfers, use slow method
+
+ if (len<0x200) {
+ rval = ScsiWriteBytesSlow(g, pbytes, len,
+ pActualLen, phase);
+ return rval;
+ }
+
+ // start dma for this card
+
+ T128EnableDmaWrite(g);
+
+ {
+ PVOID t128_data = (PUCHAR)g->BaseIoAddress + T128_DATA;
+ ULONG xfer_count = len;
+
+ // we have a 16 bit VGA problem
+ // must only move from even addresses
+
+ _asm {
+ pushf
+ push eax
+ push ebx
+ push ecx
+ push edx
+ push esi
+ push edi
+ push ds
+ push es
+#ifdef MODE_32BIT
+ mov edi,t128_data
+ mov esi,pbytes
+ mov ecx,len
+#define segment_override ds
+#else
+ mov edi, word ptr t128_data
+ mov esi, word ptr pbytes
+ mov es, word ptr t128_data+2
+ mov ds, word ptr pbytes+2
+ mov cx, word ptr len
+#define segment_override es
+#endif // MODE_32BIT
+ cld
+ get_bytes:
+ test segment_override:[edi-0x1e0],SR_XFR_READY
+ jz big_wait
+ ready:
+ movsb
+ dec edi
+ dec ecx
+ jnz get_bytes
+ }
+ goto done_asm;
+ _asm {
+ big_wait:
+ test segment_override:[edi-0x1e0],SR_XFR_READY
+ jnz ready
+ test segment_override:[edi-0x1e0],SR_XFR_READY
+ jnz ready
+ test segment_override:[edi-0x1e0],SR_XFR_READY
+ jnz ready
+ test segment_override:[edi-0x1e0],SR_XFR_READY
+ jnz ready
+
+ mov eax,TIMEOUT_READWRITE_LOOP
+ loop1:
+ mov ebx,0x10000
+ loop2:
+ test segment_override:[edi-0x1e0],SR_XFR_READY
+ jnz ready
+ test segment_override:[edi-(8-N5380_CURRENT_STATUS)*0x20],CS_REQ
+ jz no_req
+ test segment_override:[edi-(8-N5380_DMA_STATUS)*0x20],DS_PHASE_MATCH
+ jz phase_error
+ no_req:
+
+ dec ebx
+ jnz loop2
+ dec eax
+ jnz loop1
+ mov rval,RET_STATUS_TIMEOUT
+ jmp done_asm
+ phase_error:
+ mov rval,RET_STATUS_DATA_OVERRUN
+ done_asm:
+ pop es
+ pop ds
+#ifdef MODE_32BIT
+ mov xfer_count,ecx
+#else
+ mov word ptr xfer_count,ecx
+#endif
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ popf
+ }
+
+ // compute actual xfer len
+ *pActualLen = len - xfer_count;
+ }
+
+ // disable dma
+
+ T128DisableDmaWrite(g);
+
+ // some error checking...
+
+ if (rval == RET_STATUS_TIMEOUT) {
+ TrantorLogError (g->BaseIoAddress, rval, 5);
+ }
+
+ return rval;
+}
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);
+}
+
+