diff options
Diffstat (limited to '')
31 files changed, 12434 insertions, 0 deletions
diff --git a/private/ntos/ndis/netflex.bc/init.c b/private/ntos/ndis/netflex.bc/init.c new file mode 100644 index 000000000..49527f812 --- /dev/null +++ b/private/ntos/ndis/netflex.bc/init.c @@ -0,0 +1 @@ +#include <..\netflex\init.c> diff --git a/private/ntos/ndis/netflex.bc/initd.c b/private/ntos/ndis/netflex.bc/initd.c new file mode 100644 index 000000000..269d5b0b2 --- /dev/null +++ b/private/ntos/ndis/netflex.bc/initd.c @@ -0,0 +1 @@ +#include <..\netflex\initd.c> diff --git a/private/ntos/ndis/netflex.bc/int.c b/private/ntos/ndis/netflex.bc/int.c new file mode 100644 index 000000000..e3ae56d06 --- /dev/null +++ b/private/ntos/ndis/netflex.bc/int.c @@ -0,0 +1 @@ +#include <..\netflex\int.c> diff --git a/private/ntos/ndis/netflex.bc/makefile b/private/ntos/ndis/netflex.bc/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/netflex.bc/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.bc/netflex.rc b/private/ntos/ndis/netflex.bc/netflex.rc new file mode 100644 index 000000000..0574267ee --- /dev/null +++ b/private/ntos/ndis/netflex.bc/netflex.rc @@ -0,0 +1 @@ +#include <..\netflex\netflex.rc> diff --git a/private/ntos/ndis/netflex.bc/netflxbc.prf b/private/ntos/ndis/netflex.bc/netflxbc.prf new file mode 100644 index 000000000..8ad30ddbb --- /dev/null +++ b/private/ntos/ndis/netflex.bc/netflxbc.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.bc/receive.c b/private/ntos/ndis/netflex.bc/receive.c new file mode 100644 index 000000000..05bb6366b --- /dev/null +++ b/private/ntos/ndis/netflex.bc/receive.c @@ -0,0 +1 @@ +#include <..\netflex\receive.c> diff --git a/private/ntos/ndis/netflex.bc/request.c b/private/ntos/ndis/netflex.bc/request.c new file mode 100644 index 000000000..2e01f6d72 --- /dev/null +++ b/private/ntos/ndis/netflex.bc/request.c @@ -0,0 +1 @@ +#include <..\netflex\request.c> diff --git a/private/ntos/ndis/netflex.bc/reset.c b/private/ntos/ndis/netflex.bc/reset.c new file mode 100644 index 000000000..12b124679 --- /dev/null +++ b/private/ntos/ndis/netflex.bc/reset.c @@ -0,0 +1 @@ +#include <..\netflex\reset.c> diff --git a/private/ntos/ndis/netflex.bc/sources b/private/ntos/ndis/netflex.bc/sources new file mode 100644 index 000000000..62a9b1dae --- /dev/null +++ b/private/ntos/ndis/netflex.bc/sources @@ -0,0 +1,83 @@ +!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=netflxbc +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 + +# +# Make it a ndis 40 miniport +# +C_DEFINES=$(C_DEFINES) -DNDIS40_MINIPORT + +INCLUDES=..\..\inc;..\..\..\inc;..\netflex + +LINKER_FLAGS=$(LINKER_FLAGS) /map +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 diff --git a/private/ntos/ndis/netflex.bc/support.c b/private/ntos/ndis/netflex.bc/support.c new file mode 100644 index 000000000..206fea2bf --- /dev/null +++ b/private/ntos/ndis/netflex.bc/support.c @@ -0,0 +1 @@ +#include <..\netflex\support.c> diff --git a/private/ntos/ndis/netflex.bc/transmit.c b/private/ntos/ndis/netflex.bc/transmit.c new file mode 100644 index 000000000..ca78eab9e --- /dev/null +++ b/private/ntos/ndis/netflex.bc/transmit.c @@ -0,0 +1 @@ +#include <..\netflex\transmit.c> 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, ®_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 Binary files differnew file mode 100644 index 000000000..50d5106e5 --- /dev/null +++ b/private/ntos/ndis/netflex/netflx.bin 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 *)¯eq + ); + + // + // 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) ðobjs->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 *)¯eq); + 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 *)¯eq); + 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 *)¯eq); + 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 *)¯eq); + + 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 *)ðobjs->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; +} |