summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/netflex
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/ndis/netflex
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/ndis/netflex')
-rw-r--r--private/ntos/ndis/netflex/adapter.h137
-rw-r--r--private/ntos/ndis/netflex/cpqntssd.ver68
-rw-r--r--private/ntos/ndis/netflex/init.c1605
-rw-r--r--private/ntos/ndis/netflex/initd.c230
-rw-r--r--private/ntos/ndis/netflex/int.c977
-rw-r--r--private/ntos/ndis/netflex/macstrct.h581
-rw-r--r--private/ntos/ndis/netflex/makefile6
-rw-r--r--private/ntos/ndis/netflex/makefile.inc5
-rw-r--r--private/ntos/ndis/netflex/netflex.rc40
-rw-r--r--private/ntos/ndis/netflex/netflx.binbin0 -> 110720 bytes
-rw-r--r--private/ntos/ndis/netflex/netflx.prf27
-rw-r--r--private/ntos/ndis/netflex/protos.h450
-rw-r--r--private/ntos/ndis/netflex/receive.c633
-rw-r--r--private/ntos/ndis/netflex/request.c2148
-rw-r--r--private/ntos/ndis/netflex/reset.c1924
-rw-r--r--private/ntos/ndis/netflex/sources84
-rw-r--r--private/ntos/ndis/netflex/support.c1986
-rw-r--r--private/ntos/ndis/netflex/tmsstrct.h606
-rw-r--r--private/ntos/ndis/netflex/transmit.c802
19 files changed, 12309 insertions, 0 deletions
diff --git a/private/ntos/ndis/netflex/adapter.h b/private/ntos/ndis/netflex/adapter.h
new file mode 100644
index 000000000..956082620
--- /dev/null
+++ b/private/ntos/ndis/netflex/adapter.h
@@ -0,0 +1,137 @@
+/***********************************************************************/
+/***********************************************************************/
+/* */
+/* File Name: ADAPTER.H */
+/* */
+/* Program Name: NetFlex NDIS 3.0 Driver */
+/* */
+/* Companion Files: None */
+/* */
+/* Function: This module contains all the adapter specific data */
+/* structure definitions that are specific to the */
+/* CPQTOK board. */
+/* */
+/* (c) Compaq Computer Corporation, 1992,1993 */
+/* */
+/* This file is licensed by Compaq Computer Corporation to Microsoft */
+/* Corporation pursuant to the letter of August 20, 1992 from */
+/* Gary Stimac to Mark Baber. */
+/* */
+/* History: */
+/* */
+/* 02/24/92 Carol Fuss - Reworked from NDIS driver */
+/* 06/14/93 Cat Abueg - Modified for MAPLE */
+/* 08/09/93 Cat Abueg - Modified for BONSAI */
+/* */
+/***********************************************************************/
+/***********************************************************************/
+
+/*
+ * COMPAQ Token Ring Configuration Register definitions -
+ * These equates define the bit settings in the CPQTOK
+ * adapter's configuration registers.
+ */
+#define CFG_INTS 0xe000 /* Interrupt Level 5, 9 10, 11, 15 */
+#define CFG_INTRIG 0x1000 /* Interrupt Level Trigger */
+#define CFG_MEDIA 0x0800 /* Type 3 Media (else type 1) */
+#define CFG_16MBS 0x0400 /* 16Mbs select (else 4Mbs) */
+#define CFG_RSVD1 0x0300 /* Reserved */
+
+#define CFG_RSVD2 0x00f8 /* Reserved */
+#define CFG_ZERO 0x0006 /* Always zero */
+#define CFG_ENABLE 0x0001 /* Adapter Enable */
+
+/*
+ * The following configuration registers are read as long words during
+ * init time - i.e. 0xc84 and 0xc85, and 0x01b and 0x01c
+ */
+//define CFG_REGISTER 0xc84 /* Configuration register */
+#define CFG_REGISTER 0x4 /* Configuration register */
+ /* Actual value = 0xc85 */
+#define CFG_REGRODAN 0x01b /* Cfg reg for 2nd port of Rodan */
+ /* Actual value = 0x01c */
+
+#define CFG_REG2_OFF 0x01c /* ext cfg reg for 2nd port of Rodan */
+ /* Actual value = 0x01c */
+
+#define COMPAQ_ID 0x110e /* Product Register ID */
+#define CPQTOK_ID 0x0060 /* Cpqtok's board ID */
+#define DURANGO_ID 0x0260 /* Durango's board ID */
+#define NETFLEX_ID 0x0061 /* NETFLEX's board ID */
+#define MAPLE_ID 0x0161 /* Manitu's board ID */
+#define BONSAI_ID 0x0062 /* Bonsai board ID */
+#define RODAN_ID 0x0063 /* Rodan board ID */
+#define NETFLEX_REVMASK 0xf0ff /* Board ID revision mask - MAJ */
+#define NETFLEX_MINMASK 0xff00 /* Board ID revision mask - MIN */
+#define PAGE3_MASK 0xc0000000 /* PCI mask - for < TRIC 5 */
+
+#define CFG_DUALPT_ADP1 0x0800 /* Type of connection for adp 1 */
+#define CFG_DUALPT_ADP2 0x0400 /* Type of connection for adp 2 */
+
+#define CFG_FULL_DUPLEX 0x04 /* Mask For Full Duplex */
+#define CFG_FULL_DUPLEX_HEAD2 0x08 /* Mask For Full Duplex Bonsai H2 */
+
+#define DUALHEAD_CFG_PORT_OFFSET 0x20 /* base port range for dual head z020 - z02e */
+#define CFG_PORT_OFFSET 0xc80 /* adapter configuration ports */
+#define EXTCFG_PORT_OFFSET 0xc63 /* extra adapter configuration ports */
+
+#define NUM_BASE_PORTS 0x20 /* z0000 - z001f */
+#define NUM_CFG_PORTS 0x8 /* z0c80 - z0c87 */
+#define NUM_EXTCFG_PORTS 0x5 /* z0c63 - z0c67 */
+
+#define NUM_DUALHEAD_CFG_PORTS 0x30 /* z000 - z02F */
+
+#define COLL_DETECT_ENABLED 0x8 /* bit 7 = 1 if collision enabled */
+
+#define LOOP_BACK_ENABLE_OFF 0x2 /* added to 0zc63 = 0Zc65 */
+#define LOOP_BACK_STATUS_OFF 0x1 /* added to 0zc63 = 0Zc64 */
+
+#define LOOP_BACK_ENABLE_HEAD1_OFF 0x3 /* added to 0zc63 = 0Zc66 */
+#define LOOP_BACK_STATUS_HEAD1_OFF 0x3 /* added to 0zc63 = 0Zc66 */
+#define LOOP_BACK_ENABLE_HEAD2_OFF 0x4 /* added to 0zc63 = 0Zc67 */
+#define LOOP_BACK_STATUS_HEAD2_OFF 0x4 /* added to 0zc63 = 0Zc67 */
+
+
+#define SWAPL(x) (((ULONG)(x) << 24) | \
+ (((ULONG)(x) >> 24) & 0x000000ff) | \
+ (((ULONG)(x) << 8) & 0x00ff0000) | \
+ (((ULONG)(x) >> 8) & 0x0000ff00))
+
+#define SWAPS(x) (((USHORT)(x) << 8) | (((USHORT)(x) >> 8) & 0x00ff))
+
+#define CTRL_ADDR(x) ((x) | 0x80000000)
+
+#define MAKE_ODD(x) (x |= 0x1000000)
+#define MAKE_EVEN(x) (x &= ~0x1000000)
+
+#define TOKENMTU 4096 /* Token-Ring maximum packet size */
+#define MIN_TPKT 14 /* Minimunm packet size */
+
+#define CMD_ASYNCH 0
+#define CMD_SYNCH 1
+
+#define HARD_RESET 0
+#define SOFT_RESET 1
+
+#define DBM_NOT_SET 0
+#define DBM_RECV_ONLY 1
+#define DBM_XMIT_ONLY 2
+#define DBM_RECV_XMIT 3
+
+#define NETFLEX_INIT_ERROR_CODE ((ULONG) 0x1111)
+#define NETFLEX_RESET_FAILURE_ERROR_CODE ((ULONG) 0x2222)
+#define NETFLEX_ADAPTERCHECK_ERROR_CODE ((ULONG) 0x3333)
+#define NETFLEX_RINGSTATUS_ERROR_CODE ((ULONG) 0x4444)
+
+//
+// Structure Name: Download Structure Definition
+//
+// Description: The Download Structure Definition defines the structure
+// of the code/data to download to the TMS380 chipset.
+//
+typedef struct dl_struct
+ {
+ USHORT dl_chap; /* Section hi address */
+ USHORT dl_addr; /* Section lo address */
+ USHORT dl_bytes; /* Section length in bytes */
+ } DL_STRUCT, *PDL_STRUCT;
diff --git a/private/ntos/ndis/netflex/cpqntssd.ver b/private/ntos/ndis/netflex/cpqntssd.ver
new file mode 100644
index 000000000..efbd41516
--- /dev/null
+++ b/private/ntos/ndis/netflex/cpqntssd.ver
@@ -0,0 +1,68 @@
+/*++
+
+Copyright (c) 1993-1994 Compaq Computer Corporation
+
+
+Module Name:
+
+ CPQNTSSD.VER
+
+
+Abstract:
+
+ This file contains common version information for all device drivers
+ that are modified and released by Compaq. This file should be included
+ in the resource file of all device drivers modified by Compaq and released
+ on the Windows NT SSD or through a SoftPaq. It should be included after
+ the file NTVERP.H but before COMMON.VER.
+
+
+Author:
+
+ Michael E. McGowen
+
+
+Environment:
+
+ Resource Compiler Only
+
+
+Notes:
+
+ This file should only be modified after the initial release by the official
+ NT SSD builder and should be modified with each build.
+
+
+Revision History:
+
+ 1.00 MEM 01/11/94 Initial release.
+ 1.01 AMB 01/12/94 Modified for 1.03.01.001 release
+ 1.02 AMB 01/12/94 Modified for 1.03.01.004 release (P940217)
+ 1.03 AMB 02/22/94 Modified for 1.03.01.005 release (P940222)
+ 1.04 AMB 03/14/94 Modified for 1.04.01.001 release (P940315)
+ 1.05 MDG 03/30/94 Modified for 1.04.01.002 release <P940330>
+ 1.06 MDG 04/07/94 Modified for 1.04.01.003 release <P940407>
+ 1.07 MDG 04/12/94 Modified for 1.04.01.004 release <P940412>
+ 1.08 MDG 04/14/94 Modified for 1.04.01.004 release <P940414>
+
+Datona History:
+
+ 1.10 Beta MDG 04/20/94 Modified for 1.10.01.001 Datona Beta <P940420>
+ 1.10 Beta MDG 04/21/94 Modified for 1.10.01.002 Datona Beta <P940422>
+
+--*/
+
+
+#undef VER_COMPANYNAME_STR
+#define VER_COMPANYNAME_STR "Compaq Computer Corp."
+
+#undef VER_LEGALCOPYRIGHT_YEARS
+#define VER_LEGALCOPYRIGHT_YEARS "1993-1994"
+
+#undef VER_LEGALCOPYRIGHT_STR
+#define VER_LEGALCOPYRIGHT_STR VER_COMPANYNAME_STR " " VER_LEGALCOPYRIGHT_YEARS
+
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "Compaq Support Software for Microsoft\256 Windows NT(TM)"
+
+ \ No newline at end of file
diff --git a/private/ntos/ndis/netflex/init.c b/private/ntos/ndis/netflex/init.c
new file mode 100644
index 000000000..c5826a1e1
--- /dev/null
+++ b/private/ntos/ndis/netflex/init.c
@@ -0,0 +1,1605 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: INIT.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+//-----------------
+// Variables
+//-----------------
+
+MAC macgbls = {0};
+USHORT gbl_addingdualport = 0;
+USHORT gbl_portnumbertoadd = 0;
+
+USHORT RxIntRatio = 1;
+#ifdef XMIT_INTS
+USHORT TxIntRatio = 1;
+#endif
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: DriverEntry
+//
+// Description: This routine is the initialization entry
+// point into the driver. In this routine,
+// the driver registers itself with the wrapper
+// and initializes the global variables for the
+// driver.
+//
+// Input: DriverObject Pointer to the driver object
+// assigned to the MAC driver.
+//
+// Output: Returns NDIS_STATUS_SUCCESS for a successful
+// completion and returns an error code if an
+// error is encountered.
+//
+// Called_By: OS
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath)
+
+{
+ NDIS_STATUS Status;
+
+ //
+ // The characteristics table
+ //
+ NDIS_MINIPORT_CHARACTERISTICS NetFlexChar;
+
+ DebugPrint(1,("NetFlex: Dynamic Ratio Version\n"));
+
+#ifdef XMIT_INTS
+ DebugPrint(1,("NetFlex: with Transmit Interrupts\n"));
+#endif
+
+ //
+ // Indicate that we are in initialization mode.
+ //
+ macgbls.Initializing = TRUE;
+
+ //
+ // Initialize the Wrapper
+ //
+ NdisMInitializeWrapper(
+ &macgbls.mac_wrapper,
+ DriverObject,
+ RegistryPath,
+ NULL);
+
+ //
+ // Store the driver object. We will need this for Unloading
+ // the driver.
+
+ macgbls.mac_object = DriverObject;
+
+ //
+ // Initialize the Miniport characteristics for the call to
+ // NdisMRegisterMiniport.
+ //
+ NetFlexChar.MajorNdisVersion = NETFLEX_MAJ_VER;
+ NetFlexChar.MinorNdisVersion = NETFLEX_MIN_VER;
+ NetFlexChar.CheckForHangHandler = NetFlexCheckForHang;
+ NetFlexChar.DisableInterruptHandler = NetFlexDisableInterrupt;
+ NetFlexChar.EnableInterruptHandler = NetFlexEnableInterrupt;
+ NetFlexChar.HaltHandler = NetFlexHalt;
+ NetFlexChar.HandleInterruptHandler = NetFlexHandleInterrupt;
+ NetFlexChar.InitializeHandler = NetFlexInitialize;
+ NetFlexChar.ISRHandler = NetFlexISR;
+ NetFlexChar.QueryInformationHandler = NetFlexQueryInformation;
+ NetFlexChar.ReconfigureHandler = NULL;
+ NetFlexChar.ResetHandler = NetFlexResetDispatch;
+ NetFlexChar.SendHandler = NetFlexSend;
+ NetFlexChar.SetInformationHandler = NetFlexSetInformation;
+ NetFlexChar.TransferDataHandler = NetFlexTransferData;
+ NetFlexChar.ReturnPacketHandler = NULL;
+ NetFlexChar.SendPacketsHandler = NULL;
+ NetFlexChar.AllocateCompleteHandler = NULL;
+
+ //
+ // Register this driver with NDIS
+ //
+ Status = NdisMRegisterMiniport( macgbls.mac_wrapper,
+ &NetFlexChar,
+ sizeof(NetFlexChar) );
+
+ //
+ // Set to non-initializing mode
+ //
+ macgbls.Initializing = FALSE;
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // We can only get here if something went wrong with registering
+ // the driver or *ALL* of the adapters.
+ //
+ if ((macgbls.mac_adapters == NULL) &&
+ (macgbls.mac_wrapper != NULL))
+ {
+ NdisTerminateWrapper(macgbls.mac_wrapper, NULL);
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexInitialize
+//
+// Description: See NDIS 3.0 Miniport spec.
+// Called to initialize each adapter
+//
+// Input: See NDIS 3.0 Miniport spec.
+//
+// Output: NDIS_STATUS_SUCCESS or NDIS_STATUS_PENDING
+//
+// Called_By: NDIS Miniport Wrapper
+//
+//----------------------------------------------------------------
+NDIS_STATUS
+NetFlexInitialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+
+{
+ NDIS_STATUS status;
+ PACB acb = NULL;
+ PACB FirstHeadsAcb = NULL;
+ USHORT baseaddr;
+ UINT slot,i;
+ NDIS_STRING portnumber = NDIS_STRING_CONST("PortNumber");
+ NDIS_HANDLE ConfigHandle = NULL;
+
+ NDIS_EISA_FUNCTION_INFORMATION EisaData;
+ PNDIS_CONFIGURATION_PARAMETER cfgp;
+
+ DebugPrint(2,("NetFlex: NetFlexInitialize\n"));
+
+ //
+ // Make sure we still have the wrapper, this is needed if an adapter
+ // fails to open and there isn't any already opened, the halt routine
+ // will remove the wrapper, and thus all adapters fail. I don't know
+ // if this means that I should remove the code from the halt routine
+ // or if I need to come up with aditional logic...
+ //
+ if (macgbls.mac_wrapper == NULL)
+ {
+ DebugPrint(0,("NetFlex: Don't have a handle to the Wrapper!\n"));
+ status = NDIS_STATUS_FAILURE;
+ goto ConfigError;
+ }
+
+ //
+ // Check if we have a configuration handle before proceeding.
+ //
+ if (ConfigurationHandle == NULL)
+ {
+ DebugPrint(0,("NetFlex: Adapter not set up properly - no config handle\n"));
+ status = NDIS_STATUS_FAILURE;
+ goto ConfigError;
+ }
+
+ //
+ // Open the configuration handle
+ //
+ NdisOpenConfiguration( &status,
+ &ConfigHandle,
+ ConfigurationHandle );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NetFlex: Adapter not set up properly - couldn't open config\n"));
+ status = NDIS_STATUS_FAILURE;
+ ConfigHandle = NULL;
+ goto ConfigError;
+ }
+
+ //
+ // Find out what slot number the adapter associated with
+ // this name is in.
+ //
+ NdisReadEisaSlotInformation( &status,
+ ConfigurationHandle,
+ &slot,
+ &EisaData );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NetFlex: Slot number not set up\n"));
+ status = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
+ goto ConfigError;
+ }
+
+ baseaddr = slot * 0x1000;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &portnumber,
+ NdisParameterInteger);
+
+ //
+ // If we didn't read a portnumber, that means we're adding a
+ // non-dual port card - NETFLX, MAPLE, CPQTOK
+ //
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ gbl_portnumbertoadd = 0;
+ gbl_addingdualport = FALSE;
+ }
+ else
+ {
+ gbl_portnumbertoadd = (USHORT)cfgp->ParameterData.IntegerData;
+ if (gbl_portnumbertoadd == PORT0)
+ gbl_addingdualport = FALSE;
+ else
+ gbl_addingdualport = TRUE;
+ }
+
+ //
+ // See if this adapter has been added. If so return an error.
+ // The very first time we are called, acb should be NULL.
+ //
+
+ if (macgbls.DownloadCode == NULL)
+ {
+ // On Initial Init, We need to get the global stuff...
+ //
+ status = NetFlexInitGlobals();
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ goto ConfigError;
+ }
+ }
+ else
+ {
+ acb = macgbls.mac_adapters;
+
+ while (acb)
+ {
+ if ( acb->acb_baseaddr == baseaddr)
+ {
+ //
+ // If the card has the same slot and we're adding a dual port
+ // then go to the next acb, otherwise it is an error.
+ //
+ if ( gbl_addingdualport )
+ {
+ FirstHeadsAcb = acb;
+ acb = acb->acb_next;
+ }
+ else
+ {
+ DebugPrint(0,("NetFlex: Adapter already added\n"));
+ status = NDIS_STATUS_FAILURE;
+ goto ConfigError;
+ }
+ }
+ else
+ {
+ acb = acb->acb_next;
+ }
+ }
+ }
+
+ //
+ // Allocate adapter control block and register adapter.
+ //
+
+ status = NetFlexRegisterAdapter( &acb,
+ FirstHeadsAcb,
+ ConfigHandle,
+ baseaddr,
+ MiniportAdapterHandle
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ goto ConfigError;
+ }
+
+
+ //
+ // Search for the medium type supported matches adapter configuration
+ //
+
+ for (i = 0; i < MediumArraySize; i++)
+ {
+ if (MediumArray[i] == acb->acb_gen_objs.media_type_in_use)
+ {
+ *SelectedMediumIndex = i;
+ break;
+ }
+ }
+
+ //
+ // If supported medium not found. Return an error.
+ //
+ if (i == MediumArraySize)
+ {
+ DebugPrint(0,("NetFlex: No supported media found!\n"));
+ status = NDIS_STATUS_UNSUPPORTED_MEDIA;
+ goto ConfigError;
+ }
+
+ //
+ // Now, initialize the board and the data structures.
+ // glb_ErrorCode will be set if there was an error.
+ //
+ status = NetFlexBoardInitandReg(acb,&EisaData);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Board Init and Reg Failed\n",acb->anum));
+ goto ConfigError;
+ }
+
+ConfigError:
+
+ //
+ // Were there any errors?
+ //
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // if we allocated an acb, we need to get rid of it...
+ //
+ if (acb != NULL)
+ {
+ //
+ // Since there was an acb, the error data and section code will be in
+ // the acb instead of the globals.
+ //
+ NetFlexDeregisterAdapter(acb);
+ }
+
+ DebugPrint(0, ("NF: NetFlexInitialize Failed!\n"));
+ }
+
+ if (ConfigHandle != NULL)
+ {
+ NdisCloseConfiguration(ConfigHandle);
+ }
+ return status;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexRegisterAdapter
+//
+// Description: This routine allocates memory for the adapter
+// control block and registers with the wrapper.
+//
+// Input: acbp - pointer to adapter control block
+//
+//
+// Output: Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is
+// returned.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexRegisterAdapter(
+ PACB *acbp,
+ PACB FirstHeadsAcb,
+ NDIS_HANDLE ConfigHandle,
+ USHORT baseaddr,
+ NDIS_HANDLE MiniportAdapterHandle
+ )
+{
+ PACB acb;
+ USHORT cpqid, boardid, reg_value;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ //
+ // Allocate the Memory for the adapter's acb.
+ //
+ NdisAllocateMemory( (PVOID *)&acb,
+ (UINT) (sizeof (ACB)),
+ (UINT) 0,
+ NetFlexHighestAddress );
+ //
+ // If we did not get the memory, flag any error.
+ //
+ if (acb == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Zero out the memory. Save configuration handle.
+ //
+ NdisZeroMemory(acb, sizeof (ACB));
+ acb->acb_state = AS_REGISTERING;
+ acb->acb_baseaddr = baseaddr;
+
+ //
+ // Indicate that we are initializing the adapter.
+ //
+ acb->AdapterInitializing = TRUE;
+
+ //
+ // link in this acb
+ //
+ *acbp = acb;
+ macgbls.mac_numadpts++;
+#if (DBG || DBGPRINT)
+ acb->anum = macgbls.mac_numadpts;
+#endif
+
+ //
+ // save reference to our Miniport Handle
+ //
+ acb->acb_handle = MiniportAdapterHandle;
+
+ //
+ // Initialize reset timer
+ //
+ NdisMInitializeTimer(
+ &acb->ResetTimer,
+ acb->acb_handle,
+ (PVOID) NetFlexResetHandler,
+ (PVOID) acb );
+
+ //
+ // Initialize DPC timer
+ //
+ NdisMInitializeTimer(
+ &acb->DpcTimer,
+ acb->acb_handle,
+ (PVOID) NetFlexDeferredTimer,
+ (PVOID) acb );
+
+ //
+ // Set the attributes for this adapter
+ //
+ NdisMSetAttributes( MiniportAdapterHandle,
+ (NDIS_HANDLE) acb,
+ TRUE,
+ NdisInterfaceEisa );
+
+ //
+ // Register our shutdown handler.
+ //
+
+ NdisMRegisterAdapterShutdownHandler(
+ MiniportAdapterHandle, // wrapper miniport handle.
+ acb, // shutdown context.
+ NetFlexShutdown // shutdown handler.
+ );
+
+ //
+ // Reserve this adapters IO ports, if they haven't allready been added by the first
+ // head...
+ //
+
+ if (gbl_addingdualport)
+ {
+ if (FirstHeadsAcb == NULL)
+ {
+ // This is the first instance of a head on a dual port board,
+ // so register all the io ports for both heads.
+
+ acb->FirstHeadsAcb = acb;
+
+ //
+ // grab ports z000 - z02f
+ //
+ Status = NdisMRegisterIoPortRange( (PVOID *)&acb->BasePorts,
+ MiniportAdapterHandle,
+ baseaddr,
+ NUM_DUALHEAD_CFG_PORTS );
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // Save the master base port addresses
+ //
+ acb->MasterBasePorts = acb->BasePorts;
+
+ // grab zc80 - zc85
+ //
+ Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ConfigPorts,
+ MiniportAdapterHandle,
+ baseaddr + CFG_PORT_OFFSET,
+ NUM_CFG_PORTS );
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // grab zc63 - zc67
+ //
+ Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ExtConfigPorts,
+ MiniportAdapterHandle,
+ baseaddr + EXTCFG_PORT_OFFSET,
+ NUM_EXTCFG_PORTS );
+ }
+ }
+ }
+ else
+ {
+ // Get the pointers to the other head's ports, which are already mapped.
+ //
+ acb->FirstHeadsAcb = FirstHeadsAcb;
+ acb->BasePorts = FirstHeadsAcb->MasterBasePorts;
+ acb->ConfigPorts = FirstHeadsAcb->ConfigPorts;
+ acb->ExtConfigPorts = FirstHeadsAcb->ExtConfigPorts;
+ acb->MasterBasePorts= FirstHeadsAcb->MasterBasePorts;
+ Status = NDIS_STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ // grab ports z000 - z01f
+ //
+ Status = NdisMRegisterIoPortRange( (PVOID *)&acb->BasePorts,
+ MiniportAdapterHandle,
+ baseaddr,
+ NUM_BASE_PORTS );
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // grab zc80 - zc85
+ //
+ Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ConfigPorts,
+ MiniportAdapterHandle,
+ baseaddr + CFG_PORT_OFFSET,
+ NUM_CFG_PORTS );
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // grab zc63 - zc67
+ //
+ Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ExtConfigPorts,
+ MiniportAdapterHandle,
+ baseaddr + EXTCFG_PORT_OFFSET,
+ NUM_EXTCFG_PORTS );
+ }
+ }
+ }
+
+ //
+ // If the registration fails, free up the memory we allocated
+ // for the acb.
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF: Registration FAILED for slot#%d\n",(baseaddr / 1000)));
+ goto HandleRegisterError;
+ }
+
+ //
+ // Read in the company product id.
+ //
+ NdisRawReadPortUshort( acb->ConfigPorts, (PUSHORT) &cpqid);
+ //
+ // Read in the board product id.
+ //
+ NdisRawReadPortUshort( acb->ConfigPorts + 2, (PUSHORT) &boardid);
+ //
+ // Does it have a Compaq id?
+ //
+ // NETFLEX_ID covers NetFlex and NetFlex-2
+ // CPQTOK_ID covers DualSpeed and 16/4 Token-Ring
+
+ if ( !( (cpqid == COMPAQ_ID) &&
+ ( ((boardid & NETFLEX_REVMASK) == NETFLEX_ID) ||
+ ((boardid & NETFLEX_REVMASK) == CPQTOK_ID) ||
+ ((boardid & NETFLEX_REVMASK) == RODAN_ID) ||
+ ((boardid & NETFLEX_REVMASK) == BONSAI_ID)
+ ) ) )
+ {
+ //
+ // Not a Compaq id.
+ //
+ DebugPrint(0,("NF(%d): No Compaq adapter found\n",acb->anum));
+ Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+ goto HandleRegisterError;
+ }
+
+ //
+ // Make sure this is our board.
+ //
+ NdisRawReadPortUshort( acb->ConfigPorts + CFG_REGISTER, &reg_value);
+
+ if (!(reg_value & CFG_ENABLE))
+ {
+ DebugPrint(0,("NF(%d): Adapter is not enabled\n",acb->anum));
+ DebugPrint(0,("NF(%d): Board Test Failed\n",acb->anum));
+ Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+ goto HandleRegisterError;
+ }
+
+ //
+ // Check to see if it's a card with FPA or a dual port adapter
+ //
+
+ if ( (boardid == MAPLE_ID) ||
+ (boardid == DURANGO_ID) )
+ {
+ DebugPrint(1,("NF(%d): We're adding a card using FPA ! \n",acb->anum));
+ acb->acb_usefpa = TRUE;
+ }
+ else if ( ((boardid & NETFLEX_REVMASK) == BONSAI_ID) ||
+ ((boardid & NETFLEX_REVMASK) == RODAN_ID ) )
+ {
+ acb->acb_usefpa = TRUE;
+ acb->acb_dualport = TRUE;
+ acb->acb_portnumber = gbl_portnumbertoadd;
+ DebugPrint(1,("NF(%d): We're adding BONSAI or RODAN port #%d\n",acb->anum,acb->acb_portnumber));
+ }
+
+ //
+ // Set up the Config register location and the extended sif address
+ // register location.
+ //
+ acb->AdapterConfigPort = acb->ConfigPorts + CFG_REGISTER;
+
+ if (acb->acb_dualport && (acb->acb_portnumber == PORT2) )
+ {
+ //
+ // Align the ports right for the head #2's ports
+ //
+ acb->BasePorts = acb->FirstHeadsAcb->BasePorts + DUALHEAD_CFG_PORT_OFFSET;
+
+ if ((boardid & NETFLEX_REVMASK) == RODAN_ID)
+ {
+ acb->AdapterConfigPort = acb->MasterBasePorts + CFG_REGRODAN;
+ }
+ }
+
+ acb->SifDataPort = acb->BasePorts + SIF_DATA_OFF; /* SIF data register */
+ acb->SifDIncPort = acb->BasePorts + SIF_DINC_OFF; /* SIF data autoincrment reg */
+ acb->SifAddrPort = acb->BasePorts + SIF_ADDR_OFF; /* SIF address register */
+ acb->SifIntPort = acb->BasePorts + SIF_INT_OFF; /* SIF interrupt register */
+ acb->SifActlPort = acb->BasePorts + SIF_ACTL_OFF; /* SIF ACTL register */
+ acb->SifAddrxPort = acb->BasePorts + SIF_ACTL_EXT_OFF;/* SIF SIF extended address reg */
+
+ //
+ // Save the Board ID
+ //
+ acb->acb_boardid = boardid;
+
+ //
+ // Do a reset to the adapter
+ //
+ NdisRawWritePortUshort(acb->SifActlPort, 0xEE);
+
+ //
+ // Wait 15 milliseconds to let the reset take place.
+ //
+ NdisStallExecution((UINT)15000); // Wait 15 milliseconds
+
+ //
+ // Get the Network type and speed from the eisa config info.
+ //
+ NetFlexSetupNetType(acb);
+
+ //
+ // Read configuration parameters from the registry if there are any
+ //
+
+ Status = NetFlexReadConfigurationParameters(acb,ConfigHandle);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): NetFlexReadConfigurationParameters Failed\n",acb->anum));
+ Status = NDIS_STATUS_RESOURCES;
+ goto HandleRegisterError;
+ }
+
+HandleRegisterError:
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ if (acb!=NULL)
+ {
+ if (acb->acb_parms != NULL)
+ {
+ NdisFreeMemory( (PVOID) acb->acb_parms, (UINT) sizeof(PNETFLEX_PARMS), (UINT) 0);
+ }
+ *acbp = NULL;
+ NdisFreeMemory( (PVOID) acb, (UINT) sizeof(ACB), (UINT) 0);
+ }
+ }
+
+ return(Status);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexReadConfigurationParameters
+//
+// Description: This routine reads configuration parameters
+// set by the user in the registry if exist.
+//
+// Input: acb - Adapter Context
+// ConfigHandle
+//
+// Output: Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is
+// returned.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexReadConfigurationParameters(
+ PACB acb,
+ NDIS_HANDLE ConfigHandle
+ )
+
+{
+ NDIS_STATUS status;
+ PNETFLEX_PARMS pParms = NULL;
+ ULONG length;
+ PVOID NetworkAddress;
+ BOOLEAN WriteError;
+ PNDIS_CONFIGURATION_PARAMETER cfgp;
+
+ ULONG netspeed = acb->acb_gen_objs.link_speed;
+
+ NDIS_STRING maxreceives = NDIS_STRING_CONST("MAXRECEIVES");
+ NDIS_STRING productid = NDIS_STRING_CONST("PRODUCTID");
+ NDIS_STRING earlyrelease = NDIS_STRING_CONST("EARLYRELEASE");
+ NDIS_STRING maxtransmits = NDIS_STRING_CONST("MAXTRANSMITS");
+ NDIS_STRING maxframesz = NDIS_STRING_CONST("MAXFRAMESIZE");
+ NDIS_STRING maxmulticast = NDIS_STRING_CONST("MAXMULTICAST");
+ NDIS_STRING maxinternalreqs = NDIS_STRING_CONST("MAXINTERNALREQS");
+ NDIS_STRING maxinternalbufs = NDIS_STRING_CONST("MAXINTERNALBUFS");
+ NDIS_STRING maxtxbuf = NDIS_STRING_CONST("MAXTXBUF");
+ NDIS_STRING mintxbuf = NDIS_STRING_CONST("MINTXBUF");
+ NDIS_STRING extremecheckforhang = NDIS_STRING_CONST("ExtremeCheckForHang");
+
+#ifdef XMIT_INTS
+ NDIS_STRING xmitintratio = NDIS_STRING_CONST("TXINTRATIO");
+#endif
+ NDIS_STRING rcvintratio = NDIS_STRING_CONST("RXINTRATIO");
+
+ //
+ // Allocate the Memory for the adapter's parms structure.
+ //
+ NdisAllocateMemory( (PVOID *)&pParms,
+ (UINT) (sizeof (NETFLEX_PARMS)),
+ (UINT) 0,
+ NetFlexHighestAddress );
+ //
+ // If we did not get the memory, flag any error.
+ //
+ if (pParms == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ NdisMoveMemory(pParms, &NetFlex_Defaults, sizeof(NETFLEX_PARMS));
+
+
+ //
+ // See if the user has specified the maximum number of internal
+ // transmit buffers
+ //
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxinternalbufs,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_INTERNALBUFS) &&
+ (cfgp->ParameterData.IntegerData >= MIN_INTERNALBUFS) )
+ {
+ pParms->utd_maxinternalbufs = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MAXINTERNALBUFS parameter is out of range, using default\n",acb->anum));
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXINTERNALBUFS_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxinternalbufs);
+ }
+ }
+
+ //
+ // Read the network specific information from the registry
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ {
+ // TokenRing
+ //
+ //
+ // See if early token release has been selected.
+ //
+ if (netspeed == 16)
+ {
+ // Default to early token release.
+ //
+ pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_ETR);
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &earlyrelease,
+ NdisParameterInteger );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( cfgp->ParameterData.IntegerData == 0)
+ {
+ // The user does not want early token release.
+ //
+ pParms->utd_open.OPEN_Options &= SWAPS((~OOPTS_ETR));
+ }
+ }
+ }
+
+ //
+ // Set the framehold bit so that we can allow promiscuous mode
+ // to be set later on. We don't necessarily have to set
+ // promiscuous mode but if we do, this is a requirement.
+ //
+ pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_FHOLD);
+
+ //
+ // Set MaxTransmits
+ //
+ pParms->utd_numsmallbufs = pParms->utd_maxtrans = DF_XMITS_TR;
+ //
+ // See if the user has specified the maximum number of transmit
+ // lists supported.
+ //
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxtransmits,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_XMITS_TR) &&
+ (cfgp->ParameterData.IntegerData >= MIN_XMITS) )
+ {
+ pParms->utd_numsmallbufs = pParms->utd_maxtrans = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MAXTRANSMITS parameter is out of range, using default\n",acb->anum));
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXTRANSMITS_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxtrans);
+ }
+ }
+
+ //
+ // See if the user has specified the maximum frame size.
+ //
+ pParms->utd_maxframesz = DF_FRAMESIZE_TR;
+ WriteError = FALSE;
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxframesz,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if (cfgp->ParameterData.IntegerData < MIN_FRAMESIZE)
+ {
+ pParms->utd_maxframesz = MIN_FRAMESIZE;
+ WriteError = TRUE;
+ }
+ else if (netspeed == 16)
+ {
+ // 16 Mb
+ //
+ if (cfgp->ParameterData.IntegerData > MAX_FRAMESIZE_TR16)
+ {
+ pParms->utd_maxframesz = MAX_FRAMESIZE_TR16;
+ WriteError = TRUE;
+ }
+ else
+ {
+ pParms->utd_maxframesz = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ }
+ //
+ // 4Mb
+ //
+ else if (cfgp->ParameterData.IntegerData > MAX_FRAMESIZE_TR4)
+ {
+ pParms->utd_maxframesz = MAX_FRAMESIZE_TR4;
+ WriteError = TRUE;
+ }
+ else
+ {
+ pParms->utd_maxframesz = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+
+ if (WriteError)
+ {
+ // The parameter is out of range.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXFRAMESIZE_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxframesz);
+
+ DebugPrint(0,("NF(%d): MaxFrameSize parameter is out of range, using default\n",acb->anum));
+ }
+ }
+
+ //
+ // See if the user has specified the maximum number of Receive
+ // lists supported.
+ //
+ pParms->utd_maxrcvs = DF_RCVS_TR;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxreceives,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_RCVS_TR) &&
+ (cfgp->ParameterData.IntegerData >= MIN_RCVS) )
+ {
+ pParms->utd_maxrcvs = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXRECEIVES_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxrcvs);
+
+ DebugPrint(0,("NF(%d): MAXReceives parameter is out of range, using default\n",acb->anum));
+ }
+ }
+
+ //
+ // Adjust Number of Lists based on size of Max TR Frame Size
+ //
+ //
+ // For every frame size which is greater than a multiple of 4096,
+ // decrease number of transmits, Receives, and internal buffers.
+ //
+ if (pParms->utd_maxframesz > DF_FRAMESIZE_TR)
+ {
+ if (pParms->utd_maxframesz < ( (DF_FRAMESIZE_TR*2)+2) )
+ {
+ pParms->utd_maxtrans = MAX_XMITS_TR-2; /* 6 xmits, 30 mapregs */
+ pParms->utd_maxrcvs = MAX_XMITS_TR-2;
+ pParms->utd_maxinternalbufs = pParms->utd_maxtrans / 2;
+ }
+ else
+ {
+ pParms->utd_maxtrans = MAX_XMITS_TR-4; /* 4 xmits, 25 mapregs */
+ pParms->utd_maxrcvs = MAX_XMITS_TR-4;
+ pParms->utd_maxinternalbufs = pParms->utd_maxtrans / 2;
+ }
+ }
+
+ }
+ else
+ {
+ // Ethernet
+ //
+ //
+ // Set the framehold bit so that we can allow promiscuous mode
+ // to be set later on. We don't necessarily have to set
+ // promiscuous mode but if we do, this is a requirement.
+ //
+ pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_REQ + OOPTS_FHOLD);
+ pParms->utd_maxframesz = DF_FRAMESIZE_ETH;
+
+ //
+ // See if the user has specified the maximum number of multicast
+ // addresses supported.
+ //
+
+ pParms->utd_maxmulticast = DF_MULTICASTS;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxmulticast,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_MULTICASTS) &&
+ (cfgp->ParameterData.IntegerData >= MIN_MULTICASTS) )
+ {
+ pParms->utd_maxmulticast = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MAXMULTICAST Parameter is out of range, using default\n",acb->anum));
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXMULTICAST_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxmulticast);
+ }
+ }
+
+ //
+ // See if the user has specified the maximum number of transmit lists.
+ //
+
+ pParms->utd_numsmallbufs = pParms->utd_maxtrans = DF_XMITS_ETH;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxtransmits,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_XMITS_ETH) &&
+ (cfgp->ParameterData.IntegerData >= MIN_XMITS) )
+ {
+ pParms->utd_numsmallbufs = pParms->utd_maxtrans = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MAXTRANSMITS parameter is out of range, using default\n",acb->anum));
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXTRANSMITS_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxtrans);
+ }
+ }
+
+ //
+ // See if the user has specified the maximum frame size.
+ //
+ WriteError = FALSE;
+ pParms->utd_maxframesz = MAX_FRAMESIZE_ETH;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxframesz,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if (cfgp->ParameterData.IntegerData < MIN_FRAMESIZE)
+ {
+ pParms->utd_maxframesz = MIN_FRAMESIZE;
+ WriteError = TRUE;
+ }
+ else if (cfgp->ParameterData.IntegerData > MAX_FRAMESIZE_ETH)
+ {
+ pParms->utd_maxframesz = MAX_FRAMESIZE_ETH;
+ WriteError = TRUE;
+ }
+ else
+ {
+ pParms->utd_maxframesz = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+
+ if (WriteError)
+ {
+ // The parameter is out of range.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXFRAMESIZE_ERROR,
+ 2,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxframesz);
+
+ DebugPrint(0,("NF(%d): MaxFrameSize parameter is out of range, using default\n",acb->anum));
+ }
+ }
+
+ //
+ // See if the user has specified the maximum number of Receive
+ // lists supported.
+ //
+
+ pParms->utd_maxrcvs = DF_RCVS_ETH;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxreceives,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_RCVS_ETH) &&
+ (cfgp->ParameterData.IntegerData >= MIN_RCVS) )
+ {
+ pParms->utd_maxrcvs = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_MAXRECEIVES_ERROR,
+ (ULONG)cfgp->ParameterData.IntegerData,
+ (ULONG)pParms->utd_maxrcvs);
+ DebugPrint(0,("NF(%d): MAXReceives parameter is out of range, using default\n",acb->anum));
+ }
+ }
+ }
+
+ DebugPrint(1,("NF(%d): MaxFrameSize = %d\n",acb->anum,pParms->utd_maxframesz));
+ DebugPrint(1,("NF(%d): MaxTransmits = %d\n",acb->anum,pParms->utd_maxtrans));
+ DebugPrint(1,("NF(%d): MaxReceives = %d\n",acb->anum,pParms->utd_maxrcvs));
+
+ //
+ // Common Configuration settings for both Ethernet and TokenRing
+ //
+
+ //
+ // See if the user has specified extreme checking for adapter hang.
+ //
+ NdisReadConfiguration(&status,
+ &cfgp,
+ ConfigHandle,
+ &extremecheckforhang,
+ NdisParameterInteger);
+ if ((NDIS_STATUS_SUCCESS == status) &&
+ (cfgp->ParameterData.IntegerData != 0))
+ {
+ //
+ // They want the extreme checking to see if this adapter is
+ // hung.
+ //
+ pParms->utd_extremecheckforhang = TRUE;
+ }
+
+ //
+ // See if the user has specified the maximum number of adapter transmit buffers.
+ //
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxtxbuf,
+ NdisParameterInteger);
+
+ //
+ // Set default Transmist_Buffer_Maximum_Count based on the max frame size * 2 tx lists
+ //
+
+ pParms->utd_open.OPEN_Xbufmax = ((pParms->utd_maxframesz / 1024) + 1 ) * 2;
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ // Make Sure the value doesn't preclude us from transmiting a max frame size
+ //
+ if (cfgp->ParameterData.IntegerData > (UINT) (pParms->utd_maxframesz / 1024))
+ {
+ pParms->utd_open.OPEN_Xbufmax = (UCHAR)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MaxTXBuf parameter is out of range, using default\n",acb->anum));
+ }
+ }
+
+ DebugPrint(1,("NF(%d): MaxTXBuf = 0x%x\n",acb->anum,pParms->utd_open.OPEN_Xbufmax));
+
+ //
+ // See if the user has specified the minimum number of adapter transmit buffers.
+ //
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &mintxbuf,
+ NdisParameterInteger);
+
+ //
+ // Set default Transmist_Buffer_Minimum_Count based on the max
+ //
+ pParms->utd_open.OPEN_Xbufmin = pParms->utd_open.OPEN_Xbufmax;
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+
+ if ((cfgp->ParameterData.IntegerData >= 0) &&
+ (cfgp->ParameterData.IntegerData <= pParms->utd_open.OPEN_Xbufmax) )
+ {
+ pParms->utd_open.OPEN_Xbufmin = (UCHAR)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MinTXBuf parameter is out of range, using default\n",acb->anum));
+ }
+ }
+
+ DebugPrint(1,("NF(%d): MinTXBuf = 0x%x\n",acb->anum,pParms->utd_open.OPEN_Xbufmin));
+
+
+ //
+ // See if the user has specified the maximum number of internal
+ // requests supported.
+ //
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &maxinternalreqs,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if ( (cfgp->ParameterData.IntegerData <= MAX_INTERNALREQS) &&
+ (cfgp->ParameterData.IntegerData >= MIN_INTERNALREQS) )
+ {
+ pParms->utd_maxinternalreqs = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ else
+ {
+ // The parameter is out of range.
+ DebugPrint(0,("NF(%d): MAXINTERNALREQS parameter is out of range, using default\n",acb->anum));
+ }
+ }
+
+ //
+ // See if the user has specified the node address
+ //
+ NdisReadNetworkAddress( &status,
+ &NetworkAddress,
+ &length,
+ ConfigHandle );
+
+ if ((length == NET_ADDR_SIZE) && (status == NDIS_STATUS_SUCCESS))
+ {
+ NdisMoveMemory((PUCHAR)pParms->utd_open.OPEN_NodeAddr,
+ (PUCHAR)NetworkAddress,
+ NET_ADDR_SIZE);
+ }
+ else
+ {
+ DebugPrint(1,("NF(%d): Error in NdisReadNetworkAddress or none specified\n",acb->anum));
+ }
+
+ //
+ // See if the user has specified the product id
+ //
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &productid,NdisParameterString );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ status = NetFlexAsciiToHex( &(cfgp->ParameterData.StringData),
+ (PUCHAR)pParms->utd_open.OPEN_ProdID,
+ (USHORT)(18) );
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ // The parameter is out of range.
+ DebugPrint(1,("NF(%d): PRODUCTID parameter is invalid, using default\n",acb->anum));
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_PRODUCTID_ERROR,
+ 0);
+ }
+ }
+
+ //
+ // See if we need to open in Full Duplex
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ //
+ // Allocate the xmit spin lock.
+ //
+ NdisAllocateSpinLock(&acb->XmitLock);
+
+ pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_FULLDUP);
+ }
+
+ acb->acb_parms = pParms;
+
+#ifdef XMIT_INTS
+ //
+ // See if the user has specified the xmit_int_ratio
+ //
+
+ acb->XmitIntRatio = TxIntRatio;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &xmitintratio,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS) {
+ acb->XmitIntRatio = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ DebugPrint(1,("NF(%d): TxIntRatio = 1:%d\n",acb->anum,acb->XmitIntRatio));
+#endif
+
+ //
+ // See if the user has specified the rcv_int_ratio
+ //
+
+ acb->RcvIntRatio = RxIntRatio;
+
+ NdisReadConfiguration( &status,
+ &cfgp,
+ ConfigHandle,
+ &rcvintratio,
+ NdisParameterInteger);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ acb->RcvIntRatio = (USHORT)cfgp->ParameterData.IntegerData;
+ }
+ DebugPrint(1,("NF(%d): Rx Int Ratio = 1:%d\n",acb->anum,acb->RcvIntRatio));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexBoardInitandReg
+//
+// Description: This routine initiailizes the board, downloads
+// the mac code, and registers the adapter with
+// the wrapper.
+//
+// Input: acbp - Pointer to an acb ptr.
+// pParms - Settable parameters
+//
+// Output: acbp - Pointer to allocated acb
+// Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is
+// returned.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexBoardInitandReg(
+ PACB acb,
+ PNDIS_EISA_FUNCTION_INFORMATION EisaData
+ )
+{
+ UINT int_vector;
+ NDIS_INTERRUPT_MODE int_mode;
+ NDIS_STATUS status;
+ UINT i=0;
+
+ //
+ // Initialize the fields of the acb.
+ //
+ if ((status = NetFlexInitializeAcb(acb)) != NDIS_STATUS_SUCCESS)
+ {
+ // Failed, get out now...
+ //
+ return status;
+ }
+
+ //
+ // Get EISA Config Data so we can set the interrupt data
+ //
+ int_vector = EisaData->EisaIrq[0].ConfigurationByte.Interrupt;
+
+ if (!int_vector)
+ {
+ return NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
+ }
+
+ if (gbl_addingdualport)
+ {
+ // Dualport boards share the same interupt between heads
+ //
+ acb->InterruptsShared = TRUE;
+ }
+ else
+ {
+ acb->InterruptsShared = EisaData->EisaIrq[0].ConfigurationByte.Shared;
+ }
+
+ int_mode = EisaData->EisaIrq[0].ConfigurationByte.LevelTriggered ? NdisInterruptLevelSensitive : NdisInterruptLatched;
+
+ //
+ // Add this acb to the global list
+ //
+ acb->acb_next = macgbls.mac_adapters;
+ macgbls.mac_adapters = acb;
+
+ //
+ // Initialize the interrupt.
+ //
+ status = NdisMRegisterInterrupt( &acb->acb_interrupt,
+ acb->acb_handle,
+ int_vector,
+ int_vector,
+ FALSE, // TRUE,
+ acb->InterruptsShared,
+ int_mode );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Initialization of the Interrupt FAILED\n",acb->anum));
+
+ NetFlexDequeue_OnePtrQ( (PVOID *)&macgbls.mac_adapters,
+ (PVOID)acb);
+
+ return status;
+ }
+
+ //
+ // Ok, we're set, so reset the adapter and open'er up!
+ // Try three times...
+ //
+ do
+ {
+ status = NetFlexAdapterReset(acb,HARD_RESET);
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Send the Open Command
+ //
+ status = NetFlexOpenAdapter(acb);
+ }
+
+ } while ((++i < 3) && (status != NDIS_STATUS_SUCCESS));
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ // Something failed, so get out.
+ //
+ return status;
+ }
+
+ //
+ // Get the Burned In Address
+ //
+
+ NetFlexGetBIA(acb);
+
+ //
+ // Set the Default DPC timer
+ //
+
+ NdisMSetTimer(&acb->DpcTimer, 10);
+
+ //
+ // Indidicate that we're done with initializing this adapter.
+ //
+ acb->AdapterInitializing = FALSE;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexInitGlobals
+//
+// Description: This routine initializes the global
+// variables and downloads the mac download
+// code into our map buffer area.
+//
+// Input: None.
+//
+// Output: Status = SUCCESS .
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexInitGlobals(
+ )
+{
+ NDIS_STRING maccode = NDIS_STRING_CONST("NETFLX.BIN");
+ UINT length;
+ NDIS_STATUS status;
+ PUSHORT MappedBuffer;
+ NDIS_HANDLE mac_filehandle;
+
+ //
+ // Open the file containing the MAC download code.
+ //
+ NdisOpenFile( &status,
+ &mac_filehandle,
+ &length,
+ &maccode,
+ NetFlexHighestAddress);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF: Download file could not be opened\n"));
+ return status;
+ }
+
+ //
+ // Allocate the buffer.
+ //
+ NdisAllocateMemory( (PVOID *)&macgbls.DownloadCode,
+ length,
+ FALSE,
+ NetFlexHighestAddress);
+
+ if (macgbls.DownloadCode == NULL)
+ {
+ status = NDIS_STATUS_FAILURE;
+ }
+ else
+ {
+ // Store the length
+ //
+ macgbls.DownloadLength = length;
+ //
+ // Get a mapping to the opened download file.
+ //
+ NdisMapFile( &status,
+ (PVOID *)&MappedBuffer,
+ mac_filehandle);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF: Download file could not be mapped\n"));
+ }
+ else
+ {
+ // Copy the download code into the shared memory space
+ //
+ NdisMoveMemory(macgbls.DownloadCode,MappedBuffer,length);
+ NdisUnmapFile(mac_filehandle);
+ }
+
+ //
+ // Done with the file
+ NdisCloseFile(mac_filehandle);
+ }
+
+ return status;
+}
diff --git a/private/ntos/ndis/netflex/initd.c b/private/ntos/ndis/netflex/initd.c
new file mode 100644
index 000000000..f05ebb41f
--- /dev/null
+++ b/private/ntos/ndis/netflex/initd.c
@@ -0,0 +1,230 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: INITD.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+
+INIT init_mask =
+{
+ 0x9f00,
+ { 0, 0, 0, 0, 0, 0 },
+ 0,
+ 0,
+ 0x0505
+};
+
+
+NETFLEX_PARMS NetFlex_Defaults =
+{
+ { 0, // Options
+ { 0, 0, 0, 0, 0, 0 }, // Node Address
+ { 0, 0, 0, 0}, // Group Address
+ { 0, 0, 0, 0}, // Functional Address
+ 0x0e00, // Receive list size
+ SWAPS(SIZE_XMIT_LIST), // Transmit list size w/ NUM_BUFS_PER_LIST frags
+ 0x0004, // Buffer size 1 k
+ 0x0000, // Ram start
+ 0xffff, // Ram end
+ 0xc, // Xmit buf min (4k/1k)*2
+ 0xc, // Xmit buf max
+ (char *) NetFlex_Defaults.utd_open.OPEN_ProdID,
+ { 0x09, 0x10,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }
+ },
+ DF_XMITS_TR,
+ DF_RCVS_TR,
+ DF_FRAMESIZE_TR,
+ DF_MULTICASTS,
+ DF_INTERNALREQS,
+ DF_INTERNALBUFS,
+ DF_XMITS_TR,
+ 256,
+ 0
+};
+// USHORT utd_numsmallbufs;
+// USHORT utd_smallbufsz;
+
+
+NDIS_OID NetFlexGlobalOIDs_Eth[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_GEN_RCV_CRC_ERROR,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+ OID_802_3_XMIT_DEFERRED,
+ OID_802_3_XMIT_LATE_COLLISIONS,
+ OID_802_3_XMIT_MAX_COLLISIONS,
+ OID_802_3_XMIT_TIMES_CRS_LOST,
+ OID_NF_INTERRUPT_COUNT,
+ OID_NF_INTERRUPT_RATIO,
+ OID_NF_INTERRUPT_RATIO_CHANGES
+};
+SHORT NetFlexGlobalOIDs_Eth_size = sizeof (NetFlexGlobalOIDs_Eth);
+
+
+NDIS_OID NetFlexNetworkOIDs_Eth[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAC_OPTIONS,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE
+};
+SHORT NetFlexNetworkOIDs_Eth_size = sizeof(NetFlexNetworkOIDs_Eth);
+
+NDIS_OID NetFlexGlobalOIDs_Tr[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_802_5_PERMANENT_ADDRESS,
+ OID_802_5_CURRENT_ADDRESS,
+ OID_802_5_UPSTREAM_ADDRESS,
+ OID_802_5_CURRENT_FUNCTIONAL,
+ OID_802_5_CURRENT_GROUP,
+ OID_802_5_LAST_OPEN_STATUS,
+ OID_802_5_CURRENT_RING_STATUS,
+ OID_802_5_CURRENT_RING_STATE,
+ OID_802_5_LINE_ERRORS,
+ OID_802_5_LOST_FRAMES,
+ OID_802_5_BURST_ERRORS,
+ OID_802_5_AC_ERRORS,
+ OID_802_5_CONGESTION_ERRORS,
+ OID_802_5_FRAME_COPIED_ERRORS,
+ OID_802_5_TOKEN_ERRORS
+};
+SHORT NetFlexGlobalOIDs_Tr_size = sizeof(NetFlexGlobalOIDs_Tr);
+
+NDIS_OID NetFlexNetworkOIDs_Tr[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAC_OPTIONS,
+ OID_802_5_PERMANENT_ADDRESS,
+ OID_802_5_CURRENT_ADDRESS,
+ OID_802_5_UPSTREAM_ADDRESS,
+ OID_802_5_CURRENT_FUNCTIONAL,
+ OID_802_5_CURRENT_GROUP
+};
+SHORT NetFlexNetworkOIDs_Tr_size = sizeof(NetFlexNetworkOIDs_Tr);
+
+//
+// Make a 64-bit Ndis_Physical_Address value for the highest acceptable
+// Physical address allowable. The -1 means that it does not matter.
+//
+NDIS_PHYSICAL_ADDRESS NetFlexHighestAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
diff --git a/private/ntos/ndis/netflex/int.c b/private/ntos/ndis/netflex/int.c
new file mode 100644
index 000000000..64571a328
--- /dev/null
+++ b/private/ntos/ndis/netflex/int.c
@@ -0,0 +1,977 @@
+
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: INT.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//
+//
+//***********************************************************************
+
+
+/*-------------------------------------*/
+/* Include all general companion files */
+/*-------------------------------------*/
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexISR
+//
+// Description:
+// This routine is the ISR for this Netflx mac driver.
+// This routine determines if the interrupt is for it
+// and if so, it clears the system interrupt bit of
+// the sifint register.
+//
+// Input:
+// Context - Our Driver Context for this adapter or head.
+//
+// Output:
+// Returns TRUE if the interrupt belongs to the
+// adapter and returns FALSE if it does not
+// belong to the adapter.
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexISR(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN PVOID Context )
+{
+ PACB acb;
+ USHORT sifint_reg;
+ USHORT actl_reg;
+
+ acb = (PACB) Context;
+
+ //
+ // Read the Sifint register.
+ //
+ NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg);
+
+ //
+ // See if the System Interrupt bit is set. If it is, this is an
+ // interrupt for us.
+ //
+ if (sifint_reg & SIFINT_SYSINT)
+ {
+ //
+ // Acknowledge and Clear Int
+ //
+ if (!acb->InterruptsDisabled)
+ {
+ actl_reg = acb->actl_reg & ~ACTL_SINTEN;
+ NdisRawWritePortUshort(acb->SifActlPort, actl_reg);
+ DebugPrint(3,("NF(%d)(D)\n",acb->anum));
+ acb->InterruptsDisabled = TRUE;
+
+ //
+ // Return that we recognize it
+ //
+ *InterruptRecognized = TRUE;
+ *QueueDpc = TRUE;
+ }
+ else
+ {
+ //
+ // It appears that a second head is generating
+ // the interrupt, and we have a DPC queued to
+ // process our int, return that we don't recognize it
+ // so that the oterh head's isr gets called...
+ //
+ *InterruptRecognized = FALSE;
+ *QueueDpc = FALSE;
+ }
+ }
+ else
+ {
+ // Return that we don't recognize it
+ //
+ *InterruptRecognized = FALSE;
+ *QueueDpc = FALSE;
+ }
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDeferredTimer
+//
+// Description:
+// This routine is called every 10ms to check to see
+// if there is any receives or transmits which need
+// to be cleaned up since we don't require an interrupt
+// for each frame.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None.
+//
+// Called By:
+// Miniport Wrapper via acb->DpcTimer
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+#ifdef NEW_DYNAMIC_RATIO
+UINT MaxIntRatio = 4;
+
+//
+// New Threshold for xmit disabled case.
+//
+UINT RaiseIntThreshold = 26;
+
+//
+// Run threshold of 1.5 seconds instead of 200msecs.
+//
+UINT RunThreshold = 15;
+UINT RatioCheckCount = 10;
+#else
+
+UINT sw24 = 220;
+UINT sw21 = 40;
+#endif
+
+#ifdef ALLOW_DISABLE_DYNAMIC_RATIO
+BOOLEAN EnableDynamicRatio = TRUE;
+UINT ratio = 1;
+#endif
+
+VOID NetFlexDeferredTimer(
+ IN PVOID SystemSpecific1,
+ IN PACB acb,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+)
+{
+ USHORT ReceivesProcessed = 0;
+ USHORT sifint_reg;
+ UINT IntAve;
+
+ //
+ // Indicate that a timer has expired.
+ //
+ DebugPrint(3,("NF(%d) - Defered Timer Expired!\n",acb->anum));
+
+ //
+ // If we are resetting, get out...
+ //
+ if (acb->acb_state == AS_RESETTING)
+ {
+ return;
+ }
+
+ //
+ // See if there are any recieves to do...
+ //
+
+ if (acb->acb_rcv_head->RCV_CSTAT & RCSTAT_COMPLETE)
+ {
+ //
+ // Increment the interrupt count.
+ //
+ acb->acb_int_count++;
+
+ // yes, do them...
+ //
+ ReceivesProcessed = acb->ProcessReceiveHandler(acb);
+ }
+
+ //
+ // See if there are any transmits to do...
+ //
+ NetFlexProcessXmit(acb);
+
+ //
+ // Processed any receives which need IndicateReceiveComplete?
+ //
+ if (ReceivesProcessed)
+ {
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ {
+ // Token Ring
+ //
+ NdisMTrIndicateReceiveComplete(acb->acb_handle);
+ }
+ else
+ {
+ // Ethernet
+ //
+ NdisMEthIndicateReceiveComplete(acb->acb_handle);
+ }
+ }
+
+
+ if ( ++acb->timer_run_count >= RatioCheckCount )
+ {
+ acb->timer_run_count = 0;
+
+#ifdef ALLOW_DISABLE_DYNAMIC_RATIO
+ if ( EnableDynamicRatio )
+ {
+#endif
+
+#ifdef NEW_DYNAMIC_RATIO
+
+ //
+ // Should we increase the ratio?
+ //
+ if ( acb->handled_interrupts > RaiseIntThreshold)
+ {
+ acb->current_run_down = 0;
+ if (acb->XmitIntRatio == 1)
+ {
+ if ( ++acb->current_run_up > RunThreshold )
+ {
+#ifdef XMIT_INTS
+ acb->XmitIntRatio = acb->acb_maxtrans;
+#endif
+ acb->acb_gen_objs.interrupt_ratio_changes++;
+ acb->current_run_up = 0;
+ DebugPrint(1,("NF(%d) - RcvIntRatio = %d\n",acb->anum,acb->RcvIntRatio));
+ }
+ }
+ }
+ //
+ // Or, should we decrease it?
+ //
+ else //if ( acb->handled_interrupts < LowerIntThreshold )
+ {
+ acb->current_run_up = 0;
+ if (acb->XmitIntRatio != 1)
+
+ {
+ if ( ++acb->current_run_down > RunThreshold )
+ {
+
+#ifdef XMIT_INTS
+ acb->XmitIntRatio = 1;
+#endif
+ acb->acb_gen_objs.interrupt_ratio_changes++;
+ acb->current_run_down = 0;
+ DebugPrint(1,("NF(%d) - RcvIntRatio = %d\n",acb->anum,acb->RcvIntRatio));
+ }
+ }
+ }
+
+#else // !defined(NEW_DYNAMIC_RATIO)
+
+ if ( acb->XmitIntRatio != 1 )
+ {
+ if ( acb->handled_interrupts < sw21 )
+ {
+ if ( ++acb->current_run > RunThreshold )
+ {
+
+#ifdef XMIT_INTS
+ acb->XmitIntRatio = 1;
+#endif
+ acb->RcvIntRatio = 1;
+ acb->acb_gen_objs.interrupt_ratio_changes++;
+ acb->current_run = 0;
+ acb->sw24 += 3;
+
+ acb->cleartime = 0;
+ }
+ }
+ else
+ {
+ acb->current_run = 0;
+ }
+ }
+ else
+ {
+ if ( acb->handled_interrupts > sw24 )
+ {
+ if ( ++acb->current_run > RunThreshold )
+ {
+
+#ifdef XMIT_INTS
+ acb->XmitIntRatio = ratio;
+#endif
+ acb->RcvIntRatio = ratio;
+ acb->acb_gen_objs.interrupt_ratio_changes++;
+ acb->current_run = 0;
+ }
+ }
+ else
+ {
+ acb->current_run = 0;
+ }
+ }
+
+#ifdef DYNAMIC_RATIO_HISTORY
+ acb->IntHistory[acb->Hndx] = acb->handled_interrupts;
+ acb->RatioHistory[acb->Hndx] = (UCHAR)acb->RcvIntRatio;
+
+ if ( ++acb->Hndx >= 1024 )
+ {
+ acb->Hndx = 0;
+ }
+#endif
+ //
+ // The switchover value to turbo gets incremented each time
+ // we drop to normal mode. We reset this value every x seconds.
+ // This will prevent the driver from toggling rapidly between
+ // turbo <-> normal mode.
+ //
+ if ( ++acb->cleartime > 50 )
+ {
+ acb->sw24 = sw24;
+ acb->cleartime = 0;
+ }
+
+#endif // !NEW_DYNAMIC_RATIO
+
+#ifdef ALLOW_DISABLE_DYNAMIC_RATIO
+ }
+ else
+ {
+
+#ifdef XMIT_INTS
+ acb->XmitIntRatio = ratio;
+#endif
+ acb->RcvIntRatio = ratio;
+ }
+#endif // ALLOW_DISABLE_DYNAMIC_RATIO
+
+ acb->acb_gen_objs.interrupt_count = acb->handled_interrupts;
+ acb->handled_interrupts = 0;
+ }
+
+ //
+ // Set the timer...
+ //
+ NdisMSetTimer(&acb->DpcTimer, 10);
+
+} // NetFlexDeferredTimer
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexHandleInterrupt
+//
+// Description:
+// This routine is the deferred processing
+// routine for all adapter interrupts.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexHandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ USHORT sifint_reg;
+ USHORT tmp_reg;
+ USHORT ReceivesProcessed = 0;
+
+ PACB acb = (PACB) MiniportAdapterContext;
+
+ //
+ // Read the SifInt
+ //
+ NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg);
+
+ while (sifint_reg & SIFINT_SYSINT)
+ {
+ //
+ // Ack the interrupt
+ //
+ sifint_reg &= ~SIFINT_SYSINT;
+ NdisRawWritePortUshort( acb->SifIntPort, sifint_reg);
+
+ //
+ // mask off the int code
+ //
+ sifint_reg &= INT_CODES;
+
+ //
+ // See if there are any recieves to do...
+ //
+ if (acb->acb_rcv_head->RCV_CSTAT & RCSTAT_COMPLETE)
+ {
+ //
+ // Increment the interrupt count.
+ //
+ acb->acb_int_count++;
+
+ //
+ // yes, do them...
+ //
+ acb->handled_interrupts++;
+ ReceivesProcessed += acb->ProcessReceiveHandler(acb);
+ }
+
+ //
+ // See if there are any transmits to do...
+ //
+ NetFlexProcessXmit(acb);
+
+ switch (sifint_reg)
+ {
+ case INT_SCBCLEAR:
+ acb->acb_scbclearout = FALSE;
+ //
+ // Is the SCB really clear?
+ //
+ // If the SCB is clear, send a SCB command off now.
+ // Otherwise, if we are not currently waiting for an SCB clear
+ // interrupt, signal the adapter to send us a SCB clear interrupt
+ // when it is done with the SCB.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if ((acb->acb_xmit_whead) ||
+ (acb->acb_rcv_whead) ||
+ (acb->acb_scbreq_next))
+ {
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort(
+ acb->SifIntPort,
+ (USHORT)SIFINT_SCBREQST);
+ }
+ break;
+
+ case INT_COMMAND:
+ NetFlexCommand(acb);
+
+ //
+ // Do we have any commands to complete?
+ //
+ if (acb->acb_confirm_qhead != NULL)
+ {
+ NetFlexProcessMacReq(acb);
+ }
+ break;
+
+ case INT_ADPCHECK:
+ //
+ // Read the Adapter Check Status @ 1.05e0
+ //
+ NdisRawWritePortUshort(acb->SifAddrxPort, (USHORT) 1);
+ NdisRawWritePortUshort(acb->SifAddrPort, (USHORT) 0x5e0);
+ NdisRawReadPortUshort( acb->SifDIncPort, &tmp_reg);
+
+ DebugPrint(1,("NF(%d): Adapter Check - 0x%x\n",acb->anum,tmp_reg));
+
+ //
+ // Reset has failed, errorlog an entry.
+ //
+
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_ADAPTER_CHECK_ERROR,
+ 2,
+ NETFLEX_ADAPTERCHECK_ERROR_CODE,
+ tmp_reg );
+
+ //
+ // Set the variables up showing that the hardware has an unrecoverable
+ // error.
+ //
+ acb->acb_state = AS_HARDERROR;
+ break;
+
+ case INT_RINGSTAT:
+ NetFlexRingStatus(acb);
+ break;
+
+ case INT_RECEIVE:
+ break;
+
+ case INT_TRANSMIT:
+ //
+ // If we reached the end of the xmit lists,
+ // then the xmit status will indicate COMMAND_COMPLETE.
+ // The transmiter will be stalled until another transmit
+ // command is issued with a valid list.
+ //
+ if (acb->acb_ssb_virtptr->SSB_Status & XSTAT_LERROR)
+ {
+ //
+ // We have a list error...
+ //
+ NetFlexTransmitStatus(acb);
+ }
+
+ default:
+ break;
+ }
+
+ //
+ // Issue a ssb clear. After this we may see SIFCMD interrupts.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, SIFINT_SSBCLEAR);
+
+ //
+ // Read the SifInt
+ //
+ NdisRawReadPortUshort(acb->SifIntPort, &sifint_reg);
+ }
+
+ //
+ // Processed any receives which need IndicateReceiveComplete?
+ //
+ if (ReceivesProcessed)
+ {
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ {
+ // Token Ring
+ //
+ NdisMTrIndicateReceiveComplete(acb->acb_handle);
+ }
+ else
+ {
+ // Ethernet
+ //
+ NdisMEthIndicateReceiveComplete(acb->acb_handle);
+ }
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexRingStatus
+//
+// Description:
+// This routine does the clean up work necessary
+// when a ring status occurs.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexHandleInterrupt
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexRingStatus(
+ PACB acb
+ )
+{
+ USHORT value;
+ ULONG RingStatus = 0;
+
+ value = acb->acb_ssb_virtptr->SSB_Status;
+
+ DebugPrint(1,("NF(%d): RingStatus value = %x\n",acb->anum, value));
+
+ //
+ // Determine the reason for the ring interrupt.
+ //
+ if (value & RING_STATUS_SIGNAL_LOSS)
+ {
+ RingStatus |= NDIS_RING_SIGNAL_LOSS;
+ DebugPrint(1,("NF(%d): RING_STATUS_SIGNAL_LOSS\n",acb->anum));
+
+ //
+ // Have we already reported the error?
+ //
+ if (!acb->SentRingStatusLog &&
+ ((acb->acb_lastringstatus & RING_STATUS_SIGNAL_LOSS) == 0))
+ {
+ // no, so send one.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_SIGNAL_LOSS_ERROR,
+ 3,
+ NETFLEX_RINGSTATUS_ERROR_CODE,
+ (ULONG) acb->acb_baseaddr,
+ (ULONG) value
+ );
+ acb->SentRingStatusLog = TRUE;
+ }
+ }
+
+ if (value & RING_STATUS_HARD_ERROR)
+ {
+ RingStatus |= NDIS_RING_HARD_ERROR;
+ DebugPrint(1,("NF(%d): RING_STATUS_HARD_ERROR\n",acb->anum));
+ }
+ if (value & RING_STATUS_SOFT_ERROR)
+ {
+ RingStatus |= NDIS_RING_SOFT_ERROR;
+ DebugPrint(1,("NF(%d): RING_STATUS_SOFT_ERROR\n",acb->anum));
+ }
+ if (value & RING_STATUS_XMIT_BEACON)
+ {
+ RingStatus |= NDIS_RING_TRANSMIT_BEACON;
+ DebugPrint(1,("NF(%d): RING_STATUS_XMIT_BEACON\n",acb->anum));
+ }
+ if (value & RING_STATUS_LOBE_WIRE_FAULT)
+ {
+ RingStatus |= NDIS_RING_LOBE_WIRE_FAULT;
+ DebugPrint(1,("NF(%d): RING_STATUS_LOBE_WIRE_FAULT\n",acb->anum));
+ //
+ // Have we already reported the error?
+ //
+ if (!acb->SentRingStatusLog &&
+ ((acb->acb_lastringstatus & NDIS_RING_LOBE_WIRE_FAULT) == 0))
+ {
+ // no, so send one.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_LOBE_FAILUE_ERROR,
+ 3,
+ NETFLEX_RINGSTATUS_ERROR_CODE,
+ (ULONG) acb->acb_baseaddr,
+ (ULONG) value
+ );
+
+ acb->SentRingStatusLog = TRUE;
+ }
+ }
+
+ if (value & (RING_STATUS_AUTO_REMOVE_1 | RING_STATUS_REMOVE_RECEIVED))
+ {
+ if (value & RING_STATUS_AUTO_REMOVE_1)
+ {
+ RingStatus |= NDIS_RING_AUTO_REMOVAL_ERROR;
+ DebugPrint(1,("NF(%d): RING_STATUS_AUTO_REMOVE_1\n",acb->anum));
+ }
+ if (value & RING_STATUS_REMOVE_RECEIVED)
+ {
+ RingStatus |= NDIS_RING_REMOVE_RECEIVED;
+ DebugPrint(1,("NF(%d): RING_STATUS_REMOVE_RECEIVED\n",acb->anum));
+ }
+ //
+ // Have we already reported the error?
+ //
+ if ((acb->acb_lastringstatus &
+ (RING_STATUS_AUTO_REMOVE_1 | RING_STATUS_REMOVE_RECEIVED )) == 0)
+ {
+ // no, so send one.
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_REMOVE_RECEIVED_ERROR,
+ 3,
+ NETFLEX_RINGSTATUS_ERROR_CODE,
+ (ULONG) acb->acb_baseaddr,
+ (ULONG) value
+ );
+ }
+ }
+
+ if (value & RING_STATUS_OVERFLOW)
+ {
+ RingStatus |= NDIS_RING_COUNTER_OVERFLOW;
+ DebugPrint(1,("NF(%d): RING_STATUS_OVERFLOW\n",acb->anum));
+ }
+
+ if (value & RING_STATUS_SINGLESTATION)
+ {
+ RingStatus |= NDIS_RING_SINGLE_STATION;
+ DebugPrint(1,("NF(%d): RING_STATUS_SINGLESTATION\n",acb->anum));
+ }
+
+ if (value & RING_STATUS_RINGRECOVERY)
+ {
+ RingStatus |= NDIS_RING_RING_RECOVERY;
+ DebugPrint(1,("NF(%d): RING_STATUS_RINGRECOVERY\n",acb->anum));
+ }
+
+ //
+ // Save the Ring Status
+ //
+ acb->acb_lastringstatus = RingStatus;
+
+
+ //
+ // Indicate to the filter the ring status.
+ //
+ NdisMIndicateStatus(
+ acb->acb_handle,
+ NDIS_STATUS_RING_STATUS,
+ &RingStatus,
+ sizeof(ULONG)
+ );
+
+ //
+ // Tell the filter that we have completed the ring status.
+ //
+ NdisMIndicateStatusComplete(acb->acb_handle);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexCommand
+//
+// Description:
+// This routine looks at the current SSB struct
+// and places the corresponding request on the
+// Request Confirm Queue. If the command that
+// has completed is an open, a receive and
+// transmit command are issued.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexHandleInterrupt
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexCommand(
+ PACB acb
+ )
+{
+ PSCBREQ scbreq;
+ PMACREQ macreq;
+ PTR_OBJS trobjs;
+ PETH_OBJS ethobjs;
+ SHORT value,i;
+ PUSHORT tempptr;
+ NDIS_STATUS Status;
+
+#if (DBG || DBGPRINT)
+ //
+ // I wanted to know if I'm getting bad commands
+ //
+ if (acb->acb_ssb_virtptr->SSB_Cmd == TMS_CMDREJECT)
+ {
+ DebugPrint(0,("NF(%d): Command rejected\n",acb->anum));
+ DebugPrint(0,("NF(%d): SSB Status %x\n",acb->anum,SWAPS(acb->acb_ssb_virtptr->SSB_Status)));
+ DebugPrint(0,("NF(%d): SSB Ptr %x\n",acb->anum,SWAPL(acb->acb_ssb_virtptr->SSB_Ptr)));
+ }
+ else if (acb->acb_ssb_virtptr->SSB_Status != SSB_GOOD)
+ {
+ DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status));
+ DebugPrint(0,("NF(%d): cmd is %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Cmd));
+ }
+#endif
+
+ //
+ // Get the scb request associated with the completed request.
+ //
+ Status = NetFlexDequeue_TwoPtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_head),
+ (PVOID *)&(acb->acb_scbreq_tail),
+ (PVOID *)&scbreq
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d) NetFlexCommand - dequeue scbreq failed!\n",acb->anum));
+ return;
+ }
+
+ //
+ // If we have a Macreq to place on the confirm q. Do this now.
+ //
+ macreq = scbreq->req_macreq;
+
+ if (macreq)
+ {
+ //
+ // If the command had a problem, save the failure reason and
+ // exit out of the routine. Otherwise, save the success code
+ // and see if the completed command is an open or a read error log.
+ //
+ if (acb->acb_ssb_virtptr->SSB_Cmd == TMS_CMDREJECT)
+ {
+ DebugPrint(0,("NF(%d): Command rejected\n",acb->anum));
+ DebugPrint(0,("NF(%d): SSB Status %x\n",acb->anum,SWAPS(acb->acb_ssb_virtptr->SSB_Status)));
+ DebugPrint(0,("NF(%d): SSB Ptr %x\n",acb->anum,SWAPL(acb->acb_ssb_virtptr->SSB_Ptr)));
+ macreq->req_status = NDIS_STATUS_FAILURE;
+ }
+ else if (acb->acb_ssb_virtptr->SSB_Status != SSB_GOOD)
+ {
+ DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status));
+ DebugPrint(0,("NF(%d): cmd is %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Cmd));
+
+ if ((acb->acb_ssb_virtptr->SSB_Cmd == TMS_OPEN) &&
+ (acb->acb_ssb_virtptr->SSB_Status & SSB_OPENERR)
+ )
+ {
+ macreq->req_status = NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
+ macreq->req_info = (PVOID)(acb->acb_ssb_virtptr->SSB_Status >> 8);
+ }
+ else
+ {
+ macreq->req_status = NDIS_STATUS_FAILURE;
+ }
+ }
+ else if (acb->acb_ssb_virtptr->SSB_Cmd == TMS_READLOG)
+ {
+ acb->acb_logbuf_valid = TRUE;
+ //
+ // Fill in the appropriate fields with the information
+ // given by the log buffer.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ {
+ // TOKEN RING
+ trobjs = (PTR_OBJS)(acb->acb_spec_objs);
+ trobjs->REL_Congestion += ((PREL)(acb->acb_logbuf_virtptr))->REL_Congestion;
+ trobjs->REL_LineError += ((PREL)(acb->acb_logbuf_virtptr))->REL_LineError;
+ trobjs->REL_LostError += ((PREL)(acb->acb_logbuf_virtptr))->REL_LostError;
+ trobjs->REL_BurstError += ((PREL)(acb->acb_logbuf_virtptr))->REL_BurstError;
+ trobjs->REL_ARIFCIError += ((PREL)(acb->acb_logbuf_virtptr))->REL_ARIFCIError;
+ trobjs->REL_Congestion += ((PREL)(acb->acb_logbuf_virtptr))->REL_Congestion;
+ trobjs->REL_CopiedError += ((PREL)(acb->acb_logbuf_virtptr))->REL_CopiedError;
+ trobjs->REL_TokenError += ((PREL)(acb->acb_logbuf_virtptr))->REL_TokenError;
+ }
+ else
+ {
+ // ETHERNET
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ ethobjs->RSL_AlignmentErr = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_AlignmentErr);
+ ethobjs->RSL_1_Collision = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_1_Collision);
+ ethobjs->RSL_FrameCheckSeq = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_FrameCheckSeq);
+ ethobjs->RSL_DeferredXmit = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_DeferredXmit);
+ ethobjs->RSL_LateCollision = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_LateCollision);
+ ethobjs->RSL_Excessive = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_Excessive);
+ ethobjs->RSL_CarrierErr = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_CarrierErr);
+ tempptr = (PUSHORT)&(((PRSL)(acb->acb_logbuf_virtptr))->RSL_2_Collision);
+ value = 0;
+ for (i = 0; i < 14; i++)
+ {
+ value += SWAPS( *(tempptr+i) );
+ }
+ ethobjs->RSL_More_Collision = value;
+ }
+ }
+
+ //
+ // Take the Mac request off the macreq queue and place it on
+ // the confirm queue so that the command can be completed.
+ //
+ NetFlexDequeue_TwoPtrQ(
+ (PVOID *)&(acb->acb_macreq_head),
+ (PVOID *)&(acb->acb_macreq_tail),
+ (PVOID)macreq
+ );
+
+ NetFlexEnqueue_TwoPtrQ_Tail(
+ (PVOID *)&(acb->acb_confirm_qhead),
+ (PVOID *)&(acb->acb_confirm_qtail),
+ (PVOID)macreq
+ );
+ } // if (macreq)
+
+ //
+ // Free up the SCB request associated with this command.
+ //
+ scbreq->req_macreq = NULL;
+
+ NetFlexEnqueue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID)scbreq
+ );
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexEnableInterrupt
+//
+// Description:
+// This routine is used to enable the adapter to
+// interrupt the system.
+//
+// Input:
+// Context - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexEnableInterrupt(
+ IN NDIS_HANDLE Context
+ )
+{
+ USHORT actl_reg;
+ PACB acb = (PACB) Context;
+
+ DebugPrint(3,("NF(%d)(E)\n",acb->anum));
+ //
+ // Enable System Interrupts
+ //
+ actl_reg = acb->actl_reg | ACTL_SINTEN;
+
+ NdisRawWritePortUshort(acb->SifActlPort, actl_reg);
+
+ acb->InterruptsDisabled = FALSE;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDisableInterrupt
+//
+// Description:
+// This routine is used to disable the adapter from being
+// able to interrupt the system.
+//
+// Input:
+// Context - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDisableInterrupt(
+ IN NDIS_HANDLE Context
+ )
+{
+ USHORT actl_reg;
+ PACB acb = (PACB) Context;
+
+ //
+ // Disable System Interrupts
+ //
+ actl_reg = acb->actl_reg & ~ACTL_SINTEN;
+
+ NdisRawWritePortUshort(acb->SifActlPort, actl_reg);
+
+ acb->InterruptsDisabled = TRUE;
+
+ DebugPrint(3,("NF(%d)(D)\n",acb->anum));
+}
diff --git a/private/ntos/ndis/netflex/macstrct.h b/private/ntos/ndis/netflex/macstrct.h
new file mode 100644
index 000000000..e6d9184d1
--- /dev/null
+++ b/private/ntos/ndis/netflex/macstrct.h
@@ -0,0 +1,581 @@
+//************************************************************************
+//************************************************************************
+//
+// File Name: MACSTRCT.H
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//***********************************************************************
+//***********************************************************************
+
+#ifndef _MACSTRCT_
+#define _MACSTRCT_
+
+#if DBG
+#define BreakPoint() DbgBreakPoint()
+#endif
+
+typedef
+USHORT
+(FASTCALL *W_PROCESS_RECEIVE_HANDLER) (
+ struct acb_block *acb
+ );
+
+typedef struct netflx_parameters {
+ OPEN utd_open;
+ USHORT utd_maxtrans;
+ USHORT utd_maxrcvs;
+ USHORT utd_maxframesz;
+ USHORT utd_maxmulticast;
+ USHORT utd_maxinternalreqs;
+ USHORT utd_maxinternalbufs;
+ USHORT utd_numsmallbufs;
+ USHORT utd_smallbufsz;
+ BOOLEAN utd_extremecheckforhang;
+} NETFLEX_PARMS, *PNETFLEX_PARMS;
+
+/* Netflx parms defaults */
+
+#define MIN_MULTICASTS 10
+#define MAX_MULTICASTS 40
+#define DF_MULTICASTS 20
+
+#define MIN_INTERNALREQS 10
+#define MAX_INTERNALREQS 80
+#define DF_INTERNALREQS 40
+
+#define MIN_INTERNALBUFS 2 /* Transmit buffers */
+#define MAX_INTERNALBUFS 8
+#define DF_INTERNALBUFS 8
+
+//
+// Number of xmit packets
+// Number of lists is this number * MAX_LISTS_PER_XMIT
+//
+#define MAX_XMITS_TR 10
+#define MIN_XMITS 3
+#define DF_XMITS_TR 8
+
+//
+// Number of rcv packets.
+// Because a packet requires only one list, this is the number of Receive
+// list as well.
+//
+
+#define MAX_RCVS_ETH 40
+#define MAX_RCVS_TR 20
+#define MIN_RCVS 3
+#define DF_RCVS_ETH 20
+#define DF_RCVS_TR 10
+
+#define MAX_XMITS_ETH 20
+#define DF_XMITS_ETH 16
+
+#define MAX_FRAMESIZE_ETH 1514
+#define DF_FRAMESIZE_ETH 1514
+#define MAX_FRAMESIZE_TR4 4096
+#define MAX_FRAMESIZE_TR16 17952
+#define DF_FRAMESIZE_TR 4500 // Was 4096.
+#define MIN_FRAMESIZE 256
+
+//
+// Additional Statistics supported by Netflex but not by MS
+//
+
+#define OID_802_5_UPSTREAM_ADDRESS 0xff020201
+#define OID_802_5_CONGESTION_ERRORS 0xff020202
+#define OID_NF_INTERRUPT_COUNT 0xff020203
+#define OID_NF_INTERRUPT_RATIO 0xff020204
+#define OID_NF_INTERRUPT_RATIO_CHANGES 0xff020205
+
+/*----------------------------------------------------------------------*/
+/* Structure Name: Netflx Global MAC structure (MAC) */
+/* */
+/* Description: The adapter binding block contain the internal variables*/
+/* for the binding between a protocol and an adpater. */
+/*----------------------------------------------------------------------*/
+typedef struct mac
+{
+ struct acb_block *mac_adapters;/* Ptr to registered adapters */
+ PDRIVER_OBJECT mac_object; /* Value passed by DriverEntry */
+ NDIS_HANDLE mac_wrapper; /* global handle to miniport wrapper*/
+ USHORT mac_numadpts; /* number of adpaters on list */
+ PVOID DownloadCode; /* Virtual address of Download code */
+ USHORT DownloadLength; /* length of download image */
+ BOOLEAN Initializing; /* is the system still in intitialization mode */
+} MAC, *PMAC;
+
+/*----------------------------------------------------------------------*/
+/* Structure Name: Multicast Table */
+/* */
+/* Description: The multicast table contains a list of the enabled */
+/* multicast or group address on the adapter. */
+/*----------------------------------------------------------------------*/
+
+typedef struct multi_table {
+ struct multi_table *mt_next;
+ UCHAR mt_addr[NET_ADDR_SIZE]; /* Multicast address */
+} MULTI_TABLE, *PMULTI_TABLE;
+
+/*----------------------------------------------------------------------*/
+/* Structure Name: Mac Request Block */
+/* */
+/* Description: The mac request block contains the variables necessary */
+/* to complete a pending command. */
+/*----------------------------------------------------------------------*/
+typedef struct macreq_blk
+{
+ struct macreq_blk *req_next; /* Pointer to the next request */
+ ULONG req_type; /* Type of request and completion */
+ NDIS_STATUS req_status; /* Status of command */
+ PVOID req_info; /* Extra info needed to complete the req */
+ BOOLEAN req_timeout; /* This field is used to timestamp the command blocks */
+ UCHAR req_timeoutcount; /* Count of the number of times we have retried a command. */
+} MACREQ, *PMACREQ;
+
+#define MACREQSIZE sizeof(MACREQ)
+
+#define NO_CMP_NEEDED 0
+#define OPENADAPTER_CMP 1
+#define OPENADAPTER_DUMCMP 2
+#define CLOSEADAPTER_CMP 3
+#define CLOSEADAPTER_DUMCMP 4
+#define SEND_CMP 5
+#define TRANSFERDATA_CMP 6
+#define RESET_CMP 7
+#define REQUEST_CMP 8
+#define INDICATERCV_CMP 9
+#define INDICATESTATUS_CMP 10
+#define QUERY_CMP 11
+
+#define RESET_STAGE_1 1
+#define RESET_STAGE_2 2
+#define RESET_STAGE_3 3
+#define RESET_STAGE_4 4
+#define RESET_HALTED 5
+/*----------------------------------------------------------------------*/
+/* Structure Name: SCB Request Block */
+/* */
+/* Description: The SCB Request block contains the variables necessary */
+/* to send a command to the adapter, wait for the response */
+/* and find the mac request block in order to complete the */
+/* request if necessary. */
+/*----------------------------------------------------------------------*/
+typedef struct scbreq_blk
+{
+ struct scbreq_blk *req_next; /* Pointer to the next request */
+ SCB req_scb; /* Copy of the SCB to send */
+ MULTI_BLOCK req_multi;
+ PMACREQ req_macreq; /* Ptr to the corresponding macreq */
+} SCBREQ, *PSCBREQ;
+
+#define SCBREQSIZE sizeof(SCBREQ)
+
+
+
+/*----------------------------------------------------------------------*/
+/* Structure Name: General Objects structure */
+/* */
+/* Description: The General Objects strucuture contains the variables */
+/* necessary to hold the gerneral operational */
+/* characteristics and statistics. */
+/*----------------------------------------------------------------------*/
+typedef struct general_objs
+{
+ NDIS_MEDIUM media_type_in_use;
+ ULONG max_frame_size;
+ ULONG min_frame_size;
+ ULONG link_speed;
+ ULONG cur_filter;
+ ULONG frames_xmitd_ok;
+ ULONG frames_rcvd_ok;
+ ULONG frames_xmitd_err;
+ ULONG frames_rcvd_err;
+ ULONG interrupt_count;
+ ULONG interrupt_ratio_changes;
+ UCHAR perm_staddr[NET_ADDR_SIZE];
+ UCHAR current_staddr[NET_ADDR_SIZE];
+} GENERAL_OBJS, *PGENERAL_OBJS;
+
+typedef struct eth_objs
+{
+ USHORT MaxMulticast;
+ UCHAR *MulticastEntries;
+ USHORT NumberOfEntries;
+ USHORT RSL_AlignmentErr;
+ USHORT RSL_1_Collision;
+ USHORT RSL_More_Collision;
+ USHORT RSL_FrameCheckSeq;
+ USHORT RSL_DeferredXmit;
+ USHORT RSL_Excessive;
+ USHORT RSL_LateCollision;
+ USHORT RSL_CarrierErr;
+} ETH_OBJS, *PETH_OBJS;
+
+typedef struct tr_objs
+{
+ UCHAR cur_func_addr[NET_GROUP_SIZE];
+ UCHAR cur_grp_addr[NET_GROUP_SIZE];
+ UCHAR upstream_addr[NET_GROUP_SIZE];
+ USHORT grp_users_count;
+ ULONG frames_xmtd_no_return;
+ UCHAR REL_LineError;
+ UCHAR REL_Congestion;
+ UCHAR REL_LostError;
+ UCHAR REL_BurstError;
+ UCHAR REL_ARIFCIError;
+ UCHAR REL_CopiedError;
+ UCHAR REL_TokenError;
+} TR_OBJS, *PTR_OBJS;
+
+/*----------------------------------------------------------------------*/
+/* Structure Name: MAC Internal Adapter Control Block (ACB) */
+/* */
+/* Description: The Mac internal adapter control block contains all */
+/* internal variables for ONE SINGLE adapter. The Global */
+/* variables structure for this driver contains a pointer */
+/* to a linked list of ACBs. (One ACB for each adapter */
+/* registered by this driver). The variables in the ACB */
+/* are used by the NDI driver to maintain internal */
+/* statistics, driver states, and resources. */
+/*----------------------------------------------------------------------*/
+typedef struct acb_block {
+ struct acb_block *acb_next; /* Next ACB */
+ NDIS_HANDLE acb_handle; /* Our Miniport Handle */
+
+ USHORT actl_reg; // Saved value of our ACTL_REG
+ USHORT InterruptsDisabled;
+
+ PUCHAR SifIntPort; // SIF interrupt register
+ PUCHAR SifActlPort; // SIF ACTL register
+ PRCV acb_rcv_head; /* Head of our Receive Lists */
+
+#ifdef ODD_POINTER
+ BOOLEAN XmitStalled; /* state of the transmiter */
+#endif
+
+ NDIS_SPIN_LOCK XmitLock;
+ PXMIT acb_xmit_head; /* */
+ PXMIT acb_xmit_ahead; /* */
+ PXMIT acb_xmit_atail; /* */
+
+ USHORT acb_maxrcvs;
+ USHORT acb_avail_xmit;
+
+ USHORT acb_curmap;
+ USHORT acb_maxmaps;
+
+ W_PROCESS_RECEIVE_HANDLER ProcessReceiveHandler;
+
+ PSCB acb_scb_virtptr; /* Virt ptr to the SCB */
+ PSSB acb_ssb_virtptr; /* Virt ptr to the SSB */
+
+ USHORT RcvIntRatio;
+
+#ifdef XMIT_INTS
+ USHORT XmitIntRatio;
+#endif
+
+#ifdef ODD_POINTER
+ BOOLEAN XmitStalled; /* state of the transmiter */
+ BOOLEAN HandlingInterrupt;
+#endif
+
+ PBUFFER_DESCRIPTOR OurBuffersListHead;
+ PBUFFER_DESCRIPTOR SmallBuffersListHead;
+
+ //
+ // Dynamic ratio stuff
+ //
+ UINT timer_run_count;
+ UINT handled_interrupts;
+#ifdef NEW_DYNAMIC_RATIO
+ union {
+ struct {
+ USHORT current_run_up;
+ USHORT current_run_down;
+ } ;
+ ULONG current_run_both;
+ } ;
+#else
+ UINT current_run;
+#endif
+
+ //
+ // Dynamic ratio
+ //
+
+#ifdef DYNAMIC_RATIO_HISTORY
+ UCHAR IntHistory[1024];
+ UCHAR RatioHistory[1024];
+ UINT Hndx;
+#endif
+
+#ifndef NEW_DYNAMIC_RATIO
+ UINT cleartime;
+ UINT sw24;
+#endif
+
+ GENERAL_OBJS acb_gen_objs; // General chars and stats
+
+ NDIS_MINIPORT_TIMER DpcTimer;
+
+ NDIS_MINIPORT_INTERRUPT acb_interrupt;
+
+ PNDIS_HANDLE FlushBufferPoolHandle; // The Flush buffer pool
+
+ USHORT acb_scbclearout;
+ USHORT acb_maxtrans;
+ USHORT acb_smallbufsz;
+ USHORT acb_padJim;
+ USHORT acb_maxreqs;
+ USHORT acb_openoptions;
+ NDIS_STATUS acb_lastopenstat;
+ ULONG acb_lastringstate;
+ ULONG acb_lastringstatus;
+
+ NDIS_PHYSICAL_ADDRESS acb_rcv_physptr;
+ PRCV acb_rcv_virtptr;
+
+ NDIS_PHYSICAL_ADDRESS acb_xmit_physptr; /* Ptr to Xmit memory */
+ PXMIT acb_xmit_virtptr;
+
+
+ PMULTI_BLOCK acb_multiblk_virtptr; /* Virt ptr to Multicast blk */
+ NDIS_PHYSICAL_ADDRESS acb_multiblk_physptr; /* Phys ptr to Multicast blk */
+ USHORT acb_multi_index; /* index to Multicast blks */
+
+ PRCV acb_rcv_tail; /* Tail, has the odd fwdptr */
+ PRCV acb_rcv_whead; /* */
+ PXMIT acb_xmit_whead; /* */
+ PXMIT acb_xmit_wtail; /* */
+ PXMIT acb_xmit_chead; /* */
+ PXMIT acb_xmit_ctail; /* */
+
+ USHORT acb_state; /* Adapter Primary State */
+ ULONG acb_int_timeout; // Interrupt timeout.
+ ULONG acb_int_count; // Count of interrupts.
+
+ //
+ // Various mapped I/O Port Addresses for this adapter.
+ //
+ PUCHAR SifDataPort; // SIF data register
+ PUCHAR SifDIncPort; // SIF data autoincrment reg
+ PUCHAR SifAddrPort; // SIF address register
+ PUCHAR SifAddrxPort; // SIF SIF extended address reg
+
+ PUCHAR BasePorts;
+ PUCHAR MasterBasePorts;
+ PUCHAR ConfigPorts;
+ PUCHAR ExtConfigPorts;
+
+ PUCHAR AdapterConfigPort; // Adapter configuration reg
+
+ PVOID acb_xmitbuf_virtptr; /* Virt ptr to our xmit bufs */
+ NDIS_PHYSICAL_ADDRESS acb_xmitbuf_physptr; /* Phys ptr to our xmit bufs */
+
+ PVOID OurBuffersVirtPtr; /* Virt ptr to our internal bufs */
+
+ PVOID SmallBuffersVirtPtr; /* Virt ptr to our internal bufs */
+ NDIS_PHYSICAL_ADDRESS acb_scb_physptr; /* Phys ptr to the SCB */
+ NDIS_PHYSICAL_ADDRESS acb_ssb_physptr; /* Phys ptr to the SSB */
+
+ USHORT acb_logbuf_valid; /* Validity of the log contents */
+ PVOID acb_logbuf_virtptr; /* Virt ptr to READ ERROR LOG */
+ NDIS_PHYSICAL_ADDRESS acb_logbuf_physptr; /* Phys ptr to READ ERROR LOG */
+
+ POPEN acb_opnblk_virtptr; /* Virt ptr to OPEN block */
+ NDIS_PHYSICAL_ADDRESS acb_opnblk_physptr; /* Phys ptr to OPEN block */
+
+ INIT acb_initblk; /* Virt ptr to INIT block */
+
+ PSCBREQ acb_scbreq_ptr; /* Ptr to SCB Request memory */
+ PSCBREQ acb_scbreq_head; /* Ptr to next SCB */
+ PSCBREQ acb_scbreq_tail; /* Ptr to last SCB */
+ PSCBREQ acb_scbreq_free; /* Ptr to free SCB Requests */
+ PSCBREQ acb_scbreq_next; /* Ptr to next SCB to execute */
+
+ PMACREQ acb_macreq_ptr; /* Ptr to MAC Request memory */
+ PMACREQ acb_macreq_head; /* Ptr to front of pending reqs */
+ PMACREQ acb_macreq_tail; /* Ptr to end of pending reqs */
+ PMACREQ acb_macreq_free; /* Ptr to free MAC Requests */
+ PMACREQ acb_confirm_qhead; /* Ptr to pending MAC Reqs to complete */
+ PMACREQ acb_confirm_qtail; /* Ptr to pending MAC Reqs to complete */
+
+
+ PNDIS_OID acb_gbl_oid_list;
+ PNDIS_OID acb_spec_oid_list;
+ SHORT acb_gbl_oid_list_size;
+ SHORT acb_spec_oid_list_size;
+ PVOID acb_spec_objs; /* Network specific chars and stats */
+
+
+ USHORT acb_promiscuousmode; /* Board accepts all pkts */
+ USHORT acb_boardid; /* Board id */
+ USHORT acb_baseaddr; /* Base address of board */
+ PNETFLEX_PARMS acb_parms; /* Pointer to adp's param's */
+
+ USHORT acb_usefpa; /* are using fast pkt accel */
+ USHORT acb_dualport; /* is this a dual port card */
+ USHORT acb_portnumber; /* which head of dual card */
+
+ struct acb_block *FirstHeadsAcb; /* Pointer to first Head's ACB */
+
+ USHORT acb_upstreamaddrptr; /* buffer for read adapter */
+ USHORT acb_maxinternalbufs; /* maximum internal xmit bufs */
+
+ USHORT acb_numsmallbufs; /* maximum small xmit bufs */
+ BOOLEAN RequestInProgress; // Is there an outstanding request
+ BOOLEAN AdapterInitializing; // Are we initialing?
+
+
+ //
+ // These variables hold information about a pending request.
+ //
+
+ PUINT BytesWritten;
+ PUINT BytesRead;
+ PUINT BytesNeeded;
+ NDIS_OID Oid;
+ PVOID InformationBuffer;
+ UINT InformationBufferLength;
+
+ BOOLEAN InterruptsShared;
+ BOOLEAN FullDuplexEnabled;
+ BOOLEAN SmallBuffersAreContiguous;
+ BOOLEAN MergeBuffersAreContiguous;
+ BOOLEAN RecvBuffersAreContiguous;
+
+ BOOLEAN nfpad1;
+ USHORT nfpad2;
+
+ //
+ // Stuff Needed for a reset.
+ //
+ NDIS_MINIPORT_TIMER ResetTimer;
+ USHORT ResetState;
+ USHORT ResetRetries;
+ USHORT InitRetries;
+ BOOLEAN SentRingStatusLog;
+ BOOLEAN ResetErrorLogged;
+
+ //
+ // Memory pools.
+ //
+
+ PVOID ReceiveBufferPoolVirt;
+ NDIS_PHYSICAL_ADDRESS ReceiveBufferPoolPhys;
+
+ PVOID MergeBufferPoolVirt;
+ NDIS_PHYSICAL_ADDRESS MergeBufferPoolPhys;
+
+ PVOID SmallBufferPoolVirt;
+ NDIS_PHYSICAL_ADDRESS SmallBufferPoolPhys;
+#if (DBG || DBGPRINT)
+ USHORT anum;
+ USHORT max_int_buffs_used;
+ USHORT num_int_buffs_used;
+ ULONG XmitSent;
+ ULONG LastXmitSent;
+#endif
+
+} ACB, *PACB;
+
+/*----------------------------------------------------------------------*/
+/* Structure Name: ACB Adpter States (AS) */
+/* */
+/* Description: These equates define the primary states that an */
+/* adapter may take on. */
+/*----------------------------------------------------------------------*/
+#define AS_NOTINSTALLED 0 // Adapter not installed
+#define AS_REGISTERING 1 // Adapter is registering
+#define AS_REGISTERED 2 // Adapter has been
+ // registered - but not initialized
+#define AS_INITIALIZING 3 // Adapter is initializing
+#define AS_INITIALIZED 4 // Adapter initialized
+#define AS_OPENING 5 // Adapter is opening
+#define AS_OPENED 6 // Adapter opened
+#define AS_CLOSING 7 // Adapter is closing
+#define AS_RESET_HOLDING 8 // Adapter reset
+#define AS_RESETTING 9 // Adapter is resetting
+#define AS_UNLOADING 10
+#define AS_REMOVING 11
+
+#define AS_HARDERROR 100 // Adapter suffered hardware error
+#define AS_CARDERROR 101 // Adapter reset error
+#define AS_INITERROR 102 // Adapter initialization error
+#define AS_INSTALLED 103 // Adapter installed (not reset)
+#define AS_IRQERROR 104 // Adapter IRQ error
+#define AS_DMAERROR 105 // Adapter DMA error
+#define AS_DOWNFILERR 106 // Adapter download no file error
+#define AS_DOWNMEMERR 107 // Adapter download no mem error
+#define AS_MEDIAERROR 108 // Adapter media error
+#define AS_SPEEDERROR 109 // Adapter ring speed error
+
+
+typedef struct netflx_reqrsvd {
+ PNDIS_REQUEST rsvd_nextreq;
+ USHORT rsvd_req_type;
+} NETFLEX_REQRSVD, *PNETFLEX_REQRSVD;
+
+typedef struct netflx_sendpkt_reqrsvd {
+ PNDIS_PACKET next;
+} NETFLEX_SENDPKT_RESERVED, *PNETFLEX_SENDPKT_RESERVED;
+
+#define RESERVED_FROM_PACKET(Packet)\
+ ((PNETFLEX_SENDPKT_RESERVED)((Packet)->MiniportReserved))
+
+typedef struct netflx_entry {
+ PVOID next;
+} NETFLEX_ENTRY, *PNETFLEX_ENTRY;
+
+
+//------------------
+// Definitions
+//------------------
+
+
+#define NETFLEX_MAJ_VER 4
+#define NETFLEX_MIN_VER 0
+
+//-------------------------------------
+// External Data Variable References
+//-------------------------------------
+
+extern MAC macgbls;
+extern USHORT gbl_addingdualport;
+extern USHORT gbl_portnumbertoadd;
+extern NDIS_HANDLE gbl_confighandle;
+
+extern NDIS_OID NetFlexGlobalOIDs_Eth[];
+extern NDIS_OID NetFlexNetworkOIDs_Eth[];
+extern NDIS_OID NetFlexGlobalOIDs_Tr[];
+extern NDIS_OID NetFlexNetworkOIDs_Tr[];
+extern SHORT NetFlexGlobalOIDs_Eth_size;
+extern SHORT NetFlexNetworkOIDs_Eth_size;
+extern SHORT NetFlexGlobalOIDs_Tr_size;
+extern SHORT NetFlexNetworkOIDs_Tr_size;
+
+extern OPEN open_mask;
+extern INIT init_mask;
+
+extern NDIS_PHYSICAL_ADDRESS NetFlexHighestAddress;
+extern NETFLEX_PARMS NetFlex_Defaults;
+
+#endif
+
diff --git a/private/ntos/ndis/netflex/makefile b/private/ntos/ndis/netflex/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/netflex/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/netflex/makefile.inc b/private/ntos/ndis/netflex/makefile.inc
new file mode 100644
index 000000000..e2934cb73
--- /dev/null
+++ b/private/ntos/ndis/netflex/makefile.inc
@@ -0,0 +1,5 @@
+netflx.bin: $(TARGETEXEFILES)
+ chmode -r netflx.bin
+ binplace netflx.bin
+ touch netflx.bin
+ chmode +r netflx.bin
diff --git a/private/ntos/ndis/netflex/netflex.rc b/private/ntos/ndis/netflex/netflex.rc
new file mode 100644
index 000000000..8282cdf15
--- /dev/null
+++ b/private/ntos/ndis/netflex/netflex.rc
@@ -0,0 +1,40 @@
+#include <windows.h>
+#include <ntverp.h>
+
+/*-----------------------------------------------*/
+/* the following lines are specific to this file */
+/*-----------------------------------------------*/
+
+/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
+ * and VER_INTERNALNAME_STR must be defined before including COMMON.VER
+ * The strings don't need a '\0', since common.ver has them.
+ */
+#define VER_FILETYPE VFT_DRV
+/* possible values: VFT_UNKNOWN
+ VFT_APP
+ VFT_DLL
+ VFT_DRV
+ VFT_FONT
+ VFT_VXD
+ VFT_STATIC_LIB
+*/
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+/* possible values VFT2_UNKNOWN
+ VFT2_DRV_PRINTER
+ VFT2_DRV_KEYBOARD
+ VFT2_DRV_LANGUAGE
+ VFT2_DRV_DISPLAY
+ VFT2_DRV_MOUSE
+ VFT2_DRV_NETWORK
+ VFT2_DRV_SYSTEM
+ VFT2_DRV_INSTALLABLE
+ VFT2_DRV_SOUND
+ VFT2_DRV_COMM
+*/
+#define VER_FILEDESCRIPTION_STR "Compaq NetFlex network driver"
+#define VER_INTERNALNAME_STR "NETFLX.SYS"
+#define VER_ORIGINALFILENAME_STR "NETFLX.SYS"
+
+#include "cpqntssd.ver"
+
+#include "common.ver"
diff --git a/private/ntos/ndis/netflex/netflx.bin b/private/ntos/ndis/netflex/netflx.bin
new file mode 100644
index 000000000..50d5106e5
--- /dev/null
+++ b/private/ntos/ndis/netflex/netflx.bin
Binary files differ
diff --git a/private/ntos/ndis/netflex/netflx.prf b/private/ntos/ndis/netflex/netflx.prf
new file mode 100644
index 000000000..8ad30ddbb
--- /dev/null
+++ b/private/ntos/ndis/netflex/netflx.prf
@@ -0,0 +1,27 @@
+NetFlexDisableInterrupt@4
+NetFlexHandleInterrupt@4
+NetFlexSend@12
+@NetFlexProcessXmit@4
+@NetFlexProcessEthRcv@4
+NetFlexDeferredTimer@16
+NetFlexEnableInterrupt@4
+NetFlexConstrainPacket@24
+NetFlexCheckForHang@4
+NetFlexTransferData@24
+NetFlexInitialize@24
+NetFlexSetupNetType@4
+NetFlexAdapterReset@8
+NetFlexSetInformation@24
+NetFlexQueryInformation@24
+NetFlexDownload@4
+NetFlexOpenAdapter@4
+NetFlexBudWait@4
+NetFlexInitializeAdapter@4
+NetFlexSendNextSCB@4
+NetFlexBoardInitandReg@8
+DriverEntry@8
+NetFlexInitializeAcb@4
+NetFlexInitGlobals@0
+NetFlexGetBIA@4
+NetFlexReadConfigurationParameters@8
+NetFlexRegisterAdapter@20
diff --git a/private/ntos/ndis/netflex/protos.h b/private/ntos/ndis/netflex/protos.h
new file mode 100644
index 000000000..47204461d
--- /dev/null
+++ b/private/ntos/ndis/netflex/protos.h
@@ -0,0 +1,450 @@
+//************************************************************************
+//************************************************************************
+//
+// File Name: PROTOS.H
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: All
+//
+// Function: This module contains the NetFlex Miniport Driver
+// routine prototypes references.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//***********************************************************************
+//***********************************************************************
+
+
+#ifndef _PROTOS_
+#define _PROTOS_
+
+
+NDIS_STATUS
+NetFlexBoardTest(
+ PACB acb,
+ NDIS_HANDLE NdisAdapterHandle
+ );
+
+NDIS_STATUS
+NetFlexBoardInitandReg(
+ PACB acb,
+ PNDIS_EISA_FUNCTION_INFORMATION EisaData
+ );
+
+
+VOID
+NetFlexSetupNetType(
+ PACB acb
+ );
+
+VOID
+NetFlexGetBIA(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexDownload(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexReadConfigurationParameters(
+ PACB acb,
+ NDIS_HANDLE ConfigHandle
+ );
+
+VOID
+NetFlexGetUpstreamAddrPtr(
+ PACB acb
+ );
+
+//++
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+BOOLEAN
+NetFlexCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+VOID
+NetFlexISR(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN PVOID Context
+ );
+
+VOID
+NetFlexHandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+VOID
+NetFlexDeferredTimer(
+ IN PVOID SystemSpecific1,
+ IN PACB acb,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+VOID
+NetFlexEnableInterrupt(
+ IN NDIS_HANDLE Context
+ );
+
+VOID
+NetFlexDisableInterrupt(
+ IN NDIS_HANDLE Context
+ );
+
+VOID
+NetFlexHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+VOID
+NetFlexShutdown(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+NDIS_STATUS
+NetFlexInitialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE ConfigurationHandle
+ );
+
+NDIS_STATUS
+NetFlexSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+ );
+
+NDIS_STATUS
+NetFlexQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ );
+
+VOID
+NetFlexFinishQueryInformation(
+ PACB acb,
+ NDIS_STATUS Status
+ );
+
+NDIS_STATUS
+NetFlexResetDispatch(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+VOID
+NetFlexResetHandler(
+ IN PVOID SystemSpecific1,
+ IN PACB acb,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+NDIS_STATUS NetFlexSend(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET Packet,
+ IN UINT Flags
+ );
+
+NDIS_STATUS NetFlexTransferData(
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE MiniportReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ );
+
+NDIS_STATUS
+NetFlexRegisterAdapter(
+ PACB *acbp,
+ PACB FirstHeadsAcb,
+ NDIS_HANDLE ConfigurationHandle,
+ USHORT baseaddr,
+ NDIS_HANDLE MiniportAdapterHandle
+ );
+
+NDIS_STATUS
+NetFlexInitializeAcb(
+ PACB acb
+ );
+VOID
+NetFlexDeallocateAcb(
+ PACB acb);
+
+
+VOID
+NetFlexSendNextSCB(
+ PACB acb
+ );
+
+VOID
+NetFlexRemoveRequests(
+ PACB acb
+ );
+
+VOID
+NetFlexDoResetIndications(
+ IN PACB acb,
+ IN NDIS_STATUS Status
+ );
+
+VOID
+NetFlexQueueSCB(
+ PACB acb,
+ PSCBREQ scbreq
+ );
+
+NDIS_STATUS
+NetFlexAdapterReset(
+ PACB acb,
+ INT mode
+ );
+
+NDIS_STATUS
+NetFlexBudWait(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexInitializeAdapter(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexProcessRequest(
+ PACB acb
+ );
+
+VOID
+NetFlexFinishUnloading(
+ VOID
+ );
+
+VOID
+NetFlexDeregisterAdapter(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexAsciiToHex(
+ PNDIS_STRING src,
+ PUCHAR dst,
+ USHORT dst_length
+ );
+
+VOID
+FASTCALL
+NetFlexProcessXmit(
+ PACB acb
+ );
+
+USHORT
+FASTCALL
+NetFlexProcessTrRcv(
+ PACB acb
+ );
+
+USHORT
+FASTCALL
+NetFlexProcessEthRcv(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexProcessSendQueue(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexProcessSend(
+ PACB acb,
+ PNDIS_PACKET Packet,
+ UINT PhysicalBufferCount,
+ UINT BufferCount,
+ PNDIS_BUFFER curbuf,
+ UINT TotalPacketLength
+ );
+
+VOID
+NetFlexGetUpstreamAddress(
+ PACB acb
+ );
+
+VOID
+NetFlexRingStatus(
+ PACB acb
+ );
+
+VOID
+NetFlexCommand(
+ PACB acb
+ );
+
+VOID
+NetFlexTransmitStatus(
+ PACB acb
+ );
+
+BOOLEAN
+NetFlexReset_Test(
+ PACB acb,
+ PMACREQ *resetreq
+ );
+
+VOID
+NetFlexProcessMacReq(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexValidateMulticasts(
+ PUCHAR multiaddrs,
+ USHORT multinumber
+ );
+
+NDIS_STATUS
+NetFlexOpenAdapter(
+ PACB acb
+ );
+
+
+BOOLEAN
+NetFlexCloseAdapter(
+ PACB acb
+ );
+
+NDIS_STATUS
+NetFlexInitGlobals(
+ );
+
+NDIS_STATUS
+NetFlexConstrainPacket(
+ PACB acb,
+ PXMIT xmitptr,
+ PNDIS_PACKET Packet,
+ UINT PhysicalBufferCount,
+ PNDIS_BUFFER curbuf,
+ UINT TotalPacketLength
+ );
+
+BOOLEAN
+NetFlexFindEntry(
+ PVOID head,
+ PVOID *back,
+ PVOID entry
+ );
+VOID
+NetFlexDequeue_OnePtrQ(
+ PVOID *head,
+ PVOID entry
+ );
+
+VOID
+NetFlexEnqueue_OnePtrQ_Head(
+ PVOID *head,
+ PVOID entry
+ );
+
+NDIS_STATUS
+NetFlexDequeue_OnePtrQ_Head(
+ PVOID *head,
+ PVOID *entry
+ );
+
+NDIS_STATUS
+NetFlexEnqueue_TwoPtrQ_Tail(
+ PVOID *head,
+ PVOID *tail,
+ PVOID entry
+ );
+
+VOID
+NetFlexDequeue_TwoPtrQ(
+ PVOID *head,
+ PVOID *tail,
+ PVOID entry
+ );
+
+NDIS_STATUS
+NetFlexDequeue_TwoPtrQ_Head(
+ PVOID *head,
+ PVOID *tail,
+ PVOID *entry
+ );
+
+//
+// Debug macros
+//
+
+#if (DBG || DBGPRINT)
+extern ULONG DebugLevel;
+
+
+VOID
+_DebugPrint(
+ PCCHAR DebugMessage,
+ ...
+ );
+
+#define DebugPrint(level, msg) \
+ if ((ULONG) level <= DebugLevel) \
+ _DebugPrint msg
+
+extern USHORT DisplayLists;
+VOID
+_DisplayXmitList(
+ PACB acb
+ );
+
+VOID
+_DisplayRcvList(
+ PACB acb
+ );
+
+#define DisplayXmitList(_acb) \
+ if (DisplayLists) \
+ _DisplayXmitList(_acb)
+
+#define DisplayRcvList(_acb) \
+ if (DisplayLists) \
+ _DisplayRcvList(_acb)
+
+#else
+
+#define DebugPrint(level, x)
+#define DisplayXmitList(x)
+#define DisplayRcvList(x)
+#endif // DBG
+
+
+#endif
diff --git a/private/ntos/ndis/netflex/receive.c b/private/ntos/ndis/netflex/receive.c
new file mode 100644
index 000000000..1219cb033
--- /dev/null
+++ b/private/ntos/ndis/netflex/receive.c
@@ -0,0 +1,633 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: RECEIVE.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexProcessRcv
+//
+// Description: This routine looks through the receive lists
+// looking for received packets. A receive
+// indication is given for each packet received
+//
+// Input: acb - Pointer to the Adapter's acb
+//
+// Output: true if we should indicaterecievecomplete
+//
+// Calls: NdisIndicateReceive
+//
+// Called_By: NetflxHandleInterrupt
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+USHORT
+FASTCALL
+NetFlexProcessEthRcv(
+ PACB acb
+ )
+{
+ PRCV rcvptr;
+ USHORT FrameSize;
+ USHORT ReceiveCount = 0;
+ PUCHAR Temp;
+
+#if (DBG || DBGPRINT)
+ BOOLEAN IsBroadcast;
+ PUCHAR SourceAddress;
+#endif
+
+ //
+ // While there is recieves to process...
+ //
+ rcvptr = acb->acb_rcv_head;
+
+ //
+ // Ensure that our Receive Entry is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(rcvptr->RCV_Phys) & 1));
+
+ do
+ {
+ //
+ // See if the recieve is on one list...
+ //
+ if ((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) == (RCSTAT_EOF | RCSTAT_SOF))
+ {
+ // Frame is on one list.
+ //
+ FrameSize = (USHORT)(SWAPS(rcvptr->RCV_Fsize));
+ rcvptr->RCV_HeaderLen = HDR_SIZE;
+
+ //
+ // Flush the receive buffer
+ //
+ NdisFlushBuffer(rcvptr->RCV_FlushBuffer, FALSE);
+
+#if (DBG || DBGPRINT)
+ SourceAddress = (PVOID)((PUCHAR)&(rcvptr->RCV_Buf) + 2);
+ IsBroadcast = ETH_IS_BROADCAST(SourceAddress); // works for eth & tr
+ if (IsBroadcast)
+ {
+ DebugPrint(3,("NF(%d): Recieved broadcast!\n",acb->anum));
+ }
+ else if (ETH_IS_MULTICAST(SourceAddress))
+ {
+ DebugPrint(3,("NF(%d): Recieved multicast!\n",acb->anum));
+ }
+#endif
+ //
+ // For speed...
+ //
+ Temp = (PUCHAR) rcvptr->RCV_Buf;
+
+ //
+ // Check for Runt or Normal Packet
+ //
+ if (FrameSize >= HDR_SIZE)
+ {
+ // Normal Packet
+ //
+ ReceiveCount++;
+ NdisMEthIndicateReceive(acb->acb_handle,
+ (NDIS_HANDLE)(((PUCHAR) Temp) + HDR_SIZE),
+ Temp,
+ (UINT)HDR_SIZE,
+ (((PUCHAR) Temp) + HDR_SIZE),
+ (UINT)(FrameSize - HDR_SIZE),
+ (UINT)(FrameSize - HDR_SIZE));
+
+ }
+ else if (FrameSize >= NET_ADDR_SIZE)
+ {
+ ReceiveCount++;
+ // Runt Packet
+ //
+ DebugPrint(1,("NF(%d) - Got Runt! len = %d\n",acb->anum,FrameSize));
+ NdisMEthIndicateReceive(acb->acb_handle,
+ (NDIS_HANDLE)(((PUCHAR) Temp) + HDR_SIZE),
+ Temp,
+ (UINT)FrameSize,
+ NULL,
+ 0,
+ 0);
+ }
+#if DBG
+ else
+ {
+ DebugPrint(1,("NF(%d) - Rec - Packetlen = %d",acb->anum,FrameSize));
+ }
+#endif
+
+ rcvptr->RCV_CSTAT =
+ ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+ //
+ // Get next receive list
+ //
+ rcvptr = rcvptr->RCV_Next;
+ }
+ else
+ {
+ //
+ // Frame is too large. Release the frame.
+ //
+ acb->acb_gen_objs.frames_rcvd_err++;
+
+ DebugPrint(0,("Netflx: Receive Not on one list.\n"));
+
+ //
+ // Clean up the list making up this packet.
+ //
+ while (((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) != (RCSTAT_EOF | RCSTAT_SOF)) &&
+ ((rcvptr->RCV_CSTAT & RCSTAT_COMPLETE) != 0)
+ )
+ {
+ //
+ // Clean the list and set the FINT based on ratio.
+ //
+
+ rcvptr->RCV_CSTAT =
+ ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ rcvptr = rcvptr->RCV_Next;
+ }
+ }
+
+ //
+ // If we're processing too many, get out
+ //
+ if (ReceiveCount >= acb->acb_maxrcvs)
+ break;
+
+ } while (rcvptr->RCV_CSTAT & RCSTAT_COMPLETE);
+
+ //
+ // Update head pointer
+ //
+ acb->acb_rcv_head = rcvptr;
+
+ //
+ // Tell Adapter that there are more receives available
+ //
+ NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_RCVVALID);
+
+ //
+ // Update number of received frames
+ //
+ acb->acb_gen_objs.frames_rcvd_ok += ReceiveCount;
+
+ return(ReceiveCount);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexProcessTrRcv
+//
+// Description: This routine looks through the receive lists
+// looking for received packets. A receive
+// indication is given for each packet received.
+//
+// Input: acb - Pointer to the Adapter's acb
+//
+// Output: true if we should indicaterecievecomplete
+//
+// Calls: NdisIndicateReceive
+//
+// Called_By: NetflxHandleInterrupt
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+USHORT
+FASTCALL
+NetFlexProcessTrRcv(
+ PACB acb
+ )
+{
+ PRCV rcvptr;
+ USHORT FrameSize;
+ USHORT HeaderSize;
+ USHORT ReceiveCount = 0;
+ PUCHAR Temp;
+
+#if (DBG || DBGPRINT)
+ BOOLEAN IsBroadcast;
+ PUCHAR SourceAddress;
+#endif
+
+ //
+ // While there is recieves to process...
+ //
+ rcvptr = acb->acb_rcv_head;
+
+ //
+ // Ensure that our Receive Entry is on an even boundary.
+ //
+ ASSERT(!(NdisGetPhysicalAddressLow(rcvptr->RCV_Phys) & 1));
+
+ do
+ {
+ // See if the recieve is on one list...
+ //
+ if ((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) == (RCSTAT_EOF | RCSTAT_SOF))
+ {
+ // Frame is on one list.
+ //
+ FrameSize = (USHORT)(SWAPS(rcvptr->RCV_Fsize));
+
+ HeaderSize = HDR_SIZE;
+
+ //
+ // Flush the receive buffer
+ //
+ NdisFlushBuffer(rcvptr->RCV_FlushBuffer, FALSE);
+
+#if (DBG || DBGPRINT)
+ SourceAddress = (PVOID)((PUCHAR)&(rcvptr->RCV_Buf) + 2);
+
+ IsBroadcast = ETH_IS_BROADCAST(SourceAddress); // works for eth & tr
+ if (IsBroadcast)
+ {
+ DebugPrint(3,("NF(%d): Recieved broadcast!\n",acb->anum));
+ }
+ else
+ {
+ TR_IS_GROUP(SourceAddress,&IsBroadcast);
+ if (IsBroadcast)
+ {
+ DebugPrint(3,("NF(%d): Recieved TR Group!\n",acb->anum));
+ }
+ }
+
+ TR_IS_FUNCTIONAL(SourceAddress,&IsBroadcast);
+ if (IsBroadcast)
+ DebugPrint(2,("NF(%d): Recieved TR Fuctional!\n",acb->anum));
+#endif
+ //
+ // For speed...
+ //
+ Temp = (PUCHAR) rcvptr->RCV_Buf;
+
+ //
+ // Make sure we have at least the AC, FS, SRC & DST fields before
+ // looking at the source routing info.
+ //
+ if (FrameSize >= HeaderSize)
+ {
+ // Is the source routing bit is on?
+ //
+ if (Temp[8] & 0x80)
+ {
+ // Yes, figure out the size of the MAC Frame Header.
+ //
+ HeaderSize = (Temp[HDR_SIZE] & 0x1f) + HDR_SIZE;
+ rcvptr->RCV_HeaderLen = HeaderSize;
+ //
+ // Check for Runt or Normal Packet again...
+ //
+ if (FrameSize >= HeaderSize)
+ {
+ // Normal Packet
+ //
+ ReceiveCount++;
+
+ NdisMTrIndicateReceive(
+ acb->acb_handle,
+ (NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
+ Temp,
+ (UINT)HeaderSize,
+ (((PUCHAR) Temp) + HeaderSize),
+ (UINT)(FrameSize - HeaderSize),
+ (UINT)(FrameSize - HeaderSize));
+ }
+ else if (FrameSize >= NET_ADDR_SIZE)
+ {
+ // Runt Packet
+ //
+ ReceiveCount++;
+
+ DebugPrint(1,("NF(%d) - Got Runt - len = %d!\n",acb->anum,FrameSize));
+
+ NdisMTrIndicateReceive(
+ acb->acb_handle,
+ (NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
+ Temp,
+ (UINT)FrameSize,
+ NULL,
+ 0,
+ 0);
+ }
+ }
+ else
+ {
+ // No Source Routing info, but has Normal Packet Length
+ //
+ rcvptr->RCV_HeaderLen = HeaderSize;
+
+ ReceiveCount++;
+
+ NdisMTrIndicateReceive(
+ acb->acb_handle,
+ (NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
+ Temp,
+ (UINT)HeaderSize,
+ (((PUCHAR) Temp) + HeaderSize),
+ (UINT)(FrameSize - HeaderSize),
+ (UINT)(FrameSize - HeaderSize));
+ }
+ }
+ else
+ {
+ // No, Frame doesn't have AC, FC, SRC & DST.
+ // Is it bigger than net_addr_size?
+ //
+ if (FrameSize >= NET_ADDR_SIZE)
+ {
+ // Yes, so indicate Runt Packet
+ //
+ ReceiveCount++;
+
+ DebugPrint(1,("NF(%d) - Got Runt - len = %d!\n",acb->anum,FrameSize));
+
+ NdisMTrIndicateReceive(
+ acb->acb_handle,
+ (NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
+ Temp,
+ (UINT)FrameSize,
+ NULL,
+ 0,
+ 0);
+ }
+ }
+
+ rcvptr->RCV_CSTAT =
+ ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ //
+ // Get next receive list
+ //
+ rcvptr = rcvptr->RCV_Next;
+
+ }
+ else
+ {
+ // Frame is too large. Release the frame.
+ //
+ acb->acb_gen_objs.frames_rcvd_err++;
+ DebugPrint(0,("Netflx: Receive Not on one list.\n"));
+ //
+ // Clean up the list making up this packet.
+ //
+ while (((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) != (RCSTAT_EOF | RCSTAT_SOF)) &&
+ ((rcvptr->RCV_CSTAT & RCSTAT_COMPLETE) != 0))
+ {
+ // Clean the list and set the FINT based on ratio.
+ //
+ rcvptr->RCV_CSTAT =
+ ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ rcvptr = rcvptr->RCV_Next;
+ }
+ }
+
+ //
+ // If we're processing too many, get out
+ //
+ if (ReceiveCount >= acb->acb_maxrcvs)
+ break;
+
+ } while (rcvptr->RCV_CSTAT & RCSTAT_COMPLETE);
+
+ //
+ // Update head pointer
+ //
+ acb->acb_rcv_head = rcvptr;
+
+ //
+ // Tell Adapter that there are more receives available
+ //
+ NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_RCVVALID);
+
+ //
+ // Update number of recieved frames
+ //
+ acb->acb_gen_objs.frames_rcvd_ok += ReceiveCount;
+
+ return ReceiveCount;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexTransferData
+//
+// Description: This routine copies the received data into
+// a packet structure provided by the caller.
+//
+// Input:
+//
+// MiniportAdapterContext - The context value returned by the driver when the
+// adapter was initialized. In reality this is a pointer to NE3200_ADAPTER.
+//
+// MiniportReceiveContext - The context value passed by the driver on its call
+// to NdisMIndicateReceive. The driver can use this value to determine
+// which packet, on which adapter, is being received.
+//
+// ByteOffset - An unsigned integer specifying the offset within the
+// received packet at which the copy is to begin. If the entire packet
+// is to be copied, ByteOffset must be zero.
+//
+// BytesToTransfer - An unsigned integer specifying the number of bytes
+// to copy. It is legal to transfer zero bytes; this has no effect. If
+// the sum of ByteOffset and BytesToTransfer is greater than the size
+// of the received packet, then the remainder of the packet (starting from
+// ByteOffset) is transferred, and the trailing portion of the receive
+// buffer is not modified.
+//
+// Packet - A pointer to a descriptor for the packet storage into which
+// the MAC is to copy the received packet.
+//
+// BytesTransfered - A pointer to an unsigned integer. The MAC writes
+// the actual number of bytes transferred into this location. This value
+// is not valid if the return Status is STATUS_PENDING.
+//
+// Output:
+// Packet - Place to copy data.
+// BytesTransferred - Number of bytes copied.
+// Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is returned.
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexTransferData(
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE MiniportReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ )
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ PNDIS_BUFFER DestinationCurrentBuffer;
+ UINT DestinationBufferCount;
+ PUCHAR SourceCurrentAddress;
+ PVOID DestinationVirtualAddress;
+ UINT DestinationCurrentLength;
+ UINT LocalBytesTransferred = 0;
+ UINT AmountToMove;
+ UINT Remaining;
+
+ //
+ // Display number of bytes to transfer on the debugger
+ //
+ DebugPrint(2,("NF(%d) - Copying %u bytes\n",acb->anum,BytesToTransfer));
+
+ //
+ // Initialize the number of bytes transferred to 0
+ //
+ *BytesTransferred = 0;
+
+ //
+ // If we don't have any more to transfer, we're done
+ //
+ if (BytesToTransfer == 0)
+ {
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ //
+ // Get the first buffer of the destination.
+ //
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &DestinationBufferCount,
+ &DestinationCurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet. If so, we are done.
+ //
+ if (DestinationBufferCount == 0)
+ {
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ //
+ // Get information on the buffer.
+ //
+ NdisQueryBuffer(
+ DestinationCurrentBuffer,
+ &DestinationVirtualAddress,
+ &DestinationCurrentLength
+ );
+
+ //
+ // Set up the source address.
+ //
+ SourceCurrentAddress = (PCHAR)(MiniportReceiveContext) + ByteOffset;
+
+ //
+ // Do the actual transfer from source to destination
+ //
+ while (LocalBytesTransferred < BytesToTransfer)
+ {
+ // Check to see whether we've exhausted the current destination
+ // buffer. If so, move onto the next one.
+ //
+ if (DestinationCurrentLength == 0)
+ {
+ NdisGetNextBuffer(
+ DestinationCurrentBuffer,
+ &DestinationCurrentBuffer
+ );
+
+ if (DestinationCurrentBuffer == NULL)
+ {
+ // We've reached the end of the packet. We return
+ // with what we've done so far. (Which must be shorter
+ // than requested.)
+ //
+ break;
+ }
+
+ NdisQueryBuffer(
+ DestinationCurrentBuffer,
+ &DestinationVirtualAddress,
+ &DestinationCurrentLength
+ );
+
+ continue;
+ }
+
+ //
+ // Copy the data.
+ //
+
+ Remaining = BytesToTransfer - LocalBytesTransferred;
+
+ AmountToMove = DestinationCurrentLength;
+
+ AmountToMove = ((Remaining < AmountToMove)?
+ (Remaining):(AmountToMove));
+
+ NdisMoveMemory(
+ DestinationVirtualAddress,
+ SourceCurrentAddress,
+ AmountToMove
+ );
+
+ //
+ // Update pointers and counters
+ //
+ SourceCurrentAddress += AmountToMove;
+ LocalBytesTransferred += AmountToMove;
+ DestinationCurrentLength -= AmountToMove;
+ }
+
+ //
+ // Indicate how many bytes were transferred
+ //
+ *BytesTransferred = LocalBytesTransferred;
+
+ //
+ // Display total bytes transferred on debugger
+ //
+ DebugPrint(2,("NF(%d) - Total bytes transferred = %x\n",acb->anum,*BytesTransferred));
+
+ return NDIS_STATUS_SUCCESS;
+}
diff --git a/private/ntos/ndis/netflex/request.c b/private/ntos/ndis/netflex/request.c
new file mode 100644
index 000000000..7188d17dd
--- /dev/null
+++ b/private/ntos/ndis/netflex/request.c
@@ -0,0 +1,2148 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: REQUEST.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexAddMulticasts
+//
+// Description:
+// This routine adds a Multicast address to
+// the adapter if it has not already been added.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+//
+// Called By: NetFlexSetInformation
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS NetFlexAddMulticasts(
+ PACB acb,
+ PSCBREQ *ScbHead,
+ PSCBREQ *ScbTail
+)
+{
+ NDIS_STATUS Status;
+ PETH_OBJS ethobjs;
+ PSCBREQ scbreq;
+ USHORT j;
+ PUCHAR addr;
+
+ //
+ // Set ethobjs to the special objects...
+ //
+ ethobjs = (PETH_OBJS)acb->acb_spec_objs;
+
+ //
+ // Loop through the multicast table, and send them to the card
+ //
+ for (j = 0; j < ethobjs->NumberOfEntries; j++)
+ {
+ //
+ // Get an SCB.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)(&acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(
+ 0,
+ ("NF(%d): Add Multicast, Ran out of SCB's!\n",
+ acb->anum)
+ );
+
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ //
+ // Add Multicast entry to card
+ //
+ addr = ethobjs->MulticastEntries + (j * NET_ADDR_SIZE);
+
+ DebugPrint(
+ 1, ("NF(%d): Adding %02x-%02x-%02x-%02x-%02x-%02x to Multicast Table\n",
+ acb->anum, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]));
+
+ scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
+ scbreq->req_macreq = NULL;
+ scbreq->req_multi.MB_Option = MPB_ADD_ADDRESS;
+ scbreq->req_multi.MB_Addr_Hi = *((PUSHORT) addr);
+ scbreq->req_multi.MB_Addr_Med = *((PUSHORT)(addr + 2));
+ scbreq->req_multi.MB_Addr_Lo = *((PUSHORT)(addr + 4));
+
+ //
+ // Queue the scb.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDeleteMulticast
+//
+// Description:
+// This routine removes the multicast address from the
+// enabled multicast lists.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// Status - SUCCESS | FAILURE
+//
+// Called By:
+// NetFlexSetInformation
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS NetFlexDeleteMulticast(
+ PACB acb,
+ PSCBREQ *ScbHead,
+ PSCBREQ *ScbTail
+)
+{
+ NDIS_STATUS Status;
+ PSCBREQ scbreq;
+
+ DebugPrint(1, ("NF(%d): Delete Multicast Table\n", acb->anum));
+
+ //
+ // Get a free SCBReq block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // Queue SCB to process request
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
+ scbreq->req_macreq = NULL;
+ scbreq->req_multi.MB_Option = MPB_CLEAR_ALL;
+
+ NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
+ }
+ else
+ {
+ DebugPrint(0,("NF(%d): Delete Multicast Table, Ran out of SCB's!\n",acb->anum));
+ }
+
+ return(Status);
+}
+
+
+NDIS_STATUS PromiscuousFilterChanged(
+ PACB acb,
+ ULONG Filter,
+ PSCBREQ *ScbHead,
+ PSCBREQ *ScbTail
+)
+{
+ NDIS_STATUS Status;
+ PSCBREQ scbreq;
+ ULONG open_options;
+
+ // Modify the open options to set COPY ALL FRAMES (promiscuous)
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Queue SCB to process request
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_MODIFYOPEN;
+ scbreq->req_macreq = NULL;
+
+ //
+ // Set the open options for ethernet and token ring.
+ //
+ open_options = OOPTS_CNMAC;
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ open_options |= OOPTS_CMAC;
+
+ //
+ // If we are turning it on, set the copy all frame bit
+ // bit, else turn it off.
+ //
+ if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
+ {
+ //
+ // Turn on promiscuous mode.
+ //
+ acb->acb_opnblk_virtptr->OPEN_Options |= SWAPS((USHORT)open_options);
+ scbreq->req_scb.SCB_Ptr = acb->acb_opnblk_virtptr->OPEN_Options;
+
+ DebugPrint(1,("NF(%d): FilterChanged: Turn Promiscous Mode ON...\n",acb->anum));
+ acb->acb_promiscuousmode++;
+ }
+ else
+ {
+ //
+ // Turn off promiscuous mode.
+ //
+ acb->acb_opnblk_virtptr->OPEN_Options &= SWAPS((USHORT)~open_options);
+ scbreq->req_scb.SCB_Ptr = acb->acb_opnblk_virtptr->OPEN_Options;
+
+ DebugPrint(1,("NF(%d): FilterChanged: Turn Promiscous Mode OFF...\n",acb->anum));
+ acb->acb_promiscuousmode--;
+ }
+
+ //
+ // Queue the scb to be sent.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
+ }
+ else
+ {
+ DebugPrint(0, ("NF(%d): Change Promiscuous mode, ran out of SCB's\n", acb->anum));
+ }
+
+ return(Status);
+}
+
+
+NDIS_STATUS AllMulticastFilterChanged(
+ PACB acb,
+ ULONG Filter,
+ PSCBREQ *ScbHead,
+ PSCBREQ *ScbTail
+)
+{
+ NDIS_STATUS Status;
+ PSCBREQ scbreq;
+ PETH_OBJS ethobjs = acb->acb_spec_objs;
+
+ //
+ // Get a free SCBReq block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0, ("NF(%d): AllMulticastFilterChanged(), Ran out of SCB's!\n",acb->anum));
+ return(Status);
+ }
+
+ //
+ // Turning All_Multicast On?
+ //
+ if (Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+ {
+ DebugPrint(1,("NF(%d): FilterChanged: Turn ALL_Multicast ON...\n",acb->anum));
+
+ // Queue SCB to process request
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
+ scbreq->req_macreq = NULL;
+ scbreq->req_multi.MB_Option = MPB_SET_ALL;
+
+ //
+ // Queue the scb to be sent.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
+ }
+ else
+ {
+ // Turn All_Multicast Off.
+ //
+ DebugPrint(1,("NF(%d): FilterChanged: Turn ALL_Multicast OFF, delete all\n",acb->anum));
+
+ //
+ // Set up the scb to turn off ALL_MULTICAST.
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
+ scbreq->req_macreq = NULL;
+ scbreq->req_multi.MB_Option = MPB_CLEAR_ALL;
+
+ //
+ // Queue the scb to be sent.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
+
+ //
+ // Is Multicast on?
+ //
+ if (Filter & NDIS_PACKET_TYPE_MULTICAST)
+ {
+ //
+ // Yes, we need to re-enable all of the entries...
+ // The call to delete the multicast address above
+ // will determine if a completion is queued.
+ //
+ if (ethobjs->NumberOfEntries > 0)
+ NetFlexAddMulticasts(acb, ScbHead, ScbTail);
+ }
+ else
+ {
+ //
+ // Multicast isn't enabled, and we deleted them, so indicate
+ // that we also removed the multicast entries.
+ //
+ ethobjs->NumberOfEntries = 0;
+ }
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+NDIS_STATUS MulticastFilterChanged(
+ PACB acb,
+ ULONG Filter,
+ PSCBREQ *ScbHead,
+ PSCBREQ *ScbTail
+)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PSCBREQ scbreq;
+ PETH_OBJS ethobjs;
+
+ //
+ // If the ALL_MULTICAST filter bit is set then we don't need to
+ // turn on/off the MULTICAST crap. We will save the current filter
+ // options with the ACB in the calling routine so that we know
+ // to turn on the MULTICAST addresses when the ALL_MULTICAST bit
+ // is cleared.
+ //
+ if (Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+ return(NDIS_STATUS_SUCCESS);
+
+ //
+ // Get a pointer to the ethernet objecst.
+ //
+ ethobjs = acb->acb_spec_objs;
+
+ //
+ // Are we turning the MULTICAST bit on or off?
+ //
+ if (Filter & NDIS_PACKET_TYPE_MULTICAST)
+ {
+ DebugPrint(1,("NF(%d): FilterChanged: Turn multicast ON...\n",acb->anum));
+
+ //
+ // Do we have any entries to enable?
+ //
+ if (ethobjs->NumberOfEntries > 0)
+ Status = NetFlexAddMulticasts(acb, ScbHead, ScbTail);
+ }
+ else
+ {
+ DebugPrint(1,("NF(%d): FilterChanged: Turn multicast OFF, delete all\n", acb->anum));
+
+ //
+ // Have any to delete?
+ //
+ if (ethobjs->NumberOfEntries > 0)
+ Status = NetFlexDeleteMulticast(acb, ScbHead, ScbTail);
+ }
+
+ return(Status);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexSetInformation
+//
+// Description:
+// NetFlexSetInformation handles a set operation for a
+// single OID.
+//
+// Input:
+// MiniportAdapterContext - Our Driver Context for
+// this adapter or head.
+//
+// Oid - The OID of the set.
+//
+// InformationBuffer - Holds the data to be set.
+//
+// InformationBufferLength - The length of InformationBuffer.
+//
+// Output:
+//
+// BytesRead - If the call is successful, returns the number
+// of bytes read from InformationBuffer.
+//
+// BytesNeeded - If there is not enough data in OvbBuffer
+// to satisfy the OID, returns the amount of
+// storage needed.
+// Status
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS NetFlexSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+)
+{
+ ULONG value;
+ PMACREQ macreq;
+ PETH_OBJS ethobjs;
+ PTR_OBJS trobjs;
+ PSCBREQ scbreq;
+ PSCBREQ ScbHead = NULL;
+ PSCBREQ ScbTail = NULL;
+ ULONG Filter;
+ ULONG BadFilter;
+ BOOLEAN QueueCompletion = FALSE;
+ BOOLEAN QueueCleanup = FALSE;
+
+ PACB acb = (PACB) MiniportAdapterContext;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ if (acb->acb_state == AS_RESETTING)
+ {
+ return(NDIS_STATUS_RESET_IN_PROGRESS);
+ }
+
+ if (acb->RequestInProgress)
+ {
+ DebugPrint(0,("NF(%d): SetOID: Aready have RequestInProcess!\n",acb->anum));
+ return NDIS_STATUS_FAILURE;
+ }
+
+ acb->RequestInProgress = TRUE;
+
+ //
+ // Save the information about the request
+ //
+ acb->BytesRead = BytesRead;
+ acb->BytesNeeded = BytesNeeded;
+ acb->Oid = Oid;
+ acb->InformationBuffer = InformationBuffer;
+ acb->InformationBufferLength = InformationBufferLength;
+
+ switch (Oid)
+ {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ if (InformationBufferLength != sizeof(ULONG))
+ {
+ DebugPrint(0,("NF(%d): Bad Packet Filter\n",acb->anum));
+ acb->RequestInProgress = FALSE;
+
+ return(NDIS_STATUS_INVALID_DATA);
+ }
+
+ Filter = *(PULONG)(InformationBuffer);
+ DebugPrint(1,("NF(%d): OidSet: GEN_CURRENT_PACKET_FILTER = %x\n",acb->anum,Filter));
+
+ //-------------------------------------------
+ // Filters Common to TokenRing and Ethernet
+ //-------------------------------------------
+
+#if (DBG || DBGPRINT)
+ if (Filter & NDIS_PACKET_TYPE_DIRECTED)
+ DebugPrint(1,("NF(%d): FilterChangeAction: Directed\n",acb->anum));
+#endif
+ //
+ // Verify Filter
+ //
+ if ( acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ //--------------------------------
+ // Ethernet Specific Filters...
+ //--------------------------------
+ //
+ // accept only the following:
+ //
+ BadFilter = (ULONG)~(NDIS_PACKET_TYPE_DIRECTED |
+ NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_BROADCAST |
+ (acb->FullDuplexEnabled ?
+ 0 : NDIS_PACKET_TYPE_PROMISCUOUS)
+ );
+ if (Filter & BadFilter)
+ {
+ DebugPrint(1,("NF(%d): PacketFilter Not Supported\n",acb->anum));
+
+ *BytesRead = sizeof(ULONG);
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ }
+
+ //
+ // Did the state of the ALL_MULTICAST bit change?
+ //
+ if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ^
+ (Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+ )
+ {
+ Status = AllMulticastFilterChanged(
+ acb,
+ Filter,
+ &ScbHead,
+ &ScbTail
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ //
+ // We might need to cleanup the local
+ // queue of SCBs.
+ //
+ QueueCleanup = TRUE;
+ break;
+ }
+
+ //
+ // We successfully changed the ALL_MULTICAST bit.
+ //
+ QueueCompletion = TRUE;
+ }
+
+ //
+ // Did the state of the MULTICAST bit change?
+ //
+ if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_MULTICAST) ^
+ (Filter & NDIS_PACKET_TYPE_MULTICAST)
+ )
+ {
+ Status = MulticastFilterChanged(
+ acb,
+ Filter,
+ &ScbHead,
+ &ScbTail
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ //
+ // We might need to cleanup the local
+ // queue of SCBs.
+ //
+ QueueCleanup = TRUE;
+ break;
+ }
+
+ //
+ // We successfully changed the MULTICAST bit.
+ //
+ QueueCompletion = TRUE;
+ }
+ }
+ else
+ {
+ //-------------------------------
+ // Token Ring Specific Filters...
+ //-------------------------------
+ //
+ // accept all of the following:
+ //
+ BadFilter = (ULONG)~(NDIS_PACKET_TYPE_FUNCTIONAL |
+ NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
+ NDIS_PACKET_TYPE_GROUP |
+ NDIS_PACKET_TYPE_DIRECTED |
+ NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS
+ );
+ if (Filter & BadFilter)
+ {
+ DebugPrint(1,("NF(%d): PacketFilter Not Supported\n",acb->anum));
+
+ *BytesRead = sizeof(ULONG);
+
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ }
+
+ //
+ // Are we turning the All Functional address filter on or off?
+ //
+ if (((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) ^
+ (Filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)) ||
+ ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_FUNCTIONAL) ^
+ (Filter & NDIS_PACKET_TYPE_FUNCTIONAL))
+ )
+ {
+ //
+ // We are changing it. Are we turning it on?
+ // Set functional address to all functional address
+ //
+ // Get a free SCBReq block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // We failed to get an scb. We don't need
+ // to cleanup the scb queue since this is the
+ // first one.
+ //
+ break;
+ }
+
+ //
+ // Queue SCB to process request
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_SETFUNCT;
+ scbreq->req_macreq = NULL;
+
+ //
+ // If we are turning it on, set the functional address
+ // to all ones, else set it to the acb's functional
+ // address.
+ //
+ if (Filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
+ {
+ scbreq->req_scb.SCB_Ptr = SWAPL(0x7fffffff);
+ }
+ else
+ {
+ if (Filter & NDIS_PACKET_TYPE_FUNCTIONAL)
+ {
+ scbreq->req_scb.SCB_Ptr =
+ *((PLONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_func_addr));
+ }
+ else
+ {
+ //
+ // clear it
+ //
+ scbreq->req_scb.SCB_Ptr = 0;
+ }
+ }
+
+ DebugPrint(1,("NF(%d): FilterChanged: Setting Functional Address =0x%x\n",acb->anum,scbreq->req_scb.SCB_Ptr));
+
+ //
+ // Queue the scb.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
+
+ //
+ // Indicate we need to QueueCompletion MacReq
+ //
+ QueueCompletion = TRUE;
+ }
+
+ //
+ // Changing Group?
+ //
+ if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_GROUP) ^
+ (Filter & NDIS_PACKET_TYPE_GROUP)
+ )
+ {
+ // Get a free SCBReq block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // We might need to cleanup the local
+ // queue of SCBs.
+ //
+ QueueCleanup = TRUE;
+
+ break;
+ }
+
+ //
+ // Queue SCB to process request
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_SETGROUP;
+ scbreq->req_macreq = NULL;
+
+ //
+ // Set or Clear the Group Address?
+ //
+ if (Filter & NDIS_PACKET_TYPE_GROUP)
+ {
+ scbreq->req_scb.SCB_Ptr =
+ *((PLONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_grp_addr));
+ }
+ else
+ {
+ scbreq->req_scb.SCB_Ptr = 0;
+ }
+
+ DebugPrint(1,("NF(%d): FilterChanged: Setting Group Address =0x%x\n",acb->anum,scbreq->req_scb.SCB_Ptr));
+
+ //
+ // Queue the scb.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
+
+ //
+ // Indicate we need to QueueCompletion MacReq
+ //
+ QueueCompletion = TRUE;
+ }
+ }
+
+ //
+ // Did the state of the PROMISCUOUS flag change?
+ //
+ if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_PROMISCUOUS) ^
+ (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
+ )
+ {
+ Status = PromiscuousFilterChanged(
+ acb,
+ Filter,
+ &ScbHead,
+ &ScbTail
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ //
+ // We might need to cleanup the local
+ // queue of SCBs.
+ //
+ QueueCleanup = TRUE;
+ break;
+ }
+
+ //
+ // We successfully changed the PROMISCUOUS bit.
+ //
+ QueueCompletion = TRUE;
+ }
+
+ acb->acb_gen_objs.cur_filter = Filter;
+ *BytesRead = InformationBufferLength;
+
+ break;
+
+ case OID_802_3_MULTICAST_LIST:
+
+ //
+ // Is the adapter setup for token ring?
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5 )
+ {
+ //
+ // Token ring does not support multicast.
+ //
+ DebugPrint(0,("NF(%d): MULTICAST LIST INVALID OID\n",acb->anum));
+ *BytesRead = 0;
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ }
+
+ if (InformationBufferLength % NET_ADDR_SIZE != 0)
+ {
+ //
+ // The data must be a multiple of the Ethernet address size.
+ //
+ DebugPrint(0,("NF(%d): MULTICAST LIST INVALID LENGTH\n",acb->anum));
+
+ *BytesNeeded = InformationBufferLength + (NET_ADDR_SIZE - (InformationBufferLength % NET_ADDR_SIZE));
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_INVALID_DATA;
+
+ break;
+ }
+
+ //
+ // Get a pointer to the ethernet objects.
+ //
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ scbreq = NULL;
+
+ value = (InformationBufferLength / NET_ADDR_SIZE );
+
+ if (value > ethobjs->MaxMulticast)
+ {
+ DebugPrint(0,("NF(%d): TOO MANY MULTICAST ADDRESSES\n",acb->anum));
+
+ //
+ // There are too many, but add as many as we can.
+ //
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_MULTICAST_FULL;
+
+ break;
+ }
+
+ DebugPrint(1, ("NF(%d): Saving multicast address\n", acb->anum));
+
+ //
+ // Save entries in the table.
+ //
+ NdisMoveMemory(
+ ethobjs->MulticastEntries,
+ InformationBuffer,
+ value * NET_ADDR_SIZE
+ );
+
+ //
+ // If we have any entries enabled, delete them,
+ // unless NDIS_PACKET_TYPE_ALL_MULTICAST is set.
+ //
+ if (!(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) &&
+ (ethobjs->NumberOfEntries > 0)
+ )
+ {
+ //
+ // Get a free SCBReq block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): MULTICAST_LIST: out of SCBs\n", acb->anum));
+
+ //
+ // Since this is the first SCB, and it failed,
+ // we don't need to clean up.
+ //
+ break;
+ }
+
+ DebugPrint(1,("NF(%d): MULTICAST_LIST: clearing current list\n", acb->anum));
+
+ // Queue SCB to process request
+ //
+ scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
+ scbreq->req_macreq = NULL;
+ scbreq->req_multi.MB_Option = MPB_CLEAR_ALL;
+
+ //
+ // Queue the scb.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
+
+ //
+ // Indicate we need to a Queue MacReq Completion
+ //
+ QueueCompletion = TRUE;
+ }
+
+ //
+ // Save number of entrys
+ //
+ ethobjs->NumberOfEntries = (SHORT)value;
+
+ //
+ // If filter has NDIS_PACKET_TYPE_MULTICAST, but NOT
+ // NDIS_PACKET_TYPE_ALL_MULTICAST, then enable these entries now.
+ //
+ if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_MULTICAST) &&
+ !(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+ )
+ {
+ if (ethobjs->NumberOfEntries > 0)
+ {
+ Status = NetFlexAddMulticasts(acb, &ScbHead, &ScbTail);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Cleanup the local SCB queue.
+ //
+ QueueCleanup = TRUE;
+ break;
+ }
+
+ //
+ // Indicate we need to a Queue MacReq Completion
+ //
+ QueueCompletion = TRUE;
+ }
+ }
+
+ *BytesRead = InformationBufferLength;
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ //
+ // We don't set anything, just return ok. - RVC true?
+ //
+ *BytesRead = 4;
+ Status = NDIS_STATUS_SUCCESS;
+ DebugPrint(1,("NF(%d): OID_GEN_CURRENT_LOOKAHEAD...\n",acb->anum));
+
+ break;
+
+
+ case OID_802_5_CURRENT_FUNCTIONAL:
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ //
+ // If we are running Ethernet, a call for this oid is an error.
+ //
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ }
+
+ if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL )
+ {
+ DebugPrint(0,("NF(%d): Oid_Set Functional Address bad\n",acb->anum));
+ *BytesNeeded = TR_LENGTH_OF_FUNCTIONAL - InformationBufferLength;
+
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ break;
+ }
+
+ //
+ // Get the oid info.
+ //
+ NdisMoveMemory(
+ (PVOID)&value,
+ InformationBuffer,
+ TR_LENGTH_OF_FUNCTIONAL
+ );
+
+ //
+ // Get a pointer to the token ring objects.
+ //
+ trobjs = (PTR_OBJS)(acb->acb_spec_objs);
+
+ *((PULONG)(trobjs->cur_func_addr)) = value;
+
+ DebugPrint(1,("NF(%d): OidSet Functional Address = %08x\n",acb->anum,value));
+
+ //
+ // Update filter if the funcational address has been set in
+ // the packet filter.
+ //
+ if (!(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) &&
+ (acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_FUNCTIONAL)
+ )
+ {
+ //
+ // Get an scb.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ scbreq->req_scb.SCB_Cmd = TMS_SETFUNCT;
+ scbreq->req_macreq = NULL;
+ scbreq->req_scb.SCB_Ptr = value;
+
+ //
+ // Queue the scb.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
+
+ QueueCompletion = TRUE;
+ }
+ }
+
+ *BytesRead = TR_LENGTH_OF_FUNCTIONAL;
+ break;
+
+ case OID_802_5_CURRENT_GROUP:
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3 )
+ {
+ // If we are running Ethernet, a call for this oid is an error.
+ //
+ acb->RequestInProgress = FALSE;
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ }
+
+ if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL)
+ {
+ DebugPrint(0,("NF(%d): OidSet Group Address BAD\n",acb->anum));
+ *BytesNeeded = TR_LENGTH_OF_FUNCTIONAL - InformationBufferLength;
+
+ acb->RequestInProgress = FALSE;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ break;
+ }
+
+ NdisMoveMemory(
+ (PVOID)&value,
+ InformationBuffer,
+ TR_LENGTH_OF_FUNCTIONAL
+ );
+
+ trobjs = (PTR_OBJS)(acb->acb_spec_objs);
+
+ *((PULONG)(trobjs->cur_grp_addr)) = value;
+
+ DebugPrint(1,("NF(%d): OidSet Group Address = %08x\n",acb->anum,value));
+
+ //
+ // Update filter if the group address has been set in
+ // the packet filter.
+ //
+ if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_GROUP) != 0)
+ {
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq
+ );
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ scbreq->req_scb.SCB_Cmd = TMS_SETGROUP;
+ scbreq->req_macreq = NULL;
+ scbreq->req_scb.SCB_Ptr = value;
+
+ //
+ // Queue the scb.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
+
+ QueueCompletion = TRUE;
+ }
+ }
+
+ *BytesRead = TR_LENGTH_OF_FUNCTIONAL;
+ break;
+
+ default:
+
+ Status = NDIS_STATUS_INVALID_OID;
+ break;
+
+ }
+
+ if (QueueCleanup)
+ {
+ DebugPrint(1,("NF(%d): Error Setting OID (0x%x)\n",acb->anum, Oid));
+
+ //
+ // There was an error trying to get sufficent SCBs to
+ // complete the request.
+ //
+ while (ScbHead != NULL)
+ {
+ NetFlexDequeue_OnePtrQ_Head(&ScbHead, &scbreq);
+
+ NetFlexEnqueue_OnePtrQ_Head(
+ (PVOID *)&acb->acb_scbreq_free,
+ scbreq
+ );
+ }
+
+ QueueCompletion = FALSE;
+ }
+
+ if (QueueCompletion)
+ {
+ //
+ // Was there actually an scb queued?
+ //
+ if (NULL != ScbHead)
+ {
+ //
+ // We should have a local list of scb's to send.
+ //
+ do
+ {
+ //
+ // Get a pointer to the next scb to process.
+ //
+ scbreq = ScbHead->req_next;
+
+ //
+ // Are we on the last scb?
+ //
+ if (NULL == scbreq)
+ {
+ //
+ // Get a mac request in case we need the completeion
+ //
+ NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_macreq_free),
+ (PVOID *)&macreq
+ );
+
+ //
+ // Initialize the completion request.
+ //
+ macreq->req_next = NULL;
+ macreq->req_type = REQUEST_CMP;
+ macreq->req_status = NDIS_STATUS_SUCCESS;
+
+ //
+ // Setup the last scb to be sent to the card.
+ //
+ ScbHead->req_macreq = macreq;
+
+ //
+ // put the macreq on the macreq queue
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(
+ (PVOID *)&(acb->acb_macreq_head),
+ (PVOID *)&(acb->acb_macreq_tail),
+ (PVOID)macreq
+ );
+ }
+
+ //
+ // Send the scb down to the card
+ //
+ NetFlexQueueSCB(acb, ScbHead);
+
+ ScbHead = scbreq;
+
+ } while (NULL != scbreq);
+
+ return(NDIS_STATUS_PENDING);
+ }
+ }
+
+ //
+ // Request was aborted due to error.
+ //
+ acb->RequestInProgress = FALSE;
+
+ return(Status);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexQueryInformation
+//
+// Description:
+// The NetFlexQueryInformation process a Query request for
+// NDIS_OIDs that are specific about the Driver.
+//
+// Input:
+// MiniportAdapterContext - Our Driver Context for this
+// adapter or head.
+//
+// Oid - the NDIS_OID to process.
+//
+// InformationBuffer - a pointer into the NdisRequest->InformationBuffer
+// into which store the result of the query.
+//
+// InformationBufferLength - a pointer to the number of bytes left in the
+// InformationBuffer.
+//
+// Output:
+// BytesWritten - a pointer to the number of bytes written into the
+// InformationBuffer.
+//
+// BytesNeeded - If there is not enough room in the information buffer
+// then this will contain the number of bytes needed to complete the
+// request.
+//
+// Status - The function value is the Status of the operation.
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+)
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ PMACREQ macreq;
+ ULONG lvalue;
+ USHORT svalue;
+ PTR_OBJS trobjs;
+ PETH_OBJS ethobjs;
+ PUCHAR srcptr;
+ PUCHAR copyptr = NULL;
+ PSCBREQ scbreq;
+ UCHAR vendorid[4];
+ SHORT copylen = (SHORT)sizeof(ULONG); // Most common length
+
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ BOOLEAN needcopy = TRUE;
+
+ if (acb->acb_state == AS_RESETTING)
+ {
+ return(NDIS_STATUS_RESET_IN_PROGRESS);
+ }
+
+ //
+ // Initialize the result
+ //
+ *BytesWritten = 0;
+ *BytesNeeded = 0;
+
+ //
+ // General Objects Characteristics
+ //
+
+ switch (Oid)
+ {
+ case OID_GEN_SUPPORTED_LIST:
+ copyptr = (PUCHAR)acb->acb_gbl_oid_list;
+ copylen = (SHORT)acb->acb_gbl_oid_list_size;
+ DebugPrint(2,("NF: Query OID_GEN_SUPPORTED_LIST...\n",acb->anum));
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+ lvalue = NdisHardwareStatusNotReady;
+ switch (acb->acb_state)
+ {
+ case AS_OPENED:
+ lvalue = NdisHardwareStatusReady;
+ DebugPrint(1,("NF(%d):Query HW Status - AS_OPENED\n",acb->anum));
+ break;
+ case AS_CLOSING:
+ lvalue = NdisHardwareStatusClosing;
+ DebugPrint(1,("NF(%d):Query HW Status - AS_CLOSING\n",acb->anum));
+ break;
+ case AS_RESETTING:
+ case AS_RESET_HOLDING:
+ DebugPrint(1,("NF(%d):Query HW Status - AS_RESETTING\n",acb->anum));
+ lvalue = NdisHardwareStatusReset;
+ break;
+ case AS_INITIALIZING:
+ DebugPrint(1,("NF(%d):Query HW Status - AS_INITIALIZING\n",acb->anum));
+ lvalue = NdisHardwareStatusInitializing;
+ break;
+ default:
+ DebugPrint(1,("NF(%d):NetFlexQueryInformation: Undefinded State - 0x%x",acb->anum,acb->acb_state));
+ break;
+ }
+ copyptr = (PUCHAR)&lvalue;
+ DebugPrint(2,("NF(%d): Query OID_GEN_HARDWARE_STATUS 0x%x...\n",acb->anum,lvalue));
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.media_type_in_use;
+ DebugPrint(2,("NF(%d): Query OID_GEN_MEDIA_IN_USE 0x%x...\n",acb->anum,
+ acb->acb_gen_objs.media_type_in_use));
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.max_frame_size;
+ break;
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ // Frame size is the max frame size minus the minimum header size.
+ //
+ lvalue = acb->acb_gen_objs.max_frame_size - 14;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_GEN_LINK_SPEED:
+ lvalue = acb->acb_gen_objs.link_speed * 10000;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ lvalue = acb->acb_gen_objs.max_frame_size * acb->acb_maxtrans;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ lvalue = acb->acb_gen_objs.max_frame_size * acb->acb_maxrcvs;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_GEN_VENDOR_ID:
+ NdisMoveMemory(vendorid,acb->acb_gen_objs.perm_staddr,3);
+ vendorid[3] = 0x0;
+ copyptr = (PUCHAR)vendorid;
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+ copyptr = (PUCHAR)"Compaq NetFlex Driver, Version 1.10"; // RVC: move to string...
+ copylen = (USHORT)36;
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+ svalue = 0x0300;
+ copyptr = (PUCHAR)&svalue;
+ copylen = (SHORT)sizeof(USHORT);
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ lvalue = acb->acb_gen_objs.cur_filter;
+ copyptr = (PUCHAR)&lvalue;
+ DebugPrint(2,("NF(%d): Query OID_GEN_CURRENT_PACKET_FILTER = 0x%x\n",acb->anum,lvalue));
+ break;
+
+ case OID_GEN_MAC_OPTIONS:
+ lvalue = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED;
+
+ //
+ // Indicate we need loop back if running Full Duplex
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ lvalue |= NDIS_MAC_OPTION_NO_LOOPBACK |
+ NDIS_MAC_OPTION_FULL_DUPLEX;
+ }
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ //
+ // GENERAL STATISTICS (Mandatory)
+ //
+
+ case OID_GEN_XMIT_OK:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.frames_xmitd_ok;
+ break;
+
+ case OID_GEN_RCV_OK:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.frames_rcvd_ok;
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.frames_xmitd_err;
+ break;
+
+ case OID_GEN_RCV_ERROR:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.frames_rcvd_err;
+ break;
+
+ case OID_NF_INTERRUPT_COUNT:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.interrupt_count;
+ break;
+
+ case OID_NF_INTERRUPT_RATIO:
+ copyptr = (PUCHAR)&acb->RcvIntRatio;
+ break;
+
+ case OID_NF_INTERRUPT_RATIO_CHANGES:
+ copyptr = (PUCHAR)&acb->acb_gen_objs.interrupt_ratio_changes;
+ break;
+
+ } // end of general
+
+ if (copyptr == NULL)
+ {
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3 )
+ {
+ //---------------------------------------
+ // Ethernet Specific Oid's
+ //---------------------------------------
+ //
+
+ switch (Oid)
+ {
+ //-------------------------------------
+ // 802.3 OPERATIONAL CHARACTERISTICS
+ //-------------------------------------
+
+ case OID_802_3_PERMANENT_ADDRESS:
+ srcptr = acb->acb_gen_objs.perm_staddr;
+ copyptr = (PUCHAR)srcptr;
+ copylen = (SHORT)NET_ADDR_SIZE;
+
+ case OID_802_3_CURRENT_ADDRESS:
+ srcptr = acb->acb_gen_objs.current_staddr;
+ copyptr = (PUCHAR)srcptr;
+ copylen = (SHORT)NET_ADDR_SIZE;
+ break;
+
+ case OID_802_3_MULTICAST_LIST:
+ DebugPrint(2,("NF(%d): Query OID_802_3_MULTICAST_LIST\n",acb->anum));
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+
+ needcopy = TRUE;
+ copylen = ethobjs->NumberOfEntries * NET_ADDR_SIZE;
+ copyptr = (PVOID) &ethobjs->NumberOfEntries;
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ lvalue = ethobjs->MaxMulticast;
+ copyptr = (PUCHAR)&lvalue;
+ DebugPrint(2,("NF(%d): Query OID_802_3_MAXIMUM_LIST_SIZE = 0x%x\n",acb->anum,lvalue));
+ break;
+
+ //-------------------------------
+ // 802.3 STATISTICS (Mandatory)
+ //-------------------------------
+
+ case OID_GEN_RCV_NO_BUFFER:
+ lvalue = 0;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ case OID_802_3_XMIT_DEFERRED:
+ case OID_802_3_XMIT_LATE_COLLISIONS:
+ case OID_802_3_XMIT_MAX_COLLISIONS:
+ case OID_802_3_XMIT_TIMES_CRS_LOST:
+ case OID_GEN_RCV_CRC_ERROR:
+ if (acb->acb_logbuf_valid)
+ {
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+
+ switch (Oid)
+ {
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ lvalue = ethobjs->RSL_AlignmentErr;
+ break;
+ case OID_802_3_XMIT_ONE_COLLISION:
+ lvalue = ethobjs->RSL_1_Collision;
+ break;
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ lvalue = ethobjs->RSL_More_Collision;
+ break;
+ case OID_802_3_XMIT_DEFERRED:
+ lvalue = ethobjs->RSL_DeferredXmit;
+ break;
+ case OID_802_3_XMIT_LATE_COLLISIONS:
+ lvalue = ethobjs->RSL_LateCollision;
+ break;
+ case OID_802_3_XMIT_MAX_COLLISIONS:
+ case OID_802_3_XMIT_TIMES_CRS_LOST:
+ lvalue = ethobjs->RSL_Excessive;
+ break;
+ default:
+ lvalue = ethobjs->RSL_FrameCheckSeq;
+ break;
+ }
+ copyptr = (PUCHAR)&lvalue;
+ }
+ else
+ {
+ needcopy = FALSE;
+ Status = NetFlexDequeue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ }
+ else
+ {
+ // Save the information about the request
+ //
+ if (acb->RequestInProgress)
+ {
+ DebugPrint(0,("NF(%d): Query OID: Aready have RequestInProcess!\n",acb->anum));
+ // return NDIS_STATUS_FAILURE;
+ }
+
+ acb->RequestInProgress = TRUE;
+
+ acb->BytesWritten = BytesWritten;
+ acb->BytesNeeded = BytesNeeded;
+ acb->Oid = Oid;
+ acb->InformationBuffer = InformationBuffer;
+ acb->InformationBufferLength = InformationBufferLength;
+
+ DebugPrint(2,("NF(%d): Queue Up Request to get OID (0x%x) info\n",acb->anum,Oid));
+
+ NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free),
+ (PVOID *)&macreq);
+ macreq->req_next = NULL;
+ macreq->req_type = QUERY_CMP;
+ macreq->req_status = NDIS_STATUS_SUCCESS;
+
+ scbreq->req_scb.SCB_Cmd = TMS_READLOG;
+ scbreq->req_macreq = macreq;
+ scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_logbuf_physptr)));
+
+ //
+ // put the macreq on the macreq queue
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail( (PVOID *)&(acb->acb_macreq_head),
+ (PVOID *)&(acb->acb_macreq_tail),
+ (PVOID)macreq);
+
+ NetFlexQueueSCB(acb, scbreq);
+ Status = NDIS_STATUS_PENDING;
+ }
+ }
+ break;
+
+ default:
+ DebugPrint(1,("NF(%d): (ETH) Invalid Query or Unsupported OID, %x\n",acb->anum,Oid));
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ needcopy = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ //---------------------------------------
+ // Token Ring Specific Oid's
+ //---------------------------------------
+ //
+ switch (Oid)
+ {
+ // We added the 802.5 stats here as well because of the
+ // read error log buffer.
+ //
+ case OID_802_5_LINE_ERRORS:
+ case OID_802_5_LOST_FRAMES:
+ case OID_802_5_BURST_ERRORS:
+ case OID_802_5_AC_ERRORS:
+ case OID_802_5_CONGESTION_ERRORS:
+ case OID_802_5_FRAME_COPIED_ERRORS:
+ case OID_802_5_TOKEN_ERRORS:
+ case OID_GEN_RCV_NO_BUFFER:
+ if (acb->acb_logbuf_valid)
+ {
+ trobjs = (PTR_OBJS)(acb->acb_spec_objs);
+ switch (Oid)
+ {
+ case OID_GEN_RCV_NO_BUFFER:
+ lvalue = trobjs->REL_Congestion;
+ break;
+ case OID_802_5_LINE_ERRORS:
+ lvalue = trobjs->REL_LineError;
+ break;
+ case OID_802_5_LOST_FRAMES:
+ lvalue = trobjs->REL_LostError;
+ break;
+ case OID_802_5_BURST_ERRORS:
+ lvalue = trobjs->REL_BurstError;
+ break;
+ case OID_802_5_AC_ERRORS:
+ lvalue = trobjs->REL_ARIFCIError;
+ break;
+ case OID_802_5_CONGESTION_ERRORS:
+ lvalue = trobjs->REL_Congestion;
+ break;
+ case OID_802_5_FRAME_COPIED_ERRORS:
+ lvalue = trobjs->REL_CopiedError;
+ break;
+ case OID_802_5_TOKEN_ERRORS:
+ lvalue = trobjs->REL_TokenError;
+ break;
+ default:
+ DebugPrint(0,("NetFlexQueryInformation: Undefinded OID - 0x%x",Oid));
+ break;
+ }
+ copyptr = (PUCHAR)&lvalue;
+ }
+ else
+ {
+ needcopy = FALSE;
+ Status = NetFlexDequeue_OnePtrQ_Head((PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ }
+ else
+ {
+ //
+ // Save the information about the request
+ //
+ if (acb->RequestInProgress)
+ {
+ DebugPrint(0,("NF(%d): Query OID: Aready have RequestInProcess!\n",acb->anum));
+ //return NDIS_STATUS_FAILURE;
+ }
+
+ acb->RequestInProgress = TRUE;
+
+ acb->BytesWritten = BytesWritten;
+ acb->BytesNeeded = BytesNeeded;
+ acb->Oid = Oid;
+ acb->InformationBuffer = InformationBuffer;
+ acb->InformationBufferLength = InformationBufferLength;
+
+ DebugPrint(2,("NF(%d): Queue Up Request to get OID (0x%x) info\n",acb->anum,Oid));
+
+ NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free),
+ (PVOID *)&macreq);
+ macreq->req_next = NULL;
+ macreq->req_type = QUERY_CMP;
+ macreq->req_status = NDIS_STATUS_SUCCESS;
+
+ scbreq->req_scb.SCB_Cmd = TMS_READLOG;
+ scbreq->req_macreq = macreq;
+ scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_logbuf_physptr)));
+ //
+ // put the macreq on the macreq queue
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail( (PVOID *)&(acb->acb_macreq_head),
+ (PVOID *)&(acb->acb_macreq_tail),
+ (PVOID)macreq);
+
+ NetFlexQueueSCB(acb, scbreq);
+ Status = NDIS_STATUS_PENDING;
+ }
+ }
+ break;
+
+ //------------------------------------
+ // 802.5 OPERATIONAL CHARACTERISTICS
+ //------------------------------------
+
+ case OID_802_5_PERMANENT_ADDRESS:
+ srcptr = acb->acb_gen_objs.perm_staddr;
+ copyptr = (PUCHAR)srcptr;
+ copylen = (SHORT)NET_ADDR_SIZE;
+ break;
+
+ case OID_802_5_CURRENT_ADDRESS:
+ srcptr = acb->acb_gen_objs.current_staddr;
+ copyptr = (PUCHAR)srcptr;
+ copylen = (SHORT)NET_ADDR_SIZE;
+ break;
+
+ case OID_802_5_UPSTREAM_ADDRESS:
+ NetFlexGetUpstreamAddress(acb);
+ srcptr = ((PTR_OBJS)acb->acb_spec_objs)->upstream_addr;
+ copyptr = (PUCHAR)srcptr;
+ copylen = (SHORT)NET_ADDR_SIZE;
+ break;
+
+ case OID_802_5_CURRENT_FUNCTIONAL:
+ lvalue = *( (PULONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_func_addr));
+ copyptr = (PUCHAR)&lvalue;
+ copylen = (SHORT)NET_GROUP_SIZE;
+ break;
+
+ case OID_802_5_CURRENT_GROUP:
+ lvalue = *( (PULONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_grp_addr));
+ copylen = (lvalue == 0) ? 0 : NET_GROUP_SIZE;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_802_5_LAST_OPEN_STATUS:
+ lvalue = acb->acb_lastopenstat;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_802_5_CURRENT_RING_STATUS:
+ lvalue = acb->acb_lastringstatus;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_802_5_CURRENT_RING_STATE:
+ lvalue = acb->acb_lastringstate;
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ default:
+ DebugPrint(1,("NF(%d): (TR) Invalid Query or Unsupported OID, %x\n",acb->anum,Oid));
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ needcopy = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (needcopy)
+ {
+ // Do we have enough space for the list + the oid value + the length?
+ //
+ if (InformationBufferLength < (USHORT) copylen)
+ {
+ DebugPrint(1,("NF(%d): Tell the user of the bytes needed\n",acb->anum));
+ *BytesNeeded = copylen - InformationBufferLength;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ // Copy the data bytes
+ //
+ NdisMoveMemory( InformationBuffer,
+ copyptr,
+ copylen);
+ //
+ // Update the information pointer and size.
+ //
+ *BytesWritten += copylen;
+ }
+ }
+
+ acb->RequestInProgress = Status == NDIS_STATUS_PENDING;
+
+ return Status;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexFinishQueryInformation
+//
+// Description:
+// The NetFlexFinishQueryInformation finish processing a Query request for
+// NDIS_OIDs that are specific about the Driver which we had to update
+// before returning.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// The function value is the Status of the operation.
+//
+// Called By:
+//
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexFinishQueryInformation(
+ PACB acb,
+ NDIS_STATUS Status
+ )
+{
+ ULONG lvalue;
+ PTR_OBJS trobjs;
+ PETH_OBJS ethobjs;
+ BOOLEAN needcopy = TRUE;
+ PUCHAR copyptr;
+ SHORT copylen = (SHORT)sizeof(ULONG); // Most common length
+
+ //
+ // Get the saved information about the request.
+ //
+
+ PUINT BytesWritten = acb->BytesWritten;
+ PUINT BytesNeeded = acb->BytesNeeded;
+ NDIS_OID Oid = acb->Oid;
+ PVOID InformationBuffer = acb->InformationBuffer;
+ UINT InformationBufferLength = acb->InformationBufferLength;
+
+ DebugPrint(2,("NF(%d): NetFlexFinishQueryInformation\n",acb->anum));
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ *BytesNeeded = 0;
+
+ switch (Oid)
+ {
+
+ case OID_GEN_RCV_NO_BUFFER:
+ case OID_802_5_LINE_ERRORS:
+ case OID_802_5_LOST_FRAMES:
+ case OID_802_5_BURST_ERRORS:
+ case OID_802_5_AC_ERRORS:
+ case OID_802_5_CONGESTION_ERRORS:
+ case OID_802_5_FRAME_COPIED_ERRORS:
+ case OID_802_5_TOKEN_ERRORS:
+ trobjs = (PTR_OBJS)(acb->acb_spec_objs);
+ switch (Oid)
+ {
+ case OID_GEN_RCV_NO_BUFFER:
+ lvalue = trobjs->REL_Congestion;
+ break;
+ case OID_802_5_LINE_ERRORS:
+ lvalue = trobjs->REL_LineError;
+ break;
+ case OID_802_5_LOST_FRAMES:
+ lvalue = trobjs->REL_LostError;
+ break;
+ case OID_802_5_BURST_ERRORS:
+ lvalue = trobjs->REL_BurstError;
+ break;
+ case OID_802_5_AC_ERRORS:
+ lvalue = trobjs->REL_ARIFCIError;
+ break;
+ case OID_802_5_CONGESTION_ERRORS:
+ lvalue = trobjs->REL_Congestion;
+ break;
+ case OID_802_5_FRAME_COPIED_ERRORS:
+ lvalue = trobjs->REL_CopiedError;
+ break;
+ case OID_802_5_TOKEN_ERRORS:
+ lvalue = trobjs->REL_TokenError;
+ break;
+ default:
+ DebugPrint(0,("NetFlexFinishQueryInformation: Undefinded OID - 0x%x",Oid));
+ break;
+ }
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ case OID_802_3_XMIT_DEFERRED:
+ case OID_802_3_XMIT_LATE_COLLISIONS:
+ case OID_802_3_XMIT_MAX_COLLISIONS:
+ case OID_802_3_XMIT_TIMES_CRS_LOST:
+ case OID_GEN_RCV_CRC_ERROR:
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+
+ switch (Oid)
+ {
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ lvalue = ethobjs->RSL_AlignmentErr;
+ break;
+ case OID_802_3_XMIT_ONE_COLLISION:
+ lvalue = ethobjs->RSL_1_Collision;
+ break;
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ lvalue = ethobjs->RSL_More_Collision;
+ break;
+ case OID_802_3_XMIT_DEFERRED:
+ lvalue = ethobjs->RSL_DeferredXmit;
+ break;
+ case OID_802_3_XMIT_LATE_COLLISIONS:
+ lvalue = ethobjs->RSL_LateCollision;
+ break;
+ case OID_802_3_XMIT_MAX_COLLISIONS:
+ case OID_802_3_XMIT_TIMES_CRS_LOST:
+ lvalue = ethobjs->RSL_Excessive;
+ break;
+ default:
+ lvalue = ethobjs->RSL_FrameCheckSeq;
+ break;
+ }
+ copyptr = (PUCHAR)&lvalue;
+ break;
+
+ default:
+ DebugPrint(1,("NF(%d): Invalid Query or Unsupported OID, %x\n",acb->anum,Oid));
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ needcopy = FALSE;
+ break;
+ }
+
+ if (needcopy)
+ {
+ // Do we have enough space for the list + the oid value + the length?
+ //
+ if (InformationBufferLength < (USHORT) copylen)
+ {
+ DebugPrint(1,("NF(%d): Tell the user of the bytes needed\n",acb->anum));
+ *BytesNeeded = copylen - InformationBufferLength;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ // Copy the data bytes
+ //
+ NdisMoveMemory( InformationBuffer,
+ copyptr,
+ copylen);
+ //
+ // Update the information pointer and size.
+ //
+ *BytesWritten += copylen;
+ }
+ }
+ }
+
+ //
+ // Complete the request
+ //
+ NdisMQueryInformationComplete( acb->acb_handle,
+ Status );
+ acb->RequestInProgress = FALSE;
+
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexGetUpstreamAddress
+//
+// Description:
+// This routine gets the upstream neighbor of
+// the adapter in Token-Ring.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is returned.
+//
+// Called By:
+// NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexGetUpstreamAddress(
+ PACB acb
+ )
+{
+ USHORT value;
+ SHORT i;
+
+ NdisRawWritePortUshort(acb->SifAddrPort, acb->acb_upstreamaddrptr+4 );
+
+ for (i = 0; i < 3; i++)
+ {
+ NdisRawReadPortUshort(acb->SifDIncPort,(PUSHORT) &value);
+
+ ((PTR_OBJS)(acb->acb_spec_objs))->upstream_addr[i*2] =
+ (UCHAR)(SWAPS(value));
+ ((PTR_OBJS)(acb->acb_spec_objs))->upstream_addr[(i*2)+1] =
+ (UCHAR)value;
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexProcessMacReq
+//
+// Description:
+// This routine completes a request which had to wait
+// for a adapter command to complete.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexHandleInterrupt
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexProcessMacReq(
+ PACB acb
+ )
+{
+
+ NDIS_STATUS status;
+ PMACREQ macreq;
+ BOOLEAN ReceiveResult;
+
+ DebugPrint(1,("NF(%d): NetFlexProcessMacReq entered.\n", acb->anum));
+
+ while (acb->acb_confirm_qhead != NULL)
+ {
+ // We have command to complete.
+ //
+ macreq = acb->acb_confirm_qhead;
+ if ((acb->acb_confirm_qhead = macreq->req_next) == NULL)
+ {
+ acb->acb_confirm_qtail = NULL;
+ }
+ //
+ // what was the status...
+ //
+ status = macreq->req_status;
+
+ switch (macreq->req_type)
+ {
+ case OPENADAPTER_CMP:
+
+ //
+ // Cancel the Reset Timer, since the hardware seems to be working correctly
+ //
+ NdisMCancelTimer(&acb->ResetTimer,&ReceiveResult);
+
+ //
+ // Did the open complete successfully?
+ //
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ // Yes, mark as opened.
+ //
+ acb->acb_lastopenstat = 0;
+ acb->acb_lastringstate = NdisRingStateOpened;
+
+ //
+ // If the open completed successfully, we need to
+ // issue the transmit and receive commands. Also,
+ // we need to set the state according to the status.
+ //
+ if (acb->acb_state == AS_OPENING)
+ {
+ acb->acb_state = AS_OPENED;
+ }
+
+ //
+ // Now lets finish the open by sending a receive command to the adapter.
+ //
+ acb->acb_rcv_whead = acb->acb_rcv_head;
+
+ //
+ // Now lets finish the open by sending a
+ // transmit and receive command to the adapter.
+ //
+ acb->acb_xmit_whead = acb->acb_xmit_wtail = acb->acb_xmit_head;
+
+ //
+ // If the adapter is ready for a command, call a
+ // routine that will kick off the transmit command.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if (!acb->acb_scbclearout)
+ {
+ //
+ // Make sure we are interrupted when the SCB is
+ // available so that we can send the transmit command.
+ //
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort(
+ acb->SifIntPort,
+ (USHORT)SIFINT_SCBREQST);
+ }
+ }
+ else
+ {
+ // Open failed.
+ // If we had an open error that is specific to TOKEN RING,
+ // set the last open status to the correct error code. Otherwise,
+ // just send the status as normal.
+ //
+ if (macreq->req_status == NDIS_STATUS_TOKEN_RING_OPEN_ERROR)
+ {
+ acb->acb_lastopenstat = (NDIS_STATUS)(macreq->req_info) |
+ NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
+ }
+ else
+ {
+ acb->acb_lastopenstat = 0;
+ }
+ acb->acb_lastringstate = NdisRingStateOpenFailure;
+
+ if (acb->acb_state == AS_OPENING)
+ {
+ acb->acb_state = AS_INITIALIZED;
+ }
+ //
+ // Force a reset.
+ //
+ acb->ResetState = RESET_STAGE_4;
+ }
+
+ //
+ // Put Macreq back on free queue
+ //
+ NetFlexEnqueue_OnePtrQ_Head((PVOID *)&(acb->acb_macreq_free),
+ (PVOID)macreq);
+
+
+ //
+ //
+ // processed the open command.
+ //
+
+ if (acb->ResetState == RESET_STAGE_4)
+ {
+ //
+ // If this is the completion of a Reset, set the reset timer
+ // so it can be completed.
+ //
+ NdisMSetTimer(&acb->ResetTimer,10);
+ }
+ break;
+
+ case CLOSEADAPTER_CMP:
+ acb->acb_state = AS_CLOSING;
+ break;
+
+ case QUERY_CMP:
+ case REQUEST_CMP:
+
+ if (acb->RequestInProgress)
+ {
+ //
+ // Go process the request
+ // Is it a Query or a Set?
+ //
+ if (macreq->req_type == QUERY_CMP)
+ {
+ NetFlexFinishQueryInformation(acb,status);
+ }
+ else
+ {
+ DebugPrint(1,("NF(%d): NetFlexProcessMacReq: Completing request.\n", acb->anum));
+
+ acb->RequestInProgress = FALSE;
+ NdisMSetInformationComplete(acb->acb_handle, status);
+ }
+ }
+ else
+ {
+ DebugPrint(0,("NF(%d): Have macreq QUERY_CMP or REQUEST_CMP without RequestInProgress!\n",acb->anum));
+ }
+
+ NdisZeroMemory(macreq, sizeof(MACREQ));
+ NetFlexEnqueue_OnePtrQ_Head(
+ (PVOID *)&(acb->acb_macreq_free),
+ (PVOID)macreq
+ );
+
+ break;
+
+ default: // We should NEVER be here
+ DebugPrint(0,("NF(%d): ProcessMaqReq - No command - ERROR!\n",acb->anum));
+ break;
+ } // End of switch
+ } // End of while confirm q
+}
diff --git a/private/ntos/ndis/netflex/reset.c b/private/ntos/ndis/netflex/reset.c
new file mode 100644
index 000000000..f907de47e
--- /dev/null
+++ b/private/ntos/ndis/netflex/reset.c
@@ -0,0 +1,1924 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: RESET.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexResetDispatch
+//
+// Description:
+// Kick off a reset!
+//
+// Input:
+// MiniportAdapterContext - really our acb.
+//
+// Output:
+// Returns NDIS_STATUS_PENDING unless we are already handling a reset,
+// in which case we return NDIS_STATUS_RESET_IN_PROGRESS.
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexResetDispatch(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ BOOLEAN ReceiveResult = FALSE;
+
+ DebugPrint(1,("NF(%d): Reset Called!\n",acb->anum));
+
+ if ( acb->ResetState && (acb->ResetState != RESET_HALTED))
+ {
+ return NDIS_STATUS_RESET_IN_PROGRESS;
+ }
+
+ acb->acb_lastringstate = NdisRingStateClosed;
+ acb->acb_state = AS_RESETTING;
+ acb->ResetState = RESET_STAGE_1;
+
+ //
+ // Cancel the DPC Timer!
+ //
+
+ NdisMCancelTimer(&acb->DpcTimer,&ReceiveResult);
+
+ //
+ // Set the timer for the NetFlexResetHandler DPC.
+ //
+ NdisMSetTimer(&acb->ResetTimer,500 );
+
+ return NDIS_STATUS_PENDING;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexResetHandler
+//
+// Description:
+// Performs that operations to put the adatper
+// through a reset and back into operation.
+//
+//
+// Input:
+//
+// SystemSpecific1 - Not used.
+// acb - The Adapter whose hardware is being reset.
+// SystemSpecific2 - Not used.
+// SystemSpecific3 - Not used.
+//
+// Output:
+// None.
+//
+// Called By:
+// via acb->ResetTimer
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexResetHandler(
+ IN PVOID SystemSpecific1,
+ IN PACB acb,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+{
+ NDIS_STATUS Status;
+ BOOLEAN ReceiveResult;
+ BOOLEAN DoneWReset;
+
+ //
+ // Cancel the reset timer
+ //
+ NdisMCancelTimer(&acb->ResetTimer,&ReceiveResult);
+
+ do
+ {
+ DoneWReset = TRUE; // default to true...
+
+ //
+ // Based on the current acb->ResetState, proceed with the reset.
+ //
+ switch(acb->ResetState)
+ {
+
+ case RESET_STAGE_1:
+
+ acb->ResetRetries = 0;
+ acb->InitRetries = 0;
+
+ //
+ // Issue Close
+ //
+ NetFlexCloseAdapter(acb);
+
+ //
+ // Remove all xmit mappings, and clean up queues
+ //
+ NetFlexRemoveRequests(acb);
+ acb->ResetState = RESET_STAGE_2;
+
+ case RESET_STAGE_2:
+
+ //
+ // Try soft resetting adapter
+ //
+ Status = NetFlexAdapterReset(acb,SOFT_RESET);
+ //
+ // Was the reset successful?
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // No!
+ // Increment the retry count
+ //
+ acb->ResetRetries++;
+ //
+ // have we tried 3 times?
+ //
+ if (acb->ResetRetries < 3 )
+ {
+ // no, try it again in 10 sec
+ //
+ NdisMSetTimer(&acb->ResetTimer,10000 );
+ }
+ else
+ {
+ // yes, try a hard reset
+ //
+ acb->ResetState = RESET_STAGE_3;
+ acb->ResetRetries = 0;
+ DoneWReset = FALSE;
+ }
+ break;
+ }
+
+ //
+ // Yes, soft reset was successful, send open request...
+ // Note: When the Open request completes/fails
+ // we wind up in Reset_Stage_4.
+ //
+ acb->ResetState = RESET_STAGE_4;
+ acb->InitRetries++;
+
+ NetFlexOpenAdapter(acb);
+
+ //
+ // Give the Open 20 seconds to Complete
+ //
+ NdisMSetTimer(&acb->ResetTimer,20000);
+ break;
+
+ case RESET_STAGE_3:
+ //
+ // Perform Hard Reset!
+ //
+ Status = NetFlexAdapterReset(acb,HARD_RESET);
+ //
+ // Was the reset successful?
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // No!
+ // Increment the retry count
+ //
+ acb->ResetRetries++;
+ //
+ // have we tried Hard Reset 3 times?
+ //
+ if (acb->ResetRetries < 3 )
+ {
+ // no, try it again in 10 sec
+ //
+ acb->ResetState = RESET_STAGE_3;
+ NdisMSetTimer(&acb->ResetTimer,10000 );
+ }
+ else
+ {
+ // Hard Reset timed out, do the reset indications.
+ //
+ DebugPrint(0,("NF(%d): Reset - Exceeded Hard Reset Retries\n",acb->anum));
+ NetFlexDoResetIndications(acb,NDIS_STATUS_FAILURE);
+ }
+ break;
+ }
+
+ //
+ // Yes, hard reset was successful, go do init stuff...
+ //
+ acb->ResetState = RESET_STAGE_4;
+ //
+ // Send Open Comand, when complete, we end up in Reset_Stage_4
+ //
+ NetFlexOpenAdapter(acb);
+ //
+ // Give the Open 20 seconds to Complete
+ //
+ NdisMSetTimer(&acb->ResetTimer,20000);
+ break;
+
+ case RESET_STAGE_4:
+
+ //
+ // Increment the retry count
+ //
+ acb->InitRetries++;
+
+ if (acb->acb_state != AS_OPENED)
+ {
+ // Have we expired the retry count, do the indications
+ //
+ if (acb->InitRetries > 4)
+ {
+ DebugPrint(0,("NF(%d): Reset - Exceeded Open Retries\n",acb->anum));
+
+ NetFlexDoResetIndications(acb,NDIS_STATUS_FAILURE);
+ }
+ else
+ {
+ // Perform a Soft Reset again!
+ //
+ acb->ResetState = RESET_STAGE_2;
+ DoneWReset = FALSE;
+ }
+ }
+ else
+ {
+ // We were successful!
+ //
+ NetFlexDoResetIndications(acb,NDIS_STATUS_SUCCESS);
+ }
+ break;
+ }
+ } while (!DoneWReset);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDoResetIndications
+//
+// Description:
+// This routine is called by NetFlexResetHandler to perform any
+// indications which need to be done after a reset. Note that
+// this routine will be called after either a successful reset
+// or a failed reset.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Status - The status of the reset to send to the protocol(s).
+//
+// Called By:
+// NetFlexResetHandler
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDoResetIndications(
+ IN PACB acb,
+ IN NDIS_STATUS Status
+ )
+{
+ USHORT actl_reg;
+ //
+ // If we have a bad result, we stop the chip and do the indication
+ // back to the protocol(s).
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Reset failed!\n",acb->anum));
+
+ //
+ // Stop the chip
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg));
+ actl_reg |= ACTL_ARESET;
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg);
+
+ //
+ // Reset has failed, errorlog an entry if
+ // did not already send out a message.
+ //
+ if (!acb->ResetErrorLogged)
+ {
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_RESET_FAILURE_ERROR,
+ 1,
+ NETFLEX_RESET_FAILURE_ERROR_CODE
+ );
+ acb->ResetErrorLogged = TRUE;
+ }
+
+ acb->ResetState = RESET_HALTED;
+ acb->acb_state = AS_CARDERROR;
+ Status = NDIS_STATUS_HARD_ERRORS;
+
+ }
+
+ //
+ // Verify that the dpc timer is set.
+ //
+ NdisMSetTimer(&acb->DpcTimer,10);
+
+ NdisMResetComplete( acb->acb_handle,
+ Status,
+ TRUE );
+
+ //
+ // We are no longer resetting the Adapter.
+ //
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ acb->ResetState = 0;
+
+ //
+ // Did we send out a message that a reset failed before?
+ //
+ if (acb->ResetErrorLogged)
+ {
+ //
+ // Log the fact that everything is ok now...
+ //
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_RESET_FAILURE_CORRECTION,
+ 0);
+
+ acb->ResetErrorLogged = FALSE;
+ }
+ else
+ {
+ if (acb->acb_lastringstatus &
+ ( NDIS_RING_SIGNAL_LOSS |
+ NDIS_RING_LOBE_WIRE_FAULT |
+ NDIS_RING_AUTO_REMOVAL_ERROR |
+ NDIS_RING_REMOVE_RECEIVED
+ ))
+ {
+ //
+ // Log the fact that we have reinserted in a TR MAU...
+ //
+ acb->SentRingStatusLog = FALSE;
+ acb->acb_lastringstatus = 0;
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_TOKEN_RING_CORRECTION,
+ 0);
+
+ }
+ }
+ }
+
+ DebugPrint(1,("NF(%d): Reset Complete.\n",acb->anum));
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexCheckForHang
+//
+// Description:
+// This function simply gets call once every two seconds to
+// check on the head of the command block queue.
+// It will fire off the queue if the head has been sleeping on
+// the job.
+//
+// It also detects when the NetFlex adapter has failed, where the
+// symptoms are that the adapter will transmit packets, but will
+// not receive them.
+//
+// Input: acb - Our Driver Context.
+//
+// Output: True if we think the adapter is hung..
+//
+// Called By: Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+BOOLEAN
+NetFlexCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PXMIT xmitptr;
+ PMACREQ macreq;
+ PSCBREQ scbreq;
+
+ PACB acb = (PACB) MiniportAdapterContext;
+
+ //
+ // If we're run into a hard error, return true
+ //
+
+ if (acb->acb_state == AS_HARDERROR)
+ {
+ return TRUE;
+ }
+
+ //
+ // If we're not open return false
+ //
+ else if (acb->acb_state != AS_OPENED)
+ {
+ return FALSE;
+ }
+
+ //
+ // Is there a command outstanding?
+ //
+ if (acb->acb_scbreq_head != NULL)
+ {
+ scbreq = acb->acb_scbreq_head;
+ macreq = scbreq->req_macreq;
+
+ if (macreq != NULL)
+ {
+ // See if the command block has timed-out.
+ //
+ if (macreq->req_timeout)
+ {
+ // See if we have given it enough time
+ //
+ if ( macreq->req_timeoutcount >= 40)
+ {
+ DebugPrint(1,("NF(%d): CheckHang - Command Timed Out!\n",acb->anum));
+ return TRUE;
+ }
+ else
+ {
+ macreq->req_timeoutcount++;
+ }
+ }
+ else
+ {
+ // Start testing this command to check timeout
+ //
+ macreq->req_timeout = TRUE;
+ macreq->req_timeoutcount = 0;
+ }
+ }
+ }
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisAcquireSpinLock(&acb->XmitLock);
+ }
+
+ //
+ // See if there is any xmits which have not been processed
+ //
+ if (acb->acb_xmit_ahead != NULL)
+ {
+ xmitptr = acb->acb_xmit_ahead;
+
+ if (xmitptr->XMIT_Timeout)
+ {
+#if DBG
+ if (xmitptr->XMIT_CSTAT & XCSTAT_COMPLETE)
+ {
+ DebugPrint(0,("NF(%d): CheckHang - Xmit Complete but Xmit Timed Out!\n",acb->anum));
+ }
+ else
+ {
+ DebugPrint(0,("NF(%d): CheckHang - Xmit Timed Out!\n",acb->anum));
+ }
+#endif
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return TRUE;
+ }
+ xmitptr->XMIT_Timeout++;
+ }
+
+ //
+ // If we are in full-duplex mode then that is the extent of our
+ // checking to see if we are hung. If we are in half-duplex mode
+ // then we might want to send a dummy packet to see if our receiver
+ // is working correctly....
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ //
+ // Should we do extreme checking?
+ //
+ if (!acb->acb_parms->utd_extremecheckforhang)
+ {
+ return(FALSE);
+ }
+
+ //
+ // Have we been getting interrupts?
+ //
+ if (acb->acb_int_count != 0)
+ {
+ //
+ // We got some, initialize the counts.
+ //
+ acb->acb_int_count = 0;
+ acb->acb_int_timeout = 0;
+ }
+ else
+ {
+ //
+ // Increment the timeout count.
+ //
+ acb->acb_int_timeout++;
+
+ //
+ // We will do this 5 times before we reset.
+ //
+ if (5 == acb->acb_int_timeout)
+ {
+ //
+ // Clear our counts and request a reset.
+ //
+ acb->acb_int_timeout = 0;
+ acb->acb_int_count = 0;
+
+ return(TRUE);
+ }
+ }
+
+ //
+ // Not certain we're hung yet...
+ //
+ return FALSE;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexOpenAdapter
+//
+// Description:
+// This routine is called to queue up and issue
+// an open command to the adapter.
+//
+// If the system is still in initialization, then
+// the routine polls for the open command to complete,
+// otherwise, the interrupt hander processes the complete
+// and then returns to the reset handler for completion.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Success or Failure.
+//
+// Called By:
+// NetFlexResetHandler, NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexOpenAdapter(
+ PACB acb
+ )
+{
+ NDIS_STATUS Status;
+ PMACREQ macreq;
+ PSCBREQ scbreq;
+ ULONG Counter=0;
+
+ //
+ // Open Adapter
+ //
+ acb->acb_state = AS_OPENING;
+ acb->acb_lastringstate = NdisRingStateOpening;
+
+ //
+ // Are we doing an open for reset or during initialization?
+ //
+ if (!acb->AdapterInitializing)
+ {
+ //
+ // Get a free block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Could not get an SCBREQ for the Open Command\n",acb->anum));
+ return Status;
+ }
+
+ acb->acb_opnblk_virtptr->OPEN_Options = acb->acb_openoptions;
+ scbreq->req_scb.SCB_Cmd = TMS_OPEN;
+ scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_opnblk_physptr)));
+
+ Status = NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free),
+ (PVOID *)&macreq);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // We have no more room for another request currently
+ //
+ DebugPrint(0,("NF(%d): No macreq for the Open Command\n",acb->anum));
+ //
+ // Put the SCBREQ back...
+ //
+ NetFlexEnqueue_OnePtrQ_Head((PVOID *)&acb->acb_scbreq_free,(PVOID)scbreq);
+ return Status;
+ }
+
+ macreq->req_info = 0;
+ macreq->req_type = OPENADAPTER_CMP;
+ macreq->req_status = NDIS_STATUS_SUCCESS;
+ scbreq->req_macreq = macreq;
+
+ NetFlexEnqueue_TwoPtrQ_Tail((PVOID *)&(acb->acb_macreq_head),
+ (PVOID *)&(acb->acb_macreq_tail),
+ (PVOID)macreq);
+ //
+ // Verify that interrupts are enabled!
+ //
+ NetFlexEnableInterrupt(acb);
+
+ //
+ // Send the command out...
+ //
+ NetFlexQueueSCB(acb, scbreq);
+
+ //
+ // Note: acb->ErrorCode will be set while processing the
+ // open command complete if there is an error.
+ //
+ }
+ else
+ {
+ //
+ // Open for Initialization
+ //
+ ULONG Counter = 0;
+ ULONG CounterTimeOut = 2000; // 2 seconds in miliseconds
+ USHORT sifint_reg;
+
+ Status = NDIS_STATUS_FAILURE;
+
+ //
+ // Make sure the command is clear, try for 2 seconds
+ //
+ while ((acb->acb_scb_virtptr->SCB_Cmd != 0) && (Counter++ < CounterTimeOut))
+ NdisStallExecution((UINT)1000);
+
+ if (Counter < CounterTimeOut)
+ {
+ // Get the command together...
+ //
+ acb->acb_opnblk_virtptr->OPEN_Options = acb->acb_openoptions;
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_OPEN;
+ acb->acb_scb_virtptr->SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_opnblk_physptr)));
+
+ //
+ // Make sure interrupts are disabled!
+ //
+ NetFlexDisableInterrupt(acb);
+
+ //
+ // Send the SCB to the adapter.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, SIFINT_CMD);
+
+ Counter = 0;
+ CounterTimeOut = 20000; // 20 seconds in miliseconds
+
+ do
+ {
+ Counter++;
+ NdisStallExecution((UINT)1000); // 1 milisecond in microseconds
+ //
+ // Read the Sifint register.
+ //
+ NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg);
+
+ //
+ // Is there an interrupt pending?
+ //
+ if ((sifint_reg & SIFINT_SYSINT) && ((sifint_reg & INT_CODES) == INT_COMMAND))
+ {
+
+ // Ack the interrupt
+ //
+ sifint_reg &= ~SIFINT_SYSINT;
+ NdisRawWritePortUshort( acb->SifIntPort, sifint_reg);
+
+ if (acb->acb_ssb_virtptr->SSB_Status == SSB_GOOD)
+ {
+ Status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status));
+
+ if (acb->acb_ssb_virtptr->SSB_Status & SSB_OPENERR) // only Token Ring
+ {
+ Status = NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
+ acb->acb_lastopenstat = NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
+ }
+ else
+ {
+ acb->acb_lastopenstat = 0;
+ }
+ acb->acb_lastringstate = NdisRingStateOpenFailure;
+ }
+ //
+ // Issue a ssb clear.
+ //
+ NdisRawWritePortUshort( acb->SifIntPort, SIFINT_SSBCLEAR);
+
+ break;
+ }
+ } while (Counter < CounterTimeOut);
+ }
+
+ //
+ // Did it work?
+ //
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // Set State to Opened
+ //
+ acb->acb_state = AS_OPENED;
+ //
+ // Now lets finish the open by sending a receive command to the adapter.
+ //
+ acb->acb_rcv_whead = acb->acb_rcv_head;
+
+ //
+ // Now lets finish the open by sending a
+ // transmit command to the adapter.
+ //
+
+ acb->acb_xmit_whead = acb->acb_xmit_wtail = acb->acb_xmit_head;
+
+ //
+ // Verify that interrupts are enabled!
+ //
+ NetFlexEnableInterrupt(acb);
+
+ //
+ // If the adapter is ready for a command, call a
+ // routine that will kick off the transmit command.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if (!acb->acb_scbclearout)
+ {
+ // Make sure we are interrupted when the SCB is
+ // available so that we can send the transmit command.
+ //
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_SCBREQST);
+ }
+ }
+ else
+ {
+ // Set State back to Initialized since the open failed.
+ //
+ acb->acb_state = AS_INITIALIZED;
+ }
+ }
+
+ return Status;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexCloseAdapter
+//
+// Description:
+// This routine is called to queue up and issue an close
+// command to the adapter.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Success or Failure.
+//
+// Called By:
+// NetFlexResetHandler
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+BOOLEAN
+NetFlexCloseAdapter(
+ PACB acb)
+
+{
+ USHORT Counter = 0;
+ USHORT CounterTimeOut = 500;
+
+ if ((acb->acb_state == AS_OPENED) ||
+ (acb->acb_state == AS_RESETTING))
+ {
+ //
+ // Make sure the command is clear, try for 5 seconds
+ //
+ while ((acb->acb_scb_virtptr->SCB_Cmd != 0) && (Counter++ < CounterTimeOut)) {
+
+ NdisStallExecution((UINT)1000);
+ }
+
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ //
+ // Send Close,
+ //
+
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_CLOSE;
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_CMD);
+
+ acb->acb_state = AS_CLOSING;
+ //
+ // Give it a little time...
+ //
+ NdisStallExecution((UINT)10000);
+ }
+
+ return (Counter >= CounterTimeOut);
+ }
+ return TRUE;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexHalt
+//
+// Description:
+// Removes an adapter previously initialized.
+//
+// Input:
+// MacAdapterContext - Actually as pointer to an PACB.
+//
+// Output:
+// None.
+//
+// Called By:
+// Miniport Wrapper.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ USHORT actl_reg;
+ BOOLEAN ReceiveResult1;
+ BOOLEAN ReceiveResult2;
+
+ //
+ // The adapter to halt
+ //
+ PACB acb = (PACB) MiniportAdapterContext;
+
+ DebugPrint(1,("NF(%d): Halt Called!\n", acb->anum));
+
+ //
+ // Cancel all of our timers.
+ //
+ NdisMCancelTimer(&acb->DpcTimer, &ReceiveResult1);
+ NdisMCancelTimer(&acb->ResetTimer, &ReceiveResult2);
+
+ //
+ // Is one of the timer dpc's going to fire?
+ //
+ if (!ReceiveResult1 || !ReceiveResult2)
+ {
+ NdisStallExecution(500000);
+ }
+
+ //
+ // Send Close
+ //
+ NetFlexCloseAdapter(acb);
+
+ //
+ // Stop Adapter
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg));
+ actl_reg |= ACTL_ARESET;
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg);
+
+ //
+ // Complete mappings
+ //
+ NetFlexRemoveRequests(acb);
+
+ //
+ // Free adapter resources
+ //
+ NetFlexDeregisterAdapter(acb);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexShutdown
+//
+// Description:
+// Removes an adapter previously initialized.
+//
+// Input:
+// MacAdapterContext - Actually as pointer to an PACB.
+//
+// Output:
+// None.
+//
+// Called By:
+// Miniport Wrapper.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexShutdown(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ USHORT actl_reg;
+
+ //
+ // Send Close.
+ //
+
+ NetFlexCloseAdapter(acb);
+
+ //
+ // Stop Adapter
+ //
+
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg));
+ actl_reg |= ACTL_ARESET;
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexRemoveRequests
+//
+// Description:
+// Clean up queues during a Reset and Halt
+//
+// Input:
+// acb - Pointer to acb
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexResetHandler,
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexRemoveRequests(
+ PACB acb
+ )
+{
+ PXMIT xmitptr;
+ PRCV rcvptr;
+ UINT curmap;
+ PNDIS_PACKET packet;
+ PNDIS_BUFFER curbuf;
+ PMULTI_TABLE mt;
+ PETH_OBJS ethobjs;
+ USHORT i;
+ PSCBREQ scbreq;
+ PMACREQ macreq;
+
+ //
+ // Terminate all the transmits on the active queue.
+ //
+ xmitptr = acb->acb_xmit_ahead;
+
+ while (xmitptr != NULL)
+ {
+ // Did we use an internal buffer?
+ //
+ if (xmitptr->XMIT_OurBufferPtr != NULL)
+ {
+ // We've used one of our adapter buffers, so put the adapter
+ // buffer back on the free list.
+ //
+ if (xmitptr->XMIT_OurBufferPtr->BufferSize != acb->acb_smallbufsz) {
+ xmitptr->XMIT_OurBufferPtr->Next = acb->OurBuffersListHead;
+ acb->OurBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ else { // small buffer
+ xmitptr->XMIT_OurBufferPtr->Next = acb->SmallBuffersListHead;
+ acb->SmallBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ xmitptr->XMIT_OurBufferPtr = NULL;
+ }
+ else
+ {
+ packet = xmitptr->XMIT_Packet;
+
+ if ( packet != NULL ) {
+
+ curmap = xmitptr->XMIT_MapReg;
+
+ // Complete mappings, but don't complete the sends...
+ //
+
+ NdisQueryPacket(
+ packet,
+ NULL,
+ NULL,
+ (PNDIS_BUFFER *) &curbuf,
+ NULL
+ );
+
+ while (curbuf)
+ {
+ NdisMCompleteBufferPhysicalMapping(
+ acb->acb_handle,
+ (PNDIS_BUFFER) curbuf,
+ curmap
+ );
+
+ curmap++;
+ if (curmap == acb->acb_maxmaps)
+ {
+ curmap = 0;
+ }
+
+ NdisGetNextBuffer(curbuf, &curbuf);
+ }
+ }
+ }
+
+ xmitptr->XMIT_CSTAT = 0;
+ xmitptr->XMIT_Packet = NULL;
+
+ //
+ // If we've reached the active queue tail, we are done.
+ //
+ if (xmitptr == acb->acb_xmit_atail)
+ xmitptr = NULL;
+ else
+ xmitptr = xmitptr->XMIT_Next;
+ }
+
+ acb->acb_xmit_ahead = acb->acb_xmit_atail = NULL;
+ acb->acb_avail_xmit = acb->acb_parms->utd_maxtrans;
+
+ //
+ // Clean up the Receive Lists
+ //
+
+ rcvptr = acb->acb_rcv_head;
+
+ do {
+
+ //
+ // Mark receive list available
+ //
+ rcvptr->RCV_CSTAT =
+ ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ //
+ // Get next receive list
+ //
+ rcvptr = rcvptr->RCV_Next;
+
+ } while (rcvptr != acb->acb_rcv_head);
+
+ //
+ // Clean up multicast if ethernet.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ ethobjs = (PETH_OBJS)acb->acb_spec_objs;
+
+ NdisZeroMemory(
+ ethobjs->MulticastEntries,
+ ethobjs->MaxMulticast * NET_ADDR_SIZE
+ );
+
+ ethobjs->NumberOfEntries = 0;
+ }
+
+ //
+ // Clean up SCB Requests
+ //
+ while (acb->acb_scbreq_head)
+ {
+ NetFlexDequeue_TwoPtrQ_Head((PVOID *)&acb->acb_scbreq_head,
+ (PVOID *)&acb->acb_scbreq_tail,
+ (PVOID *)&scbreq);
+
+ NdisZeroMemory(scbreq, sizeof(SCBREQ));
+
+ NetFlexEnqueue_OnePtrQ_Head((PVOID *)&acb->acb_scbreq_free,(PVOID)scbreq);
+
+ }
+
+ //
+ // Clean up MacReq Requests
+ //
+ while (acb->acb_macreq_head)
+ {
+ NetFlexDequeue_TwoPtrQ_Head((PVOID *)&acb->acb_macreq_head,
+ (PVOID *)&acb->acb_macreq_tail,
+ (PVOID *)&macreq);
+
+ NdisZeroMemory(macreq, sizeof(MACREQ));
+
+ NetFlexEnqueue_OnePtrQ_Head( (PVOID *)&acb->acb_macreq_free,
+ (PVOID)macreq);
+
+ }
+
+ //
+ // Clean Up some more State stuff...
+ //
+ acb->RequestInProgress = FALSE;
+ acb->acb_scbclearout = FALSE;
+ acb->acb_scbreq_next = NULL;
+ acb->acb_gen_objs.cur_filter = 0;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexAdapterReset
+//
+// Description:
+// This routine resets the Super Eagle or Eagle
+//
+// Input:
+// mode - 0 = Hard Reset, ~0 = Soft Reset
+//
+// Output:
+// status - NDIS_STATUS_SUCCESS if Success
+//
+// Called By:
+// NetFlexResetHandler
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexAdapterReset(
+ PACB acb,
+ INT mode)
+{
+ NDIS_STATUS status;
+
+ //
+ // Which Reset?
+ //
+ if (mode == HARD_RESET)
+ {
+
+ // Do the reset
+ //
+ NdisRawWritePortUshort(acb->SifActlPort, ACTL_HARD_RESET);
+
+ //
+ // Wait 15 milliseconds to let the reset take place.
+ //
+ NdisStallExecution((UINT)15000); // Wait 15 milliseconds
+
+ //
+ // Call NetFlexSetupNetType to verify everything gets set correctly.
+ //
+ NetFlexSetupNetType(acb);
+
+ //
+ // Make sure that promiscuous mode is turned off
+ //
+ acb->acb_opnblk_virtptr->OPEN_Options &= SWAPS((USHORT) ~(OOPTS_CNMAC | OOPTS_CMAC));
+
+ //
+ // Download and initialize the adapter
+ //
+ if ((status = NetFlexDownload(acb)) == NDIS_STATUS_SUCCESS)
+ {
+ // Verify Bring Up Diagnostics
+ //
+ if ((status = NetFlexBudWait(acb))== NDIS_STATUS_SUCCESS)
+ {
+ // Initialize the adapter
+ //
+ if ((status = NetFlexInitializeAdapter(acb)) == NDIS_STATUS_SUCCESS)
+ {
+ // Yes, do we need to save the address that will give up our upstream address?
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ {
+ // Yes, get it...
+ //
+ NetFlexGetUpstreamAddrPtr(acb);
+ }
+ }
+ }
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Hard Reset Failed!\n",acb->anum));
+ }
+ }
+ else
+ {
+ // A Soft Reset was requested. Write the reset code into the
+ // SIF interrupt register.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, SIF_SOFT_RESET);
+
+ //
+ // Write the saved ACTL Settings.
+ //
+ NdisRawWritePortUshort( acb->SifActlPort, acb->actl_reg);
+
+ //
+ // Go check to see if the bring up diagnostics worked...
+ //
+ if ((status = NetFlexBudWait(acb)) == NDIS_STATUS_SUCCESS)
+ {
+ status = NetFlexInitializeAdapter(acb);
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Soft Reset Failed!\n",acb->anum));
+ }
+ }
+
+ return status;
+}
+
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexBudWait
+//
+// Description:
+// This routine waits for the Bring Up Diags
+// (BUD) code to finish on the Super Eagle or Eagle
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// status - 0 = SUCCESS, ~0 = failure
+//
+// Called By:
+// NetFlexAdapterReset, NetFlexDownload
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexBudWait(
+ PACB acb
+ )
+{
+ int i;
+ USHORT value;
+
+ //
+ // Wait for Bring Up Diagnotics to start.
+ //
+ for (i = 0; i < 3000; i++)
+ {
+ NdisStallExecution((UINT)1000); /* Wait 1 millisecond */
+ NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) &value);
+ if ((value & 0x00f0) >= 0x0020)
+ break;
+ }
+
+ if (i >= 3000)
+ {
+ // Diags never got started!!
+ //
+ DebugPrint(0,("NF(%d): Diags never got started\n",acb->anum));
+ DebugPrint(0,("NF(%d): Sif int is 0x%x\n",acb->anum,value));
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ //
+ // Wait for either success or failure.
+ //
+ for (i = 0; i < 3000; i++)
+ {
+ NdisStallExecution((UINT)1000); /* Wait 1 millisecond */
+ NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) (&value));
+ if ((value & 0x00f0) >= 0x0030)
+ break;
+ }
+
+ if (i >= 3000)
+ {
+ // Diags never finished!!
+ //
+ DebugPrint(0,("NetFlex: Diags never finished\n"));
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ if ((value & 0x00f0) != 0x0040)
+ {
+ // Diags failed!!
+ //
+ DebugPrint(0,("NF(%d): Diags Failed!\n",acb->anum));
+ return(NDIS_STATUS_FAILURE);
+ }
+ else
+ {
+ // The Diags passed OK!
+ //
+ DebugPrint(0,("NF(%d): Diags Passed OK\n",acb->anum));
+ return(NDIS_STATUS_SUCCESS);
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexInitializeAdapter
+//
+// Description:
+// This routine initializes the adapter for open.
+//
+// Input:
+// acb - Our Driver Context
+//
+// Output:
+// Returns a NDIS_STATUS_SUCCESS if the adapter
+// initialized properly. Otherwise, an error code is returned,
+// showing that an initialization error has occurred.
+//
+// Called By:
+// NetFlexProcess_Open_Request
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexInitializeAdapter(
+ PACB acb
+ )
+{
+ ULONG temp;
+ INT i;
+ SHORT *ps;
+
+ //
+ // Set the SIF address register to point to the INIT block location
+ // and copy the INIT block info into the data inc register.
+ // make sure we are at chapter 1.
+ //
+ NdisRawWritePortUshort(acb->SifAddrxPort, (USHORT) 1);
+ NdisRawWritePortUshort(acb->SifAddrPort, (USHORT) ADDR_INIT);
+
+ for (i = 0, ps = (SHORT *) &acb->acb_initblk;
+ i < (SIZE_INIT / 2); i++, ps++)
+ {
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) *ps);
+ }
+
+ //
+ // Now write the SCB and SSB addresses into the
+ // data inc register.
+ //
+ temp = CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_scb_physptr) + sizeof(USHORT));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) (temp >> 16));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) temp);
+
+ temp = CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_ssb_physptr));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) (temp >> 16));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) temp);
+
+ //
+ // Now write the execute command out to the SIF.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_CMD);
+
+ //
+ // Wait for the intialization to complete.
+ //
+ for (i = 0; i < 3000; i++)
+ {
+ NdisStallExecution((UINT)1000); /* Wait 1 millisecond */
+ NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) (&temp));
+ if ((temp & 0x00ff) != 0x0040)
+ break;
+ }
+
+ if ( (i >= 3000) || ((temp & 0x00ff) != 0x0000) )
+ {
+ //
+ // Initialization never finished!! OR Initialization failed!!
+ //
+ return(NDIS_STATUS_FAILURE);
+
+ }
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDownload
+//
+// Description:
+// This routine downloads the TMS380 MAC code to the
+// Super Eagle or Eagle.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// status - 0 = SUCCESS, ~0 = failure
+//
+// Called By:
+// NetFlexAdapterReset
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexDownload(
+ PACB acb
+ )
+{
+ LONG j;
+ USHORT temp_value;
+ LONG totalbytes;
+ PUSHORT MappedBuffer;
+ PDL_STRUCT ds;
+ PUCHAR dataptr;
+
+ if (macgbls.DownloadCode == NULL)
+ {
+ DebugPrint(0,("NF(%d) - No Download code!\n",acb->anum));
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Get our pointers ready. Currently the MappedBuffer is pointing
+ // to the length of the header. The data begins after the header.
+ // Also the section headers are contained within the header just
+ // past the length field which is 2 bytes long.
+ //
+
+ MappedBuffer = macgbls.DownloadCode;
+
+ dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) );
+
+ ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2);
+
+ //
+ // If we're using FPA skip to the second set of mac code. The
+ // order of the mac code is TOK, ETH, TOKFPA and ETHFPA.
+ //
+ if (acb->acb_usefpa)
+ {
+ for (j=0; j<2; j++)
+ {
+ totalbytes = 0;
+ while (ds->dl_chap != 0x7ffe)
+ {
+ totalbytes += ds->dl_bytes;
+ ds++;
+ }
+
+ MappedBuffer = (PUSHORT)(dataptr + totalbytes);
+
+ dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) );
+ ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2);
+ }
+ }
+
+ //
+ // No need to perform a hard reset of the Super Eagle or Eagle
+ // since we have already done.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ //
+ // We need to skip around the download code for Token Ring.
+ // Therefore, find the end of the token ring download code.
+ //
+ totalbytes = 0;
+ while (ds->dl_chap != 0x7ffe)
+ {
+ totalbytes += ds->dl_bytes;
+ ds++;
+ }
+
+ MappedBuffer = (PUSHORT)(dataptr + totalbytes);
+
+ dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) );
+ ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2);
+ }
+
+ //
+ // Download each section of data
+ //
+ while (ds->dl_chap != 0x7ffe)
+ {
+ NdisRawWritePortUshort( acb->SifAddrxPort, (USHORT) ds->dl_chap);
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) ds->dl_addr);
+
+ for (j = 0; j < (ds->dl_bytes / 2); j++)
+ {
+ NdisRawWritePortUshort( acb->SifDIncPort,
+ (USHORT)(SWAPS(*( (PUSHORT)(dataptr)))) );
+ dataptr += 2;
+ }
+ ds++;
+ }
+
+ //
+ // Now turn off the CP halt bit in the ACTL register to let the
+ // TMS380 chipset startup. Wait for the BUD to finish and report
+ // the appropriate status code.
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&temp_value));
+
+ temp_value &= ~ACTL_CPHALT;
+
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) temp_value);
+
+ //
+ // Save the Current Actl value
+ //
+ acb->actl_reg = temp_value;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexSetupNetType
+//
+// Description:
+// This routine sets up the Super Eagle to run the type of
+// network and network speed requested by config. It assumes
+// that the adapter is in a halted state after reset.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is returned.
+//
+// Called By:
+// NetFlexResetHandler, NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexSetupNetType(
+ PACB acb
+ )
+{
+ USHORT cfg_reg, actl_reg;
+ USHORT cfg_reg2, tmp_reg;
+ UCHAR cfg_regl, cfg_regh;
+ NDIS_MEDIUM nettype;
+ ULONG netspeed;
+ USHORT board_id = acb->acb_boardid;
+
+ //
+ // Get the network type and speed the user set up in EISA config.
+ // The port address for the cfg port is odd which will cause an
+ // alignment fault on RISC.
+ //
+ // NdisRawReadPortUshort(acb->AdapterConfigPort, &cfg_reg);
+ NdisRawReadPortUchar(acb->AdapterConfigPort, &cfg_regl);
+ NdisRawReadPortUchar(acb->AdapterConfigPort+1, &cfg_regh);
+ cfg_reg = (cfg_regh << 8) + cfg_regl;
+
+ //
+ // Read the actl register and turn off the reset bit.
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, &actl_reg);
+
+ actl_reg &= ~ACTL_ARESET;
+
+ //
+ // If we're using FPA turn on ROM reserved bit 11
+ //
+ if (acb->acb_usefpa)
+ {
+ actl_reg |= ACTL_ROM;
+ }
+
+ //
+ // If the board is a Cpqtok board, just fill in the parameters,
+ // reset the board, and get out. If the board is a Netflx board,
+ // fill in the parameters, reset the board specifying the type and
+ // speed of the network, make sure we get what we asked for, and
+ // then get out.
+
+ if ( (board_id & NETFLEX_REVMASK) == CPQTOK_ID &&
+ (board_id != DURANGO_ID))
+ {
+ // This is a JUPITER board
+ //
+ DebugPrint(1,("NF(%d): Setting up Jupiter\n",acb->anum));
+
+ if (acb->AdapterInitializing)
+ {
+ nettype = NdisMedium802_5;
+ if (cfg_reg & CFG_16MBS)
+ netspeed = 4;
+ else
+ netspeed = 16;
+ //
+ // Setup the ProcessReceiveHandler
+ //
+ acb->ProcessReceiveHandler = &NetFlexProcessTrRcv;
+ }
+ }
+ else if ( ((board_id & NETFLEX_REVMASK) == NETFLEX_ID) ||
+ ((board_id & NETFLEX_REVMASK) == RODAN_ID) ||
+ (board_id == DURANGO_ID) )
+ {
+ //
+ // This is a NETFLEX, MAPLE, DURANGO or RODAN board
+ //
+ // The Nselout1 bit has been redefined as the media bit. If this
+ // bit is set to a 1, AUI/DB-9 has been selected. Otherwise,
+ // unshielded has been selected.
+ // If the CFG_MEDIA bit is set, Unshielded has been selected.
+
+ DebugPrint(1,("NF(%d): Setting up Netflx, Durango, or Rodan\n",acb->anum));
+
+ if (cfg_reg & CFG_MEDIA)
+ {
+ actl_reg &= (~ACTL_NSELOUT1);
+ }
+ else
+ {
+ actl_reg |= ACTL_NSELOUT1;
+ }
+
+ if (cfg_reg & CFG_16MBS)
+ {
+ actl_reg |= ACTL_NSELOUT0;
+ }
+ else
+ {
+ actl_reg &= (~ACTL_NSELOUT0);
+ }
+ }
+ else
+ {
+ // This is a BONSAI board
+ //
+ // Bits 3 and 2 represent net type for head 1 and 2, respectively.
+ DebugPrint(1,("NF(%d): Setting up Bonsai head %d\n",acb->anum,acb->acb_portnumber));
+
+ if (acb->acb_portnumber == PORT1)
+ {
+ if (cfg_reg & CFG_DUALPT_ADP1)
+ {
+ actl_reg &= (~ACTL_NSELOUT1);
+ }
+ else
+ {
+ actl_reg |= ACTL_NSELOUT1;
+ }
+ }
+ else
+ {
+ if (cfg_reg & CFG_DUALPT_ADP2)
+ {
+ actl_reg &= (~ACTL_NSELOUT1);
+ }
+ else
+ {
+ actl_reg |= ACTL_NSELOUT1;
+ }
+ }
+ }
+
+ NdisRawWritePortUshort(acb->SifActlPort, actl_reg);
+
+ //
+ // If this is during an initial initialization
+ //
+ if (acb->AdapterInitializing)
+ {
+ //
+ // If this is a NETFLEX type board, make sure we got what
+ // we were asking for
+ //
+ if ( ( (board_id & NETFLEX_REVMASK) == NETFLEX_ID ) ||
+ ( (board_id & NETFLEX_REVMASK) == BONSAI_ID ) ||
+ ( (board_id & NETFLEX_REVMASK) == RODAN_ID ) ||
+ (board_id == DURANGO_ID) )
+ {
+ NdisRawReadPortUshort( acb->SifActlPort, &actl_reg);
+ //
+ // Now, find out our network type and speed.
+ //
+ if (actl_reg & ACTL_TEST1)
+ {
+ //
+ // We are token ring. Are we 16 mbps or 4 mbps.
+ //
+ nettype = NdisMedium802_5;
+ if (actl_reg & ACTL_TEST0)
+ netspeed = 4;
+ else
+ netspeed = 16;
+
+ //
+ // Setup the ProcessReceiveHandler
+ //
+ acb->ProcessReceiveHandler = &NetFlexProcessTrRcv;
+
+ }
+ else
+ {
+ // Ethernet is selected
+ nettype = NdisMedium802_3;
+ netspeed = 10;
+ //
+ // Setup the ProcessReceiveHandler
+ //
+ acb->ProcessReceiveHandler = &NetFlexProcessEthRcv;
+ }
+ }
+ //
+ // Initialize some of acb fields as well as adapter information.
+ //
+ acb->acb_gen_objs.media_type_in_use = nettype;
+ acb->acb_gen_objs.link_speed = netspeed;
+ }
+ else
+ {
+ nettype = acb->acb_gen_objs.media_type_in_use;
+ netspeed = acb->acb_gen_objs.link_speed;
+ }
+
+ //
+ // Check Full Duplex Support... Ethernet Only!
+ //
+ if (nettype == NdisMedium802_3)
+ {
+ // Do we want Full Duplex?
+ //
+
+ if (acb->acb_portnumber != PORT2)
+ {
+ NdisRawReadPortUchar( acb->BasePorts + CFG_REG2_OFF , &cfg_reg2);
+ if (cfg_reg2 & CFG_FULL_DUPLEX)
+ {
+ acb->FullDuplexEnabled = TRUE;
+ }
+ }
+ else
+ {
+ NdisRawReadPortUchar( acb->BasePorts + CFG_REG2_OFF - DUALHEAD_CFG_PORT_OFFSET, &cfg_reg2);
+ if (cfg_reg2 & CFG_FULL_DUPLEX_HEAD2)
+ {
+ acb->FullDuplexEnabled = TRUE;
+ }
+ }
+
+ if (acb->FullDuplexEnabled)
+ {
+ DebugPrint(1,("NF(%d): Enabling FullDuplex Support!\n",acb->anum));
+ if ( (board_id & NETFLEX_REVMASK) == BONSAI_ID )
+ {
+ // On Bansai, disable colision detect by writing to 0xZc67 for H2 0xZc66 for H1
+ //
+ if (acb->acb_portnumber == PORT2)
+ {
+ NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_HEAD2_OFF , 0xff);
+ }
+ else
+ {
+ NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_HEAD1_OFF , 0xff);
+ }
+ }
+ else
+ {
+ // On NetFlex/NetFlex-2, disable colision detect by writing to 0xZc65
+ // until status indicates that it is ok, per Ray...
+ //
+ do
+ {
+ NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_OFF , 0xff);
+ NdisStallExecution((UINT)1000); // Wait 1 milliseconds
+ NdisRawReadPortUchar( acb->ExtConfigPorts + LOOP_BACK_STATUS_OFF , &tmp_reg);
+ } while (tmp_reg & COLL_DETECT_ENABLED);
+ }
+ }
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexFinishUnloading
+//
+// Description: This routine finishes the unloading process
+//
+// Input: None.
+//
+// Output: None.
+//
+// Calls: NdisDeregisterMac,NdisTerminateWrapper,
+//
+// Called By: NetFlexUnload, NetFlexDeregisterAdapter
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexFinishUnloading(VOID)
+{
+ //
+ //
+ // Free the memory with the download software in it.
+ //
+ if (macgbls.DownloadCode != NULL) {
+
+ NdisFreeMemory( macgbls.DownloadCode,
+ macgbls.DownloadLength,
+ 0);
+
+ }
+
+ NdisTerminateWrapper(macgbls.mac_wrapper,(PVOID)NULL);
+ macgbls.mac_wrapper = NULL;
+ macgbls.DownloadCode= NULL;
+ macgbls.DownloadLength = 0;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDeregisterAdapter
+//
+// Description:
+// This routine finishes the removal of an adapter.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// None.
+//
+// Called By:
+// NetFlexHalt, NetFlexInitialize
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexDeregisterAdapter(PACB acb)
+{
+ //
+ // Remove the acb from the mac's acb list
+ //
+ NetFlexDequeue_OnePtrQ((PVOID *) &macgbls.mac_adapters,(PVOID)acb);
+
+ if (acb->acb_interrupt.InterruptObject != NULL)
+ NdisMDeregisterInterrupt(&acb->acb_interrupt);
+
+ //
+ // Deallocate the memory for the acb.
+ //
+ NetFlexDeallocateAcb(acb);
+
+ if ((macgbls.mac_adapters == NULL) && !macgbls.Initializing)
+ {
+ NetFlexFinishUnloading();
+ }
+}
+
diff --git a/private/ntos/ndis/netflex/sources b/private/ntos/ndis/netflex/sources
new file mode 100644
index 000000000..22fd6def5
--- /dev/null
+++ b/private/ntos/ndis/netflex/sources
@@ -0,0 +1,84 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ Carol Fuss 13-July-1992 - Converted for the Netflx driver.
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=ndis
+
+TARGETNAME=netflx
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+
+#
+# Standard Dynamic Ratio w/o Xmit Ints
+#
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DDBGPRINT=0
+
+#
+# Add Xmit Ints
+#
+C_DEFINES=$(C_DEFINES) -DXMIT_INTS
+
+#
+# Add Newer Dynamic Ratio
+#
+C_DEFINES=$(C_DEFINES) -DNEW_DYNAMIC_RATIO
+
+#
+# Add dynamic ratio history.
+#
+#C_DEFINES=$(C_DEFINES) -DDYNAMIC_RATIO_HISTORY
+
+#
+# Turn on dynamic ratio stuff.
+#
+C_DEFINES=$(C_DEFINES) -DALLOW_DISABLE_DYNAMIC_RATIO
+
+#
+# Turn off binary compatibility. Comment out the line below to enable it.
+#
+C_DEFINES=$(C_DEFINES) -DBINARY_COMPATIBLE=0 -DNDIS40_MINIPORT
+
+INCLUDES=..\..\inc;..\..\..\inc
+
+NTPROFILEINPUT=yes
+
+
+SOURCES= init.c \
+ initd.c \
+ int.c \
+ request.c \
+ receive.c \
+ reset.c \
+ support.c \
+ netflex.rc \
+ transmit.c
+
+RELATIVE_DEPTH=..\..
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTTARGETFILES=netflx.bin
diff --git a/private/ntos/ndis/netflex/support.c b/private/ntos/ndis/netflex/support.c
new file mode 100644
index 000000000..73a0dc74b
--- /dev/null
+++ b/private/ntos/ndis/netflex/support.c
@@ -0,0 +1,1986 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: SUPPORT.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#if (DBG || DBGPRINT)
+#include <stdarg.h>
+#include <stdio.h>
+
+#endif
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+
+#if (DBG || DBGPRINT)
+ULONG DebugLevel=1;
+#endif
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexInitializeAcb
+//
+// Description: This routine initializes the given ACB. This
+// routine allocates memory for certain fields
+// pointed to by the ACB.
+//
+// Input: acb - Pointer to acb to fill in.
+// parms - Settable mac driver parms.
+//
+// Output: Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is
+// returned.
+//
+// Calls: NdisAllocateMemory,NdisZeroMemory,NdisMoveMemory
+// NdisMAllocateSharedMemory,SWAPL,CTRL_ADDR
+//
+// Called By: NetFlexInitialize
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexInitializeAcb(PACB acb)
+{
+ USHORT i;
+
+ PRCV CurrentReceiveEntry;
+ PXMIT CurrentXmitEntry;
+ PVOID start, next, current;
+ ULONG next_phys, current_phys, temp;
+ PETH_OBJS ethobjs;
+ NDIS_STATUS Status;
+ PBUFFER_DESCRIPTOR OurBuf;
+ ULONG LowPart;
+ PUCHAR CurrentReceiveBuffer;
+ PUCHAR CurrentMergeBuffer;
+ PNETFLEX_PARMS parms = acb->acb_parms;
+ ULONG Alignment, FrameSizeCacheAligned;
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb entered.\n",acb->anum));
+
+ //
+ // Initialize pointers and counters
+ //
+ acb->InterruptsDisabled = FALSE; // interrupts are enabled after a reset.
+ acb->ResetState = 0;
+
+ //
+ // Set up rest of general oid variables.
+ //
+ acb->acb_smallbufsz = parms->utd_smallbufsz;
+ acb->acb_maxmaps = parms->utd_maxtrans * MAX_BUFS_PER_XMIT;
+ acb->acb_gen_objs.max_frame_size = parms->utd_maxframesz;
+ acb->acb_lastringstate = NdisRingStateClosed;
+ acb->acb_curmap = 0;
+
+ //
+ // Get the max frame size, cache align it and a save it for later.
+ //
+
+ Alignment = NdisGetCacheFillSize();
+
+ if ( Alignment < sizeof(ULONG) ) {
+
+ Alignment = sizeof(ULONG);
+ }
+
+ FrameSizeCacheAligned = (parms->utd_maxframesz + Alignment - 1) & ~(Alignment - 1);
+
+ //
+ // Allocate the map registers
+ //
+
+ if (NdisMAllocateMapRegisters(
+ acb->acb_handle,
+ 0,
+ TRUE,
+ acb->acb_maxmaps,
+ acb->acb_gen_objs.max_frame_size
+ ) != NDIS_STATUS_SUCCESS)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Get the OID structures set up. The list of oids is determined
+ // by the network type of the adapter. Also set up any network type
+ // specific information.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ // ETHERNET
+
+ //
+ // Load up the oid pointers and lengths
+ //
+ acb->acb_gbl_oid_list = (PNDIS_OID)NetFlexGlobalOIDs_Eth;
+ acb->acb_gbl_oid_list_size = NetFlexGlobalOIDs_Eth_size;
+ acb->acb_spec_oid_list = (PNDIS_OID)NetFlexNetworkOIDs_Eth;
+ acb->acb_spec_oid_list_size = NetFlexNetworkOIDs_Eth_size;
+
+ //
+ // Allocate and Zero out the Memory for Ethernet specific objects
+ //
+ NdisAllocateMemory( (PVOID *)&(acb->acb_spec_objs),
+ (UINT) (sizeof (ETH_OBJS)),
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ if (acb->acb_spec_objs == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ NdisZeroMemory( acb->acb_spec_objs, sizeof (ETH_OBJS) );
+
+ //
+ // Allocate and Zero out Memory for the Multicast table.
+ //
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ ethobjs->MaxMulticast = parms->utd_maxmulticast;
+
+ NdisAllocateMemory( (PVOID *)&ethobjs->MulticastEntries,
+ (UINT) (ethobjs->MaxMulticast * NET_ADDR_SIZE),
+ (UINT) 0,
+ NetFlexHighestAddress);
+ if (ethobjs->MulticastEntries == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ NdisZeroMemory(ethobjs->MulticastEntries, ethobjs->MaxMulticast * NET_ADDR_SIZE);
+ ethobjs->NumberOfEntries = 0;
+
+ //
+ // Allocate Memory for sending multicast requests to the adapter.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(MULTI_BLOCK) * 2),
+ FALSE,
+ (PVOID *)(&(acb->acb_multiblk_virtptr)),
+ &acb->acb_multiblk_physptr);
+
+ if (acb->acb_multiblk_virtptr == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ }
+ else
+ {
+ // TOKEN RING
+
+ //
+ // Load up the oid pointers and lengths
+ //
+ acb->acb_gbl_oid_list = (PNDIS_OID)NetFlexGlobalOIDs_Tr;
+ acb->acb_gbl_oid_list_size = NetFlexGlobalOIDs_Tr_size;
+ acb->acb_spec_oid_list = (PNDIS_OID)NetFlexNetworkOIDs_Tr;
+ acb->acb_spec_oid_list_size = NetFlexNetworkOIDs_Tr_size;
+
+ //
+ // Allocate and Zero out Memory for Token Ring specific objects
+ //
+ NdisAllocateMemory( (PVOID *)&(acb->acb_spec_objs),
+ (UINT) (sizeof (TR_OBJS)),
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ if (acb->acb_spec_objs == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ NdisZeroMemory( acb->acb_spec_objs, sizeof (TR_OBJS) );
+ }
+
+ //
+ // Allocate the SCB for this adapter.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SCB,
+ FALSE,
+ (PVOID *)(&(acb->acb_scb_virtptr)),
+ &acb->acb_scb_physptr);
+
+ if (acb->acb_scb_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating SCB failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Allocate the SSB for this adapter.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SSB,
+ FALSE,
+ (PVOID *)(&(acb->acb_ssb_virtptr)),
+ &acb->acb_ssb_physptr);
+
+ if (acb->acb_ssb_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating SSB failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ acb->acb_maxinternalbufs = parms->utd_maxinternalbufs;
+ acb->acb_numsmallbufs = parms->utd_numsmallbufs;
+
+ //
+ // Allocate Flush Buffer Pool for our InteralBuffers and the ReceiveBuffers
+ //
+ NdisAllocateBufferPool(
+ &Status,
+ (PVOID*)&acb->FlushBufferPoolHandle,
+ acb->acb_gen_objs.max_frame_size * ( parms->utd_maxinternalbufs + acb->acb_maxrcvs + acb->acb_maxinternalbufs));
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating flush buffer pool failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Now allocate our internal buffers, and their flush buffers...
+ //
+ NdisAllocateMemory(
+ (PVOID *) &acb->OurBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_maxinternalbufs,
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ //
+ // Zero the memory of all the descriptors so that we can
+ // know which buffers weren't allocated incase we can't allocate
+ // them all.
+ //
+ NdisZeroMemory(
+ acb->OurBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_maxinternalbufs );
+
+
+ //
+ // Allocate each of the buffers and fill in the
+ // buffer descriptor.
+ //
+ OurBuf = acb->OurBuffersVirtPtr;
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * acb->acb_maxinternalbufs,
+ TRUE,
+ &acb->MergeBufferPoolVirt,
+ &acb->MergeBufferPoolPhys);
+
+ if ( acb->MergeBufferPoolVirt != NULL )
+ {
+ acb->MergeBuffersAreContiguous = TRUE;
+
+ CurrentMergeBuffer = acb->MergeBufferPoolVirt;
+
+ LowPart = NdisGetPhysicalAddressLow(acb->MergeBufferPoolPhys);
+
+ //
+ // If the high part is non-zero then this adapter is hosed anyway since
+ // its a 32-bit busmaster device.
+ //
+ ASSERT( NdisGetPhysicalAddressHigh(acb->MergeBufferPoolPhys) == 0 );
+ }
+ else
+ {
+ acb->MergeBuffersAreContiguous = FALSE;
+
+ acb->MergeBufferPoolVirt = NULL;
+
+ CurrentMergeBuffer = NULL;
+ }
+
+ for (i = 0; i < acb->acb_maxinternalbufs; i++ )
+ {
+ //
+ // Allocate a buffer
+ //
+ if ( acb->MergeBuffersAreContiguous )
+ {
+ OurBuf->VirtualBuffer = CurrentMergeBuffer;
+
+ NdisSetPhysicalAddressLow(OurBuf->PhysicalBuffer, LowPart);
+ NdisSetPhysicalAddressHigh(OurBuf->PhysicalBuffer, 0);
+
+ CurrentMergeBuffer += FrameSizeCacheAligned;
+
+ LowPart += FrameSizeCacheAligned;
+ }
+ else
+ {
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ &OurBuf->VirtualBuffer,
+ &OurBuf->PhysicalBuffer);
+
+ if ( OurBuf->VirtualBuffer == NULL )
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating individual merge buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ //
+ // Build flush buffers
+ //
+ NdisAllocateBuffer(
+ &Status,
+ &OurBuf->FlushBuffer,
+ acb->FlushBufferPoolHandle,
+ OurBuf->VirtualBuffer,
+ acb->acb_gen_objs.max_frame_size );
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating FLUSH buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Insert this buffer into the queue
+ //
+ OurBuf->Next = (OurBuf + 1);
+ OurBuf->BufferSize = acb->acb_gen_objs.max_frame_size;
+ OurBuf = OurBuf->Next;
+ }
+
+ //
+ // Make sure that the last buffer correctly terminates the free list.
+ //
+ (OurBuf - 1)->Next = NULL;
+ acb->OurBuffersListHead = acb->OurBuffersVirtPtr;
+
+ //
+ // Now allocate our internal buffers, and their flush buffers...
+ //
+ NdisAllocateMemory(
+ (PVOID *) &acb->SmallBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * parms->utd_numsmallbufs,
+ (UINT) 0,
+ NetFlexHighestAddress);
+
+ //
+ // Zero the memory of all the descriptors so that we can
+ // know which buffers weren't allocated incase we can't allocate
+ // them all.
+ //
+ NdisZeroMemory(
+ acb->SmallBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * parms->utd_numsmallbufs);
+
+ //
+ // Allocate each of the buffers and fill in the
+ // buffer descriptor.
+ //
+ OurBuf = acb->SmallBuffersVirtPtr;
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz * parms->utd_numsmallbufs,
+ TRUE,
+ &acb->SmallBufferPoolVirt,
+ &acb->SmallBufferPoolPhys);
+
+ if ( acb->SmallBufferPoolVirt != NULL )
+ {
+ acb->SmallBuffersAreContiguous = TRUE;
+
+ CurrentMergeBuffer = acb->SmallBufferPoolVirt;
+
+ LowPart = NdisGetPhysicalAddressLow(acb->SmallBufferPoolPhys);
+
+ //
+ // If the high part is non-zero then this adapter is hosed anyway since
+ // its a 32-bit busmaster device.
+ //
+
+ ASSERT( NdisGetPhysicalAddressHigh(acb->SmallBufferPoolPhys) == 0 );
+
+ }
+ else
+ {
+ acb->SmallBuffersAreContiguous = FALSE;
+
+ acb->SmallBufferPoolVirt = NULL;
+
+ CurrentMergeBuffer = NULL;
+ }
+
+ for (i = 0; i < parms->utd_numsmallbufs; i++ )
+ {
+ //
+ // Allocate a small buffer
+ //
+
+ if ( acb->SmallBuffersAreContiguous ) {
+
+ OurBuf->VirtualBuffer = CurrentMergeBuffer;
+
+ NdisSetPhysicalAddressLow(OurBuf->PhysicalBuffer, LowPart);
+ NdisSetPhysicalAddressHigh(OurBuf->PhysicalBuffer, 0);
+
+ CurrentMergeBuffer += acb->acb_smallbufsz;
+
+ LowPart += acb->acb_smallbufsz;
+
+ } else {
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz,
+ TRUE,
+ &OurBuf->VirtualBuffer,
+ &OurBuf->PhysicalBuffer
+ );
+
+ if ( OurBuf->VirtualBuffer == NULL ) {
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating individual merge buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ //
+ // Build flush buffers
+ //
+
+ NdisAllocateBuffer( &Status,
+ &OurBuf->FlushBuffer,
+ acb->FlushBufferPoolHandle,
+ OurBuf->VirtualBuffer,
+ acb->acb_smallbufsz );
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating FLUSH buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Insert this buffer into the queue
+ //
+ OurBuf->Next = (OurBuf + 1);
+ OurBuf->BufferSize = acb->acb_smallbufsz;
+ OurBuf = OurBuf->Next;
+ }
+
+ //
+ // Make sure that the last buffer correctly terminates the free list.
+ //
+ (OurBuf - 1)->Next = NULL;
+ acb->SmallBuffersListHead = acb->SmallBuffersVirtPtr;
+
+ //
+ // Now, Allocate the transmit lists
+ //
+ acb->acb_maxtrans = parms->utd_maxtrans * (USHORT)MAX_LISTS_PER_XMIT;
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(SIZE_XMIT * acb->acb_maxtrans),
+ FALSE,
+ (PVOID *)&acb->acb_xmit_virtptr,
+ &acb->acb_xmit_physptr);
+
+ if (acb->acb_xmit_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating transmit list failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Initialize the transmit lists and link them together.
+ //
+
+ acb->acb_xmit_head = acb->acb_xmit_virtptr;
+
+ current_phys = NdisGetPhysicalAddressLow(acb->acb_xmit_physptr);
+
+ for (i = 0, CurrentXmitEntry = acb->acb_xmit_virtptr;
+ i < acb->acb_maxtrans;
+ i++, CurrentXmitEntry++ )
+ {
+ NdisSetPhysicalAddressHigh(CurrentXmitEntry->XMIT_Phys, 0);
+ NdisSetPhysicalAddressLow( CurrentXmitEntry->XMIT_Phys,
+ current_phys);
+
+ CurrentXmitEntry->XMIT_MyMoto = SWAPL(CTRL_ADDR((LONG)current_phys));
+
+ CurrentXmitEntry->XMIT_CSTAT = 0;
+
+#ifdef XMIT_INTS
+ CurrentXmitEntry->XMIT_Number = i;
+#endif
+ next_phys = current_phys + SIZE_XMIT;
+
+ //
+ // Make the forward pointer odd.
+ //
+ CurrentXmitEntry->XMIT_FwdPtr = SWAPL(CTRL_ADDR((LONG)next_phys));
+
+ CurrentXmitEntry->XMIT_Next = (CurrentXmitEntry + 1);
+ CurrentXmitEntry->XMIT_OurBufferPtr = NULL;
+ current_phys = next_phys;
+ }
+
+ //
+ // Make sure the last entry is properly set to the begining...
+ //
+ (CurrentXmitEntry - 1)->XMIT_Next = acb->acb_xmit_virtptr;
+ (CurrentXmitEntry - 1)->XMIT_FwdPtr =
+ SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_xmit_physptr)));
+
+ acb->acb_avail_xmit = parms->utd_maxtrans;
+
+ //
+ // Now, Allocate the Receive lists.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(RCV) * parms->utd_maxrcvs),
+ FALSE,
+ (PVOID *) &acb->acb_rcv_virtptr,
+ &acb->acb_rcv_physptr);
+
+ if (acb->acb_rcv_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating receive list failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Point the head to the first one...
+ //
+ acb->acb_rcv_head = acb->acb_rcv_virtptr;
+ //
+ // Clear the receive lists
+ //
+ NdisZeroMemory( acb->acb_rcv_virtptr,
+ sizeof(RCV) * parms->utd_maxrcvs );
+
+ //
+ // Initialize the receive lists and link them together.
+ //
+
+ acb->acb_maxrcvs = parms->utd_maxrcvs;
+ current_phys = NdisGetPhysicalAddressLow(acb->acb_rcv_physptr);
+
+ CurrentReceiveEntry = acb->acb_rcv_virtptr;
+
+ //
+ // Create the receive buffer pool.
+ //
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * parms->utd_maxrcvs,
+ TRUE,
+ &acb->ReceiveBufferPoolVirt,
+ &acb->ReceiveBufferPoolPhys
+ );
+
+ if ( acb->ReceiveBufferPoolVirt != NULL ) {
+
+ acb->RecvBuffersAreContiguous = TRUE;
+
+ CurrentReceiveBuffer = acb->ReceiveBufferPoolVirt;
+
+ LowPart = NdisGetPhysicalAddressLow(acb->ReceiveBufferPoolPhys);
+
+ //
+ // If the high part is non-zero then this adapter is hosed anyway since
+ // its a 32-bit busmaster device.
+ //
+
+ ASSERT( NdisGetPhysicalAddressHigh(acb->ReceiveBufferPoolPhys) == 0 );
+
+ } else {
+
+ acb->RecvBuffersAreContiguous = FALSE;
+
+ acb->ReceiveBufferPoolVirt = NULL;
+
+ CurrentReceiveBuffer = NULL;
+ }
+
+ for ( i = 0; i < parms->utd_maxrcvs; ++i, ++CurrentReceiveEntry )
+ {
+ //
+ // Allocate the actual receive frame buffers.
+ //
+
+ if ( acb->RecvBuffersAreContiguous ) {
+
+ CurrentReceiveEntry->RCV_Buf = CurrentReceiveBuffer;
+
+ NdisSetPhysicalAddressLow(CurrentReceiveEntry->RCV_BufPhys, LowPart);
+ NdisSetPhysicalAddressHigh(CurrentReceiveEntry->RCV_BufPhys, 0);
+
+ CurrentReceiveBuffer += FrameSizeCacheAligned;
+
+ LowPart += FrameSizeCacheAligned;
+
+ } else {
+
+ NdisMAllocateSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ &CurrentReceiveEntry->RCV_Buf,
+ &CurrentReceiveEntry->RCV_BufPhys
+ );
+
+ if ( CurrentReceiveEntry->RCV_Buf == NULL ) {
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating individual receive buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ //
+ // Build flush buffers
+ //
+
+ NdisAllocateBuffer(
+ &Status,
+ &CurrentReceiveEntry->RCV_FlushBuffer,
+ acb->FlushBufferPoolHandle,
+ CurrentReceiveEntry->RCV_Buf,
+ acb->acb_gen_objs.max_frame_size);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating FLUSH receive buffer failed.\n",acb->anum));
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Initialize receive buffers
+ //
+ NdisFlushBuffer(CurrentReceiveEntry->RCV_FlushBuffer, FALSE);
+
+ CurrentReceiveEntry->RCV_Number = i;
+ CurrentReceiveEntry->RCV_CSTAT = ((i % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ CurrentReceiveEntry->RCV_Dsize = (SHORT) SWAPS((USHORT)(acb->acb_gen_objs.max_frame_size));
+ CurrentReceiveEntry->RCV_Dsize &= DATA_LAST;
+
+ temp = NdisGetPhysicalAddressLow(CurrentReceiveEntry->RCV_BufPhys);
+ temp = SWAPL(temp);
+
+ CurrentReceiveEntry->RCV_DptrHi = (USHORT)temp;
+ CurrentReceiveEntry->RCV_DptrLo = (USHORT)(temp >> 16);
+
+ NdisSetPhysicalAddressHigh(CurrentReceiveEntry->RCV_Phys, 0);
+ NdisSetPhysicalAddressLow( CurrentReceiveEntry->RCV_Phys,
+ current_phys);
+
+ next_phys = current_phys + SIZE_RCV;
+
+ CurrentReceiveEntry->RCV_FwdPtr = SWAPL(CTRL_ADDR(next_phys));
+ CurrentReceiveEntry->RCV_MyMoto = SWAPL(CTRL_ADDR(current_phys));
+
+ CurrentReceiveEntry->RCV_Next = (CurrentReceiveEntry + 1);
+ current_phys = next_phys;
+ }
+
+ //
+ // Make sure the last entry is properly set to the begining...
+ //
+ (CurrentReceiveEntry - 1)->RCV_Next = acb->acb_rcv_virtptr;
+ (CurrentReceiveEntry - 1)->RCV_FwdPtr =
+ SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_rcv_physptr)));
+
+ //
+ // Allocate and initialize the OPEN parameter block.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_OPEN,
+ FALSE,
+ (PVOID *)(&(acb->acb_opnblk_virtptr)),
+ &acb->acb_opnblk_physptr );
+
+ if (acb->acb_opnblk_virtptr == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating OPEN block failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ NdisMoveMemory(acb->acb_opnblk_virtptr, &(parms->utd_open), SIZE_OPEN);
+
+ //
+ // Convert the product ID pointer in the Open parameter block
+ // into a big endian type address.
+ //
+ acb->acb_opnblk_virtptr->OPEN_ProdIdPtr =
+ (CHAR *) (SWAPL((LONG) acb->acb_opnblk_virtptr->OPEN_ProdIdPtr));
+
+ acb->acb_openoptions = parms->utd_open.OPEN_Options;
+
+ //
+ // Initialize the intialization block.
+ //
+ NdisMoveMemory(&acb->acb_initblk, &init_mask, SIZE_INIT);
+
+ //
+ // Allocate Memory to hold the Read Statistics Log information.
+ //
+ NdisMAllocateSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(RSL)),
+ FALSE,
+ (PVOID *)(&(acb->acb_logbuf_virtptr)),
+ &acb->acb_logbuf_physptr );
+
+ if (acb->acb_logbuf_virtptr == NULL)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Allocate Memory for internal SCB requests.
+ //
+ NdisAllocateMemory( (PVOID *)&(start),
+ (UINT) (SCBREQSIZE * parms->utd_maxinternalreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS,
+ NetFlexHighestAddress);
+ if (start == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating internal SCB request failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Initialize the SCB requests and place them on the free queue.
+ //
+ acb->acb_maxreqs = parms->utd_maxinternalreqs;
+ current = start;
+ for (i = 0; i < parms->utd_maxinternalreqs; i++)
+ {
+ next = (PVOID)( ((PUCHAR)(current)) + SCBREQSIZE);
+ ((PSCBREQ) current)->req_next = next;
+ if (i < (USHORT)(parms->utd_maxinternalreqs-1))
+ {
+ current = next;
+ }
+ }
+ ((PSCBREQ)current)->req_next = (PSCBREQ) NULL;
+ acb->acb_scbreq_ptr = (PSCBREQ)start;
+ acb->acb_scbreq_free = (PSCBREQ)start;
+
+ //
+ // Allocate Memory for the internal MAC requests.
+ //
+ NdisAllocateMemory( (PVOID *)&(start),
+ (UINT) (MACREQSIZE * parms->utd_maxinternalreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS,
+ NetFlexHighestAddress);
+ if (start == NULL)
+ {
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb: Allocating internal MAC request failed.\n",acb->anum));
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Initialize the internal MAC requests and place them
+ // on the free queue.
+ //
+ current = start;
+ for (i = 0; i < parms->utd_maxinternalreqs; i++)
+ {
+ next = (PVOID)( ((PUCHAR)(current)) + MACREQSIZE);
+ ((PMACREQ) current)->req_next = next;
+ if (i < (USHORT)(parms->utd_maxinternalreqs-1))
+ {
+ current = next;
+ }
+ }
+ ((PMACREQ)current)->req_next = (PMACREQ) NULL;
+ acb->acb_macreq_ptr = (PMACREQ)start;
+ acb->acb_macreq_free = (PMACREQ)start;
+
+ DebugPrint(1,("NF(%d): NetFlexInitializeAcb completed successfully!\n",acb->anum));
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDeallocateAcb
+//
+// Description: This routine deallocates the acb resources.
+//
+// Input: acb - Our Driver Context for this adapter or head.
+//
+// Output: None.
+//
+// Called By: NetFlexInitialize,
+// NetFlexDeregisterAdapter
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDeallocateAcb(
+ PACB acb
+ )
+{
+ PETH_OBJS ethobjs;
+ PRCV CurrentReceiveEntry;
+ PNETFLEX_PARMS parms = acb->acb_parms;
+ USHORT i;
+ PBUFFER_DESCRIPTOR OurBuf;
+ ULONG Alignment, FrameSizeCacheAligned;
+
+ //
+ // Get the max frame size, cache align it and a save it for later.
+ //
+
+ Alignment = NdisGetCacheFillSize();
+
+ if ( Alignment < sizeof(ULONG) ) {
+
+ Alignment = sizeof(ULONG);
+ }
+
+ FrameSizeCacheAligned = (parms->utd_maxframesz + Alignment - 1) & ~(Alignment - 1);
+
+ //
+ // If we have allocated memory for the network specific information,
+ // release this memory now.
+ //
+
+ if (acb->acb_spec_objs)
+ {
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ // ETHERNET
+
+ ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
+ //
+ // If we have allocated the multicast table entries, free
+ // the memory.
+ //
+ if (ethobjs->MulticastEntries)
+ {
+ NdisFreeMemory( (PVOID)(ethobjs->MulticastEntries),
+ (UINT) (ethobjs->MaxMulticast * NET_ADDR_SIZE),
+ (UINT) 0);
+ }
+ //
+ // Deallocate Memory for Ethernet specific objects
+ //
+ NdisFreeMemory((PVOID)(acb->acb_spec_objs),
+ (UINT) (sizeof (ETH_OBJS)),
+ (UINT) 0);
+ }
+ else
+ {
+ // Token Ring
+ //
+ // Deallocate Memory for Token Ring specific objects
+ //
+ NdisFreeMemory( (PVOID)(acb->acb_spec_objs),
+ (UINT) (sizeof (TR_OBJS)),
+ (UINT) 0);
+
+ }
+ }
+
+ //
+ // If we have allocated memory for the multicast request to the
+ // adapter, free the memory.
+ //
+ if (acb->acb_multiblk_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(MULTI_BLOCK) * 2),
+ FALSE,
+ (PVOID)(acb->acb_multiblk_virtptr),
+ acb->acb_multiblk_physptr);
+ }
+
+ //
+ // If we have allocated memory for the scb, free the memory.
+ //
+ if (acb->acb_scb_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SCB,
+ FALSE,
+ (PVOID)(acb->acb_scb_virtptr),
+ acb->acb_scb_physptr);
+ }
+
+ //
+ // If we have allocated memory for the ssb, free the memory.
+ //
+ if (acb->acb_ssb_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_SSB,
+ FALSE,
+ (PVOID)(acb->acb_ssb_virtptr),
+ acb->acb_ssb_physptr);
+ }
+
+ //
+ // Free merge buffer pool.
+ //
+
+ if (acb->MergeBufferPoolVirt) {
+
+ OurBuf = acb->OurBuffersVirtPtr;
+
+ //
+ // Free flush buffers
+ //
+
+ for (i = 0; i < acb->acb_maxinternalbufs; ++i, ++OurBuf) {
+
+ if (OurBuf->FlushBuffer)
+ {
+ NdisFreeBuffer(OurBuf->FlushBuffer);
+
+ if ( !acb->MergeBuffersAreContiguous ) {
+
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ OurBuf->VirtualBuffer,
+ OurBuf->PhysicalBuffer
+ );
+ }
+ }
+ }
+
+ //
+ // Free the pool itself.
+ //
+
+ if ( acb->MergeBuffersAreContiguous ) {
+
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * acb->acb_maxinternalbufs,
+ TRUE,
+ acb->MergeBufferPoolVirt,
+ acb->MergeBufferPoolPhys
+ );
+ }
+ }
+ //
+ // Free our own transmit buffers.
+ //
+
+ if (acb->OurBuffersVirtPtr)
+ {
+ //
+ // Free OurBuffers
+ //
+
+ NdisFreeMemory(
+ acb->OurBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_maxinternalbufs,
+ 0
+ );
+ }
+
+ //
+ // Free Small Merge buffer pool.
+ //
+ if (acb->SmallBufferPoolVirt)
+ {
+ OurBuf = acb->SmallBuffersVirtPtr;
+
+ //
+ // Free flush buffers
+ //
+ for (i = 0; i < acb->acb_numsmallbufs; ++i, ++OurBuf)
+ {
+ if (OurBuf->FlushBuffer)
+ {
+ NdisFreeBuffer(OurBuf->FlushBuffer);
+
+ if ( !acb->SmallBuffersAreContiguous ) {
+
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz,
+ TRUE,
+ OurBuf->VirtualBuffer,
+ OurBuf->PhysicalBuffer);
+ }
+ }
+ }
+
+ //
+ // Free the pool itself.
+ //
+ if ( acb->SmallBuffersAreContiguous )
+ {
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ acb->acb_smallbufsz * acb->acb_numsmallbufs,
+ TRUE,
+ acb->SmallBufferPoolVirt,
+ acb->SmallBufferPoolPhys);
+ }
+ }
+
+ //
+ // Free our Small transmit buffers.
+ //
+ if (acb->SmallBuffersVirtPtr)
+ {
+ //
+ // Free Small Buffers
+ //
+
+ NdisFreeMemory(
+ acb->SmallBuffersVirtPtr,
+ sizeof(BUFFER_DESCRIPTOR) * acb->acb_numsmallbufs,
+ 0
+ );
+ }
+ //
+ // If we have allocated memory for the transmit lists, free it.
+ //
+ if (acb->acb_xmit_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(SIZE_XMIT * acb->acb_maxtrans),
+ FALSE,
+ (PVOID)(acb->acb_xmit_virtptr),
+ acb->acb_xmit_physptr );
+ }
+
+ //
+ // If we have allocated memory for the receive lists, free it.
+ //
+
+ if ( acb->acb_rcv_virtptr ) {
+
+ //
+ // If we allocated the receive buffer pool, free it.
+ //
+ CurrentReceiveEntry = acb->acb_rcv_virtptr;
+
+ for (i = 0; i < parms->utd_maxrcvs; ++i, ++CurrentReceiveEntry) {
+ //
+ // Free flush buffers
+ //
+
+ if ( CurrentReceiveEntry->RCV_FlushBuffer )
+ {
+ NdisFreeBuffer(CurrentReceiveEntry->RCV_FlushBuffer);
+
+ }
+
+ //
+ // Free individual buffer, if allocated.
+ //
+ if ((!acb->RecvBuffersAreContiguous) &&
+ (CurrentReceiveEntry->RCV_Buf))
+ {
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ parms->utd_maxframesz,
+ TRUE,
+ CurrentReceiveEntry->RCV_Buf,
+ CurrentReceiveEntry->RCV_BufPhys
+ );
+ }
+ }
+
+ //
+ // Free the pool itself, if it was allocated contiguously.
+ //
+ if ( acb->RecvBuffersAreContiguous && acb->ReceiveBufferPoolVirt)
+ {
+ NdisMFreeSharedMemory(
+ acb->acb_handle,
+ FrameSizeCacheAligned * parms->utd_maxrcvs,
+ TRUE,
+ acb->ReceiveBufferPoolVirt,
+ acb->ReceiveBufferPoolPhys
+ );
+ }
+
+ //
+ // Now Free the RCV Lists
+ //
+
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(SIZE_RCV * parms->utd_maxrcvs),
+ FALSE,
+ (PVOID)acb->acb_rcv_virtptr,
+ acb->acb_rcv_physptr);
+ }
+
+ //
+ // Free the Flush Pool
+ //
+ if (acb->FlushBufferPoolHandle)
+ {
+ // Free the buffer pool
+ //
+ NdisFreeBufferPool(acb->FlushBufferPoolHandle);
+ }
+
+
+ //
+ // If we have allocated memory for the open block, free it.
+ //
+ if (acb->acb_opnblk_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)SIZE_OPEN,
+ FALSE,
+ (PVOID)(acb->acb_opnblk_virtptr),
+ acb->acb_opnblk_physptr);
+ }
+
+ //
+ // If we have allocated memory for the Read Statistics Log, free it.
+ //
+ if (acb->acb_logbuf_virtptr)
+ {
+ NdisMFreeSharedMemory( acb->acb_handle,
+ (ULONG)(sizeof(RSL)),
+ FALSE,
+ (PVOID)(acb->acb_logbuf_virtptr),
+ acb->acb_logbuf_physptr);
+ }
+
+ //
+ // If we have allocated memory for the internal SCB requests,
+ // free it.
+ //
+ if (acb->acb_scbreq_ptr)
+ {
+ NdisFreeMemory( (PVOID)acb->acb_scbreq_ptr,
+ (UINT) (SCBREQSIZE * acb->acb_maxreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS);
+ }
+ //
+ // If we have allocated memory for the internal MAC requests,
+ // free it.
+ //
+ if (acb->acb_macreq_ptr)
+ {
+ NdisFreeMemory( (PVOID)acb->acb_macreq_ptr,
+ (UINT) (MACREQSIZE * acb->acb_maxreqs),
+ (UINT) NDIS_MEMORY_CONTIGUOUS);
+ }
+
+ //
+ // Free map registers
+ //
+ NdisMFreeMapRegisters(acb->acb_handle);
+
+ //
+ // Deregister IO mappings
+ //
+
+ if (acb->acb_dualport)
+ {
+ BOOLEAN OtherHeadStillActive = FALSE;
+ PACB tmp_acb = macgbls.mac_adapters;
+ while (tmp_acb)
+ {
+ if ((tmp_acb->acb_baseaddr == acb->acb_baseaddr) &&
+ (tmp_acb->acb_portnumber != acb->acb_portnumber))
+ {
+ OtherHeadStillActive = TRUE;
+ break;
+ }
+ else
+ {
+ tmp_acb = tmp_acb->acb_next;
+ }
+ }
+
+ if (!OtherHeadStillActive)
+ {
+ // Remove ports for both heads
+ //
+
+ // free ports z000 - -z02f
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr,
+ NUM_DUALHEAD_CFG_PORTS,
+ (PVOID) acb->MasterBasePorts );
+
+ // free ports zc80 - zc87
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + CFG_PORT_OFFSET,
+ NUM_CFG_PORTS,
+ (PVOID)acb->ConfigPorts );
+
+ // free ports zc63 - zc67
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + EXTCFG_PORT_OFFSET,
+ NUM_EXTCFG_PORTS,
+ (PVOID)acb->ExtConfigPorts );
+ }
+ }
+ else
+ {
+ // free ports z000 - z01f
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr,
+ NUM_BASE_PORTS,
+ (PVOID) acb->BasePorts );
+
+ // free ports zc80 - zc87
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + CFG_PORT_OFFSET,
+ NUM_CFG_PORTS,
+ (PVOID)acb->ConfigPorts );
+
+ // free ports zc63 - zc67
+ //
+ NdisMDeregisterIoPortRange( acb->acb_handle,
+ acb->acb_baseaddr + EXTCFG_PORT_OFFSET,
+ NUM_EXTCFG_PORTS,
+ (PVOID)acb->ExtConfigPorts );
+ }
+
+ //
+ // Free the Memory for the adapter's acb.
+ //
+ if (acb->acb_parms != NULL)
+ {
+ NdisFreeMemory( (PVOID) acb->acb_parms, (UINT) sizeof(PNETFLEX_PARMS), (UINT) 0);
+ }
+ if (acb != NULL)
+ {
+ NdisFreeMemory( (PVOID)acb, (UINT) (sizeof (ACB)),(UINT) 0);
+ }
+ //
+ // Indicate New Number of Adapters
+ //
+ macgbls.mac_numadpts--;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexSendNextSCB
+//
+// Description:
+// This routine either sends a TMS_TRANSMIT SCB
+// command to the adapter or sends a command on
+// the SCBReq active queue.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexSCBClear,
+// NetFlexQueueSCB,
+// NetFlexTransmitStatus
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexSendNextSCB(
+ PACB acb
+ )
+{
+ USHORT sifint_reg;
+ PSCBREQ req;
+ PMACREQ macreq;
+ PMULTI_BLOCK tempmulti;
+
+ //
+ // If there is a Transmit command waiting, issue it. Otherwise,
+ // issue the first SCBReq on the SCBReq active queue.
+ //
+ if (acb->acb_xmit_whead)
+ {
+ // Load up the real SCB with a Transmit command
+ //
+ DebugPrint(2,("!S!"));
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_TRANSMIT;
+ acb->acb_scb_virtptr->SCB_Ptr = acb->acb_xmit_whead->XMIT_MyMoto;
+
+ //
+ // If the transmit lists on the waiting queue are ready to
+ // transmit, put them on the active queue.
+ //
+ if ((acb->acb_xmit_whead->XMIT_CSTAT & XCSTAT_GO) != 0)
+ {
+ acb->acb_xmit_ahead = acb->acb_xmit_whead;
+ acb->acb_xmit_atail = acb->acb_xmit_wtail;
+ }
+
+ acb->acb_xmit_whead = 0;
+ acb->acb_xmit_wtail = 0;
+ }
+ //
+ // If there is a Receive command waiting, issue it.
+ //
+ else if (acb->acb_rcv_whead)
+ {
+
+ // Load up the real SCB with a receive command
+ //
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_RECEIVE;
+ acb->acb_scb_virtptr->SCB_Ptr = acb->acb_rcv_whead->RCV_MyMoto;
+
+ acb->acb_rcv_head = acb->acb_rcv_whead;
+ acb->acb_rcv_whead = 0;
+ }
+ //
+ // Otherwise, if there is a SCB request waiting, issue it.
+ //
+ else if (acb->acb_scbreq_next)
+ {
+ // First, let's skip over any dummy SCB commands
+ //
+ req = acb->acb_scbreq_next;
+
+ //
+ // Fill in the real SCB with the first SCBReq on the SCBReq active
+ // queue.
+ //
+ acb->acb_scbreq_next = acb->acb_scbreq_next->req_next;
+ acb->acb_scb_virtptr->SCB_Cmd = req->req_scb.SCB_Cmd;
+
+ //
+ // If this is a Multicast request, we have to fill in a Multicast
+ // buffer.
+ //
+ if (req->req_scb.SCB_Cmd == TMS_MULTICAST)
+ {
+ acb->acb_scb_virtptr->SCB_Ptr = SWAPL(CTRL_ADDR((ULONG)(NdisGetPhysicalAddressLow(acb->acb_multiblk_physptr) +
+ (acb->acb_multi_index * sizeof(MULTI_BLOCK)))) );
+
+ tempmulti = (PMULTI_BLOCK)((ULONG)(acb->acb_multiblk_virtptr) +
+ (acb->acb_multi_index * sizeof(MULTI_BLOCK)));
+
+ acb->acb_multi_index = acb->acb_multi_index ^ (SHORT)1;
+
+ tempmulti->MB_Option = req->req_multi.MB_Option;
+ tempmulti->MB_Addr_Hi = req->req_multi.MB_Addr_Hi;
+ tempmulti->MB_Addr_Med = req->req_multi.MB_Addr_Med;
+ tempmulti->MB_Addr_Lo = req->req_multi.MB_Addr_Lo;
+ }
+ else
+ {
+ acb->acb_scb_virtptr->SCB_Ptr = req->req_scb.SCB_Ptr;
+ }
+ }
+ else
+ {
+ // Nothing to do
+ //
+ return;
+ }
+
+ sifint_reg = SIFINT_CMD;
+
+ //
+ // If there are other requests to send and we are not waiting for
+ // an SCB clear interrupt, tell the adapter we want an SCB clear int.
+ //
+ if ((!acb->acb_scbclearout) &&
+ ((acb->acb_scbreq_next) || (acb->acb_rcv_whead))
+ )
+ {
+ sifint_reg |= SIFINT_SCBREQST;
+ acb->acb_scbclearout = TRUE;
+ }
+
+ //
+ // Send the SCB to the adapter.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) sifint_reg);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexQueueSCB
+//
+// Description:
+// This routine places the given SCBReq onto the
+// active SCBreq queue.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+// scbreq - Ptr to the SCBReq to execute
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexQueryInformation
+// NetFlexSetInformation,
+// NetFlexDeleteMulticast,
+// NetFlexAddMulticast
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexQueueSCB(
+ PACB acb,
+ PSCBREQ scbreq
+)
+{
+ //
+ // Place the scbreq on the SCBReq active queue.
+ //
+ NetFlexEnqueue_TwoPtrQ_Tail(
+ (PVOID *)&(acb->acb_scbreq_head),
+ (PVOID *)&(acb->acb_scbreq_tail),
+ (PVOID)scbreq
+ );
+
+ //
+ // If there are no requests waiting for the SCB to clear,
+ // point the request waiting queue to this SCBReq.
+ //
+ if (!acb->acb_scbreq_next)
+ acb->acb_scbreq_next = scbreq;
+
+ //
+ // If the SCB is clear, send a SCB command off now.
+ // Otherwise, if we are not currently waiting for an SCB clear
+ // interrupt, signal the adapter to send us a SCB clear interrupt
+ // when it is done with the SCB.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if (!acb->acb_scbclearout)
+ {
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT)SIFINT_SCBREQST);
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexGetBIA
+//
+// Description:
+// This routine gets the Burned In Address of the adapter.
+//
+// Input:
+// acb - Acb pointer
+//
+// Output:
+// NDIS_STATUS_SUCCESS if successful
+//
+// Called By:
+// NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexGetBIA(
+ PACB acb
+ )
+{
+ USHORT value;
+ SHORT i;
+
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) 0x0a00);
+ NdisRawReadPortUshort( acb->SifDataPort, (PUSHORT) &value);
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) value);
+
+ for (i = 0; i < 3; i++)
+ {
+ NdisRawReadPortUshort( acb->SifDIncPort, (PUSHORT) &value);
+ //
+ // Copy the value into the permanent and current station addresses
+ //
+ acb->acb_gen_objs.perm_staddr[i*2] = (UCHAR)(SWAPS(value));
+ acb->acb_gen_objs.perm_staddr[(i*2)+1] = (UCHAR)(value);
+ }
+
+ //
+ // Figure out whether the current station address will be the bia or
+ // an address set up in the configuration file.
+ //
+ if ( (acb->acb_opnblk_virtptr->OPEN_NodeAddr[0] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[1] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[2] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[3] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[4] == 0) &&
+ (acb->acb_opnblk_virtptr->OPEN_NodeAddr[5] == 0) )
+ {
+ NdisMoveMemory(acb->acb_gen_objs.current_staddr,
+ acb->acb_gen_objs.perm_staddr,
+ NET_ADDR_SIZE);
+ }
+ else
+ {
+ NdisMoveMemory(acb->acb_gen_objs.current_staddr,
+ acb->acb_opnblk_virtptr->OPEN_NodeAddr,
+ NET_ADDR_SIZE);
+ }
+}
+
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexGetUpstreamAddrPtr
+//
+// Description: This routine saves the address of where to
+// get the upstream address after opening.
+//
+// Input:
+// acb - Our Driver Context for this adapter or head.
+//
+// Output:
+// NDIS_STATUS_SUCCESS if successful
+//
+// Called By:
+// NetFlexAdapterReset
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexGetUpstreamAddrPtr(
+ PACB acb
+ )
+{
+ USHORT value;
+
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) 0x0a06); // RVC: what is this value for?
+
+ NdisRawReadPortUshort( acb->SifDataPort, (PUSHORT) &value);
+
+ //
+ // Save the address of where to get the UNA for later requests
+ //
+ acb->acb_upstreamaddrptr = value;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexAsciiToHex
+//
+// Description:
+// This routine takes an ascii string an converts
+// it into hex digits storing them in an array provided.
+//
+// Input:
+// src - source string.
+// dst - destiniation string
+// dst_length - length of dst
+//
+// Output:
+// NDIS_STATUS_SUCCESS if the string was converted successfully.
+//
+// Called By:
+// NetFlexReadConfigurationParameters
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS NetFlexAsciiToHex(
+ PNDIS_STRING src,
+ PUCHAR dst,
+ USHORT dst_length
+ )
+{
+ ULONG i;
+ UCHAR num;
+
+ //
+ // If the string is too short, return an error.
+ //
+ if (src->Length < (USHORT)(dst_length*2))
+ return(NDIS_STATUS_FAILURE);
+
+ //
+ // Begin to convert.
+ //
+ for (i = 0; i < dst_length; i++)
+ {
+ //
+ // Get first digit of the byte
+ //
+ num = (UCHAR)(src->Buffer[i*2]);
+ if ( (num >= '0') && (num <= '9') )
+ *dst = (UCHAR)(num - '0') * 0x10;
+ else if ( (num >= 'a') && (num <= 'f') )
+ *dst = (UCHAR)(num - 'a' + 10) * 0x10;
+ else if ( (num >= 'A') && (num <= 'F') )
+ *dst = (UCHAR)(num - 'A' + 10) * 0x10;
+ else
+ return(NDIS_STATUS_FAILURE);
+
+ //
+ // Get second digit of the byte
+ //
+ num = (UCHAR)(src->Buffer[(i*2)+1]);
+ if ( (num >= '0') && (num <= '9') )
+ *dst += (UCHAR)(num - '0');
+ else if ( (num >= 'a') && (num <= 'f') )
+ *dst += (UCHAR)(num - 'a' + 10);
+ else if ( (num >= 'A') && (num <= 'F') )
+ *dst += (UCHAR)(num - 'A' + 10);
+ else
+ return(NDIS_STATUS_FAILURE);
+
+ dst++;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexFindEntry
+//
+// Description:
+// This routine finds the given entry in a queue given to it.
+//
+// Input:
+// head - Ptr to the head of the queue.
+// entry - Ptr to the entry to find.
+//
+// Output:
+// back - Ptr to the address of the entry in front of the
+// entry given.
+// Returns TRUE if found and FALSE if not.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+BOOLEAN
+NetFlexFindEntry(
+ PVOID head,
+ PVOID *back,
+ PVOID entry
+ )
+{
+ PVOID current;
+
+ current = *back = head;
+ while (current)
+ {
+ if (current == entry)
+ return(TRUE);
+ *back = current;
+ current = (PVOID)( ( (PNETFLEX_ENTRY)(current) )->next );
+ }
+
+ return FALSE;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_OnePtrQ
+//
+// Description: This routine finds the given entry and removes
+// it from the queueu given.
+//
+// Input: head - Ptr to the head of the queue.
+// entry - Ptr to the entry to remove.
+//
+// Output: None.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDequeue_OnePtrQ(
+ PVOID *head,
+ PVOID entry
+ )
+{
+ PNETFLEX_ENTRY back;
+
+ if (NetFlexFindEntry(*head, (PVOID *) &back, entry))
+ {
+ if (entry == *head)
+ *head = (PVOID)( ( (PNETFLEX_ENTRY)(entry) )->next );
+ else
+ back->next = ( (PNETFLEX_ENTRY)(entry) )->next;
+ }
+}
+
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexEnqueue_OnePtrQ_Head
+//
+// Description:
+// This routine places the entry given on the front of the
+// queue given.
+//
+// Input:
+// head - Ptr to the ptr of the head of the queue.
+// entry - Pointer to the entry to add
+//
+// Output: None
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexEnqueue_OnePtrQ_Head(
+ PVOID *head,
+ PVOID entry
+ )
+{
+ ((PNETFLEX_ENTRY)(entry))->next = *head;
+ *head = entry;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_OnePtrQ_Head
+//
+// Description:
+// This routine dequeues a the first entry of the given queue
+//
+// Input:
+// head - Ptr to the ptr of the head of the queue.
+//
+// Output:
+// entry - Ptr to the ptr of the dequeued entry.
+//
+// Returns NDIS_STATUS_SUCCESS if an entry is freed.
+// Otherwise, NDIS_STATUS_RESOURCES.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexDequeue_OnePtrQ_Head(
+ PVOID *head,
+ PVOID *entry
+ )
+{
+ //
+ // Is there a free entry? If not, return an error.
+ //
+ if (!(*head))
+ {
+ *entry = NULL;
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Dequeue the free entry from the queue.
+ //
+ *entry = *head;
+ *head = ( (PNETFLEX_ENTRY)(*head))->next;
+ ((PNETFLEX_ENTRY)(*entry))->next = NULL;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexEnqueue_TwoPtrQ_Tail
+//
+// Description:
+// This routine places an entry on the tail of
+// a queue with a head and tail pointer.
+//
+// Input:
+// head - Ptr to address of the head of the queue.
+// tail - Ptr to the address of the tail of the queue.
+// entry - Ptr to the entry to enqueue
+//
+// Output:
+// Status.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexEnqueue_TwoPtrQ_Tail(
+ PVOID *head,
+ PVOID *tail,
+ PVOID entry)
+{
+ //
+ // Place the entry on tail of the queue.
+ //
+ ((PNETFLEX_ENTRY)(entry))->next = NULL;
+ if (*tail)
+ ((PNETFLEX_ENTRY)(*tail))->next = entry;
+ else
+ *head = entry;
+ *tail = entry;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_TwoPtrQ
+//
+// Description:
+// This routine finds the given entry and removes it from
+// the queue. Queue has a head and tail pointer.
+//
+// Input:
+// head - Ptr to address of the head of the queue.
+// tail - Ptr to the address of the tail of the queue.
+// entry - Ptr to the entry to enqueue
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDequeue_TwoPtrQ(
+ PVOID *head,
+ PVOID *tail,
+ PVOID entry
+ )
+{
+ PVOID back;
+
+ if (NetFlexFindEntry(*head, &back, entry))
+ {
+ if (entry == *head)
+ {
+ if ( (*head = ((PNETFLEX_ENTRY)entry)->next) == NULL)
+ *tail = NULL;
+ }
+ else
+ {
+ ((PNETFLEX_ENTRY)back)->next = ((PNETFLEX_ENTRY)entry)->next;
+ if (*tail == entry)
+ *tail = back;
+ }
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDequeue_TwoPtrQ_Head
+//
+// Description:
+// This routine dequeues a the first entry of the given queue
+//
+// Input:
+// head - Ptr to the ptr of the head of the queue.
+// tail - Ptr to the address of the tail of the queue.
+//
+// Output:
+// entry - Ptr to the ptr of the dequeued entry.
+//
+// Status - NDIS_STATUS_SUCCESS if an entry is freed.
+// Otherwise, NDIS_STATUS_RESOURCES.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexDequeue_TwoPtrQ_Head(
+ PVOID *head,
+ PVOID *tail,
+ PVOID *entry
+ )
+{
+ //
+ // Is there a free entry? If not, return an error.
+ //
+ if (!(*head))
+ {
+ *entry = NULL;
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Dequeue the free entry from the queue.
+ //
+ *entry = *head;
+ *head = ((PNETFLEX_ENTRY)(*head))->next;
+ if (*head == NULL)
+ *tail = NULL;
+ ((PNETFLEX_ENTRY)(*entry))->next = NULL;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+#if (DBG || DBGPRINT)
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: _DebugPrint
+//
+// Description:
+// Level sensitive debug print. It is called through
+// a the DebugPrint macro which compares the current
+// DebugLevel to that specified. If the level indicated
+// is less than or equal, the message is displayed.
+//
+// Input:
+// Variable PrintF style Message to display
+//
+// Output:
+// Displays Message on Debug Screen
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+VOID
+_DebugPrint(PCHAR DebugMessage,
+ ...
+ )
+{
+ char buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+ vsprintf(buffer, DebugMessage, ap);
+ DbgPrint(buffer);
+ va_end(ap);
+
+} // end _DebugPrint()
+
+#endif /* DBG */
diff --git a/private/ntos/ndis/netflex/tmsstrct.h b/private/ntos/ndis/netflex/tmsstrct.h
new file mode 100644
index 000000000..f091a2124
--- /dev/null
+++ b/private/ntos/ndis/netflex/tmsstrct.h
@@ -0,0 +1,606 @@
+/***********************************************************************/
+/***********************************************************************/
+/* */
+/* File Name: TMSSTRCT.H */
+/* */
+/* Program Name: NetFlex NDIS 3.0 Driver */
+/* */
+/* Companion Files: None */
+/* */
+/* Function: This module contains all the data strcuture defini- */
+/* tions that are specific to the TMS380 software */
+/* interface specification. The data structures */
+/* defined are as follows: */
+/* */
+/* - TMS380 Adapter Command Definitions */
+/* - TMS380 SIF Register Offset Definitions */
+/* - Adapter Interrupt Register Bit Definition */
+/* - Adapter Configuration Register Bit Definition */
+/* - TMS380 Adapter Command Definitions */
+/* - System Command Block (SCB) */
+/* - System Status Block (SSB) */
+/* - Adapter Initialization Parameter Block */
+/* - Adapter Open Parameter Block */
+/* - Adapter Transmit Parameter List */
+/* - Transmit CSTAT Bit Definitions */
+/* - Transmit Status Bit Definitions */
+/* - Adapter Receive Parameter List */
+/* - Receive CSTAT Bit Definitions */
+/* - Receive Status Bit Definitions */
+/* - Read Error Log Buffer Definition */
+/* */
+/* (c) Compaq Computer Corporation, 1992,1993,1994 */
+/* */
+/* This file is licensed by Compaq Computer Corporation to Microsoft */
+/* Corporation pursuant to the letter of August 20, 1992 from */
+/* Gary Stimac to Mark Baber. */
+/* */
+/* History: */
+/* */
+/* 05/24/94 Robert Van Cleve - Reworked from NDIS 3.0 Driver */
+/* */
+/***********************************************************************/
+/***********************************************************************/
+
+#define NET_ADDR_SIZE 6
+#define NET_GROUP_SIZE 4
+#define HDR_SIZE 14
+
+
+
+/*
+ * Structure Name: TMS380 Adapter Command Definitions
+ *
+ * Description: The TMS380 Adapter Commands Definitions define the
+ * reversed byte ordering of the TMS380 adapter command
+ * word values.
+ */
+#define TMS_RESET 0x0000 /* Reset Adapter (doesn't exist) */
+#define TMS_CMDREJECT 0x0200 /* Command Reject */
+#define TMS_OPEN 0x0300 /* Open Adapter */
+#define TMS_TRANSMIT 0x0400 /* Transmit Frame */
+#define TMS_XMITHALT 0x0500 /* Transmit Halt */
+#define TMS_RECEIVE 0x0600 /* Receive */
+#define TMS_CLOSE 0x0700 /* Close Adapter */
+#define TMS_SETGROUP 0x0800 /* Set Group Address */
+#define TMS_SETFUNCT 0x0900 /* Set Functional Address */
+#define TMS_READLOG 0x0a00 /* Read Error Log */
+#define TMS_READADP 0x0b00 /* Read Adapter Buffer */
+#define TMS_MODIFYOPEN 0x0d00 /* Modify Open Parameters */
+#define TMS_MULTICAST 0x1200 /* Set/Clr Multicast Address */
+#define TMS_DUMMYCMD 0x1111 /* Dummy SCB */
+
+
+/*
+ * Structure Name: TMS380 SIF Register Offset Definitions
+ *
+ * Description: The TMS380 Register Offset Definitions describe the
+ * offsets to and number of TMS380 SIF registers.
+ */
+#define NUMREGS 4
+
+#define SIF_DATA_OFF 0x0 /* SIF data register */
+#define SIF_DINC_OFF 0x2 /* SIF data autoincrment reg */
+#define SIF_ADDR_OFF 0x4 /* SIF address register */
+#define SIF_INT_OFF 0x6 /* SIF interrupt register */
+#define SIF_ACTL_OFF 0x8 /* SIF ACTL register */
+#define SIF_ACTL_EXT_OFF 0xc /* SIF Address Extended reg */
+
+
+#define PORT0 0 /* Regular single port adapter */
+#define PORT1 1 /* Port 1 of dual port adapter */
+#define PORT2 2 /* Port 2 of dual port adapter */
+
+/*
+ * Structure Name: Adapter Control Register Bit Definitions
+ *
+ * Description: The Adapter Control Register Bit Definitions define
+ * functions of the individual bits in the Adapter Con-
+ * trol register of the EAGLE chip. Bit combinations are
+ * also defined here.
+ */
+#define ACTL_TEST0 0x8000 /* Test0, set - 4mbps, clr - 16 */
+#define ACTL_TEST1 0x4000 /* Test1, set - TR, clr - Eth */
+#define ACTL_SWHLDA 0x0800 /* Software Hold Acknowledge */
+#define ACTL_SWDDIR 0x0400 /* Current SDDIR signal level */
+#define ACTL_SWHRQ 0x0200 /* Software Hold Request */
+#define ACTL_PSDMALEN 0x0100 /* Psuedo System DMA Length */
+#define ACTL_ARESET 0x0080 /* Adapter Reset */
+#define ACTL_CPHALT 0x0040 /* Comm Processor Halt */
+#define ACTL_BOOT 0x0020 /* Bootstrapped CP Code */
+#define ACTL_ROM 0x0010 /* Reserved */
+#define ACTL_SINTEN 0x0008 /* System Interrupt Enable */
+#define ACTL_PEN 0x0004 /* Adapter Parity Enable */
+#define ACTL_NSELOUT0 0x0002 /* Net Select, set - 4, clr -16 */
+#define ACTL_NSELOUT1 0x0001 /* Net Select,set - tr, clr -eth*/
+
+#define ACTL_TESTPINS ACTL_TEST1 + ACTL_TEST0
+
+#define ACTL_HARD_RESET 0xEE /* Force Hard Reset */
+#define SIF_SOFT_RESET 0xff00 /* Soft Reset */
+/*
+ * Structure Name: Adapter Interrupt Register Bit Definitions
+ *
+ * Description: The Adapter Interrupt Register Bit Definitions define
+ * functions of the individual bits in the System Inter-
+ * rupt register of the TMS380 chipset. Bit combinations
+ * are also defined here.
+ */
+#define SIFINT_ADPINT 0x8000 /* Adapter Interrupt */
+#define SIFINT_RESET 0x4000 /* Reset request */
+#define SIFINT_SSBCLR 0x2000 /* SSB Clear */
+#define SIFINT_EXECUTE 0x1000 /* Execute Command */
+#define SIFINT_SCBREQ 0x0800 /* SCB Clear request */
+#define SIFINT_RCVCON 0x0400 /* Receive Continue */
+#define SIFINT_RCVVLD 0x0200 /* Receive Valid */
+#define SIFINT_XMTVLD 0x0100 /* Transmit Valid */
+#define SIFINT_SYSINT 0x0080 /* System Interrupt */
+
+#define SIFINT_CMD (SIFINT_ADPINT | SIFINT_EXECUTE | SIFINT_SYSINT)
+#define SIFINT_SSBCLEAR (SIFINT_ADPINT | SIFINT_SSBCLR)
+#define SIFINT_SCBREQST (SIFINT_ADPINT | SIFINT_SCBREQ | SIFINT_SYSINT)
+#define SIFINT_RCVVALID (SIFINT_ADPINT | SIFINT_RCVVLD | SIFINT_SYSINT)
+#define SIFINT_XMTVALID (SIFINT_ADPINT | SIFINT_XMTVLD | SIFINT_SYSINT)
+#define SIFINT_RCVCONT (SIFINT_ADPINT | SIFINT_RCVCON | SIFINT_SYSINT)
+
+#define INT_ADPCHECK 0x0000 /* Adapter Check Interrupt */
+#define INT_RINGSTAT 0x0004 /* Ring Status Interrupt */
+#define INT_SCBCLEAR 0x0006 /* SCB Clear Interrupt */
+#define INT_COMMAND 0x0008 /* Command Interrupt */
+#define INT_TRANSMIT 0x000c /* Transmit Interrupt */
+#define INT_RECEIVE 0x000a /* Receive Interrupt */
+
+#define INT_CODES 0x000f /* Mask for interrupt codes */
+
+
+/*
+ * Structure Name: Address Register INIT Block Location Definition
+ *
+ * Description: The Address Register INIT Block Loaction Definition defines
+ * the value that must be placed into the SIF address reg
+ * when the TMS380 is being initialized.
+ */
+#define ADDR_INIT 0x0a00 /* Start at address 0x0a00 */
+
+
+/*
+ * Structure Name: System Command Block (SCB) Structure Definition
+ *
+ * Description: The System Command Block Structure Definition defines
+ * the structure of the TMS380 based SCB block.
+ */
+typedef struct SCB_Block
+{
+ USHORT SCB_Dummy; /* Force SCB.Ptr to word boundry */
+ USHORT SCB_Cmd; /* SCB Command field */
+ ULONG SCB_Ptr; /* SCB Pointer field */
+} SCB, *PSCB;
+
+#define SIZE_SCB sizeof(SCB)
+
+
+/*
+ * Structure Name: System Status Block (SSB) Structure Definition
+ *
+ * Description: The System Status Block Structure Definition defines
+ * the structure of the TMS380 based SSB block. Also in-
+ * cluded are the SSB status field bit definitions.
+ */
+typedef struct SSB_Block
+{
+ USHORT SSB_Cmd; /* SSB Command field */
+ USHORT SSB_Status; /* SSB Status field */
+ ULONG SSB_Ptr; /* SSB Pointer field */
+} SSB, *PSSB;
+
+#define SIZE_SSB sizeof(SSB)
+
+#define SSB_GOOD 0x0080 /* SSB Command successful status */
+#define SSB_OPENERR 0x0002 /* Open Error Completion */
+
+
+/*
+ * Structure Name: Adapter Initialization Parameter Block Definition
+ *
+ * Description: The Adapter Initialization Parameter Block Definition
+ * defines the structure of the TMS380 based initiali-
+ * zation block.
+ */
+
+typedef struct INIT_Block
+{
+ USHORT INIT_Options; /* Initialization Options */
+ UCHAR INIT_Vectors[6]; /* Interrupt vector codes */
+ USHORT INIT_Rburst; /* Receive DMA burst size */
+ USHORT INIT_Xburst; /* Transmit DMA burst size */
+ USHORT INIT_DMARetry; /* DMA retry counts */
+} INIT, *PINIT;
+
+#define SIZE_INIT sizeof(INIT)
+
+
+//
+// Structure Name: Open Adapter Parameter Block Structure Definition
+//
+// Description: The Open Adapter Parameter Block Structure Definition
+// defines the structure of the TMS380 based parameter
+// block passed to the adapter on an Open Adapter request.
+// All parameter defaults listed here are already byte
+// swapped for DMA into the adapter. Open options are
+// also defined here.
+//
+
+typedef struct OPEN_Block
+{
+ USHORT OPEN_Options; /* Open options */
+ UCHAR OPEN_NodeAddr[NET_ADDR_SIZE]; /* Adapter node addr */
+ UCHAR OPEN_GroupAddr[NET_GROUP_SIZE]; /* Adapter grp addr */
+ UCHAR OPEN_FunctAddr[NET_GROUP_SIZE]; /* Adapter fnc addr */
+ USHORT OPEN_RLSize; /* Receive list size */
+ USHORT OPEN_XLSize; /* Transmit list size */
+ USHORT OPEN_BufSize; /* Adapter buffer size (1K) */
+ USHORT OPEN_RAMStart; /* Adapter RAM start addr */
+ USHORT OPEN_RAMEnd; /* Adapter RAM end address */
+ UCHAR OPEN_Xbufmin; /* Adapter xmit min buf cnt */
+ UCHAR OPEN_Xbufmax; /* Adapter xmit max buf cnt */
+ UCHAR *OPEN_ProdIdPtr; /* Product ID pointer */
+ UCHAR OPEN_ProdID[18]; /* Product ID */
+} OPEN, *POPEN;
+
+#define SIZE_OPEN sizeof(OPEN)
+
+
+#define OOPTS_WRAP 0x8000 /* Open Wrap Mode BOTH */
+#define OOPTS_DHARD 0x4000 /* Disable Hard Errors TR */
+#define OOPTS_DSOFT 0x2000 /* Disable Soft Errors TR */
+#define OOPTS_PADPM 0x1000 /* Pass Adapter MAC Frames TR */
+#define OOPTS_PATTM 0x0800 /* Pass Attention MAC Frames TR */
+#define OOPTS_PADR 0x0400 /* Pad Routing Field TR */
+#define OOPTS_FHOLD 0x0200 /* Frame Hold BOTH */
+#define OOPTS_CONT 0x0100 /* Contender TR */
+#define OOPTS_SHFR 0x0100 /* Pad Short Frames ETH */
+#define OOPTS_PBCNM 0x0080 /* Pass Beacon MAC Frames TR */
+#define OOPTS_REQ 0x0040 /* Required bit. ETH */
+#define OOPTS_FULLDUP 0x0020 /* Full duplex enable ETH */
+#define OOPTS_ETR 0x0010 /* Early Token Release TR */
+#define OOPTS_CMAC 0x0004 /* Copy All MAC Frames TR */
+#define OOPTS_CNMAC 0x0002 /* Copy All Non-MAC Frames BOTH */
+#define OOPTS_FONLY 0x0001 /* Pass First Buffer Only */
+
+#define OOPTS_TR_CFG 0xff87 /* Token ring configurable bits */
+#define OOPTS_ETH_CFG 0x8263 /* Ethernet configurable bits */
+
+//
+// Structure Name: Transmit List Data Pointer Structure Definition
+//
+// Description: The Transmit List Data Pointer Structure Definition
+// defines the structure of the data pointers contained
+// in the TMS380 based Transmit Parameter List.
+//
+
+typedef struct _XMIT_DATA
+{
+ USHORT DataCount;
+ USHORT DataHi;
+ USHORT DataLo;
+} XMIT_DATA, *PXMIT_DATA;
+
+
+#define DATA_NOT_LAST 0x0080 /* "Not last" mask for len field*/
+#define DATA_LAST 0xff7f /* "Last" mask for len field */
+
+
+//
+// Structure Name: Transmit List Structure Definition
+//
+// Description: The Transmit List Structure Definition defines the
+// structure of the TMS380 based Transmit Parameter List.
+// Also included are the definitions of the TRNDD parti-
+// cular fields that have been added to the end of the
+// list structure to allow easy management of the trans-
+// mit process.
+//
+
+
+#define MAX_LISTS_PER_XMIT 1
+#define NUM_BUFS_PER_LIST 6 // MAC Can Handle max of 9 fragments
+#define MAX_BUFS_PER_XMIT (MAX_LISTS_PER_XMIT * NUM_BUFS_PER_LIST)
+#define SIZE_XMIT_DATA (NUM_BUFS_PER_LIST * 6) // 3 words per
+#define SIZE_XMIT_LIST (SIZE_XMIT_DATA + 8) // data + fwrdptr + size + count
+
+//
+// Definition of the buffer structures we need for recieve lists,
+// and our own transmit buffers.
+//
+typedef struct _BUFFER_DESCRIPTOR {
+
+ NDIS_PHYSICAL_ADDRESS PhysicalBuffer;
+ PVOID VirtualBuffer;
+ PNDIS_BUFFER FlushBuffer;
+ struct _BUFFER_DESCRIPTOR *Next; // NULL implies no more entries in the list.
+ UINT BufferSize; // bytes available in the buffer
+ UINT DataLength; // actual bytes placed into buffer.
+
+} BUFFER_DESCRIPTOR, *PBUFFER_DESCRIPTOR;
+
+
+typedef struct XMIT_List
+{
+ // Hardware List Fields
+ //
+ ULONG XMIT_FwdPtr; // Motorola pointer to next list
+ USHORT XMIT_CSTAT; // Command/Status field
+ SHORT XMIT_Fsize; // Frame size
+ XMIT_DATA XMIT_Data[MAX_BUFS_PER_XMIT]; // Data
+ struct XMIT_List *XMIT_Next; // Intel pointer to next list
+ //
+ // Our extra List Fields...
+ //
+ ULONG XMIT_MyMoto; // My motorola address
+
+#ifndef COPALL
+ ULONG XMIT_MapReg; // Index to mapping register
+ PNDIS_PACKET XMIT_Packet; //
+#endif
+
+ NDIS_PHYSICAL_ADDRESS XMIT_Phys; // Physical Pointer to this XMIT
+ ULONG XMIT_Timeout; // > 0 if checking for timeout
+
+#ifdef XMIT_INTS
+ ULONG XMIT_Number; // index of this list
+#endif
+
+ PBUFFER_DESCRIPTOR XMIT_OurBufferPtr; // which buffer we used...
+
+} XMIT, *PXMIT;
+
+#define SIZE_XMIT sizeof(XMIT) /* Size of transmit list */
+
+// Structure Name: Transmit List CSTAT Bit Definitions
+//
+// Description: The Transmit List CSTAT Bit Definitions defines the
+// meaning of the bits in the CSTAT field of the transmit
+// list.
+//
+#define XCSTAT_VALID 0x0080 /* Transmit Valid */
+#define XCSTAT_COMPLETE 0x0040 /* Transmit Frame Complete */
+#define XCSTAT_SOF 0x0020 /* Transmit Start of Frame */
+#define XCSTAT_EOF 0x0010 /* Transmit End of Frame */
+#define XCSTAT_FINT 0x0008 /* Transmit Frame Interrupt */
+#define XCSTAT_ERROR 0x0004 /* Transmit Error */
+#define XCSTAT_GOODFS 0x8800 /* Good Transmit FS btye */
+
+#define XCSTAT_LSOF 0x00a8 /* Transmit Start of Frame */
+#define XCSTAT_GO_INT 0x00b8 /* Transmit VALID/SOF/EOF/FINT */
+#define XCSTAT_GO 0x00b0 /* Transmit VALID/SOF/EOF */
+
+
+//
+// Structure Name: Transmit SSB Status Codes Definitions
+//
+// Description: The Transmit SSB Status Codes Definitions defines the
+// meaning of the bits in the Status field of the trans-
+// mit completion SSB.
+//
+#define XSTAT_CMDCMPLT 0x0080 /* Command Complete */
+#define XSTAT_FRMCMPLT 0x0040 /* Frame Complete */
+#define XSTAT_LERROR 0x0020 /* List Error */
+
+#define XSTAT_FRAME_SIZE_ERROR 0x8000
+#define XSTAT_XMIT_THRESHOLD 0x4000
+#define XSTAT_ODD_ADDRESS 0x2000
+#define XSTAT_FRAME_ERROR 0x1000
+#define XSTAT_ACCESS_PRIORITY_ERR 0x0800
+#define XSTAT_UNENABLE_MAC_FRAME 0x0400
+#define XSTAT_ILLEGAL_FRAME_FORMAT 0x0200
+
+
+//
+// Structure Name: Receive List Structure Definition
+//
+// Description: The Receive List Structure Definition defines the
+// structure of the TMS380 based Receive Parameter List.
+// Also included are the definitions of the TRNDD parti-
+// cular fields that have been added to the end of the
+// list structure to allow easy management of the receive
+// process.
+//
+typedef struct RCV_List
+{
+ // Physical Hardware List Fields
+ //
+ ULONG RCV_FwdPtr; /* Motorola pointer to next list*/
+ USHORT RCV_CSTAT; /* Command/Status field */
+ SHORT RCV_Fsize; /* Frame size */
+ USHORT RCV_Dsize; /* Receive list data size */
+ USHORT RCV_DptrHi; /* Receive list date pointer hi word*/
+ USHORT RCV_DptrLo; /* Receive list data pointer lo word*/
+ //
+ // Our Extra Receive List Fields
+ //
+ struct RCV_List *RCV_Next; // Intel pointer to next list
+#ifdef ODD_POINTER
+ struct RCV_List *RCV_Prev; // Intel pointer to previous list
+#endif
+ ULONG RCV_Number; // index
+
+ ULONG RCV_MyMoto; // Motorola Physical Address
+ ULONG RCV_HeaderLen; // Len of the rcvd packet's hdr
+ NDIS_PHYSICAL_ADDRESS RCV_Phys; // Physical Pointer to this RCV
+ PVOID RCV_Buf; // pointer to our recieve buffer
+ NDIS_PHYSICAL_ADDRESS RCV_BufPhys; // Physical Pointer to our Frame Buffer
+ PNDIS_BUFFER RCV_FlushBuffer; // Points to an NDIS buffer which describes thisbuffer
+} RCV, *PRCV;
+
+#define SIZE_RCV sizeof(RCV) // Size of receive list
+
+//
+// Structure Name: Receive List CSTAT Bit Definitions
+//
+// Description: The Receive List CSTAT Bit Definitions defines the
+// meaning of the bits in the CSTAT field of the receive
+// list.
+//
+#define RCSTAT_VALID 0x0080 /* Receive Valid */
+#define RCSTAT_COMPLETE 0x0040 /* Receive Frame Complete */
+#define RCSTAT_SOF 0x0020 /* Receive Start of Frame */
+#define RCSTAT_EOF 0x0010 /* Receive End of Frame */
+#define RCSTAT_FINT 0x0008 /* Receive Frame Interrupt */
+
+#define RCSTAT_GO_INT 0x0088 /* Receive Valid and frame int */
+#define RCSTAT_GO 0x0080 /* Receive Valid and frame int */
+
+//
+// Receive_Status Field Defines
+//
+#define RSTAT_FRAME_COMPLETE 0x0080 /* Frame Complete */
+#define RSTAT_RX_SUSPENDED 0x0040 /* Receive Suspended */
+//
+// Structure Name: Token-Ring Frame Format
+//
+// Description: The Token-Ring Frame Format structure defines the
+// fields of a valid Token-Ring frame.
+//
+typedef struct TR_Format
+{
+ UCHAR FF_Ac; /* AC Field */
+ UCHAR FF_Fc; /* FC Field */
+ UCHAR FF_Dest[6]; /* Destination Address */
+ UCHAR FF_Src[6]; /* Source Address */
+} TRF, *PTRF;
+
+//
+// Structure Name: Source Routing Format
+//
+// Description: The Source Routing Format structure defines the fields
+// of Source Routing information contained within a frame
+//
+typedef struct routing_control
+{
+ UCHAR rc_L:5, /* Length of RI including rc */
+ rc_B:3; /* Broadcast Bits */
+ UCHAR rc_r:3, /* Reserved */
+ rc_LF:4, /* Largest Frame */
+ rc_D:1; /* Direction bits */
+} ROUTING_CONTROL, *PROUTING_CONTROL;
+
+
+//
+// Structure Name: Ethernet Frame Format
+//
+// Description: The Ethernet Frame Format structure defines the
+// fields of a valid Ethernet frame.
+//
+typedef struct Eth_Format
+{
+ UCHAR FF_Dest[6]; /* Destination Address */
+ UCHAR FF_Src[6]; /* Source Address */
+} ETHF, *PETHF;
+
+
+//
+// MAC Header Size. This is the same header size for both network types.
+//
+#define NETFLEX_MACHEADER_SIZE 14
+
+
+//
+// Structure Name: Read Error Log Buffer Structure Definition
+// (Token Ring Only)
+//
+// Description: The Read Error Log Buffer Structure Definition defines
+// the structure of the TMS380 based Read Error Log.
+//
+typedef struct REL_Block
+{
+ UCHAR REL_LineError;
+ UCHAR REL_Rsvd1;
+ UCHAR REL_BurstError;
+ UCHAR REL_ARIFCIError;
+ UCHAR REL_Rsvd2;
+ UCHAR REL_Rsvd3;
+ UCHAR REL_LostError;
+ UCHAR REL_Congestion;
+ UCHAR REL_CopiedError;
+ UCHAR REL_Rsvd4;
+ UCHAR REL_TokenError;
+ UCHAR REL_Rsvd5;
+ UCHAR REL_DMABUSError;
+ UCHAR REL_DMAPARError;
+} REL, *PREL;
+
+#define SIZE_REL sizeof(REL)
+
+//
+// Structure Name: Read Statistics Log Buffer Structure Definition
+// (Ethernet Only)
+//
+// Description: The Read Statistics Log Buffer Structure Definition defines
+// the structure of the TMS380 based Read Statistics Log.
+//
+typedef struct RSL_Block
+{
+ USHORT RSL_ReceviedOK;
+ USHORT RSL_Rsvd1;
+ USHORT RSL_FrameCheckSeq;
+ USHORT RSL_AlignmentErr;
+ USHORT RSL_DeferredXmit;
+ USHORT RSL_Excessive;
+ USHORT RSL_LateCollision;
+ USHORT RSL_CarrierErr;
+ USHORT RSL_XmitdOK;
+ USHORT RSL_1_Collision;
+ USHORT RSL_2_Collision;
+ USHORT RSL_3_Collision;
+ USHORT RSL_4_Collision;
+ USHORT RSL_5_Collision;
+ USHORT RSL_6_Collision;
+ USHORT RSL_7_Collision;
+ USHORT RSL_8_Collision;
+ USHORT RSL_9_Collision;
+ USHORT RSL_10_Collision;
+ USHORT RSL_11_Collision;
+ USHORT RSL_12_Collision;
+ USHORT RSL_13_Collision;
+ USHORT RSL_14_Collision;
+ USHORT RSL_15_Collision;
+} RSL, *PRSL;
+
+#define SIZE_RSL sizeof(RSL)
+
+
+
+struct read_adapter_buf
+{
+ SHORT count;
+ SHORT addr;
+ UCHAR data[100];
+};
+
+
+typedef struct multi_block
+{
+ USHORT MB_Option;
+ USHORT MB_Addr_Hi;
+ USHORT MB_Addr_Med;
+ USHORT MB_Addr_Lo;
+} MULTI_BLOCK, *PMULTI_BLOCK;
+
+#define MPB_DELETE_ADDRESS 0x0000
+#define MPB_ADD_ADDRESS 0x0100
+#define MPB_CLEAR_ALL 0x0200
+#define MPB_SET_ALL 0x0300
+
+
+#define RING_STATUS_OVERFLOW 0x8000
+#define RING_STATUS_SINGLESTATION 0x4000
+#define RING_STATUS_RINGRECOVERY 0x2000
+#define RING_STATUS_SIGNAL_LOSS 0x0080
+#define RING_STATUS_HARD_ERROR 0x0040
+#define RING_STATUS_SOFT_ERROR 0x0020
+#define RING_STATUS_XMIT_BEACON 0x0010
+#define RING_STATUS_LOBE_WIRE_FAULT 0x0008
+#define RING_STATUS_AUTO_REMOVE_1 0x0004
+#define RING_STATUS_REMOVE_RECEIVED 0x0001
+
+
diff --git a/private/ntos/ndis/netflex/transmit.c b/private/ntos/ndis/netflex/transmit.c
new file mode 100644
index 000000000..37373c5f8
--- /dev/null
+++ b/private/ntos/ndis/netflex/transmit.c
@@ -0,0 +1,802 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: TRANSMIT.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexProcessXmit
+//
+// Description: This routine looks through the tranmit lists
+// and calls the send complete routines of the
+// bindings whose sends have completed.
+//
+// Input: acb - Pointer to the Adapter's acb
+//
+// Output: None
+//
+// Calls: NetFlexDequeue_TwoPtrQ,
+// NetFlexEnqueue_TwoPtrQ_Tail
+//
+// Called_By: NetFlexDPR
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+FASTCALL
+NetFlexProcessXmit(
+ PACB acb
+ )
+{
+ PXMIT xmitptr;
+ UINT curmap;
+ PNDIS_PACKET packet;
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ PNDIS_BUFFER SourceBuffer;
+ ULONG XmitedOk = 0;
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisAcquireSpinLock(&acb->XmitLock);
+ }
+
+ xmitptr = acb->acb_xmit_ahead;
+
+ if ((xmitptr == NULL) ||
+ !(xmitptr->XMIT_CSTAT & XCSTAT_COMPLETE))
+ {
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return;
+ }
+
+ //
+ // Increment the interrupt count.
+ //
+ acb->acb_int_count++;
+
+ //
+ // For each completed frame issue a NdisMSendComplete.
+ // Before completing the send, release the mapping of
+ // the phyical buffers if we are using the protocol's buffers.
+ //
+ while (xmitptr->XMIT_CSTAT & XCSTAT_COMPLETE)
+ {
+ XmitedOk++;
+
+ //
+ // Check the status of the transmit and update the
+ // counter accordingly.
+ //
+ if (xmitptr->XMIT_CSTAT & XCSTAT_ERROR)
+ {
+ // Transmit error
+ //
+ DebugPrint(1,("NF(%d): Xmit Error CSTAT = 0x%x\n",acb->anum,xmitptr->XMIT_CSTAT));
+ acb->acb_gen_objs.frames_xmitd_err++;
+ XmitedOk--;
+ status = NDIS_STATUS_FAILURE;
+ }
+ else if (( xmitptr->XMIT_CSTAT & 0xff00) &&
+ ((xmitptr->XMIT_CSTAT & 0xff00) != 0xcc00))
+ {
+ // FS indicates something happened
+ //
+ DebugPrint(1,("NF(%d): Xmit: FS = 0x%x\n",acb->anum,xmitptr->XMIT_CSTAT));
+ status = ((xmitptr->XMIT_CSTAT & XCSTAT_GOODFS) != XCSTAT_GOODFS)
+ ? NDIS_STATUS_NOT_RECOGNIZED : NDIS_STATUS_NOT_COPIED;
+ }
+
+ //
+ // Get the info we need from the sof.
+ //
+ curmap = xmitptr->XMIT_MapReg;
+ packet = xmitptr->XMIT_Packet;
+
+ //
+ // Clean up the transmit lists and the transmit queues.
+ //
+ xmitptr->XMIT_CSTAT = 0;
+ xmitptr->XMIT_Packet = NULL;
+
+ if (xmitptr->XMIT_OurBufferPtr == NULL)
+ {
+ // Normal Xmit Packet
+ //
+ NdisQueryPacket(
+ packet,
+ NULL,
+ NULL,
+ (PNDIS_BUFFER *)&SourceBuffer,
+ NULL);
+ while (SourceBuffer)
+ {
+ NdisMCompleteBufferPhysicalMapping(
+ acb->acb_handle,
+ (PNDIS_BUFFER)SourceBuffer,
+ curmap);
+ curmap++;
+ if (curmap == acb->acb_maxmaps)
+ {
+ curmap = 0;
+ }
+
+ NdisGetNextBuffer(SourceBuffer, &SourceBuffer);
+ }
+ }
+ else
+ {
+ // We've used one of our adapter buffers, so put the adapter
+ // buffer back on the free list.
+ //
+ if (xmitptr->XMIT_OurBufferPtr->BufferSize != acb->acb_smallbufsz)
+ {
+ xmitptr->XMIT_OurBufferPtr->Next = acb->OurBuffersListHead;
+ acb->OurBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ else
+ {
+ //
+ // small buffer
+ //
+ xmitptr->XMIT_OurBufferPtr->Next = acb->SmallBuffersListHead;
+ acb->SmallBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ xmitptr->XMIT_OurBufferPtr = NULL;
+ }
+
+ //
+ // Point to next xmit
+ //
+ if (xmitptr == acb->acb_xmit_atail)
+ {
+ // Set the list to null, also have to
+ // the ahead pointer, since if we had run
+ // out of xmit buffers, the wrapper can call
+ // our sendhandler during the completion.
+ //
+ xmitptr = acb->acb_xmit_ahead = acb->acb_xmit_atail = NULL;
+ }
+ else
+ {
+ // Point to the next xmit list
+ //
+ xmitptr = xmitptr->XMIT_Next;
+ }
+
+ //
+ // Increase the number of available xmit lists
+ //
+ acb->acb_avail_xmit++;
+
+ //
+ // Complete the request
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ if (packet != NULL)
+ {
+ NdisMSendComplete(acb->acb_handle, packet, status);
+ }
+ else
+ {
+ NdisMSendResourcesAvailable(acb->acb_handle);
+ }
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisAcquireSpinLock(&acb->XmitLock);
+ }
+
+ if (xmitptr == NULL)
+ break;
+ }
+
+ //
+ // Update the head of the active lists if we ran into a non-completed
+ // list.
+ //
+ if (xmitptr)
+ {
+ acb->acb_xmit_ahead = xmitptr;
+ }
+
+ if (acb->acb_xmit_ahead)
+ {
+ //
+ // Issue a xmit valid adapter interrupt
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_XMTVALID);
+ }
+
+ acb->acb_gen_objs.frames_xmitd_ok += XmitedOk;
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexTransmitStatus
+//
+// Description: This routine detemined the action to take
+// depending on the reason for the xmit interrupt
+//
+// Input: acb - Pointer to the Adapter's acb
+//
+// Output: None
+//
+// Calls: NdisRawWritePortUshort,
+// NetFlexDequeue_TwoPtrQ,
+// NetFlexSendNextSCB,
+// NetFlexEnqueue_TwoPtrQ_Tail
+//
+// Called_By: NetFlexDPR
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexTransmitStatus(
+ PACB acb
+ )
+{
+ PXMIT xmitptr;
+ UINT curmap;
+ PNDIS_PACKET packet;
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ PNDIS_BUFFER SourceBuffer;
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisAcquireSpinLock(&acb->XmitLock);
+ }
+
+ if (acb->acb_xmit_ahead == NULL)
+ {
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return;
+ }
+
+ //
+ // We have received a list error. Determine the type of list error
+ // in order to tell the protocol what happened.
+ //
+ acb->acb_gen_objs.frames_xmitd_err++;
+ xmitptr = acb->acb_xmit_ahead;
+
+ DebugPrint(1,("NF(%d): xmitptr = %x, Cstat = %x\n",acb->anum,xmitptr,xmitptr->XMIT_CSTAT));
+
+ switch (acb->acb_ssb_virtptr->SSB_Status & 0xff00)
+ {
+ case XSTAT_FRAME_SIZE_ERROR:
+ case XSTAT_ILLEGAL_FRAME_FORMAT:
+ case XSTAT_ACCESS_PRIORITY_ERR:
+ DebugPrint(1,("NF(%d): Frame sz err, illegal format or access priority\n",acb->anum));
+ status = NDIS_STATUS_INVALID_PACKET;
+ break;
+ case XSTAT_XMIT_THRESHOLD:
+ case XSTAT_ODD_ADDRESS:
+ case XSTAT_FRAME_ERROR:
+ case XSTAT_UNENABLE_MAC_FRAME:
+ acb->acb_gen_objs.frames_xmitd_err++;
+ DebugPrint(1,("NF(%d): threshold, frame error or unenable\n",acb->anum));
+ status = NDIS_STATUS_FAILURE;
+ break;
+ default:
+ acb->acb_gen_objs.frames_xmitd_err++;
+ DebugPrint(1,("NF(%d): Unknown error\n",acb->anum));
+ status = NDIS_STATUS_SUCCESS;
+ break;
+ }
+
+
+ //
+ // Get the info we need from the sof.
+ //
+ curmap = xmitptr->XMIT_MapReg;
+ packet = xmitptr->XMIT_Packet;
+
+ //
+ // Clean up the transmit lists and the transmit queues.
+ //
+ xmitptr->XMIT_CSTAT = 0;
+ xmitptr->XMIT_Packet = NULL;
+
+ //
+ // Take the error list off the active list. Set up the waiting list
+ // to either point to the next list of the active queue or the next
+ // available list from transmission.
+ //
+ if (acb->acb_state == AS_OPENED)
+ {
+ if (acb->acb_xmit_atail == xmitptr)
+ {
+ acb->acb_xmit_whead = acb->acb_xmit_wtail = xmitptr->XMIT_Next;
+ }
+ else
+ {
+ acb->acb_xmit_whead = xmitptr->XMIT_Next;
+ acb->acb_xmit_wtail = acb->acb_xmit_atail;
+ }
+ acb->acb_xmit_atail = acb->acb_xmit_ahead = NULL;
+
+ //
+ // Send off the transmit command to the adapter since the transmit
+ // command completes when a list error is encountered.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if (!acb->acb_scbclearout)
+ {
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_SCBREQST);
+ }
+ }
+ else
+ {
+ acb->acb_xmit_atail = acb->acb_xmit_ahead = NULL;
+ }
+ acb->acb_avail_xmit++;
+
+ if (xmitptr->XMIT_OurBufferPtr != NULL)
+ {
+ // We've used one of our adapter buffers, so put the adapter
+ // buffer back on the free list.
+ //
+ if (xmitptr->XMIT_OurBufferPtr->BufferSize != acb->acb_smallbufsz)
+ {
+ xmitptr->XMIT_OurBufferPtr->Next = acb->OurBuffersListHead;
+ acb->OurBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ else
+ {
+ //
+ // small buffer
+ //
+ xmitptr->XMIT_OurBufferPtr->Next = acb->SmallBuffersListHead;
+ acb->SmallBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ xmitptr->XMIT_OurBufferPtr = NULL;
+ }
+ else
+ {
+ NdisQueryPacket(
+ packet,
+ NULL,
+ NULL,
+ (PNDIS_BUFFER *)&SourceBuffer,
+ NULL);
+
+ while (SourceBuffer)
+ {
+ NdisMCompleteBufferPhysicalMapping(
+ acb->acb_handle,
+ (PNDIS_BUFFER)SourceBuffer,
+ curmap);
+
+ curmap++;
+ if (curmap == acb->acb_maxmaps)
+ {
+ curmap = 0;
+ }
+
+ NdisGetNextBuffer(SourceBuffer, &SourceBuffer);
+ }
+ }
+ //
+ // Complete the request
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ if (packet)
+ {
+ NdisMSendComplete(acb->acb_handle, packet, status);
+ }
+ else
+ {
+ NdisMSendResourcesAvailable(acb->acb_handle);
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexSend
+//
+// Description: This routine places the given packet on the
+// adapter's transmit list.
+//
+// Input:
+// MiniportAdapterContext - The context value
+// returned by the Miniport when the adapter was
+// initialized. In reality, it is a pointer to ACB
+//
+// Packet - A pointer to a descriptor for the packet
+// that is to be transmitted.
+//
+// Flags - The send options to use.
+//
+// Output: Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is
+// returned.
+//
+// Calls: NdisQueryPacket,NdisQueryBuffer,NdisMoveMemory
+// NdisGetNextBuffer,NdisGetBufferPhysicalAddress
+// NdisWritePortUshort,NetFlexEnqueue_TwoPtrQ_Tail
+// NetFlexDequeue_OnePtrQ_Head,SWAPL,SWAPS
+//
+// Called_By: Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS NetFlexSend(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET Packet,
+ IN UINT Flags
+ )
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ PXMIT xmitptr;
+
+ UINT PhysicalBufferCount, BufferCount;
+ UINT TotalPacketLength;
+ PNDIS_BUFFER SourceBuffer;
+ PUSHORT avail_xmits;
+
+
+ UINT curmap,j,i;
+ UINT arraysize;
+ ULONG physbufptr;
+ NDIS_STATUS status = NDIS_STATUS_PENDING;
+
+ NDIS_PHYSICAL_ADDRESS_UNIT physaddrarray[MAX_BUFS_PER_XMIT];
+
+ //
+ // if we are in full duplex mode then acquire the xmit spin lock.
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ NdisAcquireSpinLock(&acb->XmitLock);
+ }
+
+ avail_xmits = &acb->acb_avail_xmit;
+
+ //
+ // Do we have at least one available xmit list?
+ //
+ if (*avail_xmits)
+ {
+ // Yes, See if we can process this send request
+ //
+ NdisQueryPacket(
+ Packet,
+ (PUINT)&PhysicalBufferCount,
+ (PUINT)&BufferCount,
+ (PNDIS_BUFFER *)(&SourceBuffer),
+ (PUINT)(&TotalPacketLength));
+
+ //
+ // Point to the head of the xmit list
+ //
+ xmitptr = acb->acb_xmit_head;
+
+ //
+ // Do we need to use our own buffer?
+ //
+ if ((PhysicalBufferCount <= MAX_BUFS_PER_XMIT) &&
+ (TotalPacketLength > acb->acb_smallbufsz ||
+ acb->SmallBuffersListHead == NULL))
+ {
+ // Clean the Data fields
+ //
+ NdisZeroMemory(xmitptr->XMIT_Data, SIZE_XMIT_DATA);
+
+ // With the new fpa mac code we can only use 1
+ // xmit list per xmit. Point the head pointer to the next
+ // available list. At this point we are guaranteed less than
+ // MAX_BUFS_PER_XMIT buffers per xmit = 1 xmit list.
+ //
+
+ curmap = acb->acb_curmap;
+ acb->acb_curmap += BufferCount;
+ if (acb->acb_curmap >= acb->acb_maxmaps)
+ {
+ acb->acb_curmap -= acb->acb_maxmaps;
+ }
+
+ xmitptr->XMIT_MapReg = curmap;
+
+ i=0;
+ while (SourceBuffer != NULL)
+ {
+ NdisMStartBufferPhysicalMapping(
+ acb->acb_handle,
+ SourceBuffer,
+ curmap,
+ TRUE,
+ physaddrarray,
+ &arraysize);
+
+ curmap++;
+ if (curmap == acb->acb_maxmaps)
+ {
+ curmap = 0;
+ }
+
+ for (j=0; j < arraysize; j++)
+ {
+ physbufptr = SWAPL(NdisGetPhysicalAddressLow(physaddrarray[j].PhysicalAddress));
+ xmitptr->XMIT_Data[i].DataCount = (USHORT)(SWAPS(physaddrarray[j].Length)) | DATA_NOT_LAST;
+ xmitptr->XMIT_Data[i].DataHi = (USHORT)physbufptr;
+ xmitptr->XMIT_Data[i].DataLo = (USHORT)(physbufptr >> 16);
+ PhysicalBufferCount--;
+ i++;
+ }
+ NdisFlushBuffer(SourceBuffer, TRUE);
+ NdisGetNextBuffer(SourceBuffer, &SourceBuffer);
+ }
+
+ xmitptr->XMIT_Data[i-1].DataCount &= DATA_LAST;
+ xmitptr->XMIT_Fsize = (SHORT)(SWAPS((USHORT)TotalPacketLength));
+ xmitptr->XMIT_Packet = Packet;
+ xmitptr->XMIT_OurBufferPtr = NULL;
+ }
+ else
+ {
+ // We need to constrain the packet into our own buffer
+ //
+ if (((PhysicalBufferCount > MAX_BUFS_PER_XMIT) &&
+ (acb->OurBuffersListHead != NULL)) ||
+ ((acb->SmallBuffersListHead != NULL) &&
+ (TotalPacketLength <= acb->acb_smallbufsz)))
+ {
+ status = NetFlexConstrainPacket(
+ acb,
+ xmitptr,
+ Packet,
+ PhysicalBufferCount,
+ SourceBuffer,
+ TotalPacketLength);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return(status);
+ }
+ }
+ else
+ {
+ // we don't have any buffers at this time...
+ // See if we can process any transmits, freeing up any that are completed...
+ //
+ DebugPrint(1,("NF(%d): No empty Xmit Buffers to transfer into\n",acb->anum));
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+ }
+
+ //
+ // Update all the pointers...
+ //
+ acb->acb_xmit_head = xmitptr->XMIT_Next;
+
+ xmitptr->XMIT_Timeout = 0;
+
+#ifdef XMIT_INTS
+
+ //
+ // Leave the original FInt setting
+ //
+ xmitptr->XMIT_CSTAT =
+ ((xmitptr->XMIT_Number % acb->XmitIntRatio) == 0) ? XCSTAT_GO_INT : XCSTAT_GO;
+#else
+ xmitptr->XMIT_CSTAT = XCSTAT_GO;
+#endif
+
+ //
+ // Update Tail Pointer
+ //
+ acb->acb_xmit_atail = xmitptr;
+
+ //
+ // Update the head if this is the first one...
+ //
+ if (acb->acb_xmit_ahead == NULL)
+ {
+ acb->acb_xmit_ahead = xmitptr;
+ }
+
+ //
+ // If the transmitter had stalled because it ran out of
+ // valid lists, issue an adapter int to pickup this new valid one.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_XMTVALID);
+
+ //
+ // Indicate we've taken one of the ints
+ //
+ (*avail_xmits)--;
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return(status);
+ }
+
+ // No, We don't have any transmits at this time...
+ //
+ DebugPrint(2,("NF(%d): Send, Out of Xmit Lists...\n",acb->anum));
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return(NDIS_STATUS_RESOURCES);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexConstrainPacket
+//
+// Description: This routine combines the packet fragments
+// into our own buffer for transmition.
+//
+// Called_By: NetFlexSend
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexConstrainPacket(
+ PACB acb,
+ PXMIT xmitptr,
+ PNDIS_PACKET Packet,
+ UINT PhysicalBufferCount,
+ PNDIS_BUFFER SourceBuffer,
+ UINT TotalPacketLength
+ )
+{
+ PVOID SourceData; // Points to the virtual address of the source buffers data.
+ UINT SourceLength; // Number of bytes of data in the source buffer.
+ PCHAR CurrentDestination; // Pointer to virtual address for the adapter buffer
+ UINT TotalDataMoved = 0;
+ ULONG AdapterPhysicalBufferPtr;
+
+ PBUFFER_DESCRIPTOR BufferDescriptor;
+
+ if (TotalPacketLength > acb->acb_smallbufsz)
+ {
+ BufferDescriptor = acb->OurBuffersListHead;
+
+ if (!BufferDescriptor)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ acb->OurBuffersListHead = BufferDescriptor->Next;
+ BufferDescriptor->Next = NULL;
+ }
+ else
+ {
+ BufferDescriptor = acb->SmallBuffersListHead;
+
+ if (!BufferDescriptor)
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ acb->SmallBuffersListHead = BufferDescriptor->Next;
+ BufferDescriptor->Next = NULL;
+ }
+
+ //
+ // Clear out the data fields in the xmit list
+ //
+ NdisZeroMemory(xmitptr->XMIT_Data, SIZE_XMIT_DATA);
+
+ //
+ // Copy the packet's buffers into our buffer
+ //
+ CurrentDestination = BufferDescriptor->VirtualBuffer;
+ BufferDescriptor->DataLength = TotalPacketLength;
+
+ do
+ {
+ // Get Buffer info
+ //
+ NdisQueryBuffer(SourceBuffer, &SourceData, &SourceLength);
+
+ // Copy this buffer
+ //
+ NdisMoveMemory(CurrentDestination, SourceData, SourceLength);
+
+ //
+ // Update destination address
+ //
+ CurrentDestination = (PCHAR)CurrentDestination + SourceLength;
+
+ //
+ // Update count of packet length.
+ //
+ TotalDataMoved += SourceLength;
+
+ //
+ // Get the next buffers information
+ //
+ NdisGetNextBuffer(SourceBuffer, &SourceBuffer);
+
+ } while (SourceBuffer != NULL);
+
+
+ NdisFlushBuffer(BufferDescriptor->FlushBuffer, TRUE);
+
+ AdapterPhysicalBufferPtr =
+ SWAPL(NdisGetPhysicalAddressLow(BufferDescriptor->PhysicalBuffer));
+
+ xmitptr->XMIT_OurBufferPtr = BufferDescriptor;
+ xmitptr->XMIT_Data[0].DataCount = (USHORT)(SWAPS((USHORT)TotalPacketLength)) & DATA_LAST;
+ xmitptr->XMIT_Data[0].DataHi = (USHORT) AdapterPhysicalBufferPtr;
+ xmitptr->XMIT_Data[0].DataLo = (USHORT)(AdapterPhysicalBufferPtr >> 16);
+ xmitptr->XMIT_Fsize = (SHORT)(SWAPS((USHORT)TotalPacketLength));
+ xmitptr->XMIT_Packet = NULL;
+
+
+ DebugPrint(2,("NF(%d): Using internal buffer\n",acb->anum));
+
+ return NDIS_STATUS_SUCCESS;
+}